diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8098484a9..bf675a7a8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -31,6 +31,8 @@
[#390](https://github.com/nextcloud/cookbook/pull/390) @christianlupus
- Automatic deployment of new releases to the nextcloud app store
[#433](https://github.com/nextcloud/cookbook/pull/433) @christianlupus
+- Category and keyword selection from list of existing ones in recipe editor
+ [#402](https://github.com/nextcloud/cookbook/pull/402/) @seyfeb
### Changed
- Switch of project ownership to neextcloud organization in GitHub
diff --git a/src/components/EditMultiselect.vue b/src/components/EditMultiselect.vue
new file mode 100644
index 000000000..9933cab29
--- /dev/null
+++ b/src/components/EditMultiselect.vue
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/components/RecipeEdit.vue b/src/components/RecipeEdit.vue
index 1991de642..54997bfb4 100644
--- a/src/components/RecipeEdit.vue
+++ b/src/components/RecipeEdit.vue
@@ -7,8 +7,8 @@
-
-
+
+
@@ -20,6 +20,7 @@
import EditImageField from './EditImageField'
import EditInputField from './EditInputField'
import EditInputGroup from './EditInputGroup'
+import EditMultiselect from './EditMultiselect'
import EditTimeField from './EditTimeField'
export default {
@@ -28,6 +29,7 @@ export default {
EditImageField,
EditInputField,
EditInputGroup,
+ EditMultiselect,
EditTimeField,
},
props: ['id'],
@@ -57,6 +59,11 @@ export default {
prepTime: [0, 0],
cookTime: [0, 0],
totalTime: [0, 0],
+ allCategories: [],
+ isFetchingCategories: true,
+ isFetchingKeywords: true,
+ allKeywords: [],
+ selectedKeywords: [],
}
},
watch: {
@@ -75,14 +82,83 @@ export default {
let mins = this.totalTime[1].toString().padStart(2, '0')
this.recipe.totalTime = 'PT' + hours + 'H' + mins + 'M'
},
+ selectedKeywords: {
+ deep: true,
+ handler() {
+ // convert keyword array to comma-separated string
+ this.recipe['keywords'] = this.selectedKeywords.join()
+ }
+ }
},
methods: {
+ /**
+ * Add newly created category and set as selected.
+ */
+ addCategory (newCategory) {
+ this.allCategories.push(newCategory)
+ this.recipe['recipeCategory'] = newCategory
+ },
+ /**
+ * Add newly created keyword.
+ */
+ addKeyword (newKeyword) {
+ this.allKeywords.push(newKeyword)
+ this.selectedKeywords.push(newKeyword)
+ },
addEntry: function(field, index, content='') {
this.recipe[field].splice(index, 0, content)
},
deleteEntry: function(field, index) {
this.recipe[field].splice(index, 1)
},
+ /**
+ * Fetch and display recipe categories
+ */
+ fetchCategories: function() {
+ $.get(this.$window.baseUrl + '/categories').done((json) => {
+ json = json || []
+ this.allCategories = []
+ for (let i=0; i {
+ alert(t('cookbook', 'Failed to fetch categories'))
+ if (e && e instanceof Error) {
+ throw e
+ }
+ })
+ },
+ /**
+ * Fetch and display recipe keywords
+ */
+ fetchKeywords: function() {
+ $.ajax(this.$window.baseUrl + '/keywords').done((json) => {
+ json = json || []
+ if (json) {
+ this.allKeywords = []
+ for (let i=0; i {
+ alert(t('cookbook', 'Failed to fetch keywords'))
+ if (e && e instanceof Error) {
+ throw e
+ }
+ })
+ },
loadRecipeData: function() {
if (!this.$store.state.recipe) {
// Make the control row show that a recipe is loading
@@ -171,6 +247,8 @@ export default {
}
},
setup: function() {
+ this.fetchCategories()
+ this.fetchKeywords()
if (this.$route.params.id) {
// Load the recipe from store and make edits to a local copy first
this.recipe = { ...this.$store.state.recipe }
@@ -187,6 +265,20 @@ export default {
if (timeComps) {
this.totalTime = [timeComps[1], timeComps[2]]
}
+ this.selectedKeywords = this.recipe['keywords'].split(',')
+
+ // fallback if fetching all keywords fails
+ this.selectedKeywords.forEach(kw => {
+ if (!this.allKeywords.includes(kw)) {
+ this.allKeywords.push(kw)
+ }
+ })
+
+ // fallback if fetching all categories fails
+ if (!this.allCategories.includes(this.recipe['recipeCategory'])) {
+ this.allCategories.push(this.recipe['recipeCategory'])
+ }
+
// Always set the active page last!
this.$store.dispatch('setPage', { page: 'edit' })
} else {