mirror of
https://gitlab.com/openstapps/openstapps.git
synced 2026-02-28 03:42:11 +00:00
152
src/app/modules/data/data-facets.provider.ts
Normal file
152
src/app/modules/data/data-facets.provider.ts
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* 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, SCThing} from '@openstapps/core';
|
||||
|
||||
@Injectable()
|
||||
export class DataFacetsProvider {
|
||||
// tslint:disable-next-line:no-empty
|
||||
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)
|
||||
*/
|
||||
addBuckets(bucketsMap: {[key: string]: number}, fields: string[]): {[key: string]: number} {
|
||||
fields.forEach((field) => {
|
||||
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
|
||||
*/
|
||||
bucketsToMap(buckets: Array<{[key: string]: number}>): {[key: string]: number} {
|
||||
const bucketsMap: {[key: string]: number} = {};
|
||||
buckets.forEach((bucket) => {
|
||||
for (const key in bucket) {
|
||||
if (bucket.hasOwnProperty(key)) {
|
||||
bucketsMap[key] = bucket[key];
|
||||
}
|
||||
}
|
||||
});
|
||||
return bucketsMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a buckets map into buckets array (as it is inside of a facet)
|
||||
*
|
||||
* @param bucketsMap A map from a buckets array
|
||||
*/
|
||||
mapToBuckets(bucketsMap: {[key: string]: number}): Array<{[key: string]: number}> {
|
||||
const buckets: Array<{[key: string]: number}> = [];
|
||||
for (const key in bucketsMap) {
|
||||
if (bucketsMap.hasOwnProperty(key)) {
|
||||
const bucket: {[key: string]: number} = {};
|
||||
bucket[key] = bucketsMap[key];
|
||||
buckets.push(bucket);
|
||||
}
|
||||
}
|
||||
return buckets;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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}} = {};
|
||||
facets.forEach((facet) => {
|
||||
facetsMap[facet.field] = this.bucketsToMap(facet.buckets);
|
||||
});
|
||||
return facetsMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 [];
|
||||
} else {
|
||||
return facets;
|
||||
}
|
||||
}
|
||||
const combinedFacets: SCFacet[] = facets;
|
||||
const combinedFacetsMap: {[key: string]: {[key: string]: number}} = this.facetsToMap(combinedFacets);
|
||||
(items as any[]).forEach((item) => {
|
||||
aggregations.forEach((aggregation) => {
|
||||
let fieldValues: string | string[] = item[aggregation.fieldName];
|
||||
if (typeof fieldValues === 'undefined') {
|
||||
return;
|
||||
}
|
||||
if (typeof fieldValues === 'string') {
|
||||
fieldValues = [fieldValues];
|
||||
}
|
||||
if (typeof aggregation.onlyOnTypes === 'undefined') {
|
||||
combinedFacetsMap[aggregation.fieldName] = this.addBuckets(
|
||||
combinedFacetsMap[aggregation.fieldName] || {},
|
||||
fieldValues,
|
||||
);
|
||||
} else if (aggregation.onlyOnTypes.indexOf(item.type) !== -1) {
|
||||
combinedFacetsMap[aggregation.fieldName] = this.addBuckets(
|
||||
combinedFacetsMap[aggregation.fieldName] || {},
|
||||
fieldValues,
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
return this.mapToFacets(combinedFacetsMap);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user