diff --git a/addons/core/addon/decorators/resource-filter-param.js b/addons/core/addon/decorators/resource-filter-param.js index b8395a20f..6619ee6ee 100644 --- a/addons/core/addon/decorators/resource-filter-param.js +++ b/addons/core/addon/decorators/resource-filter-param.js @@ -1,3 +1,94 @@ +import EmberObject from '@ember/object'; +import { getOwner } from '@ember/application'; + +/** + * + */ +class ResourceFilter extends EmberObject { + // =attributes + + route; + name; + allowedValues; + defaultValue; + + /** + * + */ + get filterKey() { + return `filter-${this.name}`; + } + + /** + * + */ + get value() { + const value = + this.route.paramsFor(this.route.routeName)[this.filterKey] || + JSON.stringify(this.defaultValue); + return value ? JSON.parse(value) : null; + } + + /** + * + */ + set value(value) { + const queryParams = {}; + queryParams[this.filterKey] = JSON.stringify(value); + this.route.transitionTo({ queryParams }); + } + + // =static methods + + /** + * + */ + static setupRouteQueryParams(routeClass, name) { + const filterKey = `filter-${name}`; + + // If the route has no query params specified yet, declare them. + if (!Object.keys(routeClass.queryParams).length) + routeClass.queryParams = {}; + + // If the route has no resource filters list specified yet, create one. + if (!routeClass.resourceFilterParams) routeClass.resourceFilterParams = []; + + // Add the resource filter query parameter to the route. Resource filter + // param changes refresh the model but do not contribute to browser history. + // See https://guides.emberjs.com/release/routing/query-params/ + routeClass.queryParams[filterKey] = { + refreshModel: true, + replace: true, + }; + } + + /** + * + */ + static getOrCreateRouteResourceFilter( + routeInstance, + name, + allowedValues, + defaultValue + ) { + const owner = getOwner(routeInstance); + const containerKey = `route-resource-filter:${name}@${routeInstance.routeName}`; + const factory = owner.factoryFor(containerKey); + if (!factory) { + // create factory + class RouteResourceFilter extends this { + route = routeInstance; + name = name; + allowedValues = allowedValues; + defaultValue = defaultValue; + } + owner.register(containerKey, RouteResourceFilter); + } + const instance = owner.lookup(containerKey); + return instance; + } +} + /** * A resource filter param is a concise way to express a route query parameter. * Resource filter params abstract away a route's query parameter @@ -40,29 +131,9 @@ export function resourceFilterParam(allowedValues, defaultValue) { * @return {object{get, set}} */ return function (target, name /*, descriptor*/) { - const filterKey = `filter-${name}`; - const filterAllowedValuesKey = `filter-allowed-values-${name}`; + ResourceFilter.setupRouteQueryParams(target, name); - // If the route has no query params specified yet, declare them. - if (!Object.keys(target.queryParams).length) target.queryParams = {}; - - // If the route has no resource filters list specified yet, create one. - if (!target.resourceFilterParams) target.resourceFilterParams = []; - - // Add the resource filter query parameter to the route. Resource filter - // param changes refresh the model but do not contribute to browser history. - // See https://guides.emberjs.com/release/routing/query-params/ - target.queryParams[filterKey] = { - refreshModel: true, - replace: true, - }; - - // Note the name of this filter param. - target.resourceFilterParams.push(name); - - // Store the allowed values for future lookup - // (via `ResourceFilterParamHelper`). - target[filterAllowedValuesKey] = allowedValues; + let instance; // Override the decorated attribute with a getter and setter. return { @@ -70,10 +141,13 @@ export function resourceFilterParam(allowedValues, defaultValue) { * Returns the JSON-parsed query parameter value OR defaultValue. */ get() { - const value = - this.paramsFor(this.routeName)[filterKey] || - JSON.stringify(defaultValue); - return value ? JSON.parse(value) : null; + instance = ResourceFilter.getOrCreateRouteResourceFilter( + this, + name, + allowedValues, + defaultValue + ); + return instance.value; }, /** @@ -83,9 +157,7 @@ export function resourceFilterParam(allowedValues, defaultValue) { * @param value */ set(value) { - const queryParams = {}; - queryParams[filterKey] = JSON.stringify(value); - this.transitionTo({ queryParams }); + instance.value = value; }, }; }; diff --git a/addons/core/addon/helpers/has-resource-filter-param-selections.js b/addons/core/addon/helpers/has-resource-filter-param-selections.js index 6f6015078..2768c5187 100644 --- a/addons/core/addon/helpers/has-resource-filter-param-selections.js +++ b/addons/core/addon/helpers/has-resource-filter-param-selections.js @@ -44,14 +44,14 @@ export default class HasResourceFilterParamSelectionsHelper extends Helper { /** * Returns true if the specified route has a value set for - * any resource filter. + * any resource filter passed into the helper. * @param {string} routeName + * @param {string[]} names - names of resource filter fields * @return {boolean} */ - compute([routeName]) { + compute([routeName, ...names]) { const owner = getOwner(this); const route = owner.lookup(`route:${routeName}`); - const names = route.resourceFilterParams; const selectedValues = names.map((name) => route[name] || null).flat(); const anyTruthy = selectedValues.reduce( (previousValue, currentValue) => previousValue || currentValue, diff --git a/addons/core/addon/helpers/resource-filter-param.js b/addons/core/addon/helpers/resource-filter-param.js index e78ac20a7..d777c3737 100644 --- a/addons/core/addon/helpers/resource-filter-param.js +++ b/addons/core/addon/helpers/resource-filter-param.js @@ -50,13 +50,9 @@ export default class ResourceFilterParamHelper extends Helper { */ compute([routeName, name]) { const owner = getOwner(this); - // Filter options - const route = owner.lookup(`route:${routeName}`); - const filterAllowedValuesKey = `filter-allowed-values-${name}`; - const allowedValues = route[filterAllowedValuesKey]; - // Selected filters - const rawValue = route[name]; - const selectedValue = rawValue || null; + const containerKey = `route-resource-filter:${name}@${routeName}`; + const resourceFilter = owner.lookup(containerKey); + const { allowedValues, value: selectedValue } = resourceFilter; return { name, allowedValues, selectedValue }; } diff --git a/ui/admin/app/templates/scopes/scope/auth-methods/index.hbs b/ui/admin/app/templates/scopes/scope/auth-methods/index.hbs index d6075980e..cf69c278e 100644 --- a/ui/admin/app/templates/scopes/scope/auth-methods/index.hbs +++ b/ui/admin/app/templates/scopes/scope/auth-methods/index.hbs @@ -39,7 +39,9 @@ {{#if (or @model - (has-resource-filter-param-selections 'scopes.scope.auth-methods') + (has-resource-filter-param-selections + 'scopes.scope.auth-methods' 'type' + ) ) }} @@ -74,7 +76,9 @@ {{/with}} {{#if - (has-resource-filter-param-selections 'scopes.scope.auth-methods') + (has-resource-filter-param-selections + 'scopes.scope.auth-methods' 'type' + ) }} {{else if (has-resource-filter-param-selections - 'scopes.scope.auth-methods' + 'scopes.scope.auth-methods' 'type' )}} diff --git a/ui/admin/app/templates/scopes/scope/sessions/index.hbs b/ui/admin/app/templates/scopes/scope/sessions/index.hbs index d5052b1ee..c3492de75 100644 --- a/ui/admin/app/templates/scopes/scope/sessions/index.hbs +++ b/ui/admin/app/templates/scopes/scope/sessions/index.hbs @@ -16,7 +16,8 @@ {{#if (feature-flag 'filter')}} {{#if (or - @model (has-resource-filter-param-selections 'scopes.scope.sessions') + @model + (has-resource-filter-param-selections 'scopes.scope.sessions' 'type') ) }} @@ -51,7 +52,9 @@ {{/with}} {{#if - (has-resource-filter-param-selections 'scopes.scope.sessions') + (has-resource-filter-param-selections + 'scopes.scope.sessions' 'type' + ) }} - {{else if (has-resource-filter-param-selections 'scopes.scope.sessions')}} + {{else if (has-resource-filter-param-selections + 'scopes.scope.sessions' 'type' + )}} diff --git a/ui/desktop/app/templates/scopes/scope/projects/sessions/index.hbs b/ui/desktop/app/templates/scopes/scope/projects/sessions/index.hbs index 2ebe5491b..a92fb4fe9 100644 --- a/ui/desktop/app/templates/scopes/scope/projects/sessions/index.hbs +++ b/ui/desktop/app/templates/scopes/scope/projects/sessions/index.hbs @@ -14,7 +14,7 @@ (or @model (has-resource-filter-param-selections - 'scopes.scope.projects.sessions' + 'scopes.scope.projects.sessions' 'type' ) ) }} @@ -51,7 +51,7 @@ {{#if (has-resource-filter-param-selections - 'scopes.scope.projects.sessions' + 'scopes.scope.projects.sessions' 'type' ) }} {{else if (has-resource-filter-param-selections - 'scopes.scope.projects.sessions' + 'scopes.scope.projects.sessions' 'type' )}}