@provoly/dashboard 0.15.8 → 0.15.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2022/admin/components/admin-classes/admin-classes-customize/tooltip/admin-classes-customize-tooltip.component.mjs +7 -6
- package/esm2022/admin/components/admin-classes/admin-classes-form/admin-classes-form.component.mjs +5 -4
- package/esm2022/admin/components/admin-classes/admin-classes-view/admin-attributes-form/admin-attributes-form.component.mjs +3 -3
- package/esm2022/admin/components/admin-dataset/shared/admin-form-dataset/admin-form-dataset.component.mjs +2 -2
- package/esm2022/admin/i18n/fr.translations.mjs +2 -2
- package/esm2022/dataset/i18n/fr.translations.mjs +2 -2
- package/esm2022/filters/date/date-filter.component.mjs +3 -3
- package/esm2022/lib/core/auth/geoAuth.service.mjs +8 -15
- package/esm2022/lib/core/components/modal-status/modal-status.component.mjs +2 -2
- package/esm2022/lib/core/model/dataset.interface.mjs +1 -1
- package/esm2022/lib/core/model/filter.interface.mjs +1 -1
- package/esm2022/lib/core/model/widget-map-manifest.interface.mjs +1 -1
- package/esm2022/lib/core/public-api.mjs +2 -2
- package/esm2022/lib/core/store/aggregation/frontend-aggregation/aggregation-utils.class.mjs +184 -0
- package/esm2022/lib/core/store/aggregation/frontend-aggregation/frontend-aggregation.service.mjs +93 -0
- package/esm2022/lib/dashboard/store/dashboard.selectors.mjs +2 -2
- package/esm2022/presentation/components/presentation.component.mjs +3 -3
- package/esm2022/presentation/i18n/en.translations.mjs +3 -2
- package/esm2022/presentation/i18n/fr.translations.mjs +6 -5
- package/esm2022/presentation/style/css.component.mjs +2 -2
- package/esm2022/restitution/i18n/fr.translations.mjs +2 -2
- package/esm2022/restitution/style/css.component.mjs +2 -2
- package/esm2022/tooltips/attribute/attribute-tooltip.component.mjs +19 -10
- package/esm2022/widgets/widget-map/component/widget-map.component.mjs +18 -11
- package/esm2022/widgets/widget-map/utils/widget-map.utils.mjs +36 -1
- package/esm2022/widgets/widget-table/component/widget-table.component.mjs +3 -3
- package/fesm2022/provoly-dashboard-admin.mjs +14 -12
- package/fesm2022/provoly-dashboard-admin.mjs.map +1 -1
- package/fesm2022/provoly-dashboard-dataset.mjs +1 -1
- package/fesm2022/provoly-dashboard-dataset.mjs.map +1 -1
- package/fesm2022/provoly-dashboard-filters-date.mjs +2 -2
- package/fesm2022/provoly-dashboard-filters-date.mjs.map +1 -1
- package/fesm2022/provoly-dashboard-presentation.mjs +11 -9
- package/fesm2022/provoly-dashboard-presentation.mjs.map +1 -1
- package/fesm2022/provoly-dashboard-restitution.mjs +3 -3
- package/fesm2022/provoly-dashboard-restitution.mjs.map +1 -1
- package/fesm2022/provoly-dashboard-tooltips-attribute.mjs +18 -9
- package/fesm2022/provoly-dashboard-tooltips-attribute.mjs.map +1 -1
- package/fesm2022/provoly-dashboard-widgets-widget-map.mjs +52 -10
- package/fesm2022/provoly-dashboard-widgets-widget-map.mjs.map +1 -1
- package/fesm2022/provoly-dashboard-widgets-widget-table.mjs +2 -2
- package/fesm2022/provoly-dashboard-widgets-widget-table.mjs.map +1 -1
- package/fesm2022/provoly-dashboard.mjs +237 -179
- package/fesm2022/provoly-dashboard.mjs.map +1 -1
- package/lib/core/auth/geoAuth.service.d.ts +3 -1
- package/lib/core/model/dataset.interface.d.ts +1 -1
- package/lib/core/model/filter.interface.d.ts +1 -1
- package/lib/core/model/widget-map-manifest.interface.d.ts +1 -0
- package/lib/core/public-api.d.ts +1 -1
- package/lib/core/store/aggregation/frontend-aggregation/aggregation-utils.class.d.ts +33 -0
- package/lib/core/store/aggregation/frontend-aggregation/frontend-aggregation.service.d.ts +22 -0
- package/lib/dashboard/store/dashboard.selectors.d.ts +1 -1
- package/package.json +30 -30
- package/presentation/i18n/en.translations.d.ts +1 -0
- package/presentation/i18n/fr.translations.d.ts +1 -0
- package/presentation/style/_o-pry-presentation.scss +7 -2
- package/tooltips/attribute/attribute-tooltip.component.d.ts +5 -1
- package/widgets/widget-map/component/widget-map.component.d.ts +3 -4
- package/widgets/widget-map/utils/widget-map.utils.d.ts +1 -0
- package/esm2022/lib/core/store/aggregation/frontend-aggregation.service.mjs +0 -210
- package/lib/core/store/aggregation/frontend-aggregation.service.d.ts +0 -33
|
@@ -2264,7 +2264,7 @@ const frTranslations = {
|
|
|
2264
2264
|
WARNING: 'Warning'
|
|
2265
2265
|
},
|
|
2266
2266
|
code: {
|
|
2267
|
-
UNRECOGNIZED: 'Attribut{{plural}} {{name}} non reconnu{{plural}}',
|
|
2267
|
+
UNRECOGNIZED: 'Attribut {{plural}} {{name}} non reconnu {{plural}}',
|
|
2268
2268
|
FORMAT: "Format d'attribut {{name}} incorrect",
|
|
2269
2269
|
STORAGE: "Erreur d'insertion pour l'élément {{recordId}}",
|
|
2270
2270
|
NO_VALUES: 'Pas de valeur pour la ligne {{recordId}}',
|
|
@@ -2573,7 +2573,7 @@ class PryModalStatusComponent {
|
|
|
2573
2573
|
.flat()
|
|
2574
2574
|
.map((preview) => ({
|
|
2575
2575
|
...preview,
|
|
2576
|
-
name: preview.name.split(',').join(', ')
|
|
2576
|
+
name: (preview.name ?? '').split(',').join(', ')
|
|
2577
2577
|
}))));
|
|
2578
2578
|
this.messageCount$ = this.store.select(DataSourceSelectors.datasetPreviews).pipe(map((previews) => {
|
|
2579
2579
|
return previews.map((preview) => preview.count).reduce((p, c) => p + c, 0);
|
|
@@ -3856,7 +3856,7 @@ const namedQueriesUses = createSelector(globalManifest, (manifest) => manifest.w
|
|
|
3856
3856
|
const presentation = createSelector(feature$4, (state) => state?.presentation);
|
|
3857
3857
|
const isCurrentPresentationModified = createSelector(presentation, globalManifest, (state, global) => !equal(global, state.initial));
|
|
3858
3858
|
const isCurrentPresentationOwner = createSelector(presentation, (state) => !!state.current && state.current.owner);
|
|
3859
|
-
const filters = createSelector(feature$4, (state) => state?.manifests.manifest.filters ??
|
|
3859
|
+
const filters = createSelector(feature$4, (state) => state?.manifests.manifest.filters ?? []);
|
|
3860
3860
|
const datasourceFilters = createSelector(feature$4, (state) => state?.manifests.manifest.filters
|
|
3861
3861
|
? state?.manifests.manifest.filters.reduce((obj, filter) => (filter.attributes.forEach((attribute) => (obj[attribute.datasource] || (obj[attribute.datasource] = [])).push({
|
|
3862
3862
|
attribute: attribute.id,
|
|
@@ -4884,29 +4884,21 @@ class PryGeoAuthService {
|
|
|
4884
4884
|
}
|
|
4885
4885
|
const PRY_GEOAUTH_TOKEN = new InjectionToken('PRY_GEOAUTH_TOKEN');
|
|
4886
4886
|
class PryDefaultGeoAuthService extends PryGeoAuthService {
|
|
4887
|
-
constructor() {
|
|
4887
|
+
constructor(httpClient) {
|
|
4888
4888
|
super();
|
|
4889
|
+
this.httpClient = httpClient;
|
|
4889
4890
|
}
|
|
4890
4891
|
customLoader(tile, src) {
|
|
4891
|
-
|
|
4892
|
-
|
|
4893
|
-
xhr.addEventListener('loadend', function (evt) {
|
|
4894
|
-
const data = this.response;
|
|
4895
|
-
if (data !== undefined) {
|
|
4896
|
-
tile.getImage().src = URL.createObjectURL(data);
|
|
4897
|
-
}
|
|
4892
|
+
this.httpClient.get(src, { observe: 'response', params: {}, responseType: 'blob' }).subscribe((blob) => {
|
|
4893
|
+
tile.getImage().src = URL.createObjectURL(blob.body);
|
|
4898
4894
|
});
|
|
4899
|
-
xhr.open('GET', src);
|
|
4900
|
-
// Exemple of how to pass authentification header
|
|
4901
|
-
// client.setRequestHeader('Authorization', 'Basic ' + window.btoa('user:pass'));
|
|
4902
|
-
xhr.send();
|
|
4903
4895
|
}
|
|
4904
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.6", ngImport: i0, type: PryDefaultGeoAuthService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4896
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.6", ngImport: i0, type: PryDefaultGeoAuthService, deps: [{ token: i1$2.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4905
4897
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.1.6", ngImport: i0, type: PryDefaultGeoAuthService }); }
|
|
4906
4898
|
}
|
|
4907
4899
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.6", ngImport: i0, type: PryDefaultGeoAuthService, decorators: [{
|
|
4908
4900
|
type: Injectable
|
|
4909
|
-
}], ctorParameters: function () { return []; } });
|
|
4901
|
+
}], ctorParameters: function () { return [{ type: i1$2.HttpClient }]; } });
|
|
4910
4902
|
|
|
4911
4903
|
const SELECTORS = [
|
|
4912
4904
|
TranslateIdPipe,
|
|
@@ -5293,195 +5285,261 @@ class ResultsetUtils {
|
|
|
5293
5285
|
}
|
|
5294
5286
|
}
|
|
5295
5287
|
|
|
5296
|
-
class
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
|
|
5288
|
+
class AggregationUtils {
|
|
5289
|
+
static getAxisAttribute(classes, options, axis) {
|
|
5290
|
+
return classes
|
|
5291
|
+
.map((clazz) => clazz.attributes.find((attr) => attr.id === options[axis].attribute))
|
|
5292
|
+
.find((attr) => !!attr)?.name;
|
|
5300
5293
|
}
|
|
5301
|
-
|
|
5302
|
-
|
|
5303
|
-
|
|
5304
|
-
|
|
5305
|
-
|
|
5306
|
-
|
|
5307
|
-
|
|
5308
|
-
|
|
5309
|
-
|
|
5310
|
-
const ordinate = classes
|
|
5311
|
-
.map((clazz) => clazz.attributes.find((attr) => attr.id === options.ordinate.attribute))
|
|
5312
|
-
.find((attr) => !!attr)?.name;
|
|
5313
|
-
if (!abscissa || !ordinate) {
|
|
5314
|
-
throw new Error('abscissaorodinateinvalid');
|
|
5315
|
-
}
|
|
5316
|
-
let data = datasource.map((rsName) => resultSets[rsName ?? '']).filter((rsName) => !!rsName);
|
|
5317
|
-
const resultSet = data.reduce((rs1, rs2) => ResultsetUtils.mergeResultSets(rs1, rs2), {
|
|
5318
|
-
items: {},
|
|
5319
|
-
relations: [],
|
|
5320
|
-
merged: data.length
|
|
5321
|
-
});
|
|
5322
|
-
let items = Object.keys(resultSet.items)
|
|
5323
|
-
.map((classId) => resultSet.items[classId])
|
|
5324
|
-
.reduce((prev, curr) => [...prev, ...curr], []);
|
|
5325
|
-
if (!!options.groupBy) {
|
|
5326
|
-
const groupBy = classes
|
|
5327
|
-
.map((clazz) => clazz.attributes.find((attr) => attr.id === options.groupBy?.attribute))
|
|
5328
|
-
.find((attr) => !!attr)?.name;
|
|
5329
|
-
if (!groupBy) {
|
|
5330
|
-
throw new Error('groupByAttributeisinvalid');
|
|
5331
|
-
}
|
|
5332
|
-
const itemsGrouped = this.groupBy(items, groupBy);
|
|
5333
|
-
const values = [];
|
|
5334
|
-
Object.keys(itemsGrouped).forEach((key) => {
|
|
5335
|
-
values.push({
|
|
5336
|
-
key,
|
|
5337
|
-
groupBy: this.getValueFromOperation(itemsGrouped[key], options.ordinate.operation, abscissa, ordinate, options.abscissa.limit)
|
|
5338
|
-
});
|
|
5339
|
-
});
|
|
5340
|
-
return { operation: options.ordinate.operation, values: values };
|
|
5341
|
-
}
|
|
5342
|
-
const values = this.getValueFromOperation(items, options.ordinate.operation, abscissa, ordinate, options.abscissa.limit);
|
|
5343
|
-
return { operation: options.ordinate.operation, values: values };
|
|
5344
|
-
}));
|
|
5294
|
+
static getChartDatasourceResultSet(datasources, resultSets) {
|
|
5295
|
+
return datasources
|
|
5296
|
+
.filter((rsName) => rsName in resultSets)
|
|
5297
|
+
.map((rsName) => resultSets[rsName])
|
|
5298
|
+
.reduce((rs1, rs2) => ResultsetUtils.mergeResultSets(rs1, rs2), {
|
|
5299
|
+
items: {},
|
|
5300
|
+
relations: [],
|
|
5301
|
+
merged: datasources.filter((rsName) => rsName in resultSets).length
|
|
5302
|
+
});
|
|
5345
5303
|
}
|
|
5346
|
-
|
|
5347
|
-
|
|
5348
|
-
|
|
5349
|
-
|
|
5304
|
+
static getAggregatedValue(operation, groupedItems, abscissaAttribute, ordinateAttribute) {
|
|
5305
|
+
return this.getAggregatedValueForOperation(operation, groupedItems[abscissaAttribute].map((item) => this.getValueFromAttribute(item, ordinateAttribute).value));
|
|
5306
|
+
}
|
|
5307
|
+
static getValueFromAttribute(item, attribute) {
|
|
5308
|
+
let value = ItemUtils.getAttributeValue(item, attribute);
|
|
5309
|
+
return Array.isArray(value) ? value[0] : value;
|
|
5310
|
+
}
|
|
5311
|
+
static getAggregatedValueForOperation(operation, values) {
|
|
5350
5312
|
switch (operation) {
|
|
5351
5313
|
case Operation.COUNT:
|
|
5352
|
-
|
|
5353
|
-
key: key,
|
|
5354
|
-
value: groupByAbscissa[key].length
|
|
5355
|
-
})));
|
|
5356
|
-
break;
|
|
5314
|
+
return values.length;
|
|
5357
5315
|
case Operation.SUM:
|
|
5358
|
-
|
|
5359
|
-
key: key,
|
|
5360
|
-
value: this.getSum(groupByAbscissa[key], ordinate)
|
|
5361
|
-
})));
|
|
5362
|
-
break;
|
|
5316
|
+
return values.reduce((acc, val) => acc + val, 0);
|
|
5363
5317
|
case Operation.DISTINCT:
|
|
5364
|
-
|
|
5365
|
-
key: key,
|
|
5366
|
-
value: this.getDistinct(groupByAbscissa[key], ordinate)
|
|
5367
|
-
})));
|
|
5368
|
-
break;
|
|
5318
|
+
return [...new Set(values)].length;
|
|
5369
5319
|
case Operation.AVERAGE:
|
|
5370
|
-
|
|
5371
|
-
key: key,
|
|
5372
|
-
value: this.getAverage(groupByAbscissa[key], ordinate)
|
|
5373
|
-
})));
|
|
5374
|
-
break;
|
|
5320
|
+
return values.reduce((acc, val) => acc + val, 0) / values.length;
|
|
5375
5321
|
case Operation.MEDIAN:
|
|
5376
|
-
|
|
5377
|
-
key: key,
|
|
5378
|
-
value: this.getQuartile(groupByAbscissa[key], ordinate, 0.5)
|
|
5379
|
-
})));
|
|
5380
|
-
break;
|
|
5322
|
+
return this.getQuartile(values, 0.5);
|
|
5381
5323
|
case Operation.Q1:
|
|
5382
|
-
|
|
5383
|
-
key: key,
|
|
5384
|
-
value: this.getQuartile(groupByAbscissa[key], ordinate, 0.25)
|
|
5385
|
-
})));
|
|
5386
|
-
break;
|
|
5324
|
+
return this.getQuartile(values, 0.25);
|
|
5387
5325
|
case Operation.Q3:
|
|
5388
|
-
|
|
5389
|
-
key: key,
|
|
5390
|
-
value: this.getQuartile(groupByAbscissa[key], ordinate, 0.75)
|
|
5391
|
-
})));
|
|
5392
|
-
break;
|
|
5326
|
+
return this.getQuartile(values, 0.75);
|
|
5393
5327
|
case Operation.MIN:
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
})));
|
|
5398
|
-
break;
|
|
5328
|
+
return Math.min(...values);
|
|
5329
|
+
case Operation.MAX:
|
|
5330
|
+
return Math.max(...values);
|
|
5399
5331
|
default:
|
|
5400
|
-
|
|
5401
|
-
key: key,
|
|
5402
|
-
value: this.getMax(groupByAbscissa[key], ordinate)
|
|
5403
|
-
})));
|
|
5404
|
-
break;
|
|
5332
|
+
return -1;
|
|
5405
5333
|
}
|
|
5406
|
-
|
|
5407
|
-
|
|
5334
|
+
}
|
|
5335
|
+
static getQuartile(values, q) {
|
|
5336
|
+
if (values.length === 0)
|
|
5337
|
+
return 0;
|
|
5338
|
+
values.sort((a, b) => a - b);
|
|
5339
|
+
let pos = (values.length - 1) * q;
|
|
5340
|
+
if (pos % 1 === 0) {
|
|
5341
|
+
return values[pos];
|
|
5408
5342
|
}
|
|
5409
|
-
|
|
5343
|
+
pos = Math.floor(pos);
|
|
5344
|
+
return values[pos + 1] !== undefined ? (values[pos] + values[pos + 1]) / 2 : values[pos];
|
|
5410
5345
|
}
|
|
5411
|
-
|
|
5412
|
-
|
|
5413
|
-
|
|
5414
|
-
|
|
5415
|
-
|
|
5416
|
-
|
|
5346
|
+
static formatByLimit(data, limit, operation) {
|
|
5347
|
+
if (!limit.isTimeLimit) {
|
|
5348
|
+
data
|
|
5349
|
+
.sort((a, b) => (limit.order === 'asc' ? (a.value > b.value ? 1 : -1) : a.value < b.value ? 1 : -1))
|
|
5350
|
+
.splice(limit.at);
|
|
5351
|
+
return data;
|
|
5352
|
+
}
|
|
5353
|
+
return this.formatDataByTimeLimit(data, limit, operation);
|
|
5354
|
+
}
|
|
5355
|
+
static formatDataByTimeLimit(data, limit, operation) {
|
|
5356
|
+
let distinctValues = [];
|
|
5357
|
+
data
|
|
5358
|
+
.map((obj) => ({ ...obj, key: this.getKeyValueForTimeInterval(obj.key, limit.interval) }))
|
|
5359
|
+
.forEach((obj) => {
|
|
5360
|
+
const isNotDistinct = distinctValues.find((distinct) => obj.key === distinct.key);
|
|
5361
|
+
if (!!isNotDistinct) {
|
|
5362
|
+
isNotDistinct.values.push(obj.value);
|
|
5417
5363
|
}
|
|
5418
5364
|
else {
|
|
5419
|
-
|
|
5365
|
+
distinctValues.push({ key: obj.key, values: [] });
|
|
5420
5366
|
}
|
|
5421
5367
|
});
|
|
5422
|
-
return
|
|
5423
|
-
|
|
5424
|
-
|
|
5425
|
-
|
|
5426
|
-
return Array.isArray(value) ? value[0] : value;
|
|
5427
|
-
}
|
|
5428
|
-
getSum(items, attribute) {
|
|
5429
|
-
let sum = 0;
|
|
5430
|
-
items.forEach((item) => {
|
|
5431
|
-
sum += this.getValueFromAttribute(item, attribute).value;
|
|
5432
|
-
});
|
|
5433
|
-
return sum;
|
|
5368
|
+
return distinctValues.map((obj) => ({
|
|
5369
|
+
...obj,
|
|
5370
|
+
value: AggregationUtils.getAggregatedValueForOperation(operation, obj.values)
|
|
5371
|
+
}));
|
|
5434
5372
|
}
|
|
5435
|
-
|
|
5436
|
-
const
|
|
5437
|
-
|
|
5438
|
-
|
|
5439
|
-
|
|
5440
|
-
|
|
5441
|
-
|
|
5373
|
+
static getKeyValueForTimeInterval(key, interval) {
|
|
5374
|
+
const date = new Date(key);
|
|
5375
|
+
switch (interval) {
|
|
5376
|
+
case 'second':
|
|
5377
|
+
return new Date(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds()).toISOString();
|
|
5378
|
+
case 'minute':
|
|
5379
|
+
return new Date(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes()).toISOString();
|
|
5380
|
+
case 'hour':
|
|
5381
|
+
return new Date(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours()).toISOString();
|
|
5382
|
+
case 'day':
|
|
5383
|
+
return new Date(date.getFullYear(), date.getMonth(), date.getDate()).toISOString();
|
|
5384
|
+
case 'week':
|
|
5385
|
+
const daysToSubtract = (7 + date.getUTCDay()) % 7;
|
|
5386
|
+
date.setUTCDate(date.getUTCDate() - daysToSubtract);
|
|
5387
|
+
return date.toISOString();
|
|
5388
|
+
case 'quarter':
|
|
5389
|
+
const quarterStartMonths = [0, 3, 6, 9]; // January, April, July, October
|
|
5390
|
+
const quarter = Math.floor(date.getUTCMonth() / 3);
|
|
5391
|
+
const year = date.getUTCFullYear();
|
|
5392
|
+
const startOfQuarter = new Date(Date.UTC(year, quarterStartMonths[quarter], 1, 0, 0, 0, 0));
|
|
5393
|
+
return startOfQuarter.toISOString();
|
|
5394
|
+
case 'year':
|
|
5395
|
+
return new Date(new Date(key).getFullYear(), 0, 1).toISOString();
|
|
5396
|
+
default:
|
|
5397
|
+
return date.toISOString();
|
|
5398
|
+
}
|
|
5442
5399
|
}
|
|
5443
|
-
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
|
|
5447
|
-
|
|
5448
|
-
|
|
5449
|
-
|
|
5400
|
+
static filterItems(items, filters) {
|
|
5401
|
+
let filtersByAttribute = filters
|
|
5402
|
+
.map((filter) => filter.attributes.map((attribute) => ({
|
|
5403
|
+
...filter,
|
|
5404
|
+
attribute: attribute.id,
|
|
5405
|
+
attributes: undefined
|
|
5406
|
+
})))
|
|
5407
|
+
.flat();
|
|
5408
|
+
return filters.length > 0
|
|
5409
|
+
? [
|
|
5410
|
+
...new Set(filtersByAttribute
|
|
5411
|
+
.map((filter) => items.filter((item) => this.doesItemValuePassFilter(item, filter.attribute, filter.operator, filter.value)))
|
|
5412
|
+
.flat())
|
|
5413
|
+
]
|
|
5414
|
+
: items;
|
|
5415
|
+
}
|
|
5416
|
+
static doesItemValuePassFilter(item, attribute, operator, filterValue) {
|
|
5417
|
+
let value = AggregationUtils.getValueFromAttribute(item, attribute)?.value;
|
|
5418
|
+
let date1, date2;
|
|
5419
|
+
console.log(operator);
|
|
5420
|
+
switch (operator) {
|
|
5421
|
+
case 'EQUALS':
|
|
5422
|
+
return value === filterValue;
|
|
5423
|
+
case 'NOT_EQUALS':
|
|
5424
|
+
return value !== filterValue;
|
|
5425
|
+
case 'CONTAINS':
|
|
5426
|
+
return value.includes(filterValue);
|
|
5427
|
+
case 'START_WITH':
|
|
5428
|
+
return value.startsWith(filterValue);
|
|
5429
|
+
case 'END_WITH':
|
|
5430
|
+
return value.endsWith(filterValue);
|
|
5431
|
+
case 'GREATER_THAN':
|
|
5432
|
+
if (typeof filterValue === 'number') {
|
|
5433
|
+
return value > filterValue;
|
|
5434
|
+
}
|
|
5435
|
+
else if (typeof filterValue === 'string') {
|
|
5436
|
+
return new Date(value) > new Date(filterValue);
|
|
5437
|
+
}
|
|
5438
|
+
else {
|
|
5439
|
+
return false;
|
|
5440
|
+
}
|
|
5441
|
+
case 'LOWER_THAN':
|
|
5442
|
+
if (typeof filterValue === 'number') {
|
|
5443
|
+
return value < filterValue;
|
|
5444
|
+
}
|
|
5445
|
+
else if (typeof filterValue === 'string') {
|
|
5446
|
+
return new Date(value) < new Date(filterValue);
|
|
5447
|
+
}
|
|
5448
|
+
else {
|
|
5449
|
+
return false;
|
|
5450
|
+
}
|
|
5451
|
+
case 'INSIDE':
|
|
5452
|
+
[date1, date2] = [
|
|
5453
|
+
new Date(filterValue.split(',')[0]),
|
|
5454
|
+
new Date(filterValue.split(',')[1])
|
|
5455
|
+
];
|
|
5456
|
+
return new Date(value) > new Date(date1) && new Date(value) < new Date(date2);
|
|
5457
|
+
case 'OUTSIDE':
|
|
5458
|
+
[date1, date2] = [
|
|
5459
|
+
new Date(filterValue.split(',')[0]),
|
|
5460
|
+
new Date(filterValue.split(',')[1])
|
|
5461
|
+
];
|
|
5462
|
+
return new Date(value) < new Date(date1) && new Date(value) > new Date(date2);
|
|
5463
|
+
default:
|
|
5464
|
+
return true;
|
|
5465
|
+
}
|
|
5450
5466
|
}
|
|
5451
|
-
|
|
5452
|
-
|
|
5453
|
-
|
|
5467
|
+
}
|
|
5468
|
+
|
|
5469
|
+
class PryFrontendAggregationService extends PryAggregationService {
|
|
5470
|
+
constructor(store) {
|
|
5471
|
+
super();
|
|
5472
|
+
this.store = store;
|
|
5454
5473
|
}
|
|
5455
|
-
|
|
5456
|
-
return [
|
|
5474
|
+
aggregate(datasources, options) {
|
|
5475
|
+
return combineLatest([
|
|
5476
|
+
this.store.select(DashboardSelectors.resultSets),
|
|
5477
|
+
this.store.select(ClassSelectors.classes),
|
|
5478
|
+
this.store.select(DashboardSelectors.filters)
|
|
5479
|
+
]).pipe(map(([resultSets, classes, filters]) => {
|
|
5480
|
+
const resultSet = AggregationUtils.getChartDatasourceResultSet(datasources, resultSets);
|
|
5481
|
+
let items = Object.keys(resultSet.items)
|
|
5482
|
+
.map((classId) => resultSet.items[classId])
|
|
5483
|
+
.reduce((prev, curr) => [...prev, ...curr], []);
|
|
5484
|
+
items = AggregationUtils.filterItems(items, filters);
|
|
5485
|
+
return this.getAggregationResult(options, classes, items);
|
|
5486
|
+
}));
|
|
5457
5487
|
}
|
|
5458
|
-
|
|
5459
|
-
const
|
|
5460
|
-
|
|
5461
|
-
|
|
5462
|
-
|
|
5463
|
-
|
|
5488
|
+
getAggregationResult(options, classes, items) {
|
|
5489
|
+
const [abscissa, ordinate] = [
|
|
5490
|
+
AggregationUtils.getAxisAttribute(classes, options, 'abscissa') ?? '',
|
|
5491
|
+
AggregationUtils.getAxisAttribute(classes, options, 'ordinate') ?? ''
|
|
5492
|
+
];
|
|
5493
|
+
const aggregationResult = {
|
|
5494
|
+
operation: options.ordinate.operation,
|
|
5495
|
+
values: []
|
|
5496
|
+
};
|
|
5497
|
+
if (!options.groupBy) {
|
|
5498
|
+
if (!!options.ordinate.operation)
|
|
5499
|
+
console.warn('no ordinate operation selected');
|
|
5500
|
+
aggregationResult.values = this.getChartDataBasedOnOperation(items, options.ordinate.operation, abscissa, ordinate, options.abscissa.limit);
|
|
5501
|
+
console.log(aggregationResult.values);
|
|
5464
5502
|
}
|
|
5465
|
-
|
|
5466
|
-
|
|
5467
|
-
|
|
5503
|
+
else {
|
|
5504
|
+
const groupByAttribute = classes
|
|
5505
|
+
.map((clazz) => clazz.attributes.find((attr) => attr.id === options.groupBy?.attribute))
|
|
5506
|
+
.find((attr) => !!attr)?.name ?? '';
|
|
5507
|
+
const itemsGrouped = this.getItemsGroupedByAttributeValue(items, groupByAttribute);
|
|
5508
|
+
aggregationResult.values = Object.keys(itemsGrouped).map((key) => ({
|
|
5509
|
+
key,
|
|
5510
|
+
groupBy: this.getChartDataBasedOnOperation(itemsGrouped[key], options.ordinate.operation, abscissa, ordinate, options.abscissa.limit)
|
|
5511
|
+
}));
|
|
5468
5512
|
}
|
|
5469
|
-
return
|
|
5513
|
+
return aggregationResult;
|
|
5470
5514
|
}
|
|
5471
|
-
|
|
5472
|
-
|
|
5473
|
-
|
|
5474
|
-
|
|
5475
|
-
|
|
5476
|
-
|
|
5477
|
-
|
|
5478
|
-
|
|
5479
|
-
|
|
5480
|
-
|
|
5481
|
-
|
|
5482
|
-
|
|
5483
|
-
|
|
5484
|
-
|
|
5515
|
+
getItemsGroupedByAttributeValue(items, attribute) {
|
|
5516
|
+
if (attribute === '')
|
|
5517
|
+
console.warn('groupBy attribute not found');
|
|
5518
|
+
let distinctValues = {};
|
|
5519
|
+
items.forEach((item) => {
|
|
5520
|
+
let value = AggregationUtils.getValueFromAttribute(item, attribute)?.value;
|
|
5521
|
+
if (!!value)
|
|
5522
|
+
distinctValues[value] = [...(distinctValues[value] ?? []), item];
|
|
5523
|
+
});
|
|
5524
|
+
return distinctValues;
|
|
5525
|
+
}
|
|
5526
|
+
// get { key, value } object list that will be our data to show in the chart
|
|
5527
|
+
getChartDataBasedOnOperation(items, operation, abscissa, ordinate, limit) {
|
|
5528
|
+
if (abscissa === '' || ordinate === '')
|
|
5529
|
+
console.warn('abscissa or ordinate attribute not found');
|
|
5530
|
+
const groupByAbscissa = this.getItemsGroupedByAttributeValue(items, abscissa);
|
|
5531
|
+
let result = [
|
|
5532
|
+
...Object.keys(groupByAbscissa).map((abscissaAttribute) => {
|
|
5533
|
+
console.log(AggregationUtils.getAggregatedValue(operation, groupByAbscissa, abscissaAttribute, ordinate ?? ''));
|
|
5534
|
+
return {
|
|
5535
|
+
key: +abscissaAttribute || abscissaAttribute,
|
|
5536
|
+
value: AggregationUtils.getAggregatedValue(operation, groupByAbscissa, abscissaAttribute, ordinate ?? '')
|
|
5537
|
+
};
|
|
5538
|
+
})
|
|
5539
|
+
];
|
|
5540
|
+
if (limit)
|
|
5541
|
+
result = AggregationUtils.formatByLimit(result, limit, operation);
|
|
5542
|
+
return result;
|
|
5485
5543
|
}
|
|
5486
5544
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.6", ngImport: i0, type: PryFrontendAggregationService, deps: [{ token: i1.Store }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
5487
5545
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.1.6", ngImport: i0, type: PryFrontendAggregationService, providedIn: 'root' }); }
|