wip shopping dialog

This commit is contained in:
vabene1111
2024-12-22 18:36:56 +01:00
parent d611391bea
commit e0223e0c5c
13 changed files with 520 additions and 42 deletions

View File

@@ -1139,7 +1139,7 @@ class MealPlanSerializer(SpacedModelSerializer, WritableNestedModelSerializer):
fields = (
'id', 'title', 'recipe', 'servings', 'note', 'note_markdown',
'from_date', 'to_date', 'meal_type', 'created_by', 'shared', 'recipe_name',
'meal_type_name', 'shopping','addshopping'
'meal_type_name', 'shopping', 'addshopping'
)
read_only_fields = ('created_by',)
@@ -1155,26 +1155,12 @@ class AutoMealPlanSerializer(serializers.Serializer):
class ShoppingListRecipeSerializer(serializers.ModelSerializer):
name = serializers.SerializerMethodField('get_name') # should this be done at the front end?
recipe_name = serializers.ReadOnlyField(source='recipe.name')
mealplan_note = serializers.ReadOnlyField(source='mealplan.note')
mealplan_from_date = serializers.ReadOnlyField(source='mealplan.from_date')
mealplan_type = serializers.ReadOnlyField(source='mealplan.meal_type.name')
servings = CustomDecimalField()
@extend_schema_field(str)
def get_name(self, obj):
if not isinstance(value := obj.servings, Decimal):
value = Decimal(value)
value = value.quantize(
Decimal(1)) if value == value.to_integral() else value.normalize() # strips trailing zero
return (
obj.name
or getattr(obj.mealplan, 'title', None)
or (d := getattr(obj.mealplan, 'date', None)) and ': '.join([obj.mealplan.recipe.name, str(d)])
or obj.recipe.name
) + f' ({value:.2g})'
def update(self, instance, validated_data):
# TODO remove once old shopping list
if 'servings' in validated_data and self.context.get('view', None).__class__.__name__ != 'ShoppingListViewSet':
@@ -1252,6 +1238,16 @@ class ShoppingListEntrySerializer(WritableNestedModelSerializer):
read_only_fields = ('id', 'created_by', 'created_at')
class ShoppingListEntrySimpleCreateSerializer(serializers.Serializer):
amount = CustomDecimalField()
unit_id = serializers.IntegerField(allow_null=True)
food_id = serializers.IntegerField(allow_null=True)
class ShoppingListEntryBulkCreateSerializer(serializers.Serializer):
entries = serializers.ListField(child=ShoppingListEntrySimpleCreateSerializer())
class ShoppingListEntryBulkSerializer(serializers.Serializer):
ids = serializers.ListField()
checked = serializers.BooleanField()
@@ -1537,8 +1533,8 @@ class RecipeExportSerializer(WritableNestedModelSerializer):
class RecipeShoppingUpdateSerializer(serializers.ModelSerializer):
list_recipe = serializers.IntegerField(write_only=True, allow_null=True, required=False,
help_text=_("Existing shopping list to update"))
ingredients = serializers.IntegerField(write_only=True, allow_null=True, required=False, help_text=_(
"List of ingredient IDs from the recipe to add, if not provided all ingredients will be added."))
ingredients = serializers.ListField(child=serializers.IntegerField(write_only=True, allow_null=True, required=False, help_text=_(
"List of ingredient IDs from the recipe to add, if not provided all ingredients will be added.")))
servings = serializers.IntegerField(default=1, write_only=True, allow_null=True, required=False, help_text=_(
"Providing a list_recipe ID and servings of 0 will delete that shopping list."))
@@ -1627,9 +1623,10 @@ class SourceImportDuplicateSerializer(serializers.Serializer):
id = serializers.IntegerField()
name = serializers.CharField()
class RecipeFromSourceResponseSerializer(serializers.Serializer):
recipe = SourceImportRecipeSerializer(default=None)
images = serializers.ListField(child=serializers.CharField(),default=[], allow_null=False)
images = serializers.ListField(child=serializers.CharField(), default=[], allow_null=False)
error = serializers.BooleanField(default=False)
msg = serializers.CharField(max_length=1024, default='')
duplicates = serializers.ListField(child=SourceImportDuplicateSerializer(), default=[], allow_null=False)

