diff --git a/cookbook/serializer.py b/cookbook/serializer.py index fe33d9667..46171c531 100644 --- a/cookbook/serializer.py +++ b/cookbook/serializer.py @@ -1104,7 +1104,7 @@ class MealPlanSerializer(SpacedModelSerializer, WritableNestedModelSerializer): servings = CustomDecimalField() shared = UserSerializer(many=True, required=False, allow_null=True) shopping = serializers.SerializerMethodField('in_shopping') - addshopping = serializers.BooleanField(write_only=True) + addshopping = serializers.BooleanField(write_only=True, required=False) to_date = serializers.DateTimeField(required=False) diff --git a/vue3/src/components/display/ClosableHelpAlert.vue b/vue3/src/components/display/ClosableHelpAlert.vue new file mode 100644 index 000000000..ffa876c69 --- /dev/null +++ b/vue3/src/components/display/ClosableHelpAlert.vue @@ -0,0 +1,59 @@ + + + + + + + {{ props.text}} + {{ actionText}} + + + + + + + \ No newline at end of file diff --git a/vue3/src/components/display/IngredientString.vue b/vue3/src/components/display/IngredientString.vue new file mode 100644 index 000000000..9950b947a --- /dev/null +++ b/vue3/src/components/display/IngredientString.vue @@ -0,0 +1,22 @@ + + {{$n(ingredient.amount)}} + {{ ingredient.unit.name}} + {{ ingredient.food.name}} + + + + + + + \ No newline at end of file diff --git a/vue3/src/components/display/MealPlanView.vue b/vue3/src/components/display/MealPlanView.vue index af8370787..a51826b84 100644 --- a/vue3/src/components/display/MealPlanView.vue +++ b/vue3/src/components/display/MealPlanView.vue @@ -1,34 +1,38 @@ - - - { newPlanDialogDefaultItem.fromDate = date; newPlanDialogDefaultItem.toDate = date; newPlanDialog = true }"> - - calendarDate = d"> - - - {useMealPlanStore().plans.delete(arg.id)}" - :detailed-items="lgAndUp" - > - - + + + + + { newPlanDialogDefaultItem.fromDate = date; newPlanDialogDefaultItem.toDate = date; newPlanDialog = true }"> + + calendarDate = d"> + + + {useMealPlanStore().plans.delete(arg.id)}" + :detailed-items="lgAndUp" + > + + + + useMealPlanStore().plans.set(arg.id, arg)"> @@ -44,8 +48,8 @@ import "vue-simple-calendar/dist/css/default.css" import MealPlanCalendarItem from "@/components/display/MealPlanCalendarItem.vue"; import {IMealPlanCalendarItem, IMealPlanNormalizedCalendarItem} from "@/types/MealPlan"; -import {computed, onMounted, ref} from "vue"; -import {DateTime} from "luxon"; +import {computed, onMounted, ref, watch} from "vue"; +import {DateTime, Duration} from "luxon"; import {useDisplay} from "vuetify"; import {useMealPlanStore} from "@/stores/MealPlanStore"; import ModelEditDialog from "@/components/dialogs/ModelEditDialog.vue"; @@ -89,22 +93,47 @@ const calendarItemHeight = computed(() => { } }) -onMounted(() => { - useMealPlanStore().refreshFromAPI() //TODO filter to visible date +/** + * watch calendar date and load entries accordingly + */ +watch(calendarDate, () => { + let daysInPeriod = 7 + if (useUserPreferenceStore().deviceSettings.mealplan_displayPeriod == 'month') { + daysInPeriod = 31 + } else if (useUserPreferenceStore().deviceSettings.mealplan_displayPeriod == 'year') { + daysInPeriod = 365 + } + + let days = useUserPreferenceStore().deviceSettings.mealplan_displayPeriodCount * daysInPeriod + useMealPlanStore().refreshFromAPI(calendarDate.value, DateTime.now().plus({days: days}).toJSDate()) }) +onMounted(() => { + // initial load for next 30 days + useMealPlanStore().refreshFromAPI(calendarDate.value, DateTime.now().plus({days: 30}).toJSDate()) +}) + +/** + * handle drop event for calendar items on fields + * @param undefinedItem + * @param targetDate + * @param event + */ function dropCalendarItemOnDate(undefinedItem: IMealPlanNormalizedCalendarItem, targetDate: Date, event: DragEvent) { //The item argument (first) is undefined because our custom calendar item cannot manipulate the calendar state so the item is unknown to the calendar (probably fixable by somehow binding state to the item) if (currentlyDraggedMealplan.value.originalItem.mealPlan.id != undefined) { let mealPlan = useMealPlanStore().plans.get(currentlyDraggedMealplan.value.originalItem.mealPlan.id) if (mealPlan != undefined) { - let fromToDiff = DateTime.fromJSDate(mealPlan.toDate).diff(DateTime.fromJSDate(mealPlan.fromDate), 'days') + let fromToDiff = {days: 1} + if (mealPlan.toDate) { + fromToDiff = DateTime.fromJSDate(mealPlan.toDate).diff(DateTime.fromJSDate(mealPlan.fromDate), 'days') + } + // create copy of item if control is pressed if (event.ctrlKey) { let new_entry = Object.assign({}, mealPlan) new_entry.fromDate = targetDate new_entry.toDate = DateTime.fromJSDate(targetDate).plus(fromToDiff).toJSDate() useMealPlanStore().createObject(new_entry) - } else { mealPlan.fromDate = targetDate mealPlan.toDate = DateTime.fromJSDate(targetDate).plus(fromToDiff).toJSDate() diff --git a/vue3/src/components/inputs/ModelSelect.vue b/vue3/src/components/inputs/ModelSelect.vue index 81b064e65..9228c8e5c 100644 --- a/vue3/src/components/inputs/ModelSelect.vue +++ b/vue3/src/components/inputs/ModelSelect.vue @@ -4,7 +4,6 @@ - + {{ + $t('Name') + }} + {{ $t('Time') }} {{ $t('File') }} {{ $t('Recipe') }} - {{ $t('Delete') }} + {{ $t('Delete') }} @@ -27,7 +31,8 @@ @@ -46,20 +51,21 @@ {{ $t('Ingredients') }} - + - + - + handleIngredientNoteTab(event, index)"> - + @@ -74,15 +80,36 @@ - + + + + + + + + + + + + + + {{ $t('Add') }} - + + + + {{ $t('Instructions') }} - - {{ step.instruction }} + + + {{ step.instruction }} + + + {{ $t('InstructionsEditHelp') }} + @@ -92,12 +119,15 @@ - + + + {{ $t('Close') }} + @@ -115,34 +145,59 @@ + + + + + + + + + + + + + + {{ $t('Close') }} + + +
+ {{ props.text}} + {{ actionText}} +