DEV: Introduce dedicated controller and route for `discovery.filter` (#20837)
Instead of being tied to the old implementation and constraints, a dedicated route and controller for the `discovery.filter` app route will allow us to iterate on changes much faster.
This commit is contained in:
parent
9c36a49668
commit
e0155b6955
|
@ -1,33 +1,19 @@
|
|||
{{#if this.isQueryFilterMode}}
|
||||
<div class="topic-query-filter">
|
||||
<div class="topic-query-filter__input">
|
||||
{{d-icon "filter" class="topic-query-filter__icon"}}
|
||||
<Input
|
||||
class="topic-query-filter__filter-term"
|
||||
@value={{this.queryString}}
|
||||
@enter={{action @updateTopicsListQueryParams this.queryString}}
|
||||
@type="text"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<BreadCrumbs
|
||||
@categories={{this.categories}}
|
||||
@category={{this.category}}
|
||||
@noSubcategories={{this.noSubcategories}}
|
||||
@tag={{this.tag}}
|
||||
@additionalTags={{this.additionalTags}}
|
||||
/>
|
||||
<BreadCrumbs
|
||||
@categories={{this.categories}}
|
||||
@category={{this.category}}
|
||||
@noSubcategories={{this.noSubcategories}}
|
||||
@tag={{this.tag}}
|
||||
@additionalTags={{this.additionalTags}}
|
||||
/>
|
||||
|
||||
{{#unless this.additionalTags}}
|
||||
{{! nav bar doesn't work with tag intersections }}
|
||||
<NavigationBar
|
||||
@navItems={{this.navItems}}
|
||||
@filterMode={{this.filterMode}}
|
||||
@category={{this.category}}
|
||||
/>
|
||||
{{/unless}}
|
||||
{{/if}}
|
||||
{{#unless this.additionalTags}}
|
||||
{{! nav bar doesn't work with tag intersections }}
|
||||
<NavigationBar
|
||||
@navItems={{this.navItems}}
|
||||
@filterMode={{this.filterMode}}
|
||||
@category={{this.category}}
|
||||
/>
|
||||
{{/unless}}
|
||||
|
||||
<div class="navigation-controls">
|
||||
{{#if (and this.notCategoriesRoute this.site.mobileView this.canBulk)}}
|
||||
|
|
|
@ -6,18 +6,11 @@ import { NotificationLevels } from "discourse/lib/notification-levels";
|
|||
import { getOwner } from "discourse-common/lib/get-owner";
|
||||
import { htmlSafe } from "@ember/template";
|
||||
import { inject as service } from "@ember/service";
|
||||
import { equal } from "@ember/object/computed";
|
||||
|
||||
export default Component.extend(FilterModeMixin, {
|
||||
router: service(),
|
||||
dialog: service(),
|
||||
tagName: "",
|
||||
queryString: "",
|
||||
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
this.queryString = this.filterQueryString;
|
||||
},
|
||||
|
||||
// Should be a `readOnly` instead but some themes/plugins still pass
|
||||
// the `categories` property into this component
|
||||
|
@ -147,8 +140,6 @@ export default Component.extend(FilterModeMixin, {
|
|||
return controller.canBulkSelect;
|
||||
},
|
||||
|
||||
isQueryFilterMode: equal("filterMode", "filter"),
|
||||
|
||||
actions: {
|
||||
changeCategoryNotificationLevel(notificationLevel) {
|
||||
this.category.setNotification(notificationLevel);
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
import Controller from "@ember/controller";
|
||||
import { action } from "@ember/object";
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
|
||||
export default class extends Controller {
|
||||
@tracked status = "";
|
||||
|
||||
queryParams = ["status"];
|
||||
|
||||
get queryString() {
|
||||
let paramStrings = [];
|
||||
|
||||
this.queryParams.forEach((key) => {
|
||||
if (this[key]) {
|
||||
paramStrings.push(`${key}:${this[key]}`);
|
||||
}
|
||||
});
|
||||
|
||||
return paramStrings.join(" ");
|
||||
}
|
||||
|
||||
@action
|
||||
updateTopicsListQueryParams(queryString) {
|
||||
for (const match of queryString.matchAll(/(\w+):([^:\s]+)/g)) {
|
||||
const key = match[1];
|
||||
const value = match[2];
|
||||
|
||||
if (this.queryParams.includes(key)) {
|
||||
this.set(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,4 @@
|
|||
import Controller, { inject as controller } from "@ember/controller";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import { action } from "@ember/object";
|
||||
|
||||
// Just add query params here to have them automatically passed to topic list filters.
|
||||
export const queryParams = {
|
||||
|
@ -29,31 +27,6 @@ export const queryParams = {
|
|||
const controllerOpts = {
|
||||
discoveryTopics: controller("discovery/topics"),
|
||||
queryParams: Object.keys(queryParams),
|
||||
|
||||
@discourseComputed(...Object.keys(queryParams))
|
||||
queryString() {
|
||||
let paramStrings = [];
|
||||
|
||||
this.queryParams.forEach((key) => {
|
||||
if (this[key]) {
|
||||
paramStrings.push(`${key}:${this[key]}`);
|
||||
}
|
||||
});
|
||||
|
||||
return paramStrings.join(" ");
|
||||
},
|
||||
|
||||
@action
|
||||
updateTopicsListQueryParams(queryString) {
|
||||
for (const match of queryString.matchAll(/(\w+):([^:\s]+)/g)) {
|
||||
const key = match[1];
|
||||
const value = match[2];
|
||||
|
||||
if (controllerOpts.queryParams.includes(key)) {
|
||||
this.set(key, value);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// Default to `undefined`
|
||||
|
|
|
@ -6,7 +6,6 @@ import { TRACKED_QUERY_PARAM_VALUE } from "discourse/lib/topic-list-tracked-filt
|
|||
|
||||
export default Controller.extend(FilterModeMixin, {
|
||||
discovery: controller(),
|
||||
discoveryFilter: controller("discovery.filter"),
|
||||
router: service(),
|
||||
|
||||
@discourseComputed("router.currentRoute.queryParams.f")
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
import Controller, { inject as controller } from "@ember/controller";
|
||||
|
||||
export default class extends Controller {
|
||||
@controller("discovery/filter") discoveryFilter;
|
||||
|
||||
queryString = "";
|
||||
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.queryString = this.discoveryFilter.queryString;
|
||||
}
|
||||
}
|
|
@ -11,13 +11,6 @@ export default {
|
|||
name: "dynamic-route-builders",
|
||||
|
||||
initialize(_container, app) {
|
||||
app.register(
|
||||
"controller:discovery.filter",
|
||||
DiscoverySortableController.extend()
|
||||
);
|
||||
|
||||
app.register("route:discovery.filter", buildTopicRoute("filter"));
|
||||
|
||||
app.register(
|
||||
"controller:discovery.category",
|
||||
DiscoverySortableController.extend()
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
import I18n from "I18n";
|
||||
|
||||
import DiscourseRoute from "discourse/routes/discourse";
|
||||
import { isEmpty } from "@ember/utils";
|
||||
import { action } from "@ember/object";
|
||||
|
||||
export default class extends DiscourseRoute {
|
||||
queryParams = {
|
||||
status: { replace: true, refreshModel: true },
|
||||
};
|
||||
|
||||
model(data) {
|
||||
return this.store.findFiltered("topicList", {
|
||||
filter: "filter",
|
||||
params: this.#filterQueryParams(data),
|
||||
});
|
||||
}
|
||||
|
||||
titleToken() {
|
||||
const filterText = I18n.t("filters.filter.title");
|
||||
return I18n.t("filters.with_topics", { filter: filterText });
|
||||
}
|
||||
|
||||
setupController(_controller, model) {
|
||||
this.controllerFor("discovery/topics").setProperties({ model });
|
||||
}
|
||||
|
||||
renderTemplate() {
|
||||
this.render("navigation/filter", { outlet: "navigation-bar" });
|
||||
|
||||
this.render("discovery/topics", {
|
||||
controller: "discovery/topics",
|
||||
outlet: "list-container",
|
||||
});
|
||||
}
|
||||
|
||||
// TODO(tgxworld): This action is required by the `discovery/topics` controller which is not necessary for this route.
|
||||
// Figure out a way to remove this.
|
||||
@action
|
||||
changeSort() {}
|
||||
|
||||
#filterQueryParams(data) {
|
||||
const params = {};
|
||||
|
||||
Object.keys(this.queryParams).forEach((key) => {
|
||||
if (!isEmpty(data[key])) {
|
||||
params[key] = data[key];
|
||||
}
|
||||
});
|
||||
|
||||
return params;
|
||||
}
|
||||
}
|
|
@ -9,7 +9,5 @@
|
|||
@hasDraft={{this.currentUser.has_topic_draft}}
|
||||
@createTopic={{route-action "createTopic"}}
|
||||
@skipCategoriesNavItem={{this.skipCategoriesNavItem}}
|
||||
@filterQueryString={{this.discoveryFilter.queryString}}
|
||||
@updateTopicsListQueryParams={{this.discoveryFilter.updateTopicsListQueryParams}}
|
||||
/>
|
||||
</DSection>
|
|
@ -0,0 +1,20 @@
|
|||
<DSection
|
||||
@bodyClass="navigation-filter"
|
||||
@class="navigation-container"
|
||||
@scrollTop={{false}}
|
||||
>
|
||||
<div class="topic-query-filter">
|
||||
<div class="topic-query-filter__input">
|
||||
{{d-icon "filter" class="topic-query-filter__icon"}}
|
||||
<Input
|
||||
class="topic-query-filter__filter-term"
|
||||
@value={{this.queryString}}
|
||||
@enter={{action
|
||||
this.discoveryFilter.updateTopicsListQueryParams
|
||||
this.queryString
|
||||
}}
|
||||
@type="text"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</DSection>
|
Loading…
Reference in New Issue