View File

@@ -105,7 +105,7 @@ from cookbook.serializer import (AccessTokenSerializer, AutomationSerializer, Au
SupermarketSerializer, SyncLogSerializer, SyncSerializer,
UnitConversionSerializer, UnitSerializer, UserFileSerializer, UserPreferenceSerializer,
UserSerializer, UserSpaceSerializer, ViewLogSerializer, ImportImageSerializer,
LocalizationSerializer, ServerSettingsSerializer, RecipeFromSourceResponseSerializer
LocalizationSerializer, ServerSettingsSerializer, RecipeFromSourceResponseSerializer, ShoppingListEntryBulkCreateSerializer
)
from cookbook.version_info import TANDOOR_VERSION
from cookbook.views.import_export import get_integration
@@ -1289,7 +1289,8 @@ class RecipeViewSet(LoggingMixin, viewsets.ModelViewSet):
return Response(content, status=http_status)
@decorators.action(detail=True, methods=['GET'], serializer_class=RecipeSimpleSerializer)
@extend_schema(responses=RecipeSimpleSerializer(many=True))
@decorators.action(detail=True, pagination_class=None, methods=['GET'], serializer_class=RecipeSimpleSerializer)
def related(self, request, pk):
obj = self.get_object()
if obj.get_space() != request.space:
@@ -1371,8 +1372,34 @@ class ShoppingListRecipeViewSet(LoggingMixin, viewsets.ModelViewSet):
self.queryset = self.queryset.filter(Q(entries__space=self.request.space) | Q(recipe__space=self.request.space))
return self.queryset.filter(Q(entries__isnull=True)
| Q(entries__created_by=self.request.user)
| Q(
entries__created_by__in=list(self.request.user.get_shopping_share()))).distinct().all()
| Q(entries__created_by__in=list(self.request.user.get_shopping_share()))).distinct().all()
@decorators.action(detail=True, methods=['POST'], serializer_class=ShoppingListEntryBulkCreateSerializer, permission_classes=[CustomIsUser])
def bulk_create_entries(self, request, pk):
obj = self.get_object()
if obj.get_space() != request.space:
raise PermissionDenied(detail='You do not have the required permission to perform this action', code=403)
serializer = self.serializer_class(data=request.data)
if serializer.is_valid():
entries = []
for e in serializer.validated_data['entries']:
entries.append(
ShoppingListEntry(
list_recipe_id=obj.pk,
amount=e['amount'],
unit_id=e['unit_id'],
food_id=e['food_id'],
created_by_id=request.user.id,
space_id=request.space.id,
)
)
ShoppingListEntry.objects.bulk_create(entries)
return Response(serializer.validated_data)
else:
return Response(serializer.errors, 400)
@extend_schema_view(list=extend_schema(parameters=[

View File

@@ -1,9 +1,133 @@
<template>
<v-dialog activator="parent" max-width="600px" v-model="dialog">
<v-card :loading="loading">
<v-closable-card-title :title="$t('Add_Servings_to_Shopping', servings)" v-model="dialog"></v-closable-card-title>
<v-card-text>
<v-expansion-panels variant="accordion">
<v-expansion-panel>
<v-expansion-panel-title>{{ recipe.name }}</v-expansion-panel-title>
<v-expansion-panel-text>
<v-list>
<template v-for="s in recipe.steps">
<v-list-item v-for="i in s.ingredients">
{{ i }}
</v-list-item>
</template>
</v-list>
</v-expansion-panel-text>
</v-expansion-panel>
<v-expansion-panel v-for="r in relatedRecipes">
<v-expansion-panel-title>{{ r.name }}</v-expansion-panel-title>
<v-expansion-panel-text>
<v-list>
<template v-for="s in r.steps">
<v-list-item v-for="i in s.ingredients">{{ i }}</v-list-item>
</template>
</v-list>
</v-expansion-panel-text>
</v-expansion-panel>
</v-expansion-panels>
<v-number-input v-model="servings" class="mt-3" control-variant="split" :label="$t('Servings')"></v-number-input>
</v-card-text>
<v-card-actions>
<v-btn class="float-right" prepend-icon="$create" color="create" @click="createShoppingListRecipe()">{{$t('Add_to_Shopping')}}</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script setup lang="ts">
import {computed, onMounted, PropType, ref} from "vue";
import VClosableCardTitle from "@/components/dialogs/VClosableCardTitle.vue";
import {ApiApi, Recipe, RecipeFlat, RecipeOverview, type RecipeShoppingUpdate, type ShoppingListEntryBulkCreate, ShoppingListRecipe} from "@/openapi";
import {ErrorMessageType, useMessageStore} from "@/stores/MessageStore";
import {VNumberInput} from 'vuetify/labs/VNumberInput'
const props = defineProps({
recipe: {type: Object as PropType<Recipe | RecipeFlat | RecipeOverview>, required: true},
})
const dialog = ref(false)
const loading = ref(false)
const servings = ref(1)
const recipe = ref({} as Recipe)
const relatedRecipes = ref([] as Recipe[])
onMounted(() => {
loadRecipeData()
})
/**
* load data for the given recipe and all of its related recipes
*/
function loadRecipeData() {
let api = new ApiApi()
let promises: Promise<any>[] = []
let recipeRequest = api.apiRecipeRetrieve({id: props.recipe.id!}).then(r => {
recipe.value = r
servings.value = r.servings ? r.servings : 1
console.log('main loaded')
}).catch(err => {
useMessageStore().addError(ErrorMessageType.FETCH_ERROR, err)
})
promises.push(recipeRequest)
api.apiRecipeRelatedList({id: props.recipe.id!}).then(r => {
r.forEach(rs => {
let p = api.apiRecipeRetrieve({id: rs.id!}).then(recipe => {
relatedRecipes.value.push(recipe)
console.log('related loaded', recipe.name)
})
promises.push(p)
})
Promise.allSettled(promises).then(() => {
console.log('ALL LOADED')
loading.value = false
})
})
}
/**
* creates a shopping list recipe from all selected ingredients
*/
function createShoppingListRecipe() {
let api = new ApiApi()
let shoppingListRecipe = {
recipe: props.recipe.id,
servings: servings.value,
} as ShoppingListRecipe
let shoppingListEntries = {
entries: []
} as ShoppingListEntryBulkCreate
recipe.value.steps.forEach(step => {
step.ingredients.forEach(ingredient => {
shoppingListEntries.entries.push({
amount: ingredient.amount * (servings.value / (recipe.value.servings ? recipe.value.servings : 1)),
foodId: ingredient.food ? ingredient.food.id! : null,
unitId: ingredient.unit ? ingredient.unit.id! : null
})
})
})
api.apiShoppingListRecipeCreate({shoppingListRecipe: shoppingListRecipe}).then(slr => {
api.apiShoppingListRecipeBulkCreateEntriesCreate({id: slr.id!, shoppingListEntryBulkCreate: shoppingListEntries}).then(r => {
}).catch(err => {
useMessageStore().addError(ErrorMessageType.CREATE_ERROR, err)
})
}).catch(err => {
useMessageStore().addError(ErrorMessageType.CREATE_ERROR, err)
})
}
</script>
<style scoped>

View File

@@ -10,6 +10,10 @@
{{ $t('Add_to_Plan') }}
<model-edit-dialog model="MealPlan" :itemDefaults="{recipe: recipe}"></model-edit-dialog>
</v-list-item>
<v-list-item prepend-icon="$shopping" link>
{{ $t('Add_to_Shopping') }}
<add-to-shopping-dialog :recipe="props.recipe"></add-to-shopping-dialog>
</v-list-item>
<v-list-item prepend-icon="fa-solid fa-share-nodes" link>
{{ $t('Share') }}
<recipe-share-dialog :recipe="props.recipe"></recipe-share-dialog>
@@ -26,6 +30,7 @@ import {PropType} from 'vue'
import {Recipe, RecipeFlat, RecipeOverview} from "@/openapi";
import ModelEditDialog from "@/components/dialogs/ModelEditDialog.vue";
import RecipeShareDialog from "@/components/dialogs/RecipeShareDialog.vue";
import AddToShoppingDialog from "@/components/dialogs/AddToShoppingDialog.vue";
const props = defineProps({

View File

@@ -133,6 +133,8 @@ models/ServerSettings.ts
models/ShareLink.ts
models/ShoppingListEntry.ts
models/ShoppingListEntryBulk.ts
models/ShoppingListEntryBulkCreate.ts
models/ShoppingListEntrySimpleCreate.ts
models/ShoppingListRecipe.ts
models/SourceImportDuplicate.ts
models/SourceImportFood.ts

View File

@@ -131,6 +131,7 @@ import type {
ShareLink,
ShoppingListEntry,
ShoppingListEntryBulk,
ShoppingListEntryBulkCreate,
ShoppingListRecipe,
Space,
Step,
@@ -381,6 +382,8 @@ import {
ShoppingListEntryToJSON,
ShoppingListEntryBulkFromJSON,
ShoppingListEntryBulkToJSON,
ShoppingListEntryBulkCreateFromJSON,
ShoppingListEntryBulkCreateToJSON,
ShoppingListRecipeFromJSON,
ShoppingListRecipeToJSON,
SpaceFromJSON,
@@ -1214,7 +1217,7 @@ export interface ApiRecipePartialUpdateRequest {
patchedRecipe?: Omit<PatchedRecipe, 'image'|'created_by'|'created_at'|'updated_at'|'food_properties'|'rating'|'last_cooked'>;
}
export interface ApiRecipeRelatedRetrieveRequest {
export interface ApiRecipeRelatedListRequest {
id: number;
}
@@ -1224,7 +1227,7 @@ export interface ApiRecipeRetrieveRequest {
export interface ApiRecipeShoppingUpdateRequest {
id: number;
recipeShoppingUpdate?: RecipeShoppingUpdate;
recipeShoppingUpdate: RecipeShoppingUpdate;
}
export interface ApiRecipeUpdateRequest {
@@ -1268,8 +1271,13 @@ export interface ApiShoppingListEntryUpdateRequest {
shoppingListEntry: Omit<ShoppingListEntry, 'recipe_mealplan'|'created_by'|'created_at'|'updated_at'>;
}
export interface ApiShoppingListRecipeBulkCreateEntriesCreateRequest {
id: number;
shoppingListEntryBulkCreate: ShoppingListEntryBulkCreate;
}
export interface ApiShoppingListRecipeCreateRequest {
shoppingListRecipe: Omit<ShoppingListRecipe, 'recipe_name'|'name'|'mealplan_note'|'mealplan_from_date'|'mealplan_type'>;
shoppingListRecipe: Omit<ShoppingListRecipe, 'recipe_name'|'mealplan_note'|'mealplan_from_date'|'mealplan_type'>;
}
export interface ApiShoppingListRecipeDestroyRequest {
@@ -1283,7 +1291,7 @@ export interface ApiShoppingListRecipeListRequest {
export interface ApiShoppingListRecipePartialUpdateRequest {
id: number;
patchedShoppingListRecipe?: Omit<PatchedShoppingListRecipe, 'recipe_name'|'name'|'mealplan_note'|'mealplan_from_date'|'mealplan_type'>;
patchedShoppingListRecipe?: Omit<PatchedShoppingListRecipe, 'recipe_name'|'mealplan_note'|'mealplan_from_date'|'mealplan_type'>;
}
export interface ApiShoppingListRecipeRetrieveRequest {
@@ -1292,7 +1300,7 @@ export interface ApiShoppingListRecipeRetrieveRequest {
export interface ApiShoppingListRecipeUpdateRequest {
id: number;
shoppingListRecipe: Omit<ShoppingListRecipe, 'recipe_name'|'name'|'mealplan_note'|'mealplan_from_date'|'mealplan_type'>;
shoppingListRecipe: Omit<ShoppingListRecipe, 'recipe_name'|'mealplan_note'|'mealplan_from_date'|'mealplan_type'>;
}
export interface ApiSpaceListRequest {
@@ -8856,11 +8864,11 @@ export class ApiApi extends runtime.BaseAPI {
/**
* logs request counts to redis cache total/per user/
*/
async apiRecipeRelatedRetrieveRaw(requestParameters: ApiRecipeRelatedRetrieveRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<RecipeSimple>> {
async apiRecipeRelatedListRaw(requestParameters: ApiRecipeRelatedListRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Array<RecipeSimple>>> {
if (requestParameters['id'] == null) {
throw new runtime.RequiredError(
'id',
'Required parameter "id" was null or undefined when calling apiRecipeRelatedRetrieve().'
'Required parameter "id" was null or undefined when calling apiRecipeRelatedList().'
);
}
@@ -8879,14 +8887,14 @@ export class ApiApi extends runtime.BaseAPI {
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => RecipeSimpleFromJSON(jsonValue));
return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(RecipeSimpleFromJSON));
}
/**
* logs request counts to redis cache total/per user/
*/
async apiRecipeRelatedRetrieve(requestParameters: ApiRecipeRelatedRetrieveRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<RecipeSimple> {
const response = await this.apiRecipeRelatedRetrieveRaw(requestParameters, initOverrides);
async apiRecipeRelatedList(requestParameters: ApiRecipeRelatedListRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<Array<RecipeSimple>> {
const response = await this.apiRecipeRelatedListRaw(requestParameters, initOverrides);
return await response.value();
}
@@ -8938,6 +8946,13 @@ export class ApiApi extends runtime.BaseAPI {
);
}
if (requestParameters['recipeShoppingUpdate'] == null) {
throw new runtime.RequiredError(
'recipeShoppingUpdate',
'Required parameter "recipeShoppingUpdate" was null or undefined when calling apiRecipeShoppingUpdate().'
);
}
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
@@ -9388,6 +9403,53 @@ export class ApiApi extends runtime.BaseAPI {
return await response.value();
}
/**
* logs request counts to redis cache total/per user/
*/
async apiShoppingListRecipeBulkCreateEntriesCreateRaw(requestParameters: ApiShoppingListRecipeBulkCreateEntriesCreateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<ShoppingListEntryBulkCreate>> {
if (requestParameters['id'] == null) {
throw new runtime.RequiredError(
'id',
'Required parameter "id" was null or undefined when calling apiShoppingListRecipeBulkCreateEntriesCreate().'
);
}
if (requestParameters['shoppingListEntryBulkCreate'] == null) {
throw new runtime.RequiredError(
'shoppingListEntryBulkCreate',
'Required parameter "shoppingListEntryBulkCreate" was null or undefined when calling apiShoppingListRecipeBulkCreateEntriesCreate().'
);
}
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
headerParameters['Content-Type'] = 'application/json';
if (this.configuration && this.configuration.apiKey) {
headerParameters["Authorization"] = await this.configuration.apiKey("Authorization"); // ApiKeyAuth authentication
}
const response = await this.request({
path: `/api/shopping-list-recipe/{id}/bulk_create_entries/`.replace(`{${"id"}}`, encodeURIComponent(String(requestParameters['id']))),
method: 'POST',
headers: headerParameters,
query: queryParameters,
body: ShoppingListEntryBulkCreateToJSON(requestParameters['shoppingListEntryBulkCreate']),
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => ShoppingListEntryBulkCreateFromJSON(jsonValue));
}
/**
* logs request counts to redis cache total/per user/
*/
async apiShoppingListRecipeBulkCreateEntriesCreate(requestParameters: ApiShoppingListRecipeBulkCreateEntriesCreateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<ShoppingListEntryBulkCreate> {
const response = await this.apiShoppingListRecipeBulkCreateEntriesCreateRaw(requestParameters, initOverrides);
return await response.value();
}
/**
* logs request counts to redis cache total/per user/
*/

View File

@@ -0,0 +1,99 @@
/* tslint:disable */
/* eslint-disable */
/**
* Tandoor
* Tandoor API Docs
*
* The version of the OpenAPI document: 0.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime';
import type { RecipeSimple } from './RecipeSimple';
import {
RecipeSimpleFromJSON,
RecipeSimpleFromJSONTyped,
RecipeSimpleToJSON,
RecipeSimpleToJSONTyped,
} from './RecipeSimple';
/**
*
* @export
* @interface PaginatedRecipeSimpleList
*/
export interface PaginatedRecipeSimpleList {
/**
*
* @type {number}
* @memberof PaginatedRecipeSimpleList
*/
count: number;
/**
*
* @type {string}
* @memberof PaginatedRecipeSimpleList
*/
next?: string | null;
/**
*
* @type {string}
* @memberof PaginatedRecipeSimpleList
*/
previous?: string | null;
/**
*
* @type {Array<RecipeSimple>}
* @memberof PaginatedRecipeSimpleList
*/
results: Array<RecipeSimple>;
}
/**
* Check if a given object implements the PaginatedRecipeSimpleList interface.
*/
export function instanceOfPaginatedRecipeSimpleList(value: object): value is PaginatedRecipeSimpleList {
if (!('count' in value) || value['count'] === undefined) return false;
if (!('results' in value) || value['results'] === undefined) return false;
return true;
}
export function PaginatedRecipeSimpleListFromJSON(json: any): PaginatedRecipeSimpleList {
return PaginatedRecipeSimpleListFromJSONTyped(json, false);
}
export function PaginatedRecipeSimpleListFromJSONTyped(json: any, ignoreDiscriminator: boolean): PaginatedRecipeSimpleList {
if (json == null) {
return json;
}
return {
'count': json['count'],
'next': json['next'] == null ? undefined : json['next'],
'previous': json['previous'] == null ? undefined : json['previous'],
'results': ((json['results'] as Array<any>).map(RecipeSimpleFromJSON)),
};
}
export function PaginatedRecipeSimpleListToJSON(json: any): PaginatedRecipeSimpleList {
return PaginatedRecipeSimpleListToJSONTyped(json, false);
}
export function PaginatedRecipeSimpleListToJSONTyped(value?: PaginatedRecipeSimpleList | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value;
}
return {
'count': value['count'],
'next': value['next'],
'previous': value['previous'],
'results': ((value['results'] as Array<any>).map(RecipeSimpleToJSON)),
};
}

View File

@@ -36,7 +36,7 @@ export interface PatchedShoppingListRecipe {
* @type {string}
* @memberof PatchedShoppingListRecipe
*/
readonly name?: string;
name?: string;
/**
*
* @type {number}
@@ -108,7 +108,7 @@ export function PatchedShoppingListRecipeToJSON(json: any): PatchedShoppingListR
return PatchedShoppingListRecipeToJSONTyped(json, false);
}
export function PatchedShoppingListRecipeToJSONTyped(value?: Omit<PatchedShoppingListRecipe, 'recipe_name'|'name'|'mealplan_note'|'mealplan_from_date'|'mealplan_type'> | null, ignoreDiscriminator: boolean = false): any {
export function PatchedShoppingListRecipeToJSONTyped(value?: Omit<PatchedShoppingListRecipe, 'recipe_name'|'mealplan_note'|'mealplan_from_date'|'mealplan_type'> | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value;
}
@@ -116,6 +116,7 @@ export function PatchedShoppingListRecipeToJSONTyped(value?: Omit<PatchedShoppin
return {
'id': value['id'],
'name': value['name'],
'recipe': value['recipe'],
'mealplan': value['mealplan'],
'servings': value['servings'],

View File

@@ -32,11 +32,11 @@ export interface RecipeShoppingUpdate {
*/
listRecipe?: number | null;
/**
* List of ingredient IDs from the recipe to add, if not provided all ingredients will be added.
* @type {number}
*
* @type {Array<number | null>}
* @memberof RecipeShoppingUpdate
*/
ingredients?: number | null;
ingredients: Array<number | null>;
/**
* Providing a list_recipe ID and servings of 0 will delete that shopping list.
* @type {number}
@@ -49,6 +49,7 @@ export interface RecipeShoppingUpdate {
* Check if a given object implements the RecipeShoppingUpdate interface.
*/
export function instanceOfRecipeShoppingUpdate(value: object): value is RecipeShoppingUpdate {
if (!('ingredients' in value) || value['ingredients'] === undefined) return false;
return true;
}
@@ -64,7 +65,7 @@ export function RecipeShoppingUpdateFromJSONTyped(json: any, ignoreDiscriminator
'id': json['id'] == null ? undefined : json['id'],
'listRecipe': json['list_recipe'] == null ? undefined : json['list_recipe'],
'ingredients': json['ingredients'] == null ? undefined : json['ingredients'],
'ingredients': json['ingredients'],
'servings': json['servings'] == null ? undefined : json['servings'],
};
}

View File

@@ -0,0 +1,74 @@
/* tslint:disable */
/* eslint-disable */
/**
* Tandoor
* Tandoor API Docs
*
* The version of the OpenAPI document: 0.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime';
import type { ShoppingListEntrySimpleCreate } from './ShoppingListEntrySimpleCreate';
import {
ShoppingListEntrySimpleCreateFromJSON,
ShoppingListEntrySimpleCreateFromJSONTyped,
ShoppingListEntrySimpleCreateToJSON,
ShoppingListEntrySimpleCreateToJSONTyped,
} from './ShoppingListEntrySimpleCreate';
/**
*
* @export
* @interface ShoppingListEntryBulkCreate
*/
export interface ShoppingListEntryBulkCreate {
/**
*
* @type {Array<ShoppingListEntrySimpleCreate>}
* @memberof ShoppingListEntryBulkCreate
*/
entries: Array<ShoppingListEntrySimpleCreate>;
}
/**
* Check if a given object implements the ShoppingListEntryBulkCreate interface.
*/
export function instanceOfShoppingListEntryBulkCreate(value: object): value is ShoppingListEntryBulkCreate {
if (!('entries' in value) || value['entries'] === undefined) return false;
return true;
}
export function ShoppingListEntryBulkCreateFromJSON(json: any): ShoppingListEntryBulkCreate {
return ShoppingListEntryBulkCreateFromJSONTyped(json, false);
}
export function ShoppingListEntryBulkCreateFromJSONTyped(json: any, ignoreDiscriminator: boolean): ShoppingListEntryBulkCreate {
if (json == null) {
return json;
}
return {
'entries': ((json['entries'] as Array<any>).map(ShoppingListEntrySimpleCreateFromJSON)),
};
}
export function ShoppingListEntryBulkCreateToJSON(json: any): ShoppingListEntryBulkCreate {
return ShoppingListEntryBulkCreateToJSONTyped(json, false);
}
export function ShoppingListEntryBulkCreateToJSONTyped(value?: ShoppingListEntryBulkCreate | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value;
}
return {
'entries': ((value['entries'] as Array<any>).map(ShoppingListEntrySimpleCreateToJSON)),
};
}

View File

@@ -0,0 +1,84 @@
/* tslint:disable */
/* eslint-disable */
/**
* Tandoor
* Tandoor API Docs
*
* The version of the OpenAPI document: 0.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime';
/**
*
* @export
* @interface ShoppingListEntrySimpleCreate
*/
export interface ShoppingListEntrySimpleCreate {
/**
*
* @type {number}
* @memberof ShoppingListEntrySimpleCreate
*/
amount: number;
/**
*
* @type {number}
* @memberof ShoppingListEntrySimpleCreate
*/
unitId: number | null;
/**
*
* @type {number}
* @memberof ShoppingListEntrySimpleCreate
*/
foodId: number | null;
}
/**
* Check if a given object implements the ShoppingListEntrySimpleCreate interface.
*/
export function instanceOfShoppingListEntrySimpleCreate(value: object): value is ShoppingListEntrySimpleCreate {
if (!('amount' in value) || value['amount'] === undefined) return false;
if (!('unitId' in value) || value['unitId'] === undefined) return false;
if (!('foodId' in value) || value['foodId'] === undefined) return false;
return true;
}
export function ShoppingListEntrySimpleCreateFromJSON(json: any): ShoppingListEntrySimpleCreate {
return ShoppingListEntrySimpleCreateFromJSONTyped(json, false);
}
export function ShoppingListEntrySimpleCreateFromJSONTyped(json: any, ignoreDiscriminator: boolean): ShoppingListEntrySimpleCreate {
if (json == null) {
return json;
}
return {
'amount': json['amount'],
'unitId': json['unit_id'],
'foodId': json['food_id'],
};
}
export function ShoppingListEntrySimpleCreateToJSON(json: any): ShoppingListEntrySimpleCreate {
return ShoppingListEntrySimpleCreateToJSONTyped(json, false);
}
export function ShoppingListEntrySimpleCreateToJSONTyped(value?: ShoppingListEntrySimpleCreate | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value;
}
return {
'amount': value['amount'],
'unit_id': value['unitId'],
'food_id': value['foodId'],
};
}

View File

@@ -36,7 +36,7 @@ export interface ShoppingListRecipe {
* @type {string}
* @memberof ShoppingListRecipe
*/
readonly name: string;
name?: string;
/**
*
* @type {number}
@@ -80,7 +80,6 @@ export interface ShoppingListRecipe {
*/
export function instanceOfShoppingListRecipe(value: object): value is ShoppingListRecipe {
if (!('recipeName' in value) || value['recipeName'] === undefined) return false;
if (!('name' in value) || value['name'] === undefined) return false;
if (!('servings' in value) || value['servings'] === undefined) return false;
if (!('mealplanNote' in value) || value['mealplanNote'] === undefined) return false;
if (!('mealplanFromDate' in value) || value['mealplanFromDate'] === undefined) return false;
@@ -100,7 +99,7 @@ export function ShoppingListRecipeFromJSONTyped(json: any, ignoreDiscriminator:
'id': json['id'] == null ? undefined : json['id'],
'recipeName': json['recipe_name'],
'name': json['name'],
'name': json['name'] == null ? undefined : json['name'],
'recipe': json['recipe'] == null ? undefined : json['recipe'],
'mealplan': json['mealplan'] == null ? undefined : json['mealplan'],
'servings': json['servings'],
@@ -114,7 +113,7 @@ export function ShoppingListRecipeToJSON(json: any): ShoppingListRecipe {
return ShoppingListRecipeToJSONTyped(json, false);
}
export function ShoppingListRecipeToJSONTyped(value?: Omit<ShoppingListRecipe, 'recipe_name'|'name'|'mealplan_note'|'mealplan_from_date'|'mealplan_type'> | null, ignoreDiscriminator: boolean = false): any {
export function ShoppingListRecipeToJSONTyped(value?: Omit<ShoppingListRecipe, 'recipe_name'|'mealplan_note'|'mealplan_from_date'|'mealplan_type'> | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value;
}
@@ -122,6 +121,7 @@ export function ShoppingListRecipeToJSONTyped(value?: Omit<ShoppingListRecipe, '
return {
'id': value['id'],
'name': value['name'],
'recipe': value['recipe'],
'mealplan': value['mealplan'],
'servings': value['servings'],

View File

@@ -130,6 +130,8 @@ export * from './ServerSettings';
export * from './ShareLink';
export * from './ShoppingListEntry';
export * from './ShoppingListEntryBulk';
export * from './ShoppingListEntryBulkCreate';
export * from './ShoppingListEntrySimpleCreate';
export * from './ShoppingListRecipe';
export * from './SourceImportDuplicate';
export * from './SourceImportFood';