various fixes

This commit is contained in:
vabene1111
2025-01-30 10:29:21 +01:00
parent fcbc4cb792
commit 3880f205b6
9 changed files with 53 additions and 34 deletions

View File

@@ -1041,7 +1041,7 @@ class RecipeImageSerializer(WritableNestedModelSerializer):
def create(self, validated_data): def create(self, validated_data):
if 'image' in validated_data and not is_file_type_allowed(validated_data['image'].name, image_only=True): if 'image' in validated_data and not is_file_type_allowed(validated_data['image'].name, image_only=True):
return None return None
return super().create( validated_data) return super().create(validated_data)
def update(self, instance, validated_data): def update(self, instance, validated_data):
if 'image' in validated_data and not is_file_type_allowed(validated_data['image'].name, image_only=True): if 'image' in validated_data and not is_file_type_allowed(validated_data['image'].name, image_only=True):
@@ -1151,6 +1151,13 @@ class MealPlanSerializer(SpacedModelSerializer, WritableNestedModelSerializer):
SLR.create(mealplan=mealplan, servings=validated_data['servings']) SLR.create(mealplan=mealplan, servings=validated_data['servings'])
return mealplan return mealplan
def update(self, obj, validated_data):
if sr := ShoppingListRecipe.objects.filter(mealplan=obj.id).first():
SLR = RecipeShoppingEditor(user=obj.created_by, space=obj.space, id=sr.id)
SLR.edit(mealplan=obj, servings=validated_data['servings'])
return super().update(obj, validated_data)
class Meta: class Meta:
model = MealPlan model = MealPlan
fields = ( fields = (
@@ -1311,7 +1318,8 @@ class ViewLogSerializer(serializers.ModelSerializer):
validated_data['created_by'] = self.context['request'].user validated_data['created_by'] = self.context['request'].user
validated_data['space'] = self.context['request'].space validated_data['space'] = self.context['request'].space
view_log = ViewLog.objects.filter(recipe=validated_data['recipe'], created_by=self.context['request'].user, created_at__gt=(timezone.now() - timezone.timedelta(minutes=5)), space=self.context['request'].space).first() view_log = ViewLog.objects.filter(recipe=validated_data['recipe'], created_by=self.context['request'].user, created_at__gt=(timezone.now() - timezone.timedelta(minutes=5)),
space=self.context['request'].space).first()
if not view_log: if not view_log:
view_log = ViewLog.objects.create(recipe=validated_data['recipe'], created_by=self.context['request'].user, space=self.context['request'].space) view_log = ViewLog.objects.create(recipe=validated_data['recipe'], created_by=self.context['request'].user, space=self.context['request'].space)

View File

@@ -533,14 +533,14 @@ def web_manifest(request):
"url": "./mealplan", "url": "./mealplan",
"icons": [ "icons": [
{ {
"src": static('logo_color_plan.svg'), "src": static('assets/logo_color_plan.svg'),
"sizes": "any" "sizes": "any"
}, { }, {
"src": static('logo_color_plan_144.png'), "src": static('assets/logo_color_plan_144.png'),
"type": "image/png", "type": "image/png",
"sizes": "144x144" "sizes": "144x144"
}, { }, {
"src": static('logo_color_plan_512.png'), "src": static('assets/logo_color_plan_512.png'),
"type": "image/png", "type": "image/png",
"sizes": "512x512" "sizes": "512x512"
} }
@@ -552,14 +552,14 @@ def web_manifest(request):
"url": "./shopping", "url": "./shopping",
"icons": [ "icons": [
{ {
"src": static('logo_color_shopping.svg'), "src": static('assets/logo_color_shopping.svg'),
"sizes": "any" "sizes": "any"
}, { }, {
"src": static('logo_color_shopping_144.png'), "src": static('assets/logo_color_shopping_144.png'),
"type": "image/png", "type": "image/png",
"sizes": "144x144" "sizes": "144x144"
}, { }, {
"src": static('logo_color_shopping_512.png'), "src": static('assets/logo_color_shopping_512.png'),
"type": "image/png", "type": "image/png",
"sizes": "512x512" "sizes": "512x512"
} }
@@ -568,6 +568,7 @@ def web_manifest(request):
"share_target": { "share_target": {
"action": "/recipe/import", "action": "/recipe/import",
"method": "GET", "method": "GET",
"enctype": "application/x-www-form-urlencoded",
"params": { "params": {
"title": "title", "title": "title",
"url": "url", "url": "url",

View File

@@ -87,24 +87,27 @@
<!-- </template>--> <!-- </template>-->
<v-btn-group divided border> <v-btn-group divided border>
<v-btn icon="" @click="e.amount = e.amount / 2; updateEntryAmount(e)"> <v-btn icon="" @click="e.amount = e.amount / 2; updateEntryAmount(e)" v-if="!e.listRecipeData">
<v-icon icon="fa-solid fa-divide"></v-icon> <v-icon icon="fa-solid fa-divide"></v-icon>
</v-btn> </v-btn>
<v-btn icon="" @click="e.amount--; updateEntryAmount(e)"> <v-btn icon="" @click="e.amount--; updateEntryAmount(e)" v-if="!e.listRecipeData">
<v-icon icon="fa-solid fa-minus"></v-icon> <v-icon icon="fa-solid fa-minus"></v-icon>
</v-btn> </v-btn>
<v-btn icon="" @click="e.amount++; updateEntryAmount(e)"> <v-btn icon="" @click="e.amount++; updateEntryAmount(e)" v-if="!e.listRecipeData">
<v-icon icon="fa-solid fa-plus"></v-icon> <v-icon icon="fa-solid fa-plus"></v-icon>
</v-btn> </v-btn>
<v-btn icon="" @click="e.amount = e.amount * 2; updateEntryAmount(e)"> <v-btn icon="" @click="e.amount = e.amount * 2; updateEntryAmount(e)" v-if="!e.listRecipeData">
<v-icon icon="fa-solid fa-times"></v-icon> <v-icon icon="fa-solid fa-times"></v-icon>
</v-btn> </v-btn>
<v-btn color="edit" icon="$edit" v-if="!e.recipeMealplan"> <v-btn color="edit" icon="$edit" v-if="!e.listRecipeData">
<v-icon icon="$edit"></v-icon> <v-icon icon="$edit"></v-icon>
<model-edit-dialog model="ShoppingListEntry" :item="e" @delete="useShoppingStore().entries.delete(e.id); shoppingListFood.entries.delete(e.id)" <model-edit-dialog model="ShoppingListEntry" :item="e" @delete="useShoppingStore().entries.delete(e.id); shoppingListFood.entries.delete(e.id)"
@save="(args: ShoppingListEntry) => (shoppingListFood.entries.set(e.id, args))"></model-edit-dialog> @save="(args: ShoppingListEntry) => (shoppingListFood.entries.set(e.id, args))"></model-edit-dialog>
</v-btn> </v-btn>
<v-btn color="edit" icon="$recipes" v-if="e.listRecipe && e.listRecipeData.recipe" :to="{name: 'view_recipe', params: {id: e.listRecipeData.recipe}}">
<v-icon icon="$recipes"></v-icon>
</v-btn>
<v-btn icon="" @click="useShoppingStore().deleteObject(e, true); shoppingListFood.entries.delete(e.id)" color="delete"> <v-btn icon="" @click="useShoppingStore().deleteObject(e, true); shoppingListFood.entries.delete(e.id)" color="delete">
<v-icon icon="$delete"></v-icon> <v-icon icon="$delete"></v-icon>
</v-btn> </v-btn>

View File

@@ -164,7 +164,7 @@
<v-list> <v-list>
<v-list-item v-for="r in useShoppingStore().getAssociatedRecipes()"> <v-list-item v-for="r in useShoppingStore().getAssociatedRecipes()">
<template #prepend> <template #prepend>
<v-btn color="edit" icon> <v-btn color="edit" icon :disabled="r.mealplan">
{{ r.servings }} {{ r.servings }}
<number-scaler-dialog :number="r.servings" <number-scaler-dialog :number="r.servings"
@confirm="(servings: number) => {updateRecipeServings(r, servings)}"></number-scaler-dialog> @confirm="(servings: number) => {updateRecipeServings(r, servings)}"></number-scaler-dialog>

View File

@@ -10,16 +10,16 @@
:close-on-back="false" :close-on-back="false"
multi-line multi-line
> >
<small>{{ DateTime.fromSeconds(visibleMessage.createdAt).toLocaleString(DateTime.DATETIME_MED) }}</small> <br/> <!-- <small>{{ DateTime.fromSeconds(visibleMessage.createdAt).toLocaleString(DateTime.DATETIME_MED) }}</small> <br/>-->
<h3 v-if="visibleMessage.msg.title">{{ visibleMessage.msg.title }}</h3> <h3 v-if="visibleMessage.msg.title">{{ visibleMessage.msg.title }}</h3>
<span class="text-pre">{{ visibleMessage.msg.text }}</span> <span class="text-pre">{{ visibleMessage.msg.text }}</span>
<template v-slot:actions> <template v-slot:actions>
<v-btn ref="ref_btn_view">View</v-btn> <v-btn ref="ref_btn_view">{{$t('View')}}</v-btn>
<v-btn variant="text" @click="removeItem()"> <v-btn variant="text" @click="removeItem()">
<span v-if="useMessageStore().snackbarQueue.length > 1">Next ({{ useMessageStore().snackbarQueue.length - 1 }})</span> <span v-if="useMessageStore().snackbarQueue.length > 1">{{$t('Next')}} ({{ useMessageStore().snackbarQueue.length - 1 }})</span>
<span v-else>Close</span> <span v-else>{{$t('Close')}}</span>
</v-btn> </v-btn>
</template> </template>
</v-snackbar> </v-snackbar>

View File

@@ -6,7 +6,7 @@
<v-card-text> <v-card-text>
<v-number-input v-model="mutable_number" @update:modelValue="updateNumber('set')" control-variant="split" :min="0"> <v-number-input v-model="mutableNumber" @update:modelValue="updateNumber('set')" control-variant="split" :min="0">
</v-number-input> </v-number-input>
<v-btn-group divided class="d-flex"> <v-btn-group divided class="d-flex">
@@ -21,7 +21,7 @@
</v-card-text> </v-card-text>
<v-card-actions> <v-card-actions>
<v-btn @click=" dialog=false">{{ $t('Close') }}</v-btn> <v-btn @click=" dialog=false">{{ $t('Close') }}</v-btn>
<v-btn color="save" prepend-icon="$save" @click="emit('confirm', mutable_number); dialog=false">{{ $t('Save') }}</v-btn> <v-btn color="save" prepend-icon="$save" @click="emit('confirm', mutableNumber); dialog=false">{{ $t('Save') }}</v-btn>
</v-card-actions> </v-card-actions>
</v-card> </v-card>
@@ -49,14 +49,15 @@ const props = defineProps({
}) })
const dialog = ref(false) const dialog = ref(false)
const mutable_number = ref(0) const mutableNumber = ref(0)
watch(() => props.number, (newVal) => { watch(() => props.number, (newVal) => {
mutable_number.value = newVal mutableNumber.value = newVal
console.log('prop updated')
}) })
onMounted(() => { onMounted(() => {
mutable_number.value = props.number mutableNumber.value = props.number
}) })
/** /**
@@ -65,19 +66,19 @@ onMounted(() => {
*/ */
function updateNumber(operation: string) { function updateNumber(operation: string) {
if (operation === 'half') { if (operation === 'half') {
mutable_number.value = props.number / 2 mutableNumber.value = mutableNumber.value / 2
} }
if (operation === 'double') { if (operation === 'double') {
mutable_number.value = props.number * 2 mutableNumber.value = mutableNumber.value * 2
} }
if (operation === 'add') { if (operation === 'add') {
mutable_number.value = props.number + 1 mutableNumber.value = mutableNumber.value + 1
} }
if (operation === 'sub') { if (operation === 'sub') {
mutable_number.value = props.number - 1 mutableNumber.value = mutableNumber.value - 1
} }
console.log('change emitted')
emit('change', mutable_number.value) emit('change', mutableNumber.value)
} }
</script> </script>

View File

@@ -215,6 +215,7 @@
@update:modelValue="step.ingredients[editingIngredientIndex].unit = null; step.ingredients[editingIngredientIndex].food = null; step.ingredients[editingIngredientIndex].amount = 0" @update:modelValue="step.ingredients[editingIngredientIndex].unit = null; step.ingredients[editingIngredientIndex].food = null; step.ingredients[editingIngredientIndex].amount = 0"
></v-checkbox> ></v-checkbox>
</v-form> </v-form>
<v-btn color="info" class="mt-2" @click="dialogIngredientEditor = false; dialogIngredientSorter = true" prepend-icon="fa-solid fa-sort">{{ $t('Move') }}</v-btn>
</v-card-text> </v-card-text>
<v-card-actions> <v-card-actions>
<v-btn @click="dialogIngredientEditor = false; deleteIngredientAtIndex(editingIngredientIndex); editingIngredientIndex = -1" color="delete" prepend-icon="$delete"> <v-btn @click="dialogIngredientEditor = false; deleteIngredientAtIndex(editingIngredientIndex); editingIngredientIndex = -1" color="delete" prepend-icon="$delete">

View File

@@ -138,19 +138,19 @@ export const useMessageStore = defineStore('message_store', () => {
*/ */
function addPreparedMessage(preparedMessage: PreparedMessage, data?: any) { function addPreparedMessage(preparedMessage: PreparedMessage, data?: any) {
if (preparedMessage == PreparedMessage.UPDATE_SUCCESS) { if (preparedMessage == PreparedMessage.UPDATE_SUCCESS) {
addMessage(MessageType.SUCCESS, {title: t('Updated'), text: ''} as StructuredMessage, 6000, data) addMessage(MessageType.SUCCESS, {title: t('Updated'), text: ''} as StructuredMessage, 1500, data)
} }
if (preparedMessage == PreparedMessage.DELETE_SUCCESS) { if (preparedMessage == PreparedMessage.DELETE_SUCCESS) {
addMessage(MessageType.SUCCESS, {title: t('Deleted'), text: ''} as StructuredMessage, 6000, data) addMessage(MessageType.SUCCESS, {title: t('Deleted'), text: ''} as StructuredMessage, 1500, data)
} }
if (preparedMessage == PreparedMessage.CREATE_SUCCESS) { if (preparedMessage == PreparedMessage.CREATE_SUCCESS) {
addMessage(MessageType.SUCCESS, {title: t('Created'), text: ''} as StructuredMessage, 6000, data) addMessage(MessageType.SUCCESS, {title: t('Created'), text: ''} as StructuredMessage, 1500, data)
} }
if (preparedMessage == PreparedMessage.MERGE_SUCCESS) { if (preparedMessage == PreparedMessage.MERGE_SUCCESS) {
addMessage(MessageType.SUCCESS, {title: t('Merge'), text: ''} as StructuredMessage, 6000, data) addMessage(MessageType.SUCCESS, {title: t('Merge'), text: ''} as StructuredMessage, 1500, data)
} }
if (preparedMessage == PreparedMessage.MOVE_SUCCESS) { if (preparedMessage == PreparedMessage.MOVE_SUCCESS) {
addMessage(MessageType.SUCCESS, {title: t('Move'), text: ''} as StructuredMessage, 6000, data) addMessage(MessageType.SUCCESS, {title: t('Move'), text: ''} as StructuredMessage, 1500, data)
} }
if (preparedMessage == PreparedMessage.NOT_FOUND) { if (preparedMessage == PreparedMessage.NOT_FOUND) {
addMessage(MessageType.WARNING, {title: t('NotFound'), text: t('NotFoundHelp')} as StructuredMessage, 6000, data) addMessage(MessageType.WARNING, {title: t('NotFound'), text: t('NotFoundHelp')} as StructuredMessage, 6000, data)

View File

@@ -6,6 +6,11 @@ import {Ingredient} from "@/openapi";
*/ */
export function ingredientToString(ingredient: Ingredient) { export function ingredientToString(ingredient: Ingredient) {
let content = [] let content = []
if(ingredient == undefined){
return ''
}
if(ingredient.amount != 0){ if(ingredient.amount != 0){
content.push(ingredient.amount) content.push(ingredient.amount)
} }