@@ -18,6 +18,7 @@
diff --git a/src/components/EditMultiselectPopup.vue b/src/components/EditMultiselectPopup.vue
new file mode 100644
index 000000000..52554990b
--- /dev/null
+++ b/src/components/EditMultiselectPopup.vue
@@ -0,0 +1,114 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/components/RecipeEdit.vue b/src/components/RecipeEdit.vue
index bd9a99b16..b1566885e 100644
--- a/src/components/RecipeEdit.vue
+++ b/src/components/RecipeEdit.vue
@@ -2,7 +2,7 @@
-
+
@@ -12,9 +12,10 @@
-
-
-
+
+
+
+
@@ -26,6 +27,7 @@ import EditInputField from './EditInputField'
import EditInputGroup from './EditInputGroup'
import EditMultiselect from './EditMultiselect'
import EditMultiselectInputGroup from './EditMultiselectInputGroup'
+import EditMultiselectPopup from './EditMultiselectPopup'
import EditTimeField from './EditTimeField'
export default {
@@ -37,6 +39,7 @@ export default {
EditMultiselect,
EditTimeField,
EditMultiselectInputGroup,
+ EditMultiselectPopup
},
props: ['id'],
data () {
@@ -78,6 +81,7 @@ export default {
isFetchingKeywords: true,
allKeywords: [],
selectedKeywords: [],
+ allRecipes: [],
availableNutritionFields:
[{ key: 'calories', label: t('cookbook', 'Calories'), placeholder: t('cookbook', 'E.g.: 450 kcal (amount & unit)') },
{ key: 'carbohydrateContent', label: t('cookbook', 'Carbohydrate content'), placeholder: t('cookbook', 'E.g.: 2 g (amount & unit)') },
@@ -90,10 +94,18 @@ export default {
{ key: 'sodiumContent',label: t('cookbook', 'Sodium content'), placeholder: t('cookbook', 'E.g.: 2 g (amount & unit)') },
{ key: 'sugarContent', label: t('cookbook', 'Sugar content'), placeholder: t('cookbook', 'E.g.: 2 g (amount & unit)') },
{ key: 'transFatContent', label: t('cookbook', 'Trans-fat content'), placeholder: t('cookbook', 'E.g.: 2 g (amount & unit)') },
- { key: 'unsaturatedFatContent', label: t('cookbook', 'Unsaturated-fat content'), placeholder: t('cookbook', 'E.g.: 2 g (amount & unit)') }]
+ { key: 'unsaturatedFatContent', label: t('cookbook', 'Unsaturated-fat content'), placeholder: t('cookbook', 'E.g.: 2 g (amount & unit)') }],
+ referencesPopupFocused: false,
+ popupContext: undefined,
+ loadingRecipeReferences: true
}
},
computed: {
+ allrecipeOptions() {
+ return this.allRecipes.map(r => {
+ return {recipe_id: r.recipe_id, title: r.recipe_id + ": " + r.name}
+ })
+ },
categoryUpdating() {
return this.$store.state.categoryUpdating
},
@@ -368,6 +380,8 @@ export default {
}
},
mounted () {
+ let $this = this
+
// Store the initial recipe configuration for possible later use
if (this.recipeInit === null) {
this.recipeInit = this.recipe
@@ -397,7 +411,39 @@ export default {
this.recipe.recipeCategory = val[0]
}
})
+ // Register recipe-reference selection hook for showing popup when requested
+ // from a child element
+ this.$off('showRecipeReferencesPopup')
+ this.$on('showRecipeReferencesPopup', (val) => {
+ this.referencesPopupFocused = true
+ this.popupContext = val
+ })
+ // Register hook when recipe reference has been selected in popup
+ this.$off('ms-popup-selected')
+ this.$on('ms-popup-selected', (opt) => {
+ this.referencesPopupFocused = false
+ this.popupContext.context.pasteString('r/' + opt.recipe_id + ' ')
+ })
+ // Register hook when recipe reference has been selected in popup
+ this.$off('ms-popup-selection-canceled')
+ this.$on('ms-popup-selection-canceled', (opt) => {
+ this.referencesPopupFocused = false
+ this.popupContext.context.pasteCanceled()
+ })
this.savingRecipe = false
+
+ // Load data for all recipes to be used in recipe-reference popup suggestions
+ axios.get(this.$window.baseUrl + '/api/recipes')
+ .then(function (response) {
+ $this.allRecipes = response.data
+ })
+ .catch(function (e) {
+ console.log(e)
+ })
+ .then(() => {
+ // finally
+ $this.loadingRecipeReferences = false
+ })
},
beforeDestroy() {
window.removeEventListener('beforeunload', this.beforeWindowUnload)
@@ -488,4 +534,13 @@ form fieldset ul label input[type="checkbox"] {
cursor: pointer;
} */
+.referencesPopup {
+ position: fixed;
+ display: none;
+}
+
+.referencesPopup.visible {
+ display: block;
+}
+
diff --git a/src/components/RecipeIngredient.vue b/src/components/RecipeIngredient.vue
index bfdff6558..b600bd451 100644
--- a/src/components/RecipeIngredient.vue
+++ b/src/components/RecipeIngredient.vue
@@ -1,7 +1,7 @@
- ✔
- {{ displayIngredient }}
+ ✔
+
diff --git a/src/components/RecipeInstruction.vue b/src/components/RecipeInstruction.vue
index 4a9130711..cf4ebcd0a 100644
--- a/src/components/RecipeInstruction.vue
+++ b/src/components/RecipeInstruction.vue
@@ -1,5 +1,5 @@
- {{ instruction }}
+
diff --git a/src/components/RecipeView.vue b/src/components/RecipeView.vue
index c1600b9d5..9492121b9 100644
--- a/src/components/RecipeView.vue
+++ b/src/components/RecipeView.vue
@@ -25,7 +25,7 @@
-
+
{{ t('cookbook', 'Source') }}: {{ $store.state.recipe.url }}
@@ -117,6 +117,7 @@ export default {
computed: {
recipe: function() {
let recipe = {
+ description: '',
ingredients: [],
instructions: [],
keywords: [],
@@ -129,12 +130,23 @@ export default {
nutrition: null
}
+ if (this.$store.state.recipe.description) {
+ recipe.description = this.convertRecipeReferences(
+ this.escapeHtml(this.$store.state.recipe.description))
+ }
+
if (this.$store.state.recipe.recipeIngredient) {
recipe.ingredients = Object.values(this.$store.state.recipe.recipeIngredient)
+ .map((i) => {
+ return this.convertRecipeReferences(this.escapeHtml(i))
+ })
}
if (this.$store.state.recipe.recipeInstructions) {
recipe.instructions = Object.values(this.$store.state.recipe.recipeInstructions)
+ .map((i) => {
+ return this.convertRecipeReferences(this.escapeHtml(i))
+ })
}
if (this.$store.state.recipe.keywords) {
@@ -166,7 +178,9 @@ export default {
}
if (this.$store.state.recipe.tool) {
- recipe.tools = this.$store.state.recipe.tool
+ recipe.tools = this.$store.state.recipe.tool.map((i) => {
+ return this.convertRecipeReferences(this.escapeHtml(i))
+ })
}
if (this.$store.state.recipe.dateCreated) {
@@ -178,6 +192,7 @@ export default {
let date = this.parseDateTime(this.$store.state.recipe.dateModified)
recipe.dateModified = (date != null ? date.format('L, LT').toString() : null)
}
+
if (this.$store.state.recipe.nutrition) {
if ( this.$store.state.recipe.nutrition instanceof Array) {
this.$store.state.recipe.nutrition = {}
@@ -223,6 +238,20 @@ export default {
}
},
methods: {
+ escapeHtml: function(unsafeString) {
+ return unsafeString
+ .replace(/&/g, "&")
+ .replace(/\~/g, "˜")
+ .replace(//g, ">")
+ .replace(/"/g, """)
+ .replace(/'/g, "'");
+ },
+ convertRecipeReferences: function(text) {
+ let re = /(?<=^|\s|[,._+&?!-])#r\/(\d+)(?=$|\s|[.,_+&?!-])/g
+ let converted = text.replace(re, '
#$1')
+ return converted
+ },
isNullOrEmpty: function(str) {
return !str || typeof(str) === 'string' && 0 === str.trim().length;
},
@@ -549,3 +578,13 @@ export default {
content: '✔';
}
+
+