more recipe editor

This commit is contained in:
vabene1111
2024-03-05 21:46:50 +01:00
parent 82ebeacea9
commit 73ba5a591d
5 changed files with 148 additions and 17 deletions

View File

@@ -1,8 +1,21 @@
<template> <template>
<v-table density="compact" v-if="ingredients.length > 0"> <v-table density="compact" v-if="ingredients.length > 0">
<tbody>
<IngredientsTableRow v-for="i in ingredients" :ingredient="i" :key="i.id"></IngredientsTableRow> <template v-if="draggable">
</tbody> <draggable tag="tbody" v-model="mutable_ingredients" handle=".drag-handle" item-key="id">
<template #item="{element}">
<IngredientsTableRow :ingredient="element" :key="element.id" :show-notes="showNotes" :draggable="draggable"></IngredientsTableRow>
</template>
</draggable>
</template>
<template v-else>
<tbody>
<!-- TODO make into one condition so there is no duplicate code possibly by disabling dragging when not enabled?! -->
<IngredientsTableRow v-for="i in ingredients" :ingredient="i" :key="i.id" :show-notes="showNotes" :draggable="draggable"></IngredientsTableRow>
</tbody>
</template>
</v-table> </v-table>
</template> </template>
@@ -10,18 +23,31 @@
import {defineComponent, PropType} from 'vue' import {defineComponent, PropType} from 'vue'
import {Ingredient, Step} from "@/openapi"; import {Ingredient, Step} from "@/openapi";
import IngredientsTableRow from "@/components/display/IngredientsTableRow.vue"; import IngredientsTableRow from "@/components/display/IngredientsTableRow.vue";
import draggable from 'vuedraggable'
export default defineComponent({ export default defineComponent({
name: "IngredientsTable", name: "IngredientsTable",
components: {IngredientsTableRow}, components: {IngredientsTableRow, draggable},
props: { props: {
ingredients: { ingredients: {
type: Array as PropType<Array<Ingredient>>, type: Array as PropType<Array<Ingredient>>,
default: [], default: [],
}, },
showNotes: {
type: Boolean,
default: true
},
draggable: {
type: Boolean,
},
},
data() {
return {
mutable_ingredients: [] as Ingredient[]
}
}, },
mounted() { mounted() {
this.mutable_ingredients = this.ingredients
} }
}) })
</script> </script>

View File

