@hestia-earth/ui-components 0.25.0 → 0.25.2

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.
@@ -19,11 +19,11 @@ import { AngularSvgIconModule } from 'angular-svg-icon';
19
19
  import * as i2 from 'angular-svg-icon-preloader';
20
20
  import { AngularSvgIconPreloaderModule } from 'angular-svg-icon-preloader';
21
21
  import get from 'lodash.get';
22
- import { SchemaType, isExpandable, TermTermType, EmissionMethodTier, NodeType, productTermTermType, nestedSearchableKeys, SCHEMA_VERSION, sortKeysByType, isTypeNode, SiteSiteType, emissionTermTermType, measurementTermTermType, impactAssessmentTermTermType, CycleFunctionalUnit, isTypeValid, typeToSchemaType, UploadLimit } from '@hestia-earth/schema';
22
+ import { SchemaType, isExpandable, TermTermType, EmissionMethodTier, NodeType, productTermTermType, nestedSearchableKeys, SCHEMA_VERSION, sortKeysByType, isTypeNode, emissionTermTermType, measurementTermTermType, impactAssessmentTermTermType, CycleFunctionalUnit, SiteSiteType, isTypeValid, typeToSchemaType, UploadLimit } from '@hestia-earth/schema';
23
23
  import * as i4$2 from 'rxjs';
24
24
  import { ReplaySubject, Subject, fromEvent, timer, of, zip, from, forkJoin, merge } from 'rxjs';
25
25
  import { BreakpointObserver } from '@angular/cdk/layout';
26
- import { map, distinctUntilChanged, tap, take, skipUntil, catchError, mergeAll, filter, toArray, mergeMap, shareReplay, delay, debounceTime, switchMap, first, reduce, groupBy, distinct, startWith } from 'rxjs/operators';
26
+ import { map, distinctUntilChanged, tap, take, skipUntil, catchError, mergeAll, filter, toArray, mergeMap, shareReplay, delay, debounceTime, switchMap, first, reduce, distinct, groupBy, startWith } from 'rxjs/operators';
27
27
  import { toSignal, takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';
28
28
  import * as i1$2 from '@angular/platform-browser';
29
29
  import { isUndefined, keyToLabel, toPrecision, isNumber, toComma, toDashCase, isBoolean, ConvertUnits, converters, convertValue, isEmpty, isEqual as isEqual$2, unique, diffInDays } from '@hestia-earth/utils';
@@ -6346,611 +6346,40 @@ const logValueArray = (value) => [';', ':'].some(v => value.includes(v))
6346
6346
  })
6347
6347
  : null;
6348
6348
 
6349
- class HeNodeCsvService {
6350
- constructor(schemaService) {
6351
- this.schemaService = schemaService;
6352
- }
6353
- async csvToJson(content) {
6354
- return toJson(await this.schemaService.schemas(), content);
6355
- }
6356
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: HeNodeCsvService, deps: [{ token: HeSchemaService }], target: i0.ɵɵFactoryTarget.Injectable }); }
6357
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: HeNodeCsvService, providedIn: 'root' }); }
6358
- }
6359
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: HeNodeCsvService, decorators: [{
6360
- type: Injectable,
6361
- args: [{
6362
- providedIn: 'root'
6363
- }]
6364
- }], ctorParameters: function () { return [{ type: HeSchemaService }]; } });
6365
-
6366
- const defaultDataStates = [DataState.original, DataState.recalculated];
6367
- const nodeTypeDataState = {
6368
- [NodeType.Cycle]: {
6369
- default: defaultDataStates,
6370
- aggregated: [DataState.original]
6371
- },
6372
- [NodeType.ImpactAssessment]: {
6373
- default: defaultDataStates,
6374
- aggregated: [DataState.recalculated]
6375
- },
6376
- [NodeType.Site]: {
6377
- default: defaultDataStates,
6378
- aggregated: [DataState.original]
6379
- }
6380
- };
6381
- const nodeTypeDataStates = (nodeType, aggregated = false) => {
6382
- const dataStatesMapping = nodeTypeDataState[nodeType] || {
6383
- default: [DataState.original],
6384
- aggregated: [DataState.original]
6385
- };
6386
- return aggregated ? dataStatesMapping.aggregated : dataStatesMapping.default;
6387
- };
6388
- const sortNodes = (values) => values?.length
6389
- ? orderBy(values.filter(Boolean), ['original.aggregated', 'original.site.@id', 'original.cycle.@id', 'original.@id'], ['asc', 'asc', 'asc', 'asc'])
6390
- : [];
6391
- const isAggregated = (id) => !!id.match(/^[a-zA-Z]+[-][a-zA-Z]+[-][\d]{4,}[-][\d]{4,}/g);
6392
- class HeNodeStoreService {
6393
- constructor(nodeService) {
6394
- this.nodeService = nodeService;
6395
- this._nodesLoadRequests = {};
6396
- this._nodes = {};
6397
- this._nodes$ = new ReplaySubject(1);
6398
- }
6399
- findNodeIndex(node) {
6400
- const nodes = this._nodes?.[node['@type']] || [];
6401
- return nodes.findIndex(n => n.type === node['@type'] && n.id === node['@id']);
6402
- }
6403
- loadNode(node) {
6404
- const aggregated = 'aggregated' in node ? node.aggregated : isAggregated(node['@id']);
6405
- const dataStates = nodeTypeDataStates(node['@type'], aggregated);
6406
- const index = this._nodesLoadRequests[node['@type']].length;
6407
- const request = forkJoin(dataStates.reduce((prev, dataState) => ({
6408
- ...prev,
6409
- [dataState]: this.nodeService
6410
- .get$({ ...node, dataState })
6411
- .pipe(catchError(() => of(undefined)))
6412
- }), {})).pipe(shareReplay({ bufferSize: 1, refCount: true }), map((values) => Object.fromEntries(Object.values(DataState).map(dataState => [
6413
- dataState,
6414
- values[dataState] || values[DataState.original] || node
6415
- ]))), map(values => ({
6416
- index,
6417
- type: node['@type'],
6418
- id: node['@id'],
6419
- ...values
6420
- })));
6421
- this._nodesLoadRequests[node['@type']].push({
6422
- id: node['@id'],
6423
- request
6424
- });
6425
- request.subscribe(data => {
6426
- this._nodes[node['@type']][index] = data;
6427
- this._nodes$.next(this._nodes);
6428
- });
6429
- return request;
6430
- }
6431
- addNode(node) {
6432
- this._nodesLoadRequests[node['@type']] = this._nodesLoadRequests[node['@type']] || [];
6433
- this._nodes[node['@type']] = this._nodes[node['@type']] || [];
6434
- const existingRequest = this._nodesLoadRequests[node['@type']].find(({ id }) => id === node['@id']);
6435
- return existingRequest ? existingRequest.request : this.loadNode(node);
6436
- }
6437
- removeNodeByIndex(nodeType, index) {
6438
- this._nodesLoadRequests[nodeType].splice(index, 1);
6439
- this._nodes[nodeType].splice(index, 1);
6440
- this._nodes$.next(this._nodes);
6441
- }
6442
- removeNode(node) {
6443
- const index = this.findNodeIndex(node);
6444
- return index >= 0 ? this.removeNodeByIndex(node['@type'], index) : null;
6445
- }
6446
- clearNodes() {
6447
- this._nodesLoadRequests = {};
6448
- this._nodes = {};
6449
- this._nodes$.next(this._nodes);
6450
- }
6451
- nodes$() {
6452
- return this._nodes$.asObservable();
6453
- }
6454
- sortedNodes$() {
6455
- return this.nodes$().pipe(map(nodes => Object.fromEntries(Object.entries(nodes).map(([nodeKey, values]) => [nodeKey, sortNodes(values)]))));
6456
- }
6457
- ids$(nodeType) {
6458
- return this.nodes$().pipe(mergeMap(values => values[nodeType]), map(({ id }) => id), toArray());
6459
- }
6460
- find$(nodeType, id) {
6461
- return this.nodes$().pipe(map(values => (values[nodeType] || []).filter(node => !id || node.id === id)));
6462
- }
6463
- findByState$(nodeType, dataState, id) {
6464
- return this.find$(nodeType, id).pipe(map(values => values.map(v => v[dataState]).filter(Boolean)));
6465
- }
6466
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: HeNodeStoreService, deps: [{ token: HeNodeService }], target: i0.ɵɵFactoryTarget.Injectable }); }
6467
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: HeNodeStoreService, providedIn: 'root' }); }
6468
- }
6469
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: HeNodeStoreService, decorators: [{
6470
- type: Injectable,
6471
- args: [{
6472
- providedIn: 'root'
6473
- }]
6474
- }], ctorParameters: function () { return [{ type: HeNodeService }]; } });
6475
-
6476
- class NodeMissingLookupFactorsComponent {
6477
- constructor(ref, nodeService) {
6478
- this.ref = ref;
6479
- this.nodeService = nodeService;
6480
- this.loading = true;
6481
- this.logs = [];
6482
- }
6483
- async ngOnInit() {
6484
- this.loading = true;
6485
- this.logs = await this.nodeService.getMissingLookupsLog({
6486
- ...this.node,
6487
- dataState: DataState.recalculated
6488
- });
6489
- this.loading = false;
6490
- this.ref.detectChanges();
6491
- }
6492
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: NodeMissingLookupFactorsComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: HeNodeService }], target: i0.ɵɵFactoryTarget.Component }); }
6493
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.8", type: NodeMissingLookupFactorsComponent, selector: "he-node-missing-lookup-factors", inputs: { node: "node" }, ngImport: i0, template: "<div *ngIf=\"!loading; else loader\" class=\"table-container data-table-container\">\n <table class=\"table is-fullwidth is-hoverable is-striped mb-0\">\n <thead>\n <tr>\n <th>\n <span>Filename</span>\n </th>\n <th>\n <span>Column Title</span>\n </th>\n <th>\n <span>Row (term.id)</span>\n </th>\n <th>\n <span>Model</span>\n </th>\n </tr>\n </thead>\n <tbody>\n <tr *ngIf=\"!logs.length\">\n <td colspan=\"3\">\n <span>No missing lookup factors.</span>\n </td>\n </tr>\n <tr *ngFor=\"let log of logs\">\n <td>{{ log.filename }}</td>\n <td>\n <span *ngIf=\"log.column; else na\">{{ log.column }}</span>\n </td>\n <td>\n <span *ngIf=\"log.termId; else na\">{{ log.termId }}</span>\n </td>\n <td>\n <ng-container *ngIf=\"log.model; else na\">\n <span>{{ log.model }}</span>\n <span class=\"pl-1\" *ngIf=\"log.key\">/ {{ log.key }}</span>\n <span class=\"pl-1\" *ngIf=\"log.term && log.term !== log.termId\">/ {{ log.term }}</span>\n </ng-container>\n </td>\n </tr>\n </tbody>\n </table>\n</div>\n\n<ng-template #loader>\n <div class=\"has-text-center py-3\">\n <fa-icon icon=\"spinner\" [pulse]=\"true\" size=\"lg\"></fa-icon>\n </div>\n</ng-template>\n\n<ng-template #na>\n <span>-</span>\n</ng-template>\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "spin", "pulse", "mask", "styles", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "classes", "transform", "a11yRole"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
6494
- }
6495
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: NodeMissingLookupFactorsComponent, decorators: [{
6496
- type: Component$1,
6497
- args: [{ selector: 'he-node-missing-lookup-factors', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div *ngIf=\"!loading; else loader\" class=\"table-container data-table-container\">\n <table class=\"table is-fullwidth is-hoverable is-striped mb-0\">\n <thead>\n <tr>\n <th>\n <span>Filename</span>\n </th>\n <th>\n <span>Column Title</span>\n </th>\n <th>\n <span>Row (term.id)</span>\n </th>\n <th>\n <span>Model</span>\n </th>\n </tr>\n </thead>\n <tbody>\n <tr *ngIf=\"!logs.length\">\n <td colspan=\"3\">\n <span>No missing lookup factors.</span>\n </td>\n </tr>\n <tr *ngFor=\"let log of logs\">\n <td>{{ log.filename }}</td>\n <td>\n <span *ngIf=\"log.column; else na\">{{ log.column }}</span>\n </td>\n <td>\n <span *ngIf=\"log.termId; else na\">{{ log.termId }}</span>\n </td>\n <td>\n <ng-container *ngIf=\"log.model; else na\">\n <span>{{ log.model }}</span>\n <span class=\"pl-1\" *ngIf=\"log.key\">/ {{ log.key }}</span>\n <span class=\"pl-1\" *ngIf=\"log.term && log.term !== log.termId\">/ {{ log.term }}</span>\n </ng-container>\n </td>\n </tr>\n </tbody>\n </table>\n</div>\n\n<ng-template #loader>\n <div class=\"has-text-center py-3\">\n <fa-icon icon=\"spinner\" [pulse]=\"true\" size=\"lg\"></fa-icon>\n </div>\n</ng-template>\n\n<ng-template #na>\n <span>-</span>\n</ng-template>\n", styles: [":host{display:block}\n"] }]
6498
- }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: HeNodeService }]; }, propDecorators: { node: [{
6499
- type: Input
6500
- }] } });
6501
-
6502
- // TODO: compute from the list of unique properties
6503
- const additionalKeys = [
6504
- 'key',
6505
- 'methodModelDescription',
6506
- 'methodDescription',
6507
- 'description',
6508
- 'primary',
6509
- 'emissionDuration',
6510
- 'observations',
6511
- 'statsDefinition',
6512
- 'term',
6513
- 'source',
6514
- 'variety',
6515
- 'reliability',
6516
- 'price',
6517
- 'currency',
6518
- 'cost',
6519
- 'revenue',
6520
- 'economicValueShare',
6521
- 'operation',
6522
- 'impactAssessment',
6523
- 'properties',
6524
- 'isAnimalFeed',
6525
- 'fate'
6526
- ];
6527
- const tableKeys = [
6528
- 'aniamals',
6529
- 'inputs',
6530
- 'properties',
6531
- 'transformation',
6532
- 'operation',
6533
- 'impactAssessment',
6534
- 'value',
6535
- 'term.units',
6536
- 'dates',
6537
- 'methodModel',
6538
- 'methodTier',
6539
- 'statsDefinition',
6540
- 'depthUpper',
6541
- 'depthLower'
6542
- ];
6543
- class NodeValueDetailsComponent {
6544
- constructor() {
6545
- this.baseUrl = baseUrl();
6546
- this.keys = ['value', ...grouppedValueKeys];
6547
- this.additionalKeys = additionalKeys;
6548
- this.tableKeys = tableKeys;
6549
- }
6550
- ngOnInit() {
6551
- this.tableKeys = tableKeys.filter(key => (this.data?.nodes || []).some(node => !!get(node, key)));
6552
- }
6553
- get type() {
6554
- return this.data?.nodes[0]['@type'];
6555
- }
6556
- get showInline() {
6557
- return this.data?.nodes?.length === 1;
6558
- }
6559
- defaultValue(key) {
6560
- return ['impactAssessment', 'transformation'].includes(key) ? 'N/A (from Cycle)' : '';
6561
- }
6562
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: NodeValueDetailsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6563
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.8", type: NodeValueDetailsComponent, selector: "he-node-value-details", inputs: { data: "data", nodeType: "nodeType", dataKey: "dataKey", dataState: "dataState" }, ngImport: i0, template: "<ng-container *bindOnce=\"data\">\n <ng-container *ngIf=\"showInline; else asTable\">\n <ng-container *ngFor=\"let key of keys\">\n <he-link-key-value\n [node]=\"data!.nodes[0]\"\n [nodeType]=\"nodeType\"\n [dataState]=\"dataState\"\n [dataKey]=\"dataKey\"\n [key]=\"key\"></he-link-key-value>\n </ng-container>\n <ng-container *ngFor=\"let key of additionalKeys\">\n <he-link-key-value\n [node]=\"data!.nodes[0]\"\n [nodeType]=\"nodeType\"\n [dataState]=\"dataState\"\n [dataKey]=\"dataKey\"\n [key]=\"key\"></he-link-key-value>\n </ng-container>\n </ng-container>\n</ng-container>\n\n<ng-template #asTable>\n <he-link-key-value\n [node]=\"data!.nodes[0]\"\n [nodeType]=\"nodeType\"\n [dataState]=\"dataState\"\n [dataKey]=\"dataKey\"\n key=\"term\"></he-link-key-value>\n\n <div class=\"table-container mt-2\">\n <table class=\"table is-dark is-narrow is-striped\">\n <thead>\n <th *ngFor=\"let key of tableKeys\">\n <a class=\"is-dark\" [href]=\"baseUrl + '/schema/' + type + '#' + key.split('.')[0]\" target=\"_blank\">\n <b>{{ key.includes('.') ? key.split('.')[1] : key }}</b>\n </a>\n </th>\n </thead>\n <tbody>\n <tr *ngFor=\"let node of data!.nodes\">\n <td *ngFor=\"let key of tableKeys\">\n <he-link-key-value\n [node]=\"node\"\n [nodeType]=\"nodeType\"\n [dataState]=\"dataState\"\n [dataKey]=\"dataKey\"\n [key]=\"key\"\n [defaultValue]=\"defaultValue(key)\"></he-link-key-value>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n</ng-template>\n", styles: ["table{background-color:transparent}table::ng-deep he-link-key-value>a:first-child,table::ng-deep he-link-key-value>a:first-child+span{display:none}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: BindOnceDirective, selector: "[bindOnce]", inputs: ["bindOnce"] }, { kind: "component", type: LinkKeyValueComponent, selector: "he-link-key-value", inputs: ["node", "nodeType", "dataKey", "key", "defaultValue", "dataState"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
6564
- }
6565
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: NodeValueDetailsComponent, decorators: [{
6566
- type: Component$1,
6567
- args: [{ selector: 'he-node-value-details', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *bindOnce=\"data\">\n <ng-container *ngIf=\"showInline; else asTable\">\n <ng-container *ngFor=\"let key of keys\">\n <he-link-key-value\n [node]=\"data!.nodes[0]\"\n [nodeType]=\"nodeType\"\n [dataState]=\"dataState\"\n [dataKey]=\"dataKey\"\n [key]=\"key\"></he-link-key-value>\n </ng-container>\n <ng-container *ngFor=\"let key of additionalKeys\">\n <he-link-key-value\n [node]=\"data!.nodes[0]\"\n [nodeType]=\"nodeType\"\n [dataState]=\"dataState\"\n [dataKey]=\"dataKey\"\n [key]=\"key\"></he-link-key-value>\n </ng-container>\n </ng-container>\n</ng-container>\n\n<ng-template #asTable>\n <he-link-key-value\n [node]=\"data!.nodes[0]\"\n [nodeType]=\"nodeType\"\n [dataState]=\"dataState\"\n [dataKey]=\"dataKey\"\n key=\"term\"></he-link-key-value>\n\n <div class=\"table-container mt-2\">\n <table class=\"table is-dark is-narrow is-striped\">\n <thead>\n <th *ngFor=\"let key of tableKeys\">\n <a class=\"is-dark\" [href]=\"baseUrl + '/schema/' + type + '#' + key.split('.')[0]\" target=\"_blank\">\n <b>{{ key.includes('.') ? key.split('.')[1] : key }}</b>\n </a>\n </th>\n </thead>\n <tbody>\n <tr *ngFor=\"let node of data!.nodes\">\n <td *ngFor=\"let key of tableKeys\">\n <he-link-key-value\n [node]=\"node\"\n [nodeType]=\"nodeType\"\n [dataState]=\"dataState\"\n [dataKey]=\"dataKey\"\n [key]=\"key\"\n [defaultValue]=\"defaultValue(key)\"></he-link-key-value>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n</ng-template>\n", styles: ["table{background-color:transparent}table::ng-deep he-link-key-value>a:first-child,table::ng-deep he-link-key-value>a:first-child+span{display:none}\n"] }]
6568
- }], propDecorators: { data: [{
6569
- type: Input
6570
- }], nodeType: [{
6571
- type: Input
6572
- }], dataKey: [{
6573
- type: Input
6574
- }], dataState: [{
6575
- type: Input
6576
- }] } });
6577
-
6578
- var NodeField;
6579
- (function (NodeField) {
6580
- NodeField["inputs"] = "inputs";
6581
- NodeField["measurements"] = "measurements";
6582
- NodeField["practices"] = "practices";
6583
- NodeField["products"] = "products";
6584
- })(NodeField || (NodeField = {}));
6585
- const filtersByType = {
6586
- [NodeType.Cycle]: cycle => {
6587
- const primaryProduct = (cycle.products || []).find(p => p.primary && !!p.term?.['@id']);
6588
- return primaryProduct
6589
- ? {
6590
- productTermId: primaryProduct.term['@id']
6591
- }
6592
- : {};
6593
- },
6594
- [NodeType.Site]: ({ siteType }) => ({
6595
- siteType
6596
- })
6597
- };
6598
- const termTypesByField = {
6599
- [NodeField.inputs]: SchemaType.Input,
6600
- [NodeField.measurements]: SchemaType.Measurement,
6601
- [NodeField.practices]: SchemaType.Practice,
6602
- [NodeField.products]: SchemaType.Product
6603
- };
6604
- const isValid = (node, nodeField) => Object.values(NodeField).includes(nodeField) && (node?.type || node?.['@type']) in filtersByType;
6605
- class NodeRecommendationsComponent {
6606
- constructor(engineService) {
6607
- this.engineService = engineService;
6608
- this.selectRecommendation = new EventEmitter$1();
6609
- this.loading = false;
6610
- this.visible = false;
6611
- this.recommendations = [];
6612
- }
6613
- ngOnChanges(changes) {
6614
- if ('node' in changes && isValid(this.node, this.nodeField)) {
6615
- const oldFilters = copyObject(this._filters);
6616
- this._filters = filterParams(filtersByType[this.type](this.node));
6617
- if (oldFilters === null || !isEqual(oldFilters, this._filters)) {
6618
- this.refresh();
6619
- }
6620
- }
6621
- }
6622
- trackByValue(_index, id) {
6623
- return id;
6624
- }
6625
- get type() {
6626
- return this.node?.type || this.node?.['@type'];
6627
- }
6628
- async refresh() {
6629
- this.loading = true;
6630
- const termType = termTypesByField[this.nodeField];
6631
- const ids = await this.engineService.getTermIds({ ...this._filters, termType });
6632
- const existingIds = (this.node[this.nodeField] || []).map(n => n.term?.['@id']).filter(Boolean);
6633
- this.recommendations = ids.filter(id => !existingIds.includes(id)).sort();
6634
- this.loading = false;
6635
- }
6636
- add(id, index) {
6637
- this.selectRecommendation.next(id);
6638
- const recommendations = this.recommendations.slice();
6639
- recommendations.splice(index, 1);
6640
- this.recommendations = recommendations;
6641
- }
6642
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: NodeRecommendationsComponent, deps: [{ token: HeEngineService }], target: i0.ɵɵFactoryTarget.Component }); }
6643
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.8", type: NodeRecommendationsComponent, selector: "he-node-recommendations", inputs: { node: "node", nodeField: "nodeField", buttonClass: "buttonClass" }, outputs: { selectRecommendation: "selectRecommendation" }, usesOnChanges: true, ngImport: i0, template: "<p class=\"my-2 is-size-7\" [class.is-hidden]=\"!loading && recommendations.length === 0\">\n <span class=\"pr-2\">Recommendations</span>\n <span *ngIf=\"loading\">\n <fa-icon icon=\"spinner\" [pulse]=\"true\" size=\"sm\"></fa-icon>\n </span>\n <a *ngIf=\"!loading\" (click)=\"visible = !visible\">\n <span *ngIf=\"visible\">Hide</span>\n <span *ngIf=\"!visible\">Show</span>\n </a>\n</p>\n\n<div [class.is-hidden]=\"!visible\">\n <button\n class=\"button mr-2 mb-2 {{ buttonClass }}\"\n *ngFor=\"let id of recommendations; trackBy: trackByValue; let i = index\"\n (click)=\"add(id, i)\">\n <fa-icon icon=\"plus-circle\"></fa-icon>\n <span class=\"pl-2\">Add</span>\n <span class=\"pl-1\">{{ id | keyToLabel }}</span>\n </button>\n</div>\n", styles: [""], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "spin", "pulse", "mask", "styles", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "classes", "transform", "a11yRole"] }, { kind: "pipe", type: KeyToLabelPipe, name: "keyToLabel" }] }); }
6644
- }
6645
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: NodeRecommendationsComponent, decorators: [{
6646
- type: Component$1,
6647
- args: [{ selector: 'he-node-recommendations', template: "<p class=\"my-2 is-size-7\" [class.is-hidden]=\"!loading && recommendations.length === 0\">\n <span class=\"pr-2\">Recommendations</span>\n <span *ngIf=\"loading\">\n <fa-icon icon=\"spinner\" [pulse]=\"true\" size=\"sm\"></fa-icon>\n </span>\n <a *ngIf=\"!loading\" (click)=\"visible = !visible\">\n <span *ngIf=\"visible\">Hide</span>\n <span *ngIf=\"!visible\">Show</span>\n </a>\n</p>\n\n<div [class.is-hidden]=\"!visible\">\n <button\n class=\"button mr-2 mb-2 {{ buttonClass }}\"\n *ngFor=\"let id of recommendations; trackBy: trackByValue; let i = index\"\n (click)=\"add(id, i)\">\n <fa-icon icon=\"plus-circle\"></fa-icon>\n <span class=\"pl-2\">Add</span>\n <span class=\"pl-1\">{{ id | keyToLabel }}</span>\n </button>\n</div>\n" }]
6648
- }], ctorParameters: function () { return [{ type: HeEngineService }]; }, propDecorators: { node: [{
6649
- type: Input
6650
- }], nodeField: [{
6651
- type: Input
6652
- }], buttonClass: [{
6653
- type: Input
6654
- }], selectRecommendation: [{
6655
- type: Output
6656
- }] } });
6657
-
6658
- // TODO: remove fallback
6659
- const MAX_STAGE = {
6660
- [NodeType.Cycle]: 2,
6661
- [NodeType.ImpactAssessment]: 1,
6662
- [NodeType.Site]: 2
6663
- };
6664
- class EngineModelsStageComponent {
6665
- set node(value) {
6666
- this._node.set(value);
6667
- }
6668
- constructor(nodeService) {
6669
- this.nodeService = nodeService;
6670
- this._node = signal(null);
6671
- this.defaultMaxStage = computed(() => MAX_STAGE[this._node()['@type']]);
6672
- this.node$ = toObservable(this._node);
6673
- this.headers = toSignal(this.node$.pipe(filter(node => !!node), mergeMap(node => this.nodeService.getWithHeaders$({
6674
- ...node,
6675
- dataState: DataState.recalculated
6676
- })), map(({ headers }) => headers)));
6677
- this.stage = computed(() => +this.headers()?.get('stage'));
6678
- this.maxStage = computed(() => +this.headers()?.get('maxstage') || this.defaultMaxStage());
6679
- this.inProgress = computed(() => this.stage() && this.stage() !== this.maxStage());
6680
- }
6681
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: EngineModelsStageComponent, deps: [{ token: HeNodeService }], target: i0.ɵɵFactoryTarget.Component }); }
6682
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.8", type: EngineModelsStageComponent, selector: "he-engine-models-stage", inputs: { node: "node" }, ngImport: i0, template: "<ng-container *ngIf=\"inProgress()\">\n <span class=\"tag is-warning\">\n <span>Calculation in progress (stage {{ stage() }} out of {{ maxStage() }})</span>\n </span>\n</ng-container>\n", styles: [":host{display:inline-block}\n"], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
6683
- }
6684
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: EngineModelsStageComponent, decorators: [{
6685
- type: Component$1,
6686
- args: [{ selector: 'he-engine-models-stage', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"inProgress()\">\n <span class=\"tag is-warning\">\n <span>Calculation in progress (stage {{ stage() }} out of {{ maxStage() }})</span>\n </span>\n</ng-container>\n", styles: [":host{display:inline-block}\n"] }]
6687
- }], ctorParameters: function () { return [{ type: HeNodeService }]; }, propDecorators: { node: [{
6688
- type: Input
6689
- }] } });
6690
-
6691
- /* eslint-disable max-len */
6692
- const semverRegex = () => /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/gi;
6693
- /* eslint-enable max-len */
6694
- const sort = (versions, compare) => versions.sort((v1, v2) => {
6695
- const sv1 = semverRegex().exec(v1)[0] || v1;
6696
- const sv2 = semverRegex().exec(v2)[0] || v2;
6697
- return compare(sv1, sv2);
6698
- });
6699
- const asc = (versions) => sort(versions, semver.compare);
6700
- const desc = (versions) => sort(versions, semver.rcompare);
6701
-
6702
- const isVersionKey = (key) => ['addedVersion', 'updatedVersion'].includes(key);
6703
- const isValidValue = (value) => !isUndefined(value) &&
6704
- typeof value === 'object' &&
6705
- (Array.isArray(value) || value.addedVersion || value.updatedVersion);
6706
- /**
6707
- * Get the most recent version of the models used to recalculate the node.
6708
- *
6709
- * @param node
6710
- * @returns The latest version
6711
- */
6712
- const nodeVersion = (node) => {
6713
- const versions = Object.entries(node || {})
6714
- .filter(([key, value]) => isVersionKey(key) || isValidValue(value))
6715
- .flatMap(([key, value]) => isVersionKey(key)
6716
- ? value
6717
- : typeof value === 'object'
6718
- ? Array.isArray(value)
6719
- ? value.map(nodeVersion)
6720
- : value.addedVersion || value.updatedVersion
6721
- : value)
6722
- .filter(Boolean);
6723
- return versions?.length ? desc(versions)[0] : null;
6724
- };
6725
-
6726
- class EngineModelsVersionLinkComponent {
6727
- constructor(service) {
6728
- this.service = service;
6729
- this.showDetails = false;
6730
- }
6731
- get version() {
6732
- return nodeVersion(this.node);
6733
- }
6734
- get url() {
6735
- return [engineGitBaseUrl(), '-', 'tree', `v${this.version}`].filter(Boolean).join('/');
6736
- }
6737
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: EngineModelsVersionLinkComponent, deps: [{ token: HeEngineService }], target: i0.ɵɵFactoryTarget.Component }); }
6738
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.8", type: EngineModelsVersionLinkComponent, selector: "he-engine-models-version-link", inputs: { node: "node", showDetails: "showDetails" }, ngImport: i0, template: "<ng-container *ngIf=\"version\">\n <div class=\"tags has-addons\" *ngIf=\"service.latestVersion$ | async as latestVersion\">\n <ng-container *bindOnce=\"url\">\n <a class=\"tag is-info\" [href]=\"url\" target=\"_blank\" (click)=\"$event.stopPropagation()\">\n {{ version }}\n <fa-icon class=\"ml-2\" icon=\"external-link-alt\" size=\"sm\"></fa-icon>\n </a>\n </ng-container>\n <ng-container *ngIf=\"showDetails\">\n <ng-container *ngIf=\"latestVersion === version; else outdated\">\n <ng-container *ngTemplateOutlet=\"latest\"></ng-container>\n </ng-container>\n </ng-container>\n </div>\n</ng-container>\n\n<ng-template #latest>\n <span class=\"tag is-success\">latest recalculations</span>\n</ng-template>\n\n<ng-template #outdated>\n <span class=\"tag is-warning\">outdated recalculations</span>\n</ng-template>\n", styles: [":host{display:inline-block}a{color:inherit}\n"], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i3.FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "spin", "pulse", "mask", "styles", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "classes", "transform", "a11yRole"] }, { kind: "directive", type: BindOnceDirective, selector: "[bindOnce]", inputs: ["bindOnce"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
6739
- }
6740
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: EngineModelsVersionLinkComponent, decorators: [{
6741
- type: Component$1,
6742
- args: [{ selector: 'he-engine-models-version-link', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"version\">\n <div class=\"tags has-addons\" *ngIf=\"service.latestVersion$ | async as latestVersion\">\n <ng-container *bindOnce=\"url\">\n <a class=\"tag is-info\" [href]=\"url\" target=\"_blank\" (click)=\"$event.stopPropagation()\">\n {{ version }}\n <fa-icon class=\"ml-2\" icon=\"external-link-alt\" size=\"sm\"></fa-icon>\n </a>\n </ng-container>\n <ng-container *ngIf=\"showDetails\">\n <ng-container *ngIf=\"latestVersion === version; else outdated\">\n <ng-container *ngTemplateOutlet=\"latest\"></ng-container>\n </ng-container>\n </ng-container>\n </div>\n</ng-container>\n\n<ng-template #latest>\n <span class=\"tag is-success\">latest recalculations</span>\n</ng-template>\n\n<ng-template #outdated>\n <span class=\"tag is-warning\">outdated recalculations</span>\n</ng-template>\n", styles: [":host{display:inline-block}a{color:inherit}\n"] }]
6743
- }], ctorParameters: function () { return [{ type: HeEngineService }]; }, propDecorators: { node: [{
6744
- type: Input
6745
- }], showDetails: [{
6746
- type: Input
6747
- }] } });
6748
-
6749
- const gitUrl = `${gitHome}/${Repository.orchestrator}/-/blob/${gitBranch()}`;
6750
- const generalDocsUrl = `${gitUrl}/hestia_earth/orchestrator/config/README.md`;
6751
- const strategiesDocs = `${gitUrl}/hestia_earth/orchestrator/strategies`;
6752
- const schemaTypeKeys = Object.keys(SchemaType);
6753
- const toSchemaType = (value) => keyToLabel(value).replace(/\s/g, '');
6754
- const isSchemaType = (value) => [
6755
- schemaTypeKeys.includes(value),
6756
- schemaTypeKeys.includes(pluralize(value, 1)),
6757
- schemaTypeKeys.includes(pluralize(toSchemaType(value), 1)),
6758
- ['emissionsResourceUse', 'impacts', 'endpoints'].includes(value)
6759
- ].some(Boolean);
6760
- const isGapFilled = ({ runStrategy, mergeStrategy, mergeArgs }) => ['add_blank_node_if_missing', 'add_key_if_missing'].includes(runStrategy) &&
6761
- (mergeStrategy !== 'list' || !mergeArgs?.replaceThreshold);
6762
- const isRecalculated = ({ runStrategy, mergeStrategy, mergeArgs }) => ['add_blank_node_if_missing', 'add_key_if_missing'].includes(runStrategy) &&
6763
- mergeStrategy === 'list' &&
6764
- mergeArgs?.replaceThreshold;
6765
- const filterGapFilled = (configs, onlyGapFilled) => configs
6766
- .map(model => (Array.isArray(model) && onlyGapFilled ? model.filter(isGapFilled) : model))
6767
- .filter(model => !onlyGapFilled || Array.isArray(model) || isGapFilled(model));
6768
- const modelMatch = (term) => ({ key, model, value }) => [key, model, value].filter(Boolean).some(v => v.toLowerCase().includes(term.toLowerCase()));
6769
- const filterModels = (configs, term = '') => configs
6770
- .map(model => (Array.isArray(model) && !!term ? model.filter(modelMatch(term)) : model))
6771
- .filter(model => !term || Array.isArray(model) || modelMatch(term)(model));
6772
- const modelKeyName = (modelKey) => (modelKey.includes('.') ? modelKey.split('.')[1] : modelKey);
6773
- const groupConfig = (configs) => from(configs.flat())
6774
- .pipe(filter(({ key }) => isSchemaType(key)), groupBy(({ key }) => key), mergeMap(group => group.pipe(toArray())), reduce((prev, curr) => {
6775
- const key = curr[0].key;
6776
- prev[toSchemaType(key)] = curr;
6777
- return prev;
6778
- }, {}))
6779
- .toPromise();
6780
- class EngineOrchestratorEditComponent {
6781
- constructor(hestiaEngineService, searchService) {
6782
- this.hestiaEngineService = hestiaEngineService;
6783
- this.searchService = searchService;
6784
- this.modelKeyName = modelKeyName;
6785
- this.isArray = Array.isArray;
6786
- this.generalDocsUrl = generalDocsUrl;
6787
- this.strategiesDocs = strategiesDocs;
6788
- this.termsById = {};
6789
- this.showConfig = false;
6790
- this.search = '';
6791
- this.onlyGapFilled = false;
6792
- this.showAdvanced = false;
6793
- this.displayBy = 'list';
6794
- this.showDisplayBy = false;
6795
- }
6796
- ngOnChanges(changes) {
6797
- if (changes.config?.currentValue) {
6798
- this.allModels = this.config.models;
6799
- this.computeTermsById();
6800
- return this.filterModels();
6801
- }
6802
- if ('nodeType' in changes) {
6803
- return this.loadDefaultConfig();
6804
- }
6805
- }
6806
- async loadDefaultConfig() {
6807
- const { models } = await this.hestiaEngineService.ochestratorConfig(this.nodeType);
6808
- this.allModels = models;
6809
- this.computeTermsById();
6810
- return this.filterModels();
6811
- }
6812
- async computeTermsById() {
6813
- const ids = unique(this.allModels
6814
- .flat()
6815
- .flatMap(model => [model.model, model.value])
6816
- .filter(Boolean));
6817
- const { results } = await this.searchService.search({
6818
- fields: ['@type', '@id', 'name', 'units'],
6819
- limit: ids.length,
6820
- query: {
6821
- bool: {
6822
- must: [matchType(NodeType.Term)],
6823
- should: ids.map(matchId),
6824
- minimum_should_match: 1
6825
- }
6826
- }
6827
- });
6828
- this.termsById = results.reduce((p, c) => ({ ...p, [c['@id']]: c }), {});
6829
- }
6830
- trackByKey(_index, { key }) {
6831
- return key;
6832
- }
6833
- modelLink$({ model, value }) {
6834
- return this.hestiaEngineService.model$({ model, term: value });
6835
- }
6836
- modelPathLink$({ model, value }) {
6837
- return this.hestiaEngineService.model$({
6838
- path: `${engineGitUrl()}/hestia_earth/models/${model}/${(value || '').replace('.', '/')}.py`
6839
- });
6840
- }
6841
- get configUrl() {
6842
- return this.hestiaEngineService.orchestratorConfigUrl(this.nodeType);
6843
- }
6844
- modelKeyUrl({ modelKey }, model) {
6845
- const parts = modelKey.split('.');
6846
- const schemaType = parts.length === 2 ? parts[0] : model;
6847
- const url = [baseUrl(), 'schema', toSchemaType(schemaType)].filter(Boolean).join('/');
6848
- return isSchemaType(schemaType) ? `${url}#${parts.pop()}` : null;
6849
- }
6850
- filterModels() {
6851
- setTimeout(async () => {
6852
- const models = filterModels(filterGapFilled(this.allModels, this.onlyGapFilled), this.search);
6853
- this.models = models;
6854
- this.groupedModels = await groupConfig(models);
6855
- this.selectedGroupedKey = Object.keys(this.groupedModels)?.[0];
6856
- });
6857
- }
6858
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: EngineOrchestratorEditComponent, deps: [{ token: HeEngineService }, { token: HeSearchService }], target: i0.ɵɵFactoryTarget.Component }); }
6859
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.8", type: EngineOrchestratorEditComponent, selector: "he-engine-orchestrator-edit", inputs: { config: "config", nodeType: "nodeType" }, usesOnChanges: true, ngImport: i0, template: "<p>\n <i>\n The configuration below is a preview of the\n <a [href]=\"configUrl\" target=\"_blank\">JSON configuration file</a>\n used for the orchestration of the Hestia's calculations.\n </i>\n</p>\n<p>\n <i>Note: not all models might be represented accurately.</i>\n</p>\n\n<div class=\"is-size-7 is-italic\">\n <div class=\"columns is-mobile is-multiline is-vcentered is-variable is-1 my-0\">\n <div class=\"column\">\n <div class=\"pl-3 model-parallel my-3\">\n <span>Models running in parallel</span>\n </div>\n </div>\n\n <div class=\"column is-narrow has-text-right\">\n <div\n class=\"dropdown is-right has-text-left is-dropdown-filters\"\n [class.is-active]=\"showConfig\"\n (clickOutside)=\"showConfig = false\">\n <div class=\"dropdown-trigger\" (click)=\"showConfig = !showConfig\">\n <button\n class=\"button is-ghost\"\n [class.is-active]=\"showConfig\"\n aria-haspopup=\"true\"\n aria-controls=\"option-menu\"\n ngbTooltip=\"Filters\"\n placement=\"bottom\"\n container=\"body\"\n [disableTooltip]=\"showConfig\">\n <span class=\"icon is-small\">\n <fa-icon icon=\"cog\" aria-hidden=\"true\"></fa-icon>\n </span>\n </button>\n </div>\n <div class=\"dropdown-menu\" id=\"option-menu\" role=\"menu\">\n <div class=\"dropdown-content\">\n <div class=\"dropdown-item\">\n <div class=\"field\">\n <div class=\"control is-expanded has-icons-right\">\n <input\n type=\"text\"\n class=\"input search-input is-secondary is-small\"\n [(ngModel)]=\"search\"\n name=\"collection\"\n placeholder=\"Filter by key, name or model\"\n (input)=\"filterModels()\" />\n <a class=\"icon is-small is-right\" (click)=\"search = ''; filterModels()\">\n <fa-icon icon=\"times\"></fa-icon>\n </a>\n </div>\n </div>\n\n <div class=\"field is-relative\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded is-secondary\"\n [(ngModel)]=\"showAdvanced\"\n id=\"showAdvanced\"\n (change)=\"filterModels()\" />\n <label class=\"is-size-7\" for=\"showAdvanced\">\n <span>Show advanced data</span>\n </label>\n </div>\n\n <div class=\"field is-relative\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded is-secondary\"\n [(ngModel)]=\"onlyGapFilled\"\n id=\"onlyGapFilled\"\n (change)=\"filterModels()\" />\n <label class=\"is-size-7\" for=\"onlyGapFilled\">\n <span>Show only gap-filled data</span>\n </label>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"column is-narrow has-text-right\">\n <div\n class=\"dropdown is-right has-text-left\"\n [class.is-active]=\"showDisplayBy\"\n (clickOutside)=\"showDisplayBy = false\">\n <div class=\"dropdown-trigger\" (click)=\"showDisplayBy = !showDisplayBy\">\n <button\n class=\"button is-ghost\"\n aria-haspopup=\"true\"\n aria-controls=\"display-menu\"\n ngbTooltip=\"Display options\"\n placement=\"bottom\"\n container=\"body\"\n [disableTooltip]=\"showDisplayBy\">\n <ng-container [ngSwitch]=\"displayBy\">\n <ng-container *ngSwitchCase=\"'list'\">\n <span class=\"icon is-small\">\n <fa-icon icon=\"list\" aria-hidden=\"true\"></fa-icon>\n </span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'type'\">\n <span class=\"icon is-small\">\n <fa-icon icon=\"table\" aria-hidden=\"true\"></fa-icon>\n </span>\n </ng-container>\n </ng-container>\n </button>\n </div>\n <div class=\"dropdown-menu\" id=\"display-menu\" role=\"menu\">\n <div class=\"dropdown-content\" (click)=\"showDisplayBy = false\">\n <a class=\"dropdown-item\" [class.is-selected]=\"displayBy === 'list'\" (click)=\"displayBy = 'list'\">\n <fa-icon icon=\"list\" aria-hidden=\"true\"></fa-icon>\n <span class=\"pl-2\">Display by Priority</span>\n </a>\n <a class=\"dropdown-item\" [class.is-selected]=\"displayBy === 'type'\" (click)=\"displayBy = 'type'\">\n <fa-icon icon=\"table\" aria-hidden=\"true\"></fa-icon>\n <span class=\"pl-2\">Display by Type</span>\n </a>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n\n<ng-container *ngIf=\"displayBy === 'list' && models\">\n <div class=\"pl-3\">\n <ng-container *ngTemplateOutlet=\"modelList; context: { $implicit: models }\"></ng-container>\n </div>\n</ng-container>\n\n<ng-container *ngIf=\"displayBy === 'type' && groupedModels\">\n <div class=\"tabs\">\n <ul>\n <li\n *ngFor=\"let group of groupedModels | keys; trackBy: trackByKey\"\n [class.is-active]=\"selectedGroupedKey === group.key\">\n <a (click)=\"selectedGroupedKey = group.key\">\n <span class=\"pl-2\">{{ group.key }} ({{ group.value.length }})</span>\n </a>\n </li>\n </ul>\n </div>\n\n <div class=\"pl-3\">\n <ng-container\n *ngTemplateOutlet=\"modelList; context: { $implicit: groupedModels[selectedGroupedKey] }\"></ng-container>\n </div>\n</ng-container>\n\n<ng-template #termLink let-value>\n <ng-template #defaultLabel>\n <span>{{ value | keyToLabel }}</span>\n </ng-template>\n\n <ng-container *ngIf=\"termsById[value]; else defaultLabel\">\n <he-node-link [node]=\"termsById[value]\" [showExternalLink]=\"true\">\n <span>{{ termsById[value].name }}</span>\n </he-node-link>\n </ng-container>\n</ng-template>\n\n<ng-template #modelList let-data>\n <div *ngFor=\"let v of data\">\n <ng-container *ngTemplateOutlet=\"model; context: { $implicit: v }\"></ng-container>\n </div>\n</ng-template>\n\n<ng-template #model let-data>\n <ng-container *ngIf=\"isArray(data) && data.length\">\n <div class=\"pl-3 model-parallel\">\n <ng-container *ngTemplateOutlet=\"modelList; context: { $implicit: data }\"></ng-container>\n </div>\n\n <hr />\n </ng-container>\n <ng-container *ngIf=\"!isArray(data)\">\n <div class=\"card mb-2 model-serie is-size-6\">\n <div class=\"card-content p-3\">\n <span class=\"is-capitalized\">{{ data.key | keyToLabel }}</span>\n :\n <ng-template #defaultView>\n <span class=\"default-value\">{{ data.value }}</span>\n\n <p>\n <span class=\"pr-1\">Model:</span>\n <span class=\"pr-2\">\n <ng-container *ngTemplateOutlet=\"termLink; context: { $implicit: data.model }\"></ng-container>\n </span>\n </p>\n </ng-template>\n\n <ng-template #modelFromPathLink>\n <ng-container *ngIf=\"modelPathLink$(data) | async as link; else defaultView\">\n <ng-container\n *ngTemplateOutlet=\"modelPathLink; context: { model: data.model, value: data.value, link }\"></ng-container>\n </ng-container>\n </ng-template>\n\n <ng-container *ngIf=\"modelLink$(data) | async as link; else modelFromPathLink\">\n <ng-container\n *ngTemplateOutlet=\"modelLink; context: { model: data.model, value: data.value, link }\"></ng-container>\n </ng-container>\n\n <div *ngIf=\"showAdvanced\">\n <div *ngIf=\"data.runStrategy\">\n <span class=\"pr-1\">Run strategy:</span>\n <ng-container\n *ngTemplateOutlet=\"strategiesLink; context: { strategy: data.runStrategy, type: 'run' }\"></ng-container>\n\n <div class=\"pl-3 is-size-7\" *ngIf=\"data.runArgs\">\n <p><b>Run arguments:</b></p>\n <ng-container *ngTemplateOutlet=\"strategiesArgs; context: { $implicit: data.runArgs }\"></ng-container>\n </div>\n </div>\n <div *ngIf=\"data.mergeStrategy\">\n <span class=\"pr-1\">Merge strategy:</span>\n <ng-container\n *ngTemplateOutlet=\"\n strategiesLink;\n context: { strategy: data.mergeStrategy, type: 'merge' }\n \"></ng-container>\n\n <div class=\"pl-3 is-size-7\" *ngIf=\"data.mergeArgs\">\n <p><b>Merge arguments:</b></p>\n <ng-container *ngTemplateOutlet=\"strategiesArgs; context: { $implicit: data.mergeArgs }\"></ng-container>\n </div>\n </div>\n </div>\n </div>\n </div>\n </ng-container>\n</ng-template>\n\n<ng-template #modelLinkKey let-model=\"model\" let-link=\"link\">\n <a [href]=\"modelKeyUrl(link, model)\" target=\"_blank\">{{ modelKeyName(link.modelKey) }}</a>\n</ng-template>\n\n<ng-template #modelLink let-model=\"model\" let-link=\"link\" let-value=\"value\">\n <ng-container *ngIf=\"link.term\">\n <ng-container *ngTemplateOutlet=\"termLink; context: { $implicit: link.term }\"></ng-container>\n </ng-container>\n\n <span *ngIf=\"!link.term && !link?.modelKey\" class=\"default-value\">{{ value }}</span>\n\n <ng-container *ngIf=\"!link.term && link?.modelKey\">\n <ng-container *ngTemplateOutlet=\"modelLinkKey; context: { link, model }\"></ng-container>\n </ng-container>\n\n <p class=\"model-link\">\n <span class=\"pr-1\">Model:</span>\n <span class=\"pr-2\">\n <ng-container *ngTemplateOutlet=\"termLink; context: { $implicit: model }\"></ng-container>\n </span>\n\n <a class=\"is-size-7\" [href]=\"link.docPath\" target=\"_blank\">\n <span class=\"pr-1\">(View Docs)</span>\n <fa-icon icon=\"external-link-alt\"></fa-icon>\n </a>\n </p>\n</ng-template>\n\n<ng-template #modelPathLink let-model=\"model\" let-link=\"link\" let-value=\"value\">\n <span *ngIf=\"!link?.modelKey\" class=\"default-value\">{{ value }}</span>\n\n <ng-container *ngIf=\"link?.modelKey\">\n <ng-container *ngTemplateOutlet=\"modelLinkKey; context: { link, model }\"></ng-container>\n </ng-container>\n\n <p class=\"model-path-link\">\n <span class=\"pr-1\">Model:</span>\n <span class=\"pr-2\">\n <ng-container *ngTemplateOutlet=\"termLink; context: { $implicit: model }\"></ng-container>\n </span>\n\n <a class=\"is-size-7\" [href]=\"link.docPath\" target=\"_blank\">\n <span class=\"pr-1\">(View Docs)</span>\n <fa-icon icon=\"external-link-alt\"></fa-icon>\n </a>\n </p>\n</ng-template>\n\n<ng-template #strategiesLink let-strategy=\"strategy\" let-type=\"type\">\n <span class=\"pr-2 is-inline-block\">\n <code>{{ strategy }}</code>\n </span>\n\n <a\n class=\"is-size-7\"\n [href]=\"strategiesDocs + '/' + type + '/' + (type === 'merge' ? 'merge_' : '') + strategy + '.md'\"\n target=\"_blank\">\n <span class=\"pr-1\">(View Docs)</span>\n <fa-icon icon=\"external-link-alt\"></fa-icon>\n </a>\n</ng-template>\n\n<ng-template #strategiesArgs let-args>\n <div class=\"pl-2\">\n <p *ngFor=\"let arg of args | keys\">\n <span class=\"has-text-underline\">{{ arg.key }}</span>\n :\n <code>{{ arg.value | json }}</code>\n </p>\n </div>\n</ng-template>\n", styles: [":host{display:block}.model-parallel{border-left:3px solid #4a4a4a}.dropdown.is-dropdown-filters .dropdown-content{min-width:250px}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1$1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1$1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i2$1.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: i2$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i4$1.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: i3.FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "spin", "pulse", "mask", "styles", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "classes", "transform", "a11yRole"] }, { kind: "directive", type: ClickOutsideDirective, selector: "[clickOutside]", inputs: ["clickOutsideListenAfter"], outputs: ["clickOutside"] }, { kind: "component", type: NodeLinkComponent, selector: "he-node-link", inputs: ["node", "showExternalLink", "linkClass"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }, { kind: "pipe", type: KeysPipe, name: "keys" }, { kind: "pipe", type: KeyToLabelPipe, name: "keyToLabel" }] }); }
6860
- }
6861
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: EngineOrchestratorEditComponent, decorators: [{
6862
- type: Component$1,
6863
- args: [{ selector: 'he-engine-orchestrator-edit', template: "<p>\n <i>\n The configuration below is a preview of the\n <a [href]=\"configUrl\" target=\"_blank\">JSON configuration file</a>\n used for the orchestration of the Hestia's calculations.\n </i>\n</p>\n<p>\n <i>Note: not all models might be represented accurately.</i>\n</p>\n\n<div class=\"is-size-7 is-italic\">\n <div class=\"columns is-mobile is-multiline is-vcentered is-variable is-1 my-0\">\n <div class=\"column\">\n <div class=\"pl-3 model-parallel my-3\">\n <span>Models running in parallel</span>\n </div>\n </div>\n\n <div class=\"column is-narrow has-text-right\">\n <div\n class=\"dropdown is-right has-text-left is-dropdown-filters\"\n [class.is-active]=\"showConfig\"\n (clickOutside)=\"showConfig = false\">\n <div class=\"dropdown-trigger\" (click)=\"showConfig = !showConfig\">\n <button\n class=\"button is-ghost\"\n [class.is-active]=\"showConfig\"\n aria-haspopup=\"true\"\n aria-controls=\"option-menu\"\n ngbTooltip=\"Filters\"\n placement=\"bottom\"\n container=\"body\"\n [disableTooltip]=\"showConfig\">\n <span class=\"icon is-small\">\n <fa-icon icon=\"cog\" aria-hidden=\"true\"></fa-icon>\n </span>\n </button>\n </div>\n <div class=\"dropdown-menu\" id=\"option-menu\" role=\"menu\">\n <div class=\"dropdown-content\">\n <div class=\"dropdown-item\">\n <div class=\"field\">\n <div class=\"control is-expanded has-icons-right\">\n <input\n type=\"text\"\n class=\"input search-input is-secondary is-small\"\n [(ngModel)]=\"search\"\n name=\"collection\"\n placeholder=\"Filter by key, name or model\"\n (input)=\"filterModels()\" />\n <a class=\"icon is-small is-right\" (click)=\"search = ''; filterModels()\">\n <fa-icon icon=\"times\"></fa-icon>\n </a>\n </div>\n </div>\n\n <div class=\"field is-relative\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded is-secondary\"\n [(ngModel)]=\"showAdvanced\"\n id=\"showAdvanced\"\n (change)=\"filterModels()\" />\n <label class=\"is-size-7\" for=\"showAdvanced\">\n <span>Show advanced data</span>\n </label>\n </div>\n\n <div class=\"field is-relative\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded is-secondary\"\n [(ngModel)]=\"onlyGapFilled\"\n id=\"onlyGapFilled\"\n (change)=\"filterModels()\" />\n <label class=\"is-size-7\" for=\"onlyGapFilled\">\n <span>Show only gap-filled data</span>\n </label>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"column is-narrow has-text-right\">\n <div\n class=\"dropdown is-right has-text-left\"\n [class.is-active]=\"showDisplayBy\"\n (clickOutside)=\"showDisplayBy = false\">\n <div class=\"dropdown-trigger\" (click)=\"showDisplayBy = !showDisplayBy\">\n <button\n class=\"button is-ghost\"\n aria-haspopup=\"true\"\n aria-controls=\"display-menu\"\n ngbTooltip=\"Display options\"\n placement=\"bottom\"\n container=\"body\"\n [disableTooltip]=\"showDisplayBy\">\n <ng-container [ngSwitch]=\"displayBy\">\n <ng-container *ngSwitchCase=\"'list'\">\n <span class=\"icon is-small\">\n <fa-icon icon=\"list\" aria-hidden=\"true\"></fa-icon>\n </span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'type'\">\n <span class=\"icon is-small\">\n <fa-icon icon=\"table\" aria-hidden=\"true\"></fa-icon>\n </span>\n </ng-container>\n </ng-container>\n </button>\n </div>\n <div class=\"dropdown-menu\" id=\"display-menu\" role=\"menu\">\n <div class=\"dropdown-content\" (click)=\"showDisplayBy = false\">\n <a class=\"dropdown-item\" [class.is-selected]=\"displayBy === 'list'\" (click)=\"displayBy = 'list'\">\n <fa-icon icon=\"list\" aria-hidden=\"true\"></fa-icon>\n <span class=\"pl-2\">Display by Priority</span>\n </a>\n <a class=\"dropdown-item\" [class.is-selected]=\"displayBy === 'type'\" (click)=\"displayBy = 'type'\">\n <fa-icon icon=\"table\" aria-hidden=\"true\"></fa-icon>\n <span class=\"pl-2\">Display by Type</span>\n </a>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n\n<ng-container *ngIf=\"displayBy === 'list' && models\">\n <div class=\"pl-3\">\n <ng-container *ngTemplateOutlet=\"modelList; context: { $implicit: models }\"></ng-container>\n </div>\n</ng-container>\n\n<ng-container *ngIf=\"displayBy === 'type' && groupedModels\">\n <div class=\"tabs\">\n <ul>\n <li\n *ngFor=\"let group of groupedModels | keys; trackBy: trackByKey\"\n [class.is-active]=\"selectedGroupedKey === group.key\">\n <a (click)=\"selectedGroupedKey = group.key\">\n <span class=\"pl-2\">{{ group.key }} ({{ group.value.length }})</span>\n </a>\n </li>\n </ul>\n </div>\n\n <div class=\"pl-3\">\n <ng-container\n *ngTemplateOutlet=\"modelList; context: { $implicit: groupedModels[selectedGroupedKey] }\"></ng-container>\n </div>\n</ng-container>\n\n<ng-template #termLink let-value>\n <ng-template #defaultLabel>\n <span>{{ value | keyToLabel }}</span>\n </ng-template>\n\n <ng-container *ngIf=\"termsById[value]; else defaultLabel\">\n <he-node-link [node]=\"termsById[value]\" [showExternalLink]=\"true\">\n <span>{{ termsById[value].name }}</span>\n </he-node-link>\n </ng-container>\n</ng-template>\n\n<ng-template #modelList let-data>\n <div *ngFor=\"let v of data\">\n <ng-container *ngTemplateOutlet=\"model; context: { $implicit: v }\"></ng-container>\n </div>\n</ng-template>\n\n<ng-template #model let-data>\n <ng-container *ngIf=\"isArray(data) && data.length\">\n <div class=\"pl-3 model-parallel\">\n <ng-container *ngTemplateOutlet=\"modelList; context: { $implicit: data }\"></ng-container>\n </div>\n\n <hr />\n </ng-container>\n <ng-container *ngIf=\"!isArray(data)\">\n <div class=\"card mb-2 model-serie is-size-6\">\n <div class=\"card-content p-3\">\n <span class=\"is-capitalized\">{{ data.key | keyToLabel }}</span>\n :\n <ng-template #defaultView>\n <span class=\"default-value\">{{ data.value }}</span>\n\n <p>\n <span class=\"pr-1\">Model:</span>\n <span class=\"pr-2\">\n <ng-container *ngTemplateOutlet=\"termLink; context: { $implicit: data.model }\"></ng-container>\n </span>\n </p>\n </ng-template>\n\n <ng-template #modelFromPathLink>\n <ng-container *ngIf=\"modelPathLink$(data) | async as link; else defaultView\">\n <ng-container\n *ngTemplateOutlet=\"modelPathLink; context: { model: data.model, value: data.value, link }\"></ng-container>\n </ng-container>\n </ng-template>\n\n <ng-container *ngIf=\"modelLink$(data) | async as link; else modelFromPathLink\">\n <ng-container\n *ngTemplateOutlet=\"modelLink; context: { model: data.model, value: data.value, link }\"></ng-container>\n </ng-container>\n\n <div *ngIf=\"showAdvanced\">\n <div *ngIf=\"data.runStrategy\">\n <span class=\"pr-1\">Run strategy:</span>\n <ng-container\n *ngTemplateOutlet=\"strategiesLink; context: { strategy: data.runStrategy, type: 'run' }\"></ng-container>\n\n <div class=\"pl-3 is-size-7\" *ngIf=\"data.runArgs\">\n <p><b>Run arguments:</b></p>\n <ng-container *ngTemplateOutlet=\"strategiesArgs; context: { $implicit: data.runArgs }\"></ng-container>\n </div>\n </div>\n <div *ngIf=\"data.mergeStrategy\">\n <span class=\"pr-1\">Merge strategy:</span>\n <ng-container\n *ngTemplateOutlet=\"\n strategiesLink;\n context: { strategy: data.mergeStrategy, type: 'merge' }\n \"></ng-container>\n\n <div class=\"pl-3 is-size-7\" *ngIf=\"data.mergeArgs\">\n <p><b>Merge arguments:</b></p>\n <ng-container *ngTemplateOutlet=\"strategiesArgs; context: { $implicit: data.mergeArgs }\"></ng-container>\n </div>\n </div>\n </div>\n </div>\n </div>\n </ng-container>\n</ng-template>\n\n<ng-template #modelLinkKey let-model=\"model\" let-link=\"link\">\n <a [href]=\"modelKeyUrl(link, model)\" target=\"_blank\">{{ modelKeyName(link.modelKey) }}</a>\n</ng-template>\n\n<ng-template #modelLink let-model=\"model\" let-link=\"link\" let-value=\"value\">\n <ng-container *ngIf=\"link.term\">\n <ng-container *ngTemplateOutlet=\"termLink; context: { $implicit: link.term }\"></ng-container>\n </ng-container>\n\n <span *ngIf=\"!link.term && !link?.modelKey\" class=\"default-value\">{{ value }}</span>\n\n <ng-container *ngIf=\"!link.term && link?.modelKey\">\n <ng-container *ngTemplateOutlet=\"modelLinkKey; context: { link, model }\"></ng-container>\n </ng-container>\n\n <p class=\"model-link\">\n <span class=\"pr-1\">Model:</span>\n <span class=\"pr-2\">\n <ng-container *ngTemplateOutlet=\"termLink; context: { $implicit: model }\"></ng-container>\n </span>\n\n <a class=\"is-size-7\" [href]=\"link.docPath\" target=\"_blank\">\n <span class=\"pr-1\">(View Docs)</span>\n <fa-icon icon=\"external-link-alt\"></fa-icon>\n </a>\n </p>\n</ng-template>\n\n<ng-template #modelPathLink let-model=\"model\" let-link=\"link\" let-value=\"value\">\n <span *ngIf=\"!link?.modelKey\" class=\"default-value\">{{ value }}</span>\n\n <ng-container *ngIf=\"link?.modelKey\">\n <ng-container *ngTemplateOutlet=\"modelLinkKey; context: { link, model }\"></ng-container>\n </ng-container>\n\n <p class=\"model-path-link\">\n <span class=\"pr-1\">Model:</span>\n <span class=\"pr-2\">\n <ng-container *ngTemplateOutlet=\"termLink; context: { $implicit: model }\"></ng-container>\n </span>\n\n <a class=\"is-size-7\" [href]=\"link.docPath\" target=\"_blank\">\n <span class=\"pr-1\">(View Docs)</span>\n <fa-icon icon=\"external-link-alt\"></fa-icon>\n </a>\n </p>\n</ng-template>\n\n<ng-template #strategiesLink let-strategy=\"strategy\" let-type=\"type\">\n <span class=\"pr-2 is-inline-block\">\n <code>{{ strategy }}</code>\n </span>\n\n <a\n class=\"is-size-7\"\n [href]=\"strategiesDocs + '/' + type + '/' + (type === 'merge' ? 'merge_' : '') + strategy + '.md'\"\n target=\"_blank\">\n <span class=\"pr-1\">(View Docs)</span>\n <fa-icon icon=\"external-link-alt\"></fa-icon>\n </a>\n</ng-template>\n\n<ng-template #strategiesArgs let-args>\n <div class=\"pl-2\">\n <p *ngFor=\"let arg of args | keys\">\n <span class=\"has-text-underline\">{{ arg.key }}</span>\n :\n <code>{{ arg.value | json }}</code>\n </p>\n </div>\n</ng-template>\n", styles: [":host{display:block}.model-parallel{border-left:3px solid #4a4a4a}.dropdown.is-dropdown-filters .dropdown-content{min-width:250px}\n"] }]
6864
- }], ctorParameters: function () { return [{ type: HeEngineService }, { type: HeSearchService }]; }, propDecorators: { config: [{
6865
- type: Input
6866
- }], nodeType: [{
6867
- type: Input
6868
- }] } });
6869
-
6870
- class EngineRequirementsFormComponent {
6871
- constructor(formBuilder, searchService) {
6872
- this.formBuilder = formBuilder;
6873
- this.searchService = searchService;
6874
- this.form = this.formBuilder.group({
6875
- productTermId: [undefined],
6876
- productTermType: [undefined],
6877
- tier: [undefined],
6878
- siteType: [undefined]
6879
- });
6880
- this.productTermTermType = productTermTermType.term;
6881
- this.EmissionMethodTier = EmissionMethodTier;
6882
- this.SiteSiteType = SiteSiteType;
6883
- this.suggestingProductTermId = false;
6884
- this.suggestProductTermId = (text$) => text$.pipe(debounceTime(300), distinctUntilChanged(), tap(() => (this.suggestingProductTermId = true)), switchMap(term => (term.length < 1 ? [] : this.suggestTerm(term))), tap(() => (this.suggestingProductTermId = false)));
6885
- this.inputFormatterProductTermId = ({ name }) => name;
6886
- }
6887
- suggestTerm(term) {
6888
- return this.searchService.suggest(term, NodeType.Term, null, {
6889
- bool: {
6890
- must: [
6891
- matchType(NodeType.Term),
6892
- {
6893
- bool: {
6894
- should: suggestMatchQuery(term),
6895
- minimum_should_match: 1
6896
- }
6897
- },
6898
- {
6899
- bool: {
6900
- should: productTermTermType.term.map(matchTermType),
6901
- minimum_should_match: 1
6902
- }
6903
- }
6904
- ]
6905
- }
6906
- });
6907
- }
6908
- /**
6909
- * Return if form is valid.
6910
- */
6911
- get valid() {
6912
- return this.form ? !this.form.invalid : true;
6913
- }
6914
- formValue() {
6915
- const { productTermId, ...value } = this.form ? this.form.getRawValue() : { productTermId: undefined };
6916
- return {
6917
- ...value,
6918
- ...(productTermId ? { productTermId: productTermId['@id'] } : {}) // selected as a JSON-LD Object
6919
- };
6920
- }
6921
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: EngineRequirementsFormComponent, deps: [{ token: i2$1.UntypedFormBuilder }, { token: HeSearchService }], target: i0.ɵɵFactoryTarget.Component }); }
6922
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.8", type: EngineRequirementsFormComponent, selector: "he-engine-requirements-form", ngImport: i0, 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 <fa-icon icon=\"spinner\" [pulse]=\"true\"></fa-icon>\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 <option *ngFor=\"let termType of productTermTermType\" [value]=\"termType\">\n {{ termType | keyToLabel }}\n </option>\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 <option *ngFor=\"let tier of EmissionMethodTier | keys\" [value]=\"tier.value\">{{ tier.value }}</option>\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 <option *ngFor=\"let siteType of SiteSiteType | keys\" [value]=\"siteType.value\">\n {{ siteType.value }}\n </option>\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\"></ngb-highlight>\n</ng-template>\n", styles: [""], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2$1.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: i2$1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i4$1.NgbHighlight, selector: "ngb-highlight", inputs: ["highlightClass", "result", "term", "accentSensitive"] }, { kind: "directive", type: i4$1.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: i3.FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "spin", "pulse", "mask", "styles", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "classes", "transform", "a11yRole"] }, { kind: "pipe", type: KeysPipe, name: "keys" }, { kind: "pipe", type: KeyToLabelPipe, name: "keyToLabel" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
6923
- }
6924
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: EngineRequirementsFormComponent, decorators: [{
6925
- type: Component$1,
6926
- args: [{ selector: 'he-engine-requirements-form', changeDetection: ChangeDetectionStrategy.OnPush, 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 <fa-icon icon=\"spinner\" [pulse]=\"true\"></fa-icon>\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 <option *ngFor=\"let termType of productTermTermType\" [value]=\"termType\">\n {{ termType | keyToLabel }}\n </option>\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 <option *ngFor=\"let tier of EmissionMethodTier | keys\" [value]=\"tier.value\">{{ tier.value }}</option>\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 <option *ngFor=\"let siteType of SiteSiteType | keys\" [value]=\"siteType.value\">\n {{ siteType.value }}\n </option>\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\"></ngb-highlight>\n</ng-template>\n" }]
6927
- }], ctorParameters: function () { return [{ type: i2$1.UntypedFormBuilder }, { type: HeSearchService }]; } });
6349
+ /* eslint-disable max-len */
6350
+ const semverRegex = () => /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/gi;
6351
+ /* eslint-enable max-len */
6352
+ const sort = (versions, compare) => versions.sort((v1, v2) => {
6353
+ const sv1 = semverRegex().exec(v1)[0] || v1;
6354
+ const sv2 = semverRegex().exec(v2)[0] || v2;
6355
+ return compare(sv1, sv2);
6356
+ });
6357
+ const asc = (versions) => sort(versions, semver.compare);
6358
+ const desc = (versions) => sort(versions, semver.rcompare);
6928
6359
 
