DEV: Clean up sidebar modals (#26999)

1. async/await
2. TrackedSet
3. don't rely on ember array methods
4. list used props
5. move stuff out of constructors
6. don't use ember's Input component
7. convert a function to a method (to avoid passing in a class prop)
8. add missing `@tracked`
9. remove tracking from props that don't need it (not used in templates)
This commit is contained in:
Jarek Radosz 2024-05-21 14:35:22 +02:00 committed by GitHub
parent fe12cfeab2
commit eb2df2b7d6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 109 additions and 117 deletions

View File

@ -1,12 +1,12 @@
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { Input } from "@ember/component";
import { concat, fn, get } from "@ember/helper";
import { on } from "@ember/modifier";
import { action } from "@ember/object";
import didInsert from "@ember/render-modifiers/modifiers/did-insert";
import { service } from "@ember/service";
import { gt, includes, not } from "truth-helpers";
import { TrackedSet } from "@ember-compat/tracked-built-ins";
import { gt, has, includes, not } from "truth-helpers";
import EditNavigationMenuModal from "discourse/components/sidebar/edit-navigation-menu/modal";
import borderColor from "discourse/helpers/border-color";
import categoryBadge from "discourse/helpers/category-badge";
@ -46,19 +46,6 @@ function findAncestors(categories) {
return ancestors;
}
function applyMode(mode, categories, selectedSidebarCategoryIds) {
return categories.filter((c) => {
switch (mode) {
case "everything":
return true;
case "only-selected":
return selectedSidebarCategoryIds.includes(c.id);
case "only-unselected":
return !selectedSidebarCategoryIds.includes(c.id);
}
});
}
export default class SidebarEditNavigationMenuCategoriesModal extends Component {
@service currentUser;
@service site;
@ -67,26 +54,32 @@ export default class SidebarEditNavigationMenuCategoriesModal extends Component
@tracked initialLoad = true;
@tracked filteredCategoriesGroupings = [];
@tracked filteredCategoryIds = [];
// TODO: tracked array, no ember array methods
@tracked
selectedSidebarCategoryIds = [...this.currentUser.sidebar_category_ids];
selectedSidebarCategoryIds = new TrackedSet([
...this.currentUser.sidebar_category_ids,
]);
hasMorePages;
loadedFilter;
loadedMode;
loadedPage;
processing = false;
requestedFilter;
requestedMode;
saving = false;
observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
this.observer.disconnect();
this.loadMore();
}
},
{
threshold: 1.0,
}
);
constructor() {
super(...arguments);
this.observer = new IntersectionObserver(
(entries) => {
if (entries.some((entry) => entry.isIntersecting)) {
this.observer.disconnect();
this.loadMore();
}
},
{
threshold: 1.0,
}
);
this.processing = false;
this.setFilterAndMode("", "everything");
}
@ -108,15 +101,24 @@ export default class SidebarEditNavigationMenuCategoriesModal extends Component
}
setFetchedCategories(mode, categories) {
this.setFilteredCategories(
applyMode(mode, categories, this.selectedSidebarCategoryIds)
);
this.setFilteredCategories(this.applyMode(mode, categories));
}
concatFetchedCategories(mode, categories) {
this.concatFilteredCategories(
applyMode(mode, categories, this.selectedSidebarCategoryIds)
);
this.concatFilteredCategories(this.applyMode(mode, categories));
}
applyMode(mode, categories) {
return categories.filter((c) => {
switch (mode) {
case "everything":
return true;
case "only-selected":
return this.selectedSidebarCategoryIds.has(c.id);
case "only-unselected":
return !this.selectedSidebarCategoryIds.has(c.id);
}
});
}
@action
@ -128,7 +130,7 @@ export default class SidebarEditNavigationMenuCategoriesModal extends Component
async searchCategories(filter, mode) {
if (filter === "" && mode === "only-selected") {
this.setFilteredCategories(
await Category.asyncFindByIds(this.selectedSidebarCategoryIds)
await Category.asyncFindByIds([...this.selectedSidebarCategoryIds])
);
this.loadedPage = null;
@ -241,43 +243,40 @@ export default class SidebarEditNavigationMenuCategoriesModal extends Component
@action
toggleCategory(categoryId) {
if (this.selectedSidebarCategoryIds.includes(categoryId)) {
this.selectedSidebarCategoryIds.removeObject(categoryId);
if (this.selectedSidebarCategoryIds.has(categoryId)) {
this.selectedSidebarCategoryIds.delete(categoryId);
} else {
this.selectedSidebarCategoryIds.addObject(categoryId);
this.selectedSidebarCategoryIds.add(categoryId);
}
}
@action
resetToDefaults() {
this.selectedSidebarCategoryIds =
this.selectedSidebarCategoryIds = new TrackedSet(
this.siteSettings.default_navigation_menu_categories
.split("|")
.map((id) => parseInt(id, 10));
.map((id) => parseInt(id, 10))
);
}
@action
save() {
async save() {
this.saving = true;
const initialSidebarCategoryIds = this.currentUser.sidebar_category_ids;
this.currentUser.set(
"sidebar_category_ids",
this.selectedSidebarCategoryIds
);
this.currentUser.set("sidebar_category_ids", [
...this.selectedSidebarCategoryIds,
]);
this.currentUser
.save(["sidebar_category_ids"])
.then(() => {
this.args.closeModal();
})
.catch((error) => {
this.currentUser.set("sidebar_category_ids", initialSidebarCategoryIds);
popupAjaxError(error);
})
.finally(() => {
this.saving = false;
});
try {
await this.currentUser.save(["sidebar_category_ids"]);
this.args.closeModal();
} catch (error) {
this.currentUser.set("sidebar_category_ids", initialSidebarCategoryIds);
popupAjaxError(error);
} finally {
this.saving = false;
}
}
<template>
@ -344,10 +343,10 @@ export default class SidebarEditNavigationMenuCategoriesModal extends Component
{{/unless}}
</div>
<Input
<input
{{on "click" (fn this.toggleCategory category.id)}}
@type="checkbox"
@checked={{includes
type="checkbox"
checked={{has
this.selectedSidebarCategoryIds
category.id
}}

View File

@ -1,7 +1,6 @@
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { Input } from "@ember/component";
import { hash } from "@ember/helper";
import { fn, hash } from "@ember/helper";
import { on } from "@ember/modifier";
import { action } from "@ember/object";
import DButton from "discourse/components/d-button";
@ -15,7 +14,6 @@ import DropdownSelectBox from "select-kit/components/dropdown-select-box";
export default class SidebarEditNavigationMenuModal extends Component {
@tracked filter = "";
@tracked filterDropdownValue = "all";
filterDropdownContent = [
{
id: "all",
@ -80,10 +78,11 @@ export default class SidebarEditNavigationMenuModal extends Component {
class="sidebar__edit-navigation-menu__filter-input-icon"
}}
<Input
<input
{{on "input" (withEventValue (fn (mut this.filter)))}}
{{on "input" (withEventValue @onFilterInput)}}
@type="text"
@value={{this.filter}}
type="text"
value={{this.filter}}
placeholder={{@inputFilterPlaceholder}}
autofocus="true"
class="sidebar__edit-navigation-menu__filter-input-field"

View File

@ -1,12 +1,12 @@
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { Input } from "@ember/component";
import { concat, fn } from "@ember/helper";
import { on } from "@ember/modifier";
import { action } from "@ember/object";
import didInsert from "@ember/render-modifiers/modifiers/did-insert";
import { service } from "@ember/service";
import { gt, includes, or } from "truth-helpers";
import { TrackedSet } from "@ember-compat/tracked-built-ins";
import { gt, has, or } from "truth-helpers";
import ConditionalLoadingSpinner from "discourse/components/conditional-loading-spinner";
import loadingSpinner from "discourse/helpers/loading-spinner";
import { popupAjaxError } from "discourse/lib/ajax-error";
@ -20,13 +20,14 @@ export default class SidebarEditNavigationMenuTagsModal extends Component {
@service siteSettings;
@service store;
@tracked filter = "";
@tracked onlySelected = false;
@tracked onlyUnSelected = false;
@tracked disableFiltering = false;
@tracked saving = false;
@tracked selectedTags = new TrackedSet([...this.currentUser.sidebarTagNames]);
@tracked tags = [];
@tracked tagsLoading;
@tracked disableFiltering;
@tracked selectedTags = [...this.currentUser.sidebarTagNames];
@tracked tagsLoading = false;
observer;
onlySelected = false;
onlyUnselected = false;
constructor() {
super(...arguments);
@ -38,30 +39,25 @@ export default class SidebarEditNavigationMenuTagsModal extends Component {
const findArgs = {};
if (this.filter !== "") {
if (this.filter) {
findArgs.filter = this.filter;
}
if (this.onlySelected) {
findArgs.only_tags = this.selectedTags.join(",");
findArgs.only_tags = [...this.selectedTags].join(",");
} else if (this.onlyUnselected) {
findArgs.exclude_tags = [...this.selectedTags].join(",");
}
if (this.onlyUnselected) {
findArgs.exclude_tags = this.selectedTags.join(",");
try {
const tags = await this.store.findAll("listTag", findArgs);
this.tags = tags;
} catch (error) {
popupAjaxError(error);
} finally {
this.tagsLoading = false;
this.disableFiltering = false;
}
await this.store
.findAll("listTag", findArgs)
.then((tags) => {
this.tags = tags;
})
.catch((error) => {
popupAjaxError(error);
})
.finally(() => {
this.tagsLoading = false;
this.disableFiltering = false;
});
}
@action
@ -137,38 +133,36 @@ export default class SidebarEditNavigationMenuTagsModal extends Component {
@action
resetToDefaults() {
this.selectedTags =
this.siteSettings.default_navigation_menu_tags.split("|");
this.selectedTags = new TrackedSet(
this.siteSettings.default_navigation_menu_tags.split("|")
);
}
@action
toggleTag(tag) {
if (this.selectedTags.includes(tag)) {
this.selectedTags.removeObject(tag);
if (this.selectedTags.has(tag)) {
this.selectedTags.delete(tag);
} else {
this.selectedTags.addObject(tag);
this.selectedTags.add(tag);
}
}
@action
save() {
async save() {
this.saving = true;
const initialSidebarTags = this.currentUser.sidebar_tags;
this.currentUser.set("sidebar_tag_names", this.selectedTags);
this.currentUser.set("sidebar_tag_names", [...this.selectedTags]);
this.currentUser
.save(["sidebar_tag_names"])
.then((result) => {
this.currentUser.set("sidebar_tags", result.user.sidebar_tags);
this.args.closeModal();
})
.catch((error) => {
this.currentUser.set("sidebar_tags", initialSidebarTags);
popupAjaxError(error);
})
.finally(() => {
this.saving = false;
});
try {
const result = await this.currentUser.save(["sidebar_tag_names"]);
this.currentUser.set("sidebar_tags", result.user.sidebar_tags);
this.args.closeModal();
} catch (error) {
this.currentUser.set("sidebar_tags", initialSidebarTags);
popupAjaxError(error);
} finally {
this.saving = false;
}
}
<template>
@ -204,10 +198,10 @@ export default class SidebarEditNavigationMenuTagsModal extends Component {
data-tag-name={{tag.name}}
class="sidebar-tags-form__tag"
>
<Input
<input
{{on "click" (fn this.toggleTag tag.name)}}
@type="checkbox"
@checked={{includes this.selectedTags tag.name}}
type="checkbox"
checked={{has this.selectedTags tag.name}}
id={{concat "sidebar-tags-form__input--" tag.name}}
class="sidebar-tags-form__input"
/>