allow marking recipe as food
This commit is contained in:
parent
c950e6dabb
commit
486d197854
@ -364,16 +364,23 @@ class SupermarketSerializer(UniqueFieldsMixin, SpacedModelSerializer):
|
|||||||
fields = ('id', 'name', 'description', 'category_to_supermarket')
|
fields = ('id', 'name', 'description', 'category_to_supermarket')
|
||||||
|
|
||||||
|
|
||||||
class RecipeSimpleSerializer(serializers.ModelSerializer):
|
class RecipeSimpleSerializer(WritableNestedModelSerializer):
|
||||||
url = serializers.SerializerMethodField('get_url')
|
url = serializers.SerializerMethodField('get_url')
|
||||||
|
|
||||||
def get_url(self, obj):
|
def get_url(self, obj):
|
||||||
return reverse('view_recipe', args=[obj.id])
|
return reverse('view_recipe', args=[obj.id])
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
# don't allow writing to Recipe via this API
|
||||||
|
return Recipe.objects.get(**validated_data)
|
||||||
|
|
||||||
|
def update(self, instance, validated_data):
|
||||||
|
# don't allow writing to Recipe via this API
|
||||||
|
return Recipe.objects.get(**validated_data)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Recipe
|
model = Recipe
|
||||||
fields = ('id', 'name', 'url')
|
fields = ('id', 'name', 'url')
|
||||||
read_only_fields = ['id', 'name', 'url']
|
|
||||||
|
|
||||||
|
|
||||||
class FoodSimpleSerializer(serializers.ModelSerializer):
|
class FoodSimpleSerializer(serializers.ModelSerializer):
|
||||||
@ -427,6 +434,8 @@ class FoodSerializer(UniqueFieldsMixin, WritableNestedModelSerializer, ExtendedR
|
|||||||
name=sc_name,
|
name=sc_name,
|
||||||
space=space, defaults=sm_category)
|
space=space, defaults=sm_category)
|
||||||
onhand = validated_data.pop('food_onhand', None)
|
onhand = validated_data.pop('food_onhand', None)
|
||||||
|
if recipe := validated_data.get('recipe', None):
|
||||||
|
validated_data['recipe'] = Recipe.objects.get(**recipe)
|
||||||
|
|
||||||
# assuming if on hand for user also onhand for shopping_share users
|
# assuming if on hand for user also onhand for shopping_share users
|
||||||
if not onhand is None:
|
if not onhand is None:
|
||||||
|
@ -79,7 +79,7 @@
|
|||||||
:loading="keywords_loading"
|
:loading="keywords_loading"
|
||||||
@search-change="searchKeywords"
|
@search-change="searchKeywords"
|
||||||
>
|
>
|
||||||
<template v-slot:noOptions>{{ $t("empty_list") }}</template>
|
<template v-slot:noOptions>{{ $t("empty_list") }}</template>
|
||||||
</multiselect>
|
</multiselect>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -140,6 +140,24 @@
|
|||||||
</div>
|
</div>
|
||||||
</b-collapse>
|
</b-collapse>
|
||||||
</div>
|
</div>
|
||||||
|
<b-card-header header-tag="header" class="p-1" role="tab">
|
||||||
|
<b-button squared block v-b-toggle.additional_collapse class="text-left" variant="outline-primary">{{ $t("additional_options") }}</b-button>
|
||||||
|
</b-card-header>
|
||||||
|
<b-collapse id="additional_collapse" class="mt-2" v-model="additional_visible">
|
||||||
|
<b-form-group>
|
||||||
|
<b-input-group-append>
|
||||||
|
<b-input-group-text squared> {{ $t("Create Food") }}</b-input-group-text>
|
||||||
|
<b-input-group-text squared>
|
||||||
|
<b-form-checkbox v-model="recipe.create_food"></b-form-checkbox>
|
||||||
|
</b-input-group-text>
|
||||||
|
<b-input-group-text squared v-if="recipe.create_food"> {{ $t("Name") }}</b-input-group-text>
|
||||||
|
<b-form-input squared v-if="recipe.create_food" v-model="recipe.food_name" id="food_name"></b-form-input>
|
||||||
|
</b-input-group-append>
|
||||||
|
<em class="small text-muted">
|
||||||
|
{{ $t("create_food_desc") }}
|
||||||
|
</em>
|
||||||
|
</b-form-group>
|
||||||
|
</b-collapse>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -260,7 +278,7 @@
|
|||||||
style="flex-grow: 1; flex-shrink: 1; flex-basis: 0"
|
style="flex-grow: 1; flex-shrink: 1; flex-basis: 0"
|
||||||
@search-change="searchFiles"
|
@search-change="searchFiles"
|
||||||
>
|
>
|
||||||
<template v-slot:noOptions>{{ $t("empty_list") }}</template>
|
<template v-slot:noOptions>{{ $t("empty_list") }}</template>
|
||||||
</multiselect>
|
</multiselect>
|
||||||
<b-input-group-append>
|
<b-input-group-append>
|
||||||
<b-button
|
<b-button
|
||||||
@ -300,7 +318,7 @@
|
|||||||
:loading="recipes_loading"
|
:loading="recipes_loading"
|
||||||
@search-change="searchRecipes"
|
@search-change="searchRecipes"
|
||||||
>
|
>
|
||||||
<template v-slot:noOptions>{{ $t("empty_list") }}</template>
|
<template v-slot:noOptions>{{ $t("empty_list") }}</template>
|
||||||
</multiselect>
|
</multiselect>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -362,7 +380,7 @@
|
|||||||
:loading="units_loading"
|
:loading="units_loading"
|
||||||
@search-change="searchUnits"
|
@search-change="searchUnits"
|
||||||
>
|
>
|
||||||
<template v-slot:noOptions>{{ $t("empty_list") }}</template>
|
<template v-slot:noOptions>{{ $t("empty_list") }}</template>
|
||||||
</multiselect>
|
</multiselect>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-4 col-md-6 small-padding" v-if="!ingredient.is_header">
|
<div class="col-lg-4 col-md-6 small-padding" v-if="!ingredient.is_header">
|
||||||
@ -392,7 +410,7 @@
|
|||||||
:loading="foods_loading"
|
:loading="foods_loading"
|
||||||
@search-change="searchFoods"
|
@search-change="searchFoods"
|
||||||
>
|
>
|
||||||
<template v-slot:noOptions>{{ $t("empty_list") }}</template>
|
<template v-slot:noOptions>{{ $t("empty_list") }}</template>
|
||||||
</multiselect>
|
</multiselect>
|
||||||
</div>
|
</div>
|
||||||
<div class="small-padding" v-bind:class="{ 'col-lg-4 col-md-6': !ingredient.is_header, 'col-lg-12 col-md-12': ingredient.is_header }">
|
<div class="small-padding" v-bind:class="{ 'col-lg-4 col-md-6': !ingredient.is_header, 'col-lg-12 col-md-12': ingredient.is_header }">
|
||||||
@ -617,6 +635,8 @@ export default {
|
|||||||
paste_step: undefined,
|
paste_step: undefined,
|
||||||
show_file_create: false,
|
show_file_create: false,
|
||||||
step_for_file_create: undefined,
|
step_for_file_create: undefined,
|
||||||
|
additional_visible: false,
|
||||||
|
create_food: undefined,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -648,6 +668,12 @@ export default {
|
|||||||
this.recipe_changed = this.recipe_changed !== undefined
|
this.recipe_changed = this.recipe_changed !== undefined
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"recipe.name": function () {
|
||||||
|
this.recipe.food_name = this.recipe.name.toLowerCase()
|
||||||
|
},
|
||||||
|
"recipe.create_food": function () {
|
||||||
|
this.create_food = this.recipe.create_food
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
keyboardListener: function (e) {
|
keyboardListener: function (e) {
|
||||||
@ -734,6 +760,9 @@ export default {
|
|||||||
.then((response) => {
|
.then((response) => {
|
||||||
StandardToasts.makeStandardToast(StandardToasts.SUCCESS_UPDATE)
|
StandardToasts.makeStandardToast(StandardToasts.SUCCESS_UPDATE)
|
||||||
this.recipe_changed = false
|
this.recipe_changed = false
|
||||||
|
if (this.create_food) {
|
||||||
|
apiFactory.createFood({ name: this.recipe.food_name, recipe: { id: this.recipe.id, name: this.recipe.name } })
|
||||||
|
}
|
||||||
if (view_after) {
|
if (view_after) {
|
||||||
location.href = resolveDjangoUrl("view_recipe", this.recipe_id)
|
location.href = resolveDjangoUrl("view_recipe", this.recipe_id)
|
||||||
}
|
}
|
||||||
|
@ -376,5 +376,8 @@
|
|||||||
"Keyword": "Keyword",
|
"Keyword": "Keyword",
|
||||||
"Advanced": "Advanced",
|
"Advanced": "Advanced",
|
||||||
"Page": "Page",
|
"Page": "Page",
|
||||||
"Reset": "Reset"
|
"Reset": "Reset",
|
||||||
|
"Create Food": "Create Food",
|
||||||
|
"create_food_desc": "Create a food and link it to this recipe.",
|
||||||
|
"additional_options": "Additional Options"
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user