@hestia-earth/ui-components 0.3.3 → 0.3.6

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.
@@ -22,7 +22,7 @@ import { ReplaySubject, of, forkJoin, from, zip } from 'rxjs';
22
22
  import { keyToLabel, isUndefined, isNumber, toPrecision, toDashCase, isBoolean, ConvertUnits, converters, convertValue, isEmpty, isEqual as isEqual$1, unique, diffInDays } from '@hestia-earth/utils';
23
23
  import * as pluralize from 'pluralize';
24
24
  import { propertyValue as propertyValue$1, emptyValue } from '@hestia-earth/utils/dist/term';
25
- import { getDefaultModeId } from '@hestia-earth/glossary';
25
+ import { getDefaultModelId } from '@hestia-earth/glossary';
26
26
  import { __rest, __awaiter } from 'tslib';
27
27
  import { catchError, map, take, mergeMap, debounceTime, distinctUntilChanged, tap, switchMap, reduce, distinct, toArray, filter, mergeAll, groupBy } from 'rxjs/operators';
28
28
  import * as csvtojson from 'csvtojson';
@@ -682,7 +682,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImpo
682
682
  }] });
683
683
 
684
684
  const get$5 = require('lodash.get');
685
- const isMethodModelAllowed = (filterMethod) => (node) => { var _a, _b; return ((_a = node.methodModel) === null || _a === void 0 ? void 0 : _a['@id']) === (filterMethod ? filterMethod['@id'] : getDefaultModeId((_b = node.term) === null || _b === void 0 ? void 0 : _b['@id'])); };
685
+ const isMethodModelAllowed = (filterMethod) => (node) => { var _a, _b; return ((_a = node.methodModel) === null || _a === void 0 ? void 0 : _a['@id']) === (filterMethod ? filterMethod['@id'] : getDefaultModelId((_b = node.term) === null || _b === void 0 ? void 0 : _b['@id'])); };
686
686
  var NodeKeyState;
687
687
  (function (NodeKeyState) {
688
688
  NodeKeyState["added"] = "added";
@@ -832,9 +832,9 @@ class HeNodeService {
832
832
  params: filterParams({ dataState })
833
833
  }).toPromise().catch(handleAPIError);
834
834
  }
