diff --git a/client/src/components/Form/Elements/FormSelectMany/FormSelectMany.vue b/client/src/components/Form/Elements/FormSelectMany/FormSelectMany.vue index 0c762ae90bd4..95581fbc3972 100644 --- a/client/src/components/Form/Elements/FormSelectMany/FormSelectMany.vue +++ b/client/src/components/Form/Elements/FormSelectMany/FormSelectMany.vue @@ -124,6 +124,29 @@ function focusOptionAtIndex(selected: "selected" | "unselected", index: number) } } +/** convert array of select options to a map of select labels to select values */ +function optionsToLabelMap(options: SelectOption[]): Map { + return new Map(options.map((o) => [o.label, o.value])); +} + +function valuesToOptions(values: SelectValue[]): SelectOption[] { + function stringifyObject(value: SelectValue) { + return typeof value === "object" && value !== null ? JSON.stringify(value) : value; + } + + const comparableValues = values.map(stringifyObject); + const valueSet = new Set(comparableValues); + const options: SelectOption[] = []; + + props.options.forEach((option) => { + if (valueSet.has(stringifyObject(option.value))) { + options.push(option); + } + }); + + return options; +} + async function selectOption(event: MouseEvent, index: number): Promise { if (event.shiftKey || event.ctrlKey) { handleHighlight(event, index, highlightUnselected); @@ -168,10 +191,10 @@ async function deselectOption(event: MouseEvent, index: number) { function selectAll() { if (highlightUnselected.highlightedIndexes.length > 0) { const highlightedValues = highlightUnselected.highlightedOptions.map((o) => o.value); - const selectedSet = new Set([...selected.value, ...highlightedValues]); - selected.value = Array.from(selectedSet); + selected.value = [...selected.value, ...highlightedValues]; - unselectedOptionsFiltered.value.filter((o) => highlightedValues.includes(o.value)); + const highlightedMap = optionsToLabelMap(highlightUnselected.highlightedOptions); + unselectedOptionsFiltered.value.filter((o) => highlightedMap.has(o.label)); } else if (searchValue.value === "") { selected.value = props.options.map((o) => o.value); @@ -188,13 +211,13 @@ function selectAll() { function deselectAll() { if (highlightSelected.highlightedIndexes.length > 0) { - const selectedSet = new Set(selected.value); - const highlightedValues = highlightSelected.highlightedOptions.map((o) => o.value); + const selectedMap = optionsToLabelMap(valuesToOptions(selected.value)); + const highlightedMap = optionsToLabelMap(highlightSelected.highlightedOptions); - highlightedValues.forEach((v) => selectedSet.delete(v)); - selected.value = Array.from(selectedSet); + highlightedMap.forEach((_value, label) => selectedMap.delete(label)); + selected.value = Array.from(selectedMap.values()); - selectedOptionsFiltered.value.filter((o) => highlightedValues.includes(o.value)); + selectedOptionsFiltered.value.filter((o) => highlightedMap.has(o.label)); } else if (searchValue.value === "") { selected.value = []; selectedOptionsFiltered.value = []; diff --git a/client/src/components/Sharing/UserSharing.vue b/client/src/components/Sharing/UserSharing.vue index f85b5c223913..270d80548a89 100644 --- a/client/src/components/Sharing/UserSharing.vue +++ b/client/src/components/Sharing/UserSharing.vue @@ -239,7 +239,7 @@ defineExpose({ class="mb-4"> Make datasets public - + Make datasets private to me and users this {{ modelClass }} is shared with Share {{ modelClass }} anyways