6929
- const components$8 = [
6930
- EngineModelsStageComponent,
6931
- EngineModelsVersionLinkComponent,
6932
- EngineOrchestratorEditComponent,
6933
- EngineRequirementsFormComponent
6934
- ];
6935
- class HeEngineModule {
6936
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: HeEngineModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
6937
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.1.8", ngImport: i0, type: HeEngineModule, declarations: [EngineModelsStageComponent,
6938
- EngineModelsVersionLinkComponent,
6939
- EngineOrchestratorEditComponent,
6940
- EngineRequirementsFormComponent], imports: [CommonModule, ReactiveFormsModule, FormsModule, HeCommonModule, HeNodeModule], exports: [EngineModelsStageComponent,
6941
- EngineModelsVersionLinkComponent,
6942
- EngineOrchestratorEditComponent,
6943
- EngineRequirementsFormComponent] }); }
6944
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: HeEngineModule, imports: [CommonModule, ReactiveFormsModule, FormsModule, HeCommonModule, HeNodeModule] }); }
6945
- }
6946
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: HeEngineModule, decorators: [{
6947
- type: NgModule,
6948
- args: [{
6949
- declarations: components$8,
6950
- exports: components$8,
6951
- imports: [CommonModule, ReactiveFormsModule, FormsModule, HeCommonModule, HeNodeModule]
6952
- }]
6953
- }] });
6360
+ const isVersionKey = (key) => ['addedVersion', 'updatedVersion'].includes(key);
6361
+ const isValidValue = (value) => !isUndefined(value) &&
6362
+ typeof value === 'object' &&
6363
+ (Array.isArray(value) || value.addedVersion || value.updatedVersion);
6364
+ /**
6365
+ * Get the most recent version of the models used to recalculate the node.
6366
+ *
6367
+ * @param node
6368
+ * @returns The latest version
6369
+ */
6370
+ const nodeVersion = (node) => {
6371
+ const versions = Object.entries(node || {})
6372
+ .filter(([key, value]) => isVersionKey(key) || isValidValue(value))
6373
+ .flatMap(([key, value]) => isVersionKey(key)
6374
+ ? value
6375
+ : typeof value === 'object'
6376
+ ? Array.isArray(value)
6377
+ ? value.map(nodeVersion)
6378
+ : value.addedVersion || value.updatedVersion
6379
+ : value)
6380
+ .filter(Boolean);
6381
+ return versions?.length ? desc(versions)[0] : null;
6382
+ };
6954
6383
 
6955
6384
  const nodeType = (node) => node?.['@type'] || node?.type;
6956
6385
  const nodeId = (node) => node?.['@id'] || node?.id;
@@ -7230,12 +6659,6 @@ class NodeLogsModelsComponent {
7230
6659
  trackByBlankNode(_index, node) {
7231
6660
  return node.termId || node.key;
7232
6661
  }
7233
- termChanged(value) {
7234
- this.term.set(value);
7235
- }
7236
- onlyRequiredChanged(value) {
7237
- this.onlyRequired.set(value);
7238
- }
7239
6662
  methodName({ methodId, model }) {
7240
6663
  return this.methodsById()?.[methodId]?.name || methodIdLabel(methodId, model);
7241
6664
  }
@@ -7251,11 +6674,11 @@ class NodeLogsModelsComponent {
7251
6674
  });
7252
6675
  }
