From fe11b88fd03ed0100106f52d3139f0f8fb58a4c6 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Sat, 2 Dec 2023 17:41:02 +0100 Subject: [PATCH] pretty nice property editor --- cookbook/views/api.py | 10 ++- vue/src/apps/TestView/TestView.vue | 133 ++++++++++++++++------------- 2 files changed, 82 insertions(+), 61 deletions(-) diff --git a/cookbook/views/api.py b/cookbook/views/api.py index a35ac1ce25..c2f78d72f6 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -612,10 +612,14 @@ def fdc(self, request, pk): data = json.loads(response.content) food_property_list = [] - food_property_types = food.foodproperty_set.values_list('property__property_type_id', flat=True) - for pt in PropertyType.objects.filter(space=request.space).all(): - if pt.fdc_id and pt.id not in food_property_types: + # delete all properties where the property type has a fdc_id as these should be overridden + for fp in food.properties.all(): + if fp.property_type.fdc_id: + fp.delete() + + for pt in PropertyType.objects.filter(space=request.space, fdc_id__gte=0).all(): + if pt.fdc_id: for fn in data['foodNutrients']: if fn['nutrient']['id'] == pt.fdc_id: food_property_list.append(Property( diff --git a/vue/src/apps/TestView/TestView.vue b/vue/src/apps/TestView/TestView.vue index 25a4dd0fe1..31ec9087e4 100644 --- a/vue/src/apps/TestView/TestView.vue +++ b/vue/src/apps/TestView/TestView.vue @@ -4,48 +4,46 @@

{{ recipe.name }}

- +
- - + - - - @@ -57,7 +55,7 @@ :model="Models.PROPERTY_TYPE" :action="Actions.UPDATE" :item1="editing_property_type" - @finish-action="editing_property_type = null; loadPropertyTypes()"> + @finish-action="editing_property_type = null; loadData()"> @@ -86,32 +84,7 @@ export default { mixins: [ApiMixin], components: {GenericModalForm, GenericMultiselect}, computed: { - foods: function () { - let foods = {} - if (this.recipe !== null && this.property_types !== []) { - this.recipe.steps.forEach(s => { - s.ingredients.forEach(i => { - let food = {food: i.food, properties: {}, loading: false} - - this.property_types.forEach(pt => { - food.properties[pt.id] = {changed: false, property_amount: 0, property_type: pt} - }) - i.food.properties.forEach(fp => { - food.properties[fp.property_type.id] = {changed: false, property_amount: fp.property_amount, property_type: fp.property_type} - }) - foods[food.food.id] = food - }) - }) - } - return foods - }, - properties: function () { - let properties = {} - this.property_types.forEach(pt => { - properties[pt.id] = pt - }) - return properties - } + }, data() { return { @@ -119,51 +92,95 @@ export default { property_types: [], editing_property_type: null, loading: false, + foods: [], } }, mounted() { this.$i18n.locale = window.CUSTOM_LOCALE - this.loadRecipe(); - this.loadPropertyTypes(); + this.loadData(); }, methods: { - loadRecipe: function () { + loadData: function () { let apiClient = new ApiApiFactory() - apiClient.retrieveRecipe("112").then(result => { - this.recipe = result.data - this.loading = false; - }).catch((err) => { - StandardToasts.makeStandardToast(this, StandardToasts.FAIL_FETCH, err) - }) - }, - loadPropertyTypes: function () { - let apiClient = new ApiApiFactory() apiClient.listPropertyTypes().then(result => { this.property_types = result.data + + apiClient.retrieveRecipe("112").then(result => { //TODO get recipe id + this.recipe = result.data + + this.foods = [] + + this.recipe.steps.forEach(s => { + s.ingredients.forEach(i => { + if (this.foods.filter(x => (x.id === i.food.id)).length === 0) { + this.foods.push(this.buildFood(i.food)) + } + }) + }) + this.loading = false; + }).catch((err) => { + StandardToasts.makeStandardToast(this, StandardToasts.FAIL_FETCH, err) + }) }).catch((err) => { StandardToasts.makeStandardToast(this, StandardToasts.FAIL_FETCH, err) }) }, + buildFood: function (food) { + /** + * Prepare food for display in grid by making sure the food properties are in the same order as property_types and that no types are missing + * */ + + let existing_properties = {} + food.properties.forEach(fp => { + existing_properties[fp.property_type.id] = fp + }) + + let food_properties = [] + this.property_types.forEach(pt => { + let new_food_property = { + property_type: pt, + property_amount: 0, + } + if (pt.id in existing_properties) { + new_food_property = existing_properties[pt.id] + } + food_properties.push(new_food_property) + }) + + this.$set(food, 'loading', false) + + food.properties = food_properties + + return food + }, + spliceInFood: function (food){ + /** + * replace food in foods list, for example after updates from the server + */ + this.foods = this.foods.map(f => (f.id === food.id) ? food : f) + + }, updateFood: function (food) { let apiClient = new ApiApiFactory() apiClient.partialUpdateFood(food.id, food).then(result => { + this.spliceInFood(this.buildFood(result.data)) StandardToasts.makeStandardToast(this, StandardToasts.SUCCESS_UPDATE) }).catch((err) => { StandardToasts.makeStandardToast(this, StandardToasts.FAIL_UPDATE, err) }) }, updateFoodFromFDC: function (food) { - this.loading = true; + food.loading = true; let apiClient = new ApiApiFactory() apiClient.fdcFood(food.id).then(result => { StandardToasts.makeStandardToast(this, StandardToasts.SUCCESS_UPDATE) - this.loadRecipe() + this.spliceInFood(this.buildFood(result.data)) }).catch((err) => { StandardToasts.makeStandardToast(this, StandardToasts.FAIL_UPDATE, err) - this.loading = false; + food.loading = false; }) } },
{{ $t('Name') }} FDC {{ $t('Properties_Food_Amount') }} {{ $t('Properties_Food_Unit') }} - - + {{ pt.name }} ({{ pt.unit }})
- {{ f.food.name }} + {{ f.name }} + - + - + - + + + + :disabled="f.loading"/> - +