@hestia-earth/ui-components 0.43.13 → 0.43.14

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.
@@ -11839,6 +11839,20 @@ const isMissingValue = (values, binding) => isSubstitutable(binding) && isMissin
11839
11839
  * identical to the symbolic one.
11840
11840
  */
11841
11841
  const hasAnySubstitution = (values, bindings) => bindings.some(binding => isSubstitutable(binding) && !isMissing(values[binding.key]));
11842
+ const CONTRIBUTORS = {
11843
+ cycle: { row: 'Cycle', group: 'Cycles', heading: 'Cycles combined' },
11844
+ subAggregation: { row: 'Sub-aggregation', group: 'sub-aggregations', heading: 'Sub-aggregations combined' },
11845
+ country: { row: 'Country aggregation', group: 'country aggregations', heading: 'Country aggregations combined' }
11846
+ };
11847
+ /**
11848
+ * What one contributor of an aggregation is, which is what the `$i$` of every rule stands for: a
11849
+ * World aggregation combines country aggregations, a country aggregation the sub-aggregations of its
11850
+ * sub-systems, and a sub-aggregation the Cycles uploaded for the country. The documentation has to
11851
+ * write both, so naming the stage is what tells a reader which of the two a rule is about.
11852
+ *
11853
+ * A World aggregation is never itself a sub-aggregation, so that stage is read first.
11854
+ */
11855
+ const contributorNames = ({ worldAggregation, subAggregation }) => worldAggregation ? CONTRIBUTORS.country : subAggregation ? CONTRIBUTORS.cycle : CONTRIBUTORS.subAggregation;
11842
11856
  // a symbol reading one column of a contributors table: `key` names the table, `column` the field
11843
11857
  const isTableBinding = (binding) => !!binding.key && !!binding.column && !binding.match;
11844
11858
  // the packed `log_as_table` string: rows split on `;`, columns on `_`, each column a `key:value`
@@ -11852,6 +11866,10 @@ const parseRows = (packed) => typeof packed !== 'string'
11852
11866
  return at === -1 ? columns : { ...columns, [pair.slice(0, at)]: pair.slice(at + 1) };
11853
11867
  }, {}));
11854
11868
  const ID_COLUMN$1 = 'id';
11869
+ // A column no contributor recorded is dropped rather than shown as a column of blanks, which is
11870
+ // how the values of the Cycles behind a sub-aggregation are left out. Kept as documented where
11871
+ // there is no row to judge them by: the contributors were counted rather than listed.
11872
+ const recordedColumns = (columns, rows) => rows.length ? columns.filter(({ column }) => rows.some(row => !isMissing(row[column]))) : columns;
11855
11873
  // how many leading segments every id shares, e.g. the product and country of a sub-aggregation
