diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 00000000..35eb1ddf --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/cookbook/views/api.py b/cookbook/views/api.py index 96e0ce2d..48409721 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -678,7 +678,6 @@ class AutoPlanViewSet(viewsets.ViewSet): keywords = serializer.validated_data['keywords'] start_date = serializer.validated_data['start_date'] end_date = serializer.validated_data['end_date'] - meal_type = MealType.objects.get(pk=serializer.validated_data['meal_type_id']) servings = serializer.validated_data['servings'] shared = serializer.get_initial().get('shared', None) shared_pks = list() @@ -686,8 +685,9 @@ class AutoPlanViewSet(viewsets.ViewSet): for i in range(len(shared)): shared_pks.append(shared[i]['id']) - days = (end_date - start_date).days + 1 - recipes = Recipe.objects.all() + days = min((end_date - start_date).days + 1, 14) + + recipes = Recipe.objects.values('id', 'name') meal_plans = list() for keyword in keywords: @@ -695,15 +695,14 @@ class AutoPlanViewSet(viewsets.ViewSet): if len(recipes) == 0: return Response(serializer.data) - recipes = recipes.order_by('?')[:days] - recipes = list(recipes) + recipes = list(recipes.order_by('?')[:days]) for i in range(0, days): day = start_date + datetime.timedelta(i) recipe = recipes[i % len(recipes)] - args = {'recipe': recipe, 'servings': servings, 'title': recipe.name, + args = {'recipe_id': recipe['id'], 'servings': servings, 'created_by': request.user, - 'meal_type': meal_type, + 'meal_type_id': serializer.validated_data['meal_type_id'], 'note': '', 'date': day, 'space': request.space} m = MealPlan(**args) diff --git a/vue/src/apps/MealPlanView/MealPlanView.vue b/vue/src/apps/MealPlanView/MealPlanView.vue index 2763ac0d..39342410 100644 --- a/vue/src/apps/MealPlanView/MealPlanView.vue +++ b/vue/src/apps/MealPlanView/MealPlanView.vue @@ -83,7 +83,7 @@ - +
- +
@@ -293,12 +292,6 @@ - - {{ $t("Export_To_ICal") }} @@ -307,7 +300,7 @@ @@ -351,7 +344,7 @@ let SETTINGS_COOKIE_NAME = "mealplan_settings" export default { name: "MealPlanView", components: { - AutoMealPlanModal, + AutoMealPlanModal, MealPlanEditModal, MealPlanCard, CalendarView, @@ -365,16 +358,16 @@ export default { mixins: [CalendarMathMixin, ApiMixin, ResolveUrlMixin], data: function () { return { - AutoPlan: { - meal_types: [], - keywords: [[]], - servings: 1, - date: Date.now(), - startDay: null, - endDay: null, - shared: [], - addshopping: false - }, + AutoPlan: { + meal_types: [], + keywords: [[]], + servings: 1, + date: Date.now(), + startDay: null, + endDay: null, + shared: [], + addshopping: false + }, showDate: new Date(), plan_entries: [], recipe_viewed: {}, @@ -688,36 +681,7 @@ export default { createAutoPlan() { this.$bvModal.show(`autoplan-modal`) }, - async autoPlanThread(autoPlan, mealTypeIndex) { - let apiClient = new ApiApiFactory() - let data = { - "start_date" : moment(autoPlan.startDay).format("YYYY-MM-DD"), - "end_date" : moment(autoPlan.endDay).format("YYYY-MM-DD"), - "meal_type_id" : autoPlan.meal_types[mealTypeIndex].id, - "keywords" : autoPlan.keywords[mealTypeIndex], - "servings" : autoPlan.servings, - "shared" : autoPlan.shared, - "addshopping": autoPlan.addshopping - } - await apiClient.createAutoPlanViewSet(data) - }, - async doAutoPlan(autoPlan) { - for (let i = 0; i < autoPlan.meal_types.length; i++) { - if (autoPlan.keywords[i].length === 0) continue - await this.autoPlanThread(autoPlan, i) - } - this.refreshEntries() - }, - refreshEntries(){//todo Remove method - let date = this.current_period - useMealPlanStore().refreshFromAPI(moment(date.periodStart).format("YYYY-MM-DD"), moment(date.periodEnd).format("YYYY-MM-DD")) - }, - deleteAll(){//todo Remove method, only used in debugging - for (let i = 0; i < useMealPlanStore().plan_list.length; i++) { - useMealPlanStore().deleteObject(useMealPlanStore().plan_list[i]) - } - } }, directives: { hover: { diff --git a/vue/src/components/AutoMealPlanModal.vue b/vue/src/components/AutoMealPlanModal.vue index a2997c56..5428fdfe 100644 --- a/vue/src/components/AutoMealPlanModal.vue +++ b/vue/src/components/AutoMealPlanModal.vue @@ -1,79 +1,82 @@ @@ -84,9 +87,11 @@ import GenericMultiselect from "@/components/GenericMultiselect" import {ApiMixin} from "@/utils/utils" import {useUserPreferenceStore} from "@/stores/UserPreferenceStore"; import VueCookies from "vue-cookies"; +import moment from "moment/moment"; +import {useMealPlanStore} from "@/stores/MealPlanStore"; -const { ApiApiFactory } = require("@/utils/openapi/api") -const { StandardToasts } = require("@/utils/utils") +const {ApiApiFactory} = require("@/utils/openapi/api") +const {StandardToasts} = require("@/utils/utils") Vue.use(BootstrapVue) Vue.use(VueCookies) @@ -94,8 +99,8 @@ let MEALPLAN_COOKIE_NAME = "mealplan_settings" export default { name: "AutoMealPlanModal", - components: { - GenericMultiselect + components: { + GenericMultiselect }, props: { modal_title: String, @@ -108,22 +113,23 @@ export default { mixins: [ApiMixin], data() { return { - AutoPlan: { - meal_types: [], - keywords: [[]], - servings: 1, - date: Date.now(), - startDay: null, - endDay: null, - shared: [], - addshopping: false - }, - mealplan_settings: { + AutoPlan: { + meal_types: [], + keywords: [[]], + servings: 1, + date: Date.now(), + startDay: null, + endDay: null, + shared: [], + addshopping: false + }, + mealplan_settings: { addshopping: false, - } + }, + loading: false, } }, - watch: { + watch: { mealplan_settings: { handler(newVal) { this.$cookies.set(MEALPLAN_COOKIE_NAME, this.mealplan_settings) @@ -141,22 +147,25 @@ export default { }, methods: { genericSelectChanged: function (obj) { - this.AutoPlan.keywords[obj.var] = obj.val + this.AutoPlan.keywords[obj.var] = obj.val }, showModal() { - if (this.$cookies.isKey(MEALPLAN_COOKIE_NAME)) { + if (this.$cookies.isKey(MEALPLAN_COOKIE_NAME)) { this.mealplan_settings = Object.assign({}, this.mealplan_settings, this.$cookies.get(MEALPLAN_COOKIE_NAME)) - } - this.refreshMealTypes() + } + this.refreshMealTypes() - this.AutoPlan.servings = 1 - this.AutoPlan.startDay = new Date() - this.AutoPlan.endDay = this.current_period.periodEnd - useUserPreferenceStore().getData().then(userPreference => { - this.AutoPlan.shared = userPreference.plan_share + this.AutoPlan.servings = 1 + this.AutoPlan.startDay = new Date() + this.AutoPlan.endDay = this.current_period.periodEnd + useUserPreferenceStore().getData().then(userPreference => { + this.AutoPlan.shared = userPreference.plan_share }) + this.AutoPlan.addshopping = this.mealplan_settings.addshopping + + this.loading = false }, - sortMealTypes() { + sortMealTypes() { this.meal_types.forEach(function (element, index) { element.order = index }) @@ -178,7 +187,7 @@ export default { }) }) }, - refreshMealTypes() { + refreshMealTypes() { let apiClient = new ApiApiFactory() Promise.resolve(apiClient.listMealTypes().then((result) => { @@ -186,30 +195,57 @@ export default { meal_type.editing = false }) this.AutoPlan.meal_types = result.data - })).then( () => { - let mealArray = this.AutoPlan.meal_types - for (let i = 0; i < mealArray.length; i++) { - this.AutoPlan.keywords[i] = []; - }} + })).then(() => { + let mealArray = this.AutoPlan.meal_types + for (let i = 0; i < mealArray.length; i++) { + this.AutoPlan.keywords[i] = []; + } + } ) }, - createPlan() { - this.$bvModal.hide(`autoplan-modal`) - this.AutoPlan.addshopping = this.mealplan_settings.addshopping - this.$emit("create-plan", this.AutoPlan) + createPlan() { + if (!this.loading) { + this.loading = true + + let requests = [] + for (let i = 0; i < this.AutoPlan.meal_types.length; i++) { + if (this.AutoPlan.keywords[i].length === 0) continue + requests.push(this.autoPlanThread(this.AutoPlan, i)) + } + + Promise.allSettled(requests).then(r => { + this.refreshEntries() + this.loading = false + this.$bvModal.hide(`autoplan-modal`) + }).catch(err => { + StandardToasts.makeStandardToast(this, StandardToasts.FAIL_CREATE, err) + this.loading = false + }) + } + }, - updateStartDay(date){ - this.AutoPlan.startDay = date - }, - updateEndDay(date){ - this.AutoPlan.endDay = date - }, - updateServings(numberOfServings) { - this.AutoPlan.servings = numberOfServings - }, - exitPlan() { - this.$bvModal.hide(`autoplan-modal`) - } + + async autoPlanThread(autoPlan, mealTypeIndex) { + let apiClient = new ApiApiFactory() + let data = { + "start_date": moment(autoPlan.startDay).format("YYYY-MM-DD"), + "end_date": moment(autoPlan.endDay).format("YYYY-MM-DD"), + "meal_type_id": autoPlan.meal_types[mealTypeIndex].id, + "keywords": autoPlan.keywords[mealTypeIndex], + "servings": autoPlan.servings, + "shared": autoPlan.shared, + "addshopping": autoPlan.addshopping + } + return apiClient.createAutoPlanViewSet(data) + + }, + refreshEntries() { //TODO move properly to MealPLanStore (save period for default refresh) + let date = this.current_period + useMealPlanStore().refreshFromAPI(moment(date.periodStart).format("YYYY-MM-DD"), moment(date.periodEnd).format("YYYY-MM-DD")) + }, + exitPlan() { + this.$bvModal.hide(`autoplan-modal`) + } },