7253
6676
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: NodeLogsModelsComponent, deps: [{ token: HeNodeService }, { token: HeSearchService }, { token: HeEngineService }], target: i0.ɵɵFactoryTarget.Component }); }
7254
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.8", type: NodeLogsModelsComponent, selector: "he-node-logs-models", inputs: { node: "node", nodeKey: "nodeKey", originalValues: "originalValues", recalculatedValues: "recalculatedValues", terms: "terms", filterTermTypes: "filterTermTypes", filterTermTypesLabel: "filterTermTypesLabel", logsKey: "logsKey", noDataMessage: "noDataMessage" }, ngImport: i0, template: "<div\n *ngIf=\"showOutdatedLogs() || engineModelVersion() === currentModelVersion(); else showOutdatedLogsWarning\"\n class=\"is-px-3 is-pb-3\">\n <div class=\"has-text-right is-mb-2\" *ngIf=\"!isExternal && logsUrl()\">\n <a class=\"is-size-7\" [href]=\"logsUrl()\" target=\"_blank\">\n <fa-icon icon=\"external-link-alt\"></fa-icon>\n <span class=\"pl-2\">Open Full Logs</span>\n </a>\n </div>\n\n <he-data-table class=\"mb-1 is-small\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n <tr>\n <th class=\"width-auto has-border-right\">\n <div class=\"field\" *ngIf=\"enableFilterByTerm()\">\n <div class=\"control is-expanded has-icons-right\">\n <input\n class=\"input search-input is-small\"\n [ngModel]=\"term()\"\n name=\"term\"\n placeholder=\"Select entry by name\"\n [ngbTypeahead]=\"suggestTerm\"\n [focusFirst]=\"true\"\n (focus)=\"typeaheadFocus($event)\"\n (selectItem)=\"termChanged($event.item)\" />\n <a class=\"icon is-small is-right\" [class.is-hidden]=\"!term()\" (click)=\"termChanged('')\">\n <fa-icon icon=\"times\"></fa-icon>\n </a>\n </div>\n </div>\n </th>\n <th *ngIf=\"isBlankNodes()\">\n <span class=\"is-pr-1\">Units</span>\n <span>(per&nbsp;</span>\n <span [ngSwitch]=\"functionalUnit()\">\n <ng-container *ngSwitchCase=\"CycleFunctionalUnit['1 ha']\">hectare</ng-container>\n <ng-container *ngSwitchDefault>kg product</ng-container>\n </span>\n <span>)</span>\n </th>\n <th>Original</th>\n <th>Recalculated</th>\n <th *ngIf=\"isBlankNodes()\">Difference</th>\n <th *ngFor=\"let c of methodModelsCount() | times; let i = index\">({{ i + 1 }})</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngIf=\"loading()\">\n <td class=\"has-text-centered\" colspan=\"6\">\n <div class=\"has-text-center py-3\">\n <fa-icon icon=\"spinner\" [pulse]=\"true\" size=\"lg\"></fa-icon>\n </div>\n </td>\n </tr>\n <tr *ngIf=\"!loading() && blankNodes().length === 0\">\n <td class=\"has-text-centered\" colspan=\"6\">\n <span>{{ _noDataMessage() || 'No data' }}</span>\n </td>\n </tr>\n <ng-container *ngFor=\"let blankNode of blankNodes(); trackBy: trackByBlankNode\">\n <tr [class.has-sub-rows]=\"blankNode.canOpen\" [class.is-open]=\"blankNode.isOpen\">\n <td class=\"width-auto has-border-right is-nowrap\" [attr.title]=\"blankNode.term?.name || blankNode.key\">\n <a\n class=\"is-inline-block is-align-top pr-2 open-node\"\n (click)=\"blankNode.isOpen = !blankNode.isOpen\"\n *ngIf=\"blankNode.canOpen\">\n <fa-icon icon=\"angle-down\" [class.is-hidden]=\"!blankNode.isOpen\"></fa-icon>\n <fa-icon icon=\"angle-right\" [class.is-hidden]=\"blankNode.isOpen\"></fa-icon>\n </a>\n <he-node-link class=\"is-inline-block is-pre-wrap\" *ngIf=\"blankNode.term\" [node]=\"blankNode.term\">\n <span [innerHtml]=\"blankNode.term.name | compound\"></span>\n </he-node-link>\n <ng-template #showBlankNodeKey>\n <span>{{ blankNode.key }}</span>\n </ng-template>\n <ng-container *ngIf=\"blankNode.key; else showBlankNodeKey\">\n <a\n *ngIf=\"_nodeKey() === 'completeness'\"\n [href]=\"baseUrl + '/schema/Completeness#' + blankNode.key\"\n target=\"_blank\">\n <span>{{ blankNode.key | keyToLabel }}</span>\n </a>\n </ng-container>\n </td>\n <td *ngIf=\"isBlankNodes()\">\n <span class=\"is-nowrap\" [innerHtml]=\"blankNode.term?.units | compound\"></span>\n </td>\n <td>\n <ng-template #defaultOriginalValue>\n <span>{{ blankNode.originalValue | precision: 3 | default: '-' }}</span>\n </ng-template>\n <ng-container *ngIf=\"blankNode.allParallel; else defaultOriginalValue\">\n <div *ngFor=\"let model of blankNode.configModels[0]\">\n {{ blankNode.originalValueByMethodId[model.methodId] | precision: 3 | default: '-' }}\n </div>\n </ng-container>\n </td>\n <td>\n <ng-container *ngIf=\"!blankNode.isOriginal || blankNode.isRecalculated; else notRecalculated\">\n <ng-template #defaultRecalculatedValue>\n <span>{{ blankNode.recalculatedValue | precision: 3 | default: '-' }}</span>\n </ng-template>\n <ng-container *ngIf=\"blankNode.allParallel; else defaultRecalculatedValue\">\n <div *ngFor=\"let model of blankNode.configModels[0]\">\n {{ blankNode.recalculatedValueByMethodId[model.methodId] | precision: 3 | default: '-' }}\n </div>\n </ng-container>\n </ng-container>\n </td>\n <td *ngIf=\"isBlankNodes()\" class=\"is-nowrap\">\n <ng-template #defaultDeltaValue>\n <he-blank-node-value-delta\n *ngIf=\"blankNode.original.length && blankNode.isRecalculated; else noValue\"\n [value]=\"blankNode.recalculatedValue\"\n [originalValue]=\"blankNode.originalValue\"></he-blank-node-value-delta>\n </ng-template>\n <ng-container *ngIf=\"blankNode.allParallel; else defaultDeltaValue\">\n <div *ngFor=\"let model of blankNode.configModels[0]\">\n <he-blank-node-value-delta\n *ngIf=\"\n blankNode.originalValueByMethodId[model.methodId] !== null &&\n blankNode.recalculatedValueByMethodId[model.methodId] !== null;\n else noValue\n \"\n [value]=\"blankNode.recalculatedValueByMethodId[model.methodId]\"\n [originalValue]=\"blankNode.originalValueByMethodId[model.methodId]\"></he-blank-node-value-delta>\n </div>\n </ng-container>\n </td>\n <ng-container *ngTemplateOutlet=\"blankNodeModels; context: { data: blankNode }\"></ng-container>\n </tr>\n\n <tr\n *ngFor=\"let subValue of blankNode.keys\"\n [class.is-hidden]=\"!blankNode.isOpen\"\n [class.has-sub-rows]=\"blankNode.subValues?.length\"\n [class.is-sub-row]=\"blankNode.canOpen\">\n <td class=\"width-auto has-border-right is-nowrap\">\n <span class=\"is-inline-block is-align-top pl-3 pr-1 field-node\">Field:</span>\n\n <a\n class=\"is-inline-block is-pre-wrap\"\n *ngIf=\"blankNode.type\"\n [href]=\"baseUrl + '/schema/' + blankNode.type + '#' + subValue.key\"\n target=\"_blank\"\n [title]=\"subValue.key\">\n <span>{{ subValue.key }}</span>\n </a>\n <span class=\"is-inline-block is-align-top\" *ngIf=\"!blankNode.type\">{{ subValue.key }}</span>\n </td>\n <td *ngIf=\"isBlankNodes()\"></td>\n <td>\n <span *ngIf=\"subValue.originalValue !== null; else noValue\">\n {{ subValue.originalValue | precision: 3 | default: '-' }}\n </span>\n </td>\n <td>\n <span *ngIf=\"subValue.isRecalculated || subValue.key === 'impactAssessment'; else notRecalculated\">\n {{ subValue.recalculatedValue | precision: 3 | default: '-' }}\n </span>\n </td>\n <td *ngIf=\"isBlankNodes()\">-</td>\n <ng-container *ngTemplateOutlet=\"blankNodeModels; context: { data: subValue }\"></ng-container>\n </tr>\n\n <tr\n *ngFor=\"let subValue of blankNode.subValues\"\n [class.is-hidden]=\"!blankNode.isOpen\"\n [class.is-sub-row]=\"blankNode.canOpen\">\n <td class=\"width-auto has-border-right\">\n <span class=\"is-inline-block is-align-top pl-3\">{{ subValue.key | keyToLabel }}</span>\n\n <ng-container *ngIf=\"subValue.id\">\n <span class=\"is-inline-block\" class=\"is-inline-block is-align-top pr-1\">:</span>\n\n <ng-container [ngSwitch]=\"subValue.key\">\n <span class=\"is-inline-block\" *ngSwitchCase=\"'backgroundData'\">{{ subValue.id | keyToLabel }}</span>\n <he-node-link\n *ngSwitchDefault\n class=\"is-block pl-4\"\n [node]=\"termById(subValue.id)\"\n [attr.title]=\"termById(subValue.id).name\">\n <span [innerHtml]=\"termById(subValue.id).name | compound\"></span>\n </he-node-link>\n </ng-container>\n </ng-container>\n </td>\n <td *ngIf=\"isBlankNodes()\">\n <span class=\"is-nowrap\" *ngIf=\"subValue.showUnits\" [innerHtml]=\"blankNode.term?.units | compound\"></span>\n </td>\n <td>\n <span *ngIf=\"subValue.originalValue !== null; else noValue\">\n {{ subValue.originalValue | precision: 3 | default: '-' }}\n </span>\n </td>\n <td>\n <span *ngIf=\"subValue.isRecalculated; else notRecalculated\">\n {{ subValue.recalculatedValue | precision: 3 | default: '-' }}\n </span>\n </td>\n <td *ngIf=\"isBlankNodes()\">-</td>\n <ng-container *ngTemplateOutlet=\"blankNodeModels; context: { data: subValue }\"></ng-container>\n </tr>\n </ng-container>\n </tbody>\n </table>\n </he-data-table>\n\n <div class=\"is-size-7 is-italic\">\n <div class=\"columns is-variable is-1 my-0\">\n <div class=\"column is-narrow\">\n <p>\n <a class=\"is-inline-block pr-2\" (click)=\"showLegend = !showLegend\">\n <fa-icon icon=\"angle-down\" [class.is-hidden]=\"!showLegend\"></fa-icon>\n <fa-icon icon=\"angle-right\" [class.is-hidden]=\"showLegend\"></fa-icon>\n </a>\n <span class=\"is-inline-block\">Legend:</span>\n </p>\n <ul class=\"content pl-2\" [class.is-hidden]=\"!showLegend\">\n <ng-container *ngFor=\"let status of LogStatus | keys\">\n <li *ngIf=\"logIcon[status.value]\" class=\"has-text-{{ logColor[status.value] }}\">\n <fa-icon [icon]=\"logIcon[status.value]\"></fa-icon>\n <span class=\"pl-1\">{{ status.value }}</span>\n </li>\n </ng-container>\n </ul>\n </div>\n <div class=\"column has-text-right\" *ngIf=\"filteredType()\">\n <label class=\"is-inline-block checkbox\">\n <input\n type=\"checkbox\"\n class=\"selector\"\n [ngModel]=\"onlyRequired\"\n (change)=\"onlyRequiredChanged($event.target.checked)\"\n [disabled]=\"!!term()\" />\n <span class=\"ml-2\">\n Show only {{ filteredType() | pluralize }} included in the default Hestia system boundary\n </span>\n </label>\n </div>\n </div>\n </div>\n</div>\n\n<ng-template #showOutdatedLogsWarning>\n <div class=\"is-3 has-text-centered\">\n <p class=\"is-mb-2\">\n <fa-icon class=\"is-pr-2\" icon=\"exclamation-triangle\"></fa-icon>\n <span>These logs might be incorrect as the calculations are outdated.</span>\n </p>\n <p class=\"is-underlined is-size-7\"><a (click)=\"showOutdatedLogs.set(true)\">View logs anyway.</a></p>\n </div>\n</ng-template>\n\n<ng-template #blankNodeModels let-data=\"data\">\n <ng-template #notInSystemBoundary>\n <td [attr.colspan]=\"methodModelsCount()\">\n <span>Not in Hestia system boundary</span>\n </td>\n </ng-template>\n\n <ng-container *ngIf=\"isSystemBoundary(data); else noValue\">\n <td class=\"blank-node-index-{{ i }}\" *ngFor=\"let c of methodModelsCount() | times; let i = index\">\n <ng-container *ngIf=\"getModelsAt(data, i); let models; else: noValue\">\n <ng-template #modelSerie>\n <ng-container *ngTemplateOutlet=\"blankNodeModel; context: { model: models, data }\"></ng-container>\n </ng-template>\n <div *ngIf=\"models | isArray; else modelSerie\">\n <p *ngFor=\"let model of models\">\n <ng-container *ngTemplateOutlet=\"blankNodeModel; context: { model, data }\"></ng-container>\n </p>\n </div>\n </ng-container>\n </td>\n </ng-container>\n</ng-template>\n\n<ng-template #blankNodeModel let-model=\"model\" let-data=\"data\">\n <span\n class=\"is-nowrap\"\n [class.trigger-popover]=\"model.showLogs\"\n [ngbPopover]=\"logDetails\"\n [autoClose]=\"'outside'\"\n popoverClass=\"is-narrow\"\n triggers=\"manual\"\n #p=\"ngbPopover\"\n placement=\"left\"\n container=\"body\"\n (click)=\"p.isOpen() ? p.close() : model.showLogs ? p.open({ logs: model.logs }) : null\">\n <span class=\"is-capitalized\">{{ methodName(model) }}</span>\n <span class=\"pl-1\" *ngIf=\"model.logs?.methodTier || model.model?.methodTier\">\n [{{ model.logs?.methodTier || model.model?.methodTier }}]\n </span>\n\n <span\n class=\"pl-1 has-text-{{ logColor[model.status] }} trigger-popover\"\n [ngbPopover]=\"logStatusDetails\"\n [autoClose]=\"'outside'\"\n popoverClass=\"is-narrow\"\n triggers=\"manual\"\n #p1=\"ngbPopover\"\n placement=\"left\"\n container=\"body\"\n (click)=\"$event.stopPropagation(); p1.isOpen() ? p1.close() : p1.open({ model, data })\">\n <fa-icon [icon]=\"logIcon[model.status]\"></fa-icon>\n </span>\n\n <span class=\"pl-1\" *ngIf=\"model.model\">\n (\n <ng-container *ngTemplateOutlet=\"docsLink; context: { $implicit: model.model }\"></ng-container>\n )\n </span>\n </span>\n</ng-template>\n\n<ng-template #noValue>-</ng-template>\n\n<ng-template #notRecalculated>not recalculated</ng-template>\n\n<ng-template #logDetails let-logs=\"logs\">\n <div class=\"table-container\" *bindOnce=\"logs\">\n <table class=\"table is-dark is-fullwidth\">\n <tbody>\n <ng-container *ngIf=\"logs?.requirements\">\n <ng-container *ngFor=\"let key of requirementKeys(logs.requirements)\">\n <ng-container *ngTemplateOutlet=\"logLine; context: { key, value: logs.requirements[key] }\"></ng-container>\n </ng-container>\n </ng-container>\n\n <ng-container *ngIf=\"logs?.logs\">\n <ng-container *ngFor=\"let key of logs.logs | keys\">\n <ng-container *ngTemplateOutlet=\"logLine; context: key\"></ng-container>\n </ng-container>\n </ng-container>\n </tbody>\n </table>\n </div>\n\n <ng-container *bindOnce=\"logs\">\n <div class=\"it-mt-2\" *ngIf=\"logs?.missingLookups?.length\">\n <p>Optional data missing:</p>\n\n <div class=\"table-container data-table-container\">\n <table class=\"table is-dark is-fullwidth is-striped\">\n <thead>\n <tr>\n <th class=\"has-text-white\">\n <span>Filename</span>\n </th>\n <th class=\"has-text-white\">\n <span>Column Title</span>\n </th>\n <th class=\"has-text-white\">\n <span>Row (term.id)</span>\n </th>\n </tr>\n </thead>\n <tbody class=\"has-text-white\">\n <tr *ngFor=\"let data of logs.missingLookups\">\n <td>{{ data.filename }}</td>\n <td>{{ data.column }}</td>\n <td>{{ data.termId }}</td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n </ng-container>\n</ng-template>\n\n<ng-template #logLineValue let-key=\"key\" let-value=\"value\">\n <ng-template #defaultValue>\n <span class=\"is-inline-block is-align-middle\">{{ value }}</span>\n </ng-template>\n <ng-container *ngIf=\"requirementLinkedNode(key, value); let linkedNode; else: defaultValue\">\n <he-node-link\n class=\"is-inline-block is-align-middle\"\n linkClass=\"is-dark\"\n [node]=\"linkedNode\"\n [showExternalLink]=\"true\"></he-node-link>\n </ng-container>\n</ng-template>\n\n<ng-template #logLine let-key=\"key\" let-value=\"value\">\n <tr>\n <td class=\"has-border-right copy-log\">\n <span class=\"is-inline-block is-align-middle\">\n <ng-template #defaultMessage>\n <ng-container [ngSwitch]=\"key\">\n <ng-container *ngSwitchDefault>{{ key | keyToLabel }}</ng-container>\n\n <ng-container *ngSwitchCase=\"'property_id'\">Property Term @id</ng-container>\n <ng-container *ngSwitchCase=\"'product_id'\">Product Term @id</ng-container>\n <ng-container *ngSwitchCase=\"'input_id'\">Input Term @id</ng-container>\n\n <ng-container *ngSwitchCase=\"'node_type_allowed'\">\n <span>Is the current</span>\n <code class=\"is-mx-1\">Node</code>\n <span>allowed to run this model</span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'siteType_allowed'\">\n <span>Is the current</span>\n <code class=\"is-mx-1\">siteType</code>\n <span>allowed to run this model</span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'product_id_allowed'\">\n <span>Are any of the Product</span>\n <code class=\"is-mx-1\">@id</code>\n <span>allowed to run this model</span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'product_termType_allowed'\">\n <span>Are any of the Product</span>\n <code class=\"is-mx-1\">termType</code>\n <span>allowed to run this model</span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'input_id_allowed'\">\n <span>Are any of the Input</span>\n <code class=\"is-mx-1\">@id</code>\n <span>allowed to run this model</span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'input_termType_allowed'\">\n <span>Are any of the Input</span>\n <code class=\"is-mx-1\">termType</code>\n <span>allowed to run this model</span>\n </ng-container>\n\n <!-- Deprecated -->\n <ng-container *ngSwitchCase=\"'primary_product_id_allowed'\">\n <span>Is the current primary product</span>\n <code class=\"is-mx-1\">@id</code>\n <span>allowed to run this model</span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'primary_product_termType_allowed'\">\n <span>Is the current primary product</span>\n <code class=\"is-mx-1\">termType</code>\n <span>allowed to run this model</span>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'geospatial_data'\">\n Has geospatial data necessary to run this model\n </ng-container>\n <ng-container *ngSwitchCase=\"'contains_geospatial_data'\">\n Has geospatial data necessary to run this model\n </ng-container>\n <ng-container *ngSwitchCase=\"'current_size'\">Current polygon area</ng-container>\n <ng-container *ngSwitchCase=\"'max_area_size'\">Maximum polygon area to run this model</ng-container>\n <ng-container *ngSwitchCase=\"'below_max_area_size'\">Polygon below the maximum area</ng-container>\n <ng-container *ngSwitchCase=\"'region_factor'\">Factor from region lookup</ng-container>\n\n <ng-container *ngSwitchCase=\"'has_pesticides_inputs'\">\n <span>Cycle contains</span>\n <code class=\"is-mx-1\">pesticideAI</code>\n <span>Inputs</span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'all_pesticideAI_have_lookup_value'\">\n <span>All</span>\n <code class=\"is-mx-1\">pesticideAI</code>\n <span>Inputs have a lookup value</span>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'has_crop_residue_burnt'\">\n <code class=\"is-mr-1\">aboveGroundCropResidueBurnt</code>\n <span>is present as Product</span>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'liquid_slurry_sludge_P'\">Liquid, Slurry, and Sludge P</ng-container>\n </ng-container>\n </ng-template>\n\n <ng-container *ngIf=\"parseLogCompleteness(key); let completeness; else: defaultMessage\">\n <span>Data completeness for</span>\n <code class=\"is-mx-1\">{{ completeness.key }}</code>\n <span>must be</span>\n <code class=\"is-mx-1\">{{ completeness.value }}</code>\n </ng-container>\n </span>\n <he-clipboard\n class=\"is-inline-block is-align-middle\"\n clipboardClass=\"is-size-7 is-p-1\"\n [icon]=\"['far', 'clone']\"\n [value]=\"key\"\n [hideText]=\"true\"></he-clipboard>\n </td>\n <td>\n <ng-template #singleValue>\n <ng-container *ngTemplateOutlet=\"logLineValue; context: { key, value }\"></ng-container>\n </ng-template>\n <div *ngIf=\"logValueArray(value); let valueArray; else: singleValue\">\n <table class=\"table is-dark is-bordered is-striped\">\n <thead *ngIf=\"valueArray[0] | isObject\">\n <tr>\n <th class=\"has-text-white\" *ngFor=\"let v of valueArray[0] | keys\">{{ v.key }}</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let v of valueArray\">\n <ng-template #singleArrayValue>\n <td>{{ v }}</td>\n </ng-template>\n <ng-container *ngIf=\"v | isObject; else singleArrayValue\">\n <td *ngFor=\"let vv of v | keys\">{{ vv.value }}</td>\n </ng-container>\n </tr>\n </tbody>\n </table>\n </div>\n </td>\n </tr>\n</ng-template>\n\n<ng-template #logStatusDetails let-model=\"model\" let-data=\"data\">\n <ng-container *bindOnce=\"model\">\n <div class=\"is-mb-2\">\n <span>Status:</span>\n <span class=\"is-pl-1\">{{ model.status }}</span>\n </div>\n\n <ng-container *ngIf=\"model.status === LogStatus.notRequired && model.logs?.is_not_relevant === 'True'\">\n <ul class=\"is-pl-3 is-list-style-disc\">\n <li *ngIf=\"model.logs.logs?.siteType_allowed === 'False'\">\n The\n <code class=\"is-mx-1\">site.siteType</code>\n is not relevant.\n </li>\n <li *ngIf=\"model.logs.logs?.product_id_allowed === 'False'\">\n None of the\n <code class=\"is-mx-1\">Product</code>\n <code class=\"is-mr-1\">term.@id</code>\n is relevant.\n </li>\n <li *ngIf=\"model.logs.logs?.product_termType_allowed === 'False'\">\n None of the\n <code class=\"is-mx-1\">Product</code>\n <code class=\"is-mr-1\">term.termType</code>\n is relevant.\n </li>\n <li *ngIf=\"model.logs.logs?.input_id_allowed === 'False'\">\n None of the\n <code class=\"is-mx-1\">Input</code>\n <code class=\"is-mr-1\">term.@id</code>\n is relevant.\n </li>\n <li *ngIf=\"model.logs.logs?.input_termType_allowed === 'False'\">\n None of the\n <code class=\"is-mx-1\">Input</code>\n <code class=\"is-mr-1\">term.termType</code>\n is relevant.\n </li>\n </ul>\n </ng-container>\n\n <ng-container\n *ngIf=\"model.logs && model.status !== LogStatus.notRequired && model.status !== LogStatus.skipHierarchy\">\n <ul class=\"is-pl-3 is-list-style-disc\">\n <ng-template #showRunOrchestrator>\n <li class=\"is-run-orchestrator\">\n <p *ngIf=\"model.logs?.shouldRun\">All the requirements were met to run the model.</p>\n <ng-container *ngIf=\"!model.logs?.shouldRun\">\n <p>Some of the requirements were not met to run the model.</p>\n <p>You can click on the model name on the left to view the debugging logs.</p>\n </ng-container>\n <ng-container *ngIf=\"model.logs?.logs?.error\">\n <p>The model failed to run for the following reason:</p>\n <p>\n <code>{{ model.logs.logs.error }}</code>\n </p>\n </ng-container>\n </li>\n </ng-template>\n\n <li\n class=\"is-no-run-orchestrator\"\n *ngIf=\"model.logs?.shouldRunOrchestrator === false; else showRunOrchestrator\">\n <ng-container *ngIf=\"!model.logs.runRequired\">\n <span class=\"is-run-node-type-not-allowed\" *ngIf=\"model.logs.logs?.node_type_allowed === 'False'\">\n This model should not run for {{ nodeType() | pluralize: 0 }}\n </span>\n </ng-container>\n\n <ng-template #runNoConfig>\n <span class=\"is-run-not-empty\" *ngIf=\"model.logs.logs?.is_empty === 'False'\">\n The {{ data.type || 'blank node' }} with Term\n <code class=\"is-mx-1\">{{ data.termId }}</code>\n is already present or already added by another model.\n </span>\n </ng-template>\n\n <ng-container *ngIf=\"model.config; else runNoConfig\">\n <p class=\"is-run-strategy-{{ model.config.runStrategy }}\" [ngSwitch]=\"model.config.runStrategy\">\n <span *ngSwitchCase=\"'always'\"></span>\n <span *ngSwitchCase=\"'add_key_if_missing'\">We only gap-fill this key if not present</span>\n <span *ngSwitchCase=\"'add_blank_node_if_missing'\">We only gap-fill this Blank Node if not present.</span>\n </p>\n\n <p class=\"is-mt-1\">\n <span\n class=\"is-run-with-measured\"\n *ngIf=\"\n model.config.runArgs?.runNonMeasured && hasMethodTier(data.original, EmissionMethodTier.measured)\n \">\n The\n <code class=\"is-mx-1\">{{ model.config.value }}</code>\n was reported as measured.\n </span>\n </p>\n </ng-container>\n </li>\n\n <li *ngIf=\"model.logs?.replaceLowerTier !== undefined\">\n <span>\n The recalculated\n <b>methodTier</b>\n was\n </span>\n <span class=\"is-pl-1 is-underlined\" *ngIf=\"!model.logs.replaceLowerTier\">lower than</span>\n <span class=\"is-pl-1 is-underlined\" *ngIf=\"model.logs.replaceLowerTier\">higher than or equal to</span>\n <span class=\"is-pl-1\">\n the original\n <b>methodTier</b>\n .\n </span>\n </li>\n\n <li class=\"is-merge-replaceLowerTier\" *ngIf=\"model.logs.replaceLowerTier\">\n <span>The recalculated</span>\n <b class=\"is-pl-1\">{{ model.config?.mergeArgs?.replaceThreshold?.[0] || 'value' }}</b>\n <span class=\"is-pl-1\">was</span>\n <span class=\"is-pl-1\">\n <ng-container *ngIf=\"model.config?.mergeArgs\">\n <span class=\"is-underlined\" *ngIf=\"!model.logs.replaceThreshold\">less than</span>\n <span class=\"is-underlined\" *ngIf=\"model.logs.replaceThreshold\">more than or equal to</span>\n <b class=\"is-pl-1\">{{ model.config.mergeArgs.replaceThreshold[1] * 100 }}%</b>\n </ng-container>\n <ng-container *ngIf=\"!model.config?.mergeArgs\">\n <span class=\"is-underlined\" *ngIf=\"!model.logs.replaceThreshold\">not sufficiently</span>\n <span class=\"is-underlined\" *ngIf=\"model.logs.replaceThreshold\">sufficiently</span>\n </ng-container>\n </span>\n <span class=\"is-pl-1\">different from the original</span>\n <b class=\"is-pl-1\">{{ model.config?.mergeArgs?.replaceThreshold?.[0] || 'value' }}.</b>\n </li>\n </ul>\n </ng-container>\n </ng-container>\n</ng-template>\n\n<ng-template #docsLink let-model>\n <a [href]=\"model.apiDocsPath || model.docPath || model.path\" target=\"_blank\" (click)=\"$event.stopPropagation()\">\n <span>Docs</span>\n <fa-icon class=\"ml-1\" icon=\"external-link-alt\" size=\"sm\"></fa-icon>\n </a>\n</ng-template>\n", styles: [":host{display:block}::ng-deep .table{background-color:transparent}::ng-deep .table td he-node-link{width:190px}@media screen and (max-width: 768px){::ng-deep .table td he-node-link{width:150px}}::ng-deep .table td .open-node+he-node-link{width:170px}@media screen and (max-width: 768px){::ng-deep .table td .open-node+he-node-link{width:130px}}::ng-deep .table td.has-border-right{box-shadow:1px 0 #6c8093}::ng-deep .table .has-sub-rows.is-open>td:first-child:before,::ng-deep .table .is-sub-row>td:first-child:before{display:block;position:absolute;content:\" \";background-color:#6c809333;height:100%;width:1px;top:0;left:12px}::ng-deep .table .has-sub-rows.is-open>td:first-child:before{top:25px}::ng-deep .table .popover-body .table-container{max-height:260px;overflow-y:auto}::ng-deep .copy-log he-clipboard{visibility:hidden}::ng-deep .copy-log:hover he-clipboard{visibility:visible}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1$1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1$1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1$1.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "directive", type: i2$1.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: i2$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i4$1.NgbTypeahead, selector: "input[ngbTypeahead]", inputs: ["autocomplete", "container", "editable", "focusFirst", "inputFormatter", "ngbTypeahead", "resultFormatter", "resultTemplate", "selectOnExact", "showHint", "placement", "popperOptions", "popupClass"], outputs: ["selectItem"], exportAs: ["ngbTypeahead"] }, { kind: "directive", type: i4$1.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: i3.FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "spin", "pulse", "mask", "styles", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "classes", "transform", "a11yRole"] }, { kind: "directive", type: BindOnceDirective, selector: "[bindOnce]", inputs: ["bindOnce"] }, { kind: "component", type: BlankNodeValueDeltaComponent, selector: "he-blank-node-value-delta", inputs: ["value", "originalValue", "displayType"] }, { kind: "component", type: ClipboardComponent, selector: "he-clipboard", inputs: ["value", "disabled", "hideText", "icon", "size", "rotate", "clipboardClass"] }, { kind: "component", type: DataTableComponent, selector: "he-data-table", inputs: ["minHeight", "maxHeight", "small"] }, { kind: "component", type: NodeLinkComponent, selector: "he-node-link", inputs: ["node", "showExternalLink", "linkClass"] }, { kind: "pipe", type: CompoundPipe, name: "compound" }, { kind: "pipe", type: DefaultPipe, name: "default" }, { kind: "pipe", type: KeysPipe, name: "keys" }, { kind: "pipe", type: PluralizePipe, name: "pluralize" }, { kind: "pipe", type: KeyToLabelPipe, name: "keyToLabel" }, { kind: "pipe", type: PrecisionPipe, name: "precision" }, { kind: "pipe", type: TimesPipe, name: "times" }, { kind: "pipe", type: IsArrayPipe, name: "isArray" }, { kind: "pipe", type: IsObjectPipe, name: "isObject" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
6677
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.8", type: NodeLogsModelsComponent, selector: "he-node-logs-models", inputs: { node: "node", nodeKey: "nodeKey", originalValues: "originalValues", recalculatedValues: "recalculatedValues", terms: "terms", filterTermTypes: "filterTermTypes", filterTermTypesLabel: "filterTermTypesLabel", logsKey: "logsKey", noDataMessage: "noDataMessage" }, ngImport: i0, template: "<div\n *ngIf=\"showOutdatedLogs() || engineModelVersion() === currentModelVersion(); else showOutdatedLogsWarning\"\n class=\"is-px-3 is-pb-3\">\n <div class=\"has-text-right is-mb-2\" *ngIf=\"!isExternal && logsUrl()\">\n <a class=\"is-size-7\" [href]=\"logsUrl()\" target=\"_blank\">\n <fa-icon icon=\"external-link-alt\"></fa-icon>\n <span class=\"pl-2\">Open Full Logs</span>\n </a>\n </div>\n\n <he-data-table class=\"mb-1 is-small\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n <tr>\n <th class=\"width-auto has-border-right\">\n <div class=\"field\" *ngIf=\"enableFilterByTerm()\">\n <div class=\"control is-expanded has-icons-right\">\n <input\n class=\"input search-input is-small\"\n [ngModel]=\"term()\"\n name=\"term\"\n placeholder=\"Select entry by name\"\n [ngbTypeahead]=\"suggestTerm\"\n [focusFirst]=\"true\"\n (focus)=\"typeaheadFocus($event)\"\n (selectItem)=\"term.set($event.item)\" />\n <a class=\"icon is-small is-right\" [class.is-hidden]=\"!term()\" (click)=\"term.set('')\">\n <fa-icon icon=\"times\"></fa-icon>\n </a>\n </div>\n </div>\n </th>\n <th *ngIf=\"isBlankNodes()\">\n <span class=\"is-pr-1\">Units</span>\n <span>(per&nbsp;</span>\n <span [ngSwitch]=\"functionalUnit()\">\n <ng-container *ngSwitchCase=\"CycleFunctionalUnit['1 ha']\">hectare</ng-container>\n <ng-container *ngSwitchDefault>kg product</ng-container>\n </span>\n <span>)</span>\n </th>\n <th>Original</th>\n <th>Recalculated</th>\n <th *ngIf=\"isBlankNodes()\">Difference</th>\n <th *ngFor=\"let c of methodModelsCount() | times; let i = index\">({{ i + 1 }})</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngIf=\"loading()\">\n <td class=\"has-text-centered\" colspan=\"6\">\n <div class=\"has-text-center py-3\">\n <fa-icon icon=\"spinner\" [pulse]=\"true\" size=\"lg\"></fa-icon>\n </div>\n </td>\n </tr>\n <tr *ngIf=\"!loading() && blankNodes().length === 0\">\n <td class=\"has-text-centered\" colspan=\"6\">\n <span>{{ _noDataMessage() || 'No data' }}</span>\n </td>\n </tr>\n <ng-container *ngFor=\"let blankNode of blankNodes(); trackBy: trackByBlankNode\">\n <tr [class.has-sub-rows]=\"blankNode.canOpen\" [class.is-open]=\"blankNode.isOpen\">\n <td class=\"width-auto has-border-right is-nowrap\" [attr.title]=\"blankNode.term?.name || blankNode.key\">\n <a\n class=\"is-inline-block is-align-top pr-2 open-node\"\n (click)=\"blankNode.isOpen = !blankNode.isOpen\"\n *ngIf=\"blankNode.canOpen\">\n <fa-icon icon=\"angle-down\" [class.is-hidden]=\"!blankNode.isOpen\"></fa-icon>\n <fa-icon icon=\"angle-right\" [class.is-hidden]=\"blankNode.isOpen\"></fa-icon>\n </a>\n <he-node-link class=\"is-inline-block is-pre-wrap\" *ngIf=\"blankNode.term\" [node]=\"blankNode.term\">\n <span [innerHtml]=\"blankNode.term.name | compound\"></span>\n </he-node-link>\n <ng-template #showBlankNodeKey>\n <span>{{ blankNode.key }}</span>\n </ng-template>\n <ng-container *ngIf=\"blankNode.key; else showBlankNodeKey\">\n <a\n *ngIf=\"_nodeKey() === 'completeness'\"\n [href]=\"baseUrl + '/schema/Completeness#' + blankNode.key\"\n target=\"_blank\">\n <span>{{ blankNode.key | keyToLabel }}</span>\n </a>\n </ng-container>\n </td>\n <td *ngIf=\"isBlankNodes()\">\n <span class=\"is-nowrap\" [innerHtml]=\"blankNode.term?.units | compound\"></span>\n </td>\n <td>\n <ng-template #defaultOriginalValue>\n <span>{{ blankNode.originalValue | precision: 3 | default: '-' }}</span>\n </ng-template>\n <ng-container *ngIf=\"blankNode.allParallel; else defaultOriginalValue\">\n <div *ngFor=\"let model of blankNode.configModels[0]\">\n {{ blankNode.originalValueByMethodId[model.methodId] | precision: 3 | default: '-' }}\n </div>\n </ng-container>\n </td>\n <td>\n <ng-container *ngIf=\"!blankNode.isOriginal || blankNode.isRecalculated; else notRecalculated\">\n <ng-template #defaultRecalculatedValue>\n <span>{{ blankNode.recalculatedValue | precision: 3 | default: '-' }}</span>\n </ng-template>\n <ng-container *ngIf=\"blankNode.allParallel; else defaultRecalculatedValue\">\n <div *ngFor=\"let model of blankNode.configModels[0]\">\n {{ blankNode.recalculatedValueByMethodId[model.methodId] | precision: 3 | default: '-' }}\n </div>\n </ng-container>\n </ng-container>\n </td>\n <td *ngIf=\"isBlankNodes()\" class=\"is-nowrap\">\n <ng-template #defaultDeltaValue>\n <he-blank-node-value-delta\n *ngIf=\"blankNode.original.length && blankNode.isRecalculated; else noValue\"\n [value]=\"blankNode.recalculatedValue\"\n [originalValue]=\"blankNode.originalValue\"></he-blank-node-value-delta>\n </ng-template>\n <ng-container *ngIf=\"blankNode.allParallel; else defaultDeltaValue\">\n <div *ngFor=\"let model of blankNode.configModels[0]\">\n <he-blank-node-value-delta\n *ngIf=\"\n blankNode.originalValueByMethodId[model.methodId] !== null &&\n blankNode.recalculatedValueByMethodId[model.methodId] !== null;\n else noValue\n \"\n [value]=\"blankNode.recalculatedValueByMethodId[model.methodId]\"\n [originalValue]=\"blankNode.originalValueByMethodId[model.methodId]\"></he-blank-node-value-delta>\n </div>\n </ng-container>\n </td>\n <ng-container *ngTemplateOutlet=\"blankNodeModels; context: { data: blankNode }\"></ng-container>\n </tr>\n\n <tr\n *ngFor=\"let subValue of blankNode.keys\"\n [class.is-hidden]=\"!blankNode.isOpen\"\n [class.has-sub-rows]=\"blankNode.subValues?.length\"\n [class.is-sub-row]=\"blankNode.canOpen\">\n <td class=\"width-auto has-border-right is-nowrap\">\n <span class=\"is-inline-block is-align-top pl-3 pr-1 field-node\">Field:</span>\n\n <a\n class=\"is-inline-block is-pre-wrap\"\n *ngIf=\"blankNode.type\"\n [href]=\"baseUrl + '/schema/' + blankNode.type + '#' + subValue.key\"\n target=\"_blank\"\n [title]=\"subValue.key\">\n <span>{{ subValue.key }}</span>\n </a>\n <span class=\"is-inline-block is-align-top\" *ngIf=\"!blankNode.type\">{{ subValue.key }}</span>\n </td>\n <td *ngIf=\"isBlankNodes()\"></td>\n <td>\n <span *ngIf=\"subValue.originalValue !== null; else noValue\">\n {{ subValue.originalValue | precision: 3 | default: '-' }}\n </span>\n </td>\n <td>\n <span *ngIf=\"subValue.isRecalculated || subValue.key === 'impactAssessment'; else notRecalculated\">\n {{ subValue.recalculatedValue | precision: 3 | default: '-' }}\n </span>\n </td>\n <td *ngIf=\"isBlankNodes()\">-</td>\n <ng-container *ngTemplateOutlet=\"blankNodeModels; context: { data: subValue }\"></ng-container>\n </tr>\n\n <tr\n *ngFor=\"let subValue of blankNode.subValues\"\n [class.is-hidden]=\"!blankNode.isOpen\"\n [class.is-sub-row]=\"blankNode.canOpen\">\n <td class=\"width-auto has-border-right\">\n <span class=\"is-inline-block is-align-top pl-3\">{{ subValue.key | keyToLabel }}</span>\n\n <ng-container *ngIf=\"subValue.id\">\n <span class=\"is-inline-block\" class=\"is-inline-block is-align-top pr-1\">:</span>\n\n <ng-container [ngSwitch]=\"subValue.key\">\n <span class=\"is-inline-block\" *ngSwitchCase=\"'backgroundData'\">{{ subValue.id | keyToLabel }}</span>\n <he-node-link\n *ngSwitchDefault\n class=\"is-block pl-4\"\n [node]=\"termById(subValue.id)\"\n [attr.title]=\"termById(subValue.id).name\">\n <span [innerHtml]=\"termById(subValue.id).name | compound\"></span>\n </he-node-link>\n </ng-container>\n </ng-container>\n </td>\n <td *ngIf=\"isBlankNodes()\">\n <span class=\"is-nowrap\" *ngIf=\"subValue.showUnits\" [innerHtml]=\"blankNode.term?.units | compound\"></span>\n </td>\n <td>\n <span *ngIf=\"subValue.originalValue !== null; else noValue\">\n {{ subValue.originalValue | precision: 3 | default: '-' }}\n </span>\n </td>\n <td>\n <span *ngIf=\"subValue.isRecalculated; else notRecalculated\">\n {{ subValue.recalculatedValue | precision: 3 | default: '-' }}\n </span>\n </td>\n <td *ngIf=\"isBlankNodes()\">-</td>\n <ng-container *ngTemplateOutlet=\"blankNodeModels; context: { data: subValue }\"></ng-container>\n </tr>\n </ng-container>\n </tbody>\n </table>\n </he-data-table>\n\n <div class=\"is-size-7 is-italic\">\n <div class=\"columns is-variable is-1 my-0\">\n <div class=\"column is-narrow\">\n <p>\n <a class=\"is-inline-block pr-2\" (click)=\"showLegend = !showLegend\">\n <fa-icon icon=\"angle-down\" [class.is-hidden]=\"!showLegend\"></fa-icon>\n <fa-icon icon=\"angle-right\" [class.is-hidden]=\"showLegend\"></fa-icon>\n </a>\n <span class=\"is-inline-block\">Legend:</span>\n </p>\n <ul class=\"content pl-2\" [class.is-hidden]=\"!showLegend\">\n <ng-container *ngFor=\"let status of LogStatus | keys\">\n <li *ngIf=\"logIcon[status.value]\" class=\"has-text-{{ logColor[status.value] }}\">\n <fa-icon [icon]=\"logIcon[status.value]\"></fa-icon>\n <span class=\"pl-1\">{{ status.value }}</span>\n </li>\n </ng-container>\n </ul>\n </div>\n <div class=\"column has-text-right\" *ngIf=\"filteredType()\">\n <label class=\"is-inline-block checkbox\">\n <input\n type=\"checkbox\"\n class=\"selector\"\n [ngModel]=\"onlyRequired\"\n (change)=\"onlyRequired.set($event.target.checked)\"\n [disabled]=\"!!term()\" />\n <span class=\"ml-2\">\n Show only {{ filteredType() | pluralize }} included in the default Hestia system boundary\n </span>\n </label>\n </div>\n </div>\n </div>\n</div>\n\n<ng-template #showOutdatedLogsWarning>\n <div class=\"is-3 has-text-centered\">\n <p class=\"is-mb-2\">\n <fa-icon class=\"is-pr-2\" icon=\"exclamation-triangle\"></fa-icon>\n <span>These logs might be incorrect as the calculations are outdated.</span>\n </p>\n <p class=\"is-underlined is-size-7\"><a (click)=\"showOutdatedLogs.set(true)\">View logs anyway.</a></p>\n </div>\n</ng-template>\n\n<ng-template #blankNodeModels let-data=\"data\">\n <ng-template #notInSystemBoundary>\n <td [attr.colspan]=\"methodModelsCount()\">\n <span>Not in Hestia system boundary</span>\n </td>\n </ng-template>\n\n <ng-container *ngIf=\"isSystemBoundary(data); else noValue\">\n <td class=\"blank-node-index-{{ i }}\" *ngFor=\"let c of methodModelsCount() | times; let i = index\">\n <ng-container *ngIf=\"getModelsAt(data, i); let models; else: noValue\">\n <ng-template #modelSerie>\n <ng-container *ngTemplateOutlet=\"blankNodeModel; context: { model: models, data }\"></ng-container>\n </ng-template>\n <div *ngIf=\"models | isArray; else modelSerie\">\n <p *ngFor=\"let model of models\">\n <ng-container *ngTemplateOutlet=\"blankNodeModel; context: { model, data }\"></ng-container>\n </p>\n </div>\n </ng-container>\n </td>\n </ng-container>\n</ng-template>\n\n<ng-template #blankNodeModel let-model=\"model\" let-data=\"data\">\n <span\n class=\"is-nowrap\"\n [class.trigger-popover]=\"model.showLogs\"\n [ngbPopover]=\"logDetails\"\n [autoClose]=\"'outside'\"\n popoverClass=\"is-narrow\"\n triggers=\"manual\"\n #p=\"ngbPopover\"\n placement=\"left\"\n container=\"body\"\n (click)=\"p.isOpen() ? p.close() : model.showLogs ? p.open({ logs: model.logs }) : null\">\n <span class=\"is-capitalized\">{{ methodName(model) }}</span>\n <span class=\"pl-1\" *ngIf=\"model.logs?.methodTier || model.model?.methodTier\">\n [{{ model.logs?.methodTier || model.model?.methodTier }}]\n </span>\n\n <span\n class=\"pl-1 has-text-{{ logColor[model.status] }} trigger-popover\"\n [ngbPopover]=\"logStatusDetails\"\n [autoClose]=\"'outside'\"\n popoverClass=\"is-narrow\"\n triggers=\"manual\"\n #p1=\"ngbPopover\"\n placement=\"left\"\n container=\"body\"\n (click)=\"$event.stopPropagation(); p1.isOpen() ? p1.close() : p1.open({ model, data })\">\n <fa-icon [icon]=\"logIcon[model.status]\"></fa-icon>\n </span>\n\n <span class=\"pl-1\" *ngIf=\"model.model\">\n (\n <ng-container *ngTemplateOutlet=\"docsLink; context: { $implicit: model.model }\"></ng-container>\n )\n </span>\n </span>\n</ng-template>\n\n<ng-template #noValue>-</ng-template>\n\n<ng-template #notRecalculated>not recalculated</ng-template>\n\n<ng-template #logDetails let-logs=\"logs\">\n <div class=\"table-container\" *bindOnce=\"logs\">\n <table class=\"table is-dark is-fullwidth\">\n <tbody>\n <ng-container *ngIf=\"logs?.requirements\">\n <ng-container *ngFor=\"let key of requirementKeys(logs.requirements)\">\n <ng-container *ngTemplateOutlet=\"logLine; context: { key, value: logs.requirements[key] }\"></ng-container>\n </ng-container>\n </ng-container>\n\n <ng-container *ngIf=\"logs?.logs\">\n <ng-container *ngFor=\"let key of logs.logs | keys\">\n <ng-container *ngTemplateOutlet=\"logLine; context: key\"></ng-container>\n </ng-container>\n </ng-container>\n </tbody>\n </table>\n </div>\n\n <ng-container *bindOnce=\"logs\">\n <div class=\"it-mt-2\" *ngIf=\"logs?.missingLookups?.length\">\n <p>Optional data missing:</p>\n\n <div class=\"table-container data-table-container\">\n <table class=\"table is-dark is-fullwidth is-striped\">\n <thead>\n <tr>\n <th class=\"has-text-white\">\n <span>Filename</span>\n </th>\n <th class=\"has-text-white\">\n <span>Column Title</span>\n </th>\n <th class=\"has-text-white\">\n <span>Row (term.id)</span>\n </th>\n </tr>\n </thead>\n <tbody class=\"has-text-white\">\n <tr *ngFor=\"let data of logs.missingLookups\">\n <td>{{ data.filename }}</td>\n <td>{{ data.column }}</td>\n <td>{{ data.termId }}</td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n </ng-container>\n</ng-template>\n\n<ng-template #logLineValue let-key=\"key\" let-value=\"value\">\n <ng-template #defaultValue>\n <span class=\"is-inline-block is-align-middle\">{{ value }}</span>\n </ng-template>\n <ng-container *ngIf=\"requirementLinkedNode(key, value); let linkedNode; else: defaultValue\">\n <he-node-link\n class=\"is-inline-block is-align-middle\"\n linkClass=\"is-dark\"\n [node]=\"linkedNode\"\n [showExternalLink]=\"true\"></he-node-link>\n </ng-container>\n</ng-template>\n\n<ng-template #logLine let-key=\"key\" let-value=\"value\">\n <tr>\n <td class=\"has-border-right copy-log\">\n <span class=\"is-inline-block is-align-middle\">\n <ng-template #defaultMessage>\n <ng-container [ngSwitch]=\"key\">\n <ng-container *ngSwitchDefault>{{ key | keyToLabel }}</ng-container>\n\n <ng-container *ngSwitchCase=\"'property_id'\">Property Term @id</ng-container>\n <ng-container *ngSwitchCase=\"'product_id'\">Product Term @id</ng-container>\n <ng-container *ngSwitchCase=\"'input_id'\">Input Term @id</ng-container>\n\n <ng-container *ngSwitchCase=\"'node_type_allowed'\">\n <span>Is the current</span>\n <code class=\"is-mx-1\">Node</code>\n <span>allowed to run this model</span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'siteType_allowed'\">\n <span>Is the current</span>\n <code class=\"is-mx-1\">siteType</code>\n <span>allowed to run this model</span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'product_id_allowed'\">\n <span>Are any of the Product</span>\n <code class=\"is-mx-1\">@id</code>\n <span>allowed to run this model</span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'product_termType_allowed'\">\n <span>Are any of the Product</span>\n <code class=\"is-mx-1\">termType</code>\n <span>allowed to run this model</span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'input_id_allowed'\">\n <span>Are any of the Input</span>\n <code class=\"is-mx-1\">@id</code>\n <span>allowed to run this model</span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'input_termType_allowed'\">\n <span>Are any of the Input</span>\n <code class=\"is-mx-1\">termType</code>\n <span>allowed to run this model</span>\n </ng-container>\n\n <!-- Deprecated -->\n <ng-container *ngSwitchCase=\"'primary_product_id_allowed'\">\n <span>Is the current primary product</span>\n <code class=\"is-mx-1\">@id</code>\n <span>allowed to run this model</span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'primary_product_termType_allowed'\">\n <span>Is the current primary product</span>\n <code class=\"is-mx-1\">termType</code>\n <span>allowed to run this model</span>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'geospatial_data'\">\n Has geospatial data necessary to run this model\n </ng-container>\n <ng-container *ngSwitchCase=\"'contains_geospatial_data'\">\n Has geospatial data necessary to run this model\n </ng-container>\n <ng-container *ngSwitchCase=\"'current_size'\">Current polygon area</ng-container>\n <ng-container *ngSwitchCase=\"'max_area_size'\">Maximum polygon area to run this model</ng-container>\n <ng-container *ngSwitchCase=\"'below_max_area_size'\">Polygon below the maximum area</ng-container>\n <ng-container *ngSwitchCase=\"'region_factor'\">Factor from region lookup</ng-container>\n\n <ng-container *ngSwitchCase=\"'has_pesticides_inputs'\">\n <span>Cycle contains</span>\n <code class=\"is-mx-1\">pesticideAI</code>\n <span>Inputs</span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'all_pesticideAI_have_lookup_value'\">\n <span>All</span>\n <code class=\"is-mx-1\">pesticideAI</code>\n <span>Inputs have a lookup value</span>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'has_crop_residue_burnt'\">\n <code class=\"is-mr-1\">aboveGroundCropResidueBurnt</code>\n <span>is present as Product</span>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'liquid_slurry_sludge_P'\">Liquid, Slurry, and Sludge P</ng-container>\n </ng-container>\n </ng-template>\n\n <ng-container *ngIf=\"parseLogCompleteness(key); let completeness; else: defaultMessage\">\n <span>Data completeness for</span>\n <code class=\"is-mx-1\">{{ completeness.key }}</code>\n <span>must be</span>\n <code class=\"is-mx-1\">{{ completeness.value }}</code>\n </ng-container>\n </span>\n <he-clipboard\n class=\"is-inline-block is-align-middle\"\n clipboardClass=\"is-size-7 is-p-1\"\n [icon]=\"['far', 'clone']\"\n [value]=\"key\"\n [hideText]=\"true\"></he-clipboard>\n </td>\n <td>\n <ng-template #singleValue>\n <ng-container *ngTemplateOutlet=\"logLineValue; context: { key, value }\"></ng-container>\n </ng-template>\n <div *ngIf=\"logValueArray(value); let valueArray; else: singleValue\">\n <table class=\"table is-dark is-bordered is-striped\">\n <thead *ngIf=\"valueArray[0] | isObject\">\n <tr>\n <th class=\"has-text-white\" *ngFor=\"let v of valueArray[0] | keys\">{{ v.key }}</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let v of valueArray\">\n <ng-template #singleArrayValue>\n <td>{{ v }}</td>\n </ng-template>\n <ng-container *ngIf=\"v | isObject; else singleArrayValue\">\n <td *ngFor=\"let vv of v | keys\">{{ vv.value }}</td>\n </ng-container>\n </tr>\n </tbody>\n </table>\n </div>\n </td>\n </tr>\n</ng-template>\n\n<ng-template #logStatusDetails let-model=\"model\" let-data=\"data\">\n <ng-container *bindOnce=\"model\">\n <div class=\"is-mb-2\">\n <span>Status:</span>\n <span class=\"is-pl-1\">{{ model.status }}</span>\n </div>\n\n <ng-container *ngIf=\"model.status === LogStatus.notRequired && model.logs?.is_not_relevant === 'True'\">\n <ul class=\"is-pl-3 is-list-style-disc\">\n <li *ngIf=\"model.logs.logs?.siteType_allowed === 'False'\">\n The\n <code class=\"is-mx-1\">site.siteType</code>\n is not relevant.\n </li>\n <li *ngIf=\"model.logs.logs?.product_id_allowed === 'False'\">\n None of the\n <code class=\"is-mx-1\">Product</code>\n <code class=\"is-mr-1\">term.@id</code>\n is relevant.\n </li>\n <li *ngIf=\"model.logs.logs?.product_termType_allowed === 'False'\">\n None of the\n <code class=\"is-mx-1\">Product</code>\n <code class=\"is-mr-1\">term.termType</code>\n is relevant.\n </li>\n <li *ngIf=\"model.logs.logs?.input_id_allowed === 'False'\">\n None of the\n <code class=\"is-mx-1\">Input</code>\n <code class=\"is-mr-1\">term.@id</code>\n is relevant.\n </li>\n <li *ngIf=\"model.logs.logs?.input_termType_allowed === 'False'\">\n None of the\n <code class=\"is-mx-1\">Input</code>\n <code class=\"is-mr-1\">term.termType</code>\n is relevant.\n </li>\n </ul>\n </ng-container>\n\n <ng-container\n *ngIf=\"model.logs && model.status !== LogStatus.notRequired && model.status !== LogStatus.skipHierarchy\">\n <ul class=\"is-pl-3 is-list-style-disc\">\n <ng-template #showRunOrchestrator>\n <li class=\"is-run-orchestrator\">\n <p *ngIf=\"model.logs?.shouldRun\">All the requirements were met to run the model.</p>\n <ng-container *ngIf=\"!model.logs?.shouldRun\">\n <p>Some of the requirements were not met to run the model.</p>\n <p>You can click on the model name on the left to view the debugging logs.</p>\n </ng-container>\n <ng-container *ngIf=\"model.logs?.logs?.error\">\n <p>The model failed to run for the following reason:</p>\n <p>\n <code>{{ model.logs.logs.error }}</code>\n </p>\n </ng-container>\n </li>\n </ng-template>\n\n <li\n class=\"is-no-run-orchestrator\"\n *ngIf=\"model.logs?.shouldRunOrchestrator === false; else showRunOrchestrator\">\n <ng-container *ngIf=\"!model.logs.runRequired\">\n <span class=\"is-run-node-type-not-allowed\" *ngIf=\"model.logs.logs?.node_type_allowed === 'False'\">\n This model should not run for {{ nodeType() | pluralize: 0 }}\n </span>\n </ng-container>\n\n <ng-template #runNoConfig>\n <span class=\"is-run-not-empty\" *ngIf=\"model.logs.logs?.is_empty === 'False'\">\n The {{ data.type || 'blank node' }} with Term\n <code class=\"is-mx-1\">{{ data.termId }}</code>\n is already present or already added by another model.\n </span>\n </ng-template>\n\n <ng-container *ngIf=\"model.config; else runNoConfig\">\n <p class=\"is-run-strategy-{{ model.config.runStrategy }}\" [ngSwitch]=\"model.config.runStrategy\">\n <span *ngSwitchCase=\"'always'\"></span>\n <span *ngSwitchCase=\"'add_key_if_missing'\">We only gap-fill this key if not present</span>\n <span *ngSwitchCase=\"'add_blank_node_if_missing'\">We only gap-fill this Blank Node if not present.</span>\n </p>\n\n <p class=\"is-mt-1\">\n <span\n class=\"is-run-with-measured\"\n *ngIf=\"\n model.config.runArgs?.runNonMeasured && hasMethodTier(data.original, EmissionMethodTier.measured)\n \">\n The\n <code class=\"is-mx-1\">{{ model.config.value }}</code>\n was reported as measured.\n </span>\n </p>\n </ng-container>\n </li>\n\n <li *ngIf=\"model.logs?.replaceLowerTier !== undefined\">\n <span>\n The recalculated\n <b>methodTier</b>\n was\n </span>\n <span class=\"is-pl-1 is-underlined\" *ngIf=\"!model.logs.replaceLowerTier\">lower than</span>\n <span class=\"is-pl-1 is-underlined\" *ngIf=\"model.logs.replaceLowerTier\">higher than or equal to</span>\n <span class=\"is-pl-1\">\n the original\n <b>methodTier</b>\n .\n </span>\n </li>\n\n <li class=\"is-merge-replaceLowerTier\" *ngIf=\"model.logs.replaceLowerTier\">\n <span>The recalculated</span>\n <b class=\"is-pl-1\">{{ model.config?.mergeArgs?.replaceThreshold?.[0] || 'value' }}</b>\n <span class=\"is-pl-1\">was</span>\n <span class=\"is-pl-1\">\n <ng-container *ngIf=\"model.config?.mergeArgs\">\n <span class=\"is-underlined\" *ngIf=\"!model.logs.replaceThreshold\">less than</span>\n <span class=\"is-underlined\" *ngIf=\"model.logs.replaceThreshold\">more than or equal to</span>\n <b class=\"is-pl-1\">{{ model.config.mergeArgs.replaceThreshold[1] * 100 }}%</b>\n </ng-container>\n <ng-container *ngIf=\"!model.config?.mergeArgs\">\n <span class=\"is-underlined\" *ngIf=\"!model.logs.replaceThreshold\">not sufficiently</span>\n <span class=\"is-underlined\" *ngIf=\"model.logs.replaceThreshold\">sufficiently</span>\n </ng-container>\n </span>\n <span class=\"is-pl-1\">different from the original</span>\n <b class=\"is-pl-1\">{{ model.config?.mergeArgs?.replaceThreshold?.[0] || 'value' }}.</b>\n </li>\n </ul>\n </ng-container>\n </ng-container>\n</ng-template>\n\n<ng-template #docsLink let-model>\n <a [href]=\"model.apiDocsPath || model.docPath || model.path\" target=\"_blank\" (click)=\"$event.stopPropagation()\">\n <span>Docs</span>\n <fa-icon class=\"ml-1\" icon=\"external-link-alt\" size=\"sm\"></fa-icon>\n </a>\n</ng-template>\n", styles: [":host{display:block}::ng-deep .table{background-color:transparent}::ng-deep .table td he-node-link{width:190px}@media screen and (max-width: 768px){::ng-deep .table td he-node-link{width:150px}}::ng-deep .table td .open-node+he-node-link{width:170px}@media screen and (max-width: 768px){::ng-deep .table td .open-node+he-node-link{width:130px}}::ng-deep .table td.has-border-right{box-shadow:1px 0 #6c8093}::ng-deep .table .has-sub-rows.is-open>td:first-child:before,::ng-deep .table .is-sub-row>td:first-child:before{display:block;position:absolute;content:\" \";background-color:#6c809333;height:100%;width:1px;top:0;left:12px}::ng-deep .table .has-sub-rows.is-open>td:first-child:before{top:25px}::ng-deep .table .popover-body .table-container{max-height:260px;overflow-y:auto}::ng-deep .copy-log he-clipboard{visibility:hidden}::ng-deep .copy-log:hover he-clipboard{visibility:visible}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1$1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1$1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1$1.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "directive", type: i2$1.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: i2$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i4$1.NgbTypeahead, selector: "input[ngbTypeahead]", inputs: ["autocomplete", "container", "editable", "focusFirst", "inputFormatter", "ngbTypeahead", "resultFormatter", "resultTemplate", "selectOnExact", "showHint", "placement", "popperOptions", "popupClass"], outputs: ["selectItem"], exportAs: ["ngbTypeahead"] }, { kind: "directive", type: i4$1.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: i3.FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "spin", "pulse", "mask", "styles", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "classes", "transform", "a11yRole"] }, { kind: "directive", type: BindOnceDirective, selector: "[bindOnce]", inputs: ["bindOnce"] }, { kind: "component", type: BlankNodeValueDeltaComponent, selector: "he-blank-node-value-delta", inputs: ["value", "originalValue", "displayType"] }, { kind: "component", type: ClipboardComponent, selector: "he-clipboard", inputs: ["value", "disabled", "hideText", "icon", "size", "rotate", "clipboardClass"] }, { kind: "component", type: DataTableComponent, selector: "he-data-table", inputs: ["minHeight", "maxHeight", "small"] }, { kind: "component", type: NodeLinkComponent, selector: "he-node-link", inputs: ["node", "showExternalLink", "linkClass"] }, { kind: "pipe", type: CompoundPipe, name: "compound" }, { kind: "pipe", type: DefaultPipe, name: "default" }, { kind: "pipe", type: KeysPipe, name: "keys" }, { kind: "pipe", type: PluralizePipe, name: "pluralize" }, { kind: "pipe", type: KeyToLabelPipe, name: "keyToLabel" }, { kind: "pipe", type: PrecisionPipe, name: "precision" }, { kind: "pipe", type: TimesPipe, name: "times" }, { kind: "pipe", type: IsArrayPipe, name: "isArray" }, { kind: "pipe", type: IsObjectPipe, name: "isObject" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
7255
6678
  }
7256
6679
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: NodeLogsModelsComponent, decorators: [{
7257
6680
  type: Component$1,
7258
- args: [{ selector: 'he-node-logs-models', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n *ngIf=\"showOutdatedLogs() || engineModelVersion() === currentModelVersion(); else showOutdatedLogsWarning\"\n class=\"is-px-3 is-pb-3\">\n <div class=\"has-text-right is-mb-2\" *ngIf=\"!isExternal && logsUrl()\">\n <a class=\"is-size-7\" [href]=\"logsUrl()\" target=\"_blank\">\n <fa-icon icon=\"external-link-alt\"></fa-icon>\n <span class=\"pl-2\">Open Full Logs</span>\n </a>\n </div>\n\n <he-data-table class=\"mb-1 is-small\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n <tr>\n <th class=\"width-auto has-border-right\">\n <div class=\"field\" *ngIf=\"enableFilterByTerm()\">\n <div class=\"control is-expanded has-icons-right\">\n <input\n class=\"input search-input is-small\"\n [ngModel]=\"term()\"\n name=\"term\"\n placeholder=\"Select entry by name\"\n [ngbTypeahead]=\"suggestTerm\"\n [focusFirst]=\"true\"\n (focus)=\"typeaheadFocus($event)\"\n (selectItem)=\"termChanged($event.item)\" />\n <a class=\"icon is-small is-right\" [class.is-hidden]=\"!term()\" (click)=\"termChanged('')\">\n <fa-icon icon=\"times\"></fa-icon>\n </a>\n </div>\n </div>\n </th>\n <th *ngIf=\"isBlankNodes()\">\n <span class=\"is-pr-1\">Units</span>\n <span>(per&nbsp;</span>\n <span [ngSwitch]=\"functionalUnit()\">\n <ng-container *ngSwitchCase=\"CycleFunctionalUnit['1 ha']\">hectare</ng-container>\n <ng-container *ngSwitchDefault>kg product</ng-container>\n </span>\n <span>)</span>\n </th>\n <th>Original</th>\n <th>Recalculated</th>\n <th *ngIf=\"isBlankNodes()\">Difference</th>\n <th *ngFor=\"let c of methodModelsCount() | times; let i = index\">({{ i + 1 }})</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngIf=\"loading()\">\n <td class=\"has-text-centered\" colspan=\"6\">\n <div class=\"has-text-center py-3\">\n <fa-icon icon=\"spinner\" [pulse]=\"true\" size=\"lg\"></fa-icon>\n </div>\n </td>\n </tr>\n <tr *ngIf=\"!loading() && blankNodes().length === 0\">\n <td class=\"has-text-centered\" colspan=\"6\">\n <span>{{ _noDataMessage() || 'No data' }}</span>\n </td>\n </tr>\n <ng-container *ngFor=\"let blankNode of blankNodes(); trackBy: trackByBlankNode\">\n <tr [class.has-sub-rows]=\"blankNode.canOpen\" [class.is-open]=\"blankNode.isOpen\">\n <td class=\"width-auto has-border-right is-nowrap\" [attr.title]=\"blankNode.term?.name || blankNode.key\">\n <a\n class=\"is-inline-block is-align-top pr-2 open-node\"\n (click)=\"blankNode.isOpen = !blankNode.isOpen\"\n *ngIf=\"blankNode.canOpen\">\n <fa-icon icon=\"angle-down\" [class.is-hidden]=\"!blankNode.isOpen\"></fa-icon>\n <fa-icon icon=\"angle-right\" [class.is-hidden]=\"blankNode.isOpen\"></fa-icon>\n </a>\n <he-node-link class=\"is-inline-block is-pre-wrap\" *ngIf=\"blankNode.term\" [node]=\"blankNode.term\">\n <span [innerHtml]=\"blankNode.term.name | compound\"></span>\n </he-node-link>\n <ng-template #showBlankNodeKey>\n <span>{{ blankNode.key }}</span>\n </ng-template>\n <ng-container *ngIf=\"blankNode.key; else showBlankNodeKey\">\n <a\n *ngIf=\"_nodeKey() === 'completeness'\"\n [href]=\"baseUrl + '/schema/Completeness#' + blankNode.key\"\n target=\"_blank\">\n <span>{{ blankNode.key | keyToLabel }}</span>\n </a>\n </ng-container>\n </td>\n <td *ngIf=\"isBlankNodes()\">\n <span class=\"is-nowrap\" [innerHtml]=\"blankNode.term?.units | compound\"></span>\n </td>\n <td>\n <ng-template #defaultOriginalValue>\n <span>{{ blankNode.originalValue | precision: 3 | default: '-' }}</span>\n </ng-template>\n <ng-container *ngIf=\"blankNode.allParallel; else defaultOriginalValue\">\n <div *ngFor=\"let model of blankNode.configModels[0]\">\n {{ blankNode.originalValueByMethodId[model.methodId] | precision: 3 | default: '-' }}\n </div>\n </ng-container>\n </td>\n <td>\n <ng-container *ngIf=\"!blankNode.isOriginal || blankNode.isRecalculated; else notRecalculated\">\n <ng-template #defaultRecalculatedValue>\n <span>{{ blankNode.recalculatedValue | precision: 3 | default: '-' }}</span>\n </ng-template>\n <ng-container *ngIf=\"blankNode.allParallel; else defaultRecalculatedValue\">\n <div *ngFor=\"let model of blankNode.configModels[0]\">\n {{ blankNode.recalculatedValueByMethodId[model.methodId] | precision: 3 | default: '-' }}\n </div>\n </ng-container>\n </ng-container>\n </td>\n <td *ngIf=\"isBlankNodes()\" class=\"is-nowrap\">\n <ng-template #defaultDeltaValue>\n <he-blank-node-value-delta\n *ngIf=\"blankNode.original.length && blankNode.isRecalculated; else noValue\"\n [value]=\"blankNode.recalculatedValue\"\n [originalValue]=\"blankNode.originalValue\"></he-blank-node-value-delta>\n </ng-template>\n <ng-container *ngIf=\"blankNode.allParallel; else defaultDeltaValue\">\n <div *ngFor=\"let model of blankNode.configModels[0]\">\n <he-blank-node-value-delta\n *ngIf=\"\n blankNode.originalValueByMethodId[model.methodId] !== null &&\n blankNode.recalculatedValueByMethodId[model.methodId] !== null;\n else noValue\n \"\n [value]=\"blankNode.recalculatedValueByMethodId[model.methodId]\"\n [originalValue]=\"blankNode.originalValueByMethodId[model.methodId]\"></he-blank-node-value-delta>\n </div>\n </ng-container>\n </td>\n <ng-container *ngTemplateOutlet=\"blankNodeModels; context: { data: blankNode }\"></ng-container>\n </tr>\n\n <tr\n *ngFor=\"let subValue of blankNode.keys\"\n [class.is-hidden]=\"!blankNode.isOpen\"\n [class.has-sub-rows]=\"blankNode.subValues?.length\"\n [class.is-sub-row]=\"blankNode.canOpen\">\n <td class=\"width-auto has-border-right is-nowrap\">\n <span class=\"is-inline-block is-align-top pl-3 pr-1 field-node\">Field:</span>\n\n <a\n class=\"is-inline-block is-pre-wrap\"\n *ngIf=\"blankNode.type\"\n [href]=\"baseUrl + '/schema/' + blankNode.type + '#' + subValue.key\"\n target=\"_blank\"\n [title]=\"subValue.key\">\n <span>{{ subValue.key }}</span>\n </a>\n <span class=\"is-inline-block is-align-top\" *ngIf=\"!blankNode.type\">{{ subValue.key }}</span>\n </td>\n <td *ngIf=\"isBlankNodes()\"></td>\n <td>\n <span *ngIf=\"subValue.originalValue !== null; else noValue\">\n {{ subValue.originalValue | precision: 3 | default: '-' }}\n </span>\n </td>\n <td>\n <span *ngIf=\"subValue.isRecalculated || subValue.key === 'impactAssessment'; else notRecalculated\">\n {{ subValue.recalculatedValue | precision: 3 | default: '-' }}\n </span>\n </td>\n <td *ngIf=\"isBlankNodes()\">-</td>\n <ng-container *ngTemplateOutlet=\"blankNodeModels; context: { data: subValue }\"></ng-container>\n </tr>\n\n <tr\n *ngFor=\"let subValue of blankNode.subValues\"\n [class.is-hidden]=\"!blankNode.isOpen\"\n [class.is-sub-row]=\"blankNode.canOpen\">\n <td class=\"width-auto has-border-right\">\n <span class=\"is-inline-block is-align-top pl-3\">{{ subValue.key | keyToLabel }}</span>\n\n <ng-container *ngIf=\"subValue.id\">\n <span class=\"is-inline-block\" class=\"is-inline-block is-align-top pr-1\">:</span>\n\n <ng-container [ngSwitch]=\"subValue.key\">\n <span class=\"is-inline-block\" *ngSwitchCase=\"'backgroundData'\">{{ subValue.id | keyToLabel }}</span>\n <he-node-link\n *ngSwitchDefault\n class=\"is-block pl-4\"\n [node]=\"termById(subValue.id)\"\n [attr.title]=\"termById(subValue.id).name\">\n <span [innerHtml]=\"termById(subValue.id).name | compound\"></span>\n </he-node-link>\n </ng-container>\n </ng-container>\n </td>\n <td *ngIf=\"isBlankNodes()\">\n <span class=\"is-nowrap\" *ngIf=\"subValue.showUnits\" [innerHtml]=\"blankNode.term?.units | compound\"></span>\n </td>\n <td>\n <span *ngIf=\"subValue.originalValue !== null; else noValue\">\n {{ subValue.originalValue | precision: 3 | default: '-' }}\n </span>\n </td>\n <td>\n <span *ngIf=\"subValue.isRecalculated; else notRecalculated\">\n {{ subValue.recalculatedValue | precision: 3 | default: '-' }}\n </span>\n </td>\n <td *ngIf=\"isBlankNodes()\">-</td>\n <ng-container *ngTemplateOutlet=\"blankNodeModels; context: { data: subValue }\"></ng-container>\n </tr>\n </ng-container>\n </tbody>\n </table>\n </he-data-table>\n\n <div class=\"is-size-7 is-italic\">\n <div class=\"columns is-variable is-1 my-0\">\n <div class=\"column is-narrow\">\n <p>\n <a class=\"is-inline-block pr-2\" (click)=\"showLegend = !showLegend\">\n <fa-icon icon=\"angle-down\" [class.is-hidden]=\"!showLegend\"></fa-icon>\n <fa-icon icon=\"angle-right\" [class.is-hidden]=\"showLegend\"></fa-icon>\n </a>\n <span class=\"is-inline-block\">Legend:</span>\n </p>\n <ul class=\"content pl-2\" [class.is-hidden]=\"!showLegend\">\n <ng-container *ngFor=\"let status of LogStatus | keys\">\n <li *ngIf=\"logIcon[status.value]\" class=\"has-text-{{ logColor[status.value] }}\">\n <fa-icon [icon]=\"logIcon[status.value]\"></fa-icon>\n <span class=\"pl-1\">{{ status.value }}</span>\n </li>\n </ng-container>\n </ul>\n </div>\n <div class=\"column has-text-right\" *ngIf=\"filteredType()\">\n <label class=\"is-inline-block checkbox\">\n <input\n type=\"checkbox\"\n class=\"selector\"\n [ngModel]=\"onlyRequired\"\n (change)=\"onlyRequiredChanged($event.target.checked)\"\n [disabled]=\"!!term()\" />\n <span class=\"ml-2\">\n Show only {{ filteredType() | pluralize }} included in the default Hestia system boundary\n </span>\n </label>\n </div>\n </div>\n </div>\n</div>\n\n<ng-template #showOutdatedLogsWarning>\n <div class=\"is-3 has-text-centered\">\n <p class=\"is-mb-2\">\n <fa-icon class=\"is-pr-2\" icon=\"exclamation-triangle\"></fa-icon>\n <span>These logs might be incorrect as the calculations are outdated.</span>\n </p>\n <p class=\"is-underlined is-size-7\"><a (click)=\"showOutdatedLogs.set(true)\">View logs anyway.</a></p>\n </div>\n</ng-template>\n\n<ng-template #blankNodeModels let-data=\"data\">\n <ng-template #notInSystemBoundary>\n <td [attr.colspan]=\"methodModelsCount()\">\n <span>Not in Hestia system boundary</span>\n </td>\n </ng-template>\n\n <ng-container *ngIf=\"isSystemBoundary(data); else noValue\">\n <td class=\"blank-node-index-{{ i }}\" *ngFor=\"let c of methodModelsCount() | times; let i = index\">\n <ng-container *ngIf=\"getModelsAt(data, i); let models; else: noValue\">\n <ng-template #modelSerie>\n <ng-container *ngTemplateOutlet=\"blankNodeModel; context: { model: models, data }\"></ng-container>\n </ng-template>\n <div *ngIf=\"models | isArray; else modelSerie\">\n <p *ngFor=\"let model of models\">\n <ng-container *ngTemplateOutlet=\"blankNodeModel; context: { model, data }\"></ng-container>\n </p>\n </div>\n </ng-container>\n </td>\n </ng-container>\n</ng-template>\n\n<ng-template #blankNodeModel let-model=\"model\" let-data=\"data\">\n <span\n class=\"is-nowrap\"\n [class.trigger-popover]=\"model.showLogs\"\n [ngbPopover]=\"logDetails\"\n [autoClose]=\"'outside'\"\n popoverClass=\"is-narrow\"\n triggers=\"manual\"\n #p=\"ngbPopover\"\n placement=\"left\"\n container=\"body\"\n (click)=\"p.isOpen() ? p.close() : model.showLogs ? p.open({ logs: model.logs }) : null\">\n <span class=\"is-capitalized\">{{ methodName(model) }}</span>\n <span class=\"pl-1\" *ngIf=\"model.logs?.methodTier || model.model?.methodTier\">\n [{{ model.logs?.methodTier || model.model?.methodTier }}]\n </span>\n\n <span\n class=\"pl-1 has-text-{{ logColor[model.status] }} trigger-popover\"\n [ngbPopover]=\"logStatusDetails\"\n [autoClose]=\"'outside'\"\n popoverClass=\"is-narrow\"\n triggers=\"manual\"\n #p1=\"ngbPopover\"\n placement=\"left\"\n container=\"body\"\n (click)=\"$event.stopPropagation(); p1.isOpen() ? p1.close() : p1.open({ model, data })\">\n <fa-icon [icon]=\"logIcon[model.status]\"></fa-icon>\n </span>\n\n <span class=\"pl-1\" *ngIf=\"model.model\">\n (\n <ng-container *ngTemplateOutlet=\"docsLink; context: { $implicit: model.model }\"></ng-container>\n )\n </span>\n </span>\n</ng-template>\n\n<ng-template #noValue>-</ng-template>\n\n<ng-template #notRecalculated>not recalculated</ng-template>\n\n<ng-template #logDetails let-logs=\"logs\">\n <div class=\"table-container\" *bindOnce=\"logs\">\n <table class=\"table is-dark is-fullwidth\">\n <tbody>\n <ng-container *ngIf=\"logs?.requirements\">\n <ng-container *ngFor=\"let key of requirementKeys(logs.requirements)\">\n <ng-container *ngTemplateOutlet=\"logLine; context: { key, value: logs.requirements[key] }\"></ng-container>\n </ng-container>\n </ng-container>\n\n <ng-container *ngIf=\"logs?.logs\">\n <ng-container *ngFor=\"let key of logs.logs | keys\">\n <ng-container *ngTemplateOutlet=\"logLine; context: key\"></ng-container>\n </ng-container>\n </ng-container>\n </tbody>\n </table>\n </div>\n\n <ng-container *bindOnce=\"logs\">\n <div class=\"it-mt-2\" *ngIf=\"logs?.missingLookups?.length\">\n <p>Optional data missing:</p>\n\n <div class=\"table-container data-table-container\">\n <table class=\"table is-dark is-fullwidth is-striped\">\n <thead>\n <tr>\n <th class=\"has-text-white\">\n <span>Filename</span>\n </th>\n <th class=\"has-text-white\">\n <span>Column Title</span>\n </th>\n <th class=\"has-text-white\">\n <span>Row (term.id)</span>\n </th>\n </tr>\n </thead>\n <tbody class=\"has-text-white\">\n <tr *ngFor=\"let data of logs.missingLookups\">\n <td>{{ data.filename }}</td>\n <td>{{ data.column }}</td>\n <td>{{ data.termId }}</td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n </ng-container>\n</ng-template>\n\n<ng-template #logLineValue let-key=\"key\" let-value=\"value\">\n <ng-template #defaultValue>\n <span class=\"is-inline-block is-align-middle\">{{ value }}</span>\n </ng-template>\n <ng-container *ngIf=\"requirementLinkedNode(key, value); let linkedNode; else: defaultValue\">\n <he-node-link\n class=\"is-inline-block is-align-middle\"\n linkClass=\"is-dark\"\n [node]=\"linkedNode\"\n [showExternalLink]=\"true\"></he-node-link>\n </ng-container>\n</ng-template>\n\n<ng-template #logLine let-key=\"key\" let-value=\"value\">\n <tr>\n <td class=\"has-border-right copy-log\">\n <span class=\"is-inline-block is-align-middle\">\n <ng-template #defaultMessage>\n <ng-container [ngSwitch]=\"key\">\n <ng-container *ngSwitchDefault>{{ key | keyToLabel }}</ng-container>\n\n <ng-container *ngSwitchCase=\"'property_id'\">Property Term @id</ng-container>\n <ng-container *ngSwitchCase=\"'product_id'\">Product Term @id</ng-container>\n <ng-container *ngSwitchCase=\"'input_id'\">Input Term @id</ng-container>\n\n <ng-container *ngSwitchCase=\"'node_type_allowed'\">\n <span>Is the current</span>\n <code class=\"is-mx-1\">Node</code>\n <span>allowed to run this model</span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'siteType_allowed'\">\n <span>Is the current</span>\n <code class=\"is-mx-1\">siteType</code>\n <span>allowed to run this model</span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'product_id_allowed'\">\n <span>Are any of the Product</span>\n <code class=\"is-mx-1\">@id</code>\n <span>allowed to run this model</span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'product_termType_allowed'\">\n <span>Are any of the Product</span>\n <code class=\"is-mx-1\">termType</code>\n <span>allowed to run this model</span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'input_id_allowed'\">\n <span>Are any of the Input</span>\n <code class=\"is-mx-1\">@id</code>\n <span>allowed to run this model</span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'input_termType_allowed'\">\n <span>Are any of the Input</span>\n <code class=\"is-mx-1\">termType</code>\n <span>allowed to run this model</span>\n </ng-container>\n\n <!-- Deprecated -->\n <ng-container *ngSwitchCase=\"'primary_product_id_allowed'\">\n <span>Is the current primary product</span>\n <code class=\"is-mx-1\">@id</code>\n <span>allowed to run this model</span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'primary_product_termType_allowed'\">\n <span>Is the current primary product</span>\n <code class=\"is-mx-1\">termType</code>\n <span>allowed to run this model</span>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'geospatial_data'\">\n Has geospatial data necessary to run this model\n </ng-container>\n <ng-container *ngSwitchCase=\"'contains_geospatial_data'\">\n Has geospatial data necessary to run this model\n </ng-container>\n <ng-container *ngSwitchCase=\"'current_size'\">Current polygon area</ng-container>\n <ng-container *ngSwitchCase=\"'max_area_size'\">Maximum polygon area to run this model</ng-container>\n <ng-container *ngSwitchCase=\"'below_max_area_size'\">Polygon below the maximum area</ng-container>\n <ng-container *ngSwitchCase=\"'region_factor'\">Factor from region lookup</ng-container>\n\n <ng-container *ngSwitchCase=\"'has_pesticides_inputs'\">\n <span>Cycle contains</span>\n <code class=\"is-mx-1\">pesticideAI</code>\n <span>Inputs</span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'all_pesticideAI_have_lookup_value'\">\n <span>All</span>\n <code class=\"is-mx-1\">pesticideAI</code>\n <span>Inputs have a lookup value</span>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'has_crop_residue_burnt'\">\n <code class=\"is-mr-1\">aboveGroundCropResidueBurnt</code>\n <span>is present as Product</span>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'liquid_slurry_sludge_P'\">Liquid, Slurry, and Sludge P</ng-container>\n </ng-container>\n </ng-template>\n\n <ng-container *ngIf=\"parseLogCompleteness(key); let completeness; else: defaultMessage\">\n <span>Data completeness for</span>\n <code class=\"is-mx-1\">{{ completeness.key }}</code>\n <span>must be</span>\n <code class=\"is-mx-1\">{{ completeness.value }}</code>\n </ng-container>\n </span>\n <he-clipboard\n class=\"is-inline-block is-align-middle\"\n clipboardClass=\"is-size-7 is-p-1\"\n [icon]=\"['far', 'clone']\"\n [value]=\"key\"\n [hideText]=\"true\"></he-clipboard>\n </td>\n <td>\n <ng-template #singleValue>\n <ng-container *ngTemplateOutlet=\"logLineValue; context: { key, value }\"></ng-container>\n </ng-template>\n <div *ngIf=\"logValueArray(value); let valueArray; else: singleValue\">\n <table class=\"table is-dark is-bordered is-striped\">\n <thead *ngIf=\"valueArray[0] | isObject\">\n <tr>\n <th class=\"has-text-white\" *ngFor=\"let v of valueArray[0] | keys\">{{ v.key }}</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let v of valueArray\">\n <ng-template #singleArrayValue>\n <td>{{ v }}</td>\n </ng-template>\n <ng-container *ngIf=\"v | isObject; else singleArrayValue\">\n <td *ngFor=\"let vv of v | keys\">{{ vv.value }}</td>\n </ng-container>\n </tr>\n </tbody>\n </table>\n </div>\n </td>\n </tr>\n</ng-template>\n\n<ng-template #logStatusDetails let-model=\"model\" let-data=\"data\">\n <ng-container *bindOnce=\"model\">\n <div class=\"is-mb-2\">\n <span>Status:</span>\n <span class=\"is-pl-1\">{{ model.status }}</span>\n </div>\n\n <ng-container *ngIf=\"model.status === LogStatus.notRequired && model.logs?.is_not_relevant === 'True'\">\n <ul class=\"is-pl-3 is-list-style-disc\">\n <li *ngIf=\"model.logs.logs?.siteType_allowed === 'False'\">\n The\n <code class=\"is-mx-1\">site.siteType</code>\n is not relevant.\n </li>\n <li *ngIf=\"model.logs.logs?.product_id_allowed === 'False'\">\n None of the\n <code class=\"is-mx-1\">Product</code>\n <code class=\"is-mr-1\">term.@id</code>\n is relevant.\n </li>\n <li *ngIf=\"model.logs.logs?.product_termType_allowed === 'False'\">\n None of the\n <code class=\"is-mx-1\">Product</code>\n <code class=\"is-mr-1\">term.termType</code>\n is relevant.\n </li>\n <li *ngIf=\"model.logs.logs?.input_id_allowed === 'False'\">\n None of the\n <code class=\"is-mx-1\">Input</code>\n <code class=\"is-mr-1\">term.@id</code>\n is relevant.\n </li>\n <li *ngIf=\"model.logs.logs?.input_termType_allowed === 'False'\">\n None of the\n <code class=\"is-mx-1\">Input</code>\n <code class=\"is-mr-1\">term.termType</code>\n is relevant.\n </li>\n </ul>\n </ng-container>\n\n <ng-container\n *ngIf=\"model.logs && model.status !== LogStatus.notRequired && model.status !== LogStatus.skipHierarchy\">\n <ul class=\"is-pl-3 is-list-style-disc\">\n <ng-template #showRunOrchestrator>\n <li class=\"is-run-orchestrator\">\n <p *ngIf=\"model.logs?.shouldRun\">All the requirements were met to run the model.</p>\n <ng-container *ngIf=\"!model.logs?.shouldRun\">\n <p>Some of the requirements were not met to run the model.</p>\n <p>You can click on the model name on the left to view the debugging logs.</p>\n </ng-container>\n <ng-container *ngIf=\"model.logs?.logs?.error\">\n <p>The model failed to run for the following reason:</p>\n <p>\n <code>{{ model.logs.logs.error }}</code>\n </p>\n </ng-container>\n </li>\n </ng-template>\n\n <li\n class=\"is-no-run-orchestrator\"\n *ngIf=\"model.logs?.shouldRunOrchestrator === false; else showRunOrchestrator\">\n <ng-container *ngIf=\"!model.logs.runRequired\">\n <span class=\"is-run-node-type-not-allowed\" *ngIf=\"model.logs.logs?.node_type_allowed === 'False'\">\n This model should not run for {{ nodeType() | pluralize: 0 }}\n </span>\n </ng-container>\n\n <ng-template #runNoConfig>\n <span class=\"is-run-not-empty\" *ngIf=\"model.logs.logs?.is_empty === 'False'\">\n The {{ data.type || 'blank node' }} with Term\n <code class=\"is-mx-1\">{{ data.termId }}</code>\n is already present or already added by another model.\n </span>\n </ng-template>\n\n <ng-container *ngIf=\"model.config; else runNoConfig\">\n <p class=\"is-run-strategy-{{ model.config.runStrategy }}\" [ngSwitch]=\"model.config.runStrategy\">\n <span *ngSwitchCase=\"'always'\"></span>\n <span *ngSwitchCase=\"'add_key_if_missing'\">We only gap-fill this key if not present</span>\n <span *ngSwitchCase=\"'add_blank_node_if_missing'\">We only gap-fill this Blank Node if not present.</span>\n </p>\n\n <p class=\"is-mt-1\">\n <span\n class=\"is-run-with-measured\"\n *ngIf=\"\n model.config.runArgs?.runNonMeasured && hasMethodTier(data.original, EmissionMethodTier.measured)\n \">\n The\n <code class=\"is-mx-1\">{{ model.config.value }}</code>\n was reported as measured.\n </span>\n </p>\n </ng-container>\n </li>\n\n <li *ngIf=\"model.logs?.replaceLowerTier !== undefined\">\n <span>\n The recalculated\n <b>methodTier</b>\n was\n </span>\n <span class=\"is-pl-1 is-underlined\" *ngIf=\"!model.logs.replaceLowerTier\">lower than</span>\n <span class=\"is-pl-1 is-underlined\" *ngIf=\"model.logs.replaceLowerTier\">higher than or equal to</span>\n <span class=\"is-pl-1\">\n the original\n <b>methodTier</b>\n .\n </span>\n </li>\n\n <li class=\"is-merge-replaceLowerTier\" *ngIf=\"model.logs.replaceLowerTier\">\n <span>The recalculated</span>\n <b class=\"is-pl-1\">{{ model.config?.mergeArgs?.replaceThreshold?.[0] || 'value' }}</b>\n <span class=\"is-pl-1\">was</span>\n <span class=\"is-pl-1\">\n <ng-container *ngIf=\"model.config?.mergeArgs\">\n <span class=\"is-underlined\" *ngIf=\"!model.logs.replaceThreshold\">less than</span>\n <span class=\"is-underlined\" *ngIf=\"model.logs.replaceThreshold\">more than or equal to</span>\n <b class=\"is-pl-1\">{{ model.config.mergeArgs.replaceThreshold[1] * 100 }}%</b>\n </ng-container>\n <ng-container *ngIf=\"!model.config?.mergeArgs\">\n <span class=\"is-underlined\" *ngIf=\"!model.logs.replaceThreshold\">not sufficiently</span>\n <span class=\"is-underlined\" *ngIf=\"model.logs.replaceThreshold\">sufficiently</span>\n </ng-container>\n </span>\n <span class=\"is-pl-1\">different from the original</span>\n <b class=\"is-pl-1\">{{ model.config?.mergeArgs?.replaceThreshold?.[0] || 'value' }}.</b>\n </li>\n </ul>\n </ng-container>\n </ng-container>\n</ng-template>\n\n<ng-template #docsLink let-model>\n <a [href]=\"model.apiDocsPath || model.docPath || model.path\" target=\"_blank\" (click)=\"$event.stopPropagation()\">\n <span>Docs</span>\n <fa-icon class=\"ml-1\" icon=\"external-link-alt\" size=\"sm\"></fa-icon>\n </a>\n</ng-template>\n", styles: [":host{display:block}::ng-deep .table{background-color:transparent}::ng-deep .table td he-node-link{width:190px}@media screen and (max-width: 768px){::ng-deep .table td he-node-link{width:150px}}::ng-deep .table td .open-node+he-node-link{width:170px}@media screen and (max-width: 768px){::ng-deep .table td .open-node+he-node-link{width:130px}}::ng-deep .table td.has-border-right{box-shadow:1px 0 #6c8093}::ng-deep .table .has-sub-rows.is-open>td:first-child:before,::ng-deep .table .is-sub-row>td:first-child:before{display:block;position:absolute;content:\" \";background-color:#6c809333;height:100%;width:1px;top:0;left:12px}::ng-deep .table .has-sub-rows.is-open>td:first-child:before{top:25px}::ng-deep .table .popover-body .table-container{max-height:260px;overflow-y:auto}::ng-deep .copy-log he-clipboard{visibility:hidden}::ng-deep .copy-log:hover he-clipboard{visibility:visible}\n"] }]
6681
+ args: [{ selector: 'he-node-logs-models', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n *ngIf=\"showOutdatedLogs() || engineModelVersion() === currentModelVersion(); else showOutdatedLogsWarning\"\n class=\"is-px-3 is-pb-3\">\n <div class=\"has-text-right is-mb-2\" *ngIf=\"!isExternal && logsUrl()\">\n <a class=\"is-size-7\" [href]=\"logsUrl()\" target=\"_blank\">\n <fa-icon icon=\"external-link-alt\"></fa-icon>\n <span class=\"pl-2\">Open Full Logs</span>\n </a>\n </div>\n\n <he-data-table class=\"mb-1 is-small\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n <tr>\n <th class=\"width-auto has-border-right\">\n <div class=\"field\" *ngIf=\"enableFilterByTerm()\">\n <div class=\"control is-expanded has-icons-right\">\n <input\n class=\"input search-input is-small\"\n [ngModel]=\"term()\"\n name=\"term\"\n placeholder=\"Select entry by name\"\n [ngbTypeahead]=\"suggestTerm\"\n [focusFirst]=\"true\"\n (focus)=\"typeaheadFocus($event)\"\n (selectItem)=\"term.set($event.item)\" />\n <a class=\"icon is-small is-right\" [class.is-hidden]=\"!term()\" (click)=\"term.set('')\">\n <fa-icon icon=\"times\"></fa-icon>\n </a>\n </div>\n </div>\n </th>\n <th *ngIf=\"isBlankNodes()\">\n <span class=\"is-pr-1\">Units</span>\n <span>(per&nbsp;</span>\n <span [ngSwitch]=\"functionalUnit()\">\n <ng-container *ngSwitchCase=\"CycleFunctionalUnit['1 ha']\">hectare</ng-container>\n <ng-container *ngSwitchDefault>kg product</ng-container>\n </span>\n <span>)</span>\n </th>\n <th>Original</th>\n <th>Recalculated</th>\n <th *ngIf=\"isBlankNodes()\">Difference</th>\n <th *ngFor=\"let c of methodModelsCount() | times; let i = index\">({{ i + 1 }})</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngIf=\"loading()\">\n <td class=\"has-text-centered\" colspan=\"6\">\n <div class=\"has-text-center py-3\">\n <fa-icon icon=\"spinner\" [pulse]=\"true\" size=\"lg\"></fa-icon>\n </div>\n </td>\n </tr>\n <tr *ngIf=\"!loading() && blankNodes().length === 0\">\n <td class=\"has-text-centered\" colspan=\"6\">\n <span>{{ _noDataMessage() || 'No data' }}</span>\n </td>\n </tr>\n <ng-container *ngFor=\"let blankNode of blankNodes(); trackBy: trackByBlankNode\">\n <tr [class.has-sub-rows]=\"blankNode.canOpen\" [class.is-open]=\"blankNode.isOpen\">\n <td class=\"width-auto has-border-right is-nowrap\" [attr.title]=\"blankNode.term?.name || blankNode.key\">\n <a\n class=\"is-inline-block is-align-top pr-2 open-node\"\n (click)=\"blankNode.isOpen = !blankNode.isOpen\"\n *ngIf=\"blankNode.canOpen\">\n <fa-icon icon=\"angle-down\" [class.is-hidden]=\"!blankNode.isOpen\"></fa-icon>\n <fa-icon icon=\"angle-right\" [class.is-hidden]=\"blankNode.isOpen\"></fa-icon>\n </a>\n <he-node-link class=\"is-inline-block is-pre-wrap\" *ngIf=\"blankNode.term\" [node]=\"blankNode.term\">\n <span [innerHtml]=\"blankNode.term.name | compound\"></span>\n </he-node-link>\n <ng-template #showBlankNodeKey>\n <span>{{ blankNode.key }}</span>\n </ng-template>\n <ng-container *ngIf=\"blankNode.key; else showBlankNodeKey\">\n <a\n *ngIf=\"_nodeKey() === 'completeness'\"\n [href]=\"baseUrl + '/schema/Completeness#' + blankNode.key\"\n target=\"_blank\">\n <span>{{ blankNode.key | keyToLabel }}</span>\n </a>\n </ng-container>\n </td>\n <td *ngIf=\"isBlankNodes()\">\n <span class=\"is-nowrap\" [innerHtml]=\"blankNode.term?.units | compound\"></span>\n </td>\n <td>\n <ng-template #defaultOriginalValue>\n <span>{{ blankNode.originalValue | precision: 3 | default: '-' }}</span>\n </ng-template>\n <ng-container *ngIf=\"blankNode.allParallel; else defaultOriginalValue\">\n <div *ngFor=\"let model of blankNode.configModels[0]\">\n {{ blankNode.originalValueByMethodId[model.methodId] | precision: 3 | default: '-' }}\n </div>\n </ng-container>\n </td>\n <td>\n <ng-container *ngIf=\"!blankNode.isOriginal || blankNode.isRecalculated; else notRecalculated\">\n <ng-template #defaultRecalculatedValue>\n <span>{{ blankNode.recalculatedValue | precision: 3 | default: '-' }}</span>\n </ng-template>\n <ng-container *ngIf=\"blankNode.allParallel; else defaultRecalculatedValue\">\n <div *ngFor=\"let model of blankNode.configModels[0]\">\n {{ blankNode.recalculatedValueByMethodId[model.methodId] | precision: 3 | default: '-' }}\n </div>\n </ng-container>\n </ng-container>\n </td>\n <td *ngIf=\"isBlankNodes()\" class=\"is-nowrap\">\n <ng-template #defaultDeltaValue>\n <he-blank-node-value-delta\n *ngIf=\"blankNode.original.length && blankNode.isRecalculated; else noValue\"\n [value]=\"blankNode.recalculatedValue\"\n [originalValue]=\"blankNode.originalValue\"></he-blank-node-value-delta>\n </ng-template>\n <ng-container *ngIf=\"blankNode.allParallel; else defaultDeltaValue\">\n <div *ngFor=\"let model of blankNode.configModels[0]\">\n <he-blank-node-value-delta\n *ngIf=\"\n blankNode.originalValueByMethodId[model.methodId] !== null &&\n blankNode.recalculatedValueByMethodId[model.methodId] !== null;\n else noValue\n \"\n [value]=\"blankNode.recalculatedValueByMethodId[model.methodId]\"\n [originalValue]=\"blankNode.originalValueByMethodId[model.methodId]\"></he-blank-node-value-delta>\n </div>\n </ng-container>\n </td>\n <ng-container *ngTemplateOutlet=\"blankNodeModels; context: { data: blankNode }\"></ng-container>\n </tr>\n\n <tr\n *ngFor=\"let subValue of blankNode.keys\"\n [class.is-hidden]=\"!blankNode.isOpen\"\n [class.has-sub-rows]=\"blankNode.subValues?.length\"\n [class.is-sub-row]=\"blankNode.canOpen\">\n <td class=\"width-auto has-border-right is-nowrap\">\n <span class=\"is-inline-block is-align-top pl-3 pr-1 field-node\">Field:</span>\n\n <a\n class=\"is-inline-block is-pre-wrap\"\n *ngIf=\"blankNode.type\"\n [href]=\"baseUrl + '/schema/' + blankNode.type + '#' + subValue.key\"\n target=\"_blank\"\n [title]=\"subValue.key\">\n <span>{{ subValue.key }}</span>\n </a>\n <span class=\"is-inline-block is-align-top\" *ngIf=\"!blankNode.type\">{{ subValue.key }}</span>\n </td>\n <td *ngIf=\"isBlankNodes()\"></td>\n <td>\n <span *ngIf=\"subValue.originalValue !== null; else noValue\">\n {{ subValue.originalValue | precision: 3 | default: '-' }}\n </span>\n </td>\n <td>\n <span *ngIf=\"subValue.isRecalculated || subValue.key === 'impactAssessment'; else notRecalculated\">\n {{ subValue.recalculatedValue | precision: 3 | default: '-' }}\n </span>\n </td>\n <td *ngIf=\"isBlankNodes()\">-</td>\n <ng-container *ngTemplateOutlet=\"blankNodeModels; context: { data: subValue }\"></ng-container>\n </tr>\n\n <tr\n *ngFor=\"let subValue of blankNode.subValues\"\n [class.is-hidden]=\"!blankNode.isOpen\"\n [class.is-sub-row]=\"blankNode.canOpen\">\n <td class=\"width-auto has-border-right\">\n <span class=\"is-inline-block is-align-top pl-3\">{{ subValue.key | keyToLabel }}</span>\n\n <ng-container *ngIf=\"subValue.id\">\n <span class=\"is-inline-block\" class=\"is-inline-block is-align-top pr-1\">:</span>\n\n <ng-container [ngSwitch]=\"subValue.key\">\n <span class=\"is-inline-block\" *ngSwitchCase=\"'backgroundData'\">{{ subValue.id | keyToLabel }}</span>\n <he-node-link\n *ngSwitchDefault\n class=\"is-block pl-4\"\n [node]=\"termById(subValue.id)\"\n [attr.title]=\"termById(subValue.id).name\">\n <span [innerHtml]=\"termById(subValue.id).name | compound\"></span>\n </he-node-link>\n </ng-container>\n </ng-container>\n </td>\n <td *ngIf=\"isBlankNodes()\">\n <span class=\"is-nowrap\" *ngIf=\"subValue.showUnits\" [innerHtml]=\"blankNode.term?.units | compound\"></span>\n </td>\n <td>\n <span *ngIf=\"subValue.originalValue !== null; else noValue\">\n {{ subValue.originalValue | precision: 3 | default: '-' }}\n </span>\n </td>\n <td>\n <span *ngIf=\"subValue.isRecalculated; else notRecalculated\">\n {{ subValue.recalculatedValue | precision: 3 | default: '-' }}\n </span>\n </td>\n <td *ngIf=\"isBlankNodes()\">-</td>\n <ng-container *ngTemplateOutlet=\"blankNodeModels; context: { data: subValue }\"></ng-container>\n </tr>\n </ng-container>\n </tbody>\n </table>\n </he-data-table>\n\n <div class=\"is-size-7 is-italic\">\n <div class=\"columns is-variable is-1 my-0\">\n <div class=\"column is-narrow\">\n <p>\n <a class=\"is-inline-block pr-2\" (click)=\"showLegend = !showLegend\">\n <fa-icon icon=\"angle-down\" [class.is-hidden]=\"!showLegend\"></fa-icon>\n <fa-icon icon=\"angle-right\" [class.is-hidden]=\"showLegend\"></fa-icon>\n </a>\n <span class=\"is-inline-block\">Legend:</span>\n </p>\n <ul class=\"content pl-2\" [class.is-hidden]=\"!showLegend\">\n <ng-container *ngFor=\"let status of LogStatus | keys\">\n <li *ngIf=\"logIcon[status.value]\" class=\"has-text-{{ logColor[status.value] }}\">\n <fa-icon [icon]=\"logIcon[status.value]\"></fa-icon>\n <span class=\"pl-1\">{{ status.value }}</span>\n </li>\n </ng-container>\n </ul>\n </div>\n <div class=\"column has-text-right\" *ngIf=\"filteredType()\">\n <label class=\"is-inline-block checkbox\">\n <input\n type=\"checkbox\"\n class=\"selector\"\n [ngModel]=\"onlyRequired\"\n (change)=\"onlyRequired.set($event.target.checked)\"\n [disabled]=\"!!term()\" />\n <span class=\"ml-2\">\n Show only {{ filteredType() | pluralize }} included in the default Hestia system boundary\n </span>\n </label>\n </div>\n </div>\n </div>\n</div>\n\n<ng-template #showOutdatedLogsWarning>\n <div class=\"is-3 has-text-centered\">\n <p class=\"is-mb-2\">\n <fa-icon class=\"is-pr-2\" icon=\"exclamation-triangle\"></fa-icon>\n <span>These logs might be incorrect as the calculations are outdated.</span>\n </p>\n <p class=\"is-underlined is-size-7\"><a (click)=\"showOutdatedLogs.set(true)\">View logs anyway.</a></p>\n </div>\n</ng-template>\n\n<ng-template #blankNodeModels let-data=\"data\">\n <ng-template #notInSystemBoundary>\n <td [attr.colspan]=\"methodModelsCount()\">\n <span>Not in Hestia system boundary</span>\n </td>\n </ng-template>\n\n <ng-container *ngIf=\"isSystemBoundary(data); else noValue\">\n <td class=\"blank-node-index-{{ i }}\" *ngFor=\"let c of methodModelsCount() | times; let i = index\">\n <ng-container *ngIf=\"getModelsAt(data, i); let models; else: noValue\">\n <ng-template #modelSerie>\n <ng-container *ngTemplateOutlet=\"blankNodeModel; context: { model: models, data }\"></ng-container>\n </ng-template>\n <div *ngIf=\"models | isArray; else modelSerie\">\n <p *ngFor=\"let model of models\">\n <ng-container *ngTemplateOutlet=\"blankNodeModel; context: { model, data }\"></ng-container>\n </p>\n </div>\n </ng-container>\n </td>\n </ng-container>\n</ng-template>\n\n<ng-template #blankNodeModel let-model=\"model\" let-data=\"data\">\n <span\n class=\"is-nowrap\"\n [class.trigger-popover]=\"model.showLogs\"\n [ngbPopover]=\"logDetails\"\n [autoClose]=\"'outside'\"\n popoverClass=\"is-narrow\"\n triggers=\"manual\"\n #p=\"ngbPopover\"\n placement=\"left\"\n container=\"body\"\n (click)=\"p.isOpen() ? p.close() : model.showLogs ? p.open({ logs: model.logs }) : null\">\n <span class=\"is-capitalized\">{{ methodName(model) }}</span>\n <span class=\"pl-1\" *ngIf=\"model.logs?.methodTier || model.model?.methodTier\">\n [{{ model.logs?.methodTier || model.model?.methodTier }}]\n </span>\n\n <span\n class=\"pl-1 has-text-{{ logColor[model.status] }} trigger-popover\"\n [ngbPopover]=\"logStatusDetails\"\n [autoClose]=\"'outside'\"\n popoverClass=\"is-narrow\"\n triggers=\"manual\"\n #p1=\"ngbPopover\"\n placement=\"left\"\n container=\"body\"\n (click)=\"$event.stopPropagation(); p1.isOpen() ? p1.close() : p1.open({ model, data })\">\n <fa-icon [icon]=\"logIcon[model.status]\"></fa-icon>\n </span>\n\n <span class=\"pl-1\" *ngIf=\"model.model\">\n (\n <ng-container *ngTemplateOutlet=\"docsLink; context: { $implicit: model.model }\"></ng-container>\n )\n </span>\n </span>\n</ng-template>\n\n<ng-template #noValue>-</ng-template>\n\n<ng-template #notRecalculated>not recalculated</ng-template>\n\n<ng-template #logDetails let-logs=\"logs\">\n <div class=\"table-container\" *bindOnce=\"logs\">\n <table class=\"table is-dark is-fullwidth\">\n <tbody>\n <ng-container *ngIf=\"logs?.requirements\">\n <ng-container *ngFor=\"let key of requirementKeys(logs.requirements)\">\n <ng-container *ngTemplateOutlet=\"logLine; context: { key, value: logs.requirements[key] }\"></ng-container>\n </ng-container>\n </ng-container>\n\n <ng-container *ngIf=\"logs?.logs\">\n <ng-container *ngFor=\"let key of logs.logs | keys\">\n <ng-container *ngTemplateOutlet=\"logLine; context: key\"></ng-container>\n </ng-container>\n </ng-container>\n </tbody>\n </table>\n </div>\n\n <ng-container *bindOnce=\"logs\">\n <div class=\"it-mt-2\" *ngIf=\"logs?.missingLookups?.length\">\n <p>Optional data missing:</p>\n\n <div class=\"table-container data-table-container\">\n <table class=\"table is-dark is-fullwidth is-striped\">\n <thead>\n <tr>\n <th class=\"has-text-white\">\n <span>Filename</span>\n </th>\n <th class=\"has-text-white\">\n <span>Column Title</span>\n </th>\n <th class=\"has-text-white\">\n <span>Row (term.id)</span>\n </th>\n </tr>\n </thead>\n <tbody class=\"has-text-white\">\n <tr *ngFor=\"let data of logs.missingLookups\">\n <td>{{ data.filename }}</td>\n <td>{{ data.column }}</td>\n <td>{{ data.termId }}</td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n </ng-container>\n</ng-template>\n\n<ng-template #logLineValue let-key=\"key\" let-value=\"value\">\n <ng-template #defaultValue>\n <span class=\"is-inline-block is-align-middle\">{{ value }}</span>\n </ng-template>\n <ng-container *ngIf=\"requirementLinkedNode(key, value); let linkedNode; else: defaultValue\">\n <he-node-link\n class=\"is-inline-block is-align-middle\"\n linkClass=\"is-dark\"\n [node]=\"linkedNode\"\n [showExternalLink]=\"true\"></he-node-link>\n </ng-container>\n</ng-template>\n\n<ng-template #logLine let-key=\"key\" let-value=\"value\">\n <tr>\n <td class=\"has-border-right copy-log\">\n <span class=\"is-inline-block is-align-middle\">\n <ng-template #defaultMessage>\n <ng-container [ngSwitch]=\"key\">\n <ng-container *ngSwitchDefault>{{ key | keyToLabel }}</ng-container>\n\n <ng-container *ngSwitchCase=\"'property_id'\">Property Term @id</ng-container>\n <ng-container *ngSwitchCase=\"'product_id'\">Product Term @id</ng-container>\n <ng-container *ngSwitchCase=\"'input_id'\">Input Term @id</ng-container>\n\n <ng-container *ngSwitchCase=\"'node_type_allowed'\">\n <span>Is the current</span>\n <code class=\"is-mx-1\">Node</code>\n <span>allowed to run this model</span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'siteType_allowed'\">\n <span>Is the current</span>\n <code class=\"is-mx-1\">siteType</code>\n <span>allowed to run this model</span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'product_id_allowed'\">\n <span>Are any of the Product</span>\n <code class=\"is-mx-1\">@id</code>\n <span>allowed to run this model</span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'product_termType_allowed'\">\n <span>Are any of the Product</span>\n <code class=\"is-mx-1\">termType</code>\n <span>allowed to run this model</span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'input_id_allowed'\">\n <span>Are any of the Input</span>\n <code class=\"is-mx-1\">@id</code>\n <span>allowed to run this model</span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'input_termType_allowed'\">\n <span>Are any of the Input</span>\n <code class=\"is-mx-1\">termType</code>\n <span>allowed to run this model</span>\n </ng-container>\n\n <!-- Deprecated -->\n <ng-container *ngSwitchCase=\"'primary_product_id_allowed'\">\n <span>Is the current primary product</span>\n <code class=\"is-mx-1\">@id</code>\n <span>allowed to run this model</span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'primary_product_termType_allowed'\">\n <span>Is the current primary product</span>\n <code class=\"is-mx-1\">termType</code>\n <span>allowed to run this model</span>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'geospatial_data'\">\n Has geospatial data necessary to run this model\n </ng-container>\n <ng-container *ngSwitchCase=\"'contains_geospatial_data'\">\n Has geospatial data necessary to run this model\n </ng-container>\n <ng-container *ngSwitchCase=\"'current_size'\">Current polygon area</ng-container>\n <ng-container *ngSwitchCase=\"'max_area_size'\">Maximum polygon area to run this model</ng-container>\n <ng-container *ngSwitchCase=\"'below_max_area_size'\">Polygon below the maximum area</ng-container>\n <ng-container *ngSwitchCase=\"'region_factor'\">Factor from region lookup</ng-container>\n\n <ng-container *ngSwitchCase=\"'has_pesticides_inputs'\">\n <span>Cycle contains</span>\n <code class=\"is-mx-1\">pesticideAI</code>\n <span>Inputs</span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'all_pesticideAI_have_lookup_value'\">\n <span>All</span>\n <code class=\"is-mx-1\">pesticideAI</code>\n <span>Inputs have a lookup value</span>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'has_crop_residue_burnt'\">\n <code class=\"is-mr-1\">aboveGroundCropResidueBurnt</code>\n <span>is present as Product</span>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'liquid_slurry_sludge_P'\">Liquid, Slurry, and Sludge P</ng-container>\n </ng-container>\n </ng-template>\n\n <ng-container *ngIf=\"parseLogCompleteness(key); let completeness; else: defaultMessage\">\n <span>Data completeness for</span>\n <code class=\"is-mx-1\">{{ completeness.key }}</code>\n <span>must be</span>\n <code class=\"is-mx-1\">{{ completeness.value }}</code>\n </ng-container>\n </span>\n <he-clipboard\n class=\"is-inline-block is-align-middle\"\n clipboardClass=\"is-size-7 is-p-1\"\n [icon]=\"['far', 'clone']\"\n [value]=\"key\"\n [hideText]=\"true\"></he-clipboard>\n </td>\n <td>\n <ng-template #singleValue>\n <ng-container *ngTemplateOutlet=\"logLineValue; context: { key, value }\"></ng-container>\n </ng-template>\n <div *ngIf=\"logValueArray(value); let valueArray; else: singleValue\">\n <table class=\"table is-dark is-bordered is-striped\">\n <thead *ngIf=\"valueArray[0] | isObject\">\n <tr>\n <th class=\"has-text-white\" *ngFor=\"let v of valueArray[0] | keys\">{{ v.key }}</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let v of valueArray\">\n <ng-template #singleArrayValue>\n <td>{{ v }}</td>\n </ng-template>\n <ng-container *ngIf=\"v | isObject; else singleArrayValue\">\n <td *ngFor=\"let vv of v | keys\">{{ vv.value }}</td>\n </ng-container>\n </tr>\n </tbody>\n </table>\n </div>\n </td>\n </tr>\n</ng-template>\n\n<ng-template #logStatusDetails let-model=\"model\" let-data=\"data\">\n <ng-container *bindOnce=\"model\">\n <div class=\"is-mb-2\">\n <span>Status:</span>\n <span class=\"is-pl-1\">{{ model.status }}</span>\n </div>\n\n <ng-container *ngIf=\"model.status === LogStatus.notRequired && model.logs?.is_not_relevant === 'True'\">\n <ul class=\"is-pl-3 is-list-style-disc\">\n <li *ngIf=\"model.logs.logs?.siteType_allowed === 'False'\">\n The\n <code class=\"is-mx-1\">site.siteType</code>\n is not relevant.\n </li>\n <li *ngIf=\"model.logs.logs?.product_id_allowed === 'False'\">\n None of the\n <code class=\"is-mx-1\">Product</code>\n <code class=\"is-mr-1\">term.@id</code>\n is relevant.\n </li>\n <li *ngIf=\"model.logs.logs?.product_termType_allowed === 'False'\">\n None of the\n <code class=\"is-mx-1\">Product</code>\n <code class=\"is-mr-1\">term.termType</code>\n is relevant.\n </li>\n <li *ngIf=\"model.logs.logs?.input_id_allowed === 'False'\">\n None of the\n <code class=\"is-mx-1\">Input</code>\n <code class=\"is-mr-1\">term.@id</code>\n is relevant.\n </li>\n <li *ngIf=\"model.logs.logs?.input_termType_allowed === 'False'\">\n None of the\n <code class=\"is-mx-1\">Input</code>\n <code class=\"is-mr-1\">term.termType</code>\n is relevant.\n </li>\n </ul>\n </ng-container>\n\n <ng-container\n *ngIf=\"model.logs && model.status !== LogStatus.notRequired && model.status !== LogStatus.skipHierarchy\">\n <ul class=\"is-pl-3 is-list-style-disc\">\n <ng-template #showRunOrchestrator>\n <li class=\"is-run-orchestrator\">\n <p *ngIf=\"model.logs?.shouldRun\">All the requirements were met to run the model.</p>\n <ng-container *ngIf=\"!model.logs?.shouldRun\">\n <p>Some of the requirements were not met to run the model.</p>\n <p>You can click on the model name on the left to view the debugging logs.</p>\n </ng-container>\n <ng-container *ngIf=\"model.logs?.logs?.error\">\n <p>The model failed to run for the following reason:</p>\n <p>\n <code>{{ model.logs.logs.error }}</code>\n </p>\n </ng-container>\n </li>\n </ng-template>\n\n <li\n class=\"is-no-run-orchestrator\"\n *ngIf=\"model.logs?.shouldRunOrchestrator === false; else showRunOrchestrator\">\n <ng-container *ngIf=\"!model.logs.runRequired\">\n <span class=\"is-run-node-type-not-allowed\" *ngIf=\"model.logs.logs?.node_type_allowed === 'False'\">\n This model should not run for {{ nodeType() | pluralize: 0 }}\n </span>\n </ng-container>\n\n <ng-template #runNoConfig>\n <span class=\"is-run-not-empty\" *ngIf=\"model.logs.logs?.is_empty === 'False'\">\n The {{ data.type || 'blank node' }} with Term\n <code class=\"is-mx-1\">{{ data.termId }}</code>\n is already present or already added by another model.\n </span>\n </ng-template>\n\n <ng-container *ngIf=\"model.config; else runNoConfig\">\n <p class=\"is-run-strategy-{{ model.config.runStrategy }}\" [ngSwitch]=\"model.config.runStrategy\">\n <span *ngSwitchCase=\"'always'\"></span>\n <span *ngSwitchCase=\"'add_key_if_missing'\">We only gap-fill this key if not present</span>\n <span *ngSwitchCase=\"'add_blank_node_if_missing'\">We only gap-fill this Blank Node if not present.</span>\n </p>\n\n <p class=\"is-mt-1\">\n <span\n class=\"is-run-with-measured\"\n *ngIf=\"\n model.config.runArgs?.runNonMeasured && hasMethodTier(data.original, EmissionMethodTier.measured)\n \">\n The\n <code class=\"is-mx-1\">{{ model.config.value }}</code>\n was reported as measured.\n </span>\n </p>\n </ng-container>\n </li>\n\n <li *ngIf=\"model.logs?.replaceLowerTier !== undefined\">\n <span>\n The recalculated\n <b>methodTier</b>\n was\n </span>\n <span class=\"is-pl-1 is-underlined\" *ngIf=\"!model.logs.replaceLowerTier\">lower than</span>\n <span class=\"is-pl-1 is-underlined\" *ngIf=\"model.logs.replaceLowerTier\">higher than or equal to</span>\n <span class=\"is-pl-1\">\n the original\n <b>methodTier</b>\n .\n </span>\n </li>\n\n <li class=\"is-merge-replaceLowerTier\" *ngIf=\"model.logs.replaceLowerTier\">\n <span>The recalculated</span>\n <b class=\"is-pl-1\">{{ model.config?.mergeArgs?.replaceThreshold?.[0] || 'value' }}</b>\n <span class=\"is-pl-1\">was</span>\n <span class=\"is-pl-1\">\n <ng-container *ngIf=\"model.config?.mergeArgs\">\n <span class=\"is-underlined\" *ngIf=\"!model.logs.replaceThreshold\">less than</span>\n <span class=\"is-underlined\" *ngIf=\"model.logs.replaceThreshold\">more than or equal to</span>\n <b class=\"is-pl-1\">{{ model.config.mergeArgs.replaceThreshold[1] * 100 }}%</b>\n </ng-container>\n <ng-container *ngIf=\"!model.config?.mergeArgs\">\n <span class=\"is-underlined\" *ngIf=\"!model.logs.replaceThreshold\">not sufficiently</span>\n <span class=\"is-underlined\" *ngIf=\"model.logs.replaceThreshold\">sufficiently</span>\n </ng-container>\n </span>\n <span class=\"is-pl-1\">different from the original</span>\n <b class=\"is-pl-1\">{{ model.config?.mergeArgs?.replaceThreshold?.[0] || 'value' }}.</b>\n </li>\n </ul>\n </ng-container>\n </ng-container>\n</ng-template>\n\n<ng-template #docsLink let-model>\n <a [href]=\"model.apiDocsPath || model.docPath || model.path\" target=\"_blank\" (click)=\"$event.stopPropagation()\">\n <span>Docs</span>\n <fa-icon class=\"ml-1\" icon=\"external-link-alt\" size=\"sm\"></fa-icon>\n </a>\n</ng-template>\n", styles: [":host{display:block}::ng-deep .table{background-color:transparent}::ng-deep .table td he-node-link{width:190px}@media screen and (max-width: 768px){::ng-deep .table td he-node-link{width:150px}}::ng-deep .table td .open-node+he-node-link{width:170px}@media screen and (max-width: 768px){::ng-deep .table td .open-node+he-node-link{width:130px}}::ng-deep .table td.has-border-right{box-shadow:1px 0 #6c8093}::ng-deep .table .has-sub-rows.is-open>td:first-child:before,::ng-deep .table .is-sub-row>td:first-child:before{display:block;position:absolute;content:\" \";background-color:#6c809333;height:100%;width:1px;top:0;left:12px}::ng-deep .table .has-sub-rows.is-open>td:first-child:before{top:25px}::ng-deep .table .popover-body .table-container{max-height:260px;overflow-y:auto}::ng-deep .copy-log he-clipboard{visibility:hidden}::ng-deep .copy-log:hover he-clipboard{visibility:visible}\n"] }]
7259
6682
  }], ctorParameters: function () { return [{ type: HeNodeService }, { type: HeSearchService }, { type: HeEngineService }]; }, propDecorators: { node: [{
7260
6683
  type: Input
7261
6684
  }], nodeKey: [{
@@ -7270,13 +6693,195 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.8", ngImpor
7270
6693
  type: Input
7271
6694
  }], filterTermTypesLabel: [{
7272
6695
  type: Input
7273
- }], logsKey: [{
6696
+ }], logsKey: [{
6697
+ type: Input
6698
+ }], noDataMessage: [{
6699
+ type: Input
6700
+ }] } });
6701
+
6702
+ class NodeMissingLookupFactorsComponent {
6703
+ constructor(ref, nodeService) {
6704
+ this.ref = ref;
6705
+ this.nodeService = nodeService;
6706
+ this.loading = true;
6707
+ this.logs = [];
6708
+ }
6709
+ async ngOnInit() {
6710
+ this.loading = true;
6711
+ this.logs = await this.nodeService.getMissingLookupsLog({
6712
+ ...this.node,
6713
+ dataState: DataState.recalculated
6714
+ });
6715
+ this.loading = false;
6716
+ this.ref.detectChanges();
6717
+ }
6718
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: NodeMissingLookupFactorsComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: HeNodeService }], target: i0.ɵɵFactoryTarget.Component }); }
6719
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.8", type: NodeMissingLookupFactorsComponent, selector: "he-node-missing-lookup-factors", inputs: { node: "node" }, ngImport: i0, template: "<div *ngIf=\"!loading; else loader\" class=\"table-container data-table-container\">\n <table class=\"table is-fullwidth is-hoverable is-striped mb-0\">\n <thead>\n <tr>\n <th>\n <span>Filename</span>\n </th>\n <th>\n <span>Column Title</span>\n </th>\n <th>\n <span>Row (term.id)</span>\n </th>\n <th>\n <span>Model</span>\n </th>\n </tr>\n </thead>\n <tbody>\n <tr *ngIf=\"!logs.length\">\n <td colspan=\"3\">\n <span>No missing lookup factors.</span>\n </td>\n </tr>\n <tr *ngFor=\"let log of logs\">\n <td>{{ log.filename }}</td>\n <td>\n <span *ngIf=\"log.column; else na\">{{ log.column }}</span>\n </td>\n <td>\n <span *ngIf=\"log.termId; else na\">{{ log.termId }}</span>\n </td>\n <td>\n <ng-container *ngIf=\"log.model; else na\">\n <span>{{ log.model }}</span>\n <span class=\"pl-1\" *ngIf=\"log.key\">/ {{ log.key }}</span>\n <span class=\"pl-1\" *ngIf=\"log.term && log.term !== log.termId\">/ {{ log.term }}</span>\n </ng-container>\n </td>\n </tr>\n </tbody>\n </table>\n</div>\n\n<ng-template #loader>\n <div class=\"has-text-center py-3\">\n <fa-icon icon=\"spinner\" [pulse]=\"true\" size=\"lg\"></fa-icon>\n </div>\n</ng-template>\n\n<ng-template #na>\n <span>-</span>\n</ng-template>\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "spin", "pulse", "mask", "styles", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "classes", "transform", "a11yRole"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
6720
+ }
6721
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: NodeMissingLookupFactorsComponent, decorators: [{
6722
+ type: Component$1,
6723
+ args: [{ selector: 'he-node-missing-lookup-factors', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div *ngIf=\"!loading; else loader\" class=\"table-container data-table-container\">\n <table class=\"table is-fullwidth is-hoverable is-striped mb-0\">\n <thead>\n <tr>\n <th>\n <span>Filename</span>\n </th>\n <th>\n <span>Column Title</span>\n </th>\n <th>\n <span>Row (term.id)</span>\n </th>\n <th>\n <span>Model</span>\n </th>\n </tr>\n </thead>\n <tbody>\n <tr *ngIf=\"!logs.length\">\n <td colspan=\"3\">\n <span>No missing lookup factors.</span>\n </td>\n </tr>\n <tr *ngFor=\"let log of logs\">\n <td>{{ log.filename }}</td>\n <td>\n <span *ngIf=\"log.column; else na\">{{ log.column }}</span>\n </td>\n <td>\n <span *ngIf=\"log.termId; else na\">{{ log.termId }}</span>\n </td>\n <td>\n <ng-container *ngIf=\"log.model; else na\">\n <span>{{ log.model }}</span>\n <span class=\"pl-1\" *ngIf=\"log.key\">/ {{ log.key }}</span>\n <span class=\"pl-1\" *ngIf=\"log.term && log.term !== log.termId\">/ {{ log.term }}</span>\n </ng-container>\n </td>\n </tr>\n </tbody>\n </table>\n</div>\n\n<ng-template #loader>\n <div class=\"has-text-center py-3\">\n <fa-icon icon=\"spinner\" [pulse]=\"true\" size=\"lg\"></fa-icon>\n </div>\n</ng-template>\n\n<ng-template #na>\n <span>-</span>\n</ng-template>\n", styles: [":host{display:block}\n"] }]
6724
+ }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: HeNodeService }]; }, propDecorators: { node: [{
6725
+ type: Input
6726
+ }] } });
6727
+
6728
+ // TODO: compute from the list of unique properties
6729
+ const additionalKeys = [
6730
+ 'key',
6731
+ 'methodModelDescription',
6732
+ 'methodDescription',
6733
+ 'description',
6734
+ 'primary',
6735
+ 'emissionDuration',
6736
+ 'observations',
6737
+ 'statsDefinition',
6738
+ 'term',
6739
+ 'source',
6740
+ 'variety',
6741
+ 'reliability',
6742
+ 'price',
6743
+ 'currency',
6744
+ 'cost',
6745
+ 'revenue',
6746
+ 'economicValueShare',
6747
+ 'operation',
6748
+ 'impactAssessment',
6749
+ 'properties',
6750
+ 'isAnimalFeed',
6751
+ 'fate'
6752
+ ];
6753
+ const tableKeys = [
6754
+ 'aniamals',
6755
+ 'inputs',
6756
+ 'properties',
6757
+ 'transformation',
6758
+ 'operation',
6759
+ 'impactAssessment',
6760
+ 'value',
6761
+ 'term.units',
6762
+ 'dates',
6763
+ 'methodModel',
6764
+ 'methodTier',
6765
+ 'statsDefinition',
6766
+ 'depthUpper',
6767
+ 'depthLower'
6768
+ ];
6769
+ class NodeValueDetailsComponent {
6770
+ constructor() {
6771
+ this.baseUrl = baseUrl();
6772
+ this.keys = ['value', ...grouppedValueKeys];
6773
+ this.additionalKeys = additionalKeys;
6774
+ this.tableKeys = tableKeys;
6775
+ }
6776
+ ngOnInit() {
6777
+ this.tableKeys = tableKeys.filter(key => (this.data?.nodes || []).some(node => !!get(node, key)));
6778
+ }
6779
+ get type() {
6780
+ return this.data?.nodes[0]['@type'];
6781
+ }
6782
+ get showInline() {
6783
+ return this.data?.nodes?.length === 1;
6784
+ }
6785
+ defaultValue(key) {
6786
+ return ['impactAssessment', 'transformation'].includes(key) ? 'N/A (from Cycle)' : '';
6787
+ }
6788
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: NodeValueDetailsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6789
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.8", type: NodeValueDetailsComponent, selector: "he-node-value-details", inputs: { data: "data", nodeType: "nodeType", dataKey: "dataKey", dataState: "dataState" }, ngImport: i0, template: "<ng-container *bindOnce=\"data\">\n <ng-container *ngIf=\"showInline; else asTable\">\n <ng-container *ngFor=\"let key of keys\">\n <he-link-key-value\n [node]=\"data!.nodes[0]\"\n [nodeType]=\"nodeType\"\n [dataState]=\"dataState\"\n [dataKey]=\"dataKey\"\n [key]=\"key\"></he-link-key-value>\n </ng-container>\n <ng-container *ngFor=\"let key of additionalKeys\">\n <he-link-key-value\n [node]=\"data!.nodes[0]\"\n [nodeType]=\"nodeType\"\n [dataState]=\"dataState\"\n [dataKey]=\"dataKey\"\n [key]=\"key\"></he-link-key-value>\n </ng-container>\n </ng-container>\n</ng-container>\n\n<ng-template #asTable>\n <he-link-key-value\n [node]=\"data!.nodes[0]\"\n [nodeType]=\"nodeType\"\n [dataState]=\"dataState\"\n [dataKey]=\"dataKey\"\n key=\"term\"></he-link-key-value>\n\n <div class=\"table-container mt-2\">\n <table class=\"table is-dark is-narrow is-striped\">\n <thead>\n <th *ngFor=\"let key of tableKeys\">\n <a class=\"is-dark\" [href]=\"baseUrl + '/schema/' + type + '#' + key.split('.')[0]\" target=\"_blank\">\n <b>{{ key.includes('.') ? key.split('.')[1] : key }}</b>\n </a>\n </th>\n </thead>\n <tbody>\n <tr *ngFor=\"let node of data!.nodes\">\n <td *ngFor=\"let key of tableKeys\">\n <he-link-key-value\n [node]=\"node\"\n [nodeType]=\"nodeType\"\n [dataState]=\"dataState\"\n [dataKey]=\"dataKey\"\n [key]=\"key\"\n [defaultValue]=\"defaultValue(key)\"></he-link-key-value>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n</ng-template>\n", styles: ["table{background-color:transparent}table::ng-deep he-link-key-value>a:first-child,table::ng-deep he-link-key-value>a:first-child+span{display:none}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: BindOnceDirective, selector: "[bindOnce]", inputs: ["bindOnce"] }, { kind: "component", type: LinkKeyValueComponent, selector: "he-link-key-value", inputs: ["node", "nodeType", "dataKey", "key", "defaultValue", "dataState"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
6790
+ }
6791
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: NodeValueDetailsComponent, decorators: [{
6792
+ type: Component$1,
6793
+ args: [{ selector: 'he-node-value-details', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *bindOnce=\"data\">\n <ng-container *ngIf=\"showInline; else asTable\">\n <ng-container *ngFor=\"let key of keys\">\n <he-link-key-value\n [node]=\"data!.nodes[0]\"\n [nodeType]=\"nodeType\"\n [dataState]=\"dataState\"\n [dataKey]=\"dataKey\"\n [key]=\"key\"></he-link-key-value>\n </ng-container>\n <ng-container *ngFor=\"let key of additionalKeys\">\n <he-link-key-value\n [node]=\"data!.nodes[0]\"\n [nodeType]=\"nodeType\"\n [dataState]=\"dataState\"\n [dataKey]=\"dataKey\"\n [key]=\"key\"></he-link-key-value>\n </ng-container>\n </ng-container>\n</ng-container>\n\n<ng-template #asTable>\n <he-link-key-value\n [node]=\"data!.nodes[0]\"\n [nodeType]=\"nodeType\"\n [dataState]=\"dataState\"\n [dataKey]=\"dataKey\"\n key=\"term\"></he-link-key-value>\n\n <div class=\"table-container mt-2\">\n <table class=\"table is-dark is-narrow is-striped\">\n <thead>\n <th *ngFor=\"let key of tableKeys\">\n <a class=\"is-dark\" [href]=\"baseUrl + '/schema/' + type + '#' + key.split('.')[0]\" target=\"_blank\">\n <b>{{ key.includes('.') ? key.split('.')[1] : key }}</b>\n </a>\n </th>\n </thead>\n <tbody>\n <tr *ngFor=\"let node of data!.nodes\">\n <td *ngFor=\"let key of tableKeys\">\n <he-link-key-value\n [node]=\"node\"\n [nodeType]=\"nodeType\"\n [dataState]=\"dataState\"\n [dataKey]=\"dataKey\"\n [key]=\"key\"\n [defaultValue]=\"defaultValue(key)\"></he-link-key-value>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n</ng-template>\n", styles: ["table{background-color:transparent}table::ng-deep he-link-key-value>a:first-child,table::ng-deep he-link-key-value>a:first-child+span{display:none}\n"] }]
6794
+ }], propDecorators: { data: [{
6795
+ type: Input
6796
+ }], nodeType: [{
6797
+ type: Input
6798
+ }], dataKey: [{
6799
+ type: Input
6800
+ }], dataState: [{
6801
+ type: Input
6802
+ }] } });
6803
+
6804
+ var NodeField;
6805
+ (function (NodeField) {
6806
+ NodeField["inputs"] = "inputs";
6807
+ NodeField["measurements"] = "measurements";
6808
+ NodeField["practices"] = "practices";
6809
+ NodeField["products"] = "products";
6810
+ })(NodeField || (NodeField = {}));
6811
+ const filtersByType = {
6812
+ [NodeType.Cycle]: cycle => {
6813
+ const primaryProduct = (cycle.products || []).find(p => p.primary && !!p.term?.['@id']);
6814
+ return primaryProduct
6815
+ ? {
6816
+ productTermId: primaryProduct.term['@id']
6817
+ }
6818
+ : {};
6819
+ },
6820
+ [NodeType.Site]: ({ siteType }) => ({
6821
+ siteType
6822
+ })
6823
+ };
6824
+ const termTypesByField = {
6825
+ [NodeField.inputs]: SchemaType.Input,
6826
+ [NodeField.measurements]: SchemaType.Measurement,
6827
+ [NodeField.practices]: SchemaType.Practice,
6828
+ [NodeField.products]: SchemaType.Product
6829
+ };
6830
+ const isValid = (node, nodeField) => Object.values(NodeField).includes(nodeField) && (node?.type || node?.['@type']) in filtersByType;
6831
+ class NodeRecommendationsComponent {
6832
+ constructor(engineService) {
6833
+ this.engineService = engineService;
6834
+ this.selectRecommendation = new EventEmitter$1();
6835
+ this.loading = false;
6836
+ this.visible = false;
6837
+ this.recommendations = [];
6838
+ }
6839
+ ngOnChanges(changes) {
6840
+ if ('node' in changes && isValid(this.node, this.nodeField)) {
6841
+ const oldFilters = copyObject(this._filters);
6842
+ this._filters = filterParams(filtersByType[this.type](this.node));
6843
+ if (oldFilters === null || !isEqual(oldFilters, this._filters)) {
6844
+ this.refresh();
6845
+ }
6846
+ }
6847
+ }
6848
+ trackByValue(_index, id) {
6849
+ return id;
6850
+ }
6851
+ get type() {
6852
+ return this.node?.type || this.node?.['@type'];
6853
+ }
6854
+ async refresh() {
6855
+ this.loading = true;
6856
+ const termType = termTypesByField[this.nodeField];
6857
+ const ids = await this.engineService.getTermIds({ ...this._filters, termType });
6858
+ const existingIds = (this.node[this.nodeField] || []).map(n => n.term?.['@id']).filter(Boolean);
6859
+ this.recommendations = ids.filter(id => !existingIds.includes(id)).sort();
6860
+ this.loading = false;
6861
+ }
6862
+ add(id, index) {
6863
+ this.selectRecommendation.next(id);
6864
+ const recommendations = this.recommendations.slice();
6865
+ recommendations.splice(index, 1);
6866
+ this.recommendations = recommendations;
6867
+ }
6868
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: NodeRecommendationsComponent, deps: [{ token: HeEngineService }], target: i0.ɵɵFactoryTarget.Component }); }
6869
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.8", type: NodeRecommendationsComponent, selector: "he-node-recommendations", inputs: { node: "node", nodeField: "nodeField", buttonClass: "buttonClass" }, outputs: { selectRecommendation: "selectRecommendation" }, usesOnChanges: true, ngImport: i0, template: "<p class=\"my-2 is-size-7\" [class.is-hidden]=\"!loading && recommendations.length === 0\">\n <span class=\"pr-2\">Recommendations</span>\n <span *ngIf=\"loading\">\n <fa-icon icon=\"spinner\" [pulse]=\"true\" size=\"sm\"></fa-icon>\n </span>\n <a *ngIf=\"!loading\" (click)=\"visible = !visible\">\n <span *ngIf=\"visible\">Hide</span>\n <span *ngIf=\"!visible\">Show</span>\n </a>\n</p>\n\n<div [class.is-hidden]=\"!visible\">\n <button\n class=\"button mr-2 mb-2 {{ buttonClass }}\"\n *ngFor=\"let id of recommendations; trackBy: trackByValue; let i = index\"\n (click)=\"add(id, i)\">\n <fa-icon icon=\"plus-circle\"></fa-icon>\n <span class=\"pl-2\">Add</span>\n <span class=\"pl-1\">{{ id | keyToLabel }}</span>\n </button>\n</div>\n", styles: [""], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "spin", "pulse", "mask", "styles", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "classes", "transform", "a11yRole"] }, { kind: "pipe", type: KeyToLabelPipe, name: "keyToLabel" }] }); }
6870
+ }
6871
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: NodeRecommendationsComponent, decorators: [{
6872
+ type: Component$1,
6873
+ args: [{ selector: 'he-node-recommendations', template: "<p class=\"my-2 is-size-7\" [class.is-hidden]=\"!loading && recommendations.length === 0\">\n <span class=\"pr-2\">Recommendations</span>\n <span *ngIf=\"loading\">\n <fa-icon icon=\"spinner\" [pulse]=\"true\" size=\"sm\"></fa-icon>\n </span>\n <a *ngIf=\"!loading\" (click)=\"visible = !visible\">\n <span *ngIf=\"visible\">Hide</span>\n <span *ngIf=\"!visible\">Show</span>\n </a>\n</p>\n\n<div [class.is-hidden]=\"!visible\">\n <button\n class=\"button mr-2 mb-2 {{ buttonClass }}\"\n *ngFor=\"let id of recommendations; trackBy: trackByValue; let i = index\"\n (click)=\"add(id, i)\">\n <fa-icon icon=\"plus-circle\"></fa-icon>\n <span class=\"pl-2\">Add</span>\n <span class=\"pl-1\">{{ id | keyToLabel }}</span>\n </button>\n</div>\n" }]
6874
+ }], ctorParameters: function () { return [{ type: HeEngineService }]; }, propDecorators: { node: [{
6875
+ type: Input
6876
+ }], nodeField: [{
7274
6877
  type: Input
7275
- }], noDataMessage: [{
6878
+ }], buttonClass: [{
7276
6879
  type: Input
6880
+ }], selectRecommendation: [{
6881
+ type: Output
7277
6882
  }] } });