@@ -7,11 +7,14 @@
<td>{{ ingredient.amount }}</td> <td>{{ ingredient.amount }}</td>
<td><span v-if="ingredient.unit != null">{{ ingredient.unit.name }}</span></td> <td><span v-if="ingredient.unit != null">{{ ingredient.unit.name }}</span></td>
<td><span v-if="ingredient.food != null">{{ ingredient.food.name }}</span></td> <td><span v-if="ingredient.food != null">{{ ingredient.food.name }}</span></td>
<td> <td v-if="showNotes">
<v-icon class="far fa-comment" v-if="ingredient.note != ''" @click="show_tooltip = !show_tooltip"> <v-icon class="far fa-comment" v-if="ingredient.note != ''" @click="show_tooltip = !show_tooltip">
<v-tooltip v-model="show_tooltip" activator="parent" location="start">{{ ingredient.note }}</v-tooltip> <v-tooltip v-model="show_tooltip" activator="parent" location="start">{{ ingredient.note }}</v-tooltip>
</v-icon> </v-icon>
</td> </td>
<td v-if="draggable">
<i class="fas fa-grip-lines drag-handle"></i>
</td>
</template> </template>
</tr> </tr>
@@ -23,11 +26,19 @@ import {Ingredient} from "@/openapi";
export default defineComponent({ export default defineComponent({
name: "IngredientsTableRow", name: "IngredientsTableRow",
components: {},
props: { props: {
ingredient: { ingredient: {
type: {} as PropType<Ingredient>, type: {} as PropType<Ingredient>,
required: true required: true
} },
showNotes: {
type: Boolean,
default: true
},
draggable: {
type: Boolean,
},
}, },
data() { data() {
return { return {

View File

@@ -0,0 +1,84 @@
<template>
<!--TODO name, time, recipe, file(s), ingredients, quick add ingredients -->
<v-card>
<template #title>
<v-card-title v-if="step.name">{{ step.name }}</v-card-title>
<v-card-title v-else-if="stepIndex !== undefined">Step {{ stepIndex + 1 }}</v-card-title>
</template>
<template v-slot:append>
<v-btn size="small" variant="plain" icon="fas fa-sliders-h"></v-btn> <!--TODO implement -->
</template>
<v-card-text>
<v-text-field
v-model="step.name"
label="Step Name"
></v-text-field>
<v-chip-group>
<v-chip><i class="fas fa-plus-circle"></i> Time</v-chip>
</v-chip-group>
<ingredients-table :ingredients="step.ingredients" :show-notes="false" draggable>
</ingredients-table>
<v-alert @click="dialog_markdown_edit = true">
{{ step.instruction }}
</v-alert>
</v-card-text>
</v-card>
<v-dialog
v-model="dialog_markdown_edit"
transition="dialog-bottom-transition"
fullscreen
@close="$emit('change', {step: step})">
<v-card>
<v-toolbar>
<v-toolbar-title>Edit Instructions</v-toolbar-title>
<v-btn icon="fas fa-close" @click="dialog_markdown_edit = false"></v-btn>
</v-toolbar>
<step-markdown-editor class="h-100" :step="step" @change="step = $event.step; $emit('change', {step: step})"></step-markdown-editor>
</v-card>
</v-dialog>
</template>
<script lang="ts">
import {defineComponent, PropType} from 'vue'
import {Step} from "@/openapi";
import StepMarkdownEditor from "@/components/inputs/StepMarkdownEditor.vue";
import IngredientsTable from "@/components/display/IngredientsTable.vue";
export default defineComponent({
name: "StepEditor",
components: {IngredientsTable, StepMarkdownEditor},
emits: {
change(payload: { step: Step }) {
return payload
}
},
props: {
step: {
type: Object as PropType<Step>,
required: true,
},
stepIndex: {
type: Number,
required: false,
},
},
data() {
return {
dialog_markdown_edit: false,
}
}
})
</script>
<style scoped>
</style>

View File

@@ -8,7 +8,7 @@
<button <button
type="button" type="button"
@click="mutable_step.instruction+= ' {{ scale(100) }}'" @click="mutable_step.instruction+= ' {{ scale(100) }}'"
class="op-icon fas fa-times" class="op-icon fas fa-calculator"
aria-hidden="true" aria-hidden="true"
title="Scalable Number" title="Scalable Number"
></button> ></button>
@@ -24,6 +24,16 @@ import 'mavon-editor/dist/css/index.css'
export default defineComponent({ export default defineComponent({
name: "StepMarkdownEditor", name: "StepMarkdownEditor",
emits: {
change(payload: { step: Step }) {
return payload
}
},
watch: {
mutable_step: function (){
this.$emit('change', {step: this.mutable_step})
}
},
props: { props: {
step: {type: Object as PropType<Step>, required: true} step: {type: Object as PropType<Step>, required: true}
}, },
@@ -38,22 +48,22 @@ export default defineComponent({
underline: true, underline: true,
strikethrough: true, strikethrough: true,
mark: false, mark: false,
superscript: true, superscript: false,
subscript: true, subscript: false,
quote: true, quote: true,
ol: true, ol: true,
ul: true, ul: true,
link: true, link: true,
imagelink: false, imagelink: false,
code: true, code: false,
table: false, table: false,
fullscreen: false, fullscreen: false,
readmodel: false, readmodel: false,
htmlcode: false, htmlcode: false,
help: true, help: false,
undo: true, undo: true,
redo: true, redo: true,
navigation: true, navigation: false,
alignleft: false, alignleft: false,
aligncenter: false, aligncenter: false,
alignright: false, alignright: false,

View File

@@ -53,10 +53,9 @@
</v-col> </v-col>
</v-row> </v-row>
<v-row v-for="step in recipe.steps"> <v-row v-for="(step, index) in recipe.steps">
<!--TODO name, time, recipe, file(s), ingredients, quick add ingredients -->
<v-col> <v-col>
<step-markdown-editor :step="step"></step-markdown-editor> <step-editor :step="step" :step-index="index"></step-editor>
</v-col> </v-col>
</v-row> </v-row>
@@ -73,11 +72,12 @@
import {defineComponent, PropType} from 'vue' import {defineComponent, PropType} from 'vue'
import {ApiApi, Keyword, Recipe} from "@/openapi"; import {ApiApi, Keyword, Recipe} from "@/openapi";
import StepMarkdownEditor from "@/components/inputs/StepMarkdownEditor.vue"; import StepMarkdownEditor from "@/components/inputs/StepMarkdownEditor.vue";
import StepEditor from "@/components/inputs/StepEditor.vue";
export default defineComponent({ export default defineComponent({
name: "RecipeEditPage", name: "RecipeEditPage",
components: {StepMarkdownEditor}, components: {StepEditor, StepMarkdownEditor},
props: { props: {
recipe_id: {type: String, required: false}, recipe_id: {type: String, required: false},
}, },