DEV: Modernize admin-site-text route/controller (#23581)

- Switch to `@tracked` and native getters
- Remove queryParam defaults which are awkward to work with. Instead, add `resolvedBlah` getters
- Add 'no results found' text
- Use standard 'model' key instead of a custom `setupController` method
- Remove use of `route-action`
- Remove `{{action` helper

Default queryParams in ember controllers are tricky to work with, especially when combined with the new router service. Instead, we can handle defaults ourselves
This commit is contained in:
David Taylor
2023-09-14 11:27:09 +01:00
committed by GitHub
parent 040a19d4cf
commit a60d7a2bc7
4 changed files with 91 additions and 69 deletions

View File

@ -1,51 +1,65 @@
import { action } from "@ember/object"; import { action } from "@ember/object";
import Controller from "@ember/controller"; import Controller from "@ember/controller";
import discourseComputed from "discourse-common/utils/decorators";
import discourseDebounce from "discourse-common/lib/debounce"; import discourseDebounce from "discourse-common/lib/debounce";
import { inject as service } from "@ember/service"; import { inject as service } from "@ember/service";
import { tracked } from "@glimmer/tracking";
import { disableImplicitInjections } from "discourse/lib/implicit-injections";
import ReseedModal from "admin/components/modal/reseed";
let lastSearch; let lastSearch;
@disableImplicitInjections
export default class AdminSiteTextIndexController extends Controller { export default class AdminSiteTextIndexController extends Controller {
@service router; @service router;
@service siteSettings; @service siteSettings;
@service modal;
@service store;
@tracked locale;
@tracked q;
@tracked overridden;
@tracked outdated;
@tracked model;
@tracked searching = false;
@tracked preferred = false;
searching = false;
siteTexts = null;
preferred = false;
queryParams = ["q", "overridden", "outdated", "locale"]; queryParams = ["q", "overridden", "outdated", "locale"];
locale = null;
q = null;
overridden = false;
outdated = false;
init() { get resolvedOverridden() {
super.init(...arguments); return [true, "true"].includes(this.overridden) ?? false;
this.set("locale", this.siteSettings.default_locale);
} }
_performSearch() { get resolvedOutdated() {
this.store return [true, "true"].includes(this.outdated) ?? false;
.find(
"site-text",
this.getProperties("q", "overridden", "outdated", "locale")
)
.then((results) => {
this.set("siteTexts", results);
})
.finally(() => this.set("searching", false));
} }
@discourseComputed() get resolvedLocale() {
availableLocales() { return this.locale ?? this.siteSettings.default_locale;
}
async _performSearch() {
try {
this.model = await this.store.find("site-text", {
q: this.q,
overridden: this.resolvedOverridden,
outdated: this.resolvedOutdated,
locale: this.resolvedLocale,
});
} finally {
this.searching = false;
}
}
get availableLocales() {
return JSON.parse(this.siteSettings.available_locales); return JSON.parse(this.siteSettings.available_locales);
} }
@discourseComputed("locale") get fallbackLocaleFullName() {
fallbackLocaleFullName() { if (this.model.extras.fallback_locale) {
if (this.siteTexts.extras.fallback_locale) {
return this.availableLocales.find((l) => { return this.availableLocales.find((l) => {
return l.value === this.siteTexts.extras.fallback_locale; return l.value === this.model.extras.fallback_locale;
}).name; }).name;
} }
} }
@ -54,22 +68,30 @@ export default class AdminSiteTextIndexController extends Controller {
edit(siteText) { edit(siteText) {
this.router.transitionTo("adminSiteText.edit", siteText.get("id"), { this.router.transitionTo("adminSiteText.edit", siteText.get("id"), {
queryParams: { queryParams: {
locale: this.locale, locale: this.resolvedLocale,
}, },
}); });
} }
@action @action
toggleOverridden() { toggleOverridden() {
this.toggleProperty("overridden"); if (this.resolvedOverridden) {
this.set("searching", true); this.overridden = null;
} else {
this.overridden = true;
}
this.searching = true;
discourseDebounce(this, this._performSearch, 400); discourseDebounce(this, this._performSearch, 400);
} }
@action @action
toggleOutdated() { toggleOutdated() {
this.toggleProperty("outdated"); if (this.resolvedOutdated) {
this.set("searching", true); this.outdated = null;
} else {
this.outdated = true;
}
this.searching = true;
discourseDebounce(this, this._performSearch, 400); discourseDebounce(this, this._performSearch, 400);
} }
@ -77,7 +99,7 @@ export default class AdminSiteTextIndexController extends Controller {
search() { search() {
const q = this.q; const q = this.q;
if (q !== lastSearch) { if (q !== lastSearch) {
this.set("searching", true); this.searching = true;
discourseDebounce(this, this._performSearch, 400); discourseDebounce(this, this._performSearch, 400);
lastSearch = q; lastSearch = q;
} }
@ -85,11 +107,14 @@ export default class AdminSiteTextIndexController extends Controller {
@action @action
updateLocale(value) { updateLocale(value) {
this.setProperties({ this.searching = true;
searching: true, this.locale = value;
locale: value,
});
discourseDebounce(this, this._performSearch, 400); discourseDebounce(this, this._performSearch, 400);
} }
@action
showReseedModal() {
this.modal.show(ReseedModal);
}
} }

View File

@ -1,10 +1,11 @@
import Route from "@ember/routing/route"; import Route from "@ember/routing/route";
import { action, getProperties } from "@ember/object"; import { disableImplicitInjections } from "discourse/lib/implicit-injections";
import { inject as service } from "@ember/service"; import { inject as service } from "@ember/service";
import ReseedModal from "admin/components/modal/reseed";
@disableImplicitInjections
export default class AdminSiteTextIndexRoute extends Route { export default class AdminSiteTextIndexRoute extends Route {
@service modal; @service siteSettings;
@service store;
queryParams = { queryParams = {
q: { replace: true }, q: { replace: true },
@ -14,18 +15,11 @@ export default class AdminSiteTextIndexRoute extends Route {
}; };
model(params) { model(params) {
return this.store.find( return this.store.find("site-text", {
"site-text", q: params.q,
getProperties(params, "q", "overridden", "outdated", "locale") overridden: params.overridden ?? false,
); outdated: params.outdated ?? false,
} locale: params.locale ?? this.siteSettings.default_locale,
});
setupController(controller, model) {
controller.set("siteTexts", model);
}
@action
showReseedModal() {
this.modal.show(ReseedModal);
} }
} }

View File

@ -6,12 +6,12 @@
@placeholderKey="admin.site_text.search" @placeholderKey="admin.site_text.search"
@class="no-blur site-text-search" @class="no-blur site-text-search"
@autofocus="true" @autofocus="true"
@key-up={{action "search"}} @key-up={{this.search}}
/> />
<div class="reseed"> <div class="reseed">
<DButton <DButton
@action={{route-action "showReseedModal"}} @action={{this.showReseedModal}}
@label="admin.reseed.action.label" @label="admin.reseed.action.label"
@title="admin.reseed.action.title" @title="admin.reseed.action.title"
@icon="sync" @icon="sync"
@ -26,27 +26,27 @@
@valueProperty="value" @valueProperty="value"
@content={{this.availableLocales}} @content={{this.availableLocales}}
@value={{this.locale}} @value={{this.locale}}
@onChange={{action "updateLocale"}} @onChange={{this.updateLocale}}
@class="locale-search" @class="locale-search"
@options={{hash filterable=true}} @options={{hash filterable=true}}
/> />
</div> </div>
<label> <label>
<Input <input
id="toggle-overridden" id="toggle-overridden"
@type="checkbox" type="checkbox"
@checked={{this.overridden}} checked={{this.resolvedOverridden}}
{{on "click" (action "toggleOverridden")}} {{on "click" this.toggleOverridden}}
/> />
{{i18n "admin.site_text.show_overriden"}} {{i18n "admin.site_text.show_overriden"}}
</label> </label>
<label> <label>
<Input <input
id="toggle-outdated" id="toggle-outdated"
@type="checkbox" type="checkbox"
@checked={{this.outdated}} checked={{this.resolvedOutdated}}
{{on "click" this.toggleOutdated}} {{on "click" this.toggleOutdated}}
/> />
{{i18n "admin.site_text.show_outdated"}} {{i18n "admin.site_text.show_outdated"}}
@ -55,20 +55,22 @@
</div> </div>
<ConditionalLoadingSpinner @condition={{this.searching}}> <ConditionalLoadingSpinner @condition={{this.searching}}>
{{#if this.siteTexts.extras.recommended}} {{#if this.model.extras.recommended}}
<p><b>{{i18n "admin.site_text.recommended"}}</b></p> <p><b>{{i18n "admin.site_text.recommended"}}</b></p>
{{/if}} {{/if}}
{{#each this.siteTexts as |siteText|}} {{#each this.model as |siteText|}}
<SiteTextSummary <SiteTextSummary
@siteText={{siteText}} @siteText={{siteText}}
@editAction={{action "edit"}} @editAction={{this.edit}}
@term={{this.q}} @term={{this.q}}
@searchRegex={{this.siteTexts.extras.regex}} @searchRegex={{this.model.extras.regex}}
/> />
{{else}}
{{i18n "admin.site_text.no_results"}}
{{/each}} {{/each}}
{{#if this.siteTexts.extras.has_more}} {{#if this.model.extras.has_more}}
<p class="warning">{{i18n "admin.site_text.more_than_50_results"}}</p> <p class="warning">{{i18n "admin.site_text.more_than_50_results"}}</p>
{{/if}} {{/if}}
</ConditionalLoadingSpinner> </ConditionalLoadingSpinner>

View File

@ -6143,6 +6143,7 @@ en:
show_outdated: "Only show outdated/invalid" show_outdated: "Only show outdated/invalid"
locale: "Language:" locale: "Language:"
more_than_50_results: "There are more than 50 results. Please refine your search." more_than_50_results: "There are more than 50 results. Please refine your search."
no_results: "No matching site texts found"
interpolation_keys: "Available interpolation keys:" interpolation_keys: "Available interpolation keys:"
outdated: outdated:
title: "This translation is outdated" title: "This translation is outdated"