Merge pull request #2941 from tomtjes/add-human-friendly-css-classes

Add human-friendly css classes and scaling indicators
This commit is contained in:
vabene1111 2024-02-18 08:05:10 +01:00 committed by GitHub
commit 03ccc8e044
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 159 additions and 101 deletions

View File

@ -1,5 +1,5 @@
<template> <template>
<div id="app" class="col-12 col-xl-8 col-lg-10 offset-xl-2 offset-lg-1 offset"> <div id="app" class="books col-12 col-xl-8 col-lg-10 offset-xl-2 offset-lg-1 offset">
<div class="col-12 col-xl-8 col-lg-10 offset-xl-2 offset-lg-1"> <div class="col-12 col-xl-8 col-lg-10 offset-xl-2 offset-lg-1">
<div class="row"> <div class="row">
<div class="col col-md-12"> <div class="col col-md-12">

View File

@ -1,5 +1,5 @@
<template> <template>
<div> <div id="app" class="mealplan">
<div class="d-none d-lg-block"> <div class="d-none d-lg-block">
<div class="row "> <div class="row ">
<div class="col col-2"> <div class="col col-2">

View File

@ -1,5 +1,5 @@
<template> <template>
<div id="app" style="padding-bottom: 60px"> <div id="app" class="search" style="padding-bottom: 60px">
<RecipeSwitcher ref="ref_recipe_switcher" /> <RecipeSwitcher ref="ref_recipe_switcher" />
<div class="row"> <div class="row">
<div class="col-12 col-xl-10 col-lg-10 offset-xl-1 offset-lg-1"> <div class="col-12 col-xl-10 col-lg-10 offset-xl-1 offset-lg-1">

View File

@ -1,5 +1,5 @@
<template> <template>
<div id="app" v-if="recipe_id !== undefined"> <div id="app" class="recipe" v-if="recipe_id !== undefined">
<recipe-view-component :recipe_id="recipe_id"></recipe-view-component> <recipe-view-component :recipe_id="recipe_id"></recipe-view-component>
<bottom-navigation-bar active-view="view_search"></bottom-navigation-bar> <bottom-navigation-bar active-view="view_search"></bottom-navigation-bar>

View File

@ -1,5 +1,5 @@
<template> <template>
<div id="app"> <div id="app" class="shopping">
<b-alert :show="shopping_list_store.has_failed_items" class="float-up mt-2" variant="warning"> <b-alert :show="shopping_list_store.has_failed_items" class="float-up mt-2" variant="warning">
{{ $t('ShoppingBackgroundSyncWarning') }} {{ $t('ShoppingBackgroundSyncWarning') }}
</b-alert> </b-alert>
@ -55,7 +55,6 @@
</span> </span>
</div> </div>
</template> </template>
<!-- Entry input on large screens --> <!-- Entry input on large screens -->
<b-row class="d-lg-block d-print-none d-none mb-3 mt-3"> <b-row class="d-lg-block d-print-none d-none mb-3 mt-3">
<b-col cols="12"> <b-col cols="12">

View File

