Skip to content

Commit 7474aac

Browse files
authored
Merge pull request #4737 from AllanOXDi/bulk_editting-fix
Undo the reverted changes in #4714
2 parents f0091d3 + 55432b4 commit 7474aac

File tree

4 files changed

+36
-82
lines changed

4 files changed

+36
-82
lines changed

contentcuration/contentcuration/frontend/channelEdit/components/QuickEditModal/EditBooleanMapModal.vue

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
12
<template>
23

34
<KModal
45
:title="title"
56
:submitText="$tr('saveAction')"
7+
:submitDisabled="!canSave"
68
:cancelText="$tr('cancelAction')"
79
data-test="edit-booleanMap-modal"
810
@submit="handleSave"
@@ -11,6 +13,9 @@
1113
<p v-if="resourcesSelectedText.length > 0" data-test="resources-selected-message">
1214
{{ resourcesSelectedText }}
1315
</p>
16+
<p v-if="hasMixedCategories" data-test="mixed-categories-message">
17+
{{ hasMixedCategoriesMessage }}
18+
</p>
1419
<template v-if="isDescendantsUpdatable && isTopicSelected">
1520
<KCheckbox
1621
:checked="updateDescendants"
@@ -26,9 +31,6 @@
2631
:inputHandler="(value) => { selectedValues = value }"
2732
></slot>
2833

29-
<span v-if="error" class="red--text">
30-
{{ error }}
31-
</span>
3234
</KModal>
3335

