commit
This commit is contained in:
parent
983d40f2c1
commit
0eebd438ca
@ -16,7 +16,7 @@ class IngredientObject(object):
|
|||||||
if ingredient.no_amount:
|
if ingredient.no_amount:
|
||||||
self.amount = ""
|
self.amount = ""
|
||||||
else:
|
else:
|
||||||
self.amount = f'[[calculateAmount({ingredient.amount})]]'
|
self.amount = f"<scalable-number v-bind:number='{ingredient.amount}' v-bind:factor='servings'></scalable-number>"
|
||||||
if ingredient.unit:
|
if ingredient.unit:
|
||||||
self.unit = ingredient.unit
|
self.unit = ingredient.unit
|
||||||
else:
|
else:
|
||||||
@ -32,17 +32,7 @@ class IngredientObject(object):
|
|||||||
|
|
||||||
|
|
||||||
def render_instructions(step): # TODO deduplicate markdown cleanup code
|
def render_instructions(step): # TODO deduplicate markdown cleanup code
|
||||||
|
instructions = step.instruction
|
||||||
ingredients = []
|
|
||||||
|
|
||||||
for i in step.ingredients.all():
|
|
||||||
ingredients.append(IngredientObject(i))
|
|
||||||
|
|
||||||
try:
|
|
||||||
template = Template(step.instruction)
|
|
||||||
instructions = template.render(ingredients=ingredients)
|
|
||||||
except TemplateSyntaxError:
|
|
||||||
instructions = step.instruction
|
|
||||||
|
|
||||||
tags = markdown_tags + [
|
tags = markdown_tags + [
|
||||||
'pre', 'table', 'td', 'tr', 'th', 'tbody', 'style', 'thead'
|
'pre', 'table', 'td', 'tr', 'th', 'tbody', 'style', 'thead'
|
||||||
@ -56,4 +46,17 @@ def render_instructions(step): # TODO deduplicate markdown cleanup code
|
|||||||
)
|
)
|
||||||
markdown_attrs['*'] = markdown_attrs['*'] + ['class']
|
markdown_attrs['*'] = markdown_attrs['*'] + ['class']
|
||||||
|
|
||||||
return bleach.clean(parsed_md, tags, markdown_attrs)
|
instructions = bleach.clean(parsed_md, tags, markdown_attrs)
|
||||||
|
|
||||||
|
ingredients = []
|
||||||
|
|
||||||
|
for i in step.ingredients.all():
|
||||||
|
ingredients.append(IngredientObject(i))
|
||||||
|
|
||||||
|
try:
|
||||||
|
template = Template(instructions)
|
||||||
|
instructions = template.render(ingredients=ingredients)
|
||||||
|
except TemplateSyntaxError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return instructions
|
||||||
|
@ -158,11 +158,15 @@ class IngredientSerializer(WritableNestedModelSerializer):
|
|||||||
|
|
||||||
class StepSerializer(WritableNestedModelSerializer):
|
class StepSerializer(WritableNestedModelSerializer):
|
||||||
ingredients = IngredientSerializer(many=True)
|
ingredients = IngredientSerializer(many=True)
|
||||||
|
ingredients_markdown = serializers.SerializerMethodField('get_ingredients_markdown')
|
||||||
|
|
||||||
|
def get_ingredients_markdown(self, obj):
|
||||||
|
return obj.get_instruction_render()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Step
|
model = Step
|
||||||
fields = (
|
fields = (
|
||||||
'id', 'name', 'type', 'instruction', 'ingredients',
|
'id', 'name', 'type', 'instruction', 'ingredients', 'ingredients_markdown',
|
||||||
'time', 'order', 'show_as_header'
|
'time', 'order', 'show_as_header'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
<div class="col col-md-3">
|
<div class="col col-md-3">
|
||||||
<div class="input-group d-print-none">
|
<div class="input-group d-print-none">
|
||||||
<input type="number" value="1" maxlength="3" class="form-control" style="min-width: 2vw"
|
<input type="number" value="1" maxlength="3" class="form-control" style="min-width: 2vw"
|
||||||
v-model="servings"/>
|
v-model.number="servings"/>
|
||||||
<div class="input-group-append">
|
<div class="input-group-append">
|
||||||
<span class="input-group-text"><i class="fas fa-calculator"></i></span>
|
<span class="input-group-text"><i class="fas fa-calculator"></i></span>
|
||||||
</div>
|
</div>
|
||||||
@ -68,10 +68,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!--TODO timers -->
|
||||||
<div v-for="(s, index) in recipe.steps" v-bind:key="s.id" style="margin-top: 1vh">
|
<div v-for="(s, index) in recipe.steps" v-bind:key="s.id" style="margin-top: 1vh">
|
||||||
<Step v-bind:step="s" v-bind:servings="servings" v-bind:index="index"></Step>
|
<Step v-bind:step="s" v-bind:servings="servings" v-bind:index="index"></Step>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!--TODO Comments -->
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -88,6 +92,8 @@ import RecipeContextMenu from "@/components/RecipeContextMenu";
|
|||||||
import {GettextMixin, ToastMixin} from "@/utils/utils";
|
import {GettextMixin, ToastMixin} from "@/utils/utils";
|
||||||
import Ingredient from "@/components/Ingredient";
|
import Ingredient from "@/components/Ingredient";
|
||||||
|
|
||||||
|
import ScalableNumber from "@/components/ScalableNumber";
|
||||||
|
|
||||||
Vue.use(BootstrapVue)
|
Vue.use(BootstrapVue)
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -100,6 +106,7 @@ export default {
|
|||||||
Ingredient,
|
Ingredient,
|
||||||
Step,
|
Step,
|
||||||
RecipeContextMenu,
|
RecipeContextMenu,
|
||||||
|
ScalableNumber, // eslint-disable-line
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
42
vue/src/components/CompileComponent.vue
Normal file
42
vue/src/components/CompileComponent.vue
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<template>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<component :is="compiled" :servings="servings"></component>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Vue from 'vue'
|
||||||
|
|
||||||
|
import ScalableNumber from "@/components/ScalableNumber";
|
||||||
|
|
||||||
|
var res = Vue.compile('<div><span>{{servings}} Test <scalable-number v-bind:number="2" :factor="servings"></scalable-number></span></div>')
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'CompileComponent',
|
||||||
|
props: ['code', 'servings'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
compiled: null,
|
||||||
|
test: '<div><span>{{servings}} Test <scalable-number v-bind:number="2" :factor="servings"></scalable-number></span></div>'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
ScalableNumber, // eslint-disable-line
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.compiled = Vue.component('button-counter', {
|
||||||
|
props: ['servings'],
|
||||||
|
data: function () {
|
||||||
|
return {
|
||||||
|
count: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
template: '<button v-on:click="count++">You clicked me {{ servings }} times.</button>'
|
||||||
|
})
|
||||||
|
}, 500)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
25
vue/src/components/ScalableNumber.vue
Normal file
25
vue/src/components/ScalableNumber.vue
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<template>
|
||||||
|
<p>{{ calculateAmount(number) }}</p>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
import {calculateAmount} from "@/utils/utils";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ScalableNumber',
|
||||||
|
props: {
|
||||||
|
number: Number,
|
||||||
|
factor: {
|
||||||
|
type: Number,
|
||||||
|
default: 4
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
calculateAmount: function (x) {
|
||||||
|
console.log("calculated amount")
|
||||||
|
return calculateAmount(x, this.factor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
<h5 class="text-secondary">
|
<h5 class="text-secondary">
|
||||||
<template v-if="step.name">{{ step.name }}</template>
|
<template v-if="step.name">{{ step.name }}</template>
|
||||||
<template v-else>{{ _('Step') }} {{index + 1}}</template>
|
<template v-else>{{ _('Step') }} {{ index + 1 }}</template>
|
||||||
</h5>
|
</h5>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@ -16,25 +16,32 @@
|
|||||||
<div v-for="i in step.ingredients" v-bind:key="i.id">
|
<div v-for="i in step.ingredients" v-bind:key="i.id">
|
||||||
<Ingredient v-bind:ingredient="i" v-bind:servings="servings"></Ingredient>
|
<Ingredient v-bind:ingredient="i" v-bind:servings="servings"></Ingredient>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-9">
|
<div class="col-md-9">
|
||||||
<i class="fas fa-paragraph text-secondary"></i>
|
<i class="fas fa-paragraph text-secondary"></i>
|
||||||
{{ step.instruction }}
|
<span v-html="step.ingredients_markdown">
|
||||||
|
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<compile-component :code="step.ingredients_markdown" :servings="servings"></compile-component>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
|
import {calculateAmount} from "@/utils/utils";
|
||||||
|
|
||||||
import Ingredient from "@/components/Ingredient";
|
import Ingredient from "@/components/Ingredient";
|
||||||
import {GettextMixin} from "@/utils/utils";
|
import {GettextMixin} from "@/utils/utils";
|
||||||
|
import ScalableNumber from "@/components/ScalableNumber";
|
||||||
|
|
||||||
|
import CompileComponent from "@/components/CompileComponent";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Step',
|
name: 'Step',
|
||||||
@ -43,11 +50,22 @@ export default {
|
|||||||
],
|
],
|
||||||
components: {
|
components: {
|
||||||
Ingredient,
|
Ingredient,
|
||||||
|
CompileComponent, //eslint-disable-line
|
||||||
|
ScalableNumber, // eslint-disable-line
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
step: Object,
|
step: Object,
|
||||||
servings: Number,
|
servings: Number,
|
||||||
index: Number,
|
index: Number,
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
calculateAmount: function (x) {
|
||||||
|
// used by the jinja2 template
|
||||||
|
return calculateAmount(x, this.servings)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -15,7 +15,7 @@ module.exports = {
|
|||||||
? ''
|
? ''
|
||||||
: 'http://localhost:8080/',
|
: 'http://localhost:8080/',
|
||||||
outputDir: '../cookbook/static/vue/',
|
outputDir: '../cookbook/static/vue/',
|
||||||
|
runtimeCompiler: true,
|
||||||
chainWebpack: config => {
|
chainWebpack: config => {
|
||||||
|
|
||||||
config.optimization
|
config.optimization
|
||||||
|
@ -1 +1 @@
|
|||||||
{"status":"done","publicPath":"http://localhost:8080/","chunks":{"chunk-vendors":[{"name":"js/chunk-vendors.js","publicPath":"http://localhost:8080/js/chunk-vendors.js","path":"F:\\Developement\\Django\\recipes\\cookbook\\static\\vue\\js\\chunk-vendors.js"}],"recipe_view":[{"name":"js/recipe_view.js","publicPath":"http://localhost:8080/js/recipe_view.js","path":"F:\\Developement\\Django\\recipes\\cookbook\\static\\vue\\js\\recipe_view.js"},{"name":"recipe_view.e165d99965cf62182119.hot-update.js","publicPath":"http://localhost:8080/recipe_view.e165d99965cf62182119.hot-update.js","path":"F:\\Developement\\Django\\recipes\\cookbook\\static\\vue\\recipe_view.e165d99965cf62182119.hot-update.js"}]},"error":"ModuleError","message":"Module Error (from ./node_modules/eslint-loader/index.js):\n\nF:\\Developement\\Django\\recipes\\vue\\src\\components\\Step.vue\n 22:37 error Parsing error: duplicate-attribute vue/no-parsing-error\n 22:37 error Duplicate attribute 'class' vue/no-duplicate-attributes\n\n✖ 2 problems (2 errors, 0 warnings)\n"}
|
{"status":"done","publicPath":"http://localhost:8080/","chunks":{"chunk-vendors":[{"name":"js/chunk-vendors.js","publicPath":"http://localhost:8080/js/chunk-vendors.js","path":"F:\\Developement\\Django\\recipes\\cookbook\\static\\vue\\js\\chunk-vendors.js"}],"recipe_view":[{"name":"js/recipe_view.js","publicPath":"http://localhost:8080/js/recipe_view.js","path":"F:\\Developement\\Django\\recipes\\cookbook\\static\\vue\\js\\recipe_view.js"},{"name":"recipe_view.6895bd28654af90f46e1.hot-update.js","publicPath":"http://localhost:8080/recipe_view.6895bd28654af90f46e1.hot-update.js","path":"F:\\Developement\\Django\\recipes\\cookbook\\static\\vue\\recipe_view.6895bd28654af90f46e1.hot-update.js"}]},"error":"ModuleError","message":"Module Error (from ./node_modules/eslint-loader/index.js):\n\nF:\\Developement\\Django\\recipes\\vue\\src\\components\\CompileComponent.vue\n 1:1 error The template requires child element vue/valid-template-root\n\n✖ 1 problem (1 error, 0 warnings)\n"}
|
Loading…
Reference in New Issue
Block a user