7278
6883
 
7279
- const components$7 = [
6884
+ const components$8 = [
7280
6885
  NodeIconComponent,
7281
6886
  NodeLinkComponent,
7282
6887
  NodeCsvExportConfirmComponent,
@@ -7314,8 +6919,8 @@ class HeNodeModule {
7314
6919
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: HeNodeModule, decorators: [{
7315
6920
  type: NgModule,
7316
6921
  args: [{
7317
- declarations: components$7,
7318
- exports: components$7,
6922
+ declarations: components$8,
6923
+ exports: components$8,
7319
6924
  imports: [CommonModule, RouterModule, FormsModule, DragDropModule, HeCommonModule]
7320
6925
  }]
7321
6926
  }] });
@@ -7399,7 +7004,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.8", ngImpor
7399
7004
  type: Input
7400
7005
  }] } });
7401
7006
 
7402
- const components$6 = [TermsPropertyContentComponent, TermsSubClassOfContentComponent, TermsUnitsDescriptionComponent];
7007
+ const components$7 = [TermsPropertyContentComponent, TermsSubClassOfContentComponent, TermsUnitsDescriptionComponent];
7403
7008
  class HeTermsModule {
7404
7009
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: HeTermsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
7405
7010
  static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.1.8", ngImport: i0, type: HeTermsModule, declarations: [TermsPropertyContentComponent, TermsSubClassOfContentComponent, TermsUnitsDescriptionComponent], imports: [CommonModule,
@@ -7420,8 +7025,8 @@ class HeTermsModule {
7420
7025
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: HeTermsModule, decorators: [{
7421
7026
  type: NgModule,
7422
7027
  args: [{
7423
- declarations: components$6,
7424
- exports: components$6,
7028
+ declarations: components$7,
7029
+ exports: components$7,
7425
7030
  imports: [
7426
7031
  CommonModule,
7427
7032
  RouterModule,
@@ -7434,6 +7039,116 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.8", ngImpor
7434
7039
  }]
7435
7040
  }] });
7436
7041
 
7042
+ const defaultDataStates = [DataState.original, DataState.recalculated];
7043
+ const nodeTypeDataState = {
7044
+ [NodeType.Cycle]: {
7045
+ default: defaultDataStates,
7046
+ aggregated: [DataState.original]
7047
+ },
7048
+ [NodeType.ImpactAssessment]: {
7049
+ default: defaultDataStates,
7050
+ aggregated: [DataState.recalculated]
7051
+ },
7052
+ [NodeType.Site]: {
7053
+ default: defaultDataStates,
7054
+ aggregated: [DataState.original]
7055
+ }
7056
+ };
7057
+ const nodeTypeDataStates = (nodeType, aggregated = false) => {
7058
+ const dataStatesMapping = nodeTypeDataState[nodeType] || {
7059
+ default: [DataState.original],
7060
+ aggregated: [DataState.original]
7061
+ };
7062
+ return aggregated ? dataStatesMapping.aggregated : dataStatesMapping.default;
7063
+ };
7064
+ const sortNodes = (values) => values?.length
7065
+ ? orderBy(values.filter(Boolean), ['original.aggregated', 'original.site.@id', 'original.cycle.@id', 'original.@id'], ['asc', 'asc', 'asc', 'asc'])
7066
+ : [];
7067
+ const isAggregated = (id) => !!id.match(/^[a-zA-Z]+[-][a-zA-Z]+[-][\d]{4,}[-][\d]{4,}/g);
7068
+ class HeNodeStoreService {
7069
+ constructor(nodeService) {
7070
+ this.nodeService = nodeService;
7071
+ this._nodesLoadRequests = {};
7072
+ this._nodes = {};
7073
+ this._nodes$ = new ReplaySubject(1);
7074
+ }
7075
+ findNodeIndex(node) {
7076
+ const nodes = this._nodes?.[node['@type']] || [];
7077
+ return nodes.findIndex(n => n.type === node['@type'] && n.id === node['@id']);
7078
+ }
7079
+ loadNode(node) {
7080
+ const aggregated = 'aggregated' in node ? node.aggregated : isAggregated(node['@id']);
7081
+ const dataStates = nodeTypeDataStates(node['@type'], aggregated);
7082
+ const index = this._nodesLoadRequests[node['@type']].length;
7083
+ const request = forkJoin(dataStates.reduce((prev, dataState) => ({
7084
+ ...prev,
7085
+ [dataState]: this.nodeService
7086
+ .get$({ ...node, dataState })
7087
+ .pipe(catchError(() => of(undefined)))
7088
+ }), {})).pipe(shareReplay({ bufferSize: 1, refCount: true }), map((values) => Object.fromEntries(Object.values(DataState).map(dataState => [
7089
+ dataState,
7090
+ values[dataState] || values[DataState.original] || node
7091
+ ]))), map(values => ({
7092
+ index,
7093
+ type: node['@type'],
7094
+ id: node['@id'],
7095
+ ...values
7096
+ })));
7097
+ this._nodesLoadRequests[node['@type']].push({
7098
+ id: node['@id'],
7099
+ request
7100
+ });
7101
+ request.subscribe(data => {
7102
+ this._nodes[node['@type']][index] = data;
7103
+ this._nodes$.next(this._nodes);
7104
+ });
7105
+ return request;
7106
+ }
7107
+ addNode(node) {
7108
+ this._nodesLoadRequests[node['@type']] = this._nodesLoadRequests[node['@type']] || [];
7109
+ this._nodes[node['@type']] = this._nodes[node['@type']] || [];
7110
+ const existingRequest = this._nodesLoadRequests[node['@type']].find(({ id }) => id === node['@id']);
7111
+ return existingRequest ? existingRequest.request : this.loadNode(node);
7112
+ }
7113
+ removeNodeByIndex(nodeType, index) {
7114
+ this._nodesLoadRequests[nodeType].splice(index, 1);
7115
+ this._nodes[nodeType].splice(index, 1);
7116
+ this._nodes$.next(this._nodes);
7117
+ }
7118
+ removeNode(node) {
7119
+ const index = this.findNodeIndex(node);
7120
+ return index >= 0 ? this.removeNodeByIndex(node['@type'], index) : null;
7121
+ }
7122
+ clearNodes() {
7123
+ this._nodesLoadRequests = {};
7124
+ this._nodes = {};
7125
+ this._nodes$.next(this._nodes);
7126
+ }
7127
+ nodes$() {
7128
+ return this._nodes$.asObservable();
7129
+ }
7130
+ sortedNodes$() {
7131
+ return this.nodes$().pipe(map(nodes => Object.fromEntries(Object.entries(nodes).map(([nodeKey, values]) => [nodeKey, sortNodes(values)]))));
7132
+ }
7133
+ ids$(nodeType) {
7134
+ return this.nodes$().pipe(mergeMap(values => values[nodeType]), map(({ id }) => id), toArray());
7135
+ }
7136
+ find$(nodeType, id) {
7137
+ return this.nodes$().pipe(map(values => (values[nodeType] || []).filter(node => !id || node.id === id)));
7138
+ }
7139
+ findByState$(nodeType, dataState, id) {
7140
+ return this.find$(nodeType, id).pipe(map(values => values.map(v => v[dataState]).filter(Boolean)));
7141
+ }
7142
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: HeNodeStoreService, deps: [{ token: HeNodeService }], target: i0.ɵɵFactoryTarget.Injectable }); }
7143
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: HeNodeStoreService, providedIn: 'root' }); }
7144
+ }
7145
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: HeNodeStoreService, decorators: [{
7146
+ type: Injectable,
7147
+ args: [{
7148
+ providedIn: 'root'
7149
+ }]
7150
+ }], ctorParameters: function () { return [{ type: HeNodeService }]; } });
7151
+
7437
7152
  var View$3;
