@hestia-earth/ui-components 0.43.27 → 0.43.29

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.
@@ -2,7 +2,7 @@ import * as i0 from '@angular/core';
2
2
  import { Injectable, InjectionToken, inject, ElementRef, PLATFORM_ID, output, Directive, DestroyRef, input, computed, ChangeDetectionStrategy, Component as Component$1, Pipe, viewChild, HostListener, model, ViewEncapsulation, signal, afterNextRender, effect, HostBinding, contentChild, untracked, linkedSignal, viewChildren, forwardRef, LOCALE_ID } from '@angular/core';
3
3
  import { toObservable, toSignal, outputFromObservable, takeUntilDestroyed, rxResource } from '@angular/core/rxjs-interop';
4
4
  import * as i1 from '@angular/forms';
5
- import { FormsModule, NG_VALUE_ACCESSOR, UntypedFormBuilder, Validators, ReactiveFormsModule, FormControl } from '@angular/forms';
5
+ import { FormsModule, NG_VALUE_ACCESSOR, UntypedFormBuilder, Validators, ReactiveFormsModule, FormBuilder, FormControl } from '@angular/forms';
6
6
  import { isPlatformBrowser, NgClass, DecimalPipe, NgTemplateOutlet, DOCUMENT, KeyValuePipe, NgStyle, UpperCasePipe, JsonPipe, DatePipe, AsyncPipe, formatDate as formatDate$1 } from '@angular/common';
7
7
  import * as i1$1 from '@ng-bootstrap/ng-bootstrap';
8
8
  import { NgbTooltip, NgbDropdown, NgbDropdownMenu, NgbDropdownToggle, NgbActiveModal, NgbHighlight, NgbModal, NgbDropdownItem, NgbTypeahead, NgbPopover, NgbTooltipModule, NgbDropdownModule, NgbPopoverModule } from '@ng-bootstrap/ng-bootstrap';
@@ -12,7 +12,7 @@ import get from 'lodash.get';
12
12
  import { SCHEMA_VERSION, SchemaType, NodeType, TermTermType, productTermTermType, nestedSearchableKeys, SiteSiteType, EmissionMethodTier, isExpandable, isTypeNode, sortKeysByType, uniquenessFields, BlankNodesKey, impactAssessmentTermTermType, measurementTermTermType, emissionTermTermType, inputTermTermType, CycleFunctionalUnit, NonBlankNodesKey, jsonldPath, isTypeValid, typeToSchemaType, infrastructureTermTermType, managementTermTermType } from '@hestia-earth/schema';
13
13
  import { formatPrecision, axisLabelCursor, defaultChartSettings, exportAsSVG, downloadFile, hasNegativeContributions, withOthers, barDataset, defaultBarDatasets, defaultBarSettings, categoryLabel, emissionCategories, categoryValues, emissionCategoriesOf, emissionCategoryValue, contributionItemColor, contributionChartHeight, groupDataByCategory, contributionChartConfig, hasNegativeValues, contributionData, defaultContributionSettings, contributionCsv, dataAtIndex, datasetCenter, distributionChart, defaultLineSettings, defaultHorizontalTooltip, horizontalBarHeight, lollipopChartPlugin, backgroundHoverPlugin, afterBarDrawPlugin, axisHoverPlugin, defaultHorizontalBarConfig, chartLabelMaxLength, listColor, getColor, nodeBorderColours, nodeColours as nodeColours$1, hierarchyLegend, downloadSvg, downloadPng, hierarchyCsv, drawHierarchyChart, hierarchyTermTypes, hierarchyContributions, missingTermIds, hierarchyWarnings, hierarchyModels, hierarchyData, defaultIndicatorsModelId, parseContributions, indicatorLogs, nonZeroContributors, logsTotalValue, namedContributors, breakdownBars, breakdownTooltip, breakdownBarText, breakdownScale, logToCsv as logToCsv$1 } from '@hestia-earth/ui-components-charts';
14
14
  export { ColorPalette, afterBarDrawPlugin, axisHoverPlugin, axisLabelCursor, backgroundHoverPlugin, chartLabelMaxLength, colorToRgba, convertToSvg, d3ellipse, d3wrap, defaultTicksFont, downloadFile, downloadPng, downloadSvg, exportAsSVG, getColor, groupDataByCategory, hexToRgba, increaseScaleLimits, listColor, listColorContinuous, listColorWithAlpha, lollipopChartPlugin, parseColor, registerChart, sumValues } from '@hestia-earth/ui-components-charts';
15
- import { isEmpty, unique, monthsBefore, toPrecision, isNumber, isUndefined, duration, keyToLabel, sum, min, max, mean, median, isEqual as isEqual$2, diffInDays } from '@hestia-earth/utils';
15
+ import { isEmpty, unique, monthsBefore, toPrecision, isNumber, isUndefined, keyToLabel, duration, sum, min, max, mean, median, isEqual as isEqual$2, diffInDays } from '@hestia-earth/utils';
16
16
  import { json2csv } from 'json-2-csv';
17
17
  import { propertyValue as propertyValue$1, emptyValue } from '@hestia-earth/utils/term';
18
18
  import defaultModelId from '@hestia-earth/glossary/resources/defaultModelId.json';
@@ -897,7 +897,13 @@ const isDateBetween = (date, dates) => {
897
897
  const start = dates.start ? formatDate(dates.start, true) : monthsBefore(end, 1);
898
898
  return [new Date(date).getTime() >= start.getTime(), new Date(date).getTime() <= end.getTime()].every(Boolean);
899
899
  };
900
- const filterBlankNode$1 = (filterTerm) => (node) => [!filterTerm || node.term?.name?.toLowerCase()?.includes(filterTerm.toLowerCase())].every(Boolean);
900
+ const filterBlankNode$1 = (filterTerm, termTypes = []) => (node) => [
901
+ !filterTerm || node.term?.name?.toLowerCase()?.includes(filterTerm.toLowerCase()),
902
+ !termTypes.length || termTypes.includes(node.term?.termType)
903
+ ].every(Boolean);
904
+ const blankNodesTermTypes = (nodes = [], keys = []) => unique(nodes.flatMap(node => keys.flatMap(key => (node?.[key] || []).map(({ term }) => term?.termType))))
905
+ .filter(Boolean)
906
+ .sort();
901
907
  const ignoreKeys$2 = ['@type', 'type', 'added', 'updated', 'addedVersion', 'updatedVersion'];
902
908
  const isValidKey = (key) => !ignoreKeys$2.includes(key);
903
909
  const isMethodModelAllowed = (filterMethod) => (node) => node.methodModel?.['@id'] === (filterMethod ? filterMethod['@id'] : getDefaultModelId(node.term?.['@id'])) ||
@@ -1632,12 +1638,31 @@ const findConfigModels = (config, termId, modelKey) => {
1632
1638
  .filter(({ value, key }) => termId === value && (!modelKey || key === modelKey));
1633
1639
  return configModels.length ? configModels : findModels(termId);
1634
1640
  };
1641
+ const defaultRequiredDataIndicators = [
1642
+ 'gwp100',
1643
+ 'eutrophicationPotentialExcludingFate',
1644
+ 'terrestrialAcidificationPotentialIncludingFateAverageEurope',
1645
+ 'freshwaterEutrophicationPotential',
1646
+ 'agriculturalLandOccupationPotential'
1647
+ ];
1648
+ // mirrors `_SITE_TYPES` in engine-models `orchestrator/preflight/coverage.py`
1649
+ const productSiteTypes = {
1650
+ [TermTermType.crop]: SiteSiteType.cropland,
1651
+ [TermTermType.forage]: SiteSiteType['permanent pasture']
1652
+ };
1653
+ const defaultRequiredDataSiteType = (productTermType) => productSiteTypes[productTermType];
1654
+ const requiredDataParams = ({ indicators, terms, ...params }) => filterParams({
1655
+ ...params,
1656
+ indicators: indicators?.join(','),
1657
+ terms: terms?.join(',')
1658
+ });
1635
1659
  class HeEngineService {
1636
1660
  constructor() {
1637
1661
  this._calculationsBaseUrl = inject(HE_CALCULATIONS_BASE_URL);
1638
1662
  this.http = inject(HttpClient);
1639
1663
  this._recommendations = {};
1640
1664
  this._requirements = {};
1665
+ this._requiredData = {};
1641
1666
  }
1642
1667
  listModels$(params) {
1643
1668
  return this.http.get(`${this._calculationsBaseUrl}/models`, {
@@ -1655,6 +1680,23 @@ class HeEngineService {
1655
1680
  .pipe(shareReplay(1));
1656
1681
  return this._requirements[key];
1657
1682
  }
1683
+ getRequiredData$(params) {
1684
+ const key = JSON.stringify(requiredDataParams(params));
1685
+ this._requiredData[key] =
1686
+ this._requiredData[key] ||
1687
+ this.http
1688
+ .get(`${this._calculationsBaseUrl}/models/required-data`, {
1689
+ params: requiredDataParams(params)
1690
+ })
1691
+ .pipe(shareReplay(1));
1692
+ return this._requiredData[key];
1693
+ }
1694
+ getRequiredDataTemplate$(params) {
1695
+ return this.http.get(`${this._calculationsBaseUrl}/models/required-data`, {
1696
+ params: { ...requiredDataParams(params), format: 'csv' },
1697
+ responseType: 'text'
1698
+ });
1699
+ }
1658
1700
  getTermIds$(params) {
1659
1701
  const key = JSON.stringify(filterParams(params));
1660
1702
  this._recommendations[key] =
@@ -3075,6 +3117,68 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
3075
3117
  args: [{ selector: 'he-schema-version-link', changeDetection: ChangeDetectionStrategy.OnPush, imports: [HESvgIconComponent], template: "<a [href]=\"url()\" target=\"_blank\" [class]=\"linkClass()\" (click)=\"$event.stopPropagation()\">\n <ng-content />\n @if (showExternalLink()) {\n <he-svg-icon name=\"external-link\" class=\"ml-2\" />\n }\n</a>\n", styles: ["a{color:inherit}\n"] }]
3076
3118
  }], propDecorators: { node: [{ type: i0.Input, args: [{ isSignal: true, alias: "node", required: true }] }], showExternalLink: [{ type: i0.Input, args: [{ isSignal: true, alias: "showExternalLink", required: false }] }], linkClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "linkClass", required: false }] }] } });
3077
3119
 
