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 {