7438
7153
  (function (View) {
7439
7154
  View["table"] = "Table view";
@@ -7901,76 +7616,355 @@ class CyclesNodesComponent {
7901
7616
  if (!this.selectedGroupTerm() || !this.groupNodeTerms().includes(this.selectedGroupTerm())) {
7902
7617
  this.selectedGroupTerm.set(this.groupNodeTerms()[0]);
7903
7618
  }
7904
- }, { allowSignalWrites: true });
7619
+ }, { allowSignalWrites: true });
7620
+ }
7621
+ groupNodesByKey({ nodeKey }) {
7622
+ const nodesPerCycle = groupNodesByTerm(this.cycles(), nodeKey, this.originalValues(), filterBlankNode$1(this.filterTerm()));
7623
+ return orderBy(grouppedKeys(nodesPerCycle), ['key'], ['asc']);
7624
+ }
7625
+ groupEmissions() {
7626
+ const emissionsPerCycle = groupNodesByTerm(this.cycles(), BlankNodesKey.emissions, this.originalValues(), filterBlankNode$1(this.filterTerm()));
7627
+ const values = orderBy(grouppedKeys(emissionsPerCycle), ['key'], ['asc']);
7628
+ const methodTiers = orderBy(unique(values.map(({ value }) => value.methodTier)).map(methodTier => ({
7629
+ methodTier,
7630
+ methodTierOrder: methodTierOrder(methodTier)
7631
+ })), ['methodTierOrder'], ['asc']);
7632
+ return Object.fromEntries(methodTiers.map(({ methodTier }) => [methodTier, values.filter(({ value }) => value.methodTier === methodTier)]));
7633
+ }
7634
+ trackById(_index, item) {
7635
+ return item['@id'];
7636
+ }
7637
+ togglePopover(popover, context) {
7638
+ return popover.isOpen() ? popover.close() : popover.open(context);
7639
+ }
7640
+ filterByTerm(term) {
7641
+ this.filterTerm.set(term);
7642
+ }
7643
+ selectIndex({ target: { value } }) {
7644
+ this.selectedIndex.set(+value);
7645
+ }
7646
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: CyclesNodesComponent, deps: [{ token: HeNodeStoreService }], target: i0.ɵɵFactoryTarget.Component }); }
7647
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.8", type: CyclesNodesComponent, selector: "he-cycles-nodes", inputs: { dataState: "dataState", nodeKeys: "nodeKeys", nodeKeyGroup: "nodeKeyGroup" }, ngImport: i0, template: "<div class=\"tabs is-mb-1\" *ngIf=\"isGroupNode()\">\n <ul>\n <li *ngFor=\"let term of groupNodeTerms()\" [class.is-active]=\"selectedGroupTerm() === term\">\n <a (click)=\"selectedGroupTerm.set(term)\">{{ term.name }}</a>\n </li>\n </ul>\n</div>\n\n<div class=\"columns is-variable is-align-items-center is-2 is-m-0\" *ngIf=\"hasData()\">\n <div class=\"column\">\n <ng-container *ngIf=\"selectedView() === View.table\">\n <button\n class=\"button is-small is-ghost\"\n (click)=\"showDownload = true\"\n ngbTooltip=\"Download as CSV\"\n placement=\"bottom\">\n <fa-icon icon=\"download\" size=\"lg\"></fa-icon>\n </button>\n </ng-container>\n </div>\n <div class=\"column is-narrow\" *ngIf=\"selectedView() === View.table\">\n <he-search-extend\n class=\"is-secondary is-small\"\n placeholder=\"Filter terms by name\"\n (search)=\"filterByTerm($event)\"></he-search-extend>\n </div>\n <div class=\"column is-narrow\" *ngIf=\"views()?.length > 1\">\n <div class=\"field has-addons\">\n <div class=\"control\" *ngFor=\"let view of views()\">\n <button class=\"button is-small\" [class.is-selected]=\"selectedView() === view\" (click)=\"selectedView.set(view)\">\n <span class=\"icon is-small\">\n <fa-icon [icon]=\"viewIcon[view]\" aria-hidden=\"true\"></fa-icon>\n </span>\n <span class=\"is-hidden-mobile\">{{ view }}</span>\n </button>\n </div>\n </div>\n </div>\n</div>\n\n<ng-container *ngIf=\"isNodeKeyAllowed()\">\n <ng-container [ngSwitch]=\"selectedView()\">\n <div class=\"is-px-3 is-pb-3\" *ngSwitchCase=\"View.table\">\n <ng-container *ngIf=\"hasData(); else emptyTable\">\n <he-data-table class=\"mb-1 is-small\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n <tr class=\"has-text-weight-bold\" *ngIf=\"dataKeys().length > 1\">\n <th class=\"width-auto\"></th>\n <th [class.is-hidden]=\"isGroupNode()\"></th>\n\n <ng-container *ngFor=\"let dataKey of dataKeys(); let dataKeyLast = last\">\n <ng-container *ngIf=\"data()[dataKey]?.length\">\n <th [attr.colspan]=\"data()[dataKey].length\" [class.has-border-right]=\"!dataKeyLast\">\n <span>{{ dataKey | keyToLabel }}</span>\n </th>\n </ng-container>\n </ng-container>\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\n <ng-container *ngFor=\"let dataKey of dataKeys(); let dataKeyLast = last\">\n <th\n *ngFor=\"let node of data()[dataKey]; let nodeLast = last\"\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 [innerHtml]=\"node.value.term.name | ellipsis: 30 | compound\"></span>\n </he-node-link>\n </th>\n </ng-container>\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]=\"baseUrl + '/schema/Cycle#functionalUnit'\" target=\"_blank\">Functional unit</a>\n </th>\n\n <ng-container *ngFor=\"let dataKey of dataKeys(); let dataKeyLast = last\">\n <th\n *ngFor=\"let node of data()[dataKey]; let nodeLast = last\"\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\n class=\"is-inline-block is-ml-2\"\n [term]=\"node.value.term\"></he-terms-units-description>\n </th>\n </ng-container>\n </tr>\n </thead>\n <tbody>\n <ng-container *ngFor=\"let cycle of cycles(); trackBy: trackById; let cycleIndex = index\">\n <tr>\n <td class=\"width-auto has-border-right\" [attr.title]=\"defaultLabel(cycle)\">\n <he-node-link [node]=\"cycle.term || cycle\">\n <span>{{ cycleIndex + 1 }}. {{ defaultLabel(cycle) }}</span>\n </he-node-link>\n </td>\n <td class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\">\n <he-cycles-functional-unit-measure [cycle]=\"cycles()[0]\"></he-cycles-functional-unit-measure>\n </td>\n\n <ng-container *ngFor=\"let dataKey of dataKeys(); let dataKeyLast = last\">\n <td\n class=\"is-nowrap\"\n *ngFor=\"let node of data()[dataKey]; let nodeLast = last\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n <span\n *ngIf=\"node.value.values[cycle['@id']]; else emptyValue\"\n class=\"trigger-popover\"\n [ngbPopover]=\"details\"\n [autoClose]=\"'outside'\"\n popoverClass=\"is-narrow\"\n triggers=\"manual\"\n #p=\"ngbPopover\"\n placement=\"left\"\n container=\"body\"\n (click)=\"\n togglePopover(p, { data: node.value.values[cycle['@id']], cycle: cycle, key: dataKey })\n \">\n <span pointer>\n {{\n propertyValue(node.value.values[cycle['@id']].value, node.value.term['@id'])\n | precision: 3\n | default: '-'\n }}\n </span>\n <he-blank-node-state\n class=\"ml-1\"\n [dataState]=\"_dataState()\"\n [node]=\"node.value.values[cycle['@id']].node\"\n key=\"value\"></he-blank-node-state>\n </span>\n </td>\n </ng-container>\n </tr>\n </ng-container>\n </tbody>\n </table>\n </he-data-table>\n\n <he-blank-node-state-notice [dataState]=\"_dataState()\"></he-blank-node-state-notice>\n </ng-container>\n </div>\n\n <ng-container *ngSwitchCase=\"View.chart\">\n <ng-container [ngSwitch]=\"firstNodeKey()\">\n <he-cycles-result *ngSwitchCase=\"BlankNodesKey.inputs\" [cycles]=\"cycles()\"></he-cycles-result>\n <he-cycles-emissions-chart\n *ngSwitchCase=\"BlankNodesKey.emissions\"\n [cycles]=\"cycles()\"></he-cycles-emissions-chart>\n </ng-container>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"View.timeline\">\n <ng-container *ngTemplateOutlet=\"selectCycle\"></ng-container>\n\n <div class=\"is-px-3 is-pb-3\">\n <he-cycles-nodes-timeline\n [recalculatedValues]=\"timelineValues()\"\n [dataState]=\"_dataState()\"></he-cycles-nodes-timeline>\n\n <he-blank-node-state-notice [dataState]=\"_dataState()\"></he-blank-node-state-notice>\n </div>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"View.logs\">\n <ng-container *ngTemplateOutlet=\"selectCycle\"></ng-container>\n\n <div class=\"tabs is-mb-2\" *ngIf=\"_nodeKeys().length > 1\">\n <ul>\n <li *ngFor=\"let nodeKey of _nodeKeys()\" [class.is-active]=\"selectedNodeKey() === nodeKey\">\n <a (click)=\"selectedNodeKey.set(nodeKey)\">{{ nodeKey | keyToLabel }}</a>\n </li>\n </ul>\n </div>\n\n <he-node-logs-models\n *ngIf=\"selectedNode()\"\n [node]=\"selectedNode()\"\n [nodeKey]=\"selectedNodeKey()\"\n [logsKey]=\"selectedLogsKey()\"\n [originalValues]=\"selectedOriginalValues()\"\n [recalculatedValues]=\"selectedRecalculatedValues()\"\n [filterTermTypes]=\"filterTermTypes()\"></he-node-logs-models>\n </ng-container>\n </ng-container>\n</ng-container>\n\n<he-node-csv-export-confirm\n *ngIf=\"showDownload\"\n [nodes]=\"cycles()\"\n [filename]=\"csvFilename()\"\n [isUpload]=\"false\"\n [headerKeys]=\"headerKeys()\"\n (closed)=\"showDownload = false\"></he-node-csv-export-confirm>\n\n<ng-template #emptyTable>\n <div class=\"is-pt-3 has-text-centered\">\n <span>No data available</span>\n <span class=\"is-pl-1\" [class.is-hidden]=\"!filterTerm()\">matching your search criteria</span>\n <span>.</span>\n <span *ngIf=\"showSwitchToRecalculated()\">\n Switch to\n <code>recalculated</code>\n version.\n </span>\n </div>\n</ng-template>\n\n<ng-template #emptyValue>\n <span>-</span>\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 [data]=\"data\"\n [dataState]=\"_dataState()\"\n [nodeType]=\"node['@type']\"\n [dataKey]=\"key\"></he-node-value-details>\n</ng-template>\n\n<ng-template #selectCycle>\n <div class=\"field has-addons is-py-2 is-px-3\" *ngIf=\"cycles().length > 1\">\n <div class=\"control\">\n <span class=\"button is-small is-static is-secondary\">Select a Cycle</span>\n </div>\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth is-secondary\">\n <select (change)=\"selectIndex($event)\">\n <option *ngFor=\"let value of cycles(); let cycleIndex = index\" [value]=\"cycleIndex\">\n {{ cycleIndex + 1 }}. {{ defaultLabel(value) }}\n </option>\n </select>\n </div>\n </div>\n </div>\n</ng-template>\n", styles: ["fa-icon{display:inline-block;width:10px}he-data-table ::ng-deep .table thead tr th:nth-child(2),he-data-table ::ng-deep .table tbody tr td:nth-child(2){max-width:102px;width:102px}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1$1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1$1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i2$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i4$1.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: i4$1.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: i3.FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "spin", "pulse", "mask", "styles", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "classes", "transform", "a11yRole"] }, { 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", "showAggregated", "showDeleted"] }, { kind: "component", type: DataTableComponent, selector: "he-data-table", inputs: ["minHeight", "maxHeight", "small"] }, { kind: "component", type: SearchExtendComponent, selector: "he-search-extend", inputs: ["value", "disabled", "placeholder", "class"], outputs: ["search"] }, { kind: "component", type: NodeLinkComponent, selector: "he-node-link", inputs: ["node", "showExternalLink", "linkClass"] }, { kind: "component", type: NodeCsvExportConfirmComponent, selector: "he-node-csv-export-confirm", inputs: ["nodes", "filename", "headerKeys", "extension", "isUpload"], outputs: ["closed"] }, { kind: "component", type: NodeLogsModelsComponent, selector: "he-node-logs-models", inputs: ["node", "nodeKey", "originalValues", "recalculatedValues", "terms", "filterTermTypes", "filterTermTypesLabel", "logsKey", "noDataMessage"] }, { kind: "component", type: NodeValueDetailsComponent, selector: "he-node-value-details", inputs: ["data", "nodeType", "dataKey", "dataState"] }, { kind: "component", type: TermsUnitsDescriptionComponent, selector: "he-terms-units-description", inputs: ["term", "iconTemplate"] }, { kind: "component", type: CyclesEmissionsChartComponent, selector: "he-cycles-emissions-chart", inputs: ["cycles"] }, { kind: "component", type: CyclesFunctionalUnitMeasureComponent, selector: "he-cycles-functional-unit-measure", inputs: ["cycle"] }, { kind: "component", type: CyclesNodesTimelineComponent, selector: "he-cycles-nodes-timeline", inputs: ["recalculatedValues", "dataState"] }, { kind: "component", type: CyclesResultComponent, selector: "he-cycles-result", inputs: ["cycles"] }, { 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" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
7648
+ }
7649
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: CyclesNodesComponent, decorators: [{
7650
+ type: Component$1,
7651
+ args: [{ selector: 'he-cycles-nodes', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"tabs is-mb-1\" *ngIf=\"isGroupNode()\">\n <ul>\n <li *ngFor=\"let term of groupNodeTerms()\" [class.is-active]=\"selectedGroupTerm() === term\">\n <a (click)=\"selectedGroupTerm.set(term)\">{{ term.name }}</a>\n </li>\n </ul>\n</div>\n\n<div class=\"columns is-variable is-align-items-center is-2 is-m-0\" *ngIf=\"hasData()\">\n <div class=\"column\">\n <ng-container *ngIf=\"selectedView() === View.table\">\n <button\n class=\"button is-small is-ghost\"\n (click)=\"showDownload = true\"\n ngbTooltip=\"Download as CSV\"\n placement=\"bottom\">\n <fa-icon icon=\"download\" size=\"lg\"></fa-icon>\n </button>\n </ng-container>\n </div>\n <div class=\"column is-narrow\" *ngIf=\"selectedView() === View.table\">\n <he-search-extend\n class=\"is-secondary is-small\"\n placeholder=\"Filter terms by name\"\n (search)=\"filterByTerm($event)\"></he-search-extend>\n </div>\n <div class=\"column is-narrow\" *ngIf=\"views()?.length > 1\">\n <div class=\"field has-addons\">\n <div class=\"control\" *ngFor=\"let view of views()\">\n <button class=\"button is-small\" [class.is-selected]=\"selectedView() === view\" (click)=\"selectedView.set(view)\">\n <span class=\"icon is-small\">\n <fa-icon [icon]=\"viewIcon[view]\" aria-hidden=\"true\"></fa-icon>\n </span>\n <span class=\"is-hidden-mobile\">{{ view }}</span>\n </button>\n </div>\n </div>\n </div>\n</div>\n\n<ng-container *ngIf=\"isNodeKeyAllowed()\">\n <ng-container [ngSwitch]=\"selectedView()\">\n <div class=\"is-px-3 is-pb-3\" *ngSwitchCase=\"View.table\">\n <ng-container *ngIf=\"hasData(); else emptyTable\">\n <he-data-table class=\"mb-1 is-small\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n <tr class=\"has-text-weight-bold\" *ngIf=\"dataKeys().length > 1\">\n <th class=\"width-auto\"></th>\n <th [class.is-hidden]=\"isGroupNode()\"></th>\n\n <ng-container *ngFor=\"let dataKey of dataKeys(); let dataKeyLast = last\">\n <ng-container *ngIf=\"data()[dataKey]?.length\">\n <th [attr.colspan]=\"data()[dataKey].length\" [class.has-border-right]=\"!dataKeyLast\">\n <span>{{ dataKey | keyToLabel }}</span>\n </th>\n </ng-container>\n </ng-container>\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\n <ng-container *ngFor=\"let dataKey of dataKeys(); let dataKeyLast = last\">\n <th\n *ngFor=\"let node of data()[dataKey]; let nodeLast = last\"\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 [innerHtml]=\"node.value.term.name | ellipsis: 30 | compound\"></span>\n </he-node-link>\n </th>\n </ng-container>\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]=\"baseUrl + '/schema/Cycle#functionalUnit'\" target=\"_blank\">Functional unit</a>\n </th>\n\n <ng-container *ngFor=\"let dataKey of dataKeys(); let dataKeyLast = last\">\n <th\n *ngFor=\"let node of data()[dataKey]; let nodeLast = last\"\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\n class=\"is-inline-block is-ml-2\"\n [term]=\"node.value.term\"></he-terms-units-description>\n </th>\n </ng-container>\n </tr>\n </thead>\n <tbody>\n <ng-container *ngFor=\"let cycle of cycles(); trackBy: trackById; let cycleIndex = index\">\n <tr>\n <td class=\"width-auto has-border-right\" [attr.title]=\"defaultLabel(cycle)\">\n <he-node-link [node]=\"cycle.term || cycle\">\n <span>{{ cycleIndex + 1 }}. {{ defaultLabel(cycle) }}</span>\n </he-node-link>\n </td>\n <td class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\">\n <he-cycles-functional-unit-measure [cycle]=\"cycles()[0]\"></he-cycles-functional-unit-measure>\n </td>\n\n <ng-container *ngFor=\"let dataKey of dataKeys(); let dataKeyLast = last\">\n <td\n class=\"is-nowrap\"\n *ngFor=\"let node of data()[dataKey]; let nodeLast = last\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n <span\n *ngIf=\"node.value.values[cycle['@id']]; else emptyValue\"\n class=\"trigger-popover\"\n [ngbPopover]=\"details\"\n [autoClose]=\"'outside'\"\n popoverClass=\"is-narrow\"\n triggers=\"manual\"\n #p=\"ngbPopover\"\n placement=\"left\"\n container=\"body\"\n (click)=\"\n togglePopover(p, { data: node.value.values[cycle['@id']], cycle: cycle, key: dataKey })\n \">\n <span pointer>\n {{\n propertyValue(node.value.values[cycle['@id']].value, node.value.term['@id'])\n | precision: 3\n | default: '-'\n }}\n </span>\n <he-blank-node-state\n class=\"ml-1\"\n [dataState]=\"_dataState()\"\n [node]=\"node.value.values[cycle['@id']].node\"\n key=\"value\"></he-blank-node-state>\n </span>\n </td>\n </ng-container>\n </tr>\n </ng-container>\n </tbody>\n </table>\n </he-data-table>\n\n <he-blank-node-state-notice [dataState]=\"_dataState()\"></he-blank-node-state-notice>\n </ng-container>\n </div>\n\n <ng-container *ngSwitchCase=\"View.chart\">\n <ng-container [ngSwitch]=\"firstNodeKey()\">\n <he-cycles-result *ngSwitchCase=\"BlankNodesKey.inputs\" [cycles]=\"cycles()\"></he-cycles-result>\n <he-cycles-emissions-chart\n *ngSwitchCase=\"BlankNodesKey.emissions\"\n [cycles]=\"cycles()\"></he-cycles-emissions-chart>\n </ng-container>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"View.timeline\">\n <ng-container *ngTemplateOutlet=\"selectCycle\"></ng-container>\n\n <div class=\"is-px-3 is-pb-3\">\n <he-cycles-nodes-timeline\n [recalculatedValues]=\"timelineValues()\"\n [dataState]=\"_dataState()\"></he-cycles-nodes-timeline>\n\n <he-blank-node-state-notice [dataState]=\"_dataState()\"></he-blank-node-state-notice>\n </div>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"View.logs\">\n <ng-container *ngTemplateOutlet=\"selectCycle\"></ng-container>\n\n <div class=\"tabs is-mb-2\" *ngIf=\"_nodeKeys().length > 1\">\n <ul>\n <li *ngFor=\"let nodeKey of _nodeKeys()\" [class.is-active]=\"selectedNodeKey() === nodeKey\">\n <a (click)=\"selectedNodeKey.set(nodeKey)\">{{ nodeKey | keyToLabel }}</a>\n </li>\n </ul>\n </div>\n\n <he-node-logs-models\n *ngIf=\"selectedNode()\"\n [node]=\"selectedNode()\"\n [nodeKey]=\"selectedNodeKey()\"\n [logsKey]=\"selectedLogsKey()\"\n [originalValues]=\"selectedOriginalValues()\"\n [recalculatedValues]=\"selectedRecalculatedValues()\"\n [filterTermTypes]=\"filterTermTypes()\"></he-node-logs-models>\n </ng-container>\n </ng-container>\n</ng-container>\n\n<he-node-csv-export-confirm\n *ngIf=\"showDownload\"\n [nodes]=\"cycles()\"\n [filename]=\"csvFilename()\"\n [isUpload]=\"false\"\n [headerKeys]=\"headerKeys()\"\n (closed)=\"showDownload = false\"></he-node-csv-export-confirm>\n\n<ng-template #emptyTable>\n <div class=\"is-pt-3 has-text-centered\">\n <span>No data available</span>\n <span class=\"is-pl-1\" [class.is-hidden]=\"!filterTerm()\">matching your search criteria</span>\n <span>.</span>\n <span *ngIf=\"showSwitchToRecalculated()\">\n Switch to\n <code>recalculated</code>\n version.\n </span>\n </div>\n</ng-template>\n\n<ng-template #emptyValue>\n <span>-</span>\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 [data]=\"data\"\n [dataState]=\"_dataState()\"\n [nodeType]=\"node['@type']\"\n [dataKey]=\"key\"></he-node-value-details>\n</ng-template>\n\n<ng-template #selectCycle>\n <div class=\"field has-addons is-py-2 is-px-3\" *ngIf=\"cycles().length > 1\">\n <div class=\"control\">\n <span class=\"button is-small is-static is-secondary\">Select a Cycle</span>\n </div>\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth is-secondary\">\n <select (change)=\"selectIndex($event)\">\n <option *ngFor=\"let value of cycles(); let cycleIndex = index\" [value]=\"cycleIndex\">\n {{ cycleIndex + 1 }}. {{ defaultLabel(value) }}\n </option>\n </select>\n </div>\n </div>\n </div>\n</ng-template>\n", styles: ["fa-icon{display:inline-block;width:10px}he-data-table ::ng-deep .table thead tr th:nth-child(2),he-data-table ::ng-deep .table tbody tr td:nth-child(2){max-width:102px;width:102px}\n"] }]
7652
+ }], ctorParameters: function () { return [{ type: HeNodeStoreService }]; }, propDecorators: { dataState: [{
7653
+ type: Input
7654
+ }], nodeKeys: [{
7655
+ type: Input
7656
+ }], nodeKeyGroup: [{
7657
+ type: Input
7658
+ }] } });
7659
+
7660
+ const components$6 = [
7661
+ CyclesCompletenessComponent,
7662
+ CyclesEmissionsChartComponent,
7663
+ CyclesFunctionalUnitMeasureComponent,
7664
+ CyclesNodesComponent,
7665
+ CyclesNodesTimelineComponent,
7666
+ CyclesResultComponent
7667
+ ];
7668
+ class HeCyclesModule {
7669
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: HeCyclesModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
7670
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.1.8", ngImport: i0, type: HeCyclesModule, declarations: [CyclesCompletenessComponent,
7671
+ CyclesEmissionsChartComponent,
7672
+ CyclesFunctionalUnitMeasureComponent,
7673
+ CyclesNodesComponent,
7674
+ CyclesNodesTimelineComponent,
7675
+ CyclesResultComponent], imports: [CommonModule, FormsModule, HeCommonModule, HeNodeModule, HeTermsModule], exports: [CyclesCompletenessComponent,
7676
+ CyclesEmissionsChartComponent,
7677
+ CyclesFunctionalUnitMeasureComponent,
7678
+ CyclesNodesComponent,
7679
+ CyclesNodesTimelineComponent,
7680
+ CyclesResultComponent] }); }
7681
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: HeCyclesModule, imports: [CommonModule, FormsModule, HeCommonModule, HeNodeModule, HeTermsModule] }); }
7682
+ }
7683
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: HeCyclesModule, decorators: [{
7684
+ type: NgModule,
7685
+ args: [{
7686
+ declarations: components$6,
7687
+ exports: components$6,
7688
+ imports: [CommonModule, FormsModule, HeCommonModule, HeNodeModule, HeTermsModule]
7689
+ }]
7690
+ }] });
7691
+
7692
+ class HeNodeCsvService {
7693
+ constructor(schemaService) {
7694
+ this.schemaService = schemaService;
7695
+ }
7696
+ async csvToJson(content) {
7697
+ return toJson(await this.schemaService.schemas(), content);
7698
+ }
7699
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: HeNodeCsvService, deps: [{ token: HeSchemaService }], target: i0.ɵɵFactoryTarget.Injectable }); }
7700
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: HeNodeCsvService, providedIn: 'root' }); }
7701
+ }
7702
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: HeNodeCsvService, decorators: [{
7703
+ type: Injectable,
7704
+ args: [{
7705
+ providedIn: 'root'
7706
+ }]
7707
+ }], ctorParameters: function () { return [{ type: HeSchemaService }]; } });
7708
+
7709
+ // TODO: remove fallback
7710
+ const MAX_STAGE = {
7711
+ [NodeType.Cycle]: 2,
7712
+ [NodeType.ImpactAssessment]: 1,
7713
+ [NodeType.Site]: 2
7714
+ };
7715
+ class EngineModelsStageComponent {
7716
+ set node(value) {
7717
+ this._node.set(value);
7718
+ }
7719
+ constructor(nodeService) {
7720
+ this.nodeService = nodeService;
7721
+ this._node = signal(null);
7722
+ this.defaultMaxStage = computed(() => MAX_STAGE[this._node()['@type']]);
7723
+ this.node$ = toObservable(this._node);
7724
+ this.headers = toSignal(this.node$.pipe(filter(node => !!node), mergeMap(node => this.nodeService.getWithHeaders$({
7725
+ ...node,
7726
+ dataState: DataState.recalculated
7727
+ })), map(({ headers }) => headers)));
7728
+ this.stage = computed(() => +this.headers()?.get('stage'));
7729
+ this.maxStage = computed(() => +this.headers()?.get('maxstage') || this.defaultMaxStage());
7730
+ this.inProgress = computed(() => this.stage() && this.stage() !== this.maxStage());
7731
+ }
7732
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: EngineModelsStageComponent, deps: [{ token: HeNodeService }], target: i0.ɵɵFactoryTarget.Component }); }
7733
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.8", type: EngineModelsStageComponent, selector: "he-engine-models-stage", inputs: { node: "node" }, ngImport: i0, template: "<ng-container *ngIf=\"inProgress()\">\n <span class=\"tag is-warning\">\n <span>Calculation in progress (stage {{ stage() }} out of {{ maxStage() }})</span>\n </span>\n</ng-container>\n", styles: [":host{display:inline-block}\n"], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
7734
+ }
7735
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: EngineModelsStageComponent, decorators: [{
7736
+ type: Component$1,
7737
+ args: [{ selector: 'he-engine-models-stage', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"inProgress()\">\n <span class=\"tag is-warning\">\n <span>Calculation in progress (stage {{ stage() }} out of {{ maxStage() }})</span>\n </span>\n</ng-container>\n", styles: [":host{display:inline-block}\n"] }]
7738
+ }], ctorParameters: function () { return [{ type: HeNodeService }]; }, propDecorators: { node: [{
7739
+ type: Input
7740
+ }] } });
7741
+
7742
+ class EngineModelsVersionLinkComponent {
7743
+ constructor(service) {
7744
+ this.service = service;
7745
+ this.showDetails = false;
7746
+ }
7747
+ get version() {
7748
+ return nodeVersion(this.node);
7749
+ }
7750
+ get url() {
7751
+ return [engineGitBaseUrl(), '-', 'tree', `v${this.version}`].filter(Boolean).join('/');
7752
+ }
7753
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: EngineModelsVersionLinkComponent, deps: [{ token: HeEngineService }], target: i0.ɵɵFactoryTarget.Component }); }
7754
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.8", type: EngineModelsVersionLinkComponent, selector: "he-engine-models-version-link", inputs: { node: "node", showDetails: "showDetails" }, ngImport: i0, template: "<ng-container *ngIf=\"version\">\n <div class=\"tags has-addons\" *ngIf=\"service.latestVersion$ | async as latestVersion\">\n <ng-container *bindOnce=\"url\">\n <a class=\"tag is-info\" [href]=\"url\" target=\"_blank\" (click)=\"$event.stopPropagation()\">\n {{ version }}\n <fa-icon class=\"ml-2\" icon=\"external-link-alt\" size=\"sm\"></fa-icon>\n </a>\n </ng-container>\n <ng-container *ngIf=\"showDetails\">\n <ng-container *ngIf=\"latestVersion === version; else outdated\">\n <ng-container *ngTemplateOutlet=\"latest\"></ng-container>\n </ng-container>\n </ng-container>\n </div>\n</ng-container>\n\n<ng-template #latest>\n <span class=\"tag is-success\">latest recalculations</span>\n</ng-template>\n\n<ng-template #outdated>\n <span class=\"tag is-warning\">outdated recalculations</span>\n</ng-template>\n", styles: [":host{display:inline-block}a{color:inherit}\n"], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i3.FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "spin", "pulse", "mask", "styles", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "classes", "transform", "a11yRole"] }, { kind: "directive", type: BindOnceDirective, selector: "[bindOnce]", inputs: ["bindOnce"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
7755
+ }
7756
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: EngineModelsVersionLinkComponent, decorators: [{
7757
+ type: Component$1,
7758
+ args: [{ selector: 'he-engine-models-version-link', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"version\">\n <div class=\"tags has-addons\" *ngIf=\"service.latestVersion$ | async as latestVersion\">\n <ng-container *bindOnce=\"url\">\n <a class=\"tag is-info\" [href]=\"url\" target=\"_blank\" (click)=\"$event.stopPropagation()\">\n {{ version }}\n <fa-icon class=\"ml-2\" icon=\"external-link-alt\" size=\"sm\"></fa-icon>\n </a>\n </ng-container>\n <ng-container *ngIf=\"showDetails\">\n <ng-container *ngIf=\"latestVersion === version; else outdated\">\n <ng-container *ngTemplateOutlet=\"latest\"></ng-container>\n </ng-container>\n </ng-container>\n </div>\n</ng-container>\n\n<ng-template #latest>\n <span class=\"tag is-success\">latest recalculations</span>\n</ng-template>\n\n<ng-template #outdated>\n <span class=\"tag is-warning\">outdated recalculations</span>\n</ng-template>\n", styles: [":host{display:inline-block}a{color:inherit}\n"] }]
7759
+ }], ctorParameters: function () { return [{ type: HeEngineService }]; }, propDecorators: { node: [{
7760
+ type: Input
7761
+ }], showDetails: [{
7762
+ type: Input
7763
+ }] } });
7764
+
7765
+ const gitUrl = `${gitHome}/${Repository.orchestrator}/-/blob/${gitBranch()}`;
7766
+ const generalDocsUrl = `${gitUrl}/hestia_earth/orchestrator/config/README.md`;
7767
+ const strategiesDocs = `${gitUrl}/hestia_earth/orchestrator/strategies`;
7768
+ const schemaTypeKeys = Object.keys(SchemaType);
7769
+ const toSchemaType = (value) => keyToLabel(value).replace(/\s/g, '');
7770
+ const isSchemaType = (value) => [
7771
+ schemaTypeKeys.includes(value),
7772
+ schemaTypeKeys.includes(pluralize(value, 1)),
7773
+ schemaTypeKeys.includes(pluralize(toSchemaType(value), 1)),
7774
+ ['emissionsResourceUse', 'impacts', 'endpoints'].includes(value)
7775
+ ].some(Boolean);
7776
+ const isGapFilled = ({ runStrategy, mergeStrategy, mergeArgs }) => ['add_blank_node_if_missing', 'add_key_if_missing'].includes(runStrategy) &&
7777
+ (mergeStrategy !== 'list' || !mergeArgs?.replaceThreshold);
7778
+ const isRecalculated = ({ runStrategy, mergeStrategy, mergeArgs }) => ['add_blank_node_if_missing', 'add_key_if_missing'].includes(runStrategy) &&
7779
+ mergeStrategy === 'list' &&
7780
+ mergeArgs?.replaceThreshold;
7781
+ const filterGapFilled = (configs, onlyGapFilled) => configs
7782
+ .map(model => (Array.isArray(model) && onlyGapFilled ? model.filter(isGapFilled) : model))
7783
+ .filter(model => !onlyGapFilled || Array.isArray(model) || isGapFilled(model));
7784
+ const modelMatch = (term) => ({ key, model, value }) => [key, model, value].filter(Boolean).some(v => v.toLowerCase().includes(term.toLowerCase()));
7785
+ const filterModels = (configs, term = '') => configs
7786
+ .map(model => (Array.isArray(model) && !!term ? model.filter(modelMatch(term)) : model))
7787
+ .filter(model => !term || Array.isArray(model) || modelMatch(term)(model));
7788
+ const modelKeyName = (modelKey) => (modelKey.includes('.') ? modelKey.split('.')[1] : modelKey);
7789
+ const groupConfig = (configs) => from(configs.flat())
7790
+ .pipe(filter(({ key }) => isSchemaType(key)), groupBy(({ key }) => key), mergeMap(group => group.pipe(toArray())), reduce((prev, curr) => {
7791
+ const key = curr[0].key;
7792
+ prev[toSchemaType(key)] = curr;
7793
+ return prev;
7794
+ }, {}))
7795
+ .toPromise();
7796
+ class EngineOrchestratorEditComponent {
7797
+ constructor(hestiaEngineService, searchService) {
7798
+ this.hestiaEngineService = hestiaEngineService;
7799
+ this.searchService = searchService;
7800
+ this.modelKeyName = modelKeyName;
7801
+ this.isArray = Array.isArray;
7802
+ this.generalDocsUrl = generalDocsUrl;
7803
+ this.strategiesDocs = strategiesDocs;
7804
+ this.termsById = {};
7805
+ this.showConfig = false;
7806
+ this.search = '';
7807
+ this.onlyGapFilled = false;
7808
+ this.showAdvanced = false;
7809
+ this.displayBy = 'list';
7810
+ this.showDisplayBy = false;
7811
+ }
7812
+ ngOnChanges(changes) {
7813
+ if (changes.config?.currentValue) {
7814
+ this.allModels = this.config.models;
7815
+ this.computeTermsById();
7816
+ return this.filterModels();
7817
+ }
7818
+ if ('nodeType' in changes) {
7819
+ return this.loadDefaultConfig();
7820
+ }
7821
+ }
7822
+ async loadDefaultConfig() {
7823
+ const { models } = await this.hestiaEngineService.ochestratorConfig(this.nodeType);
7824
+ this.allModels = models;
7825
+ this.computeTermsById();
7826
+ return this.filterModels();
7827
+ }
7828
+ async computeTermsById() {
7829
+ const ids = unique(this.allModels
7830
+ .flat()
7831
+ .flatMap(model => [model.model, model.value])
7832
+ .filter(Boolean));
7833
+ const { results } = await this.searchService.search({
7834
+ fields: ['@type', '@id', 'name', 'units'],
7835
+ limit: ids.length,
7836
+ query: {
7837
+ bool: {
7838
+ must: [matchType(NodeType.Term)],
7839
+ should: ids.map(matchId),
7840
+ minimum_should_match: 1
7841
+ }
7842
+ }
7843
+ });
7844
+ this.termsById = results.reduce((p, c) => ({ ...p, [c['@id']]: c }), {});
7905
7845
  }
7906
- groupNodesByKey({ nodeKey }) {
7907
- const nodesPerCycle = groupNodesByTerm(this.cycles(), nodeKey, this.originalValues(), filterBlankNode$1(this.filterTerm()));
7908
- return orderBy(grouppedKeys(nodesPerCycle), ['key'], ['asc']);
7846
+ trackByKey(_index, { key }) {
7847
+ return key;
7909
7848
  }
7910
- groupEmissions() {
7911
- const emissionsPerCycle = groupNodesByTerm(this.cycles(), BlankNodesKey.emissions, this.originalValues(), filterBlankNode$1(this.filterTerm()));
7912
- const values = orderBy(grouppedKeys(emissionsPerCycle), ['key'], ['asc']);
7913
- const methodTiers = orderBy(unique(values.map(({ value }) => value.methodTier)).map(methodTier => ({
7914
- methodTier,
7915
- methodTierOrder: methodTierOrder(methodTier)
7916
- })), ['methodTierOrder'], ['asc']);
7917
- return Object.fromEntries(methodTiers.map(({ methodTier }) => [methodTier, values.filter(({ value }) => value.methodTier === methodTier)]));
7849
+ modelLink$({ model, value }) {
7850
+ return this.hestiaEngineService.model$({ model, term: value });
7918
7851
  }
7919
- trackById(_index, item) {
7920
- return item['@id'];
7852
+ modelPathLink$({ model, value }) {
7853
+ return this.hestiaEngineService.model$({
7854
+ path: `${engineGitUrl()}/hestia_earth/models/${model}/${(value || '').replace('.', '/')}.py`
7855
+ });
7921
7856
  }
7922
- togglePopover(popover, context) {
7923
- return popover.isOpen() ? popover.close() : popover.open(context);
7857
+ get configUrl() {
7858
+ return this.hestiaEngineService.orchestratorConfigUrl(this.nodeType);
7924
7859
  }
7925
- filterByTerm(term) {
7926
- this.filterTerm.set(term);
7860
+ modelKeyUrl({ modelKey }, model) {
7861
+ const parts = modelKey.split('.');
7862
+ const schemaType = parts.length === 2 ? parts[0] : model;
7863
+ const url = [baseUrl(), 'schema', toSchemaType(schemaType)].filter(Boolean).join('/');
7864
+ return isSchemaType(schemaType) ? `${url}#${parts.pop()}` : null;
7927
7865
  }
7928
- selectIndex({ target: { value } }) {
7929
- this.selectedIndex.set(+value);
7866
+ filterModels() {
7867
+ setTimeout(async () => {
7868
+ const models = filterModels(filterGapFilled(this.allModels, this.onlyGapFilled), this.search);
7869
+ this.models = models;
7870
+ this.groupedModels = await groupConfig(models);
7871
+ this.selectedGroupedKey = Object.keys(this.groupedModels)?.[0];
7872
+ });
7930
7873
  }
7931
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: CyclesNodesComponent, deps: [{ token: HeNodeStoreService }], target: i0.ɵɵFactoryTarget.Component }); }
7932
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.8", type: CyclesNodesComponent, selector: "he-cycles-nodes", inputs: { dataState: "dataState", nodeKeys: "nodeKeys", nodeKeyGroup: "nodeKeyGroup" }, ngImport: i0, template: "<div class=\"tabs is-mb-1\" *ngIf=\"isGroupNode()\">\n <ul>\n <li *ngFor=\"let term of groupNodeTerms()\" [class.is-active]=\"selectedGroupTerm() === term\">\n <a (click)=\"selectedGroupTerm.set(term)\">{{ term.name }}</a>\n </li>\n </ul>\n</div>\n\n<div class=\"columns is-variable is-align-items-center is-2 is-m-0\" *ngIf=\"hasData()\">\n <div class=\"column\">\n <ng-container *ngIf=\"selectedView() === View.table\">\n <button\n class=\"button is-small is-ghost\"\n (click)=\"showDownload = true\"\n ngbTooltip=\"Download as CSV\"\n placement=\"bottom\">\n <fa-icon icon=\"download\" size=\"lg\"></fa-icon>\n </button>\n </ng-container>\n </div>\n <div class=\"column is-narrow\" *ngIf=\"selectedView() === View.table\">\n <he-search-extend\n class=\"is-secondary is-small\"\n placeholder=\"Filter terms by name\"\n (search)=\"filterByTerm($event)\"></he-search-extend>\n </div>\n <div class=\"column is-narrow\" *ngIf=\"views()?.length > 1\">\n <div class=\"field has-addons\">\n <div class=\"control\" *ngFor=\"let view of views()\">\n <button class=\"button is-small\" [class.is-selected]=\"selectedView() === view\" (click)=\"selectedView.set(view)\">\n <span class=\"icon is-small\">\n <fa-icon [icon]=\"viewIcon[view]\" aria-hidden=\"true\"></fa-icon>\n </span>\n <span class=\"is-hidden-mobile\">{{ view }}</span>\n </button>\n </div>\n </div>\n </div>\n</div>\n\n<ng-container *ngIf=\"isNodeKeyAllowed()\">\n <ng-container [ngSwitch]=\"selectedView()\">\n <div class=\"is-px-3 is-pb-3\" *ngSwitchCase=\"View.table\">\n <ng-container *ngIf=\"hasData(); else emptyTable\">\n <he-data-table class=\"mb-1 is-small\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n <tr class=\"has-text-weight-bold\" *ngIf=\"dataKeys().length > 1\">\n <th class=\"width-auto\"></th>\n <th [class.is-hidden]=\"isGroupNode()\"></th>\n\n <ng-container *ngFor=\"let dataKey of dataKeys(); let dataKeyLast = last\">\n <ng-container *ngIf=\"data()[dataKey]?.length\">\n <th [attr.colspan]=\"data()[dataKey].length\" [class.has-border-right]=\"!dataKeyLast\">\n <span>{{ dataKey | keyToLabel }}</span>\n </th>\n </ng-container>\n </ng-container>\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\n <ng-container *ngFor=\"let dataKey of dataKeys(); let dataKeyLast = last\">\n <th\n *ngFor=\"let node of data()[dataKey]; let nodeLast = last\"\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 [innerHtml]=\"node.value.term.name | ellipsis: 30 | compound\"></span>\n </he-node-link>\n </th>\n </ng-container>\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]=\"baseUrl + '/schema/Cycle#functionalUnit'\" target=\"_blank\">Functional unit</a>\n </th>\n\n <ng-container *ngFor=\"let dataKey of dataKeys(); let dataKeyLast = last\">\n <th\n *ngFor=\"let node of data()[dataKey]; let nodeLast = last\"\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\n class=\"is-inline-block is-ml-2\"\n [term]=\"node.value.term\"></he-terms-units-description>\n </th>\n </ng-container>\n </tr>\n </thead>\n <tbody>\n <ng-container *ngFor=\"let cycle of cycles(); trackBy: trackById; let cycleIndex = index\">\n <tr>\n <td class=\"width-auto has-border-right\" [attr.title]=\"defaultLabel(cycle)\">\n <he-node-link [node]=\"cycle.term || cycle\">\n <span>{{ cycleIndex + 1 }}. {{ defaultLabel(cycle) }}</span>\n </he-node-link>\n </td>\n <td class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\">\n <he-cycles-functional-unit-measure [cycle]=\"cycles()[0]\"></he-cycles-functional-unit-measure>\n </td>\n\n <ng-container *ngFor=\"let dataKey of dataKeys(); let dataKeyLast = last\">\n <td\n class=\"is-nowrap\"\n *ngFor=\"let node of data()[dataKey]; let nodeLast = last\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n <span\n *ngIf=\"node.value.values[cycle['@id']]; else emptyValue\"\n class=\"trigger-popover\"\n [ngbPopover]=\"details\"\n [autoClose]=\"'outside'\"\n popoverClass=\"is-narrow\"\n triggers=\"manual\"\n #p=\"ngbPopover\"\n placement=\"left\"\n container=\"body\"\n (click)=\"\n togglePopover(p, { data: node.value.values[cycle['@id']], cycle: cycle, key: dataKey })\n \">\n <span pointer>\n {{\n propertyValue(node.value.values[cycle['@id']].value, node.value.term['@id'])\n | precision: 3\n | default: '-'\n }}\n </span>\n <he-blank-node-state\n class=\"ml-1\"\n [dataState]=\"_dataState()\"\n [node]=\"node.value.values[cycle['@id']].node\"\n key=\"value\"></he-blank-node-state>\n </span>\n </td>\n </ng-container>\n </tr>\n </ng-container>\n </tbody>\n </table>\n </he-data-table>\n\n <he-blank-node-state-notice [dataState]=\"_dataState()\"></he-blank-node-state-notice>\n </ng-container>\n </div>\n\n <ng-container *ngSwitchCase=\"View.chart\">\n <ng-container [ngSwitch]=\"firstNodeKey()\">\n <he-cycles-result *ngSwitchCase=\"BlankNodesKey.inputs\" [cycles]=\"cycles()\"></he-cycles-result>\n <he-cycles-emissions-chart\n *ngSwitchCase=\"BlankNodesKey.emissions\"\n [cycles]=\"cycles()\"></he-cycles-emissions-chart>\n </ng-container>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"View.timeline\">\n <ng-container *ngTemplateOutlet=\"selectCycle\"></ng-container>\n\n <div class=\"is-px-3 is-pb-3\">\n <he-cycles-nodes-timeline\n [recalculatedValues]=\"timelineValues()\"\n [dataState]=\"_dataState()\"></he-cycles-nodes-timeline>\n\n <he-blank-node-state-notice [dataState]=\"_dataState()\"></he-blank-node-state-notice>\n </div>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"View.logs\">\n <ng-container *ngTemplateOutlet=\"selectCycle\"></ng-container>\n\n <div class=\"tabs is-mb-2\" *ngIf=\"_nodeKeys().length > 1\">\n <ul>\n <li *ngFor=\"let nodeKey of _nodeKeys()\" [class.is-active]=\"selectedNodeKey() === nodeKey\">\n <a (click)=\"selectedNodeKey.set(nodeKey)\">{{ nodeKey | keyToLabel }}</a>\n </li>\n </ul>\n </div>\n\n <he-node-logs-models\n *ngIf=\"selectedNode()\"\n [node]=\"selectedNode()\"\n [nodeKey]=\"selectedNodeKey()\"\n [logsKey]=\"selectedLogsKey()\"\n [originalValues]=\"selectedOriginalValues()\"\n [recalculatedValues]=\"selectedRecalculatedValues()\"\n [filterTermTypes]=\"filterTermTypes()\"></he-node-logs-models>\n </ng-container>\n </ng-container>\n</ng-container>\n\n<he-node-csv-export-confirm\n *ngIf=\"showDownload\"\n [nodes]=\"cycles()\"\n [filename]=\"csvFilename()\"\n [isUpload]=\"false\"\n [headerKeys]=\"headerKeys()\"\n (closed)=\"showDownload = false\"></he-node-csv-export-confirm>\n\n<ng-template #emptyTable>\n <div class=\"is-pt-3 has-text-centered\">\n <span>No data available</span>\n <span class=\"is-pl-1\" [class.is-hidden]=\"!filterTerm()\">matching your search criteria</span>\n <span>.</span>\n <span *ngIf=\"showSwitchToRecalculated()\">\n Switch to\n <code>recalculated</code>\n version.\n </span>\n </div>\n</ng-template>\n\n<ng-template #emptyValue>\n <span>-</span>\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 [data]=\"data\"\n [dataState]=\"_dataState()\"\n [nodeType]=\"node['@type']\"\n [dataKey]=\"key\"></he-node-value-details>\n</ng-template>\n\n<ng-template #selectCycle>\n <div class=\"field has-addons is-py-2 is-px-3\" *ngIf=\"cycles().length > 1\">\n <div class=\"control\">\n <span class=\"button is-small is-static is-secondary\">Select a Cycle</span>\n </div>\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth is-secondary\">\n <select (change)=\"selectIndex($event)\">\n <option *ngFor=\"let value of cycles(); let cycleIndex = index\" [value]=\"cycleIndex\">\n {{ cycleIndex + 1 }}. {{ defaultLabel(value) }}\n </option>\n </select>\n </div>\n </div>\n </div>\n</ng-template>\n", styles: ["fa-icon{display:inline-block;width:10px}he-data-table ::ng-deep .table thead tr th:nth-child(2),he-data-table ::ng-deep .table tbody tr td:nth-child(2){max-width:102px;width:102px}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1$1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1$1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i2$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i4$1.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: i4$1.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: i3.FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "spin", "pulse", "mask", "styles", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "classes", "transform", "a11yRole"] }, { 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", "showAggregated", "showDeleted"] }, { kind: "component", type: DataTableComponent, selector: "he-data-table", inputs: ["minHeight", "maxHeight", "small"] }, { kind: "component", type: SearchExtendComponent, selector: "he-search-extend", inputs: ["value", "disabled", "placeholder", "class"], outputs: ["search"] }, { kind: "component", type: NodeLinkComponent, selector: "he-node-link", inputs: ["node", "showExternalLink", "linkClass"] }, { kind: "component", type: NodeCsvExportConfirmComponent, selector: "he-node-csv-export-confirm", inputs: ["nodes", "filename", "headerKeys", "extension", "isUpload"], outputs: ["closed"] }, { kind: "component", type: NodeLogsModelsComponent, selector: "he-node-logs-models", inputs: ["node", "nodeKey", "originalValues", "recalculatedValues", "terms", "filterTermTypes", "filterTermTypesLabel", "logsKey", "noDataMessage"] }, { kind: "component", type: NodeValueDetailsComponent, selector: "he-node-value-details", inputs: ["data", "nodeType", "dataKey", "dataState"] }, { kind: "component", type: TermsUnitsDescriptionComponent, selector: "he-terms-units-description", inputs: ["term", "iconTemplate"] }, { kind: "component", type: CyclesEmissionsChartComponent, selector: "he-cycles-emissions-chart", inputs: ["cycles"] }, { kind: "component", type: CyclesFunctionalUnitMeasureComponent, selector: "he-cycles-functional-unit-measure", inputs: ["cycle"] }, { kind: "component", type: CyclesNodesTimelineComponent, selector: "he-cycles-nodes-timeline", inputs: ["recalculatedValues", "dataState"] }, { kind: "component", type: CyclesResultComponent, selector: "he-cycles-result", inputs: ["cycles"] }, { 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" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
7874
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: EngineOrchestratorEditComponent, deps: [{ token: HeEngineService }, { token: HeSearchService }], target: i0.ɵɵFactoryTarget.Component }); }
7875
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.8", type: EngineOrchestratorEditComponent, selector: "he-engine-orchestrator-edit", inputs: { config: "config", nodeType: "nodeType" }, usesOnChanges: true, ngImport: i0, template: "<p>\n <i>\n The configuration below is a preview of the\n <a [href]=\"configUrl\" target=\"_blank\">JSON configuration file</a>\n used for the orchestration of the Hestia's calculations.\n </i>\n</p>\n<p>\n <i>Note: not all models might be represented accurately.</i>\n</p>\n\n<div class=\"is-size-7 is-italic\">\n <div class=\"columns is-mobile is-multiline is-vcentered is-variable is-1 my-0\">\n <div class=\"column\">\n <div class=\"pl-3 model-parallel my-3\">\n <span>Models running in parallel</span>\n </div>\n </div>\n\n <div class=\"column is-narrow has-text-right\">\n <div\n class=\"dropdown is-right has-text-left is-dropdown-filters\"\n [class.is-active]=\"showConfig\"\n (clickOutside)=\"showConfig = false\">\n <div class=\"dropdown-trigger\" (click)=\"showConfig = !showConfig\">\n <button\n class=\"button is-ghost\"\n [class.is-active]=\"showConfig\"\n aria-haspopup=\"true\"\n aria-controls=\"option-menu\"\n ngbTooltip=\"Filters\"\n placement=\"bottom\"\n container=\"body\"\n [disableTooltip]=\"showConfig\">\n <span class=\"icon is-small\">\n <fa-icon icon=\"cog\" aria-hidden=\"true\"></fa-icon>\n </span>\n </button>\n </div>\n <div class=\"dropdown-menu\" id=\"option-menu\" role=\"menu\">\n <div class=\"dropdown-content\">\n <div class=\"dropdown-item\">\n <div class=\"field\">\n <div class=\"control is-expanded has-icons-right\">\n <input\n type=\"text\"\n class=\"input search-input is-secondary is-small\"\n [(ngModel)]=\"search\"\n name=\"collection\"\n placeholder=\"Filter by key, name or model\"\n (input)=\"filterModels()\" />\n <a class=\"icon is-small is-right\" (click)=\"search = ''; filterModels()\">\n <fa-icon icon=\"times\"></fa-icon>\n </a>\n </div>\n </div>\n\n <div class=\"field is-relative\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded is-secondary\"\n [(ngModel)]=\"showAdvanced\"\n id=\"showAdvanced\"\n (change)=\"filterModels()\" />\n <label class=\"is-size-7\" for=\"showAdvanced\">\n <span>Show advanced data</span>\n </label>\n </div>\n\n <div class=\"field is-relative\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded is-secondary\"\n [(ngModel)]=\"onlyGapFilled\"\n id=\"onlyGapFilled\"\n (change)=\"filterModels()\" />\n <label class=\"is-size-7\" for=\"onlyGapFilled\">\n <span>Show only gap-filled data</span>\n </label>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"column is-narrow has-text-right\">\n <div\n class=\"dropdown is-right has-text-left\"\n [class.is-active]=\"showDisplayBy\"\n (clickOutside)=\"showDisplayBy = false\">\n <div class=\"dropdown-trigger\" (click)=\"showDisplayBy = !showDisplayBy\">\n <button\n class=\"button is-ghost\"\n aria-haspopup=\"true\"\n aria-controls=\"display-menu\"\n ngbTooltip=\"Display options\"\n placement=\"bottom\"\n container=\"body\"\n [disableTooltip]=\"showDisplayBy\">\n <ng-container [ngSwitch]=\"displayBy\">\n <ng-container *ngSwitchCase=\"'list'\">\n <span class=\"icon is-small\">\n <fa-icon icon=\"list\" aria-hidden=\"true\"></fa-icon>\n </span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'type'\">\n <span class=\"icon is-small\">\n <fa-icon icon=\"table\" aria-hidden=\"true\"></fa-icon>\n </span>\n </ng-container>\n </ng-container>\n </button>\n </div>\n <div class=\"dropdown-menu\" id=\"display-menu\" role=\"menu\">\n <div class=\"dropdown-content\" (click)=\"showDisplayBy = false\">\n <a class=\"dropdown-item\" [class.is-selected]=\"displayBy === 'list'\" (click)=\"displayBy = 'list'\">\n <fa-icon icon=\"list\" aria-hidden=\"true\"></fa-icon>\n <span class=\"pl-2\">Display by Priority</span>\n </a>\n <a class=\"dropdown-item\" [class.is-selected]=\"displayBy === 'type'\" (click)=\"displayBy = 'type'\">\n <fa-icon icon=\"table\" aria-hidden=\"true\"></fa-icon>\n <span class=\"pl-2\">Display by Type</span>\n </a>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n\n<ng-container *ngIf=\"displayBy === 'list' && models\">\n <div class=\"pl-3\">\n <ng-container *ngTemplateOutlet=\"modelList; context: { $implicit: models }\"></ng-container>\n </div>\n</ng-container>\n\n<ng-container *ngIf=\"displayBy === 'type' && groupedModels\">\n <div class=\"tabs\">\n <ul>\n <li\n *ngFor=\"let group of groupedModels | keys; trackBy: trackByKey\"\n [class.is-active]=\"selectedGroupedKey === group.key\">\n <a (click)=\"selectedGroupedKey = group.key\">\n <span class=\"pl-2\">{{ group.key }} ({{ group.value.length }})</span>\n </a>\n </li>\n </ul>\n </div>\n\n <div class=\"pl-3\">\n <ng-container\n *ngTemplateOutlet=\"modelList; context: { $implicit: groupedModels[selectedGroupedKey] }\"></ng-container>\n </div>\n</ng-container>\n\n<ng-template #termLink let-value>\n <ng-template #defaultLabel>\n <span>{{ value | keyToLabel }}</span>\n </ng-template>\n\n <ng-container *ngIf=\"termsById[value]; else defaultLabel\">\n <he-node-link [node]=\"termsById[value]\" [showExternalLink]=\"true\">\n <span>{{ termsById[value].name }}</span>\n </he-node-link>\n </ng-container>\n</ng-template>\n\n<ng-template #modelList let-data>\n <div *ngFor=\"let v of data\">\n <ng-container *ngTemplateOutlet=\"model; context: { $implicit: v }\"></ng-container>\n </div>\n</ng-template>\n\n<ng-template #model let-data>\n <ng-container *ngIf=\"isArray(data) && data.length\">\n <div class=\"pl-3 model-parallel\">\n <ng-container *ngTemplateOutlet=\"modelList; context: { $implicit: data }\"></ng-container>\n </div>\n\n <hr />\n </ng-container>\n <ng-container *ngIf=\"!isArray(data)\">\n <div class=\"card mb-2 model-serie is-size-6\">\n <div class=\"card-content p-3\">\n <span class=\"is-capitalized\">{{ data.key | keyToLabel }}</span>\n :\n <ng-template #defaultView>\n <span class=\"default-value\">{{ data.value }}</span>\n\n <p>\n <span class=\"pr-1\">Model:</span>\n <span class=\"pr-2\">\n <ng-container *ngTemplateOutlet=\"termLink; context: { $implicit: data.model }\"></ng-container>\n </span>\n </p>\n </ng-template>\n\n <ng-template #modelFromPathLink>\n <ng-container *ngIf=\"modelPathLink$(data) | async as link; else defaultView\">\n <ng-container\n *ngTemplateOutlet=\"modelPathLink; context: { model: data.model, value: data.value, link }\"></ng-container>\n </ng-container>\n </ng-template>\n\n <ng-container *ngIf=\"modelLink$(data) | async as link; else modelFromPathLink\">\n <ng-container\n *ngTemplateOutlet=\"modelLink; context: { model: data.model, value: data.value, link }\"></ng-container>\n </ng-container>\n\n <div *ngIf=\"showAdvanced\">\n <div *ngIf=\"data.runStrategy\">\n <span class=\"pr-1\">Run strategy:</span>\n <ng-container\n *ngTemplateOutlet=\"strategiesLink; context: { strategy: data.runStrategy, type: 'run' }\"></ng-container>\n\n <div class=\"pl-3 is-size-7\" *ngIf=\"data.runArgs\">\n <p><b>Run arguments:</b></p>\n <ng-container *ngTemplateOutlet=\"strategiesArgs; context: { $implicit: data.runArgs }\"></ng-container>\n </div>\n </div>\n <div *ngIf=\"data.mergeStrategy\">\n <span class=\"pr-1\">Merge strategy:</span>\n <ng-container\n *ngTemplateOutlet=\"\n strategiesLink;\n context: { strategy: data.mergeStrategy, type: 'merge' }\n \"></ng-container>\n\n <div class=\"pl-3 is-size-7\" *ngIf=\"data.mergeArgs\">\n <p><b>Merge arguments:</b></p>\n <ng-container *ngTemplateOutlet=\"strategiesArgs; context: { $implicit: data.mergeArgs }\"></ng-container>\n </div>\n </div>\n </div>\n </div>\n </div>\n </ng-container>\n</ng-template>\n\n<ng-template #modelLinkKey let-model=\"model\" let-link=\"link\">\n <a [href]=\"modelKeyUrl(link, model)\" target=\"_blank\">{{ modelKeyName(link.modelKey) }}</a>\n</ng-template>\n\n<ng-template #modelLink let-model=\"model\" let-link=\"link\" let-value=\"value\">\n <ng-container *ngIf=\"link.term\">\n <ng-container *ngTemplateOutlet=\"termLink; context: { $implicit: link.term }\"></ng-container>\n </ng-container>\n\n <span *ngIf=\"!link.term && !link?.modelKey\" class=\"default-value\">{{ value }}</span>\n\n <ng-container *ngIf=\"!link.term && link?.modelKey\">\n <ng-container *ngTemplateOutlet=\"modelLinkKey; context: { link, model }\"></ng-container>\n </ng-container>\n\n <p class=\"model-link\">\n <span class=\"pr-1\">Model:</span>\n <span class=\"pr-2\">\n <ng-container *ngTemplateOutlet=\"termLink; context: { $implicit: model }\"></ng-container>\n </span>\n\n <a class=\"is-size-7\" [href]=\"link.docPath\" target=\"_blank\">\n <span class=\"pr-1\">(View Docs)</span>\n <fa-icon icon=\"external-link-alt\"></fa-icon>\n </a>\n </p>\n</ng-template>\n\n<ng-template #modelPathLink let-model=\"model\" let-link=\"link\" let-value=\"value\">\n <span *ngIf=\"!link?.modelKey\" class=\"default-value\">{{ value }}</span>\n\n <ng-container *ngIf=\"link?.modelKey\">\n <ng-container *ngTemplateOutlet=\"modelLinkKey; context: { link, model }\"></ng-container>\n </ng-container>\n\n <p class=\"model-path-link\">\n <span class=\"pr-1\">Model:</span>\n <span class=\"pr-2\">\n <ng-container *ngTemplateOutlet=\"termLink; context: { $implicit: model }\"></ng-container>\n </span>\n\n <a class=\"is-size-7\" [href]=\"link.docPath\" target=\"_blank\">\n <span class=\"pr-1\">(View Docs)</span>\n <fa-icon icon=\"external-link-alt\"></fa-icon>\n </a>\n </p>\n</ng-template>\n\n<ng-template #strategiesLink let-strategy=\"strategy\" let-type=\"type\">\n <span class=\"pr-2 is-inline-block\">\n <code>{{ strategy }}</code>\n </span>\n\n <a\n class=\"is-size-7\"\n [href]=\"strategiesDocs + '/' + type + '/' + (type === 'merge' ? 'merge_' : '') + strategy + '.md'\"\n target=\"_blank\">\n <span class=\"pr-1\">(View Docs)</span>\n <fa-icon icon=\"external-link-alt\"></fa-icon>\n </a>\n</ng-template>\n\n<ng-template #strategiesArgs let-args>\n <div class=\"pl-2\">\n <p *ngFor=\"let arg of args | keys\">\n <span class=\"has-text-underline\">{{ arg.key }}</span>\n :\n <code>{{ arg.value | json }}</code>\n </p>\n </div>\n</ng-template>\n", styles: [":host{display:block}.model-parallel{border-left:3px solid #4a4a4a}.dropdown.is-dropdown-filters .dropdown-content{min-width:250px}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1$1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1$1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i2$1.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: i2$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i4$1.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: i3.FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "spin", "pulse", "mask", "styles", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "classes", "transform", "a11yRole"] }, { kind: "directive", type: ClickOutsideDirective, selector: "[clickOutside]", inputs: ["clickOutsideListenAfter"], outputs: ["clickOutside"] }, { kind: "component", type: NodeLinkComponent, selector: "he-node-link", inputs: ["node", "showExternalLink", "linkClass"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }, { kind: "pipe", type: KeysPipe, name: "keys" }, { kind: "pipe", type: KeyToLabelPipe, name: "keyToLabel" }] }); }
7933
7876
  }
7934
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: CyclesNodesComponent, decorators: [{
7877
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: EngineOrchestratorEditComponent, decorators: [{
7935
7878
  type: Component$1,
7936
- args: [{ selector: 'he-cycles-nodes', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"tabs is-mb-1\" *ngIf=\"isGroupNode()\">\n <ul>\n <li *ngFor=\"let term of groupNodeTerms()\" [class.is-active]=\"selectedGroupTerm() === term\">\n <a (click)=\"selectedGroupTerm.set(term)\">{{ term.name }}</a>\n </li>\n </ul>\n</div>\n\n<div class=\"columns is-variable is-align-items-center is-2 is-m-0\" *ngIf=\"hasData()\">\n <div class=\"column\">\n <ng-container *ngIf=\"selectedView() === View.table\">\n <button\n class=\"button is-small is-ghost\"\n (click)=\"showDownload = true\"\n ngbTooltip=\"Download as CSV\"\n placement=\"bottom\">\n <fa-icon icon=\"download\" size=\"lg\"></fa-icon>\n </button>\n </ng-container>\n </div>\n <div class=\"column is-narrow\" *ngIf=\"selectedView() === View.table\">\n <he-search-extend\n class=\"is-secondary is-small\"\n placeholder=\"Filter terms by name\"\n (search)=\"filterByTerm($event)\"></he-search-extend>\n </div>\n <div class=\"column is-narrow\" *ngIf=\"views()?.length > 1\">\n <div class=\"field has-addons\">\n <div class=\"control\" *ngFor=\"let view of views()\">\n <button class=\"button is-small\" [class.is-selected]=\"selectedView() === view\" (click)=\"selectedView.set(view)\">\n <span class=\"icon is-small\">\n <fa-icon [icon]=\"viewIcon[view]\" aria-hidden=\"true\"></fa-icon>\n </span>\n <span class=\"is-hidden-mobile\">{{ view }}</span>\n </button>\n </div>\n </div>\n </div>\n</div>\n\n<ng-container *ngIf=\"isNodeKeyAllowed()\">\n <ng-container [ngSwitch]=\"selectedView()\">\n <div class=\"is-px-3 is-pb-3\" *ngSwitchCase=\"View.table\">\n <ng-container *ngIf=\"hasData(); else emptyTable\">\n <he-data-table class=\"mb-1 is-small\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n <tr class=\"has-text-weight-bold\" *ngIf=\"dataKeys().length > 1\">\n <th class=\"width-auto\"></th>\n <th [class.is-hidden]=\"isGroupNode()\"></th>\n\n <ng-container *ngFor=\"let dataKey of dataKeys(); let dataKeyLast = last\">\n <ng-container *ngIf=\"data()[dataKey]?.length\">\n <th [attr.colspan]=\"data()[dataKey].length\" [class.has-border-right]=\"!dataKeyLast\">\n <span>{{ dataKey | keyToLabel }}</span>\n </th>\n </ng-container>\n </ng-container>\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\n <ng-container *ngFor=\"let dataKey of dataKeys(); let dataKeyLast = last\">\n <th\n *ngFor=\"let node of data()[dataKey]; let nodeLast = last\"\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 [innerHtml]=\"node.value.term.name | ellipsis: 30 | compound\"></span>\n </he-node-link>\n </th>\n </ng-container>\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]=\"baseUrl + '/schema/Cycle#functionalUnit'\" target=\"_blank\">Functional unit</a>\n </th>\n\n <ng-container *ngFor=\"let dataKey of dataKeys(); let dataKeyLast = last\">\n <th\n *ngFor=\"let node of data()[dataKey]; let nodeLast = last\"\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\n class=\"is-inline-block is-ml-2\"\n [term]=\"node.value.term\"></he-terms-units-description>\n </th>\n </ng-container>\n </tr>\n </thead>\n <tbody>\n <ng-container *ngFor=\"let cycle of cycles(); trackBy: trackById; let cycleIndex = index\">\n <tr>\n <td class=\"width-auto has-border-right\" [attr.title]=\"defaultLabel(cycle)\">\n <he-node-link [node]=\"cycle.term || cycle\">\n <span>{{ cycleIndex + 1 }}. {{ defaultLabel(cycle) }}</span>\n </he-node-link>\n </td>\n <td class=\"has-border-right\" [class.is-hidden]=\"isGroupNode()\">\n <he-cycles-functional-unit-measure [cycle]=\"cycles()[0]\"></he-cycles-functional-unit-measure>\n </td>\n\n <ng-container *ngFor=\"let dataKey of dataKeys(); let dataKeyLast = last\">\n <td\n class=\"is-nowrap\"\n *ngFor=\"let node of data()[dataKey]; let nodeLast = last\"\n [class.has-border-right]=\"dataKeys().length > 1 && !dataKeyLast && nodeLast\">\n <span\n *ngIf=\"node.value.values[cycle['@id']]; else emptyValue\"\n class=\"trigger-popover\"\n [ngbPopover]=\"details\"\n [autoClose]=\"'outside'\"\n popoverClass=\"is-narrow\"\n triggers=\"manual\"\n #p=\"ngbPopover\"\n placement=\"left\"\n container=\"body\"\n (click)=\"\n togglePopover(p, { data: node.value.values[cycle['@id']], cycle: cycle, key: dataKey })\n \">\n <span pointer>\n {{\n propertyValue(node.value.values[cycle['@id']].value, node.value.term['@id'])\n | precision: 3\n | default: '-'\n }}\n </span>\n <he-blank-node-state\n class=\"ml-1\"\n [dataState]=\"_dataState()\"\n [node]=\"node.value.values[cycle['@id']].node\"\n key=\"value\"></he-blank-node-state>\n </span>\n </td>\n </ng-container>\n </tr>\n </ng-container>\n </tbody>\n </table>\n </he-data-table>\n\n <he-blank-node-state-notice [dataState]=\"_dataState()\"></he-blank-node-state-notice>\n </ng-container>\n </div>\n\n <ng-container *ngSwitchCase=\"View.chart\">\n <ng-container [ngSwitch]=\"firstNodeKey()\">\n <he-cycles-result *ngSwitchCase=\"BlankNodesKey.inputs\" [cycles]=\"cycles()\"></he-cycles-result>\n <he-cycles-emissions-chart\n *ngSwitchCase=\"BlankNodesKey.emissions\"\n [cycles]=\"cycles()\"></he-cycles-emissions-chart>\n </ng-container>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"View.timeline\">\n <ng-container *ngTemplateOutlet=\"selectCycle\"></ng-container>\n\n <div class=\"is-px-3 is-pb-3\">\n <he-cycles-nodes-timeline\n [recalculatedValues]=\"timelineValues()\"\n [dataState]=\"_dataState()\"></he-cycles-nodes-timeline>\n\n <he-blank-node-state-notice [dataState]=\"_dataState()\"></he-blank-node-state-notice>\n </div>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"View.logs\">\n <ng-container *ngTemplateOutlet=\"selectCycle\"></ng-container>\n\n <div class=\"tabs is-mb-2\" *ngIf=\"_nodeKeys().length > 1\">\n <ul>\n <li *ngFor=\"let nodeKey of _nodeKeys()\" [class.is-active]=\"selectedNodeKey() === nodeKey\">\n <a (click)=\"selectedNodeKey.set(nodeKey)\">{{ nodeKey | keyToLabel }}</a>\n </li>\n </ul>\n </div>\n\n <he-node-logs-models\n *ngIf=\"selectedNode()\"\n [node]=\"selectedNode()\"\n [nodeKey]=\"selectedNodeKey()\"\n [logsKey]=\"selectedLogsKey()\"\n [originalValues]=\"selectedOriginalValues()\"\n [recalculatedValues]=\"selectedRecalculatedValues()\"\n [filterTermTypes]=\"filterTermTypes()\"></he-node-logs-models>\n </ng-container>\n </ng-container>\n</ng-container>\n\n<he-node-csv-export-confirm\n *ngIf=\"showDownload\"\n [nodes]=\"cycles()\"\n [filename]=\"csvFilename()\"\n [isUpload]=\"false\"\n [headerKeys]=\"headerKeys()\"\n (closed)=\"showDownload = false\"></he-node-csv-export-confirm>\n\n<ng-template #emptyTable>\n <div class=\"is-pt-3 has-text-centered\">\n <span>No data available</span>\n <span class=\"is-pl-1\" [class.is-hidden]=\"!filterTerm()\">matching your search criteria</span>\n <span>.</span>\n <span *ngIf=\"showSwitchToRecalculated()\">\n Switch to\n <code>recalculated</code>\n version.\n </span>\n </div>\n</ng-template>\n\n<ng-template #emptyValue>\n <span>-</span>\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 [data]=\"data\"\n [dataState]=\"_dataState()\"\n [nodeType]=\"node['@type']\"\n [dataKey]=\"key\"></he-node-value-details>\n</ng-template>\n\n<ng-template #selectCycle>\n <div class=\"field has-addons is-py-2 is-px-3\" *ngIf=\"cycles().length > 1\">\n <div class=\"control\">\n <span class=\"button is-small is-static is-secondary\">Select a Cycle</span>\n </div>\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth is-secondary\">\n <select (change)=\"selectIndex($event)\">\n <option *ngFor=\"let value of cycles(); let cycleIndex = index\" [value]=\"cycleIndex\">\n {{ cycleIndex + 1 }}. {{ defaultLabel(value) }}\n </option>\n </select>\n </div>\n </div>\n </div>\n</ng-template>\n", styles: ["fa-icon{display:inline-block;width:10px}he-data-table ::ng-deep .table thead tr th:nth-child(2),he-data-table ::ng-deep .table tbody tr td:nth-child(2){max-width:102px;width:102px}\n"] }]
7937
- }], ctorParameters: function () { return [{ type: HeNodeStoreService }]; }, propDecorators: { dataState: [{
7938
- type: Input
7939
- }], nodeKeys: [{
7879
+ args: [{ selector: 'he-engine-orchestrator-edit', template: "<p>\n <i>\n The configuration below is a preview of the\n <a [href]=\"configUrl\" target=\"_blank\">JSON configuration file</a>\n used for the orchestration of the Hestia's calculations.\n </i>\n</p>\n<p>\n <i>Note: not all models might be represented accurately.</i>\n</p>\n\n<div class=\"is-size-7 is-italic\">\n <div class=\"columns is-mobile is-multiline is-vcentered is-variable is-1 my-0\">\n <div class=\"column\">\n <div class=\"pl-3 model-parallel my-3\">\n <span>Models running in parallel</span>\n </div>\n </div>\n\n <div class=\"column is-narrow has-text-right\">\n <div\n class=\"dropdown is-right has-text-left is-dropdown-filters\"\n [class.is-active]=\"showConfig\"\n (clickOutside)=\"showConfig = false\">\n <div class=\"dropdown-trigger\" (click)=\"showConfig = !showConfig\">\n <button\n class=\"button is-ghost\"\n [class.is-active]=\"showConfig\"\n aria-haspopup=\"true\"\n aria-controls=\"option-menu\"\n ngbTooltip=\"Filters\"\n placement=\"bottom\"\n container=\"body\"\n [disableTooltip]=\"showConfig\">\n <span class=\"icon is-small\">\n <fa-icon icon=\"cog\" aria-hidden=\"true\"></fa-icon>\n </span>\n </button>\n </div>\n <div class=\"dropdown-menu\" id=\"option-menu\" role=\"menu\">\n <div class=\"dropdown-content\">\n <div class=\"dropdown-item\">\n <div class=\"field\">\n <div class=\"control is-expanded has-icons-right\">\n <input\n type=\"text\"\n class=\"input search-input is-secondary is-small\"\n [(ngModel)]=\"search\"\n name=\"collection\"\n placeholder=\"Filter by key, name or model\"\n (input)=\"filterModels()\" />\n <a class=\"icon is-small is-right\" (click)=\"search = ''; filterModels()\">\n <fa-icon icon=\"times\"></fa-icon>\n </a>\n </div>\n </div>\n\n <div class=\"field is-relative\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded is-secondary\"\n [(ngModel)]=\"showAdvanced\"\n id=\"showAdvanced\"\n (change)=\"filterModels()\" />\n <label class=\"is-size-7\" for=\"showAdvanced\">\n <span>Show advanced data</span>\n </label>\n </div>\n\n <div class=\"field is-relative\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded is-secondary\"\n [(ngModel)]=\"onlyGapFilled\"\n id=\"onlyGapFilled\"\n (change)=\"filterModels()\" />\n <label class=\"is-size-7\" for=\"onlyGapFilled\">\n <span>Show only gap-filled data</span>\n </label>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"column is-narrow has-text-right\">\n <div\n class=\"dropdown is-right has-text-left\"\n [class.is-active]=\"showDisplayBy\"\n (clickOutside)=\"showDisplayBy = false\">\n <div class=\"dropdown-trigger\" (click)=\"showDisplayBy = !showDisplayBy\">\n <button\n class=\"button is-ghost\"\n aria-haspopup=\"true\"\n aria-controls=\"display-menu\"\n ngbTooltip=\"Display options\"\n placement=\"bottom\"\n container=\"body\"\n [disableTooltip]=\"showDisplayBy\">\n <ng-container [ngSwitch]=\"displayBy\">\n <ng-container *ngSwitchCase=\"'list'\">\n <span class=\"icon is-small\">\n <fa-icon icon=\"list\" aria-hidden=\"true\"></fa-icon>\n </span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'type'\">\n <span class=\"icon is-small\">\n <fa-icon icon=\"table\" aria-hidden=\"true\"></fa-icon>\n </span>\n </ng-container>\n </ng-container>\n </button>\n </div>\n <div class=\"dropdown-menu\" id=\"display-menu\" role=\"menu\">\n <div class=\"dropdown-content\" (click)=\"showDisplayBy = false\">\n <a class=\"dropdown-item\" [class.is-selected]=\"displayBy === 'list'\" (click)=\"displayBy = 'list'\">\n <fa-icon icon=\"list\" aria-hidden=\"true\"></fa-icon>\n <span class=\"pl-2\">Display by Priority</span>\n </a>\n <a class=\"dropdown-item\" [class.is-selected]=\"displayBy === 'type'\" (click)=\"displayBy = 'type'\">\n <fa-icon icon=\"table\" aria-hidden=\"true\"></fa-icon>\n <span class=\"pl-2\">Display by Type</span>\n </a>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n\n<ng-container *ngIf=\"displayBy === 'list' && models\">\n <div class=\"pl-3\">\n <ng-container *ngTemplateOutlet=\"modelList; context: { $implicit: models }\"></ng-container>\n </div>\n</ng-container>\n\n<ng-container *ngIf=\"displayBy === 'type' && groupedModels\">\n <div class=\"tabs\">\n <ul>\n <li\n *ngFor=\"let group of groupedModels | keys; trackBy: trackByKey\"\n [class.is-active]=\"selectedGroupedKey === group.key\">\n <a (click)=\"selectedGroupedKey = group.key\">\n <span class=\"pl-2\">{{ group.key }} ({{ group.value.length }})</span>\n </a>\n </li>\n </ul>\n </div>\n\n <div class=\"pl-3\">\n <ng-container\n *ngTemplateOutlet=\"modelList; context: { $implicit: groupedModels[selectedGroupedKey] }\"></ng-container>\n </div>\n</ng-container>\n\n<ng-template #termLink let-value>\n <ng-template #defaultLabel>\n <span>{{ value | keyToLabel }}</span>\n </ng-template>\n\n <ng-container *ngIf=\"termsById[value]; else defaultLabel\">\n <he-node-link [node]=\"termsById[value]\" [showExternalLink]=\"true\">\n <span>{{ termsById[value].name }}</span>\n </he-node-link>\n </ng-container>\n</ng-template>\n\n<ng-template #modelList let-data>\n <div *ngFor=\"let v of data\">\n <ng-container *ngTemplateOutlet=\"model; context: { $implicit: v }\"></ng-container>\n </div>\n</ng-template>\n\n<ng-template #model let-data>\n <ng-container *ngIf=\"isArray(data) && data.length\">\n <div class=\"pl-3 model-parallel\">\n <ng-container *ngTemplateOutlet=\"modelList; context: { $implicit: data }\"></ng-container>\n </div>\n\n <hr />\n </ng-container>\n <ng-container *ngIf=\"!isArray(data)\">\n <div class=\"card mb-2 model-serie is-size-6\">\n <div class=\"card-content p-3\">\n <span class=\"is-capitalized\">{{ data.key | keyToLabel }}</span>\n :\n <ng-template #defaultView>\n <span class=\"default-value\">{{ data.value }}</span>\n\n <p>\n <span class=\"pr-1\">Model:</span>\n <span class=\"pr-2\">\n <ng-container *ngTemplateOutlet=\"termLink; context: { $implicit: data.model }\"></ng-container>\n </span>\n </p>\n </ng-template>\n\n <ng-template #modelFromPathLink>\n <ng-container *ngIf=\"modelPathLink$(data) | async as link; else defaultView\">\n <ng-container\n *ngTemplateOutlet=\"modelPathLink; context: { model: data.model, value: data.value, link }\"></ng-container>\n </ng-container>\n </ng-template>\n\n <ng-container *ngIf=\"modelLink$(data) | async as link; else modelFromPathLink\">\n <ng-container\n *ngTemplateOutlet=\"modelLink; context: { model: data.model, value: data.value, link }\"></ng-container>\n </ng-container>\n\n <div *ngIf=\"showAdvanced\">\n <div *ngIf=\"data.runStrategy\">\n <span class=\"pr-1\">Run strategy:</span>\n <ng-container\n *ngTemplateOutlet=\"strategiesLink; context: { strategy: data.runStrategy, type: 'run' }\"></ng-container>\n\n <div class=\"pl-3 is-size-7\" *ngIf=\"data.runArgs\">\n <p><b>Run arguments:</b></p>\n <ng-container *ngTemplateOutlet=\"strategiesArgs; context: { $implicit: data.runArgs }\"></ng-container>\n </div>\n </div>\n <div *ngIf=\"data.mergeStrategy\">\n <span class=\"pr-1\">Merge strategy:</span>\n <ng-container\n *ngTemplateOutlet=\"\n strategiesLink;\n context: { strategy: data.mergeStrategy, type: 'merge' }\n \"></ng-container>\n\n <div class=\"pl-3 is-size-7\" *ngIf=\"data.mergeArgs\">\n <p><b>Merge arguments:</b></p>\n <ng-container *ngTemplateOutlet=\"strategiesArgs; context: { $implicit: data.mergeArgs }\"></ng-container>\n </div>\n </div>\n </div>\n </div>\n </div>\n </ng-container>\n</ng-template>\n\n<ng-template #modelLinkKey let-model=\"model\" let-link=\"link\">\n <a [href]=\"modelKeyUrl(link, model)\" target=\"_blank\">{{ modelKeyName(link.modelKey) }}</a>\n</ng-template>\n\n<ng-template #modelLink let-model=\"model\" let-link=\"link\" let-value=\"value\">\n <ng-container *ngIf=\"link.term\">\n <ng-container *ngTemplateOutlet=\"termLink; context: { $implicit: link.term }\"></ng-container>\n </ng-container>\n\n <span *ngIf=\"!link.term && !link?.modelKey\" class=\"default-value\">{{ value }}</span>\n\n <ng-container *ngIf=\"!link.term && link?.modelKey\">\n <ng-container *ngTemplateOutlet=\"modelLinkKey; context: { link, model }\"></ng-container>\n </ng-container>\n\n <p class=\"model-link\">\n <span class=\"pr-1\">Model:</span>\n <span class=\"pr-2\">\n <ng-container *ngTemplateOutlet=\"termLink; context: { $implicit: model }\"></ng-container>\n </span>\n\n <a class=\"is-size-7\" [href]=\"link.docPath\" target=\"_blank\">\n <span class=\"pr-1\">(View Docs)</span>\n <fa-icon icon=\"external-link-alt\"></fa-icon>\n </a>\n </p>\n</ng-template>\n\n<ng-template #modelPathLink let-model=\"model\" let-link=\"link\" let-value=\"value\">\n <span *ngIf=\"!link?.modelKey\" class=\"default-value\">{{ value }}</span>\n\n <ng-container *ngIf=\"link?.modelKey\">\n <ng-container *ngTemplateOutlet=\"modelLinkKey; context: { link, model }\"></ng-container>\n </ng-container>\n\n <p class=\"model-path-link\">\n <span class=\"pr-1\">Model:</span>\n <span class=\"pr-2\">\n <ng-container *ngTemplateOutlet=\"termLink; context: { $implicit: model }\"></ng-container>\n </span>\n\n <a class=\"is-size-7\" [href]=\"link.docPath\" target=\"_blank\">\n <span class=\"pr-1\">(View Docs)</span>\n <fa-icon icon=\"external-link-alt\"></fa-icon>\n </a>\n </p>\n</ng-template>\n\n<ng-template #strategiesLink let-strategy=\"strategy\" let-type=\"type\">\n <span class=\"pr-2 is-inline-block\">\n <code>{{ strategy }}</code>\n </span>\n\n <a\n class=\"is-size-7\"\n [href]=\"strategiesDocs + '/' + type + '/' + (type === 'merge' ? 'merge_' : '') + strategy + '.md'\"\n target=\"_blank\">\n <span class=\"pr-1\">(View Docs)</span>\n <fa-icon icon=\"external-link-alt\"></fa-icon>\n </a>\n</ng-template>\n\n<ng-template #strategiesArgs let-args>\n <div class=\"pl-2\">\n <p *ngFor=\"let arg of args | keys\">\n <span class=\"has-text-underline\">{{ arg.key }}</span>\n :\n <code>{{ arg.value | json }}</code>\n </p>\n </div>\n</ng-template>\n", styles: [":host{display:block}.model-parallel{border-left:3px solid #4a4a4a}.dropdown.is-dropdown-filters .dropdown-content{min-width:250px}\n"] }]
7880
+ }], ctorParameters: function () { return [{ type: HeEngineService }, { type: HeSearchService }]; }, propDecorators: { config: [{
7940
7881
  type: Input
7941
- }], nodeKeyGroup: [{
7882
+ }], nodeType: [{
7942
7883
  type: Input
7943
7884
  }] } });
7944
7885
 
7886
+ class EngineRequirementsFormComponent {
7887
+ constructor(formBuilder, searchService) {
7888
+ this.formBuilder = formBuilder;
7889
+ this.searchService = searchService;
7890
+ this.form = this.formBuilder.group({
7891
+ productTermId: [undefined],
7892
+ productTermType: [undefined],
7893
+ tier: [undefined],
7894
+ siteType: [undefined]
7895
+ });
7896
+ this.productTermTermType = productTermTermType.term;
7897
+ this.EmissionMethodTier = EmissionMethodTier;
7898
+ this.SiteSiteType = SiteSiteType;
7899
+ this.suggestingProductTermId = false;
7900
+ this.suggestProductTermId = (text$) => text$.pipe(debounceTime(300), distinctUntilChanged(), tap(() => (this.suggestingProductTermId = true)), switchMap(term => (term.length < 1 ? [] : this.suggestTerm(term))), tap(() => (this.suggestingProductTermId = false)));
7901
+ this.inputFormatterProductTermId = ({ name }) => name;
7902
+ }
7903
+ suggestTerm(term) {
7904
+ return this.searchService.suggest(term, NodeType.Term, null, {
7905
+ bool: {
7906
+ must: [
7907
+ matchType(NodeType.Term),
7908
+ {
7909
+ bool: {
7910
+ should: suggestMatchQuery(term),
7911
+ minimum_should_match: 1
7912
+ }
7913
+ },
7914
+ {
7915
+ bool: {
7916
+ should: productTermTermType.term.map(matchTermType),
7917
+ minimum_should_match: 1
7918
+ }
7919
+ }
7920
+ ]
7921
+ }
7922
+ });
7923
+ }
7924
+ /**
7925
+ * Return if form is valid.
7926
+ */
7927
+ get valid() {
7928
+ return this.form ? !this.form.invalid : true;
7929
+ }
7930
+ formValue() {
7931
+ const { productTermId, ...value } = this.form ? this.form.getRawValue() : { productTermId: undefined };
7932
+ return {
7933
+ ...value,
7934
+ ...(productTermId ? { productTermId: productTermId['@id'] } : {}) // selected as a JSON-LD Object
7935
+ };
7936
+ }
7937
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: EngineRequirementsFormComponent, deps: [{ token: i2$1.UntypedFormBuilder }, { token: HeSearchService }], target: i0.ɵɵFactoryTarget.Component }); }
7938
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.8", type: EngineRequirementsFormComponent, selector: "he-engine-requirements-form", ngImport: i0, 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 <fa-icon icon=\"spinner\" [pulse]=\"true\"></fa-icon>\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 <option *ngFor=\"let termType of productTermTermType\" [value]=\"termType\">\n {{ termType | keyToLabel }}\n </option>\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 <option *ngFor=\"let tier of EmissionMethodTier | keys\" [value]=\"tier.value\">{{ tier.value }}</option>\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 <option *ngFor=\"let siteType of SiteSiteType | keys\" [value]=\"siteType.value\">\n {{ siteType.value }}\n </option>\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\"></ngb-highlight>\n</ng-template>\n", styles: [""], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2$1.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: i2$1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i4$1.NgbHighlight, selector: "ngb-highlight", inputs: ["highlightClass", "result", "term", "accentSensitive"] }, { kind: "directive", type: i4$1.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: i3.FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "spin", "pulse", "mask", "styles", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "classes", "transform", "a11yRole"] }, { kind: "pipe", type: KeysPipe, name: "keys" }, { kind: "pipe", type: KeyToLabelPipe, name: "keyToLabel" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
7939
+ }
7940
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: EngineRequirementsFormComponent, decorators: [{
7941
+ type: Component$1,
7942
+ args: [{ selector: 'he-engine-requirements-form', changeDetection: ChangeDetectionStrategy.OnPush, 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 <fa-icon icon=\"spinner\" [pulse]=\"true\"></fa-icon>\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 <option *ngFor=\"let termType of productTermTermType\" [value]=\"termType\">\n {{ termType | keyToLabel }}\n </option>\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 <option *ngFor=\"let tier of EmissionMethodTier | keys\" [value]=\"tier.value\">{{ tier.value }}</option>\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 <option *ngFor=\"let siteType of SiteSiteType | keys\" [value]=\"siteType.value\">\n {{ siteType.value }}\n </option>\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\"></ngb-highlight>\n</ng-template>\n" }]
7943
+ }], ctorParameters: function () { return [{ type: i2$1.UntypedFormBuilder }, { type: HeSearchService }]; } });
7944
+
7945
7945
  const components$5 = [
7946
- CyclesCompletenessComponent,
7947
- CyclesEmissionsChartComponent,
7948
- CyclesFunctionalUnitMeasureComponent,
7949
- CyclesNodesComponent,
7950
- CyclesNodesTimelineComponent,
7951
- CyclesResultComponent
7946
+ EngineModelsStageComponent,
7947
+ EngineModelsVersionLinkComponent,
7948
+ EngineOrchestratorEditComponent,
7949
+ EngineRequirementsFormComponent
7952
7950
  ];
