mirror of
https://github.com/hay-kot/mealie.git
synced 2025-08-22 06:23:34 -07:00
added card section card
This commit is contained in:
parent
e26566a7cc
commit
fd5a1672b0
14 changed files with 167 additions and 342 deletions
|
@ -17,7 +17,7 @@
|
||||||
@selected="navigateFromSearch"
|
@selected="navigateFromSearch"
|
||||||
/>
|
/>
|
||||||
</v-expand-x-transition>
|
</v-expand-x-transition>
|
||||||
<v-btn icon @click="toggleSearch">
|
<v-btn icon @click="search = !search">
|
||||||
<v-icon>mdi-magnify</v-icon>
|
<v-icon>mdi-magnify</v-icon>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
|
|
||||||
|
@ -34,11 +34,11 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Menu from "./components/UI/Menu"
|
import Menu from "./components/UI/Menu";
|
||||||
import SearchBar from "./components/UI/SearchBar"
|
import SearchBar from "./components/UI/SearchBar";
|
||||||
import AddRecipeFab from "./components/UI/AddRecipeFab"
|
import AddRecipeFab from "./components/UI/AddRecipeFab";
|
||||||
import SnackBar from "./components/UI/SnackBar"
|
import SnackBar from "./components/UI/SnackBar";
|
||||||
import Vuetify from "./plugins/vuetify"
|
import Vuetify from "./plugins/vuetify";
|
||||||
export default {
|
export default {
|
||||||
name: "App",
|
name: "App",
|
||||||
|
|
||||||
|
@ -51,16 +51,16 @@ export default {
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
$route() {
|
$route() {
|
||||||
this.search = false
|
this.search = false;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$store.dispatch("initTheme")
|
this.$store.dispatch("initTheme");
|
||||||
this.$store.dispatch("requestRecentRecipes")
|
this.$store.dispatch("requestRecentRecipes");
|
||||||
this.$store.dispatch("initLang")
|
this.$store.dispatch("initLang");
|
||||||
this.darkModeSystemCheck()
|
this.darkModeSystemCheck();
|
||||||
this.darkModeAddEventListener()
|
this.darkModeAddEventListener();
|
||||||
},
|
},
|
||||||
|
|
||||||
data: () => ({
|
data: () => ({
|
||||||
|
@ -74,30 +74,22 @@ export default {
|
||||||
if (this.$store.getters.getDarkMode === "system")
|
if (this.$store.getters.getDarkMode === "system")
|
||||||
Vuetify.framework.theme.dark = window.matchMedia(
|
Vuetify.framework.theme.dark = window.matchMedia(
|
||||||
"(prefers-color-scheme: dark)"
|
"(prefers-color-scheme: dark)"
|
||||||
).matches
|
).matches;
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* This will monitor the OS level darkmode and call to update dark mode.
|
* This will monitor the OS level darkmode and call to update dark mode.
|
||||||
*/
|
*/
|
||||||
darkModeAddEventListener() {
|
darkModeAddEventListener() {
|
||||||
const darkMediaQuery = window.matchMedia("(prefers-color-scheme: dark)")
|
const darkMediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
||||||
darkMediaQuery.addEventListener("change", () => {
|
darkMediaQuery.addEventListener("change", () => {
|
||||||
this.darkModeSystemCheck()
|
this.darkModeSystemCheck();
|
||||||
})
|
});
|
||||||
},
|
|
||||||
|
|
||||||
toggleSearch() {
|
|
||||||
if (this.search === true) {
|
|
||||||
this.search = false
|
|
||||||
} else {
|
|
||||||
this.search = true
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
navigateFromSearch(slug) {
|
navigateFromSearch(slug) {
|
||||||
this.$router.push(`/recipe/${slug}`)
|
this.$router.push(`/recipe/${slug}`);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
|
@ -1,79 +0,0 @@
|
||||||
<template>
|
|
||||||
<v-card-text>
|
|
||||||
<p>
|
|
||||||
{{
|
|
||||||
$t(
|
|
||||||
"migration.currently-chowdown-via-public-repo-url-is-the-only-supported-type-of-migration"
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
</p>
|
|
||||||
<v-form ref="form">
|
|
||||||
<v-row dense align="center">
|
|
||||||
<v-col cols="12" md="5" sm="5">
|
|
||||||
<v-text-field
|
|
||||||
v-model="repo"
|
|
||||||
:label="$t('migration.chowdown-repo-url')"
|
|
||||||
:rules="[rules.required]"
|
|
||||||
>
|
|
||||||
</v-text-field>
|
|
||||||
</v-col>
|
|
||||||
<v-col cols="12" md="4" sm="5">
|
|
||||||
<v-btn text color="info" @click="importRepo">
|
|
||||||
<v-icon left> mdi-import </v-icon>
|
|
||||||
{{ $t("migration.migrate") }}
|
|
||||||
</v-btn>
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
</v-form>
|
|
||||||
<v-alert v-if="failedRecipes[1]" outlined dense type="error">
|
|
||||||
<h4>{{ $t("migration.failed-recipes") }}</h4>
|
|
||||||
<v-list dense>
|
|
||||||
<v-list-item v-for="fail in this.failedRecipes" :key="fail">
|
|
||||||
{{ fail }}
|
|
||||||
</v-list-item>
|
|
||||||
</v-list>
|
|
||||||
</v-alert>
|
|
||||||
<v-alert v-if="failedImages[1]" outlined dense type="error">
|
|
||||||
<h4>{{ $t("migration.failed-images") }}</h4>
|
|
||||||
<v-list dense>
|
|
||||||
<v-list-item v-for="fail in this.failedImages" :key="fail">
|
|
||||||
{{ fail }}
|
|
||||||
</v-list-item>
|
|
||||||
</v-list>
|
|
||||||
</v-alert>
|
|
||||||
</v-card-text>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import api from "../../../api";
|
|
||||||
// import SuccessFailureAlert from "../../UI/SuccessFailureAlert";
|
|
||||||
// import TimePicker from "./Webhooks/TimePicker";
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
processRan: false,
|
|
||||||
failedImages: [],
|
|
||||||
failedRecipes: [],
|
|
||||||
repo: "",
|
|
||||||
rules: {
|
|
||||||
required: v => !!v || "Selection Required",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async importRepo() {
|
|
||||||
if (this.$refs.form.validate()) {
|
|
||||||
this.$emit("loading");
|
|
||||||
let response = await api.migrations.migrateChowdown(this.repo);
|
|
||||||
this.failedImages = response.failedImages;
|
|
||||||
this.failedRecipes = response.failedRecipes;
|
|
||||||
this.$emit("finished");
|
|
||||||
this.processRan = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
</style>
|
|
|
@ -1,112 +0,0 @@
|
||||||
<template>
|
|
||||||
<v-card-text>
|
|
||||||
<p>
|
|
||||||
{{
|
|
||||||
$t(
|
|
||||||
"migration.you-can-import-recipes-from-either-a-zip-file-or-a-directory-located-in-the-app-data-migraiton-folder-please-review-the-documentation-to-ensure-your-directory-structure-matches-what-is-expected"
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
</p>
|
|
||||||
<v-form ref="form">
|
|
||||||
<v-row align="center">
|
|
||||||
<v-col cols="12" md="5" sm="12">
|
|
||||||
<v-select
|
|
||||||
:items="availableImports"
|
|
||||||
v-model="selectedImport"
|
|
||||||
:label="$t('migration.nextcloud-data')"
|
|
||||||
:rules="[rules.required]"
|
|
||||||
></v-select>
|
|
||||||
</v-col>
|
|
||||||
<v-col md="1" sm="12">
|
|
||||||
<v-btn-toggle group>
|
|
||||||
<v-btn text color="info" @click="importRecipes">
|
|
||||||
<v-icon left> mdi-import </v-icon>
|
|
||||||
{{ $t("migration.migrate") }}
|
|
||||||
</v-btn>
|
|
||||||
<v-btn text color="error" @click="deleteImportValidation">
|
|
||||||
<v-icon left> mdi-delete </v-icon>
|
|
||||||
{{ $t("general.delete") }}
|
|
||||||
</v-btn>
|
|
||||||
<UploadBtn
|
|
||||||
url="/api/migration/upload/"
|
|
||||||
class="mt-1"
|
|
||||||
@uploaded="getAvaiableImports"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Confirmation
|
|
||||||
:title="$t('general.delete-data')"
|
|
||||||
:message="$t('migration.delete-confirmation')"
|
|
||||||
color="error"
|
|
||||||
icon="mdi-alert-circle"
|
|
||||||
ref="deleteThemeConfirm"
|
|
||||||
v-on:confirm="deleteImport()"
|
|
||||||
/>
|
|
||||||
</v-btn-toggle>
|
|
||||||
</v-col>
|
|
||||||
|
|
||||||
<v-spacer></v-spacer>
|
|
||||||
</v-row>
|
|
||||||
</v-form>
|
|
||||||
<SuccessFailureAlert
|
|
||||||
:success-header="$t('migration.successfully-imported-from-nextcloud')"
|
|
||||||
:success="successfulImports"
|
|
||||||
failed-header="$t('migration.failed-imports')"
|
|
||||||
:failed="failedImports"
|
|
||||||
/>
|
|
||||||
</v-card-text>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import api from "../../../api";
|
|
||||||
import SuccessFailureAlert from "../../UI/SuccessFailureAlert";
|
|
||||||
import Confirmation from "../../UI/Confirmation";
|
|
||||||
import UploadBtn from "../../UI/UploadBtn";
|
|
||||||
export default {
|
|
||||||
components: {
|
|
||||||
SuccessFailureAlert,
|
|
||||||
Confirmation,
|
|
||||||
UploadBtn,
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
successfulImports: [],
|
|
||||||
failedImports: [],
|
|
||||||
availableImports: [],
|
|
||||||
selectedImport: null,
|
|
||||||
rules: {
|
|
||||||
required: v => !!v || "Selection Required",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
async mounted() {
|
|
||||||
this.getAvaiableImports();
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async getAvaiableImports() {
|
|
||||||
this.availableImports = await api.migrations.getNextcloudImports();
|
|
||||||
},
|
|
||||||
async importRecipes() {
|
|
||||||
if (this.$refs.form.validate()) {
|
|
||||||
this.$emit("loading");
|
|
||||||
let data = await api.migrations.importNextcloud(this.selectedImport);
|
|
||||||
|
|
||||||
this.successfulImports = data.successful;
|
|
||||||
this.failedImports = data.failed;
|
|
||||||
this.$emit("finished");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
deleteImportValidation() {
|
|
||||||
if (this.$refs.form.validate()) {
|
|
||||||
this.$refs.deleteThemeConfirm.open();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async deleteImport() {
|
|
||||||
await api.migrations.delete(this.selectedImport);
|
|
||||||
this.getAvaiableImports();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
</style>
|
|
|
@ -1,49 +0,0 @@
|
||||||
<template>
|
|
||||||
<v-form ref="file">
|
|
||||||
<v-file-input
|
|
||||||
:loading="loading"
|
|
||||||
:label="$t('migration.upload-an-archive')"
|
|
||||||
v-model="file"
|
|
||||||
accept=".zip"
|
|
||||||
@change="upload"
|
|
||||||
:prepend-icon="icon"
|
|
||||||
class="file-icon"
|
|
||||||
>
|
|
||||||
</v-file-input>
|
|
||||||
</v-form>
|
|
||||||
</template>c
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import api from "../../../api";
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
file: null,
|
|
||||||
loading: false,
|
|
||||||
icon: "mdi-paperclip",
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async upload() {
|
|
||||||
if (this.file != null) {
|
|
||||||
this.loading = true;
|
|
||||||
let formData = new FormData();
|
|
||||||
formData.append("archive", this.file);
|
|
||||||
|
|
||||||
await api.migrations.uploadFile(formData);
|
|
||||||
|
|
||||||
this.loading = false;
|
|
||||||
this.$emit("uploaded");
|
|
||||||
this.file = null;
|
|
||||||
this.icon = "mdi-check";
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.file-icon {
|
|
||||||
transition-duration: 5s;
|
|
||||||
}
|
|
||||||
</style>
|
|
66
frontend/src/components/UI/CardSection.vue
Normal file
66
frontend/src/components/UI/CardSection.vue
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
<template>
|
||||||
|
<div class="mt-n5">
|
||||||
|
<v-card flat class="transparent mb-2" height="50px">
|
||||||
|
<v-card-text>
|
||||||
|
<v-row>
|
||||||
|
<v-col>
|
||||||
|
<v-btn-toggle group>
|
||||||
|
<v-btn text :to="`/recipes/category/${title.toLowerCase()}`">
|
||||||
|
{{ title.toUpperCase() }}
|
||||||
|
</v-btn>
|
||||||
|
</v-btn-toggle>
|
||||||
|
</v-col>
|
||||||
|
<v-spacer></v-spacer>
|
||||||
|
<v-col align="end">
|
||||||
|
<v-btn-toggle group>
|
||||||
|
<v-btn text color="accent"> Sort </v-btn>
|
||||||
|
<v-btn text color="accent"> Limit </v-btn>
|
||||||
|
</v-btn-toggle>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
<v-row>
|
||||||
|
<v-col
|
||||||
|
:sm="6"
|
||||||
|
:md="6"
|
||||||
|
:lg="4"
|
||||||
|
:xl="3"
|
||||||
|
v-for="recipe in recipes.slice(0, cardLimit)"
|
||||||
|
:key="recipe.name"
|
||||||
|
>
|
||||||
|
<RecipeCard
|
||||||
|
:name="recipe.name"
|
||||||
|
:description="recipe.description"
|
||||||
|
:slug="recipe.slug"
|
||||||
|
:rating="recipe.rating"
|
||||||
|
:image="recipe.image"
|
||||||
|
/>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import RecipeCard from "./RecipeCard";
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
RecipeCard,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
title: String,
|
||||||
|
recipes: Array,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
cardLimit: 6,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.transparent {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,40 +0,0 @@
|
||||||
<template>
|
|
||||||
<v-row>
|
|
||||||
<v-col
|
|
||||||
:sm="6"
|
|
||||||
:md="6"
|
|
||||||
:lg="4"
|
|
||||||
:xl="3"
|
|
||||||
v-for="recipe in recipes"
|
|
||||||
:key="recipe.name"
|
|
||||||
>
|
|
||||||
<RecipeCard
|
|
||||||
:name="recipe.name"
|
|
||||||
:description="recipe.description"
|
|
||||||
:slug="recipe.slug"
|
|
||||||
:rating="recipe.rating"
|
|
||||||
:image="recipe.image"
|
|
||||||
/>
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import RecipeCard from "./RecipeCard";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
components: {
|
|
||||||
RecipeCard,
|
|
||||||
},
|
|
||||||
data: () => ({}),
|
|
||||||
mounted() {},
|
|
||||||
computed: {
|
|
||||||
recipes() {
|
|
||||||
return this.$store.getters.getRecentRecipes;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
</style>
|
|
|
@ -1,15 +1,45 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<RecentRecipes />
|
<CardSection v-if="showRecent" title="Recent" :recipes="recentRecipes" />
|
||||||
|
<CardSection
|
||||||
|
v-for="section in recipeByCategory"
|
||||||
|
:key="section.title"
|
||||||
|
:title="section.title"
|
||||||
|
:recipes="section.recipes"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import RecentRecipes from "../components/UI/RecentRecipes";
|
import CardSection from "../components/UI/CardSection";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
RecentRecipes,
|
CardSection,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
showRecent: true,
|
||||||
|
recipeByCategory: [
|
||||||
|
{
|
||||||
|
title: "Title 1",
|
||||||
|
recipes: this.$store.getters.getRecentRecipes,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Title 2",
|
||||||
|
recipes: this.$store.getters.getRecentRecipes,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
recentRecipes() {
|
||||||
|
return this.$store.getters.getRecentRecipes;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getRecentRecipes() {
|
||||||
|
this.$store.dispatch("requestRecentRecipes");
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -3,7 +3,7 @@ from fastapi import FastAPI
|
||||||
from fastapi.staticfiles import StaticFiles
|
from fastapi.staticfiles import StaticFiles
|
||||||
|
|
||||||
# import utils.startup as startup
|
# import utils.startup as startup
|
||||||
from app_config import PORT, PRODUCTION, SQLITE_FILE, WEB_PATH, docs_url, redoc_url
|
from app_config import PORT, PRODUCTION, WEB_PATH, docs_url, redoc_url
|
||||||
from routes import (
|
from routes import (
|
||||||
backup_routes,
|
backup_routes,
|
||||||
meal_routes,
|
meal_routes,
|
||||||
|
@ -26,7 +26,6 @@ app = FastAPI(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def mount_static_files():
|
def mount_static_files():
|
||||||
app.mount("/static", StaticFiles(directory=WEB_PATH, html=True))
|
app.mount("/static", StaticFiles(directory=WEB_PATH, html=True))
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
from sqlalchemy.orm.session import Session
|
||||||
|
|
||||||
from db.db_base import BaseDocument
|
from db.db_base import BaseDocument
|
||||||
from db.sql.meal_models import MealPlanModel
|
from db.sql.meal_models import MealPlanModel
|
||||||
from db.sql.recipe_models import RecipeModel
|
from db.sql.recipe_models import RecipeModel
|
||||||
|
@ -16,8 +18,12 @@ class _Recipes(BaseDocument):
|
||||||
self.primary_key = "slug"
|
self.primary_key = "slug"
|
||||||
self.sql_model = RecipeModel
|
self.sql_model = RecipeModel
|
||||||
|
|
||||||
def update_image(self, slug: str, extension: str) -> None:
|
def update_image(self, session: Session, slug: str, extension: str) -> str:
|
||||||
pass
|
entry = self._query_one(session, match_value=slug)
|
||||||
|
entry.image = f"{slug}.{extension}"
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
return f"{slug}.{extension}"
|
||||||
|
|
||||||
|
|
||||||
class _Meals(BaseDocument):
|
class _Meals(BaseDocument):
|
||||||
|
@ -31,7 +37,7 @@ class _Settings(BaseDocument):
|
||||||
self.primary_key = "name"
|
self.primary_key = "name"
|
||||||
self.sql_model = SiteSettingsModel
|
self.sql_model = SiteSettingsModel
|
||||||
|
|
||||||
def save_new(self, session, main: dict, webhooks: dict) -> str:
|
def save_new(self, session: Session, main: dict, webhooks: dict) -> str:
|
||||||
new_settings = self.sql_model(main.get("name"), webhooks)
|
new_settings = self.sql_model(main.get("name"), webhooks)
|
||||||
|
|
||||||
session.add(new_settings)
|
session.add(new_settings)
|
||||||
|
@ -45,14 +51,6 @@ class _Themes(BaseDocument):
|
||||||
self.primary_key = "name"
|
self.primary_key = "name"
|
||||||
self.sql_model = SiteThemeModel
|
self.sql_model = SiteThemeModel
|
||||||
|
|
||||||
def update(self, session, data: dict) -> dict:
|
|
||||||
theme_model = self._query_one(
|
|
||||||
session=session, match_value=data["name"], match_key="name"
|
|
||||||
)
|
|
||||||
|
|
||||||
theme_model.update(**data)
|
|
||||||
session.commit()
|
|
||||||
|
|
||||||
|
|
||||||
class Database:
|
class Database:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from typing import Union
|
from typing import List, Union
|
||||||
|
|
||||||
from sqlalchemy.orm.session import Session
|
from sqlalchemy.orm.session import Session
|
||||||
|
|
||||||
|
@ -11,7 +11,10 @@ class BaseDocument:
|
||||||
self.store: str
|
self.store: str
|
||||||
self.sql_model: SqlAlchemyBase
|
self.sql_model: SqlAlchemyBase
|
||||||
|
|
||||||
def get_all(self, session: Session, limit: int = None, order_by: str = None):
|
# TODO: Improve Get All Query Functionality
|
||||||
|
def get_all(
|
||||||
|
self, session: Session, limit: int = None, order_by: str = None
|
||||||
|
) -> List[dict]:
|
||||||
list = [x.dict() for x in session.query(self.sql_model).all()]
|
list = [x.dict() for x in session.query(self.sql_model).all()]
|
||||||
|
|
||||||
if limit == 1:
|
if limit == 1:
|
||||||
|
@ -21,7 +24,7 @@ class BaseDocument:
|
||||||
|
|
||||||
def _query_one(
|
def _query_one(
|
||||||
self, session: Session, match_value: str, match_key: str = None
|
self, session: Session, match_value: str, match_key: str = None
|
||||||
) -> Union[Session, SqlAlchemyBase]:
|
) -> SqlAlchemyBase:
|
||||||
"""Query the sql database for one item an return the sql alchemy model
|
"""Query the sql database for one item an return the sql alchemy model
|
||||||
object. If no match key is provided the primary_key attribute will be used.
|
object. If no match key is provided the primary_key attribute will be used.
|
||||||
|
|
||||||
|
@ -43,7 +46,7 @@ class BaseDocument:
|
||||||
|
|
||||||
def get(
|
def get(
|
||||||
self, session: Session, match_value: str, match_key: str = None, limit=1
|
self, session: Session, match_value: str, match_key: str = None, limit=1
|
||||||
) -> dict or list[dict]:
|
) -> dict or List[dict]:
|
||||||
"""Retrieves an entry from the database by matching a key/value pair. If no
|
"""Retrieves an entry from the database by matching a key/value pair. If no
|
||||||
key is provided the class objects primary key will be used to match against.
|
key is provided the class objects primary key will be used to match against.
|
||||||
|
|
||||||
|
@ -67,6 +70,15 @@ class BaseDocument:
|
||||||
return db_entry
|
return db_entry
|
||||||
|
|
||||||
def save_new(self, session: Session, document: dict) -> dict:
|
def save_new(self, session: Session, document: dict) -> dict:
|
||||||
|
"""Creates a new database entry for the given SQL Alchemy Model.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
session (Session): A Database Session
|
||||||
|
document (dict): A python dictionary representing the data structure
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: A dictionary representation of the database entry
|
||||||
|
"""
|
||||||
new_document = self.sql_model(**document)
|
new_document = self.sql_model(**document)
|
||||||
session.add(new_document)
|
session.add(new_document)
|
||||||
return_data = new_document.dict()
|
return_data = new_document.dict()
|
||||||
|
@ -74,7 +86,18 @@ class BaseDocument:
|
||||||
|
|
||||||
return return_data
|
return return_data
|
||||||
|
|
||||||
def update(self, session: Session, match_value, new_data) -> dict:
|
def update(self, session: Session, match_value: str, new_data: str) -> dict:
|
||||||
|
"""Update a database entry.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
session (Session): Database Session
|
||||||
|
match_value (str): Match "key"
|
||||||
|
new_data (str): Match "value"
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: Returns a dictionary representation of the database entry
|
||||||
|
"""
|
||||||
|
|
||||||
entry = self._query_one(session=session, match_value=match_value)
|
entry = self._query_one(session=session, match_value=match_value)
|
||||||
entry.update(session=session, **new_data)
|
entry.update(session=session, **new_data)
|
||||||
return_data = entry.dict()
|
return_data = entry.dict()
|
||||||
|
|
|
@ -12,7 +12,7 @@ class SiteThemeModel(SqlAlchemyBase):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.colors = ThemeColorsModel(**colors)
|
self.colors = ThemeColorsModel(**colors)
|
||||||
|
|
||||||
def update(self, name, colors: dict) -> dict:
|
def update(self, session=None, name: str = None, colors: dict = None) -> dict:
|
||||||
self.colors.update(**colors)
|
self.colors.update(**colors)
|
||||||
return self.dict()
|
return self.dict()
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,6 @@ def get_recipe_img(recipe_slug: str):
|
||||||
return FileResponse(recipe_image)
|
return FileResponse(recipe_image)
|
||||||
|
|
||||||
|
|
||||||
# Recipe Creations
|
|
||||||
@router.post(
|
@router.post(
|
||||||
"/api/recipe/create-url/",
|
"/api/recipe/create-url/",
|
||||||
status_code=201,
|
status_code=201,
|
||||||
|
|
|
@ -82,15 +82,6 @@ class Recipe(BaseModel):
|
||||||
slug = calc_slug
|
slug = calc_slug
|
||||||
return slug
|
return slug
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def _unpack_doc(cls, document):
|
|
||||||
document = json.loads(document.to_json())
|
|
||||||
del document["_id"]
|
|
||||||
|
|
||||||
document["dateAdded"] = document["dateAdded"]["$date"]
|
|
||||||
|
|
||||||
return cls(**document)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_by_slug(cls, session, slug: str):
|
def get_by_slug(cls, session, slug: str):
|
||||||
""" Returns a Recipe Object by Slug """
|
""" Returns a Recipe Object by Slug """
|
||||||
|
@ -132,8 +123,15 @@ class Recipe(BaseModel):
|
||||||
return updated_slug.get("slug")
|
return updated_slug.get("slug")
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def update_image(slug: str, extension: str):
|
def update_image(slug: str, extension: str) -> str:
|
||||||
db.recipes.update_image(slug, extension)
|
"""A helper function to pass the new image name and extension
|
||||||
|
into the database.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
slug (str): The current recipe slug
|
||||||
|
extension (str): the file extension of the new image
|
||||||
|
"""
|
||||||
|
return db.recipes.update_image(slug, extension)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_all(session: Session):
|
def get_all(session: Session):
|
||||||
|
|
|
@ -103,7 +103,7 @@ class SiteTheme(BaseModel):
|
||||||
db.themes.save_new(session, self.dict())
|
db.themes.save_new(session, self.dict())
|
||||||
|
|
||||||
def update_document(self, session: Session):
|
def update_document(self, session: Session):
|
||||||
db.themes.update(session, self.dict())
|
db.themes.update(session, self.name, self.dict())
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def delete_theme(session: Session, theme_name: str) -> str:
|
def delete_theme(session: Session, theme_name: str) -> str:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue