From 35dcb4a66365c423da0d8b0e0c2f5a16f6fedf00 Mon Sep 17 00:00:00 2001
From: Allan Otodi Opeto <103313919+AllanOXDi@users.noreply.github.com>
Date: Mon, 16 Sep 2024 20:00:15 +0300
Subject: [PATCH 1/6] modified the canSave function to enableble saving of
empty booleans
---
.../QuickEditModal/EditBooleanMapModal.vue | 65 +++++++++++--------
1 file changed, 38 insertions(+), 27 deletions(-)
diff --git a/contentcuration/contentcuration/frontend/channelEdit/components/QuickEditModal/EditBooleanMapModal.vue b/contentcuration/contentcuration/frontend/channelEdit/components/QuickEditModal/EditBooleanMapModal.vue
index d949cc576b..e6e6de5536 100644
--- a/contentcuration/contentcuration/frontend/channelEdit/components/QuickEditModal/EditBooleanMapModal.vue
+++ b/contentcuration/contentcuration/frontend/channelEdit/components/QuickEditModal/EditBooleanMapModal.vue
@@ -1,8 +1,10 @@
+
+ {{ hasMixedCategoriesMessage }} +
entry[1].length === this.nodeIds.length) .map(([key]) => key); - if ( - this.expanded && - Object.values(this.selected).some(value => value.length < this.nodeIds.length) - ) { - selectedValues.push(MIXED); - } return selectedValues; }, nested() { @@ -216,9 +196,6 @@ this.selected = {}; }, tooltipText(optionId) { - if (optionId === MIXED) { - return this.$tr('mixedLabel'); - } const option = this.categoriesList.find(option => option.value === optionId); if (!option) { return ''; @@ -282,15 +259,6 @@ }); return nodeIds.size === this.nodeIds.length; }, - isCheckboxIndeterminate(optionId) { - if (this.selected[optionId] && this.selected[optionId].length < this.nodeIds.length) { - return true; - } - return ( - Object.keys(this.selected).some(selectedValue => selectedValue.startsWith(optionId)) && - !this.isSelected(optionId) - ); - }, onChange(optionId) { if (this.isSelected(optionId)) { this.remove(optionId); @@ -301,7 +269,7 @@ }, $trs: { noCategoryFoundText: 'Category not found', - mixedLabel: 'Mixed', + }, }; diff --git a/contentcuration/contentcuration/frontend/shared/views/form/ExpandableSelect.vue b/contentcuration/contentcuration/frontend/shared/views/form/ExpandableSelect.vue index 127eeabd7a..f48995156d 100644 --- a/contentcuration/contentcuration/frontend/shared/views/form/ExpandableSelect.vue +++ b/contentcuration/contentcuration/frontend/shared/views/form/ExpandableSelect.vue @@ -50,7 +50,6 @@ :key="option.value" :label="option.text" :checked="isSelected(option.value)" - :indeterminate="isIndeterminate(option.value)" data-test="option-checkbox" @change="value => setOption(option.value, value)" /> @@ -188,12 +187,6 @@ } return this.valueModel[value].length === this.availableItems.length; }, - isIndeterminate(value) { - if (!this.valueModel[value]) { - return false; - } - return this.valueModel[value].length < this.availableItems.length; - }, setOption(optionId, value) { if (value) { this.valueModel = { From 7e80cf79eb5babd0a1ce86f52c33d137814a80c4 Mon Sep 17 00:00:00 2001 From: Allan Otodi Opeto <103313919+AllanOXDi@users.noreply.github.com> Date: Tue, 17 Sep 2024 20:27:13 +0300 Subject: [PATCH 3/6] unused test --- .../QuickEditModal/EditBooleanMapModal.vue | 20 +++++++------- .../__tests__/EditBooleanMapModal.spec.js | 27 ++----------------- .../contentNodeFields/CategoryOptions.vue | 2 -- .../shared/views/form/ExpandableSelect.vue | 2 +- 4 files changed, 14 insertions(+), 37 deletions(-) diff --git a/contentcuration/contentcuration/frontend/channelEdit/components/QuickEditModal/EditBooleanMapModal.vue b/contentcuration/contentcuration/frontend/channelEdit/components/QuickEditModal/EditBooleanMapModal.vue index f686c1f0a8..34eb315126 100644 --- a/contentcuration/contentcuration/frontend/channelEdit/components/QuickEditModal/EditBooleanMapModal.vue +++ b/contentcuration/contentcuration/frontend/channelEdit/components/QuickEditModal/EditBooleanMapModal.vue @@ -43,9 +43,10 @@ * This component is a modal responsible for reusing the logic of saving * the edition of a boolean map field for multiple nodes. */ + import isEqual from 'lodash/isEqual'; import { mapGetters, mapActions } from 'vuex'; import { ContentKindsNames } from 'shared/leUtils/ContentKinds'; - import { getInvalidText } from 'shared/utils/validation'; + import { getInvalidText } from 'shared/utils/validation'; import commonStrings from 'shared/translator'; export default { @@ -92,6 +93,7 @@ * Where nodeIds is the id of the nodes that have the option selected */ selectedValues: {}, + hasMixedCategories: false, }; }, computed: { @@ -132,23 +134,23 @@ }); this.selectedValues = optionsNodes; - // reset - this.$nextTick(() => { + // reset + this.$nextTick(() => { this.changed = false; }); this.selectedValues = optionsNodes; this.hasMixedCategories = Object.values(this.selectedValues).some( - (value) => value.length < this.nodes.length + value => value.length < this.nodes.length ); }, methods: { ...mapActions('contentNode', ['updateContentNode', 'updateContentNodeDescendants']), close(changed = false) { - this.$emit('close', { - changed: this.error ? false : changed, - updateDescendants: this.updateDescendants, - }); - }, + this.$emit('close', { + changed: this.error ? false : changed, + updateDescendants: this.updateDescendants, + }); + }, validate() { if (this.validators && this.validators.length) { this.error = getInvalidText( diff --git a/contentcuration/contentcuration/frontend/channelEdit/components/QuickEditModal/__tests__/EditBooleanMapModal.spec.js b/contentcuration/contentcuration/frontend/channelEdit/components/QuickEditModal/__tests__/EditBooleanMapModal.spec.js index e8a48355e1..10005e105a 100644 --- a/contentcuration/contentcuration/frontend/channelEdit/components/QuickEditModal/__tests__/EditBooleanMapModal.spec.js +++ b/contentcuration/contentcuration/frontend/channelEdit/components/QuickEditModal/__tests__/EditBooleanMapModal.spec.js @@ -16,7 +16,6 @@ let generalActions; const CheckboxValue = { UNCHECKED: 'UNCHECKED', CHECKED: 'CHECKED', - INDETERMINATE: 'INDETERMINATE', }; const { translateMetadataString } = metadataTranslationMixin.methods; @@ -31,11 +30,9 @@ const getOptionsValues = wrapper => { const categories = {}; const checkboxes = wrapper.findAll('[data-test="option-checkbox"]'); checkboxes.wrappers.forEach(checkbox => { - const { label, checked, indeterminate } = checkbox.vm.$props || {}; + const { label, checked } = checkbox.vm.$props || {}; let value; - if (indeterminate) { - value = CheckboxValue.INDETERMINATE; - } else if (checked) { + if (checked) { value = CheckboxValue.CHECKED; } else { value = CheckboxValue.UNCHECKED; @@ -182,26 +179,6 @@ describe('EditBooleanMapModal', () => { expect(dailyLifeValue).toBe(CheckboxValue.CHECKED); expect(foundationsValue).toBe(CheckboxValue.CHECKED); }); - - test('checkbox option should be indeterminate if not all nodes have the same options set', () => { - nodes['node1'].categories = { - [Categories.DAILY_LIFE]: true, - [Categories.FOUNDATIONS]: true, - }; - nodes['node2'].categories = { - [Categories.DAILY_LIFE]: true, - }; - - const wrapper = makeWrapper({ nodeIds: ['node1', 'node2'] }); - - const optionsValues = getOptionsValues(wrapper); - const { - [Categories.DAILY_LIFE]: dailyLifeValue, - [Categories.FOUNDATIONS]: foundationsValue, - } = optionsValues; - expect(dailyLifeValue).toBe(CheckboxValue.CHECKED); - expect(foundationsValue).toBe(CheckboxValue.INDETERMINATE); - }); }); }); diff --git a/contentcuration/contentcuration/frontend/shared/views/contentNodeFields/CategoryOptions.vue b/contentcuration/contentcuration/frontend/shared/views/contentNodeFields/CategoryOptions.vue index 70f8e651b7..f6170a8b9a 100644 --- a/contentcuration/contentcuration/frontend/shared/views/contentNodeFields/CategoryOptions.vue +++ b/contentcuration/contentcuration/frontend/shared/views/contentNodeFields/CategoryOptions.vue @@ -101,7 +101,6 @@ import DropdownWrapper from 'shared/views/form/DropdownWrapper'; import { constantsTranslationMixin, metadataTranslationMixin } from 'shared/mixins'; - export default { name: 'CategoryOptions', components: { DropdownWrapper }, @@ -269,7 +268,6 @@ }, $trs: { noCategoryFoundText: 'Category not found', - }, }; diff --git a/contentcuration/contentcuration/frontend/shared/views/form/ExpandableSelect.vue b/contentcuration/contentcuration/frontend/shared/views/form/ExpandableSelect.vue index f48995156d..cdeea8ee22 100644 --- a/contentcuration/contentcuration/frontend/shared/views/form/ExpandableSelect.vue +++ b/contentcuration/contentcuration/frontend/shared/views/form/ExpandableSelect.vue @@ -209,4 +209,4 @@ pointer-events: none; opacity: 0.5; } - \ No newline at end of file + From 5d240981e30b050d16c960d8bd956ddb8c0e1947 Mon Sep 17 00:00:00 2001 From: Allan Otodi Opeto <103313919+AllanOXDi@users.noreply.github.com> Date: Tue, 17 Sep 2024 22:45:50 +0300 Subject: [PATCH 4/6] clean up and lint --- .../QuickEditModal/EditBooleanMapModal.vue | 14 +++++++------- .../__tests__/EditBooleanMapModal.spec.js | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/contentcuration/contentcuration/frontend/channelEdit/components/QuickEditModal/EditBooleanMapModal.vue b/contentcuration/contentcuration/frontend/channelEdit/components/QuickEditModal/EditBooleanMapModal.vue index 34eb315126..a92c5547bf 100644 --- a/contentcuration/contentcuration/frontend/channelEdit/components/QuickEditModal/EditBooleanMapModal.vue +++ b/contentcuration/contentcuration/frontend/channelEdit/components/QuickEditModal/EditBooleanMapModal.vue @@ -46,7 +46,7 @@ import isEqual from 'lodash/isEqual'; import { mapGetters, mapActions } from 'vuex'; import { ContentKindsNames } from 'shared/leUtils/ContentKinds'; - import { getInvalidText } from 'shared/utils/validation'; + import { getInvalidText } from 'shared/utils/validation'; import commonStrings from 'shared/translator'; export default { @@ -93,6 +93,7 @@ * Where nodeIds is the id of the nodes that have the option selected */ selectedValues: {}, + changed: false, hasMixedCategories: false, }; }, @@ -134,17 +135,16 @@ }); this.selectedValues = optionsNodes; + this.hasMixedCategories = Object.values(this.selectedValues).some( + value => value.length < this.nodes.length + ); // reset this.$nextTick(() => { this.changed = false; }); - this.selectedValues = optionsNodes; - this.hasMixedCategories = Object.values(this.selectedValues).some( - value => value.length < this.nodes.length - ); }, methods: { - ...mapActions('contentNode', ['updateContentNode', 'updateContentNodeDescendants']), + ...mapActions('contentNode', ['updateContentNode']), close(changed = false) { this.$emit('close', { changed: this.error ? false : changed, @@ -173,7 +173,7 @@ } Object.entries(this.selectedValues) - .filter(([key, value]) => value.length === this.nodeIds.length) + .filter(([value]) => value.length === this.nodeIds.length) .forEach(([key]) => { fieldValue[key] = true; }); diff --git a/contentcuration/contentcuration/frontend/channelEdit/components/QuickEditModal/__tests__/EditBooleanMapModal.spec.js b/contentcuration/contentcuration/frontend/channelEdit/components/QuickEditModal/__tests__/EditBooleanMapModal.spec.js index 10005e105a..428d41cad1 100644 --- a/contentcuration/contentcuration/frontend/channelEdit/components/QuickEditModal/__tests__/EditBooleanMapModal.spec.js +++ b/contentcuration/contentcuration/frontend/channelEdit/components/QuickEditModal/__tests__/EditBooleanMapModal.spec.js @@ -32,7 +32,7 @@ const getOptionsValues = wrapper => { checkboxes.wrappers.forEach(checkbox => { const { label, checked } = checkbox.vm.$props || {}; let value; - if (checked) { + if (checked) { value = CheckboxValue.CHECKED; } else { value = CheckboxValue.UNCHECKED; From 5f998c1035611a998cc837295d95e771d058bf77 Mon Sep 17 00:00:00 2001 From: Allan Otodi Opeto <103313919+AllanOXDi@users.noreply.github.com> Date: Tue, 17 Sep 2024 23:02:49 +0300 Subject: [PATCH 5/6] quick restore --- .../components/QuickEditModal/EditBooleanMapModal.vue | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/contentcuration/contentcuration/frontend/channelEdit/components/QuickEditModal/EditBooleanMapModal.vue b/contentcuration/contentcuration/frontend/channelEdit/components/QuickEditModal/EditBooleanMapModal.vue index a92c5547bf..e933aabbe3 100644 --- a/contentcuration/contentcuration/frontend/channelEdit/components/QuickEditModal/EditBooleanMapModal.vue +++ b/contentcuration/contentcuration/frontend/channelEdit/components/QuickEditModal/EditBooleanMapModal.vue @@ -144,7 +144,7 @@ }); }, methods: { - ...mapActions('contentNode', ['updateContentNode']), + ...mapActions('contentNode', ['updateContentNode', 'updateContentNodeDescendants']), close(changed = false) { this.$emit('close', { changed: this.error ? false : changed, @@ -168,15 +168,22 @@ this.nodes.map(async node => { const fieldValue = {}; const currentNode = this.getContentNode(node.id); + // If we have mixed categories remain the old ones, and + // just add new categories if there are any if (this.hasMixedCategories) { Object.assign(fieldValue, currentNode[this.field] || {}); } - Object.entries(this.selectedValues) .filter(([value]) => value.length === this.nodeIds.length) .forEach(([key]) => { fieldValue[key] = true; }); + if (this.updateDescendants && node.kind === ContentKindsNames.TOPIC) { + return this.updateContentNodeDescendants({ + id: node.id, + [this.field]: fieldValue, + }); + } return this.updateContentNode({ id: node.id, [this.field]: fieldValue, From 55432b4550d30cb480abb37877528a6d541b1295 Mon Sep 17 00:00:00 2001 From: Allan Otodi Opeto <103313919+AllanOXDi@users.noreply.github.com> Date: Tue, 17 Sep 2024 23:29:30 +0300 Subject: [PATCH 6/6] quick restore again --- .../components/QuickEditModal/EditBooleanMapModal.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contentcuration/contentcuration/frontend/channelEdit/components/QuickEditModal/EditBooleanMapModal.vue b/contentcuration/contentcuration/frontend/channelEdit/components/QuickEditModal/EditBooleanMapModal.vue index e933aabbe3..e5d7aa09f2 100644 --- a/contentcuration/contentcuration/frontend/channelEdit/components/QuickEditModal/EditBooleanMapModal.vue +++ b/contentcuration/contentcuration/frontend/channelEdit/components/QuickEditModal/EditBooleanMapModal.vue @@ -191,7 +191,7 @@ }) ); this.$store.dispatch('showSnackbarSimple', this.confirmationMessage || ''); - this.close(); + this.close(this.changed); }, }, $trs: {