mirror of
https://github.com/discourse/discourse.git
synced 2024-11-29 11:18:33 +08:00
FEATURE: Add input filter for editing tags in navigation menu modal (#22216)
What does this change do? This commit adds an input filter to filter through the tag checkboxes in the modal to edit tags that are shown in the user's navigation menu. The filtering is a simple matching of the given filter term against the names of the tags.
This commit is contained in:
parent
08d8bd9f43
commit
609562be3e
|
@ -3,7 +3,20 @@
|
||||||
@class="sidebar-tags-form-modal"
|
@class="sidebar-tags-form-modal"
|
||||||
>
|
>
|
||||||
<form class="sidebar-tags-form">
|
<form class="sidebar-tags-form">
|
||||||
{{#each this.tags as |tag|}}
|
<div class="sidebar-tags-form__filter">
|
||||||
|
{{d-icon "search" class="sidebar-tags-form__filter-input-icon"}}
|
||||||
|
|
||||||
|
<Input
|
||||||
|
class="sidebar-tags-form__filter-input-field"
|
||||||
|
placeholder={{i18n "sidebar.tags_form_modal.filter_placeholder"}}
|
||||||
|
@type="text"
|
||||||
|
@value={{this.filter}}
|
||||||
|
{{on "input" (action "onFilterInput" value="target.value")}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{#if (gt this.filteredTags.length 0)}}
|
||||||
|
{{#each this.filteredTags as |tag|}}
|
||||||
<div class="sidebar-tags-form__tag" data-tag-name={{tag.name}}>
|
<div class="sidebar-tags-form__tag" data-tag-name={{tag.name}}>
|
||||||
<Input
|
<Input
|
||||||
id={{concat "sidebar-tags-form__input--" tag.name}}
|
id={{concat "sidebar-tags-form__input--" tag.name}}
|
||||||
|
@ -29,6 +42,11 @@
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
{{else}}
|
||||||
|
<div class="sidebar-tags-form__no-tags">
|
||||||
|
{{i18n "sidebar.tags_form_modal.no_tags"}}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
</form>
|
</form>
|
||||||
</DModalBody>
|
</DModalBody>
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,14 @@ import { inject as service } from "@ember/service";
|
||||||
import { action } from "@ember/object";
|
import { action } from "@ember/object";
|
||||||
|
|
||||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||||
|
import { INPUT_DELAY } from "discourse-common/config/environment";
|
||||||
|
import discourseDebounce from "discourse-common/lib/debounce";
|
||||||
|
|
||||||
export default class extends Component {
|
export default class extends Component {
|
||||||
@service currentUser;
|
@service currentUser;
|
||||||
@service store;
|
@service store;
|
||||||
|
|
||||||
|
@tracked filter = "";
|
||||||
@tracked tags = [];
|
@tracked tags = [];
|
||||||
@tracked selectedTags = [...this.currentUser.sidebarTagNames];
|
@tracked selectedTags = [...this.currentUser.sidebarTagNames];
|
||||||
|
|
||||||
|
@ -31,6 +35,29 @@ export default class extends Component {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get filteredTags() {
|
||||||
|
if (this.filter.length === 0) {
|
||||||
|
return this.tags;
|
||||||
|
} else {
|
||||||
|
return this.tags.reduce((acc, tag) => {
|
||||||
|
if (tag.name.toLowerCase().includes(this.filter)) {
|
||||||
|
acc.push(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
onFilterInput(filter) {
|
||||||
|
discourseDebounce(this, this.#performFiltering, filter, INPUT_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
#performFiltering(filter) {
|
||||||
|
this.filter = filter.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
toggleTag(tag) {
|
toggleTag(tag) {
|
||||||
if (this.selectedTags.includes(tag)) {
|
if (this.selectedTags.includes(tag)) {
|
||||||
|
|
|
@ -31,4 +31,32 @@
|
||||||
.sidebar-tags-form__tag-label-count {
|
.sidebar-tags-form__tag-label-count {
|
||||||
color: var(--primary-medium);
|
color: var(--primary-medium);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sidebar-tags-form__filter {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin-right: auto;
|
||||||
|
width: 100%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-tags-form__filter-input-icon {
|
||||||
|
position: absolute;
|
||||||
|
left: 0.5em;
|
||||||
|
top: 0.65em;
|
||||||
|
color: var(--primary-low-mid);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-tags-form__filter-input-field {
|
||||||
|
border-color: var(--primary-low-mid);
|
||||||
|
padding-left: 1.75em;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
border-color: var(--tertiary);
|
||||||
|
outline: none;
|
||||||
|
outline-offset: 0;
|
||||||
|
box-shadow: inset 0px 0px 0px 1px var(--tertiary);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
.sidebar-tags-form-modal {
|
||||||
|
.modal-inner-container {
|
||||||
|
width: 35em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.sidebar-tags-form {
|
.sidebar-tags-form {
|
||||||
.sidebar-tags-form__tag {
|
.sidebar-tags-form__tag {
|
||||||
flex-basis: 100%;
|
flex-basis: 100%;
|
||||||
|
|
|
@ -4399,6 +4399,8 @@ en:
|
||||||
reset_to_defaults: "Reset to defaults"
|
reset_to_defaults: "Reset to defaults"
|
||||||
tags_form_modal:
|
tags_form_modal:
|
||||||
title: "Edit tags navigation"
|
title: "Edit tags navigation"
|
||||||
|
filter_placeholder: "Filter tags"
|
||||||
|
no_tags: "There are no tags matching the given term."
|
||||||
|
|
||||||
sections:
|
sections:
|
||||||
custom:
|
custom:
|
||||||
|
|
|
@ -49,4 +49,24 @@ RSpec.describe "Editing sidebar tags navigation", type: :system do
|
||||||
expect(sidebar).to have_no_section_link(tag2.name)
|
expect(sidebar).to have_no_section_link(tag2.name)
|
||||||
expect(sidebar).to have_no_section_link(tag3.name)
|
expect(sidebar).to have_no_section_link(tag3.name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "allows a user to filter the tags in the modal by the tag's name" do
|
||||||
|
visit "/latest"
|
||||||
|
|
||||||
|
expect(sidebar).to have_tags_section
|
||||||
|
|
||||||
|
modal = sidebar.click_edit_tags_button
|
||||||
|
|
||||||
|
modal.filter("tag")
|
||||||
|
|
||||||
|
expect(modal).to have_tag_checkboxes([tag, tag2, tag3])
|
||||||
|
|
||||||
|
modal.filter("tag2")
|
||||||
|
|
||||||
|
expect(modal).to have_tag_checkboxes([tag2])
|
||||||
|
|
||||||
|
modal.filter("someinvalidterm")
|
||||||
|
|
||||||
|
expect(modal).to have_no_tag_checkboxes
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -20,6 +20,14 @@ module PageObjects
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def has_no_tag_checkboxes?
|
||||||
|
has_no_css?(".sidebar-tags-form-modal .sidebar-tags-form__tag") &&
|
||||||
|
has_css?(
|
||||||
|
".sidebar-tags-form-modal .sidebar-tags-form__no-tags",
|
||||||
|
text: I18n.t("js.sidebar.tags_form_modal.no_tags"),
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
def toggle_tag_checkbox(tag)
|
def toggle_tag_checkbox(tag)
|
||||||
find(
|
find(
|
||||||
".sidebar-tags-form-modal .sidebar-tags-form__tag[data-tag-name='#{tag.name}'] .sidebar-tags-form__input",
|
".sidebar-tags-form-modal .sidebar-tags-form__tag[data-tag-name='#{tag.name}'] .sidebar-tags-form__input",
|
||||||
|
@ -32,6 +40,11 @@ module PageObjects
|
||||||
find(".sidebar-tags-form-modal .sidebar-tags-form__save-button").click
|
find(".sidebar-tags-form-modal .sidebar-tags-form__save-button").click
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def filter(text)
|
||||||
|
find(".sidebar-tags-form-modal .sidebar-tags-form__filter-input-field").fill_in(with: text)
|
||||||
|
self
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue
Block a user