166 lines
4.9 KiB
TypeScript
Raw Normal View History

import Component from '@ember/component';
2018-09-17 23:03:32 -07:00
import { get, set } from '@ember/object';
2019-08-31 20:51:14 -07:00
import { computed } from '@ember/object';
import { capitalize } from '@ember/string';
import { arrayMap } from 'wherehows-web/utils/array';
2018-09-17 23:03:32 -07:00
import {
ISearchFacet,
ISearchFacetOption,
IFacetsSelectionsMap,
IFacetsCounts
2019-08-31 20:51:14 -07:00
} from '@datahub/data-models/types/entity/facets';
import { task } from 'ember-concurrency';
2019-08-31 20:51:14 -07:00
import { ISearchEntityRenderProps } from '@datahub/data-models/types/entity/rendering/search-entity-render-prop';
import { DatasetPlatform } from '@datahub/metadata-types/constants/entity/dataset/platform';
import { IDataPlatform } from '@datahub/metadata-types/types/entity/dataset/platform';
import { readDataPlatforms } from '@datahub/data-models/api/dataset/platforms';
import { ETaskPromise } from '@datahub/utils/types/concurrency';
2018-09-14 16:40:45 -07:00
/**
* Container component for search facets
* It will store state related to search facets.
*/
export default class SearchFacetsContainer extends Component {
2019-08-31 20:51:14 -07:00
didInsertElement(): void {
2018-09-17 10:54:11 -07:00
this.getPlatformsTask.perform();
}
/**
* Lists data platforms available to restrict search results by source
* @type {Array<DatasetPlatform>}
* @private
*/
_sources: Array<DatasetPlatform> = [];
2018-09-14 16:40:45 -07:00
/**
* Current state of selections of facets
* EI:
* {
* source: {
* hdfs: true
* },
* fabric: {
* corp: true,
* prod: true
* }
* }
*/
2018-09-17 23:03:32 -07:00
selections!: IFacetsSelectionsMap;
2018-09-14 16:40:45 -07:00
/**
* Counts for the facets in a similar fashion of selections
*/
2018-09-17 23:03:32 -07:00
counts!: IFacetsCounts;
2018-09-14 16:40:45 -07:00
2019-08-31 20:51:14 -07:00
/**
* Fields available. We will read this to see what facets do we have available
*/
fields: Array<ISearchEntityRenderProps> = [];
2019-08-31 20:51:14 -07:00
/**
* Gets the available platforms and extracts a list of dataset sources
2019-08-31 20:51:14 -07:00
* @returns {IterableIterator<Promise<Array<IDataPlatform>>>}
* @memberof SearchFacetsContainer
*/
2019-08-31 20:51:14 -07:00
@task(function*(this: SearchFacetsContainer): IterableIterator<Promise<Array<IDataPlatform>>> {
const platforms: Array<IDataPlatform> = yield readDataPlatforms();
const getDatasetPlatform = ({ name }: IDataPlatform): DatasetPlatform => name;
const dataPlatforms = arrayMap(getDatasetPlatform)(platforms);
get(this, '_sources').setObjects(dataPlatforms);
2019-08-31 20:51:14 -07:00
})
getPlatformsTask!: ETaskPromise<Array<IDataPlatform>>;
2018-09-14 16:40:45 -07:00
/**
* I will convert a string into a facet option with counts
* @param facetValue
* @param facetName
*/
stringToFacetOption(facetValue: string): ISearchFacetOption {
return {
value: facetValue,
2019-08-31 20:51:14 -07:00
label: capitalize(facetValue),
count: 0
2018-09-14 16:40:45 -07:00
};
}
/**
* Creates a list of options with radio props for the data platforms that can be selected as a search filter
* @type {(ComputedProperty<Array<ISearchSourceOption>>}
*/
2018-09-14 16:40:45 -07:00
@computed('_sources.[]', 'counts')
2019-08-31 20:51:14 -07:00
get sources(): Array<ISearchFacetOption> {
return this._sources.map((source): ISearchFacetOption => this.stringToFacetOption(source));
}
2018-09-14 16:40:45 -07:00
/**
* Facets that are available right now.
* In the future, it should be fetched from the backend
*/
2019-08-31 20:51:14 -07:00
@computed('counts', 'fields')
2018-09-14 16:40:45 -07:00
get facets(): Array<ISearchFacet> {
2019-08-31 20:51:14 -07:00
const counts: IFacetsCounts = this.counts || {};
const facets: Array<ISearchFacet> = this.fields
2019-08-31 20:51:14 -07:00
.filterBy('showInFacets')
.map(
(field): ISearchFacet => {
const fieldCounts = counts[field.fieldName] || {};
return {
name: field.fieldName,
displayName: field.displayName,
values: Object.keys(fieldCounts)
.map(
(value): ISearchFacetOption => ({
...this.stringToFacetOption(value),
count: fieldCounts[value]
})
)
.sortBy('count')
.reverse()
};
}
)
.filter((field): boolean => field.values.length > 0);
2019-08-31 20:51:14 -07:00
return facets;
}
2018-09-14 16:40:45 -07:00
/**
* External closure action that triggers when facet changes
* @param _ Facet Selections
*/
2019-08-31 20:51:14 -07:00
onFacetsChange(_: IFacetsSelectionsMap): void {
//nothing
}
2018-09-14 16:40:45 -07:00
/**
* Internal action triggered when facet changes. It will update
* the state of selections in a redux fashion.
* @param facet The facet that changed
* @param facetValue the option of the facet that changed
*/
2019-08-31 20:51:14 -07:00
onFacetChange(facet: ISearchFacet, facetValue: ISearchFacetOption): void {
const currentFacetValues = this.selections[facet.name] || {};
2018-09-17 23:03:32 -07:00
set(this, 'selections', {
...this.selections,
[facet.name]: {
...currentFacetValues,
[facetValue.value]: !currentFacetValues[facetValue.value]
}
});
this.onFacetsChange(this.selections);
}
2018-09-14 16:40:45 -07:00
/**
* When the user clear the facet
* @param facet the facet that the user selects
*/
2019-08-31 20:51:14 -07:00
onFacetClear(facet: ISearchFacet): void {
2018-09-17 23:03:32 -07:00
set(this, 'selections', {
...this.selections,
[facet.name]: {}
});
this.onFacetsChange(this.selections);
}
}