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
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 91 additions and 69 deletions

View File

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

View File

@ -1,10 +1,11 @@
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 ReseedModal from "admin/components/modal/reseed";
@disableImplicitInjections
export default class AdminSiteTextIndexRoute extends Route {
@service modal;
@service siteSettings;
@service store;
queryParams = {
q: { replace: true },
@ -14,18 +15,11 @@ export default class AdminSiteTextIndexRoute extends Route {
};
model(params) {
return this.store.find(
"site-text",
getProperties(params, "q", "overridden", "outdated", "locale")
);
}
setupController(controller, model) {
controller.set("siteTexts", model);
}
@action
showReseedModal() {
this.modal.show(ReseedModal);
return this.store.find("site-text", {
q: params.q,
overridden: params.overridden ?? false,
outdated: params.outdated ?? false,
locale: params.locale ?? this.siteSettings.default_locale,
});
}
}

View File

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

View File

@ -6143,6 +6143,7 @@ en:
show_outdated: "Only show outdated/invalid"
locale: "Language:"
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:"
outdated:
title: "This translation is outdated"