835
- getModelsLog(_a) {
835
+ getErrorLog(_a) {
836
836
  var { dataState } = _a, node = __rest(_a, ["dataState"]);
837
- return this.http.get(`${this.nodeUrl(node)}/log/models`, {
837
+ return this.http.get(`${this.nodeUrl(node)}/log/error`, {
838
838
  headers: this.authService.headers,
839
839
  params: filterParams({ dataState })
840
840
  }).toPromise().catch(handleAPIError);
@@ -1384,6 +1384,9 @@ class LinkKeyValueComponent {
1384
1384
  this.baseUrl = baseUrl();
1385
1385
  this.toString = toString;
1386
1386
  }
1387
+ get isInlineBlock() {
1388
+ return this.isArray;
1389
+ }
1387
1390
  get type() {
1388
1391
  return this.node['@type'] || this.node.type;
1389
1392
  }
@@ -1404,7 +1407,7 @@ class LinkKeyValueComponent {
1404
1407
  }
1405
1408
  }
1406
1409
  LinkKeyValueComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: LinkKeyValueComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1407
- LinkKeyValueComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.16", type: LinkKeyValueComponent, selector: "he-link-key-value", inputs: { node: "node", nodeType: "nodeType", dataKey: "dataKey", key: "key" }, ngImport: i0, template: "<ng-container *ngIf=\"!isUndefined\">\n <ng-container *bindOnce=\"node\">\n <a [href]=\"baseUrl + '/schema/' + type + '#' + key\" target=\"_blank\"><b>{{key}}</b></a>\n <span class=\"pr-2\">:</span>\n\n <ng-container *ngIf=\"isArray; else singleValue\">\n <div class=\"array-container pl-2\">\n <p *ngFor=\"let v of value\" [innerHtml]=\"toString(v) | precision:3\"></p>\n </div>\n </ng-container>\n </ng-container>\n</ng-container>\n\n<ng-template #singleValue>\n <div class=\"is-inline-block pr-1\" [innerHtml]=\"valueString | precision:3\"></div>\n\n <he-blank-node-state\n [node]=\"node\" [nodeType]=\"nodeType\" [dataKey]=\"dataKey\" [key]=\"key\"\n ></he-blank-node-state>\n</ng-template>\n", styles: [":host{display:block}.array-container{max-height:100px;overflow-y:auto}\n"], components: [{ type: BlankNodeStateComponent, selector: "he-blank-node-state", inputs: ["nodeType", "dataKey", "key", "node", "state"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: BindOnceDirective, selector: "[bindOnce]", inputs: ["bindOnce"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], pipes: { "precision": PrecisionPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
1410
+ LinkKeyValueComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.16", type: LinkKeyValueComponent, selector: "he-link-key-value", inputs: { node: "node", nodeType: "nodeType", dataKey: "dataKey", key: "key" }, host: { properties: { "class.is-inline-block": "this.isInlineBlock" } }, ngImport: i0, template: "<ng-container *ngIf=\"!isUndefined\">\n <ng-container *bindOnce=\"node\">\n <a [href]=\"baseUrl + '/schema/' + type + '#' + key\" target=\"_blank\"><b>{{key}}</b></a>\n <span class=\"pr-2\">:</span>\n\n <ng-container *ngIf=\"isArray; else singleValue\">\n <div class=\"array-container pl-2\">\n <p *ngFor=\"let v of value\" [innerHtml]=\"toString(v) | precision:3\"></p>\n </div>\n </ng-container>\n </ng-container>\n</ng-container>\n\n<ng-template #singleValue>\n <div class=\"is-inline-block pr-1\" [innerHtml]=\"valueString | precision:3\"></div>\n\n <he-blank-node-state\n [node]=\"node\" [nodeType]=\"nodeType\" [dataKey]=\"dataKey\" [key]=\"key\"\n ></he-blank-node-state>\n</ng-template>\n", styles: [":host{display:block}.array-container{max-height:100px;overflow-y:auto}\n"], components: [{ type: BlankNodeStateComponent, selector: "he-blank-node-state", inputs: ["nodeType", "dataKey", "key", "node", "state"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: BindOnceDirective, selector: "[bindOnce]", inputs: ["bindOnce"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], pipes: { "precision": PrecisionPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
1408
1411
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: LinkKeyValueComponent, decorators: [{
1409
1412
  type: Component$1,
1410
1413
  args: [{
@@ -1421,6 +1424,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImpo
1421
1424
  type: Input
1422
1425
  }], key: [{
1423
1426
  type: Input
1427
+ }], isInlineBlock: [{
1428
+ type: HostBinding,
1429
+ args: ['class.is-inline-block']
1424
1430
  }] } });
1425
1431
 
1426
1432
  const locationQuery = (bounds, searchField = 'location') => {
@@ -4451,7 +4457,7 @@ class NodeLinkComponent {
4451
4457
  this.node['@type'].toLowerCase(),
4452
4458
  this.id
4453
4459
  ].filter(Boolean).join('/');
4454
- return `${url}?dataState=${DataState.recalculated}`;
4460
+ return `${url}${this.node.aggregated ? `?dataState=${DataState.recalculated}` : ''}`;
4455
4461
  }
4456
4462
  get showLink() {
4457
4463
  return this.node && linkTypeEnabled(this.node['@type']);
@@ -4568,6 +4574,7 @@ const groupLog = (group, _a) => {
4568
4574
  var { logger, term, model, key, should_run, run_required, property } = _a, log = __rest(_a, ["logger", "term", "model", "key", "should_run", "run_required", "property"]);
4569
4575
  const isOrchestrator = logger.includes('orchestrator');
4570
4576
  const isKey = !isOrchestrator && !!key;
4577
+ const isProperty = !isOrchestrator && !!property;
4571
4578
  const parentLogKey = [`["${term}"]`, !isOrchestrator && key || property].filter(Boolean).join('.');
4572
4579
  const logModelKey = [parentLogKey, model].filter(Boolean).join('.');
4573
4580
  set$1(group, `${parentLogKey}.models`, unique([
@@ -4575,6 +4582,7 @@ const groupLog = (group, _a) => {
4575
4582
  model
4576
4583
  ]));
4577
4584
  set$1(group, `${parentLogKey}.isKey`, isKey);
4585
+ set$1(group, `${parentLogKey}.isProperty`, isProperty);
4578
4586
  let data = get$3(group, logModelKey, {});
4579
4587
  data = includeBlankNodes(data, log);
4580
4588
  if (typeof should_run !== 'undefined') {
@@ -4623,7 +4631,7 @@ const groupLogSubValue = (group, log, key) => {
4623
4631
  const subValueKeys = [
4624
4632
  'transformation'
4625
4633
  ];
4626
- const groupLogsByModel = (data) => data.split('\n')
4634
+ const groupLogsByModel = (data) => data.trim().split('\n')
4627
4635
  .map(parseMessage)
4628
4636
  .filter(v => !!(v === null || v === void 0 ? void 0 : v.term) && (v === null || v === void 0 ? void 0 : v.term) !== 'None' && !!(v === null || v === void 0 ? void 0 : v.model))
4629
4637
  .reduce((group, log) => {
@@ -4634,7 +4642,7 @@ const groupLogsByModel = (data) => data.split('\n')
4634
4642
  groupLogSubValue(group, log, subValue) :
4635
4643
  groupLog(groupLogSubValue(group, log, subValue), log)
4636
4644
  : groupLog(group, log);
4637
- });
4645
+ }, {});
4638
4646
  const computeTerms = (originalValues, recalculatedValues, terms, filterTermTypes) => from((terms === null || terms === void 0 ? void 0 : terms.length) ?
4639
4647
  terms :
4640
4648
  [
@@ -4676,6 +4684,13 @@ const logStatus = (data, logs) => hasLog(logs)
4676
4684
  ].every(Boolean)
4677
4685
  ? LogStatus.skipHierarchy
4678
4686
  : LogStatus.dataProvided);
4687
+ const mergeSubValues = (values) => Object.values(values.reduce((prev, { id, key, configModels }) => {
4688
+ const uniqueKey = [key, id].filter(Boolean).join('.');
4689
+ prev[uniqueKey] = {
4690
+ id, key, configModels: [...((prev[uniqueKey] || {}).configModels || []), ...(configModels || [])]
4691
+ };
4692
+ return prev;
4693
+ }, {}));
4679
4694
  const reduceValues = (values, termId) => {
4680
4695
  const propertyValues = values
4681
4696
  .map(({ value }) => propertyValue$1(value, termId))
@@ -4719,25 +4734,39 @@ const logSubValue = (logs, key, prop) => logs[key][prop] ? (Array.isArray(logs[k
4719
4734
  logs[key][prop].map(id => ({ key: prop, id })) :
4720
4735
  { key: prop, id: logs[key][prop] }) : undefined;
4721
4736
  const logProperties = (nodes, models) => nodes.flatMap(node => (node.properties || []).map(({ term }) => term['@id'])).map(id => ({ key: 'property', id, configModels: findModels(models, id).map(({ model }) => model) }));
4722
- const logSubValues = (allLogs, logs, original, recalculated, models, { nodeType, type, termId }) => unique([
4737
+ const logSubValues = (allLogs, logs, original, recalculated, models, { nodeType, type, termId }) => mergeSubValues([
4738
+ ...Object.keys(logs)
4739
+ .filter(id => logs[id].isProperty)
4740
+ .map(id => ({
4741
+ id,
4742
+ key: 'property',
4743
+ configModels: (logs[id].models || []).filter(v => hasLog(logs[id][v]))
4744
+ })),
4723
4745
  ...Object.keys(logs).flatMap(key => [
4724
4746
  logSubValue(logs, key, 'input'),
4725
4747
  logSubValue(logs, key, 'property')
4726
4748
  ]
4727
4749
  .flat()
4728
4750
  .filter(Boolean)
4729
- .map(v => (Object.assign(Object.assign({}, v), { configModels: [key] })))),
4751
+ .map(v => (Object.assign(Object.assign({}, v), { configModels: v.configModels || [key] })))),
4730
4752
  ...logProperties(original, models),
4731
4753
  ...logProperties(recalculated, models)
4732
4754
  ])
4733
- .map(v => {
4734
- const originalValue = blankNodeValue(original, v.key, v.id);
4735
- const recalculatedValue = blankNodeValue(recalculated, v.key, v.id);
4736
- return Object.assign(Object.assign({}, v), { configModels: v.configModels.map(configModelWithDocs(models, { nodeType, type, termId }, v)), originalValue,
4737
- recalculatedValue, isRecalculated: !isUndefined(recalculatedValue) && recalculatedValue !== originalValue, isRequired: true });
4755
+ .map(({ key, id, configModels }) => {
4756
+ const originalValue = blankNodeValue(original, key, id);
4757
+ const recalculatedValue = blankNodeValue(recalculated, key, id);
4758
+ return {
4759
+ key,
4760
+ id,
4761
+ configModels: configModels.map(configModelWithDocs(models, { nodeType, type, termId }, { key, id })),
4762
+ originalValue,
4763
+ recalculatedValue,
4764
+ isRecalculated: !isUndefined(recalculatedValue) && recalculatedValue !== originalValue,
4765
+ isRequired: true
4766
+ };
4738
4767
  })
4739
4768
  .filter(v => v.configModels.length > 0)
4740
- .map(dataWithConfigModelLogs(allLogs));
4769
+ .map(v => v.key === 'property' ? dataWithConfigModelLogs(logs)(v) : dataWithConfigModelLogs(allLogs)(v));
4741
4770
  // const hasKey = (blankNodes: blankNode[], key: string) => (blankNodes || []).some(n => key in n);
4742
4771
  const logKeys = (logs, original, recalculated, models, { nodeType, type, termId }) => Object.keys(logs)
4743
4772
  .filter(key => logs[key].isKey)
@@ -4778,7 +4807,7 @@ const modelConfigOrder = (models, termId, modelKey, model) => {
4778
4807
  }).filter(Boolean);
4779
4808
  return indexes.length ? indexes[0] : '';
4780
4809
  };
4781
- const configModelWithDocs = (models, { nodeType, type, termId }, subValue) => (methodId) => {
4810
+ const configModelWithDocs = (models, { nodeType, type, termId, termType }, subValue) => (methodId) => {
4782
4811
  const node = {
4783
4812
  '@type': nodeType,
4784
4813
  term: { '@id': (subValue === null || subValue === void 0 ? void 0 : subValue.id) || termId },
@@ -4787,6 +4816,8 @@ const configModelWithDocs = (models, { nodeType, type, termId }, subValue) => (m
4787
4816
  return {
4788
4817
  methodId,
4789
4818
  model: findMatchingModel(models, modelParams(node)) ||
4819
+ // handle "liveAnimal"
4820
+ (termType && findMatchingModel(models, modelKeyParams(node, termType))) ||
4790
4821
  findMatchingModel(models, modelKeyParams(node, `${subValue === null || subValue === void 0 ? void 0 : subValue.key}.${methodId}`)) ||
4791
4822
  // handle "input.price"
4792
4823
  findMatchingModel(models, modelKeyParams(node, `${type.toLowerCase()}.${subValue === null || subValue === void 0 ? void 0 : subValue.key}`)) ||
@@ -4837,11 +4868,12 @@ const groupLogsByTerm = (nodeType, logs, models, config, allOriginalValues, allR
4837
4868
  undefined;
4838
4869
  return (term) => {
4839
4870
  const termId = term['@id'];
4871
+ const termType = term.termType;
4840
4872
  const termLogs = get$3(logs, termId, {});
4841
4873
  const original = originalValues.filter(v => termId === v.term['@id']);
4842
4874
  const recalculated = recalculatedValues.filter(v => termId === v.term['@id']);
4843
4875
  const hasData = !!original.length || !!recalculated.length || Object.keys(termLogs).length > 0;
4844
- const configModelsData = { nodeType, type, termId };
4876
+ const configModelsData = { nodeType, type, termId, termType };
4845
4877
  const configModels = groupParallelModels(config, termId, nodeKey, unique([
4846
4878
  ...(termLogs.models || []).filter(key => isModelLog(termLogs[key])),
4847
4879
  ...findConfigModels(config, termId, nodeKey, models).map(({ model }) => model)
@@ -4881,8 +4913,8 @@ const modelCount = (blankNodeLogs) => Math.max.apply(Math.max, [
4881
4913
  0,
4882
4914
  ...blankNodeLogs.flatMap(v => [
4883
4915
  v.configModels.length,
4884
- ...v.subValues.map(s => { var _a, _b; return (_b = (_a = s.configModels) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0; }),
4885
- v.keys.length ? 1 : 0
4916
+ ...(v.subValues.map(s => { var _a; return ((_a = s.configModels) === null || _a === void 0 ? void 0 : _a.length) || 0; })),
4917
+ ...(v.keys.map(s => { var _a; return ((_a = s.configModels) === null || _a === void 0 ? void 0 : _a.length) || 0; }))
4886
4918
  ])
4887
4919
  ]);
4888
4920
 
@@ -5069,16 +5101,20 @@ class NodeValueDetailsComponent {
5069
5101
  this.additionalKeys = additionalKeys;
5070
5102
  this.tableKeys = tableKeys;
5071
5103
  }
5104
+ ngOnInit() {
5105
+ this.tableKeys = tableKeys.filter(key => { var _a; return (((_a = this.data) === null || _a === void 0 ? void 0 : _a.nodes) || []).some(node => key in node); });
5106
+ }
5072
5107
  get type() {
5073
5108
  var _a;
5074
5109
  return (_a = this.data) === null || _a === void 0 ? void 0 : _a.nodes[0]['@type'];
5075
5110
  }
5076
- ngOnInit() {
5077
- this.tableKeys = tableKeys.filter(key => { var _a; return (((_a = this.data) === null || _a === void 0 ? void 0 : _a.nodes) || []).some(node => key in node); });
5111
+ get showInline() {
5112
+ var _a, _b;
5113
+ return ((_b = (_a = this.data) === null || _a === void 0 ? void 0 : _a.nodes) === null || _b === void 0 ? void 0 : _b.length) === 1;
5078
5114
  }
5079
5115
  }
5080
5116
  NodeValueDetailsComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: NodeValueDetailsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5081
- NodeValueDetailsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.16", type: NodeValueDetailsComponent, selector: "he-node-value-details", inputs: { data: "data", nodeType: "nodeType", dataKey: "dataKey" }, ngImport: i0, template: "<ng-container *bindOnce=\"data\">\n <ng-container *ngIf=\"data?.nodes?.length === 1; else showTable\">\n <ng-container *ngFor=\"let key of keys\">\n <he-link-key-value [node]=\"data!.nodes[0]\" [nodeType]=\"nodeType\" [dataKey]=\"dataKey\" [key]=\"key\"></he-link-key-value>\n </ng-container>\n <ng-container *ngFor=\"let key of additionalKeys\">\n <he-link-key-value [node]=\"data!.nodes[0]\" [nodeType]=\"nodeType\" [dataKey]=\"dataKey\" [key]=\"key\"></he-link-key-value>\n </ng-container>\n </ng-container>\n</ng-container>\n\n<ng-template #showTable>\n <he-link-key-value [node]=\"data!.nodes[0]\" [nodeType]=\"nodeType\" [dataKey]=\"dataKey\" key=\"term\"></he-link-key-value>\n\n <div class=\"table-container mt-2\">\n <table class=\"table is-narrow\">\n <thead>\n <th *ngFor=\"let key of tableKeys\">\n <a [href]=\"baseUrl + '/schema/' + type + '#' + key\" target=\"_blank\"><b>{{key}}</b></a>\n </th>\n </thead>\n <tbody>\n <tr *ngFor=\"let node of data!.nodes\">\n <td *ngFor=\"let key of tableKeys\">\n <he-link-key-value [node]=\"node\" [nodeType]=\"nodeType\" [dataKey]=\"dataKey\" [key]=\"key\"></he-link-key-value>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n</ng-template>\n", styles: ["table{background-color:transparent;color:#fff}table::ng-deep he-link-key-value>a:first-child,table::ng-deep he-link-key-value>a:first-child+span{display:none}\n"], components: [{ type: LinkKeyValueComponent, selector: "he-link-key-value", inputs: ["node", "nodeType", "dataKey", "key"] }], directives: [{ type: BindOnceDirective, selector: "[bindOnce]", inputs: ["bindOnce"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5117
+ NodeValueDetailsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.16", type: NodeValueDetailsComponent, selector: "he-node-value-details", inputs: { data: "data", nodeType: "nodeType", dataKey: "dataKey" }, ngImport: i0, template: "<ng-container *bindOnce=\"data\">\n <ng-container *ngIf=\"showInline; else asTable\">\n <ng-container *ngFor=\"let key of keys\">\n <he-link-key-value [node]=\"data!.nodes[0]\" [nodeType]=\"nodeType\" [dataKey]=\"dataKey\" [key]=\"key\"></he-link-key-value>\n </ng-container>\n <ng-container *ngFor=\"let key of additionalKeys\">\n <he-link-key-value [node]=\"data!.nodes[0]\" [nodeType]=\"nodeType\" [dataKey]=\"dataKey\" [key]=\"key\"></he-link-key-value>\n </ng-container>\n </ng-container>\n</ng-container>\n\n<ng-template #asTable>\n <he-link-key-value [node]=\"data!.nodes[0]\" [nodeType]=\"nodeType\" [dataKey]=\"dataKey\" key=\"term\"></he-link-key-value>\n\n <div class=\"table-container mt-2\">\n <table class=\"table is-narrow\">\n <thead>\n <th *ngFor=\"let key of tableKeys\">\n <a [href]=\"baseUrl + '/schema/' + type + '#' + key\" target=\"_blank\"><b>{{key}}</b></a>\n </th>\n </thead>\n <tbody>\n <tr *ngFor=\"let node of data!.nodes\">\n <td *ngFor=\"let key of tableKeys\">\n <he-link-key-value [node]=\"node\" [nodeType]=\"nodeType\" [dataKey]=\"dataKey\" [key]=\"key\"></he-link-key-value>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n</ng-template>\n", styles: ["table{background-color:transparent;color:#fff}table::ng-deep he-link-key-value>a:first-child,table::ng-deep he-link-key-value>a:first-child+span{display:none}\n"], components: [{ type: LinkKeyValueComponent, selector: "he-link-key-value", inputs: ["node", "nodeType", "dataKey", "key"] }], directives: [{ type: BindOnceDirective, selector: "[bindOnce]", inputs: ["bindOnce"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5082
5118
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: NodeValueDetailsComponent, decorators: [{
5083
5119
  type: Component$1,
5084
5120
  args: [{
@@ -5240,7 +5276,7 @@ class CyclesFunctionalUnitMeasureComponent {
5240
5276
  }
5241
5277
  }
5242
5278
  CyclesFunctionalUnitMeasureComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: CyclesFunctionalUnitMeasureComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5243
- CyclesFunctionalUnitMeasureComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.16", type: CyclesFunctionalUnitMeasureComponent, selector: "he-cycles-functional-unit-measure", inputs: { cycle: "cycle" }, ngImport: i0, template: "<span class=\"pl-1\" [ngSwitch]=\"cycle?.functionalUnit\">\n <ng-container *ngSwitchCase=\"CycleFunctionalUnit['1 ha']\">1 hectare</ng-container>\n <ng-container *ngSwitchDefault>relative</ng-container>\n</span>\n", styles: [""], directives: [{ type: i2.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { type: i2.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { type: i2.NgSwitchDefault, selector: "[ngSwitchDefault]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5279
+ CyclesFunctionalUnitMeasureComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.16", type: CyclesFunctionalUnitMeasureComponent, selector: "he-cycles-functional-unit-measure", inputs: { cycle: "cycle" }, ngImport: i0, template: "<span class=\"is-nowrap has-text-ellipsis\" [ngSwitch]=\"cycle?.functionalUnit\" [attr.title]=\"cycle?.functionalUnit\">\n <ng-container *ngSwitchCase=\"CycleFunctionalUnit['1 ha']\">1 hectare</ng-container>\n <ng-container *ngSwitchDefault>relative</ng-container>\n</span>\n", styles: [":host{display:inline-block}\n"], directives: [{ type: i2.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { type: i2.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { type: i2.NgSwitchDefault, selector: "[ngSwitchDefault]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5244
5280
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: CyclesFunctionalUnitMeasureComponent, decorators: [{
5245
5281
  type: Component$1,
5246
5282
  args: [{
@@ -5721,7 +5757,8 @@ class CyclesPracticesComponent {
5721
5757
  return popover.isOpen() ? popover.close() : popover.open(context);
5722
5758
  }
5723
5759
  get showTimeline() {
5724
- return (this.cycles[0].practices || []).some(p => { var _a; return timelineTermType.includes((_a = p.term) === null || _a === void 0 ? void 0 : _a.termType); });
5760
+ var _a, _b;
5761
+ return (((_b = (_a = this.cycles) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.practices) || []).some(p => { var _a; return timelineTermType.includes((_a = p.term) === null || _a === void 0 ? void 0 : _a.termType); });
5725
5762
  }
5726
5763
  // Recalculation logs
5727
5764
  selectIndex({ target: { value } }) {
@@ -6049,7 +6086,7 @@ const parseDataPath = (dataPath = '') => {
6049
6086
  const contactUsEmail = 'community@hestia.earth';
6050
6087
  const externalLink = (href, text) => `<a href="${href}" target="_blank">${text}</a>`;
6051
6088
  const glossaryLink = (text) => externalLink(`${baseUrl()}/glossary`, text);
6052
- const glossaryTypeLink = (type) => externalLink(`${baseUrl()}/glossary?termType=${type}`, termTypeLabel(type));
6089
+ const glossaryTypeLink = (type, text = termTypeLabel(type)) => externalLink(`${baseUrl()}/glossary?termType=${type}`, text);
6053
6090
  const termLink = ({ id, name }) => externalLink(`${baseUrl()}/term/${id}`, name);
6054
6091
  const nodeLink = ({ '@type': type, '@id': id, name }) => type && id ? `<a href="/${type.toLowerCase()}/${id}" target="_blank">${name || id}</a>` : null;
6055
6092
  const schemaLink = (type, title = type) => `<a href="${baseUrl()}/schema/${type}" target="_blank">${title}</a>`;
@@ -6245,7 +6282,9 @@ const customErrorMessage = {
6245
6282
  'must be less than or equal to land occupation': () => `Land transformation should be less than or equal to land occupation
6246
6283
  (land transformation is the amount of land converted between some date in the past and the current year,
6247
6284
  divided by an amortization period, so it should always be less than land occupation by definition).`,
6248
- 'should be linked to an emission in the Cycle': ({ params }, errorCount) => `${errorCount === 1 ? `${code(params === null || params === void 0 ? void 0 : params.term.name)} exists` : 'Some Emissions exist'} in both the Cycle and the Transformation but ${errorCount === 1 ? 'it is' : 'they are'} not linked using ${code('cycle.emissions.X.transformation.term')}. This may be an error.`
6285
+ 'should be linked to an emission in the Cycle': ({ params }, errorCount) => `${errorCount === 1 ? `${code(params === null || params === void 0 ? void 0 : params.term.name)} exists` : 'Some Emissions exist'} in both the Cycle and the Transformation but ${errorCount === 1 ? 'it is' : 'they are'} not linked using ${code('cycle.emissions.X.transformation.term')}. This may be an error.`,
6286
+ 'should add an animal production system': () => `For animal production cycles, we recommend specifying the animal production ${glossaryTypeLink(TermTermType.system)} as a Practice.
6287
+ You can find a list of systems in the ${glossaryTypeLink(TermTermType.system, 'Glossary')}.`
6249
6288
  };
6250
6289
  const formatCustomErrorMessage = (message, error, errorCount = 1) => {
6251
6290
  const formattedMessage = message && message in customErrorMessage ?
@@ -7736,8 +7775,8 @@ class ImpactAssessmentsIndicatorBreakdownChartComponent {
7736
7775
  }
7737
7776
  ngOnInit() {
7738
7777
  return __awaiter(this, void 0, void 0, function* () {
7739
- this.terms = unique(this.indicators.map(({ term }) => term).filter(Boolean));
7740
- this.methods = unique(this.indicators.map(({ methodModel }) => methodModel).filter(Boolean));
7778
+ this.terms = unique((this.indicators || []).map(({ term }) => term).filter(Boolean));
7779
+ this.methods = unique((this.indicators || []).map(({ methodModel }) => methodModel).filter(Boolean));
7741
7780
  const impacts = [
7742
7781
  ...this.impactAssessment.impacts || [],
7743
7782
  ...this.impactAssessment.endpoints || []
@@ -8155,7 +8194,7 @@ class ImpactAssessmentsProductsComponent {
8155
8194
  }
8156
8195
  }
8157
8196
  ImpactAssessmentsProductsComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: ImpactAssessmentsProductsComponent, deps: [{ token: HeNodeService }], target: i0.ɵɵFactoryTarget.Component });
8158
- ImpactAssessmentsProductsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.16", type: ImpactAssessmentsProductsComponent, selector: "he-impact-assessments-products", inputs: { cycles: "cycles", impactAssessments: "impactAssessments", key: "key", dataState: "dataState", filterTermTypes: "filterTermTypes", enableFilterMethodModel: "enableFilterMethodModel" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"columns is-variable is-align-items-center is-2 m-0\">\n <div class=\"column is-hidden-mobile\"></div>\n <ng-container *ngIf=\"selectedView === View.table && indicators.length\">\n <div class=\"column is-narrow\">\n <button class=\"button is-dark is-outlined is-small\" (click)=\"showDownload = true\">\n <fa-icon icon=\"download\"></fa-icon>\n <span class=\"pl-2\">Download (CSV)</span>\n </button>\n </div>\n <div class=\"column is-narrow col-sep\"></div>\n </ng-container>\n <div class=\"column is-narrow\" *ngIf=\"impactAssessments.length > 1 || enableBreakdown || !isOriginal\">\n <div class=\"field has-addons\">\n <div class=\"control\">\n <button class=\"button is-small\" [class.is-active]=\"selectedView === View.table\" (click)=\"selectedView = View.table\">\n <span class=\"icon is-small\">\n <fa-icon icon=\"list\" aria-hidden=\"true\"></fa-icon>\n </span>\n <span>Table view</span>\n </button>\n </div>\n <div class=\"control\" *ngIf=\"impactAssessments.length > 1\">\n <button class=\"button is-small\" [class.is-active]=\"selectedView === View.chart\" (click)=\"selectedView = View.chart\">\n <span class=\"icon is-small\">\n <fa-icon icon=\"chart-bar\" aria-hidden=\"true\"></fa-icon>\n </span>\n <span>Chart view</span>\n </button>\n </div>\n <div class=\"control\" *ngIf=\"enableBreakdown\">\n <button class=\"button is-small\" [class.is-active]=\"selectedView === View.breakdown\" (click)=\"selectedView = View.breakdown\">\n <span class=\"icon is-small\">\n <fa-icon icon=\"chart-bar\" aria-hidden=\"true\"></fa-icon>\n </span>\n <span>Breakdown view</span>\n </button>\n </div>\n <div class=\"control\" *ngIf=\"!isOriginal\">\n <button class=\"button is-small\" [class.is-active]=\"selectedView === View.logs\" (click)=\"showRecalculationLogs()\">\n <span class=\"icon is-small\">\n <fa-icon icon=\"calculator\" aria-hidden=\"true\"></fa-icon>\n </span>\n <span>Recalculations logs</span>\n </button>\n </div>\n </div>\n </div>\n</div>\n\n<div class=\"px-3 pb-3\" [class.is-hidden]=\"selectedView !== View.table\">\n <ng-container *ngIf=\"indicators.length; else emptyTable\">\n <he-data-table class=\"mb-1 is-small\" [small]=\"true\" [nbRows]=\"impactAssessments.length\" maxHeight=\"320\">\n <table class=\"table is-narrow is-striped\">\n <thead>\n <tr>\n <th class=\"width-auto py-0\">\n <div class=\"select is-small\" *ngIf=\"enableFilterMethodModel\">\n <select name=\"selectedMethodModel\"\n (change)=\"updateImpacts()\" [(ngModel)]=\"selectedMethodModel\"\n >\n <option [ngValue]=\"undefined\">Filter Model</option>\n <option *ngFor=\"let term of methodModels\" [ngValue]=\"term\">{{term.name}}</option>\n </select>\n </div>\n </th>\n <th class=\"has-border-right\"></th>\n <th class=\"has-border-right\"></th>\n <th *ngFor=\"let indicator of indicators\"\n [attr.title]=\"indicator.value.term.name\"\n >\n <he-node-link [node]=\"indicator.value.term\">\n <span>{{indicator.value.term.name | ellipsis:30}}</span>\n </he-node-link>\n </th>\n </tr>\n <tr>\n <th class=\"width-auto\"></th>\n <th class=\"has-border-right\">\n <a [href]=\"baseUrl + '/schema/ImpactAssessment#functionalUnit'\" target=\"_blank\">Functional unit</a>\n </th>\n <th class=\"has-border-right\">\n <a [href]=\"baseUrl + '/schema/ImpactAssessment#product'\" target=\"_blank\">Product</a>\n </th>\n <th *ngFor=\"let indicator of indicators\"\n [attr.title]=\"indicator.value.term.units\"\n >{{indicator.value.term.units}}</th>\n </tr>\n </thead>\n <tbody>\n <ng-container *ngFor=\"let impactAssessment of impactAssessments; trackBy: trackById; let i = index\">\n <tr>\n <td class=\"width-auto\" [attr.title]=\"impactName(impactAssessment)\">\n <he-node-link [node]=\"impactAssessment\">\n <span class=\"is-nowrap has-text-ellipsis\">{{i + 1}}. {{impactName(impactAssessment)}}</span>\n </he-node-link>\n </td>\n <td class=\"has-border-right\">\n <span>1 {{impactAssessment.product.units}}</span>\n </td>\n <td class=\"has-border-right\" [attr.title]=\"impactAssessment.product?.name\">\n <he-node-link *ngIf=\"impactAssessment.product\" [node]=\"impactAssessment.product\">\n <span>{{impactAssessment.product.name | ellipsis:30}}</span>\n </he-node-link>\n </td>\n <td class=\"is-nowrap\" *ngFor=\"let indicator of indicators\">\n <span *ngIf=\"indicator.value.values[impactAssessment['@id']]; else emptyValue\"\n class=\"trigger-popover\"\n [ngbPopover]=\"details\" [autoClose]=\"'outside'\"\n triggers=\"manual\" #p=\"ngbPopover\" placement=\"left\" container=\"body\"\n (click)=\"togglePopover(p, { data: indicator.value.values[impactAssessment['@id']], impactAssessment: impactAssessment, key: key })\"\n >\n <span pointer>{{propertyValue(indicator.value.values[impactAssessment['@id']].value, indicator.value.term['@id']) | precision:3 | default:'-'}}</span>\n <he-blank-node-state class=\"ml-1\"\n [node]=\"indicator.value.values[impactAssessment['@id']].node\"\n key=\"value\"\n [state]=\"impactAssessment.aggregated ? 'aggregated' : undefined\"\n ></he-blank-node-state>\n </span>\n </td>\n </tr>\n </ng-container>\n </tbody>\n </table>\n </he-data-table>\n\n <he-blank-node-state-notice [dataState]=\"dataState\"></he-blank-node-state-notice>\n </ng-container>\n</div>\n\n<he-impact-assessments-indicator-breakdown-chart *ngIf=\"selectedView === View.breakdown\"\n [impactAssessment]=\"impactAssessments[0]\"\n [indicators]=\"impactAssessments[0][key]\"\n></he-impact-assessments-indicator-breakdown-chart>\n\n<he-impact-assessments-indicators-chart *ngIf=\"impactAssessments.length > 1\" [class.is-hidden]=\"selectedView !== View.chart\"\n [key]=\"key\"\n [impactAssessments]=\"impactAssessments\"\n [filterTermTypes]=\"filterTermTypes\"\n></he-impact-assessments-indicators-chart>\n\n<ng-container *ngIf=\"selectedView === View.logs && !isOriginal\">\n <div class=\"field has-addons pt-2 px-3\" *ngIf=\"impactAssessments.length > 1\">\n <div class=\"control\">\n <span class=\"button is-small is-static\">Select an Impact Assessment</span>\n </div>\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"selectIndex($event)\">\n <option *ngFor=\"let value of impactAssessments; let i = index\" [value]=\"i\">{{i + 1}}. {{impactName(value)}}</option>\n </select>\n </div>\n </div>\n </div>\n\n <he-impact-assessments-products-logs *ngIf=\"selectedIndex >= 0\"\n [key]=\"key\"\n [impactAssessment]=\"impactAssessments[selectedIndex]\"\n [filterTermTypes]=\"filterTermTypes\"\n [originalValues]=\"originalValues[selectedIndex]?.[key]\"\n [recalculatedValues]=\"impactAssessments[selectedIndex]?.[key]\"\n ></he-impact-assessments-products-logs>\n</ng-container>\n\n<he-node-csv-export-confirm *ngIf=\"showDownload\"\n [nodes]=\"impactAssessments\" [filename]=\"'impact-' + key + '.csv'\" [isUpload]=\"false\"\n [headerKeys]=\"['impactAssessment.id', 'impactAssessment.@id', 'impactAssessment.' + key + '.']\"\n (closed)=\"showDownload = false\"\n></he-node-csv-export-confirm>\n\n<ng-template #emptyTable>\n <div class=\"has-text-centered\">\n <span>No data</span>\n </div>\n</ng-template>\n\n<ng-template #emptyValue>\n <span>-</span>\n</ng-template>\n\n<ng-template #details let-node=\"impactAssessment\" let-data=\"data\" let-key=\"key\">\n <p *bindOnce=\"node\">\n <b>\n <span *ngIf=\"data.cycle\">{{cycleLabel(node.cycle)}}</span>\n <span *ngIf=\"!data.cycle\">{{data.name}}</span>\n </b>\n </p>\n <he-node-value-details\n [data]=\"data\" [nodeType]=\"node['@type']\" [dataKey]=\"key\"\n ></he-node-value-details>\n</ng-template>\n\n<ng-template #suggestion let-impact=\"result\" let-t=\"term\">\n <div class=\"is-block\">\n <ngb-highlight [result]=\"impact.name || impact.cycle.name\" [term]=\"t\"></ngb-highlight>\n </div>\n <div class=\"columns is-flex\">\n <div class=\"column\" *ngIf=\"impact.country\">\n <span class=\"pr-1 has-text-underline\">Country:</span>\n <span class=\"is-inline-flex\"><ngb-highlight [result]=\"impact.country.name\" [term]=\"t\"></ngb-highlight></span>\n </div>\n <div class=\"column\" *ngIf=\"impact.product\">\n <span class=\"pr-1 has-text-underline\">Product:</span>\n <span class=\"is-inline-flex\"><ngb-highlight [result]=\"impact.product.name\" [term]=\"t\"></ngb-highlight></span>\n </div>\n <div class=\"column\" *ngIf=\"impact.endDate\">\n <span class=\"pr-1 has-text-underline\">Date:</span>\n <span class=\"is-inline-flex\"><ngb-highlight [result]=\"impact.endDate\" [term]=\"t\"></ngb-highlight></span>\n </div>\n </div>\n</ng-template>\n", styles: ["fa-icon{display:inline-block;width:10px}he-data-table ::ng-deep .table thead tr th:nth-child(2),he-data-table ::ng-deep .table tbody tr td:nth-child(2){max-width:102px;width:102px}\n"], components: [{ type: i1.FaIconComponent, selector: "fa-icon", inputs: ["classes", "icon", "title", "spin", "pulse", "mask", "styles", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "transform", "a11yRole"] }, { type: DataTableComponent, selector: "he-data-table", inputs: ["minHeight", "maxHeight", "nbRows", "small", "height", "width"] }, { type: NodeLinkComponent, selector: "he-node-link", inputs: ["node", "showExternalLink"] }, { type: BlankNodeStateComponent, selector: "he-blank-node-state", inputs: ["nodeType", "dataKey", "key", "node", "state"] }, { type: BlankNodeStateNoticeComponent, selector: "he-blank-node-state-notice", inputs: ["dataState", "showAggregated", "showDeleted", "showUnchanged"] }, { type: ImpactAssessmentsIndicatorBreakdownChartComponent, selector: "he-impact-assessments-indicator-breakdown-chart", inputs: ["impactAssessment", "indicators"] }, { type: ImpactAssessmentsIndicatorsChartComponent, selector: "he-impact-assessments-indicators-chart", inputs: ["impactAssessments", "key", "filterTermTypes"] }, { type: ImpactAssessmentsProductsLogsComponent, selector: "he-impact-assessments-products-logs", inputs: ["impactAssessment", "key", "filterTermTypes", "originalValues", "recalculatedValues"] }, { type: NodeCsvExportConfirmComponent, selector: "he-node-csv-export-confirm", inputs: ["nodes", "filename", "headerKeys", "extension", "isUpload"], outputs: ["closed"] }, { type: NodeValueDetailsComponent, selector: "he-node-value-details", inputs: ["data", "nodeType", "dataKey"] }, { type: i11.NgbHighlight, selector: "ngb-highlight", inputs: ["highlightClass", "result", "term"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1$1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i1$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { type: i1$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i11.NgbPopover, selector: "[ngbPopover]", inputs: ["animation", "autoClose", "placement", "triggers", "container", "disablePopover", "popoverClass", "openDelay", "closeDelay", "ngbPopover", "popoverTitle"], outputs: ["shown", "hidden"], exportAs: ["ngbPopover"] }, { type: BindOnceDirective, selector: "[bindOnce]", inputs: ["bindOnce"] }], pipes: { "ellipsis": EllipsisPipe, "default": DefaultPipe, "precision": PrecisionPipe } });
8197
+ ImpactAssessmentsProductsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.16", type: ImpactAssessmentsProductsComponent, selector: "he-impact-assessments-products", inputs: { cycles: "cycles", impactAssessments: "impactAssessments", key: "key", dataState: "dataState", filterTermTypes: "filterTermTypes", enableFilterMethodModel: "enableFilterMethodModel" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"columns is-variable is-align-items-center is-2 m-0\">\n <div class=\"column is-hidden-mobile\"></div>\n <ng-container *ngIf=\"selectedView === View.table && indicators.length\">\n <div class=\"column is-narrow\">\n <button class=\"button is-dark is-outlined is-small\" (click)=\"showDownload = true\">\n <fa-icon icon=\"download\"></fa-icon>\n <span class=\"pl-2\">Download (CSV)</span>\n </button>\n </div>\n <div class=\"column is-narrow col-sep\"></div>\n </ng-container>\n <div class=\"column is-narrow\" *ngIf=\"impactAssessments.length > 1 || enableBreakdown || !isOriginal\">\n <div class=\"field has-addons\">\n <div class=\"control\">\n <button class=\"button is-small\" [class.is-active]=\"selectedView === View.table\" (click)=\"selectedView = View.table\">\n <span class=\"icon is-small\">\n <fa-icon icon=\"list\" aria-hidden=\"true\"></fa-icon>\n </span>\n <span>Table view</span>\n </button>\n </div>\n <div class=\"control\" *ngIf=\"impactAssessments.length > 1\">\n <button class=\"button is-small\" [class.is-active]=\"selectedView === View.chart\" (click)=\"selectedView = View.chart\">\n <span class=\"icon is-small\">\n <fa-icon icon=\"chart-bar\" aria-hidden=\"true\"></fa-icon>\n </span>\n <span>Chart view</span>\n </button>\n </div>\n <div class=\"control\" *ngIf=\"enableBreakdown\">\n <button class=\"button is-small\" [class.is-active]=\"selectedView === View.breakdown\" (click)=\"selectedView = View.breakdown\">\n <span class=\"icon is-small\">\n <fa-icon icon=\"chart-bar\" aria-hidden=\"true\"></fa-icon>\n </span>\n <span>Breakdown view</span>\n </button>\n </div>\n <div class=\"control\" *ngIf=\"!isOriginal\">\n <button class=\"button is-small\" [class.is-active]=\"selectedView === View.logs\" (click)=\"showRecalculationLogs()\">\n <span class=\"icon is-small\">\n <fa-icon icon=\"calculator\" aria-hidden=\"true\"></fa-icon>\n </span>\n <span>Recalculations logs</span>\n </button>\n </div>\n </div>\n </div>\n</div>\n\n<div class=\"px-3 pb-3\" [class.is-hidden]=\"selectedView !== View.table\">\n <ng-container *ngIf=\"indicators.length; else emptyTable\">\n <he-data-table class=\"mb-1 is-small\" [small]=\"true\" [nbRows]=\"impactAssessments.length\" maxHeight=\"320\">\n <table class=\"table is-narrow is-striped\">\n <thead>\n <tr>\n <th class=\"width-auto py-0\">\n <div class=\"select is-small\" *ngIf=\"enableFilterMethodModel\">\n <select name=\"selectedMethodModel\"\n (change)=\"updateImpacts()\" [(ngModel)]=\"selectedMethodModel\"\n >\n <option [ngValue]=\"undefined\">Filter Model</option>\n <option *ngFor=\"let term of methodModels\" [ngValue]=\"term\">{{term.name}}</option>\n </select>\n </div>\n </th>\n <th class=\"has-border-right\"></th>\n <th class=\"has-border-right\"></th>\n <th *ngFor=\"let indicator of indicators\"\n [attr.title]=\"indicator.value.term.name\"\n >\n <he-node-link [node]=\"indicator.value.term\">\n <span>{{indicator.value.term.name | ellipsis:30}}</span>\n </he-node-link>\n </th>\n </tr>\n <tr>\n <th class=\"width-auto\"></th>\n <th class=\"has-border-right\">\n <a [href]=\"baseUrl + '/schema/ImpactAssessment#functionalUnit'\" target=\"_blank\">Functional unit</a>\n </th>\n <th class=\"has-border-right\">\n <a [href]=\"baseUrl + '/schema/ImpactAssessment#product'\" target=\"_blank\">Product</a>\n </th>\n <th *ngFor=\"let indicator of indicators\"\n [attr.title]=\"indicator.value.term.units\"\n >{{indicator.value.term.units}}</th>\n </tr>\n </thead>\n <tbody>\n <ng-container *ngFor=\"let impactAssessment of impactAssessments; trackBy: trackById; let i = index\">\n <tr>\n <td class=\"width-auto\" [attr.title]=\"impactName(impactAssessment)\">\n <he-node-link [node]=\"impactAssessment\">\n <span class=\"is-nowrap has-text-ellipsis\">{{i + 1}}. {{impactName(impactAssessment)}}</span>\n </he-node-link>\n </td>\n <td class=\"has-border-right\" [attr.title]=\"impactAssessment.product?.units\">\n <span class=\"is-nowrap has-text-ellipsis\">1 {{impactAssessment.product?.units}}</span>\n </td>\n <td class=\"has-border-right\" [attr.title]=\"impactAssessment.product?.name\">\n <he-node-link *ngIf=\"impactAssessment.product\" [node]=\"impactAssessment.product\">\n <span>{{impactAssessment.product.name | ellipsis:30}}</span>\n </he-node-link>\n </td>\n <td class=\"is-nowrap\" *ngFor=\"let indicator of indicators\">\n <span *ngIf=\"indicator.value.values[impactAssessment['@id']]; else emptyValue\"\n class=\"trigger-popover\"\n [ngbPopover]=\"details\" [autoClose]=\"'outside'\"\n triggers=\"manual\" #p=\"ngbPopover\" placement=\"left\" container=\"body\"\n (click)=\"togglePopover(p, { data: indicator.value.values[impactAssessment['@id']], impactAssessment: impactAssessment, key: key })\"\n >\n <span pointer>{{propertyValue(indicator.value.values[impactAssessment['@id']].value, indicator.value.term['@id']) | precision:3 | default:'-'}}</span>\n <he-blank-node-state class=\"ml-1\"\n [node]=\"indicator.value.values[impactAssessment['@id']].node\"\n key=\"value\"\n [state]=\"impactAssessment.aggregated ? 'aggregated' : undefined\"\n ></he-blank-node-state>\n </span>\n </td>\n </tr>\n </ng-container>\n </tbody>\n </table>\n </he-data-table>\n\n <he-blank-node-state-notice [dataState]=\"dataState\"></he-blank-node-state-notice>\n </ng-container>\n</div>\n\n<he-impact-assessments-indicator-breakdown-chart *ngIf=\"selectedView === View.breakdown\"\n [impactAssessment]=\"impactAssessments[0]\"\n [indicators]=\"impactAssessments[0][key]\"\n></he-impact-assessments-indicator-breakdown-chart>\n\n<he-impact-assessments-indicators-chart *ngIf=\"impactAssessments.length > 1\" [class.is-hidden]=\"selectedView !== View.chart\"\n [key]=\"key\"\n [impactAssessments]=\"impactAssessments\"\n [filterTermTypes]=\"filterTermTypes\"\n></he-impact-assessments-indicators-chart>\n\n<ng-container *ngIf=\"selectedView === View.logs && !isOriginal\">\n <div class=\"field has-addons pt-2 px-3\" *ngIf=\"impactAssessments.length > 1\">\n <div class=\"control\">\n <span class=\"button is-small is-static\">Select an Impact Assessment</span>\n </div>\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"selectIndex($event)\">\n <option *ngFor=\"let value of impactAssessments; let i = index\" [value]=\"i\">{{i + 1}}. {{impactName(value)}}</option>\n </select>\n </div>\n </div>\n </div>\n\n <he-impact-assessments-products-logs *ngIf=\"selectedIndex >= 0\"\n [key]=\"key\"\n [impactAssessment]=\"impactAssessments[selectedIndex]\"\n [filterTermTypes]=\"filterTermTypes\"\n [originalValues]=\"originalValues[selectedIndex]?.[key]\"\n [recalculatedValues]=\"impactAssessments[selectedIndex]?.[key]\"\n ></he-impact-assessments-products-logs>\n</ng-container>\n\n<he-node-csv-export-confirm *ngIf=\"showDownload\"\n [nodes]=\"impactAssessments\" [filename]=\"'impact-' + key + '.csv'\" [isUpload]=\"false\"\n [headerKeys]=\"['impactAssessment.id', 'impactAssessment.@id', 'impactAssessment.' + key + '.']\"\n (closed)=\"showDownload = false\"\n></he-node-csv-export-confirm>\n\n<ng-template #emptyTable>\n <div class=\"has-text-centered\">\n <span>No data</span>\n </div>\n</ng-template>\n\n<ng-template #emptyValue>\n <span>-</span>\n</ng-template>\n\n<ng-template #details let-node=\"impactAssessment\" let-data=\"data\" let-key=\"key\">\n <p *bindOnce=\"node\">\n <b>\n <span *ngIf=\"data.cycle\">{{cycleLabel(node.cycle)}}</span>\n <span *ngIf=\"!data.cycle\">{{data.name}}</span>\n </b>\n </p>\n <he-node-value-details\n [data]=\"data\" [nodeType]=\"node['@type']\" [dataKey]=\"key\"\n ></he-node-value-details>\n</ng-template>\n\n<ng-template #suggestion let-impact=\"result\" let-t=\"term\">\n <div class=\"is-block\">\n <ngb-highlight [result]=\"impact.name || impact.cycle.name\" [term]=\"t\"></ngb-highlight>\n </div>\n <div class=\"columns is-flex\">\n <div class=\"column\" *ngIf=\"impact.country\">\n <span class=\"pr-1 has-text-underline\">Country:</span>\n <span class=\"is-inline-flex\"><ngb-highlight [result]=\"impact.country.name\" [term]=\"t\"></ngb-highlight></span>\n </div>\n <div class=\"column\" *ngIf=\"impact.product\">\n <span class=\"pr-1 has-text-underline\">Product:</span>\n <span class=\"is-inline-flex\"><ngb-highlight [result]=\"impact.product.name\" [term]=\"t\"></ngb-highlight></span>\n </div>\n <div class=\"column\" *ngIf=\"impact.endDate\">\n <span class=\"pr-1 has-text-underline\">Date:</span>\n <span class=\"is-inline-flex\"><ngb-highlight [result]=\"impact.endDate\" [term]=\"t\"></ngb-highlight></span>\n </div>\n </div>\n</ng-template>\n", styles: ["fa-icon{display:inline-block;width:10px}he-data-table ::ng-deep .table thead tr th:nth-child(2),he-data-table ::ng-deep .table tbody tr td:nth-child(2){max-width:102px;width:102px}\n"], components: [{ type: i1.FaIconComponent, selector: "fa-icon", inputs: ["classes", "icon", "title", "spin", "pulse", "mask", "styles", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "transform", "a11yRole"] }, { type: DataTableComponent, selector: "he-data-table", inputs: ["minHeight", "maxHeight", "nbRows", "small", "height", "width"] }, { type: NodeLinkComponent, selector: "he-node-link", inputs: ["node", "showExternalLink"] }, { type: BlankNodeStateComponent, selector: "he-blank-node-state", inputs: ["nodeType", "dataKey", "key", "node", "state"] }, { type: BlankNodeStateNoticeComponent, selector: "he-blank-node-state-notice", inputs: ["dataState", "showAggregated", "showDeleted", "showUnchanged"] }, { type: ImpactAssessmentsIndicatorBreakdownChartComponent, selector: "he-impact-assessments-indicator-breakdown-chart", inputs: ["impactAssessment", "indicators"] }, { type: ImpactAssessmentsIndicatorsChartComponent, selector: "he-impact-assessments-indicators-chart", inputs: ["impactAssessments", "key", "filterTermTypes"] }, { type: ImpactAssessmentsProductsLogsComponent, selector: "he-impact-assessments-products-logs", inputs: ["impactAssessment", "key", "filterTermTypes", "originalValues", "recalculatedValues"] }, { type: NodeCsvExportConfirmComponent, selector: "he-node-csv-export-confirm", inputs: ["nodes", "filename", "headerKeys", "extension", "isUpload"], outputs: ["closed"] }, { type: NodeValueDetailsComponent, selector: "he-node-value-details", inputs: ["data", "nodeType", "dataKey"] }, { type: i11.NgbHighlight, selector: "ngb-highlight", inputs: ["highlightClass", "result", "term"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1$1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i1$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { type: i1$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i11.NgbPopover, selector: "[ngbPopover]", inputs: ["animation", "autoClose", "placement", "triggers", "container", "disablePopover", "popoverClass", "openDelay", "closeDelay", "ngbPopover", "popoverTitle"], outputs: ["shown", "hidden"], exportAs: ["ngbPopover"] }, { type: BindOnceDirective, selector: "[bindOnce]", inputs: ["bindOnce"] }], pipes: { "ellipsis": EllipsisPipe, "default": DefaultPipe, "precision": PrecisionPipe } });
8159
8198
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: ImpactAssessmentsProductsComponent, decorators: [{
8160
8199
  type: Component$1,
8161
8200
  args: [{