3120
+ const termProperties = (term) => Object.keys(term).filter(key => !isExpandable(term[key]) &&
3121
+ ![
3122
+ 'pinned',
3123
+ 'expanded',
3124
+ 'extended',
3125
+ 'selected',
3126
+ 'loading',
3127
+ '_score',
3128
+ '@type',
3129
+ '@id',
3130
+ '@context',
3131
+ 'createdAt',
3132
+ 'updatedAt',
3133
+ 'name',
3134
+ 'synonyms',
3135
+ 'termType',
3136
+ 'location',
3137
+ 'properties',
3138
+ 'schemaVersion',
3139
+ 'last-modified'
3140
+ ].includes(key));
3141
+ const findPropertyById = ({ defaultProperties }, key) => (defaultProperties || []).find(({ term }) => term['@id'] === key);
3142
+ const termLocationName = ({ gadmFullName }) => ({
3143
+ name: gadmFullName || ''
3144
+ });
3145
+ const termLocation = ({ latitude, longitude }) => ({
3146
+ lat: latitude,
3147
+ lng: longitude
3148
+ });
3149
+ const termTypeToLabel = {
3150
+ [TermTermType.methodEmissionResourceUse]: 'Method (Emissions)',
3151
+ [TermTermType.methodMeasurement]: 'Method (Measurement)',
3152
+ [TermTermType.pesticideAI]: 'Pesticide Active Ingredient',
3153
+ [TermTermType.standardsLabels]: 'Standards & Labels',
3154
+ [TermTermType.usdaSoilType]: 'USDA Soil Type'
3155
+ };
3156
+ const termKeyToLabel = {
3157
+ pubchem: 'PubChem',
3158
+ casNumber: 'CAS Number',
3159
+ agrovoc: 'AGROVOC'
3160
+ };
3161
+ const termTypeLabel = (value = 'N/A') => termTypeToLabel[value] || termKeyToLabel[value] || keyToLabel(value);
3162
+ // glossary names are punctuated ("Land transformation, 20 year average") and a reader typing one
3163
+ // leaves the punctuation out, so neither side keeps it
3164
+ const termSearch = (term = '') => term.replace(/[,\s]/g, '').toLowerCase();
3165
+ const suggestTerms = (terms, value) => terms.filter(({ name }) => termSearch(name).includes(termSearch(value)));
3166
+
3167
+ class KeyToLabelPipe {
3168
+ transform(value) {
3169
+ // using termTypeLabel here which defaults to `keyToLabel` function
3170
+ return termTypeLabel(value);
3171
+ }
3172
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: KeyToLabelPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
3173
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: KeyToLabelPipe, isStandalone: true, name: "keyToLabel" }); }
3174
+ }
3175
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: KeyToLabelPipe, decorators: [{
3176
+ type: Pipe,
3177
+ args: [{
3178
+ name: 'keyToLabel'
3179
+ }]
3180
+ }] });
3181
+
3078
3182
  class SearchExtendComponent {
3079
3183
  constructor() {
3080
3184
  this.searchInput = viewChild('searchInput', ...(ngDevMode ? [{ debugName: "searchInput" }] : []));
@@ -3083,7 +3187,15 @@ class SearchExtendComponent {
3083
3187
  this.placeholder = input(undefined, ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
3084
3188
  this.class = input(undefined, ...(ngDevMode ? [{ debugName: "class" }] : []));
3085
3189
  this.collapsedClass = input(undefined, ...(ngDevMode ? [{ debugName: "collapsedClass" }] : []));
3190
+ this.options = input([], ...(ngDevMode ? [{ debugName: "options" }] : []));
3191
+ this.optionsPlaceholder = input('All types', ...(ngDevMode ? [{ debugName: "optionsPlaceholder" }] : []));
3192
+ this.selectedOptions = model([], ...(ngDevMode ? [{ debugName: "selectedOptions" }] : []));
3086
3193
  this.searchText = output();
3194
+ this.selectedOptionsLabel = computed(() => this.selectedOptions().length === 1
3195
+ ? termTypeLabel(this.selectedOptions()[0])
3196
+ : this.selectedOptions().length
3197
+ ? `${this.selectedOptions().length} types`
3198
+ : this.optionsPlaceholder(), ...(ngDevMode ? [{ debugName: "selectedOptionsLabel" }] : []));
3087
3199
  this.extended = signal(false, ...(ngDevMode ? [{ debugName: "extended" }] : []));
3088
3200
  }
3089
3201
  extend() {
@@ -3094,6 +3206,12 @@ class SearchExtendComponent {
3094
3206
  !!this.value() || this.searchInput().nativeElement.focus();
3095
3207
  this.searchText.emit(this.value());
3096
3208
  }
3209
+ isSelected(option) {
3210
+ return this.selectedOptions().includes(option);
3211
+ }
3212
+ toggleOption(option, selected) {
3213
+ this.selectedOptions.update(options => selected ? [...options, option] : options.filter(value => value !== option));
3214
+ }
3097
3215
  clear() {
3098
3216
  this.value.set('');
3099
3217
  return this.submit();
@@ -3102,12 +3220,21 @@ class SearchExtendComponent {
3102
3220
  return this.extended() ? this.applySearch() : this.extend();
3103
3221
  }
3104
3222
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SearchExtendComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3105
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.0.6", type: SearchExtendComponent, isStandalone: true, selector: "he-search-extend", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, collapsedClass: { classPropertyName: "collapsedClass", publicName: "collapsedClass", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", searchText: "searchText" }, viewQueries: [{ propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true, isSignal: true }], ngImport: i0, template: "<form\n class=\"field has-addons\"\n novalidate\n (submit)=\"submit()\"\n [ngbTooltip]=\"extended() ? null : placeholder()\"\n container=\"body\">\n <div class=\"control is-expanded has-icons-right\" [class.is-hidden]=\"!extended()\">\n <input\n #searchInput\n type=\"text\"\n class=\"input is-small search-input\"\n [ngClass]=\"class()\"\n name=\"search\"\n [(ngModel)]=\"value\"\n [disabled]=\"disabled()\"\n [attr.placeholder]=\"placeholder()\" />\n <a class=\"icon is-small is-right\" [class.is-hidden]=\"!value() || disabled()\" (click)=\"clear()\">\n <he-svg-icon name=\"xmark\" size=\"20\" />\n </a>\n </div>\n <div class=\"control\">\n <button\n class=\"button is-ghost is-small is-radius-right-6\"\n [ngClass]=\"extended() ? class() : collapsedClass()\"\n type=\"submit\">\n <he-svg-icon name=\"search\" size=\"20\" />\n </button>\n </div>\n</form>\n", styles: [".button{height:36px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgbTooltip, selector: "[ngbTooltip]", inputs: ["animation", "autoClose", "placement", "popperOptions", "triggers", "positionTarget", "container", "disableTooltip", "tooltipClass", "tooltipContext", "openDelay", "closeDelay", "ngbTooltip"], outputs: ["shown", "hidden"], exportAs: ["ngbTooltip"] }, { kind: "component", type: HESvgIconComponent, selector: "he-svg-icon", inputs: ["name", "size", "animation"] }] }); }
3223
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: SearchExtendComponent, isStandalone: true, selector: "he-search-extend", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, collapsedClass: { classPropertyName: "collapsedClass", publicName: "collapsedClass", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, optionsPlaceholder: { classPropertyName: "optionsPlaceholder", publicName: "optionsPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, selectedOptions: { classPropertyName: "selectedOptions", publicName: "selectedOptions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", selectedOptions: "selectedOptionsChange", searchText: "searchText" }, viewQueries: [{ propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true, isSignal: true }], ngImport: i0, template: "<form\n class=\"field has-addons\"\n novalidate\n (submit)=\"submit()\"\n [ngbTooltip]=\"extended() ? null : placeholder()\"\n container=\"body\">\n @if (extended() && options().length > 1) {\n <div class=\"control\">\n <div ngbDropdown container=\"body\" placement=\"bottom-start\" autoClose=\"outside\">\n <button\n ngbDropdownToggle\n type=\"button\"\n class=\"button is-small is-radius-left-6\"\n [ngClass]=\"class()\"\n [class.is-selected]=\"selectedOptions().length\">\n <he-svg-icon name=\"filter-funnel\" size=\"20\" aria-hidden=\"true\" />\n <span class=\"is-hidden-mobile is-nowrap\">{{ selectedOptionsLabel() }}</span>\n </button>\n <div ngbDropdownMenu>\n <div class=\"dropdown-content\">\n @for (option of options(); track option) {\n <div class=\"dropdown-item\">\n <label class=\"checkbox is-nowrap\">\n <input\n type=\"checkbox\"\n class=\"selector\"\n [checked]=\"isSelected(option)\"\n (change)=\"toggleOption(option, $any($event.target).checked)\" />\n <span class=\"is-pl-2\">{{ option | keyToLabel }}</span>\n </label>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n }\n <div class=\"control is-expanded has-icons-right\" [class.is-hidden]=\"!extended()\">\n <input\n #searchInput\n type=\"text\"\n class=\"input is-small search-input\"\n [ngClass]=\"class()\"\n name=\"search\"\n [(ngModel)]=\"value\"\n [disabled]=\"disabled()\"\n [attr.placeholder]=\"placeholder()\" />\n <a class=\"icon is-small is-right\" [class.is-hidden]=\"!value() || disabled()\" (click)=\"clear()\">\n <he-svg-icon name=\"xmark\" size=\"20\" />\n </a>\n </div>\n <div class=\"control\">\n <button\n class=\"button is-ghost is-small is-radius-right-6\"\n [ngClass]=\"extended() ? class() : collapsedClass()\"\n type=\"submit\">\n <he-svg-icon name=\"search\" size=\"20\" />\n </button>\n </div>\n</form>\n", styles: [".button{height:36px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgbTooltip, selector: "[ngbTooltip]", inputs: ["animation", "autoClose", "placement", "popperOptions", "triggers", "positionTarget", "container", "disableTooltip", "tooltipClass", "tooltipContext", "openDelay", "closeDelay", "ngbTooltip"], outputs: ["shown", "hidden"], exportAs: ["ngbTooltip"] }, { kind: "directive", type: NgbDropdown, selector: "[ngbDropdown]", inputs: ["autoClose", "dropdownClass", "open", "placement", "popperOptions", "container", "display"], outputs: ["openChange"], exportAs: ["ngbDropdown"] }, { kind: "directive", type: NgbDropdownToggle, selector: "[ngbDropdownToggle]" }, { kind: "directive", type: NgbDropdownMenu, selector: "[ngbDropdownMenu]" }, { kind: "component", type: HESvgIconComponent, selector: "he-svg-icon", inputs: ["name", "size", "animation"] }, { kind: "pipe", type: KeyToLabelPipe, name: "keyToLabel" }] }); }
3106
3224
  }
3107
3225
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SearchExtendComponent, decorators: [{
3108
3226
  type: Component$1,
3109
- args: [{ selector: 'he-search-extend', imports: [FormsModule, NgClass, NgbTooltip, HESvgIconComponent], template: "<form\n class=\"field has-addons\"\n novalidate\n (submit)=\"submit()\"\n [ngbTooltip]=\"extended() ? null : placeholder()\"\n container=\"body\">\n <div class=\"control is-expanded has-icons-right\" [class.is-hidden]=\"!extended()\">\n <input\n #searchInput\n type=\"text\"\n class=\"input is-small search-input\"\n [ngClass]=\"class()\"\n name=\"search\"\n [(ngModel)]=\"value\"\n [disabled]=\"disabled()\"\n [attr.placeholder]=\"placeholder()\" />\n <a class=\"icon is-small is-right\" [class.is-hidden]=\"!value() || disabled()\" (click)=\"clear()\">\n <he-svg-icon name=\"xmark\" size=\"20\" />\n </a>\n </div>\n <div class=\"control\">\n <button\n class=\"button is-ghost is-small is-radius-right-6\"\n [ngClass]=\"extended() ? class() : collapsedClass()\"\n type=\"submit\">\n <he-svg-icon name=\"search\" size=\"20\" />\n </button>\n </div>\n</form>\n", styles: [".button{height:36px}\n"] }]
3110
- }], propDecorators: { searchInput: [{ type: i0.ViewChild, args: ['searchInput', { isSignal: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], collapsedClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsedClass", required: false }] }], searchText: [{ type: i0.Output, args: ["searchText"] }] } });
3227
+ args: [{ selector: 'he-search-extend', imports: [
3228
+ FormsModule,
3229
+ NgClass,
3230
+ NgbTooltip,
3231
+ NgbDropdown,
3232
+ NgbDropdownToggle,
3233
+ NgbDropdownMenu,
3234
+ HESvgIconComponent,
3235
+ KeyToLabelPipe
3236
+ ], template: "<form\n class=\"field has-addons\"\n novalidate\n (submit)=\"submit()\"\n [ngbTooltip]=\"extended() ? null : placeholder()\"\n container=\"body\">\n @if (extended() && options().length > 1) {\n <div class=\"control\">\n <div ngbDropdown container=\"body\" placement=\"bottom-start\" autoClose=\"outside\">\n <button\n ngbDropdownToggle\n type=\"button\"\n class=\"button is-small is-radius-left-6\"\n [ngClass]=\"class()\"\n [class.is-selected]=\"selectedOptions().length\">\n <he-svg-icon name=\"filter-funnel\" size=\"20\" aria-hidden=\"true\" />\n <span class=\"is-hidden-mobile is-nowrap\">{{ selectedOptionsLabel() }}</span>\n </button>\n <div ngbDropdownMenu>\n <div class=\"dropdown-content\">\n @for (option of options(); track option) {\n <div class=\"dropdown-item\">\n <label class=\"checkbox is-nowrap\">\n <input\n type=\"checkbox\"\n class=\"selector\"\n [checked]=\"isSelected(option)\"\n (change)=\"toggleOption(option, $any($event.target).checked)\" />\n <span class=\"is-pl-2\">{{ option | keyToLabel }}</span>\n </label>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n }\n <div class=\"control is-expanded has-icons-right\" [class.is-hidden]=\"!extended()\">\n <input\n #searchInput\n type=\"text\"\n class=\"input is-small search-input\"\n [ngClass]=\"class()\"\n name=\"search\"\n [(ngModel)]=\"value\"\n [disabled]=\"disabled()\"\n [attr.placeholder]=\"placeholder()\" />\n <a class=\"icon is-small is-right\" [class.is-hidden]=\"!value() || disabled()\" (click)=\"clear()\">\n <he-svg-icon name=\"xmark\" size=\"20\" />\n </a>\n </div>\n <div class=\"control\">\n <button\n class=\"button is-ghost is-small is-radius-right-6\"\n [ngClass]=\"extended() ? class() : collapsedClass()\"\n type=\"submit\">\n <he-svg-icon name=\"search\" size=\"20\" />\n </button>\n </div>\n</form>\n", styles: [".button{height:36px}\n"] }]
3237
+ }], propDecorators: { searchInput: [{ type: i0.ViewChild, args: ['searchInput', { isSignal: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], collapsedClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsedClass", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], optionsPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionsPlaceholder", required: false }] }], selectedOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedOptions", required: false }] }, { type: i0.Output, args: ["selectedOptionsChange"] }], searchText: [{ type: i0.Output, args: ["searchText"] }] } });
3111
3238
 
3112
3239
  class ShellComponent {
3113
3240
  constructor() {
@@ -3487,68 +3614,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
3487
3614
  }]
3488
3615
  }] });
3489
3616
 
3490
- const termProperties = (term) => Object.keys(term).filter(key => !isExpandable(term[key]) &&
3491
- ![
3492
- 'pinned',
3493
- 'expanded',
3494
- 'extended',
3495
- 'selected',
3496
- 'loading',
3497
- '_score',
3498
- '@type',
3499
- '@id',
3500
- '@context',
3501
- 'createdAt',
3502
- 'updatedAt',
3503
- 'name',
3504
- 'synonyms',
3505
- 'termType',
3506
- 'location',
3507
- 'properties',
3508
- 'schemaVersion',
3509
- 'last-modified'
3510
- ].includes(key));
3511
- const findPropertyById = ({ defaultProperties }, key) => (defaultProperties || []).find(({ term }) => term['@id'] === key);
3512
- const termLocationName = ({ gadmFullName }) => ({
3513
- name: gadmFullName || ''
3514
- });
3515
- const termLocation = ({ latitude, longitude }) => ({
3516
- lat: latitude,
3517
- lng: longitude
3518
- });
3519
- const termTypeToLabel = {
3520
- [TermTermType.methodEmissionResourceUse]: 'Method (Emissions)',
3521
- [TermTermType.methodMeasurement]: 'Method (Measurement)',
3522
- [TermTermType.pesticideAI]: 'Pesticide Active Ingredient',
3523
- [TermTermType.standardsLabels]: 'Standards & Labels',
3524
- [TermTermType.usdaSoilType]: 'USDA Soil Type'
3525
- };
3526
- const termKeyToLabel = {
3527
- pubchem: 'PubChem',
3528
- casNumber: 'CAS Number',
3529
- agrovoc: 'AGROVOC'
3530
- };
3531
- const termTypeLabel = (value = 'N/A') => termTypeToLabel[value] || termKeyToLabel[value] || keyToLabel(value);
3532
- // glossary names are punctuated ("Land transformation, 20 year average") and a reader typing one
3533
- // leaves the punctuation out, so neither side keeps it
3534
- const termSearch = (term = '') => term.replace(/[,\s]/g, '').toLowerCase();
3535
- const suggestTerms = (terms, value) => terms.filter(({ name }) => termSearch(name).includes(termSearch(value)));
3536
-
3537
- class KeyToLabelPipe {
3538
- transform(value) {
3539
- // using termTypeLabel here which defaults to `keyToLabel` function
3540
- return termTypeLabel(value);
3541
- }
3542
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: KeyToLabelPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
3543
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: KeyToLabelPipe, isStandalone: true, name: "keyToLabel" }); }
3544
- }
3545
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: KeyToLabelPipe, decorators: [{
3546
- type: Pipe,
3547
- args: [{
3548
- name: 'keyToLabel'
3549
- }]
3550
- }] });
3551
-
3552
3617
  class NoExtPipe {
3553
3618
  transform(value) {
3554
3619
  return filenameWithoutExt(value || '');
@@ -11723,6 +11788,9 @@ class CyclesNodesComponent {
11723
11788
  this.hasVisibleData = computed(() => countGroupVisibleNodes(Object.values(this.data()).flat()) > 0, ...(ngDevMode ? [{ debugName: "hasVisibleData" }] : []));
11724
11789
  this.filterTermTypes = computed(() => nodeKeyFilterTermTypes$1[this.selectedNodeKey()], ...(ngDevMode ? [{ debugName: "filterTermTypes" }] : []));
11725
11790
  this.filterTerm = signal('', ...(ngDevMode ? [{ debugName: "filterTerm" }] : []));
11791
+ this.termTypes = computed(() => blankNodesTermTypes(this.cycles(), this.nodeKeys()), ...(ngDevMode ? [{ debugName: "termTypes" }] : []));
11792
+ this.selectedTermTypes = linkedSignal({ ...(ngDevMode ? { debugName: "selectedTermTypes" } : {}), source: this.termTypes,
11793
+ computation: (termTypes, previous) => (previous?.value ?? []).filter(termType => termTypes.includes(termType)) });
11726
11794
  this.csvFilename = computed(() => `${this.nodeKeys().join('-')}.csv`, ...(ngDevMode ? [{ debugName: "csvFilename" }] : []));
11727
11795
  this.showHideZeroValues = computed(() => [BlankNodesKey.practices, BlankNodesKey.emissions].includes(this.selectedNodeKey()), ...(ngDevMode ? [{ debugName: "showHideZeroValues" }] : []));
11728
11796
  this.hideZeroValues = signal(false, ...(ngDevMode ? [{ debugName: "hideZeroValues" }] : []));
@@ -11770,11 +11838,11 @@ class CyclesNodesComponent {
11770
11838
  });
11771
11839
  }
11772
11840
  groupNodesByKey({ nodeKey }) {
11773
- const nodesPerCycle = groupNodesByTerm(this.cycles(), nodeKey, filterBlankNode$1(this.filterTerm()), this.hideZeroValues(), this.hideIdentical());
11841
+ const nodesPerCycle = groupNodesByTerm(this.cycles(), nodeKey, filterBlankNode$1(this.filterTerm(), this.selectedTermTypes()), this.hideZeroValues(), this.hideIdentical());
11774
11842
  return orderBy(grouppedKeys(nodesPerCycle), ['key'], ['asc']);
11775
11843
  }
11776
11844
  groupEmissions() {
11777
- const emissionsPerCycle = groupNodesByTerm(this.cycles(), BlankNodesKey.emissions, filterBlankNode$1(this.filterTerm()), this.hideZeroValues(), this.hideIdentical());
11845
+ const emissionsPerCycle = groupNodesByTerm(this.cycles(), BlankNodesKey.emissions, filterBlankNode$1(this.filterTerm(), this.selectedTermTypes()), this.hideZeroValues(), this.hideIdentical());
11778
11846
  const values = orderBy(grouppedKeys(emissionsPerCycle), ['key'], ['asc']);
11779
11847
  const methodTiers = orderBy(unique(values.map(({ value }) => value.methodTier)).map(methodTier => ({
11780
11848
  methodTier,
@@ -11797,7 +11865,7 @@ class CyclesNodesComponent {
11797
11865
  component.headerKeys.set(this.headerKeys());
11798
11866
  }
11799
11867
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CyclesNodesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
11800
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: CyclesNodesComponent, isStandalone: true, selector: "he-cycles-nodes", inputs: { dataState: { classPropertyName: "dataState", publicName: "dataState", isSignal: true, isRequired: false, transformFunction: null }, nodeKeys: { classPropertyName: "nodeKeys", publicName: "nodeKeys", isSignal: true, isRequired: true, transformFunction: null }, nodeKeyGroup: { classPropertyName: "nodeKeyGroup", publicName: "nodeKeyGroup", isSignal: true, isRequired: false, transformFunction: null }, 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\n [class.is-active]=\"selectedGroup() === value.value\"\n [ngbTooltip]=\"value.term.name\"\n placement=\"top\"\n container=\"body\">\n <a (click)=\"selectedGroup.set(value.value)\">\n <span class=\"is-capitalized is-pr-1\">{{ nodeKeyGroup() | pluralize: 1 }}:</span>\n <span>{{ value.value }}</span>\n </a>\n </li>\n }\n </ul>\n </div>\n}\n\n@if (isNodeKeyAllowed()) {\n @switch (selectedView()) {\n @case (View.table) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (hasData()) {\n @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 @if (dataKeys().length > 1) {\n <tr class=\"has-text-weight-bold\">\n <th class=\"width-auto has-border-right\"></th>\n <th class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\"></th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @let blankNodesCount = countGroupVisibleNodes(blankNodes);\n @if (blankNodesCount > 0) {\n <th [attr.colspan]=\"blankNodesCount\" [class.has-border-right]=\"!dataKeyLast\">\n <span>{{ dataKey | keyToLabel }}</span>\n </th>\n }\n }\n </tr>\n }\n <tr class=\"has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n <th class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\"></th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n <th\n [attr.title]=\"node.value.term.name\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n <he-node-link [node]=\"node.value.term\">\n <span\n [innerHtml]=\"\n node.value.term.name | ellipsis: 30 | compound: node.value.term.termType\n \"></span>\n </he-node-link>\n </th>\n }\n }\n }\n </tr>\n <tr class=\"is-italic has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n <th class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\">\n <a [href]=\"schemaBaseUrl + '/Cycle#functionalUnit'\" target=\"_blank\">Functional unit</a>\n </th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n <th\n [attr.title]=\"node.value.term.units\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n <span [innerHtml]=\"node.value.term.units | compound\"></span>\n <he-terms-units-description class=\"is-inline-block is-ml-2\" [term]=\"node.value.term\" />\n </th>\n }\n }\n }\n </tr>\n </thead>\n <tbody>\n @for (cycle of cycles(); track nodeVersionKey(cycle); let cycleIndex = $index) {\n <tr [class.is-suggested]=\"$any(cycle).suggested\">\n <td class=\"width-auto has-border-right\" [attr.title]=\"defaultLabel(cycle)\">\n <he-node-link [node]=\"cycleNode(cycle)\">\n <span class=\"has-text-ellipsis is-ellipsis-3\">\n @if ($any(cycle).suggested) {\n <he-svg-icon name=\"compare\" />\n } @else {\n <span>{{ cycleIndex + 1 }}.</span>\n }\n <span class=\"is-pl-1\">{{ defaultLabel(cycle) }}</span>\n </span>\n </he-node-link>\n </td>\n <td class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\">\n <he-cycles-functional-unit-measure [cycle]=\"cycle\" />\n </td>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n @let cycleData = node.value.values[nodeVersionKey(cycle)];\n <td\n class=\"is-nowrap\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n @if (cycleData) {\n <span\n class=\"trigger-popover\"\n [ngbPopover]=\"details\"\n autoClose=\"outside\"\n popoverClass=\"is-narrow is-overflow-visible\"\n placement=\"left bottom auto\"\n container=\"body\"\n [popoverContext]=\"{ data: cycleData, cycle, key: dataKey }\">\n <span pointer>\n {{ cycleData.propertyValue | precision: 3 | default: '-' }}\n </span>\n <he-blank-node-state\n class=\"ml-1\"\n [dataState]=\"dataState()\"\n [node]=\"cycleData.node\"\n key=\"value\" />\n </span>\n } @else {\n <span>-</span>\n }\n </td>\n }\n }\n }\n </tr>\n }\n </tbody>\n </table>\n </he-data-table>\n } @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\n [dataState]=\"dataState()\"\n [showDeleted]=\"firstNodeKey() === BlankNodesKey.emissions\" />\n <div class=\"is-flex is-flex-wrap-wrap is-gap-8\">\n @if (showHideZeroValues()) {\n <div class=\"field is-relative is-mb-0\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded\"\n [id]=\"componentId() + 'hideZeroValues'\"\n name=\"hideZeroValues\"\n [(ngModel)]=\"hideZeroValues\" />\n <label [for]=\"componentId() + 'hideZeroValues'\">\n <span>\n Hide\n <b>0</b>\n values\n </span>\n </label>\n </div>\n }\n @if (cycles().length > 1) {\n <div class=\"field is-relative is-mb-0\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded\"\n [id]=\"componentId() + 'hideIdenticalValues'\"\n name=\"hideIdenticalValues\"\n [(ngModel)]=\"hideIdenticalSelected\" />\n <label [for]=\"componentId() + 'hideIdenticalValues'\">\n <span>Hide identical values</span>\n </label>\n </div>\n }\n </div>\n </div>\n } @else {\n <div class=\"is-pt-3 has-text-centered\">\n <span>No data available</span>\n @if (filterTerm()) {\n <span class=\"is-pl-1\">matching your search criteria</span>\n }\n <span>.</span>\n @if (showSwitchToRecalculated()) {\n <span>\n Switch to\n <code>recalculated</code>\n version.\n </span>\n }\n </div>\n }\n }\n @case (View.chart) {\n @switch (firstNodeKey()) {\n @case (BlankNodesKey.emissions) {\n <he-cycles-emissions-chart [cycles]=\"cycles()\">\n <ng-container *ngTemplateOutlet=\"selectView\" />\n </he-cycles-emissions-chart>\n }\n }\n }\n @case (View.aggregationLogs) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (selectedNode()) {\n <he-node-aggregation-logs\n [node]=\"selectedNode()\"\n [nodeKey]=\"selectedNodeKey()\"\n [termType]=\"primaryProductTermType()\"\n [termId]=\"primaryProductTermId()\"\n [jlogParentKey]=\"nodeKeyGroup()\"\n [jlogParentIndex]=\"jlogParentIndex()\">\n @if (nodeKeys().length > 1) {\n <div class=\"tabs is-m-0\">\n <ul>\n @for (nodeKey of nodeKeys(); track nodeKey) {\n <li [class.is-active]=\"selectedNodeKey() === nodeKey\">\n <a (click)=\"selectedNodeKey.set(nodeKey)\">{{ nodeKey | keyToLabel }}</a>\n </li>\n }\n </ul>\n </div>\n }\n </he-node-aggregation-logs>\n }\n }\n @case (View.timeline) {\n <he-cycles-nodes-timeline\n [values]=\"timelineValues()\"\n [minDate]=\"selectedCycle().startDate\"\n [maxDate]=\"selectedCycle().endDate\">\n <ng-container *ngTemplateOutlet=\"selectView\" />\n </he-cycles-nodes-timeline>\n }\n @case (View.logs) {\n <!-- keep the cycle selector visible even when the selected cycle has no grouped node (e.g. a cycle\n with no transformations under \"Transformation: Inputs\"), so the user can switch to one that has -->\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (selectedNode()) {\n <he-node-logs-models\n [node]=\"selectedNode()\"\n [cycle]=\"selectedNode()\"\n [nodeKey]=\"selectedNodeKey()\"\n [logsKey]=\"selectedLogsKey()\"\n [jlogParentKey]=\"nodeKeyGroup()\"\n [jlogParentIndex]=\"jlogParentIndex()\"\n [originalValues]=\"selectedOriginalValues()\"\n [recalculatedValues]=\"selectedRecalculatedValues()\"\n [filterTermTypes]=\"filterTermTypes()\">\n @if (nodeKeys().length > 1) {\n <div class=\"tabs is-m-0\">\n <ul>\n @for (nodeKey of nodeKeys(); track nodeKey) {\n <li [class.is-active]=\"selectedNodeKey() === nodeKey\">\n <a (click)=\"selectedNodeKey.set(nodeKey)\">{{ nodeKey | keyToLabel }}</a>\n </li>\n }\n </ul>\n </div>\n }\n </he-node-logs-models>\n } @else if (isGroupNode()) {\n <p class=\"is-p-3 has-text-grey\">\n No recalculation logs for the selected {{ nodeKeyGroup() | pluralize: 1 }} in this cycle \u2014 select another\n cycle above.\n </p>\n }\n }\n }\n}\n\n<ng-template #selectView>\n <div class=\"is-flex is-gap-8 is-align-items-center is-justify-content-space-between\">\n <div class=\"is-flex is-gap-8 is-align-items-center\">\n @if (selectedView() === View.table) {\n @if (hasData()) {\n <button class=\"button is-small is-ghost is-p-2\" (click)=\"showDownload()\">\n <he-svg-icon name=\"download\" />\n </button>\n }\n <he-search-extend\n class=\"is-secondary\"\n collapsedClass=\"is-p-2\"\n placeholder=\"Filter terms by name\"\n (searchText)=\"filterTerm.set($event)\" />\n } @else if (showSelectCycle()) {\n <ng-container *ngTemplateOutlet=\"selectCycle\" />\n }\n </div>\n\n @if (views()?.length > 1) {\n <div class=\"field has-addons button-segments\">\n @for (view of views(); track view) {\n <div class=\"control\">\n <button\n class=\"button is-small\"\n [class.is-selected]=\"selectedView() === view\"\n (click)=\"selectedView.set(view)\">\n <he-svg-icon\n name=\"checkmark\"\n aria-hidden=\"true\"\n class=\"is-hidden-mobile\"\n [class.is-hidden-tablet]=\"selectedView() !== view\" />\n <he-svg-icon\n [name]=\"viewIcon[view]\"\n aria-hidden=\"true\"\n [class.is-hidden-tablet]=\"selectedView() === view\" />\n <span class=\"is-hidden-mobile\">{{ view }}</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #selectCycle>\n @if (selectableCycles().length > 1) {\n <div class=\"field is-horizontal is-mb-0\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary is-nowrap\" for=\"selectCycle\">Cycle</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select [value]=\"selectedIndex()\" (change)=\"selectIndex($event)\" if=\"selectCycle\">\n @for (entry of selectableCycles(); track nodeVersionKey(entry.cycle)) {\n <option [value]=\"entry.index\">{{ entry.index + 1 }}. {{ defaultLabel(entry.cycle) }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n</ng-template>\n\n<ng-template #details let-node=\"cycle\" let-data=\"data\" let-key=\"key\">\n <p>\n <b>{{ defaultLabel(node) }}</b>\n </p>\n <he-node-value-details\n class=\"is-overflow-visible\"\n [data]=\"data\"\n [dataState]=\"dataState()\"\n [nodeType]=\"node['@type']\"\n [dataKey]=\"key\"\n [aggregated]=\"node.aggregated\" />\n</ng-template>\n", styles: [":host{display:block}he-data-table ::ng-deep .table thead tr th:nth-child(2),he-data-table ::ng-deep .table tbody tr td:nth-child(2){max-width:106px;width:106px}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgbPopover, selector: "[ngbPopover]", inputs: ["animation", "autoClose", "ngbPopover", "popoverTitle", "placement", "popperOptions", "triggers", "positionTarget", "container", "disablePopover", "popoverClass", "popoverContext", "openDelay", "closeDelay"], outputs: ["shown", "hidden"], exportAs: ["ngbPopover"] }, { kind: "directive", type: NgbTooltip, selector: "[ngbTooltip]", inputs: ["animation", "autoClose", "placement", "popperOptions", "triggers", "positionTarget", "container", "disableTooltip", "tooltipClass", "tooltipContext", "openDelay", "closeDelay", "ngbTooltip"], outputs: ["shown", "hidden"], exportAs: ["ngbTooltip"] }, { kind: "component", type: HESvgIconComponent, selector: "he-svg-icon", inputs: ["name", "size", "animation"] }, { kind: "component", type: SearchExtendComponent, selector: "he-search-extend", inputs: ["value", "disabled", "placeholder", "class", "collapsedClass"], outputs: ["valueChange", "searchText"] }, { kind: "component", type: DataTableComponent, selector: "he-data-table", inputs: ["minHeight", "maxHeight", "small"] }, { kind: "component", type: NodeLinkComponent, selector: "he-node-link", inputs: ["node", "dataState", "showExternalLink", "linkClass"] }, { kind: "component", type: TermsUnitsDescriptionComponent, selector: "he-terms-units-description", inputs: ["term", "iconTemplate"] }, { kind: "component", type: CyclesFunctionalUnitMeasureComponent, selector: "he-cycles-functional-unit-measure", inputs: ["cycle"] }, { kind: "component", type: BlankNodeStateComponent, selector: "he-blank-node-state", inputs: ["dataState", "nodeType", "dataKey", "key", "node", "state", "linkClass"] }, { kind: "component", type: BlankNodeStateNoticeComponent, selector: "he-blank-node-state-notice", inputs: ["dataState", "showDeleted"] }, { kind: "component", type: CyclesEmissionsChartComponent, selector: "he-cycles-emissions-chart", inputs: ["cycles"] }, { kind: "component", type: CyclesNodesTimelineComponent, selector: "he-cycles-nodes-timeline", inputs: ["values", "maxDate", "minDate"] }, { kind: "component", type: NodeLogsModelsComponent, selector: "he-node-logs-models", inputs: ["node", "nodeKey", "originalValues", "recalculatedValues", "terms", "filterTermTypes", "filterTermTypesLabel", "logsKey", "noDataMessage", "cycle", "jlogParentKey", "jlogParentIndex"] }, { kind: "component", type: 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: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "pipe", type: CompoundPipe, name: "compound" }, { kind: "pipe", type: DefaultPipe, name: "default" }, { kind: "pipe", type: EllipsisPipe, name: "ellipsis" }, { kind: "pipe", type: KeyToLabelPipe, name: "keyToLabel" }, { kind: "pipe", type: PrecisionPipe, name: "precision" }, { kind: "pipe", type: PluralizePipe, name: "pluralize" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
11868
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: CyclesNodesComponent, isStandalone: true, selector: "he-cycles-nodes", inputs: { dataState: { classPropertyName: "dataState", publicName: "dataState", isSignal: true, isRequired: false, transformFunction: null }, nodeKeys: { classPropertyName: "nodeKeys", publicName: "nodeKeys", isSignal: true, isRequired: true, transformFunction: null }, nodeKeyGroup: { classPropertyName: "nodeKeyGroup", publicName: "nodeKeyGroup", isSignal: true, isRequired: false, transformFunction: null }, 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\n [class.is-active]=\"selectedGroup() === value.value\"\n [ngbTooltip]=\"value.term.name\"\n placement=\"top\"\n container=\"body\">\n <a (click)=\"selectedGroup.set(value.value)\">\n <span class=\"is-capitalized is-pr-1\">{{ nodeKeyGroup() | pluralize: 1 }}:</span>\n <span>{{ value.value }}</span>\n </a>\n </li>\n }\n </ul>\n </div>\n}\n\n@if (isNodeKeyAllowed()) {\n @switch (selectedView()) {\n @case (View.table) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (hasData()) {\n @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 @if (dataKeys().length > 1) {\n <tr class=\"has-text-weight-bold\">\n <th class=\"width-auto has-border-right\"></th>\n <th class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\"></th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @let blankNodesCount = countGroupVisibleNodes(blankNodes);\n @if (blankNodesCount > 0) {\n <th [attr.colspan]=\"blankNodesCount\" [class.has-border-right]=\"!dataKeyLast\">\n <span>{{ dataKey | keyToLabel }}</span>\n </th>\n }\n }\n </tr>\n }\n <tr class=\"has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n <th class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\"></th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n <th\n [attr.title]=\"node.value.term.name\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n <he-node-link [node]=\"node.value.term\">\n <span\n [innerHtml]=\"\n node.value.term.name | ellipsis: 30 | compound: node.value.term.termType\n \"></span>\n </he-node-link>\n </th>\n }\n }\n }\n </tr>\n <tr class=\"is-italic has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n <th class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\">\n <a [href]=\"schemaBaseUrl + '/Cycle#functionalUnit'\" target=\"_blank\">Functional unit</a>\n </th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n <th\n [attr.title]=\"node.value.term.units\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n <span [innerHtml]=\"node.value.term.units | compound\"></span>\n <he-terms-units-description class=\"is-inline-block is-ml-2\" [term]=\"node.value.term\" />\n </th>\n }\n }\n }\n </tr>\n </thead>\n <tbody>\n @for (cycle of cycles(); track nodeVersionKey(cycle); let cycleIndex = $index) {\n <tr [class.is-suggested]=\"$any(cycle).suggested\">\n <td class=\"width-auto has-border-right\" [attr.title]=\"defaultLabel(cycle)\">\n <he-node-link [node]=\"cycleNode(cycle)\">\n <span class=\"has-text-ellipsis is-ellipsis-3\">\n @if ($any(cycle).suggested) {\n <he-svg-icon name=\"compare\" />\n } @else {\n <span>{{ cycleIndex + 1 }}.</span>\n }\n <span class=\"is-pl-1\">{{ defaultLabel(cycle) }}</span>\n </span>\n </he-node-link>\n </td>\n <td class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\">\n <he-cycles-functional-unit-measure [cycle]=\"cycle\" />\n </td>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n @let cycleData = node.value.values[nodeVersionKey(cycle)];\n <td\n class=\"is-nowrap\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n @if (cycleData) {\n <span\n class=\"trigger-popover\"\n [ngbPopover]=\"details\"\n autoClose=\"outside\"\n popoverClass=\"is-narrow is-overflow-visible\"\n placement=\"left bottom auto\"\n container=\"body\"\n [popoverContext]=\"{ data: cycleData, cycle, key: dataKey }\">\n <span pointer>\n {{ cycleData.propertyValue | precision: 3 | default: '-' }}\n </span>\n <he-blank-node-state\n class=\"ml-1\"\n [dataState]=\"dataState()\"\n [node]=\"cycleData.node\"\n key=\"value\" />\n </span>\n } @else {\n <span>-</span>\n }\n </td>\n }\n }\n }\n </tr>\n }\n </tbody>\n </table>\n </he-data-table>\n } @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\n [dataState]=\"dataState()\"\n [showDeleted]=\"firstNodeKey() === BlankNodesKey.emissions\" />\n <div class=\"is-flex is-flex-wrap-wrap is-gap-8\">\n @if (showHideZeroValues()) {\n <div class=\"field is-relative is-mb-0\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded\"\n [id]=\"componentId() + 'hideZeroValues'\"\n name=\"hideZeroValues\"\n [(ngModel)]=\"hideZeroValues\" />\n <label [for]=\"componentId() + 'hideZeroValues'\">\n <span>\n Hide\n <b>0</b>\n values\n </span>\n </label>\n </div>\n }\n @if (cycles().length > 1) {\n <div class=\"field is-relative is-mb-0\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded\"\n [id]=\"componentId() + 'hideIdenticalValues'\"\n name=\"hideIdenticalValues\"\n [(ngModel)]=\"hideIdenticalSelected\" />\n <label [for]=\"componentId() + 'hideIdenticalValues'\">\n <span>Hide identical values</span>\n </label>\n </div>\n }\n </div>\n </div>\n } @else {\n <div class=\"is-pt-3 has-text-centered\">\n <span>No data available</span>\n @if (filterTerm() || 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 @switch (firstNodeKey()) {\n @case (BlankNodesKey.emissions) {\n <he-cycles-emissions-chart [cycles]=\"cycles()\">\n <ng-container *ngTemplateOutlet=\"selectView\" />\n </he-cycles-emissions-chart>\n }\n }\n }\n @case (View.aggregationLogs) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (selectedNode()) {\n <he-node-aggregation-logs\n [node]=\"selectedNode()\"\n [nodeKey]=\"selectedNodeKey()\"\n [termType]=\"primaryProductTermType()\"\n [termId]=\"primaryProductTermId()\"\n [jlogParentKey]=\"nodeKeyGroup()\"\n [jlogParentIndex]=\"jlogParentIndex()\">\n @if (nodeKeys().length > 1) {\n <div class=\"tabs is-m-0\">\n <ul>\n @for (nodeKey of nodeKeys(); track nodeKey) {\n <li [class.is-active]=\"selectedNodeKey() === nodeKey\">\n <a (click)=\"selectedNodeKey.set(nodeKey)\">{{ nodeKey | keyToLabel }}</a>\n </li>\n }\n </ul>\n </div>\n }\n </he-node-aggregation-logs>\n }\n }\n @case (View.timeline) {\n <he-cycles-nodes-timeline\n [values]=\"timelineValues()\"\n [minDate]=\"selectedCycle().startDate\"\n [maxDate]=\"selectedCycle().endDate\">\n <ng-container *ngTemplateOutlet=\"selectView\" />\n </he-cycles-nodes-timeline>\n }\n @case (View.logs) {\n <!-- keep the cycle selector visible even when the selected cycle has no grouped node (e.g. a cycle\n with no transformations under \"Transformation: Inputs\"), so the user can switch to one that has -->\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (selectedNode()) {\n <he-node-logs-models\n [node]=\"selectedNode()\"\n [cycle]=\"selectedNode()\"\n [nodeKey]=\"selectedNodeKey()\"\n [logsKey]=\"selectedLogsKey()\"\n [jlogParentKey]=\"nodeKeyGroup()\"\n [jlogParentIndex]=\"jlogParentIndex()\"\n [originalValues]=\"selectedOriginalValues()\"\n [recalculatedValues]=\"selectedRecalculatedValues()\"\n [filterTermTypes]=\"filterTermTypes()\">\n @if (nodeKeys().length > 1) {\n <div class=\"tabs is-m-0\">\n <ul>\n @for (nodeKey of nodeKeys(); track nodeKey) {\n <li [class.is-active]=\"selectedNodeKey() === nodeKey\">\n <a (click)=\"selectedNodeKey.set(nodeKey)\">{{ nodeKey | keyToLabel }}</a>\n </li>\n }\n </ul>\n </div>\n }\n </he-node-logs-models>\n } @else if (isGroupNode()) {\n <p class=\"is-p-3 has-text-grey\">\n No recalculation logs for the selected {{ nodeKeyGroup() | pluralize: 1 }} in this cycle \u2014 select another\n cycle above.\n </p>\n }\n }\n }\n}\n\n<ng-template #selectView>\n <div class=\"is-flex is-gap-8 is-align-items-center is-justify-content-space-between\">\n <div class=\"is-flex is-gap-8 is-align-items-center\">\n @if (selectedView() === View.table) {\n @if (hasData()) {\n <button class=\"button is-small is-ghost is-p-2\" (click)=\"showDownload()\">\n <he-svg-icon name=\"download\" />\n </button>\n }\n <he-search-extend\n class=\"is-secondary\"\n collapsedClass=\"is-p-2\"\n placeholder=\"Filter terms by name\"\n [options]=\"termTypes()\"\n [(selectedOptions)]=\"selectedTermTypes\"\n (searchText)=\"filterTerm.set($event)\" />\n } @else if (showSelectCycle()) {\n <ng-container *ngTemplateOutlet=\"selectCycle\" />\n }\n </div>\n\n @if (views()?.length > 1) {\n <div class=\"field has-addons button-segments\">\n @for (view of views(); track view) {\n <div class=\"control\">\n <button\n class=\"button is-small\"\n [class.is-selected]=\"selectedView() === view\"\n (click)=\"selectedView.set(view)\">\n <he-svg-icon\n name=\"checkmark\"\n aria-hidden=\"true\"\n class=\"is-hidden-mobile\"\n [class.is-hidden-tablet]=\"selectedView() !== view\" />\n <he-svg-icon\n [name]=\"viewIcon[view]\"\n aria-hidden=\"true\"\n [class.is-hidden-tablet]=\"selectedView() === view\" />\n <span class=\"is-hidden-mobile\">{{ view }}</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #selectCycle>\n @if (selectableCycles().length > 1) {\n <div class=\"field is-horizontal is-mb-0\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary is-nowrap\" for=\"selectCycle\">Cycle</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select [value]=\"selectedIndex()\" (change)=\"selectIndex($event)\" if=\"selectCycle\">\n @for (entry of selectableCycles(); track nodeVersionKey(entry.cycle)) {\n <option [value]=\"entry.index\">{{ entry.index + 1 }}. {{ defaultLabel(entry.cycle) }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n</ng-template>\n\n<ng-template #details let-node=\"cycle\" let-data=\"data\" let-key=\"key\">\n <p>\n <b>{{ defaultLabel(node) }}</b>\n </p>\n <he-node-value-details\n class=\"is-overflow-visible\"\n [data]=\"data\"\n [dataState]=\"dataState()\"\n [nodeType]=\"node['@type']\"\n [dataKey]=\"key\"\n [aggregated]=\"node.aggregated\" />\n</ng-template>\n", styles: [":host{display:block}he-data-table ::ng-deep .table thead tr th:nth-child(2),he-data-table ::ng-deep .table tbody tr td:nth-child(2){max-width:106px;width:106px}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgbPopover, selector: "[ngbPopover]", inputs: ["animation", "autoClose", "ngbPopover", "popoverTitle", "placement", "popperOptions", "triggers", "positionTarget", "container", "disablePopover", "popoverClass", "popoverContext", "openDelay", "closeDelay"], outputs: ["shown", "hidden"], exportAs: ["ngbPopover"] }, { kind: "directive", type: NgbTooltip, selector: "[ngbTooltip]", inputs: ["animation", "autoClose", "placement", "popperOptions", "triggers", "positionTarget", "container", "disableTooltip", "tooltipClass", "tooltipContext", "openDelay", "closeDelay", "ngbTooltip"], outputs: ["shown", "hidden"], exportAs: ["ngbTooltip"] }, { kind: "component", type: HESvgIconComponent, selector: "he-svg-icon", inputs: ["name", "size", "animation"] }, { kind: "component", type: SearchExtendComponent, selector: "he-search-extend", inputs: ["value", "disabled", "placeholder", "class", "collapsedClass", "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: "component", type: CyclesFunctionalUnitMeasureComponent, selector: "he-cycles-functional-unit-measure", inputs: ["cycle"] }, { kind: "component", type: BlankNodeStateComponent, selector: "he-blank-node-state", inputs: ["dataState", "nodeType", "dataKey", "key", "node", "state", "linkClass"] }, { kind: "component", type: BlankNodeStateNoticeComponent, selector: "he-blank-node-state-notice", inputs: ["dataState", "showDeleted"] }, { kind: "component", type: CyclesEmissionsChartComponent, selector: "he-cycles-emissions-chart", inputs: ["cycles"] }, { kind: "component", type: CyclesNodesTimelineComponent, selector: "he-cycles-nodes-timeline", inputs: ["values", "maxDate", "minDate"] }, { kind: "component", type: NodeLogsModelsComponent, selector: "he-node-logs-models", inputs: ["node", "nodeKey", "originalValues", "recalculatedValues", "terms", "filterTermTypes", "filterTermTypesLabel", "logsKey", "noDataMessage", "cycle", "jlogParentKey", "jlogParentIndex"] }, { kind: "component", type: 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: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "pipe", type: CompoundPipe, name: "compound" }, { kind: "pipe", type: DefaultPipe, name: "default" }, { kind: "pipe", type: EllipsisPipe, name: "ellipsis" }, { kind: "pipe", type: KeyToLabelPipe, name: "keyToLabel" }, { kind: "pipe", type: PrecisionPipe, name: "precision" }, { kind: "pipe", type: PluralizePipe, name: "pluralize" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
11801
11869
  }
11802
11870
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CyclesNodesComponent, decorators: [{
11803
11871
  type: Component$1,
@@ -11825,7 +11893,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
11825
11893
  KeyToLabelPipe,
11826
11894
  PrecisionPipe,
11827
11895
  PluralizePipe
11828
- ], template: "@if (isGroupNode()) {\n <div class=\"tabs is-mb-1 | group-nodes-tabs\">\n <ul>\n @for (value of groupNodeValues(); track value) {\n <li\n [class.is-active]=\"selectedGroup() === value.value\"\n [ngbTooltip]=\"value.term.name\"\n placement=\"top\"\n container=\"body\">\n <a (click)=\"selectedGroup.set(value.value)\">\n <span class=\"is-capitalized is-pr-1\">{{ nodeKeyGroup() | pluralize: 1 }}:</span>\n <span>{{ value.value }}</span>\n </a>\n </li>\n }\n </ul>\n </div>\n}\n\n@if (isNodeKeyAllowed()) {\n @switch (selectedView()) {\n @case (View.table) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (hasData()) {\n @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 @if (dataKeys().length > 1) {\n <tr class=\"has-text-weight-bold\">\n <th class=\"width-auto has-border-right\"></th>\n <th class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\"></th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @let blankNodesCount = countGroupVisibleNodes(blankNodes);\n @if (blankNodesCount > 0) {\n <th [attr.colspan]=\"blankNodesCount\" [class.has-border-right]=\"!dataKeyLast\">\n <span>{{ dataKey | keyToLabel }}</span>\n </th>\n }\n }\n </tr>\n }\n <tr class=\"has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n <th class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\"></th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n <th\n [attr.title]=\"node.value.term.name\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n <he-node-link [node]=\"node.value.term\">\n <span\n [innerHtml]=\"\n node.value.term.name | ellipsis: 30 | compound: node.value.term.termType\n \"></span>\n </he-node-link>\n </th>\n }\n }\n }\n </tr>\n <tr class=\"is-italic has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n <th class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\">\n <a [href]=\"schemaBaseUrl + '/Cycle#functionalUnit'\" target=\"_blank\">Functional unit</a>\n </th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n <th\n [attr.title]=\"node.value.term.units\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n <span [innerHtml]=\"node.value.term.units | compound\"></span>\n <he-terms-units-description class=\"is-inline-block is-ml-2\" [term]=\"node.value.term\" />\n </th>\n }\n }\n }\n </tr>\n </thead>\n <tbody>\n @for (cycle of cycles(); track nodeVersionKey(cycle); let cycleIndex = $index) {\n <tr [class.is-suggested]=\"$any(cycle).suggested\">\n <td class=\"width-auto has-border-right\" [attr.title]=\"defaultLabel(cycle)\">\n <he-node-link [node]=\"cycleNode(cycle)\">\n <span class=\"has-text-ellipsis is-ellipsis-3\">\n @if ($any(cycle).suggested) {\n <he-svg-icon name=\"compare\" />\n } @else {\n <span>{{ cycleIndex + 1 }}.</span>\n }\n <span class=\"is-pl-1\">{{ defaultLabel(cycle) }}</span>\n </span>\n </he-node-link>\n </td>\n <td class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\">\n <he-cycles-functional-unit-measure [cycle]=\"cycle\" />\n </td>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n @let cycleData = node.value.values[nodeVersionKey(cycle)];\n <td\n class=\"is-nowrap\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n @if (cycleData) {\n <span\n class=\"trigger-popover\"\n [ngbPopover]=\"details\"\n autoClose=\"outside\"\n popoverClass=\"is-narrow is-overflow-visible\"\n placement=\"left bottom auto\"\n container=\"body\"\n [popoverContext]=\"{ data: cycleData, cycle, key: dataKey }\">\n <span pointer>\n {{ cycleData.propertyValue | precision: 3 | default: '-' }}\n </span>\n <he-blank-node-state\n class=\"ml-1\"\n [dataState]=\"dataState()\"\n [node]=\"cycleData.node\"\n key=\"value\" />\n </span>\n } @else {\n <span>-</span>\n }\n </td>\n }\n }\n }\n </tr>\n }\n </tbody>\n </table>\n </he-data-table>\n } @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\n [dataState]=\"dataState()\"\n [showDeleted]=\"firstNodeKey() === BlankNodesKey.emissions\" />\n <div class=\"is-flex is-flex-wrap-wrap is-gap-8\">\n @if (showHideZeroValues()) {\n <div class=\"field is-relative is-mb-0\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded\"\n [id]=\"componentId() + 'hideZeroValues'\"\n name=\"hideZeroValues\"\n [(ngModel)]=\"hideZeroValues\" />\n <label [for]=\"componentId() + 'hideZeroValues'\">\n <span>\n Hide\n <b>0</b>\n values\n </span>\n </label>\n </div>\n }\n @if (cycles().length > 1) {\n <div class=\"field is-relative is-mb-0\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded\"\n [id]=\"componentId() + 'hideIdenticalValues'\"\n name=\"hideIdenticalValues\"\n [(ngModel)]=\"hideIdenticalSelected\" />\n <label [for]=\"componentId() + 'hideIdenticalValues'\">\n <span>Hide identical values</span>\n </label>\n </div>\n }\n </div>\n </div>\n } @else {\n <div class=\"is-pt-3 has-text-centered\">\n <span>No data available</span>\n @if (filterTerm()) {\n <span class=\"is-pl-1\">matching your search criteria</span>\n }\n <span>.</span>\n @if (showSwitchToRecalculated()) {\n <span>\n Switch to\n <code>recalculated</code>\n version.\n </span>\n }\n </div>\n }\n }\n @case (View.chart) {\n @switch (firstNodeKey()) {\n @case (BlankNodesKey.emissions) {\n <he-cycles-emissions-chart [cycles]=\"cycles()\">\n <ng-container *ngTemplateOutlet=\"selectView\" />\n </he-cycles-emissions-chart>\n }\n }\n }\n @case (View.aggregationLogs) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (selectedNode()) {\n <he-node-aggregation-logs\n [node]=\"selectedNode()\"\n [nodeKey]=\"selectedNodeKey()\"\n [termType]=\"primaryProductTermType()\"\n [termId]=\"primaryProductTermId()\"\n [jlogParentKey]=\"nodeKeyGroup()\"\n [jlogParentIndex]=\"jlogParentIndex()\">\n @if (nodeKeys().length > 1) {\n <div class=\"tabs is-m-0\">\n <ul>\n @for (nodeKey of nodeKeys(); track nodeKey) {\n <li [class.is-active]=\"selectedNodeKey() === nodeKey\">\n <a (click)=\"selectedNodeKey.set(nodeKey)\">{{ nodeKey | keyToLabel }}</a>\n </li>\n }\n </ul>\n </div>\n }\n </he-node-aggregation-logs>\n }\n }\n @case (View.timeline) {\n <he-cycles-nodes-timeline\n [values]=\"timelineValues()\"\n [minDate]=\"selectedCycle().startDate\"\n [maxDate]=\"selectedCycle().endDate\">\n <ng-container *ngTemplateOutlet=\"selectView\" />\n </he-cycles-nodes-timeline>\n }\n @case (View.logs) {\n <!-- keep the cycle selector visible even when the selected cycle has no grouped node (e.g. a cycle\n with no transformations under \"Transformation: Inputs\"), so the user can switch to one that has -->\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (selectedNode()) {\n <he-node-logs-models\n [node]=\"selectedNode()\"\n [cycle]=\"selectedNode()\"\n [nodeKey]=\"selectedNodeKey()\"\n [logsKey]=\"selectedLogsKey()\"\n [jlogParentKey]=\"nodeKeyGroup()\"\n [jlogParentIndex]=\"jlogParentIndex()\"\n [originalValues]=\"selectedOriginalValues()\"\n [recalculatedValues]=\"selectedRecalculatedValues()\"\n [filterTermTypes]=\"filterTermTypes()\">\n @if (nodeKeys().length > 1) {\n <div class=\"tabs is-m-0\">\n <ul>\n @for (nodeKey of nodeKeys(); track nodeKey) {\n <li [class.is-active]=\"selectedNodeKey() === nodeKey\">\n <a (click)=\"selectedNodeKey.set(nodeKey)\">{{ nodeKey | keyToLabel }}</a>\n </li>\n }\n </ul>\n </div>\n }\n </he-node-logs-models>\n } @else if (isGroupNode()) {\n <p class=\"is-p-3 has-text-grey\">\n No recalculation logs for the selected {{ nodeKeyGroup() | pluralize: 1 }} in this cycle \u2014 select another\n cycle above.\n </p>\n }\n }\n }\n}\n\n<ng-template #selectView>\n <div class=\"is-flex is-gap-8 is-align-items-center is-justify-content-space-between\">\n <div class=\"is-flex is-gap-8 is-align-items-center\">\n @if (selectedView() === View.table) {\n @if (hasData()) {\n <button class=\"button is-small is-ghost is-p-2\" (click)=\"showDownload()\">\n <he-svg-icon name=\"download\" />\n </button>\n }\n <he-search-extend\n class=\"is-secondary\"\n collapsedClass=\"is-p-2\"\n placeholder=\"Filter terms by name\"\n (searchText)=\"filterTerm.set($event)\" />\n } @else if (showSelectCycle()) {\n <ng-container *ngTemplateOutlet=\"selectCycle\" />\n }\n </div>\n\n @if (views()?.length > 1) {\n <div class=\"field has-addons button-segments\">\n @for (view of views(); track view) {\n <div class=\"control\">\n <button\n class=\"button is-small\"\n [class.is-selected]=\"selectedView() === view\"\n (click)=\"selectedView.set(view)\">\n <he-svg-icon\n name=\"checkmark\"\n aria-hidden=\"true\"\n class=\"is-hidden-mobile\"\n [class.is-hidden-tablet]=\"selectedView() !== view\" />\n <he-svg-icon\n [name]=\"viewIcon[view]\"\n aria-hidden=\"true\"\n [class.is-hidden-tablet]=\"selectedView() === view\" />\n <span class=\"is-hidden-mobile\">{{ view }}</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #selectCycle>\n @if (selectableCycles().length > 1) {\n <div class=\"field is-horizontal is-mb-0\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary is-nowrap\" for=\"selectCycle\">Cycle</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select [value]=\"selectedIndex()\" (change)=\"selectIndex($event)\" if=\"selectCycle\">\n @for (entry of selectableCycles(); track nodeVersionKey(entry.cycle)) {\n <option [value]=\"entry.index\">{{ entry.index + 1 }}. {{ defaultLabel(entry.cycle) }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n</ng-template>\n\n<ng-template #details let-node=\"cycle\" let-data=\"data\" let-key=\"key\">\n <p>\n <b>{{ defaultLabel(node) }}</b>\n </p>\n <he-node-value-details\n class=\"is-overflow-visible\"\n [data]=\"data\"\n [dataState]=\"dataState()\"\n [nodeType]=\"node['@type']\"\n [dataKey]=\"key\"\n [aggregated]=\"node.aggregated\" />\n</ng-template>\n", styles: [":host{display:block}he-data-table ::ng-deep .table thead tr th:nth-child(2),he-data-table ::ng-deep .table tbody tr td:nth-child(2){max-width:106px;width:106px}\n"] }]
11896
+ ], template: "@if (isGroupNode()) {\n <div class=\"tabs is-mb-1 | group-nodes-tabs\">\n <ul>\n @for (value of groupNodeValues(); track value) {\n <li\n [class.is-active]=\"selectedGroup() === value.value\"\n [ngbTooltip]=\"value.term.name\"\n placement=\"top\"\n container=\"body\">\n <a (click)=\"selectedGroup.set(value.value)\">\n <span class=\"is-capitalized is-pr-1\">{{ nodeKeyGroup() | pluralize: 1 }}:</span>\n <span>{{ value.value }}</span>\n </a>\n </li>\n }\n </ul>\n </div>\n}\n\n@if (isNodeKeyAllowed()) {\n @switch (selectedView()) {\n @case (View.table) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (hasData()) {\n @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 @if (dataKeys().length > 1) {\n <tr class=\"has-text-weight-bold\">\n <th class=\"width-auto has-border-right\"></th>\n <th class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\"></th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @let blankNodesCount = countGroupVisibleNodes(blankNodes);\n @if (blankNodesCount > 0) {\n <th [attr.colspan]=\"blankNodesCount\" [class.has-border-right]=\"!dataKeyLast\">\n <span>{{ dataKey | keyToLabel }}</span>\n </th>\n }\n }\n </tr>\n }\n <tr class=\"has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n <th class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\"></th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n <th\n [attr.title]=\"node.value.term.name\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n <he-node-link [node]=\"node.value.term\">\n <span\n [innerHtml]=\"\n node.value.term.name | ellipsis: 30 | compound: node.value.term.termType\n \"></span>\n </he-node-link>\n </th>\n }\n }\n }\n </tr>\n <tr class=\"is-italic has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n <th class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\">\n <a [href]=\"schemaBaseUrl + '/Cycle#functionalUnit'\" target=\"_blank\">Functional unit</a>\n </th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n <th\n [attr.title]=\"node.value.term.units\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n <span [innerHtml]=\"node.value.term.units | compound\"></span>\n <he-terms-units-description class=\"is-inline-block is-ml-2\" [term]=\"node.value.term\" />\n </th>\n }\n }\n }\n </tr>\n </thead>\n <tbody>\n @for (cycle of cycles(); track nodeVersionKey(cycle); let cycleIndex = $index) {\n <tr [class.is-suggested]=\"$any(cycle).suggested\">\n <td class=\"width-auto has-border-right\" [attr.title]=\"defaultLabel(cycle)\">\n <he-node-link [node]=\"cycleNode(cycle)\">\n <span class=\"has-text-ellipsis is-ellipsis-3\">\n @if ($any(cycle).suggested) {\n <he-svg-icon name=\"compare\" />\n } @else {\n <span>{{ cycleIndex + 1 }}.</span>\n }\n <span class=\"is-pl-1\">{{ defaultLabel(cycle) }}</span>\n </span>\n </he-node-link>\n </td>\n <td class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\">\n <he-cycles-functional-unit-measure [cycle]=\"cycle\" />\n </td>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n @let cycleData = node.value.values[nodeVersionKey(cycle)];\n <td\n class=\"is-nowrap\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n @if (cycleData) {\n <span\n class=\"trigger-popover\"\n [ngbPopover]=\"details\"\n autoClose=\"outside\"\n popoverClass=\"is-narrow is-overflow-visible\"\n placement=\"left bottom auto\"\n container=\"body\"\n [popoverContext]=\"{ data: cycleData, cycle, key: dataKey }\">\n <span pointer>\n {{ cycleData.propertyValue | precision: 3 | default: '-' }}\n </span>\n <he-blank-node-state\n class=\"ml-1\"\n [dataState]=\"dataState()\"\n [node]=\"cycleData.node\"\n key=\"value\" />\n </span>\n } @else {\n <span>-</span>\n }\n </td>\n }\n }\n }\n </tr>\n }\n </tbody>\n </table>\n </he-data-table>\n } @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\n [dataState]=\"dataState()\"\n [showDeleted]=\"firstNodeKey() === BlankNodesKey.emissions\" />\n <div class=\"is-flex is-flex-wrap-wrap is-gap-8\">\n @if (showHideZeroValues()) {\n <div class=\"field is-relative is-mb-0\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded\"\n [id]=\"componentId() + 'hideZeroValues'\"\n name=\"hideZeroValues\"\n [(ngModel)]=\"hideZeroValues\" />\n <label [for]=\"componentId() + 'hideZeroValues'\">\n <span>\n Hide\n <b>0</b>\n values\n </span>\n </label>\n </div>\n }\n @if (cycles().length > 1) {\n <div class=\"field is-relative is-mb-0\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded\"\n [id]=\"componentId() + 'hideIdenticalValues'\"\n name=\"hideIdenticalValues\"\n [(ngModel)]=\"hideIdenticalSelected\" />\n <label [for]=\"componentId() + 'hideIdenticalValues'\">\n <span>Hide identical values</span>\n </label>\n </div>\n }\n </div>\n </div>\n } @else {\n <div class=\"is-pt-3 has-text-centered\">\n <span>No data available</span>\n @if (filterTerm() || 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 @switch (firstNodeKey()) {\n @case (BlankNodesKey.emissions) {\n <he-cycles-emissions-chart [cycles]=\"cycles()\">\n <ng-container *ngTemplateOutlet=\"selectView\" />\n </he-cycles-emissions-chart>\n }\n }\n }\n @case (View.aggregationLogs) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (selectedNode()) {\n <he-node-aggregation-logs\n [node]=\"selectedNode()\"\n [nodeKey]=\"selectedNodeKey()\"\n [termType]=\"primaryProductTermType()\"\n [termId]=\"primaryProductTermId()\"\n [jlogParentKey]=\"nodeKeyGroup()\"\n [jlogParentIndex]=\"jlogParentIndex()\">\n @if (nodeKeys().length > 1) {\n <div class=\"tabs is-m-0\">\n <ul>\n @for (nodeKey of nodeKeys(); track nodeKey) {\n <li [class.is-active]=\"selectedNodeKey() === nodeKey\">\n <a (click)=\"selectedNodeKey.set(nodeKey)\">{{ nodeKey | keyToLabel }}</a>\n </li>\n }\n </ul>\n </div>\n }\n </he-node-aggregation-logs>\n }\n }\n @case (View.timeline) {\n <he-cycles-nodes-timeline\n [values]=\"timelineValues()\"\n [minDate]=\"selectedCycle().startDate\"\n [maxDate]=\"selectedCycle().endDate\">\n <ng-container *ngTemplateOutlet=\"selectView\" />\n </he-cycles-nodes-timeline>\n }\n @case (View.logs) {\n <!-- keep the cycle selector visible even when the selected cycle has no grouped node (e.g. a cycle\n with no transformations under \"Transformation: Inputs\"), so the user can switch to one that has -->\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (selectedNode()) {\n <he-node-logs-models\n [node]=\"selectedNode()\"\n [cycle]=\"selectedNode()\"\n [nodeKey]=\"selectedNodeKey()\"\n [logsKey]=\"selectedLogsKey()\"\n [jlogParentKey]=\"nodeKeyGroup()\"\n [jlogParentIndex]=\"jlogParentIndex()\"\n [originalValues]=\"selectedOriginalValues()\"\n [recalculatedValues]=\"selectedRecalculatedValues()\"\n [filterTermTypes]=\"filterTermTypes()\">\n @if (nodeKeys().length > 1) {\n <div class=\"tabs is-m-0\">\n <ul>\n @for (nodeKey of nodeKeys(); track nodeKey) {\n <li [class.is-active]=\"selectedNodeKey() === nodeKey\">\n <a (click)=\"selectedNodeKey.set(nodeKey)\">{{ nodeKey | keyToLabel }}</a>\n </li>\n }\n </ul>\n </div>\n }\n </he-node-logs-models>\n } @else if (isGroupNode()) {\n <p class=\"is-p-3 has-text-grey\">\n No recalculation logs for the selected {{ nodeKeyGroup() | pluralize: 1 }} in this cycle \u2014 select another\n cycle above.\n </p>\n }\n }\n }\n}\n\n<ng-template #selectView>\n <div class=\"is-flex is-gap-8 is-align-items-center is-justify-content-space-between\">\n <div class=\"is-flex is-gap-8 is-align-items-center\">\n @if (selectedView() === View.table) {\n @if (hasData()) {\n <button class=\"button is-small is-ghost is-p-2\" (click)=\"showDownload()\">\n <he-svg-icon name=\"download\" />\n </button>\n }\n <he-search-extend\n class=\"is-secondary\"\n collapsedClass=\"is-p-2\"\n placeholder=\"Filter terms by name\"\n [options]=\"termTypes()\"\n [(selectedOptions)]=\"selectedTermTypes\"\n (searchText)=\"filterTerm.set($event)\" />\n } @else if (showSelectCycle()) {\n <ng-container *ngTemplateOutlet=\"selectCycle\" />\n }\n </div>\n\n @if (views()?.length > 1) {\n <div class=\"field has-addons button-segments\">\n @for (view of views(); track view) {\n <div class=\"control\">\n <button\n class=\"button is-small\"\n [class.is-selected]=\"selectedView() === view\"\n (click)=\"selectedView.set(view)\">\n <he-svg-icon\n name=\"checkmark\"\n aria-hidden=\"true\"\n class=\"is-hidden-mobile\"\n [class.is-hidden-tablet]=\"selectedView() !== view\" />\n <he-svg-icon\n [name]=\"viewIcon[view]\"\n aria-hidden=\"true\"\n [class.is-hidden-tablet]=\"selectedView() === view\" />\n <span class=\"is-hidden-mobile\">{{ view }}</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #selectCycle>\n @if (selectableCycles().length > 1) {\n <div class=\"field is-horizontal is-mb-0\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary is-nowrap\" for=\"selectCycle\">Cycle</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select [value]=\"selectedIndex()\" (change)=\"selectIndex($event)\" if=\"selectCycle\">\n @for (entry of selectableCycles(); track nodeVersionKey(entry.cycle)) {\n <option [value]=\"entry.index\">{{ entry.index + 1 }}. {{ defaultLabel(entry.cycle) }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n</ng-template>\n\n<ng-template #details let-node=\"cycle\" let-data=\"data\" let-key=\"key\">\n <p>\n <b>{{ defaultLabel(node) }}</b>\n </p>\n <he-node-value-details\n class=\"is-overflow-visible\"\n [data]=\"data\"\n [dataState]=\"dataState()\"\n [nodeType]=\"node['@type']\"\n [dataKey]=\"key\"\n [aggregated]=\"node.aggregated\" />\n</ng-template>\n", styles: [":host{display:block}he-data-table ::ng-deep .table thead tr th:nth-child(2),he-data-table ::ng-deep .table tbody tr td:nth-child(2){max-width:106px;width:106px}\n"] }]
11829
11897
  }], ctorParameters: () => [], propDecorators: { dataState: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataState", required: false }] }], nodeKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "nodeKeys", required: true }] }], nodeKeyGroup: [{ type: i0.Input, args: [{ isSignal: true, alias: "nodeKeyGroup", required: false }] }], hideIdenticalValues: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideIdenticalValues", required: false }] }] } });