@ -1,52 +1,41 @@
<template> <template>
<tr> <tr class="ingredients__item">
<template v-if="ingredient.is_header"> <template v-if="ingredient.is_header">
<td colspan="5" @click="done"> <td class="ingredients__header-note header" colspan="5" @click="done">
<b>{{ ingredient.note }}</b> <b>{{ ingredient.note }}</b>
</td> </td>
</template> </template>
<template v-else> <template v-else>
<td class="d-print-none align-baseline py-2" v-if="detailed" @click="done"> <td class="ingredients__check d-print-none align-baseline py-2" v-if="detailed" @click="done">
<i class="far fa-check-circle text-success" v-if="ingredient.checked"></i> <i class="ingredients__check ingredients__check_checked far fa-check-circle text-success" v-if="ingredient.checked"></i>
<i class="far fa-check-circle text-primary" v-if="!ingredient.checked"></i> <i class="ingredients__check ingredients__check_checked_false far fa-check-circle text-primary" v-if="!ingredient.checked"></i>
</td> </td>
<td class="text-nowrap" @click="done"> <td class="ingredients__amount text-nowrap" @click="done">
<span v-if="ingredient.amount !== 0 && !ingredient.no_amount" v-html="calculateAmount(ingredient.amount)"></span> <span class="ingredients__amount" :class="amountClass" v-if="ingredient.amount !== 0 && !ingredient.no_amount" v-html="amount"></span>
</td> </td>
<td @click="done"> <td class="ingredients__unit" @click="done">
<template v-if="ingredient.unit !== null && !ingredient.no_amount"> <span v-if="ingredient.unit !== null && !ingredient.no_amount" :class="unitClass">{{ unitName }}</span>
<template>
<template v-if="ingredient.unit.plural_name === '' || ingredient.unit.plural_name === null">
<span>{{ ingredient.unit.name }}</span>
</template>
<template v-else>
<span v-if="ingredient.always_use_plural_unit">{{ ingredient.unit.plural_name }}</span>
<span v-else-if="ingredient.amount * this.ingredient_factor > 1">{{ ingredient.unit.plural_name }}</span>
<span v-else>{{ ingredient.unit.name }}</span>
</template>
</template>
</template>
</td> </td>
<td @click="done"> <td class="ingredients__food" :class="foodClass" @click="done">
<template v-if="ingredient.food !== null"> <template v-if="ingredient.food !== null">
<a :href="resolveDjangoUrl('view_recipe', ingredient.food.recipe.id)" v-if="ingredient.food.recipe !== null" target="_blank" rel="noopener noreferrer"> <a :href="resolveDjangoUrl('view_recipe', ingredient.food.recipe.id)" v-if="ingredient.food.recipe !== null" target="_blank" rel="noopener noreferrer">
{{ ingredientName(ingredient) }} {{ foodName }}
</a> </a>
<a :href="ingredient.food.url" v-else-if="ingredient.food.url !== ''" target="_blank" rel="noopener noreferrer"> <a :href="ingredient.food.url" v-else-if="ingredient.food.url !== ''" target="_blank" rel="noopener noreferrer">
{{ ingredientName(ingredient) }}</a> {{ foodName }}</a>
<template v-else> <template v-else>
<span>{{ ingredientName(ingredient) }}</span> <span :class="foodClass">{{ foodName }}</span>
</template> </template>
</template> </template>
</td> </td>
<td v-if="detailed" class="align-baseline"> <td v-if="detailed" class="ingredients__note align-baseline">
<template v-if="ingredient.note"> <template v-if="ingredient.note">
<span class="d-print-none touchable py-0 px-2" v-b-popover.hover="ingredient.note"> <span class="ingredients__note ingredients__note_hover d-print-none touchable py-0 px-2" v-b-popover.hover="ingredient.note">
<i class="far fa-comment"></i> <i class="far fa-comment"></i>
</span> </span>
<div class="d-none d-print-block"><i class="far fa-comment-alt d-print-none"></i> {{ ingredient.note }}</div> <div class="ingredients__note ingredients__note_print d-none d-print-block"><i class="far fa-comment-alt d-print-none"></i> {{ ingredient.note }}</div>
</template> </template>
</td> </td>
</template> </template>
@ -54,7 +43,7 @@
</template> </template>
<script> <script>
import {calculateAmount, ResolveUrlMixin} from "@/utils/utils" import {calculateAmount, ResolveUrlMixin, EscapeCSSMixin} from "@/utils/utils"
import Vue from "vue" import Vue from "vue"
import VueSanitize from "vue-sanitize" import VueSanitize from "vue-sanitize"
@ -68,7 +57,7 @@ export default {
ingredient_factor: {type: Number, default: 1}, ingredient_factor: {type: Number, default: 1},
detailed: {type: Boolean, default: true}, detailed: {type: Boolean, default: true},
}, },
mixins: [ResolveUrlMixin], mixins: [ResolveUrlMixin, EscapeCSSMixin],
data() { data() {
return { return {
checked: false, checked: false,
@ -77,27 +66,65 @@ export default {
watch: {}, watch: {},
mounted() { mounted() {
}, },
methods: { computed: {
calculateAmount: function (x) { amount: function() {
return this.$sanitize(calculateAmount(x, this.ingredient_factor)) return this.$sanitize(calculateAmount(this.ingredient.amount, this.ingredient_factor))
}, },
isScaledUp: function() {
return this.ingredient_factor > 1 ? true:false
},
isScaledDown: function() {
return this.ingredient_factor < 1 ? true:false
},
amountClass: function () {
if (this.isScaledDown) {
return this.escapeCSS('ingredients__amount_scaled_down')
} else if (this.isScaledUp) {
return this.escapeCSS('ingredients__amount_scaled_up')
} else {
return this.escapeCSS('ingredients__amount_scaled_false')
}
},
isUnitPlural: function () {
if (this.ingredient.unit.plural_name === '' || this.ingredient.unit.plural_name === null) {
return false
} else if (this.ingredient.always_use_plural_unit || this.ingredient.amount * this.ingredient_factor > 1) {
return true
} else {
return false
}
},
isFoodPlural: function () {
if (this.ingredient.food.plural_name == null || this.ingredient.food.plural_name === '') {
return false
}
if (this.ingredient.always_use_plural_food) {
return true
} else if (this.ingredient.no_amount) {
return false
} else if (this.ingredient.amount * this.ingredient_factor > 1) {
return true
} else {
return false
}
},
unitClass: function () {
return this.escapeCSS('_unitname-' + this.ingredient.unit.name)
},
foodClass: function () {
return this.escapeCSS('_foodname-' + this.ingredient.food.name)
},
unitName: function () {
return this.isUnitPlural ? this.ingredient.unit.plural_name : this.ingredient.unit.name
},
foodName: function () {
return this.isFoodPlural ? this.ingredient.food.plural_name : this.ingredient.food.name
}
},
methods: {
// sends parent recipe ingredient to notify complete has been toggled // sends parent recipe ingredient to notify complete has been toggled
done: function () { done: function () {
this.$emit("checked-state-changed", this.ingredient) this.$emit("checked-state-changed", this.ingredient)
},
ingredientName: function (ingredient) {
if (ingredient.food.plural_name == null || ingredient.food.plural_name === '') {
return ingredient.food.name
}
if (ingredient.always_use_plural_food) {
return ingredient.food.plural_name
} else if (ingredient.no_amount) {
return ingredient.food.name
} else if (ingredient.amount * this.ingredient_factor > 1) {
return ingredient.food.plural_name
} else {
return ingredient.food.name
}
} }
}, },
} }

View File

@ -1,5 +1,5 @@
<template> <template>
<div :class="{ 'card border-primary no-border': header }"> <div class="ingredients" :class="{ 'card border-primary no-border': header }">
<div :class="{ 'card-body': header, 'p-0': header }"> <div :class="{ 'card-body': header, 'p-0': header }">
<div class="card-header" v-if="header"> <div class="card-header" v-if="header">
<div class="row"> <div class="row">
@ -15,7 +15,7 @@
<table class="table table-sm mb-0"> <table class="table table-sm mb-0">
<!-- eslint-disable vue/no-v-for-template-key-on-child --> <!-- eslint-disable vue/no-v-for-template-key-on-child -->
<template v-for="s in steps"> <template v-for="s in steps">
<tr v-bind:key="s.id" v-if="s.show_as_header && s.name !== '' && steps.length > 1"> <tr class="ingredients__header-step-name" v-bind:key="s.id" v-if="s.show_as_header && s.name !== '' && steps.length > 1">
<td colspan="5"> <td colspan="5">
<b>{{ s.name }}</b> <b>{{ s.name }}</b>
</td> </td>

View File

@ -1,6 +1,6 @@
<template> <template>
<div v-if="recipe.keywords.length > 0"> <div class="keywords" v-if="recipe.keywords.length > 0">
<span :key="k.id" v-for="k in recipe.keywords.slice(0,keyword_splice).filter((kk) => { return kk.show || kk.show === undefined })" class="pl-1"> <span :key="k.id" v-for="k in recipe.keywords.slice(0,keyword_splice).filter((kk) => { return kk.show || kk.show === undefined })" class="keywords__item pl-1" :class="keywordClass(k)">
<template v-if="enable_keyword_links"> <template v-if="enable_keyword_links">
<a :href="`${resolveDjangoUrl('view_search')}?keyword=${k.id}`"> <a :href="`${resolveDjangoUrl('view_search')}?keyword=${k.id}`">
<b-badge pill variant="light" class="font-weight-normal">{{ k.label }}</b-badge> <b-badge pill variant="light" class="font-weight-normal">{{ k.label }}</b-badge>
@ -9,18 +9,17 @@
<template v-else> <template v-else>
<b-badge pill variant="light" class="font-weight-normal">{{ k.label }}</b-badge> <b-badge pill variant="light" class="font-weight-normal">{{ k.label }}</b-badge>
</template> </template>
</span> </span>
</div> </div>
</template> </template>
<script> <script>
import {ResolveUrlMixin} from "@/utils/utils"; import {ResolveUrlMixin, EscapeCSSMixin} from "@/utils/utils";
export default { export default {
name: 'KeywordsComponent', name: 'KeywordsComponent',
mixins: [ResolveUrlMixin], mixins: [ResolveUrlMixin, EscapeCSSMixin],
props: { props: {
recipe: Object, recipe: Object,
limit: Number, limit: Number,
@ -31,7 +30,12 @@ export default {
if (this.limit) { if (this.limit) {
return this.limit return this.limit
} }
return this.recipe.keywords.lenght return this.recipe.keywords.length
}
},
methods: {
keywordClass: function(k) {
return this.escapeCSS('_keywordname-' + k.label)
} }
} }
} }

View File

@ -1,5 +1,5 @@
<template> <template>
<div> <div class="last-cooked">
<span class="pl-1" v-if="recipe.last_cooked !== undefined && recipe.last_cooked !== null"> <span class="pl-1" v-if="recipe.last_cooked !== undefined && recipe.last_cooked !== null">
<b-badge pill variant="primary" class="font-weight-normal"><i class="fas fa-utensils"></i> {{ <b-badge pill variant="primary" class="font-weight-normal"><i class="fas fa-utensils"></i> {{
formatDate(recipe.last_cooked) formatDate(recipe.last_cooked)

View File

@ -1,5 +1,5 @@
<template> <template>
<div> <div class="rating">
<span class="d-inline" v-if="recipe.rating > 0"> <span class="d-inline" v-if="recipe.rating > 0">
<div v-if="!pill"> <div v-if="!pill">
<i class="fas fa-star fa-xs text-primary" v-for="i in Math.floor(recipe.rating)" v-bind:key="i"></i> <i class="fas fa-star fa-xs text-primary" v-for="i in Math.floor(recipe.rating)" v-bind:key="i"></i>

View File

@ -7,32 +7,32 @@
<div v-if="!loading" style="padding-bottom: 60px"> <div v-if="!loading" style="padding-bottom: 60px">
<RecipeSwitcher ref="ref_recipe_switcher" @switch="quickSwitch($event)" v-if="show_recipe_switcher"/> <RecipeSwitcher ref="ref_recipe_switcher" @switch="quickSwitch($event)" v-if="show_recipe_switcher"/>
<div class="row"> <div class="recipe__title row">
<div class="col-12" style="text-align: center"> <div class="col-12" style="text-align: center">
<h3>{{ recipe.name }}</h3> <h3>{{ recipe.name }}</h3>
</div> </div>
</div> </div>
<div class="row text-center"> <div class="recipe__history row text-center">
<div class="col col-md-12"> <div class="col col-md-12">
<recipe-rating :recipe="recipe"></recipe-rating> <recipe-rating :recipe="recipe"></recipe-rating>
<last-cooked :recipe="recipe" class="mt-2"></last-cooked> <last-cooked :recipe="recipe" class="mt-2"></last-cooked>
</div> </div>
</div> </div>
<div class="my-auto"> <div class="recipe__description my-auto">
<div class="col-12" style="text-align: center"> <div class="col-12" style="text-align: center">
<i>{{ recipe.description }}</i> <i>{{ recipe.description }}</i>
</div> </div>
</div> </div>
<div style="text-align: center"> <div class="recipe__keywords" style="text-align: center">
<keywords-component :recipe="recipe" :enable_keyword_links="enable_keyword_links"></keywords-component> <keywords-component :recipe="recipe" :enable_keyword_links="enable_keyword_links"></keywords-component>
</div> </div>
<hr/> <hr/>
<div class="row align-items-center"> <div class="recipe__prep-data row align-items-center">
<div class="col col-md-3"> <div class="recipe__prep-time col col-md-3">
<div class="d-flex"> <div class="d-flex">
<div class="my-auto mr-1"> <div class="my-auto mr-1">
<i class="fas fa-fw fa-user-clock fa-2x text-primary"></i> <i class="fas fa-fw fa-user-clock fa-2x text-primary"></i>
@ -44,7 +44,7 @@
</div> </div>
</div> </div>
<div class="col col-md-3"> <div class="recipe__wait-time col col-md-3">
<div class="row d-flex"> <div class="row d-flex">
<div class="my-auto mr-1"> <div class="my-auto mr-1">
<i class="far fa-fw fa-clock fa-2x text-primary"></i> <i class="far fa-fw fa-clock fa-2x text-primary"></i>
@ -56,7 +56,7 @@
</div> </div>
</div> </div>
<div class="col col-md-4 col-10 mt-2 mt-md-0"> <div class="recipe__servings col col-md-4 col-10 mt-2 mt-md-0">
<div class="d-flex"> <div class="d-flex">
<div class="my-auto mr-1"> <div class="my-auto mr-1">
<i class="fas fa-fw fa-pizza-slice fa-2x text-primary"></i> <i class="fas fa-fw fa-pizza-slice fa-2x text-primary"></i>
@ -75,15 +75,15 @@
</div> </div>
</div> </div>
<div class="col col-md-2 col-2 mt-2 mt-md-0 text-right"> <div class="recipe__context-menu col col-md-2 col-2 mt-2 mt-md-0 text-right">
<recipe-context-menu v-bind:recipe="recipe" :servings="servings" <recipe-context-menu v-bind:recipe="recipe" :servings="servings"
:disabled_options="{print:false}" v-if="show_context_menu"></recipe-context-menu> :disabled_options="{print:false}" v-if="show_context_menu"></recipe-context-menu>
</div> </div>
</div> </div>
<hr/> <hr/>
<div class="row"> <div class="recipe__overview row">
<div class="col-md-6 order-md-1 col-sm-12 order-sm-2 col-12 order-2" <div class="recipe__ingredients col-md-6 order-md-1 col-sm-12 order-sm-2 col-12 order-2"
v-if="recipe && ingredient_count > 0 && (recipe.show_ingredient_overview || recipe.steps.length < 2)"> v-if="recipe && ingredient_count > 0 && (recipe.show_ingredient_overview || recipe.steps.length < 2)">
<ingredients-card <ingredients-card
:recipe="recipe.id" :recipe="recipe.id"
@ -97,7 +97,7 @@
/> />
</div> </div>
<div class="col-12 order-1 col-sm-12 order-sm-1 col-md-6 order-md-2"> <div class="recipe__image col-12 order-1 col-sm-12 order-sm-1 col-md-6 order-md-2">
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<img class="img img-fluid rounded" :src="recipe.image" :alt="$t('Recipe_Image')" <img class="img img-fluid rounded" :src="recipe.image" :alt="$t('Recipe_Image')"
@ -109,16 +109,17 @@
</div> </div>
<template v-if="!recipe.internal"> <template v-if="!recipe.internal">
<div v-if="recipe.file_path.includes('.pdf')"> <div v-if="recipe.file_path.includes('.pdf')" class="recipe__file-pdf">
<PdfViewer :recipe="recipe"></PdfViewer> <PdfViewer :recipe="recipe"></PdfViewer>
</div> </div>
<div <div
v-if="recipe.file_path.includes('.png') || recipe.file_path.includes('.jpg') || recipe.file_path.includes('.jpeg') || recipe.file_path.includes('.gif')"> v-if="recipe.file_path.includes('.png') || recipe.file_path.includes('.jpg') || recipe.file_path.includes('.jpeg') || recipe.file_path.includes('.gif')"
class="recipe__file-img">
<ImageViewer :recipe="recipe"></ImageViewer> <ImageViewer :recipe="recipe"></ImageViewer>
</div> </div>
</template> </template>
<div v-for="(s, index) in recipe.steps" v-bind:key="s.id" style="margin-top: 1vh"> <div class="recipe__step" v-for="(s, index) in recipe.steps" v-bind:key="s.id" style="margin-top: 1vh">
<step-component <step-component
:recipe="recipe" :recipe="recipe"
:step="s" :step="s"
@ -130,13 +131,13 @@
></step-component> ></step-component>
</div> </div>
<div v-if="recipe.source_url !== null"> <div class="recipe__source" v-if="recipe.source_url !== null">
<h6 class="d-print-none"><i class="fas fa-file-import"></i> {{ $t("Imported_From") }}</h6> <h6 class="d-print-none"><i class="fas fa-file-import"></i> {{ $t("Imported_From") }}</h6>
<span class="text-muted mt-1"><a style="overflow-wrap: break-word;" <span class="text-muted mt-1"><a style="overflow-wrap: break-word;"
:href="recipe.source_url">{{ recipe.source_url }}</a></span> :href="recipe.source_url">{{ recipe.source_url }}</a></span>
</div> </div>
<div class="row" style="margin-top: 2vh; "> <div class="recipe__properties row" style="margin-top: 2vh; ">
<div class="col-lg-6 offset-lg-3 col-12"> <div class="col-lg-6 offset-lg-3 col-12">
<property-view-component :recipe="recipe" :servings="servings" @foodUpdated="loadRecipe(recipe.id)"></property-view-component> <property-view-component :recipe="recipe" :servings="servings" @foodUpdated="loadRecipe(recipe.id)"></property-view-component>
</div> </div>

View File

@ -1,6 +1,5 @@
<template> <template>
<span v-html="calculateAmount(number)"></span> <span class="step__scalable-num" :class="[this.factor===1 ? 'step__scalable-num_scaled_false' : (this.factor > 1 ? 'step__scalable-num_scaled_up':'step__scalable-num_scaled_down')]" v-html="calculateAmount(number)"></span>
</template> </template>
<script> <script>

View File

@ -1,15 +1,14 @@
<template> <template>
<div> <div class="step" :class="stepClassName" >
<hr/> <hr/>
<!-- Step header (only shown if more than one step --> <!-- Step header (only shown if more than one step -->
<div class="row mb-1" v-if="recipe.steps.length > 1"> <div class="row mb-1" v-if="recipe.steps.length > 1">
<div class="col col-md-8"> <div class="col col-md-8">
<h5 class="text-primary"> <h5 class="step__name text-primary" :class="stepClassNameType">
<template v-if="step.name">{{ step.name }}</template> {{ step_name }}
<template v-else>{{ $t("Step") }} {{ index + 1 }}</template> <small style="margin-left: 4px" class="step__time text-muted" v-if="step.time !== 0"><i
<small style="margin-left: 4px" class="text-muted" v-if="step.time !== 0"><i
class="fas fa-user-clock"></i> {{ step_time }}</small> class="fas fa-user-clock"></i> {{ step_time }}</small>
<small v-if="start_time !== ''" class="d-print-none"> <small v-if="start_time !== ''" class="step__start-time d-print-none">
<b-link :id="`id_reactive_popover_${step.id}`" @click="openPopover" href="#"> <b-link :id="`id_reactive_popover_${step.id}`" @click="openPopover" href="#">
{{ moment(start_time).add(step.time_offset, "minutes").format("HH:mm") }} {{ moment(start_time).add(step.time_offset, "minutes").format("HH:mm") }}
</b-link> </b-link>
@ -20,19 +19,19 @@
<b-button <b-button
@click="details_visible = !details_visible" @click="details_visible = !details_visible"
style="border: none; background: none" style="border: none; background: none"
class="shadow-none d-print-none" class="shadow-none d-print-none step__button-collapse"
:class="{ 'text-primary': details_visible, 'text-success': !details_visible }" :class="{ 'step__button-collapse_visible text-primary': details_visible, 'step_button-collapse_visible_false text-success': !details_visible }"
> >
<i class="far fa-check-circle"></i> <i class="far fa-check-circle"></i>
</b-button> </b-button>
</div> </div>
</div> </div>
<b-collapse id="collapse-1" v-model="details_visible"> <b-collapse id="collapse-1" class="step__details" :class="[details_visible ? 'step__details_visible':'step__details_visible_false']" v-model="details_visible">
<div class="row"> <div class="row">
<!-- ingredients table --> <!-- ingredients table -->
<div class="col col-md-4" <div class="step__ingredients col col-md-4"
v-if="step.show_ingredients_table && step.ingredients.length > 0 && (recipe.steps.length > 1 || force_ingredients)"> v-if="step.show_ingredients_table && step.ingredients.length > 0 && (recipe.steps.length > 1 || force_ingredients)">
<table class="table table-sm"> <table class="table table-sm">
<ingredients-card :steps="[step]" :ingredient_factor="ingredient_factor" <ingredients-card :steps="[step]" :ingredient_factor="ingredient_factor"
@ -40,7 +39,7 @@
</table> </table>
</div> </div>
<div class="col" <div class="step__instructions col"
:class="{ 'col-md-8 col-12': recipe.steps.length > 1, 'col-md-12 col-12': recipe.steps.length <= 1 }"> :class="{ 'col-md-8 col-12': recipe.steps.length > 1, 'col-md-12 col-12': recipe.steps.length <= 1 }">
<!-- step text --> <!-- step text -->
<div class="row"> <div class="row">
@ -51,7 +50,7 @@
</div> </div>
<!-- File (preview if image, download else) --> <!-- File (preview if image, download else) -->
<div class="row" v-if="step.file !== null"> <div class="step__file row" v-if="step.file !== null">
<div class="col col-md-12"> <div class="col col-md-12">
<template> <template>
<div <div
@ -71,10 +70,10 @@
</div> </div>
<!-- Sub recipe (always full width own row) --> <!-- Sub recipe (always full width own row) -->
<div class="row"> <div class="step__subrecipe row">
<div class="col col-md-12"> <div class="col col-md-12">
<div class="card" v-if="step.step_recipe_data !== null"> <div class="card" v-if="step.step_recipe_data !== null">
<b-collapse id="collapse-1" v-model="details_visible"> <b-collapse id="collapse-1" :class="[details_visible ? 'step__details_visible':'step__details_visible_false']" v-model="details_visible">
<div class="card-body"> <div class="card-body">
<h2 class="card-title"> <h2 class="card-title">
<a :href="resolveDjangoUrl('view_recipe', step.step_recipe_data.id)">{{ <a :href="resolveDjangoUrl('view_recipe', step.step_recipe_data.id)">{{
@ -128,13 +127,13 @@ import CompileComponent from "@/components/CompileComponent"
import IngredientsCard from "@/components/IngredientsCard" import IngredientsCard from "@/components/IngredientsCard"
import Vue from "vue" import Vue from "vue"
import moment from "moment" import moment from "moment"
import {ResolveUrlMixin, calculateHourMinuteSplit} from "@/utils/utils" import {ResolveUrlMixin, calculateHourMinuteSplit, EscapeCSSMixin} from "@/utils/utils"
Vue.prototype.moment = moment Vue.prototype.moment = moment
export default { export default {
name: "StepComponent", name: "StepComponent",
mixins: [GettextMixin, ResolveUrlMixin], mixins: [GettextMixin, ResolveUrlMixin, EscapeCSSMixin],
components: {CompileComponent, IngredientsCard}, components: {CompileComponent, IngredientsCard},
props: { props: {
step: Object, step: Object,
@ -149,7 +148,27 @@ export default {
}, },
computed: { computed: {
step_time: function() { step_time: function() {
return calculateHourMinuteSplit(this.step.time)}, return calculateHourMinuteSplit(this.step.time)
},
step_name: function() {
if (this.step.name) {
return this.step.name
}
return this.$t("Step") + ' ' + String(this.index+1)
},
stepClassName: function() {
let classes = {}
const nameclass = this.escapeCSS("_stepname-" + this.step_name)
classes[nameclass] = !!this.step.name
classes['_stepname-' + String(this.index+1)] = !this.step.name
return classes
},
stepClassNameType: function() {
let classes = {}
classes['step__name_custom'] = !!this.step.name
classes['step__name_custom_false'] = !this.step.name
return classes
}
}, },
data() { data() {
return { return {
@ -178,7 +197,7 @@ export default {
}, },
openPopover: function () { openPopover: function () {
this.$refs[`id_reactive_popover_${this.step.id}`].$emit("open") this.$refs[`id_reactive_popover_${this.step.id}`].$emit("open")
}, }
}, },
} }
</script> </script>

View File

@ -317,6 +317,15 @@ export function calculateAmount(amount, factor) {
} }
} }
/* Replace spaces by dashes, then use DOM method to escape special characters. Use for dynamically generated CSS classes*/
export const EscapeCSSMixin = {
methods: {
escapeCSS: function(classname) {
return CSS.escape(classname.replace(/\s+/g, "-").toLowerCase())
}
}
}
export function roundDecimals(num) { export function roundDecimals(num) {
let decimals = getUserPreference("user_fractions") ? getUserPreference("user_fractions") : 2 let decimals = getUserPreference("user_fractions") ? getUserPreference("user_fractions") : 2
return +(Math.round(num + `e+${decimals}`) + `e-${decimals}`) return +(Math.round(num + `e+${decimals}`) + `e-${decimals}`)