@fleetbase/ember-ui
Version:
Fleetbase UI provides all the interface components, helpers, services and utilities for building a Fleetbase extension into the Console.
143 lines (116 loc) • 4.21 kB
JavaScript
import Component from '@glimmer/component';
import { inject as service } from '@ember/service';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { getOwner } from '@ember/application';
import { isArray } from '@ember/array';
import getUrlParam from '../utils/get-url-param';
export default class FiltersPickerComponent extends Component {
hostRouter;
router;
events;
filters = [];
get activeRouter() {
/* eslint-disable-next-line ember/no-private-routing-service */
return this.hostRouter ?? this.router ?? getOwner(this).lookup('router:main');
}
get activeFilters() {
return this.filters.filter((f) => f.isFilterActive);
}
get hasFilters() {
return this.activeFilters.length > 0;
}
constructor() {
super(...arguments);
this.#rebuildFilters(); // initial state
// Refresh whenever the route (→ query-params) changes
this._routeHandler = () => this.#rebuildFilters();
this.activeRouter?.on?.('routeDidChange', this._routeHandler);
}
willDestroy() {
super.willDestroy(...arguments);
this.activeRouter?.off?.('routeDidChange', this._routeHandler);
}
#readUrlValue(param) {
const raw = getUrlParam(param); // string | string[] | undefined
if (isArray(raw)) {
return raw.length ? raw : undefined;
}
return raw === '' ? undefined : raw;
}
#rebuildFilters(onColumn) {
const cols = this.args.columns ?? [];
this.filters = cols
.filter((c) => c.filterable)
.map((column, index) => {
const param = column.filterParam ?? column.valuePath;
const value = this.#readUrlValue(param);
const active = value != null; // null & undefined only
const filterCol = {
...column,
trueIndex: index,
param,
filterValue: value,
isFilterActive: active,
};
if (typeof onColumn === 'function') {
onColumn(filterCol, index, value);
}
return filterCol;
});
return this;
}
applyFilters() {
// Trigger filter applied event
if (this.events) {
this.events.trackEvent('ui.filter.applied', this.activeFilters);
}
if (typeof this.args.onApply === 'function') {
this.args.onApply();
}
}
updateFilterValue({ param }, value) {
if (typeof this.args.onChange === 'function') {
this.args.onChange(param, value);
}
}
clearFilterValue({ param }) {
if (typeof this.args.onFilterClear === 'function') {
this.args.onFilterClear(param);
}
}
async clearFilters(...args) {
// Trigger filter cleared event
if (this.events) {
this.events.trackEvent('ui.filter.cleared');
}
if (typeof this.args.onClear === 'function') {
this.args.onClear(...args);
}
// Build a qp bag that explicitly clears the filter params
const router = this.activeRouter;
const qp = { ...router.currentRoute.queryParams };
(this.args.columns ?? [])
.filter((c) => c.filterable)
.forEach((c) => {
const key = c.filterParam ?? c.valuePath;
// Explicitly clear them instead of deleting
if (key in qp) {
qp[key] = null; // will remove from URL if default is null
}
const arrayKey = `${key}[]`;
if (arrayKey in qp) {
qp[arrayKey] = null;
}
});
try {
await router.transitionTo(router.currentRouteName, {
queryParams: qp,
});
} catch (error) {
if (error?.name !== 'TransitionAborted') {
throw error;
}
}
}
}