11830
11898
 
11831
11899
  const labelMaxLength = 25;
@@ -12895,6 +12963,85 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
12895
12963
  ], template: "<form class=\"needs-validation mt-3\" novalidate [formGroup]=\"form\">\n <div class=\"field is-horizontal\">\n <div class=\"field-label is-normal\">\n <label class=\"label\" for=\"productTermId\">\n <span>Product Term ID</span>\n </label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\" [class.has-icons-right]=\"suggestingProductTermId()\">\n <input\n class=\"input\"\n formControlName=\"productTermId\"\n name=\"productTermId\"\n placeholder=\"Search product by ID or name\"\n [editable]=\"false\"\n [ngbTypeahead]=\"suggestProductTermId\"\n [resultTemplate]=\"suggestionProductTermId\"\n [inputFormatter]=\"inputFormatterProductTermId\" />\n <span class=\"icon is-right has-text-grey-dark\" [class.is-hidden]=\"!suggestingProductTermId()\">\n <he-svg-icon name=\"loading\" animation=\"spin\" size=\"20\" />\n </span>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"field is-horizontal mt-3\">\n <div class=\"field-label is-normal\">\n <label class=\"label\" for=\"productTermType\">\n <span>Product Term Type</span>\n </label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-fullwidth\">\n <select formControlName=\"productTermType\" name=\"productTermType\">\n <option [ngValue]=\"undefined\">Select a Type</option>\n @for (termType of productTermTermType; track termType) {\n <option [value]=\"termType\">\n {{ termType | keyToLabel }}\n </option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"field is-horizontal mt-3\">\n <div class=\"field-label is-normal\">\n <label class=\"label\" for=\"tier\">\n <span>Emissions Method Tier</span>\n </label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-fullwidth\">\n <select formControlName=\"tier\" name=\"tier\">\n <option [ngValue]=\"undefined\">Select a Tier</option>\n @for (tier of EmissionMethodTier | keyvalue; track tier) {\n <option [value]=\"tier.value\">{{ tier.value }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"field is-horizontal mt-3\">\n <div class=\"field-label is-normal\">\n <label class=\"label\" for=\"siteType\">\n <span>Site Type</span>\n </label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-fullwidth\">\n <select formControlName=\"siteType\" name=\"siteType\">\n <option [ngValue]=\"undefined\">Select a Type</option>\n @for (siteType of SiteSiteType | keyvalue; track siteType) {\n <option [value]=\"siteType.value\">\n {{ siteType.value }}\n </option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n</form>\n\n<ng-template #suggestionProductTermId let-r=\"result\" let-t=\"term\">\n <ngb-highlight [result]=\"r.name\" [term]=\"t\" />\n</ng-template>\n" }]
