120 lines
3.5 KiB
JavaScript
120 lines
3.5 KiB
JavaScript
import Component from '@glimmer/component';
|
|
import { inject as service } from '@ember/service';
|
|
import { computed, get, action } from '@ember/object';
|
|
import { alias } from '@ember/object/computed';
|
|
import { tracked } from '@glimmer/tracking';
|
|
import { sort } from '@ember/object/computed';
|
|
import { defineProperty } from '@ember/object';
|
|
|
|
export default class DataCollectionComponent extends Component {
|
|
@service('filter') filter;
|
|
@service('sort') sort;
|
|
@service('search') searchService;
|
|
|
|
@tracked term = '';
|
|
|
|
@alias('searchService.searchables') searchableMap;
|
|
|
|
get type() {
|
|
return this.args.type;
|
|
}
|
|
|
|
get searchMethod() {
|
|
return this.args.searchable || 'exact';
|
|
}
|
|
|
|
get searchProperties() {
|
|
return this.args.filters.searchproperties;
|
|
}
|
|
|
|
@computed('term', 'args.search')
|
|
get searchTerm() {
|
|
return this.term || this.args.search || '';
|
|
}
|
|
|
|
@computed('type', 'searchMethod', 'filtered', 'args.filters')
|
|
get searchable() {
|
|
const searchproperties =
|
|
get(this, 'args.filters.searchproperty.value') || get(this, 'args.filters.searchproperty');
|
|
const Searchable =
|
|
typeof this.searchMethod === 'string'
|
|
? this.searchableMap[this.searchMethod]
|
|
: this.args.searchable;
|
|
|
|
return new Searchable(this.filtered, {
|
|
finders: Object.fromEntries(
|
|
Object.entries(this.searchService.predicate(this.type)).filter(([key, value]) => {
|
|
return typeof searchproperties === 'undefined' ? true : searchproperties.includes(key);
|
|
})
|
|
),
|
|
});
|
|
}
|
|
|
|
@computed('type', 'args.sort')
|
|
get comparator() {
|
|
if (typeof this.args.sort === 'undefined') {
|
|
return [];
|
|
}
|
|
return this.sort.comparator(this.type)(this.args.sort);
|
|
}
|
|
|
|
@computed('comparator', 'searched')
|
|
get items() {
|
|
// the ember sort computed accepts either:
|
|
// 1. The name of a property (as a string) returning an array properties to sort by
|
|
// 2. A function to use for sorting
|
|
let comparator = 'comparator';
|
|
if (typeof this.comparator === 'function') {
|
|
comparator = this.comparator;
|
|
}
|
|
defineProperty(this, 'sorted', sort('searched', comparator));
|
|
return this.sorted;
|
|
}
|
|
|
|
@computed('searchTerm', 'searchable', 'filtered')
|
|
get searched() {
|
|
if (this.searchTerm === '') {
|
|
return this.filtered;
|
|
}
|
|
return this.searchable.search(this.searchTerm);
|
|
}
|
|
|
|
@computed('type', 'content', 'args.filters')
|
|
get filtered() {
|
|
// if we don't filter, return a copy of the content so we end up with what
|
|
// filter will return when filtering ED recordsets
|
|
if (typeof this.args.filters === 'undefined') {
|
|
return this.content.slice();
|
|
}
|
|
const predicate = this.filter.predicate(this.type);
|
|
if (typeof predicate === 'undefined') {
|
|
return this.content.slice();
|
|
}
|
|
const filters = Object.entries(this.args.filters)
|
|
.filter(([key, value]) => Boolean(value))
|
|
.map(([key, value]) => {
|
|
const val = typeof value !== 'string' ? value.value : value;
|
|
return [key, val];
|
|
});
|
|
return this.content.filter(predicate(Object.fromEntries(filters)));
|
|
}
|
|
|
|
@computed('args.{items.[],items.content.[]}')
|
|
get content() {
|
|
// TODO: Temporary little hack to ensure we detect DataSource proxy
|
|
// objects but not any other special Ember Proxy object like ember-data
|
|
// things. Remove this once we no longer need the Proxies
|
|
const items = this.args.items || [];
|
|
if (typeof items.dispatchEvent === 'function') {
|
|
return items.content;
|
|
}
|
|
return items;
|
|
}
|
|
|
|
@action
|
|
search(term) {
|
|
this.term = term;
|
|
return this.items;
|
|
}
|
|
}
|