From 3236b65d9e04ea73f8a272e05c643ea43e09e5a5 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Wed, 24 May 2023 13:49:29 +0200 Subject: [PATCH] food editor and property view improvements --- cookbook/models.py | 51 ++--- cookbook/views/api.py | 4 + recipes/settings.py | 3 + vue/src/apps/RecipeView/RecipeView.vue | 4 +- vue/src/components/FoodEditor.vue | 181 +++++++++++------- .../components/FoodPropertyViewComponent.vue | 34 +++- .../components/Modals/GenericModalForm.vue | 2 +- 7 files changed, 177 insertions(+), 102 deletions(-) diff --git a/cookbook/models.py b/cookbook/models.py index 7a7891d0..a84b943c 100644 --- a/cookbook/models.py +++ b/cookbook/models.py @@ -82,31 +82,34 @@ class TreeManager(MP_NodeManager): # model.Manager get_or_create() is not compatible with MP_Tree def get_or_create(self, *args, **kwargs): kwargs['name'] = kwargs['name'].strip() - - if obj := self.filter(name__iexact=kwargs['name'], space=kwargs['space']).first(): - return obj, False + if hasattr(self, 'space'): + if obj := self.filter(name__iexact=kwargs['name'], space=kwargs['space']).first(): + return obj, False else: - with scopes_disabled(): - try: - defaults = kwargs.pop('defaults', None) - if defaults: - kwargs = {**kwargs, **defaults} - # ManyToMany fields can't be set this way, so pop them out to save for later - fields = [field.name for field in self.model._meta.get_fields() if issubclass(type(field), ManyToManyField)] - many_to_many = {field: kwargs.pop(field) for field in list(kwargs) if field in fields} - obj = self.model.add_root(**kwargs) - for field in many_to_many: - field_model = getattr(obj, field).model - for related_obj in many_to_many[field]: - if isinstance(related_obj, User): - getattr(obj, field).add(field_model.objects.get(id=related_obj.id)) - else: - getattr(obj, field).add(field_model.objects.get(**dict(related_obj))) - return obj, True - except IntegrityError as e: - if 'Key (path)' in e.args[0]: - self.model.fix_tree(fix_paths=True) - return self.model.add_root(**kwargs), True + if obj := self.filter(name__iexact=kwargs['name']).first(): + return obj, False + + with scopes_disabled(): + try: + defaults = kwargs.pop('defaults', None) + if defaults: + kwargs = {**kwargs, **defaults} + # ManyToMany fields can't be set this way, so pop them out to save for later + fields = [field.name for field in self.model._meta.get_fields() if issubclass(type(field), ManyToManyField)] + many_to_many = {field: kwargs.pop(field) for field in list(kwargs) if field in fields} + obj = self.model.add_root(**kwargs) + for field in many_to_many: + field_model = getattr(obj, field).model + for related_obj in many_to_many[field]: + if isinstance(related_obj, User): + getattr(obj, field).add(field_model.objects.get(id=related_obj.id)) + else: + getattr(obj, field).add(field_model.objects.get(**dict(related_obj))) + return obj, True + except IntegrityError as e: + if 'Key (path)' in e.args[0]: + self.model.fix_tree(fix_paths=True) + return self.model.add_root(**kwargs), True class TreeModel(MP_Node): diff --git a/cookbook/views/api.py b/cookbook/views/api.py index a77ea5ca..9681f17c 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -250,6 +250,9 @@ class MergeMixin(ViewSetMixin): isTree = False try: + if isinstance(source, Food): + FoodProperty.objects.filter(food=source).delete() + for link in [field for field in source._meta.get_fields() if issubclass(type(field), ForeignObjectRel)]: linkManager = getattr(source, link.get_accessor_name()) related = linkManager.all() @@ -279,6 +282,7 @@ class MergeMixin(ViewSetMixin): source.delete() return Response(content, status=status.HTTP_200_OK) except Exception: + traceback.print_exc() content = {'error': True, 'msg': _(f'An error occurred attempting to merge {source.name} with {target.name}')} return Response(content, status=status.HTTP_400_BAD_REQUEST) diff --git a/recipes/settings.py b/recipes/settings.py index d05d0373..479bf144 100644 --- a/recipes/settings.py +++ b/recipes/settings.py @@ -11,6 +11,7 @@ https://docs.djangoproject.com/en/2.0/ref/settings/ """ import ast import json +import mimetypes import os import re import sys @@ -519,3 +520,5 @@ EMAIL_USE_SSL = bool(int(os.getenv('EMAIL_USE_SSL', False))) DEFAULT_FROM_EMAIL = os.getenv('DEFAULT_FROM_EMAIL', 'webmaster@localhost') ACCOUNT_EMAIL_SUBJECT_PREFIX = os.getenv( 'ACCOUNT_EMAIL_SUBJECT_PREFIX', '[Tandoor Recipes] ') # allauth sender prefix + +mimetypes.add_type("text/javascript", ".js", True) \ No newline at end of file diff --git a/vue/src/apps/RecipeView/RecipeView.vue b/vue/src/apps/RecipeView/RecipeView.vue index 59d9f953..b13fbce3 100644 --- a/vue/src/apps/RecipeView/RecipeView.vue +++ b/vue/src/apps/RecipeView/RecipeView.vue @@ -137,9 +137,7 @@
- - - +
diff --git a/vue/src/components/FoodEditor.vue b/vue/src/components/FoodEditor.vue index 4b111ceb..ad84bd71 100644 --- a/vue/src/components/FoodEditor.vue +++ b/vue/src/components/FoodEditor.vue @@ -36,12 +36,12 @@ @@ -54,12 +54,12 @@ @@ -76,13 +76,13 @@ @@ -90,12 +90,12 @@ @@ -108,24 +108,24 @@ @@ -174,15 +174,16 @@ export default { props: { id: {type: String, default: 'id_food_edit_modal_modal'}, show: {required: true, type: Boolean, default: false}, + item1: { + type: Object, + default: undefined + }, }, watch: { show: function () { - console.log('trigger') if (this.show) { - console.log('show modal') this.$bvModal.show(this.id) } else { - console.log('show modal false') this.$bvModal.hide(this.id) } }, @@ -197,9 +198,35 @@ export default { this.$bvModal.show(this.id) this.$i18n.locale = window.CUSTOM_LOCALE let apiClient = new ApiApiFactory() - apiClient.retrieveFood('1').then((r) => { - this.food = r.data + let pf + if (this.item1.id !== undefined) { + pf = apiClient.retrieveFood(this.item1.id).then((r) => { + this.food = r.data + }).catch(err => { + StandardToasts.makeStandardToast(this, StandardToasts.FAIL_FETCH, err) + }) + } else { + this.food = { + name: "", + plural_name: "", + description: "", + shopping: false, + recipe: null, + food_onhand: false, + supermarket_category: null, + parent: null, + numchild: 0, + inherit_fields: [], + ignore_shopping: false, + substitute: [], + substitute_siblings: false, + substitute_children: false, + substitute_onhand: false, + child_inherit_fields: [], + } + } + Promise.allSettled([pf]).then(r => { let property_types = [] let property_values = [] @@ -207,15 +234,18 @@ export default { property_types = r.data }) - let p2 = apiClient.listFoodPropertys(this.food.id).then((r) => { - property_values = r.data - }) + let p2 + if (this.food.id !== undefined) { + p2 = apiClient.listFoodPropertys(this.food.id).then((r) => { + property_values = r.data + }) + } Promise.allSettled([p1, p2]).then(r => { property_types.forEach(fpt => { let food_property = { - 'food_amount': 0, - 'food_unit': null, + 'food_amount': 100, + 'food_unit': {'name': 'g'}, 'food': this.food, 'property_amount': 0, 'property_type': fpt, @@ -234,35 +264,46 @@ export default { }) }) }) - - }, methods: { updateFood: function () { let apiClient = new ApiApiFactory() - apiClient.updateFood(this.food.id, this.food).then((r) => { - this.food = r.data - StandardToasts.makeStandardToast(this, StandardToasts.SUCCESS_UPDATE) - }).catch(err => { - StandardToasts.makeStandardToast(this, StandardToasts.FAIL_UPDATE, err) + let p + if (this.food.id !== undefined) { + p = apiClient.updateFood(this.food.id, this.food).then((r) => { + this.food = r.data + StandardToasts.makeStandardToast(this, StandardToasts.SUCCESS_UPDATE) + }).catch(err => { + StandardToasts.makeStandardToast(this, StandardToasts.FAIL_UPDATE, err) + }) + } else { + p = apiClient.createFood(this.food).then((r) => { + this.food = r.data + StandardToasts.makeStandardToast(this, StandardToasts.SUCCESS_CREATE) + }).catch(err => { + StandardToasts.makeStandardToast(this, StandardToasts.FAIL_UPDATE, err) + }) + } + + Promise.allSettled([p]).then(r => { + this.food_properties.forEach(fp => { + fp.food = this.food + if (fp.id === undefined) { + apiClient.createFoodProperty(fp).then((r) => { + fp = r.data + }).catch(err => { + StandardToasts.makeStandardToast(this, StandardToasts.FAIL_UPDATE, err) + }) + } else { + apiClient.updateFoodProperty(fp.id, fp).then((r) => { + fp = r.data + }).catch(err => { + StandardToasts.makeStandardToast(this, StandardToasts.FAIL_UPDATE, err) + }) + } + }) }) - this.food_properties.forEach(fp => { - if (fp.id === undefined) { - apiClient.createFoodProperty(fp).then((r) => { - fp = r.data - }).catch(err => { - StandardToasts.makeStandardToast(this, StandardToasts.FAIL_UPDATE, err) - }) - } else { - apiClient.updateFoodProperty(fp.id, fp).then((r) => { - fp = r.data - }).catch(err => { - StandardToasts.makeStandardToast(this, StandardToasts.FAIL_UPDATE, err) - }) - } - - }) }, cancelAction: function () { this.$emit("hidden", "") diff --git a/vue/src/components/FoodPropertyViewComponent.vue b/vue/src/components/FoodPropertyViewComponent.vue index 6278ffe6..e51cd6a1 100644 --- a/vue/src/components/FoodPropertyViewComponent.vue +++ b/vue/src/components/FoodPropertyViewComponent.vue @@ -49,24 +49,34 @@ - +
{{ f.food }}{{ f.food }} {{ f.value }} {{ selected_property.unit }}
- + + +