7953
- class HeCyclesModule {
7954
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: HeCyclesModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
7955
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.1.8", ngImport: i0, type: HeCyclesModule, declarations: [CyclesCompletenessComponent,
7956
- CyclesEmissionsChartComponent,
7957
- CyclesFunctionalUnitMeasureComponent,
7958
- CyclesNodesComponent,
7959
- CyclesNodesTimelineComponent,
7960
- CyclesResultComponent], imports: [CommonModule, FormsModule, HeCommonModule, HeNodeModule, HeTermsModule], exports: [CyclesCompletenessComponent,
7961
- CyclesEmissionsChartComponent,
7962
- CyclesFunctionalUnitMeasureComponent,
7963
- CyclesNodesComponent,
7964
- CyclesNodesTimelineComponent,
7965
- CyclesResultComponent] }); }
7966
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: HeCyclesModule, imports: [CommonModule, FormsModule, HeCommonModule, HeNodeModule, HeTermsModule] }); }
7951
+ class HeEngineModule {
7952
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: HeEngineModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
7953
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.1.8", ngImport: i0, type: HeEngineModule, declarations: [EngineModelsStageComponent,
7954
+ EngineModelsVersionLinkComponent,
7955
+ EngineOrchestratorEditComponent,
7956
+ EngineRequirementsFormComponent], imports: [CommonModule, ReactiveFormsModule, FormsModule, HeCommonModule, HeNodeModule], exports: [EngineModelsStageComponent,
7957
+ EngineModelsVersionLinkComponent,
7958
+ EngineOrchestratorEditComponent,
7959
+ EngineRequirementsFormComponent] }); }
7960
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: HeEngineModule, imports: [CommonModule, ReactiveFormsModule, FormsModule, HeCommonModule, HeNodeModule] }); }
7967
7961
  }