12896
12964
  }] });
12897
12965
 
12966
+ const indicatorNames = {
12967
+ gwp100: 'GWP100',
12968
+ eutrophicationPotentialExcludingFate: 'Eutrophication potential, excluding fate',
12969
+ terrestrialAcidificationPotentialIncludingFateAverageEurope: 'Terrestrial acidification potential, including fate, average Europe',
12970
+ freshwaterEutrophicationPotential: 'Freshwater eutrophication potential',
12971
+ agriculturalLandOccupationPotential: 'Agricultural land occupation potential'
12972
+ };
12973
+ const termQuery = (text, termTypes, extraQueries = []) => ({
12974
+ bool: {
12975
+ must: [
12976
+ matchType(NodeType.Term),
12977
+ { bool: { should: suggestMatchQuery(text), minimum_should_match: 1 } },
12978
+ { bool: { should: termTypes.map(matchTermType), minimum_should_match: 1 } },
12979
+ ...extraQueries
12980
+ ]
12981
+ }
12982
+ });
12983
+ const selectedIndicators = (indicators) => Object.fromEntries(defaultRequiredDataIndicators.map(id => [id, !indicators?.length || indicators.includes(id)]));
12984
+ class EngineRequiredDataFormComponent {
12985
+ constructor() {
12986
+ this.formBuilder = inject(FormBuilder);
12987
+ this.searchService = inject(HeSearchService);
12988
+ this.value = input(...(ngDevMode ? [undefined, { debugName: "value" }] : []));
12989
+ this.loading = input(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
12990
+ this.submitted = output();
12991
+ this.siteTypes = Object.values(SiteSiteType);
12992
+ this.indicators = defaultRequiredDataIndicators.map(id => ({ id, name: indicatorNames[id] }));
12993
+ this.form = this.formBuilder.group({
12994
+ product: [undefined, Validators.required],
12995
+ country: [undefined],
12996
+ siteType: [undefined],
12997
+ endDate: [undefined, [Validators.min(1900), Validators.max(2100)]],
12998
+ indicators: this.formBuilder.group(selectedIndicators())
12999
+ });
13000
+ this.suggestingProduct = signal(false, ...(ngDevMode ? [{ debugName: "suggestingProduct" }] : []));
13001
+ this.suggestingCountry = signal(false, ...(ngDevMode ? [{ debugName: "suggestingCountry" }] : []));
13002
+ this.suggestProduct = this.suggest(this.suggestingProduct, text => termQuery(text, productTermTermType.term));
13003
+ this.suggestCountry = this.suggest(this.suggestingCountry, text => termQuery(text, [TermTermType.region], [matchCountry]));
13004
+ this.termFormatter = ({ name }) => name;
13005
+ effect(() => this.value() && this.patch(this.value()));
13006
+ this.form.controls.product.valueChanges
13007
+ .pipe(takeUntilDestroyed())
13008
+ .subscribe(product => this.form.controls.siteType.dirty ||
13009
+ this.form.controls.siteType.setValue(defaultRequiredDataSiteType(product?.termType) ?? null));
13010
+ }
13011
+ patch({ product, country, siteType, endDate, indicators }) {
13012
+ this.form.patchValue({ product, country, endDate: endDate ? +endDate : undefined });
13013
+ this.form.controls.indicators.setValue(selectedIndicators(indicators));
13014
+ if (siteType) {
13015
+ this.form.controls.siteType.setValue(siteType);
13016
+ this.form.controls.siteType.markAsDirty();
13017
+ }
13018
+ }
13019
+ suggest(loading, query) {
13020
+ return text$ => text$.pipe(debounceTime(300), distinctUntilChanged(), tap(() => loading.set(true)), switchMap(text => text.length < 1 ? [[]] : this.searchService.suggest$(text, NodeType.Term, null, query(text))), tap(() => loading.set(false)));
13021
+ }
13022
+ formValue() {
13023
+ const { product, country, siteType, endDate, indicators } = this.form.getRawValue();
13024
+ return {
13025
+ productTermId: product?.['@id'],
13026
+ countryId: country?.['@id'],
13027
+ siteType: siteType || undefined,
13028
+ endDate: endDate ? `${endDate}` : undefined,
13029
+ indicators: Object.entries(indicators)
13030
+ .filter(([, selected]) => selected)
13031
+ .map(([id]) => id)
13032
+ };
13033
+ }
13034
+ submit() {
13035
+ return this.form.valid && this.submitted.emit(this.formValue());
13036
+ }
13037
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: EngineRequiredDataFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
13038
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: EngineRequiredDataFormComponent, isStandalone: true, selector: "he-engine-required-data-form", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { submitted: "submitted" }, ngImport: i0, template: "<form novalidate [formGroup]=\"form\" (ngSubmit)=\"submit()\">\n <div class=\"field\">\n <label class=\"label\" for=\"required-data-product\">Product</label>\n <div class=\"control\" [class.has-icons-right]=\"suggestingProduct()\">\n <input\n id=\"required-data-product\"\n class=\"input\"\n formControlName=\"product\"\n placeholder=\"Search a product by name\"\n [editable]=\"false\"\n [ngbTypeahead]=\"suggestProduct\"\n [resultTemplate]=\"suggestion\"\n [inputFormatter]=\"termFormatter\" />\n @if (suggestingProduct()) {\n <span class=\"icon is-right has-text-grey-dark\">\n <he-svg-icon name=\"loading\" animation=\"spin\" size=\"20\" />\n </span>\n }\n </div>\n </div>\n\n <div class=\"columns is-multiline\">\n <div class=\"column is-6-tablet\">\n <div class=\"field\">\n <label class=\"label\" for=\"required-data-country\">Country</label>\n <div class=\"control\" [class.has-icons-right]=\"suggestingCountry()\">\n <input\n id=\"required-data-country\"\n class=\"input\"\n formControlName=\"country\"\n placeholder=\"Search a country or region (optional)\"\n [editable]=\"false\"\n [ngbTypeahead]=\"suggestCountry\"\n [resultTemplate]=\"suggestion\"\n [inputFormatter]=\"termFormatter\" />\n @if (suggestingCountry()) {\n <span class=\"icon is-right has-text-grey-dark\">\n <he-svg-icon name=\"loading\" animation=\"spin\" size=\"20\" />\n </span>\n }\n </div>\n </div>\n </div>\n\n <div class=\"column is-3-tablet\">\n <div class=\"field\">\n <label class=\"label\" for=\"required-data-site-type\">Site type</label>\n <div class=\"control\">\n <div class=\"select is-fullwidth\">\n <select id=\"required-data-site-type\" formControlName=\"siteType\">\n <option [ngValue]=\"null\">Any</option>\n @for (siteType of siteTypes; track siteType) {\n <option [ngValue]=\"siteType\">{{ siteType }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"column is-3-tablet\">\n <div class=\"field\">\n <label class=\"label\" for=\"required-data-end-date\">Harvest year</label>\n <div class=\"control\">\n <input\n id=\"required-data-end-date\"\n class=\"input\"\n type=\"number\"\n formControlName=\"endDate\"\n placeholder=\"Optional\" />\n </div>\n </div>\n </div>\n </div>\n\n <fieldset class=\"field\" formGroupName=\"indicators\">\n <legend class=\"label\">Indicators</legend>\n @for (indicator of indicators; track indicator.id) {\n <div class=\"control\">\n <label class=\"checkbox\">\n <input type=\"checkbox\" [formControlName]=\"indicator.id\" />\n <span class=\"ml-2\">{{ indicator.name }}</span>\n </label>\n </div>\n }\n </fieldset>\n\n <div class=\"field\">\n <div class=\"control\">\n <button class=\"button is-primary\" type=\"submit\" [class.is-loading]=\"loading()\" [disabled]=\"form.invalid\">\n Show the data to collect\n </button>\n </div>\n </div>\n</form>\n\n<ng-template #suggestion let-r=\"result\" let-t=\"term\">\n <ngb-highlight [result]=\"r.name\" [term]=\"t\" />\n</ng-template>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { 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.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { 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: "component", type: NgbHighlight, selector: "ngb-highlight", inputs: ["highlightClass", "result", "term", "accentSensitive"] }, { kind: "component", type: HESvgIconComponent, selector: "he-svg-icon", inputs: ["name", "size", "animation"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
13039
+ }
13040
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: EngineRequiredDataFormComponent, decorators: [{
13041
+ type: Component$1,
13042
+ args: [{ selector: 'he-engine-required-data-form', changeDetection: ChangeDetectionStrategy.OnPush, imports: [ReactiveFormsModule, NgbTypeahead, NgbHighlight, HESvgIconComponent], template: "<form novalidate [formGroup]=\"form\" (ngSubmit)=\"submit()\">\n <div class=\"field\">\n <label class=\"label\" for=\"required-data-product\">Product</label>\n <div class=\"control\" [class.has-icons-right]=\"suggestingProduct()\">\n <input\n id=\"required-data-product\"\n class=\"input\"\n formControlName=\"product\"\n placeholder=\"Search a product by name\"\n [editable]=\"false\"\n [ngbTypeahead]=\"suggestProduct\"\n [resultTemplate]=\"suggestion\"\n [inputFormatter]=\"termFormatter\" />\n @if (suggestingProduct()) {\n <span class=\"icon is-right has-text-grey-dark\">\n <he-svg-icon name=\"loading\" animation=\"spin\" size=\"20\" />\n </span>\n }\n </div>\n </div>\n\n <div class=\"columns is-multiline\">\n <div class=\"column is-6-tablet\">\n <div class=\"field\">\n <label class=\"label\" for=\"required-data-country\">Country</label>\n <div class=\"control\" [class.has-icons-right]=\"suggestingCountry()\">\n <input\n id=\"required-data-country\"\n class=\"input\"\n formControlName=\"country\"\n placeholder=\"Search a country or region (optional)\"\n [editable]=\"false\"\n [ngbTypeahead]=\"suggestCountry\"\n [resultTemplate]=\"suggestion\"\n [inputFormatter]=\"termFormatter\" />\n @if (suggestingCountry()) {\n <span class=\"icon is-right has-text-grey-dark\">\n <he-svg-icon name=\"loading\" animation=\"spin\" size=\"20\" />\n </span>\n }\n </div>\n </div>\n </div>\n\n <div class=\"column is-3-tablet\">\n <div class=\"field\">\n <label class=\"label\" for=\"required-data-site-type\">Site type</label>\n <div class=\"control\">\n <div class=\"select is-fullwidth\">\n <select id=\"required-data-site-type\" formControlName=\"siteType\">\n <option [ngValue]=\"null\">Any</option>\n @for (siteType of siteTypes; track siteType) {\n <option [ngValue]=\"siteType\">{{ siteType }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"column is-3-tablet\">\n <div class=\"field\">\n <label class=\"label\" for=\"required-data-end-date\">Harvest year</label>\n <div class=\"control\">\n <input\n id=\"required-data-end-date\"\n class=\"input\"\n type=\"number\"\n formControlName=\"endDate\"\n placeholder=\"Optional\" />\n </div>\n </div>\n </div>\n </div>\n\n <fieldset class=\"field\" formGroupName=\"indicators\">\n <legend class=\"label\">Indicators</legend>\n @for (indicator of indicators; track indicator.id) {\n <div class=\"control\">\n <label class=\"checkbox\">\n <input type=\"checkbox\" [formControlName]=\"indicator.id\" />\n <span class=\"ml-2\">{{ indicator.name }}</span>\n </label>\n </div>\n }\n </fieldset>\n\n <div class=\"field\">\n <div class=\"control\">\n <button class=\"button is-primary\" type=\"submit\" [class.is-loading]=\"loading()\" [disabled]=\"form.invalid\">\n Show the data to collect\n </button>\n </div>\n </div>\n</form>\n\n<ng-template #suggestion let-r=\"result\" let-t=\"term\">\n <ngb-highlight [result]=\"r.name\" [term]=\"t\" />\n</ng-template>\n" }]
13043
+ }], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], submitted: [{ type: i0.Output, args: ["submitted"] }] } });
13044
+
12898
13045
  /**
12899
13046
  * Angular-side adapter over the framework-agnostic error catalog.
12900
13047
  *
@@ -13227,10 +13374,11 @@ const isOpenDefault = (schemaType) => [SchemaType.Term].includes(schemaType);
13227
13374
  const isKeyClosedVisible = (key) => ['id', '@id', 'originalId'].includes(key);
13228
13375
  const isKeyHidden = (key) => ['type', '@type'].includes(key);
13229
13376
  const isKeyRequired = (key, def) => ['type', 'id'].includes(key) || (def?.required || []).includes(key);
13230
- const propertyError = (errors) => (dataPath, nonExpandableArray = false) => errors.find(error => (error.dataPath === dataPath ||
13377
+ const propertyErrors = (errors) => (dataPath, nonExpandableArray = false) => errors.filter(error => (error.dataPath === dataPath ||
13231
13378
  (nonExpandableArray &&
13232
13379
  nonExpandableArrayDataPath(error.dataPath) === nonExpandableArrayDataPath(dataPath))) &&
13233
13380
  (dataPath.length > 0 || !isMissingPropertyError(error)));
13381
+ const propertyError = (errors) => (dataPath, nonExpandableArray = false) => propertyErrors(errors)(dataPath, nonExpandableArray)[0];
13234
13382
  const expectedSchemaType = (schema) => {
13235
13383
  const def = (schema?.items ?? schema);
13236
13384
  const type = def ? definitionToSchemaType(def) : null;
@@ -13958,7 +14106,8 @@ class FilesFormComponent {
13958
14106
  ? `/${nodeLink({ '@type': this.schemaType(), '@id': this.nodeId() }, nodeDataState({ '@type': this.schemaType(), aggregated: this.node().aggregated }))}`
13959
14107
  : '', ...(ngDevMode ? [{ debugName: "nodeUrl" }] : []));
13960
14108
  this.filteredErrors = computed(() => this.errors()?.filter(filterError) ?? [], ...(ngDevMode ? [{ debugName: "filteredErrors" }] : []));
13961
- this.nodeError = computed(() => propertyError(this.filteredErrors())(''), ...(ngDevMode ? [{ debugName: "nodeError" }] : []));
14109
+ this.nodeErrors = computed(() => propertyErrors(this.filteredErrors())(''), ...(ngDevMode ? [{ debugName: "nodeErrors" }] : []));
14110
+ this.nodeError = computed(() => this.nodeErrors()[0], ...(ngDevMode ? [{ debugName: "nodeError" }] : []));
13962
14111
  this.nodeProperty = computed(() => this.schema()
13963
14112
  ? {
13964
14113
  id: propertyId(),
@@ -13980,6 +14129,19 @@ class FilesFormComponent {
13980
14129
  formatter: formatter$1('')
13981
14130
  }
13982
14131
  : undefined, ...(ngDevMode ? [{ debugName: "nodeProperty" }] : []));
14132
+ /**
14133
+ * A node can have several errors of its own, each shown on its own line.
14134
+ */
14135
+ this.nodeErrorProperties = computed(() => this.nodeProperty()
14136
+ ? this.nodeErrors().map(error => ({
14137
+ ...this.nodeProperty(),
14138
+ id: propertyId(),
14139
+ error: formatError(error),
14140
+ errorGuidePageId: guidePageId(this.schemaType(), error.message),
14141
+ hasError: errorHasError(error),
14142
+ hasWarning: errorHasWarning(error)
14143
+ }))
14144
+ : [], ...(ngDevMode ? [{ debugName: "nodeErrorProperties" }] : []));
13983
14145
  this.properties = computed(() => [!isUndefined(this.schemas()), !isUndefined(this.node())].every(Boolean)
13984
14146
  ? recursiveProperties(this.schemas(), this.filteredErrors(), this.schema(), false)(this.node())
13985
14147
  : [], ...(ngDevMode ? [{ debugName: "properties" }] : []));
@@ -14024,7 +14186,7 @@ class FilesFormComponent {
14024
14186
  return focusFirstError(this.ref.nativeElement);
14025
14187
  }
