editor improvements

This commit is contained in:
vabene1111
2024-03-06 21:44:55 +01:00
parent cf20b22404
commit 95583dbe2c
8 changed files with 150 additions and 101 deletions

View File

@@ -1,11 +1,11 @@
{% load django_vite %} {% load django_vite %}
<!DOCTYPE html>
<html> <html>
<head> <head>
<title></title> <title>Tandoor</title>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, viewport-fit=cover"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5, minimal-ui, shrink-to-fit=no">
<meta name="robots" content="noindex,nofollow"/> <meta name="robots" content="noindex,nofollow"/>
<meta name="apple-mobile-web-app-capable" content="yes"/> <meta name="apple-mobile-web-app-capable" content="yes"/>
@@ -15,7 +15,7 @@
{% vite_hmr_client %} {% vite_hmr_client %}
{% vite_asset 'src/apps/tandoor/main.ts' %} {% vite_asset 'src/apps/tandoor/main.ts' %}
<script src="{% url 'js_reverse' %}"></script>
</body> </body>
</html> </html>

View File

@@ -17,7 +17,7 @@
"vue": "^3.4.15", "vue": "^3.4.15",
"vue-router": "4", "vue-router": "4",
"vuedraggable": "^4.1.0", "vuedraggable": "^4.1.0",
"vuetify": "^3.3.15" "vuetify": "^3.5.8"
}, },
"devDependencies": { "devDependencies": {
"@fortawesome/fontawesome-free": "^6.5.1", "@fortawesome/fontawesome-free": "^6.5.1",

View File

@@ -1,21 +1,18 @@
<template> <template>
<v-app> <v-app >
<v-app-bar color="tandoor" flat density="comfortable"> <v-app-bar color="tandoor" flat density="comfortable">
<router-link :to="{name: 'view_search', params: {}}"> <router-link :to="{name: 'view_search', params: {}}">
<v-img src="../../assets/brand_logo.svg" width="140px" class="ms-2"></v-img> <v-img src="../../assets/brand_logo.svg" width="140px" class="ms-2"></v-img>
</router-link> </router-link>
<global-search-dialog></global-search-dialog> <global-search-dialog></global-search-dialog>
<v-spacer></v-spacer> <v-spacer></v-spacer>
<!-- <v-btn density="compact" icon="fas fa-ellipsis-v"></v-btn>--> <!-- <v-btn density="compact" icon="fas fa-ellipsis-v"></v-btn>-->
</v-app-bar> </v-app-bar>
<v-main> <v-main>
<router-view></router-view> <router-view></router-view>
</v-main> </v-main>
<v-bottom-navigation grow> <v-bottom-navigation grow>
@@ -58,6 +55,7 @@ export default defineComponent({
return { return {
drawer: true, drawer: true,
rail: true, rail: true,
overlay: false
} }
}, },
mounted() { mounted() {

View File

@@ -1,20 +1,9 @@
<template> <template>
<v-table density="compact" v-if="ingredients.length > 0"> <v-table density="compact" v-if="ingredients.length > 0">
<template v-if="draggable"> <tbody>
<draggable tag="tbody" v-model="mutable_ingredients" handle=".drag-handle" item-key="id"> <IngredientsTableRow v-for="i in ingredients" :ingredient="i" :key="i.id" :show-notes="showNotes" :draggable="draggable"></IngredientsTableRow>
<template #item="{element}"> </tbody>
<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>

View File

@@ -19,29 +19,63 @@
<v-chip><i class="fas fa-plus-circle"></i> Time</v-chip> <v-chip><i class="fas fa-plus-circle"></i> Time</v-chip>
</v-chip-group> </v-chip-group>
<ingredients-table :ingredients="step.ingredients" :show-notes="false" draggable> <v-table density="compact">
</ingredients-table> <draggable tag="tbody" v-model="step.ingredients" handle=".drag-handle" item-key="id" @sort="sortIngredients">
<template #item="{element}">
<v-dialog>
<template v-slot:activator="{ props: activatorProps }">
<IngredientsTableRow v-bind="activatorProps" :ingredient="element" :key="element.id" :show-notes="false" :draggable="true"></IngredientsTableRow>
</template>
<template v-slot:default="{ isActive }">
<v-card >
<v-card-title>Ingredient</v-card-title>
<v-card-text>
<v-form>
<v-text-field
label="Amount"
v-model="element.amount"
></v-text-field>
</v-form>
<v-alert @click="dialog_markdown_edit = true"> </v-card-text>
</v-card>
</template>
</v-dialog>
</template>
</draggable>
</v-table>
<v-alert @click="dialog_markdown_edit = true" class="mt-2">
{{ step.instruction }} {{ step.instruction }}
</v-alert> </v-alert>
</v-card-text> </v-card-text>
</v-card> </v-card>
<v-dialog
v-model="dialog_markdown_edit"
transition="dialog-bottom-transition">
<v-card>
<v-card-title>Ingredient</v-card-title>
<v-form>
<v-text-field></v-text-field>
</v-form>
</v-card>
</v-dialog>
<v-dialog <v-dialog
v-model="dialog_markdown_edit" v-model="dialog_markdown_edit"
transition="dialog-bottom-transition" transition="dialog-bottom-transition"
fullscreen fullscreen>
@close="$emit('change', {step: step})">
<v-card> <v-card>
<v-toolbar> <v-toolbar>
<v-toolbar-title>Edit Instructions</v-toolbar-title> <v-toolbar-title>Edit Instructions</v-toolbar-title>
<v-btn icon="fas fa-close" @click="dialog_markdown_edit = false"></v-btn> <v-btn icon="fas fa-close" @click="dialog_markdown_edit = false"></v-btn>
</v-toolbar> </v-toolbar>
<step-markdown-editor class="h-100" :step="step" @change="step = $event.step; $emit('change', {step: step})"></step-markdown-editor> <step-markdown-editor class="h-100" :step="step" @change="step = $event.step;"></step-markdown-editor>
</v-card> </v-card>
</v-dialog> </v-dialog>
</template> </template>
@@ -51,17 +85,15 @@ import {defineComponent, PropType} from 'vue'
import {Step} from "@/openapi"; import {Step} from "@/openapi";
import StepMarkdownEditor from "@/components/inputs/StepMarkdownEditor.vue"; import StepMarkdownEditor from "@/components/inputs/StepMarkdownEditor.vue";
import IngredientsTable from "@/components/display/IngredientsTable.vue"; import IngredientsTable from "@/components/display/IngredientsTable.vue";
import IngredientsTableRow from "@/components/display/IngredientsTableRow.vue";
import draggable from "vuedraggable";
export default defineComponent({ export default defineComponent({
name: "StepEditor", name: "StepEditor",
components: {IngredientsTable, StepMarkdownEditor}, components: {draggable, IngredientsTableRow, IngredientsTable, StepMarkdownEditor},
emits: { emits: ['update:modelValue'],
change(payload: { step: Step }) {
return payload
}
},
props: { props: {
step: { modelValue: {
type: Object as PropType<Step>, type: Object as PropType<Step>,
required: true, required: true,
}, },
@@ -70,10 +102,27 @@ export default defineComponent({
required: false, required: false,
}, },
}, },
computed: {
step: {
get() {
return this.modelValue
},
set(value: Step) {
this.$emit('update:modelValue', value)
}
}
},
data() { data() {
return { return {
dialog_markdown_edit: false, dialog_markdown_edit: false,
} }
},
methods: {
sortIngredients() {
this.step.ingredients.forEach((value, index) => {
value.order = index
})
}
} }
}) })
</script> </script>

View File

@@ -1,70 +1,83 @@
<template> <template>
<v-container> <v-container>
<v-row>
<v-col>
<v-card>
<v-card-title>{{ recipe.name }}</v-card-title>
<v-form> <v-card-text>
<v-text-field
label="Name"
v-model="recipe.name"
></v-text-field>
<v-textarea
label="Description"
v-model="recipe.description"
clearable
></v-textarea>
<v-combobox <v-form>
label="Keywords" <v-text-field
v-model="recipe.keywords" label="Name"
:items="keywords" v-model="recipe.name"
item-title="name" ></v-text-field>
multiple
clearable
chips
></v-combobox>
<v-row> <v-textarea
<v-col> label="Description"
<v-text-field v-model="recipe.description"
v-model.number="recipe.waitingTime" clearable
label="Waiting Time (min)" ></v-textarea>
></v-text-field>
</v-col>
<v-col>
<v-text-field
v-model.number="recipe.workingTime"
label="Working Time (min)"
></v-text-field>
</v-col>
</v-row>
<v-row> <v-combobox
<v-col> label="Keywords"
<v-text-field v-model="recipe.keywords"
v-model.number="recipe.servings" :items="keywords"
label="Servings" item-title="name"
></v-text-field> multiple
</v-col> clearable
<v-col> chips
<v-text-field ></v-combobox>
v-model="recipe.servingsText"
label="Servings Text"
></v-text-field>
</v-col>
</v-row>
<v-row v-for="(step, index) in recipe.steps"> <v-row>
<v-col> <v-col>
<step-editor :step="step" :step-index="index"></step-editor> <v-text-field
</v-col> v-model.number="recipe.waitingTime"
</v-row> label="Waiting Time (min)"
></v-text-field>
</v-col>
<v-col>
<v-text-field
v-model.number="recipe.workingTime"
label="Working Time (min)"
></v-text-field>
</v-col>
</v-row>
</v-form> <v-row>
<v-col>
<v-text-field
v-model.number="recipe.servings"
label="Servings"
></v-text-field>
</v-col>
<v-col>
<v-text-field
v-model="recipe.servingsText"
label="Servings Text"
></v-text-field>
</v-col>
</v-row>
<v-btn @click="updateRecipe()">Save</v-btn>
<v-btn :to="{name: 'view_recipe', params: {id: recipe_id}}">View</v-btn> </v-form>
</v-card-text>
</v-card>
</v-col>
</v-row>
<v-row v-for="(step, index) in recipe.steps" class="mt-1">
<v-col>
<step-editor v-model="recipe.steps[index]" :step-index="index"></step-editor>
</v-col>
</v-row>
</v-container> </v-container>
<v-btn @click="updateRecipe()">Save</v-btn>
<v-btn :to="{name: 'view_recipe', params: {id: recipe_id}}">View</v-btn>
</template> </template>
@@ -96,13 +109,13 @@ export default defineComponent({
this.refreshRecipe() this.refreshRecipe()
const api = new ApiApi() const api = new ApiApi()
api.apiKeywordList().then(r => { api.apiKeywordList({page: 1, pageSize: 100}).then(r => {
this.keywords = r.results this.keywords = r.results
}) })
}, },
methods: { methods: {
refreshRecipe() { refreshRecipe() {
if (this.recipe.id != this.recipe_id) { if (this.recipe.id != Number(this.recipe_id)) {
const api = new ApiApi() const api = new ApiApi()
api.apiRecipeRetrieve({id: Number(this.recipe_id)}).then(r => { api.apiRecipeRetrieve({id: Number(this.recipe_id)}).then(r => {
this.recipe = r this.recipe = r
@@ -111,7 +124,7 @@ export default defineComponent({
}, },
updateRecipe() { updateRecipe() {
const api = new ApiApi() const api = new ApiApi()
api.apiRecipeUpdate({id: this.recipe_id, recipe: this.recipe}).then(r => { api.apiRecipeUpdate({id: Number(this.recipe_id), recipe: this.recipe}).then(r => {
this.recipe = r this.recipe = r
}) })
} }

View File

@@ -3,7 +3,7 @@
<!--TODO ideas for "start page": new recipes, meal plan, "last year/month/cooked long ago", high rated, random keyword --> <!--TODO ideas for "start page": new recipes, meal plan, "last year/month/cooked long ago", high rated, random keyword -->
<horizontal-recipe-scroller title="New Recipes" :recipes="new_recipes"></horizontal-recipe-scroller> <horizontal-recipe-scroller title="New Recipes" :recipes="new_recipes"></horizontal-recipe-scroller>
<horizontal-recipe-scroller title="Top Rated" :recipes="high_rated_recipes"></horizontal-recipe-scroller> <horizontal-recipe-scroller title="Top Rated" :recipes="high_rated_recipes" ></horizontal-recipe-scroller>
</v-container> </v-container>

View File

@@ -904,10 +904,10 @@ vuedraggable@^4.1.0:
dependencies: dependencies:
sortablejs "1.14.0" sortablejs "1.14.0"
vuetify@^3.3.15: vuetify@^3.5.8:
version "3.5.4" version "3.5.8"
resolved "https://registry.yarnpkg.com/vuetify/-/vuetify-3.5.4.tgz#f919c5194995a123815c277a95812bc230e33464" resolved "https://registry.yarnpkg.com/vuetify/-/vuetify-3.5.8.tgz#bc8f08dfd3314640e7b5d43b50138a26d650cbbf"
integrity sha512-fHgfWMI7+z/UtbVPOezX+O1MNBOOMBW9HnKejcBIyQQ7jFRnTHbDQmbINf25FK0wrg/zkjfzyOmWWREKW39eXg== integrity sha512-8nGS+lKejZkev55HFwIfsRt+9fOqbeDQNmXxfmLKAlnUT8FtynVwbjAwHMtX/OQAQ3ZwRaR1ptqQQmx3OgxzbQ==
w3c-xmlserializer@^4.0.0: w3c-xmlserializer@^4.0.0:
version "4.0.0" version "4.0.0"