mirror of
https://github.com/TandoorRecipes/recipes.git
synced 2025-12-24 02:39:20 -05:00
baisc implementation of books WIP
This commit is contained in:
@@ -1073,6 +1073,7 @@ class CustomFilterSerializer(SpacedModelSerializer, WritableNestedModelSerialize
|
||||
|
||||
|
||||
class RecipeBookSerializer(SpacedModelSerializer, WritableNestedModelSerializer):
|
||||
created_by = UserSerializer(read_only=True)
|
||||
shared = UserSerializer(many=True)
|
||||
filter = CustomFilterSerializer(allow_null=True, required=False)
|
||||
|
||||
|
||||
@@ -114,10 +114,11 @@
|
||||
<v-list-item-subtitle>{{ useUserPreferenceStore().activeSpace.name }}</v-list-item-subtitle>
|
||||
</v-list-item>
|
||||
<v-divider></v-divider>
|
||||
<v-list-item prepend-icon="fas fa-book" title="Home" :to="{ name: 'view_home', params: {} }"></v-list-item>
|
||||
<v-list-item prepend-icon="fas fa-calendar-alt" :title="$t('Meal_Plan')" :to="{ name: 'view_mealplan', params: {} }"></v-list-item>
|
||||
<v-list-item prepend-icon="fas fa-shopping-cart" :title="$t('Shopping_list')" :to="{ name: 'view_shopping', params: {} }"></v-list-item>
|
||||
<v-list-item prepend-icon="$recipes" title="Home" :to="{ name: 'view_home', params: {} }"></v-list-item>
|
||||
<v-list-item prepend-icon="$mealplan" :title="$t('Meal_Plan')" :to="{ name: 'view_mealplan', params: {} }"></v-list-item>
|
||||
<v-list-item prepend-icon="$shopping" :title="$t('Shopping_list')" :to="{ name: 'view_shopping', params: {} }"></v-list-item>
|
||||
<v-list-item prepend-icon="fas fa-globe" :title="$t('Import')" :to="{ name: 'RecipeImportPage', params: {} }"></v-list-item>
|
||||
<v-list-item prepend-icon="$books" :title="$t('Books')" :to="{ name: 'BooksPage', params: {} }"></v-list-item>
|
||||
<v-list-item prepend-icon="fa-solid fa-folder-tree" :title="$t('Database')" :to="{ name: 'ModelListPage', params: {model: 'food'} }"></v-list-item>
|
||||
|
||||
<navigation-drawer-context-menu></navigation-drawer-context-menu>
|
||||
|
||||
@@ -28,6 +28,7 @@ import ModelListPage from "@/pages/ModelListPage.vue";
|
||||
import ModelEditPage from "@/pages/ModelEditPage.vue";
|
||||
import RecipeImportPage from "@/pages/RecipeImportPage.vue";
|
||||
import IngredientEditorPage from "@/pages/IngredientEditorPage.vue";
|
||||
import BooksPage from "@/pages/BooksPage.vue";
|
||||
|
||||
const routes = [
|
||||
{path: '/', component: StartPage, name: 'view_home'},
|
||||
@@ -49,7 +50,7 @@ const routes = [
|
||||
{path: '/search', component: SearchPage, name: 'view_search'},
|
||||
{path: '/shopping', component: ShoppingListPage, name: 'view_shopping'},
|
||||
{path: '/mealplan', component: MealPlanPage, name: 'view_mealplan'},
|
||||
{path: '/books', component: ShoppingListPage, name: 'view_books'},
|
||||
{path: '/books', component: BooksPage, name: 'BooksPage'},
|
||||
{path: '/recipe/import', component: RecipeImportPage, name: 'RecipeImportPage'},
|
||||
|
||||
{path: '/recipe/:id', component: RecipeViewPage, name: 'view_recipe', props: true},
|
||||
|
||||
@@ -9,55 +9,139 @@
|
||||
:is-changed="editingObjChanged"
|
||||
:model-class="modelClass"
|
||||
:object-name="editingObjName()">
|
||||
<v-card-text>
|
||||
<v-form :disabled="loading">
|
||||
<v-row>
|
||||
<v-col cols="10">
|
||||
<v-text-field label="Token" v-model="editingObj.token" disabled></v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="2">
|
||||
<btn-copy :copy-value="editingObj.token" class="me-1"></btn-copy>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-text-field label="Scope" v-model="editingObj.scope"></v-text-field>
|
||||
<v-date-input :label="$t('Valid Until')" v-model="editingObj.expires"></v-date-input>
|
||||
</v-form>
|
||||
<v-tabs v-model="tab" :disabled="loading" grow>
|
||||
<v-tab value="book">{{ $t('Book') }}</v-tab>
|
||||
<v-tab value="recipes" :disabled="!isUpdate()">{{ $t('Recipes') }}</v-tab>
|
||||
</v-tabs>
|
||||
|
||||
<v-card-text>
|
||||
<v-tabs-window v-model="tab">
|
||||
|
||||
<v-tabs-window-item value="book">
|
||||
|
||||
<v-form :disabled="loading">
|
||||
<v-text-field :label="$t('Name')" v-model="editingObj.name"></v-text-field>
|
||||
<v-textarea :label="$t('Description')" v-model="editingObj.description" rows="3"></v-textarea>
|
||||
<model-select model="User" v-model="editingObj.shared" mode="tags"></model-select>
|
||||
<model-select model="CustomFilter" v-model="editingObj.filter"></model-select>
|
||||
<v-number-input :label="$t('Order')" :hint="$t('OrderInformation')" v-model="editingObj.order"></v-number-input>
|
||||
</v-form>
|
||||
</v-tabs-window-item>
|
||||
|
||||
<v-tabs-window-item value="recipes">
|
||||
<model-select model="Recipe" v-model="selectedRecipe">
|
||||
<template #append>
|
||||
<v-btn @click="addRecipeToBook()">
|
||||
<v-icon icon="$create"></v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
</model-select>
|
||||
<v-data-table-server
|
||||
@update:options="loadRecipeBookEntries"
|
||||
:items="recipeBookEntries"
|
||||
:headers="tableHeaders"
|
||||
:items-length="itemCount"
|
||||
>
|
||||
|
||||
</v-data-table-server>
|
||||
</v-tabs-window-item>
|
||||
</v-tabs-window>
|
||||
|
||||
|
||||
</v-card-text>
|
||||
</model-editor-base>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
||||
import {VDateInput} from 'vuetify/labs/VDateInput' //TODO remove once component is out of labs
|
||||
import {onMounted, PropType} from "vue";
|
||||
import {AccessToken} from "@/openapi";
|
||||
|
||||
import {DateTime} from "luxon";
|
||||
import BtnCopy from "@/components/buttons/BtnCopy.vue";
|
||||
import {VNumberInput} from 'vuetify/labs/VNumberInput'
|
||||
import {onMounted, PropType, ref} from "vue";
|
||||
import {ApiApi, Recipe, RecipeBook, RecipeBookEntry, User} from "@/openapi";
|
||||
import {VDataTableUpdateOptions} from "@/vuetify";
|
||||
|
||||
import {useModelEditorFunctions} from "@/composables/useModelEditorFunctions";
|
||||
import ModelEditorBase from "@/components/model_editors/ModelEditorBase.vue";
|
||||
import ModelSelect from "@/components/inputs/ModelSelect.vue";
|
||||
import {ErrorMessageType, useMessageStore} from "@/stores/MessageStore";
|
||||
import {useUserPreferenceStore} from "@/stores/UserPreferenceStore";
|
||||
import {useI18n} from "vue-i18n";
|
||||
|
||||
const props = defineProps({
|
||||
item: {type: {} as PropType<AccessToken>, required: false, default: null},
|
||||
item: {type: {} as PropType<RecipeBook>, required: false, default: null},
|
||||
itemId: {type: [Number, String], required: false, default: undefined},
|
||||
dialog: {type: Boolean, default: false}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['create', 'save', 'delete', 'close'])
|
||||
const {setupState, deleteObject, saveObject, isUpdate, editingObjName, loading, editingObj, editingObjChanged, modelClass} = useModelEditorFunctions<AccessToken>('AccessToken', emit)
|
||||
const {setupState, deleteObject, saveObject, isUpdate, editingObjName, loading, editingObj, editingObjChanged, modelClass} = useModelEditorFunctions<RecipeBook>('RecipeBook', emit)
|
||||
|
||||
const {t} = useI18n()
|
||||
const tab = ref("book")
|
||||
const recipeBookEntries = ref([] as RecipeBookEntry[])
|
||||
|
||||
const selectedRecipe = ref({} as Recipe)
|
||||
|
||||
const tablePage = ref(1)
|
||||
const itemCount = ref(0)
|
||||
|
||||
const tableHeaders = [
|
||||
{title: t('Name'), key: 'recipeContent.name', },
|
||||
{key: 'action', width: '1%', noBreak: true, align: 'end'},
|
||||
]
|
||||
|
||||
onMounted(() => {
|
||||
setupState(props.item, props.itemId, {
|
||||
newItemFunction: () => {
|
||||
editingObj.value.expires = DateTime.now().plus({year: 1}).toJSDate()
|
||||
editingObj.value.scope = 'read write'
|
||||
editingObj.value.shared = [] as User[]
|
||||
recipeBookEntries.value = []
|
||||
},
|
||||
existingItemFunction: () => {
|
||||
recipeBookEntries.value = []
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
function addRecipeToBook() {
|
||||
let api = new ApiApi()
|
||||
// TODO check both for null, handle errors
|
||||
|
||||
api.apiRecipeBookEntryCreate({recipeBookEntry: {book: editingObj.value.id!, recipe: selectedRecipe.value.id!}}).then(r => {
|
||||
recipeBookEntries.value.push(r) // TODO or reload ?
|
||||
selectedRecipe.value = {} as Recipe
|
||||
}).catch(err => {
|
||||
useMessageStore().addError(ErrorMessageType.CREATE_ERROR, err)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* load items from API whenever the table calls for it
|
||||
* parameters defined by vuetify
|
||||
* @param options
|
||||
*/
|
||||
function loadRecipeBookEntries(options: VDataTableUpdateOptions) {
|
||||
let api = new ApiApi()
|
||||
|
||||
loading.value = true
|
||||
window.scrollTo({top: 0, behavior: 'smooth'})
|
||||
|
||||
if (tablePage.value != options.page) {
|
||||
tablePage.value = options.page
|
||||
}
|
||||
|
||||
useUserPreferenceStore().deviceSettings.general_tableItemsPerPage = options.itemsPerPage
|
||||
|
||||
api.apiRecipeBookEntryList({page: options.page, pageSize: options.itemsPerPage,}).then((r: any) => {
|
||||
recipeBookEntries.value = r.results
|
||||
itemCount.value = r.count
|
||||
}).catch((err: any) => {
|
||||
useMessageStore().addError(ErrorMessageType.FETCH_ERROR, err)
|
||||
}).finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
"AvailableCategories": "",
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "",
|
||||
"Books": "",
|
||||
"Calories": "",
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
"AvailableCategories": "",
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "Книжен пазар",
|
||||
"Books": "Книги",
|
||||
"Calories": "Калории",
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
"Back": "",
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "",
|
||||
"Books": "",
|
||||
"Calculator": "",
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
"Back": "Zpět",
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "Skript v záložce",
|
||||
"Books": "Kuchařky",
|
||||
"Calculator": "Kalkulačka",
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
"Back": "Tilbage",
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "Bogmærke",
|
||||
"Books": "Bøger",
|
||||
"Calories": "Kalorier",
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
"Back": "Zurück",
|
||||
"BaseUnit": "Basiseinheit",
|
||||
"BaseUnitHelp": "Optionale Standardeinheit zur automatischen Umrechnung",
|
||||
"Book": "Buch",
|
||||
"Bookmarklet": "Lesezeichen",
|
||||
"Books": "Kochbücher",
|
||||
"Calculator": "Rechner",
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
"Back": "Πίσω",
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "Bookmarklet",
|
||||
"Books": "Βιβλία",
|
||||
"Calories": "Θερμίδες",
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
"Back": "Back",
|
||||
"BaseUnit": "Base Unit",
|
||||
"BaseUnitHelp": "Standard unit for automatic unit conversion",
|
||||
"Book": "Book",
|
||||
"Bookmarklet": "Bookmarklet",
|
||||
"Books": "Books",
|
||||
"Calculator": "Calculator",
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
"Back": "Atrás",
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "Marcadores",
|
||||
"Books": "Libros",
|
||||
"Calculator": "Calculadora",
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
"AvailableCategories": "",
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Books": "Kirjat",
|
||||
"Calories": "Kalorit",
|
||||
"Cancel": "Peruuta",
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
"Back": "Retour",
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "Signet",
|
||||
"Books": "Livres",
|
||||
"Calculator": "Calculatrice",
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
"Back": "חזור",
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "סימניה",
|
||||
"Books": "ספרים",
|
||||
"Calculator": "מחשבון",
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
"Back": "Vissza",
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "Könyvjelző",
|
||||
"Books": "Könyvek",
|
||||
"Calories": "Kalóriák",
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
"AvailableCategories": "",
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Books": "",
|
||||
"Calories": "",
|
||||
"Cancel": "",
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
"AvailableCategories": "",
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "",
|
||||
"Books": "Buku",
|
||||
"Calories": "Kalori",
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
"Back": "",
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "",
|
||||
"Books": "",
|
||||
"Calculator": "",
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
"AvailableCategories": "",
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "Segnalibro",
|
||||
"Books": "Libri",
|
||||
"Calories": "Calorie",
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
"Back": "",
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "",
|
||||
"Books": "",
|
||||
"Calories": "",
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
"AvailableCategories": "",
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "",
|
||||
"Books": "Bøker",
|
||||
"Calories": "Kalorier",
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
"Back": "Terug",
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "Bladwijzer",
|
||||
"Books": "Boeken",
|
||||
"Calories": "Calorieën",
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
"Back": "Z powrotem",
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "Skryptozakładka",
|
||||
"Books": "Książki",
|
||||
"Calculator": "Kalkulator",
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
"AvailableCategories": "",
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Books": "Livros",
|
||||
"Calories": "Calorias",
|
||||
"Cancel": "Cancelar",
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
"Back": "Voltar",
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Books": "Livros",
|
||||
"Calculator": "Calculadora",
|
||||
"Calories": "Calorias",
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
"AvailableCategories": "",
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "Marcaj",
|
||||
"Books": "Cărți",
|
||||
"Calories": "Calorii",
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
"AvailableCategories": "",
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Books": "Книги",
|
||||
"Calories": "Каллории",
|
||||
"Cancel": "Отменить",
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
"AvailableCategories": "",
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Books": "Knjige",
|
||||
"Calories": "Kalorije",
|
||||
"Cancel": "Prekini",
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
"Back": "Tillbaka",
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "Bokmärke",
|
||||
"Books": "Böcker",
|
||||
"Calculator": "Räknare",
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
"Back": "Geri",
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "Yer İmi",
|
||||
"Books": "Kitaplar",
|
||||
"Calculator": "Hesap Makinesi",
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
"AvailableCategories": "",
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "",
|
||||
"Books": "Книжки",
|
||||
"Calories": "Калорії",
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
"Back": "后退",
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "书签",
|
||||
"Books": "书籍",
|
||||
"Calories": "卡路里",
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
"AvailableCategories": "",
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Books": "",
|
||||
"Calories": "",
|
||||
"Cancel": "",
|
||||
|
||||
@@ -7,8 +7,6 @@ models/AccessToken.ts
|
||||
models/AuthToken.ts
|
||||
models/AutoMealPlan.ts
|
||||
models/Automation.ts
|
||||
models/AutomationTypeEnum.ts
|
||||
models/BaseUnitEnum.ts
|
||||
models/BookmarkletImport.ts
|
||||
models/BookmarkletImportList.ts
|
||||
models/ConnectorConfigConfig.ts
|
||||
@@ -33,16 +31,6 @@ models/MealPlan.ts
|
||||
models/MealType.ts
|
||||
models/MethodEnum.ts
|
||||
models/NutritionInformation.ts
|
||||
models/OpenDataCategory.ts
|
||||
models/OpenDataConversion.ts
|
||||
models/OpenDataFood.ts
|
||||
models/OpenDataFoodProperty.ts
|
||||
models/OpenDataProperty.ts
|
||||
models/OpenDataStore.ts
|
||||
models/OpenDataStoreCategory.ts
|
||||
models/OpenDataUnit.ts
|
||||
models/OpenDataUnitTypeEnum.ts
|
||||
models/OpenDataVersion.ts
|
||||
models/PaginatedAutomationList.ts
|
||||
models/PaginatedBookmarkletImportListList.ts
|
||||
models/PaginatedCookLogList.ts
|
||||
@@ -89,13 +77,6 @@ models/PatchedInviteLink.ts
|
||||
models/PatchedKeyword.ts
|
||||
models/PatchedMealPlan.ts
|
||||
models/PatchedMealType.ts
|
||||
models/PatchedOpenDataCategory.ts
|
||||
models/PatchedOpenDataConversion.ts
|
||||
models/PatchedOpenDataFood.ts
|
||||
models/PatchedOpenDataProperty.ts
|
||||
models/PatchedOpenDataStore.ts
|
||||
models/PatchedOpenDataUnit.ts
|
||||
models/PatchedOpenDataVersion.ts
|
||||
models/PatchedProperty.ts
|
||||
models/PatchedPropertyType.ts
|
||||
models/PatchedRecipe.ts
|
||||
@@ -155,6 +136,7 @@ models/SupermarketCategoryRelation.ts
|
||||
models/Sync.ts
|
||||
models/SyncLog.ts
|
||||
models/ThemeEnum.ts
|
||||
models/TypeEnum.ts
|
||||
models/Unit.ts
|
||||
models/UnitConversion.ts
|
||||
models/User.ts
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -13,13 +13,13 @@
|
||||
*/
|
||||
|
||||
import { mapValues } from '../runtime';
|
||||
import type { AutomationTypeEnum } from './AutomationTypeEnum';
|
||||
import type { TypeEnum } from './TypeEnum';
|
||||
import {
|
||||
AutomationTypeEnumFromJSON,
|
||||
AutomationTypeEnumFromJSONTyped,
|
||||
AutomationTypeEnumToJSON,
|
||||
AutomationTypeEnumToJSONTyped,
|
||||
} from './AutomationTypeEnum';
|
||||
TypeEnumFromJSON,
|
||||
TypeEnumFromJSONTyped,
|
||||
TypeEnumToJSON,
|
||||
TypeEnumToJSONTyped,
|
||||
} from './TypeEnum';
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -35,10 +35,10 @@ export interface Automation {
|
||||
id?: number;
|
||||
/**
|
||||
*
|
||||
* @type {AutomationTypeEnum}
|
||||
* @type {TypeEnum}
|
||||
* @memberof Automation
|
||||
*/
|
||||
type: AutomationTypeEnum;
|
||||
type: TypeEnum;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
@@ -111,7 +111,7 @@ export function AutomationFromJSONTyped(json: any, ignoreDiscriminator: boolean)
|
||||
return {
|
||||
|
||||
'id': json['id'] == null ? undefined : json['id'],
|
||||
'type': AutomationTypeEnumFromJSON(json['type']),
|
||||
'type': TypeEnumFromJSON(json['type']),
|
||||
'name': json['name'] == null ? undefined : json['name'],
|
||||
'description': json['description'] == null ? undefined : json['description'],
|
||||
'param1': json['param_1'] == null ? undefined : json['param_1'],
|
||||
@@ -135,7 +135,7 @@ export function AutomationToJSONTyped(value?: Omit<Automation, 'created_by'> | n
|
||||
return {
|
||||
|
||||
'id': value['id'],
|
||||
'type': AutomationTypeEnumToJSON(value['type']),
|
||||
'type': TypeEnumToJSON(value['type']),
|
||||
'name': value['name'],
|
||||
'description': value['description'],
|
||||
'param_1': value['param1'],
|
||||
|
||||
@@ -13,13 +13,13 @@
|
||||
*/
|
||||
|
||||
import { mapValues } from '../runtime';
|
||||
import type { AutomationTypeEnum } from './AutomationTypeEnum';
|
||||
import type { TypeEnum } from './TypeEnum';
|
||||
import {
|
||||
AutomationTypeEnumFromJSON,
|
||||
AutomationTypeEnumFromJSONTyped,
|
||||
AutomationTypeEnumToJSON,
|
||||
AutomationTypeEnumToJSONTyped,
|
||||
} from './AutomationTypeEnum';
|
||||
TypeEnumFromJSON,
|
||||
TypeEnumFromJSONTyped,
|
||||
TypeEnumToJSON,
|
||||
TypeEnumToJSONTyped,
|
||||
} from './TypeEnum';
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -35,10 +35,10 @@ export interface PatchedAutomation {
|
||||
id?: number;
|
||||
/**
|
||||
*
|
||||
* @type {AutomationTypeEnum}
|
||||
* @type {TypeEnum}
|
||||
* @memberof PatchedAutomation
|
||||
*/
|
||||
type?: AutomationTypeEnum;
|
||||
type?: TypeEnum;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
@@ -109,7 +109,7 @@ export function PatchedAutomationFromJSONTyped(json: any, ignoreDiscriminator: b
|
||||
return {
|
||||
|
||||
'id': json['id'] == null ? undefined : json['id'],
|
||||
'type': json['type'] == null ? undefined : AutomationTypeEnumFromJSON(json['type']),
|
||||
'type': json['type'] == null ? undefined : TypeEnumFromJSON(json['type']),
|
||||
'name': json['name'] == null ? undefined : json['name'],
|
||||
'description': json['description'] == null ? undefined : json['description'],
|
||||
'param1': json['param_1'] == null ? undefined : json['param_1'],
|
||||
@@ -133,7 +133,7 @@ export function PatchedAutomationToJSONTyped(value?: Omit<PatchedAutomation, 'cr
|
||||
return {
|
||||
|
||||
'id': value['id'],
|
||||
'type': AutomationTypeEnumToJSON(value['type']),
|
||||
'type': TypeEnumToJSON(value['type']),
|
||||
'name': value['name'],
|
||||
'description': value['description'],
|
||||
'param_1': value['param1'],
|
||||
|
||||
@@ -60,10 +60,10 @@ export interface PatchedRecipeBook {
|
||||
shared?: Array<User>;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @type {User}
|
||||
* @memberof PatchedRecipeBook
|
||||
*/
|
||||
readonly createdBy?: number;
|
||||
readonly createdBy?: User;
|
||||
/**
|
||||
*
|
||||
* @type {CustomFilter}
|
||||
@@ -99,7 +99,7 @@ export function PatchedRecipeBookFromJSONTyped(json: any, ignoreDiscriminator: b
|
||||
'name': json['name'] == null ? undefined : json['name'],
|
||||
'description': json['description'] == null ? undefined : json['description'],
|
||||
'shared': json['shared'] == null ? undefined : ((json['shared'] as Array<any>).map(UserFromJSON)),
|
||||
'createdBy': json['created_by'] == null ? undefined : json['created_by'],
|
||||
'createdBy': json['created_by'] == null ? undefined : UserFromJSON(json['created_by']),
|
||||
'filter': json['filter'] == null ? undefined : CustomFilterFromJSON(json['filter']),
|
||||
'order': json['order'] == null ? undefined : json['order'],
|
||||
};
|
||||
|
||||
@@ -60,10 +60,10 @@ export interface RecipeBook {
|
||||
shared: Array<User>;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @type {User}
|
||||
* @memberof RecipeBook
|
||||
*/
|
||||
readonly createdBy: number;
|
||||
readonly createdBy: User;
|
||||
/**
|
||||
*
|
||||
* @type {CustomFilter}
|
||||
@@ -102,7 +102,7 @@ export function RecipeBookFromJSONTyped(json: any, ignoreDiscriminator: boolean)
|
||||
'name': json['name'],
|
||||
'description': json['description'] == null ? undefined : json['description'],
|
||||
'shared': ((json['shared'] as Array<any>).map(UserFromJSON)),
|
||||
'createdBy': json['created_by'],
|
||||
'createdBy': UserFromJSON(json['created_by']),
|
||||
'filter': json['filter'] == null ? undefined : CustomFilterFromJSON(json['filter']),
|
||||
'order': json['order'] == null ? undefined : json['order'],
|
||||
};
|
||||
|
||||
@@ -4,8 +4,6 @@ export * from './AccessToken';
|
||||
export * from './AuthToken';
|
||||
export * from './AutoMealPlan';
|
||||
export * from './Automation';
|
||||
export * from './AutomationTypeEnum';
|
||||
export * from './BaseUnitEnum';
|
||||
export * from './BookmarkletImport';
|
||||
export * from './BookmarkletImportList';
|
||||
export * from './ConnectorConfigConfig';
|
||||
@@ -30,16 +28,6 @@ export * from './MealPlan';
|
||||
export * from './MealType';
|
||||
export * from './MethodEnum';
|
||||
export * from './NutritionInformation';
|
||||
export * from './OpenDataCategory';
|
||||
export * from './OpenDataConversion';
|
||||
export * from './OpenDataFood';
|
||||
export * from './OpenDataFoodProperty';
|
||||
export * from './OpenDataProperty';
|
||||
export * from './OpenDataStore';
|
||||
export * from './OpenDataStoreCategory';
|
||||
export * from './OpenDataUnit';
|
||||
export * from './OpenDataUnitTypeEnum';
|
||||
export * from './OpenDataVersion';
|
||||
export * from './PaginatedAutomationList';
|
||||
export * from './PaginatedBookmarkletImportListList';
|
||||
export * from './PaginatedCookLogList';
|
||||
@@ -86,13 +74,6 @@ export * from './PatchedInviteLink';
|
||||
export * from './PatchedKeyword';
|
||||
export * from './PatchedMealPlan';
|
||||
export * from './PatchedMealType';
|
||||
export * from './PatchedOpenDataCategory';
|
||||
export * from './PatchedOpenDataConversion';
|
||||
export * from './PatchedOpenDataFood';
|
||||
export * from './PatchedOpenDataProperty';
|
||||
export * from './PatchedOpenDataStore';
|
||||
export * from './PatchedOpenDataUnit';
|
||||
export * from './PatchedOpenDataVersion';
|
||||
export * from './PatchedProperty';
|
||||
export * from './PatchedPropertyType';
|
||||
export * from './PatchedRecipe';
|
||||
@@ -152,6 +133,7 @@ export * from './SupermarketCategoryRelation';
|
||||
export * from './Sync';
|
||||
export * from './SyncLog';
|
||||
export * from './ThemeEnum';
|
||||
export * from './TypeEnum';
|
||||
export * from './Unit';
|
||||
export * from './UnitConversion';
|
||||
export * from './User';
|
||||
|
||||
@@ -1,40 +1,61 @@
|
||||
<template>
|
||||
<v-container>
|
||||
<horizontal-meal-plan-window></horizontal-meal-plan-window>
|
||||
|
||||
<v-card v-if="totalRecipes == 0" class="mt-5 mb-5">
|
||||
<v-card-title><i class="fa-solid fa-eye-slash"></i> {{ $t('search_no_recipes') }}</v-card-title>
|
||||
<v-card-text>
|
||||
<v-btn-group divided>
|
||||
<v-btn size="large" color="success" prepend-icon="$create" :to="{ name: 'ModelEditPage', params: {model: 'recipe'} }">{{ $t('Create Recipe') }}</v-btn>
|
||||
<v-btn size="large" color="primary" prepend-icon="fa-solid fa-globe" :to="{ name: 'RecipeImportPage', params: {} }">{{ $t('Import Recipe') }}</v-btn>
|
||||
</v-btn-group>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
|
||||
<horizontal-recipe-scroller :skeletons="4" mode="recent"></horizontal-recipe-scroller>
|
||||
<horizontal-recipe-scroller :skeletons="4" mode="new"></horizontal-recipe-scroller>
|
||||
<horizontal-recipe-scroller :skeletons="4" mode="keyword"></horizontal-recipe-scroller>
|
||||
<horizontal-recipe-scroller :skeletons="4" mode="random"></horizontal-recipe-scroller>
|
||||
<horizontal-recipe-scroller :skeletons="2" mode="rating"></horizontal-recipe-scroller>
|
||||
<horizontal-recipe-scroller :skeletons="4" mode="keyword"></horizontal-recipe-scroller>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" md="6" offset-md="3">
|
||||
<v-text-field>
|
||||
<template #append>
|
||||
<v-btn icon color="create">
|
||||
<v-icon icon="$create"></v-icon>
|
||||
<model-edit-dialog model="RecipeBook" @create="(arg: RecipeBook) => {books.push(arg)}"></model-edit-dialog>
|
||||
</v-btn>
|
||||
</template>
|
||||
</v-text-field>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row>
|
||||
<v-col cols="12" md="3" v-for="(b, i) in books">
|
||||
<v-card>
|
||||
<v-card-title>
|
||||
<v-icon icon="$books" size="small"></v-icon>
|
||||
{{ b.name }}
|
||||
</v-card-title>
|
||||
<v-card-subtitle>{{ b.createdBy.displayName }}</v-card-subtitle>
|
||||
<v-card-text>
|
||||
{{ b.description }}
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-btn>
|
||||
{{ $t('Edit') }}
|
||||
<model-edit-dialog model="RecipeBook" :item="books[i]"
|
||||
@delete="(arg: RecipeBook) => { books.splice(books.findIndex((value: RecipeBook) => value.id == arg.id!),1)}"></model-edit-dialog>
|
||||
</v-btn>
|
||||
<v-btn>
|
||||
{{ $t('View') }}
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {onMounted, ref} from "vue"
|
||||
import {ApiApi} from "@/openapi"
|
||||
import HorizontalRecipeScroller from "@/components/display/HorizontalRecipeWindow.vue"
|
||||
import HorizontalMealPlanWindow from "@/components/display/HorizontalMealPlanWindow.vue"
|
||||
|
||||
const totalRecipes = ref(-1)
|
||||
|
||||
import {onMounted, ref} from "vue";
|
||||
import {ApiApi, RecipeBook} from "@/openapi";
|
||||
import {ErrorMessageType, useMessageStore} from "@/stores/MessageStore";
|
||||
import ModelEditDialog from "@/components/dialogs/ModelEditDialog.vue";
|
||||
|
||||
const books = ref([] as RecipeBook[])
|
||||
|
||||
onMounted(() => {
|
||||
const api = new ApiApi()
|
||||
|
||||
api.apiRecipeList({pageSize: 1}).then((r) => {
|
||||
totalRecipes.value = r.count
|
||||
api.apiRecipeBookList().then(r => {
|
||||
books.value = r.results
|
||||
}).catch(err => {
|
||||
useMessageStore().addError(ErrorMessageType.FETCH_ERROR)
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -302,7 +302,7 @@ registerModel(TMealPlan)
|
||||
export const TRecipeBook = {
|
||||
name: 'RecipeBook',
|
||||
localizationKey: 'Recipe_Book',
|
||||
icon: 'fa-solid fa-book-open',
|
||||
icon: 'fa-solid fa-book-bookmark',
|
||||
|
||||
isPaginated: true,
|
||||
toStringKeys: ['name'],
|
||||
@@ -319,7 +319,7 @@ registerModel(TRecipeBook)
|
||||
export const TRecipeBookEntry = {
|
||||
name: 'RecipeBookEntry',
|
||||
localizationKey: 'Recipe_Book',
|
||||
icon: 'fa-solid fa-book-open',
|
||||
icon: 'fa-solid fa-book-bookmark',
|
||||
|
||||
isPaginated: true,
|
||||
toStringKeys: ['book.name', 'recipe.name'],
|
||||
|
||||
@@ -81,7 +81,7 @@ export default createVuetify({
|
||||
shopping: 'fa-solid fa-cart-shopping',
|
||||
mealplan: 'fa-solid fa-calendar-days',
|
||||
recipes: 'fa-solid fa-book',
|
||||
books: 'fa-solid fa-book-open',
|
||||
books: 'fa-solid fa-book-bookmark',
|
||||
menu: 'fa-solid fa-ellipsis-vertical'
|
||||
},
|
||||
sets: {
|
||||
|
||||
Reference in New Issue
Block a user