merge ignore shopping with onhand
This commit is contained in:
@ -82,7 +82,7 @@ def list_from_recipe(list_recipe=None, recipe=None, mealplan=None, servings=None
|
|||||||
ingredients = Ingredient.objects.filter(step__recipe=r, space=space)
|
ingredients = Ingredient.objects.filter(step__recipe=r, space=space)
|
||||||
|
|
||||||
if exclude_onhand := created_by.userpreference.mealplan_autoexclude_onhand:
|
if exclude_onhand := created_by.userpreference.mealplan_autoexclude_onhand:
|
||||||
ingredients = ingredients.exclude(food__on_hand=True)
|
ingredients = ingredients.exclude(food__food_onhand=True)
|
||||||
|
|
||||||
if related := created_by.userpreference.mealplan_autoinclude_related:
|
if related := created_by.userpreference.mealplan_autoinclude_related:
|
||||||
# TODO: add levels of related recipes (related recipes of related recipes) to use when auto-adding mealplans
|
# TODO: add levels of related recipes (related recipes of related recipes) to use when auto-adding mealplans
|
||||||
@ -93,7 +93,7 @@ def list_from_recipe(list_recipe=None, recipe=None, mealplan=None, servings=None
|
|||||||
# TODO once/if Steps can have a serving size this needs to be refactored
|
# TODO once/if Steps can have a serving size this needs to be refactored
|
||||||
if exclude_onhand:
|
if exclude_onhand:
|
||||||
# if steps are used more than once in a recipe or subrecipe - I don' think this results in the desired behavior
|
# if steps are used more than once in a recipe or subrecipe - I don' think this results in the desired behavior
|
||||||
related_step_ing += Ingredient.objects.filter(step__recipe=x, food__on_hand=False, space=space).values_list('id', flat=True)
|
related_step_ing += Ingredient.objects.filter(step__recipe=x, food__food_onhand=False, space=space).values_list('id', flat=True)
|
||||||
else:
|
else:
|
||||||
related_step_ing += Ingredient.objects.filter(step__recipe=x, space=space).values_list('id', flat=True)
|
related_step_ing += Ingredient.objects.filter(step__recipe=x, space=space).values_list('id', flat=True)
|
||||||
|
|
||||||
@ -101,10 +101,10 @@ def list_from_recipe(list_recipe=None, recipe=None, mealplan=None, servings=None
|
|||||||
if ingredients.filter(food__recipe=x).exists():
|
if ingredients.filter(food__recipe=x).exists():
|
||||||
for ing in ingredients.filter(food__recipe=x):
|
for ing in ingredients.filter(food__recipe=x):
|
||||||
if exclude_onhand:
|
if exclude_onhand:
|
||||||
x_ing = Ingredient.objects.filter(step__recipe=x, food__on_hand=False, space=space)
|
x_ing = Ingredient.objects.filter(step__recipe=x, food__food_onhand=False, space=space)
|
||||||
else:
|
else:
|
||||||
x_ing = Ingredient.objects.filter(step__recipe=x, space=space)
|
x_ing = Ingredient.objects.filter(step__recipe=x, space=space)
|
||||||
for i in [x for x in x_ing if not x.food.ignore_shopping]:
|
for i in [x for x in x_ing]:
|
||||||
ShoppingListEntry.objects.create(
|
ShoppingListEntry.objects.create(
|
||||||
list_recipe=list_recipe,
|
list_recipe=list_recipe,
|
||||||
food=i.food,
|
food=i.food,
|
||||||
@ -139,7 +139,7 @@ def list_from_recipe(list_recipe=None, recipe=None, mealplan=None, servings=None
|
|||||||
sle.save()
|
sle.save()
|
||||||
|
|
||||||
# add any missing Entrys
|
# add any missing Entrys
|
||||||
for i in [x for x in add_ingredients if x.food and not x.food.ignore_shopping]:
|
for i in [x for x in add_ingredients if x.food]:
|
||||||
|
|
||||||
ShoppingListEntry.objects.create(
|
ShoppingListEntry.objects.create(
|
||||||
list_recipe=list_recipe,
|
list_recipe=list_recipe,
|
||||||
|
@ -28,11 +28,11 @@ class Migration(migrations.Migration):
|
|||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.AddField(
|
# migrations.AddField(
|
||||||
model_name='food',
|
# model_name='food',
|
||||||
name='on_hand',
|
# name='on_hand',
|
||||||
field=models.BooleanField(default=False),
|
# field=models.BooleanField(default=False),
|
||||||
),
|
# ),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='shoppinglistentry',
|
model_name='shoppinglistentry',
|
||||||
name='completed_at',
|
name='completed_at',
|
||||||
|
@ -21,7 +21,7 @@ def delete_orphaned_sle(apps, schema_editor):
|
|||||||
|
|
||||||
def create_inheritfields(apps, schema_editor):
|
def create_inheritfields(apps, schema_editor):
|
||||||
FoodInheritField.objects.create(name='Supermarket Category', field='supermarket_category')
|
FoodInheritField.objects.create(name='Supermarket Category', field='supermarket_category')
|
||||||
FoodInheritField.objects.create(name='Ignore Shopping', field='ignore_shopping')
|
FoodInheritField.objects.create(name='On Hand', field='food_onhand')
|
||||||
FoodInheritField.objects.create(name='Diet', field='diet')
|
FoodInheritField.objects.create(name='Diet', field='diet')
|
||||||
FoodInheritField.objects.create(name='Substitute', field='substitute')
|
FoodInheritField.objects.create(name='Substitute', field='substitute')
|
||||||
FoodInheritField.objects.create(name='Substitute Children', field='substitute_children')
|
FoodInheritField.objects.create(name='Substitute Children', field='substitute_children')
|
||||||
|
35
cookbook/migrations/0163_auto_20211229_1411.py
Normal file
35
cookbook/migrations/0163_auto_20211229_1411.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# Generated by Django 3.2.10 on 2021-12-29 20:11
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
from cookbook.models import FoodInheritField
|
||||||
|
|
||||||
|
# TODO this can be deleted
|
||||||
|
# def temp_migration(apps, schema_editor):
|
||||||
|
# x = FoodInheritField.objects.get(name='Ignore Shopping', field='ignore_shopping')
|
||||||
|
# x.name = 'On Hand'
|
||||||
|
# x.field = 'food_onhand'
|
||||||
|
# x.save
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('cookbook', '0162_userpreference_csv_delim'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
# TODO this can be deleted
|
||||||
|
# migrations.RunPython(temp_migration),
|
||||||
|
# TODO this stays
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name='food',
|
||||||
|
old_name='ignore_shopping',
|
||||||
|
new_name='food_onhand',
|
||||||
|
),
|
||||||
|
# TODO this can be deleted
|
||||||
|
# migrations.RemoveField(
|
||||||
|
# model_name='food',
|
||||||
|
# name='on_hand',
|
||||||
|
# ),
|
||||||
|
]
|
@ -490,9 +490,9 @@ class Food(ExportModelOperationsMixin('food'), TreeModel, PermissionModelMixin):
|
|||||||
name = models.CharField(max_length=128, validators=[MinLengthValidator(1)])
|
name = models.CharField(max_length=128, validators=[MinLengthValidator(1)])
|
||||||
recipe = models.ForeignKey('Recipe', null=True, blank=True, on_delete=models.SET_NULL)
|
recipe = models.ForeignKey('Recipe', null=True, blank=True, on_delete=models.SET_NULL)
|
||||||
supermarket_category = models.ForeignKey(SupermarketCategory, null=True, blank=True, on_delete=models.SET_NULL)
|
supermarket_category = models.ForeignKey(SupermarketCategory, null=True, blank=True, on_delete=models.SET_NULL)
|
||||||
ignore_shopping = models.BooleanField(default=False) # inherited field
|
food_onhand = models.BooleanField(default=False) # inherited field
|
||||||
description = models.TextField(default='', blank=True)
|
description = models.TextField(default='', blank=True)
|
||||||
on_hand = models.BooleanField(default=False)
|
# on_hand = models.BooleanField(default=False)
|
||||||
inherit = models.BooleanField(default=False)
|
inherit = models.BooleanField(default=False)
|
||||||
ignore_inherit = models.ManyToManyField(FoodInheritField, blank=True) # inherited field: is this name better as inherit instead of ignore inherit? which is more intuitive?
|
ignore_inherit = models.ManyToManyField(FoodInheritField, blank=True) # inherited field: is this name better as inherit instead of ignore inherit? which is more intuitive?
|
||||||
|
|
||||||
@ -528,10 +528,10 @@ class Food(ExportModelOperationsMixin('food'), TreeModel, PermissionModelMixin):
|
|||||||
])
|
])
|
||||||
|
|
||||||
inherit = inherit.values_list('field', flat=True)
|
inherit = inherit.values_list('field', flat=True)
|
||||||
if 'ignore_shopping' in inherit:
|
if 'food_onhand' in inherit:
|
||||||
# get food at root that have children that need updated
|
# get food at root that have children that need updated
|
||||||
Food.include_descendants(queryset=Food.objects.filter(depth=1, numchild__gt=0, space=space, ignore_shopping=True)).update(ignore_shopping=True)
|
Food.include_descendants(queryset=Food.objects.filter(depth=1, numchild__gt=0, space=space, food_onhand=True)).update(food_onhand=True)
|
||||||
Food.include_descendants(queryset=Food.objects.filter(depth=1, numchild__gt=0, space=space, ignore_shopping=False)).update(ignore_shopping=False)
|
Food.include_descendants(queryset=Food.objects.filter(depth=1, numchild__gt=0, space=space, food_onhand=False)).update(food_onhand=False)
|
||||||
if 'supermarket_category' in inherit:
|
if 'supermarket_category' in inherit:
|
||||||
# when supermarket_category is null or blank assuming it is not set and not intended to be blank for all descedants
|
# when supermarket_category is null or blank assuming it is not set and not intended to be blank for all descedants
|
||||||
# find top node that has category set
|
# find top node that has category set
|
||||||
|
@ -402,8 +402,8 @@ class FoodSerializer(UniqueFieldsMixin, WritableNestedModelSerializer, ExtendedR
|
|||||||
class Meta:
|
class Meta:
|
||||||
model = Food
|
model = Food
|
||||||
fields = (
|
fields = (
|
||||||
'id', 'name', 'description', 'shopping', 'recipe', 'ignore_shopping', 'supermarket_category',
|
'id', 'name', 'description', 'shopping', 'recipe', 'food_onhand', 'supermarket_category',
|
||||||
'image', 'parent', 'numchild', 'numrecipe', 'on_hand', 'inherit', 'ignore_inherit', 'full_name'
|
'image', 'parent', 'numchild', 'numrecipe', 'inherit', 'ignore_inherit', 'full_name'
|
||||||
)
|
)
|
||||||
read_only_fields = ('id', 'numchild', 'parent', 'image', 'numrecipe')
|
read_only_fields = ('id', 'numchild', 'parent', 'image', 'numrecipe')
|
||||||
|
|
||||||
@ -867,7 +867,7 @@ class FoodExportSerializer(FoodSerializer):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Food
|
model = Food
|
||||||
fields = ('name', 'ignore_shopping', 'supermarket_category', 'on_hand')
|
fields = ('name', 'food_onhand', 'supermarket_category',)
|
||||||
|
|
||||||
|
|
||||||
class IngredientExportSerializer(WritableNestedModelSerializer):
|
class IngredientExportSerializer(WritableNestedModelSerializer):
|
||||||
|
@ -75,8 +75,8 @@ def update_food_inheritance(sender, instance=None, created=False, **kwargs):
|
|||||||
# apply changes from parent to instance for each inheritted field
|
# apply changes from parent to instance for each inheritted field
|
||||||
if instance.inherit and instance.parent and inherit.count() > 0:
|
if instance.inherit and instance.parent and inherit.count() > 0:
|
||||||
parent = instance.get_parent()
|
parent = instance.get_parent()
|
||||||
if 'ignore_shopping' in inherit:
|
if 'food_onhand' in inherit:
|
||||||
instance.ignore_shopping = parent.ignore_shopping
|
instance.food_onhand = parent.food_onhand
|
||||||
# if supermarket_category is not set, do not cascade - if this becomes non-intuitive can change
|
# if supermarket_category is not set, do not cascade - if this becomes non-intuitive can change
|
||||||
if 'supermarket_category' in inherit and parent.supermarket_category:
|
if 'supermarket_category' in inherit and parent.supermarket_category:
|
||||||
instance.supermarket_category = parent.supermarket_category
|
instance.supermarket_category = parent.supermarket_category
|
||||||
@ -89,8 +89,8 @@ def update_food_inheritance(sender, instance=None, created=False, **kwargs):
|
|||||||
# TODO figure out how to generalize this
|
# TODO figure out how to generalize this
|
||||||
# apply changes to direct children - depend on save signals for those objects to cascade inheritance down
|
# apply changes to direct children - depend on save signals for those objects to cascade inheritance down
|
||||||
_save = []
|
_save = []
|
||||||
for child in instance.get_children().filter(inherit=True).exclude(ignore_inherit__field='ignore_shopping'):
|
for child in instance.get_children().filter(inherit=True).exclude(ignore_inherit__field='food_onhand'):
|
||||||
child.ignore_shopping = instance.ignore_shopping
|
child.food_onhand = instance.food_onhand
|
||||||
_save.append(child)
|
_save.append(child)
|
||||||
# don't cascade empty supermarket category
|
# don't cascade empty supermarket category
|
||||||
if instance.supermarket_category:
|
if instance.supermarket_category:
|
||||||
|
@ -834,7 +834,7 @@
|
|||||||
this.$http.get('{% url 'api:recipe-detail' 123456 %}'.replace('123456', recipe.id)).then((response) => {
|
this.$http.get('{% url 'api:recipe-detail' 123456 %}'.replace('123456', recipe.id)).then((response) => {
|
||||||
for (let s of response.data.steps) {
|
for (let s of response.data.steps) {
|
||||||
for (let i of s.ingredients) {
|
for (let i of s.ingredients) {
|
||||||
if (!i.is_header && i.food !== null && i.food.ignore_shopping === false) {
|
if (!i.is_header && i.food !== null && i.food.food_onhand === false) {
|
||||||
this.shopping_list.entries.push({
|
this.shopping_list.entries.push({
|
||||||
'list_recipe': slr.id,
|
'list_recipe': slr.id,
|
||||||
'food': i.food,
|
'food': i.food,
|
||||||
|
@ -471,8 +471,8 @@ def test_tree_filter(obj_tree_1, obj_2, obj_3, u1_s1):
|
|||||||
@pytest.mark.parametrize("obj_tree_1, field, inherit, new_val", [
|
@pytest.mark.parametrize("obj_tree_1, field, inherit, new_val", [
|
||||||
({'has_category': True, 'inherit': True}, 'supermarket_category', True, 'cat_1'),
|
({'has_category': True, 'inherit': True}, 'supermarket_category', True, 'cat_1'),
|
||||||
({'has_category': True, 'inherit': False}, 'supermarket_category', False, 'cat_1'),
|
({'has_category': True, 'inherit': False}, 'supermarket_category', False, 'cat_1'),
|
||||||
({'ignore_shopping': True, 'inherit': True}, 'ignore_shopping', True, 'false'),
|
({'food_onhand': True, 'inherit': True}, 'food_onhand', True, 'false'),
|
||||||
({'ignore_shopping': True, 'inherit': False}, 'ignore_shopping', False, 'false'),
|
({'food_onhand': True, 'inherit': False}, 'food_onhand', False, 'false'),
|
||||||
], indirect=['obj_tree_1']) # indirect=True populates magic variable request.param of obj_tree_1 with the parameter
|
], indirect=['obj_tree_1']) # indirect=True populates magic variable request.param of obj_tree_1 with the parameter
|
||||||
def test_inherit(request, obj_tree_1, field, inherit, new_val, u1_s1):
|
def test_inherit(request, obj_tree_1, field, inherit, new_val, u1_s1):
|
||||||
with scope(space=obj_tree_1.space):
|
with scope(space=obj_tree_1.space):
|
||||||
@ -498,7 +498,7 @@ def test_inherit(request, obj_tree_1, field, inherit, new_val, u1_s1):
|
|||||||
|
|
||||||
@pytest.mark.parametrize("obj_tree_1, field, inherit, new_val", [
|
@pytest.mark.parametrize("obj_tree_1, field, inherit, new_val", [
|
||||||
({'has_category': True, 'inherit': True, }, 'supermarket_category', True, 'cat_1'),
|
({'has_category': True, 'inherit': True, }, 'supermarket_category', True, 'cat_1'),
|
||||||
({'ignore_shopping': True, 'inherit': True, }, 'ignore_shopping', True, 'false'),
|
({'food_onhand': True, 'inherit': True, }, 'food_onhand', True, 'false'),
|
||||||
], indirect=['obj_tree_1'])
|
], indirect=['obj_tree_1'])
|
||||||
# This is more about the model than the API - should this be moved to a different test?
|
# This is more about the model than the API - should this be moved to a different test?
|
||||||
def test_ignoreinherit_field(request, obj_tree_1, field, inherit, new_val, u1_s1):
|
def test_ignoreinherit_field(request, obj_tree_1, field, inherit, new_val, u1_s1):
|
||||||
@ -527,16 +527,16 @@ def test_ignoreinherit_field(request, obj_tree_1, field, inherit, new_val, u1_s1
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("obj_tree_1", [
|
@pytest.mark.parametrize("obj_tree_1", [
|
||||||
({'has_category': True, 'inherit': False, 'ignore_shopping': True}),
|
({'has_category': True, 'inherit': False, 'food_onhand': True}),
|
||||||
], indirect=['obj_tree_1'])
|
], indirect=['obj_tree_1'])
|
||||||
def test_reset_inherit(obj_tree_1, space_1):
|
def test_reset_inherit(obj_tree_1, space_1):
|
||||||
with scope(space=space_1):
|
with scope(space=space_1):
|
||||||
space_1.food_inherit.add(*Food.inherit_fields.values_list('id', flat=True)) # set default inherit fields
|
space_1.food_inherit.add(*Food.inherit_fields.values_list('id', flat=True)) # set default inherit fields
|
||||||
parent = obj_tree_1.get_parent()
|
parent = obj_tree_1.get_parent()
|
||||||
child = obj_tree_1.get_descendants()[0]
|
child = obj_tree_1.get_descendants()[0]
|
||||||
obj_tree_1.ignore_shopping = False
|
obj_tree_1.food_onhand = False
|
||||||
assert parent.ignore_shopping == child.ignore_shopping
|
assert parent.food_onhand == child.food_onhand
|
||||||
assert parent.ignore_shopping != obj_tree_1.ignore_shopping
|
assert parent.food_onhand != obj_tree_1.food_onhand
|
||||||
assert parent.supermarket_category != child.supermarket_category
|
assert parent.supermarket_category != child.supermarket_category
|
||||||
assert parent.supermarket_category != obj_tree_1.supermarket_category
|
assert parent.supermarket_category != obj_tree_1.supermarket_category
|
||||||
|
|
||||||
@ -545,5 +545,5 @@ def test_reset_inherit(obj_tree_1, space_1):
|
|||||||
obj_tree_1 = Food.objects.get(id=obj_tree_1.id)
|
obj_tree_1 = Food.objects.get(id=obj_tree_1.id)
|
||||||
parent = obj_tree_1.get_parent()
|
parent = obj_tree_1.get_parent()
|
||||||
child = obj_tree_1.get_descendants()[0]
|
child = obj_tree_1.get_descendants()[0]
|
||||||
assert parent.ignore_shopping == obj_tree_1.ignore_shopping == child.ignore_shopping
|
assert parent.food_onhand == obj_tree_1.food_onhand == child.food_onhand
|
||||||
assert parent.supermarket_category == obj_tree_1.supermarket_category == child.supermarket_category
|
assert parent.supermarket_category == obj_tree_1.supermarket_category == child.supermarket_category
|
||||||
|
@ -185,27 +185,24 @@ def test_shopping_recipe_edit(request, recipe, sle_count, use_mealplan, u1_s1, u
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("user2, sle_count", [
|
@pytest.mark.parametrize("user2, sle_count", [
|
||||||
({'mealplan_autoadd_shopping': False}, (0, 17)),
|
({'mealplan_autoadd_shopping': False}, (0, 18)),
|
||||||
({'mealplan_autoinclude_related': False}, (8, 8)),
|
({'mealplan_autoinclude_related': False}, (9, 9)),
|
||||||
({'mealplan_autoexclude_onhand': False}, (19, 19)),
|
({'mealplan_autoexclude_onhand': False}, (20, 20)),
|
||||||
({'mealplan_autoexclude_onhand': False, 'mealplan_autoinclude_related': False}, (9, 9)),
|
({'mealplan_autoexclude_onhand': False, 'mealplan_autoinclude_related': False}, (10, 10)),
|
||||||
], indirect=['user2'])
|
], indirect=['user2'])
|
||||||
@pytest.mark.parametrize("use_mealplan", [(False), (True), ])
|
@pytest.mark.parametrize("use_mealplan", [(False), (True), ])
|
||||||
@pytest.mark.parametrize("recipe", [({'steps__recipe_count': 1})], indirect=['recipe'])
|
@pytest.mark.parametrize("recipe", [({'steps__recipe_count': 1})], indirect=['recipe'])
|
||||||
def test_shopping_recipe_userpreference(recipe, sle_count, use_mealplan, user2):
|
def test_shopping_recipe_userpreference(recipe, sle_count, use_mealplan, user2):
|
||||||
with scopes_disabled():
|
with scopes_disabled():
|
||||||
user = auth.get_user(user2)
|
user = auth.get_user(user2)
|
||||||
# setup recipe with 10 ingredients, 1 step recipe with 10 ingredients, 2 food onhand(from recipe and step_recipe), 1 food ignore shopping
|
# setup recipe with 10 ingredients, 1 step recipe with 10 ingredients, 2 food onhand(from recipe and step_recipe)
|
||||||
ingredients = Ingredient.objects.filter(step__recipe=recipe)
|
ingredients = Ingredient.objects.filter(step__recipe=recipe)
|
||||||
food = Food.objects.get(id=ingredients[2].food.id)
|
food = Food.objects.get(id=ingredients[2].food.id)
|
||||||
food.on_hand = True
|
food.food_onhand = True
|
||||||
food.save()
|
food.save()
|
||||||
food = recipe.steps.filter(type=Step.RECIPE).first().step_recipe.steps.first().ingredients.first().food
|
food = recipe.steps.filter(type=Step.RECIPE).first().step_recipe.steps.first().ingredients.first().food
|
||||||
food = Food.objects.get(id=food.id)
|
food = Food.objects.get(id=food.id)
|
||||||
food.on_hand = True
|
food.food_onhand = True
|
||||||
food.save()
|
|
||||||
food = Food.objects.get(id=ingredients[4].food.id)
|
|
||||||
food.ignore_shopping = True
|
|
||||||
food.save()
|
food.save()
|
||||||
|
|
||||||
if use_mealplan:
|
if use_mealplan:
|
||||||
|
@ -19,8 +19,10 @@
|
|||||||
<!-- <span><b-button variant="link" size="sm" class="text-dark shadow-none"><i class="fas fa-chevron-down"></i></b-button></span> -->
|
<!-- <span><b-button variant="link" size="sm" class="text-dark shadow-none"><i class="fas fa-chevron-down"></i></b-button></span> -->
|
||||||
<model-menu />
|
<model-menu />
|
||||||
<span>{{ this.this_model.name }}</span>
|
<span>{{ this.this_model.name }}</span>
|
||||||
<span v-if="this_model.name !== 'Step'"
|
<span v-if="apiName !== 'Step'">
|
||||||
><b-button variant="link" @click="startAction({ action: 'new' })"><i class="fas fa-plus-circle fa-2x"></i></b-button></span
|
<b-button variant="link" @click="startAction({ action: 'new' })">
|
||||||
|
<i class="fas fa-plus-circle fa-2x"></i>
|
||||||
|
</b-button> </span
|
||||||
><!-- TODO add proper field to model config to determine if create should be available or not -->
|
><!-- TODO add proper field to model config to determine if create should be available or not -->
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
@ -112,6 +114,9 @@ export default {
|
|||||||
// TODO this is not necessarily bad but maybe there are better options to do this
|
// TODO this is not necessarily bad but maybe there are better options to do this
|
||||||
return () => import(/* webpackChunkName: "header-component" */ `@/components/${this.header_component_name}`)
|
return () => import(/* webpackChunkName: "header-component" */ `@/components/${this.header_component_name}`)
|
||||||
},
|
},
|
||||||
|
apiName() {
|
||||||
|
return this.this_model?.apiName
|
||||||
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
// value is passed from lists.py
|
// value is passed from lists.py
|
||||||
@ -291,11 +296,6 @@ export default {
|
|||||||
this.refreshCard({ ...food }, this.items_right)
|
this.refreshCard({ ...food }, this.items_right)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
addOnhand: function (item) {
|
|
||||||
item.on_hand = true
|
|
||||||
this.saveThis(item)
|
|
||||||
},
|
|
||||||
|
|
||||||
updateThis: function (item) {
|
updateThis: function (item) {
|
||||||
this.refreshThis(item.id)
|
this.refreshThis(item.id)
|
||||||
},
|
},
|
||||||
|
@ -493,15 +493,6 @@
|
|||||||
</b-form-group>
|
</b-form-group>
|
||||||
</ContextMenuItem>
|
</ContextMenuItem>
|
||||||
|
|
||||||
<ContextMenuItem
|
|
||||||
@click="
|
|
||||||
$refs.menu.close()
|
|
||||||
ignoreThis(contextData)
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<a class="dropdown-item p-2" href="#"><i class="fas fa-ban"></i> {{ $t("IgnoreThis", { food: foodName(contextData) }) }}</a>
|
|
||||||
</ContextMenuItem>
|
|
||||||
|
|
||||||
<ContextMenuItem
|
<ContextMenuItem
|
||||||
@click="
|
@click="
|
||||||
$refs.menu.close()
|
$refs.menu.close()
|
||||||
@ -908,13 +899,6 @@ export default {
|
|||||||
getThis: function (id) {
|
getThis: function (id) {
|
||||||
return this.genericAPI(this.Models.SHOPPING_CATEGORY, this.Actions.FETCH, { id: id })
|
return this.genericAPI(this.Models.SHOPPING_CATEGORY, this.Actions.FETCH, { id: id })
|
||||||
},
|
},
|
||||||
ignoreThis: function (item) {
|
|
||||||
let food = {
|
|
||||||
id: item?.[0]?.food.id ?? item.food.id,
|
|
||||||
ignore_shopping: true,
|
|
||||||
}
|
|
||||||
this.updateFood(food, "ignore_shopping")
|
|
||||||
},
|
|
||||||
mergeShoppingList: function (data) {
|
mergeShoppingList: function (data) {
|
||||||
this.items.map((x) =>
|
this.items.map((x) =>
|
||||||
data.map((y) => {
|
data.map((y) => {
|
||||||
@ -941,10 +925,10 @@ export default {
|
|||||||
let api = new ApiApiFactory()
|
let api = new ApiApiFactory()
|
||||||
let food = {
|
let food = {
|
||||||
id: item?.[0]?.food.id ?? item?.food?.id,
|
id: item?.[0]?.food.id ?? item?.food?.id,
|
||||||
on_hand: true,
|
food_onhand: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
this.updateFood(food)
|
this.updateFood(food, "food_onhand")
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
let entries = this.items.filter((x) => x.food.id == food.id).map((x) => x.id)
|
let entries = this.items.filter((x) => x.food.id == food.id).map((x) => x.id)
|
||||||
this.items = this.items.filter((x) => x.food.id !== food.id)
|
this.items = this.items.filter((x) => x.food.id !== food.id)
|
||||||
|
@ -1,35 +1,29 @@
|
|||||||
<template>
|
<template>
|
||||||
<span>
|
<span>
|
||||||
<linked-recipe v-if="linkedRecipe"
|
<linked-recipe v-if="linkedRecipe" :item="item" />
|
||||||
:item="item"/>
|
<icon-badge v-if="Icon" :item="item" />
|
||||||
<icon-badge v-if="Icon"
|
<on-hand-badge v-if="OnHand" :item="item" />
|
||||||
:item="item"/>
|
<shopping-badge v-if="Shopping" :item="item" />
|
||||||
<on-hand-badge v-if="OnHand"
|
|
||||||
:item="item"/>
|
|
||||||
<shopping-badge v-if="Shopping"
|
|
||||||
:item="item"/>
|
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import LinkedRecipe from "@/components/Badges/LinkedRecipe";
|
import LinkedRecipe from "@/components/Badges/LinkedRecipe"
|
||||||
import IconBadge from "@/components/Badges/Icon";
|
import IconBadge from "@/components/Badges/Icon"
|
||||||
import OnHandBadge from "@/components/Badges/OnHand";
|
import OnHandBadge from "@/components/Badges/OnHand"
|
||||||
import ShoppingBadge from "@/components/Badges/Shopping";
|
import ShoppingBadge from "@/components/Badges/Shopping"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'CardBadges',
|
name: "CardBadges",
|
||||||
components: { LinkedRecipe, IconBadge, OnHandBadge, ShoppingBadge },
|
components: { LinkedRecipe, IconBadge, OnHandBadge, ShoppingBadge },
|
||||||
props: {
|
props: {
|
||||||
item: { type: Object },
|
item: { type: Object },
|
||||||
model: {type: Object}
|
model: { type: Object },
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {}
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
},
|
},
|
||||||
|
mounted() {},
|
||||||
computed: {
|
computed: {
|
||||||
linkedRecipe: function () {
|
linkedRecipe: function () {
|
||||||
return this.model?.badges?.linked_recipe ?? false
|
return this.model?.badges?.linked_recipe ?? false
|
||||||
@ -38,15 +32,13 @@ export default {
|
|||||||
return this.model?.badges?.icon ?? false
|
return this.model?.badges?.icon ?? false
|
||||||
},
|
},
|
||||||
OnHand: function () {
|
OnHand: function () {
|
||||||
return this.model?.badges?.on_hand ?? false
|
return this.model?.badges?.food_onhand ?? false
|
||||||
},
|
},
|
||||||
Shopping: function () {
|
Shopping: function () {
|
||||||
return this.model?.badges?.shopping ?? false
|
return this.model?.badges?.shopping ?? false
|
||||||
}
|
|
||||||
},
|
},
|
||||||
watch: {
|
|
||||||
},
|
},
|
||||||
methods: {
|
watch: {},
|
||||||
}
|
methods: {},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
@ -26,16 +26,16 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.onhand = this.item.on_hand
|
this.onhand = this.item.food_onhand
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
"item.on_hand": function(newVal, oldVal) {
|
"item.food_onhand": function (newVal, oldVal) {
|
||||||
this.onhand = newVal
|
this.onhand = newVal
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
toggleOnHand() {
|
toggleOnHand() {
|
||||||
let params = { id: this.item.id, on_hand: !this.onhand }
|
let params = { id: this.item.id, food_onhand: !this.onhand }
|
||||||
this.genericAPI(this.Models.FOOD, this.Actions.UPDATE, params).then(() => {
|
this.genericAPI(this.Models.FOOD, this.Actions.UPDATE, params).then(() => {
|
||||||
this.onhand = !this.onhand
|
this.onhand = !this.onhand
|
||||||
})
|
})
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<span>
|
<span>
|
||||||
<b-button class="btn text-decoration-none px-1 border-0" variant="link" v-if="ShowBadge" :id="`shopping${item.id}`" @click="addShopping()">
|
<b-button class="btn text-decoration-none px-1 border-0" variant="link" :id="`shopping${item.id}`" @click="addShopping()">
|
||||||
<i
|
<i
|
||||||
class="fas"
|
class="fas"
|
||||||
v-b-popover.hover.html
|
v-b-popover.hover.html
|
||||||
@ -27,7 +27,6 @@ export default {
|
|||||||
name: "ShoppingBadge",
|
name: "ShoppingBadge",
|
||||||
props: {
|
props: {
|
||||||
item: { type: Object },
|
item: { type: Object },
|
||||||
override_ignore: { type: Boolean, default: false },
|
|
||||||
},
|
},
|
||||||
mixins: [ApiMixin],
|
mixins: [ApiMixin],
|
||||||
data() {
|
data() {
|
||||||
@ -40,13 +39,6 @@ export default {
|
|||||||
this.shopping = this.item?.shopping //?? random[Math.floor(Math.random() * random.length)]
|
this.shopping = this.item?.shopping //?? random[Math.floor(Math.random() * random.length)]
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
ShowBadge() {
|
|
||||||
if (this.override_ignore) {
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return !this.item.ignore_shopping
|
|
||||||
}
|
|
||||||
},
|
|
||||||
DeleteConfirmation() {
|
DeleteConfirmation() {
|
||||||
return this.$t("DeleteShoppingConfirm", { food: this.item.name })
|
return this.$t("DeleteShoppingConfirm", { food: this.item.name })
|
||||||
},
|
},
|
||||||
|
@ -1,74 +1,52 @@
|
|||||||
<template>
|
<template>
|
||||||
<!-- <b-button variant="link" size="sm" class="text-dark shadow-none"><i class="fas fa-chevron-down"></i></b-button> -->
|
<!-- <b-button variant="link" size="sm" class="text-dark shadow-none"><i class="fas fa-chevron-down"></i></b-button> -->
|
||||||
<span>
|
<span>
|
||||||
<b-dropdown variant="link" toggle-class="text-decoration-none text-dark shadow-none" no-caret
|
<b-dropdown variant="link" toggle-class="text-decoration-none text-dark shadow-none" no-caret style="boundary: window">
|
||||||
style="boundary:window">
|
|
||||||
<template #button-content>
|
<template #button-content>
|
||||||
<i class="fas fa-chevron-down"></i>
|
<i class="fas fa-chevron-down"></i>
|
||||||
</template>
|
</template>
|
||||||
<b-dropdown-item :href="resolveDjangoUrl('list_food')">
|
<b-dropdown-item :href="resolveDjangoUrl('list_food')"> <i class="fas fa-leaf fa-fw"></i> {{ Models["FOOD"].name }} </b-dropdown-item>
|
||||||
<i class="fas fa-leaf fa-fw"></i> {{ Models['FOOD'].name }}
|
|
||||||
</b-dropdown-item>
|
|
||||||
|
|
||||||
<b-dropdown-item :href="resolveDjangoUrl('list_keyword')">
|
<b-dropdown-item :href="resolveDjangoUrl('list_keyword')"> <i class="fas fa-tags fa-fw"></i> {{ Models["KEYWORD"].name }} </b-dropdown-item>
|
||||||
<i class="fas fa-tags fa-fw"></i> {{ Models['KEYWORD'].name }}
|
|
||||||
</b-dropdown-item>
|
|
||||||
|
|
||||||
<b-dropdown-item :href="resolveDjangoUrl('list_unit')">
|
<b-dropdown-item :href="resolveDjangoUrl('list_unit')"> <i class="fas fa-balance-scale fa-fw"></i> {{ Models["UNIT"].name }} </b-dropdown-item>
|
||||||
<i class="fas fa-balance-scale fa-fw"></i> {{ Models['UNIT'].name }}
|
|
||||||
</b-dropdown-item>
|
|
||||||
|
|
||||||
<b-dropdown-item :href="resolveDjangoUrl('list_supermarket')">
|
<b-dropdown-item :href="resolveDjangoUrl('list_supermarket')"> <i class="fas fa-store-alt fa-fw"></i> {{ Models["SUPERMARKET"].name }} </b-dropdown-item>
|
||||||
<i class="fas fa-store-alt fa-fw"></i> {{ Models['SUPERMARKET'].name }}
|
|
||||||
</b-dropdown-item>
|
|
||||||
|
|
||||||
<b-dropdown-item :href="resolveDjangoUrl('list_supermarket_category')">
|
<b-dropdown-item :href="resolveDjangoUrl('list_supermarket_category')"> <i class="fas fa-cubes fa-fw"></i> {{ Models["SHOPPING_CATEGORY"].name }} </b-dropdown-item>
|
||||||
<i class="fas fa-cubes fa-fw"></i> {{ Models['SHOPPING_CATEGORY'].name }}
|
|
||||||
</b-dropdown-item>
|
|
||||||
|
|
||||||
<b-dropdown-item :href="resolveDjangoUrl('list_automation')">
|
<b-dropdown-item :href="resolveDjangoUrl('list_automation')"> <i class="fas fa-robot fa-fw"></i> {{ Models["AUTOMATION"].name }} </b-dropdown-item>
|
||||||
<i class="fas fa-robot fa-fw"></i> {{ Models['AUTOMATION'].name }}
|
|
||||||
</b-dropdown-item>
|
|
||||||
|
|
||||||
<b-dropdown-item :href="resolveDjangoUrl('list_user_file')">
|
<b-dropdown-item :href="resolveDjangoUrl('list_user_file')"> <i class="fas fa-file fa-fw"></i> {{ Models["USERFILE"].name }} </b-dropdown-item>
|
||||||
<i class="fas fa-file fa-fw"></i> {{ Models['USERFILE'].name }}
|
|
||||||
</b-dropdown-item>
|
|
||||||
|
|
||||||
<b-dropdown-item :href="resolveDjangoUrl('list_step')">
|
|
||||||
<i class="fas fa-puzzle-piece fa-fw"></i>{{ Models['STEP'].name }}
|
|
||||||
</b-dropdown-item>
|
|
||||||
|
|
||||||
|
<b-dropdown-item :href="resolveDjangoUrl('list_step')"> <i class="fas fa-puzzle-piece fa-fw"></i>{{ Models["STEP"].name }} </b-dropdown-item>
|
||||||
</b-dropdown>
|
</b-dropdown>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import Vue from "vue"
|
||||||
|
import { BootstrapVue } from "bootstrap-vue"
|
||||||
|
import "bootstrap-vue/dist/bootstrap-vue.css"
|
||||||
|
|
||||||
import Vue from 'vue'
|
import { Models } from "@/utils/models"
|
||||||
import {BootstrapVue} from 'bootstrap-vue'
|
import { ResolveUrlMixin } from "@/utils/utils"
|
||||||
import 'bootstrap-vue/dist/bootstrap-vue.css'
|
|
||||||
|
|
||||||
import {Models} from "@/utils/models";
|
|
||||||
import {ResolveUrlMixin} from "@/utils/utils";
|
|
||||||
|
|
||||||
|
|
||||||
Vue.use(BootstrapVue)
|
Vue.use(BootstrapVue)
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ModelMenu',
|
name: "ModelMenu",
|
||||||
mixins: [ResolveUrlMixin],
|
mixins: [ResolveUrlMixin],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
Models: Models
|
Models: Models,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {},
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
gotoURL: function (model) {
|
gotoURL: function (model) {
|
||||||
return
|
return
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
</script>
|
@ -191,7 +191,7 @@ export default {
|
|||||||
return this.model?.ordered_tags ?? []
|
return this.model?.ordered_tags ?? []
|
||||||
},
|
},
|
||||||
getFullname: function () {
|
getFullname: function () {
|
||||||
if (!this.item?.full_name.includes(">")) {
|
if (!this.item?.full_name?.includes(">")) {
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
return this.item?.full_name
|
return this.item?.full_name
|
||||||
|
@ -10,12 +10,7 @@
|
|||||||
export default {
|
export default {
|
||||||
name: "GenericPill",
|
name: "GenericPill",
|
||||||
props: {
|
props: {
|
||||||
item_list: {
|
item_list: { type: Object },
|
||||||
type: Array,
|
|
||||||
default() {
|
|
||||||
return []
|
|
||||||
},
|
|
||||||
},
|
|
||||||
label: { type: String, default: "name" },
|
label: { type: String, default: "name" },
|
||||||
color: { type: String, default: "light" },
|
color: { type: String, default: "light" },
|
||||||
},
|
},
|
||||||
|
@ -33,8 +33,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td v-else-if="show_shopping" class="text-right text-nowrap">
|
<td v-else-if="show_shopping" class="text-right text-nowrap">
|
||||||
<!-- in shopping mode and ingredient is not ignored -->
|
|
||||||
<div v-if="!ingredient.food.ignore_shopping">
|
|
||||||
<b-button
|
<b-button
|
||||||
class="btn text-decoration-none fas fa-shopping-cart px-2 user-select-none"
|
class="btn text-decoration-none fas fa-shopping-cart px-2 user-select-none"
|
||||||
variant="link"
|
variant="link"
|
||||||
@ -49,15 +47,6 @@
|
|||||||
<input type="checkbox" class="align-middle" v-model="shop" @change="changeShopping" />
|
<input type="checkbox" class="align-middle" v-model="shop" @change="changeShopping" />
|
||||||
</span>
|
</span>
|
||||||
<on-hand-badge :item="ingredient.food" />
|
<on-hand-badge :item="ingredient.food" />
|
||||||
</div>
|
|
||||||
<div v-else>
|
|
||||||
<!-- or in shopping mode and food is ignored: Shopping Badge bypasses linking ingredient to Recipe which would get ignored -->
|
|
||||||
<shopping-badge :item="ingredient.food" :override_ignore="true" class="px-1" />
|
|
||||||
<span class="px-2">
|
|
||||||
<input type="checkbox" class="align-middle" disabled v-b-popover.hover.click.blur :title="$t('IgnoredFood', { food: ingredient.food.name })" />
|
|
||||||
</span>
|
|
||||||
<on-hand-badge :item="ingredient.food" />
|
|
||||||
</div>
|
|
||||||
</td>
|
</td>
|
||||||
</template>
|
</template>
|
||||||
</tr>
|
</tr>
|
||||||
@ -66,11 +55,10 @@
|
|||||||
<script>
|
<script>
|
||||||
import { calculateAmount, ResolveUrlMixin, ApiMixin } from "@/utils/utils"
|
import { calculateAmount, ResolveUrlMixin, ApiMixin } from "@/utils/utils"
|
||||||
import OnHandBadge from "@/components/Badges/OnHand"
|
import OnHandBadge from "@/components/Badges/OnHand"
|
||||||
import ShoppingBadge from "@/components/Badges/Shopping"
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "IngredientComponent",
|
name: "IngredientComponent",
|
||||||
components: { OnHandBadge, ShoppingBadge },
|
components: { OnHandBadge },
|
||||||
props: {
|
props: {
|
||||||
ingredient: Object,
|
ingredient: Object,
|
||||||
ingredient_factor: { type: Number, default: 1 },
|
ingredient_factor: { type: Number, default: 1 },
|
||||||
@ -129,7 +117,7 @@ export default {
|
|||||||
} else {
|
} else {
|
||||||
// there are not recipes in the shopping list
|
// there are not recipes in the shopping list
|
||||||
// set default value
|
// set default value
|
||||||
this.shop = !this.ingredient?.food?.on_hand && !this.ingredient?.food?.ignore_shopping && !this.ingredient?.food?.recipe
|
this.shop = !this.ingredient?.food?.food_onhand && !this.ingredient?.food?.recipe
|
||||||
this.$emit("add-to-shopping", { item: this.ingredient, add: this.shop })
|
this.$emit("add-to-shopping", { item: this.ingredient, add: this.shop })
|
||||||
// mark checked if the food is in the shopping list for this ingredient/recipe
|
// mark checked if the food is in the shopping list for this ingredient/recipe
|
||||||
if (count_shopping_ingredient >= 1) {
|
if (count_shopping_ingredient >= 1) {
|
||||||
@ -146,8 +134,8 @@ export default {
|
|||||||
|
|
||||||
if (this.add_shopping_mode) {
|
if (this.add_shopping_mode) {
|
||||||
// if we are in add shopping mode (e.g. recipe_shopping_modal) start with all checks marked
|
// if we are in add shopping mode (e.g. recipe_shopping_modal) start with all checks marked
|
||||||
// except if on_hand and ignore_shopping (could be if recipe too?)
|
// except if on_hand (could be if recipe too?)
|
||||||
this.shop = !this.ingredient?.food?.on_hand && !this.ingredient?.food?.ignore_shopping && !this.ingredient?.food?.recipe
|
this.shop = !this.ingredient?.food?.food_onhand && !this.ingredient?.food?.recipe
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -106,7 +106,7 @@ export default {
|
|||||||
...this.steps
|
...this.steps
|
||||||
.map((x) => x.ingredients)
|
.map((x) => x.ingredients)
|
||||||
.flat()
|
.flat()
|
||||||
.filter((x) => !x?.food?.on_hand && !x?.food?.ignore_shopping)
|
.filter((x) => !x?.food?.food_onhand)
|
||||||
.map((x) => x.id),
|
.map((x) => x.id),
|
||||||
]
|
]
|
||||||
this.recipe_servings = result.data?.servings
|
this.recipe_servings = result.data?.servings
|
||||||
@ -141,7 +141,7 @@ export default {
|
|||||||
.flat()
|
.flat()
|
||||||
.map((x) => x.ingredients)
|
.map((x) => x.ingredients)
|
||||||
.flat()
|
.flat()
|
||||||
.filter((x) => !x.food.on_hand && !x.food.ignore_shopping)
|
.filter((x) => !x.food.override_ignore)
|
||||||
.map((x) => x.id),
|
.map((x) => x.id),
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
@ -179,7 +179,7 @@
|
|||||||
"AddToShopping": "Add to shopping list",
|
"AddToShopping": "Add to shopping list",
|
||||||
"IngredientInShopping": "This ingredient is in your shopping list.",
|
"IngredientInShopping": "This ingredient is in your shopping list.",
|
||||||
"NotInShopping": "{food} is not in your shopping list.",
|
"NotInShopping": "{food} is not in your shopping list.",
|
||||||
"OnHand": "Have On Hand",
|
"OnHand": "Currently On Hand",
|
||||||
"FoodOnHand": "You have {food} on hand.",
|
"FoodOnHand": "You have {food} on hand.",
|
||||||
"FoodNotOnHand": "You do not have {food} on hand.",
|
"FoodNotOnHand": "You do not have {food} on hand.",
|
||||||
"Undefined": "Undefined",
|
"Undefined": "Undefined",
|
||||||
@ -240,13 +240,13 @@
|
|||||||
"shopping_share": "Share Shopping List",
|
"shopping_share": "Share Shopping List",
|
||||||
"shopping_auto_sync": "Autosync",
|
"shopping_auto_sync": "Autosync",
|
||||||
"mealplan_autoadd_shopping": "Auto Add Meal Plan",
|
"mealplan_autoadd_shopping": "Auto Add Meal Plan",
|
||||||
"mealplan_autoexclude_onhand": "Exclude On Hand",
|
"mealplan_autoexclude_onhand": "Exclude Food On Hand",
|
||||||
"mealplan_autoinclude_related": "Add Related Recipes",
|
"mealplan_autoinclude_related": "Add Related Recipes",
|
||||||
"default_delay": "Default Delay Hours",
|
"default_delay": "Default Delay Hours",
|
||||||
"shopping_share_desc": "Users will see all items you add to your shopping list. They must add you to see items on their list.",
|
"shopping_share_desc": "Users will see all items you add to your shopping list. They must add you to see items on their list.",
|
||||||
"shopping_auto_sync_desc": "Setting to 0 will disable auto sync. When viewing a shopping list the list is updated every set seconds to sync changes someone else might have made. Useful when shopping with multiple people but will use mobile data.",
|
"shopping_auto_sync_desc": "Setting to 0 will disable auto sync. When viewing a shopping list the list is updated every set seconds to sync changes someone else might have made. Useful when shopping with multiple people but will use mobile data.",
|
||||||
"mealplan_autoadd_shopping_desc": "Automatically add meal plan ingredients to shopping list.",
|
"mealplan_autoadd_shopping_desc": "Automatically add meal plan ingredients to shopping list.",
|
||||||
"mealplan_autoexclude_onhand_desc": "When adding a meal plan to the shopping list (manually or automatically), exclude ingredients that are on hand.",
|
"mealplan_autoexclude_onhand_desc": "When adding a meal plan to the shopping list (manually or automatically), exclude ingredients that are currently on hand.",
|
||||||
"mealplan_autoinclude_related_desc": "When adding a meal plan to the shopping list (manually or automatically), include all related recipes.",
|
"mealplan_autoinclude_related_desc": "When adding a meal plan to the shopping list (manually or automatically), include all related recipes.",
|
||||||
"default_delay_desc": "Default number of hours to delay a shopping list entry.",
|
"default_delay_desc": "Default number of hours to delay a shopping list entry.",
|
||||||
"filter_to_supermarket": "Filter to Supermarket",
|
"filter_to_supermarket": "Filter to Supermarket",
|
||||||
|
@ -69,14 +69,14 @@ export class Models {
|
|||||||
onhand: true,
|
onhand: true,
|
||||||
badges: {
|
badges: {
|
||||||
linked_recipe: true,
|
linked_recipe: true,
|
||||||
on_hand: true,
|
food_onhand: true,
|
||||||
shopping: true,
|
shopping: true,
|
||||||
},
|
},
|
||||||
tags: [{ field: "supermarket_category", label: "name", color: "info" }],
|
tags: [{ field: "supermarket_category", label: "name", color: "info" }],
|
||||||
// REQUIRED: unordered array of fields that can be set during create
|
// REQUIRED: unordered array of fields that can be set during create
|
||||||
create: {
|
create: {
|
||||||
// if not defined partialUpdate will use the same parameters, prepending 'id'
|
// if not defined partialUpdate will use the same parameters, prepending 'id'
|
||||||
params: [["name", "description", "recipe", "ignore_shopping", "supermarket_category", "on_hand", "inherit", "ignore_inherit"]],
|
params: [["name", "description", "recipe", "food_onhand", "supermarket_category", "inherit", "ignore_inherit"]],
|
||||||
|
|
||||||
form: {
|
form: {
|
||||||
name: {
|
name: {
|
||||||
@ -103,13 +103,7 @@ export class Models {
|
|||||||
shopping: {
|
shopping: {
|
||||||
form_field: true,
|
form_field: true,
|
||||||
type: "checkbox",
|
type: "checkbox",
|
||||||
field: "ignore_shopping",
|
field: "food_onhand",
|
||||||
label: i18n.t("Ignore_Shopping"),
|
|
||||||
},
|
|
||||||
onhand: {
|
|
||||||
form_field: true,
|
|
||||||
type: "checkbox",
|
|
||||||
field: "on_hand",
|
|
||||||
label: i18n.t("OnHand"),
|
label: i18n.t("OnHand"),
|
||||||
},
|
},
|
||||||
shopping_category: {
|
shopping_category: {
|
||||||
@ -507,6 +501,14 @@ export class Models {
|
|||||||
apiName: "User",
|
apiName: "User",
|
||||||
paginated: false,
|
paginated: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static STEP = {
|
||||||
|
name: i18n.t("Step"),
|
||||||
|
apiName: "Step",
|
||||||
|
list: {
|
||||||
|
params: ["recipe", "query", "page", "pageSize", "options"],
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Actions {
|
export class Actions {
|
||||||
|
Reference in New Issue
Block a user