@hestia-earth/ui-components 0.42.17 → 0.42.18

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.
@@ -150,6 +150,12 @@ const nodeDefaultLabel = {
150
150
  const defaultLabel = (node) => node
151
151
  ? (node['@type'] in nodeDefaultLabel ? nodeDefaultLabel[node['@type']](node) : node.name) || node['@id'] || node.id
152
152
  : '';
153
+ /**
154
+ * Stable `@for` track key for a node that uniquely identifies it across data versions.
155
+ * Two nodes with the same `@id` but a different `dataVersion` (e.g. current vs a compared version)
156
+ * produce distinct keys, so lists reconcile instead of colliding or being re-created.
157
+ */
158
+ const nodeVersionKey = (node) => `${node?.['@id']}#${node?.dataVersion || ''}`;
153
159
  const repeat = (times = 0) => Array.from(Array(times), Math.random);
154
160
  const copyObject = (data) => (data ? JSON.parse(JSON.stringify(data)) : null);
155
161
  const isEqual = (a, b) => JSON.stringify(a) === JSON.stringify(b);
@@ -7385,7 +7391,12 @@ const nodeTypeUrl = (apiBaseUrl, type) => (type ? `${apiBaseUrl}/${nodeTypeToPar
7385
7391
  * @returns The full url.
7386
7392
  */
7387
7393
  const nodeUrl = (apiBaseUrl, { dataState, ...node }) => `${nodeTypeUrl(apiBaseUrl, node['@type'] || node.type)}/${node['@id'] || node.id}${dataState ? `?dataState=${dataState}` : ''}`;
7388
- const nodeLogsUrl = (apiBaseUrl, { dataState, ...node }) => `${nodeUrl(apiBaseUrl, node)}/log${dataState ? `?dataState=${dataState}` : ''}`;
7394
+ const nodeLogsUrl = (apiBaseUrl, { dataState, dataVersion, ...node }) => {
7395
+ const query = [dataState ? `dataState=${dataState}` : '', dataVersion ? `dataVersion=${dataVersion}` : '']
7396
+ .filter(Boolean)
7397
+ .join('&');
7398
+ return `${nodeUrl(apiBaseUrl, node)}/log${query ? `?${query}` : ''}`;
7399
+ };
7389
7400
  const lookupUrl = (filename) => filename.startsWith('http') ? filename : `${glossaryBaseUrl(false)}/lookups/${filename}.csv`;
7390
7401
  class RelatedNodeResult {
7391
7402
  constructor() {
@@ -7450,16 +7461,19 @@ class HeNodeService {
7450
7461
  headers: dataVersionHeader(dataVersion)
7451
7462
  });
7452
7463
  }
7453
- getRelated$(node, relatedType, limit = 100, offset = 0, relationship) {
7464
+ getRelated$(node, relatedType, limit = 100, offset = 0, relationship, dataVersion) {
7454
7465
  return this.http
7455
7466
  .get(`${this.nodeUrl(node)}/${nodeTypeToParam(relatedType)}`, {
7456
- params: filterParams({ limit, offset, relationship })
7467
+ params: filterParams({ limit, offset, relationship, dataVersion })
7457
7468
  })
7458
7469
  .pipe(catchError(() => of({ count: 0, results: [] })));
7459
7470
  }
7460
- getLog$({ dataState, aggregated, ...node }, format = 'text') {
7471
+ getLog$({ dataState, aggregated, dataVersion, ...node }, format = 'text') {
7461
7472
  const url = `${this.nodeUrl(node)}/log`;
7462
- const params = filterParams(dataState === DataState.recalculated ? { dataState } : { aggregated });
7473
+ const params = filterParams({
7474
+ ...(dataState === DataState.recalculated ? { dataState } : { aggregated }),
7475
+ dataVersion
7476
+ });
7463
7477
  return format === 'text'
7464
7478
  ? this.http
7465
7479
  .get(url, {
@@ -7554,7 +7568,7 @@ const sortNodes = (values) => values?.length
7554
7568
  ? orderBy(values.filter(Boolean), ['original.aggregated', 'original.site.@id', 'original.cycle.@id', 'original.@id'], ['asc', 'asc', 'asc', 'asc'])
7555
7569
  : [];
7556
7570
  const isAggregated$1 = (id = '') => !!id?.match(/^[a-zA-Z]+[-][a-zA-Z]+[-][\d]{4,}[-][\d]{4,}/g);
7557
- const nodeRequestId = (node, params = {}) => [node['@id'], params?.version].filter(Boolean).join('#');
7571
+ const nodeRequestId = (node, params = {}) => [node['@id'], params?.version, params?.dataVersion].filter(Boolean).join('#');
7558
7572
  const pickHeaderKeys = ['stage', 'maxstage', 'error', 'last-modified'];
7559
7573
  const mergeDataWithHeaders = (data, headers) => ({
7560
7574
  ...data,
@@ -7591,7 +7605,10 @@ class HeNodeStoreService {
7591
7605
  const request = forkJoin(dataStates.reduce((prev, dataState) => ({
7592
7606
  ...prev,
7593
7607
  [dataState]: this.nodeService.getWithHeaders$({ ...node, dataState }, params).pipe(map(({ data, headers }) => mergeDataWithHeaders(dataTransform(data), headers)), catchError(err => (dataState === DataState.original ? throwError(() => err) : of(undefined))))
7594
- }), {})).pipe(shareReplay({ bufferSize: 1, refCount: true }), map((values) => Object.fromEntries(Object.values(DataState).map(dataState => [
7608
+ }), {})).pipe(
7609
+ // cache the completed result so an already-loaded node is never re-fetched on re-subscription
7610
+ // (refCount: true would drop the buffer once the first load completes, defeating the addNode dedup)
7611
+ shareReplay({ bufferSize: 1, refCount: false }), map((values) => Object.fromEntries(Object.values(DataState).map(dataState => [
7595
7612
  dataState,
7596
7613
  values[dataState] || values[DataState.original] || node
7597
7614
  ]))), map(values => ({
@@ -9195,7 +9212,8 @@ const groupLogsByModel = (data = '', groupBySubValue = false, groupByAnimal = fa
9195
9212
  const logNodeFor = (node) => ({
9196
9213
  '@type': node['@type'],
9197
9214
  '@id': node['@id'],
9198
- dataState: node.aggregated && node['@type'] !== NodeType.ImpactAssessment ? DataState.original : DataState.recalculated
9215
+ dataState: node.aggregated && node['@type'] !== NodeType.ImpactAssessment ? DataState.original : DataState.recalculated,
9216
+ dataVersion: node.dataVersion
9199
9217
  });
9200
9218
  class NodeLogsModelsService {
9201
9219
  constructor() {
@@ -9763,7 +9781,12 @@ const withRowLabels = (group) => {
9763
9781
  ...group,
9764
9782
  rows: group.rows.map(row => {
9765
9783
  const { segments, scalars } = resolveRowIdentity(row, fallbackKeys, keepNoisy, cycleOwned);
9766
- return { ...row, identitySegments: segments, identityScalars: scalars, identityLabel: identityScalarsLabel(scalars) };
9784
+ return {
9785
+ ...row,
9786
+ identitySegments: segments,
9787
+ identityScalars: scalars,
9788
+ identityLabel: identityScalarsLabel(scalars)
9789
+ };
9767
9790
  })
9768
9791
  };
9769
9792
  };
@@ -10705,7 +10728,7 @@ class NodeJLogModelsComponent {
10705
10728
  return model.methodId;
10706
10729
  }
10707
10730
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NodeJLogModelsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
10708
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: NodeJLogModelsComponent, isStandalone: true, selector: "he-node-jlog-models", inputs: { node: { classPropertyName: "node", publicName: "node", isSignal: true, isRequired: true, transformFunction: null }, nodeKey: { classPropertyName: "nodeKey", publicName: "nodeKey", isSignal: true, isRequired: false, transformFunction: null }, originalValues: { classPropertyName: "originalValues", publicName: "originalValues", isSignal: true, isRequired: false, transformFunction: null }, recalculatedValues: { classPropertyName: "recalculatedValues", publicName: "recalculatedValues", isSignal: true, isRequired: false, transformFunction: null }, filterTermTypes: { classPropertyName: "filterTermTypes", publicName: "filterTermTypes", isSignal: true, isRequired: false, transformFunction: null }, filterTermTypesLabel: { classPropertyName: "filterTermTypesLabel", publicName: "filterTermTypesLabel", isSignal: true, isRequired: false, transformFunction: null }, cycle: { classPropertyName: "cycle", publicName: "cycle", isSignal: true, isRequired: false, transformFunction: null }, jlog: { classPropertyName: "jlog", publicName: "jlog", isSignal: true, isRequired: false, transformFunction: null }, jlogParentKey: { classPropertyName: "jlogParentKey", publicName: "jlogParentKey", isSignal: true, isRequired: false, transformFunction: null }, jlogParentIndex: { classPropertyName: "jlogParentIndex", publicName: "jlogParentIndex", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<he-data-table class=\"is-mt-2 is-mb-1 is-bordered\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n <tr>\n <th class=\"width-auto has-border-right\">\n @if (enableFilterByTerm()) {\n <div class=\"field is-pb-1\">\n <div class=\"control is-expanded has-icons-right\">\n <input\n class=\"input search-input is-small\"\n [ngModel]=\"term()\"\n name=\"term\"\n placeholder=\"Select entry by name\"\n [ngbTypeahead]=\"suggestTerm\"\n [resultFormatter]=\"termFormatter\"\n [inputFormatter]=\"termFormatter\"\n [focusFirst]=\"true\"\n (focus)=\"typeaheadFocus($event)\"\n (selectItem)=\"term.set($event.item)\"\n container=\"body\"\n popupClass=\"is-small\" />\n <a class=\"icon is-small is-right\" [class.is-hidden]=\"!term()\" (click)=\"term.set(undefined)\">\n <he-svg-icon name=\"xmark\" />\n </a>\n </div>\n </div>\n }\n </th>\n @if (isBlankNodes()) {\n <th class=\"has-border-right\"><span>Units</span></th>\n }\n <th class=\"has-border-right\"><span>Original</span></th>\n <th class=\"has-border-right\"><span>Recalculated</span></th>\n @if (isBlankNodes()) {\n <th class=\"has-border-right\"><span>Difference</span></th>\n }\n @for (c of methodModelsCount() | times; track i; let i = $index) {\n <th class=\"has-border-right\">\n <span>Model {{ i + 1 }}</span>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @if (groups().length === 0) {\n <tr>\n <td class=\"has-border-right has-text-centered\" colspan=\"100\">\n <p class=\"is-p-1\">No recalculation logs to show.</p>\n </td>\n </tr>\n }\n @for (group of groups(); track trackByGroup($index, group)) {\n @let single = group.rows.length === 1;\n <tr [class.has-sub-rows]=\"group.canOpen\" [class.is-open]=\"group.isOpen\">\n <td class=\"width-auto has-border-right is-nowrap\" [attr.title]=\"group.term?.name\">\n <div class=\"is-flex is-align-items-flex-start is-gap-4\">\n @if (group.canOpen) {\n <a class=\"open-node\" (click)=\"toggleGroup(group)\">\n <he-svg-icon [name]=\"group.isOpen ? 'chevron-down' : 'chevron-right'\" />\n </a>\n }\n @if (group.term) {\n <he-node-link class=\"is-inline-block is-pre-wrap is-pr-2\" [node]=\"group.term\">\n <span class=\"break-word\" [innerHtml]=\"group.term?.name | compound: group.term?.termType\"></span>\n </he-node-link>\n } @else if (group.key) {\n @if (nodeKey() === 'completeness') {\n <a [href]=\"schemaBaseUrl + '/Completeness#' + group.key\" target=\"_blank\">\n <span>{{ group.key | keyToLabel }}</span>\n </a>\n } @else {\n <a [href]=\"schemaBaseUrl + '/' + nodeType() + '#' + group.key\" target=\"_blank\">\n <span>{{ group.key | keyToLabel }}</span>\n </a>\n }\n }\n </div>\n </td>\n @if (single) {\n <ng-container *ngTemplateOutlet=\"valueCells; context: { row: group.rows[0] }\" />\n <ng-container *ngTemplateOutlet=\"modelCells; context: { row: group.rows[0], open: group.isOpen }\" />\n } @else {\n @if (isBlankNodes()) {\n <td class=\"has-border-right\">\n @if (group.term) {\n <span class=\"is-nowrap\" [innerHtml]=\"group.term.units | compound\"></span>\n }\n </td>\n }\n <td class=\"has-border-right\">\n @if (!isEmptyValue(group.originalValue)) {\n <ng-container *ngTemplateOutlet=\"valueContent; context: { value: group.originalValue }\" />\n } @else {\n -\n }\n </td>\n <td class=\"has-border-right\">\n @if (group.isRecalculated && !isEmptyValue(group.recalculatedValue)) {\n @if (group.recalculatedFormula) {\n <span\n class=\"has-formula\"\n [ngbPopover]=\"group.recalculatedFormula\"\n popoverClass=\"is-narrow\"\n triggers=\"click\"\n container=\"body\">\n <ng-container *ngTemplateOutlet=\"valueContent; context: { value: group.recalculatedValue }\" />\n </span>\n } @else {\n <ng-container *ngTemplateOutlet=\"valueContent; context: { value: group.recalculatedValue }\" />\n }\n } @else {\n -\n }\n </td>\n @if (isBlankNodes()) {\n <td class=\"has-border-right is-nowrap\">\n @if (\n group.isRecalculated && !isEmptyValue(group.originalValue) && !isEmptyValue(group.recalculatedValue)\n ) {\n <he-blank-node-value-delta\n [value]=\"group.recalculatedValue\"\n [originalValue]=\"group.originalValue\"\n [useCustomFunctions]=\"false\" />\n } @else {\n -\n }\n </td>\n }\n <td class=\"has-border-right\" [attr.colspan]=\"methodModelsCount()\">\n <span>Expand to see logs (</span>\n @if (group.allSucceeded) {\n <span>all succeeded</span>\n <he-svg-icon class=\"is-ml-1 has-text-success\" name=\"checkmark\" />\n } @else {\n <span>some failed</span>\n <he-svg-icon class=\"is-ml-1 has-text-danger\" name=\"xmark\" />\n }\n <span>)</span>\n </td>\n }\n </tr>\n\n @if (single) {\n <ng-container\n *ngTemplateOutlet=\"subRowsTemplate; context: { row: group.rows[0], open: group.isOpen, nested: false }\" />\n } @else if (group.isOpen) {\n @for (row of group.rows; track trackByRow($index, row)) {\n <tr [class.has-sub-rows]=\"row.canOpen\" [class.is-sub-row]=\"true\">\n <td class=\"width-auto has-border-right\">\n <div class=\"is-flex is-align-items-flex-start is-gap-4 is-pl-3\">\n @if (row.canOpen) {\n <a class=\"open-node\" (click)=\"toggleRow(row)\">\n <he-svg-icon [name]=\"row.isOpen ? 'chevron-down' : 'chevron-right'\" />\n </a>\n }\n <he-svg-icon class=\"sub-sub-row-icon\" name=\"chevron-double-right\" />\n <div class=\"is-flex is-align-items-center is-flex-wrap-wrap is-gap-4\">\n @if (row.isFailed) {\n <span class=\"has-text-danger\">failed</span>\n } @else if (row.identitySegments.length || row.identityScalars.length) {\n @for (segment of row.identitySegments; track segment.field; let s = $index) {\n @if (s > 0) {<span>\u00B7</span>}\n <span>{{ segment.field | keyToLabel }}:</span>\n @for (term of segment.terms; track term['@id']) {\n <he-node-link class=\"is-inline-block\" [node]=\"term\">\n <span class=\"break-word\" [innerHtml]=\"term.name | compound: term.termType\"></span>\n </he-node-link>\n }\n }\n @for (scalar of row.identityScalars; track scalar.key; let i = $index) {\n <span class=\"break-word\">\n @if (i > 0 || row.identitySegments.length) {\u00B7}\n @if (scalar.field && row.type) {\n <a [href]=\"schemaBaseUrl + '/' + row.type + '#' + scalar.field\" target=\"_blank\">{{\n scalar.key\n }}</a\n >@if (scalar.value) {: {{ scalar.value }}}\n } @else {\n {{ scalar.key }}@if (scalar.value) {: {{ scalar.value }}}\n }\n </span>\n }\n } @else {\n <span class=\"has-text-grey\">entry {{ row.index + 1 }}</span>\n }\n </div>\n </div>\n </td>\n <ng-container *ngTemplateOutlet=\"valueCells; context: { row }\" />\n <ng-container *ngTemplateOutlet=\"modelCells; context: { row, open: row.isOpen }\" />\n </tr>\n <ng-container *ngTemplateOutlet=\"subRowsTemplate; context: { row, open: row.isOpen, nested: true }\" />\n }\n }\n }\n </tbody>\n </table>\n</he-data-table>\n\n<div class=\"is-size-7\">\n <div class=\"is-flex is-py-2 is-px-3 is-gap-16 | status-legend\">\n <div\n class=\"is-flex is-justify-content-center is-align-items-center is-align-content-center is-flex-wrap-wrap is-gap-8\">\n @for (status of LogStatus | keyvalue; track status.value) {\n @if (logIcon[status.value]) {\n <span class=\"is-flex is-align-items-center is-gap-8\">\n <he-svg-icon [name]=\"logIcon[status.value]\" size=\"20\" class=\"has-text-{{ logColor[status.value] }}\" />\n <span class=\"is-size-7\">{{ status.value | capitalize }}</span>\n </span>\n }\n }\n </div>\n\n @if (filteredType()) {\n <div class=\"field is-relative\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded is-secondary\"\n [(ngModel)]=\"onlyRequired\"\n [disabled]=\"!!term()\"\n [id]=\"onlyRequiredId\" />\n <label class=\"is-size-7\" [attr.for]=\"onlyRequiredId\">\n <span>Only show {{ filteredType() }} included in the default HESTIA system boundary</span>\n </label>\n </div>\n }\n </div>\n</div>\n\n<ng-template #valueCells let-row=\"row\">\n @if (isBlankNodes()) {\n <td class=\"has-border-right\">\n @if (row.term) {\n <span class=\"is-nowrap\" [innerHtml]=\"row.term.units | compound\"></span>\n }\n </td>\n }\n <td class=\"has-border-right\">\n @if (!isEmptyValue(row.originalValue)) {\n <ng-container *ngTemplateOutlet=\"valueContent; context: { value: row.originalValue }\" />\n } @else {\n -\n }\n </td>\n <td class=\"has-border-right\">\n @if (row.isRecalculated) {\n <ng-container *ngTemplateOutlet=\"valueContent; context: { value: row.recalculatedValue }\" />\n } @else if (row.key === 'backgroundData') {\n <!-- a container grouping the input's background-emission models; it has no value of its own -->\n -\n } @else if (row.isFailed || row.models.length || isEmptyValue(row.originalValue)) {\n not recalculated\n } @else {\n -\n }\n </td>\n @if (isBlankNodes()) {\n <td class=\"has-border-right is-nowrap\">\n @if (row.isOriginal && row.isRecalculated) {\n <he-blank-node-value-delta\n [value]=\"row.recalculatedValue\"\n [originalValue]=\"row.originalValue\"\n [useCustomFunctions]=\"false\" />\n } @else {\n -\n }\n </td>\n }\n</ng-template>\n\n<ng-template #subRowsTemplate let-row=\"row\" let-open=\"open\" let-nested=\"nested\">\n @if (row.canOpen && open) {\n @for (subRow of row.subRows; track trackByRow($index, subRow)) {\n <tr class=\"is-sub-row\">\n <td class=\"width-auto has-border-right\">\n <div\n class=\"is-flex is-align-items-flex-start is-flex-wrap-wrap is-gap-4\"\n [class.is-pl-3]=\"!nested\"\n [class.is-pl-5]=\"nested\">\n <he-svg-icon class=\"sub-sub-row-icon\" name=\"chevron-double-right\" />\n @if (subRow.key === 'backgroundData') {\n <span>Background Data</span>\n } @else if (subRow.term) {\n <span>{{ subRow.key | keyToLabel }}:</span>\n <he-node-link class=\"is-inline-block\" [node]=\"subRow.term\">\n <span class=\"break-word\" [innerHtml]=\"subRow.term?.name | compound\"></span>\n </he-node-link>\n } @else {\n <span>Field:</span>\n @if (subRow.type) {\n <a [href]=\"schemaBaseUrl + '/' + subRow.type + '#' + subRow.key\" target=\"_blank\">{{ subRow.key }}</a>\n } @else {\n <span>{{ subRow.key }}</span>\n }\n }\n </div>\n </td>\n <ng-container *ngTemplateOutlet=\"valueCells; context: { row: subRow }\" />\n <ng-container *ngTemplateOutlet=\"modelCells; context: { row: subRow, open: true }\" />\n </tr>\n }\n }\n</ng-template>\n\n<ng-template #valueContent let-value=\"value\">\n @if (isNumber(value)) {\n {{ value | precision: 3 | default: '-' }}\n } @else {\n {{ value | default: '-' }}\n }\n</ng-template>\n\n<ng-template #modelCells let-row=\"row\" let-open=\"open\">\n @if (row.canOpen && !open && row.models.length === 0) {\n <td class=\"has-border-right\" [attr.colspan]=\"methodModelsCount()\">\n <span>Expand to see logs (</span>\n @if (row.allSucceeded) {\n <span>all succeeded</span>\n <he-svg-icon class=\"is-ml-1 has-text-success\" name=\"checkmark\" />\n } @else {\n <span>some failed</span>\n <he-svg-icon class=\"is-ml-1 has-text-danger\" name=\"xmark\" />\n }\n <span>)</span>\n </td>\n } @else {\n @for (i of methodModelsCount() | times; track modelIndex; let modelIndex = $index) {\n <td class=\"has-border-right\">\n @if (row.modelColumns[modelIndex]; as column) {\n @if (isArray(column)) {\n <!-- parallel models: stacked in the same column, each with its own status -->\n @for (model of column; track model.methodId) {\n <ng-container *ngTemplateOutlet=\"modelCell; context: { model, row }\" />\n }\n } @else {\n <ng-container *ngTemplateOutlet=\"modelCell; context: { model: column, row }\" />\n }\n } @else {\n -\n }\n </td>\n }\n }\n</ng-template>\n\n<ng-template #modelCell let-model=\"model\" let-row=\"row\">\n <div class=\"is-flex is-align-self-stretch is-justify-content-center is-align-items-center is-gap-8\">\n <div class=\"is-flex is-gap-4 is-flex-grow-1 is-align-items-center\">\n <span\n class=\"pl-1 has-text-{{ logColor[model.status] }}\"\n [class.trigger-popover]=\"hasLogs()\"\n [ngbPopover]=\"logStatusDetails\"\n [disablePopover]=\"!hasLogs()\"\n autoClose=\"outside\"\n popoverClass=\"is-narrow\"\n triggers=\"manual\"\n #p1=\"ngbPopover\"\n placement=\"bottom left right auto\"\n container=\"body\"\n (click)=\"$event.stopPropagation(); p1.isOpen() ? p1.close() : p1.open({ model, row })\">\n <he-svg-icon [name]=\"logIcon[model.status]\" />\n </span>\n\n <span class=\"is-flex is-flex-grow-1 is-gap-4\">\n <span class=\"is-nowrap is-capitalized\">{{ methodName(model) }}</span>\n @if (modelMethodTier(model); as methodTier) {\n <span class=\"is-nowrap\">[{{ methodTier }}]</span>\n }\n </span>\n </div>\n\n <div class=\"is-flex is-gap-4 is-flex-shrink-0 is-align-items-center\">\n @if (model.showLogs) {\n <span\n class=\"is-nowrap is-clickable\"\n [ngbPopover]=\"logDetails\"\n autoClose=\"outside\"\n popoverClass=\"is-narrow\"\n triggers=\"manual\"\n #p=\"ngbPopover\"\n placement=\"bottom left right auto\"\n container=\"body\"\n (click)=\"p.isOpen() ? p.close() : p.open({ model, row })\">\n <span class=\"has-text-link\">Logs</span>\n </span>\n }\n @if (model.model) {\n @if (model.showLogs) {\n <div class=\"vertical-divider\"></div>\n }\n <ng-container *ngTemplateOutlet=\"docsLink; context: { $implicit: model.model }\" />\n }\n </div>\n </div>\n</ng-template>\n\n<ng-template #logDetails let-model=\"model\" let-row=\"row\">\n <he-node-logs-models-details\n [model]=\"model\"\n [value]=\"row?.recalculatedValue\"\n [node]=\"node()\"\n [nodeKey]=\"nodeKey()\"\n [hasContributions]=\"hasContributions()\" />\n</ng-template>\n\n<ng-template #logStatusDetails let-model=\"model\" let-row=\"row\">\n <he-node-logs-models-logs-status [nodeType]=\"nodeType()\" [model]=\"model\" [data]=\"$any(row)\" />\n</ng-template>\n\n<ng-template #docsLink let-model>\n @if (guideEnabled && model.guidePath) {\n <he-guide-overlay [pageId]=\"model.guidePath\" [width]=\"500\" />\n } @else {\n <a [href]=\"model.docPath || model.path\" target=\"_blank\" (click)=\"$event.stopPropagation()\">\n <span>Docs</span>\n <he-svg-icon name=\"external-link\" class=\"ml-2\" />\n </a>\n }\n</ng-template>\n", styles: [":host{display:block}:host .vertical-divider{width:1px;height:20px;background:#dbe3ea}:host .status-legend{border:1px solid #dbe3ea;background:#f5f7f9}:host .has-formula{cursor:help;border-bottom:1px dotted currentColor}::ng-deep .table{background-color:transparent}::ng-deep .table td.has-border-right{box-shadow:1px 0 #4c7194}::ng-deep .table td>div{min-height:24px}::ng-deep .table .has-sub-rows.is-open>td:first-child:before,::ng-deep .table .is-sub-row>td:first-child:before{display:block;position:absolute;content:\" \";background-color:#4c719433;height:100%;width:1px;top:0;left:14px}::ng-deep .table .has-sub-rows.is-open>td:first-child:before{top:25px}::ng-deep .table .is-sub-row .open-node>he-svg-icon,::ng-deep .table .is-sub-row .sub-sub-row-icon{height:16px!important;width:16px!important}::ng-deep .table .is-sub-sub-row td:first-child{padding-left:24px}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: DataTableComponent, selector: "he-data-table", inputs: ["minHeight", "maxHeight", "small"] }, { kind: "component", type: BlankNodeValueDeltaComponent, selector: "he-blank-node-value-delta", inputs: ["value", "originalValue", "displayType", "useCustomFunctions"] }, { kind: "component", type: NodeLinkComponent, selector: "he-node-link", inputs: ["node", "dataState", "showExternalLink", "linkClass"] }, { kind: "directive", type: NgbTypeahead, selector: "input[ngbTypeahead]", inputs: ["autocomplete", "container", "editable", "focusFirst", "inputFormatter", "ngbTypeahead", "resultFormatter", "resultTemplate", "selectOnExact", "showHint", "placement", "popperOptions", "popupClass"], outputs: ["selectItem"], exportAs: ["ngbTypeahead"] }, { kind: "directive", type: NgbPopover, selector: "[ngbPopover]", inputs: ["animation", "autoClose", "ngbPopover", "popoverTitle", "placement", "popperOptions", "triggers", "positionTarget", "container", "disablePopover", "popoverClass", "popoverContext", "openDelay", "closeDelay"], outputs: ["shown", "hidden"], exportAs: ["ngbPopover"] }, { kind: "component", type: HESvgIconComponent, selector: "he-svg-icon", inputs: ["name", "size", "animation"] }, { kind: "component", type: NodeLogsModelsLogsStatusComponent, selector: "he-node-logs-models-logs-status", inputs: ["nodeType", "model", "data"] }, { kind: "component", type: NodeLogsModelsDetailsComponent, selector: "he-node-logs-models-details", inputs: ["model", "value", "node", "nodeKey", "hasContributions"] }, { kind: "component", type: GuideOverlayComponent, selector: "he-guide-overlay", inputs: ["pageId", "width", "height", "positions"], outputs: ["widthChange", "heightChange"] }, { kind: "pipe", type: KeyValuePipe, name: "keyvalue" }, { kind: "pipe", type: CompoundPipe, name: "compound" }, { kind: "pipe", type: DefaultPipe, name: "default" }, { kind: "pipe", type: KeyToLabelPipe, name: "keyToLabel" }, { kind: "pipe", type: PrecisionPipe, name: "precision" }, { kind: "pipe", type: TimesPipe, name: "times" }, { kind: "pipe", type: CapitalizePipe, name: "capitalize" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
10731
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: NodeJLogModelsComponent, isStandalone: true, selector: "he-node-jlog-models", inputs: { node: { classPropertyName: "node", publicName: "node", isSignal: true, isRequired: true, transformFunction: null }, nodeKey: { classPropertyName: "nodeKey", publicName: "nodeKey", isSignal: true, isRequired: false, transformFunction: null }, originalValues: { classPropertyName: "originalValues", publicName: "originalValues", isSignal: true, isRequired: false, transformFunction: null }, recalculatedValues: { classPropertyName: "recalculatedValues", publicName: "recalculatedValues", isSignal: true, isRequired: false, transformFunction: null }, filterTermTypes: { classPropertyName: "filterTermTypes", publicName: "filterTermTypes", isSignal: true, isRequired: false, transformFunction: null }, filterTermTypesLabel: { classPropertyName: "filterTermTypesLabel", publicName: "filterTermTypesLabel", isSignal: true, isRequired: false, transformFunction: null }, cycle: { classPropertyName: "cycle", publicName: "cycle", isSignal: true, isRequired: false, transformFunction: null }, jlog: { classPropertyName: "jlog", publicName: "jlog", isSignal: true, isRequired: false, transformFunction: null }, jlogParentKey: { classPropertyName: "jlogParentKey", publicName: "jlogParentKey", isSignal: true, isRequired: false, transformFunction: null }, jlogParentIndex: { classPropertyName: "jlogParentIndex", publicName: "jlogParentIndex", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<he-data-table class=\"is-mt-2 is-mb-1 is-bordered\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n <tr>\n <th class=\"width-auto has-border-right\">\n @if (enableFilterByTerm()) {\n <div class=\"field is-pb-1\">\n <div class=\"control is-expanded has-icons-right\">\n <input\n class=\"input search-input is-small\"\n [ngModel]=\"term()\"\n name=\"term\"\n placeholder=\"Select entry by name\"\n [ngbTypeahead]=\"suggestTerm\"\n [resultFormatter]=\"termFormatter\"\n [inputFormatter]=\"termFormatter\"\n [focusFirst]=\"true\"\n (focus)=\"typeaheadFocus($event)\"\n (selectItem)=\"term.set($event.item)\"\n container=\"body\"\n popupClass=\"is-small\" />\n <a class=\"icon is-small is-right\" [class.is-hidden]=\"!term()\" (click)=\"term.set(undefined)\">\n <he-svg-icon name=\"xmark\" />\n </a>\n </div>\n </div>\n }\n </th>\n @if (isBlankNodes()) {\n <th class=\"has-border-right\"><span>Units</span></th>\n }\n <th class=\"has-border-right\"><span>Original</span></th>\n <th class=\"has-border-right\"><span>Recalculated</span></th>\n @if (isBlankNodes()) {\n <th class=\"has-border-right\"><span>Difference</span></th>\n }\n @for (c of methodModelsCount() | times; track i; let i = $index) {\n <th class=\"has-border-right\">\n <span>Model {{ i + 1 }}</span>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @if (groups().length === 0) {\n <tr>\n <td class=\"has-border-right has-text-centered\" colspan=\"100\">\n <p class=\"is-p-1\">No recalculation logs to show.</p>\n </td>\n </tr>\n }\n @for (group of groups(); track trackByGroup($index, group)) {\n @let single = group.rows.length === 1;\n <tr [class.has-sub-rows]=\"group.canOpen\" [class.is-open]=\"group.isOpen\">\n <td class=\"width-auto has-border-right is-nowrap\" [attr.title]=\"group.term?.name\">\n <div class=\"is-flex is-align-items-flex-start is-gap-4\">\n @if (group.canOpen) {\n <a class=\"open-node\" (click)=\"toggleGroup(group)\">\n <he-svg-icon [name]=\"group.isOpen ? 'chevron-down' : 'chevron-right'\" />\n </a>\n }\n @if (group.term) {\n <he-node-link class=\"is-inline-block is-pre-wrap is-pr-2\" [node]=\"group.term\">\n <span class=\"break-word\" [innerHtml]=\"group.term?.name | compound: group.term?.termType\"></span>\n </he-node-link>\n } @else if (group.key) {\n @if (nodeKey() === 'completeness') {\n <a [href]=\"schemaBaseUrl + '/Completeness#' + group.key\" target=\"_blank\">\n <span>{{ group.key | keyToLabel }}</span>\n </a>\n } @else {\n <a [href]=\"schemaBaseUrl + '/' + nodeType() + '#' + group.key\" target=\"_blank\">\n <span>{{ group.key | keyToLabel }}</span>\n </a>\n }\n }\n </div>\n </td>\n @if (single) {\n <ng-container *ngTemplateOutlet=\"valueCells; context: { row: group.rows[0] }\" />\n <ng-container *ngTemplateOutlet=\"modelCells; context: { row: group.rows[0], open: group.isOpen }\" />\n } @else {\n @if (isBlankNodes()) {\n <td class=\"has-border-right\">\n @if (group.term) {\n <span class=\"is-nowrap\" [innerHtml]=\"group.term.units | compound\"></span>\n }\n </td>\n }\n <td class=\"has-border-right\">\n @if (!isEmptyValue(group.originalValue)) {\n <ng-container *ngTemplateOutlet=\"valueContent; context: { value: group.originalValue }\" />\n } @else {\n -\n }\n </td>\n <td class=\"has-border-right\">\n @if (group.isRecalculated && !isEmptyValue(group.recalculatedValue)) {\n @if (group.recalculatedFormula) {\n <span\n class=\"has-formula\"\n [ngbPopover]=\"group.recalculatedFormula\"\n popoverClass=\"is-narrow\"\n triggers=\"click\"\n container=\"body\">\n <ng-container *ngTemplateOutlet=\"valueContent; context: { value: group.recalculatedValue }\" />\n </span>\n } @else {\n <ng-container *ngTemplateOutlet=\"valueContent; context: { value: group.recalculatedValue }\" />\n }\n } @else {\n -\n }\n </td>\n @if (isBlankNodes()) {\n <td class=\"has-border-right is-nowrap\">\n @if (\n group.isRecalculated && !isEmptyValue(group.originalValue) && !isEmptyValue(group.recalculatedValue)\n ) {\n <he-blank-node-value-delta\n [value]=\"group.recalculatedValue\"\n [originalValue]=\"group.originalValue\"\n [useCustomFunctions]=\"false\" />\n } @else {\n -\n }\n </td>\n }\n <td class=\"has-border-right\" [attr.colspan]=\"methodModelsCount()\">\n <span>Expand to see logs (</span>\n @if (group.allSucceeded) {\n <span>all succeeded</span>\n <he-svg-icon class=\"is-ml-1 has-text-success\" name=\"checkmark\" />\n } @else {\n <span>some failed</span>\n <he-svg-icon class=\"is-ml-1 has-text-danger\" name=\"xmark\" />\n }\n <span>)</span>\n </td>\n }\n </tr>\n\n @if (single) {\n <ng-container\n *ngTemplateOutlet=\"subRowsTemplate; context: { row: group.rows[0], open: group.isOpen, nested: false }\" />\n } @else if (group.isOpen) {\n @for (row of group.rows; track trackByRow($index, row)) {\n <tr [class.has-sub-rows]=\"row.canOpen\" [class.is-sub-row]=\"true\">\n <td class=\"width-auto has-border-right\">\n <div class=\"is-flex is-align-items-flex-start is-gap-4 is-pl-3\">\n @if (row.canOpen) {\n <a class=\"open-node\" (click)=\"toggleRow(row)\">\n <he-svg-icon [name]=\"row.isOpen ? 'chevron-down' : 'chevron-right'\" />\n </a>\n }\n <he-svg-icon class=\"sub-sub-row-icon\" name=\"chevron-double-right\" />\n <div class=\"is-flex is-align-items-center is-flex-wrap-wrap is-gap-4\">\n @if (row.isFailed) {\n <span class=\"has-text-danger\">failed</span>\n } @else if (row.identitySegments.length || row.identityScalars.length) {\n @for (segment of row.identitySegments; track segment.field; let s = $index) {\n @if (s > 0) {\n <span>\u00B7</span>\n }\n <span>{{ segment.field | keyToLabel }}:</span>\n @for (term of segment.terms; track term['@id']) {\n <he-node-link class=\"is-inline-block\" [node]=\"term\">\n <span class=\"break-word\" [innerHtml]=\"term.name | compound: term.termType\"></span>\n </he-node-link>\n }\n }\n @for (scalar of row.identityScalars; track scalar.key; let i = $index) {\n <span class=\"break-word\">\n @if (i > 0 || row.identitySegments.length) {\n \u00B7\n }\n @if (scalar.field && row.type) {\n <a [href]=\"schemaBaseUrl + '/' + row.type + '#' + scalar.field\" target=\"_blank\">\n {{ scalar.key }}\n </a>\n @if (scalar.value) {\n : {{ scalar.value }}\n }\n } @else {\n {{ scalar.key }}\n @if (scalar.value) {\n : {{ scalar.value }}\n }\n }\n </span>\n }\n } @else {\n <span class=\"has-text-grey\">entry {{ row.index + 1 }}</span>\n }\n </div>\n </div>\n </td>\n <ng-container *ngTemplateOutlet=\"valueCells; context: { row }\" />\n <ng-container *ngTemplateOutlet=\"modelCells; context: { row, open: row.isOpen }\" />\n </tr>\n <ng-container *ngTemplateOutlet=\"subRowsTemplate; context: { row, open: row.isOpen, nested: true }\" />\n }\n }\n }\n </tbody>\n </table>\n</he-data-table>\n\n<div class=\"is-size-7\">\n <div class=\"is-flex is-py-2 is-px-3 is-gap-16 | status-legend\">\n <div\n class=\"is-flex is-justify-content-center is-align-items-center is-align-content-center is-flex-wrap-wrap is-gap-8\">\n @for (status of LogStatus | keyvalue; track status.value) {\n @if (logIcon[status.value]) {\n <span class=\"is-flex is-align-items-center is-gap-8\">\n <he-svg-icon [name]=\"logIcon[status.value]\" size=\"20\" class=\"has-text-{{ logColor[status.value] }}\" />\n <span class=\"is-size-7\">{{ status.value | capitalize }}</span>\n </span>\n }\n }\n </div>\n\n @if (filteredType()) {\n <div class=\"field is-relative\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded is-secondary\"\n [(ngModel)]=\"onlyRequired\"\n [disabled]=\"!!term()\"\n [id]=\"onlyRequiredId\" />\n <label class=\"is-size-7\" [attr.for]=\"onlyRequiredId\">\n <span>Only show {{ filteredType() }} included in the default HESTIA system boundary</span>\n </label>\n </div>\n }\n </div>\n</div>\n\n<ng-template #valueCells let-row=\"row\">\n @if (isBlankNodes()) {\n <td class=\"has-border-right\">\n @if (row.term) {\n <span class=\"is-nowrap\" [innerHtml]=\"row.term.units | compound\"></span>\n }\n </td>\n }\n <td class=\"has-border-right\">\n @if (!isEmptyValue(row.originalValue)) {\n <ng-container *ngTemplateOutlet=\"valueContent; context: { value: row.originalValue }\" />\n } @else {\n -\n }\n </td>\n <td class=\"has-border-right\">\n @if (row.isRecalculated) {\n <ng-container *ngTemplateOutlet=\"valueContent; context: { value: row.recalculatedValue }\" />\n } @else if (row.key === 'backgroundData') {\n <!-- a container grouping the input's background-emission models; it has no value of its own -->\n -\n } @else if (row.isFailed || row.models.length || isEmptyValue(row.originalValue)) {\n not recalculated\n } @else {\n -\n }\n </td>\n @if (isBlankNodes()) {\n <td class=\"has-border-right is-nowrap\">\n @if (row.isOriginal && row.isRecalculated) {\n <he-blank-node-value-delta\n [value]=\"row.recalculatedValue\"\n [originalValue]=\"row.originalValue\"\n [useCustomFunctions]=\"false\" />\n } @else {\n -\n }\n </td>\n }\n</ng-template>\n\n<ng-template #subRowsTemplate let-row=\"row\" let-open=\"open\" let-nested=\"nested\">\n @if (row.canOpen && open) {\n @for (subRow of row.subRows; track trackByRow($index, subRow)) {\n <tr class=\"is-sub-row\">\n <td class=\"width-auto has-border-right\">\n <div\n class=\"is-flex is-align-items-flex-start is-flex-wrap-wrap is-gap-4\"\n [class.is-pl-3]=\"!nested\"\n [class.is-pl-5]=\"nested\">\n <he-svg-icon class=\"sub-sub-row-icon\" name=\"chevron-double-right\" />\n @if (subRow.key === 'backgroundData') {\n <span>Background Data</span>\n } @else if (subRow.term) {\n <span>{{ subRow.key | keyToLabel }}:</span>\n <he-node-link class=\"is-inline-block\" [node]=\"subRow.term\">\n <span class=\"break-word\" [innerHtml]=\"subRow.term?.name | compound\"></span>\n </he-node-link>\n } @else {\n <span>Field:</span>\n @if (subRow.type) {\n <a [href]=\"schemaBaseUrl + '/' + subRow.type + '#' + subRow.key\" target=\"_blank\">{{ subRow.key }}</a>\n } @else {\n <span>{{ subRow.key }}</span>\n }\n }\n </div>\n </td>\n <ng-container *ngTemplateOutlet=\"valueCells; context: { row: subRow }\" />\n <ng-container *ngTemplateOutlet=\"modelCells; context: { row: subRow, open: true }\" />\n </tr>\n }\n }\n</ng-template>\n\n<ng-template #valueContent let-value=\"value\">\n @if (isNumber(value)) {\n {{ value | precision: 3 | default: '-' }}\n } @else {\n {{ value | default: '-' }}\n }\n</ng-template>\n\n<ng-template #modelCells let-row=\"row\" let-open=\"open\">\n @if (row.canOpen && !open && row.models.length === 0) {\n <td class=\"has-border-right\" [attr.colspan]=\"methodModelsCount()\">\n <span>Expand to see logs (</span>\n @if (row.allSucceeded) {\n <span>all succeeded</span>\n <he-svg-icon class=\"is-ml-1 has-text-success\" name=\"checkmark\" />\n } @else {\n <span>some failed</span>\n <he-svg-icon class=\"is-ml-1 has-text-danger\" name=\"xmark\" />\n }\n <span>)</span>\n </td>\n } @else {\n @for (i of methodModelsCount() | times; track modelIndex; let modelIndex = $index) {\n <td class=\"has-border-right\">\n @if (row.modelColumns[modelIndex]; as column) {\n @if (isArray(column)) {\n <!-- parallel models: stacked in the same column, each with its own status -->\n @for (model of column; track model.methodId) {\n <ng-container *ngTemplateOutlet=\"modelCell; context: { model, row }\" />\n }\n } @else {\n <ng-container *ngTemplateOutlet=\"modelCell; context: { model: column, row }\" />\n }\n } @else {\n -\n }\n </td>\n }\n }\n</ng-template>\n\n<ng-template #modelCell let-model=\"model\" let-row=\"row\">\n <div class=\"is-flex is-align-self-stretch is-justify-content-center is-align-items-center is-gap-8\">\n <div class=\"is-flex is-gap-4 is-flex-grow-1 is-align-items-center\">\n <span\n class=\"pl-1 has-text-{{ logColor[model.status] }}\"\n [class.trigger-popover]=\"hasLogs()\"\n [ngbPopover]=\"logStatusDetails\"\n [disablePopover]=\"!hasLogs()\"\n autoClose=\"outside\"\n popoverClass=\"is-narrow\"\n triggers=\"manual\"\n #p1=\"ngbPopover\"\n placement=\"bottom left right auto\"\n container=\"body\"\n (click)=\"$event.stopPropagation(); p1.isOpen() ? p1.close() : p1.open({ model, row })\">\n <he-svg-icon [name]=\"logIcon[model.status]\" />\n </span>\n\n <span class=\"is-flex is-flex-grow-1 is-gap-4\">\n <span class=\"is-nowrap is-capitalized\">{{ methodName(model) }}</span>\n @if (modelMethodTier(model); as methodTier) {\n <span class=\"is-nowrap\">[{{ methodTier }}]</span>\n }\n </span>\n </div>\n\n <div class=\"is-flex is-gap-4 is-flex-shrink-0 is-align-items-center\">\n @if (model.showLogs) {\n <span\n class=\"is-nowrap is-clickable\"\n [ngbPopover]=\"logDetails\"\n autoClose=\"outside\"\n popoverClass=\"is-narrow\"\n triggers=\"manual\"\n #p=\"ngbPopover\"\n placement=\"bottom left right auto\"\n container=\"body\"\n (click)=\"p.isOpen() ? p.close() : p.open({ model, row })\">\n <span class=\"has-text-link\">Logs</span>\n </span>\n }\n @if (model.model) {\n @if (model.showLogs) {\n <div class=\"vertical-divider\"></div>\n }\n <ng-container *ngTemplateOutlet=\"docsLink; context: { $implicit: model.model }\" />\n }\n </div>\n </div>\n</ng-template>\n\n<ng-template #logDetails let-model=\"model\" let-row=\"row\">\n <he-node-logs-models-details\n [model]=\"model\"\n [value]=\"row?.recalculatedValue\"\n [node]=\"node()\"\n [nodeKey]=\"nodeKey()\"\n [hasContributions]=\"hasContributions()\" />\n</ng-template>\n\n<ng-template #logStatusDetails let-model=\"model\" let-row=\"row\">\n <he-node-logs-models-logs-status [nodeType]=\"nodeType()\" [model]=\"model\" [data]=\"$any(row)\" />\n</ng-template>\n\n<ng-template #docsLink let-model>\n @if (guideEnabled && model.guidePath) {\n <he-guide-overlay [pageId]=\"model.guidePath\" [width]=\"500\" />\n } @else {\n <a [href]=\"model.docPath || model.path\" target=\"_blank\" (click)=\"$event.stopPropagation()\">\n <span>Docs</span>\n <he-svg-icon name=\"external-link\" class=\"ml-2\" />\n </a>\n }\n</ng-template>\n", styles: [":host{display:block}:host .vertical-divider{width:1px;height:20px;background:#dbe3ea}:host .status-legend{border:1px solid #dbe3ea;background:#f5f7f9}:host .has-formula{cursor:help;border-bottom:1px dotted currentColor}::ng-deep .table{background-color:transparent}::ng-deep .table td.has-border-right{box-shadow:1px 0 #4c7194}::ng-deep .table td>div{min-height:24px}::ng-deep .table .has-sub-rows.is-open>td:first-child:before,::ng-deep .table .is-sub-row>td:first-child:before{display:block;position:absolute;content:\" \";background-color:#4c719433;height:100%;width:1px;top:0;left:14px}::ng-deep .table .has-sub-rows.is-open>td:first-child:before{top:25px}::ng-deep .table .is-sub-row .open-node>he-svg-icon,::ng-deep .table .is-sub-row .sub-sub-row-icon{height:16px!important;width:16px!important}::ng-deep .table .is-sub-sub-row td:first-child{padding-left:24px}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: DataTableComponent, selector: "he-data-table", inputs: ["minHeight", "maxHeight", "small"] }, { kind: "component", type: BlankNodeValueDeltaComponent, selector: "he-blank-node-value-delta", inputs: ["value", "originalValue", "displayType", "useCustomFunctions"] }, { kind: "component", type: NodeLinkComponent, selector: "he-node-link", inputs: ["node", "dataState", "showExternalLink", "linkClass"] }, { kind: "directive", type: NgbTypeahead, selector: "input[ngbTypeahead]", inputs: ["autocomplete", "container", "editable", "focusFirst", "inputFormatter", "ngbTypeahead", "resultFormatter", "resultTemplate", "selectOnExact", "showHint", "placement", "popperOptions", "popupClass"], outputs: ["selectItem"], exportAs: ["ngbTypeahead"] }, { kind: "directive", type: NgbPopover, selector: "[ngbPopover]", inputs: ["animation", "autoClose", "ngbPopover", "popoverTitle", "placement", "popperOptions", "triggers", "positionTarget", "container", "disablePopover", "popoverClass", "popoverContext", "openDelay", "closeDelay"], outputs: ["shown", "hidden"], exportAs: ["ngbPopover"] }, { kind: "component", type: HESvgIconComponent, selector: "he-svg-icon", inputs: ["name", "size", "animation"] }, { kind: "component", type: NodeLogsModelsLogsStatusComponent, selector: "he-node-logs-models-logs-status", inputs: ["nodeType", "model", "data"] }, { kind: "component", type: NodeLogsModelsDetailsComponent, selector: "he-node-logs-models-details", inputs: ["model", "value", "node", "nodeKey", "hasContributions"] }, { kind: "component", type: GuideOverlayComponent, selector: "he-guide-overlay", inputs: ["pageId", "width", "height", "positions"], outputs: ["widthChange", "heightChange"] }, { kind: "pipe", type: KeyValuePipe, name: "keyvalue" }, { kind: "pipe", type: CompoundPipe, name: "compound" }, { kind: "pipe", type: DefaultPipe, name: "default" }, { kind: "pipe", type: KeyToLabelPipe, name: "keyToLabel" }, { kind: "pipe", type: PrecisionPipe, name: "precision" }, { kind: "pipe", type: TimesPipe, name: "times" }, { kind: "pipe", type: CapitalizePipe, name: "capitalize" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
10709
10732
  }
10710
10733
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NodeJLogModelsComponent, decorators: [{
10711
10734
  type: Component$1,
@@ -10728,7 +10751,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
10728
10751
  NodeLogsModelsLogsStatusComponent,
10729
10752
  NodeLogsModelsDetailsComponent,
10730
10753
  GuideOverlayComponent
10731
- ], template: "<he-data-table class=\"is-mt-2 is-mb-1 is-bordered\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n <tr>\n <th class=\"width-auto has-border-right\">\n @if (enableFilterByTerm()) {\n <div class=\"field is-pb-1\">\n <div class=\"control is-expanded has-icons-right\">\n <input\n class=\"input search-input is-small\"\n [ngModel]=\"term()\"\n name=\"term\"\n placeholder=\"Select entry by name\"\n [ngbTypeahead]=\"suggestTerm\"\n [resultFormatter]=\"termFormatter\"\n [inputFormatter]=\"termFormatter\"\n [focusFirst]=\"true\"\n (focus)=\"typeaheadFocus($event)\"\n (selectItem)=\"term.set($event.item)\"\n container=\"body\"\n popupClass=\"is-small\" />\n <a class=\"icon is-small is-right\" [class.is-hidden]=\"!term()\" (click)=\"term.set(undefined)\">\n <he-svg-icon name=\"xmark\" />\n </a>\n </div>\n </div>\n }\n </th>\n @if (isBlankNodes()) {\n <th class=\"has-border-right\"><span>Units</span></th>\n }\n <th class=\"has-border-right\"><span>Original</span></th>\n <th class=\"has-border-right\"><span>Recalculated</span></th>\n @if (isBlankNodes()) {\n <th class=\"has-border-right\"><span>Difference</span></th>\n }\n @for (c of methodModelsCount() | times; track i; let i = $index) {\n <th class=\"has-border-right\">\n <span>Model {{ i + 1 }}</span>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @if (groups().length === 0) {\n <tr>\n <td class=\"has-border-right has-text-centered\" colspan=\"100\">\n <p class=\"is-p-1\">No recalculation logs to show.</p>\n </td>\n </tr>\n }\n @for (group of groups(); track trackByGroup($index, group)) {\n @let single = group.rows.length === 1;\n <tr [class.has-sub-rows]=\"group.canOpen\" [class.is-open]=\"group.isOpen\">\n <td class=\"width-auto has-border-right is-nowrap\" [attr.title]=\"group.term?.name\">\n <div class=\"is-flex is-align-items-flex-start is-gap-4\">\n @if (group.canOpen) {\n <a class=\"open-node\" (click)=\"toggleGroup(group)\">\n <he-svg-icon [name]=\"group.isOpen ? 'chevron-down' : 'chevron-right'\" />\n </a>\n }\n @if (group.term) {\n <he-node-link class=\"is-inline-block is-pre-wrap is-pr-2\" [node]=\"group.term\">\n <span class=\"break-word\" [innerHtml]=\"group.term?.name | compound: group.term?.termType\"></span>\n </he-node-link>\n } @else if (group.key) {\n @if (nodeKey() === 'completeness') {\n <a [href]=\"schemaBaseUrl + '/Completeness#' + group.key\" target=\"_blank\">\n <span>{{ group.key | keyToLabel }}</span>\n </a>\n } @else {\n <a [href]=\"schemaBaseUrl + '/' + nodeType() + '#' + group.key\" target=\"_blank\">\n <span>{{ group.key | keyToLabel }}</span>\n </a>\n }\n }\n </div>\n </td>\n @if (single) {\n <ng-container *ngTemplateOutlet=\"valueCells; context: { row: group.rows[0] }\" />\n <ng-container *ngTemplateOutlet=\"modelCells; context: { row: group.rows[0], open: group.isOpen }\" />\n } @else {\n @if (isBlankNodes()) {\n <td class=\"has-border-right\">\n @if (group.term) {\n <span class=\"is-nowrap\" [innerHtml]=\"group.term.units | compound\"></span>\n }\n </td>\n }\n <td class=\"has-border-right\">\n @if (!isEmptyValue(group.originalValue)) {\n <ng-container *ngTemplateOutlet=\"valueContent; context: { value: group.originalValue }\" />\n } @else {\n -\n }\n </td>\n <td class=\"has-border-right\">\n @if (group.isRecalculated && !isEmptyValue(group.recalculatedValue)) {\n @if (group.recalculatedFormula) {\n <span\n class=\"has-formula\"\n [ngbPopover]=\"group.recalculatedFormula\"\n popoverClass=\"is-narrow\"\n triggers=\"click\"\n container=\"body\">\n <ng-container *ngTemplateOutlet=\"valueContent; context: { value: group.recalculatedValue }\" />\n </span>\n } @else {\n <ng-container *ngTemplateOutlet=\"valueContent; context: { value: group.recalculatedValue }\" />\n }\n } @else {\n -\n }\n </td>\n @if (isBlankNodes()) {\n <td class=\"has-border-right is-nowrap\">\n @if (\n group.isRecalculated && !isEmptyValue(group.originalValue) && !isEmptyValue(group.recalculatedValue)\n ) {\n <he-blank-node-value-delta\n [value]=\"group.recalculatedValue\"\n [originalValue]=\"group.originalValue\"\n [useCustomFunctions]=\"false\" />\n } @else {\n -\n }\n </td>\n }\n <td class=\"has-border-right\" [attr.colspan]=\"methodModelsCount()\">\n <span>Expand to see logs (</span>\n @if (group.allSucceeded) {\n <span>all succeeded</span>\n <he-svg-icon class=\"is-ml-1 has-text-success\" name=\"checkmark\" />\n } @else {\n <span>some failed</span>\n <he-svg-icon class=\"is-ml-1 has-text-danger\" name=\"xmark\" />\n }\n <span>)</span>\n </td>\n }\n </tr>\n\n @if (single) {\n <ng-container\n *ngTemplateOutlet=\"subRowsTemplate; context: { row: group.rows[0], open: group.isOpen, nested: false }\" />\n } @else if (group.isOpen) {\n @for (row of group.rows; track trackByRow($index, row)) {\n <tr [class.has-sub-rows]=\"row.canOpen\" [class.is-sub-row]=\"true\">\n <td class=\"width-auto has-border-right\">\n <div class=\"is-flex is-align-items-flex-start is-gap-4 is-pl-3\">\n @if (row.canOpen) {\n <a class=\"open-node\" (click)=\"toggleRow(row)\">\n <he-svg-icon [name]=\"row.isOpen ? 'chevron-down' : 'chevron-right'\" />\n </a>\n }\n <he-svg-icon class=\"sub-sub-row-icon\" name=\"chevron-double-right\" />\n <div class=\"is-flex is-align-items-center is-flex-wrap-wrap is-gap-4\">\n @if (row.isFailed) {\n <span class=\"has-text-danger\">failed</span>\n } @else if (row.identitySegments.length || row.identityScalars.length) {\n @for (segment of row.identitySegments; track segment.field; let s = $index) {\n @if (s > 0) {<span>\u00B7</span>}\n <span>{{ segment.field | keyToLabel }}:</span>\n @for (term of segment.terms; track term['@id']) {\n <he-node-link class=\"is-inline-block\" [node]=\"term\">\n <span class=\"break-word\" [innerHtml]=\"term.name | compound: term.termType\"></span>\n </he-node-link>\n }\n }\n @for (scalar of row.identityScalars; track scalar.key; let i = $index) {\n <span class=\"break-word\">\n @if (i > 0 || row.identitySegments.length) {\u00B7}\n @if (scalar.field && row.type) {\n <a [href]=\"schemaBaseUrl + '/' + row.type + '#' + scalar.field\" target=\"_blank\">{{\n scalar.key\n }}</a\n >@if (scalar.value) {: {{ scalar.value }}}\n } @else {\n {{ scalar.key }}@if (scalar.value) {: {{ scalar.value }}}\n }\n </span>\n }\n } @else {\n <span class=\"has-text-grey\">entry {{ row.index + 1 }}</span>\n }\n </div>\n </div>\n </td>\n <ng-container *ngTemplateOutlet=\"valueCells; context: { row }\" />\n <ng-container *ngTemplateOutlet=\"modelCells; context: { row, open: row.isOpen }\" />\n </tr>\n <ng-container *ngTemplateOutlet=\"subRowsTemplate; context: { row, open: row.isOpen, nested: true }\" />\n }\n }\n }\n </tbody>\n </table>\n</he-data-table>\n\n<div class=\"is-size-7\">\n <div class=\"is-flex is-py-2 is-px-3 is-gap-16 | status-legend\">\n <div\n class=\"is-flex is-justify-content-center is-align-items-center is-align-content-center is-flex-wrap-wrap is-gap-8\">\n @for (status of LogStatus | keyvalue; track status.value) {\n @if (logIcon[status.value]) {\n <span class=\"is-flex is-align-items-center is-gap-8\">\n <he-svg-icon [name]=\"logIcon[status.value]\" size=\"20\" class=\"has-text-{{ logColor[status.value] }}\" />\n <span class=\"is-size-7\">{{ status.value | capitalize }}</span>\n </span>\n }\n }\n </div>\n\n @if (filteredType()) {\n <div class=\"field is-relative\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded is-secondary\"\n [(ngModel)]=\"onlyRequired\"\n [disabled]=\"!!term()\"\n [id]=\"onlyRequiredId\" />\n <label class=\"is-size-7\" [attr.for]=\"onlyRequiredId\">\n <span>Only show {{ filteredType() }} included in the default HESTIA system boundary</span>\n </label>\n </div>\n }\n </div>\n</div>\n\n<ng-template #valueCells let-row=\"row\">\n @if (isBlankNodes()) {\n <td class=\"has-border-right\">\n @if (row.term) {\n <span class=\"is-nowrap\" [innerHtml]=\"row.term.units | compound\"></span>\n }\n </td>\n }\n <td class=\"has-border-right\">\n @if (!isEmptyValue(row.originalValue)) {\n <ng-container *ngTemplateOutlet=\"valueContent; context: { value: row.originalValue }\" />\n } @else {\n -\n }\n </td>\n <td class=\"has-border-right\">\n @if (row.isRecalculated) {\n <ng-container *ngTemplateOutlet=\"valueContent; context: { value: row.recalculatedValue }\" />\n } @else if (row.key === 'backgroundData') {\n <!-- a container grouping the input's background-emission models; it has no value of its own -->\n -\n } @else if (row.isFailed || row.models.length || isEmptyValue(row.originalValue)) {\n not recalculated\n } @else {\n -\n }\n </td>\n @if (isBlankNodes()) {\n <td class=\"has-border-right is-nowrap\">\n @if (row.isOriginal && row.isRecalculated) {\n <he-blank-node-value-delta\n [value]=\"row.recalculatedValue\"\n [originalValue]=\"row.originalValue\"\n [useCustomFunctions]=\"false\" />\n } @else {\n -\n }\n </td>\n }\n</ng-template>\n\n<ng-template #subRowsTemplate let-row=\"row\" let-open=\"open\" let-nested=\"nested\">\n @if (row.canOpen && open) {\n @for (subRow of row.subRows; track trackByRow($index, subRow)) {\n <tr class=\"is-sub-row\">\n <td class=\"width-auto has-border-right\">\n <div\n class=\"is-flex is-align-items-flex-start is-flex-wrap-wrap is-gap-4\"\n [class.is-pl-3]=\"!nested\"\n [class.is-pl-5]=\"nested\">\n <he-svg-icon class=\"sub-sub-row-icon\" name=\"chevron-double-right\" />\n @if (subRow.key === 'backgroundData') {\n <span>Background Data</span>\n } @else if (subRow.term) {\n <span>{{ subRow.key | keyToLabel }}:</span>\n <he-node-link class=\"is-inline-block\" [node]=\"subRow.term\">\n <span class=\"break-word\" [innerHtml]=\"subRow.term?.name | compound\"></span>\n </he-node-link>\n } @else {\n <span>Field:</span>\n @if (subRow.type) {\n <a [href]=\"schemaBaseUrl + '/' + subRow.type + '#' + subRow.key\" target=\"_blank\">{{ subRow.key }}</a>\n } @else {\n <span>{{ subRow.key }}</span>\n }\n }\n </div>\n </td>\n <ng-container *ngTemplateOutlet=\"valueCells; context: { row: subRow }\" />\n <ng-container *ngTemplateOutlet=\"modelCells; context: { row: subRow, open: true }\" />\n </tr>\n }\n }\n</ng-template>\n\n<ng-template #valueContent let-value=\"value\">\n @if (isNumber(value)) {\n {{ value | precision: 3 | default: '-' }}\n } @else {\n {{ value | default: '-' }}\n }\n</ng-template>\n\n<ng-template #modelCells let-row=\"row\" let-open=\"open\">\n @if (row.canOpen && !open && row.models.length === 0) {\n <td class=\"has-border-right\" [attr.colspan]=\"methodModelsCount()\">\n <span>Expand to see logs (</span>\n @if (row.allSucceeded) {\n <span>all succeeded</span>\n <he-svg-icon class=\"is-ml-1 has-text-success\" name=\"checkmark\" />\n } @else {\n <span>some failed</span>\n <he-svg-icon class=\"is-ml-1 has-text-danger\" name=\"xmark\" />\n }\n <span>)</span>\n </td>\n } @else {\n @for (i of methodModelsCount() | times; track modelIndex; let modelIndex = $index) {\n <td class=\"has-border-right\">\n @if (row.modelColumns[modelIndex]; as column) {\n @if (isArray(column)) {\n <!-- parallel models: stacked in the same column, each with its own status -->\n @for (model of column; track model.methodId) {\n <ng-container *ngTemplateOutlet=\"modelCell; context: { model, row }\" />\n }\n } @else {\n <ng-container *ngTemplateOutlet=\"modelCell; context: { model: column, row }\" />\n }\n } @else {\n -\n }\n </td>\n }\n }\n</ng-template>\n\n<ng-template #modelCell let-model=\"model\" let-row=\"row\">\n <div class=\"is-flex is-align-self-stretch is-justify-content-center is-align-items-center is-gap-8\">\n <div class=\"is-flex is-gap-4 is-flex-grow-1 is-align-items-center\">\n <span\n class=\"pl-1 has-text-{{ logColor[model.status] }}\"\n [class.trigger-popover]=\"hasLogs()\"\n [ngbPopover]=\"logStatusDetails\"\n [disablePopover]=\"!hasLogs()\"\n autoClose=\"outside\"\n popoverClass=\"is-narrow\"\n triggers=\"manual\"\n #p1=\"ngbPopover\"\n placement=\"bottom left right auto\"\n container=\"body\"\n (click)=\"$event.stopPropagation(); p1.isOpen() ? p1.close() : p1.open({ model, row })\">\n <he-svg-icon [name]=\"logIcon[model.status]\" />\n </span>\n\n <span class=\"is-flex is-flex-grow-1 is-gap-4\">\n <span class=\"is-nowrap is-capitalized\">{{ methodName(model) }}</span>\n @if (modelMethodTier(model); as methodTier) {\n <span class=\"is-nowrap\">[{{ methodTier }}]</span>\n }\n </span>\n </div>\n\n <div class=\"is-flex is-gap-4 is-flex-shrink-0 is-align-items-center\">\n @if (model.showLogs) {\n <span\n class=\"is-nowrap is-clickable\"\n [ngbPopover]=\"logDetails\"\n autoClose=\"outside\"\n popoverClass=\"is-narrow\"\n triggers=\"manual\"\n #p=\"ngbPopover\"\n placement=\"bottom left right auto\"\n container=\"body\"\n (click)=\"p.isOpen() ? p.close() : p.open({ model, row })\">\n <span class=\"has-text-link\">Logs</span>\n </span>\n }\n @if (model.model) {\n @if (model.showLogs) {\n <div class=\"vertical-divider\"></div>\n }\n <ng-container *ngTemplateOutlet=\"docsLink; context: { $implicit: model.model }\" />\n }\n </div>\n </div>\n</ng-template>\n\n<ng-template #logDetails let-model=\"model\" let-row=\"row\">\n <he-node-logs-models-details\n [model]=\"model\"\n [value]=\"row?.recalculatedValue\"\n [node]=\"node()\"\n [nodeKey]=\"nodeKey()\"\n [hasContributions]=\"hasContributions()\" />\n</ng-template>\n\n<ng-template #logStatusDetails let-model=\"model\" let-row=\"row\">\n <he-node-logs-models-logs-status [nodeType]=\"nodeType()\" [model]=\"model\" [data]=\"$any(row)\" />\n</ng-template>\n\n<ng-template #docsLink let-model>\n @if (guideEnabled && model.guidePath) {\n <he-guide-overlay [pageId]=\"model.guidePath\" [width]=\"500\" />\n } @else {\n <a [href]=\"model.docPath || model.path\" target=\"_blank\" (click)=\"$event.stopPropagation()\">\n <span>Docs</span>\n <he-svg-icon name=\"external-link\" class=\"ml-2\" />\n </a>\n }\n</ng-template>\n", styles: [":host{display:block}:host .vertical-divider{width:1px;height:20px;background:#dbe3ea}:host .status-legend{border:1px solid #dbe3ea;background:#f5f7f9}:host .has-formula{cursor:help;border-bottom:1px dotted currentColor}::ng-deep .table{background-color:transparent}::ng-deep .table td.has-border-right{box-shadow:1px 0 #4c7194}::ng-deep .table td>div{min-height:24px}::ng-deep .table .has-sub-rows.is-open>td:first-child:before,::ng-deep .table .is-sub-row>td:first-child:before{display:block;position:absolute;content:\" \";background-color:#4c719433;height:100%;width:1px;top:0;left:14px}::ng-deep .table .has-sub-rows.is-open>td:first-child:before{top:25px}::ng-deep .table .is-sub-row .open-node>he-svg-icon,::ng-deep .table .is-sub-row .sub-sub-row-icon{height:16px!important;width:16px!important}::ng-deep .table .is-sub-sub-row td:first-child{padding-left:24px}\n"] }]
10754
+ ], template: "<he-data-table class=\"is-mt-2 is-mb-1 is-bordered\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n <tr>\n <th class=\"width-auto has-border-right\">\n @if (enableFilterByTerm()) {\n <div class=\"field is-pb-1\">\n <div class=\"control is-expanded has-icons-right\">\n <input\n class=\"input search-input is-small\"\n [ngModel]=\"term()\"\n name=\"term\"\n placeholder=\"Select entry by name\"\n [ngbTypeahead]=\"suggestTerm\"\n [resultFormatter]=\"termFormatter\"\n [inputFormatter]=\"termFormatter\"\n [focusFirst]=\"true\"\n (focus)=\"typeaheadFocus($event)\"\n (selectItem)=\"term.set($event.item)\"\n container=\"body\"\n popupClass=\"is-small\" />\n <a class=\"icon is-small is-right\" [class.is-hidden]=\"!term()\" (click)=\"term.set(undefined)\">\n <he-svg-icon name=\"xmark\" />\n </a>\n </div>\n </div>\n }\n </th>\n @if (isBlankNodes()) {\n <th class=\"has-border-right\"><span>Units</span></th>\n }\n <th class=\"has-border-right\"><span>Original</span></th>\n <th class=\"has-border-right\"><span>Recalculated</span></th>\n @if (isBlankNodes()) {\n <th class=\"has-border-right\"><span>Difference</span></th>\n }\n @for (c of methodModelsCount() | times; track i; let i = $index) {\n <th class=\"has-border-right\">\n <span>Model {{ i + 1 }}</span>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @if (groups().length === 0) {\n <tr>\n <td class=\"has-border-right has-text-centered\" colspan=\"100\">\n <p class=\"is-p-1\">No recalculation logs to show.</p>\n </td>\n </tr>\n }\n @for (group of groups(); track trackByGroup($index, group)) {\n @let single = group.rows.length === 1;\n <tr [class.has-sub-rows]=\"group.canOpen\" [class.is-open]=\"group.isOpen\">\n <td class=\"width-auto has-border-right is-nowrap\" [attr.title]=\"group.term?.name\">\n <div class=\"is-flex is-align-items-flex-start is-gap-4\">\n @if (group.canOpen) {\n <a class=\"open-node\" (click)=\"toggleGroup(group)\">\n <he-svg-icon [name]=\"group.isOpen ? 'chevron-down' : 'chevron-right'\" />\n </a>\n }\n @if (group.term) {\n <he-node-link class=\"is-inline-block is-pre-wrap is-pr-2\" [node]=\"group.term\">\n <span class=\"break-word\" [innerHtml]=\"group.term?.name | compound: group.term?.termType\"></span>\n </he-node-link>\n } @else if (group.key) {\n @if (nodeKey() === 'completeness') {\n <a [href]=\"schemaBaseUrl + '/Completeness#' + group.key\" target=\"_blank\">\n <span>{{ group.key | keyToLabel }}</span>\n </a>\n } @else {\n <a [href]=\"schemaBaseUrl + '/' + nodeType() + '#' + group.key\" target=\"_blank\">\n <span>{{ group.key | keyToLabel }}</span>\n </a>\n }\n }\n </div>\n </td>\n @if (single) {\n <ng-container *ngTemplateOutlet=\"valueCells; context: { row: group.rows[0] }\" />\n <ng-container *ngTemplateOutlet=\"modelCells; context: { row: group.rows[0], open: group.isOpen }\" />\n } @else {\n @if (isBlankNodes()) {\n <td class=\"has-border-right\">\n @if (group.term) {\n <span class=\"is-nowrap\" [innerHtml]=\"group.term.units | compound\"></span>\n }\n </td>\n }\n <td class=\"has-border-right\">\n @if (!isEmptyValue(group.originalValue)) {\n <ng-container *ngTemplateOutlet=\"valueContent; context: { value: group.originalValue }\" />\n } @else {\n -\n }\n </td>\n <td class=\"has-border-right\">\n @if (group.isRecalculated && !isEmptyValue(group.recalculatedValue)) {\n @if (group.recalculatedFormula) {\n <span\n class=\"has-formula\"\n [ngbPopover]=\"group.recalculatedFormula\"\n popoverClass=\"is-narrow\"\n triggers=\"click\"\n container=\"body\">\n <ng-container *ngTemplateOutlet=\"valueContent; context: { value: group.recalculatedValue }\" />\n </span>\n } @else {\n <ng-container *ngTemplateOutlet=\"valueContent; context: { value: group.recalculatedValue }\" />\n }\n } @else {\n -\n }\n </td>\n @if (isBlankNodes()) {\n <td class=\"has-border-right is-nowrap\">\n @if (\n group.isRecalculated && !isEmptyValue(group.originalValue) && !isEmptyValue(group.recalculatedValue)\n ) {\n <he-blank-node-value-delta\n [value]=\"group.recalculatedValue\"\n [originalValue]=\"group.originalValue\"\n [useCustomFunctions]=\"false\" />\n } @else {\n -\n }\n </td>\n }\n <td class=\"has-border-right\" [attr.colspan]=\"methodModelsCount()\">\n <span>Expand to see logs (</span>\n @if (group.allSucceeded) {\n <span>all succeeded</span>\n <he-svg-icon class=\"is-ml-1 has-text-success\" name=\"checkmark\" />\n } @else {\n <span>some failed</span>\n <he-svg-icon class=\"is-ml-1 has-text-danger\" name=\"xmark\" />\n }\n <span>)</span>\n </td>\n }\n </tr>\n\n @if (single) {\n <ng-container\n *ngTemplateOutlet=\"subRowsTemplate; context: { row: group.rows[0], open: group.isOpen, nested: false }\" />\n } @else if (group.isOpen) {\n @for (row of group.rows; track trackByRow($index, row)) {\n <tr [class.has-sub-rows]=\"row.canOpen\" [class.is-sub-row]=\"true\">\n <td class=\"width-auto has-border-right\">\n <div class=\"is-flex is-align-items-flex-start is-gap-4 is-pl-3\">\n @if (row.canOpen) {\n <a class=\"open-node\" (click)=\"toggleRow(row)\">\n <he-svg-icon [name]=\"row.isOpen ? 'chevron-down' : 'chevron-right'\" />\n </a>\n }\n <he-svg-icon class=\"sub-sub-row-icon\" name=\"chevron-double-right\" />\n <div class=\"is-flex is-align-items-center is-flex-wrap-wrap is-gap-4\">\n @if (row.isFailed) {\n <span class=\"has-text-danger\">failed</span>\n } @else if (row.identitySegments.length || row.identityScalars.length) {\n @for (segment of row.identitySegments; track segment.field; let s = $index) {\n @if (s > 0) {\n <span>\u00B7</span>\n }\n <span>{{ segment.field | keyToLabel }}:</span>\n @for (term of segment.terms; track term['@id']) {\n <he-node-link class=\"is-inline-block\" [node]=\"term\">\n <span class=\"break-word\" [innerHtml]=\"term.name | compound: term.termType\"></span>\n </he-node-link>\n }\n }\n @for (scalar of row.identityScalars; track scalar.key; let i = $index) {\n <span class=\"break-word\">\n @if (i > 0 || row.identitySegments.length) {\n \u00B7\n }\n @if (scalar.field && row.type) {\n <a [href]=\"schemaBaseUrl + '/' + row.type + '#' + scalar.field\" target=\"_blank\">\n {{ scalar.key }}\n </a>\n @if (scalar.value) {\n : {{ scalar.value }}\n }\n } @else {\n {{ scalar.key }}\n @if (scalar.value) {\n : {{ scalar.value }}\n }\n }\n </span>\n }\n } @else {\n <span class=\"has-text-grey\">entry {{ row.index + 1 }}</span>\n }\n </div>\n </div>\n </td>\n <ng-container *ngTemplateOutlet=\"valueCells; context: { row }\" />\n <ng-container *ngTemplateOutlet=\"modelCells; context: { row, open: row.isOpen }\" />\n </tr>\n <ng-container *ngTemplateOutlet=\"subRowsTemplate; context: { row, open: row.isOpen, nested: true }\" />\n }\n }\n }\n </tbody>\n </table>\n</he-data-table>\n\n<div class=\"is-size-7\">\n <div class=\"is-flex is-py-2 is-px-3 is-gap-16 | status-legend\">\n <div\n class=\"is-flex is-justify-content-center is-align-items-center is-align-content-center is-flex-wrap-wrap is-gap-8\">\n @for (status of LogStatus | keyvalue; track status.value) {\n @if (logIcon[status.value]) {\n <span class=\"is-flex is-align-items-center is-gap-8\">\n <he-svg-icon [name]=\"logIcon[status.value]\" size=\"20\" class=\"has-text-{{ logColor[status.value] }}\" />\n <span class=\"is-size-7\">{{ status.value | capitalize }}</span>\n </span>\n }\n }\n </div>\n\n @if (filteredType()) {\n <div class=\"field is-relative\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded is-secondary\"\n [(ngModel)]=\"onlyRequired\"\n [disabled]=\"!!term()\"\n [id]=\"onlyRequiredId\" />\n <label class=\"is-size-7\" [attr.for]=\"onlyRequiredId\">\n <span>Only show {{ filteredType() }} included in the default HESTIA system boundary</span>\n </label>\n </div>\n }\n </div>\n</div>\n\n<ng-template #valueCells let-row=\"row\">\n @if (isBlankNodes()) {\n <td class=\"has-border-right\">\n @if (row.term) {\n <span class=\"is-nowrap\" [innerHtml]=\"row.term.units | compound\"></span>\n }\n </td>\n }\n <td class=\"has-border-right\">\n @if (!isEmptyValue(row.originalValue)) {\n <ng-container *ngTemplateOutlet=\"valueContent; context: { value: row.originalValue }\" />\n } @else {\n -\n }\n </td>\n <td class=\"has-border-right\">\n @if (row.isRecalculated) {\n <ng-container *ngTemplateOutlet=\"valueContent; context: { value: row.recalculatedValue }\" />\n } @else if (row.key === 'backgroundData') {\n <!-- a container grouping the input's background-emission models; it has no value of its own -->\n -\n } @else if (row.isFailed || row.models.length || isEmptyValue(row.originalValue)) {\n not recalculated\n } @else {\n -\n }\n </td>\n @if (isBlankNodes()) {\n <td class=\"has-border-right is-nowrap\">\n @if (row.isOriginal && row.isRecalculated) {\n <he-blank-node-value-delta\n [value]=\"row.recalculatedValue\"\n [originalValue]=\"row.originalValue\"\n [useCustomFunctions]=\"false\" />\n } @else {\n -\n }\n </td>\n }\n</ng-template>\n\n<ng-template #subRowsTemplate let-row=\"row\" let-open=\"open\" let-nested=\"nested\">\n @if (row.canOpen && open) {\n @for (subRow of row.subRows; track trackByRow($index, subRow)) {\n <tr class=\"is-sub-row\">\n <td class=\"width-auto has-border-right\">\n <div\n class=\"is-flex is-align-items-flex-start is-flex-wrap-wrap is-gap-4\"\n [class.is-pl-3]=\"!nested\"\n [class.is-pl-5]=\"nested\">\n <he-svg-icon class=\"sub-sub-row-icon\" name=\"chevron-double-right\" />\n @if (subRow.key === 'backgroundData') {\n <span>Background Data</span>\n } @else if (subRow.term) {\n <span>{{ subRow.key | keyToLabel }}:</span>\n <he-node-link class=\"is-inline-block\" [node]=\"subRow.term\">\n <span class=\"break-word\" [innerHtml]=\"subRow.term?.name | compound\"></span>\n </he-node-link>\n } @else {\n <span>Field:</span>\n @if (subRow.type) {\n <a [href]=\"schemaBaseUrl + '/' + subRow.type + '#' + subRow.key\" target=\"_blank\">{{ subRow.key }}</a>\n } @else {\n <span>{{ subRow.key }}</span>\n }\n }\n </div>\n </td>\n <ng-container *ngTemplateOutlet=\"valueCells; context: { row: subRow }\" />\n <ng-container *ngTemplateOutlet=\"modelCells; context: { row: subRow, open: true }\" />\n </tr>\n }\n }\n</ng-template>\n\n<ng-template #valueContent let-value=\"value\">\n @if (isNumber(value)) {\n {{ value | precision: 3 | default: '-' }}\n } @else {\n {{ value | default: '-' }}\n }\n</ng-template>\n\n<ng-template #modelCells let-row=\"row\" let-open=\"open\">\n @if (row.canOpen && !open && row.models.length === 0) {\n <td class=\"has-border-right\" [attr.colspan]=\"methodModelsCount()\">\n <span>Expand to see logs (</span>\n @if (row.allSucceeded) {\n <span>all succeeded</span>\n <he-svg-icon class=\"is-ml-1 has-text-success\" name=\"checkmark\" />\n } @else {\n <span>some failed</span>\n <he-svg-icon class=\"is-ml-1 has-text-danger\" name=\"xmark\" />\n }\n <span>)</span>\n </td>\n } @else {\n @for (i of methodModelsCount() | times; track modelIndex; let modelIndex = $index) {\n <td class=\"has-border-right\">\n @if (row.modelColumns[modelIndex]; as column) {\n @if (isArray(column)) {\n <!-- parallel models: stacked in the same column, each with its own status -->\n @for (model of column; track model.methodId) {\n <ng-container *ngTemplateOutlet=\"modelCell; context: { model, row }\" />\n }\n } @else {\n <ng-container *ngTemplateOutlet=\"modelCell; context: { model: column, row }\" />\n }\n } @else {\n -\n }\n </td>\n }\n }\n</ng-template>\n\n<ng-template #modelCell let-model=\"model\" let-row=\"row\">\n <div class=\"is-flex is-align-self-stretch is-justify-content-center is-align-items-center is-gap-8\">\n <div class=\"is-flex is-gap-4 is-flex-grow-1 is-align-items-center\">\n <span\n class=\"pl-1 has-text-{{ logColor[model.status] }}\"\n [class.trigger-popover]=\"hasLogs()\"\n [ngbPopover]=\"logStatusDetails\"\n [disablePopover]=\"!hasLogs()\"\n autoClose=\"outside\"\n popoverClass=\"is-narrow\"\n triggers=\"manual\"\n #p1=\"ngbPopover\"\n placement=\"bottom left right auto\"\n container=\"body\"\n (click)=\"$event.stopPropagation(); p1.isOpen() ? p1.close() : p1.open({ model, row })\">\n <he-svg-icon [name]=\"logIcon[model.status]\" />\n </span>\n\n <span class=\"is-flex is-flex-grow-1 is-gap-4\">\n <span class=\"is-nowrap is-capitalized\">{{ methodName(model) }}</span>\n @if (modelMethodTier(model); as methodTier) {\n <span class=\"is-nowrap\">[{{ methodTier }}]</span>\n }\n </span>\n </div>\n\n <div class=\"is-flex is-gap-4 is-flex-shrink-0 is-align-items-center\">\n @if (model.showLogs) {\n <span\n class=\"is-nowrap is-clickable\"\n [ngbPopover]=\"logDetails\"\n autoClose=\"outside\"\n popoverClass=\"is-narrow\"\n triggers=\"manual\"\n #p=\"ngbPopover\"\n placement=\"bottom left right auto\"\n container=\"body\"\n (click)=\"p.isOpen() ? p.close() : p.open({ model, row })\">\n <span class=\"has-text-link\">Logs</span>\n </span>\n }\n @if (model.model) {\n @if (model.showLogs) {\n <div class=\"vertical-divider\"></div>\n }\n <ng-container *ngTemplateOutlet=\"docsLink; context: { $implicit: model.model }\" />\n }\n </div>\n </div>\n</ng-template>\n\n<ng-template #logDetails let-model=\"model\" let-row=\"row\">\n <he-node-logs-models-details\n [model]=\"model\"\n [value]=\"row?.recalculatedValue\"\n [node]=\"node()\"\n [nodeKey]=\"nodeKey()\"\n [hasContributions]=\"hasContributions()\" />\n</ng-template>\n\n<ng-template #logStatusDetails let-model=\"model\" let-row=\"row\">\n <he-node-logs-models-logs-status [nodeType]=\"nodeType()\" [model]=\"model\" [data]=\"$any(row)\" />\n</ng-template>\n\n<ng-template #docsLink let-model>\n @if (guideEnabled && model.guidePath) {\n <he-guide-overlay [pageId]=\"model.guidePath\" [width]=\"500\" />\n } @else {\n <a [href]=\"model.docPath || model.path\" target=\"_blank\" (click)=\"$event.stopPropagation()\">\n <span>Docs</span>\n <he-svg-icon name=\"external-link\" class=\"ml-2\" />\n </a>\n }\n</ng-template>\n", styles: [":host{display:block}:host .vertical-divider{width:1px;height:20px;background:#dbe3ea}:host .status-legend{border:1px solid #dbe3ea;background:#f5f7f9}:host .has-formula{cursor:help;border-bottom:1px dotted currentColor}::ng-deep .table{background-color:transparent}::ng-deep .table td.has-border-right{box-shadow:1px 0 #4c7194}::ng-deep .table td>div{min-height:24px}::ng-deep .table .has-sub-rows.is-open>td:first-child:before,::ng-deep .table .is-sub-row>td:first-child:before{display:block;position:absolute;content:\" \";background-color:#4c719433;height:100%;width:1px;top:0;left:14px}::ng-deep .table .has-sub-rows.is-open>td:first-child:before{top:25px}::ng-deep .table .is-sub-row .open-node>he-svg-icon,::ng-deep .table .is-sub-row .sub-sub-row-icon{height:16px!important;width:16px!important}::ng-deep .table .is-sub-sub-row td:first-child{padding-left:24px}\n"] }]
10732
10755
  }], propDecorators: { node: [{ type: i0.Input, args: [{ isSignal: true, alias: "node", required: true }] }], nodeKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "nodeKey", required: false }] }], originalValues: [{ type: i0.Input, args: [{ isSignal: true, alias: "originalValues", required: false }] }], recalculatedValues: [{ type: i0.Input, args: [{ isSignal: true, alias: "recalculatedValues", required: false }] }], filterTermTypes: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterTermTypes", required: false }] }], filterTermTypesLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterTermTypesLabel", required: false }] }], cycle: [{ type: i0.Input, args: [{ isSignal: true, alias: "cycle", required: false }] }], jlog: [{ type: i0.Input, args: [{ isSignal: true, alias: "jlog", required: false }] }], jlogParentKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "jlogParentKey", required: false }] }], jlogParentIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "jlogParentIndex", required: false }] }] } });
10733
10756
 
10734
10757
  const groupTerms = (terms) => terms.reduce((prev, curr) => ({ ...prev, [curr['@id']]: curr }), {});
@@ -11109,6 +11132,7 @@ class CyclesCompletenessComponent {
11109
11132
  this.dataState = input(DataState.original, ...(ngDevMode ? [{ debugName: "dataState" }] : []));
11110
11133
  this.schemaBaseUrl = schemaBaseUrl();
11111
11134
  this.defaultLabel = defaultLabel;
11135
+ this.nodeVersionKey = nodeVersionKey;
11112
11136
  this.keyToLabel = keyToLabel;
11113
11137
  this.getCompleteness = getCompleteness;
11114
11138
  this.nodeKey = NonBlankNodesKey.completeness;
@@ -11158,7 +11182,7 @@ class CyclesCompletenessComponent {
11158
11182
  component.headerKeys.set(headerKeys$1);
11159
11183
  }
11160
11184
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CyclesCompletenessComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
11161
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: CyclesCompletenessComponent, isStandalone: true, selector: "he-cycles-completeness", inputs: { dataState: { classPropertyName: "dataState", publicName: "dataState", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@switch (selectedView()) {\n @case (View.table) {\n @if (hasData()) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n <he-data-table class=\"is-mt-3 is-bordered\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n <tr class=\"has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n @for (completeness of completenessKeys(); track completeness) {\n <th [attr.title]=\"completeness\">\n <a [href]=\"schemaBaseUrl + '/Completeness#' + completeness\" target=\"_blank\">\n {{ keyToLabel(completeness) }}\n </a>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (cycle of cycles(); track cycle['@id']; let cycleIndex = $index) {\n <tr [class.is-suggested]=\"$any(cycle).suggested\">\n <td class=\"width-auto has-border-right\" [attr.title]=\"defaultLabel(cycle)\">\n <he-node-link [node]=\"cycle\">\n <span class=\"has-text-ellipsis is-ellipsis-3\">\n @if ($any(cycle).suggested) {\n <he-svg-icon name=\"compare\" />\n } @else {\n <span>{{ cycleIndex + 1 }}.</span>\n }\n <span class=\"is-pl-1\">{{ defaultLabel(cycle) }}</span>\n </span>\n </he-node-link>\n </td>\n @for (key of completenessKeys(); track key) {\n <td class=\"is-nowrap\">\n <span>\n {{ getCompleteness(cycle)[key] ? 'Complete' : 'Incomplete' }}\n </span>\n <he-blank-node-state\n class=\"ml-1\"\n [dataState]=\"dataState()\"\n [node]=\"getCompleteness(cycle)\"\n [key]=\"key\" />\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n </he-data-table>\n <he-blank-node-state-notice class=\"is-mt-2\" [dataState]=\"dataState()\" />\n } @else {\n <div class=\"panel-block\">\n <span>No completeness data</span>\n </div>\n }\n }\n @case (View.logs) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (selectedNode()) {\n <he-node-logs-models\n class=\"is-mt-2\"\n [node]=\"selectedNode()\"\n [nodeKey]=\"nodeKey\"\n [logsKey]=\"selectedLogsKey()\"\n [originalValues]=\"selectedOriginalValues()\"\n [recalculatedValues]=\"selectedRecalculatedValues()\" />\n }\n }\n}\n\n<ng-template #selectView>\n <div class=\"is-flex is-gap-8 is-align-items-center is-justify-content-space-between\">\n <div class=\"is-flex is-gap-8 is-align-items-center\">\n @if (selectedView() === View.table) {\n @if (hasData()) {\n <button class=\"button is-small is-ghost\" (click)=\"showDownload()\">\n <he-svg-icon name=\"download\" />\n </button>\n }\n } @else if (selectedView() === View.logs) {\n <ng-container *ngTemplateOutlet=\"selectCycle\" />\n }\n </div>\n\n @if (views()?.length > 1) {\n <div class=\"field has-addons button-segments\">\n @for (view of views(); track view) {\n <div class=\"control\">\n <button\n class=\"button is-small\"\n [class.is-selected]=\"selectedView() === view\"\n (click)=\"selectedView.set(view)\">\n <he-svg-icon\n name=\"checkmark\"\n aria-hidden=\"true\"\n class=\"is-hidden-mobile\"\n [class.is-hidden-tablet]=\"selectedView() !== view\" />\n <he-svg-icon\n [name]=\"viewIcon[view]\"\n aria-hidden=\"true\"\n [class.is-hidden-tablet]=\"selectedView() === view\" />\n <span class=\"is-hidden-mobile\">{{ view }}</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #selectCycle>\n @if (cycles().length > 1) {\n <div class=\"field is-horizontal is-mb-0\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary is-nowrap\" for=\"selectCycle\">Cycle</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"selectIndex($event)\" id=\"selectCycle\">\n @for (value of cycles(); track value; let cycleIndex = $index) {\n <option [value]=\"cycleIndex\">{{ cycleIndex + 1 }}. {{ defaultLabel(value) }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n</ng-template>\n", styles: [""], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: HESvgIconComponent, selector: "he-svg-icon", inputs: ["name", "size", "animation"] }, { kind: "component", type: DataTableComponent, selector: "he-data-table", inputs: ["minHeight", "maxHeight", "small"] }, { kind: "component", type: NodeLinkComponent, selector: "he-node-link", inputs: ["node", "dataState", "showExternalLink", "linkClass"] }, { kind: "component", type: BlankNodeStateComponent, selector: "he-blank-node-state", inputs: ["dataState", "nodeType", "dataKey", "key", "node", "state", "linkClass"] }, { kind: "component", type: BlankNodeStateNoticeComponent, selector: "he-blank-node-state-notice", inputs: ["dataState", "showDeleted"] }, { kind: "component", type: NodeLogsModelsComponent, selector: "he-node-logs-models", inputs: ["node", "nodeKey", "originalValues", "recalculatedValues", "terms", "filterTermTypes", "filterTermTypesLabel", "logsKey", "noDataMessage", "cycle", "jlogParentKey", "jlogParentIndex"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
11185
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: CyclesCompletenessComponent, isStandalone: true, selector: "he-cycles-completeness", inputs: { dataState: { classPropertyName: "dataState", publicName: "dataState", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@switch (selectedView()) {\n @case (View.table) {\n @if (hasData()) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n <he-data-table class=\"is-mt-3 is-bordered\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n <tr class=\"has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n @for (completeness of completenessKeys(); track completeness) {\n <th [attr.title]=\"completeness\">\n <a [href]=\"schemaBaseUrl + '/Completeness#' + completeness\" target=\"_blank\">\n {{ keyToLabel(completeness) }}\n </a>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (cycle of cycles(); track nodeVersionKey(cycle); let cycleIndex = $index) {\n <tr [class.is-suggested]=\"$any(cycle).suggested\">\n <td class=\"width-auto has-border-right\" [attr.title]=\"defaultLabel(cycle)\">\n <he-node-link [node]=\"cycle\">\n <span class=\"has-text-ellipsis is-ellipsis-3\">\n @if ($any(cycle).suggested) {\n <he-svg-icon name=\"compare\" />\n } @else {\n <span>{{ cycleIndex + 1 }}.</span>\n }\n <span class=\"is-pl-1\">{{ defaultLabel(cycle) }}</span>\n </span>\n </he-node-link>\n </td>\n @for (key of completenessKeys(); track key) {\n <td class=\"is-nowrap\">\n <span>\n {{ getCompleteness(cycle)[key] ? 'Complete' : 'Incomplete' }}\n </span>\n <he-blank-node-state\n class=\"ml-1\"\n [dataState]=\"dataState()\"\n [node]=\"getCompleteness(cycle)\"\n [key]=\"key\" />\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n </he-data-table>\n <he-blank-node-state-notice class=\"is-mt-2\" [dataState]=\"dataState()\" />\n } @else {\n <div class=\"panel-block\">\n <span>No completeness data</span>\n </div>\n }\n }\n @case (View.logs) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (selectedNode()) {\n <he-node-logs-models\n class=\"is-mt-2\"\n [node]=\"selectedNode()\"\n [nodeKey]=\"nodeKey\"\n [logsKey]=\"selectedLogsKey()\"\n [originalValues]=\"selectedOriginalValues()\"\n [recalculatedValues]=\"selectedRecalculatedValues()\" />\n }\n }\n}\n\n<ng-template #selectView>\n <div class=\"is-flex is-gap-8 is-align-items-center is-justify-content-space-between\">\n <div class=\"is-flex is-gap-8 is-align-items-center\">\n @if (selectedView() === View.table) {\n @if (hasData()) {\n <button class=\"button is-small is-ghost\" (click)=\"showDownload()\">\n <he-svg-icon name=\"download\" />\n </button>\n }\n } @else if (selectedView() === View.logs) {\n <ng-container *ngTemplateOutlet=\"selectCycle\" />\n }\n </div>\n\n @if (views()?.length > 1) {\n <div class=\"field has-addons button-segments\">\n @for (view of views(); track view) {\n <div class=\"control\">\n <button\n class=\"button is-small\"\n [class.is-selected]=\"selectedView() === view\"\n (click)=\"selectedView.set(view)\">\n <he-svg-icon\n name=\"checkmark\"\n aria-hidden=\"true\"\n class=\"is-hidden-mobile\"\n [class.is-hidden-tablet]=\"selectedView() !== view\" />\n <he-svg-icon\n [name]=\"viewIcon[view]\"\n aria-hidden=\"true\"\n [class.is-hidden-tablet]=\"selectedView() === view\" />\n <span class=\"is-hidden-mobile\">{{ view }}</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #selectCycle>\n @if (cycles().length > 1) {\n <div class=\"field is-horizontal is-mb-0\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary is-nowrap\" for=\"selectCycle\">Cycle</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"selectIndex($event)\" id=\"selectCycle\">\n @for (value of cycles(); track nodeVersionKey(value); let cycleIndex = $index) {\n <option [value]=\"cycleIndex\">{{ cycleIndex + 1 }}. {{ defaultLabel(value) }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n</ng-template>\n", styles: [""], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: HESvgIconComponent, selector: "he-svg-icon", inputs: ["name", "size", "animation"] }, { kind: "component", type: DataTableComponent, selector: "he-data-table", inputs: ["minHeight", "maxHeight", "small"] }, { kind: "component", type: NodeLinkComponent, selector: "he-node-link", inputs: ["node", "dataState", "showExternalLink", "linkClass"] }, { kind: "component", type: BlankNodeStateComponent, selector: "he-blank-node-state", inputs: ["dataState", "nodeType", "dataKey", "key", "node", "state", "linkClass"] }, { kind: "component", type: BlankNodeStateNoticeComponent, selector: "he-blank-node-state-notice", inputs: ["dataState", "showDeleted"] }, { kind: "component", type: NodeLogsModelsComponent, selector: "he-node-logs-models", inputs: ["node", "nodeKey", "originalValues", "recalculatedValues", "terms", "filterTermTypes", "filterTermTypesLabel", "logsKey", "noDataMessage", "cycle", "jlogParentKey", "jlogParentIndex"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
11162
11186
  }
11163
11187
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CyclesCompletenessComponent, decorators: [{
11164
11188
  type: Component$1,
@@ -11170,7 +11194,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
11170
11194
  BlankNodeStateComponent,
11171
11195
  BlankNodeStateNoticeComponent,
11172
11196
  NodeLogsModelsComponent
11173
- ], template: "@switch (selectedView()) {\n @case (View.table) {\n @if (hasData()) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n <he-data-table class=\"is-mt-3 is-bordered\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n <tr class=\"has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n @for (completeness of completenessKeys(); track completeness) {\n <th [attr.title]=\"completeness\">\n <a [href]=\"schemaBaseUrl + '/Completeness#' + completeness\" target=\"_blank\">\n {{ keyToLabel(completeness) }}\n </a>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (cycle of cycles(); track cycle['@id']; let cycleIndex = $index) {\n <tr [class.is-suggested]=\"$any(cycle).suggested\">\n <td class=\"width-auto has-border-right\" [attr.title]=\"defaultLabel(cycle)\">\n <he-node-link [node]=\"cycle\">\n <span class=\"has-text-ellipsis is-ellipsis-3\">\n @if ($any(cycle).suggested) {\n <he-svg-icon name=\"compare\" />\n } @else {\n <span>{{ cycleIndex + 1 }}.</span>\n }\n <span class=\"is-pl-1\">{{ defaultLabel(cycle) }}</span>\n </span>\n </he-node-link>\n </td>\n @for (key of completenessKeys(); track key) {\n <td class=\"is-nowrap\">\n <span>\n {{ getCompleteness(cycle)[key] ? 'Complete' : 'Incomplete' }}\n </span>\n <he-blank-node-state\n class=\"ml-1\"\n [dataState]=\"dataState()\"\n [node]=\"getCompleteness(cycle)\"\n [key]=\"key\" />\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n </he-data-table>\n <he-blank-node-state-notice class=\"is-mt-2\" [dataState]=\"dataState()\" />\n } @else {\n <div class=\"panel-block\">\n <span>No completeness data</span>\n </div>\n }\n }\n @case (View.logs) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (selectedNode()) {\n <he-node-logs-models\n class=\"is-mt-2\"\n [node]=\"selectedNode()\"\n [nodeKey]=\"nodeKey\"\n [logsKey]=\"selectedLogsKey()\"\n [originalValues]=\"selectedOriginalValues()\"\n [recalculatedValues]=\"selectedRecalculatedValues()\" />\n }\n }\n}\n\n<ng-template #selectView>\n <div class=\"is-flex is-gap-8 is-align-items-center is-justify-content-space-between\">\n <div class=\"is-flex is-gap-8 is-align-items-center\">\n @if (selectedView() === View.table) {\n @if (hasData()) {\n <button class=\"button is-small is-ghost\" (click)=\"showDownload()\">\n <he-svg-icon name=\"download\" />\n </button>\n }\n } @else if (selectedView() === View.logs) {\n <ng-container *ngTemplateOutlet=\"selectCycle\" />\n }\n </div>\n\n @if (views()?.length > 1) {\n <div class=\"field has-addons button-segments\">\n @for (view of views(); track view) {\n <div class=\"control\">\n <button\n class=\"button is-small\"\n [class.is-selected]=\"selectedView() === view\"\n (click)=\"selectedView.set(view)\">\n <he-svg-icon\n name=\"checkmark\"\n aria-hidden=\"true\"\n class=\"is-hidden-mobile\"\n [class.is-hidden-tablet]=\"selectedView() !== view\" />\n <he-svg-icon\n [name]=\"viewIcon[view]\"\n aria-hidden=\"true\"\n [class.is-hidden-tablet]=\"selectedView() === view\" />\n <span class=\"is-hidden-mobile\">{{ view }}</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #selectCycle>\n @if (cycles().length > 1) {\n <div class=\"field is-horizontal is-mb-0\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary is-nowrap\" for=\"selectCycle\">Cycle</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"selectIndex($event)\" id=\"selectCycle\">\n @for (value of cycles(); track value; let cycleIndex = $index) {\n <option [value]=\"cycleIndex\">{{ cycleIndex + 1 }}. {{ defaultLabel(value) }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n</ng-template>\n" }]
11197
+ ], template: "@switch (selectedView()) {\n @case (View.table) {\n @if (hasData()) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n <he-data-table class=\"is-mt-3 is-bordered\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n <tr class=\"has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n @for (completeness of completenessKeys(); track completeness) {\n <th [attr.title]=\"completeness\">\n <a [href]=\"schemaBaseUrl + '/Completeness#' + completeness\" target=\"_blank\">\n {{ keyToLabel(completeness) }}\n </a>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (cycle of cycles(); track nodeVersionKey(cycle); let cycleIndex = $index) {\n <tr [class.is-suggested]=\"$any(cycle).suggested\">\n <td class=\"width-auto has-border-right\" [attr.title]=\"defaultLabel(cycle)\">\n <he-node-link [node]=\"cycle\">\n <span class=\"has-text-ellipsis is-ellipsis-3\">\n @if ($any(cycle).suggested) {\n <he-svg-icon name=\"compare\" />\n } @else {\n <span>{{ cycleIndex + 1 }}.</span>\n }\n <span class=\"is-pl-1\">{{ defaultLabel(cycle) }}</span>\n </span>\n </he-node-link>\n </td>\n @for (key of completenessKeys(); track key) {\n <td class=\"is-nowrap\">\n <span>\n {{ getCompleteness(cycle)[key] ? 'Complete' : 'Incomplete' }}\n </span>\n <he-blank-node-state\n class=\"ml-1\"\n [dataState]=\"dataState()\"\n [node]=\"getCompleteness(cycle)\"\n [key]=\"key\" />\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n </he-data-table>\n <he-blank-node-state-notice class=\"is-mt-2\" [dataState]=\"dataState()\" />\n } @else {\n <div class=\"panel-block\">\n <span>No completeness data</span>\n </div>\n }\n }\n @case (View.logs) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (selectedNode()) {\n <he-node-logs-models\n class=\"is-mt-2\"\n [node]=\"selectedNode()\"\n [nodeKey]=\"nodeKey\"\n [logsKey]=\"selectedLogsKey()\"\n [originalValues]=\"selectedOriginalValues()\"\n [recalculatedValues]=\"selectedRecalculatedValues()\" />\n }\n }\n}\n\n<ng-template #selectView>\n <div class=\"is-flex is-gap-8 is-align-items-center is-justify-content-space-between\">\n <div class=\"is-flex is-gap-8 is-align-items-center\">\n @if (selectedView() === View.table) {\n @if (hasData()) {\n <button class=\"button is-small is-ghost\" (click)=\"showDownload()\">\n <he-svg-icon name=\"download\" />\n </button>\n }\n } @else if (selectedView() === View.logs) {\n <ng-container *ngTemplateOutlet=\"selectCycle\" />\n }\n </div>\n\n @if (views()?.length > 1) {\n <div class=\"field has-addons button-segments\">\n @for (view of views(); track view) {\n <div class=\"control\">\n <button\n class=\"button is-small\"\n [class.is-selected]=\"selectedView() === view\"\n (click)=\"selectedView.set(view)\">\n <he-svg-icon\n name=\"checkmark\"\n aria-hidden=\"true\"\n class=\"is-hidden-mobile\"\n [class.is-hidden-tablet]=\"selectedView() !== view\" />\n <he-svg-icon\n [name]=\"viewIcon[view]\"\n aria-hidden=\"true\"\n [class.is-hidden-tablet]=\"selectedView() === view\" />\n <span class=\"is-hidden-mobile\">{{ view }}</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #selectCycle>\n @if (cycles().length > 1) {\n <div class=\"field is-horizontal is-mb-0\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary is-nowrap\" for=\"selectCycle\">Cycle</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"selectIndex($event)\" id=\"selectCycle\">\n @for (value of cycles(); track nodeVersionKey(value); let cycleIndex = $index) {\n <option [value]=\"cycleIndex\">{{ cycleIndex + 1 }}. {{ defaultLabel(value) }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n</ng-template>\n" }]
11174
11198
  }], ctorParameters: () => [], propDecorators: { dataState: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataState", required: false }] }] } });
11175
11199
 
11176
11200
  const cycleValue = (cycle, values) => (values[cycle['@id']]?.nodes[0] || { value: [0] }).value;
@@ -11257,6 +11281,7 @@ class CyclesMetadataComponent {
11257
11281
  this.dataState = input(DataState.original, ...(ngDevMode ? [{ debugName: "dataState" }] : []));
11258
11282
  this.schemaBaseUrl = schemaBaseUrl();
11259
11283
  this.defaultLabel = defaultLabel;
11284
+ this.nodeVersionKey = nodeVersionKey;
11260
11285
  this.keyToLabel = keyToLabel;
11261
11286
  this.NodeType = NodeType;
11262
11287
  this.View = View$3;
@@ -11295,7 +11320,7 @@ class CyclesMetadataComponent {
11295
11320
  component.headerKeys.set(headerKeys);
11296
11321
  }
11297
11322
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CyclesMetadataComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
11298
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: CyclesMetadataComponent, isStandalone: true, selector: "he-cycles-metadata", inputs: { dataState: { classPropertyName: "dataState", publicName: "dataState", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@switch (selectedView()) {\n @case (View.table) {\n @if (hasData()) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n <he-data-table class=\"is-mt-3 is-bordered\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n <tr class=\"has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n @for (key of keys(); track key) {\n <th [attr.title]=\"key\">\n <a [href]=\"schemaBaseUrl + '/Cycle#' + key\" target=\"_blank\">\n {{ keyToLabel(key) }}\n </a>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (cycle of cycles(); track cycle['@id']; let cycleIndex = $index) {\n <tr [class.is-suggested]=\"$any(cycle).suggested\">\n <td class=\"width-auto has-border-right\" [attr.title]=\"defaultLabel(cycle)\">\n <he-node-link [node]=\"cycle\">\n <span class=\"has-text-ellipsis is-ellipsis-3\">\n @if ($any(cycle).suggested) {\n <he-svg-icon name=\"compare\" />\n } @else {\n <span>{{ cycleIndex + 1 }}.</span>\n }\n <span class=\"is-pl-1\">{{ defaultLabel(cycle) }}</span>\n </span>\n </he-node-link>\n </td>\n @for (key of keys(); track key) {\n <td class=\"is-nowrap\">\n @if (isUndefined(cycle[key])) {\n <span>-</span>\n } @else {\n <span>{{ toString(cycle[key]) }}</span>\n }\n <he-blank-node-state class=\"ml-1\" [dataState]=\"dataState()\" [node]=\"cycle\" [key]=\"key\" />\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n </he-data-table>\n <he-blank-node-state-notice class=\"is-mt-2\" [dataState]=\"dataState()\" />\n } @else {\n <div class=\"panel-block\">\n <span>No data.</span>\n @if (showSwitchToRecalculated()) {\n <span>\n Switch to\n <code>recalculated</code>\n version.\n </span>\n }\n </div>\n }\n }\n @case (View.logs) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (selectedCycle()) {\n <he-node-logs-models\n class=\"is-mt-2\"\n [node]=\"selectedCycle()\"\n [originalValues]=\"selectedOriginalValues()\"\n [recalculatedValues]=\"selectedRecalculatedValues()\" />\n }\n }\n}\n\n<ng-template #selectView>\n <div class=\"is-flex is-gap-8 is-align-items-center is-justify-content-space-between\">\n <div class=\"is-flex is-gap-8 is-align-items-center\">\n @if (selectedView() === View.table) {\n @if (hasData()) {\n <button class=\"button is-small is-ghost\" (click)=\"showDownload()\">\n <he-svg-icon name=\"download\" />\n </button>\n }\n } @else if (showSelectCycle()) {\n <ng-container *ngTemplateOutlet=\"selectCycle\" />\n }\n </div>\n\n @if (views()?.length > 1) {\n <div class=\"field has-addons button-segments\">\n @for (view of views(); track view) {\n <div class=\"control\">\n <button\n class=\"button is-small\"\n [class.is-selected]=\"selectedView() === view\"\n (click)=\"selectedView.set(view)\">\n <he-svg-icon\n name=\"checkmark\"\n aria-hidden=\"true\"\n class=\"is-hidden-mobile\"\n [class.is-hidden-tablet]=\"selectedView() !== view\" />\n <he-svg-icon\n [name]=\"viewIcon[view]\"\n aria-hidden=\"true\"\n [class.is-hidden-tablet]=\"selectedView() === view\" />\n <span class=\"is-hidden-mobile\">{{ view }}</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #selectCycle>\n @if (cycles().length > 1) {\n <div class=\"field is-horizontal is-mb-0\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary is-nowrap\" for=\"selectCycle\">Cycle</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"selectIndex($event)\" if=\"selectCycle\">\n @for (value of cycles(); track value; let cycleIndex = $index) {\n <option [value]=\"cycleIndex\">{{ cycleIndex + 1 }}. {{ defaultLabel(value) }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n</ng-template>\n", styles: [""], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: HESvgIconComponent, selector: "he-svg-icon", inputs: ["name", "size", "animation"] }, { kind: "component", type: DataTableComponent, selector: "he-data-table", inputs: ["minHeight", "maxHeight", "small"] }, { kind: "component", type: NodeLinkComponent, selector: "he-node-link", inputs: ["node", "dataState", "showExternalLink", "linkClass"] }, { kind: "component", type: BlankNodeStateComponent, selector: "he-blank-node-state", inputs: ["dataState", "nodeType", "dataKey", "key", "node", "state", "linkClass"] }, { kind: "component", type: BlankNodeStateNoticeComponent, selector: "he-blank-node-state-notice", inputs: ["dataState", "showDeleted"] }, { kind: "component", type: NodeLogsModelsComponent, selector: "he-node-logs-models", inputs: ["node", "nodeKey", "originalValues", "recalculatedValues", "terms", "filterTermTypes", "filterTermTypesLabel", "logsKey", "noDataMessage", "cycle", "jlogParentKey", "jlogParentIndex"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
11323
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: CyclesMetadataComponent, isStandalone: true, selector: "he-cycles-metadata", inputs: { dataState: { classPropertyName: "dataState", publicName: "dataState", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@switch (selectedView()) {\n @case (View.table) {\n @if (hasData()) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n <he-data-table class=\"is-mt-3 is-bordered\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n <tr class=\"has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n @for (key of keys(); track key) {\n <th [attr.title]=\"key\">\n <a [href]=\"schemaBaseUrl + '/Cycle#' + key\" target=\"_blank\">\n {{ keyToLabel(key) }}\n </a>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (cycle of cycles(); track nodeVersionKey(cycle); let cycleIndex = $index) {\n <tr [class.is-suggested]=\"$any(cycle).suggested\">\n <td class=\"width-auto has-border-right\" [attr.title]=\"defaultLabel(cycle)\">\n <he-node-link [node]=\"cycle\">\n <span class=\"has-text-ellipsis is-ellipsis-3\">\n @if ($any(cycle).suggested) {\n <he-svg-icon name=\"compare\" />\n } @else {\n <span>{{ cycleIndex + 1 }}.</span>\n }\n <span class=\"is-pl-1\">{{ defaultLabel(cycle) }}</span>\n </span>\n </he-node-link>\n </td>\n @for (key of keys(); track key) {\n <td class=\"is-nowrap\">\n @if (isUndefined(cycle[key])) {\n <span>-</span>\n } @else {\n <span>{{ toString(cycle[key]) }}</span>\n }\n <he-blank-node-state class=\"ml-1\" [dataState]=\"dataState()\" [node]=\"cycle\" [key]=\"key\" />\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n </he-data-table>\n <he-blank-node-state-notice class=\"is-mt-2\" [dataState]=\"dataState()\" />\n } @else {\n <div class=\"panel-block\">\n <span>No data.</span>\n @if (showSwitchToRecalculated()) {\n <span>\n Switch to\n <code>recalculated</code>\n version.\n </span>\n }\n </div>\n }\n }\n @case (View.logs) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (selectedCycle()) {\n <he-node-logs-models\n class=\"is-mt-2\"\n [node]=\"selectedCycle()\"\n [originalValues]=\"selectedOriginalValues()\"\n [recalculatedValues]=\"selectedRecalculatedValues()\" />\n }\n }\n}\n\n<ng-template #selectView>\n <div class=\"is-flex is-gap-8 is-align-items-center is-justify-content-space-between\">\n <div class=\"is-flex is-gap-8 is-align-items-center\">\n @if (selectedView() === View.table) {\n @if (hasData()) {\n <button class=\"button is-small is-ghost\" (click)=\"showDownload()\">\n <he-svg-icon name=\"download\" />\n </button>\n }\n } @else if (showSelectCycle()) {\n <ng-container *ngTemplateOutlet=\"selectCycle\" />\n }\n </div>\n\n @if (views()?.length > 1) {\n <div class=\"field has-addons button-segments\">\n @for (view of views(); track view) {\n <div class=\"control\">\n <button\n class=\"button is-small\"\n [class.is-selected]=\"selectedView() === view\"\n (click)=\"selectedView.set(view)\">\n <he-svg-icon\n name=\"checkmark\"\n aria-hidden=\"true\"\n class=\"is-hidden-mobile\"\n [class.is-hidden-tablet]=\"selectedView() !== view\" />\n <he-svg-icon\n [name]=\"viewIcon[view]\"\n aria-hidden=\"true\"\n [class.is-hidden-tablet]=\"selectedView() === view\" />\n <span class=\"is-hidden-mobile\">{{ view }}</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #selectCycle>\n @if (cycles().length > 1) {\n <div class=\"field is-horizontal is-mb-0\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary is-nowrap\" for=\"selectCycle\">Cycle</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"selectIndex($event)\" if=\"selectCycle\">\n @for (value of cycles(); track nodeVersionKey(value); let cycleIndex = $index) {\n <option [value]=\"cycleIndex\">{{ cycleIndex + 1 }}. {{ defaultLabel(value) }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n</ng-template>\n", styles: [""], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: HESvgIconComponent, selector: "he-svg-icon", inputs: ["name", "size", "animation"] }, { kind: "component", type: DataTableComponent, selector: "he-data-table", inputs: ["minHeight", "maxHeight", "small"] }, { kind: "component", type: NodeLinkComponent, selector: "he-node-link", inputs: ["node", "dataState", "showExternalLink", "linkClass"] }, { kind: "component", type: BlankNodeStateComponent, selector: "he-blank-node-state", inputs: ["dataState", "nodeType", "dataKey", "key", "node", "state", "linkClass"] }, { kind: "component", type: BlankNodeStateNoticeComponent, selector: "he-blank-node-state-notice", inputs: ["dataState", "showDeleted"] }, { kind: "component", type: NodeLogsModelsComponent, selector: "he-node-logs-models", inputs: ["node", "nodeKey", "originalValues", "recalculatedValues", "terms", "filterTermTypes", "filterTermTypesLabel", "logsKey", "noDataMessage", "cycle", "jlogParentKey", "jlogParentIndex"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
11299
11324
  }
11300
11325
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CyclesMetadataComponent, decorators: [{
11301
11326
  type: Component$1,
@@ -11307,7 +11332,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
11307
11332
  BlankNodeStateComponent,
11308
11333
  BlankNodeStateNoticeComponent,
11309
11334
  NodeLogsModelsComponent
11310
- ], changeDetection: ChangeDetectionStrategy.OnPush, template: "@switch (selectedView()) {\n @case (View.table) {\n @if (hasData()) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n <he-data-table class=\"is-mt-3 is-bordered\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n <tr class=\"has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n @for (key of keys(); track key) {\n <th [attr.title]=\"key\">\n <a [href]=\"schemaBaseUrl + '/Cycle#' + key\" target=\"_blank\">\n {{ keyToLabel(key) }}\n </a>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (cycle of cycles(); track cycle['@id']; let cycleIndex = $index) {\n <tr [class.is-suggested]=\"$any(cycle).suggested\">\n <td class=\"width-auto has-border-right\" [attr.title]=\"defaultLabel(cycle)\">\n <he-node-link [node]=\"cycle\">\n <span class=\"has-text-ellipsis is-ellipsis-3\">\n @if ($any(cycle).suggested) {\n <he-svg-icon name=\"compare\" />\n } @else {\n <span>{{ cycleIndex + 1 }}.</span>\n }\n <span class=\"is-pl-1\">{{ defaultLabel(cycle) }}</span>\n </span>\n </he-node-link>\n </td>\n @for (key of keys(); track key) {\n <td class=\"is-nowrap\">\n @if (isUndefined(cycle[key])) {\n <span>-</span>\n } @else {\n <span>{{ toString(cycle[key]) }}</span>\n }\n <he-blank-node-state class=\"ml-1\" [dataState]=\"dataState()\" [node]=\"cycle\" [key]=\"key\" />\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n </he-data-table>\n <he-blank-node-state-notice class=\"is-mt-2\" [dataState]=\"dataState()\" />\n } @else {\n <div class=\"panel-block\">\n <span>No data.</span>\n @if (showSwitchToRecalculated()) {\n <span>\n Switch to\n <code>recalculated</code>\n version.\n </span>\n }\n </div>\n }\n }\n @case (View.logs) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (selectedCycle()) {\n <he-node-logs-models\n class=\"is-mt-2\"\n [node]=\"selectedCycle()\"\n [originalValues]=\"selectedOriginalValues()\"\n [recalculatedValues]=\"selectedRecalculatedValues()\" />\n }\n }\n}\n\n<ng-template #selectView>\n <div class=\"is-flex is-gap-8 is-align-items-center is-justify-content-space-between\">\n <div class=\"is-flex is-gap-8 is-align-items-center\">\n @if (selectedView() === View.table) {\n @if (hasData()) {\n <button class=\"button is-small is-ghost\" (click)=\"showDownload()\">\n <he-svg-icon name=\"download\" />\n </button>\n }\n } @else if (showSelectCycle()) {\n <ng-container *ngTemplateOutlet=\"selectCycle\" />\n }\n </div>\n\n @if (views()?.length > 1) {\n <div class=\"field has-addons button-segments\">\n @for (view of views(); track view) {\n <div class=\"control\">\n <button\n class=\"button is-small\"\n [class.is-selected]=\"selectedView() === view\"\n (click)=\"selectedView.set(view)\">\n <he-svg-icon\n name=\"checkmark\"\n aria-hidden=\"true\"\n class=\"is-hidden-mobile\"\n [class.is-hidden-tablet]=\"selectedView() !== view\" />\n <he-svg-icon\n [name]=\"viewIcon[view]\"\n aria-hidden=\"true\"\n [class.is-hidden-tablet]=\"selectedView() === view\" />\n <span class=\"is-hidden-mobile\">{{ view }}</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #selectCycle>\n @if (cycles().length > 1) {\n <div class=\"field is-horizontal is-mb-0\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary is-nowrap\" for=\"selectCycle\">Cycle</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"selectIndex($event)\" if=\"selectCycle\">\n @for (value of cycles(); track value; let cycleIndex = $index) {\n <option [value]=\"cycleIndex\">{{ cycleIndex + 1 }}. {{ defaultLabel(value) }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n</ng-template>\n" }]
11335
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "@switch (selectedView()) {\n @case (View.table) {\n @if (hasData()) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n <he-data-table class=\"is-mt-3 is-bordered\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n <tr class=\"has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n @for (key of keys(); track key) {\n <th [attr.title]=\"key\">\n <a [href]=\"schemaBaseUrl + '/Cycle#' + key\" target=\"_blank\">\n {{ keyToLabel(key) }}\n </a>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (cycle of cycles(); track nodeVersionKey(cycle); let cycleIndex = $index) {\n <tr [class.is-suggested]=\"$any(cycle).suggested\">\n <td class=\"width-auto has-border-right\" [attr.title]=\"defaultLabel(cycle)\">\n <he-node-link [node]=\"cycle\">\n <span class=\"has-text-ellipsis is-ellipsis-3\">\n @if ($any(cycle).suggested) {\n <he-svg-icon name=\"compare\" />\n } @else {\n <span>{{ cycleIndex + 1 }}.</span>\n }\n <span class=\"is-pl-1\">{{ defaultLabel(cycle) }}</span>\n </span>\n </he-node-link>\n </td>\n @for (key of keys(); track key) {\n <td class=\"is-nowrap\">\n @if (isUndefined(cycle[key])) {\n <span>-</span>\n } @else {\n <span>{{ toString(cycle[key]) }}</span>\n }\n <he-blank-node-state class=\"ml-1\" [dataState]=\"dataState()\" [node]=\"cycle\" [key]=\"key\" />\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n </he-data-table>\n <he-blank-node-state-notice class=\"is-mt-2\" [dataState]=\"dataState()\" />\n } @else {\n <div class=\"panel-block\">\n <span>No data.</span>\n @if (showSwitchToRecalculated()) {\n <span>\n Switch to\n <code>recalculated</code>\n version.\n </span>\n }\n </div>\n }\n }\n @case (View.logs) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (selectedCycle()) {\n <he-node-logs-models\n class=\"is-mt-2\"\n [node]=\"selectedCycle()\"\n [originalValues]=\"selectedOriginalValues()\"\n [recalculatedValues]=\"selectedRecalculatedValues()\" />\n }\n }\n}\n\n<ng-template #selectView>\n <div class=\"is-flex is-gap-8 is-align-items-center is-justify-content-space-between\">\n <div class=\"is-flex is-gap-8 is-align-items-center\">\n @if (selectedView() === View.table) {\n @if (hasData()) {\n <button class=\"button is-small is-ghost\" (click)=\"showDownload()\">\n <he-svg-icon name=\"download\" />\n </button>\n }\n } @else if (showSelectCycle()) {\n <ng-container *ngTemplateOutlet=\"selectCycle\" />\n }\n </div>\n\n @if (views()?.length > 1) {\n <div class=\"field has-addons button-segments\">\n @for (view of views(); track view) {\n <div class=\"control\">\n <button\n class=\"button is-small\"\n [class.is-selected]=\"selectedView() === view\"\n (click)=\"selectedView.set(view)\">\n <he-svg-icon\n name=\"checkmark\"\n aria-hidden=\"true\"\n class=\"is-hidden-mobile\"\n [class.is-hidden-tablet]=\"selectedView() !== view\" />\n <he-svg-icon\n [name]=\"viewIcon[view]\"\n aria-hidden=\"true\"\n [class.is-hidden-tablet]=\"selectedView() === view\" />\n <span class=\"is-hidden-mobile\">{{ view }}</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #selectCycle>\n @if (cycles().length > 1) {\n <div class=\"field is-horizontal is-mb-0\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary is-nowrap\" for=\"selectCycle\">Cycle</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"selectIndex($event)\" if=\"selectCycle\">\n @for (value of cycles(); track nodeVersionKey(value); let cycleIndex = $index) {\n <option [value]=\"cycleIndex\">{{ cycleIndex + 1 }}. {{ defaultLabel(value) }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n</ng-template>\n" }]
11311
11336
  }], propDecorators: { dataState: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataState", required: false }] }] } });
11312
11337
 
11313
11338
  // TODO: compute from the list of unique properties
@@ -11628,7 +11653,8 @@ const cycleGroupNode = (cycle) => (node) => node
11628
11653
  name: cycle?.name,
11629
11654
  startDate: cycle?.startDate,
11630
11655
  endDate: cycle?.endDate,
11631
- '@id': cycle?.['@id'] // set @id so we can fetch the logs from the Cycle
11656
+ '@id': cycle?.['@id'], // set @id so we can fetch the logs from the Cycle
11657
+ dataVersion: cycle?.dataVersion // keep the data version so the logs are fetched for the right version
11632
11658
  }
11633
11659
  : null;
11634
11660
  const cycleGroupNodes = (groupKey, cycle) => (cycle?.[groupKey] || []).map(cycleGroupNode(cycle)).filter(Boolean);
@@ -11652,6 +11678,7 @@ class CyclesNodesComponent {
11652
11678
  this.schemaBaseUrl = schemaBaseUrl();
11653
11679
  this.countGroupVisibleNodes = countGroupVisibleNodes;
11654
11680
  this.defaultLabel = defaultLabel;
11681
+ this.nodeVersionKey = nodeVersionKey;
11655
11682
  this.headerKeys = computed(() => [
11656
11683
  'cycle.id',
11657
11684
  'cycle.@id',
@@ -11784,7 +11811,7 @@ class CyclesNodesComponent {
11784
11811
  component.headerKeys.set(this.headerKeys());
11785
11812
  }
11786
11813
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CyclesNodesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
11787
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: CyclesNodesComponent, isStandalone: true, selector: "he-cycles-nodes", inputs: { dataState: { classPropertyName: "dataState", publicName: "dataState", isSignal: true, isRequired: false, transformFunction: null }, nodeKeys: { classPropertyName: "nodeKeys", publicName: "nodeKeys", isSignal: true, isRequired: true, transformFunction: null }, nodeKeyGroup: { classPropertyName: "nodeKeyGroup", publicName: "nodeKeyGroup", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (isGroupNode()) {\n <div class=\"tabs is-mb-1 | group-nodes-tabs\">\n <ul>\n @for (value of groupNodeValues(); track value) {\n <li\n [class.is-active]=\"selectedGroup() === value.value\"\n [ngbTooltip]=\"value.term.name\"\n placement=\"top\"\n container=\"body\">\n <a (click)=\"selectedGroup.set(value.value)\">\n <span class=\"is-capitalized is-pr-1\">{{ nodeKeyGroup() | pluralize: 1 }}:</span>\n <span>{{ value.value }}</span>\n </a>\n </li>\n }\n </ul>\n </div>\n}\n\n@if (isNodeKeyAllowed()) {\n @switch (selectedView()) {\n @case (View.table) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (hasData()) {\n <he-data-table class=\"is-mt-3 is-bordered\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n @if (dataKeys().length > 1) {\n <tr class=\"has-text-weight-bold\">\n <th class=\"width-auto has-border-right\"></th>\n <th class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\"></th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @let blankNodesCount = countGroupVisibleNodes(blankNodes);\n @if (blankNodesCount > 0) {\n <th [attr.colspan]=\"blankNodesCount\" [class.has-border-right]=\"!dataKeyLast\">\n <span>{{ dataKey | keyToLabel }}</span>\n </th>\n }\n }\n </tr>\n }\n <tr class=\"has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n <th class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\"></th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n <th\n [attr.title]=\"node.value.term.name\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n <he-node-link [node]=\"node.value.term\">\n <span\n [innerHtml]=\"\n node.value.term.name | ellipsis: 30 | compound: node.value.term.termType\n \"></span>\n </he-node-link>\n </th>\n }\n }\n }\n </tr>\n <tr class=\"is-italic has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n <th class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\">\n <a [href]=\"schemaBaseUrl + '/Cycle#functionalUnit'\" target=\"_blank\">Functional unit</a>\n </th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n <th\n [attr.title]=\"node.value.term.units\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n <span [innerHtml]=\"node.value.term.units | compound\"></span>\n <he-terms-units-description class=\"is-inline-block is-ml-2\" [term]=\"node.value.term\" />\n </th>\n }\n }\n }\n </tr>\n </thead>\n <tbody>\n @for (cycle of cycles(); track cycle['@id']; let cycleIndex = $index) {\n <tr [class.is-suggested]=\"$any(cycle).suggested\">\n <td class=\"width-auto has-border-right\" [attr.title]=\"defaultLabel(cycle)\">\n <he-node-link [node]=\"cycleNode(cycle)\">\n <span class=\"has-text-ellipsis is-ellipsis-3\">\n @if ($any(cycle).suggested) {\n <he-svg-icon name=\"compare\" />\n } @else {\n <span>{{ cycleIndex + 1 }}.</span>\n }\n <span class=\"is-pl-1\">{{ defaultLabel(cycle) }}</span>\n </span>\n </he-node-link>\n </td>\n <td class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\">\n <he-cycles-functional-unit-measure [cycle]=\"cycle\" />\n </td>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n @let cycleData = node.value.values[cycle['@id']];\n <td\n class=\"is-nowrap\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n @if (cycleData) {\n <span\n class=\"trigger-popover\"\n [ngbPopover]=\"details\"\n autoClose=\"outside\"\n popoverClass=\"is-narrow is-overflow-visible\"\n placement=\"left bottom auto\"\n container=\"body\"\n [popoverContext]=\"{ data: cycleData, cycle, key: dataKey }\">\n <span pointer>\n {{ cycleData.propertyValue | precision: 3 | default: '-' }}\n </span>\n <he-blank-node-state\n class=\"ml-1\"\n [dataState]=\"dataState()\"\n [node]=\"cycleData.node\"\n key=\"value\" />\n </span>\n } @else {\n <span>-</span>\n }\n </td>\n }\n }\n }\n </tr>\n }\n </tbody>\n </table>\n </he-data-table>\n <div class=\"is-flex is-align-items-center is-flex-wrap-wrap is-justify-content-space-between is-mt-2\">\n <he-blank-node-state-notice\n [dataState]=\"dataState()\"\n [showDeleted]=\"firstNodeKey() === BlankNodesKey.emissions\" />\n <div class=\"is-flex is-flex-wrap-wrap is-gap-8\">\n @if (showHideZeroValues()) {\n <div class=\"field is-relative is-mb-0\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded\"\n [id]=\"componentId() + 'hideZeroValues'\"\n name=\"hideZeroValues\"\n [(ngModel)]=\"hideZeroValues\" />\n <label [for]=\"componentId() + 'hideZeroValues'\">\n <span>\n Hide\n <b>0</b>\n values\n </span>\n </label>\n </div>\n }\n @if (cycles().length > 1) {\n <div class=\"field is-relative is-mb-0\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded\"\n [id]=\"componentId() + 'hideIdenticalValues'\"\n name=\"hideIdenticalValues\"\n [(ngModel)]=\"hideIdenticalValues\" />\n <label [for]=\"componentId() + 'hideIdenticalValues'\">\n <span>Hide identical values</span>\n </label>\n </div>\n }\n </div>\n </div>\n } @else {\n <div class=\"is-pt-3 has-text-centered\">\n <span>No data available</span>\n @if (filterTerm()) {\n <span class=\"is-pl-1\">matching your search criteria</span>\n }\n <span>.</span>\n @if (showSwitchToRecalculated()) {\n <span>\n Switch to\n <code>recalculated</code>\n version.\n </span>\n }\n </div>\n }\n }\n @case (View.chart) {\n @switch (firstNodeKey()) {\n @case (BlankNodesKey.emissions) {\n <he-cycles-emissions-chart [cycles]=\"cycles()\">\n <ng-container *ngTemplateOutlet=\"selectView\" />\n </he-cycles-emissions-chart>\n }\n }\n }\n @case (View.timeline) {\n <he-cycles-nodes-timeline\n [values]=\"timelineValues()\"\n [minDate]=\"selectedCycle().startDate\"\n [maxDate]=\"selectedCycle().endDate\">\n <ng-container *ngTemplateOutlet=\"selectView\" />\n </he-cycles-nodes-timeline>\n }\n @case (View.logs) {\n <!-- keep the cycle selector visible even when the selected cycle has no grouped node (e.g. a cycle\n with no transformations under \"Transformation: Inputs\"), so the user can switch to one that has -->\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (selectedNode()) {\n <he-node-logs-models\n [node]=\"selectedNode()\"\n [cycle]=\"selectedNode()\"\n [nodeKey]=\"selectedNodeKey()\"\n [logsKey]=\"selectedLogsKey()\"\n [jlogParentKey]=\"nodeKeyGroup()\"\n [jlogParentIndex]=\"jlogParentIndex()\"\n [originalValues]=\"selectedOriginalValues()\"\n [recalculatedValues]=\"selectedRecalculatedValues()\"\n [filterTermTypes]=\"filterTermTypes()\">\n @if (nodeKeys().length > 1) {\n <div class=\"tabs is-m-0\">\n <ul>\n @for (nodeKey of nodeKeys(); track nodeKey) {\n <li [class.is-active]=\"selectedNodeKey() === nodeKey\">\n <a (click)=\"selectedNodeKey.set(nodeKey)\">{{ nodeKey | keyToLabel }}</a>\n </li>\n }\n </ul>\n </div>\n }\n </he-node-logs-models>\n } @else if (isGroupNode()) {\n <p class=\"is-p-3 has-text-grey\">\n No recalculation logs for the selected {{ nodeKeyGroup() | pluralize: 1 }} in this cycle \u2014 select another\n cycle above.\n </p>\n }\n }\n }\n}\n\n<ng-template #selectView>\n <div class=\"is-flex is-gap-8 is-align-items-center is-justify-content-space-between\">\n <div class=\"is-flex is-gap-8 is-align-items-center\">\n @if (selectedView() === View.table) {\n @if (hasData()) {\n <button class=\"button is-small is-ghost is-p-2\" (click)=\"showDownload()\">\n <he-svg-icon name=\"download\" />\n </button>\n }\n <he-search-extend\n class=\"is-secondary\"\n collapsedClass=\"is-p-2\"\n placeholder=\"Filter terms by name\"\n (searchText)=\"filterTerm.set($event)\" />\n } @else if (showSelectCycle()) {\n <ng-container *ngTemplateOutlet=\"selectCycle\" />\n }\n </div>\n\n @if (views()?.length > 1) {\n <div class=\"field has-addons button-segments\">\n @for (view of views(); track view) {\n <div class=\"control\">\n <button\n class=\"button is-small\"\n [class.is-selected]=\"selectedView() === view\"\n (click)=\"selectedView.set(view)\">\n <he-svg-icon\n name=\"checkmark\"\n aria-hidden=\"true\"\n class=\"is-hidden-mobile\"\n [class.is-hidden-tablet]=\"selectedView() !== view\" />\n <he-svg-icon\n [name]=\"viewIcon[view]\"\n aria-hidden=\"true\"\n [class.is-hidden-tablet]=\"selectedView() === view\" />\n <span class=\"is-hidden-mobile\">{{ view }}</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #selectCycle>\n @if (cycles().length > 1) {\n <div class=\"field is-horizontal is-mb-0\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary is-nowrap\" for=\"selectCycle\">Cycle</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"selectIndex($event)\" if=\"selectCycle\">\n @for (value of cycles(); track value; let cycleIndex = $index) {\n <option [value]=\"cycleIndex\">{{ cycleIndex + 1 }}. {{ defaultLabel(value) }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n</ng-template>\n\n<ng-template #details let-node=\"cycle\" let-data=\"data\" let-key=\"key\">\n <p>\n <b>{{ defaultLabel(node) }}</b>\n </p>\n <he-node-value-details\n class=\"is-overflow-visible\"\n [data]=\"data\"\n [dataState]=\"dataState()\"\n [nodeType]=\"node['@type']\"\n [dataKey]=\"key\"\n [aggregated]=\"node.aggregated\" />\n</ng-template>\n", styles: [":host{display:block}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:106px;width:106px}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgbPopover, selector: "[ngbPopover]", inputs: ["animation", "autoClose", "ngbPopover", "popoverTitle", "placement", "popperOptions", "triggers", "positionTarget", "container", "disablePopover", "popoverClass", "popoverContext", "openDelay", "closeDelay"], outputs: ["shown", "hidden"], exportAs: ["ngbPopover"] }, { kind: "directive", type: NgbTooltip, selector: "[ngbTooltip]", inputs: ["animation", "autoClose", "placement", "popperOptions", "triggers", "positionTarget", "container", "disableTooltip", "tooltipClass", "tooltipContext", "openDelay", "closeDelay", "ngbTooltip"], outputs: ["shown", "hidden"], exportAs: ["ngbTooltip"] }, { kind: "component", type: HESvgIconComponent, selector: "he-svg-icon", inputs: ["name", "size", "animation"] }, { kind: "component", type: SearchExtendComponent, selector: "he-search-extend", inputs: ["value", "disabled", "placeholder", "class", "collapsedClass"], outputs: ["valueChange", "searchText"] }, { kind: "component", type: DataTableComponent, selector: "he-data-table", inputs: ["minHeight", "maxHeight", "small"] }, { kind: "component", type: NodeLinkComponent, selector: "he-node-link", inputs: ["node", "dataState", "showExternalLink", "linkClass"] }, { kind: "component", type: TermsUnitsDescriptionComponent, selector: "he-terms-units-description", inputs: ["term", "iconTemplate"] }, { kind: "component", type: CyclesFunctionalUnitMeasureComponent, selector: "he-cycles-functional-unit-measure", inputs: ["cycle"] }, { kind: "component", type: BlankNodeStateComponent, selector: "he-blank-node-state", inputs: ["dataState", "nodeType", "dataKey", "key", "node", "state", "linkClass"] }, { kind: "component", type: BlankNodeStateNoticeComponent, selector: "he-blank-node-state-notice", inputs: ["dataState", "showDeleted"] }, { kind: "component", type: CyclesEmissionsChartComponent, selector: "he-cycles-emissions-chart", inputs: ["cycles"] }, { kind: "component", type: CyclesNodesTimelineComponent, selector: "he-cycles-nodes-timeline", inputs: ["values", "maxDate", "minDate"] }, { kind: "component", type: NodeLogsModelsComponent, selector: "he-node-logs-models", inputs: ["node", "nodeKey", "originalValues", "recalculatedValues", "terms", "filterTermTypes", "filterTermTypesLabel", "logsKey", "noDataMessage", "cycle", "jlogParentKey", "jlogParentIndex"] }, { kind: "component", type: NodeValueDetailsComponent, selector: "he-node-value-details", inputs: ["data", "nodeType", "dataState", "dataKey", "aggregated"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "pipe", type: CompoundPipe, name: "compound" }, { kind: "pipe", type: DefaultPipe, name: "default" }, { kind: "pipe", type: EllipsisPipe, name: "ellipsis" }, { kind: "pipe", type: KeyToLabelPipe, name: "keyToLabel" }, { kind: "pipe", type: PrecisionPipe, name: "precision" }, { kind: "pipe", type: PluralizePipe, name: "pluralize" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
11814
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: CyclesNodesComponent, isStandalone: true, selector: "he-cycles-nodes", inputs: { dataState: { classPropertyName: "dataState", publicName: "dataState", isSignal: true, isRequired: false, transformFunction: null }, nodeKeys: { classPropertyName: "nodeKeys", publicName: "nodeKeys", isSignal: true, isRequired: true, transformFunction: null }, nodeKeyGroup: { classPropertyName: "nodeKeyGroup", publicName: "nodeKeyGroup", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (isGroupNode()) {\n <div class=\"tabs is-mb-1 | group-nodes-tabs\">\n <ul>\n @for (value of groupNodeValues(); track value) {\n <li\n [class.is-active]=\"selectedGroup() === value.value\"\n [ngbTooltip]=\"value.term.name\"\n placement=\"top\"\n container=\"body\">\n <a (click)=\"selectedGroup.set(value.value)\">\n <span class=\"is-capitalized is-pr-1\">{{ nodeKeyGroup() | pluralize: 1 }}:</span>\n <span>{{ value.value }}</span>\n </a>\n </li>\n }\n </ul>\n </div>\n}\n\n@if (isNodeKeyAllowed()) {\n @switch (selectedView()) {\n @case (View.table) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (hasData()) {\n <he-data-table class=\"is-mt-3 is-bordered\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n @if (dataKeys().length > 1) {\n <tr class=\"has-text-weight-bold\">\n <th class=\"width-auto has-border-right\"></th>\n <th class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\"></th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @let blankNodesCount = countGroupVisibleNodes(blankNodes);\n @if (blankNodesCount > 0) {\n <th [attr.colspan]=\"blankNodesCount\" [class.has-border-right]=\"!dataKeyLast\">\n <span>{{ dataKey | keyToLabel }}</span>\n </th>\n }\n }\n </tr>\n }\n <tr class=\"has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n <th class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\"></th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n <th\n [attr.title]=\"node.value.term.name\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n <he-node-link [node]=\"node.value.term\">\n <span\n [innerHtml]=\"\n node.value.term.name | ellipsis: 30 | compound: node.value.term.termType\n \"></span>\n </he-node-link>\n </th>\n }\n }\n }\n </tr>\n <tr class=\"is-italic has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n <th class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\">\n <a [href]=\"schemaBaseUrl + '/Cycle#functionalUnit'\" target=\"_blank\">Functional unit</a>\n </th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n <th\n [attr.title]=\"node.value.term.units\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n <span [innerHtml]=\"node.value.term.units | compound\"></span>\n <he-terms-units-description class=\"is-inline-block is-ml-2\" [term]=\"node.value.term\" />\n </th>\n }\n }\n }\n </tr>\n </thead>\n <tbody>\n @for (cycle of cycles(); track nodeVersionKey(cycle); let cycleIndex = $index) {\n <tr [class.is-suggested]=\"$any(cycle).suggested\">\n <td class=\"width-auto has-border-right\" [attr.title]=\"defaultLabel(cycle)\">\n <he-node-link [node]=\"cycleNode(cycle)\">\n <span class=\"has-text-ellipsis is-ellipsis-3\">\n @if ($any(cycle).suggested) {\n <he-svg-icon name=\"compare\" />\n } @else {\n <span>{{ cycleIndex + 1 }}.</span>\n }\n <span class=\"is-pl-1\">{{ defaultLabel(cycle) }}</span>\n </span>\n </he-node-link>\n </td>\n <td class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\">\n <he-cycles-functional-unit-measure [cycle]=\"cycle\" />\n </td>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n @let cycleData = node.value.values[cycle['@id']];\n <td\n class=\"is-nowrap\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n @if (cycleData) {\n <span\n class=\"trigger-popover\"\n [ngbPopover]=\"details\"\n autoClose=\"outside\"\n popoverClass=\"is-narrow is-overflow-visible\"\n placement=\"left bottom auto\"\n container=\"body\"\n [popoverContext]=\"{ data: cycleData, cycle, key: dataKey }\">\n <span pointer>\n {{ cycleData.propertyValue | precision: 3 | default: '-' }}\n </span>\n <he-blank-node-state\n class=\"ml-1\"\n [dataState]=\"dataState()\"\n [node]=\"cycleData.node\"\n key=\"value\" />\n </span>\n } @else {\n <span>-</span>\n }\n </td>\n }\n }\n }\n </tr>\n }\n </tbody>\n </table>\n </he-data-table>\n <div class=\"is-flex is-align-items-center is-flex-wrap-wrap is-justify-content-space-between is-mt-2\">\n <he-blank-node-state-notice\n [dataState]=\"dataState()\"\n [showDeleted]=\"firstNodeKey() === BlankNodesKey.emissions\" />\n <div class=\"is-flex is-flex-wrap-wrap is-gap-8\">\n @if (showHideZeroValues()) {\n <div class=\"field is-relative is-mb-0\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded\"\n [id]=\"componentId() + 'hideZeroValues'\"\n name=\"hideZeroValues\"\n [(ngModel)]=\"hideZeroValues\" />\n <label [for]=\"componentId() + 'hideZeroValues'\">\n <span>\n Hide\n <b>0</b>\n values\n </span>\n </label>\n </div>\n }\n @if (cycles().length > 1) {\n <div class=\"field is-relative is-mb-0\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded\"\n [id]=\"componentId() + 'hideIdenticalValues'\"\n name=\"hideIdenticalValues\"\n [(ngModel)]=\"hideIdenticalValues\" />\n <label [for]=\"componentId() + 'hideIdenticalValues'\">\n <span>Hide identical values</span>\n </label>\n </div>\n }\n </div>\n </div>\n } @else {\n <div class=\"is-pt-3 has-text-centered\">\n <span>No data available</span>\n @if (filterTerm()) {\n <span class=\"is-pl-1\">matching your search criteria</span>\n }\n <span>.</span>\n @if (showSwitchToRecalculated()) {\n <span>\n Switch to\n <code>recalculated</code>\n version.\n </span>\n }\n </div>\n }\n }\n @case (View.chart) {\n @switch (firstNodeKey()) {\n @case (BlankNodesKey.emissions) {\n <he-cycles-emissions-chart [cycles]=\"cycles()\">\n <ng-container *ngTemplateOutlet=\"selectView\" />\n </he-cycles-emissions-chart>\n }\n }\n }\n @case (View.timeline) {\n <he-cycles-nodes-timeline\n [values]=\"timelineValues()\"\n [minDate]=\"selectedCycle().startDate\"\n [maxDate]=\"selectedCycle().endDate\">\n <ng-container *ngTemplateOutlet=\"selectView\" />\n </he-cycles-nodes-timeline>\n }\n @case (View.logs) {\n <!-- keep the cycle selector visible even when the selected cycle has no grouped node (e.g. a cycle\n with no transformations under \"Transformation: Inputs\"), so the user can switch to one that has -->\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (selectedNode()) {\n <he-node-logs-models\n [node]=\"selectedNode()\"\n [cycle]=\"selectedNode()\"\n [nodeKey]=\"selectedNodeKey()\"\n [logsKey]=\"selectedLogsKey()\"\n [jlogParentKey]=\"nodeKeyGroup()\"\n [jlogParentIndex]=\"jlogParentIndex()\"\n [originalValues]=\"selectedOriginalValues()\"\n [recalculatedValues]=\"selectedRecalculatedValues()\"\n [filterTermTypes]=\"filterTermTypes()\">\n @if (nodeKeys().length > 1) {\n <div class=\"tabs is-m-0\">\n <ul>\n @for (nodeKey of nodeKeys(); track nodeKey) {\n <li [class.is-active]=\"selectedNodeKey() === nodeKey\">\n <a (click)=\"selectedNodeKey.set(nodeKey)\">{{ nodeKey | keyToLabel }}</a>\n </li>\n }\n </ul>\n </div>\n }\n </he-node-logs-models>\n } @else if (isGroupNode()) {\n <p class=\"is-p-3 has-text-grey\">\n No recalculation logs for the selected {{ nodeKeyGroup() | pluralize: 1 }} in this cycle \u2014 select another\n cycle above.\n </p>\n }\n }\n }\n}\n\n<ng-template #selectView>\n <div class=\"is-flex is-gap-8 is-align-items-center is-justify-content-space-between\">\n <div class=\"is-flex is-gap-8 is-align-items-center\">\n @if (selectedView() === View.table) {\n @if (hasData()) {\n <button class=\"button is-small is-ghost is-p-2\" (click)=\"showDownload()\">\n <he-svg-icon name=\"download\" />\n </button>\n }\n <he-search-extend\n class=\"is-secondary\"\n collapsedClass=\"is-p-2\"\n placeholder=\"Filter terms by name\"\n (searchText)=\"filterTerm.set($event)\" />\n } @else if (showSelectCycle()) {\n <ng-container *ngTemplateOutlet=\"selectCycle\" />\n }\n </div>\n\n @if (views()?.length > 1) {\n <div class=\"field has-addons button-segments\">\n @for (view of views(); track view) {\n <div class=\"control\">\n <button\n class=\"button is-small\"\n [class.is-selected]=\"selectedView() === view\"\n (click)=\"selectedView.set(view)\">\n <he-svg-icon\n name=\"checkmark\"\n aria-hidden=\"true\"\n class=\"is-hidden-mobile\"\n [class.is-hidden-tablet]=\"selectedView() !== view\" />\n <he-svg-icon\n [name]=\"viewIcon[view]\"\n aria-hidden=\"true\"\n [class.is-hidden-tablet]=\"selectedView() === view\" />\n <span class=\"is-hidden-mobile\">{{ view }}</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #selectCycle>\n @if (cycles().length > 1) {\n <div class=\"field is-horizontal is-mb-0\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary is-nowrap\" for=\"selectCycle\">Cycle</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"selectIndex($event)\" if=\"selectCycle\">\n @for (value of cycles(); track nodeVersionKey(value); let cycleIndex = $index) {\n <option [value]=\"cycleIndex\">{{ cycleIndex + 1 }}. {{ defaultLabel(value) }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n</ng-template>\n\n<ng-template #details let-node=\"cycle\" let-data=\"data\" let-key=\"key\">\n <p>\n <b>{{ defaultLabel(node) }}</b>\n </p>\n <he-node-value-details\n class=\"is-overflow-visible\"\n [data]=\"data\"\n [dataState]=\"dataState()\"\n [nodeType]=\"node['@type']\"\n [dataKey]=\"key\"\n [aggregated]=\"node.aggregated\" />\n</ng-template>\n", styles: [":host{display:block}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:106px;width:106px}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgbPopover, selector: "[ngbPopover]", inputs: ["animation", "autoClose", "ngbPopover", "popoverTitle", "placement", "popperOptions", "triggers", "positionTarget", "container", "disablePopover", "popoverClass", "popoverContext", "openDelay", "closeDelay"], outputs: ["shown", "hidden"], exportAs: ["ngbPopover"] }, { kind: "directive", type: NgbTooltip, selector: "[ngbTooltip]", inputs: ["animation", "autoClose", "placement", "popperOptions", "triggers", "positionTarget", "container", "disableTooltip", "tooltipClass", "tooltipContext", "openDelay", "closeDelay", "ngbTooltip"], outputs: ["shown", "hidden"], exportAs: ["ngbTooltip"] }, { kind: "component", type: HESvgIconComponent, selector: "he-svg-icon", inputs: ["name", "size", "animation"] }, { kind: "component", type: SearchExtendComponent, selector: "he-search-extend", inputs: ["value", "disabled", "placeholder", "class", "collapsedClass"], outputs: ["valueChange", "searchText"] }, { kind: "component", type: DataTableComponent, selector: "he-data-table", inputs: ["minHeight", "maxHeight", "small"] }, { kind: "component", type: NodeLinkComponent, selector: "he-node-link", inputs: ["node", "dataState", "showExternalLink", "linkClass"] }, { kind: "component", type: TermsUnitsDescriptionComponent, selector: "he-terms-units-description", inputs: ["term", "iconTemplate"] }, { kind: "component", type: CyclesFunctionalUnitMeasureComponent, selector: "he-cycles-functional-unit-measure", inputs: ["cycle"] }, { kind: "component", type: BlankNodeStateComponent, selector: "he-blank-node-state", inputs: ["dataState", "nodeType", "dataKey", "key", "node", "state", "linkClass"] }, { kind: "component", type: BlankNodeStateNoticeComponent, selector: "he-blank-node-state-notice", inputs: ["dataState", "showDeleted"] }, { kind: "component", type: CyclesEmissionsChartComponent, selector: "he-cycles-emissions-chart", inputs: ["cycles"] }, { kind: "component", type: CyclesNodesTimelineComponent, selector: "he-cycles-nodes-timeline", inputs: ["values", "maxDate", "minDate"] }, { kind: "component", type: NodeLogsModelsComponent, selector: "he-node-logs-models", inputs: ["node", "nodeKey", "originalValues", "recalculatedValues", "terms", "filterTermTypes", "filterTermTypesLabel", "logsKey", "noDataMessage", "cycle", "jlogParentKey", "jlogParentIndex"] }, { kind: "component", type: NodeValueDetailsComponent, selector: "he-node-value-details", inputs: ["data", "nodeType", "dataState", "dataKey", "aggregated"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "pipe", type: CompoundPipe, name: "compound" }, { kind: "pipe", type: DefaultPipe, name: "default" }, { kind: "pipe", type: EllipsisPipe, name: "ellipsis" }, { kind: "pipe", type: KeyToLabelPipe, name: "keyToLabel" }, { kind: "pipe", type: PrecisionPipe, name: "precision" }, { kind: "pipe", type: PluralizePipe, name: "pluralize" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
11788
11815
  }
11789
11816
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CyclesNodesComponent, decorators: [{
11790
11817
  type: Component$1,
@@ -11811,7 +11838,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
11811
11838
  KeyToLabelPipe,
11812
11839
  PrecisionPipe,
11813
11840
  PluralizePipe
11814
- ], template: "@if (isGroupNode()) {\n <div class=\"tabs is-mb-1 | group-nodes-tabs\">\n <ul>\n @for (value of groupNodeValues(); track value) {\n <li\n [class.is-active]=\"selectedGroup() === value.value\"\n [ngbTooltip]=\"value.term.name\"\n placement=\"top\"\n container=\"body\">\n <a (click)=\"selectedGroup.set(value.value)\">\n <span class=\"is-capitalized is-pr-1\">{{ nodeKeyGroup() | pluralize: 1 }}:</span>\n <span>{{ value.value }}</span>\n </a>\n </li>\n }\n </ul>\n </div>\n}\n\n@if (isNodeKeyAllowed()) {\n @switch (selectedView()) {\n @case (View.table) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (hasData()) {\n <he-data-table class=\"is-mt-3 is-bordered\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n @if (dataKeys().length > 1) {\n <tr class=\"has-text-weight-bold\">\n <th class=\"width-auto has-border-right\"></th>\n <th class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\"></th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @let blankNodesCount = countGroupVisibleNodes(blankNodes);\n @if (blankNodesCount > 0) {\n <th [attr.colspan]=\"blankNodesCount\" [class.has-border-right]=\"!dataKeyLast\">\n <span>{{ dataKey | keyToLabel }}</span>\n </th>\n }\n }\n </tr>\n }\n <tr class=\"has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n <th class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\"></th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n <th\n [attr.title]=\"node.value.term.name\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n <he-node-link [node]=\"node.value.term\">\n <span\n [innerHtml]=\"\n node.value.term.name | ellipsis: 30 | compound: node.value.term.termType\n \"></span>\n </he-node-link>\n </th>\n }\n }\n }\n </tr>\n <tr class=\"is-italic has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n <th class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\">\n <a [href]=\"schemaBaseUrl + '/Cycle#functionalUnit'\" target=\"_blank\">Functional unit</a>\n </th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n <th\n [attr.title]=\"node.value.term.units\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n <span [innerHtml]=\"node.value.term.units | compound\"></span>\n <he-terms-units-description class=\"is-inline-block is-ml-2\" [term]=\"node.value.term\" />\n </th>\n }\n }\n }\n </tr>\n </thead>\n <tbody>\n @for (cycle of cycles(); track cycle['@id']; let cycleIndex = $index) {\n <tr [class.is-suggested]=\"$any(cycle).suggested\">\n <td class=\"width-auto has-border-right\" [attr.title]=\"defaultLabel(cycle)\">\n <he-node-link [node]=\"cycleNode(cycle)\">\n <span class=\"has-text-ellipsis is-ellipsis-3\">\n @if ($any(cycle).suggested) {\n <he-svg-icon name=\"compare\" />\n } @else {\n <span>{{ cycleIndex + 1 }}.</span>\n }\n <span class=\"is-pl-1\">{{ defaultLabel(cycle) }}</span>\n </span>\n </he-node-link>\n </td>\n <td class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\">\n <he-cycles-functional-unit-measure [cycle]=\"cycle\" />\n </td>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n @let cycleData = node.value.values[cycle['@id']];\n <td\n class=\"is-nowrap\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n @if (cycleData) {\n <span\n class=\"trigger-popover\"\n [ngbPopover]=\"details\"\n autoClose=\"outside\"\n popoverClass=\"is-narrow is-overflow-visible\"\n placement=\"left bottom auto\"\n container=\"body\"\n [popoverContext]=\"{ data: cycleData, cycle, key: dataKey }\">\n <span pointer>\n {{ cycleData.propertyValue | precision: 3 | default: '-' }}\n </span>\n <he-blank-node-state\n class=\"ml-1\"\n [dataState]=\"dataState()\"\n [node]=\"cycleData.node\"\n key=\"value\" />\n </span>\n } @else {\n <span>-</span>\n }\n </td>\n }\n }\n }\n </tr>\n }\n </tbody>\n </table>\n </he-data-table>\n <div class=\"is-flex is-align-items-center is-flex-wrap-wrap is-justify-content-space-between is-mt-2\">\n <he-blank-node-state-notice\n [dataState]=\"dataState()\"\n [showDeleted]=\"firstNodeKey() === BlankNodesKey.emissions\" />\n <div class=\"is-flex is-flex-wrap-wrap is-gap-8\">\n @if (showHideZeroValues()) {\n <div class=\"field is-relative is-mb-0\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded\"\n [id]=\"componentId() + 'hideZeroValues'\"\n name=\"hideZeroValues\"\n [(ngModel)]=\"hideZeroValues\" />\n <label [for]=\"componentId() + 'hideZeroValues'\">\n <span>\n Hide\n <b>0</b>\n values\n </span>\n </label>\n </div>\n }\n @if (cycles().length > 1) {\n <div class=\"field is-relative is-mb-0\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded\"\n [id]=\"componentId() + 'hideIdenticalValues'\"\n name=\"hideIdenticalValues\"\n [(ngModel)]=\"hideIdenticalValues\" />\n <label [for]=\"componentId() + 'hideIdenticalValues'\">\n <span>Hide identical values</span>\n </label>\n </div>\n }\n </div>\n </div>\n } @else {\n <div class=\"is-pt-3 has-text-centered\">\n <span>No data available</span>\n @if (filterTerm()) {\n <span class=\"is-pl-1\">matching your search criteria</span>\n }\n <span>.</span>\n @if (showSwitchToRecalculated()) {\n <span>\n Switch to\n <code>recalculated</code>\n version.\n </span>\n }\n </div>\n }\n }\n @case (View.chart) {\n @switch (firstNodeKey()) {\n @case (BlankNodesKey.emissions) {\n <he-cycles-emissions-chart [cycles]=\"cycles()\">\n <ng-container *ngTemplateOutlet=\"selectView\" />\n </he-cycles-emissions-chart>\n }\n }\n }\n @case (View.timeline) {\n <he-cycles-nodes-timeline\n [values]=\"timelineValues()\"\n [minDate]=\"selectedCycle().startDate\"\n [maxDate]=\"selectedCycle().endDate\">\n <ng-container *ngTemplateOutlet=\"selectView\" />\n </he-cycles-nodes-timeline>\n }\n @case (View.logs) {\n <!-- keep the cycle selector visible even when the selected cycle has no grouped node (e.g. a cycle\n with no transformations under \"Transformation: Inputs\"), so the user can switch to one that has -->\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (selectedNode()) {\n <he-node-logs-models\n [node]=\"selectedNode()\"\n [cycle]=\"selectedNode()\"\n [nodeKey]=\"selectedNodeKey()\"\n [logsKey]=\"selectedLogsKey()\"\n [jlogParentKey]=\"nodeKeyGroup()\"\n [jlogParentIndex]=\"jlogParentIndex()\"\n [originalValues]=\"selectedOriginalValues()\"\n [recalculatedValues]=\"selectedRecalculatedValues()\"\n [filterTermTypes]=\"filterTermTypes()\">\n @if (nodeKeys().length > 1) {\n <div class=\"tabs is-m-0\">\n <ul>\n @for (nodeKey of nodeKeys(); track nodeKey) {\n <li [class.is-active]=\"selectedNodeKey() === nodeKey\">\n <a (click)=\"selectedNodeKey.set(nodeKey)\">{{ nodeKey | keyToLabel }}</a>\n </li>\n }\n </ul>\n </div>\n }\n </he-node-logs-models>\n } @else if (isGroupNode()) {\n <p class=\"is-p-3 has-text-grey\">\n No recalculation logs for the selected {{ nodeKeyGroup() | pluralize: 1 }} in this cycle \u2014 select another\n cycle above.\n </p>\n }\n }\n }\n}\n\n<ng-template #selectView>\n <div class=\"is-flex is-gap-8 is-align-items-center is-justify-content-space-between\">\n <div class=\"is-flex is-gap-8 is-align-items-center\">\n @if (selectedView() === View.table) {\n @if (hasData()) {\n <button class=\"button is-small is-ghost is-p-2\" (click)=\"showDownload()\">\n <he-svg-icon name=\"download\" />\n </button>\n }\n <he-search-extend\n class=\"is-secondary\"\n collapsedClass=\"is-p-2\"\n placeholder=\"Filter terms by name\"\n (searchText)=\"filterTerm.set($event)\" />\n } @else if (showSelectCycle()) {\n <ng-container *ngTemplateOutlet=\"selectCycle\" />\n }\n </div>\n\n @if (views()?.length > 1) {\n <div class=\"field has-addons button-segments\">\n @for (view of views(); track view) {\n <div class=\"control\">\n <button\n class=\"button is-small\"\n [class.is-selected]=\"selectedView() === view\"\n (click)=\"selectedView.set(view)\">\n <he-svg-icon\n name=\"checkmark\"\n aria-hidden=\"true\"\n class=\"is-hidden-mobile\"\n [class.is-hidden-tablet]=\"selectedView() !== view\" />\n <he-svg-icon\n [name]=\"viewIcon[view]\"\n aria-hidden=\"true\"\n [class.is-hidden-tablet]=\"selectedView() === view\" />\n <span class=\"is-hidden-mobile\">{{ view }}</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #selectCycle>\n @if (cycles().length > 1) {\n <div class=\"field is-horizontal is-mb-0\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary is-nowrap\" for=\"selectCycle\">Cycle</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"selectIndex($event)\" if=\"selectCycle\">\n @for (value of cycles(); track value; let cycleIndex = $index) {\n <option [value]=\"cycleIndex\">{{ cycleIndex + 1 }}. {{ defaultLabel(value) }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n</ng-template>\n\n<ng-template #details let-node=\"cycle\" let-data=\"data\" let-key=\"key\">\n <p>\n <b>{{ defaultLabel(node) }}</b>\n </p>\n <he-node-value-details\n class=\"is-overflow-visible\"\n [data]=\"data\"\n [dataState]=\"dataState()\"\n [nodeType]=\"node['@type']\"\n [dataKey]=\"key\"\n [aggregated]=\"node.aggregated\" />\n</ng-template>\n", styles: [":host{display:block}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:106px;width:106px}\n"] }]
11841
+ ], template: "@if (isGroupNode()) {\n <div class=\"tabs is-mb-1 | group-nodes-tabs\">\n <ul>\n @for (value of groupNodeValues(); track value) {\n <li\n [class.is-active]=\"selectedGroup() === value.value\"\n [ngbTooltip]=\"value.term.name\"\n placement=\"top\"\n container=\"body\">\n <a (click)=\"selectedGroup.set(value.value)\">\n <span class=\"is-capitalized is-pr-1\">{{ nodeKeyGroup() | pluralize: 1 }}:</span>\n <span>{{ value.value }}</span>\n </a>\n </li>\n }\n </ul>\n </div>\n}\n\n@if (isNodeKeyAllowed()) {\n @switch (selectedView()) {\n @case (View.table) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (hasData()) {\n <he-data-table class=\"is-mt-3 is-bordered\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n @if (dataKeys().length > 1) {\n <tr class=\"has-text-weight-bold\">\n <th class=\"width-auto has-border-right\"></th>\n <th class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\"></th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @let blankNodesCount = countGroupVisibleNodes(blankNodes);\n @if (blankNodesCount > 0) {\n <th [attr.colspan]=\"blankNodesCount\" [class.has-border-right]=\"!dataKeyLast\">\n <span>{{ dataKey | keyToLabel }}</span>\n </th>\n }\n }\n </tr>\n }\n <tr class=\"has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n <th class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\"></th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n <th\n [attr.title]=\"node.value.term.name\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n <he-node-link [node]=\"node.value.term\">\n <span\n [innerHtml]=\"\n node.value.term.name | ellipsis: 30 | compound: node.value.term.termType\n \"></span>\n </he-node-link>\n </th>\n }\n }\n }\n </tr>\n <tr class=\"is-italic has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n <th class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\">\n <a [href]=\"schemaBaseUrl + '/Cycle#functionalUnit'\" target=\"_blank\">Functional unit</a>\n </th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n <th\n [attr.title]=\"node.value.term.units\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n <span [innerHtml]=\"node.value.term.units | compound\"></span>\n <he-terms-units-description class=\"is-inline-block is-ml-2\" [term]=\"node.value.term\" />\n </th>\n }\n }\n }\n </tr>\n </thead>\n <tbody>\n @for (cycle of cycles(); track nodeVersionKey(cycle); let cycleIndex = $index) {\n <tr [class.is-suggested]=\"$any(cycle).suggested\">\n <td class=\"width-auto has-border-right\" [attr.title]=\"defaultLabel(cycle)\">\n <he-node-link [node]=\"cycleNode(cycle)\">\n <span class=\"has-text-ellipsis is-ellipsis-3\">\n @if ($any(cycle).suggested) {\n <he-svg-icon name=\"compare\" />\n } @else {\n <span>{{ cycleIndex + 1 }}.</span>\n }\n <span class=\"is-pl-1\">{{ defaultLabel(cycle) }}</span>\n </span>\n </he-node-link>\n </td>\n <td class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\">\n <he-cycles-functional-unit-measure [cycle]=\"cycle\" />\n </td>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n @let cycleData = node.value.values[cycle['@id']];\n <td\n class=\"is-nowrap\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n @if (cycleData) {\n <span\n class=\"trigger-popover\"\n [ngbPopover]=\"details\"\n autoClose=\"outside\"\n popoverClass=\"is-narrow is-overflow-visible\"\n placement=\"left bottom auto\"\n container=\"body\"\n [popoverContext]=\"{ data: cycleData, cycle, key: dataKey }\">\n <span pointer>\n {{ cycleData.propertyValue | precision: 3 | default: '-' }}\n </span>\n <he-blank-node-state\n class=\"ml-1\"\n [dataState]=\"dataState()\"\n [node]=\"cycleData.node\"\n key=\"value\" />\n </span>\n } @else {\n <span>-</span>\n }\n </td>\n }\n }\n }\n </tr>\n }\n </tbody>\n </table>\n </he-data-table>\n <div class=\"is-flex is-align-items-center is-flex-wrap-wrap is-justify-content-space-between is-mt-2\">\n <he-blank-node-state-notice\n [dataState]=\"dataState()\"\n [showDeleted]=\"firstNodeKey() === BlankNodesKey.emissions\" />\n <div class=\"is-flex is-flex-wrap-wrap is-gap-8\">\n @if (showHideZeroValues()) {\n <div class=\"field is-relative is-mb-0\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded\"\n [id]=\"componentId() + 'hideZeroValues'\"\n name=\"hideZeroValues\"\n [(ngModel)]=\"hideZeroValues\" />\n <label [for]=\"componentId() + 'hideZeroValues'\">\n <span>\n Hide\n <b>0</b>\n values\n </span>\n </label>\n </div>\n }\n @if (cycles().length > 1) {\n <div class=\"field is-relative is-mb-0\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded\"\n [id]=\"componentId() + 'hideIdenticalValues'\"\n name=\"hideIdenticalValues\"\n [(ngModel)]=\"hideIdenticalValues\" />\n <label [for]=\"componentId() + 'hideIdenticalValues'\">\n <span>Hide identical values</span>\n </label>\n </div>\n }\n </div>\n </div>\n } @else {\n <div class=\"is-pt-3 has-text-centered\">\n <span>No data available</span>\n @if (filterTerm()) {\n <span class=\"is-pl-1\">matching your search criteria</span>\n }\n <span>.</span>\n @if (showSwitchToRecalculated()) {\n <span>\n Switch to\n <code>recalculated</code>\n version.\n </span>\n }\n </div>\n }\n }\n @case (View.chart) {\n @switch (firstNodeKey()) {\n @case (BlankNodesKey.emissions) {\n <he-cycles-emissions-chart [cycles]=\"cycles()\">\n <ng-container *ngTemplateOutlet=\"selectView\" />\n </he-cycles-emissions-chart>\n }\n }\n }\n @case (View.timeline) {\n <he-cycles-nodes-timeline\n [values]=\"timelineValues()\"\n [minDate]=\"selectedCycle().startDate\"\n [maxDate]=\"selectedCycle().endDate\">\n <ng-container *ngTemplateOutlet=\"selectView\" />\n </he-cycles-nodes-timeline>\n }\n @case (View.logs) {\n <!-- keep the cycle selector visible even when the selected cycle has no grouped node (e.g. a cycle\n with no transformations under \"Transformation: Inputs\"), so the user can switch to one that has -->\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (selectedNode()) {\n <he-node-logs-models\n [node]=\"selectedNode()\"\n [cycle]=\"selectedNode()\"\n [nodeKey]=\"selectedNodeKey()\"\n [logsKey]=\"selectedLogsKey()\"\n [jlogParentKey]=\"nodeKeyGroup()\"\n [jlogParentIndex]=\"jlogParentIndex()\"\n [originalValues]=\"selectedOriginalValues()\"\n [recalculatedValues]=\"selectedRecalculatedValues()\"\n [filterTermTypes]=\"filterTermTypes()\">\n @if (nodeKeys().length > 1) {\n <div class=\"tabs is-m-0\">\n <ul>\n @for (nodeKey of nodeKeys(); track nodeKey) {\n <li [class.is-active]=\"selectedNodeKey() === nodeKey\">\n <a (click)=\"selectedNodeKey.set(nodeKey)\">{{ nodeKey | keyToLabel }}</a>\n </li>\n }\n </ul>\n </div>\n }\n </he-node-logs-models>\n } @else if (isGroupNode()) {\n <p class=\"is-p-3 has-text-grey\">\n No recalculation logs for the selected {{ nodeKeyGroup() | pluralize: 1 }} in this cycle \u2014 select another\n cycle above.\n </p>\n }\n }\n }\n}\n\n<ng-template #selectView>\n <div class=\"is-flex is-gap-8 is-align-items-center is-justify-content-space-between\">\n <div class=\"is-flex is-gap-8 is-align-items-center\">\n @if (selectedView() === View.table) {\n @if (hasData()) {\n <button class=\"button is-small is-ghost is-p-2\" (click)=\"showDownload()\">\n <he-svg-icon name=\"download\" />\n </button>\n }\n <he-search-extend\n class=\"is-secondary\"\n collapsedClass=\"is-p-2\"\n placeholder=\"Filter terms by name\"\n (searchText)=\"filterTerm.set($event)\" />\n } @else if (showSelectCycle()) {\n <ng-container *ngTemplateOutlet=\"selectCycle\" />\n }\n </div>\n\n @if (views()?.length > 1) {\n <div class=\"field has-addons button-segments\">\n @for (view of views(); track view) {\n <div class=\"control\">\n <button\n class=\"button is-small\"\n [class.is-selected]=\"selectedView() === view\"\n (click)=\"selectedView.set(view)\">\n <he-svg-icon\n name=\"checkmark\"\n aria-hidden=\"true\"\n class=\"is-hidden-mobile\"\n [class.is-hidden-tablet]=\"selectedView() !== view\" />\n <he-svg-icon\n [name]=\"viewIcon[view]\"\n aria-hidden=\"true\"\n [class.is-hidden-tablet]=\"selectedView() === view\" />\n <span class=\"is-hidden-mobile\">{{ view }}</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #selectCycle>\n @if (cycles().length > 1) {\n <div class=\"field is-horizontal is-mb-0\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary is-nowrap\" for=\"selectCycle\">Cycle</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"selectIndex($event)\" if=\"selectCycle\">\n @for (value of cycles(); track nodeVersionKey(value); let cycleIndex = $index) {\n <option [value]=\"cycleIndex\">{{ cycleIndex + 1 }}. {{ defaultLabel(value) }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n</ng-template>\n\n<ng-template #details let-node=\"cycle\" let-data=\"data\" let-key=\"key\">\n <p>\n <b>{{ defaultLabel(node) }}</b>\n </p>\n <he-node-value-details\n class=\"is-overflow-visible\"\n [data]=\"data\"\n [dataState]=\"dataState()\"\n [nodeType]=\"node['@type']\"\n [dataKey]=\"key\"\n [aggregated]=\"node.aggregated\" />\n</ng-template>\n", styles: [":host{display:block}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:106px;width:106px}\n"] }]
11815
11842
  }], ctorParameters: () => [], propDecorators: { dataState: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataState", required: false }] }], nodeKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "nodeKeys", required: true }] }], nodeKeyGroup: [{ type: i0.Input, args: [{ isSignal: true, alias: "nodeKeyGroup", required: false }] }] } });
11816
11843
 
11817
11844
  class CyclesResultComponent {
@@ -12594,13 +12621,18 @@ class EngineModelsStageDeepComponent {
12594
12621
  });
12595
12622
  this.nodesLength = computed(() => this.relatedNodesResource.value()?.length ?? 0, ...(ngDevMode ? [{ debugName: "nodesLength" }] : []));
12596
12623
  this.nodesResource = rxResource({
12624
+ // only re-resolve when the related nodes change — NOT on every store mutation, which would
12625
+ // cancel and re-issue the in-flight node requests on each load tick
12597
12626
  params: () => ({
12598
- relatedNodes: this.relatedNodesResource.value(),
12599
- nodes: this.nodeStoreService.nodes()
12627
+ relatedNodes: this.relatedNodesResource.value()
12600
12628
  }),
12601
- stream: ({ params: { relatedNodes, nodes } }) => relatedNodes?.length > 0
12602
- ? from(relatedNodes).pipe(mergeMap(node => this.findNode(nodes, node)), filter(v => !!v), distinct(node => jsonldPath(node['@type'], node['@id'])), toArray())
12603
- : of([])
12629
+ stream: ({ params: { relatedNodes } }) => {
12630
+ // read the store as a snapshot so already-loaded nodes are reused without making this reactive
12631
+ const nodes = untracked(() => this.nodeStoreService.nodes());
12632
+ return relatedNodes?.length > 0
12633
+ ? from(relatedNodes).pipe(mergeMap(node => this.findNode(nodes, node)), filter(v => !!v), distinct(node => jsonldPath(node['@type'], node['@id'])), toArray())
12634
+ : of([]);
12635
+ }
12604
12636
  });
12605
12637
  this.expandableNodes = computed(() => this.nodesResource
12606
12638
  .value()
@@ -15812,6 +15844,7 @@ class ImpactAssessmentsProductsComponent {
15812
15844
  this.filterTermTypes = input([], ...(ngDevMode ? [{ debugName: "filterTermTypes" }] : []));
15813
15845
  this.enableFilterMethodModel = input(false, ...(ngDevMode ? [{ debugName: "enableFilterMethodModel" }] : []));
15814
15846
  this.schemaBaseUrl = schemaBaseUrl();
15847
+ this.nodeVersionKey = nodeVersionKey;
15815
15848
  this.countGroupVisibleNodes = countGroupVisibleNodes;
15816
15849
  this.headerKeys = computed(() => [
15817
15850
  'impactAssessment.id',
@@ -15907,7 +15940,7 @@ class ImpactAssessmentsProductsComponent {
15907
15940
  component.headerKeys.set(this.headerKeys());
15908
15941
  }
15909
15942
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ImpactAssessmentsProductsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
15910
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: ImpactAssessmentsProductsComponent, isStandalone: true, selector: "he-impact-assessments-products", inputs: { dataState: { classPropertyName: "dataState", publicName: "dataState", isSignal: true, isRequired: false, transformFunction: null }, nodeKey: { classPropertyName: "nodeKey", publicName: "nodeKey", isSignal: true, isRequired: false, transformFunction: null }, filterTermTypes: { classPropertyName: "filterTermTypes", publicName: "filterTermTypes", isSignal: true, isRequired: false, transformFunction: null }, enableFilterMethodModel: { classPropertyName: "enableFilterMethodModel", publicName: "enableFilterMethodModel", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (isNodeKeyAllowed()) {\n @switch (selectedView()) {\n @case (View.table) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n <div class=\"is-hidden-tablet is-mt-3\">\n <ng-container *ngTemplateOutlet=\"filterModel\" />\n </div>\n\n @if (hasData()) {\n <he-data-table class=\"is-mt-3 is-bordered\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n @if (dataKeys().length > 1) {\n <tr class=\"has-text-weight-bold\">\n <th class=\"width-auto\"></th>\n <th></th>\n <th></th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @let blankNodesCount = countGroupVisibleNodes(blankNodes);\n @if (blankNodesCount > 0) {\n <th [attr.colspan]=\"blankNodesCount\" [class.has-border-right]=\"!dataKeyLast\">\n @if (dataKey) {\n <span>{{ dataKey | keyToLabel }}</span>\n }\n </th>\n }\n }\n </tr>\n }\n <tr class=\"has-text-weight-semibold\">\n <th class=\"width-auto has-border-right is-py-0\">\n <div class=\"is-hidden-mobile\">\n <ng-container *ngTemplateOutlet=\"filterModel\" />\n </div>\n </th>\n <th class=\"has-border-right\"></th>\n <th class=\"has-border-right\"></th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n <th\n [attr.title]=\"node.value.term.name\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n <he-node-link [node]=\"node.value.term\">\n <span\n [innerHtml]=\"\n node.value.term.name | ellipsis: 30 | compound: node.value.term.termType\n \"></span>\n </he-node-link>\n </th>\n }\n }\n }\n </tr>\n <tr class=\"is-italic has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n <th class=\"has-border-right\">\n <a [href]=\"schemaBaseUrl + '/ImpactAssessment#functionalUnit'\" target=\"_blank\">Functional unit</a>\n </th>\n <th class=\"has-border-right\">\n <a [href]=\"schemaBaseUrl + '/ImpactAssessment#product'\" target=\"_blank\">Product</a>\n </th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n <th\n [attr.title]=\"node.value.term.units\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n <span [innerHtml]=\"node.value.term.units | compound\"></span>\n <he-terms-units-description class=\"is-inline-block is-ml-2\" [term]=\"node.value.term\" />\n </th>\n }\n }\n }\n </tr>\n </thead>\n <tbody>\n @for (impactAssessment of impactAssessments(); track impactAssessment['@id']; let impactIndex = $index) {\n @let product = productTerm(impactAssessment);\n <tr [class.is-suggested]=\"$any(impactAssessment).suggested\">\n <td class=\"width-auto has-border-right\" [attr.title]=\"impactName(impactAssessment)\">\n <he-node-link [node]=\"impactAssessment\">\n <span class=\"has-text-ellipsis is-ellipsis-3\">\n @if ($any(impactAssessment).suggested) {\n <he-svg-icon name=\"compare\" />\n } @else {\n <span>{{ impactIndex + 1 }}.</span>\n }\n <span class=\"is-pl-1\">{{ impactName(impactAssessment) }}</span>\n </span>\n </he-node-link>\n </td>\n <td class=\"has-border-right\" [attr.title]=\"product?.units\">\n <span>1 {{ product?.units }}</span>\n </td>\n <td class=\"has-border-right\" [attr.title]=\"product?.name\">\n @if (product) {\n <he-node-link [node]=\"product\">\n <span>{{ product.name | ellipsis: 30 }}</span>\n </he-node-link>\n }\n </td>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n @let impactData = node.value.values[impactAssessment['@id']];\n <td\n class=\"is-nowrap\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n @if (impactData) {\n <span\n class=\"trigger-popover\"\n [ngbPopover]=\"details\"\n autoClose=\"outside\"\n popoverClass=\"is-narrow is-overflow-visible\"\n placement=\"left bottom auto\"\n container=\"body\"\n [popoverContext]=\"{\n data: impactData,\n impactAssessment\n }\">\n <span pointer>\n {{ impactData.propertyValue | precision: 3 | default: '-' }}\n </span>\n <he-blank-node-state\n class=\"ml-1\"\n [dataState]=\"dataState()\"\n [node]=\"impactData.node\"\n key=\"value\"\n [state]=\"impactAssessment.aggregated ? 'aggregated' : undefined\" />\n </span>\n } @else {\n <span>-</span>\n }\n </td>\n }\n }\n }\n </tr>\n }\n </tbody>\n </table>\n </he-data-table>\n <div class=\"is-flex is-align-items-center is-flex-wrap-wrap is-justify-content-space-between is-mt-2\">\n <he-blank-node-state-notice [dataState]=\"dataState()\" />\n @if (impactAssessments().length > 1) {\n <div class=\"field is-relative is-mb-0\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded\"\n [id]=\"componentId() + 'hideIdenticalValues'\"\n name=\"hideIdenticalValues\"\n [(ngModel)]=\"hideIdenticalValues\" />\n <label [for]=\"componentId() + 'hideIdenticalValues'\">\n <span>Hide identical values</span>\n </label>\n </div>\n }\n </div>\n } @else if (noDataMessage()) {\n <div class=\"is-pt-3 has-text-centered\">\n <span>{{ noDataMessage() }}</span>\n </div>\n } @else {\n <div class=\"is-pt-3 has-text-centered\">\n <span>No data available</span>\n @if (filterTerm()) {\n <span class=\"is-pl-1\">matching your search criteria</span>\n }\n <span>.</span>\n @if (showSwitchToRecalculated()) {\n <span>\n Switch to\n <code>recalculated</code>\n version.\n </span>\n }\n </div>\n }\n }\n @case (View.chart) {\n <he-impact-assessments-indicators-chart [key]=\"nodeKey()\" [filterTermTypes]=\"filterTermTypes()\">\n <ng-container *ngTemplateOutlet=\"selectView\" />\n </he-impact-assessments-indicators-chart>\n }\n @case (View.breakdown) {\n @if (selectedNode()) {\n <he-impact-assessments-indicator-breakdown-chart\n [impactAssessment]=\"selectedNode()\"\n [indicators]=\"selectedRecalculatedValues()\">\n <ng-container *ngTemplateOutlet=\"selectView\" />\n </he-impact-assessments-indicator-breakdown-chart>\n }\n }\n @case (View.logs) {\n @if (selectedNode()) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n <he-node-logs-models\n [node]=\"selectedNode()\"\n [cycle]=\"selectedCycle()\"\n [nodeKey]=\"nodeKey()\"\n [filterTermTypes]=\"filterTermTypes()\"\n [filterTermTypesLabel]=\"filterTermTypesLabel()\"\n [originalValues]=\"selectedOriginalValues()\"\n [recalculatedValues]=\"selectedRecalculatedValues()\"\n [noDataMessage]=\"noDataMessage()\" />\n }\n }\n }\n}\n\n<ng-template #filterModel>\n @if (enableFilterMethodModel()) {\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"updateSelectedMethodModel($event.target.value)\">\n <option [ngValue]=\"undefined\">Filter Model</option>\n @for (term of methodModels(); track term) {\n <option [ngValue]=\"term\">{{ term.name }}</option>\n }\n </select>\n </div>\n }\n</ng-template>\n\n<ng-template #selectView>\n <div class=\"is-flex is-gap-8 is-align-items-center is-justify-content-space-between\">\n <div class=\"is-flex is-gap-8 is-align-items-center\">\n @if (selectedView() === View.table) {\n @if (hasData()) {\n <button class=\"button is-small is-ghost is-p-2\" (click)=\"showDownload()\">\n <he-svg-icon name=\"download\" />\n </button>\n }\n <he-search-extend\n class=\"is-secondary\"\n collapsedClass=\"is-p-2\"\n placeholder=\"Filter terms by name\"\n (searchText)=\"filterTerm.set($event)\" />\n } @else if (showSelectImpact()) {\n <ng-container *ngTemplateOutlet=\"selectImpact\" />\n }\n </div>\n\n @if (views()?.length > 1) {\n <div class=\"field has-addons button-segments\">\n @for (view of views(); track view) {\n <div class=\"control\">\n <button\n class=\"button is-small\"\n [class.is-selected]=\"selectedView() === view\"\n (click)=\"selectedView.set(view)\">\n <he-svg-icon\n name=\"checkmark\"\n aria-hidden=\"true\"\n class=\"is-hidden-mobile\"\n [class.is-hidden-tablet]=\"selectedView() !== view\" />\n <he-svg-icon\n [name]=\"viewIcon[view]\"\n aria-hidden=\"true\"\n [class.is-hidden-tablet]=\"selectedView() === view\" />\n <span class=\"is-hidden-mobile\">{{ view }}</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #selectImpact>\n @if (impactAssessments().length > 1) {\n <div class=\"field is-horizontal is-mb-0\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary is-nowrap\" for=\"selectImpactAssessment\">Impact Assessment</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"selectIndex($event)\" if=\"selectImpactAssessment\">\n @for (value of impactAssessments(); track value; let i = $index) {\n <option [value]=\"i\">{{ i + 1 }}. {{ impactName(value) }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n</ng-template>\n\n<ng-template #details let-node=\"impactAssessment\" let-data=\"data\">\n <p>\n <b>\n @if (data.cycle) {\n <span>{{ cycleLabel(node.cycle) }}</span>\n }\n @if (!data.cycle) {\n <span>{{ data.name }}</span>\n }\n </b>\n </p>\n <he-node-value-details\n class=\"is-overflow-visible\"\n [data]=\"data\"\n [dataState]=\"dataState()\"\n [nodeType]=\"node['@type']\"\n [dataKey]=\"nodeKey()\"\n [aggregated]=\"node.aggregated\" />\n</ng-template>\n", styles: [":host{display:block}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}he-data-table ::ng-deep .table thead tr th:nth-child(3),he-data-table ::ng-deep .table tbody tr td:nth-child(3){min-width:110px}\n"], dependencies: [{ kind: "component", type: HESvgIconComponent, selector: "he-svg-icon", inputs: ["name", "size", "animation"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: SearchExtendComponent, selector: "he-search-extend", inputs: ["value", "disabled", "placeholder", "class", "collapsedClass"], outputs: ["valueChange", "searchText"] }, { kind: "component", type: DataTableComponent, selector: "he-data-table", inputs: ["minHeight", "maxHeight", "small"] }, { kind: "component", type: NodeLinkComponent, selector: "he-node-link", inputs: ["node", "dataState", "showExternalLink", "linkClass"] }, { kind: "component", type: TermsUnitsDescriptionComponent, selector: "he-terms-units-description", inputs: ["term", "iconTemplate"] }, { kind: "directive", type: NgbPopover, selector: "[ngbPopover]", inputs: ["animation", "autoClose", "ngbPopover", "popoverTitle", "placement", "popperOptions", "triggers", "positionTarget", "container", "disablePopover", "popoverClass", "popoverContext", "openDelay", "closeDelay"], outputs: ["shown", "hidden"], exportAs: ["ngbPopover"] }, { kind: "component", type: BlankNodeStateComponent, selector: "he-blank-node-state", inputs: ["dataState", "nodeType", "dataKey", "key", "node", "state", "linkClass"] }, { kind: "component", type: BlankNodeStateNoticeComponent, selector: "he-blank-node-state-notice", inputs: ["dataState", "showDeleted"] }, { kind: "component", type: ImpactAssessmentsIndicatorsChartComponent, selector: "he-impact-assessments-indicators-chart", inputs: ["key", "filterTermTypes"] }, { kind: "component", type: ImpactAssessmentsIndicatorBreakdownChartComponent, selector: "he-impact-assessments-indicator-breakdown-chart", inputs: ["impactAssessment", "indicators"] }, { kind: "component", type: NodeLogsModelsComponent, selector: "he-node-logs-models", inputs: ["node", "nodeKey", "originalValues", "recalculatedValues", "terms", "filterTermTypes", "filterTermTypesLabel", "logsKey", "noDataMessage", "cycle", "jlogParentKey", "jlogParentIndex"] }, { kind: "component", type: NodeValueDetailsComponent, selector: "he-node-value-details", inputs: ["data", "nodeType", "dataState", "dataKey", "aggregated"] }, { kind: "pipe", type: CompoundPipe, name: "compound" }, { kind: "pipe", type: DefaultPipe, name: "default" }, { kind: "pipe", type: EllipsisPipe, name: "ellipsis" }, { kind: "pipe", type: PrecisionPipe, name: "precision" }, { kind: "pipe", type: KeyToLabelPipe, name: "keyToLabel" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
15943
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: ImpactAssessmentsProductsComponent, isStandalone: true, selector: "he-impact-assessments-products", inputs: { dataState: { classPropertyName: "dataState", publicName: "dataState", isSignal: true, isRequired: false, transformFunction: null }, nodeKey: { classPropertyName: "nodeKey", publicName: "nodeKey", isSignal: true, isRequired: false, transformFunction: null }, filterTermTypes: { classPropertyName: "filterTermTypes", publicName: "filterTermTypes", isSignal: true, isRequired: false, transformFunction: null }, enableFilterMethodModel: { classPropertyName: "enableFilterMethodModel", publicName: "enableFilterMethodModel", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (isNodeKeyAllowed()) {\n @switch (selectedView()) {\n @case (View.table) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n <div class=\"is-hidden-tablet is-mt-3\">\n <ng-container *ngTemplateOutlet=\"filterModel\" />\n </div>\n\n @if (hasData()) {\n <he-data-table class=\"is-mt-3 is-bordered\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n @if (dataKeys().length > 1) {\n <tr class=\"has-text-weight-bold\">\n <th class=\"width-auto\"></th>\n <th></th>\n <th></th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @let blankNodesCount = countGroupVisibleNodes(blankNodes);\n @if (blankNodesCount > 0) {\n <th [attr.colspan]=\"blankNodesCount\" [class.has-border-right]=\"!dataKeyLast\">\n @if (dataKey) {\n <span>{{ dataKey | keyToLabel }}</span>\n }\n </th>\n }\n }\n </tr>\n }\n <tr class=\"has-text-weight-semibold\">\n <th class=\"width-auto has-border-right is-py-0\">\n <div class=\"is-hidden-mobile\">\n <ng-container *ngTemplateOutlet=\"filterModel\" />\n </div>\n </th>\n <th class=\"has-border-right\"></th>\n <th class=\"has-border-right\"></th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n <th\n [attr.title]=\"node.value.term.name\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n <he-node-link [node]=\"node.value.term\">\n <span\n [innerHtml]=\"\n node.value.term.name | ellipsis: 30 | compound: node.value.term.termType\n \"></span>\n </he-node-link>\n </th>\n }\n }\n }\n </tr>\n <tr class=\"is-italic has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n <th class=\"has-border-right\">\n <a [href]=\"schemaBaseUrl + '/ImpactAssessment#functionalUnit'\" target=\"_blank\">Functional unit</a>\n </th>\n <th class=\"has-border-right\">\n <a [href]=\"schemaBaseUrl + '/ImpactAssessment#product'\" target=\"_blank\">Product</a>\n </th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n <th\n [attr.title]=\"node.value.term.units\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n <span [innerHtml]=\"node.value.term.units | compound\"></span>\n <he-terms-units-description class=\"is-inline-block is-ml-2\" [term]=\"node.value.term\" />\n </th>\n }\n }\n }\n </tr>\n </thead>\n <tbody>\n @for (\n impactAssessment of impactAssessments();\n track nodeVersionKey(impactAssessment);\n let impactIndex = $index\n ) {\n @let product = productTerm(impactAssessment);\n <tr [class.is-suggested]=\"$any(impactAssessment).suggested\">\n <td class=\"width-auto has-border-right\" [attr.title]=\"impactName(impactAssessment)\">\n <he-node-link [node]=\"impactAssessment\">\n <span class=\"has-text-ellipsis is-ellipsis-3\">\n @if ($any(impactAssessment).suggested) {\n <he-svg-icon name=\"compare\" />\n } @else {\n <span>{{ impactIndex + 1 }}.</span>\n }\n <span class=\"is-pl-1\">{{ impactName(impactAssessment) }}</span>\n </span>\n </he-node-link>\n </td>\n <td class=\"has-border-right\" [attr.title]=\"product?.units\">\n <span>1 {{ product?.units }}</span>\n </td>\n <td class=\"has-border-right\" [attr.title]=\"product?.name\">\n @if (product) {\n <he-node-link [node]=\"product\">\n <span>{{ product.name | ellipsis: 30 }}</span>\n </he-node-link>\n }\n </td>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n @let impactData = node.value.values[impactAssessment['@id']];\n <td\n class=\"is-nowrap\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n @if (impactData) {\n <span\n class=\"trigger-popover\"\n [ngbPopover]=\"details\"\n autoClose=\"outside\"\n popoverClass=\"is-narrow is-overflow-visible\"\n placement=\"left bottom auto\"\n container=\"body\"\n [popoverContext]=\"{\n data: impactData,\n impactAssessment\n }\">\n <span pointer>\n {{ impactData.propertyValue | precision: 3 | default: '-' }}\n </span>\n <he-blank-node-state\n class=\"ml-1\"\n [dataState]=\"dataState()\"\n [node]=\"impactData.node\"\n key=\"value\"\n [state]=\"impactAssessment.aggregated ? 'aggregated' : undefined\" />\n </span>\n } @else {\n <span>-</span>\n }\n </td>\n }\n }\n }\n </tr>\n }\n </tbody>\n </table>\n </he-data-table>\n <div class=\"is-flex is-align-items-center is-flex-wrap-wrap is-justify-content-space-between is-mt-2\">\n <he-blank-node-state-notice [dataState]=\"dataState()\" />\n @if (impactAssessments().length > 1) {\n <div class=\"field is-relative is-mb-0\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded\"\n [id]=\"componentId() + 'hideIdenticalValues'\"\n name=\"hideIdenticalValues\"\n [(ngModel)]=\"hideIdenticalValues\" />\n <label [for]=\"componentId() + 'hideIdenticalValues'\">\n <span>Hide identical values</span>\n </label>\n </div>\n }\n </div>\n } @else if (noDataMessage()) {\n <div class=\"is-pt-3 has-text-centered\">\n <span>{{ noDataMessage() }}</span>\n </div>\n } @else {\n <div class=\"is-pt-3 has-text-centered\">\n <span>No data available</span>\n @if (filterTerm()) {\n <span class=\"is-pl-1\">matching your search criteria</span>\n }\n <span>.</span>\n @if (showSwitchToRecalculated()) {\n <span>\n Switch to\n <code>recalculated</code>\n version.\n </span>\n }\n </div>\n }\n }\n @case (View.chart) {\n <he-impact-assessments-indicators-chart [key]=\"nodeKey()\" [filterTermTypes]=\"filterTermTypes()\">\n <ng-container *ngTemplateOutlet=\"selectView\" />\n </he-impact-assessments-indicators-chart>\n }\n @case (View.breakdown) {\n @if (selectedNode()) {\n <he-impact-assessments-indicator-breakdown-chart\n [impactAssessment]=\"selectedNode()\"\n [indicators]=\"selectedRecalculatedValues()\">\n <ng-container *ngTemplateOutlet=\"selectView\" />\n </he-impact-assessments-indicator-breakdown-chart>\n }\n }\n @case (View.logs) {\n @if (selectedNode()) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n <he-node-logs-models\n [node]=\"selectedNode()\"\n [cycle]=\"selectedCycle()\"\n [nodeKey]=\"nodeKey()\"\n [filterTermTypes]=\"filterTermTypes()\"\n [filterTermTypesLabel]=\"filterTermTypesLabel()\"\n [originalValues]=\"selectedOriginalValues()\"\n [recalculatedValues]=\"selectedRecalculatedValues()\"\n [noDataMessage]=\"noDataMessage()\" />\n }\n }\n }\n}\n\n<ng-template #filterModel>\n @if (enableFilterMethodModel()) {\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"updateSelectedMethodModel($event.target.value)\">\n <option [ngValue]=\"undefined\">Filter Model</option>\n @for (term of methodModels(); track term) {\n <option [ngValue]=\"term\">{{ term.name }}</option>\n }\n </select>\n </div>\n }\n</ng-template>\n\n<ng-template #selectView>\n <div class=\"is-flex is-gap-8 is-align-items-center is-justify-content-space-between\">\n <div class=\"is-flex is-gap-8 is-align-items-center\">\n @if (selectedView() === View.table) {\n @if (hasData()) {\n <button class=\"button is-small is-ghost is-p-2\" (click)=\"showDownload()\">\n <he-svg-icon name=\"download\" />\n </button>\n }\n <he-search-extend\n class=\"is-secondary\"\n collapsedClass=\"is-p-2\"\n placeholder=\"Filter terms by name\"\n (searchText)=\"filterTerm.set($event)\" />\n } @else if (showSelectImpact()) {\n <ng-container *ngTemplateOutlet=\"selectImpact\" />\n }\n </div>\n\n @if (views()?.length > 1) {\n <div class=\"field has-addons button-segments\">\n @for (view of views(); track view) {\n <div class=\"control\">\n <button\n class=\"button is-small\"\n [class.is-selected]=\"selectedView() === view\"\n (click)=\"selectedView.set(view)\">\n <he-svg-icon\n name=\"checkmark\"\n aria-hidden=\"true\"\n class=\"is-hidden-mobile\"\n [class.is-hidden-tablet]=\"selectedView() !== view\" />\n <he-svg-icon\n [name]=\"viewIcon[view]\"\n aria-hidden=\"true\"\n [class.is-hidden-tablet]=\"selectedView() === view\" />\n <span class=\"is-hidden-mobile\">{{ view }}</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #selectImpact>\n @if (impactAssessments().length > 1) {\n <div class=\"field is-horizontal is-mb-0\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary is-nowrap\" for=\"selectImpactAssessment\">Impact Assessment</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"selectIndex($event)\" if=\"selectImpactAssessment\">\n @for (value of impactAssessments(); track nodeVersionKey(value); let i = $index) {\n <option [value]=\"i\">{{ i + 1 }}. {{ impactName(value) }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n</ng-template>\n\n<ng-template #details let-node=\"impactAssessment\" let-data=\"data\">\n <p>\n <b>\n @if (data.cycle) {\n <span>{{ cycleLabel(node.cycle) }}</span>\n }\n @if (!data.cycle) {\n <span>{{ data.name }}</span>\n }\n </b>\n </p>\n <he-node-value-details\n class=\"is-overflow-visible\"\n [data]=\"data\"\n [dataState]=\"dataState()\"\n [nodeType]=\"node['@type']\"\n [dataKey]=\"nodeKey()\"\n [aggregated]=\"node.aggregated\" />\n</ng-template>\n", styles: [":host{display:block}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}he-data-table ::ng-deep .table thead tr th:nth-child(3),he-data-table ::ng-deep .table tbody tr td:nth-child(3){min-width:110px}\n"], dependencies: [{ kind: "component", type: HESvgIconComponent, selector: "he-svg-icon", inputs: ["name", "size", "animation"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: SearchExtendComponent, selector: "he-search-extend", inputs: ["value", "disabled", "placeholder", "class", "collapsedClass"], outputs: ["valueChange", "searchText"] }, { kind: "component", type: DataTableComponent, selector: "he-data-table", inputs: ["minHeight", "maxHeight", "small"] }, { kind: "component", type: NodeLinkComponent, selector: "he-node-link", inputs: ["node", "dataState", "showExternalLink", "linkClass"] }, { kind: "component", type: TermsUnitsDescriptionComponent, selector: "he-terms-units-description", inputs: ["term", "iconTemplate"] }, { kind: "directive", type: NgbPopover, selector: "[ngbPopover]", inputs: ["animation", "autoClose", "ngbPopover", "popoverTitle", "placement", "popperOptions", "triggers", "positionTarget", "container", "disablePopover", "popoverClass", "popoverContext", "openDelay", "closeDelay"], outputs: ["shown", "hidden"], exportAs: ["ngbPopover"] }, { kind: "component", type: BlankNodeStateComponent, selector: "he-blank-node-state", inputs: ["dataState", "nodeType", "dataKey", "key", "node", "state", "linkClass"] }, { kind: "component", type: BlankNodeStateNoticeComponent, selector: "he-blank-node-state-notice", inputs: ["dataState", "showDeleted"] }, { kind: "component", type: ImpactAssessmentsIndicatorsChartComponent, selector: "he-impact-assessments-indicators-chart", inputs: ["key", "filterTermTypes"] }, { kind: "component", type: ImpactAssessmentsIndicatorBreakdownChartComponent, selector: "he-impact-assessments-indicator-breakdown-chart", inputs: ["impactAssessment", "indicators"] }, { kind: "component", type: NodeLogsModelsComponent, selector: "he-node-logs-models", inputs: ["node", "nodeKey", "originalValues", "recalculatedValues", "terms", "filterTermTypes", "filterTermTypesLabel", "logsKey", "noDataMessage", "cycle", "jlogParentKey", "jlogParentIndex"] }, { kind: "component", type: NodeValueDetailsComponent, selector: "he-node-value-details", inputs: ["data", "nodeType", "dataState", "dataKey", "aggregated"] }, { kind: "pipe", type: CompoundPipe, name: "compound" }, { kind: "pipe", type: DefaultPipe, name: "default" }, { kind: "pipe", type: EllipsisPipe, name: "ellipsis" }, { kind: "pipe", type: PrecisionPipe, name: "precision" }, { kind: "pipe", type: KeyToLabelPipe, name: "keyToLabel" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
15911
15944
  }
15912
15945
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ImpactAssessmentsProductsComponent, decorators: [{
15913
15946
  type: Component$1,
@@ -15931,7 +15964,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
15931
15964
  EllipsisPipe,
15932
15965
  PrecisionPipe,
15933
15966
  KeyToLabelPipe
15934
- ], template: "@if (isNodeKeyAllowed()) {\n @switch (selectedView()) {\n @case (View.table) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n <div class=\"is-hidden-tablet is-mt-3\">\n <ng-container *ngTemplateOutlet=\"filterModel\" />\n </div>\n\n @if (hasData()) {\n <he-data-table class=\"is-mt-3 is-bordered\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n @if (dataKeys().length > 1) {\n <tr class=\"has-text-weight-bold\">\n <th class=\"width-auto\"></th>\n <th></th>\n <th></th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @let blankNodesCount = countGroupVisibleNodes(blankNodes);\n @if (blankNodesCount > 0) {\n <th [attr.colspan]=\"blankNodesCount\" [class.has-border-right]=\"!dataKeyLast\">\n @if (dataKey) {\n <span>{{ dataKey | keyToLabel }}</span>\n }\n </th>\n }\n }\n </tr>\n }\n <tr class=\"has-text-weight-semibold\">\n <th class=\"width-auto has-border-right is-py-0\">\n <div class=\"is-hidden-mobile\">\n <ng-container *ngTemplateOutlet=\"filterModel\" />\n </div>\n </th>\n <th class=\"has-border-right\"></th>\n <th class=\"has-border-right\"></th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n <th\n [attr.title]=\"node.value.term.name\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n <he-node-link [node]=\"node.value.term\">\n <span\n [innerHtml]=\"\n node.value.term.name | ellipsis: 30 | compound: node.value.term.termType\n \"></span>\n </he-node-link>\n </th>\n }\n }\n }\n </tr>\n <tr class=\"is-italic has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n <th class=\"has-border-right\">\n <a [href]=\"schemaBaseUrl + '/ImpactAssessment#functionalUnit'\" target=\"_blank\">Functional unit</a>\n </th>\n <th class=\"has-border-right\">\n <a [href]=\"schemaBaseUrl + '/ImpactAssessment#product'\" target=\"_blank\">Product</a>\n </th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n <th\n [attr.title]=\"node.value.term.units\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n <span [innerHtml]=\"node.value.term.units | compound\"></span>\n <he-terms-units-description class=\"is-inline-block is-ml-2\" [term]=\"node.value.term\" />\n </th>\n }\n }\n }\n </tr>\n </thead>\n <tbody>\n @for (impactAssessment of impactAssessments(); track impactAssessment['@id']; let impactIndex = $index) {\n @let product = productTerm(impactAssessment);\n <tr [class.is-suggested]=\"$any(impactAssessment).suggested\">\n <td class=\"width-auto has-border-right\" [attr.title]=\"impactName(impactAssessment)\">\n <he-node-link [node]=\"impactAssessment\">\n <span class=\"has-text-ellipsis is-ellipsis-3\">\n @if ($any(impactAssessment).suggested) {\n <he-svg-icon name=\"compare\" />\n } @else {\n <span>{{ impactIndex + 1 }}.</span>\n }\n <span class=\"is-pl-1\">{{ impactName(impactAssessment) }}</span>\n </span>\n </he-node-link>\n </td>\n <td class=\"has-border-right\" [attr.title]=\"product?.units\">\n <span>1 {{ product?.units }}</span>\n </td>\n <td class=\"has-border-right\" [attr.title]=\"product?.name\">\n @if (product) {\n <he-node-link [node]=\"product\">\n <span>{{ product.name | ellipsis: 30 }}</span>\n </he-node-link>\n }\n </td>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n @let impactData = node.value.values[impactAssessment['@id']];\n <td\n class=\"is-nowrap\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n @if (impactData) {\n <span\n class=\"trigger-popover\"\n [ngbPopover]=\"details\"\n autoClose=\"outside\"\n popoverClass=\"is-narrow is-overflow-visible\"\n placement=\"left bottom auto\"\n container=\"body\"\n [popoverContext]=\"{\n data: impactData,\n impactAssessment\n }\">\n <span pointer>\n {{ impactData.propertyValue | precision: 3 | default: '-' }}\n </span>\n <he-blank-node-state\n class=\"ml-1\"\n [dataState]=\"dataState()\"\n [node]=\"impactData.node\"\n key=\"value\"\n [state]=\"impactAssessment.aggregated ? 'aggregated' : undefined\" />\n </span>\n } @else {\n <span>-</span>\n }\n </td>\n }\n }\n }\n </tr>\n }\n </tbody>\n </table>\n </he-data-table>\n <div class=\"is-flex is-align-items-center is-flex-wrap-wrap is-justify-content-space-between is-mt-2\">\n <he-blank-node-state-notice [dataState]=\"dataState()\" />\n @if (impactAssessments().length > 1) {\n <div class=\"field is-relative is-mb-0\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded\"\n [id]=\"componentId() + 'hideIdenticalValues'\"\n name=\"hideIdenticalValues\"\n [(ngModel)]=\"hideIdenticalValues\" />\n <label [for]=\"componentId() + 'hideIdenticalValues'\">\n <span>Hide identical values</span>\n </label>\n </div>\n }\n </div>\n } @else if (noDataMessage()) {\n <div class=\"is-pt-3 has-text-centered\">\n <span>{{ noDataMessage() }}</span>\n </div>\n } @else {\n <div class=\"is-pt-3 has-text-centered\">\n <span>No data available</span>\n @if (filterTerm()) {\n <span class=\"is-pl-1\">matching your search criteria</span>\n }\n <span>.</span>\n @if (showSwitchToRecalculated()) {\n <span>\n Switch to\n <code>recalculated</code>\n version.\n </span>\n }\n </div>\n }\n }\n @case (View.chart) {\n <he-impact-assessments-indicators-chart [key]=\"nodeKey()\" [filterTermTypes]=\"filterTermTypes()\">\n <ng-container *ngTemplateOutlet=\"selectView\" />\n </he-impact-assessments-indicators-chart>\n }\n @case (View.breakdown) {\n @if (selectedNode()) {\n <he-impact-assessments-indicator-breakdown-chart\n [impactAssessment]=\"selectedNode()\"\n [indicators]=\"selectedRecalculatedValues()\">\n <ng-container *ngTemplateOutlet=\"selectView\" />\n </he-impact-assessments-indicator-breakdown-chart>\n }\n }\n @case (View.logs) {\n @if (selectedNode()) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n <he-node-logs-models\n [node]=\"selectedNode()\"\n [cycle]=\"selectedCycle()\"\n [nodeKey]=\"nodeKey()\"\n [filterTermTypes]=\"filterTermTypes()\"\n [filterTermTypesLabel]=\"filterTermTypesLabel()\"\n [originalValues]=\"selectedOriginalValues()\"\n [recalculatedValues]=\"selectedRecalculatedValues()\"\n [noDataMessage]=\"noDataMessage()\" />\n }\n }\n }\n}\n\n<ng-template #filterModel>\n @if (enableFilterMethodModel()) {\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"updateSelectedMethodModel($event.target.value)\">\n <option [ngValue]=\"undefined\">Filter Model</option>\n @for (term of methodModels(); track term) {\n <option [ngValue]=\"term\">{{ term.name }}</option>\n }\n </select>\n </div>\n }\n</ng-template>\n\n<ng-template #selectView>\n <div class=\"is-flex is-gap-8 is-align-items-center is-justify-content-space-between\">\n <div class=\"is-flex is-gap-8 is-align-items-center\">\n @if (selectedView() === View.table) {\n @if (hasData()) {\n <button class=\"button is-small is-ghost is-p-2\" (click)=\"showDownload()\">\n <he-svg-icon name=\"download\" />\n </button>\n }\n <he-search-extend\n class=\"is-secondary\"\n collapsedClass=\"is-p-2\"\n placeholder=\"Filter terms by name\"\n (searchText)=\"filterTerm.set($event)\" />\n } @else if (showSelectImpact()) {\n <ng-container *ngTemplateOutlet=\"selectImpact\" />\n }\n </div>\n\n @if (views()?.length > 1) {\n <div class=\"field has-addons button-segments\">\n @for (view of views(); track view) {\n <div class=\"control\">\n <button\n class=\"button is-small\"\n [class.is-selected]=\"selectedView() === view\"\n (click)=\"selectedView.set(view)\">\n <he-svg-icon\n name=\"checkmark\"\n aria-hidden=\"true\"\n class=\"is-hidden-mobile\"\n [class.is-hidden-tablet]=\"selectedView() !== view\" />\n <he-svg-icon\n [name]=\"viewIcon[view]\"\n aria-hidden=\"true\"\n [class.is-hidden-tablet]=\"selectedView() === view\" />\n <span class=\"is-hidden-mobile\">{{ view }}</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #selectImpact>\n @if (impactAssessments().length > 1) {\n <div class=\"field is-horizontal is-mb-0\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary is-nowrap\" for=\"selectImpactAssessment\">Impact Assessment</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"selectIndex($event)\" if=\"selectImpactAssessment\">\n @for (value of impactAssessments(); track value; let i = $index) {\n <option [value]=\"i\">{{ i + 1 }}. {{ impactName(value) }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n</ng-template>\n\n<ng-template #details let-node=\"impactAssessment\" let-data=\"data\">\n <p>\n <b>\n @if (data.cycle) {\n <span>{{ cycleLabel(node.cycle) }}</span>\n }\n @if (!data.cycle) {\n <span>{{ data.name }}</span>\n }\n </b>\n </p>\n <he-node-value-details\n class=\"is-overflow-visible\"\n [data]=\"data\"\n [dataState]=\"dataState()\"\n [nodeType]=\"node['@type']\"\n [dataKey]=\"nodeKey()\"\n [aggregated]=\"node.aggregated\" />\n</ng-template>\n", styles: [":host{display:block}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}he-data-table ::ng-deep .table thead tr th:nth-child(3),he-data-table ::ng-deep .table tbody tr td:nth-child(3){min-width:110px}\n"] }]
15967
+ ], template: "@if (isNodeKeyAllowed()) {\n @switch (selectedView()) {\n @case (View.table) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n <div class=\"is-hidden-tablet is-mt-3\">\n <ng-container *ngTemplateOutlet=\"filterModel\" />\n </div>\n\n @if (hasData()) {\n <he-data-table class=\"is-mt-3 is-bordered\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n @if (dataKeys().length > 1) {\n <tr class=\"has-text-weight-bold\">\n <th class=\"width-auto\"></th>\n <th></th>\n <th></th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @let blankNodesCount = countGroupVisibleNodes(blankNodes);\n @if (blankNodesCount > 0) {\n <th [attr.colspan]=\"blankNodesCount\" [class.has-border-right]=\"!dataKeyLast\">\n @if (dataKey) {\n <span>{{ dataKey | keyToLabel }}</span>\n }\n </th>\n }\n }\n </tr>\n }\n <tr class=\"has-text-weight-semibold\">\n <th class=\"width-auto has-border-right is-py-0\">\n <div class=\"is-hidden-mobile\">\n <ng-container *ngTemplateOutlet=\"filterModel\" />\n </div>\n </th>\n <th class=\"has-border-right\"></th>\n <th class=\"has-border-right\"></th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n <th\n [attr.title]=\"node.value.term.name\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n <he-node-link [node]=\"node.value.term\">\n <span\n [innerHtml]=\"\n node.value.term.name | ellipsis: 30 | compound: node.value.term.termType\n \"></span>\n </he-node-link>\n </th>\n }\n }\n }\n </tr>\n <tr class=\"is-italic has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n <th class=\"has-border-right\">\n <a [href]=\"schemaBaseUrl + '/ImpactAssessment#functionalUnit'\" target=\"_blank\">Functional unit</a>\n </th>\n <th class=\"has-border-right\">\n <a [href]=\"schemaBaseUrl + '/ImpactAssessment#product'\" target=\"_blank\">Product</a>\n </th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n <th\n [attr.title]=\"node.value.term.units\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n <span [innerHtml]=\"node.value.term.units | compound\"></span>\n <he-terms-units-description class=\"is-inline-block is-ml-2\" [term]=\"node.value.term\" />\n </th>\n }\n }\n }\n </tr>\n </thead>\n <tbody>\n @for (\n impactAssessment of impactAssessments();\n track nodeVersionKey(impactAssessment);\n let impactIndex = $index\n ) {\n @let product = productTerm(impactAssessment);\n <tr [class.is-suggested]=\"$any(impactAssessment).suggested\">\n <td class=\"width-auto has-border-right\" [attr.title]=\"impactName(impactAssessment)\">\n <he-node-link [node]=\"impactAssessment\">\n <span class=\"has-text-ellipsis is-ellipsis-3\">\n @if ($any(impactAssessment).suggested) {\n <he-svg-icon name=\"compare\" />\n } @else {\n <span>{{ impactIndex + 1 }}.</span>\n }\n <span class=\"is-pl-1\">{{ impactName(impactAssessment) }}</span>\n </span>\n </he-node-link>\n </td>\n <td class=\"has-border-right\" [attr.title]=\"product?.units\">\n <span>1 {{ product?.units }}</span>\n </td>\n <td class=\"has-border-right\" [attr.title]=\"product?.name\">\n @if (product) {\n <he-node-link [node]=\"product\">\n <span>{{ product.name | ellipsis: 30 }}</span>\n </he-node-link>\n }\n </td>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n @let impactData = node.value.values[impactAssessment['@id']];\n <td\n class=\"is-nowrap\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n @if (impactData) {\n <span\n class=\"trigger-popover\"\n [ngbPopover]=\"details\"\n autoClose=\"outside\"\n popoverClass=\"is-narrow is-overflow-visible\"\n placement=\"left bottom auto\"\n container=\"body\"\n [popoverContext]=\"{\n data: impactData,\n impactAssessment\n }\">\n <span pointer>\n {{ impactData.propertyValue | precision: 3 | default: '-' }}\n </span>\n <he-blank-node-state\n class=\"ml-1\"\n [dataState]=\"dataState()\"\n [node]=\"impactData.node\"\n key=\"value\"\n [state]=\"impactAssessment.aggregated ? 'aggregated' : undefined\" />\n </span>\n } @else {\n <span>-</span>\n }\n </td>\n }\n }\n }\n </tr>\n }\n </tbody>\n </table>\n </he-data-table>\n <div class=\"is-flex is-align-items-center is-flex-wrap-wrap is-justify-content-space-between is-mt-2\">\n <he-blank-node-state-notice [dataState]=\"dataState()\" />\n @if (impactAssessments().length > 1) {\n <div class=\"field is-relative is-mb-0\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded\"\n [id]=\"componentId() + 'hideIdenticalValues'\"\n name=\"hideIdenticalValues\"\n [(ngModel)]=\"hideIdenticalValues\" />\n <label [for]=\"componentId() + 'hideIdenticalValues'\">\n <span>Hide identical values</span>\n </label>\n </div>\n }\n </div>\n } @else if (noDataMessage()) {\n <div class=\"is-pt-3 has-text-centered\">\n <span>{{ noDataMessage() }}</span>\n </div>\n } @else {\n <div class=\"is-pt-3 has-text-centered\">\n <span>No data available</span>\n @if (filterTerm()) {\n <span class=\"is-pl-1\">matching your search criteria</span>\n }\n <span>.</span>\n @if (showSwitchToRecalculated()) {\n <span>\n Switch to\n <code>recalculated</code>\n version.\n </span>\n }\n </div>\n }\n }\n @case (View.chart) {\n <he-impact-assessments-indicators-chart [key]=\"nodeKey()\" [filterTermTypes]=\"filterTermTypes()\">\n <ng-container *ngTemplateOutlet=\"selectView\" />\n </he-impact-assessments-indicators-chart>\n }\n @case (View.breakdown) {\n @if (selectedNode()) {\n <he-impact-assessments-indicator-breakdown-chart\n [impactAssessment]=\"selectedNode()\"\n [indicators]=\"selectedRecalculatedValues()\">\n <ng-container *ngTemplateOutlet=\"selectView\" />\n </he-impact-assessments-indicator-breakdown-chart>\n }\n }\n @case (View.logs) {\n @if (selectedNode()) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n <he-node-logs-models\n [node]=\"selectedNode()\"\n [cycle]=\"selectedCycle()\"\n [nodeKey]=\"nodeKey()\"\n [filterTermTypes]=\"filterTermTypes()\"\n [filterTermTypesLabel]=\"filterTermTypesLabel()\"\n [originalValues]=\"selectedOriginalValues()\"\n [recalculatedValues]=\"selectedRecalculatedValues()\"\n [noDataMessage]=\"noDataMessage()\" />\n }\n }\n }\n}\n\n<ng-template #filterModel>\n @if (enableFilterMethodModel()) {\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"updateSelectedMethodModel($event.target.value)\">\n <option [ngValue]=\"undefined\">Filter Model</option>\n @for (term of methodModels(); track term) {\n <option [ngValue]=\"term\">{{ term.name }}</option>\n }\n </select>\n </div>\n }\n</ng-template>\n\n<ng-template #selectView>\n <div class=\"is-flex is-gap-8 is-align-items-center is-justify-content-space-between\">\n <div class=\"is-flex is-gap-8 is-align-items-center\">\n @if (selectedView() === View.table) {\n @if (hasData()) {\n <button class=\"button is-small is-ghost is-p-2\" (click)=\"showDownload()\">\n <he-svg-icon name=\"download\" />\n </button>\n }\n <he-search-extend\n class=\"is-secondary\"\n collapsedClass=\"is-p-2\"\n placeholder=\"Filter terms by name\"\n (searchText)=\"filterTerm.set($event)\" />\n } @else if (showSelectImpact()) {\n <ng-container *ngTemplateOutlet=\"selectImpact\" />\n }\n </div>\n\n @if (views()?.length > 1) {\n <div class=\"field has-addons button-segments\">\n @for (view of views(); track view) {\n <div class=\"control\">\n <button\n class=\"button is-small\"\n [class.is-selected]=\"selectedView() === view\"\n (click)=\"selectedView.set(view)\">\n <he-svg-icon\n name=\"checkmark\"\n aria-hidden=\"true\"\n class=\"is-hidden-mobile\"\n [class.is-hidden-tablet]=\"selectedView() !== view\" />\n <he-svg-icon\n [name]=\"viewIcon[view]\"\n aria-hidden=\"true\"\n [class.is-hidden-tablet]=\"selectedView() === view\" />\n <span class=\"is-hidden-mobile\">{{ view }}</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #selectImpact>\n @if (impactAssessments().length > 1) {\n <div class=\"field is-horizontal is-mb-0\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary is-nowrap\" for=\"selectImpactAssessment\">Impact Assessment</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"selectIndex($event)\" if=\"selectImpactAssessment\">\n @for (value of impactAssessments(); track nodeVersionKey(value); let i = $index) {\n <option [value]=\"i\">{{ i + 1 }}. {{ impactName(value) }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n</ng-template>\n\n<ng-template #details let-node=\"impactAssessment\" let-data=\"data\">\n <p>\n <b>\n @if (data.cycle) {\n <span>{{ cycleLabel(node.cycle) }}</span>\n }\n @if (!data.cycle) {\n <span>{{ data.name }}</span>\n }\n </b>\n </p>\n <he-node-value-details\n class=\"is-overflow-visible\"\n [data]=\"data\"\n [dataState]=\"dataState()\"\n [nodeType]=\"node['@type']\"\n [dataKey]=\"nodeKey()\"\n [aggregated]=\"node.aggregated\" />\n</ng-template>\n", styles: [":host{display:block}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}he-data-table ::ng-deep .table thead tr th:nth-child(3),he-data-table ::ng-deep .table tbody tr td:nth-child(3){min-width:110px}\n"] }]
15935
15968
  }], ctorParameters: () => [], propDecorators: { dataState: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataState", required: false }] }], nodeKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "nodeKey", required: false }] }], filterTermTypes: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterTermTypes", required: false }] }], enableFilterMethodModel: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableFilterMethodModel", required: false }] }] } });
15936
15969
 
15937
15970
  const hasValidationError = (errors = [], level) => {
@@ -16371,7 +16404,8 @@ const siteGroupNode = (site) => (node) => node
16371
16404
  ? {
16372
16405
  ...node,
16373
16406
  name: site?.name,
16374
- '@id': site?.['@id'] // carry the parent Site @id for logs lookup
16407
+ '@id': site?.['@id'], // carry the parent Site @id for logs lookup
16408
+ dataVersion: site?.dataVersion // keep the data version so the logs are fetched for the right version
16375
16409
  }
16376
16410
  : null;
16377
16411
  const siteGroupNodes = (groupKey, site) => (site?.[groupKey] || []).map(siteGroupNode(site)).filter(Boolean);
@@ -16415,6 +16449,7 @@ class SitesNodesComponent {
16415
16449
  this.BlankNodesKey = BlankNodesKey;
16416
16450
  this.siteTooBig = siteTooBig;
16417
16451
  this.defaultLabel = defaultLabel;
16452
+ this.nodeVersionKey = nodeVersionKey;
16418
16453
  this.maxAreaSize = maxAreaSize;
16419
16454
  this.selectedGroup = signal(undefined, ...(ngDevMode ? [{ debugName: "selectedGroup" }] : []));
16420
16455
  this.headerKeys = computed(() => ['site.id', 'site.@id', `site.${this.nodeKey()}.`], ...(ngDevMode ? [{ debugName: "headerKeys" }] : []));
@@ -16499,7 +16534,7 @@ class SitesNodesComponent {
16499
16534
  component.headerKeys.set(this.headerKeys());
16500
16535
  }
16501
16536
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SitesNodesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
16502
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: SitesNodesComponent, isStandalone: true, selector: "he-sites-nodes", inputs: { dataState: { classPropertyName: "dataState", publicName: "dataState", isSignal: true, isRequired: false, transformFunction: null }, nodeKey: { classPropertyName: "nodeKey", publicName: "nodeKey", isSignal: true, isRequired: false, transformFunction: null }, enableChart: { classPropertyName: "enableChart", publicName: "enableChart", isSignal: true, isRequired: false, transformFunction: null }, nodeKeyGroup: { classPropertyName: "nodeKeyGroup", publicName: "nodeKeyGroup", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (isGroupNode()) {\n <div class=\"tabs is-mb-1 | group-nodes-tabs\">\n <ul>\n @for (value of groupNodeValues(); track value) {\n <li [class.is-active]=\"selectedGroup() === value\">\n <a (click)=\"selectedGroup.set(value)\">\n <span class=\"is-capitalized is-pr-1\">{{ nodeKeyGroup() | pluralize: 1 }}:</span>\n <span>{{ groupNodeDisplayNames()[value] || value }}</span>\n </a>\n </li>\n }\n </ul>\n </div>\n}\n\n@if (isNodeKeyAllowed()) {\n @switch (selectedView()) {\n @case (View.table) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (hasData()) {\n <he-data-table class=\"is-mt-3 is-bordered\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n <tr class=\"has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n @for (node of data(); track node.value.term.name) {\n @if (node.value.visible) {\n <th [attr.title]=\"node.value.term.name\">\n <he-node-link [node]=\"node.value.term\">\n <span\n [innerHtml]=\"node.value.term.name | ellipsis: 30 | compound: node.value.term.termType\"></span>\n </he-node-link>\n </th>\n }\n }\n </tr>\n <tr class=\"is-italic has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n @for (node of data(); track node.value.term.name) {\n @if (node.value.visible) {\n <th [attr.title]=\"node.value.term.units\">\n <span [innerHtml]=\"node.value.term.units | compound\"></span>\n <he-terms-units-description class=\"is-inline-block is-ml-2\" [term]=\"node.value.term\" />\n </th>\n }\n }\n </tr>\n </thead>\n <tbody>\n @for (site of sites(); track site['@id']; let siteIndex = $index) {\n <tr [class.is-suggested]=\"$any(site).suggested\">\n <td class=\"width-auto has-border-right\" [attr.title]=\"defaultLabel(site)\">\n <he-node-link [node]=\"site\">\n <span class=\"has-text-ellipsis is-ellipsis-3\">\n @if ($any(site).suggested) {\n <he-svg-icon name=\"compare\" />\n } @else {\n <span>{{ siteIndex + 1 }}.</span>\n }\n <span class=\"is-pl-1\">{{ defaultLabel(site) }}</span>\n </span>\n </he-node-link>\n </td>\n @for (node of data(); track node.value.term.name) {\n @if (node.value.visible) {\n @let siteData = node.value.values[site['@id']];\n <td class=\"is-nowrap\">\n @if (siteData) {\n <span\n class=\"trigger-popover\"\n [ngbPopover]=\"details\"\n autoClose=\"outside\"\n popoverClass=\"is-narrow is-overflow-visible\"\n placement=\"left bottom auto\"\n container=\"body\"\n [popoverContext]=\"{ data: siteData, site }\">\n <span pointer>\n {{ siteData.propertyValue | precision: 3 | default: '-' }}\n </span>\n <he-blank-node-state\n class=\"ml-1\"\n [dataState]=\"dataState()\"\n [node]=\"siteData.node\"\n key=\"value\" />\n </span>\n }\n @if (isMeasurement() && !siteData) {\n <span>\n <span>-</span>\n @if (siteTooBig(site)) {\n <sup class=\"pl-1\">(1)</sup>\n }\n </span>\n }\n </td>\n }\n }\n </tr>\n }\n </tbody>\n </table>\n </he-data-table>\n <div class=\"is-flex is-align-items-center is-flex-wrap-wrap is-justify-content-space-between is-mt-2\">\n <he-blank-node-state-notice [dataState]=\"dataState()\" />\n <div class=\"is-flex is-flex-wrap-wrap is-gap-8\">\n <div class=\"field is-relative is-mb-0\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded\"\n [id]=\"componentId() + 'hideZeroValues'\"\n name=\"hideZeroValues\"\n [(ngModel)]=\"hideZeroValues\" />\n <label [for]=\"componentId() + 'hideZeroValues'\">\n <span>\n Hide\n <b>0</b>\n values\n </span>\n </label>\n </div>\n @if (sites().length > 1) {\n <div class=\"field is-relative is-mb-0\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded\"\n [id]=\"componentId() + 'hideIdenticalValues'\"\n name=\"hideIdenticalValues\"\n [(ngModel)]=\"hideIdenticalValues\" />\n <label [for]=\"componentId() + 'hideIdenticalValues'\">\n <span>Hide identical values</span>\n </label>\n </div>\n }\n </div>\n </div>\n @if (showAreaTooBig()) {\n <p class=\"is-size-7 is-italic\">\n (1) This region is >{{ maxAreaSize }}km2 and is too large to reliably gap fill Measurements.\n </p>\n }\n } @else {\n <div class=\"is-pt-3 has-text-centered\">\n <span>No data available</span>\n @if (filterTerm()) {\n <span class=\"is-pl-1\">matching your search criteria</span>\n }\n <span>.</span>\n @if (showSwitchToRecalculated()) {\n <span>\n Switch to\n <code>recalculated</code>\n version.\n </span>\n }\n </div>\n }\n }\n @case (View.chart) {\n @if (nodeKey() === BlankNodesKey.management) {\n @if (selectedNode()) {\n <he-sites-management-chart [site]=\"selectedNode()\" [cycles]=\"cycles()\">\n <ng-container *ngTemplateOutlet=\"selectView\" />\n </he-sites-management-chart>\n }\n }\n }\n @case (View.logs) {\n @if (selectedNode()) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n <he-node-logs-models\n [node]=\"selectedNode()\"\n [nodeKey]=\"nodeKey()\"\n [originalValues]=\"selectedOriginalValues()\"\n [recalculatedValues]=\"selectedRecalculatedValues()\"\n [filterTermTypes]=\"filterTermTypes()\"\n [filterTermTypesLabel]=\"nodeKey() | capitalize\" />\n }\n }\n }\n}\n\n<ng-template #selectView>\n <div class=\"is-flex is-gap-8 is-align-items-center is-justify-content-space-between\">\n <div class=\"is-flex is-gap-8 is-align-items-center\">\n @if (selectedView() === View.table) {\n @if (hasData()) {\n <button class=\"button is-small is-ghost is-p-2\" (click)=\"showDownload()\">\n <he-svg-icon name=\"download\" />\n </button>\n }\n\n <he-search-extend\n class=\"is-secondary\"\n collapsedClass=\"is-p-2\"\n placeholder=\"Filter terms by name\"\n (searchText)=\"filterTerm.set($event)\" />\n } @else if (showSelectSite()) {\n <ng-container *ngTemplateOutlet=\"selectSite\" />\n }\n </div>\n\n @if (views()?.length > 1) {\n <div class=\"field has-addons button-segments\">\n @for (view of views(); track view) {\n <div class=\"control\">\n <button\n class=\"button is-small\"\n [class.is-selected]=\"selectedView() === view\"\n (click)=\"selectedView.set(view)\">\n <he-svg-icon\n name=\"checkmark\"\n aria-hidden=\"true\"\n class=\"is-hidden-mobile\"\n [class.is-hidden-tablet]=\"selectedView() !== view\" />\n <he-svg-icon\n [name]=\"viewIcon[view]\"\n aria-hidden=\"true\"\n [class.is-hidden-tablet]=\"selectedView() === view\" />\n <span class=\"is-hidden-mobile\">{{ view }}</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #selectSite>\n @if (sites().length > 1) {\n <div class=\"field is-horizontal is-mb-0\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary\" for=\"selectSite\">Site</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"selectIndex($event)\" if=\"selectSite\">\n @for (value of sites(); track value; let siteIndex = $index) {\n <option [value]=\"siteIndex\">{{ siteIndex + 1 }}. {{ defaultLabel(value) }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n</ng-template>\n\n<ng-template #emptyValue>\n <span>-</span>\n</ng-template>\n\n<ng-template #details let-node=\"site\" let-data=\"data\">\n <p>\n <b>{{ node.name }}</b>\n </p>\n <he-node-value-details\n class=\"is-overflow-visible\"\n [data]=\"data\"\n [dataState]=\"dataState()\"\n [nodeType]=\"node['@type']\"\n [dataKey]=\"nodeKey()\"\n [aggregated]=\"node.aggregated\" />\n</ng-template>\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: HESvgIconComponent, selector: "he-svg-icon", inputs: ["name", "size", "animation"] }, { kind: "component", type: SearchExtendComponent, selector: "he-search-extend", inputs: ["value", "disabled", "placeholder", "class", "collapsedClass"], outputs: ["valueChange", "searchText"] }, { kind: "component", type: DataTableComponent, selector: "he-data-table", inputs: ["minHeight", "maxHeight", "small"] }, { kind: "component", type: NodeLinkComponent, selector: "he-node-link", inputs: ["node", "dataState", "showExternalLink", "linkClass"] }, { kind: "component", type: TermsUnitsDescriptionComponent, selector: "he-terms-units-description", inputs: ["term", "iconTemplate"] }, { kind: "directive", type: NgbPopover, selector: "[ngbPopover]", inputs: ["animation", "autoClose", "ngbPopover", "popoverTitle", "placement", "popperOptions", "triggers", "positionTarget", "container", "disablePopover", "popoverClass", "popoverContext", "openDelay", "closeDelay"], outputs: ["shown", "hidden"], exportAs: ["ngbPopover"] }, { kind: "component", type: BlankNodeStateComponent, selector: "he-blank-node-state", inputs: ["dataState", "nodeType", "dataKey", "key", "node", "state", "linkClass"] }, { kind: "component", type: BlankNodeStateNoticeComponent, selector: "he-blank-node-state-notice", inputs: ["dataState", "showDeleted"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: NodeLogsModelsComponent, selector: "he-node-logs-models", inputs: ["node", "nodeKey", "originalValues", "recalculatedValues", "terms", "filterTermTypes", "filterTermTypesLabel", "logsKey", "noDataMessage", "cycle", "jlogParentKey", "jlogParentIndex"] }, { kind: "component", type: NodeValueDetailsComponent, selector: "he-node-value-details", inputs: ["data", "nodeType", "dataState", "dataKey", "aggregated"] }, { kind: "component", type: SitesManagementChartComponent, selector: "he-sites-management-chart", inputs: ["site", "cycles"] }, { kind: "pipe", type: CompoundPipe, name: "compound" }, { kind: "pipe", type: DefaultPipe, name: "default" }, { kind: "pipe", type: EllipsisPipe, name: "ellipsis" }, { kind: "pipe", type: PrecisionPipe, name: "precision" }, { kind: "pipe", type: CapitalizePipe, name: "capitalize" }, { kind: "pipe", type: PluralizePipe, name: "pluralize" }] }); }
16537
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: SitesNodesComponent, isStandalone: true, selector: "he-sites-nodes", inputs: { dataState: { classPropertyName: "dataState", publicName: "dataState", isSignal: true, isRequired: false, transformFunction: null }, nodeKey: { classPropertyName: "nodeKey", publicName: "nodeKey", isSignal: true, isRequired: false, transformFunction: null }, enableChart: { classPropertyName: "enableChart", publicName: "enableChart", isSignal: true, isRequired: false, transformFunction: null }, nodeKeyGroup: { classPropertyName: "nodeKeyGroup", publicName: "nodeKeyGroup", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (isGroupNode()) {\n <div class=\"tabs is-mb-1 | group-nodes-tabs\">\n <ul>\n @for (value of groupNodeValues(); track value) {\n <li [class.is-active]=\"selectedGroup() === value\">\n <a (click)=\"selectedGroup.set(value)\">\n <span class=\"is-capitalized is-pr-1\">{{ nodeKeyGroup() | pluralize: 1 }}:</span>\n <span>{{ groupNodeDisplayNames()[value] || value }}</span>\n </a>\n </li>\n }\n </ul>\n </div>\n}\n\n@if (isNodeKeyAllowed()) {\n @switch (selectedView()) {\n @case (View.table) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (hasData()) {\n <he-data-table class=\"is-mt-3 is-bordered\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n <tr class=\"has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n @for (node of data(); track node.value.term.name) {\n @if (node.value.visible) {\n <th [attr.title]=\"node.value.term.name\">\n <he-node-link [node]=\"node.value.term\">\n <span\n [innerHtml]=\"node.value.term.name | ellipsis: 30 | compound: node.value.term.termType\"></span>\n </he-node-link>\n </th>\n }\n }\n </tr>\n <tr class=\"is-italic has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n @for (node of data(); track node.value.term.name) {\n @if (node.value.visible) {\n <th [attr.title]=\"node.value.term.units\">\n <span [innerHtml]=\"node.value.term.units | compound\"></span>\n <he-terms-units-description class=\"is-inline-block is-ml-2\" [term]=\"node.value.term\" />\n </th>\n }\n }\n </tr>\n </thead>\n <tbody>\n @for (site of sites(); track nodeVersionKey(site); let siteIndex = $index) {\n <tr [class.is-suggested]=\"$any(site).suggested\">\n <td class=\"width-auto has-border-right\" [attr.title]=\"defaultLabel(site)\">\n <he-node-link [node]=\"site\">\n <span class=\"has-text-ellipsis is-ellipsis-3\">\n @if ($any(site).suggested) {\n <he-svg-icon name=\"compare\" />\n } @else {\n <span>{{ siteIndex + 1 }}.</span>\n }\n <span class=\"is-pl-1\">{{ defaultLabel(site) }}</span>\n </span>\n </he-node-link>\n </td>\n @for (node of data(); track node.value.term.name) {\n @if (node.value.visible) {\n @let siteData = node.value.values[site['@id']];\n <td class=\"is-nowrap\">\n @if (siteData) {\n <span\n class=\"trigger-popover\"\n [ngbPopover]=\"details\"\n autoClose=\"outside\"\n popoverClass=\"is-narrow is-overflow-visible\"\n placement=\"left bottom auto\"\n container=\"body\"\n [popoverContext]=\"{ data: siteData, site }\">\n <span pointer>\n {{ siteData.propertyValue | precision: 3 | default: '-' }}\n </span>\n <he-blank-node-state\n class=\"ml-1\"\n [dataState]=\"dataState()\"\n [node]=\"siteData.node\"\n key=\"value\" />\n </span>\n }\n @if (isMeasurement() && !siteData) {\n <span>\n <span>-</span>\n @if (siteTooBig(site)) {\n <sup class=\"pl-1\">(1)</sup>\n }\n </span>\n }\n </td>\n }\n }\n </tr>\n }\n </tbody>\n </table>\n </he-data-table>\n <div class=\"is-flex is-align-items-center is-flex-wrap-wrap is-justify-content-space-between is-mt-2\">\n <he-blank-node-state-notice [dataState]=\"dataState()\" />\n <div class=\"is-flex is-flex-wrap-wrap is-gap-8\">\n <div class=\"field is-relative is-mb-0\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded\"\n [id]=\"componentId() + 'hideZeroValues'\"\n name=\"hideZeroValues\"\n [(ngModel)]=\"hideZeroValues\" />\n <label [for]=\"componentId() + 'hideZeroValues'\">\n <span>\n Hide\n <b>0</b>\n values\n </span>\n </label>\n </div>\n @if (sites().length > 1) {\n <div class=\"field is-relative is-mb-0\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded\"\n [id]=\"componentId() + 'hideIdenticalValues'\"\n name=\"hideIdenticalValues\"\n [(ngModel)]=\"hideIdenticalValues\" />\n <label [for]=\"componentId() + 'hideIdenticalValues'\">\n <span>Hide identical values</span>\n </label>\n </div>\n }\n </div>\n </div>\n @if (showAreaTooBig()) {\n <p class=\"is-size-7 is-italic\">\n (1) This region is >{{ maxAreaSize }}km2 and is too large to reliably gap fill Measurements.\n </p>\n }\n } @else {\n <div class=\"is-pt-3 has-text-centered\">\n <span>No data available</span>\n @if (filterTerm()) {\n <span class=\"is-pl-1\">matching your search criteria</span>\n }\n <span>.</span>\n @if (showSwitchToRecalculated()) {\n <span>\n Switch to\n <code>recalculated</code>\n version.\n </span>\n }\n </div>\n }\n }\n @case (View.chart) {\n @if (nodeKey() === BlankNodesKey.management) {\n @if (selectedNode()) {\n <he-sites-management-chart [site]=\"selectedNode()\" [cycles]=\"cycles()\">\n <ng-container *ngTemplateOutlet=\"selectView\" />\n </he-sites-management-chart>\n }\n }\n }\n @case (View.logs) {\n @if (selectedNode()) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n <he-node-logs-models\n [node]=\"selectedNode()\"\n [nodeKey]=\"nodeKey()\"\n [originalValues]=\"selectedOriginalValues()\"\n [recalculatedValues]=\"selectedRecalculatedValues()\"\n [filterTermTypes]=\"filterTermTypes()\"\n [filterTermTypesLabel]=\"nodeKey() | capitalize\" />\n }\n }\n }\n}\n\n<ng-template #selectView>\n <div class=\"is-flex is-gap-8 is-align-items-center is-justify-content-space-between\">\n <div class=\"is-flex is-gap-8 is-align-items-center\">\n @if (selectedView() === View.table) {\n @if (hasData()) {\n <button class=\"button is-small is-ghost is-p-2\" (click)=\"showDownload()\">\n <he-svg-icon name=\"download\" />\n </button>\n }\n\n <he-search-extend\n class=\"is-secondary\"\n collapsedClass=\"is-p-2\"\n placeholder=\"Filter terms by name\"\n (searchText)=\"filterTerm.set($event)\" />\n } @else if (showSelectSite()) {\n <ng-container *ngTemplateOutlet=\"selectSite\" />\n }\n </div>\n\n @if (views()?.length > 1) {\n <div class=\"field has-addons button-segments\">\n @for (view of views(); track view) {\n <div class=\"control\">\n <button\n class=\"button is-small\"\n [class.is-selected]=\"selectedView() === view\"\n (click)=\"selectedView.set(view)\">\n <he-svg-icon\n name=\"checkmark\"\n aria-hidden=\"true\"\n class=\"is-hidden-mobile\"\n [class.is-hidden-tablet]=\"selectedView() !== view\" />\n <he-svg-icon\n [name]=\"viewIcon[view]\"\n aria-hidden=\"true\"\n [class.is-hidden-tablet]=\"selectedView() === view\" />\n <span class=\"is-hidden-mobile\">{{ view }}</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #selectSite>\n @if (sites().length > 1) {\n <div class=\"field is-horizontal is-mb-0\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary\" for=\"selectSite\">Site</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"selectIndex($event)\" if=\"selectSite\">\n @for (value of sites(); track nodeVersionKey(value); let siteIndex = $index) {\n <option [value]=\"siteIndex\">{{ siteIndex + 1 }}. {{ defaultLabel(value) }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n</ng-template>\n\n<ng-template #emptyValue>\n <span>-</span>\n</ng-template>\n\n<ng-template #details let-node=\"site\" let-data=\"data\">\n <p>\n <b>{{ node.name }}</b>\n </p>\n <he-node-value-details\n class=\"is-overflow-visible\"\n [data]=\"data\"\n [dataState]=\"dataState()\"\n [nodeType]=\"node['@type']\"\n [dataKey]=\"nodeKey()\"\n [aggregated]=\"node.aggregated\" />\n</ng-template>\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: HESvgIconComponent, selector: "he-svg-icon", inputs: ["name", "size", "animation"] }, { kind: "component", type: SearchExtendComponent, selector: "he-search-extend", inputs: ["value", "disabled", "placeholder", "class", "collapsedClass"], outputs: ["valueChange", "searchText"] }, { kind: "component", type: DataTableComponent, selector: "he-data-table", inputs: ["minHeight", "maxHeight", "small"] }, { kind: "component", type: NodeLinkComponent, selector: "he-node-link", inputs: ["node", "dataState", "showExternalLink", "linkClass"] }, { kind: "component", type: TermsUnitsDescriptionComponent, selector: "he-terms-units-description", inputs: ["term", "iconTemplate"] }, { kind: "directive", type: NgbPopover, selector: "[ngbPopover]", inputs: ["animation", "autoClose", "ngbPopover", "popoverTitle", "placement", "popperOptions", "triggers", "positionTarget", "container", "disablePopover", "popoverClass", "popoverContext", "openDelay", "closeDelay"], outputs: ["shown", "hidden"], exportAs: ["ngbPopover"] }, { kind: "component", type: BlankNodeStateComponent, selector: "he-blank-node-state", inputs: ["dataState", "nodeType", "dataKey", "key", "node", "state", "linkClass"] }, { kind: "component", type: BlankNodeStateNoticeComponent, selector: "he-blank-node-state-notice", inputs: ["dataState", "showDeleted"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: NodeLogsModelsComponent, selector: "he-node-logs-models", inputs: ["node", "nodeKey", "originalValues", "recalculatedValues", "terms", "filterTermTypes", "filterTermTypesLabel", "logsKey", "noDataMessage", "cycle", "jlogParentKey", "jlogParentIndex"] }, { kind: "component", type: NodeValueDetailsComponent, selector: "he-node-value-details", inputs: ["data", "nodeType", "dataState", "dataKey", "aggregated"] }, { kind: "component", type: SitesManagementChartComponent, selector: "he-sites-management-chart", inputs: ["site", "cycles"] }, { kind: "pipe", type: CompoundPipe, name: "compound" }, { kind: "pipe", type: DefaultPipe, name: "default" }, { kind: "pipe", type: EllipsisPipe, name: "ellipsis" }, { kind: "pipe", type: PrecisionPipe, name: "precision" }, { kind: "pipe", type: CapitalizePipe, name: "capitalize" }, { kind: "pipe", type: PluralizePipe, name: "pluralize" }] }); }
16503
16538
  }
16504
16539
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SitesNodesComponent, decorators: [{
16505
16540
  type: Component$1,
@@ -16523,7 +16558,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
16523
16558
  CapitalizePipe,
16524
16559
  PluralizePipe,
16525
16560
  SitesManagementChartComponent
16526
- ], template: "@if (isGroupNode()) {\n <div class=\"tabs is-mb-1 | group-nodes-tabs\">\n <ul>\n @for (value of groupNodeValues(); track value) {\n <li [class.is-active]=\"selectedGroup() === value\">\n <a (click)=\"selectedGroup.set(value)\">\n <span class=\"is-capitalized is-pr-1\">{{ nodeKeyGroup() | pluralize: 1 }}:</span>\n <span>{{ groupNodeDisplayNames()[value] || value }}</span>\n </a>\n </li>\n }\n </ul>\n </div>\n}\n\n@if (isNodeKeyAllowed()) {\n @switch (selectedView()) {\n @case (View.table) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (hasData()) {\n <he-data-table class=\"is-mt-3 is-bordered\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n <tr class=\"has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n @for (node of data(); track node.value.term.name) {\n @if (node.value.visible) {\n <th [attr.title]=\"node.value.term.name\">\n <he-node-link [node]=\"node.value.term\">\n <span\n [innerHtml]=\"node.value.term.name | ellipsis: 30 | compound: node.value.term.termType\"></span>\n </he-node-link>\n </th>\n }\n }\n </tr>\n <tr class=\"is-italic has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n @for (node of data(); track node.value.term.name) {\n @if (node.value.visible) {\n <th [attr.title]=\"node.value.term.units\">\n <span [innerHtml]=\"node.value.term.units | compound\"></span>\n <he-terms-units-description class=\"is-inline-block is-ml-2\" [term]=\"node.value.term\" />\n </th>\n }\n }\n </tr>\n </thead>\n <tbody>\n @for (site of sites(); track site['@id']; let siteIndex = $index) {\n <tr [class.is-suggested]=\"$any(site).suggested\">\n <td class=\"width-auto has-border-right\" [attr.title]=\"defaultLabel(site)\">\n <he-node-link [node]=\"site\">\n <span class=\"has-text-ellipsis is-ellipsis-3\">\n @if ($any(site).suggested) {\n <he-svg-icon name=\"compare\" />\n } @else {\n <span>{{ siteIndex + 1 }}.</span>\n }\n <span class=\"is-pl-1\">{{ defaultLabel(site) }}</span>\n </span>\n </he-node-link>\n </td>\n @for (node of data(); track node.value.term.name) {\n @if (node.value.visible) {\n @let siteData = node.value.values[site['@id']];\n <td class=\"is-nowrap\">\n @if (siteData) {\n <span\n class=\"trigger-popover\"\n [ngbPopover]=\"details\"\n autoClose=\"outside\"\n popoverClass=\"is-narrow is-overflow-visible\"\n placement=\"left bottom auto\"\n container=\"body\"\n [popoverContext]=\"{ data: siteData, site }\">\n <span pointer>\n {{ siteData.propertyValue | precision: 3 | default: '-' }}\n </span>\n <he-blank-node-state\n class=\"ml-1\"\n [dataState]=\"dataState()\"\n [node]=\"siteData.node\"\n key=\"value\" />\n </span>\n }\n @if (isMeasurement() && !siteData) {\n <span>\n <span>-</span>\n @if (siteTooBig(site)) {\n <sup class=\"pl-1\">(1)</sup>\n }\n </span>\n }\n </td>\n }\n }\n </tr>\n }\n </tbody>\n </table>\n </he-data-table>\n <div class=\"is-flex is-align-items-center is-flex-wrap-wrap is-justify-content-space-between is-mt-2\">\n <he-blank-node-state-notice [dataState]=\"dataState()\" />\n <div class=\"is-flex is-flex-wrap-wrap is-gap-8\">\n <div class=\"field is-relative is-mb-0\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded\"\n [id]=\"componentId() + 'hideZeroValues'\"\n name=\"hideZeroValues\"\n [(ngModel)]=\"hideZeroValues\" />\n <label [for]=\"componentId() + 'hideZeroValues'\">\n <span>\n Hide\n <b>0</b>\n values\n </span>\n </label>\n </div>\n @if (sites().length > 1) {\n <div class=\"field is-relative is-mb-0\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded\"\n [id]=\"componentId() + 'hideIdenticalValues'\"\n name=\"hideIdenticalValues\"\n [(ngModel)]=\"hideIdenticalValues\" />\n <label [for]=\"componentId() + 'hideIdenticalValues'\">\n <span>Hide identical values</span>\n </label>\n </div>\n }\n </div>\n </div>\n @if (showAreaTooBig()) {\n <p class=\"is-size-7 is-italic\">\n (1) This region is >{{ maxAreaSize }}km2 and is too large to reliably gap fill Measurements.\n </p>\n }\n } @else {\n <div class=\"is-pt-3 has-text-centered\">\n <span>No data available</span>\n @if (filterTerm()) {\n <span class=\"is-pl-1\">matching your search criteria</span>\n }\n <span>.</span>\n @if (showSwitchToRecalculated()) {\n <span>\n Switch to\n <code>recalculated</code>\n version.\n </span>\n }\n </div>\n }\n }\n @case (View.chart) {\n @if (nodeKey() === BlankNodesKey.management) {\n @if (selectedNode()) {\n <he-sites-management-chart [site]=\"selectedNode()\" [cycles]=\"cycles()\">\n <ng-container *ngTemplateOutlet=\"selectView\" />\n </he-sites-management-chart>\n }\n }\n }\n @case (View.logs) {\n @if (selectedNode()) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n <he-node-logs-models\n [node]=\"selectedNode()\"\n [nodeKey]=\"nodeKey()\"\n [originalValues]=\"selectedOriginalValues()\"\n [recalculatedValues]=\"selectedRecalculatedValues()\"\n [filterTermTypes]=\"filterTermTypes()\"\n [filterTermTypesLabel]=\"nodeKey() | capitalize\" />\n }\n }\n }\n}\n\n<ng-template #selectView>\n <div class=\"is-flex is-gap-8 is-align-items-center is-justify-content-space-between\">\n <div class=\"is-flex is-gap-8 is-align-items-center\">\n @if (selectedView() === View.table) {\n @if (hasData()) {\n <button class=\"button is-small is-ghost is-p-2\" (click)=\"showDownload()\">\n <he-svg-icon name=\"download\" />\n </button>\n }\n\n <he-search-extend\n class=\"is-secondary\"\n collapsedClass=\"is-p-2\"\n placeholder=\"Filter terms by name\"\n (searchText)=\"filterTerm.set($event)\" />\n } @else if (showSelectSite()) {\n <ng-container *ngTemplateOutlet=\"selectSite\" />\n }\n </div>\n\n @if (views()?.length > 1) {\n <div class=\"field has-addons button-segments\">\n @for (view of views(); track view) {\n <div class=\"control\">\n <button\n class=\"button is-small\"\n [class.is-selected]=\"selectedView() === view\"\n (click)=\"selectedView.set(view)\">\n <he-svg-icon\n name=\"checkmark\"\n aria-hidden=\"true\"\n class=\"is-hidden-mobile\"\n [class.is-hidden-tablet]=\"selectedView() !== view\" />\n <he-svg-icon\n [name]=\"viewIcon[view]\"\n aria-hidden=\"true\"\n [class.is-hidden-tablet]=\"selectedView() === view\" />\n <span class=\"is-hidden-mobile\">{{ view }}</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #selectSite>\n @if (sites().length > 1) {\n <div class=\"field is-horizontal is-mb-0\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary\" for=\"selectSite\">Site</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"selectIndex($event)\" if=\"selectSite\">\n @for (value of sites(); track value; let siteIndex = $index) {\n <option [value]=\"siteIndex\">{{ siteIndex + 1 }}. {{ defaultLabel(value) }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n</ng-template>\n\n<ng-template #emptyValue>\n <span>-</span>\n</ng-template>\n\n<ng-template #details let-node=\"site\" let-data=\"data\">\n <p>\n <b>{{ node.name }}</b>\n </p>\n <he-node-value-details\n class=\"is-overflow-visible\"\n [data]=\"data\"\n [dataState]=\"dataState()\"\n [nodeType]=\"node['@type']\"\n [dataKey]=\"nodeKey()\"\n [aggregated]=\"node.aggregated\" />\n</ng-template>\n", styles: [":host{display:block}\n"] }]
16561
+ ], template: "@if (isGroupNode()) {\n <div class=\"tabs is-mb-1 | group-nodes-tabs\">\n <ul>\n @for (value of groupNodeValues(); track value) {\n <li [class.is-active]=\"selectedGroup() === value\">\n <a (click)=\"selectedGroup.set(value)\">\n <span class=\"is-capitalized is-pr-1\">{{ nodeKeyGroup() | pluralize: 1 }}:</span>\n <span>{{ groupNodeDisplayNames()[value] || value }}</span>\n </a>\n </li>\n }\n </ul>\n </div>\n}\n\n@if (isNodeKeyAllowed()) {\n @switch (selectedView()) {\n @case (View.table) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (hasData()) {\n <he-data-table class=\"is-mt-3 is-bordered\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n <tr class=\"has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n @for (node of data(); track node.value.term.name) {\n @if (node.value.visible) {\n <th [attr.title]=\"node.value.term.name\">\n <he-node-link [node]=\"node.value.term\">\n <span\n [innerHtml]=\"node.value.term.name | ellipsis: 30 | compound: node.value.term.termType\"></span>\n </he-node-link>\n </th>\n }\n }\n </tr>\n <tr class=\"is-italic has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n @for (node of data(); track node.value.term.name) {\n @if (node.value.visible) {\n <th [attr.title]=\"node.value.term.units\">\n <span [innerHtml]=\"node.value.term.units | compound\"></span>\n <he-terms-units-description class=\"is-inline-block is-ml-2\" [term]=\"node.value.term\" />\n </th>\n }\n }\n </tr>\n </thead>\n <tbody>\n @for (site of sites(); track nodeVersionKey(site); let siteIndex = $index) {\n <tr [class.is-suggested]=\"$any(site).suggested\">\n <td class=\"width-auto has-border-right\" [attr.title]=\"defaultLabel(site)\">\n <he-node-link [node]=\"site\">\n <span class=\"has-text-ellipsis is-ellipsis-3\">\n @if ($any(site).suggested) {\n <he-svg-icon name=\"compare\" />\n } @else {\n <span>{{ siteIndex + 1 }}.</span>\n }\n <span class=\"is-pl-1\">{{ defaultLabel(site) }}</span>\n </span>\n </he-node-link>\n </td>\n @for (node of data(); track node.value.term.name) {\n @if (node.value.visible) {\n @let siteData = node.value.values[site['@id']];\n <td class=\"is-nowrap\">\n @if (siteData) {\n <span\n class=\"trigger-popover\"\n [ngbPopover]=\"details\"\n autoClose=\"outside\"\n popoverClass=\"is-narrow is-overflow-visible\"\n placement=\"left bottom auto\"\n container=\"body\"\n [popoverContext]=\"{ data: siteData, site }\">\n <span pointer>\n {{ siteData.propertyValue | precision: 3 | default: '-' }}\n </span>\n <he-blank-node-state\n class=\"ml-1\"\n [dataState]=\"dataState()\"\n [node]=\"siteData.node\"\n key=\"value\" />\n </span>\n }\n @if (isMeasurement() && !siteData) {\n <span>\n <span>-</span>\n @if (siteTooBig(site)) {\n <sup class=\"pl-1\">(1)</sup>\n }\n </span>\n }\n </td>\n }\n }\n </tr>\n }\n </tbody>\n </table>\n </he-data-table>\n <div class=\"is-flex is-align-items-center is-flex-wrap-wrap is-justify-content-space-between is-mt-2\">\n <he-blank-node-state-notice [dataState]=\"dataState()\" />\n <div class=\"is-flex is-flex-wrap-wrap is-gap-8\">\n <div class=\"field is-relative is-mb-0\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded\"\n [id]=\"componentId() + 'hideZeroValues'\"\n name=\"hideZeroValues\"\n [(ngModel)]=\"hideZeroValues\" />\n <label [for]=\"componentId() + 'hideZeroValues'\">\n <span>\n Hide\n <b>0</b>\n values\n </span>\n </label>\n </div>\n @if (sites().length > 1) {\n <div class=\"field is-relative is-mb-0\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded\"\n [id]=\"componentId() + 'hideIdenticalValues'\"\n name=\"hideIdenticalValues\"\n [(ngModel)]=\"hideIdenticalValues\" />\n <label [for]=\"componentId() + 'hideIdenticalValues'\">\n <span>Hide identical values</span>\n </label>\n </div>\n }\n </div>\n </div>\n @if (showAreaTooBig()) {\n <p class=\"is-size-7 is-italic\">\n (1) This region is >{{ maxAreaSize }}km2 and is too large to reliably gap fill Measurements.\n </p>\n }\n } @else {\n <div class=\"is-pt-3 has-text-centered\">\n <span>No data available</span>\n @if (filterTerm()) {\n <span class=\"is-pl-1\">matching your search criteria</span>\n }\n <span>.</span>\n @if (showSwitchToRecalculated()) {\n <span>\n Switch to\n <code>recalculated</code>\n version.\n </span>\n }\n </div>\n }\n }\n @case (View.chart) {\n @if (nodeKey() === BlankNodesKey.management) {\n @if (selectedNode()) {\n <he-sites-management-chart [site]=\"selectedNode()\" [cycles]=\"cycles()\">\n <ng-container *ngTemplateOutlet=\"selectView\" />\n </he-sites-management-chart>\n }\n }\n }\n @case (View.logs) {\n @if (selectedNode()) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n <he-node-logs-models\n [node]=\"selectedNode()\"\n [nodeKey]=\"nodeKey()\"\n [originalValues]=\"selectedOriginalValues()\"\n [recalculatedValues]=\"selectedRecalculatedValues()\"\n [filterTermTypes]=\"filterTermTypes()\"\n [filterTermTypesLabel]=\"nodeKey() | capitalize\" />\n }\n }\n }\n}\n\n<ng-template #selectView>\n <div class=\"is-flex is-gap-8 is-align-items-center is-justify-content-space-between\">\n <div class=\"is-flex is-gap-8 is-align-items-center\">\n @if (selectedView() === View.table) {\n @if (hasData()) {\n <button class=\"button is-small is-ghost is-p-2\" (click)=\"showDownload()\">\n <he-svg-icon name=\"download\" />\n </button>\n }\n\n <he-search-extend\n class=\"is-secondary\"\n collapsedClass=\"is-p-2\"\n placeholder=\"Filter terms by name\"\n (searchText)=\"filterTerm.set($event)\" />\n } @else if (showSelectSite()) {\n <ng-container *ngTemplateOutlet=\"selectSite\" />\n }\n </div>\n\n @if (views()?.length > 1) {\n <div class=\"field has-addons button-segments\">\n @for (view of views(); track view) {\n <div class=\"control\">\n <button\n class=\"button is-small\"\n [class.is-selected]=\"selectedView() === view\"\n (click)=\"selectedView.set(view)\">\n <he-svg-icon\n name=\"checkmark\"\n aria-hidden=\"true\"\n class=\"is-hidden-mobile\"\n [class.is-hidden-tablet]=\"selectedView() !== view\" />\n <he-svg-icon\n [name]=\"viewIcon[view]\"\n aria-hidden=\"true\"\n [class.is-hidden-tablet]=\"selectedView() === view\" />\n <span class=\"is-hidden-mobile\">{{ view }}</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #selectSite>\n @if (sites().length > 1) {\n <div class=\"field is-horizontal is-mb-0\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary\" for=\"selectSite\">Site</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"selectIndex($event)\" if=\"selectSite\">\n @for (value of sites(); track nodeVersionKey(value); let siteIndex = $index) {\n <option [value]=\"siteIndex\">{{ siteIndex + 1 }}. {{ defaultLabel(value) }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n</ng-template>\n\n<ng-template #emptyValue>\n <span>-</span>\n</ng-template>\n\n<ng-template #details let-node=\"site\" let-data=\"data\">\n <p>\n <b>{{ node.name }}</b>\n </p>\n <he-node-value-details\n class=\"is-overflow-visible\"\n [data]=\"data\"\n [dataState]=\"dataState()\"\n [nodeType]=\"node['@type']\"\n [dataKey]=\"nodeKey()\"\n [aggregated]=\"node.aggregated\" />\n</ng-template>\n", styles: [":host{display:block}\n"] }]
16527
16562
  }], ctorParameters: () => [], propDecorators: { dataState: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataState", required: false }] }], nodeKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "nodeKey", required: false }] }], enableChart: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableChart", required: false }] }], nodeKeyGroup: [{ type: i0.Input, args: [{ isSignal: true, alias: "nodeKeyGroup", required: false }] }] } });
16528
16563
 
16529
16564
  class TermsPropertyContentComponent {
@@ -16586,5 +16621,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
16586
16621
  * Generated bundle index. Do not edit.
16587
16622
  */
16588
16623
 
16589
- export { ARRAY_DELIMITER, ApplyPurePipe, BarChartComponent, BibliographiesSearchConfirmComponent, BlankNodeStateComponent, BlankNodeStateNoticeComponent, BlankNodeValueDeltaComponent, CapitalizePipe, ChartComponent, ChartConfigurationDirective, ChartExportButtonComponent, ChartTooltipComponent, ClickOutsideDirective, ClipboardComponent, CollapsibleBoxComponent, CollapsibleBoxStyle, ColorPalette, CompoundDirective, CompoundPipe, ContributionChartComponent, ControlValueAccessor, CycleNodesKeyGroup, CyclesCompletenessComponent, CyclesEmissionsCategoryService, CyclesEmissionsChartComponent, CyclesFunctionalUnitMeasureComponent, CyclesMetadataComponent, CyclesNodesComponent, CyclesNodesTimelineComponent, CyclesResultComponent, DataTableComponent, DefaultPipe, DeltaColour, DistributionChartComponent, DrawerContainerComponent, DurationPipe, EllipsisPipe, EngineModelsLinkComponent, EngineModelsLookupInfoComponent, EngineModelsStageComponent, EngineModelsStageDeepComponent, EngineModelsStageDeepService, EngineModelsVersionInfoComponent, EngineModelsVersionLinkComponent, EngineOrchestratorEditComponent, EngineRequirementsFormComponent, FileSizePipe, FileUploadErrorKeys, FilesErrorSummaryComponent, FilesFormComponent, FilesFormEditableComponent, FilesUploadErrorsComponent, FilterAccordionComponent, GUIDE_ENABLED, GetPipe, GlossaryMigrationFormat, GuideOverlayComponent, HESvgIconComponent, HE_API_BASE_URL, HE_CALCULATIONS_BASE_URL, HE_MAP_LOADED, HeAuthService, HeCommonService, HeEngineService, HeGlossaryService, HeMendeleyService, HeNodeCsvService, HeNodeService, HeNodeStoreService, HeSchemaService, HeSearchService, HeToastService, HorizontalBarChartComponent, HorizontalButtonsGroupComponent, ImpactAssessmentsGraphComponent, ImpactAssessmentsIndicatorBreakdownChartComponent, ImpactAssessmentsIndicatorsChartComponent, ImpactAssessmentsProductsComponent, IsArrayPipe, IsObjectPipe, IssueConfirmComponent, KatexDirective, KeyToLabelPipe, Level, LineChartComponent, LinkKeyValueComponent, LogStatus, LongPressDirective, MAX_RESULTS, MapsDrawingComponent, MapsDrawingConfirmComponent, MaxPipe, MeanPipe, MedianPipe, MendeleySearchResult, MinPipe, MobileShellComponent, NavigationMenuComponent, NoExtPipe, NodeAggregatedComponent, NodeAggregatedInfoComponent, NodeAggregatedQualityScoreComponent, NodeCsvExportConfirmComponent, NodeCsvPreviewComponent, NodeCsvSelectHeadersComponent, NodeIconComponent, NodeJLogModelsComponent, NodeJsonldComponent, NodeJsonldSchemaComponent, NodeKeyState, NodeLinkComponent, NodeLogsFileComponent, NodeLogsModelsComponent, NodeLogsTimeComponent, NodeMissingLookupFactorsComponent, NodeQualityScore, NodeRecommendationsComponent, NodeSelectComponent, NodeValueDetailsComponent, PipelineStagesProgressComponent, PluralizePipe, PopoverComponent, PopoverConfirmComponent, PrecisionPipe, RelatedNodeResult, RemoveMarkdownPipe, RepeatPipe, Repository, ResizedDirective, ResizedEvent, ResponsiveService, SchemaInfoComponent, SchemaVersionLinkComponent, SearchExtendComponent, ShelfDialogComponent, ShellComponent, SiteNodesKeyGroup, SitesManagementChartComponent, SitesMapsComponent, SitesNodesComponent, SkeletonTextComponent, SocialTagsComponent, SortByPipe, SortSelectComponent, SumPipe, TagsInputDirective, Template, TermsPropertyContentComponent, TermsSubClassOfContentComponent, TermsUnitsDescriptionComponent, ThousandSuffixesPipe, ThousandsPipe, TimesPipe, ToastComponent, UncapitalizePipe, addPolygonToFeature, afterBarDrawPlugin, allCountriesQuery, allGroups, allOptions, availableProperties, axisHoverPlugin, backgroundHoverPlugin, baseApiUrl, baseUrl, bottom, buildSummary, bytesSize, calculateCycleDuration, calculateCycleDurationEnabled, calculateCycleStartDate, calculateCycleStartDateEnabled, capitalize, changelogUrl, clustererImage, code, colorToRgba, compoundToHtml, computeKeys, computeTerms, contactUsEmail, contactUsLink, convertToSvg, coordinatesToPoint, copyObject, countGroupVisibleNodes, countriesQuery, createMarker, cropsQuery, d3ellipse, d3wrap, dataPathLabel, dataPathToKey, dataVersionHeader, dataVersionHeaderKey, defaultFeature, defaultLabel, defaultSuggestionType, defaultSvgIconSize, defaultTicksFont, definitionToSchemaType, distinctUntilChangedDeep, downloadFile, downloadPng, downloadSvg, ellipsis, engineGitBaseUrl, engineGitUrl, errorText, evaluateSuccess, exportAsSVG, exportFormats, externalLink, externalNodeLink, fillColor, fillStyle, filterBlankNode$1 as filterBlankNode, filterParams, findConfigModels, findMatchingModel, findModels, findNodeModel, findOrchestratorModel, findProperty, findPropertyById, flatFilterData, flatFilterNode, formatCustomErrorMessage, formatDate, formatError, formatPropertyError, formatter, getColor, getDatesBetween, gitBranch, gitHome, gitlabRawUrl, glossaryBaseUrl, glossaryLink, groupChanged, groupJLogByField, groupJLogByTerm, groupLogsByTerm, groupNodesByTerm, groupdLogsByKey, grouppedKeys, grouppedValueKeys, groupsLogsByFields, guideModelUrl, guideNamespace, handleAPIError, handleGuideEvent, hasError, hasValidationError, hasWarning, hexToRgba, iconSizes, icons, ignoreKeys$2 as ignoreKeys, increaseScaleLimits, initialFilterState, injectResizeEvent$, inputGroupsTermTypes, isAddPropertyEnabled, isChrome, isDateBetween, isEqual, isExternal, isKeyClosedVisible, isKeyHidden, isMaxStage, isMethodModelAllowed, isNonNodeModelKey, isSchemaIri, isScrolledBelow, isState, isTermTypeAllowed, isValidKey, jLogModelCount, keyToDataPath, levels, listColor, listColorContinuous, listColorWithAlpha, loadMapApi, loadSvgSprite, locationQuery, logToCsv$2 as logToCsv, logValueArray, logsKey, lollipopChartPlugin, lookupUrl, mapFilterData, mapsUrl, markerIcon, markerPie, matchAggregatedQuery, matchAggregatedValidatedQuery, matchBoolPrefixQuery, matchCountry, matchExactQuery, matchGlobalRegion, matchId, matchNameNormalized, matchNestedKey, matchPhrasePrefixQuery, matchPhraseQuery, matchPrimaryProductQuery, matchQuery, matchRegex, matchRegion, matchTermType, matchType, maxAreaSize, measurementValue, mergeDataWithHeaders, methodTierOrder, migrationErrorMessage, migrationsUrl, modelCount, modelKeyParams, modelParams, models, multiMatchQuery, nestedProperty, nestingEnabled, nestingTypeEnabled, noValue, nodeAvailableProperties, nodeById, nodeColours$1 as nodeColours, nodeDataState, nodeDataStates, nodeId, nodeIds, nodeLink, nodeLinkEnabled, nodeLinkTypeEnabled, nodeLogsUrl, nodeQualityScoreColor, nodeQualityScoreLevel, nodeQualityScoreMaxDefault, nodeQualityScoreOrder, nodeSecondaryColours, nodeToAggregationFilename, nodeType, nodeTypeDataState, nodeTypeIcon, nodeTypeIconSchema, nodeUrl, nodeUrlParams, nodeVersion, nodesByState, nodesByType, numberGte, optionsFromGroup, parentKey, parentProperty, parseColor, parseData, parseDataPath, parseLines, parseMessage, parseNewValue, pluralize, pointToCoordinates, polygonBounds, polygonToCoordinates, polygonToMap, polygonsFromFeature, populateWithTrackIdsFilterData, postGuideEvent, primaryProduct, productsQuery, propertyError, propertyId, recursiveProperties, refToSchemaType, refreshPropertyKeys, regionsQuery, registerChart, repeat, reportIssueLink, reportIssueUrl, safeJSONParse, safeJSONStringify, schemaBaseUrl, schemaDataBaseUrl, schemaLink, schemaRequiredProperties, schemaTypeToDefaultValue, scrollToEl, scrollTop, searchFilterData, searchableTypes, siblingProperty, simplifyContributions, singleProperty, siteTooBig, siteTypeToColor, siteTypeToIcon, sortProperties, sortedDates, strokeColor, strokeStyle, subValueKeys, suggestMatchQuery, suggestQuery, takeAfterViewInit, termLocation, termLocationName, termProperties, termTypeLabel, toSnakeCase, toThousands, typeToNewProperty, typeaheadFocus, uncapitalize, uniqueDatesBetween, updateProperties, valueLink, valueToString, valueTypeToDefault, valueValue, waitFor, wildcardQuery };
16624
+ export { ARRAY_DELIMITER, ApplyPurePipe, BarChartComponent, BibliographiesSearchConfirmComponent, BlankNodeStateComponent, BlankNodeStateNoticeComponent, BlankNodeValueDeltaComponent, CapitalizePipe, ChartComponent, ChartConfigurationDirective, ChartExportButtonComponent, ChartTooltipComponent, ClickOutsideDirective, ClipboardComponent, CollapsibleBoxComponent, CollapsibleBoxStyle, ColorPalette, CompoundDirective, CompoundPipe, ContributionChartComponent, ControlValueAccessor, CycleNodesKeyGroup, CyclesCompletenessComponent, CyclesEmissionsCategoryService, CyclesEmissionsChartComponent, CyclesFunctionalUnitMeasureComponent, CyclesMetadataComponent, CyclesNodesComponent, CyclesNodesTimelineComponent, CyclesResultComponent, DataTableComponent, DefaultPipe, DeltaColour, DistributionChartComponent, DrawerContainerComponent, DurationPipe, EllipsisPipe, EngineModelsLinkComponent, EngineModelsLookupInfoComponent, EngineModelsStageComponent, EngineModelsStageDeepComponent, EngineModelsStageDeepService, EngineModelsVersionInfoComponent, EngineModelsVersionLinkComponent, EngineOrchestratorEditComponent, EngineRequirementsFormComponent, FileSizePipe, FileUploadErrorKeys, FilesErrorSummaryComponent, FilesFormComponent, FilesFormEditableComponent, FilesUploadErrorsComponent, FilterAccordionComponent, GUIDE_ENABLED, GetPipe, GlossaryMigrationFormat, GuideOverlayComponent, HESvgIconComponent, HE_API_BASE_URL, HE_CALCULATIONS_BASE_URL, HE_MAP_LOADED, HeAuthService, HeCommonService, HeEngineService, HeGlossaryService, HeMendeleyService, HeNodeCsvService, HeNodeService, HeNodeStoreService, HeSchemaService, HeSearchService, HeToastService, HorizontalBarChartComponent, HorizontalButtonsGroupComponent, ImpactAssessmentsGraphComponent, ImpactAssessmentsIndicatorBreakdownChartComponent, ImpactAssessmentsIndicatorsChartComponent, ImpactAssessmentsProductsComponent, IsArrayPipe, IsObjectPipe, IssueConfirmComponent, KatexDirective, KeyToLabelPipe, Level, LineChartComponent, LinkKeyValueComponent, LogStatus, LongPressDirective, MAX_RESULTS, MapsDrawingComponent, MapsDrawingConfirmComponent, MaxPipe, MeanPipe, MedianPipe, MendeleySearchResult, MinPipe, MobileShellComponent, NavigationMenuComponent, NoExtPipe, NodeAggregatedComponent, NodeAggregatedInfoComponent, NodeAggregatedQualityScoreComponent, NodeCsvExportConfirmComponent, NodeCsvPreviewComponent, NodeCsvSelectHeadersComponent, NodeIconComponent, NodeJLogModelsComponent, NodeJsonldComponent, NodeJsonldSchemaComponent, NodeKeyState, NodeLinkComponent, NodeLogsFileComponent, NodeLogsModelsComponent, NodeLogsTimeComponent, NodeMissingLookupFactorsComponent, NodeQualityScore, NodeRecommendationsComponent, NodeSelectComponent, NodeValueDetailsComponent, PipelineStagesProgressComponent, PluralizePipe, PopoverComponent, PopoverConfirmComponent, PrecisionPipe, RelatedNodeResult, RemoveMarkdownPipe, RepeatPipe, Repository, ResizedDirective, ResizedEvent, ResponsiveService, SchemaInfoComponent, SchemaVersionLinkComponent, SearchExtendComponent, ShelfDialogComponent, ShellComponent, SiteNodesKeyGroup, SitesManagementChartComponent, SitesMapsComponent, SitesNodesComponent, SkeletonTextComponent, SocialTagsComponent, SortByPipe, SortSelectComponent, SumPipe, TagsInputDirective, Template, TermsPropertyContentComponent, TermsSubClassOfContentComponent, TermsUnitsDescriptionComponent, ThousandSuffixesPipe, ThousandsPipe, TimesPipe, ToastComponent, UncapitalizePipe, addPolygonToFeature, afterBarDrawPlugin, allCountriesQuery, allGroups, allOptions, availableProperties, axisHoverPlugin, backgroundHoverPlugin, baseApiUrl, baseUrl, bottom, buildSummary, bytesSize, calculateCycleDuration, calculateCycleDurationEnabled, calculateCycleStartDate, calculateCycleStartDateEnabled, capitalize, changelogUrl, clustererImage, code, colorToRgba, compoundToHtml, computeKeys, computeTerms, contactUsEmail, contactUsLink, convertToSvg, coordinatesToPoint, copyObject, countGroupVisibleNodes, countriesQuery, createMarker, cropsQuery, d3ellipse, d3wrap, dataPathLabel, dataPathToKey, dataVersionHeader, dataVersionHeaderKey, defaultFeature, defaultLabel, defaultSuggestionType, defaultSvgIconSize, defaultTicksFont, definitionToSchemaType, distinctUntilChangedDeep, downloadFile, downloadPng, downloadSvg, ellipsis, engineGitBaseUrl, engineGitUrl, errorText, evaluateSuccess, exportAsSVG, exportFormats, externalLink, externalNodeLink, fillColor, fillStyle, filterBlankNode$1 as filterBlankNode, filterParams, findConfigModels, findMatchingModel, findModels, findNodeModel, findOrchestratorModel, findProperty, findPropertyById, flatFilterData, flatFilterNode, formatCustomErrorMessage, formatDate, formatError, formatPropertyError, formatter, getColor, getDatesBetween, gitBranch, gitHome, gitlabRawUrl, glossaryBaseUrl, glossaryLink, groupChanged, groupJLogByField, groupJLogByTerm, groupLogsByTerm, groupNodesByTerm, groupdLogsByKey, grouppedKeys, grouppedValueKeys, groupsLogsByFields, guideModelUrl, guideNamespace, handleAPIError, handleGuideEvent, hasError, hasValidationError, hasWarning, hexToRgba, iconSizes, icons, ignoreKeys$2 as ignoreKeys, increaseScaleLimits, initialFilterState, injectResizeEvent$, inputGroupsTermTypes, isAddPropertyEnabled, isChrome, isDateBetween, isEqual, isExternal, isKeyClosedVisible, isKeyHidden, isMaxStage, isMethodModelAllowed, isNonNodeModelKey, isSchemaIri, isScrolledBelow, isState, isTermTypeAllowed, isValidKey, jLogModelCount, keyToDataPath, levels, listColor, listColorContinuous, listColorWithAlpha, loadMapApi, loadSvgSprite, locationQuery, logToCsv$2 as logToCsv, logValueArray, logsKey, lollipopChartPlugin, lookupUrl, mapFilterData, mapsUrl, markerIcon, markerPie, matchAggregatedQuery, matchAggregatedValidatedQuery, matchBoolPrefixQuery, matchCountry, matchExactQuery, matchGlobalRegion, matchId, matchNameNormalized, matchNestedKey, matchPhrasePrefixQuery, matchPhraseQuery, matchPrimaryProductQuery, matchQuery, matchRegex, matchRegion, matchTermType, matchType, maxAreaSize, measurementValue, mergeDataWithHeaders, methodTierOrder, migrationErrorMessage, migrationsUrl, modelCount, modelKeyParams, modelParams, models, multiMatchQuery, nestedProperty, nestingEnabled, nestingTypeEnabled, noValue, nodeAvailableProperties, nodeById, nodeColours$1 as nodeColours, nodeDataState, nodeDataStates, nodeId, nodeIds, nodeLink, nodeLinkEnabled, nodeLinkTypeEnabled, nodeLogsUrl, nodeQualityScoreColor, nodeQualityScoreLevel, nodeQualityScoreMaxDefault, nodeQualityScoreOrder, nodeSecondaryColours, nodeToAggregationFilename, nodeType, nodeTypeDataState, nodeTypeIcon, nodeTypeIconSchema, nodeUrl, nodeUrlParams, nodeVersion, nodeVersionKey, nodesByState, nodesByType, numberGte, optionsFromGroup, parentKey, parentProperty, parseColor, parseData, parseDataPath, parseLines, parseMessage, parseNewValue, pluralize, pointToCoordinates, polygonBounds, polygonToCoordinates, polygonToMap, polygonsFromFeature, populateWithTrackIdsFilterData, postGuideEvent, primaryProduct, productsQuery, propertyError, propertyId, recursiveProperties, refToSchemaType, refreshPropertyKeys, regionsQuery, registerChart, repeat, reportIssueLink, reportIssueUrl, safeJSONParse, safeJSONStringify, schemaBaseUrl, schemaDataBaseUrl, schemaLink, schemaRequiredProperties, schemaTypeToDefaultValue, scrollToEl, scrollTop, searchFilterData, searchableTypes, siblingProperty, simplifyContributions, singleProperty, siteTooBig, siteTypeToColor, siteTypeToIcon, sortProperties, sortedDates, strokeColor, strokeStyle, subValueKeys, suggestMatchQuery, suggestQuery, takeAfterViewInit, termLocation, termLocationName, termProperties, termTypeLabel, toSnakeCase, toThousands, typeToNewProperty, typeaheadFocus, uncapitalize, uniqueDatesBetween, updateProperties, valueLink, valueToString, valueTypeToDefault, valueValue, waitFor, wildcardQuery };
16590
16625
  //# sourceMappingURL=hestia-earth-ui-components.mjs.map