@hestia-earth/ui-components 0.43.33 → 0.43.35

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.
@@ -813,6 +813,7 @@ const getSumGroup = (id) => sumGroups.map(lookup => lookup[id]).find(group => !!
813
813
 
814
814
  const maxAreaSize = 5000;
815
815
  const siteTooBig = ({ area }) => area && area / 100 > maxAreaSize;
816
+ const infrastructureFunctionalArea = (site, infrastructure) => site?.area ?? infrastructure?.functionalArea;
816
817
  const hasMultipleValues = (values) => (values || []).length > 1;
817
818
  const weighedAverage = ({ value, depthLower, depthUpper }) => value.reduce((prev, curr, index) => prev + curr * ((depthLower[index] || 0) - (depthUpper[index] || 0)), 0) /
818
819
  value.reduce((prev, _curr, index) => prev + ((depthLower[index] || 0) - (depthUpper[index] || 0)), 0);
@@ -7334,16 +7335,16 @@ const groupLog = (group, { logger, term, model, key, should_run, should_merge, r
7334
7335
  };
7335
7336
  const groupLogSubValue = (group, log, key) => {
7336
7337
  const id = log[key];
7337
- const data = groupLog(group[id] || {}, log);
7338
- group[id] = data;
7339
- if (subValueKeys.includes(key)) {
7340
- // add value to the same term/model on parent group
7341
- Object.entries(group[id]).map(([term, models]) => Object.keys(models).map(model => {
7342
- if (typeof group?.[term]?.[model] === 'object') {
7343
- group[term][model][key] = unique([...(group[term][model][key] || []), id]);
7344
- }
7345
- }));
7346
- }
7338
+ group[id] = groupLog(group[id] || {}, log);
7339
+ return group;
7340
+ };
7341
+ // add each subValue to the same term/model on the parent group
7342
+ const linkSubValues = (group, subValues) => {
7343
+ subValues.forEach(([key, id]) => Object.entries(group[id]).forEach(([term, models]) => Object.keys(models).forEach(model => {
7344
+ if (typeof group?.[term]?.[model] === 'object') {
7345
+ group[term][model][key] = unique([...(group[term][model][key] || []), id]);
7346
+ }
7347
+ })));
7347
7348
  return group;
7348
7349
  };
7349
7350
  const csvValue = (value) => (value || '').replace('[', '').replace(']', '');
@@ -7353,50 +7354,64 @@ const parseLogMessage = (message) => {
7353
7354
  // Split on a comma (and optional space) ONLY if it's followed by "key="
7354
7355
  // \w+ matches alphanumeric characters and underscores (standard log keys)
7355
7356
  const pairs = data.message.split(/,\s*(?=\w+=)/);
7356
- return pairs.reduce((prev, parts) => {
7357
- // Use indexOf instead of split('=') just in case your values ever contain an '='
7358
- const firstEqualsIndex = parts.indexOf('=');
7359
- if (firstEqualsIndex === -1)
7360
- return prev;
7361
- const key = parts.substring(0, firstEqualsIndex).trim();
7362
- const value = parts.substring(firstEqualsIndex + 1).trim();
7363
- const val = csvValue(value);
7364
- return {
7365
- ...prev,
7366
- ...(key && val ? { [key]: val } : {})
7367
- };
7368
- }, { logger: data.logger });
7357
+ return Object.fromEntries([
7358
+ ['logger', data.logger],
7359
+ ...pairs
7360
+ // Use indexOf instead of split('=') just in case your values ever contain an '='
7361
+ .map((parts) => [parts, parts.indexOf('=')])
7362
+ .filter(([, index]) => index !== -1)
7363
+ .map(([parts, index]) => [parts.substring(0, index).trim(), csvValue(parts.substring(index + 1).trim())])
7364
+ .filter(([key, value]) => key && value)
7365
+ ]);
7369
7366
  }
7370
7367
  catch {
7371
7368
  // make sure it works even if one log is malformed
7372
7369
  return {};
7373
7370
  }
7374
7371
  };
7375
- const groupLogsByModel = (data = '', groupBySubValue = false, groupByAnimal = false) => data
7376
- .trim()
7377
- .split('\n')
7378
- .map(parseLogMessage)
7379
- .filter(v => [hasValue(v?.model), ['term', 'key', 'animalId'].some(k => hasValue(v?.[k]))].every(Boolean))
7380
- .reduce((group, log) => {
7381
- const subValue = subValueKeys.find(v => !!log[v] && log[v] != noValue);
7382
- return subValue && groupBySubValue && !log.cycle
7383
- ? groupLogSubValue(group, log, subValue)
7384
- : groupLog(group, log, groupByAnimal);
7385
- }, {});
7372
+ const subValueOf = (log, groupBySubValue) => {
7373
+ const key = groupBySubValue && !log.cycle ? subValueKeys.find(v => !!log[v] && log[v] != noValue) : undefined;
7374
+ return key ? [key, log[key]] : undefined;
7375
+ };
7376
+ const groupLogsByModel = (data = '', groupBySubValue = false, groupByAnimal = false) => {
7377
+ const logs = data
7378
+ .trim()
7379
+ .split('\n')
7380
+ .map(parseLogMessage)
7381
+ .filter(v => [hasValue(v?.model), ['term', 'key', 'animalId'].some(k => hasValue(v?.[k]))].every(Boolean));
7382
+ const subValues = logs.map(log => subValueOf(log, groupBySubValue));
7383
+ const group = logs.reduce((prev, log, index) => subValues[index] ? groupLogSubValue(prev, log, subValues[index][0]) : groupLog(prev, log, groupByAnimal), {});
7384
+ const uniqueSubValues = [...new Map(subValues.filter(Boolean).map(v => [v.join('.'), v])).values()];
7385
+ return linkSubValues(group, uniqueSubValues);
7386
+ };
7386
7387
  const logNodeFor = (node) => ({
7387
7388
  '@type': node['@type'],
7388
7389
  '@id': node['@id'],
7389
7390
  dataState: node.aggregated && node['@type'] !== NodeType.ImpactAssessment ? DataState.original : DataState.recalculated,
7390
7391
  dataVersion: node.dataVersion
7391
7392
  });
7393
+ const logsCacheSize = 3;
7394
+ const logsCacheKey = ({ '@type': type, '@id': id, dataState, dataVersion }, groupByAnimal) => [type, id, dataState, dataVersion, groupByAnimal].join('/');
7395
+ /**
7396
+ * Store `value` as the most recent entry, dropping the oldest ones beyond `size`.
7397
+ */
7398
+ const lruSet = (cache, key, value, size) => new Map([...[...cache].filter(([k]) => k !== key), [key, value]].slice(-size));
7392
7399
  class NodeLogsModelsService {
7393
7400
  constructor() {
7394
7401
  this.nodeService = inject(HeNodeService);
7402
+ // parsing a large text log takes seconds, so keep the last few parsed logs for components showing the same node
7403
+ this.logsCache = new Map();
7395
7404
  }
7396
7405
  getNodeLogs$(node, groupByAnimal = false) {
7397
- return this.nodeService
7398
- .getLog$(logNodeFor(node))
7399
- .pipe(map(logs => logs ? groupLogsByModel(logs, node['@type'] === NodeType.Cycle, groupByAnimal) : {}));
7406
+ const key = logsCacheKey(logNodeFor(node), groupByAnimal);
7407
+ const logs$ = this.logsCache.get(key) ?? this.fetchNodeLogs$(node, groupByAnimal, key);
7408
+ this.logsCache = lruSet(this.logsCache, key, logs$, logsCacheSize);
7409
+ return logs$;
7410
+ }
7411
+ fetchNodeLogs$(node, groupByAnimal, key) {
7412
+ return this.nodeService.getLog$(logNodeFor(node)).pipe(map(logs => logs ? groupLogsByModel(logs, node['@type'] === NodeType.Cycle, groupByAnimal) : {}),
7413
+ // a failed request also ends up empty: do not keep it, so the next component retries
7414
+ tap(logs => isEmpty(logs) && this.logsCache.delete(key)), shareReplay(1));
7400
7415
  }
7401
7416
  /**
7402
7417
  * Fetch the new `.jlog` (JSON) recalculation logs, following the representation of the node.
@@ -8821,7 +8836,7 @@ const identityDisplay = (identity, value) => {
8821
8836
  return { segments: orderedSegments, scalars: buildIdentityScalars(scalars) };
8822
8837
  };
8823
8838
  // the raw blank node value used to derive the fallback identity (logs/`failed` rows have no value)
8824
- const rowRawValue = (row) => row.recalculated[0] || row.original[0] || {};
8839
+ const rowRawValue = (row) => row.recalculated[0] || row.original[0] || row.failedValue || {};
8825
8840
  const identityRow = (row) => ({ identity: row.identity, raw: rowRawValue(row) });
8826
8841
  // top-level fields skipped when looking for a fallback identity: the group key (`term`), JSON-LD
8827
8842
  // metadata (`@type`/`@id`), change-tracking (`added`/`updated`/`removed` and their `Version` siblings),
@@ -9061,11 +9076,14 @@ const selectValueLog = (logs, valueModelId, isValueLog, isRecalculated) => {
9061
9076
  // (`should_run: true`) over one that was skipped (the value already existed), so we lock onto the
9062
9077
  // orchestrator that produced the value rather than a skipped sibling that would show the row as failed
9063
9078
  const byModel = logs.filter((log) => log?.model === valueModelId && isValueLog(log));
9079
+ // another model's run that did not run cannot have set the value: it is a log placed on the wrong blank
9080
+ // node (e.g. a `seed_resourceUse` failure that older engine versions placed on every Indicator of its term)
9081
+ const mayHaveSetValue = (log) => isValueLog(log) && log?.should_run !== false;
9064
9082
  return (byModel.find((log) => log?.should_run === true) ||
9065
9083
  byModel[0] ||
9066
9084
  (isRecalculated
9067
- ? logs.find((log) => isValueLog(log) && log?.should_run === true) ||
9068
- logs.find((log) => isValueLog(log) && log?.orchestrator?.should_run)
9085
+ ? logs.find((log) => mayHaveSetValue(log) && log?.should_run === true) ||
9086
+ logs.find((log) => mayHaveSetValue(log) && log?.orchestrator?.should_run)
9069
9087
  : undefined));
9070
9088
  };
9071
9089
  // model ids in display order: config models first, then any logged models, with "not relevant" models
@@ -9450,6 +9468,119 @@ const buildParallelSiblingRow = (log, term, index, context) => {
9450
9468
  isOpen: false
9451
9469
  };
9452
9470
  };
9471
+ const longestId = (text, ids) => ids
9472
+ .filter(id => text === id || text.startsWith(`${id}-`))
9473
+ .reduce((longest, id) => (id.length > (longest?.length ?? 0) ? id : longest), undefined);
9474
+ const fieldIds = (termsByField, field) => [
9475
+ ...(termsByField[field]?.keys() ?? [])
9476
+ ];
9477
+ const termTypesOf = (terms) => new Set([...(terms?.values() ?? [])].map(term => term.termType).filter(Boolean));
9478
+ // an id can sit in several fields across the node (e.g. a pesticide is the `key` of a pesticide emission
9479
+ // and the `inputs` of a background one). Preferred, in order: the field the term's own blank nodes hold
9480
+ // it in, one where they hold terms of its type, any field they use, then the first match
9481
+ const matchFailedKeyField = (text, fields, { termsByField, ownTermsByField }) => {
9482
+ const matches = fields
9483
+ .map((field, index) => ({ field, index, id: longestId(text, fieldIds(termsByField, field)) }))
9484
+ .filter(({ id }) => !!id)
9485
+ .map(match => ({ ...match, termType: termsByField[match.field].get(match.id)?.termType }));
9486
+ return (matches.find(({ field, id }) => ownTermsByField[field]?.has(id)) ??
9487
+ matches.find(({ field, termType }) => termTypesOf(ownTermsByField[field]).has(termType)) ??
9488
+ matches.find(({ field }) => ownTermsByField[field]?.size) ??
9489
+ matches[0]);
9490
+ };
9491
+ const fieldTermTypes = ({ termsByField }, field) => termTypesOf(termsByField[field]);
9492
+ // the field of an id no other blank node carries: the first one holding terms of the same type (e.g. a
9493
+ // `model` for `methodModel`), otherwise the first list field left (e.g. `inputs`)
9494
+ const unknownIdFieldIndex = (term, fields, context) => {
9495
+ const byTermType = term?.termType ? fields.findIndex(field => fieldTermTypes(context, field).has(term.termType)) : -1;
9496
+ return byTermType === -1 ? fields.findIndex(field => context.arrayFields.has(field)) : byTermType;
9497
+ };
9498
+ // an id no other blank node carries (e.g. the `seed` Input of a removed Indicator) runs up to the next
9499
+ // known id, and is resolved with `getTerm`
9500
+ const matchUnknownId = (text, fields, context) => {
9501
+ const head = [...text.matchAll(/-/g)]
9502
+ .map(({ index: position }) => text.slice(0, position))
9503
+ .find(value => !!matchFailedKeyField(text.slice(value.length + 1), fields, context));
9504
+ const id = head ?? text;
9505
+ const term = context.getTerm(id);
9506
+ const index = unknownIdFieldIndex(term, fields, context);
9507
+ return index === -1 ? undefined : { field: fields[index], index, id, term };
9508
+ };
9509
+ const matchFailedKeyId = (text, fields, context) => {
9510
+ const known = matchFailedKeyField(text, fields, context);
9511
+ return known
9512
+ ? { ...known, term: context.termsByField[known.field].get(known.id) }
9513
+ : matchUnknownId(text, fields, context);
9514
+ };
9515
+ const tokenizeFailedKey = (text, fields, context) => {
9516
+ const match = text ? matchFailedKeyId(text, fields, context) : undefined;
9517
+ const nextFields = () => fields.slice(context.arrayFields.has(match.field) ? match.index : match.index + 1);
9518
+ return match
9519
+ ? [
9520
+ { field: match.field, term: match.term },
9521
+ ...tokenizeFailedKey(text.slice(match.id.length + 1), nextFields(), context)
9522
+ ]
9523
+ : text
9524
+ ? [{ text }]
9525
+ : [];
9526
+ };
9527
+ /**
9528
+ * A blank node removed after the models ran keeps its logs under `<field>-failed`, keyed by its
9529
+ * uniqueness ids joined by `-` in the schema `uniquenessFields` order (e.g.
9530
+ * `freshwaterConsumptionInputsProduction-CAS-135410-20-7-hestia`). Ids can contain `-` themselves, so the
9531
+ * key is split on the ids the node's other blank nodes (and the orchestrator config) already carry.
9532
+ */
9533
+ const failedKeyParser = (values, type, nodeType, nodeKey, config) => {
9534
+ const roots = ((nodeType && uniquenessFields[nodeType]?.[nodeKey]) || []).map(field => field.split('.')[0]);
9535
+ const fieldTerms = (fieldValues, root) => new Map(fieldValues.flatMap(value => identityFieldTerms(value, root)).map(term => [term['@id'], term]));
9536
+ const termsByField = Object.fromEntries(roots.map(root => [root, fieldTerms(values, root)]));
9537
+ const ownTermsByField = (termId) => {
9538
+ const termValues = values.filter(value => value?.term?.['@id'] === termId);
9539
+ return Object.fromEntries(roots.map(root => [root, fieldTerms(termValues, root)]));
9540
+ };
9541
+ const arrayFields = new Set(roots.filter(root => values.some(value => Array.isArray(value?.[root]))));
9542
+ const configTermIds = (config?.models || [])
9543
+ .flat(2)
9544
+ .filter((model) => [model.key, pluralize(model.key, 2)].includes(nodeKey))
9545
+ .map((model) => model.value);
9546
+ const termIds = [...new Set([...(termsByField.term?.keys() ?? []), ...configTermIds])].filter(Boolean);
9547
+ const fields = roots.filter(root => root !== 'term');
9548
+ const toValue = (term, tokens) => tokens
9549
+ .filter(token => token.field)
9550
+ .reduce((value, { field, term: fieldTerm }) => ({
9551
+ ...value,
9552
+ [field]: arrayFields.has(field) ? [...(value[field] || []), fieldTerm] : fieldTerm
9553
+ }), { '@type': type, term });
9554
+ const parseTermKey = (key, termId, getTerm) => {
9555
+ const term = termsByField.term?.get(termId) || getTerm(termId);
9556
+ const tokens = tokenizeFailedKey(key.slice(termId.length + 1), fields, {
9557
+ termsByField,
9558
+ ownTermsByField: ownTermsByField(termId),
9559
+ arrayFields,
9560
+ getTerm
9561
+ });
9562
+ return { termId, term, value: toValue(term, tokens), text: tokens.find(token => token.text)?.text };
9563
+ };
9564
+ return (key, getTerm) => {
9565
+ const termId = termIds.includes(key) ? undefined : longestId(key, termIds);
9566
+ return termId ? parseTermKey(key, termId, getTerm) : { termId: key, term: getTerm(key) };
9567
+ };
9568
+ };
9569
+ // older engine-models versions logged the failures of the seed models on every Indicator/Emission of the
9570
+ // term, whatever its input. Those entries name their seed input in `input_details`, so one about another
9571
+ // input than the row's is dropped
9572
+ const seedOrchestrators = ['seed_emissions', 'seed_resourceUse'];
9573
+ const isMisplacedSeedLog = (inputIds) => (log) => seedOrchestrators.includes(log?.orchestrator?.value) &&
9574
+ typeof log?.input_details === 'string' &&
9575
+ !inputIds.some(id => log.input_details.includes(`term_id:${id}_`));
9576
+ const withoutMisplacedSeedLogs = (entry, value) => {
9577
+ const inputIds = (value?.inputs || []).map(input => input?.['@id']).filter(Boolean);
9578
+ const isMisplaced = isMisplacedSeedLog(inputIds);
9579
+ const logs = (entry?.logs || [])
9580
+ .map((step) => (Array.isArray(step) ? step.filter(log => !isMisplaced(log)) : step))
9581
+ .filter((step) => (Array.isArray(step) ? step.length > 0 : !isMisplaced(step)));
9582
+ return inputIds.length && entry?.logs ? { ...entry, logs } : entry;
9583
+ };
9453
9584
  /**
9454
9585
  * Group the `.jlog` logs for one node key into rows, one per term, keeping every blank node distinct.
9455
9586
  *
@@ -9470,6 +9601,7 @@ const groupJLogByTerm = (jlog, nodeKey, recalculatedValues = [], originalValues
9470
9601
  originalValues?.[0]?.['@type'];
9471
9602
  const context = { nodeType, type, nodeKey, config, getTerm };
9472
9603
  const spec = identitySpec(type, nodeType, nodeKey);
9604
+ const parseFailedKey = failedKeyParser([...(recalculatedValues || []), ...(originalValues || [])], type, nodeType, nodeKey, config);
9473
9605
  const matchOriginal = (value) => {
9474
9606
  const key = identityKey(blankNodeIdentity(value, spec));
9475
9607
  return (originalValues || []).find(original => original.term?.['@id'] === value.term?.['@id'] && identityKey(blankNodeIdentity(original, spec)) === key);
@@ -9479,7 +9611,8 @@ const groupJLogByTerm = (jlog, nodeKey, recalculatedValues = [], originalValues
9479
9611
  const valueEntries = (recalculatedValues || [])
9480
9612
  .map((value, index) => ({ value, index, term: value?.term }))
9481
9613
  .filter(({ term }) => !!term?.['@id']);
9482
- const valueNodes = valueEntries.map(({ value, index, term }) => buildBlankNode(keyLogs[index] || {}, value, matchOriginal(value), index, term, false, context));
9614
+ const entryAt = (index, value) => withoutMisplacedSeedLogs(keyLogs[index] || {}, value);
9615
+ const valueNodes = valueEntries.map(({ value, index, term }) => buildBlankNode(entryAt(index, value), value, matchOriginal(value), index, term, false, context));
9483
9616
  // when the recorded `model` is a uniqueness field, models that ran in parallel for a term's value but
9484
9617
  // produced no blank node (e.g. a sibling that failed while another set the value) are shown as their
9485
9618
  // own rows - skipping any model already represented by a value row for that term (avoiding duplicates)
@@ -9493,7 +9626,7 @@ const groupJLogByTerm = (jlog, nodeKey, recalculatedValues = [], originalValues
9493
9626
  });
9494
9627
  let siblingIndex = recalculatedValues?.length ?? 0;
9495
9628
  const siblingNodes = modelIsUniquenessField(spec)
9496
- ? valueEntries.flatMap(({ value, index, term }) => parallelSiblingLogs(keyLogs[index] || {}, blankNodeModelId(value)).flatMap(log => {
9629
+ ? valueEntries.flatMap(({ value, index, term }) => parallelSiblingLogs(entryAt(index, value), blankNodeModelId(value)).flatMap(log => {
9497
9630
  const seen = seenModelsByTerm.get(term['@id']);
9498
9631
  if (seen?.has(log.model))
9499
9632
  return [];
@@ -9504,7 +9637,22 @@ const groupJLogByTerm = (jlog, nodeKey, recalculatedValues = [], originalValues
9504
9637
  const blankNodes = [
9505
9638
  ...valueNodes,
9506
9639
  ...siblingNodes,
9507
- ...Object.entries(failedLogs).map(([termId, entry], i) => buildBlankNode(entry, undefined, undefined, -1 - i, getTerm(termId), true, context))
9640
+ ...Object.entries(failedLogs).flatMap(([key, rawEntry], i) => {
9641
+ const { term, value, text } = parseFailedKey(key, getTerm);
9642
+ const entry = withoutMisplacedSeedLogs(rawEntry, value);
9643
+ const blankNode = buildBlankNode(entry, undefined, undefined, -1 - i, term, true, context);
9644
+ return !entry?.logs?.length
9645
+ ? []
9646
+ : value
9647
+ ? [
9648
+ {
9649
+ ...blankNode,
9650
+ failedValue: value,
9651
+ identity: { ...blankNodeIdentity(value, spec), ...(text ? { [text]: '' } : {}) }
9652
+ }
9653
+ ]
9654
+ : [blankNode];
9655
+ })
9508
9656
  ].filter(Boolean);
9509
9657
  return orderGroups(groupBlankNodesByTerm(blankNodes).map(withCollapsible).map(withRowLabels).map(withDisplayValues), nodeKey);
9510
9658
  };
@@ -9900,7 +10048,7 @@ class NodeJLogModelsComponent {
9900
10048
  return model.methodId;
9901
10049
  }
9902
10050
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NodeJLogModelsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
9903
- 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 @if (row.isFailed) {\n <div class=\"is-flex is-align-items-center is-flex-wrap-wrap is-gap-4\">\n <span class=\"has-text-danger\">failed</span>\n </div>\n } @else {\n <he-blank-node-identity\n [segments]=\"row.identitySegments\"\n [scalars]=\"row.identityScalars\"\n [type]=\"row.type\"\n [fallback]=\"'entry ' + (row.index + 1)\" />\n }\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 .has-formula{cursor:help;border-bottom:1px dotted currentColor}:host .status-legend{border:1px solid #dbe3ea;background:#f5f7f9}::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: BlankNodeIdentityComponent, selector: "he-blank-node-identity", inputs: ["segments", "scalars", "type", "fallback"] }, { 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 }); }
10051
+ 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 @if (row.isFailed) {\n <div class=\"is-flex is-align-items-center is-flex-wrap-wrap is-gap-4\">\n @if (row.identitySegments.length || row.identityScalars.length) {\n <he-blank-node-identity\n [segments]=\"row.identitySegments\"\n [scalars]=\"row.identityScalars\"\n [type]=\"row.type\"\n [fallback]=\"''\" />\n }\n <span class=\"has-text-danger\">failed</span>\n </div>\n } @else {\n <he-blank-node-identity\n [segments]=\"row.identitySegments\"\n [scalars]=\"row.identityScalars\"\n [type]=\"row.type\"\n [fallback]=\"'entry ' + (row.index + 1)\" />\n }\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 .has-formula{cursor:help;border-bottom:1px dotted currentColor}:host .status-legend{border:1px solid #dbe3ea;background:#f5f7f9}::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: BlankNodeIdentityComponent, selector: "he-blank-node-identity", inputs: ["segments", "scalars", "type", "fallback"] }, { 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 }); }
9904
10052
  }
9905
10053
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NodeJLogModelsComponent, decorators: [{
9906
10054
  type: Component$1,
@@ -9924,7 +10072,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
9924
10072
  NodeLogsModelsDetailsComponent,
9925
10073
  BlankNodeIdentityComponent,
9926
10074
  GuideOverlayComponent
9927
- ], 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 @if (row.isFailed) {\n <div class=\"is-flex is-align-items-center is-flex-wrap-wrap is-gap-4\">\n <span class=\"has-text-danger\">failed</span>\n </div>\n } @else {\n <he-blank-node-identity\n [segments]=\"row.identitySegments\"\n [scalars]=\"row.identityScalars\"\n [type]=\"row.type\"\n [fallback]=\"'entry ' + (row.index + 1)\" />\n }\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 .has-formula{cursor:help;border-bottom:1px dotted currentColor}:host .status-legend{border:1px solid #dbe3ea;background:#f5f7f9}::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"] }]
10075
+ ], 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 @if (row.isFailed) {\n <div class=\"is-flex is-align-items-center is-flex-wrap-wrap is-gap-4\">\n @if (row.identitySegments.length || row.identityScalars.length) {\n <he-blank-node-identity\n [segments]=\"row.identitySegments\"\n [scalars]=\"row.identityScalars\"\n [type]=\"row.type\"\n [fallback]=\"''\" />\n }\n <span class=\"has-text-danger\">failed</span>\n </div>\n } @else {\n <he-blank-node-identity\n [segments]=\"row.identitySegments\"\n [scalars]=\"row.identityScalars\"\n [type]=\"row.type\"\n [fallback]=\"'entry ' + (row.index + 1)\" />\n }\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 .has-formula{cursor:help;border-bottom:1px dotted currentColor}:host .status-legend{border:1px solid #dbe3ea;background:#f5f7f9}::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"] }]
9928
10076
  }], 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 }] }] } });
9929
10077
 
9930
10078
  const groupTerms = (terms) => terms.reduce((prev, curr) => ({ ...prev, [curr['@id']]: curr }), {});
@@ -15988,6 +16136,7 @@ const siteGroupNode = (site) => (node) => node
15988
16136
  ? {
15989
16137
  ...node,
15990
16138
  name: site?.name,
16139
+ functionalArea: infrastructureFunctionalArea(site, node),
15991
16140
  '@id': site?.['@id'], // carry the parent Site @id for logs lookup
15992
16141
  dataVersion: site?.dataVersion // keep the data version so the logs are fetched for the right version
15993
16142
  }
@@ -16037,6 +16186,7 @@ class SitesNodesComponent {
16037
16186
  this.defaultLabel = defaultLabel;
16038
16187
  this.nodeVersionKey = nodeVersionKey;
16039
16188
  this.maxAreaSize = maxAreaSize;
16189
+ this.schemaBaseUrl = schemaBaseUrl();
16040
16190
  this.selectedGroup = signal(undefined, ...(ngDevMode ? [{ debugName: "selectedGroup" }] : []));
16041
16191
  this.headerKeys = computed(() => ['site.id', 'site.@id', `site.${this.nodeKey()}.`], ...(ngDevMode ? [{ debugName: "headerKeys" }] : []));
16042
16192
  this.View = View;
@@ -16135,7 +16285,7 @@ class SitesNodesComponent {
16135
16285
  component.headerKeys.set(this.headerKeys());
16136
16286
  }
16137
16287
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SitesNodesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
16138
- 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 }, hideIdenticalValues: { classPropertyName: "hideIdenticalValues", publicName: "hideIdenticalValues", 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 @if (hasVisibleData() || !hideIdentical()) {\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]=\"\n node.value.term.name | ellipsis: 30 | compound: node.value.term.termType\n \"></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[nodeVersionKey(site)];\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 } @else {\n <div class=\"is-pt-3 has-text-centered\">\n <span>No differences between the nodes compared.</span>\n </div>\n }\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)]=\"hideIdenticalSelected\" />\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() || selectedTermTypes().length) {\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.aggregationLogs) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (selectedNode()) {\n <he-node-aggregation-logs\n [node]=\"selectedNode()\"\n [nodeKey]=\"nodeKey()\"\n [termType]=\"primaryProductTermType()\"\n [termId]=\"primaryProductTermId()\" />\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 [options]=\"termTypes()\"\n [(selectedOptions)]=\"selectedTermTypes\"\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", "options", "optionsPlaceholder", "selectedOptions"], outputs: ["valueChange", "selectedOptionsChange", "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: NodeAggregationLogsComponent, selector: "he-node-aggregation-logs", inputs: ["node", "nodeKey", "termType", "termId", "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" }] }); }
16288
+ 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 }, hideIdenticalValues: { classPropertyName: "hideIdenticalValues", publicName: "hideIdenticalValues", 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 @if (hasVisibleData() || !hideIdentical()) {\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 @if (isGroupNode()) {\n <th class=\"width-auto has-border-right\">\n <a [href]=\"schemaBaseUrl + '/Infrastructure#functionalArea'\" target=\"_blank\">Functional area</a>\n </th>\n }\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]=\"\n node.value.term.name | ellipsis: 30 | compound: node.value.term.termType\n \"></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 @if (isGroupNode()) {\n <th class=\"width-auto has-border-right\"></th>\n }\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 @if (isGroupNode()) {\n @let functionalArea = $any(site).functionalArea;\n <td class=\"width-auto has-border-right is-nowrap\">\n @if (functionalArea !== undefined && functionalArea !== null) {\n <span>{{ functionalArea | precision: 3 }} hectare</span>\n } @else {\n <span\n class=\"trigger-popover\"\n title=\"Neither the Site area nor the functional area is set, so the Inputs have no reference area.\">\n <span>not set</span>\n </span>\n }\n </td>\n }\n @for (node of data(); track node.value.term.name) {\n @if (node.value.visible) {\n @let siteData = node.value.values[nodeVersionKey(site)];\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 } @else {\n <div class=\"is-pt-3 has-text-centered\">\n <span>No differences between the nodes compared.</span>\n </div>\n }\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)]=\"hideIdenticalSelected\" />\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() || selectedTermTypes().length) {\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.aggregationLogs) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (selectedNode()) {\n <he-node-aggregation-logs\n [node]=\"selectedNode()\"\n [nodeKey]=\"nodeKey()\"\n [termType]=\"primaryProductTermType()\"\n [termId]=\"primaryProductTermId()\" />\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 [options]=\"termTypes()\"\n [(selectedOptions)]=\"selectedTermTypes\"\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", "options", "optionsPlaceholder", "selectedOptions"], outputs: ["valueChange", "selectedOptionsChange", "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: NodeAggregationLogsComponent, selector: "he-node-aggregation-logs", inputs: ["node", "nodeKey", "termType", "termId", "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" }] }); }
16139
16289
  }
16140
16290
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SitesNodesComponent, decorators: [{
16141
16291
  type: Component$1,
@@ -16160,7 +16310,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
16160
16310
  CapitalizePipe,
16161
16311
  PluralizePipe,
16162
16312
  SitesManagementChartComponent
16163
- ], 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 @if (hasVisibleData() || !hideIdentical()) {\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]=\"\n node.value.term.name | ellipsis: 30 | compound: node.value.term.termType\n \"></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[nodeVersionKey(site)];\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 } @else {\n <div class=\"is-pt-3 has-text-centered\">\n <span>No differences between the nodes compared.</span>\n </div>\n }\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)]=\"hideIdenticalSelected\" />\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() || selectedTermTypes().length) {\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.aggregationLogs) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (selectedNode()) {\n <he-node-aggregation-logs\n [node]=\"selectedNode()\"\n [nodeKey]=\"nodeKey()\"\n [termType]=\"primaryProductTermType()\"\n [termId]=\"primaryProductTermId()\" />\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 [options]=\"termTypes()\"\n [(selectedOptions)]=\"selectedTermTypes\"\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"] }]
16313
+ ], 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 @if (hasVisibleData() || !hideIdentical()) {\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 @if (isGroupNode()) {\n <th class=\"width-auto has-border-right\">\n <a [href]=\"schemaBaseUrl + '/Infrastructure#functionalArea'\" target=\"_blank\">Functional area</a>\n </th>\n }\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]=\"\n node.value.term.name | ellipsis: 30 | compound: node.value.term.termType\n \"></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 @if (isGroupNode()) {\n <th class=\"width-auto has-border-right\"></th>\n }\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 @if (isGroupNode()) {\n @let functionalArea = $any(site).functionalArea;\n <td class=\"width-auto has-border-right is-nowrap\">\n @if (functionalArea !== undefined && functionalArea !== null) {\n <span>{{ functionalArea | precision: 3 }} hectare</span>\n } @else {\n <span\n class=\"trigger-popover\"\n title=\"Neither the Site area nor the functional area is set, so the Inputs have no reference area.\">\n <span>not set</span>\n </span>\n }\n </td>\n }\n @for (node of data(); track node.value.term.name) {\n @if (node.value.visible) {\n @let siteData = node.value.values[nodeVersionKey(site)];\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 } @else {\n <div class=\"is-pt-3 has-text-centered\">\n <span>No differences between the nodes compared.</span>\n </div>\n }\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)]=\"hideIdenticalSelected\" />\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() || selectedTermTypes().length) {\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.aggregationLogs) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (selectedNode()) {\n <he-node-aggregation-logs\n [node]=\"selectedNode()\"\n [nodeKey]=\"nodeKey()\"\n [termType]=\"primaryProductTermType()\"\n [termId]=\"primaryProductTermId()\" />\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 [options]=\"termTypes()\"\n [(selectedOptions)]=\"selectedTermTypes\"\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"] }]
16164
16314
  }], 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 }] }], hideIdenticalValues: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideIdenticalValues", required: false }] }] } });
16165
16315
 
16166
16316
  class TermsPropertyContentComponent {
@@ -16223,5 +16373,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
16223
16373
  * Generated bundle index. Do not edit.
16224
16374
  */
16225
16375
 
16226
- export { ARRAY_DELIMITER, ApplyPurePipe, BarChartComponent, BibliographiesSearchConfirmComponent, BivariateChartComponent, BlankNodeStateComponent, BlankNodeStateNoticeComponent, BlankNodeValueDeltaComponent, CapitalizePipe, ChartComponent, ChartConfigurationDirective, ChartExportButtonComponent, ChartTooltipComponent, ClickOutsideDirective, ClipboardComponent, CollapsibleBlockComponent, CollapsibleBoxComponent, CollapsibleBoxStyle, 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, EngineRequiredDataFormComponent, EngineRequirementsFormComponent, FileSizePipe, FileUploadErrorKeys, FilesDragDropDirective, FilesDropZoneComponent, FilesErrorSummaryComponent, FilesFormComponent, FilesFormEditableComponent, FilesUploadErrorsComponent, FilterAccordionComponent, FormulaBlockComponent, GUIDE_ENABLED, GetPipe, GlossaryMigrationFormat, GuideOverlayComponent, HE_API_BASE_URL, HE_CALCULATIONS_BASE_URL, HE_MAP_LOADED, HE_NODE_LINK_TYPES, HE_REGION_GEOJSON_BASE_URL, HeAuthService, HeCommonService, HeEngineService, HeGlossaryService, HeMendeleyService, HeNodeCsvService, HeNodeService, HeNodeStoreService, HeSchemaService, HeSearchService, HeToastService, HorizontalBarChartComponent, HorizontalButtonsGroupComponent, ImpactAssessmentsGraphComponent, ImpactAssessmentsIndicatorBreakdownChartComponent, ImpactAssessmentsIndicatorsChartComponent, ImpactAssessmentsProductsComponent, IsArrayPipe, IsObjectPipe, IssueConfirmComponent, KeyToLabelPipe, Level, LineChartComponent, LinkKeyValueComponent, LogStatus, LongPressDirective, MAX_RESULTS, MapsDrawingComponent, MapsDrawingConfirmComponent, MaxPipe, MeanPipe, MedianPipe, MendeleySearchResult, MinPipe, MobileShellComponent, NavigationMenuComponent, NoExtPipe, NodeAggregatedComponent, NodeAggregatedFormulasComponent, NodeAggregatedInfoComponent, NodeAggregatedQualityScoreComponent, NodeAggregationLogsComponent, 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, aggregatedSitePrimaryProduct, allCountriesQuery, allGroups, allOptions, availableProperties, axisLabelSettings, backgroundModelParams, baseApiUrl, baseUrl, blankNodesTermTypes, bottom, buildSummary, bytesSize, calculateCycleDuration, calculateCycleDurationEnabled, calculateCycleStartDate, calculateCycleStartDateEnabled, capitalize, changelogUrl, clustererImage, code, compoundToHtml, computeKeys, computeTerms, contactUsEmail, contactUsLink, coordinatesToPoint, copyObject, countGroupVisibleNodes, countriesQuery, createMarker, cropsQuery, dataPathLabel, dataPathToKey, dataVersionHeader, dataVersionHeaderKey, defaultFeature, defaultLabel, defaultNodeLinkTypes, defaultRequiredDataIndicators, defaultRequiredDataSiteType, defaultSuggestionType, definitionToSchemaType, distinctUntilChangedDeep, ellipsis, engineGitBaseUrl, engineGitUrl, errorText, errorsLabel, evaluateSuccess, exportFormats, externalLink, externalNodeLink, fillColor, fillStyle, filterBlankNode$1 as filterBlankNode, filterParams, findBackgroundModel, findConfigModels, findMatchingModel, findModels, findNodeModel, findOrchestratorModel, findProperty, findPropertyById, findTermModels, flatFilterData, flatFilterNode, formatCustomErrorMessage, formatDate, formatError, formatPropertyError, formatter$1 as formatter, getDatesBetween, gitBranch, gitHome, glossaryBaseUrl, glossaryLink, groupBlankNodesByTermIdentity, groupChanged, groupJLogByField, groupJLogByTerm, groupLogsByTerm, groupNodesByTerm, groupdLogsByKey, grouppedKeys, grouppedValueKeys, groupsLogsByFields, guideModelUrl, guideNamespace, handleAPIError, handleGuideEvent, hasError, hasValidationError, hasWarning, highestMethodTier, ignoreKeys$2 as ignoreKeys, impactAssessmentProduct, initialFilterState, injectResizeEvent$, inputGroupsTermTypes, isAddPropertyEnabled, isChrome, isDateBetween, isEqual, isExternal, isIdenticalNodeValue, isKeyClosedVisible, isKeyHidden, isMaxStage, isMethodModelAllowed, isNonNodeModelKey, isSchemaIri, isScrolledBelow, isState, isTermTypeAllowed, isValidKey, jLogModelCount, keyToDataPath, levels, loadMapApi, locationQuery, logToCsv, logValueArray, logsKey, lookupUrl, mapFilterData, mapsUrl, markerIcon, markerPie, matchAggregatedQuery, matchAggregatedValidatedQuery, matchBoolPrefixQuery, matchCountry, matchExactQuery, matchGlobalRegion, matchId, matchNameNormalized, matchNestedKey, matchPhrasePrefixQuery, matchPhraseQuery, matchPrimaryProductQuery, matchQuery, matchRegex, matchRegion, matchTermType, matchType, matchesSearchTerm, maxAreaSize, measurementValue, mergeDataWithHeaders, methodTierOrder, migrationErrorMessage, migrationsUrl, modelCount, modelKeyParams, modelParams, models, multiMatchQuery, nestedProperty, nestingEnabled, nestingTypeEnabled, noValue, nodeAvailableProperties, nodeById, nodeChartLabels, nodeColours, nodeDataState, nodeDataStates, nodeDataVersion, nodeId, nodeIdWithoutDataVersion, nodeIds, nodeLink, nodeLinkEnabled, nodeLinkTypeEnabled, nodeLogsUrl, nodeQualityScoreColor, nodeQualityScoreLevel, nodeQualityScoreMaxDefault, nodeQualityScoreOrder, nodeRequestId, nodeSecondaryColours, nodeToAggregationFilename, nodeType, nodeTypeDataState, nodeTypeIcon, nodeTypeIconSchema, nodeUrl, nodeUrlParams, nodeVersion, nodeVersionKey, nodesByState, nodesByType, numberGte, openNodeUrl, openUrl, optionsFromGroup, parentKey, parentProperty, parseData, parseDataPath, parseLines, parseMessage, parseNewValue, pluralize, pointToCoordinates, polygonBounds, polygonToCoordinates, polygonToMap, polygonsFromFeature, populateWithTrackIdsFilterData, postGuideEvent, primaryProduct, productsQuery, propertyError, propertyErrors, propertyId, recursiveProperties, refToSchemaType, refreshPropertyKeys, regionsQuery, repeat, reportIssueLink, reportIssueUrl, requiredDataParams, safeJSONParse, safeJSONStringify, schemaBaseUrl, schemaDataBaseUrl, schemaLink, schemaRequiredProperties, schemaTypeToDefaultValue, scrollToEl, scrollTop, searchFilterData, searchableTypes, siblingProperty, simplifyContributions, singleProperty, siteTooBig, siteTypeToColor, siteTypeToIcon, sortProperties, sortedDates, strokeColor, strokeStyle, subValueKeys, suggestMatchQuery, suggestQuery, suggestTerms, takeAfterViewInit, termLocation, termLocationName, termProperties, termSearch, termTypeLabel, toSnakeCase, toTextParts, toThousands, typeToNewProperty, typeaheadFocus, uncapitalize, uniqueDatesBetween, updateProperties, valueLink, valueToString, valueTypeToDefault, valueValue, versionGitRef, waitFor, wildcardQuery };
16376
+ export { ARRAY_DELIMITER, ApplyPurePipe, BarChartComponent, BibliographiesSearchConfirmComponent, BivariateChartComponent, BlankNodeStateComponent, BlankNodeStateNoticeComponent, BlankNodeValueDeltaComponent, CapitalizePipe, ChartComponent, ChartConfigurationDirective, ChartExportButtonComponent, ChartTooltipComponent, ClickOutsideDirective, ClipboardComponent, CollapsibleBlockComponent, CollapsibleBoxComponent, CollapsibleBoxStyle, 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, EngineRequiredDataFormComponent, EngineRequirementsFormComponent, FileSizePipe, FileUploadErrorKeys, FilesDragDropDirective, FilesDropZoneComponent, FilesErrorSummaryComponent, FilesFormComponent, FilesFormEditableComponent, FilesUploadErrorsComponent, FilterAccordionComponent, FormulaBlockComponent, GUIDE_ENABLED, GetPipe, GlossaryMigrationFormat, GuideOverlayComponent, HE_API_BASE_URL, HE_CALCULATIONS_BASE_URL, HE_MAP_LOADED, HE_NODE_LINK_TYPES, HE_REGION_GEOJSON_BASE_URL, HeAuthService, HeCommonService, HeEngineService, HeGlossaryService, HeMendeleyService, HeNodeCsvService, HeNodeService, HeNodeStoreService, HeSchemaService, HeSearchService, HeToastService, HorizontalBarChartComponent, HorizontalButtonsGroupComponent, ImpactAssessmentsGraphComponent, ImpactAssessmentsIndicatorBreakdownChartComponent, ImpactAssessmentsIndicatorsChartComponent, ImpactAssessmentsProductsComponent, IsArrayPipe, IsObjectPipe, IssueConfirmComponent, KeyToLabelPipe, Level, LineChartComponent, LinkKeyValueComponent, LogStatus, LongPressDirective, MAX_RESULTS, MapsDrawingComponent, MapsDrawingConfirmComponent, MaxPipe, MeanPipe, MedianPipe, MendeleySearchResult, MinPipe, MobileShellComponent, NavigationMenuComponent, NoExtPipe, NodeAggregatedComponent, NodeAggregatedFormulasComponent, NodeAggregatedInfoComponent, NodeAggregatedQualityScoreComponent, NodeAggregationLogsComponent, 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, aggregatedSitePrimaryProduct, allCountriesQuery, allGroups, allOptions, availableProperties, axisLabelSettings, backgroundModelParams, baseApiUrl, baseUrl, blankNodesTermTypes, bottom, buildSummary, bytesSize, calculateCycleDuration, calculateCycleDurationEnabled, calculateCycleStartDate, calculateCycleStartDateEnabled, capitalize, changelogUrl, clustererImage, code, compoundToHtml, computeKeys, computeTerms, contactUsEmail, contactUsLink, coordinatesToPoint, copyObject, countGroupVisibleNodes, countriesQuery, createMarker, cropsQuery, dataPathLabel, dataPathToKey, dataVersionHeader, dataVersionHeaderKey, defaultFeature, defaultLabel, defaultNodeLinkTypes, defaultRequiredDataIndicators, defaultRequiredDataSiteType, defaultSuggestionType, definitionToSchemaType, distinctUntilChangedDeep, ellipsis, engineGitBaseUrl, engineGitUrl, errorText, errorsLabel, evaluateSuccess, exportFormats, externalLink, externalNodeLink, fillColor, fillStyle, filterBlankNode$1 as filterBlankNode, filterParams, findBackgroundModel, findConfigModels, findMatchingModel, findModels, findNodeModel, findOrchestratorModel, findProperty, findPropertyById, findTermModels, flatFilterData, flatFilterNode, formatCustomErrorMessage, formatDate, formatError, formatPropertyError, formatter$1 as formatter, getDatesBetween, gitBranch, gitHome, glossaryBaseUrl, glossaryLink, groupBlankNodesByTermIdentity, groupChanged, groupJLogByField, groupJLogByTerm, groupLogsByTerm, groupNodesByTerm, groupdLogsByKey, grouppedKeys, grouppedValueKeys, groupsLogsByFields, guideModelUrl, guideNamespace, handleAPIError, handleGuideEvent, hasError, hasValidationError, hasWarning, highestMethodTier, ignoreKeys$2 as ignoreKeys, impactAssessmentProduct, infrastructureFunctionalArea, initialFilterState, injectResizeEvent$, inputGroupsTermTypes, isAddPropertyEnabled, isChrome, isDateBetween, isEqual, isExternal, isIdenticalNodeValue, isKeyClosedVisible, isKeyHidden, isMaxStage, isMethodModelAllowed, isNonNodeModelKey, isSchemaIri, isScrolledBelow, isState, isTermTypeAllowed, isValidKey, jLogModelCount, keyToDataPath, levels, loadMapApi, locationQuery, logToCsv, logValueArray, logsKey, lookupUrl, mapFilterData, mapsUrl, markerIcon, markerPie, matchAggregatedQuery, matchAggregatedValidatedQuery, matchBoolPrefixQuery, matchCountry, matchExactQuery, matchGlobalRegion, matchId, matchNameNormalized, matchNestedKey, matchPhrasePrefixQuery, matchPhraseQuery, matchPrimaryProductQuery, matchQuery, matchRegex, matchRegion, matchTermType, matchType, matchesSearchTerm, maxAreaSize, measurementValue, mergeDataWithHeaders, methodTierOrder, migrationErrorMessage, migrationsUrl, modelCount, modelKeyParams, modelParams, models, multiMatchQuery, nestedProperty, nestingEnabled, nestingTypeEnabled, noValue, nodeAvailableProperties, nodeById, nodeChartLabels, nodeColours, nodeDataState, nodeDataStates, nodeDataVersion, nodeId, nodeIdWithoutDataVersion, nodeIds, nodeLink, nodeLinkEnabled, nodeLinkTypeEnabled, nodeLogsUrl, nodeQualityScoreColor, nodeQualityScoreLevel, nodeQualityScoreMaxDefault, nodeQualityScoreOrder, nodeRequestId, nodeSecondaryColours, nodeToAggregationFilename, nodeType, nodeTypeDataState, nodeTypeIcon, nodeTypeIconSchema, nodeUrl, nodeUrlParams, nodeVersion, nodeVersionKey, nodesByState, nodesByType, numberGte, openNodeUrl, openUrl, optionsFromGroup, parentKey, parentProperty, parseData, parseDataPath, parseLines, parseMessage, parseNewValue, pluralize, pointToCoordinates, polygonBounds, polygonToCoordinates, polygonToMap, polygonsFromFeature, populateWithTrackIdsFilterData, postGuideEvent, primaryProduct, productsQuery, propertyError, propertyErrors, propertyId, recursiveProperties, refToSchemaType, refreshPropertyKeys, regionsQuery, repeat, reportIssueLink, reportIssueUrl, requiredDataParams, safeJSONParse, safeJSONStringify, schemaBaseUrl, schemaDataBaseUrl, schemaLink, schemaRequiredProperties, schemaTypeToDefaultValue, scrollToEl, scrollTop, searchFilterData, searchableTypes, siblingProperty, simplifyContributions, singleProperty, siteTooBig, siteTypeToColor, siteTypeToIcon, sortProperties, sortedDates, strokeColor, strokeStyle, subValueKeys, suggestMatchQuery, suggestQuery, suggestTerms, takeAfterViewInit, termLocation, termLocationName, termProperties, termSearch, termTypeLabel, toSnakeCase, toTextParts, toThousands, typeToNewProperty, typeaheadFocus, uncapitalize, uniqueDatesBetween, updateProperties, valueLink, valueToString, valueTypeToDefault, valueValue, versionGitRef, waitFor, wildcardQuery };
16227
16377
  //# sourceMappingURL=hestia-earth-ui-components.mjs.map