3436
</template>
@@ -45,6 +47,7 @@
4547
import { mapGetters, mapActions } from 'vuex';
4648
import { ContentKindsNames } from 'shared/leUtils/ContentKinds';
4749
import { getInvalidText } from 'shared/utils/validation';
50+
import commonStrings from 'shared/translator';
4851
4952
export default {
5053
name: 'EditBooleanMapModal',
@@ -91,16 +94,27 @@
9194
*/
9295
selectedValues: {},
9396
changed: false,
97+
hasMixedCategories: false,
9498
};
9599
},
96100
computed: {
97-
...mapGetters('contentNode', ['getContentNodes']),
101+
...mapGetters('contentNode', ['getContentNodes', 'getContentNode']),
98102
nodes() {
99103
return this.getContentNodes(this.nodeIds);
100104
},
101105
isTopicSelected() {
102106
return this.nodes.some(node => node.kind === ContentKindsNames.TOPIC);
103107
},
108+
canSave() {
109+
if (this.hasMixedCategories) {
110+
return Object.values(this.selectedValues).some(value => value.length > 0);
111+
}
112+
return !this.error;
113+
},
114+
hasMixedCategoriesMessage() {
115+
// eslint-disable-next-line kolibri/vue-no-undefined-string-uses
116+
return commonStrings.$tr('addAdditionalCatgoriesDescription');
117+
},
104118
},
105119
watch: {
106120
selectedValues(newValue, oldValue) {
@@ -121,6 +135,9 @@
121135
});
122136
123137
this.selectedValues = optionsNodes;
138+
this.hasMixedCategories = Object.values(this.selectedValues).some(
139+
value => value.length < this.nodes.length
140+
);
124141
// reset
125142
this.$nextTick(() => {
126143
this.changed = false;
@@ -147,19 +164,20 @@
147164
}
148165
},
149166
async handleSave() {
150-
this.validate();
151-
if (this.error) {
152-
return;
153-
}
154-
155167
await Promise.all(
156-
this.nodes.map(node => {
168+
this.nodes.map(async node => {
157169
const fieldValue = {};
158-
Object.entries(this.selectedValues).forEach(([key, value]) => {
159-
if (value.includes(node.id)) {
170+
const currentNode = this.getContentNode(node.id);
171+
// If we have mixed categories remain the old ones, and
172+
// just add new categories if there are any
173+
if (this.hasMixedCategories) {
174+
Object.assign(fieldValue, currentNode[this.field] || {});
175+
}
176+
Object.entries(this.selectedValues)
177+
.filter(([value]) => value.length === this.nodeIds.length)
178+
.forEach(([key]) => {
160179
fieldValue[key] = true;
161-
}
162-
});
180+
});
163181
if (this.updateDescendants && node.kind === ContentKindsNames.TOPIC) {
164182
return this.updateContentNodeDescendants({
165183
id: node.id,

contentcuration/contentcuration/frontend/channelEdit/components/QuickEditModal/__tests__/EditBooleanMapModal.spec.js

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ let generalActions;
1616
const CheckboxValue = {
1717
UNCHECKED: 'UNCHECKED',
1818
CHECKED: 'CHECKED',
19-
INDETERMINATE: 'INDETERMINATE',
2019
};
2120

2221
const { translateMetadataString } = metadataTranslationMixin.methods;
@@ -31,11 +30,9 @@ const getOptionsValues = wrapper => {
3130
const categories = {};
3231
const checkboxes = wrapper.findAll('[data-test="option-checkbox"]');
3332
checkboxes.wrappers.forEach(checkbox => {
34-
const { label, checked, indeterminate } = checkbox.vm.$props || {};
33+
const { label, checked } = checkbox.vm.$props || {};
3534
let value;
36-
if (indeterminate) {
37-
value = CheckboxValue.INDETERMINATE;
38-
} else if (checked) {
35+
if (checked) {
3936
value = CheckboxValue.CHECKED;
4037
} else {
4138
value = CheckboxValue.UNCHECKED;
@@ -182,26 +179,6 @@ describe('EditBooleanMapModal', () => {
182179
expect(dailyLifeValue).toBe(CheckboxValue.CHECKED);
183180
expect(foundationsValue).toBe(CheckboxValue.CHECKED);
184181
});
185-
186-
test('checkbox option should be indeterminate if not all nodes have the same options set', () => {
187-
nodes['node1'].categories = {
188-
[Categories.DAILY_LIFE]: true,
189-
[Categories.FOUNDATIONS]: true,
190-
};
191-
nodes['node2'].categories = {
192-
[Categories.DAILY_LIFE]: true,
193-
};
194-
195-
const wrapper = makeWrapper({ nodeIds: ['node1', 'node2'] });
196-
197-
const optionsValues = getOptionsValues(wrapper);
198-
const {
199-
[Categories.DAILY_LIFE]: dailyLifeValue,
200-
[Categories.FOUNDATIONS]: foundationsValue,
201-
} = optionsValues;
202-
expect(dailyLifeValue).toBe(CheckboxValue.CHECKED);
203-
expect(foundationsValue).toBe(CheckboxValue.INDETERMINATE);
204-
});
205182
});
206183
});
207184

contentcuration/contentcuration/frontend/shared/views/contentNodeFields/CategoryOptions.vue

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<template #default="{ attach, menuProps }">
66
<VAutocomplete
77
:value="autocompleteValues"
8-
:items="autocompleteOptions"
8+
:items="categoriesList"
99
:searchInput.sync="categoryText"
1010
:label="translateMetadataString('category')"
1111
box
@@ -81,7 +81,6 @@
8181
:label="option.text"
8282
:style="treeItemStyle(option)"
8383
:checked="isSelected(option.value)"
84-
:indeterminate="isCheckboxIndeterminate(option.value)"
8584
@change="onChange(option.value)"
8685
/>
8786
<p
@@ -102,8 +101,6 @@
102101
import DropdownWrapper from 'shared/views/form/DropdownWrapper';
103102
import { constantsTranslationMixin, metadataTranslationMixin } from 'shared/mixins';
104103
105-
const MIXED = 'mixed';
106-
107104
export default {
108105
name: 'CategoryOptions',
109106
components: { DropdownWrapper },
@@ -155,28 +152,10 @@
155152
this.$emit('input', value);
156153
},
157154
},
158-
autocompleteOptions() {
159-
const options = [...this.categoriesList];
160-
if (this.expanded) {
161-
// Just boolean maps can have indeterminate values
162-
options.push({
163-
value: MIXED,
164-
text: this.$tr('mixedLabel'),
165-
undeletable: true,
166-
});
167-
}
168-
return options;
169-
},
170155
autocompleteValues() {
171156
const selectedValues = Object.entries(this.selected)
172157
.filter(entry => entry[1].length === this.nodeIds.length)
173158
.map(([key]) => key);
174-
if (
175-
this.expanded &&
176-
Object.values(this.selected).some(value => value.length < this.nodeIds.length)
177-
) {
178-
selectedValues.push(MIXED);
179-
}
180159
return selectedValues;
181160
},
182161
nested() {
@@ -216,9 +195,6 @@
216195
this.selected = {};
217196
},
218197
tooltipText(optionId) {
219-
if (optionId === MIXED) {
220-
return this.$tr('mixedLabel');
221-
}
222198
const option = this.categoriesList.find(option => option.value === optionId);
223199
if (!option) {
224200
return '';
@@ -282,15 +258,6 @@
282258
});
283259
return nodeIds.size === this.nodeIds.length;
284260
},
285-
isCheckboxIndeterminate(optionId) {
286-
if (this.selected[optionId] && this.selected[optionId].length < this.nodeIds.length) {
287-
return true;
288-
}
289-
return (
290-
Object.keys(this.selected).some(selectedValue => selectedValue.startsWith(optionId)) &&
291-
!this.isSelected(optionId)
292-
);
293-
},
294261
onChange(optionId) {
295262
if (this.isSelected(optionId)) {
296263
this.remove(optionId);
@@ -301,7 +268,6 @@
301268
},
302269
$trs: {
303270
noCategoryFoundText: 'Category not found',
304-
mixedLabel: 'Mixed',
305271
},
306272
};
307273

contentcuration/contentcuration/frontend/shared/views/form/ExpandableSelect.vue

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@
5050
:key="option.value"
5151
:label="option.text"
5252
:checked="isSelected(option.value)"
53-
:indeterminate="isIndeterminate(option.value)"
5453
data-test="option-checkbox"
5554
@change="value => setOption(option.value, value)"
5655
/>
@@ -188,12 +187,6 @@
188187
}
189188
return this.valueModel[value].length === this.availableItems.length;
190189
},
191-
isIndeterminate(value) {
192-
if (!this.valueModel[value]) {
193-
return false;
194-
}
195-
return this.valueModel[value].length < this.availableItems.length;
196-
},
197190
setOption(optionId, value) {
198191
if (value) {
199192
this.valueModel = {
@@ -216,4 +209,4 @@
216209
pointer-events: none;
217210
opacity: 0.5;
218211
}
219-
</style>
212+
</style>

0 commit comments

Comments
 (0)