@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.
- package/engine/index.d.ts +0 -1
- package/esm2022/engine/engine-models-version-link/engine-models-version-link.component.mjs +2 -2
- package/esm2022/engine/index.mjs +1 -2
- package/esm2022/files/files-error.model.mjs +20 -4
- package/esm2022/node/index.mjs +2 -1
- package/esm2022/node/node-logs-models/node-logs-models.component.mjs +4 -10
- package/esm2022/node/node-model-version.mjs +26 -0
- package/esm2022/schema/schema-validation.model.mjs +1 -1
- package/fesm2022/hestia-earth-ui-components.mjs +685 -675
- package/fesm2022/hestia-earth-ui-components.mjs.map +1 -1
- package/node/index.d.ts +1 -0
- package/node/node-logs-models/node-logs-models.component.d.ts +0 -2
- package/package.json +1 -1
- package/schema/schema-validation.model.d.ts +1 -1
- package/esm2022/engine/engine-models-version-link/engine-models-version-link.model.mjs +0 -26
- /package/{engine/engine-models-version-link/engine-models-version-link.model.d.ts → node/node-model-version.d.ts} +0 -0
|
@@ -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,
|
|
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,
|
|
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
|
-
|
|
6350
|
-
|
|
6351
|
-
|
|
6352
|
-
|
|
6353
|
-
|
|
6354
|
-
|
|
6355
|
-
|
|
6356
|
-
|
|
6357
|
-
|
|
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
|
|
6930
|
-
|
|
6931
|
-
|
|
6932
|
-
|
|
6933
|
-
|
|
6934
|
-
|
|
6935
|
-
|
|
6936
|
-
|
|
6937
|
-
|
|
6938
|
-
|
|
6939
|
-
|
|
6940
|
-
|
|
6941
|
-
|
|
6942
|
-
|
|
6943
|
-
|
|
6944
|
-
|
|
6945
|
-
|
|
6946
|
-
|
|
6947
|
-
|
|
6948
|
-
|
|
6949
|
-
|
|
6950
|
-
|
|
6951
|
-
|
|
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 </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 </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 </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 </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
|
-
}],
|
|
6878
|
+
}], buttonClass: [{
|
|
7276
6879
|
type: Input
|
|
6880
|
+
}], selectRecommendation: [{
|
|
6881
|
+
type: Output
|
|
7277
6882
|
}] } });
|
|
7278
6883
|
|
|
7279
|
-
const components$
|
|
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$
|
|
7318
|
-
exports: components$
|
|
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$
|
|
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$
|
|
7424
|
-
exports: components$
|
|
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
|
-
|
|
7907
|
-
|
|
7908
|
-
return orderBy(grouppedKeys(nodesPerCycle), ['key'], ['asc']);
|
|
7846
|
+
trackByKey(_index, { key }) {
|
|
7847
|
+
return key;
|
|
7909
7848
|
}
|
|
7910
|
-
|
|
7911
|
-
|
|
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
|
-
|
|
7920
|
-
return
|
|
7852
|
+
modelPathLink$({ model, value }) {
|
|
7853
|
+
return this.hestiaEngineService.model$({
|
|
7854
|
+
path: `${engineGitUrl()}/hestia_earth/models/${model}/${(value || '').replace('.', '/')}.py`
|
|
7855
|
+
});
|
|
7921
7856
|
}
|
|
7922
|
-
|
|
7923
|
-
return
|
|
7857
|
+
get configUrl() {
|
|
7858
|
+
return this.hestiaEngineService.orchestratorConfigUrl(this.nodeType);
|
|
7924
7859
|
}
|
|
7925
|
-
|
|
7926
|
-
|
|
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
|
-
|
|
7929
|
-
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
-
}],
|
|
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
|
-
|
|
7947
|
-
|
|
7948
|
-
|
|
7949
|
-
|
|
7950
|
-
CyclesNodesTimelineComponent,
|
|
7951
|
-
CyclesResultComponent
|
|
7946
|
+
EngineModelsStageComponent,
|
|
7947
|
+
EngineModelsVersionLinkComponent,
|
|
7948
|
+
EngineOrchestratorEditComponent,
|
|
7949
|
+
EngineRequirementsFormComponent
|
|
7952
7950
|
];
|
|
7953
|
-
class
|
|
7954
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type:
|
|
7955
|
-
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.1.8", ngImport: i0, type:
|
|
7956
|
-
|
|
7957
|
-
|
|
7958
|
-
|
|
7959
|
-
|
|
7960
|
-
|
|
7961
|
-
|
|
7962
|
-
|
|
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:
|
|
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
|
|
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
|
|
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>')
|