DEV: Deselect all and reset to defaults btns to edit categories modal (#22143)
What does this change do? This change adds the deselect all and reset to defaults buttons to the edit navigation menu categories modal. The deselect all button when click deselects all the selected categories in the modal. If the user saves with no categories selected, the user's categories section in the navigation menu will be set to the site's top categories. The reset to defaults button is only shown when the `default_navigation_menu_categories` site setting has been configured. When clicked, the user's categories section in the navigation menu is automatically set to the categories defined by the `default_navigation_menu_categories` site setting.
This commit is contained in:
parent
cdcf6cf0dd
commit
289d2a5540
|
@ -34,15 +34,19 @@
|
||||||
/>
|
/>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if this.title}}
|
<div class="modal-title-wrapper">
|
||||||
<div class="title">
|
{{#if this.title}}
|
||||||
<h3 id="discourse-modal-title">{{this.title}}</h3>
|
<div class="title">
|
||||||
|
<h3 id="discourse-modal-title">{{this.title}}</h3>
|
||||||
|
|
||||||
{{#if this.subtitle}}
|
{{#if this.subtitle}}
|
||||||
<p class="subtitle">{{this.subtitle}}</p>
|
<p class="subtitle">{{this.subtitle}}</p>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
<span id="modal-header-after-title"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
{{#if this.panels}}
|
{{#if this.panels}}
|
||||||
<ul class="modal-tabs">
|
<ul class="modal-tabs">
|
||||||
|
|
|
@ -1,75 +1,102 @@
|
||||||
<DModalBody
|
{{#in-element this.modalHeaderAfterTitleElement}}
|
||||||
@title="sidebar.categories_form.title"
|
<p class="sidebar-categories-form__deselect">
|
||||||
@class="sidebar-categories-form-modal"
|
<DButton
|
||||||
>
|
@class="btn-flat sidebar-categories-form__deselect-all-btn"
|
||||||
<form class="sidebar-categories-form">
|
@label="sidebar.categories_form_modal.subtitle.button_text"
|
||||||
<div class="sidebar-categories-form__filter">
|
@ariaLabel="sidebar.categories_form_modal.subtitle.button_text"
|
||||||
{{d-icon "search" class="sidebar-categories-form__filter-input-icon"}}
|
@action={{this.deselectAll}}
|
||||||
|
/>
|
||||||
|
|
||||||
<Input
|
{{i18n "sidebar.categories_form_modal.subtitle.text"}}
|
||||||
class="sidebar-categories-form__filter-input-field"
|
</p>
|
||||||
placeholder={{i18n "sidebar.categories_form.filter_placeholder"}}
|
{{/in-element}}
|
||||||
@type="text"
|
|
||||||
@value={{this.filter}}
|
|
||||||
{{on "input" (action "onFilterInput" value="target.value")}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{#if (gt this.filteredCategoriesGroupings.length 0)}}
|
<div class="sidebar-categories-form-modal">
|
||||||
{{#each this.filteredCategoriesGroupings as |categories|}}
|
<DModalBody
|
||||||
<div
|
@title="sidebar.categories_form_modal.title"
|
||||||
class="sidebar-categories-form__row"
|
@class="sidebar-categories-form__modal-body"
|
||||||
style={{html-safe (border-color categories.0.color "left")}}
|
>
|
||||||
>
|
<form class="sidebar-categories-form">
|
||||||
|
<div class="sidebar-categories-form__filter">
|
||||||
|
{{d-icon "search" class="sidebar-categories-form__filter-input-icon"}}
|
||||||
|
|
||||||
{{#each categories as |category|}}
|
<Input
|
||||||
<div
|
class="sidebar-categories-form__filter-input-field"
|
||||||
class="sidebar-categories-form__category-row"
|
placeholder={{i18n
|
||||||
data-category-id={{category.id}}
|
"sidebar.categories_form_modal.filter_placeholder"
|
||||||
data-category-level={{category.level}}
|
}}
|
||||||
>
|
@type="text"
|
||||||
<label
|
@value={{this.filter}}
|
||||||
class="sidebar-categories-form__category-label"
|
{{on "input" (action "onFilterInput" value="target.value")}}
|
||||||
for={{concat "sidebar-categories-form__input--" category.id}}
|
/>
|
||||||
>
|
|
||||||
<div class="sidebar-categories-form__category-badge">
|
|
||||||
{{category-badge category}}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{#unless category.parentCategory}}
|
|
||||||
<div class="sidebar-categories-form__category-description">
|
|
||||||
{{dir-span category.description_excerpt htmlSafe="true"}}
|
|
||||||
</div>
|
|
||||||
{{/unless}}
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<Input
|
|
||||||
id={{concat "sidebar-categories-form__input--" category.id}}
|
|
||||||
class="sidebar-categories-form__input"
|
|
||||||
@type="checkbox"
|
|
||||||
@checked={{includes
|
|
||||||
this.selectedSidebarCategoryIds
|
|
||||||
category.id
|
|
||||||
}}
|
|
||||||
{{on "click" (action "toggleCategory" category.id)}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{{/each}}
|
|
||||||
</div>
|
|
||||||
{{/each}}
|
|
||||||
{{else}}
|
|
||||||
<div class="sidebar-categories-form__no-categories">
|
|
||||||
{{i18n "sidebar.categories_form.no_categories"}}
|
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
|
||||||
</form>
|
|
||||||
</DModalBody>
|
|
||||||
|
|
||||||
<div class="modal-footer">
|
{{#if (gt this.filteredCategoriesGroupings.length 0)}}
|
||||||
<DButton
|
{{#each this.filteredCategoriesGroupings as |categories|}}
|
||||||
@class="btn-primary sidebar-categories-form__save-button"
|
<div
|
||||||
@label="sidebar.categories_form.save"
|
class="sidebar-categories-form__row"
|
||||||
@disabled={{this.saving}}
|
style={{html-safe (border-color categories.0.color "left")}}
|
||||||
@action={{this.save}}
|
>
|
||||||
/>
|
|
||||||
|
{{#each categories as |category|}}
|
||||||
|
<div
|
||||||
|
class="sidebar-categories-form__category-row"
|
||||||
|
data-category-id={{category.id}}
|
||||||
|
data-category-level={{category.level}}
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="sidebar-categories-form__category-label"
|
||||||
|
for={{concat "sidebar-categories-form__input--" category.id}}
|
||||||
|
>
|
||||||
|
<div class="sidebar-categories-form__category-badge">
|
||||||
|
{{category-badge category}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{#unless category.parentCategory}}
|
||||||
|
<div class="sidebar-categories-form__category-description">
|
||||||
|
{{dir-span category.description_excerpt htmlSafe="true"}}
|
||||||
|
</div>
|
||||||
|
{{/unless}}
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
id={{concat "sidebar-categories-form__input--" category.id}}
|
||||||
|
class="sidebar-categories-form__input"
|
||||||
|
@type="checkbox"
|
||||||
|
@checked={{includes
|
||||||
|
this.selectedSidebarCategoryIds
|
||||||
|
category.id
|
||||||
|
}}
|
||||||
|
{{on "click" (action "toggleCategory" category.id)}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
|
{{else}}
|
||||||
|
<div class="sidebar-categories-form__no-categories">
|
||||||
|
{{i18n "sidebar.categories_form_modal.no_categories"}}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
</form>
|
||||||
|
</DModalBody>
|
||||||
|
|
||||||
|
<div class="modal-footer sidebar-categories-form__modal-footer">
|
||||||
|
<DButton
|
||||||
|
@class="btn-primary sidebar-categories-form__save-button"
|
||||||
|
@label="sidebar.categories_form_modal.save"
|
||||||
|
@disabled={{this.saving}}
|
||||||
|
@action={{this.save}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{{#if (gt this.siteSettings.default_navigation_menu_categories.length 0)}}
|
||||||
|
<DButton
|
||||||
|
@icon="undo"
|
||||||
|
@class="btn-flat btn-text sidebar-categories-form__reset-to-defaults-btn"
|
||||||
|
@label="sidebar.categories_form_modal.reset_to_defaults"
|
||||||
|
@disabled={{this.saving}}
|
||||||
|
@action={{this.resetToDefaults}}
|
||||||
|
/>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
|
@ -8,8 +8,9 @@ import discourseDebounce from "discourse-common/lib/debounce";
|
||||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||||
|
|
||||||
export default class extends Component {
|
export default class extends Component {
|
||||||
@service site;
|
|
||||||
@service currentUser;
|
@service currentUser;
|
||||||
|
@service site;
|
||||||
|
@service siteSettings;
|
||||||
|
|
||||||
@tracked filter = "";
|
@tracked filter = "";
|
||||||
|
|
||||||
|
@ -85,6 +86,11 @@ export default class extends Component {
|
||||||
this.filter = filter.toLowerCase();
|
this.filter = filter.toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
deselectAll() {
|
||||||
|
this.selectedSidebarCategoryIds.clear();
|
||||||
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
toggleCategory(categoryId) {
|
toggleCategory(categoryId) {
|
||||||
if (this.selectedSidebarCategoryIds.includes(categoryId)) {
|
if (this.selectedSidebarCategoryIds.includes(categoryId)) {
|
||||||
|
@ -94,6 +100,18 @@ export default class extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get modalHeaderAfterTitleElement() {
|
||||||
|
return document.getElementById("modal-header-after-title");
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
resetToDefaults() {
|
||||||
|
this.selectedSidebarCategoryIds =
|
||||||
|
this.siteSettings.default_navigation_menu_categories
|
||||||
|
.split("|")
|
||||||
|
.map((id) => parseInt(id, 10));
|
||||||
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
save() {
|
save() {
|
||||||
this.saving = true;
|
this.saving = true;
|
||||||
|
|
|
@ -134,7 +134,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&:not(.history-modal) {
|
&:not(.history-modal) {
|
||||||
.modal-body:not(.reorder-categories):not(.poll-ui-builder):not(.poll-breakdown):not(.sidebar-categories-form-modal) {
|
.modal-body:not(.reorder-categories):not(.poll-ui-builder):not(.poll-breakdown):not(.sidebar-categories-form__modal-body) {
|
||||||
max-height: 80vh !important;
|
max-height: 80vh !important;
|
||||||
@media screen and (max-height: 500px) {
|
@media screen and (max-height: 500px) {
|
||||||
max-height: 65vh !important;
|
max-height: 65vh !important;
|
||||||
|
|
|
@ -4,13 +4,43 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sidebar-categories-form__modal-footer.modal-footer {
|
||||||
|
.sidebar-categories-form__reset-to-defaults-btn {
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: 0em;
|
||||||
|
|
||||||
|
.d-icon {
|
||||||
|
font-size: var(--font-down-1);
|
||||||
|
color: var(--tertiary);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus,
|
||||||
|
&:active {
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-categories-form__deselect {
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
.btn-flat.sidebar-categories-form__deselect-all-btn {
|
||||||
|
margin-left: auto;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
&:focus,
|
||||||
|
&:active {
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.sidebar-categories-form {
|
.sidebar-categories-form {
|
||||||
.sidebar-categories-form__filter {
|
.sidebar-categories-form__filter {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-bottom: 1em;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4389,11 +4389,15 @@ en:
|
||||||
more: "More"
|
more: "More"
|
||||||
all_categories: "All categories"
|
all_categories: "All categories"
|
||||||
all_tags: "All tags"
|
all_tags: "All tags"
|
||||||
categories_form:
|
categories_form_modal:
|
||||||
save: "Save"
|
save: "Save"
|
||||||
title: "Edit categories navigation"
|
title: "Edit categories navigation"
|
||||||
|
subtitle:
|
||||||
|
button_text: "Deselect all"
|
||||||
|
text: "and we'll automatically show this site's most popular categories"
|
||||||
filter_placeholder: "Filter categories"
|
filter_placeholder: "Filter categories"
|
||||||
no_categories: "There are no categories matching the given term."
|
no_categories: "There are no categories matching the given term."
|
||||||
|
reset_to_defaults: "Reset to defaults"
|
||||||
|
|
||||||
sections:
|
sections:
|
||||||
custom:
|
custom:
|
||||||
|
|
|
@ -22,7 +22,6 @@ RSpec.describe "Editing sidebar categories navigation", type: :system do
|
||||||
|
|
||||||
before do
|
before do
|
||||||
SiteSetting.new_edit_sidebar_categories_tags_interface_groups = group.name
|
SiteSetting.new_edit_sidebar_categories_tags_interface_groups = group.name
|
||||||
SiteSetting.default_navigation_menu_categories = "#{category.id}|#{category2.id}"
|
|
||||||
sign_in(user)
|
sign_in(user)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -33,11 +32,12 @@ RSpec.describe "Editing sidebar categories navigation", type: :system do
|
||||||
|
|
||||||
modal = sidebar.click_edit_categories_button
|
modal = sidebar.click_edit_categories_button
|
||||||
|
|
||||||
expect(modal).to have_right_title(I18n.t("js.sidebar.categories_form.title"))
|
expect(modal).to have_right_title(I18n.t("js.sidebar.categories_form_modal.title"))
|
||||||
expect(modal).to have_parent_category_color(category)
|
expect(modal).to have_parent_category_color(category)
|
||||||
expect(modal).to have_category_description_excerpt(category)
|
expect(modal).to have_category_description_excerpt(category)
|
||||||
expect(modal).to have_parent_category_color(category2)
|
expect(modal).to have_parent_category_color(category2)
|
||||||
expect(modal).to have_category_description_excerpt(category2)
|
expect(modal).to have_category_description_excerpt(category2)
|
||||||
|
expect(modal).to have_no_reset_to_defaults_button
|
||||||
|
|
||||||
expect(modal).to have_categories(
|
expect(modal).to have_categories(
|
||||||
[category, category_subcategory, category_subcategory2, category2, category2_subcategory],
|
[category, category_subcategory, category_subcategory2, category2, category2_subcategory],
|
||||||
|
@ -71,6 +71,47 @@ RSpec.describe "Editing sidebar categories navigation", type: :system do
|
||||||
expect(sidebar).to have_no_section_link(category2.name)
|
expect(sidebar).to have_no_section_link(category2.name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "allows a user to deselect all categories in the modal" do
|
||||||
|
Fabricate(:category_sidebar_section_link, linkable: category, user: user)
|
||||||
|
Fabricate(:category_sidebar_section_link, linkable: category_subcategory2, user: user)
|
||||||
|
|
||||||
|
visit "/latest"
|
||||||
|
|
||||||
|
expect(sidebar).to have_categories_section
|
||||||
|
|
||||||
|
modal = sidebar.click_edit_categories_button
|
||||||
|
modal.deselect_all.save
|
||||||
|
|
||||||
|
expect(sidebar).to have_section_link(category.name)
|
||||||
|
expect(sidebar).to have_no_section_link(category_subcategory2.name)
|
||||||
|
expect(sidebar).to have_section_link(category2.name)
|
||||||
|
expect(sidebar).to have_section_link("Uncategorized")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "allows a user to reset to the default navigation menu categories site setting" do
|
||||||
|
Fabricate(:category_sidebar_section_link, linkable: category, user: user)
|
||||||
|
Fabricate(:category_sidebar_section_link, linkable: category2, user: user)
|
||||||
|
|
||||||
|
SiteSetting.default_navigation_menu_categories =
|
||||||
|
"#{category_subcategory2.id}|#{category2_subcategory.id}"
|
||||||
|
|
||||||
|
visit "/latest"
|
||||||
|
|
||||||
|
expect(sidebar).to have_categories_section
|
||||||
|
expect(sidebar).to have_section_link(category.name)
|
||||||
|
expect(sidebar).to have_section_link(category2.name)
|
||||||
|
|
||||||
|
modal = sidebar.click_edit_categories_button
|
||||||
|
modal.click_reset_to_defaults_button.save
|
||||||
|
|
||||||
|
expect(modal).to be_closed
|
||||||
|
|
||||||
|
expect(sidebar).to have_no_section_link(category.name)
|
||||||
|
expect(sidebar).to have_no_section_link(category2.name)
|
||||||
|
expect(sidebar).to have_section_link(category_subcategory2.name)
|
||||||
|
expect(sidebar).to have_section_link(category2_subcategory.name)
|
||||||
|
end
|
||||||
|
|
||||||
it "allows a user to filter the categories in the modal by the category's name" do
|
it "allows a user to filter the categories in the modal by the category's name" do
|
||||||
visit "/latest"
|
visit "/latest"
|
||||||
|
|
||||||
|
@ -127,7 +168,7 @@ RSpec.describe "Editing sidebar categories navigation", type: :system do
|
||||||
|
|
||||||
modal = sidebar.click_edit_categories_button
|
modal = sidebar.click_edit_categories_button
|
||||||
|
|
||||||
expect(modal).to have_right_title(I18n.t("js.sidebar.categories_form.title"))
|
expect(modal).to have_right_title(I18n.t("js.sidebar.categories_form_modal.title"))
|
||||||
|
|
||||||
modal
|
modal
|
||||||
.toggle_category_checkbox(category_subcategory_subcategory)
|
.toggle_category_checkbox(category_subcategory_subcategory)
|
||||||
|
|
|
@ -29,7 +29,7 @@ module PageObjects
|
||||||
has_no_css?(".sidebar-categories-form-modal .sidebar-categories-form__category-row") &&
|
has_no_css?(".sidebar-categories-form-modal .sidebar-categories-form__category-row") &&
|
||||||
has_css?(
|
has_css?(
|
||||||
".sidebar-categories-form-modal .sidebar-categories-form__no-categories",
|
".sidebar-categories-form-modal .sidebar-categories-form__no-categories",
|
||||||
text: I18n.t("js.sidebar.categories_form.no_categories"),
|
text: I18n.t("js.sidebar.categories_form_modal.no_categories"),
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -65,6 +65,20 @@ module PageObjects
|
||||||
|
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def deselect_all
|
||||||
|
click_button(I18n.t("js.sidebar.categories_form_modal.subtitle.button_text"))
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
|
def click_reset_to_defaults_button
|
||||||
|
click_button(I18n.t("js.sidebar.categories_form_modal.reset_to_defaults"))
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
|
def has_no_reset_to_defaults_button?
|
||||||
|
has_no_button?(I18n.t("js.sidebar.categories_form_modal.reset_to_defaults"))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue