@hestia-earth/ui-components 0.42.10 → 0.42.11
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.
|
@@ -9362,6 +9362,10 @@ const identitySpec = (type, nodeType, nodeKey) => {
|
|
|
9362
9362
|
const properties = [...new Set([...(def.properties || []), ...parentFields])].filter((field) => !excludedIdentityFields.includes(field) && !relations.includes(field.split('.')[0]));
|
|
9363
9363
|
return { def, properties, relations };
|
|
9364
9364
|
};
|
|
9365
|
+
// some node keys distinguish blank nodes by their recorded `model` (e.g. an Indicator's `methodModel.@id`
|
|
9366
|
+
// is a uniqueness field): models that ran in parallel for the same term's value are then separate rows
|
|
9367
|
+
// (one per model), not extra model columns on a single row
|
|
9368
|
+
const modelIsUniquenessField = (spec) => spec.properties.includes('methodModel.@id');
|
|
9365
9369
|
const isPresent = (value) => value !== undefined && value !== null && value !== '';
|
|
9366
9370
|
// the joined uniqueness-field ids of each item in a relation (e.g. an emission's `inputs[].@id`)
|
|
9367
9371
|
const relationItemIds = (items, fields) => Array.isArray(items)
|
|
@@ -9671,7 +9675,10 @@ const mapValueModel = (models, valueModelId, condition, update) => models.map(mo
|
|
|
9671
9675
|
* When the value came from the original (no model, no config), the row shows no model.
|
|
9672
9676
|
*/
|
|
9673
9677
|
// eslint-disable-next-line complexity -- orchestrates the value-model resolution (delegated to helpers)
|
|
9674
|
-
const valueModelRuns = (entry, value, originalValue, nodeType, termId, nodeKey, config
|
|
9678
|
+
const valueModelRuns = (entry, value, originalValue, nodeType, termId, nodeKey, config,
|
|
9679
|
+
// when the recorded `model` is a uniqueness field, parallel siblings are their own rows (see
|
|
9680
|
+
// `parallelSiblingRows`), so they are dropped from this value row's models
|
|
9681
|
+
splitParallelModels = false) => {
|
|
9675
9682
|
const valueModelId = blankNodeModelId(value);
|
|
9676
9683
|
const isRecalculated = isRecalculatedValue(value, originalValue);
|
|
9677
9684
|
const hasOriginal = !!originalValue && typeof originalValue.value !== 'undefined';
|
|
@@ -9685,9 +9692,21 @@ const valueModelRuns = (entry, value, originalValue, nodeType, termId, nodeKey,
|
|
|
9685
9692
|
const isValueLog = (log) => !isBackgroundLog(log) && !isSubRowOrchestrator(log?.orchestrator?.value, subRowValues);
|
|
9686
9693
|
const valueLog = selectValueLog(logs, valueModelId, isValueLog, isRecalculated);
|
|
9687
9694
|
const valueOrchestrator = valueLog?.orchestrator?.value;
|
|
9688
|
-
const
|
|
9689
|
-
|
|
9690
|
-
|
|
9695
|
+
const matchesValueOrchestrator = (log) => log?.orchestrator?.value === valueOrchestrator && !isBackgroundLog(log);
|
|
9696
|
+
// keep the parallel grouping (a nested `logs` array): parallel siblings are independent, so a model
|
|
9697
|
+
// that did not run failed rather than being "skipped" by a sibling that ran (a higher-tier hierarchy
|
|
9698
|
+
// model). `jLogModelColumns` applies the pre-group success state to each parallel sibling; flatten the
|
|
9699
|
+
// resulting columns back to the flat run list this function returns
|
|
9700
|
+
const valueLogSteps = (entry?.logs || [])
|
|
9701
|
+
.map((step) => Array.isArray(step) ? step.filter(matchesValueOrchestrator) : matchesValueOrchestrator(step) ? step : undefined)
|
|
9702
|
+
.filter((step) => (Array.isArray(step) ? step.length > 0 : !!step));
|
|
9703
|
+
const allLogModels = valueLog ? flattenColumns(jLogModelColumns(valueLogSteps, nodeType, termId, false)) : [];
|
|
9704
|
+
// when models are split into their own rows, this value row keeps only its own model (parallel siblings
|
|
9705
|
+
// become separate rows); otherwise parallel siblings stay as fallback/sibling columns on this row
|
|
9706
|
+
const siblingIds = splitParallelModels
|
|
9707
|
+
? new Set(parallelSiblingLogs(entry, valueModelId).map((log) => log.model))
|
|
9708
|
+
: new Set();
|
|
9709
|
+
const rawLogModels = allLogModels.filter(model => !siblingIds.has(model.methodId));
|
|
9691
9710
|
// the recorded value model (the blank node `methodModel`, e.g. `hestiaAggregatedData`) can differ from
|
|
9692
9711
|
// the single orchestrator model in the logs (e.g. `linkedImpactAssessment`); relabel that run to the
|
|
9693
9712
|
// recorded model so it shows under the expected name, but keep the orchestrator run's logs and its
|
|
@@ -9778,6 +9797,22 @@ const allSubRows = (entry, value, originalValue, nodeType, type, termId, getTerm
|
|
|
9778
9797
|
];
|
|
9779
9798
|
};
|
|
9780
9799
|
const flattenColumns = (columns) => columns.flatMap(column => (Array.isArray(column) ? column : [column]));
|
|
9800
|
+
// the distinct models (other than the value's own `model`) that ran in parallel with it - a nested
|
|
9801
|
+
// `logs` group holding more than one model. When `model` is a uniqueness field each becomes its own row,
|
|
9802
|
+
// so they are split off the value row (a sibling that did not win is its own failed/separate run, not a
|
|
9803
|
+
// fallback column). Keeps the first log per model.
|
|
9804
|
+
const parallelSiblingLogs = (entry, valueModelId) => {
|
|
9805
|
+
const parallelGroups = (entry?.logs || []).filter((step) => Array.isArray(step) && new Set(step.filter((e) => !!e?.model).map((e) => e.model)).size > 1);
|
|
9806
|
+
const byModel = new Map();
|
|
9807
|
+
parallelGroups
|
|
9808
|
+
.flat()
|
|
9809
|
+
.filter((log) => !!log?.model && log.model !== valueModelId)
|
|
9810
|
+
.forEach((log) => {
|
|
9811
|
+
if (!byModel.has(log.model))
|
|
9812
|
+
byModel.set(log.model, log);
|
|
9813
|
+
});
|
|
9814
|
+
return [...byModel.values()];
|
|
9815
|
+
};
|
|
9781
9816
|
// a `<key>-failed` entry has no value: its identity/sub-rows are empty and the models that tried are
|
|
9782
9817
|
// errors; parallel models (a nested `logs` array) are kept grouped (`modelColumns`) so they stack in one
|
|
9783
9818
|
// column, while `models` stays flat for the status checks
|
|
@@ -9807,7 +9842,7 @@ const valueBlankNodeContent = (entry, value, originalValue, termId, { nodeType,
|
|
|
9807
9842
|
subRows: allSubRows(entry, value, originalValue, nodeType, type, termId, getTerm || defaultGetTerm),
|
|
9808
9843
|
isRecalculated: isRecalculatedValue(value, originalValue),
|
|
9809
9844
|
recalculated: value ? [value] : [],
|
|
9810
|
-
models: valueModelRuns(entry, value, originalValue, nodeType, termId, nodeKey, config)
|
|
9845
|
+
models: valueModelRuns(entry, value, originalValue, nodeType, termId, nodeKey, config, modelIsUniquenessField(spec))
|
|
9811
9846
|
};
|
|
9812
9847
|
};
|
|
9813
9848
|
const buildBlankNode = (entry, value, originalValue, index, term, isFailed, context) => {
|
|
@@ -9829,6 +9864,42 @@ const buildBlankNode = (entry, value, originalValue, index, term, isFailed, cont
|
|
|
9829
9864
|
: valueBlankNodeContent(entry, value, originalValue, termId, context))
|
|
9830
9865
|
};
|
|
9831
9866
|
};
|
|
9867
|
+
// a parallel model that ran for a term's value but did not produce its own blank node (e.g. it failed,
|
|
9868
|
+
// while a sibling set the value). When `model` is a uniqueness field it is shown as its own row -
|
|
9869
|
+
// distinguished by its `methodModel`, with no value and a single model column carrying its status
|
|
9870
|
+
const buildParallelSiblingRow = (log, term, index, context) => {
|
|
9871
|
+
const termId = term['@id'];
|
|
9872
|
+
const run = toModelRun(log, jLogModelStatus(log, false, false), context.nodeType, termId);
|
|
9873
|
+
// carry the model as a `methodModel` Term so the row is distinguished by a methodModel link (like a
|
|
9874
|
+
// value row), resolved through the same `getTerm` the component uses for names; it has no `value`, so
|
|
9875
|
+
// it contributes nothing to the group's combined value
|
|
9876
|
+
const methodModel = context.getTerm?.(log.model) ?? { '@type': NodeType.Term, '@id': log.model };
|
|
9877
|
+
const syntheticValue = { '@type': context.type, term, methodModel };
|
|
9878
|
+
return {
|
|
9879
|
+
index,
|
|
9880
|
+
term,
|
|
9881
|
+
termId,
|
|
9882
|
+
type: context.type,
|
|
9883
|
+
originalValue: null,
|
|
9884
|
+
isOriginal: false,
|
|
9885
|
+
isRequired: true,
|
|
9886
|
+
isFailed: false,
|
|
9887
|
+
original: [],
|
|
9888
|
+
recalculatedValue: null,
|
|
9889
|
+
identity: { 'methodModel.@id': log.model },
|
|
9890
|
+
identityLabel: '',
|
|
9891
|
+
identitySegments: [],
|
|
9892
|
+
isRecalculated: false,
|
|
9893
|
+
recalculated: [syntheticValue],
|
|
9894
|
+
subRows: [],
|
|
9895
|
+
models: [run],
|
|
9896
|
+
modelColumns: [run],
|
|
9897
|
+
// `allSucceeded` is recomputed by `withDisplayValues` at the end of the pipeline
|
|
9898
|
+
allSucceeded: false,
|
|
9899
|
+
canOpen: false,
|
|
9900
|
+
isOpen: false
|
|
9901
|
+
};
|
|
9902
|
+
};
|
|
9832
9903
|
/**
|
|
9833
9904
|
* Group the `.jlog` logs for one node key into rows, one per term, keeping every blank node distinct.
|
|
9834
9905
|
*
|
|
@@ -9853,15 +9924,36 @@ const groupJLogByTerm = (jlog, nodeKey, recalculatedValues = [], originalValues
|
|
|
9853
9924
|
const key = identityKey(blankNodeIdentity(value, spec));
|
|
9854
9925
|
return (originalValues || []).find(original => original.term?.['@id'] === value.term?.['@id'] && identityKey(blankNodeIdentity(original, spec)) === key);
|
|
9855
9926
|
};
|
|
9927
|
+
// each recalculated blank node, attaching its `.jlog` logs when present (a node may exist without logs,
|
|
9928
|
+
// e.g. a value provided in the original)
|
|
9929
|
+
const valueEntries = (recalculatedValues || [])
|
|
9930
|
+
.map((value, index) => ({ value, index, term: value?.term }))
|
|
9931
|
+
.filter(({ term }) => !!term?.['@id']);
|
|
9932
|
+
const valueNodes = valueEntries.map(({ value, index, term }) => buildBlankNode(keyLogs[index] || {}, value, matchOriginal(value), index, term, false, context));
|
|
9933
|
+
// when the recorded `model` is a uniqueness field, models that ran in parallel for a term's value but
|
|
9934
|
+
// produced no blank node (e.g. a sibling that failed while another set the value) are shown as their
|
|
9935
|
+
// own rows - skipping any model already represented by a value row for that term (avoiding duplicates)
|
|
9936
|
+
const seenModelsByTerm = new Map();
|
|
9937
|
+
valueEntries.forEach(({ value, term }) => {
|
|
9938
|
+
const set = seenModelsByTerm.get(term['@id']) ?? new Set();
|
|
9939
|
+
const modelId = blankNodeModelId(value);
|
|
9940
|
+
if (modelId)
|
|
9941
|
+
set.add(modelId);
|
|
9942
|
+
seenModelsByTerm.set(term['@id'], set);
|
|
9943
|
+
});
|
|
9944
|
+
let siblingIndex = recalculatedValues?.length ?? 0;
|
|
9945
|
+
const siblingNodes = modelIsUniquenessField(spec)
|
|
9946
|
+
? valueEntries.flatMap(({ value, index, term }) => parallelSiblingLogs(keyLogs[index] || {}, blankNodeModelId(value)).flatMap(log => {
|
|
9947
|
+
const seen = seenModelsByTerm.get(term['@id']);
|
|
9948
|
+
if (seen?.has(log.model))
|
|
9949
|
+
return [];
|
|
9950
|
+
seen?.add(log.model);
|
|
9951
|
+
return [buildParallelSiblingRow(log, term, siblingIndex++, context)];
|
|
9952
|
+
}))
|
|
9953
|
+
: [];
|
|
9856
9954
|
const blankNodes = [
|
|
9857
|
-
|
|
9858
|
-
|
|
9859
|
-
...(recalculatedValues || []).map((value, index) => {
|
|
9860
|
-
const term = value?.term;
|
|
9861
|
-
return term?.['@id']
|
|
9862
|
-
? buildBlankNode(keyLogs[index] || {}, value, matchOriginal(value), index, term, false, context)
|
|
9863
|
-
: null;
|
|
9864
|
-
}),
|
|
9955
|
+
...valueNodes,
|
|
9956
|
+
...siblingNodes,
|
|
9865
9957
|
...Object.entries(failedLogs).map(([termId, entry], i) => buildBlankNode(entry, undefined, undefined, -1 - i, getTerm(termId), true, context))
|
|
9866
9958
|
].filter(Boolean);
|
|
9867
9959
|
return orderGroups(groupBlankNodesByTerm(blankNodes).map(withCollapsible).map(withRowLabels).map(withDisplayValues), nodeKey);
|
|
@@ -10089,7 +10181,9 @@ class NodeJLogModelsComponent {
|
|
|
10089
10181
|
if (!this.isBlankNodes()) {
|
|
10090
10182
|
return groupJLogByField(this.scopedJlog(), this.nodeKey(), this.originalValues(), this.recalculatedValues(), this.nodeType());
|
|
10091
10183
|
}
|
|
10092
|
-
const groups = groupJLogByTerm(this.scopedJlog(), this.nodeKey(), this.recalculatedValues(), this.originalValues(), this.nodeType(), id => this.failedTerms()[id] ||
|
|
10184
|
+
const groups = groupJLogByTerm(this.scopedJlog(), this.nodeKey(), this.recalculatedValues(), this.originalValues(), this.nodeType(), id => this.failedTerms()[id] ||
|
|
10185
|
+
this.methodsById()?.[id] ||
|
|
10186
|
+
{ '@type': NodeType.Term, '@id': id, name: termTypeLabel(id) }, this.config());
|
|
10093
10187
|
// a combined node key (e.g. `emissionsResourceUse`) holds several term types; keep only the requested
|
|
10094
10188
|
// ones (like the legacy `computeTerms`), keeping terms whose type is not yet resolved
|
|
10095
10189
|
const termTypes = this.filterTermTypes();
|