11856
11874
  const commonPrefix = (ids) => {
11857
11875
  const [first = [], ...rest] = ids;
@@ -11894,10 +11912,10 @@ const contributorsTable = (values, formulas) => {
11894
11912
  .find(name => !isMissing(values[name]) || tableCount(values, name));
11895
11913
  if (!key)
11896
11914
  return undefined;
11897
- const columns = bindings
11898
- .filter(binding => binding.key === key)
11899
- .map(({ symbol, description, column }) => ({ symbol, description, column: column }));
11900
11915
  const parsed = parseRows(values[key]);
11916
+ const columns = recordedColumns(bindings
11917
+ .filter(binding => binding.key === key)
11918
+ .map(({ symbol, description, column }) => ({ symbol, description, column: column })), parsed);
11901
11919
  const labels = distinguishingLabels(parsed.map(row => row[ID_COLUMN$1]));
11902
11920
  const rows = parsed.map((row, index) => ({
11903
11921
  id: row[ID_COLUMN$1],
@@ -11917,9 +11935,9 @@ const PRODUCT_PAGES = {
11917
11935
  };
11918
11936
  /**
11919
11937
  * The rules are shown in the order they answer a reader's questions: how this value was calculated,
11920
- * which values went into it, then how each of those was weighted. Grouping them by what they
11938
+ * which Cycles went into it, then how each of those was weighted. Grouping them by what they
11921
11939
  * compute rather than by the page they are documented on is what puts the two calculations either
11922
- * side of the values they combine.
11940
+ * side of the contributors they combine.
11923
11941
  */
11924
11942
  const GROUPS = [
11925
11943
  { id: 'value', heading: 'How the value is calculated', pageOrder: pages => pages },
@@ -12011,10 +12029,10 @@ class NodeAggregatedFormulasComponent {
12011
12029
  .filter(formula => formulaGroup(formula) === id && this.applies(formula))
12012
12030
  })).filter(section => section.formulas.length > 0), ...(ngDevMode ? [{ debugName: "sections" }] : []));
12013
12031
  /**
12014
- * The values this one was combined from, as the aggregation recorded them: one row per Cycle or
12015
- * sub-aggregation, under the symbols the formulas above read them with. Absent where the
12016
- * contributors were too many to record, which is every aggregation built straight from source
12017
- * Cycles - their number is shown instead.
12032
+ * What this value was combined from, as the aggregation recorded it: one row per contributor,
12033
+ * under the symbols the formulas above read them with. Absent where the contributors were too
12034
+ * many to record, which is every aggregation built straight from source Cycles - their number
12035
+ * is shown instead.
12018
12036
  */
12019
12037
  this.contributors = computed(() => {
12020
12038
  const table = contributorsTable(this.values(), this.sections().flatMap(section => section.formulas));
@@ -12025,6 +12043,9 @@ class NodeAggregatedFormulasComponent {
12025
12043
  rows: table.rows.map(row => ({ ...row, node: { '@type': NodeType.Cycle, '@id': row.id } }))
12026
12044
  });
12027
12045
  }, ...(ngDevMode ? [{ debugName: "contributors" }] : []));
12046
+ // what the `$i$` of every rule stands for here, which the panel names so a reader does not have to
12047
+ // pick between the two the documentation writes
12048
+ this.contributor = computed(() => contributorNames({ worldAggregation: this.worldAggregation(), subAggregation: this.subAggregation() }), ...(ngDevMode ? [{ debugName: "contributor" }] : []));
12028
12049
  this.renderedSections = computed(() => {
12029
12050
  const values = this.values();
12030
12051
  const showValues = this.substituted() && this.hasSubstitutions();
@@ -12086,7 +12107,7 @@ class NodeAggregatedFormulasComponent {
12086
12107
  return this.ranForAggregation(formula) && this.appliesToNodeKey(formula);
12087
12108
  }
12088
12109
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NodeAggregatedFormulasComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
12089
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: NodeAggregatedFormulasComponent, isStandalone: true, selector: "he-node-aggregated-formulas", inputs: { termType: { classPropertyName: "termType", publicName: "termType", isSignal: true, isRequired: false, transformFunction: null }, termId: { classPropertyName: "termId", publicName: "termId", isSignal: true, isRequired: false, transformFunction: null }, nodeKey: { classPropertyName: "nodeKey", publicName: "nodeKey", isSignal: true, isRequired: false, transformFunction: null }, values: { classPropertyName: "values", publicName: "values", isSignal: true, isRequired: false, transformFunction: null }, worldAggregation: { classPropertyName: "worldAggregation", publicName: "worldAggregation", isSignal: true, isRequired: false, transformFunction: null }, subAggregation: { classPropertyName: "subAggregation", publicName: "subAggregation", isSignal: true, isRequired: false, transformFunction: null }, substituted: { classPropertyName: "substituted", publicName: "substituted", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { substituted: "substitutedChange" }, ngImport: i0, template: "@if (renderedSections().length) {\n <div class=\"aggregated-formulas\">\n <p class=\"is-size-7 is-mb-2 | formula-intro\">\n Aggregated values are calculated from the underlying Cycles, not measured. These are the rules that produced this\n one, in the order they are applied.\n </p>\n\n <div class=\"is-pt-2 is-pr-1 is-overflow-y-auto | aggregated-formulas-rules\">\n @for (section of renderedSections(); track section.id; let first = $first) {\n <he-formula-block\n [formulas]=\"section.formulas\"\n [heading]=\"section.heading\"\n [collapsible]=\"true\"\n [showToggle]=\"first\"\n [hasSubstitutions]=\"hasSubstitutions()\"\n [(substituted)]=\"substituted\"\n emptyTitle=\"No recorded values to substitute\" />\n\n <!-- the values combined sit between the two calculations: what went in, above how each was weighted -->\n @if (section.id === 'value' && contributors(); as table) {\n <he-collapsible-block heading=\"Values combined\">\n @if (table.rows.length) {\n <table class=\"table is-narrow is-size-7 w-100 | contributors-table\">\n <thead>\n <tr>\n <th>Cycle</th>\n @for (column of table.columns; track column.symbol) {\n <th class=\"has-text-right\">\n <span [heKatex]=\"column.symbol\" [heKatexInline]=\"true\"></span>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of table.rows; track row.id) {\n <tr>\n <td [attr.title]=\"row.id\">\n <he-node-link [node]=\"row.node\" linkClass=\"has-text-white\">\n <span class=\"break-word\">{{ row.label }}</span>\n </he-node-link>\n </td>\n @for (value of row.values; track $index) {\n <td class=\"has-text-right is-nowrap\">{{ value | precision: 4 | default: '-' }}</td>\n }\n </tr>\n }\n </tbody>\n </table>\n } @else {\n <p class=\"is-size-7\">\n Combined from {{ table.count }} Cycles, too many for the aggregation to record one by one.\n </p>\n }\n </he-collapsible-block>\n }\n }\n </div>\n </div>\n}\n", styles: [".formula-intro{opacity:.85}.contributors-table{background-color:transparent;color:inherit}.contributors-table th,.contributors-table td{border-color:#fff3;color:inherit;padding:.15rem .5rem .15rem 0;vertical-align:top}.contributors-table th{opacity:.7}.contributors-table ::ng-deep .katex{font-size:1em}.aggregated-formulas-rules{max-height:50vh}\n"], dependencies: [{ kind: "directive", type: KatexDirective, selector: "[heKatex]", inputs: ["heKatex", "heKatexInline"] }, { kind: "component", type: NodeLinkComponent, selector: "he-node-link", inputs: ["node", "dataState", "showExternalLink", "linkClass"] }, { kind: "component", type: FormulaBlockComponent, selector: "he-formula-block", inputs: ["formulas", "hasSubstitutions", "emptyTitle", "heading", "note", "showToggle", "collapsible", "open", "substituted"], outputs: ["openChange", "substitutedChange"] }, { kind: "component", type: CollapsibleBlockComponent, selector: "he-collapsible-block", inputs: ["heading", "collapsible", "open"], outputs: ["openChange"] }, { kind: "pipe", type: DefaultPipe, name: "default" }, { kind: "pipe", type: PrecisionPipe, name: "precision" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
12110
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: NodeAggregatedFormulasComponent, isStandalone: true, selector: "he-node-aggregated-formulas", inputs: { termType: { classPropertyName: "termType", publicName: "termType", isSignal: true, isRequired: false, transformFunction: null }, termId: { classPropertyName: "termId", publicName: "termId", isSignal: true, isRequired: false, transformFunction: null }, nodeKey: { classPropertyName: "nodeKey", publicName: "nodeKey", isSignal: true, isRequired: false, transformFunction: null }, values: { classPropertyName: "values", publicName: "values", isSignal: true, isRequired: false, transformFunction: null }, worldAggregation: { classPropertyName: "worldAggregation", publicName: "worldAggregation", isSignal: true, isRequired: false, transformFunction: null }, subAggregation: { classPropertyName: "subAggregation", publicName: "subAggregation", isSignal: true, isRequired: false, transformFunction: null }, substituted: { classPropertyName: "substituted", publicName: "substituted", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { substituted: "substitutedChange" }, ngImport: i0, template: "@if (renderedSections().length) {\n <div class=\"aggregated-formulas\">\n <p class=\"is-size-7 is-mb-2 | formula-intro\">\n Aggregated values are calculated from the underlying {{ contributor().group }}, not measured. These are the rules\n that produced this one, in the order they are applied.\n </p>\n\n <div class=\"is-pt-2 is-pr-1 is-overflow-y-auto | aggregated-formulas-rules\">\n @for (section of renderedSections(); track section.id; let first = $first) {\n <he-formula-block\n [formulas]=\"section.formulas\"\n [heading]=\"section.heading\"\n [collapsible]=\"true\"\n [showToggle]=\"first\"\n [hasSubstitutions]=\"hasSubstitutions()\"\n [(substituted)]=\"substituted\"\n emptyTitle=\"No recorded values to substitute\" />\n\n <!-- the contributors sit between the two calculations: what went in, above how a weight is derived -->\n @if (section.id === 'value' && contributors(); as table) {\n <he-collapsible-block [heading]=\"contributor().heading\">\n @if (table.rows.length) {\n <table class=\"table is-narrow is-size-7 w-100 | contributors-table\">\n <thead>\n <tr>\n <th>{{ contributor().row }}</th>\n @for (column of table.columns; track column.symbol) {\n <th class=\"has-text-right\">\n <span [heKatex]=\"column.symbol\" [heKatexInline]=\"true\"></span>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of table.rows; track row.id) {\n <tr>\n <td [attr.title]=\"row.id\">\n <he-node-link [node]=\"row.node\" linkClass=\"has-text-white\">\n <span class=\"break-word\">{{ row.label }}</span>\n </he-node-link>\n </td>\n @for (value of row.values; track $index) {\n <td class=\"has-text-right is-nowrap\">{{ value | precision: 4 | default: '-' }}</td>\n }\n </tr>\n }\n </tbody>\n </table>\n } @else {\n <p class=\"is-size-7\">\n Combined from {{ table.count }} {{ contributor().group }}, too many for the aggregation to record one by\n one.\n </p>\n }\n </he-collapsible-block>\n }\n }\n </div>\n </div>\n}\n", styles: [".formula-intro{opacity:.85}.contributors-table{background-color:transparent;color:inherit}.contributors-table th,.contributors-table td{border-color:#fff3;color:inherit;padding:.15rem .5rem .15rem 0;vertical-align:top}.contributors-table th{opacity:.7}.contributors-table ::ng-deep .katex{font-size:1em}.aggregated-formulas-rules{max-height:50vh}\n"], dependencies: [{ kind: "directive", type: KatexDirective, selector: "[heKatex]", inputs: ["heKatex", "heKatexInline"] }, { kind: "component", type: NodeLinkComponent, selector: "he-node-link", inputs: ["node", "dataState", "showExternalLink", "linkClass"] }, { kind: "component", type: FormulaBlockComponent, selector: "he-formula-block", inputs: ["formulas", "hasSubstitutions", "emptyTitle", "heading", "note", "showToggle", "collapsible", "open", "substituted"], outputs: ["openChange", "substitutedChange"] }, { kind: "component", type: CollapsibleBlockComponent, selector: "he-collapsible-block", inputs: ["heading", "collapsible", "open"], outputs: ["openChange"] }, { kind: "pipe", type: DefaultPipe, name: "default" }, { kind: "pipe", type: PrecisionPipe, name: "precision" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
12090
12111
  }
12091
12112
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NodeAggregatedFormulasComponent, decorators: [{
12092
12113
  type: Component$1,
@@ -12097,14 +12118,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
12097
12118
  NodeLinkComponent,
12098
12119
  FormulaBlockComponent,
12099
12120
  CollapsibleBlockComponent
12100
- ], template: "@if (renderedSections().length) {\n <div class=\"aggregated-formulas\">\n <p class=\"is-size-7 is-mb-2 | formula-intro\">\n Aggregated values are calculated from the underlying Cycles, not measured. These are the rules that produced this\n one, in the order they are applied.\n </p>\n\n <div class=\"is-pt-2 is-pr-1 is-overflow-y-auto | aggregated-formulas-rules\">\n @for (section of renderedSections(); track section.id; let first = $first) {\n <he-formula-block\n [formulas]=\"section.formulas\"\n [heading]=\"section.heading\"\n [collapsible]=\"true\"\n [showToggle]=\"first\"\n [hasSubstitutions]=\"hasSubstitutions()\"\n [(substituted)]=\"substituted\"\n emptyTitle=\"No recorded values to substitute\" />\n\n <!-- the values combined sit between the two calculations: what went in, above how each was weighted -->\n @if (section.id === 'value' && contributors(); as table) {\n <he-collapsible-block heading=\"Values combined\">\n @if (table.rows.length) {\n <table class=\"table is-narrow is-size-7 w-100 | contributors-table\">\n <thead>\n <tr>\n <th>Cycle</th>\n @for (column of table.columns; track column.symbol) {\n <th class=\"has-text-right\">\n <span [heKatex]=\"column.symbol\" [heKatexInline]=\"true\"></span>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of table.rows; track row.id) {\n <tr>\n <td [attr.title]=\"row.id\">\n <he-node-link [node]=\"row.node\" linkClass=\"has-text-white\">\n <span class=\"break-word\">{{ row.label }}</span>\n </he-node-link>\n </td>\n @for (value of row.values; track $index) {\n <td class=\"has-text-right is-nowrap\">{{ value | precision: 4 | default: '-' }}</td>\n }\n </tr>\n }\n </tbody>\n </table>\n } @else {\n <p class=\"is-size-7\">\n Combined from {{ table.count }} Cycles, too many for the aggregation to record one by one.\n </p>\n }\n </he-collapsible-block>\n }\n }\n </div>\n </div>\n}\n", styles: [".formula-intro{opacity:.85}.contributors-table{background-color:transparent;color:inherit}.contributors-table th,.contributors-table td{border-color:#fff3;color:inherit;padding:.15rem .5rem .15rem 0;vertical-align:top}.contributors-table th{opacity:.7}.contributors-table ::ng-deep .katex{font-size:1em}.aggregated-formulas-rules{max-height:50vh}\n"] }]
12121
+ ], template: "@if (renderedSections().length) {\n <div class=\"aggregated-formulas\">\n <p class=\"is-size-7 is-mb-2 | formula-intro\">\n Aggregated values are calculated from the underlying {{ contributor().group }}, not measured. These are the rules\n that produced this one, in the order they are applied.\n </p>\n\n <div class=\"is-pt-2 is-pr-1 is-overflow-y-auto | aggregated-formulas-rules\">\n @for (section of renderedSections(); track section.id; let first = $first) {\n <he-formula-block\n [formulas]=\"section.formulas\"\n [heading]=\"section.heading\"\n [collapsible]=\"true\"\n [showToggle]=\"first\"\n [hasSubstitutions]=\"hasSubstitutions()\"\n [(substituted)]=\"substituted\"\n emptyTitle=\"No recorded values to substitute\" />\n\n <!-- the contributors sit between the two calculations: what went in, above how a weight is derived -->\n @if (section.id === 'value' && contributors(); as table) {\n <he-collapsible-block [heading]=\"contributor().heading\">\n @if (table.rows.length) {\n <table class=\"table is-narrow is-size-7 w-100 | contributors-table\">\n <thead>\n <tr>\n <th>{{ contributor().row }}</th>\n @for (column of table.columns; track column.symbol) {\n <th class=\"has-text-right\">\n <span [heKatex]=\"column.symbol\" [heKatexInline]=\"true\"></span>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of table.rows; track row.id) {\n <tr>\n <td [attr.title]=\"row.id\">\n <he-node-link [node]=\"row.node\" linkClass=\"has-text-white\">\n <span class=\"break-word\">{{ row.label }}</span>\n </he-node-link>\n </td>\n @for (value of row.values; track $index) {\n <td class=\"has-text-right is-nowrap\">{{ value | precision: 4 | default: '-' }}</td>\n }\n </tr>\n }\n </tbody>\n </table>\n } @else {\n <p class=\"is-size-7\">\n Combined from {{ table.count }} {{ contributor().group }}, too many for the aggregation to record one by\n one.\n </p>\n }\n </he-collapsible-block>\n }\n }\n </div>\n </div>\n}\n", styles: [".formula-intro{opacity:.85}.contributors-table{background-color:transparent;color:inherit}.contributors-table th,.contributors-table td{border-color:#fff3;color:inherit;padding:.15rem .5rem .15rem 0;vertical-align:top}.contributors-table th{opacity:.7}.contributors-table ::ng-deep .katex{font-size:1em}.aggregated-formulas-rules{max-height:50vh}\n"] }]
12101
12122
  }], propDecorators: { termType: [{ type: i0.Input, args: [{ isSignal: true, alias: "termType", required: false }] }], termId: [{ type: i0.Input, args: [{ isSignal: true, alias: "termId", required: false }] }], nodeKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "nodeKey", required: false }] }], values: [{ type: i0.Input, args: [{ isSignal: true, alias: "values", required: false }] }], worldAggregation: [{ type: i0.Input, args: [{ isSignal: true, alias: "worldAggregation", required: false }] }], subAggregation: [{ type: i0.Input, args: [{ isSignal: true, alias: "subAggregation", required: false }] }], substituted: [{ type: i0.Input, args: [{ isSignal: true, alias: "substituted", required: false }] }, { type: i0.Output, args: ["substitutedChange"] }] } });
12102
12123
 
12103
12124
  // the `.jlog` entries the aggregation records are tagged with its own model name
12104
12125
  const JLOG_MODEL = 'aggregation';
12105
12126
  const LOGS_KEY = 'logs';
12106
12127
  // the table of contributors an aggregated value is recorded with, one row per Cycle it was
12107
- // combined from: `id:<cycle id>_value:<value>_weight:<weight>;...`
12128
+ // combined from: `id:<cycle id>_value:<value>_weight:<weight>;...`. The value column is only
12129
+ // there where the contributors are sub-aggregations - the Cycles behind one record their
12130
+ // weight alone, as there can be tens of thousands of them.
12108
12131
  const WEIGHTS_KEY = 'weights';
12109
12132
  const ID_COLUMN = 'id:';
12110
12133
  /**