diff --git a/cookbook/migrations/0141_auto_20210713_1042.py b/cookbook/migrations/0141_auto_20210713_1042.py new file mode 100644 index 000000000..bb4f1d0b8 --- /dev/null +++ b/cookbook/migrations/0141_auto_20210713_1042.py @@ -0,0 +1,24 @@ +# Generated by Django 3.2.5 on 2021-07-13 08:42 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('cookbook', '0140_userpreference_created_at'), + ] + + operations = [ + migrations.AddField( + model_name='step', + name='step_recipe', + field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.PROTECT, to='cookbook.recipe'), + ), + migrations.AlterField( + model_name='step', + name='type', + field=models.CharField(choices=[('TEXT', 'Text'), ('TIME', 'Time'), ('FILE', 'File'), ('RECIPE', 'Recipe')], default='TEXT', max_length=16), + ), + ] diff --git a/cookbook/models.py b/cookbook/models.py index f753cbeeb..d81811281 100644 --- a/cookbook/models.py +++ b/cookbook/models.py @@ -331,10 +331,11 @@ class Step(ExportModelOperationsMixin('step'), models.Model, PermissionModelMixi TEXT = 'TEXT' TIME = 'TIME' FILE = 'FILE' + RECIPE = 'RECIPE' name = models.CharField(max_length=128, default='', blank=True) type = models.CharField( - choices=((TEXT, _('Text')), (TIME, _('Time')), (FILE, _('File')),), + choices=((TEXT, _('Text')), (TIME, _('Time')), (FILE, _('File')), (RECIPE, _('Recipe')),), default=TEXT, max_length=16 ) @@ -344,6 +345,7 @@ class Step(ExportModelOperationsMixin('step'), models.Model, PermissionModelMixi order = models.IntegerField(default=0) file = models.ForeignKey('UserFile', on_delete=models.PROTECT, null=True, blank=True) show_as_header = models.BooleanField(default=True) + step_recipe = models.ForeignKey('Recipe', default=None, blank=True, null=True, on_delete=models.PROTECT) space = models.ForeignKey(Space, on_delete=models.CASCADE) objects = ScopedManager(space='space') diff --git a/cookbook/serializer.py b/cookbook/serializer.py index 76fe45a44..412c953ec 100644 --- a/cookbook/serializer.py +++ b/cookbook/serializer.py @@ -300,6 +300,7 @@ class StepSerializer(WritableNestedModelSerializer): ingredients_markdown = serializers.SerializerMethodField('get_ingredients_markdown') ingredients_vue = serializers.SerializerMethodField('get_ingredients_vue') file = UserFileViewSerializer(allow_null=True, required=False) + step_recipe_data = serializers.SerializerMethodField('get_step_recipe_data') def create(self, validated_data): validated_data['space'] = self.context['request'].space @@ -311,11 +312,27 @@ class StepSerializer(WritableNestedModelSerializer): def get_ingredients_markdown(self, obj): return obj.get_instruction_render() + def get_step_recipe_data(self, obj): + # check if root type is recipe to prevent infinite recursion + # can be improved later to allow multi level embedding + if obj.step_recipe and type(self.parent.root) == RecipeSerializer: + return StepRecipeSerializer(obj.step_recipe).data + class Meta: model = Step fields = ( 'id', 'name', 'type', 'instruction', 'ingredients', 'ingredients_markdown', - 'ingredients_vue', 'time', 'order', 'show_as_header', 'file', + 'ingredients_vue', 'time', 'order', 'show_as_header', 'file', 'step_recipe', 'step_recipe_data' + ) + + +class StepRecipeSerializer(WritableNestedModelSerializer): + steps = StepSerializer(many=True) + + class Meta: + model = Recipe + fields = ( + 'id', 'name', 'steps', ) diff --git a/cookbook/templates/forms/edit_internal_recipe.html b/cookbook/templates/forms/edit_internal_recipe.html index f65235572..5cd4e04c8 100644 --- a/cookbook/templates/forms/edit_internal_recipe.html +++ b/cookbook/templates/forms/edit_internal_recipe.html @@ -202,6 +202,7 @@ + @@ -214,7 +215,7 @@ :id="'id_step_' + step.id + '_time'"> -
+
+ +
+ + + +