7968
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: HeCyclesModule, decorators: [{
7962
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: HeEngineModule, decorators: [{
7969
7963
  type: NgModule,
7970
7964
  args: [{
7971
7965
  declarations: components$5,
7972
7966
  exports: components$5,
7973
- imports: [CommonModule, FormsModule, HeCommonModule, HeNodeModule, HeTermsModule]
7967
+ imports: [CommonModule, ReactiveFormsModule, FormsModule, HeCommonModule, HeNodeModule]
7974
7968
  }]
7975
7969
  }] });
7976
7970
 
@@ -8244,9 +8238,11 @@ const customErrorMessage = {
8244
8238
  'should be linked to an emission in the Cycle': ({ params }, errorCount) => `${errorCount === 1 ? `${code(params?.term.name)} exists` : 'Some Emissions exist'} in both the Cycle and the Transformation but ${errorCount === 1 ? 'it is' : 'they are'} not linked using ${code('cycle.emissions.X.transformation.term')}. This may be an error.`,
8245
8239
  'should add an animal production system': () => `For animal production cycles, we recommend specifying the animal production ${glossaryTypeLink(TermTermType.system)} as a Practice.
8246
8240
  You can find a list of systems in the ${glossaryTypeLink(TermTermType.system, 'Glossary')}.`,
8247
- 'must be set to false when specifying fuel use': ({ params }) => `If machinery fuel (${params?.allowedValues.map(code).join(', ')}) is used during a Cycle,
8241
+ 'must be set to false when specifying fuel use': ({ params }) => `If fuel for machinery (${params?.allowedValues.map(code).join(', ')}) is used during a Cycle,
8248
8242
  but there is no data on the amount of ${glossaryTypeLink(TermTermType.material)} used for agricultural equipment,
8249
- then ${code('completeness.material')} must be ${code('false')}.`,
8243
+ then ${code('completeness.material')} must be ${code('false')}.
8244
+ Here, we mean the quantity of physical material used to construct agricultural machinery,
8245
+ which is then depreciated over each Cycle.`,
8250
8246
  'must be below or equal to 1 for unit in ha': () => `The maximum value for a product with units ${code('ha')} on a Cycle with a ${schemaLink('Cycle#functionalUnit', 'functional unit')} of ${code('1 ha')} is ${code('1')}.
8251
8247
  If you are trying to add a product with the units ${code('kg')}, use a different term.`,
8252
8248
  "pastureGrass key termType must be 'landCover'": ({ params }) => `The Term ${code(params?.term.name)} can't be used as a key for ${termLink(pastureGrass)}.
@@ -8354,7 +8350,21 @@ const customErrorMessage = {
8354
8350
  This soil measurement can vary substantially with depth.
8355
8351
  We require that you specify both ${schemaLink('Measurement#depthUpper', 'depthUpper')} and ${schemaLink('Measurement#depthLower', 'depthLower')}.
8356
8352
  If you do not have these data, consider ${schemaLink('Measurement#depthUpper', 'depthUpper')} and ${schemaLink('Measurement#depthLower', 'depthLower')} and setting an appropriate ${schemaLink('Measurement#methodClassification', 'methodClassification')}.
8357
- Alternatively, delete the Measurement.`
8353
+ Alternatively, delete the Measurement.`,
8354
+ 'multiple cycles on the same site cannot overlap': ({ params }) => `Cycles taking place on the same Site cannot overlap: ${params.ids
8355
+ ?.map(code)
8356
+ .join(', ')}. Please consider any of the following suggestions to resolve this conflict:
8357
+ <ul class="is-pl-3 is-list-style-disc is-nowrap">
8358
+ <li>You can amend the Cycles' ${schemaLink('Cycle#startDate', 'startDate')} and ${schemaLink('Cycle#endDate', 'endDate')} to ensure that they do not overlap anymore.
8359
+ <li>You can break down your Cycles into shorter Cycles to ensure that they do not overlap anymore.
8360
+ <li>You can merge the overlapping Cycles into one overall Cycle if the Products of each Cycle are grown at the same time on the same Site.
8361
+ This is relevant if intercropping is used, for instance.</li>
8362
+ <li>You can create a different Site for each overlapping Cycle.
8363
+ This is appropriate if a field is divided into different plots, each dedicated to growing a different Product; each plot would be considered a unique Site on the platform.</li>
8364
+ </ul>
8365
+ `,
8366
+ 'multiple cycles on the same site cannot be linked together': ({ params }) => `Cycles linked together by an Impact Assessment cannot take place on the same Site.
8367
+ Please create different Sites for the following Cycles: ${params.ids?.map(code).join(', ')}.`
8358
8368
  };
8359
8369
  const parseDefaultMessage = (message) => `<span class="is-capitalized-first-letter">${message?.startsWith('should have required property')
8360
8370
  ? message.replace("'", '<code>').replace("'", '</code>')