265 lines
6.4 KiB
Vue
265 lines
6.4 KiB
Vue
<template>
|
|
<div class="recipe-edit">
|
|
<template v-if="!forLogging">
|
|
|
|
<div class="columns">
|
|
<div class="column">
|
|
<app-text-field label="Name" v-model="recipe.name"></app-text-field>
|
|
</div>
|
|
|
|
<div class="column">
|
|
<app-text-field label="Source" v-model="recipe.source"></app-text-field>
|
|
</div>
|
|
</div>
|
|
|
|
<app-text-field label="Description" type="textarea" v-model="recipe.description"></app-text-field>
|
|
|
|
<div class="field">
|
|
<label class="label is-small-mobile">Tags</label>
|
|
<app-tag-editor v-model="recipe.tags"></app-tag-editor>
|
|
</div>
|
|
|
|
</template>
|
|
|
|
<div class="columns">
|
|
<div class="column">
|
|
<app-text-field label="Yields" v-model="recipe.yields"></app-text-field>
|
|
</div>
|
|
|
|
<div class="column">
|
|
<app-text-field label="Total Time" type="number" v-model="recipe.total_time"></app-text-field>
|
|
</div>
|
|
|
|
<div class="column">
|
|
<app-text-field label="Active Time" v-model="recipe.active_time"></app-text-field>
|
|
</div>
|
|
</div>
|
|
|
|
<recipe-edit-ingredient-editor :ingredients="recipe.ingredients"></recipe-edit-ingredient-editor>
|
|
|
|
<br>
|
|
<div class="field">
|
|
<label class="label title is-4">Directions <button @click="isDescriptionHelpOpen = true" class="button is-small is-link"><app-icon icon="question-mark"></app-icon></button></label>
|
|
<div class="control columns">
|
|
<div class="column">
|
|
<textarea ref="step_text_area" class="textarea directions-input" v-model="recipe.step_text"></textarea>
|
|
</div>
|
|
<div class="column">
|
|
<div class="box content" v-html="stepPreview">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="field">
|
|
<label class="checkbox">
|
|
<input type="checkbox" v-model="recipe.is_ingredient" />
|
|
Is Ingredient
|
|
</label>
|
|
</div>
|
|
|
|
<app-modal title="Markdown Help" :open="isDescriptionHelpOpen" @dismiss="isDescriptionHelpOpen = false">
|
|
<p>
|
|
The description editor uses <a href="https://www.markdownguide.org/cheat-sheet/">Markdown</a>. Follow the link for a full
|
|
description of the syntax, but below is a quick reference.
|
|
</p>
|
|
<table class="table">
|
|
<thead>
|
|
<tr>
|
|
<th>Style</th>
|
|
<th>Syntax</th>
|
|
<th>Result</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>Heading</td>
|
|
<td>
|
|
<pre>
|
|
# Biggest Heading
|
|
## Smaller Heading
|
|
###### Smallest Heading
|
|
</pre>
|
|
</td>
|
|
<td class="content">
|
|
<h1>Biggest Heading</h1>
|
|
<h2>Smaller Heading</h2>
|
|
<h6>Smallest Heading</h6>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Numbered Lists</td>
|
|
<td>
|
|
<pre>
|
|
1. First Item
|
|
1. Second Item
|
|
1. subitem A
|
|
1. subitem B
|
|
1. Thrid Item
|
|
</pre>
|
|
</td>
|
|
<td class="content">
|
|
<ol>
|
|
<li>First Item</li>
|
|
<li>Second Item
|
|
<ol>
|
|
<li>subitem A</li>
|
|
<li>subitem B</li>
|
|
</ol>
|
|
</li>
|
|
<li>Thrid Item</li>
|
|
</ol>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Lists</td>
|
|
<td>
|
|
<pre>
|
|
* First Item
|
|
* Second Item
|
|
* subitem A
|
|
* subitem B
|
|
* Third Item
|
|
</pre>
|
|
</td>
|
|
<td class="content">
|
|
<ul>
|
|
<li>First Item</li>
|
|
<li>Second Item
|
|
|
|
<ul>
|
|
<li>subitem A</li>
|
|
<li>subitem B</li>
|
|
</ul></li>
|
|
<li>Third Item</li>
|
|
</ul>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Basic Styles</td>
|
|
<td>
|
|
<pre>
|
|
*italics*
|
|
**bold**
|
|
***bold italics***
|
|
_underline_
|
|
==highlight==
|
|
</pre>
|
|
</td>
|
|
<td class="content">
|
|
<p>
|
|
<em>italics</em><br>
|
|
<strong>bold</strong><br>
|
|
<strong><em>bold italics</em></strong><br>
|
|
<u>underline</u><br>
|
|
<mark>highlight</mark>
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<h3 class="title is-3">Basic Example</h3>
|
|
<h5 class="subtitle is=3">Input</h5>
|
|
<pre>
|
|
## For the dough
|
|
1. Mix dry ingredients
|
|
1. Fold in egg whites
|
|
1. Sprinkle on sardines
|
|
|
|
## For the sauce
|
|
1. Blend clams ==thoroughly==
|
|
1. Melt beef lard and add clam slurry
|
|
|
|
### Optional (Toppings)
|
|
* Raw onion
|
|
* Sliced hard boiled eggs
|
|
</pre>
|
|
|
|
<h5 class="subtitle is=3">Output</h5>
|
|
|
|
<div class="content box">
|
|
<h2>For the dough</h2>
|
|
|
|
<ol>
|
|
<li>Mix dry ingredients</li>
|
|
<li>Fold in egg whites</li>
|
|
<li>Sprinkle on sardines</li>
|
|
</ol>
|
|
|
|
<h2>For the sauce</h2>
|
|
|
|
<ol>
|
|
<li>Blend clams <mark>thoroughly</mark></li>
|
|
<li>Melt beef lard and add clam slurry</li>
|
|
</ol>
|
|
|
|
<h3>Optional (Toppings)</h3>
|
|
|
|
<ul>
|
|
<li>Raw onion</li>
|
|
<li>Sliced hard boiled eggs</li>
|
|
</ul>
|
|
|
|
</div>
|
|
</app-modal>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
|
|
import { computed, ref, useTemplateRef, watch } from "vue";
|
|
import { useAutosize } from "../lib/useAutosize";
|
|
import debounce from "lodash/debounce";
|
|
import api from "../lib/Api";
|
|
import RecipeEditIngredientEditor from "./RecipeEditIngredientEditor";
|
|
|
|
const props = defineProps({
|
|
recipe: {
|
|
required: true,
|
|
type: Object
|
|
},
|
|
forLogging: {
|
|
required: false,
|
|
type: Boolean,
|
|
default: false
|
|
}
|
|
});
|
|
|
|
const stepTextArea = useTemplateRef("step_text_area");
|
|
const stepPreviewCache = ref(null);
|
|
const isDescriptionHelpOpen = ref(false);
|
|
|
|
useAutosize(stepTextArea);
|
|
|
|
const stepPreview = computed(() => {
|
|
if (stepPreviewCache.value === null) {
|
|
return props.recipe.rendered_steps;
|
|
} else {
|
|
return stepPreviewCache.value;
|
|
}
|
|
});
|
|
|
|
const updatePreview = debounce(function() {
|
|
api.postPreviewSteps(props.recipe.step_text)
|
|
.then(data => stepPreviewCache.value = data.rendered_steps)
|
|
.catch(err => stepPreviewCache.value = "?? Error ??");
|
|
}, 750);
|
|
|
|
watch(
|
|
() => props.recipe.step_text,
|
|
() => updatePreview()
|
|
);
|
|
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
.recipe-edit {
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.directions-input {
|
|
height: 100%;
|
|
}
|
|
</style> |