14026
14188
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: FilesFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
14027
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: FilesFormComponent, isStandalone: true, selector: "he-files-form", inputs: { isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null }, node: { classPropertyName: "node", publicName: "node", isSignal: true, isRequired: true, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, showNodeLink: { classPropertyName: "showNodeLink", publicName: "showNodeLink", isSignal: true, isRequired: false, transformFunction: null }, errorGuidePrefix: { classPropertyName: "errorGuidePrefix", publicName: "errorGuidePrefix", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { isOpen: "isOpenChange", nodeErorrResolved: "nodeErorrResolved" }, exportAs: ["filesForm"], ngImport: i0, template: "<div class=\"is-flex is-flex-direction-column is-align-items-flex-start is-align-self-stretch | files-form-container\">\n <div\n class=\"is-flex is-flex-direction-row is-justify-content-space-between is-align-items-center is-align-self-stretch is-gap-16 px-4 py-2 has-text-secondary | files-form-header\"\n (click)=\"isOpen.set(!isOpen())\"\n pointer>\n <div class=\"is-flex is-gap-8 is-align-items-center\">\n @if (nodeProperty()) {\n <he-node-icon class=\"is-flex\" [type]=\"schemaType()\" [size]=\"24\" />\n <span class=\"has-text-weight-bold has-text-secondary is-size-5\">{{ schemaType() }}</span>\n @if (nodeProperty().hasError || hasError()) {\n <he-svg-icon name=\"xmark-circle\" class=\"has-text-danger is-flex is-align-items-center\" />\n <span class=\"has-text-danger has-text-weight-bold is-italic\">{{ errorLabel() }}</span>\n } @else if (nodeProperty().hasWarning || hasWarning()) {\n <he-svg-icon name=\"exclamation-triangle\" class=\"has-text-warning is-flex is-align-items-center\" />\n <span class=\"has-text-warning has-text-weight-bold is-italic\">{{ warningLabel() }}</span>\n }\n }\n </div>\n @if ((showNodeLink() && nodeUrl()) || canOpen()) {\n <div class=\"is-flex is-flex-direction-row is-align-items-center is-gap-16\">\n @if (showNodeLink() && nodeUrl()) {\n <ng-container *ngTemplateOutlet=\"nodeLink; context: { url: nodeUrl(), nodeType: schemaType() }\" />\n }\n @if (canOpen()) {\n <he-svg-icon [name]=\"isOpen() ? 'minus' : 'plus'\" />\n }\n </div>\n }\n </div>\n\n <div class=\"is-flex is-flex-direction-column is-align-items-flex-start is-align-self-stretch\">\n @if (isOpen()) {\n @if (nodeProperty()?.error) {\n <ng-container\n *ngTemplateOutlet=\"\n propertyError;\n context: { property: nodeProperty(), classes: 'is-my-1 is-py-1 is-px-3' }\n \" />\n }\n }\n\n @if (unmatchedErrors().length) {\n @for (property of unmatchedErrors(); track property.id) {\n <ng-container *ngTemplateOutlet=\"propertyError; context: { property, classes: 'is-my-1 is-py-1 is-px-3' }\" />\n }\n }\n\n <div class=\"is-flex is-flex-direction-row is-flex-wrap-wrap is-align-self-stretch\">\n @for (property of properties(); track trackByProperty($index, property)) {\n <ng-container *ngTemplateOutlet=\"showProperty; context: { $implicit: property }\" />\n }\n </div>\n\n @if (isOpen()) {\n <ng-container *ngTemplateOutlet=\"propertyMap; context: { $implicit: nodeProperty() }\" />\n }\n </div>\n\n <ng-content />\n</div>\n\n<ng-template #propertyKeyTooltip let-property=\"property\">\n <markdown [data]=\"property.schema.description\" />\n</ng-template>\n\n<ng-template #propertyKey let-property=\"property\">\n @if (property.schema?.description) {\n <span\n class=\"trigger-popover | property-key\"\n [ngbTooltip]=\"propertyKeyTooltip\"\n [tooltipContext]=\"{ property }\"\n triggers=\"click\"\n autoClose=\"outside\"\n tooltipClass=\"property-tooltip\"\n placement=\"bottom-left auto\"\n container=\"body\"\n (click)=\"$event.stopPropagation()\">\n <span>{{ property.key }}</span>\n </span>\n } @else {\n <span>{{ property.key }}</span>\n }\n</ng-template>\n\n<ng-template #propertyContent let-property=\"property\">\n <div class=\"is-flex is-align-items-center is-flex-wrap-wrap is-gap-4\">\n <div class=\"is-flex has-text-secondary\">\n <ng-container *ngTemplateOutlet=\"propertyKey; context: { property }\" />\n <span>:</span>\n </div>\n\n <!--\n The value, the icons and \"Show more\" share one inline flow. As sibling flex items they wrap\n onto a line of their own as soon as the value fills the row, which is how the copy icon ended\n up under the text instead of at the end of it.\n -->\n <span class=\"is-size-7 | property-value\">\n @if (property.isCollapsible && property.showMaxLength) {\n {{ property.value | ellipsis: property.showMaxLength }}\n <a class=\"is-pl-1\" (click)=\"property.showMaxLength = 0\">Show more</a>\n } @else {\n {{ property.value }}\n }\n\n @if (property.schema?.internal && property.key !== 'originalId') {\n <span class=\"is-pl-1 | property-internal\" ngbTooltip=\"This value is auto-generated.\">\n <he-svg-icon name=\"autogenerate-circle\" />\n </span>\n }\n\n <span class=\"is-pl-1 | copy-button\">\n <he-clipboard [value]=\"property.value\" [hideText]=\"true\" clipboardClass=\"no-print\" />\n </span>\n </span>\n </div>\n\n <div class=\"is-flex is-gap-8\">\n @if (property.externalUrl?.url) {\n <a\n [href]=\"property.externalUrl.url + (property.externalUrl.urlParamValue ? property.value : '')\"\n target=\"_blank\"\n [title]=\"property.externalUrl.title\"\n class=\"ml-2\"\n [ngClass]=\"{ 'is-info': property.key === 'type' }\"\n [attr.disabled]=\"property.externalUrl.urlParamValue && !property.value ? true : null\">\n <he-svg-icon [name]=\"property.externalUrl.icon || 'external-link'\" />\n </a>\n }\n </div>\n</ng-template>\n\n<ng-template #showProperty let-property>\n @if ((isOpen() || property.closedVisible) && !property.isHidden) {\n @if (property.properties.length) {\n <div class=\"is-flex is-flex-direction-column is-flex-wrap-wrap w-100 | properties-container\">\n <div\n class=\"is-flex is-flex-direction-row is-justify-content-space-between is-gap-4 has-text-secondary w-100 | properties-container--title\"\n (click)=\"property.isOpen = !property.isOpen\"\n pointer\n [class.is-open]=\"property.isOpen\"\n [class.is-group-error-danger]=\"property.hasError\"\n [class.is-group-error-warning]=\"!property.hasError && property.hasWarning\">\n <div class=\"is-flex is-gap-8 has-text-weight-bold\">\n <!-- @if (property.schemaType === SchemaType.Term) {\n <he-node-icon [type]=\"property.schemaType\" />\n } -->\n <ng-container *ngTemplateOutlet=\"propertyKey; context: { property }\" />\n </div>\n <he-svg-icon [name]=\"property.isOpen ? 'minus' : 'plus'\" />\n </div>\n @if (property.isOpen) {\n @if (property.error) {\n <ng-container *ngTemplateOutlet=\"propertyError; context: { property, classes: 'is-my-1 is-px-3' }\" />\n }\n @if (property.isArray) {\n <div class=\"py-2 px-3 w-100\">\n @if (property.hasError) {\n <div class=\"is-flex is-align-items-center is-size-7 is-italic is-mb-2 has-text-warning\">\n <he-svg-icon name=\"exclamation-triangle\" />\n @if (showAllErrors()) {\n <a class=\"is-pl-2\" (click)=\"showAllErrors.set(false)\">Only show items in error.</a>\n } @else {\n <span class=\"is-pl-2\">Only showing items in error.</span>\n <a class=\"is-pl-1\" (click)=\"showAllErrors.set(true)\">Show all items</a>\n }\n </div>\n }\n\n @for (prop2 of property.properties; track trackByProperty($index, prop2)) {\n @if (prop2.key && (showAllErrors() || !property.hasError || prop2.hasError)) {\n <div class=\"pt-2 my-4 | property-array-container\" [id]=\"prop2.fullKey + '_' + prop2.id\">\n <div class=\"ml-2 is-mb-2 | property-array-number\">\n <span class=\"has-text-info is-px-1 | number-tag\">{{ prop2.key }}</span>\n </div>\n @if (prop2.error) {\n <ng-container\n *ngTemplateOutlet=\"propertyError; context: { property: prop2, classes: 'is-py-1 is-px-3' }\" />\n }\n <div class=\"p-3\">\n <div class=\"is-flex is-flex-direction-row is-flex-wrap-wrap is-align-self-stretch\">\n @for (prop3 of prop2.properties; track trackByProperty($index, prop3)) {\n <ng-container *ngTemplateOutlet=\"showProperty; context: { $implicit: prop3 }\" />\n }\n </div>\n </div>\n </div>\n }\n }\n </div>\n } @else {\n <div class=\"is-flex is-flex-direction-row is-flex-wrap-wrap is-align-self-stretch\">\n @for (prop2 of property.properties; track trackByProperty($index, prop2)) {\n <ng-container *ngTemplateOutlet=\"showProperty; context: { $implicit: prop2 }\" />\n }\n </div>\n }\n }\n </div>\n } @else {\n <div\n class=\"is-flex is-flex-direction-column is-gap-4 | property-container\"\n [class.is-error-danger]=\"property.hasError\"\n [class.is-error-warning]=\"!property.hasError && property.hasWarning\">\n <div\n class=\"is-flex is-flex-direction-row is-align-items-center is-justify-content-space-between is-gap-4 | field-container\">\n @if (property.key) {\n <ng-container *ngTemplateOutlet=\"propertyContent; context: { property }\" />\n }\n </div>\n @if (property.hasError || property.hasWarning) {\n <ng-container *ngTemplateOutlet=\"propertyError; context: { property }\" />\n }\n </div>\n }\n }\n</ng-template>\n\n<ng-template #propertyError let-property=\"property\" let-classes=\"classes\">\n @if (property.error?.message) {\n <div\n class=\"is-flex is-flex-direction-row is-gap-8 is-size-6 is-m-0 w-100 has-text-grey {{ classes }} | property-error\"\n [class.is-error-danger]=\"property.hasError\"\n [class.is-error-warning]=\"!property.hasError && property.hasWarning\">\n @if (property.hasError) {\n <he-svg-icon name=\"xmark-circle\" size=\"24\" class=\"has-text-danger is-flex-grow-0\" />\n } @else {\n <he-svg-icon name=\"exclamation-triangle\" size=\"24\" class=\"has-text-warning is-flex-grow-0\" />\n }\n\n <div class=\"is-flex is-flex-direction-column is-align-items-start is-flex-grow-1\">\n <span [innerHTML]=\"property.error.message\"></span>\n <he-files-error-distribution [error]=\"property.error\" />\n </div>\n\n @if (errorGuidePrefix() && property.errorGuidePageId) {\n <he-guide-overlay class=\"is-flex-grow-0\" [pageId]=\"errorGuidePrefix() + property.errorGuidePageId\" />\n }\n\n @if (property.error.index >= 0) {\n @if (property.hasWarning) {\n <a class=\"is-flex is-align-items-center is-flex-shrink-0\" (click)=\"resolveError(property)\">\n <he-svg-icon name=\"checkmark\" />\n <span class=\"is-pl-2\">Resolved</span>\n </a>\n }\n }\n </div>\n }\n</ng-template>\n\n<ng-template #propertyMap let-property>\n @if (showMap()) {\n <div class=\"is-flex is-flex-direction-column is-flex-wrap-wrap w-100 | properties-container\">\n <div\n class=\"is-flex is-flex-direction-row is-justify-content-space-between is-gap-4 w-100 | properties-container--title\"\n (click)=\"mapVisible.set(!mapVisible())\"\n pointer\n [class.is-open]=\"mapVisible()\">\n <span class=\"is-size-6\">View on Map</span>\n <he-svg-icon [name]=\"mapVisible() ? 'minus' : 'plus'\" />\n </div>\n @if (mapVisible()) {\n <he-sites-maps [sites]=\"[node()]\" [showNotice]=\"false\" />\n }\n </div>\n }\n</ng-template>\n\n<ng-template #nodeLink let-url=\"url\" let-nodeType=\"nodeType\">\n <a class=\"external-link\" [href]=\"url\" target=\"_blank\" (click)=\"$event.stopPropagation()\">\n <span class=\"is-hidden-mobile\">View</span>\n <span class=\"is-hidden-mobile is-pl-1\">{{ nodeType }}</span>\n <he-svg-icon name=\"external-link\" class=\"ml-2\" />\n </a>\n</ng-template>\n", styles: [".notification{color:#0a0a0a!important}.notification.is-success{background-color:#d5f3d8}.notification.is-success *:not(.button):not(.icon):not(.dropdown-item)>fa-icon,.notification.is-success>fa-icon,.notification.is-success *:not(.button):not(.icon):not(.dropdown-item)>he-svg-icon,.notification.is-success>he-svg-icon{color:#2b8434}.notification.is-info{background-color:#d3ebed}.notification.is-info *:not(.button):not(.icon):not(.dropdown-item)>fa-icon,.notification.is-info>fa-icon,.notification.is-info *:not(.button):not(.icon):not(.dropdown-item)>he-svg-icon,.notification.is-info>he-svg-icon{color:#249da5}.notification.is-warning{background-color:#ffdec0}.notification.is-warning *:not(.button):not(.icon):not(.dropdown-item)>fa-icon,.notification.is-warning>fa-icon,.notification.is-warning *:not(.button):not(.icon):not(.dropdown-item)>he-svg-icon,.notification.is-warning>he-svg-icon{color:#ff881b}.notification.is-danger{background-color:#ffcdd0}.notification.is-danger *:not(.button):not(.icon):not(.dropdown-item)>fa-icon,.notification.is-danger>fa-icon,.notification.is-danger *:not(.button):not(.icon):not(.dropdown-item)>he-svg-icon,.notification.is-danger>he-svg-icon{color:#ff3844}he-sites-maps{height:200px}.external-link{color:#4c7194}.files-form-container{box-shadow:2px 2px 4px #00000029;background-color:#fff}.files-form-header{padding:10px 12px;background-color:#dbe3ea;border-top-left-radius:3px;border-top-right-radius:3px}.properties-container--title,.property-container{padding:6px 12px}.property-container{flex:none;flex-grow:1;min-width:50%;max-width:100%;border:1px solid #f5f5f5}.property-container.is-error-danger{border-color:#ff3844}.property-container.is-error-warning{border-color:#ff881b}.properties-container--title{border-top:1px solid #dbe3ea;border-bottom:1px solid #dbe3ea;background:#f5f7f9}.properties-container .properties-container{border-radius:6px;border:1px solid #dbe3ea;margin:4px 0}.properties-container .properties-container--title{border-top:none}.property-internal{color:#249da5}.property-internal,.copy-button{vertical-align:middle}.property-internal he-svg-icon,.copy-button he-svg-icon{vertical-align:middle}.property-key,.property-value{word-break:break-word}.property-array-container{border-radius:6px;border:1px solid #dbdbdb}.number-tag{border:1px solid #249da5;border-radius:50%}.copy-button{visibility:hidden}.field-container:hover .copy-button{visibility:visible}.is-group-error-danger{background-color:#ffcdd0}.is-group-error-warning{background-color:#ffdec0}.property-error.is-error-danger{background-color:#ffeced}.field-container+.property-error.is-error-danger{background-color:transparent;color:#ff3844!important}.property-error.is-error-warning{background-color:#fff5ec}.field-container+.property-error.is-error-warning{background-color:transparent;color:#ff881b!important}::ng-deep .property-tooltip{background-color:#fff;color:#0a0a0a;border:1px solid #dbdbdb;z-index:11;max-width:50vw;max-height:50vh;overflow:auto}::ng-deep .property-tooltip pre{white-space:pre-wrap}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: MarkdownComponent, selector: "markdown, [markdown]", inputs: ["data", "src", "disableSanitizer", "inline", "clipboard", "clipboardButtonComponent", "clipboardButtonTemplate", "emoji", "katex", "katexOptions", "mermaid", "mermaidOptions", "lineHighlight", "line", "lineOffset", "lineNumbers", "start", "commandLine", "filterOutput", "host", "prompt", "output", "user"], outputs: ["error", "load", "ready"] }, { kind: "directive", type: NgbTooltip, selector: "[ngbTooltip]", inputs: ["animation", "autoClose", "placement", "popperOptions", "triggers", "positionTarget", "container", "disableTooltip", "tooltipClass", "tooltipContext", "openDelay", "closeDelay", "ngbTooltip"], outputs: ["shown", "hidden"], exportAs: ["ngbTooltip"] }, { kind: "component", type: NodeIconComponent, selector: "he-node-icon", inputs: ["type", "size"] }, { kind: "component", type: SitesMapsComponent, selector: "he-sites-maps", inputs: ["loadPolygons", "sites", "zoom", "showNotice"] }, { kind: "component", type: HESvgIconComponent, selector: "he-svg-icon", inputs: ["name", "size", "animation"] }, { kind: "component", type: ClipboardComponent, selector: "he-clipboard", inputs: ["icon", "value", "disabled", "hideText", "hideIcon", "size", "clipboardClass", "tooltipPlacement"] }, { kind: "component", type: GuideOverlayComponent, selector: "he-guide-overlay", inputs: ["pageId", "width", "height", "positions"], outputs: ["widthChange", "heightChange"] }, { kind: "component", type: FilesErrorDistributionComponent, selector: "he-files-error-distribution", inputs: ["error"] }, { kind: "pipe", type: EllipsisPipe, name: "ellipsis" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
14189
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: FilesFormComponent, isStandalone: true, selector: "he-files-form", inputs: { isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null }, node: { classPropertyName: "node", publicName: "node", isSignal: true, isRequired: true, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, showNodeLink: { classPropertyName: "showNodeLink", publicName: "showNodeLink", isSignal: true, isRequired: false, transformFunction: null }, errorGuidePrefix: { classPropertyName: "errorGuidePrefix", publicName: "errorGuidePrefix", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { isOpen: "isOpenChange", nodeErorrResolved: "nodeErorrResolved" }, exportAs: ["filesForm"], ngImport: i0, template: "<div class=\"is-flex is-flex-direction-column is-align-items-flex-start is-align-self-stretch | files-form-container\">\n <div\n class=\"is-flex is-flex-direction-row is-justify-content-space-between is-align-items-center is-align-self-stretch is-gap-16 px-4 py-2 has-text-secondary | files-form-header\"\n (click)=\"isOpen.set(!isOpen())\"\n pointer>\n <div class=\"is-flex is-gap-8 is-align-items-center\">\n @if (nodeProperty()) {\n <he-node-icon class=\"is-flex\" [type]=\"schemaType()\" [size]=\"24\" />\n <span class=\"has-text-weight-bold has-text-secondary is-size-5\">{{ schemaType() }}</span>\n @if (nodeProperty().hasError || hasError()) {\n <he-svg-icon name=\"xmark-circle\" class=\"has-text-danger is-flex is-align-items-center\" />\n <span class=\"has-text-danger has-text-weight-bold is-italic\">{{ errorLabel() }}</span>\n } @else if (nodeProperty().hasWarning || hasWarning()) {\n <he-svg-icon name=\"exclamation-triangle\" class=\"has-text-warning is-flex is-align-items-center\" />\n <span class=\"has-text-warning has-text-weight-bold is-italic\">{{ warningLabel() }}</span>\n }\n }\n </div>\n @if ((showNodeLink() && nodeUrl()) || canOpen()) {\n <div class=\"is-flex is-flex-direction-row is-align-items-center is-gap-16\">\n @if (showNodeLink() && nodeUrl()) {\n <ng-container *ngTemplateOutlet=\"nodeLink; context: { url: nodeUrl(), nodeType: schemaType() }\" />\n }\n @if (canOpen()) {\n <he-svg-icon [name]=\"isOpen() ? 'minus' : 'plus'\" />\n }\n </div>\n }\n </div>\n\n <div class=\"is-flex is-flex-direction-column is-align-items-flex-start is-align-self-stretch\">\n @if (isOpen()) {\n @for (property of nodeErrorProperties(); track property.id) {\n <ng-container *ngTemplateOutlet=\"propertyError; context: { property, classes: 'is-my-1 is-py-1 is-px-3' }\" />\n }\n }\n\n @if (unmatchedErrors().length) {\n @for (property of unmatchedErrors(); track property.id) {\n <ng-container *ngTemplateOutlet=\"propertyError; context: { property, classes: 'is-my-1 is-py-1 is-px-3' }\" />\n }\n }\n\n <div class=\"is-flex is-flex-direction-row is-flex-wrap-wrap is-align-self-stretch\">\n @for (property of properties(); track trackByProperty($index, property)) {\n <ng-container *ngTemplateOutlet=\"showProperty; context: { $implicit: property }\" />\n }\n </div>\n\n @if (isOpen()) {\n <ng-container *ngTemplateOutlet=\"propertyMap; context: { $implicit: nodeProperty() }\" />\n }\n </div>\n\n <ng-content />\n</div>\n\n<ng-template #propertyKeyTooltip let-property=\"property\">\n <markdown [data]=\"property.schema.description\" />\n</ng-template>\n\n<ng-template #propertyKey let-property=\"property\">\n @if (property.schema?.description) {\n <span\n class=\"trigger-popover | property-key\"\n [ngbTooltip]=\"propertyKeyTooltip\"\n [tooltipContext]=\"{ property }\"\n triggers=\"click\"\n autoClose=\"outside\"\n tooltipClass=\"property-tooltip\"\n placement=\"bottom-left auto\"\n container=\"body\"\n (click)=\"$event.stopPropagation()\">\n <span>{{ property.key }}</span>\n </span>\n } @else {\n <span>{{ property.key }}</span>\n }\n</ng-template>\n\n<ng-template #propertyContent let-property=\"property\">\n <div class=\"is-flex is-align-items-center is-flex-wrap-wrap is-gap-4\">\n <div class=\"is-flex has-text-secondary\">\n <ng-container *ngTemplateOutlet=\"propertyKey; context: { property }\" />\n <span>:</span>\n </div>\n\n <!--\n The value, the icons and \"Show more\" share one inline flow. As sibling flex items they wrap\n onto a line of their own as soon as the value fills the row, which is how the copy icon ended\n up under the text instead of at the end of it.\n -->\n <span class=\"is-size-7 | property-value\">\n @if (property.isCollapsible && property.showMaxLength) {\n {{ property.value | ellipsis: property.showMaxLength }}\n <a class=\"is-pl-1\" (click)=\"property.showMaxLength = 0\">Show more</a>\n } @else {\n {{ property.value }}\n }\n\n @if (property.schema?.internal && property.key !== 'originalId') {\n <span class=\"is-pl-1 | property-internal\" ngbTooltip=\"This value is auto-generated.\">\n <he-svg-icon name=\"autogenerate-circle\" />\n </span>\n }\n\n <span class=\"is-pl-1 | copy-button\">\n <he-clipboard [value]=\"property.value\" [hideText]=\"true\" clipboardClass=\"no-print\" />\n </span>\n </span>\n </div>\n\n <div class=\"is-flex is-gap-8\">\n @if (property.externalUrl?.url) {\n <a\n [href]=\"property.externalUrl.url + (property.externalUrl.urlParamValue ? property.value : '')\"\n target=\"_blank\"\n [title]=\"property.externalUrl.title\"\n class=\"ml-2\"\n [ngClass]=\"{ 'is-info': property.key === 'type' }\"\n [attr.disabled]=\"property.externalUrl.urlParamValue && !property.value ? true : null\">\n <he-svg-icon [name]=\"property.externalUrl.icon || 'external-link'\" />\n </a>\n }\n </div>\n</ng-template>\n\n<ng-template #showProperty let-property>\n @if ((isOpen() || property.closedVisible) && !property.isHidden) {\n @if (property.properties.length) {\n <div class=\"is-flex is-flex-direction-column is-flex-wrap-wrap w-100 | properties-container\">\n <div\n class=\"is-flex is-flex-direction-row is-justify-content-space-between is-gap-4 has-text-secondary w-100 | properties-container--title\"\n (click)=\"property.isOpen = !property.isOpen\"\n pointer\n [class.is-open]=\"property.isOpen\"\n [class.is-group-error-danger]=\"property.hasError\"\n [class.is-group-error-warning]=\"!property.hasError && property.hasWarning\">\n <div class=\"is-flex is-gap-8 has-text-weight-bold\">\n <!-- @if (property.schemaType === SchemaType.Term) {\n <he-node-icon [type]=\"property.schemaType\" />\n } -->\n <ng-container *ngTemplateOutlet=\"propertyKey; context: { property }\" />\n </div>\n <he-svg-icon [name]=\"property.isOpen ? 'minus' : 'plus'\" />\n </div>\n @if (property.isOpen) {\n @if (property.error) {\n <ng-container *ngTemplateOutlet=\"propertyError; context: { property, classes: 'is-my-1 is-px-3' }\" />\n }\n @if (property.isArray) {\n <div class=\"py-2 px-3 w-100\">\n @if (property.hasError) {\n <div class=\"is-flex is-align-items-center is-size-7 is-italic is-mb-2 has-text-warning\">\n <he-svg-icon name=\"exclamation-triangle\" />\n @if (showAllErrors()) {\n <a class=\"is-pl-2\" (click)=\"showAllErrors.set(false)\">Only show items in error.</a>\n } @else {\n <span class=\"is-pl-2\">Only showing items in error.</span>\n <a class=\"is-pl-1\" (click)=\"showAllErrors.set(true)\">Show all items</a>\n }\n </div>\n }\n\n @for (prop2 of property.properties; track trackByProperty($index, prop2)) {\n @if (prop2.key && (showAllErrors() || !property.hasError || prop2.hasError)) {\n <div class=\"pt-2 my-4 | property-array-container\" [id]=\"prop2.fullKey + '_' + prop2.id\">\n <div class=\"ml-2 is-mb-2 | property-array-number\">\n <span class=\"has-text-info is-px-1 | number-tag\">{{ prop2.key }}</span>\n </div>\n @if (prop2.error) {\n <ng-container\n *ngTemplateOutlet=\"propertyError; context: { property: prop2, classes: 'is-py-1 is-px-3' }\" />\n }\n <div class=\"p-3\">\n <div class=\"is-flex is-flex-direction-row is-flex-wrap-wrap is-align-self-stretch\">\n @for (prop3 of prop2.properties; track trackByProperty($index, prop3)) {\n <ng-container *ngTemplateOutlet=\"showProperty; context: { $implicit: prop3 }\" />\n }\n </div>\n </div>\n </div>\n }\n }\n </div>\n } @else {\n <div class=\"is-flex is-flex-direction-row is-flex-wrap-wrap is-align-self-stretch\">\n @for (prop2 of property.properties; track trackByProperty($index, prop2)) {\n <ng-container *ngTemplateOutlet=\"showProperty; context: { $implicit: prop2 }\" />\n }\n </div>\n }\n }\n </div>\n } @else {\n <div\n class=\"is-flex is-flex-direction-column is-gap-4 | property-container\"\n [class.is-error-danger]=\"property.hasError\"\n [class.is-error-warning]=\"!property.hasError && property.hasWarning\">\n <div\n class=\"is-flex is-flex-direction-row is-align-items-center is-justify-content-space-between is-gap-4 | field-container\">\n @if (property.key) {\n <ng-container *ngTemplateOutlet=\"propertyContent; context: { property }\" />\n }\n </div>\n @if (property.hasError || property.hasWarning) {\n <ng-container *ngTemplateOutlet=\"propertyError; context: { property }\" />\n }\n </div>\n }\n }\n</ng-template>\n\n<ng-template #propertyError let-property=\"property\" let-classes=\"classes\">\n @if (property.error?.message) {\n <div\n class=\"is-flex is-flex-direction-row is-gap-8 is-size-6 is-m-0 w-100 has-text-grey {{ classes }} | property-error\"\n [class.is-error-danger]=\"property.hasError\"\n [class.is-error-warning]=\"!property.hasError && property.hasWarning\">\n @if (property.hasError) {\n <he-svg-icon name=\"xmark-circle\" size=\"24\" class=\"has-text-danger is-flex-grow-0\" />\n } @else {\n <he-svg-icon name=\"exclamation-triangle\" size=\"24\" class=\"has-text-warning is-flex-grow-0\" />\n }\n\n <div class=\"is-flex is-flex-direction-column is-align-items-start is-flex-grow-1\">\n <span [innerHTML]=\"property.error.message\"></span>\n <he-files-error-distribution [error]=\"property.error\" />\n </div>\n\n @if (errorGuidePrefix() && property.errorGuidePageId) {\n <he-guide-overlay class=\"is-flex-grow-0\" [pageId]=\"errorGuidePrefix() + property.errorGuidePageId\" />\n }\n\n @if (property.error.index >= 0) {\n @if (property.hasWarning) {\n <a class=\"is-flex is-align-items-center is-flex-shrink-0\" (click)=\"resolveError(property)\">\n <he-svg-icon name=\"checkmark\" />\n <span class=\"is-pl-2\">Resolved</span>\n </a>\n }\n }\n </div>\n }\n</ng-template>\n\n<ng-template #propertyMap let-property>\n @if (showMap()) {\n <div class=\"is-flex is-flex-direction-column is-flex-wrap-wrap w-100 | properties-container\">\n <div\n class=\"is-flex is-flex-direction-row is-justify-content-space-between is-gap-4 w-100 | properties-container--title\"\n (click)=\"mapVisible.set(!mapVisible())\"\n pointer\n [class.is-open]=\"mapVisible()\">\n <span class=\"is-size-6\">View on Map</span>\n <he-svg-icon [name]=\"mapVisible() ? 'minus' : 'plus'\" />\n </div>\n @if (mapVisible()) {\n <he-sites-maps [sites]=\"[node()]\" [showNotice]=\"false\" />\n }\n </div>\n }\n</ng-template>\n\n<ng-template #nodeLink let-url=\"url\" let-nodeType=\"nodeType\">\n <a class=\"external-link\" [href]=\"url\" target=\"_blank\" (click)=\"$event.stopPropagation()\">\n <span class=\"is-hidden-mobile\">View</span>\n <span class=\"is-hidden-mobile is-pl-1\">{{ nodeType }}</span>\n <he-svg-icon name=\"external-link\" class=\"ml-2\" />\n </a>\n</ng-template>\n", styles: [".notification{color:#0a0a0a!important}.notification.is-success{background-color:#d5f3d8}.notification.is-success *:not(.button):not(.icon):not(.dropdown-item)>fa-icon,.notification.is-success>fa-icon,.notification.is-success *:not(.button):not(.icon):not(.dropdown-item)>he-svg-icon,.notification.is-success>he-svg-icon{color:#2b8434}.notification.is-info{background-color:#d3ebed}.notification.is-info *:not(.button):not(.icon):not(.dropdown-item)>fa-icon,.notification.is-info>fa-icon,.notification.is-info *:not(.button):not(.icon):not(.dropdown-item)>he-svg-icon,.notification.is-info>he-svg-icon{color:#249da5}.notification.is-warning{background-color:#ffdec0}.notification.is-warning *:not(.button):not(.icon):not(.dropdown-item)>fa-icon,.notification.is-warning>fa-icon,.notification.is-warning *:not(.button):not(.icon):not(.dropdown-item)>he-svg-icon,.notification.is-warning>he-svg-icon{color:#ff881b}.notification.is-danger{background-color:#ffcdd0}.notification.is-danger *:not(.button):not(.icon):not(.dropdown-item)>fa-icon,.notification.is-danger>fa-icon,.notification.is-danger *:not(.button):not(.icon):not(.dropdown-item)>he-svg-icon,.notification.is-danger>he-svg-icon{color:#ff3844}he-sites-maps{height:200px}.external-link{color:#4c7194}.files-form-container{box-shadow:2px 2px 4px #00000029;background-color:#fff}.files-form-header{padding:10px 12px;background-color:#dbe3ea;border-top-left-radius:3px;border-top-right-radius:3px}.properties-container--title,.property-container{padding:6px 12px}.property-container{flex:none;flex-grow:1;min-width:50%;max-width:100%;border:1px solid #f5f5f5}.property-container.is-error-danger{border-color:#ff3844}.property-container.is-error-warning{border-color:#ff881b}.properties-container--title{border-top:1px solid #dbe3ea;border-bottom:1px solid #dbe3ea;background:#f5f7f9}.properties-container .properties-container{border-radius:6px;border:1px solid #dbe3ea;margin:4px 0}.properties-container .properties-container--title{border-top:none}.property-internal{color:#249da5}.property-internal,.copy-button{vertical-align:middle}.property-internal he-svg-icon,.copy-button he-svg-icon{vertical-align:middle}.property-key,.property-value{word-break:break-word}.property-array-container{border-radius:6px;border:1px solid #dbdbdb}.number-tag{border:1px solid #249da5;border-radius:50%}.copy-button{visibility:hidden}.field-container:hover .copy-button{visibility:visible}.is-group-error-danger{background-color:#ffcdd0}.is-group-error-warning{background-color:#ffdec0}.property-error.is-error-danger{background-color:#ffeced}.field-container+.property-error.is-error-danger{background-color:transparent;color:#ff3844!important}.property-error.is-error-warning{background-color:#fff5ec}.field-container+.property-error.is-error-warning{background-color:transparent;color:#ff881b!important}::ng-deep .property-tooltip{background-color:#fff;color:#0a0a0a;border:1px solid #dbdbdb;z-index:11;max-width:50vw;max-height:50vh;overflow:auto}::ng-deep .property-tooltip pre{white-space:pre-wrap}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: MarkdownComponent, selector: "markdown, [markdown]", inputs: ["data", "src", "disableSanitizer", "inline", "clipboard", "clipboardButtonComponent", "clipboardButtonTemplate", "emoji", "katex", "katexOptions", "mermaid", "mermaidOptions", "lineHighlight", "line", "lineOffset", "lineNumbers", "start", "commandLine", "filterOutput", "host", "prompt", "output", "user"], outputs: ["error", "load", "ready"] }, { kind: "directive", type: NgbTooltip, selector: "[ngbTooltip]", inputs: ["animation", "autoClose", "placement", "popperOptions", "triggers", "positionTarget", "container", "disableTooltip", "tooltipClass", "tooltipContext", "openDelay", "closeDelay", "ngbTooltip"], outputs: ["shown", "hidden"], exportAs: ["ngbTooltip"] }, { kind: "component", type: NodeIconComponent, selector: "he-node-icon", inputs: ["type", "size"] }, { kind: "component", type: SitesMapsComponent, selector: "he-sites-maps", inputs: ["loadPolygons", "sites", "zoom", "showNotice"] }, { kind: "component", type: HESvgIconComponent, selector: "he-svg-icon", inputs: ["name", "size", "animation"] }, { kind: "component", type: ClipboardComponent, selector: "he-clipboard", inputs: ["icon", "value", "disabled", "hideText", "hideIcon", "size", "clipboardClass", "tooltipPlacement"] }, { kind: "component", type: GuideOverlayComponent, selector: "he-guide-overlay", inputs: ["pageId", "width", "height", "positions"], outputs: ["widthChange", "heightChange"] }, { kind: "component", type: FilesErrorDistributionComponent, selector: "he-files-error-distribution", inputs: ["error"] }, { kind: "pipe", type: EllipsisPipe, name: "ellipsis" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
14028
14190
  }
14029
14191
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: FilesFormComponent, decorators: [{
14030
14192
  type: Component$1,
@@ -14041,7 +14203,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
14041
14203
  GuideOverlayComponent,
14042
14204
  FilesErrorDistributionComponent,
14043
14205
  EllipsisPipe
14044
- ], template: "<div class=\"is-flex is-flex-direction-column is-align-items-flex-start is-align-self-stretch | files-form-container\">\n <div\n class=\"is-flex is-flex-direction-row is-justify-content-space-between is-align-items-center is-align-self-stretch is-gap-16 px-4 py-2 has-text-secondary | files-form-header\"\n (click)=\"isOpen.set(!isOpen())\"\n pointer>\n <div class=\"is-flex is-gap-8 is-align-items-center\">\n @if (nodeProperty()) {\n <he-node-icon class=\"is-flex\" [type]=\"schemaType()\" [size]=\"24\" />\n <span class=\"has-text-weight-bold has-text-secondary is-size-5\">{{ schemaType() }}</span>\n @if (nodeProperty().hasError || hasError()) {\n <he-svg-icon name=\"xmark-circle\" class=\"has-text-danger is-flex is-align-items-center\" />\n <span class=\"has-text-danger has-text-weight-bold is-italic\">{{ errorLabel() }}</span>\n } @else if (nodeProperty().hasWarning || hasWarning()) {\n <he-svg-icon name=\"exclamation-triangle\" class=\"has-text-warning is-flex is-align-items-center\" />\n <span class=\"has-text-warning has-text-weight-bold is-italic\">{{ warningLabel() }}</span>\n }\n }\n </div>\n @if ((showNodeLink() && nodeUrl()) || canOpen()) {\n <div class=\"is-flex is-flex-direction-row is-align-items-center is-gap-16\">\n @if (showNodeLink() && nodeUrl()) {\n <ng-container *ngTemplateOutlet=\"nodeLink; context: { url: nodeUrl(), nodeType: schemaType() }\" />\n }\n @if (canOpen()) {\n <he-svg-icon [name]=\"isOpen() ? 'minus' : 'plus'\" />\n }\n </div>\n }\n </div>\n\n <div class=\"is-flex is-flex-direction-column is-align-items-flex-start is-align-self-stretch\">\n @if (isOpen()) {\n @if (nodeProperty()?.error) {\n <ng-container\n *ngTemplateOutlet=\"\n propertyError;\n context: { property: nodeProperty(), classes: 'is-my-1 is-py-1 is-px-3' }\n \" />\n }\n }\n\n @if (unmatchedErrors().length) {\n @for (property of unmatchedErrors(); track property.id) {\n <ng-container *ngTemplateOutlet=\"propertyError; context: { property, classes: 'is-my-1 is-py-1 is-px-3' }\" />\n }\n }\n\n <div class=\"is-flex is-flex-direction-row is-flex-wrap-wrap is-align-self-stretch\">\n @for (property of properties(); track trackByProperty($index, property)) {\n <ng-container *ngTemplateOutlet=\"showProperty; context: { $implicit: property }\" />\n }\n </div>\n\n @if (isOpen()) {\n <ng-container *ngTemplateOutlet=\"propertyMap; context: { $implicit: nodeProperty() }\" />\n }\n </div>\n\n <ng-content />\n</div>\n\n<ng-template #propertyKeyTooltip let-property=\"property\">\n <markdown [data]=\"property.schema.description\" />\n</ng-template>\n\n<ng-template #propertyKey let-property=\"property\">\n @if (property.schema?.description) {\n <span\n class=\"trigger-popover | property-key\"\n [ngbTooltip]=\"propertyKeyTooltip\"\n [tooltipContext]=\"{ property }\"\n triggers=\"click\"\n autoClose=\"outside\"\n tooltipClass=\"property-tooltip\"\n placement=\"bottom-left auto\"\n container=\"body\"\n (click)=\"$event.stopPropagation()\">\n <span>{{ property.key }}</span>\n </span>\n } @else {\n <span>{{ property.key }}</span>\n }\n</ng-template>\n\n<ng-template #propertyContent let-property=\"property\">\n <div class=\"is-flex is-align-items-center is-flex-wrap-wrap is-gap-4\">\n <div class=\"is-flex has-text-secondary\">\n <ng-container *ngTemplateOutlet=\"propertyKey; context: { property }\" />\n <span>:</span>\n </div>\n\n <!--\n The value, the icons and \"Show more\" share one inline flow. As sibling flex items they wrap\n onto a line of their own as soon as the value fills the row, which is how the copy icon ended\n up under the text instead of at the end of it.\n -->\n <span class=\"is-size-7 | property-value\">\n @if (property.isCollapsible && property.showMaxLength) {\n {{ property.value | ellipsis: property.showMaxLength }}\n <a class=\"is-pl-1\" (click)=\"property.showMaxLength = 0\">Show more</a>\n } @else {\n {{ property.value }}\n }\n\n @if (property.schema?.internal && property.key !== 'originalId') {\n <span class=\"is-pl-1 | property-internal\" ngbTooltip=\"This value is auto-generated.\">\n <he-svg-icon name=\"autogenerate-circle\" />\n </span>\n }\n\n <span class=\"is-pl-1 | copy-button\">\n <he-clipboard [value]=\"property.value\" [hideText]=\"true\" clipboardClass=\"no-print\" />\n </span>\n </span>\n </div>\n\n <div class=\"is-flex is-gap-8\">\n @if (property.externalUrl?.url) {\n <a\n [href]=\"property.externalUrl.url + (property.externalUrl.urlParamValue ? property.value : '')\"\n target=\"_blank\"\n [title]=\"property.externalUrl.title\"\n class=\"ml-2\"\n [ngClass]=\"{ 'is-info': property.key === 'type' }\"\n [attr.disabled]=\"property.externalUrl.urlParamValue && !property.value ? true : null\">\n <he-svg-icon [name]=\"property.externalUrl.icon || 'external-link'\" />\n </a>\n }\n </div>\n</ng-template>\n\n<ng-template #showProperty let-property>\n @if ((isOpen() || property.closedVisible) && !property.isHidden) {\n @if (property.properties.length) {\n <div class=\"is-flex is-flex-direction-column is-flex-wrap-wrap w-100 | properties-container\">\n <div\n class=\"is-flex is-flex-direction-row is-justify-content-space-between is-gap-4 has-text-secondary w-100 | properties-container--title\"\n (click)=\"property.isOpen = !property.isOpen\"\n pointer\n [class.is-open]=\"property.isOpen\"\n [class.is-group-error-danger]=\"property.hasError\"\n [class.is-group-error-warning]=\"!property.hasError && property.hasWarning\">\n <div class=\"is-flex is-gap-8 has-text-weight-bold\">\n <!-- @if (property.schemaType === SchemaType.Term) {\n <he-node-icon [type]=\"property.schemaType\" />\n } -->\n <ng-container *ngTemplateOutlet=\"propertyKey; context: { property }\" />\n </div>\n <he-svg-icon [name]=\"property.isOpen ? 'minus' : 'plus'\" />\n </div>\n @if (property.isOpen) {\n @if (property.error) {\n <ng-container *ngTemplateOutlet=\"propertyError; context: { property, classes: 'is-my-1 is-px-3' }\" />\n }\n @if (property.isArray) {\n <div class=\"py-2 px-3 w-100\">\n @if (property.hasError) {\n <div class=\"is-flex is-align-items-center is-size-7 is-italic is-mb-2 has-text-warning\">\n <he-svg-icon name=\"exclamation-triangle\" />\n @if (showAllErrors()) {\n <a class=\"is-pl-2\" (click)=\"showAllErrors.set(false)\">Only show items in error.</a>\n } @else {\n <span class=\"is-pl-2\">Only showing items in error.</span>\n <a class=\"is-pl-1\" (click)=\"showAllErrors.set(true)\">Show all items</a>\n }\n </div>\n }\n\n @for (prop2 of property.properties; track trackByProperty($index, prop2)) {\n @if (prop2.key && (showAllErrors() || !property.hasError || prop2.hasError)) {\n <div class=\"pt-2 my-4 | property-array-container\" [id]=\"prop2.fullKey + '_' + prop2.id\">\n <div class=\"ml-2 is-mb-2 | property-array-number\">\n <span class=\"has-text-info is-px-1 | number-tag\">{{ prop2.key }}</span>\n </div>\n @if (prop2.error) {\n <ng-container\n *ngTemplateOutlet=\"propertyError; context: { property: prop2, classes: 'is-py-1 is-px-3' }\" />\n }\n <div class=\"p-3\">\n <div class=\"is-flex is-flex-direction-row is-flex-wrap-wrap is-align-self-stretch\">\n @for (prop3 of prop2.properties; track trackByProperty($index, prop3)) {\n <ng-container *ngTemplateOutlet=\"showProperty; context: { $implicit: prop3 }\" />\n }\n </div>\n </div>\n </div>\n }\n }\n </div>\n } @else {\n <div class=\"is-flex is-flex-direction-row is-flex-wrap-wrap is-align-self-stretch\">\n @for (prop2 of property.properties; track trackByProperty($index, prop2)) {\n <ng-container *ngTemplateOutlet=\"showProperty; context: { $implicit: prop2 }\" />\n }\n </div>\n }\n }\n </div>\n } @else {\n <div\n class=\"is-flex is-flex-direction-column is-gap-4 | property-container\"\n [class.is-error-danger]=\"property.hasError\"\n [class.is-error-warning]=\"!property.hasError && property.hasWarning\">\n <div\n class=\"is-flex is-flex-direction-row is-align-items-center is-justify-content-space-between is-gap-4 | field-container\">\n @if (property.key) {\n <ng-container *ngTemplateOutlet=\"propertyContent; context: { property }\" />\n }\n </div>\n @if (property.hasError || property.hasWarning) {\n <ng-container *ngTemplateOutlet=\"propertyError; context: { property }\" />\n }\n </div>\n }\n }\n</ng-template>\n\n<ng-template #propertyError let-property=\"property\" let-classes=\"classes\">\n @if (property.error?.message) {\n <div\n class=\"is-flex is-flex-direction-row is-gap-8 is-size-6 is-m-0 w-100 has-text-grey {{ classes }} | property-error\"\n [class.is-error-danger]=\"property.hasError\"\n [class.is-error-warning]=\"!property.hasError && property.hasWarning\">\n @if (property.hasError) {\n <he-svg-icon name=\"xmark-circle\" size=\"24\" class=\"has-text-danger is-flex-grow-0\" />\n } @else {\n <he-svg-icon name=\"exclamation-triangle\" size=\"24\" class=\"has-text-warning is-flex-grow-0\" />\n }\n\n <div class=\"is-flex is-flex-direction-column is-align-items-start is-flex-grow-1\">\n <span [innerHTML]=\"property.error.message\"></span>\n <he-files-error-distribution [error]=\"property.error\" />\n </div>\n\n @if (errorGuidePrefix() && property.errorGuidePageId) {\n <he-guide-overlay class=\"is-flex-grow-0\" [pageId]=\"errorGuidePrefix() + property.errorGuidePageId\" />\n }\n\n @if (property.error.index >= 0) {\n @if (property.hasWarning) {\n <a class=\"is-flex is-align-items-center is-flex-shrink-0\" (click)=\"resolveError(property)\">\n <he-svg-icon name=\"checkmark\" />\n <span class=\"is-pl-2\">Resolved</span>\n </a>\n }\n }\n </div>\n }\n</ng-template>\n\n<ng-template #propertyMap let-property>\n @if (showMap()) {\n <div class=\"is-flex is-flex-direction-column is-flex-wrap-wrap w-100 | properties-container\">\n <div\n class=\"is-flex is-flex-direction-row is-justify-content-space-between is-gap-4 w-100 | properties-container--title\"\n (click)=\"mapVisible.set(!mapVisible())\"\n pointer\n [class.is-open]=\"mapVisible()\">\n <span class=\"is-size-6\">View on Map</span>\n <he-svg-icon [name]=\"mapVisible() ? 'minus' : 'plus'\" />\n </div>\n @if (mapVisible()) {\n <he-sites-maps [sites]=\"[node()]\" [showNotice]=\"false\" />\n }\n </div>\n }\n</ng-template>\n\n<ng-template #nodeLink let-url=\"url\" let-nodeType=\"nodeType\">\n <a class=\"external-link\" [href]=\"url\" target=\"_blank\" (click)=\"$event.stopPropagation()\">\n <span class=\"is-hidden-mobile\">View</span>\n <span class=\"is-hidden-mobile is-pl-1\">{{ nodeType }}</span>\n <he-svg-icon name=\"external-link\" class=\"ml-2\" />\n </a>\n</ng-template>\n", styles: [".notification{color:#0a0a0a!important}.notification.is-success{background-color:#d5f3d8}.notification.is-success *:not(.button):not(.icon):not(.dropdown-item)>fa-icon,.notification.is-success>fa-icon,.notification.is-success *:not(.button):not(.icon):not(.dropdown-item)>he-svg-icon,.notification.is-success>he-svg-icon{color:#2b8434}.notification.is-info{background-color:#d3ebed}.notification.is-info *:not(.button):not(.icon):not(.dropdown-item)>fa-icon,.notification.is-info>fa-icon,.notification.is-info *:not(.button):not(.icon):not(.dropdown-item)>he-svg-icon,.notification.is-info>he-svg-icon{color:#249da5}.notification.is-warning{background-color:#ffdec0}.notification.is-warning *:not(.button):not(.icon):not(.dropdown-item)>fa-icon,.notification.is-warning>fa-icon,.notification.is-warning *:not(.button):not(.icon):not(.dropdown-item)>he-svg-icon,.notification.is-warning>he-svg-icon{color:#ff881b}.notification.is-danger{background-color:#ffcdd0}.notification.is-danger *:not(.button):not(.icon):not(.dropdown-item)>fa-icon,.notification.is-danger>fa-icon,.notification.is-danger *:not(.button):not(.icon):not(.dropdown-item)>he-svg-icon,.notification.is-danger>he-svg-icon{color:#ff3844}he-sites-maps{height:200px}.external-link{color:#4c7194}.files-form-container{box-shadow:2px 2px 4px #00000029;background-color:#fff}.files-form-header{padding:10px 12px;background-color:#dbe3ea;border-top-left-radius:3px;border-top-right-radius:3px}.properties-container--title,.property-container{padding:6px 12px}.property-container{flex:none;flex-grow:1;min-width:50%;max-width:100%;border:1px solid #f5f5f5}.property-container.is-error-danger{border-color:#ff3844}.property-container.is-error-warning{border-color:#ff881b}.properties-container--title{border-top:1px solid #dbe3ea;border-bottom:1px solid #dbe3ea;background:#f5f7f9}.properties-container .properties-container{border-radius:6px;border:1px solid #dbe3ea;margin:4px 0}.properties-container .properties-container--title{border-top:none}.property-internal{color:#249da5}.property-internal,.copy-button{vertical-align:middle}.property-internal he-svg-icon,.copy-button he-svg-icon{vertical-align:middle}.property-key,.property-value{word-break:break-word}.property-array-container{border-radius:6px;border:1px solid #dbdbdb}.number-tag{border:1px solid #249da5;border-radius:50%}.copy-button{visibility:hidden}.field-container:hover .copy-button{visibility:visible}.is-group-error-danger{background-color:#ffcdd0}.is-group-error-warning{background-color:#ffdec0}.property-error.is-error-danger{background-color:#ffeced}.field-container+.property-error.is-error-danger{background-color:transparent;color:#ff3844!important}.property-error.is-error-warning{background-color:#fff5ec}.field-container+.property-error.is-error-warning{background-color:transparent;color:#ff881b!important}::ng-deep .property-tooltip{background-color:#fff;color:#0a0a0a;border:1px solid #dbdbdb;z-index:11;max-width:50vw;max-height:50vh;overflow:auto}::ng-deep .property-tooltip pre{white-space:pre-wrap}\n"] }]
14206
+ ], template: "<div class=\"is-flex is-flex-direction-column is-align-items-flex-start is-align-self-stretch | files-form-container\">\n <div\n class=\"is-flex is-flex-direction-row is-justify-content-space-between is-align-items-center is-align-self-stretch is-gap-16 px-4 py-2 has-text-secondary | files-form-header\"\n (click)=\"isOpen.set(!isOpen())\"\n pointer>\n <div class=\"is-flex is-gap-8 is-align-items-center\">\n @if (nodeProperty()) {\n <he-node-icon class=\"is-flex\" [type]=\"schemaType()\" [size]=\"24\" />\n <span class=\"has-text-weight-bold has-text-secondary is-size-5\">{{ schemaType() }}</span>\n @if (nodeProperty().hasError || hasError()) {\n <he-svg-icon name=\"xmark-circle\" class=\"has-text-danger is-flex is-align-items-center\" />\n <span class=\"has-text-danger has-text-weight-bold is-italic\">{{ errorLabel() }}</span>\n } @else if (nodeProperty().hasWarning || hasWarning()) {\n <he-svg-icon name=\"exclamation-triangle\" class=\"has-text-warning is-flex is-align-items-center\" />\n <span class=\"has-text-warning has-text-weight-bold is-italic\">{{ warningLabel() }}</span>\n }\n }\n </div>\n @if ((showNodeLink() && nodeUrl()) || canOpen()) {\n <div class=\"is-flex is-flex-direction-row is-align-items-center is-gap-16\">\n @if (showNodeLink() && nodeUrl()) {\n <ng-container *ngTemplateOutlet=\"nodeLink; context: { url: nodeUrl(), nodeType: schemaType() }\" />\n }\n @if (canOpen()) {\n <he-svg-icon [name]=\"isOpen() ? 'minus' : 'plus'\" />\n }\n </div>\n }\n </div>\n\n <div class=\"is-flex is-flex-direction-column is-align-items-flex-start is-align-self-stretch\">\n @if (isOpen()) {\n @for (property of nodeErrorProperties(); track property.id) {\n <ng-container *ngTemplateOutlet=\"propertyError; context: { property, classes: 'is-my-1 is-py-1 is-px-3' }\" />\n }\n }\n\n @if (unmatchedErrors().length) {\n @for (property of unmatchedErrors(); track property.id) {\n <ng-container *ngTemplateOutlet=\"propertyError; context: { property, classes: 'is-my-1 is-py-1 is-px-3' }\" />\n }\n }\n\n <div class=\"is-flex is-flex-direction-row is-flex-wrap-wrap is-align-self-stretch\">\n @for (property of properties(); track trackByProperty($index, property)) {\n <ng-container *ngTemplateOutlet=\"showProperty; context: { $implicit: property }\" />\n }\n </div>\n\n @if (isOpen()) {\n <ng-container *ngTemplateOutlet=\"propertyMap; context: { $implicit: nodeProperty() }\" />\n }\n </div>\n\n <ng-content />\n</div>\n\n<ng-template #propertyKeyTooltip let-property=\"property\">\n <markdown [data]=\"property.schema.description\" />\n</ng-template>\n\n<ng-template #propertyKey let-property=\"property\">\n @if (property.schema?.description) {\n <span\n class=\"trigger-popover | property-key\"\n [ngbTooltip]=\"propertyKeyTooltip\"\n [tooltipContext]=\"{ property }\"\n triggers=\"click\"\n autoClose=\"outside\"\n tooltipClass=\"property-tooltip\"\n placement=\"bottom-left auto\"\n container=\"body\"\n (click)=\"$event.stopPropagation()\">\n <span>{{ property.key }}</span>\n </span>\n } @else {\n <span>{{ property.key }}</span>\n }\n</ng-template>\n\n<ng-template #propertyContent let-property=\"property\">\n <div class=\"is-flex is-align-items-center is-flex-wrap-wrap is-gap-4\">\n <div class=\"is-flex has-text-secondary\">\n <ng-container *ngTemplateOutlet=\"propertyKey; context: { property }\" />\n <span>:</span>\n </div>\n\n <!--\n The value, the icons and \"Show more\" share one inline flow. As sibling flex items they wrap\n onto a line of their own as soon as the value fills the row, which is how the copy icon ended\n up under the text instead of at the end of it.\n -->\n <span class=\"is-size-7 | property-value\">\n @if (property.isCollapsible && property.showMaxLength) {\n {{ property.value | ellipsis: property.showMaxLength }}\n <a class=\"is-pl-1\" (click)=\"property.showMaxLength = 0\">Show more</a>\n } @else {\n {{ property.value }}\n }\n\n @if (property.schema?.internal && property.key !== 'originalId') {\n <span class=\"is-pl-1 | property-internal\" ngbTooltip=\"This value is auto-generated.\">\n <he-svg-icon name=\"autogenerate-circle\" />\n </span>\n }\n\n <span class=\"is-pl-1 | copy-button\">\n <he-clipboard [value]=\"property.value\" [hideText]=\"true\" clipboardClass=\"no-print\" />\n </span>\n </span>\n </div>\n\n <div class=\"is-flex is-gap-8\">\n @if (property.externalUrl?.url) {\n <a\n [href]=\"property.externalUrl.url + (property.externalUrl.urlParamValue ? property.value : '')\"\n target=\"_blank\"\n [title]=\"property.externalUrl.title\"\n class=\"ml-2\"\n [ngClass]=\"{ 'is-info': property.key === 'type' }\"\n [attr.disabled]=\"property.externalUrl.urlParamValue && !property.value ? true : null\">\n <he-svg-icon [name]=\"property.externalUrl.icon || 'external-link'\" />\n </a>\n }\n </div>\n</ng-template>\n\n<ng-template #showProperty let-property>\n @if ((isOpen() || property.closedVisible) && !property.isHidden) {\n @if (property.properties.length) {\n <div class=\"is-flex is-flex-direction-column is-flex-wrap-wrap w-100 | properties-container\">\n <div\n class=\"is-flex is-flex-direction-row is-justify-content-space-between is-gap-4 has-text-secondary w-100 | properties-container--title\"\n (click)=\"property.isOpen = !property.isOpen\"\n pointer\n [class.is-open]=\"property.isOpen\"\n [class.is-group-error-danger]=\"property.hasError\"\n [class.is-group-error-warning]=\"!property.hasError && property.hasWarning\">\n <div class=\"is-flex is-gap-8 has-text-weight-bold\">\n <!-- @if (property.schemaType === SchemaType.Term) {\n <he-node-icon [type]=\"property.schemaType\" />\n } -->\n <ng-container *ngTemplateOutlet=\"propertyKey; context: { property }\" />\n </div>\n <he-svg-icon [name]=\"property.isOpen ? 'minus' : 'plus'\" />\n </div>\n @if (property.isOpen) {\n @if (property.error) {\n <ng-container *ngTemplateOutlet=\"propertyError; context: { property, classes: 'is-my-1 is-px-3' }\" />\n }\n @if (property.isArray) {\n <div class=\"py-2 px-3 w-100\">\n @if (property.hasError) {\n <div class=\"is-flex is-align-items-center is-size-7 is-italic is-mb-2 has-text-warning\">\n <he-svg-icon name=\"exclamation-triangle\" />\n @if (showAllErrors()) {\n <a class=\"is-pl-2\" (click)=\"showAllErrors.set(false)\">Only show items in error.</a>\n } @else {\n <span class=\"is-pl-2\">Only showing items in error.</span>\n <a class=\"is-pl-1\" (click)=\"showAllErrors.set(true)\">Show all items</a>\n }\n </div>\n }\n\n @for (prop2 of property.properties; track trackByProperty($index, prop2)) {\n @if (prop2.key && (showAllErrors() || !property.hasError || prop2.hasError)) {\n <div class=\"pt-2 my-4 | property-array-container\" [id]=\"prop2.fullKey + '_' + prop2.id\">\n <div class=\"ml-2 is-mb-2 | property-array-number\">\n <span class=\"has-text-info is-px-1 | number-tag\">{{ prop2.key }}</span>\n </div>\n @if (prop2.error) {\n <ng-container\n *ngTemplateOutlet=\"propertyError; context: { property: prop2, classes: 'is-py-1 is-px-3' }\" />\n }\n <div class=\"p-3\">\n <div class=\"is-flex is-flex-direction-row is-flex-wrap-wrap is-align-self-stretch\">\n @for (prop3 of prop2.properties; track trackByProperty($index, prop3)) {\n <ng-container *ngTemplateOutlet=\"showProperty; context: { $implicit: prop3 }\" />\n }\n </div>\n </div>\n </div>\n }\n }\n </div>\n } @else {\n <div class=\"is-flex is-flex-direction-row is-flex-wrap-wrap is-align-self-stretch\">\n @for (prop2 of property.properties; track trackByProperty($index, prop2)) {\n <ng-container *ngTemplateOutlet=\"showProperty; context: { $implicit: prop2 }\" />\n }\n </div>\n }\n }\n </div>\n } @else {\n <div\n class=\"is-flex is-flex-direction-column is-gap-4 | property-container\"\n [class.is-error-danger]=\"property.hasError\"\n [class.is-error-warning]=\"!property.hasError && property.hasWarning\">\n <div\n class=\"is-flex is-flex-direction-row is-align-items-center is-justify-content-space-between is-gap-4 | field-container\">\n @if (property.key) {\n <ng-container *ngTemplateOutlet=\"propertyContent; context: { property }\" />\n }\n </div>\n @if (property.hasError || property.hasWarning) {\n <ng-container *ngTemplateOutlet=\"propertyError; context: { property }\" />\n }\n </div>\n }\n }\n</ng-template>\n\n<ng-template #propertyError let-property=\"property\" let-classes=\"classes\">\n @if (property.error?.message) {\n <div\n class=\"is-flex is-flex-direction-row is-gap-8 is-size-6 is-m-0 w-100 has-text-grey {{ classes }} | property-error\"\n [class.is-error-danger]=\"property.hasError\"\n [class.is-error-warning]=\"!property.hasError && property.hasWarning\">\n @if (property.hasError) {\n <he-svg-icon name=\"xmark-circle\" size=\"24\" class=\"has-text-danger is-flex-grow-0\" />\n } @else {\n <he-svg-icon name=\"exclamation-triangle\" size=\"24\" class=\"has-text-warning is-flex-grow-0\" />\n }\n\n <div class=\"is-flex is-flex-direction-column is-align-items-start is-flex-grow-1\">\n <span [innerHTML]=\"property.error.message\"></span>\n <he-files-error-distribution [error]=\"property.error\" />\n </div>\n\n @if (errorGuidePrefix() && property.errorGuidePageId) {\n <he-guide-overlay class=\"is-flex-grow-0\" [pageId]=\"errorGuidePrefix() + property.errorGuidePageId\" />\n }\n\n @if (property.error.index >= 0) {\n @if (property.hasWarning) {\n <a class=\"is-flex is-align-items-center is-flex-shrink-0\" (click)=\"resolveError(property)\">\n <he-svg-icon name=\"checkmark\" />\n <span class=\"is-pl-2\">Resolved</span>\n </a>\n }\n }\n </div>\n }\n</ng-template>\n\n<ng-template #propertyMap let-property>\n @if (showMap()) {\n <div class=\"is-flex is-flex-direction-column is-flex-wrap-wrap w-100 | properties-container\">\n <div\n class=\"is-flex is-flex-direction-row is-justify-content-space-between is-gap-4 w-100 | properties-container--title\"\n (click)=\"mapVisible.set(!mapVisible())\"\n pointer\n [class.is-open]=\"mapVisible()\">\n <span class=\"is-size-6\">View on Map</span>\n <he-svg-icon [name]=\"mapVisible() ? 'minus' : 'plus'\" />\n </div>\n @if (mapVisible()) {\n <he-sites-maps [sites]=\"[node()]\" [showNotice]=\"false\" />\n }\n </div>\n }\n</ng-template>\n\n<ng-template #nodeLink let-url=\"url\" let-nodeType=\"nodeType\">\n <a class=\"external-link\" [href]=\"url\" target=\"_blank\" (click)=\"$event.stopPropagation()\">\n <span class=\"is-hidden-mobile\">View</span>\n <span class=\"is-hidden-mobile is-pl-1\">{{ nodeType }}</span>\n <he-svg-icon name=\"external-link\" class=\"ml-2\" />\n </a>\n</ng-template>\n", styles: [".notification{color:#0a0a0a!important}.notification.is-success{background-color:#d5f3d8}.notification.is-success *:not(.button):not(.icon):not(.dropdown-item)>fa-icon,.notification.is-success>fa-icon,.notification.is-success *:not(.button):not(.icon):not(.dropdown-item)>he-svg-icon,.notification.is-success>he-svg-icon{color:#2b8434}.notification.is-info{background-color:#d3ebed}.notification.is-info *:not(.button):not(.icon):not(.dropdown-item)>fa-icon,.notification.is-info>fa-icon,.notification.is-info *:not(.button):not(.icon):not(.dropdown-item)>he-svg-icon,.notification.is-info>he-svg-icon{color:#249da5}.notification.is-warning{background-color:#ffdec0}.notification.is-warning *:not(.button):not(.icon):not(.dropdown-item)>fa-icon,.notification.is-warning>fa-icon,.notification.is-warning *:not(.button):not(.icon):not(.dropdown-item)>he-svg-icon,.notification.is-warning>he-svg-icon{color:#ff881b}.notification.is-danger{background-color:#ffcdd0}.notification.is-danger *:not(.button):not(.icon):not(.dropdown-item)>fa-icon,.notification.is-danger>fa-icon,.notification.is-danger *:not(.button):not(.icon):not(.dropdown-item)>he-svg-icon,.notification.is-danger>he-svg-icon{color:#ff3844}he-sites-maps{height:200px}.external-link{color:#4c7194}.files-form-container{box-shadow:2px 2px 4px #00000029;background-color:#fff}.files-form-header{padding:10px 12px;background-color:#dbe3ea;border-top-left-radius:3px;border-top-right-radius:3px}.properties-container--title,.property-container{padding:6px 12px}.property-container{flex:none;flex-grow:1;min-width:50%;max-width:100%;border:1px solid #f5f5f5}.property-container.is-error-danger{border-color:#ff3844}.property-container.is-error-warning{border-color:#ff881b}.properties-container--title{border-top:1px solid #dbe3ea;border-bottom:1px solid #dbe3ea;background:#f5f7f9}.properties-container .properties-container{border-radius:6px;border:1px solid #dbe3ea;margin:4px 0}.properties-container .properties-container--title{border-top:none}.property-internal{color:#249da5}.property-internal,.copy-button{vertical-align:middle}.property-internal he-svg-icon,.copy-button he-svg-icon{vertical-align:middle}.property-key,.property-value{word-break:break-word}.property-array-container{border-radius:6px;border:1px solid #dbdbdb}.number-tag{border:1px solid #249da5;border-radius:50%}.copy-button{visibility:hidden}.field-container:hover .copy-button{visibility:visible}.is-group-error-danger{background-color:#ffcdd0}.is-group-error-warning{background-color:#ffdec0}.property-error.is-error-danger{background-color:#ffeced}.field-container+.property-error.is-error-danger{background-color:transparent;color:#ff3844!important}.property-error.is-error-warning{background-color:#fff5ec}.field-container+.property-error.is-error-warning{background-color:transparent;color:#ff881b!important}::ng-deep .property-tooltip{background-color:#fff;color:#0a0a0a;border:1px solid #dbdbdb;z-index:11;max-width:50vw;max-height:50vh;overflow:auto}::ng-deep .property-tooltip pre{white-space:pre-wrap}\n"] }]
14045
14207
  }], propDecorators: { isOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "isOpen", required: false }] }, { type: i0.Output, args: ["isOpenChange"] }], node: [{ type: i0.Input, args: [{ isSignal: true, alias: "node", required: true }] }], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], showNodeLink: [{ type: i0.Input, args: [{ isSignal: true, alias: "showNodeLink", required: false }] }], errorGuidePrefix: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorGuidePrefix", required: false }] }], nodeErorrResolved: [{ type: i0.Output, args: ["nodeErorrResolved"] }] } });
