Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,26 +26,21 @@ Object.entries(Categories).forEach(([key, value]) => {
categoriesLookup[newKey] = value;
});

const getOptionCheckboxes = wrapper => wrapper.findAllComponents({ name: 'KListboxOption' });

const getOptionsValues = wrapper => {
const categories = {};
const checkboxes = wrapper.findAllComponents('[data-test="option-checkbox"]');
checkboxes.wrappers.forEach(checkbox => {
const { label, checked } = checkbox.props();
let value;
if (checked) {
value = CheckboxValue.CHECKED;
} else {
value = CheckboxValue.UNCHECKED;
}
categories[categoriesLookup[label]] = value;
getOptionCheckboxes(wrapper).wrappers.forEach(option => {
const label = option.props('label');
const checked = option.attributes('aria-selected') === 'true';
categories[categoriesLookup[label]] = checked ? CheckboxValue.CHECKED : CheckboxValue.UNCHECKED;
});
return categories;
};

const findOptionCheckbox = (wrapper, category) => {
const checkboxes = wrapper.findAllComponents('[data-test="option-checkbox"]');
return checkboxes.wrappers.find(checkbox => {
const label = checkbox.props('label');
return getOptionCheckboxes(wrapper).wrappers.find(option => {
const label = option.props('label');
return categoriesLookup[label] === category;
});
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<div>
<KMultiSelect
v-if="!expanded"
:expanded="expanded"
:value="autocompleteValues"
:options="categoriesList"
itemValue="value"
Expand Down Expand Up @@ -32,74 +32,6 @@
/>
</template>
</KMultiSelect>

<DropdownWrapper v-if="expanded">
<template #default="{ attach, menuProps }">
<VAutocomplete
:value="autocompleteValues"
:items="categoriesList"
:searchInput.sync="categoryText"
:label="translateMetadataString('category')"
box
clearable
chips
deletableChips
multiple
item-value="value"
item-text="text"
:menu-props="{
...menuProps,
zIndex: 4,
height: 0,
maxHeight: 0,
}"
:attach="attach"
@click:clear="$nextTick(() => removeAll())"
>
<template #selection="data">
<VTooltip
bottom
lazy
>
<template #activator="{ on, attrs }">
<VChip
v-bind="attrs"
:close="!data.item.undeletable"
v-on="on"
@input="remove(data.item.value)"
>
{{ data.item.text }}
</VChip>
</template>
<div>
<div>{{ tooltipText(data.item.value) }}</div>
</div>
</VTooltip>
</template>
</VAutocomplete>
</template>
</DropdownWrapper>

<div
v-if="expanded"
class="checkbox-list-wrapper"
>
<KCheckbox
v-for="option in filteredCategories"
:key="option.value"
data-test="option-checkbox"
:label="option.text"
:style="treeItemStyle(option)"
:checked="isSelected(option.value)"
@change="onChange(option.value)"
/>
<p
v-if="!filteredCategories.length"
:style="{ color: $themeTokens.annotation }"
>
{{ $tr('noCategoryFoundText') }}
</p>
</div>
</div>

</template>
Expand All @@ -113,12 +45,11 @@
import { getSortedCategories } from 'shared/utils/helpers';
import { createMultiSelectMessages } from 'shared/utils/multiSelectMessages';
import { communityChannelsStrings } from 'shared/strings/communityChannelsStrings';
import DropdownWrapper from 'shared/views/form/DropdownWrapper';
import { constantsTranslationMixin, metadataTranslationMixin } from 'shared/mixins';

export default {
name: 'CategoryOptions',
components: { KMultiSelect, KChip, DropdownWrapper },
components: { KMultiSelect, KChip },
mixins: [constantsTranslationMixin, metadataTranslationMixin],
props: {
/**
Expand All @@ -145,11 +76,6 @@
default: false,
},
},
data() {
return {
categoryText: null,
};
},
computed: {
categoriesList() {
const categories = getSortedCategories();
Expand All @@ -173,18 +99,6 @@
.map(([key]) => key);
return selectedValues;
},
nested() {
return !this.categoryText;
},
filteredCategories() {
const searchQuery = this.categoryText?.trim().toLowerCase();
if (!searchQuery) {
return this.categoriesList;
}
return this.categoriesList.filter(option =>
option.text.toLowerCase().includes(searchQuery),
);
},
messages() {
const { clearAllAction$ } = communityChannelsStrings;
return createMultiSelectMessages({
Expand All @@ -196,30 +110,6 @@
},
},
methods: {
treeItemStyle(item) {
const rule = this.$isRTL ? 'paddingRight' : 'paddingLeft';
return this.nested ? { [rule]: `${item.level * 24}px` } : {};
},
add(value) {
this.selected = {
...this.selected,
[value]: this.nodeIds,
};
},
remove(value) {
const newSelected = { ...this.selected };
Object.keys(this.selected)
.filter(selectedValue => selectedValue.startsWith(value))
.forEach(selectedValue => {
delete newSelected[selectedValue];
});
this.selected = newSelected;
},
removeAll() {
this.selected = {};
},
// Dropdown mode is only rendered when a single node is edited, so every
// selected category simply applies to all of nodeIds.
onKMultiSelectInput(newValues) {
Comment thread
rtibblesbot marked this conversation as resolved.
Resolved
this.selected = Object.fromEntries(newValues.map(value => [value, this.nodeIds]));
},
Expand All @@ -245,55 +135,6 @@
findDepth(val) {
return val.split('.').length - 1;
},
isSelected(value) {
// If the value is truthy (true or an array of nodeIds) then
// it is selected just if it is true (not an array)
if (this.selected[value] && this.selected[value].length === this.nodeIds.length) {
return true;
}

return this.isCheckboxSelectedByChildren(value);
},
/**
* Returns true if the given option should be selected thanks to its children.
* An option will be selected thanks to its children if:
* * One of the children is selected
* * It has several indeterminate children, but by joining all the contentNodes of the
* child options, together they constitute the same array of selected contentNodes.
*/
isCheckboxSelectedByChildren(optionId) {
const childrenOptions = Object.keys(this.selected)
.filter(selectedValue => selectedValue.startsWith(optionId))
.map(selectedValue => this.selected[selectedValue]);

if (childrenOptions.length === 0) {
return false; // No childen options
} else if (childrenOptions.length === 1) {
// just one child option, the value is deterrmined by if it is selected
return childrenOptions[0].length === this.nodeIds.length;
}

// Here multiple children are selected or indeterminate
if (childrenOptions.some(value => value.length === this.nodeIds.length)) {
// if some child value is selected for all nodes, then the parent option is selected
return true;
}

// Here all children options are mixed, we need to check if together
// the parent option is common for all nodes
const nodeIds = new Set();
childrenOptions.forEach(valueNodeIds => {
valueNodeIds.forEach(nodeId => nodeIds.add(nodeId));
});
return nodeIds.size === this.nodeIds.length;
},
onChange(optionId) {
if (this.isSelected(optionId)) {
this.remove(optionId);
} else {
this.add(optionId);
}
},
},
$trs: {
noCategoryFoundText: 'Category not found',
Expand All @@ -304,13 +145,3 @@
};

</script>


<style lang="scss" scoped>

.checkbox-list-wrapper {
height: 250px;
overflow-y: auto;
}

</style>
Loading
Loading