@hestia-earth/ui-components 0.41.34 → 0.41.36

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.
@@ -6,7 +6,7 @@ import { FormsModule, NG_VALUE_ACCESSOR, UntypedFormBuilder, Validators, Reactiv
6
6
  import { NgClass, DecimalPipe, NgTemplateOutlet, KeyValuePipe, DOCUMENT, PlatformLocation, NgStyle, UpperCasePipe, JsonPipe, DatePipe, AsyncPipe, formatDate as formatDate$1 } from '@angular/common';
7
7
  import * as i1$1 from '@ng-bootstrap/ng-bootstrap';
8
8
  import { NgbTooltip, NgbDropdown, NgbDropdownMenu, NgbDropdownToggle, NgbActiveModal, NgbHighlight, NgbModal, NgbDropdownItem, NgbTypeahead, NgbPopover, NgbTooltipModule, NgbDropdownModule, NgbPopoverModule } from '@ng-bootstrap/ng-bootstrap';
9
- import { ReplaySubject, of, mergeMap, shareReplay, delay, map, catchError, distinctUntilChanged, timer, take, first, Subject, combineLatest, filter, tap, pipe, fromEvent, startWith, merge, skip, switchMap, EMPTY, throttleTime, animationFrameScheduler, debounceTime, lastValueFrom, skipUntil, zip, forkJoin, from, reduce, firstValueFrom, mergeAll, toArray, distinct, groupBy } from 'rxjs';
9
+ import { ReplaySubject, of, mergeMap, shareReplay, delay, map, catchError, distinctUntilChanged, timer, take, first, Subject, combineLatest, filter, tap, pipe, fromEvent, startWith, merge, skip, switchMap, EMPTY, throttleTime, animationFrameScheduler, debounceTime, lastValueFrom, skipUntil, zip, mergeAll, groupBy, toArray, forkJoin, from, reduce, firstValueFrom, distinct } from 'rxjs';
10
10
  import { HttpClient } from '@angular/common/http';
11
11
  import get from 'lodash.get';
12
12
  import { SCHEMA_VERSION, SchemaType, NodeType, TermTermType, productTermTermType, nestedSearchableKeys, SiteSiteType, EmissionMethodTier, isExpandable, sortKeysByType, isTypeNode, BlankNodesKey, impactAssessmentTermTermType, measurementTermTermType, emissionTermTermType, inputTermTermType, CycleFunctionalUnit, NonBlankNodesKey, jsonldPath, isTypeValid, isTypeBlankNode, typeToSchemaType, infrastructureTermTermType, managementTermTermType } from '@hestia-earth/schema';
@@ -2872,6 +2872,7 @@ const icons = [
2872
2872
  'greenhouse',
2873
2873
  'guide',
2874
2874
  'guide-overlay',
2875
+ 'heart',
2875
2876
  'help',
2876
2877
  'help-circle',
2877
2878
  'history',
@@ -2912,6 +2913,8 @@ const icons = [
2912
2913
  'private-eye',
2913
2914
  'private-eye-crossed',
2914
2915
  'private-lock',
2916
+ 'private-lock-filled',
2917
+ 'private-unlocked',
2915
2918
  'profile-checkmark',
2916
2919
  'profile-circle',
2917
2920
  'profile-gear',
@@ -7055,8 +7058,50 @@ class HeNodeService {
7055
7058
  .pipe(catchError(() => of('')))
7056
7059
  : this.http.get(url, { params }).pipe(catchError(() => of({})));
7057
7060
  }
7058
- getContributions$(node) {
7059
- return this.http.get(`${this.nodeUrl(node)}/contributions`);
7061
+ getContributions$({ dataState, ...impactAssessment }) {
7062
+ return this.http.get(`${this.nodeUrl(impactAssessment)}/contributions`).pipe(mergeMap(contributions => isEmpty(contributions) ? this.getContributionsFromLog$(impactAssessment) : of(contributions)), catchError(() => this.getContributionsFromLog$(impactAssessment)));
7063
+ }
7064
+ getContributionsFromLog$(impactAssessment) {
7065
+ return this.getLog$({ ...impactAssessment, dataState: DataState.recalculated }).pipe(map(value => (value ? parseLines(value) : [])), mergeAll(), filter(({ data }) => data.logger === 'hestia_earth.models' && data.level === Level.debug), filter(({ data: { message } }) => !!message), map(({ data: { message } }) => parseMessage(message)), filter(message => 'node' in message), map(data => ({
7066
+ modelId: data.model,
7067
+ impactTermId: data['key/term'] || data.term || data.indicator,
7068
+ blankNodeTermId: data.node,
7069
+ coefficient: +data.coefficient
7070
+ })), filter(log => !!log.impactTermId && !!log.blankNodeTermId && !isNaN(log.coefficient)), groupBy(log => [log.impactTermId, log.blankNodeTermId, log.modelId].join('/')), mergeMap(group => group.pipe(toArray())), map((logs) => {
7071
+ const log = logs[0];
7072
+ const coefficient = sum(logs.map(l => l.coefficient));
7073
+ return {
7074
+ ...log,
7075
+ coefficient
7076
+ };
7077
+ }), toArray(), map((logs) => {
7078
+ const emissionsResourceUse = impactAssessment.emissionsResourceUse || [];
7079
+ const impacts = impactAssessment.impacts || [];
7080
+ const result = {
7081
+ emissionsResourceUse: {},
7082
+ impacts: {}
7083
+ };
7084
+ logs.forEach(log => {
7085
+ emissionsResourceUse.forEach((entry, index) => {
7086
+ if (entry.term?.['@id'] === log.blankNodeTermId) {
7087
+ const key = index.toString();
7088
+ result.emissionsResourceUse[key] = result.emissionsResourceUse[key] || {};
7089
+ result.emissionsResourceUse[key][log.impactTermId] =
7090
+ result.emissionsResourceUse[key][log.impactTermId] || {};
7091
+ result.emissionsResourceUse[key][log.impactTermId][log.modelId] = toPrecision((entry.value || 0) * log.coefficient, 5);
7092
+ }
7093
+ });
7094
+ impacts.forEach((entry, index) => {
7095
+ if (entry.term?.['@id'] === log.blankNodeTermId) {
7096
+ const key = index.toString();
7097
+ result.impacts[key] = result.impacts[key] || {};
7098
+ result.impacts[key][log.impactTermId] = result.impacts[key][log.impactTermId] || {};
7099
+ result.impacts[key][log.impactTermId][log.modelId] = toPrecision((entry.value || 0) * log.coefficient, 5);
7100
+ }
7101
+ });
7102
+ });
7103
+ return result;
7104
+ }));
7060
7105
  }
7061
7106
  getErrorLog$({ dataState, aggregated, ...node }) {
7062
7107
  return this.http.get(`${this.nodeUrl(node)}/log/error`, {
@@ -7696,7 +7741,7 @@ const parseLogMultipleValue = (values) => values
7696
7741
  .map(v => (v.filter(Boolean).length === 2 ? v.join(':') : null))
7697
7742
  .filter(Boolean)
7698
7743
  .join('_');
7699
- const parseLog$3 = (log) => ['value' in log, 'coefficient' in log, 'node' in log || 'operation' in log].every(Boolean)
7744
+ const parseLog$1 = (log) => ['value' in log, 'coefficient' in log, 'node' in log || 'operation' in log].every(Boolean)
7700
7745
  ? {
7701
7746
  [log.node || log.operation]: parseLogMultipleValue([
7702
7747
  ['value', log.value],
@@ -7766,7 +7811,7 @@ const groupLog = (group, { logger, term, model, key, should_run, should_merge, r
7766
7811
  else if (!isOrchestrator) {
7767
7812
  data.logs = {
7768
7813
  ...(data.logs || {}),
7769
- ...parseLog$3(log)
7814
+ ...parseLog$1(log)
7770
7815
  };
7771
7816
  }
7772
7817
  if (typeof should_merge !== 'undefined') {
@@ -8515,8 +8560,8 @@ const filterLogValueArray = (value) => {
8515
8560
  ? null
8516
8561
  : values;
8517
8562
  };
8518
- const parseLog$2 = (key, value) => parseLogCompleteness(key, value) || { key, value: filterLogValueArray(value) };
8519
- const parseLogs = (logs) => Object.entries(logs).map(([key, value]) => parseLog$2(key, value));
8563
+ const parseLog = (key, value) => parseLogCompleteness(key, value) || { key, value: filterLogValueArray(value) };
8564
+ const parseLogs = (logs) => Object.entries(logs).map(([key, value]) => parseLog(key, value));
8520
8565
  class NodeLogsModelsLogsComponent {
8521
8566
  constructor() {
8522
8567
  this.logs = input.required(...(ngDevMode ? [{ debugName: "logs" }] : []));
@@ -8528,7 +8573,7 @@ class NodeLogsModelsLogsComponent {
8528
8573
  this.requirementKeys = computed(() => requirementKeys(this.requirements()), ...(ngDevMode ? [{ debugName: "requirementKeys" }] : []));
8529
8574
  this.missingLookups = computed(() => this.logs().missingLookups ?? [], ...(ngDevMode ? [{ debugName: "missingLookups" }] : []));
8530
8575
  this.allLogs = computed(() => [
8531
- ...requirementKeys(this.requirements()).map(key => parseLog$2(key, this.requirements()[key])),
8576
+ ...requirementKeys(this.requirements()).map(key => parseLog(key, this.requirements()[key])),
8532
8577
  ...parseLogs(this.logs()?.logs ?? {})
8533
8578
  ].filter(v => v.value !== null), ...(ngDevMode ? [{ debugName: "allLogs" }] : []));
8534
8579
  }
@@ -13747,24 +13792,9 @@ const searchParams = (should) => ({
13747
13792
  }
13748
13793
  }
13749
13794
  });
13750
- const parseLog$1 = (data) => ({
13751
- indicator: data['key/term'] || data.term || data.indicator,
13752
- contributor: data.node,
13753
- coefficient: +data.coefficient,
13754
- modelId: data.model || 'Unknown',
13755
- weightedValue: +data.value * +data.coefficient,
13756
- value: +data.value
13757
- });
13758
13795
  const defaultIndicatorsModelId = 'defaultIndicatorsModelId';
13759
13796
  const defaultIndicatorsModelName = 'Default Indicators (multi-model)';
13760
13797
  const warnings = (logs, terms) => [!logs.every(log => terms[log.indicator] && terms[log.contributor]) && 'missing-terms'].filter(Boolean);
13761
- const filterLog = (indicators, log) => [
13762
- !!log.indicator,
13763
- !!log.contributor,
13764
- !isNaN(log.weightedValue),
13765
- log.coefficient > 0,
13766
- indicators.some(eru => eru.term['@id'] === log.indicator)
13767
- ].every(Boolean);
13768
13798
  const parseLogValues = (impactAssessment, values) => {
13769
13799
  const log = values[0];
13770
13800
  const { weightedTotal, total } = values.reduce((prev, curr) => ({
@@ -13804,7 +13834,40 @@ const parseLogValues = (impactAssessment, values) => {
13804
13834
  const inputs = Object.values(inputsObj);
13805
13835
  return { ...log, weightedValue: weightedTotal, value: total, inputs };
13806
13836
  };
13807
- const parseNodeLogs$ = (impactAssessment, indicators, lines) => from(lines).pipe(filter(({ data }) => data.logger === 'hestia_earth.models' && data.level === Level.debug), filter(({ data: { message } }) => !!message), map(({ data: { message } }) => parseMessage(message)), filter(message => 'node' in message), map(data => parseLog$1(data)), filter(log => filterLog(indicators, log)), groupBy(log => [log.indicator, log.contributor, log.modelId].join('/')), mergeMap(group => group.pipe(toArray())), map(data => parseLogValues(impactAssessment, data)), toArray());
13837
+ const processContributions$1 = (record, nodes) => Object.entries(record || {}).flatMap(([index, contributions]) => {
13838
+ const indicator = nodes[+index];
13839
+ return indicator
13840
+ ? Object.entries(contributions).flatMap(([impactTermId, modelContr]) => Object.entries(modelContr).map(([modelId, weightedValue]) => {
13841
+ const contributor = indicator.term['@id'];
13842
+ const value = indicator.value || 0;
13843
+ const coefficient = value !== 0 ? weightedValue / value : 0;
13844
+ // only get contributions with positive coefficient
13845
+ return coefficient > 0
13846
+ ? {
13847
+ indicator: impactTermId,
13848
+ contributor,
13849
+ coefficient,
13850
+ modelId,
13851
+ weightedValue,
13852
+ value
13853
+ }
13854
+ : null;
13855
+ }))
13856
+ : null;
13857
+ });
13858
+ const parseContributions$1 = (impactAssessment, contributions) => {
13859
+ const allLogs = [
13860
+ ...processContributions$1(contributions.emissionsResourceUse, impactAssessment.emissionsResourceUse || []),
13861
+ ...processContributions$1(contributions.impacts, impactAssessment.impacts || [])
13862
+ ].filter(Boolean);
13863
+ const grouped = allLogs.reduce((acc, log) => {
13864
+ const key = [log.indicator, log.contributor, log.modelId].join('/');
13865
+ acc[key] = acc[key] || [];
13866
+ acc[key].push(log);
13867
+ return acc;
13868
+ }, {});
13869
+ return Object.values(grouped).map(logs => parseLogValues(impactAssessment, logs));
13870
+ };
13808
13871
  class ImpactAssessmentsGraphComponent {
13809
13872
  constructor() {
13810
13873
  this.searchService = inject(HeSearchService);
@@ -13830,32 +13893,19 @@ class ImpactAssessmentsGraphComponent {
13830
13893
  ...(this.selectedImpactAssessment()?.impacts ?? [])
13831
13894
  ], ...(ngDevMode ? [{ debugName: "indicators" }] : []));
13832
13895
  this.nodeLogsResource = rxResource({
13833
- params: () => ({ selectedImpactAssessment: this.selectedImpactAssessment() }),
13834
- stream: ({ params: { selectedImpactAssessment } }) => isEmpty(selectedImpactAssessment)
13835
- ? of([])
13836
- : this.nodeService
13837
- .getLog$({
13838
- ...selectedImpactAssessment,
13839
- dataState: DataState.recalculated
13840
- })
13841
- .pipe(map(value => (value ? parseLines(value) : [])))
13842
- });
13843
- this.parsedNodeLogsResource = rxResource({
13844
13896
  params: () => ({
13845
- isRecalculated: this.isRecalculated(),
13846
- logs: this.nodeLogsResource.value(),
13847
- indicators: this.indicators(),
13848
- impactAssessment: this.selectedImpactAssessment()
13897
+ selectedImpactAssessment: this.selectedImpactAssessment(),
13898
+ isRecalculated: this.isRecalculated()
13849
13899
  }),
13850
- stream: ({ params: { isRecalculated, logs, indicators, impactAssessment } }) => [!!logs?.length, isRecalculated, !!indicators?.length].every(Boolean)
13851
- ? parseNodeLogs$(impactAssessment, indicators, logs).pipe(catchError(err => {
13900
+ stream: ({ params: { selectedImpactAssessment, isRecalculated } }) => !selectedImpactAssessment || !isRecalculated
13901
+ ? of([])
13902
+ : this.nodeService.getContributions$(selectedImpactAssessment).pipe(map(contributions => parseContributions$1(selectedImpactAssessment, contributions)), catchError(err => {
13852
13903
  console.error(err);
13853
13904
  this.error.set(err.toString());
13854
13905
  return of([]);
13855
13906
  }))
13856
- : of([])
13857
13907
  });
13858
- this.nodeLogs = computed(() => this.parsedNodeLogsResource.value() ?? [], ...(ngDevMode ? [{ debugName: "nodeLogs" }] : []));
13908
+ this.nodeLogs = computed(() => this.nodeLogsResource.value() ?? [], ...(ngDevMode ? [{ debugName: "nodeLogs" }] : []));
13859
13909
  this.logTermIds = computed(() => unique(this.nodeLogs()
13860
13910
  .flatMap(l => [l.contributor, l.indicator, ...l.inputs.map(i => i.id)])
13861
13911
  .filter(termId => !this.initialTerms()?.[termId])), ...(ngDevMode ? [{ debugName: "logTermIds" }] : []));
@@ -13888,7 +13938,7 @@ class ImpactAssessmentsGraphComponent {
13888
13938
  (this.selectedModelId() === defaultIndicatorsModelId
13889
13939
  ? getDefaultModelId(log.indicator)
13890
13940
  : this.selectedModelId())), ...(ngDevMode ? [{ debugName: "chartData" }] : []));
13891
- this.loading = computed(() => [this.parsedNodeLogsResource.isLoading(), this.allTermsResource.isLoading()].some(Boolean), ...(ngDevMode ? [{ debugName: "loading" }] : []));
13941
+ this.loading = computed(() => [this.nodeLogsResource.isLoading(), this.allTermsResource.isLoading()].some(Boolean), ...(ngDevMode ? [{ debugName: "loading" }] : []));
13892
13942
  this.showChart = computed(() => [!isEmpty(this.chartData()), !isEmpty(this.allTerms()), !this.loading(), !this.error(), !this.showWarnings()].every(Boolean), ...(ngDevMode ? [{ debugName: "showChart" }] : []));
13893
13943
  effect(() => {
13894
13944
  const defaultId = this.filteredImpactAssessments()?.[0]?.['@id'];
@@ -13934,24 +13984,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
13934
13984
  }]
13935
13985
  }] });
13936
13986
 
13937
- const parseLog = (data) => ({
13938
- modelId: data.model,
13939
- impactTermId: data['key/term'] || data.term || data.indicator,
13940
- blankNodeTermId: data.node,
13941
- coefficient: +data.coefficient,
13942
- value: +data.value * +data.coefficient
13943
- });
13944
13987
  const filterTermTypes = [TermTermType.emission, TermTermType.characterisedIndicator];
13945
- const csvHeaders = [
13946
- 'Impact',
13947
- 'Impact Unit',
13948
- 'Method',
13949
- 'Emission',
13950
- 'Value',
13951
- 'Inputs',
13952
- 'Inputs value',
13953
- 'Functional Unit'
13954
- ];
13955
13988
  const logsTotalValue = (logs, includeNegativeValues) => sum((includeNegativeValues ? logs : logs.filter(curr => curr.value >= 0)).map(v => v.value));
13956
13989
  const valueRatio = (value, total) => (total === 0 ? 0 : toPrecision((value * 100) / total, 2));
13957
13990
  const chartLabel = (value, total) => {
@@ -13963,15 +13996,50 @@ const chartBreakdownLabel = (logs, total, maxValues) => {
13963
13996
  return values.map(({ blankNodeTermId, value }) => `${blankNodeTermId}: ${chartLabel(value, total)}`).join('</br>');
13964
13997
  };
13965
13998
  const logToCsv = (logs, impact) => [
13966
- csvHeaders.join(','),
13999
+ ['Impact', 'Impact Unit', 'Method', 'Emission', 'Value', 'Inputs', 'Functional Unit'].join(','),
13967
14000
  ...logs
13968
14001
  .sort((a, b) => a.impactTermId.localeCompare(b.impactTermId))
13969
- .flatMap(({ impactTermId, impactTermUnits, modelId, blankNodeTermId, value, inputs }) => [
13970
- [impactTermId, impactTermUnits, modelId, blankNodeTermId, value, '', ''],
13971
- ...inputs.map(v => [impactTermId, impactTermUnits, modelId, blankNodeTermId, '', v.name, v.value])
13972
- ])
13973
- .map(v => [...v, impact.product?.term?.units].join(','))
14002
+ .map(({ impactTermId, impactTermUnits, modelId, blankNodeTermId, value, inputs }) => [
14003
+ impactTermId,
14004
+ impactTermUnits,
14005
+ modelId,
14006
+ blankNodeTermId,
14007
+ value,
14008
+ inputs.join(';'),
14009
+ impact.product?.term?.units
14010
+ ].join(','))
13974
14011
  ].join('\n');
14012
+ const processContributions = (record, nodes, impacts) => Object.entries(record || {}).flatMap(([index, impactContr]) => {
14013
+ const indicator = nodes[+index];
14014
+ return indicator
14015
+ ? Object.entries(impactContr).flatMap(([impactTermId, modelContr]) => {
14016
+ const impact = impacts?.find(v => v.term['@id'] === impactTermId);
14017
+ return (impact &&
14018
+ Object.entries(modelContr).map(([modelId, value]) => {
14019
+ const inputs = (indicator.inputs || []).map(v => v['@id']);
14020
+ return {
14021
+ modelId,
14022
+ impactTermId,
14023
+ impactTermUnits: impact.term?.units,
14024
+ blankNodeTermId: indicator.term['@id'],
14025
+ value: toPrecision(value, 3),
14026
+ inputs
14027
+ };
14028
+ }));
14029
+ })
14030
+ : null;
14031
+ });
14032
+ const parseContributions = (impactAssessment, contributions) => [
14033
+ ...processContributions(contributions.emissionsResourceUse, impactAssessment.emissionsResourceUse || [], impactAssessment?.impacts || []),
14034
+ ...processContributions(contributions.impacts, impactAssessment.impacts || [], impactAssessment?.endpoints || [])
14035
+ ].filter(Boolean);
14036
+ const groupLogsById = (logs) => Object.values(logs.reduce((prev, log) => {
14037
+ const key = log.blankNodeTermId;
14038
+ prev[key] = prev[key] || { ...log, value: 0 };
14039
+ prev[key].value += log.value;
14040
+ prev[key].inputs = unique([...prev[key].inputs, ...(log.inputs || [])]);
14041
+ return prev;
14042
+ }, {}));
13975
14043
  class ImpactAssessmentsIndicatorBreakdownChartComponent {
13976
14044
  constructor() {
13977
14045
  this.searchService = inject(HeSearchService);
@@ -13985,42 +14053,16 @@ class ImpactAssessmentsIndicatorBreakdownChartComponent {
13985
14053
  this.selectedCategory = signal(undefined, ...(ngDevMode ? [{ debugName: "selectedCategory" }] : []));
13986
14054
  this.logsResource = rxResource({
13987
14055
  params: () => ({
13988
- impactAssessment: this.impactAssessment(),
13989
- impacts: this.impacts()
14056
+ impactAssessment: this.impactAssessment()
13990
14057
  }),
13991
- stream: ({ params: { impactAssessment, impacts } }) => impactAssessment
13992
- ? this.nodeService.getLog$({ ...impactAssessment, dataState: DataState.recalculated }).pipe(map(value => (value ? parseLines(value) : [])), mergeAll(), filter(({ data }) => data.logger === 'hestia_earth.models' && data.level === Level.debug), filter(({ data: { message } }) => !!message), map(({ data: { message } }) => parseMessage(message)), filter(message => 'node' in message), map(parseLog), filter(log => !!log.impactTermId && !!log.blankNodeTermId && !isNaN(log.value)), groupBy(log => [log.impactTermId, log.blankNodeTermId, log.modelId].join('/')), mergeMap(group => group.pipe(toArray())), map((values) => {
13993
- const log = values[0];
13994
- const total = logsTotalValue(values, true);
13995
- const blankNodes = [
13996
- ...(impactAssessment?.emissionsResourceUse ?? []),
13997
- ...(impactAssessment?.impacts ?? [])
13998
- ].filter(v => v.term['@id'] === log.blankNodeTermId);
13999
- const inputs = blankNodes
14000
- .filter(v => v.inputs?.length)
14001
- .map(v => ({
14002
- name: v.inputs.map(i => i['@id']).join(';'),
14003
- value: toPrecision(v.value * log.coefficient, 3)
14004
- }));
14005
- const inputsValue = inputs.reduce((prev, curr) => prev + curr.value, 0);
14006
- const impact = impacts?.find(v => v.term['@id'] === log.impactTermId);
14007
- // logs might exist but impact was not added => skip logs
14008
- return impact
14009
- ? {
14010
- ...log,
14011
- impactTermUnits: impact.term?.units,
14012
- value: toPrecision(total, 3),
14013
- inputs,
14014
- inputsValue
14015
- }
14016
- : undefined;
14017
- }), filter(log => !!log), toArray())
14018
- : of([])
14058
+ stream: ({ params: { impactAssessment } }) => this.nodeService
14059
+ .getContributions$(impactAssessment)
14060
+ .pipe(map(contributions => parseContributions(impactAssessment, contributions)))
14019
14061
  });
14020
14062
  this.logs = computed(() => (this.logsResource.value() ?? [])
14021
14063
  .filter(({ impactTermId, modelId }) => impactTermId === this.selectedTermId() && (!this.selectedMethodId() || modelId === this.selectedMethodId()))
14022
14064
  .sort((a, b) => b.value - a.value), ...(ngDevMode ? [{ debugName: "logs" }] : []));
14023
- this.nonZeroLogs = computed(() => this.logs().filter(log => log.value !== 0), ...(ngDevMode ? [{ debugName: "nonZeroLogs" }] : []));
14065
+ this.nonZeroLogs = computed(() => groupLogsById(this.logs()).filter(log => log.value !== 0), ...(ngDevMode ? [{ debugName: "nonZeroLogs" }] : []));
14024
14066
  this.emissions = toSignal(this.searchService
14025
14067
  .search$({
14026
14068
  fields: ['@type', '@id', 'name'],
@@ -14046,10 +14088,6 @@ class ImpactAssessmentsIndicatorBreakdownChartComponent {
14046
14088
  .filter(Boolean)
14047
14089
  .filter(value => this.logs().some(log => log.modelId === value['@id']))), ...(ngDevMode ? [{ debugName: "methods" }] : []));
14048
14090
  this.selectedMethod = computed(() => this.methods().find(term => term['@id'] == this.selectedMethodId()), ...(ngDevMode ? [{ debugName: "selectedMethod" }] : []));
14049
- this.impacts = computed(() => [
14050
- ...(this.impactAssessment()?.impacts || []),
14051
- ...(this.impactAssessment()?.endpoints || [])
14052
- ], ...(ngDevMode ? [{ debugName: "impacts" }] : []));
14053
14091
  this.noData = computed(() => this.nonZeroLogs()?.length === 0, ...(ngDevMode ? [{ debugName: "noData" }] : []));
14054
14092
  this.values = computed(() => this.nonZeroLogs().map((value, index) => ({
14055
14093
  ...value,
@@ -14186,7 +14224,6 @@ class ImpactAssessmentsIndicatorsChartComponent {
14186
14224
  }, {}))
14187
14225
  });
14188
14226
  this.contributionsPerImpactAssessment = computed(() => this.contributionsResource.value() ?? {}, ...(ngDevMode ? [{ debugName: "contributionsPerImpactAssessment" }] : []));
14189
- this.enableContributions = computed(() => Object.values(this.contributionsPerImpactAssessment())?.length === this.impactAssessments()?.length, ...(ngDevMode ? [{ debugName: "enableContributions" }] : []));
14190
14227
  this.contributionKey = computed(() => this.key() === 'impacts'
14191
14228
  ? 'emissionsResourceUse'
14192
14229
  : this.key() === 'endpoints'
@@ -14197,6 +14234,8 @@ class ImpactAssessmentsIndicatorsChartComponent {
14197
14234
  .flatMap(impact => impact[this.contributionKey()].map(v => v.term))
14198
14235
  .filter(Boolean)
14199
14236
  : []), ...(ngDevMode ? [{ debugName: "contributionTerms" }] : []));
14237
+ this.enableContributions = computed(() => this.contributionKey() &&
14238
+ Object.values(this.contributionsPerImpactAssessment())?.length === this.impactAssessments()?.length, ...(ngDevMode ? [{ debugName: "enableContributions" }] : []));
14200
14239
  this.indicatorPerImpactAssessment = computed(() => groupNodesByTerm(this.impactAssessments(), this.key()), ...(ngDevMode ? [{ debugName: "indicatorPerImpactAssessment" }] : []));
14201
14240
  this.terms = computed(() => Object.values(this.indicatorPerImpactAssessment() ?? {})
14202
14241
  .filter(({ term, values }) => termAllowed$1(this.filterTermTypes(), term) &&
@@ -14214,7 +14253,7 @@ class ImpactAssessmentsIndicatorsChartComponent {
14214
14253
  }, {});
14215
14254
  return Object.assign(prev, methodsPerTerm);
14216
14255
  }, {}), ...(ngDevMode ? [{ debugName: "termToMethods" }] : []));
14217
- this.methods = computed(() => this.termToMethods()[this.selectedTerm()?.['@id']], ...(ngDevMode ? [{ debugName: "methods" }] : []));
14256
+ this.methods = computed(() => unique(this.termToMethods()[this.selectedTerm()?.['@id']]), ...(ngDevMode ? [{ debugName: "methods" }] : []));
14218
14257
  this.selectedMethod = computed(() => this.methods().find(term => term['@id'] == this.selectedMethodId()), ...(ngDevMode ? [{ debugName: "selectedMethod" }] : []));
14219
14258
  this.groupedValues = computed(() => this.indicatorPerImpactAssessment()?.[this.selectedTerm()?.name]?.values || {}, ...(ngDevMode ? [{ debugName: "groupedValues" }] : []));
14220
14259
  this.contributionData = computed(() => {
@@ -14290,8 +14329,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
14290
14329
  var View$1;
14291
14330
  (function (View) {
14292
14331
  View["table"] = "Table";
14293
- View["chart"] = "Chart";
14294
14332
  View["breakdown"] = "Breakdown";
14333
+ View["chart"] = "Compare";
14295
14334
  View["logs"] = "Recalculations logs";
14296
14335
  })(View$1 || (View$1 = {}));
14297
14336
  const viewIcon$1 = {