mirror of
https://gitlab.com/openstapps/openstapps.git
synced 2026-02-28 03:42:11 +00:00
171 lines
5.0 KiB
TypeScript
171 lines
5.0 KiB
TypeScript
/*
|
|
* Copyright (C) 2018, 2019 StApps
|
|
* This program is free software: you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the Free
|
|
* Software Foundation, version 3.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
* more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with
|
|
* this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
import {Injectable} from '@angular/core';
|
|
import {
|
|
SCBackendAggregationConfiguration,
|
|
SCFacet,
|
|
SCFacetBucket,
|
|
SCThing,
|
|
} from '@openstapps/core';
|
|
|
|
/**
|
|
* TODO
|
|
*/
|
|
@Injectable()
|
|
export class DataFacetsProvider {
|
|
// eslint-disable-next-line no-empty, @typescript-eslint/no-empty-function
|
|
constructor() {}
|
|
|
|
/**
|
|
* Adds buckets to a map of buckets (e.g. if a buckets array is [{foo: 1}, {bar: 3}],
|
|
* its bucketsMap is {foo: 1, bar: 3}), if a field 'bar' is added to it it becomes:
|
|
* {foo: 1, bar: 4}
|
|
*
|
|
* @param bucketsMap Buckets array transformed into a map
|
|
* @param fields A field that should be added to buckets (its map)
|
|
*/
|
|
// eslint-disable-next-line class-methods-use-this
|
|
addBuckets(
|
|
bucketsMap: {[key: string]: number},
|
|
fields: string[],
|
|
): {[key: string]: number} {
|
|
for (const field of fields) {
|
|
if (typeof bucketsMap[field] !== 'undefined') {
|
|
bucketsMap[field] = bucketsMap[field] + 1;
|
|
} else {
|
|
bucketsMap[field] = 1;
|
|
}
|
|
}
|
|
|
|
return bucketsMap;
|
|
}
|
|
|
|
/**
|
|
* Converts a buckets array to a map
|
|
*
|
|
* @param buckets Buckets from a facet
|
|
*/
|
|
// eslint-disable-next-line class-methods-use-this
|
|
bucketsToMap(buckets: SCFacetBucket[]): {[key: string]: number} {
|
|
const bucketsMap: {[key: string]: number} = {};
|
|
for (const bucket of buckets) {
|
|
bucketsMap[bucket.key] = bucket.count;
|
|
}
|
|
|
|
return bucketsMap;
|
|
}
|
|
|
|
/**
|
|
* Extract facets from data items, optionally combine them with a list of existing facets
|
|
*
|
|
* @param items Items to extract facets from
|
|
* @param aggregations Aggregations configuration(s) from backend
|
|
* @param facets Existing facets to be combined with the facets from the items
|
|
*/
|
|
extractFacets(
|
|
items: SCThing[],
|
|
aggregations: SCBackendAggregationConfiguration[],
|
|
facets: SCFacet[] = [],
|
|
): SCFacet[] {
|
|
if (items.length === 0) {
|
|
if (facets.length === 0) {
|
|
return [];
|
|
}
|
|
|
|
return facets;
|
|
}
|
|
const combinedFacetsMap: {[key: string]: {[key: string]: number}} =
|
|
this.facetsToMap(facets);
|
|
for (const item of items) {
|
|
for (const aggregation of aggregations) {
|
|
let fieldValues = item[aggregation.fieldName as keyof SCThing] as
|
|
| string
|
|
| string[]
|
|
| undefined;
|
|
if (typeof fieldValues === 'undefined') {
|
|
continue;
|
|
}
|
|
if (typeof fieldValues === 'string') {
|
|
fieldValues = [fieldValues];
|
|
}
|
|
if (typeof aggregation.onlyOnTypes === 'undefined') {
|
|
combinedFacetsMap[aggregation.fieldName] = this.addBuckets(
|
|
combinedFacetsMap[aggregation.fieldName] || {},
|
|
fieldValues,
|
|
);
|
|
} else if (aggregation.onlyOnTypes.includes(item.type)) {
|
|
combinedFacetsMap[aggregation.fieldName] = this.addBuckets(
|
|
combinedFacetsMap[aggregation.fieldName] || {},
|
|
fieldValues,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
return this.mapToFacets(combinedFacetsMap);
|
|
}
|
|
|
|
/**
|
|
* Converts facets array into a map (for quicker operations with facets)
|
|
*
|
|
* @param facets Array of facets
|
|
*/
|
|
facetsToMap(facets: SCFacet[]): {[key: string]: {[key: string]: number}} {
|
|
const facetsMap: {[key: string]: {[key: string]: number}} = {};
|
|
for (const facet of facets) {
|
|
facetsMap[facet.field] = this.bucketsToMap(facet.buckets);
|
|
}
|
|
|
|
return facetsMap;
|
|
}
|
|
|
|
/**
|
|
* Converts a buckets map into buckets array (as it is inside of a facet)
|
|
*
|
|
* @param bucketsMap A map from a buckets array
|
|
*/
|
|
// eslint-disable-next-line class-methods-use-this
|
|
mapToBuckets(bucketsMap: {[key: string]: number}): SCFacetBucket[] {
|
|
const buckets: SCFacetBucket[] = [];
|
|
for (const key in bucketsMap) {
|
|
if (bucketsMap.hasOwnProperty(key)) {
|
|
const bucket: SCFacetBucket = {key: key, count: bucketsMap[key]};
|
|
buckets.push(bucket);
|
|
}
|
|
}
|
|
|
|
return buckets;
|
|
}
|
|
|
|
/**
|
|
* Converts facets map into an array of facets (as they are provided by backend)
|
|
*
|
|
* @param facetsMap A map from facets array
|
|
*/
|
|
mapToFacets(facetsMap: {[key: string]: {[key: string]: number}}): SCFacet[] {
|
|
const facets: SCFacet[] = [];
|
|
for (const key in facetsMap) {
|
|
if (facetsMap.hasOwnProperty(key)) {
|
|
const facet: SCFacet = {buckets: [], field: ''};
|
|
facet.field = key;
|
|
facet.buckets = this.mapToBuckets(facetsMap[key]);
|
|
facets.push(facet);
|
|
}
|
|
}
|
|
|
|
return facets;
|
|
}
|
|
}
|