From 4deb31049704aee039bdd3b152b79c1decbfd233 Mon Sep 17 00:00:00 2001 From: Jorge Manrubia Date: Tue, 18 Nov 2025 10:13:13 +0100 Subject: [PATCH 1/2] Fix: Filter by "no one" assigned This also adds support to make some selection items exclusive in the combo boxes. --- .../multi_selection_combobox_controller.js | 33 ++++++++++++++++--- .../filters/settings/_assignees.html.erb | 5 +-- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/app/javascript/controllers/multi_selection_combobox_controller.js b/app/javascript/controllers/multi_selection_combobox_controller.js index 40f7c3459..716420839 100644 --- a/app/javascript/controllers/multi_selection_combobox_controller.js +++ b/app/javascript/controllers/multi_selection_combobox_controller.js @@ -40,7 +40,7 @@ export default class extends Controller { return this.noSelectionLabelValue } - const labels = this.#selectedItems().map(item => item.dataset.multiSelectionComboboxLabel) + const labels = this.#selectedItems.map(item => item.dataset.multiSelectionComboboxLabel) const sentence = toSentence(labels, { two_words_connector: " or ", last_word_connector: ", or " @@ -55,13 +55,28 @@ export default class extends Controller { if (isSelected) { item.setAttribute(this.selectPropertyNameValue, "false") } else { + if (this.isAnExclusiveSelectionItemInvolved(item)) { + this.#deselectAll() + } + item.setAttribute(this.selectPropertyNameValue, "true") } this.#updateHiddenFields() + if (item.dataset.multiSelectionFieldName) { + this.#renameHiddenFields(item.dataset.multiSelectionFieldName) + } this.labelTarget.textContent = this.#selectedLabel } + isAnExclusiveSelectionItemInvolved(item) { + return this.#isExclusiveSelection(item) || Array.from(this.#selectedItems).some((item) => this.#isExclusiveSelection(item)) + } + + #isExclusiveSelection(item) { + return item.dataset.multiSelectionExclusive === "true" + } + #updateHiddenFields() { this.#clearHiddenFields() this.#addHiddenFields() @@ -73,22 +88,32 @@ export default class extends Controller { }) } - #selectedItems() { + get #selectedItems() { return this.itemTargets.filter(item => item.getAttribute(this.selectPropertyNameValue) === "true" ) } #selectedValues() { - return this.#selectedItems().map(item => item.dataset.multiSelectionComboboxValue) + return this.#selectedItems.map(item => item.dataset.multiSelectionComboboxValue) } #clearHiddenFields() { - this.element.querySelectorAll('input[type="hidden"]').forEach(field => { + this.#hiddenFields.forEach(field => { field.remove() }) } + #renameHiddenFields(fieldName) { + this.#hiddenFields.forEach(field => { + field.setAttribute("name", fieldName) + }) + } + + get #hiddenFields() { + return this.element.querySelectorAll("input[type='hidden']") + } + #addHiddenFields() { this.#selectedValues().forEach(value => { const [ field ] = this.hiddenFieldTemplateTarget.content.cloneNode(true).children diff --git a/app/views/filters/settings/_assignees.html.erb b/app/views/filters/settings/_assignees.html.erb index ec7e82725..9a2fdd894 100644 --- a/app/views/filters/settings/_assignees.html.erb +++ b/app/views/filters/settings/_assignees.html.erb @@ -25,9 +25,10 @@