14046
14208
 
14047
14209
  class SchemaInfoComponent {
@@ -14896,15 +15058,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
14896
15058
  }], ctorParameters: () => [], propDecorators: { impactAssessments: [{ type: i0.Input, args: [{ isSignal: true, alias: "impactAssessments", required: false }] }], dataState: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataState", required: false }] }] } });
14897
15059
 
14898
15060
  const filterTermTypes = [TermTermType.emission, TermTermType.characterisedIndicator];
15061
+ // every row keeps its label within the chart's fixed height; the rest go into the "others" bar
15062
+ const maximumValues = 10;
14899
15063
  class ImpactAssessmentsIndicatorBreakdownChartComponent {
14900
15064
  constructor() {
14901
15065
  this.searchService = inject(HeSearchService);
14902
15066
  this.nodeService = inject(HeNodeService);
14903
15067
  this.emissionCategoryService = inject(CyclesEmissionsCategoryService);
14904
- this.responsiveService = inject(ResponsiveService);
14905
15068
  this.impactAssessment = input.required(...(ngDevMode ? [{ debugName: "impactAssessment" }] : []));
14906
15069
  this.indicators = input([], ...(ngDevMode ? [{ debugName: "indicators" }] : []));
14907
- this.maximumValues = computed(() => (this.responsiveService.isMobile() ? 10 : 20), ...(ngDevMode ? [{ debugName: "maximumValues" }] : []));
15070
+ this.maximumValues = maximumValues;
14908
15071
  this.categories = this.emissionCategoryService.categories;
14909
15072
  this.selectedCategory = signal(undefined, ...(ngDevMode ? [{ debugName: "selectedCategory" }] : []));
14910
15073
  this.logsResource = rxResource({
@@ -14950,8 +15113,8 @@ class ImpactAssessmentsIndicatorBreakdownChartComponent {
14950
15113
  this.total = computed(() => logsTotalValue(this.nonZeroLogs(), true), ...(ngDevMode ? [{ debugName: "total" }] : []));
14951
15114
  this.values = computed(() => namedContributors(this.nonZeroLogs(), id => this.emissions()?.find(v => v['@id'] === id)?.name), ...(ngDevMode ? [{ debugName: "values" }] : []));
14952
15115
  this.chartData = computed(() => breakdownBars(this.values(), this.selectedCategory()), ...(ngDevMode ? [{ debugName: "chartData" }] : []));
14953
- this.chartTooltipFn = ({ includedItems, index }) => breakdownTooltip(this.chartData()[index], includedItems, this.nonZeroLogs(), this.total(), this.maximumValues());
14954
- this.afterBarDrawSettings = computed(() => breakdownBarText(this.displayValue(), this.total(), this.maximumValues()), ...(ngDevMode ? [{ debugName: "afterBarDrawSettings" }] : []));
15116
+ this.chartTooltipFn = ({ includedItems, index }) => breakdownTooltip(this.chartData()[index], includedItems, this.nonZeroLogs(), this.total(), this.maximumValues);
15117
+ this.afterBarDrawSettings = computed(() => breakdownBarText(this.displayValue(), this.total(), this.maximumValues), ...(ngDevMode ? [{ debugName: "afterBarDrawSettings" }] : []));
14955
15118
  this.configuration = computed(() => breakdownScale(this.values(), this.selectedCategory()), ...(ngDevMode ? [{ debugName: "configuration" }] : []));
14956
15119
  this.exportFormats = [
14957
15120
  ...exportFormats,
@@ -14993,11 +15156,11 @@ class ImpactAssessmentsIndicatorBreakdownChartComponent {
14993
15156
  return [blankNodeTermId, modelId, impactTermId].join('-');
14994
15157
  }
14995
15158
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ImpactAssessmentsIndicatorBreakdownChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
14996
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: ImpactAssessmentsIndicatorBreakdownChartComponent, isStandalone: true, selector: "he-impact-assessments-indicator-breakdown-chart", inputs: { impactAssessment: { classPropertyName: "impactAssessment", publicName: "impactAssessment", isSignal: true, isRequired: true, transformFunction: null }, indicators: { classPropertyName: "indicators", publicName: "indicators", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"is-flex is-gap-8 is-justify-content-space-between is-align-items-center is-mb-3\">\n <he-chart-export-button [chart]=\"chart\" [chartExportFn]=\"chartExportFn\" [exportFormats]=\"exportFormats\" />\n\n <ng-content />\n</div>\n\n@if (logsResource.isLoading()) {\n <div class=\"has-text-center py-3\">\n <he-svg-icon name=\"loading\" animation=\"spin\" size=\"40\" />\n </div>\n} @else if (terms()?.length) {\n <div class=\"is-flex is-align-items-center is-gap-12 is-mb-2 | breakdown-actions-table\">\n @if (terms()?.length) {\n <div class=\"control is-expanded is-flex-grow-1\">\n <div class=\"select is-fullwidth is-small\">\n <select [(ngModel)]=\"selectedTermId\" name=\"selectedTermId\">\n @for (term of terms(); track term['@id']) {\n <option [value]=\"term['@id']\">{{ term.name }}</option>\n }\n </select>\n </div>\n </div>\n }\n @if (methods()?.length) {\n <div class=\"control is-expanded is-flex-shrink-0\">\n <div class=\"select is-fullwidth is-small\">\n <select [(ngModel)]=\"selectedMethodId\" name=\"selectedMethodId\">\n @for (term of methods(); track term['@id']) {\n <option [value]=\"term['@id']\">{{ term.name }}</option>\n }\n </select>\n </div>\n </div>\n }\n <div class=\"control is-expanded is-flex-shrink-0\">\n <div class=\"select is-fullwidth is-small\">\n <select [(ngModel)]=\"selectedCategory\" name=\"selectedCategory\">\n <option [ngValue]=\"undefined\">No Disaggregation</option>\n @for (category of categories; track category.key) {\n <option [value]=\"category.key\">{{ category.label }}</option>\n }\n </select>\n </div>\n </div>\n\n <div class=\"is-flex is-justify-content-space-between\">\n <div class=\"field is-relative is-mb-0 is-hidden-tablet\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded is-secondary\"\n id=\"displayValue\"\n name=\"displayValue\"\n [(ngModel)]=\"displayValue\" />\n <label for=\"displayValue\">Show numerical value</label>\n </div>\n </div>\n </div>\n}\n\n@if (!logsResource.isLoading() && noData()) {\n <div class=\"chart-area-border\">\n <p class=\"has-text-centered\">\n <span>No breakdown available for</span>\n @if (selectedTerm()) {\n <span class=\"is-pl-1\">{{ selectedTerm().name }}</span>\n }\n @if (selectedMethod()) {\n <span class=\"is-pl-1\">({{ selectedMethod().name }})</span>\n }\n <span>.</span>\n </p>\n </div>\n}\n\n<he-horizontal-bar-chart\n #chart=\"horizontalBarChart\"\n class=\"is-relative h-100\"\n [class.is-hidden]=\"!logsResource.isLoading() && noData()\"\n [title]=\"selectedTerm()?.units\"\n [config]=\"configuration()\"\n [data]=\"chartData()\"\n [max]=\"totalPositive()\"\n [maximumValues]=\"maximumValues()\"\n [showExportButton]=\"false\"\n [showNegativeValues]=\"true\"\n [tooltipFn]=\"chartTooltipFn\"\n [afterBarDrawSettings]=\"afterBarDrawSettings()\" />\n", styles: [":host{display:block;overflow:visible}@media screen and (max-width:767px){.chart-area-border{padding:0}}@media screen and (max-width:767px){.breakdown-actions-table{flex-direction:column;align-items:flex-start!important}}.breakdown-legend{background:#fafafa}.breakdown-legend--color{width:8px;height:8px;border-radius:50%}\n"], dependencies: [{ kind: "component", type: HESvgIconComponent, selector: "he-svg-icon", inputs: ["name", "size", "animation"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { 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: HorizontalBarChartComponent, selector: "he-horizontal-bar-chart", inputs: ["tooltipFn", "afterBarDrawSettings", "axisTooltipFn", "axisLabelClickFn", "minHeight", "maxHeight"], exportAs: ["horizontalBarChart"] }, { kind: "component", type: ChartExportButtonComponent, selector: "he-chart-export-button", inputs: ["buttonClass", "chart", "config", "exportFormats", "chartExportFn"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
15159
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: ImpactAssessmentsIndicatorBreakdownChartComponent, isStandalone: true, selector: "he-impact-assessments-indicator-breakdown-chart", inputs: { impactAssessment: { classPropertyName: "impactAssessment", publicName: "impactAssessment", isSignal: true, isRequired: true, transformFunction: null }, indicators: { classPropertyName: "indicators", publicName: "indicators", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"is-flex is-gap-8 is-justify-content-space-between is-align-items-center is-mb-3\">\n <he-chart-export-button [chart]=\"chart\" [chartExportFn]=\"chartExportFn\" [exportFormats]=\"exportFormats\" />\n\n <ng-content />\n</div>\n\n@if (logsResource.isLoading()) {\n <div class=\"has-text-center py-3\">\n <he-svg-icon name=\"loading\" animation=\"spin\" size=\"40\" />\n </div>\n} @else if (terms()?.length) {\n <div class=\"is-flex is-align-items-center is-gap-12 is-mb-2 | breakdown-actions-table\">\n @if (terms()?.length) {\n <div class=\"control is-expanded is-flex-grow-1\">\n <div class=\"select is-fullwidth is-small\">\n <select [(ngModel)]=\"selectedTermId\" name=\"selectedTermId\">\n @for (term of terms(); track term['@id']) {\n <option [value]=\"term['@id']\">{{ term.name }}</option>\n }\n </select>\n </div>\n </div>\n }\n @if (methods()?.length) {\n <div class=\"control is-expanded is-flex-shrink-0\">\n <div class=\"select is-fullwidth is-small\">\n <select [(ngModel)]=\"selectedMethodId\" name=\"selectedMethodId\">\n @for (term of methods(); track term['@id']) {\n <option [value]=\"term['@id']\">{{ term.name }}</option>\n }\n </select>\n </div>\n </div>\n }\n <div class=\"control is-expanded is-flex-shrink-0\">\n <div class=\"select is-fullwidth is-small\">\n <select [(ngModel)]=\"selectedCategory\" name=\"selectedCategory\">\n <option [ngValue]=\"undefined\">No Disaggregation</option>\n @for (category of categories; track category.key) {\n <option [value]=\"category.key\">{{ category.label }}</option>\n }\n </select>\n </div>\n </div>\n\n <div class=\"is-flex is-justify-content-space-between\">\n <div class=\"field is-relative is-mb-0 is-hidden-tablet\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded is-secondary\"\n id=\"displayValue\"\n name=\"displayValue\"\n [(ngModel)]=\"displayValue\" />\n <label for=\"displayValue\">Show numerical value</label>\n </div>\n </div>\n </div>\n}\n\n@if (!logsResource.isLoading() && noData()) {\n <div class=\"chart-area-border\">\n <p class=\"has-text-centered\">\n <span>No breakdown available for</span>\n @if (selectedTerm()) {\n <span class=\"is-pl-1\">{{ selectedTerm().name }}</span>\n }\n @if (selectedMethod()) {\n <span class=\"is-pl-1\">({{ selectedMethod().name }})</span>\n }\n <span>.</span>\n </p>\n </div>\n}\n\n<he-horizontal-bar-chart\n #chart=\"horizontalBarChart\"\n class=\"is-relative h-100\"\n [class.is-hidden]=\"!logsResource.isLoading() && noData()\"\n [title]=\"selectedTerm()?.units\"\n [config]=\"configuration()\"\n [data]=\"chartData()\"\n [max]=\"totalPositive()\"\n [maximumValues]=\"maximumValues\"\n [showExportButton]=\"false\"\n [showNegativeValues]=\"true\"\n [tooltipFn]=\"chartTooltipFn\"\n [afterBarDrawSettings]=\"afterBarDrawSettings()\" />\n", styles: [":host{display:block;overflow:visible}@media screen and (max-width:767px){.chart-area-border{padding:0}}@media screen and (max-width:767px){.breakdown-actions-table{flex-direction:column;align-items:flex-start!important}}.breakdown-legend{background:#fafafa}.breakdown-legend--color{width:8px;height:8px;border-radius:50%}\n"], dependencies: [{ kind: "component", type: HESvgIconComponent, selector: "he-svg-icon", inputs: ["name", "size", "animation"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { 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: HorizontalBarChartComponent, selector: "he-horizontal-bar-chart", inputs: ["tooltipFn", "afterBarDrawSettings", "axisTooltipFn", "axisLabelClickFn", "minHeight", "maxHeight"], exportAs: ["horizontalBarChart"] }, { kind: "component", type: ChartExportButtonComponent, selector: "he-chart-export-button", inputs: ["buttonClass", "chart", "config", "exportFormats", "chartExportFn"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
14997
15160
  }
14998
15161
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ImpactAssessmentsIndicatorBreakdownChartComponent, decorators: [{
14999
15162
  type: Component$1,
15000
- args: [{ selector: 'he-impact-assessments-indicator-breakdown-chart', changeDetection: ChangeDetectionStrategy.OnPush, imports: [HESvgIconComponent, FormsModule, HorizontalBarChartComponent, ChartExportButtonComponent], template: "<div class=\"is-flex is-gap-8 is-justify-content-space-between is-align-items-center is-mb-3\">\n <he-chart-export-button [chart]=\"chart\" [chartExportFn]=\"chartExportFn\" [exportFormats]=\"exportFormats\" />\n\n <ng-content />\n</div>\n\n@if (logsResource.isLoading()) {\n <div class=\"has-text-center py-3\">\n <he-svg-icon name=\"loading\" animation=\"spin\" size=\"40\" />\n </div>\n} @else if (terms()?.length) {\n <div class=\"is-flex is-align-items-center is-gap-12 is-mb-2 | breakdown-actions-table\">\n @if (terms()?.length) {\n <div class=\"control is-expanded is-flex-grow-1\">\n <div class=\"select is-fullwidth is-small\">\n <select [(ngModel)]=\"selectedTermId\" name=\"selectedTermId\">\n @for (term of terms(); track term['@id']) {\n <option [value]=\"term['@id']\">{{ term.name }}</option>\n }\n </select>\n </div>\n </div>\n }\n @if (methods()?.length) {\n <div class=\"control is-expanded is-flex-shrink-0\">\n <div class=\"select is-fullwidth is-small\">\n <select [(ngModel)]=\"selectedMethodId\" name=\"selectedMethodId\">\n @for (term of methods(); track term['@id']) {\n <option [value]=\"term['@id']\">{{ term.name }}</option>\n }\n </select>\n </div>\n </div>\n }\n <div class=\"control is-expanded is-flex-shrink-0\">\n <div class=\"select is-fullwidth is-small\">\n <select [(ngModel)]=\"selectedCategory\" name=\"selectedCategory\">\n <option [ngValue]=\"undefined\">No Disaggregation</option>\n @for (category of categories; track category.key) {\n <option [value]=\"category.key\">{{ category.label }}</option>\n }\n </select>\n </div>\n </div>\n\n <div class=\"is-flex is-justify-content-space-between\">\n <div class=\"field is-relative is-mb-0 is-hidden-tablet\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded is-secondary\"\n id=\"displayValue\"\n name=\"displayValue\"\n [(ngModel)]=\"displayValue\" />\n <label for=\"displayValue\">Show numerical value</label>\n </div>\n </div>\n </div>\n}\n\n@if (!logsResource.isLoading() && noData()) {\n <div class=\"chart-area-border\">\n <p class=\"has-text-centered\">\n <span>No breakdown available for</span>\n @if (selectedTerm()) {\n <span class=\"is-pl-1\">{{ selectedTerm().name }}</span>\n }\n @if (selectedMethod()) {\n <span class=\"is-pl-1\">({{ selectedMethod().name }})</span>\n }\n <span>.</span>\n </p>\n </div>\n}\n\n<he-horizontal-bar-chart\n #chart=\"horizontalBarChart\"\n class=\"is-relative h-100\"\n [class.is-hidden]=\"!logsResource.isLoading() && noData()\"\n [title]=\"selectedTerm()?.units\"\n [config]=\"configuration()\"\n [data]=\"chartData()\"\n [max]=\"totalPositive()\"\n [maximumValues]=\"maximumValues()\"\n [showExportButton]=\"false\"\n [showNegativeValues]=\"true\"\n [tooltipFn]=\"chartTooltipFn\"\n [afterBarDrawSettings]=\"afterBarDrawSettings()\" />\n", styles: [":host{display:block;overflow:visible}@media screen and (max-width:767px){.chart-area-border{padding:0}}@media screen and (max-width:767px){.breakdown-actions-table{flex-direction:column;align-items:flex-start!important}}.breakdown-legend{background:#fafafa}.breakdown-legend--color{width:8px;height:8px;border-radius:50%}\n"] }]
15163
+ args: [{ selector: 'he-impact-assessments-indicator-breakdown-chart', changeDetection: ChangeDetectionStrategy.OnPush, imports: [HESvgIconComponent, FormsModule, HorizontalBarChartComponent, ChartExportButtonComponent], template: "<div class=\"is-flex is-gap-8 is-justify-content-space-between is-align-items-center is-mb-3\">\n <he-chart-export-button [chart]=\"chart\" [chartExportFn]=\"chartExportFn\" [exportFormats]=\"exportFormats\" />\n\n <ng-content />\n</div>\n\n@if (logsResource.isLoading()) {\n <div class=\"has-text-center py-3\">\n <he-svg-icon name=\"loading\" animation=\"spin\" size=\"40\" />\n </div>\n} @else if (terms()?.length) {\n <div class=\"is-flex is-align-items-center is-gap-12 is-mb-2 | breakdown-actions-table\">\n @if (terms()?.length) {\n <div class=\"control is-expanded is-flex-grow-1\">\n <div class=\"select is-fullwidth is-small\">\n <select [(ngModel)]=\"selectedTermId\" name=\"selectedTermId\">\n @for (term of terms(); track term['@id']) {\n <option [value]=\"term['@id']\">{{ term.name }}</option>\n }\n </select>\n </div>\n </div>\n }\n @if (methods()?.length) {\n <div class=\"control is-expanded is-flex-shrink-0\">\n <div class=\"select is-fullwidth is-small\">\n <select [(ngModel)]=\"selectedMethodId\" name=\"selectedMethodId\">\n @for (term of methods(); track term['@id']) {\n <option [value]=\"term['@id']\">{{ term.name }}</option>\n }\n </select>\n </div>\n </div>\n }\n <div class=\"control is-expanded is-flex-shrink-0\">\n <div class=\"select is-fullwidth is-small\">\n <select [(ngModel)]=\"selectedCategory\" name=\"selectedCategory\">\n <option [ngValue]=\"undefined\">No Disaggregation</option>\n @for (category of categories; track category.key) {\n <option [value]=\"category.key\">{{ category.label }}</option>\n }\n </select>\n </div>\n </div>\n\n <div class=\"is-flex is-justify-content-space-between\">\n <div class=\"field is-relative is-mb-0 is-hidden-tablet\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded is-secondary\"\n id=\"displayValue\"\n name=\"displayValue\"\n [(ngModel)]=\"displayValue\" />\n <label for=\"displayValue\">Show numerical value</label>\n </div>\n </div>\n </div>\n}\n\n@if (!logsResource.isLoading() && noData()) {\n <div class=\"chart-area-border\">\n <p class=\"has-text-centered\">\n <span>No breakdown available for</span>\n @if (selectedTerm()) {\n <span class=\"is-pl-1\">{{ selectedTerm().name }}</span>\n }\n @if (selectedMethod()) {\n <span class=\"is-pl-1\">({{ selectedMethod().name }})</span>\n }\n <span>.</span>\n </p>\n </div>\n}\n\n<he-horizontal-bar-chart\n #chart=\"horizontalBarChart\"\n class=\"is-relative h-100\"\n [class.is-hidden]=\"!logsResource.isLoading() && noData()\"\n [title]=\"selectedTerm()?.units\"\n [config]=\"configuration()\"\n [data]=\"chartData()\"\n [max]=\"totalPositive()\"\n [maximumValues]=\"maximumValues\"\n [showExportButton]=\"false\"\n [showNegativeValues]=\"true\"\n [tooltipFn]=\"chartTooltipFn\"\n [afterBarDrawSettings]=\"afterBarDrawSettings()\" />\n", styles: [":host{display:block;overflow:visible}@media screen and (max-width:767px){.chart-area-border{padding:0}}@media screen and (max-width:767px){.breakdown-actions-table{flex-direction:column;align-items:flex-start!important}}.breakdown-legend{background:#fafafa}.breakdown-legend--color{width:8px;height:8px;border-radius:50%}\n"] }]
15001
15164
  }], ctorParameters: () => [], propDecorators: { impactAssessment: [{ type: i0.Input, args: [{ isSignal: true, alias: "impactAssessment", required: true }] }], indicators: [{ type: i0.Input, args: [{ isSignal: true, alias: "indicators", required: false }] }] } });
15002
15165
 
15003
15166
  const impactValue = (impact, values) => (values[nodeVersionKey(impact)]?.nodes[0] || { value: 0 }).value;
@@ -15301,7 +15464,7 @@ class ImpactAssessmentsProductsComponent {
15301
15464
  component.headerKeys.set(this.headerKeys());
15302
15465
  }
15303
15466
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ImpactAssessmentsProductsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
15304
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: ImpactAssessmentsProductsComponent, isStandalone: true, selector: "he-impact-assessments-products", inputs: { dataState: { classPropertyName: "dataState", publicName: "dataState", isSignal: true, isRequired: false, transformFunction: null }, nodeKey: { classPropertyName: "nodeKey", publicName: "nodeKey", isSignal: true, isRequired: false, transformFunction: null }, filterTermTypes: { classPropertyName: "filterTermTypes", publicName: "filterTermTypes", isSignal: true, isRequired: false, transformFunction: null }, enableFilterMethodModel: { classPropertyName: "enableFilterMethodModel", publicName: "enableFilterMethodModel", isSignal: true, isRequired: false, transformFunction: null }, hideIdenticalValues: { classPropertyName: "hideIdenticalValues", publicName: "hideIdenticalValues", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (isNodeKeyAllowed()) {\n @switch (selectedView()) {\n @case (View.table) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n <div class=\"is-hidden-tablet is-mt-3\">\n <ng-container *ngTemplateOutlet=\"filterModel\" />\n </div>\n\n @if (hasData()) {\n @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 @if (dataKeys().length > 1) {\n <tr class=\"has-text-weight-bold\">\n <th class=\"width-auto\"></th>\n <th></th>\n <th></th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @let blankNodesCount = countGroupVisibleNodes(blankNodes);\n @if (blankNodesCount > 0) {\n <th [attr.colspan]=\"blankNodesCount\" [class.has-border-right]=\"!dataKeyLast\">\n @if (dataKey) {\n <span>{{ dataKey | keyToLabel }}</span>\n }\n </th>\n }\n }\n </tr>\n }\n <tr class=\"has-text-weight-semibold\">\n <th class=\"width-auto has-border-right is-py-0\">\n <div class=\"is-hidden-mobile\">\n <ng-container *ngTemplateOutlet=\"filterModel\" />\n </div>\n </th>\n <th class=\"has-border-right\"></th>\n <th class=\"has-border-right\"></th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n <th\n [attr.title]=\"node.value.term.name\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n <he-node-link [node]=\"node.value.term\">\n <span\n [innerHtml]=\"\n node.value.term.name | ellipsis: 30 | compound: node.value.term.termType\n \"></span>\n </he-node-link>\n </th>\n }\n }\n }\n </tr>\n <tr class=\"is-italic has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n <th class=\"has-border-right\">\n <a [href]=\"schemaBaseUrl + '/ImpactAssessment#functionalUnit'\" target=\"_blank\">Functional unit</a>\n </th>\n <th class=\"has-border-right\">\n <a [href]=\"schemaBaseUrl + '/ImpactAssessment#product'\" target=\"_blank\">Product</a>\n </th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n <th\n [attr.title]=\"node.value.term.units\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n <span [innerHtml]=\"node.value.term.units | compound\"></span>\n <he-terms-units-description class=\"is-inline-block is-ml-2\" [term]=\"node.value.term\" />\n </th>\n }\n }\n }\n </tr>\n </thead>\n <tbody>\n @for (\n impactAssessment of impactAssessments();\n track nodeVersionKey(impactAssessment);\n let impactIndex = $index\n ) {\n @let product = productTerm(impactAssessment);\n <tr [class.is-suggested]=\"$any(impactAssessment).suggested\">\n <td class=\"width-auto has-border-right\" [attr.title]=\"impactName(impactAssessment)\">\n <he-node-link [node]=\"impactAssessment\">\n <span class=\"has-text-ellipsis is-ellipsis-3\">\n @if ($any(impactAssessment).suggested) {\n <he-svg-icon name=\"compare\" />\n } @else {\n <span>{{ impactIndex + 1 }}.</span>\n }\n <span class=\"is-pl-1\">{{ impactName(impactAssessment) }}</span>\n </span>\n </he-node-link>\n </td>\n <td class=\"has-border-right\" [attr.title]=\"product?.units\">\n <span>1 {{ product?.units }}</span>\n </td>\n <td class=\"has-border-right\" [attr.title]=\"product?.name\">\n @if (product) {\n <he-node-link [node]=\"product\">\n <span>{{ product.name | ellipsis: 30 }}</span>\n </he-node-link>\n }\n </td>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n @let impactData = node.value.values[nodeVersionKey(impactAssessment)];\n <td\n class=\"is-nowrap\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n @if (impactData) {\n <span\n class=\"trigger-popover\"\n [ngbPopover]=\"details\"\n autoClose=\"outside\"\n popoverClass=\"is-narrow is-overflow-visible\"\n placement=\"left bottom auto\"\n container=\"body\"\n [popoverContext]=\"{\n data: impactData,\n impactAssessment\n }\">\n <span pointer>\n {{ impactData.propertyValue | precision: 3 | default: '-' }}\n </span>\n <he-blank-node-state\n class=\"ml-1\"\n [dataState]=\"dataState()\"\n [node]=\"impactData.node\"\n key=\"value\"\n [state]=\"impactAssessment.aggregated ? 'aggregated' : undefined\" />\n </span>\n } @else {\n <span>-</span>\n }\n </td>\n }\n }\n }\n </tr>\n }\n </tbody>\n </table>\n </he-data-table>\n } @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 @if (impactAssessments().length > 1) {\n <div class=\"field is-relative is-mb-0\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded\"\n [id]=\"componentId() + 'hideIdenticalValues'\"\n name=\"hideIdenticalValues\"\n [(ngModel)]=\"hideIdenticalSelected\" />\n <label [for]=\"componentId() + 'hideIdenticalValues'\">\n <span>Hide identical values</span>\n </label>\n </div>\n }\n </div>\n } @else if (noDataMessage()) {\n <div class=\"is-pt-3 has-text-centered\">\n <span>{{ noDataMessage() }}</span>\n </div>\n } @else {\n <div class=\"is-pt-3 has-text-centered\">\n <span>No data available</span>\n @if (filterTerm()) {\n <span class=\"is-pl-1\">matching your search criteria</span>\n }\n <span>.</span>\n @if (showSwitchToRecalculated()) {\n <span>\n Switch to\n <code>recalculated</code>\n version.\n </span>\n }\n </div>\n }\n }\n @case (View.chart) {\n <he-impact-assessments-indicators-chart [key]=\"nodeKey()\" [filterTermTypes]=\"filterTermTypes()\">\n <ng-container *ngTemplateOutlet=\"selectView\" />\n </he-impact-assessments-indicators-chart>\n }\n @case (View.breakdown) {\n @if (selectedNode()) {\n <he-impact-assessments-indicator-breakdown-chart\n [impactAssessment]=\"selectedNode()\"\n [indicators]=\"selectedRecalculatedValues()\">\n <ng-container *ngTemplateOutlet=\"selectView\" />\n </he-impact-assessments-indicator-breakdown-chart>\n }\n }\n @case (View.logs) {\n @if (selectedNode()) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n <he-node-logs-models\n [node]=\"selectedNode()\"\n [cycle]=\"selectedCycle()\"\n [nodeKey]=\"nodeKey()\"\n [filterTermTypes]=\"filterTermTypes()\"\n [filterTermTypesLabel]=\"filterTermTypesLabel()\"\n [originalValues]=\"selectedOriginalValues()\"\n [recalculatedValues]=\"selectedRecalculatedValues()\"\n [noDataMessage]=\"noDataMessage()\" />\n }\n }\n }\n}\n\n<ng-template #filterModel>\n @if (enableFilterMethodModel()) {\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"updateSelectedMethodModel($event.target.value)\">\n <option [ngValue]=\"undefined\">Filter Model</option>\n @for (term of methodModels(); track term) {\n <option [ngValue]=\"term\">{{ term.name }}</option>\n }\n </select>\n </div>\n }\n</ng-template>\n\n<ng-template #selectView>\n <div class=\"is-flex is-gap-8 is-align-items-center is-justify-content-space-between\">\n <div class=\"is-flex is-gap-8 is-align-items-center\">\n @if (selectedView() === View.table) {\n @if (hasData()) {\n <button class=\"button is-small is-ghost is-p-2\" (click)=\"showDownload()\">\n <he-svg-icon name=\"download\" />\n </button>\n }\n <he-search-extend\n class=\"is-secondary\"\n collapsedClass=\"is-p-2\"\n placeholder=\"Filter terms by name\"\n (searchText)=\"filterTerm.set($event)\" />\n } @else if (showSelectImpact()) {\n <ng-container *ngTemplateOutlet=\"selectImpact\" />\n }\n </div>\n\n @if (views()?.length > 1) {\n <div class=\"field has-addons button-segments\">\n @for (view of views(); track view) {\n <div class=\"control\">\n <button\n class=\"button is-small\"\n [class.is-selected]=\"selectedView() === view\"\n (click)=\"selectedView.set(view)\">\n <he-svg-icon\n name=\"checkmark\"\n aria-hidden=\"true\"\n class=\"is-hidden-mobile\"\n [class.is-hidden-tablet]=\"selectedView() !== view\" />\n <he-svg-icon\n [name]=\"viewIcon[view]\"\n aria-hidden=\"true\"\n [class.is-hidden-tablet]=\"selectedView() === view\" />\n <span class=\"is-hidden-mobile\">{{ view }}</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #selectImpact>\n @if (impactAssessments().length > 1) {\n <div class=\"field is-horizontal is-mb-0\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary is-nowrap\" for=\"selectImpactAssessment\">Impact Assessment</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"selectIndex($event)\" if=\"selectImpactAssessment\">\n @for (value of impactAssessments(); track nodeVersionKey(value); let i = $index) {\n <option [value]=\"i\">{{ i + 1 }}. {{ impactName(value) }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n</ng-template>\n\n<ng-template #details let-node=\"impactAssessment\" let-data=\"data\">\n <p>\n <b>\n @if (data.cycle) {\n <span>{{ cycleLabel(node.cycle) }}</span>\n }\n @if (!data.cycle) {\n <span>{{ data.name }}</span>\n }\n </b>\n </p>\n <he-node-value-details\n class=\"is-overflow-visible\"\n [data]=\"data\"\n [dataState]=\"dataState()\"\n [nodeType]=\"node['@type']\"\n [dataKey]=\"nodeKey()\"\n [aggregated]=\"node.aggregated\" />\n</ng-template>\n", styles: [":host{display:block}he-data-table ::ng-deep .table thead tr th:nth-child(2),he-data-table ::ng-deep .table tbody tr td:nth-child(2){max-width:102px;width:102px}he-data-table ::ng-deep .table thead tr th:nth-child(3),he-data-table ::ng-deep .table tbody tr td:nth-child(3){min-width:110px}\n"], dependencies: [{ kind: "component", type: HESvgIconComponent, selector: "he-svg-icon", inputs: ["name", "size", "animation"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: SearchExtendComponent, selector: "he-search-extend", inputs: ["value", "disabled", "placeholder", "class", "collapsedClass"], outputs: ["valueChange", "searchText"] }, { kind: "component", type: DataTableComponent, selector: "he-data-table", inputs: ["minHeight", "maxHeight", "small"] }, { kind: "component", type: NodeLinkComponent, selector: "he-node-link", inputs: ["node", "dataState", "showExternalLink", "linkClass"] }, { kind: "component", type: TermsUnitsDescriptionComponent, selector: "he-terms-units-description", inputs: ["term", "iconTemplate"] }, { kind: "directive", type: NgbPopover, selector: "[ngbPopover]", inputs: ["animation", "autoClose", "ngbPopover", "popoverTitle", "placement", "popperOptions", "triggers", "positionTarget", "container", "disablePopover", "popoverClass", "popoverContext", "openDelay", "closeDelay"], outputs: ["shown", "hidden"], exportAs: ["ngbPopover"] }, { kind: "component", type: BlankNodeStateComponent, selector: "he-blank-node-state", inputs: ["dataState", "nodeType", "dataKey", "key", "node", "state", "linkClass"] }, { kind: "component", type: BlankNodeStateNoticeComponent, selector: "he-blank-node-state-notice", inputs: ["dataState", "showDeleted"] }, { kind: "component", type: ImpactAssessmentsIndicatorsChartComponent, selector: "he-impact-assessments-indicators-chart", inputs: ["key", "filterTermTypes"] }, { kind: "component", type: ImpactAssessmentsIndicatorBreakdownChartComponent, selector: "he-impact-assessments-indicator-breakdown-chart", inputs: ["impactAssessment", "indicators"] }, { kind: "component", type: NodeLogsModelsComponent, selector: "he-node-logs-models", inputs: ["node", "nodeKey", "originalValues", "recalculatedValues", "terms", "filterTermTypes", "filterTermTypesLabel", "logsKey", "noDataMessage", "cycle", "jlogParentKey", "jlogParentIndex"] }, { kind: "component", type: NodeValueDetailsComponent, selector: "he-node-value-details", inputs: ["data", "nodeType", "dataState", "dataKey", "aggregated"] }, { kind: "pipe", type: CompoundPipe, name: "compound" }, { kind: "pipe", type: DefaultPipe, name: "default" }, { kind: "pipe", type: EllipsisPipe, name: "ellipsis" }, { kind: "pipe", type: PrecisionPipe, name: "precision" }, { kind: "pipe", type: KeyToLabelPipe, name: "keyToLabel" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
15467
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: ImpactAssessmentsProductsComponent, isStandalone: true, selector: "he-impact-assessments-products", inputs: { dataState: { classPropertyName: "dataState", publicName: "dataState", isSignal: true, isRequired: false, transformFunction: null }, nodeKey: { classPropertyName: "nodeKey", publicName: "nodeKey", isSignal: true, isRequired: false, transformFunction: null }, filterTermTypes: { classPropertyName: "filterTermTypes", publicName: "filterTermTypes", isSignal: true, isRequired: false, transformFunction: null }, enableFilterMethodModel: { classPropertyName: "enableFilterMethodModel", publicName: "enableFilterMethodModel", isSignal: true, isRequired: false, transformFunction: null }, hideIdenticalValues: { classPropertyName: "hideIdenticalValues", publicName: "hideIdenticalValues", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (isNodeKeyAllowed()) {\n @switch (selectedView()) {\n @case (View.table) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n <div class=\"is-hidden-tablet is-mt-3\">\n <ng-container *ngTemplateOutlet=\"filterModel\" />\n </div>\n\n @if (hasData()) {\n @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 @if (dataKeys().length > 1) {\n <tr class=\"has-text-weight-bold\">\n <th class=\"width-auto\"></th>\n <th></th>\n <th></th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @let blankNodesCount = countGroupVisibleNodes(blankNodes);\n @if (blankNodesCount > 0) {\n <th [attr.colspan]=\"blankNodesCount\" [class.has-border-right]=\"!dataKeyLast\">\n @if (dataKey) {\n <span>{{ dataKey | keyToLabel }}</span>\n }\n </th>\n }\n }\n </tr>\n }\n <tr class=\"has-text-weight-semibold\">\n <th class=\"width-auto has-border-right is-py-0\">\n <div class=\"is-hidden-mobile\">\n <ng-container *ngTemplateOutlet=\"filterModel\" />\n </div>\n </th>\n <th class=\"has-border-right\"></th>\n <th class=\"has-border-right\"></th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n <th\n [attr.title]=\"node.value.term.name\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n <he-node-link [node]=\"node.value.term\">\n <span\n [innerHtml]=\"\n node.value.term.name | ellipsis: 30 | compound: node.value.term.termType\n \"></span>\n </he-node-link>\n </th>\n }\n }\n }\n </tr>\n <tr class=\"is-italic has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n <th class=\"has-border-right\">\n <a [href]=\"schemaBaseUrl + '/ImpactAssessment#functionalUnit'\" target=\"_blank\">Functional unit</a>\n </th>\n <th class=\"has-border-right\">\n <a [href]=\"schemaBaseUrl + '/ImpactAssessment#product'\" target=\"_blank\">Product</a>\n </th>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n <th\n [attr.title]=\"node.value.term.units\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n <span [innerHtml]=\"node.value.term.units | compound\"></span>\n <he-terms-units-description class=\"is-inline-block is-ml-2\" [term]=\"node.value.term\" />\n </th>\n }\n }\n }\n </tr>\n </thead>\n <tbody>\n @for (\n impactAssessment of impactAssessments();\n track nodeVersionKey(impactAssessment);\n let impactIndex = $index\n ) {\n @let product = productTerm(impactAssessment);\n <tr [class.is-suggested]=\"$any(impactAssessment).suggested\">\n <td class=\"width-auto has-border-right\" [attr.title]=\"impactName(impactAssessment)\">\n <he-node-link [node]=\"impactAssessment\">\n <span class=\"has-text-ellipsis is-ellipsis-3\">\n @if ($any(impactAssessment).suggested) {\n <he-svg-icon name=\"compare\" />\n } @else {\n <span>{{ impactIndex + 1 }}.</span>\n }\n <span class=\"is-pl-1\">{{ impactName(impactAssessment) }}</span>\n </span>\n </he-node-link>\n </td>\n <td class=\"has-border-right\" [attr.title]=\"product?.units\">\n <span>1 {{ product?.units }}</span>\n </td>\n <td class=\"has-border-right\" [attr.title]=\"product?.name\">\n @if (product) {\n <he-node-link [node]=\"product\">\n <span>{{ product.name | ellipsis: 30 }}</span>\n </he-node-link>\n }\n </td>\n @for (dataKey of dataKeys(); track dataKey; let dataKeyLast = $last) {\n @let blankNodes = data()[dataKey];\n @for (node of blankNodes; track node.value.term.name; let nodeLast = $last) {\n @if (node.value.visible) {\n @let impactData = node.value.values[nodeVersionKey(impactAssessment)];\n <td\n class=\"is-nowrap\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n @if (impactData) {\n <span\n class=\"trigger-popover\"\n [ngbPopover]=\"details\"\n autoClose=\"outside\"\n popoverClass=\"is-narrow is-overflow-visible\"\n placement=\"left bottom auto\"\n container=\"body\"\n [popoverContext]=\"{\n data: impactData,\n impactAssessment\n }\">\n <span pointer>\n {{ impactData.propertyValue | precision: 3 | default: '-' }}\n </span>\n <he-blank-node-state\n class=\"ml-1\"\n [dataState]=\"dataState()\"\n [node]=\"impactData.node\"\n key=\"value\"\n [state]=\"impactAssessment.aggregated ? 'aggregated' : undefined\" />\n </span>\n } @else {\n <span>-</span>\n }\n </td>\n }\n }\n }\n </tr>\n }\n </tbody>\n </table>\n </he-data-table>\n } @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 @if (impactAssessments().length > 1) {\n <div class=\"field is-relative is-mb-0\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded\"\n [id]=\"componentId() + 'hideIdenticalValues'\"\n name=\"hideIdenticalValues\"\n [(ngModel)]=\"hideIdenticalSelected\" />\n <label [for]=\"componentId() + 'hideIdenticalValues'\">\n <span>Hide identical values</span>\n </label>\n </div>\n }\n </div>\n } @else if (noDataMessage()) {\n <div class=\"is-pt-3 has-text-centered\">\n <span>{{ noDataMessage() }}</span>\n </div>\n } @else {\n <div class=\"is-pt-3 has-text-centered\">\n <span>No data available</span>\n @if (filterTerm()) {\n <span class=\"is-pl-1\">matching your search criteria</span>\n }\n <span>.</span>\n @if (showSwitchToRecalculated()) {\n <span>\n Switch to\n <code>recalculated</code>\n version.\n </span>\n }\n </div>\n }\n }\n @case (View.chart) {\n <he-impact-assessments-indicators-chart [key]=\"nodeKey()\" [filterTermTypes]=\"filterTermTypes()\">\n <ng-container *ngTemplateOutlet=\"selectView\" />\n </he-impact-assessments-indicators-chart>\n }\n @case (View.breakdown) {\n @if (selectedNode()) {\n <he-impact-assessments-indicator-breakdown-chart\n [impactAssessment]=\"selectedNode()\"\n [indicators]=\"selectedRecalculatedValues()\">\n <ng-container *ngTemplateOutlet=\"selectView\" />\n </he-impact-assessments-indicator-breakdown-chart>\n }\n }\n @case (View.logs) {\n @if (selectedNode()) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n <he-node-logs-models\n [node]=\"selectedNode()\"\n [cycle]=\"selectedCycle()\"\n [nodeKey]=\"nodeKey()\"\n [filterTermTypes]=\"filterTermTypes()\"\n [filterTermTypesLabel]=\"filterTermTypesLabel()\"\n [originalValues]=\"selectedOriginalValues()\"\n [recalculatedValues]=\"selectedRecalculatedValues()\"\n [noDataMessage]=\"noDataMessage()\" />\n }\n }\n }\n}\n\n<ng-template #filterModel>\n @if (enableFilterMethodModel()) {\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"updateSelectedMethodModel($event.target.value)\">\n <option [ngValue]=\"undefined\">Filter Model</option>\n @for (term of methodModels(); track term) {\n <option [ngValue]=\"term\">{{ term.name }}</option>\n }\n </select>\n </div>\n }\n</ng-template>\n\n<ng-template #selectView>\n <div class=\"is-flex is-gap-8 is-align-items-center is-justify-content-space-between\">\n <div class=\"is-flex is-gap-8 is-align-items-center\">\n @if (selectedView() === View.table) {\n @if (hasData()) {\n <button class=\"button is-small is-ghost is-p-2\" (click)=\"showDownload()\">\n <he-svg-icon name=\"download\" />\n </button>\n }\n <he-search-extend\n class=\"is-secondary\"\n collapsedClass=\"is-p-2\"\n placeholder=\"Filter terms by name\"\n (searchText)=\"filterTerm.set($event)\" />\n } @else if (showSelectImpact()) {\n <ng-container *ngTemplateOutlet=\"selectImpact\" />\n }\n </div>\n\n @if (views()?.length > 1) {\n <div class=\"field has-addons button-segments\">\n @for (view of views(); track view) {\n <div class=\"control\">\n <button\n class=\"button is-small\"\n [class.is-selected]=\"selectedView() === view\"\n (click)=\"selectedView.set(view)\">\n <he-svg-icon\n name=\"checkmark\"\n aria-hidden=\"true\"\n class=\"is-hidden-mobile\"\n [class.is-hidden-tablet]=\"selectedView() !== view\" />\n <he-svg-icon\n [name]=\"viewIcon[view]\"\n aria-hidden=\"true\"\n [class.is-hidden-tablet]=\"selectedView() === view\" />\n <span class=\"is-hidden-mobile\">{{ view }}</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #selectImpact>\n @if (impactAssessments().length > 1) {\n <div class=\"field is-horizontal is-mb-0\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary is-nowrap\" for=\"selectImpactAssessment\">Impact Assessment</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"selectIndex($event)\" if=\"selectImpactAssessment\">\n @for (value of impactAssessments(); track nodeVersionKey(value); let i = $index) {\n <option [value]=\"i\">{{ i + 1 }}. {{ impactName(value) }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n</ng-template>\n\n<ng-template #details let-node=\"impactAssessment\" let-data=\"data\">\n <p>\n <b>\n @if (data.cycle) {\n <span>{{ cycleLabel(node.cycle) }}</span>\n }\n @if (!data.cycle) {\n <span>{{ data.name }}</span>\n }\n </b>\n </p>\n <he-node-value-details\n class=\"is-overflow-visible\"\n [data]=\"data\"\n [dataState]=\"dataState()\"\n [nodeType]=\"node['@type']\"\n [dataKey]=\"nodeKey()\"\n [aggregated]=\"node.aggregated\" />\n</ng-template>\n", styles: [":host{display:block}he-data-table ::ng-deep .table thead tr th:nth-child(2),he-data-table ::ng-deep .table tbody tr td:nth-child(2){max-width:102px;width:102px}he-data-table ::ng-deep .table thead tr th:nth-child(3),he-data-table ::ng-deep .table tbody tr td:nth-child(3){min-width:110px}\n"], dependencies: [{ kind: "component", type: HESvgIconComponent, selector: "he-svg-icon", inputs: ["name", "size", "animation"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: SearchExtendComponent, selector: "he-search-extend", inputs: ["value", "disabled", "placeholder", "class", "collapsedClass", "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: "component", type: ImpactAssessmentsIndicatorsChartComponent, selector: "he-impact-assessments-indicators-chart", inputs: ["key", "filterTermTypes"] }, { kind: "component", type: ImpactAssessmentsIndicatorBreakdownChartComponent, selector: "he-impact-assessments-indicator-breakdown-chart", inputs: ["impactAssessment", "indicators"] }, { kind: "component", type: NodeLogsModelsComponent, selector: "he-node-logs-models", inputs: ["node", "nodeKey", "originalValues", "recalculatedValues", "terms", "filterTermTypes", "filterTermTypesLabel", "logsKey", "noDataMessage", "cycle", "jlogParentKey", "jlogParentIndex"] }, { kind: "component", type: NodeValueDetailsComponent, selector: "he-node-value-details", inputs: ["data", "nodeType", "dataState", "dataKey", "aggregated"] }, { kind: "pipe", type: CompoundPipe, name: "compound" }, { kind: "pipe", type: DefaultPipe, name: "default" }, { kind: "pipe", type: EllipsisPipe, name: "ellipsis" }, { kind: "pipe", type: PrecisionPipe, name: "precision" }, { kind: "pipe", type: KeyToLabelPipe, name: "keyToLabel" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
15305
15468
  }
15306
15469
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ImpactAssessmentsProductsComponent, decorators: [{
15307
15470
  type: Component$1,
@@ -15878,6 +16041,9 @@ class SitesNodesComponent {
15878
16041
  this.hasVisibleData = computed(() => countGroupVisibleNodes(this.data()) > 0, ...(ngDevMode ? [{ debugName: "hasVisibleData" }] : []));
15879
16042
  this.filterTermTypes = computed(() => nodeKeyFilterTermTypes[this.nodeKey()], ...(ngDevMode ? [{ debugName: "filterTermTypes" }] : []));
15880
16043
  this.filterTerm = signal('', ...(ngDevMode ? [{ debugName: "filterTerm" }] : []));
16044
+ this.termTypes = computed(() => blankNodesTermTypes(this.sites(), [this.nodeKey()]), ...(ngDevMode ? [{ debugName: "termTypes" }] : []));
16045
+ this.selectedTermTypes = linkedSignal({ ...(ngDevMode ? { debugName: "selectedTermTypes" } : {}), source: this.termTypes,
16046
+ computation: (termTypes, previous) => (previous?.value ?? []).filter(termType => termTypes.includes(termType)) });
15881
16047
  this.hideZeroValues = signal(false, ...(ngDevMode ? [{ debugName: "hideZeroValues" }] : []));
15882
16048
  // a page comparing several nodes can switch every table into differences-only at once; the
15883
16049
  // checkbox stays each table's own from there, so turning it off here leaves the others alone
@@ -15888,7 +16054,7 @@ class SitesNodesComponent {
15888
16054
  this.hideIdentical = computed(() => this.hideIdenticalSelected() && this.sites().length > 1, ...(ngDevMode ? [{ debugName: "hideIdentical" }] : []));
15889
16055
  this.csvFilename = computed(() => `${this.nodeKey()}.csv`, ...(ngDevMode ? [{ debugName: "csvFilename" }] : []));
15890
16056
  this.data = computed(() => {
15891
- const dataPerSite = groupNodesByTerm(this.sites(), this.nodeKey(), filterBlankNode$1(this.filterTerm()), this.hideZeroValues(), this.hideIdentical());
16057
+ const dataPerSite = groupNodesByTerm(this.sites(), this.nodeKey(), filterBlankNode$1(this.filterTerm(), this.selectedTermTypes()), this.hideZeroValues(), this.hideIdentical());
15892
16058
  return orderBy(grouppedKeys(dataPerSite), ['key'], ['asc']);
15893
16059
  }, ...(ngDevMode ? [{ debugName: "data" }] : []));
15894
16060
  effect(() => {
@@ -15915,7 +16081,7 @@ class SitesNodesComponent {
15915
16081
  component.headerKeys.set(this.headerKeys());
15916
16082
  }
15917
16083
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SitesNodesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
15918
- 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()) {\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 (searchText)=\"filterTerm.set($event)\" />\n } @else if (showSelectSite()) {\n <ng-container *ngTemplateOutlet=\"selectSite\" />\n }\n </div>\n\n @if (views()?.length > 1) {\n <div class=\"field has-addons button-segments\">\n @for (view of views(); track view) {\n <div class=\"control\">\n <button\n class=\"button is-small\"\n [class.is-selected]=\"selectedView() === view\"\n (click)=\"selectedView.set(view)\">\n <he-svg-icon\n name=\"checkmark\"\n aria-hidden=\"true\"\n class=\"is-hidden-mobile\"\n [class.is-hidden-tablet]=\"selectedView() !== view\" />\n <he-svg-icon\n [name]=\"viewIcon[view]\"\n aria-hidden=\"true\"\n [class.is-hidden-tablet]=\"selectedView() === view\" />\n <span class=\"is-hidden-mobile\">{{ view }}</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #selectSite>\n @if (sites().length > 1) {\n <div class=\"field is-horizontal is-mb-0\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary\" for=\"selectSite\">Site</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"selectIndex($event)\" if=\"selectSite\">\n @for (value of sites(); track nodeVersionKey(value); let siteIndex = $index) {\n <option [value]=\"siteIndex\">{{ siteIndex + 1 }}. {{ defaultLabel(value) }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n</ng-template>\n\n<ng-template #emptyValue>\n <span>-</span>\n</ng-template>\n\n<ng-template #details let-node=\"site\" let-data=\"data\">\n <p>\n <b>{{ node.name }}</b>\n </p>\n <he-node-value-details\n class=\"is-overflow-visible\"\n [data]=\"data\"\n [dataState]=\"dataState()\"\n [nodeType]=\"node['@type']\"\n [dataKey]=\"nodeKey()\"\n [aggregated]=\"node.aggregated\" />\n</ng-template>\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: HESvgIconComponent, selector: "he-svg-icon", inputs: ["name", "size", "animation"] }, { kind: "component", type: SearchExtendComponent, selector: "he-search-extend", inputs: ["value", "disabled", "placeholder", "class", "collapsedClass"], outputs: ["valueChange", "searchText"] }, { kind: "component", type: DataTableComponent, selector: "he-data-table", inputs: ["minHeight", "maxHeight", "small"] }, { kind: "component", type: NodeLinkComponent, selector: "he-node-link", inputs: ["node", "dataState", "showExternalLink", "linkClass"] }, { kind: "component", type: TermsUnitsDescriptionComponent, selector: "he-terms-units-description", inputs: ["term", "iconTemplate"] }, { kind: "directive", type: NgbPopover, selector: "[ngbPopover]", inputs: ["animation", "autoClose", "ngbPopover", "popoverTitle", "placement", "popperOptions", "triggers", "positionTarget", "container", "disablePopover", "popoverClass", "popoverContext", "openDelay", "closeDelay"], outputs: ["shown", "hidden"], exportAs: ["ngbPopover"] }, { kind: "component", type: BlankNodeStateComponent, selector: "he-blank-node-state", inputs: ["dataState", "nodeType", "dataKey", "key", "node", "state", "linkClass"] }, { kind: "component", type: BlankNodeStateNoticeComponent, selector: "he-blank-node-state-notice", inputs: ["dataState", "showDeleted"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: NodeLogsModelsComponent, selector: "he-node-logs-models", inputs: ["node", "nodeKey", "originalValues", "recalculatedValues", "terms", "filterTermTypes", "filterTermTypesLabel", "logsKey", "noDataMessage", "cycle", "jlogParentKey", "jlogParentIndex"] }, { kind: "component", type: 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" }] }); }
16084
+ 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" }] }); }
15919
16085
  }
15920
16086
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SitesNodesComponent, decorators: [{
15921
16087
  type: Component$1,
@@ -15940,7 +16106,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
15940
16106
  CapitalizePipe,
15941
16107
  PluralizePipe,
15942
16108
  SitesManagementChartComponent
15943
- ], 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()) {\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 (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"] }]
16109
+ ], 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"] }]
15944
16110
  }], 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 }] }] } });
15945
16111
 
15946
16112
  class TermsPropertyContentComponent {
@@ -16003,5 +16169,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
16003
16169
  * Generated bundle index. Do not edit.
16004
16170
  */
16005
16171
 
16006
- export { ARRAY_DELIMITER, ApplyPurePipe, BarChartComponent, BibliographiesSearchConfirmComponent, 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, 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, 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, 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, propertyId, recursiveProperties, refToSchemaType, refreshPropertyKeys, regionsQuery, repeat, reportIssueLink, reportIssueUrl, safeJSONParse, safeJSONStringify, schemaBaseUrl, schemaDataBaseUrl, schemaLink, schemaRequiredProperties, schemaTypeToDefaultValue, scrollToEl, scrollTop, searchFilterData, searchableTypes, siblingProperty, simplifyContributions, singleProperty, siteTooBig, siteTypeToColor, siteTypeToIcon, sortProperties, sortedDates, strokeColor, strokeStyle, subValueKeys, suggestMatchQuery, suggestQuery, suggestTerms, takeAfterViewInit, termLocation, termLocationName, termProperties, termSearch, termTypeLabel, toSnakeCase, toTextParts, toThousands, typeToNewProperty, typeaheadFocus, uncapitalize, uniqueDatesBetween, updateProperties, valueLink, valueToString, valueTypeToDefault, valueValue, waitFor, wildcardQuery };
16172
+ export { ARRAY_DELIMITER, ApplyPurePipe, BarChartComponent, BibliographiesSearchConfirmComponent, 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, waitFor, wildcardQuery };
16007
16173
  //# sourceMappingURL=hestia-earth-ui-components.mjs.map