@meshmakers/octo-meshboard 3.4.260 → 3.4.270
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.
|
@@ -15577,6 +15577,15 @@ const COLOR_SCHEMES = {
|
|
|
15577
15577
|
blue: (min, max) => buildGradientRanges(min, max, ['#e3f2fd', '#90caf9', '#42a5f5', '#1565c0', '#0d47a1']),
|
|
15578
15578
|
heat: (min, max) => buildGradientRanges(min, max, ['#fff9c4', '#ffcc02', '#ff9800', '#f44336', '#b71c1c'])
|
|
15579
15579
|
};
|
|
15580
|
+
/**
|
|
15581
|
+
* Fixed band colors for the `threshold` color mode: a cell equal to the target
|
|
15582
|
+
* is "ok" (green), below it "warn" (amber), above it "high" (red).
|
|
15583
|
+
*/
|
|
15584
|
+
const THRESHOLD_COLORS = Object.freeze({
|
|
15585
|
+
ok: '#2e7d32',
|
|
15586
|
+
warn: '#ffb300',
|
|
15587
|
+
high: '#c62828'
|
|
15588
|
+
});
|
|
15580
15589
|
function buildGradientRanges(min, max, colors) {
|
|
15581
15590
|
if (max <= min) {
|
|
15582
15591
|
return [{ from: min, to: min + 1, color: colors[0] }];
|
|
@@ -15927,6 +15936,17 @@ class HeatmapWidgetComponent {
|
|
|
15927
15936
|
* Assigns colors to heatmap data items based on value range and color scheme.
|
|
15928
15937
|
*/
|
|
15929
15938
|
assignColors(data) {
|
|
15939
|
+
// Threshold mode: absolute ok/warn/high bands around an expected target.
|
|
15940
|
+
// Falls back to gradient when no target can be resolved (so the widget never
|
|
15941
|
+
// renders blank just because no scope/target is configured).
|
|
15942
|
+
if ((this.config?.colorMode ?? 'gradient') === 'threshold') {
|
|
15943
|
+
const target = this.resolveThresholdTarget();
|
|
15944
|
+
if (target != null && target > 0) {
|
|
15945
|
+
for (const item of data)
|
|
15946
|
+
item.color = this.getThresholdColor(item.value, target);
|
|
15947
|
+
return;
|
|
15948
|
+
}
|
|
15949
|
+
}
|
|
15930
15950
|
const scheme = this.config?.colorScheme ?? 'green';
|
|
15931
15951
|
const nonZeroValues = data.filter(d => d.value !== 0).map(d => d.value);
|
|
15932
15952
|
if (nonZeroValues.length === 0) {
|
|
@@ -15941,6 +15961,31 @@ class HeatmapWidgetComponent {
|
|
|
15941
15961
|
item.color = this.getColorForValue(item.value, ranges);
|
|
15942
15962
|
}
|
|
15943
15963
|
}
|
|
15964
|
+
/**
|
|
15965
|
+
* Resolves the expected value per cell for `threshold` color mode. Uses the
|
|
15966
|
+
* explicit {@link HeatmapWidgetConfig.thresholdTarget} when set; otherwise
|
|
15967
|
+
* auto-derives it from the number of asset-scoped source rtIds (each scoped
|
|
15968
|
+
* source contributes one value per interval, so a "healthy" cell equals the
|
|
15969
|
+
* number of scoped sources — e.g. the EnergyMeasurements under a MeteringPoint).
|
|
15970
|
+
* Returns `null` when neither is available.
|
|
15971
|
+
*/
|
|
15972
|
+
resolveThresholdTarget() {
|
|
15973
|
+
const manual = this.config?.thresholdTarget;
|
|
15974
|
+
if (manual != null && manual > 0)
|
|
15975
|
+
return manual;
|
|
15976
|
+
const ds = this.config?.dataSource;
|
|
15977
|
+
const rtIds = this.stateService.resolveStreamDataRtIds(ds?.entitySelectorId);
|
|
15978
|
+
return rtIds && rtIds.length > 0 ? rtIds.length : null;
|
|
15979
|
+
}
|
|
15980
|
+
/**
|
|
15981
|
+
* Bands a value around the target: equal → green, below (incl. empty 0-cells)
|
|
15982
|
+
* → amber, above → red.
|
|
15983
|
+
*/
|
|
15984
|
+
getThresholdColor(value, target) {
|
|
15985
|
+
if (value === target)
|
|
15986
|
+
return THRESHOLD_COLORS.ok;
|
|
15987
|
+
return value < target ? THRESHOLD_COLORS.warn : THRESHOLD_COLORS.high;
|
|
15988
|
+
}
|
|
15944
15989
|
aggregate(values, aggregation) {
|
|
15945
15990
|
if (values.length === 0)
|
|
15946
15991
|
return 0;
|
|
@@ -16112,6 +16157,8 @@ class HeatmapConfigDialogComponent {
|
|
|
16112
16157
|
initialValueField;
|
|
16113
16158
|
initialAggregation;
|
|
16114
16159
|
initialColorScheme;
|
|
16160
|
+
initialColorMode;
|
|
16161
|
+
initialThresholdTarget;
|
|
16115
16162
|
initialShowLegend;
|
|
16116
16163
|
initialLegendPosition;
|
|
16117
16164
|
initialDecimalPlaces;
|
|
@@ -16137,6 +16184,11 @@ class HeatmapConfigDialogComponent {
|
|
|
16137
16184
|
{ value: 'sum', label: 'Sum (total of values)' },
|
|
16138
16185
|
{ value: 'avg', label: 'Average (mean of values)' }
|
|
16139
16186
|
];
|
|
16187
|
+
// Color mode options
|
|
16188
|
+
colorModeOptions = [
|
|
16189
|
+
{ value: 'gradient', label: 'Gradient' },
|
|
16190
|
+
{ value: 'threshold', label: 'Threshold' }
|
|
16191
|
+
];
|
|
16140
16192
|
// Color scheme options
|
|
16141
16193
|
colorSchemeOptions = [
|
|
16142
16194
|
{ value: 'green', label: 'Green', previewColor: '#66bb6a' },
|
|
@@ -16164,6 +16216,8 @@ class HeatmapConfigDialogComponent {
|
|
|
16164
16216
|
valueField: '',
|
|
16165
16217
|
aggregation: 'count',
|
|
16166
16218
|
colorScheme: 'green',
|
|
16219
|
+
colorMode: 'gradient',
|
|
16220
|
+
thresholdTarget: undefined,
|
|
16167
16221
|
showLegend: true,
|
|
16168
16222
|
legendPosition: 'bottom',
|
|
16169
16223
|
decimalPlaces: 2,
|
|
@@ -16193,6 +16247,8 @@ class HeatmapConfigDialogComponent {
|
|
|
16193
16247
|
this.form.valueField = this.initialValueField;
|
|
16194
16248
|
this.form.aggregation = this.initialAggregation ?? 'count';
|
|
16195
16249
|
this.form.colorScheme = this.initialColorScheme ?? 'green';
|
|
16250
|
+
this.form.colorMode = this.initialColorMode ?? 'gradient';
|
|
16251
|
+
this.form.thresholdTarget = this.initialThresholdTarget;
|
|
16196
16252
|
this.form.showLegend = this.initialShowLegend ?? true;
|
|
16197
16253
|
this.form.legendPosition = this.initialLegendPosition ?? 'bottom';
|
|
16198
16254
|
this.form.decimalPlaces = this.initialDecimalPlaces ?? 2;
|
|
@@ -16323,6 +16379,8 @@ class HeatmapConfigDialogComponent {
|
|
|
16323
16379
|
valueField: this.form.valueField || undefined,
|
|
16324
16380
|
aggregation: this.form.aggregation,
|
|
16325
16381
|
colorScheme: this.form.colorScheme,
|
|
16382
|
+
colorMode: this.form.colorMode,
|
|
16383
|
+
thresholdTarget: this.form.colorMode === 'threshold' ? (this.form.thresholdTarget ?? undefined) : undefined,
|
|
16326
16384
|
showLegend: this.form.showLegend,
|
|
16327
16385
|
legendPosition: this.form.legendPosition,
|
|
16328
16386
|
decimalPlaces: this.form.decimalPlaces,
|
|
@@ -16336,7 +16394,7 @@ class HeatmapConfigDialogComponent {
|
|
|
16336
16394
|
this.windowRef.close();
|
|
16337
16395
|
}
|
|
16338
16396
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: HeatmapConfigDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
16339
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: HeatmapConfigDialogComponent, isStandalone: true, selector: "mm-heatmap-config-dialog", inputs: { initialQueryRtId: "initialQueryRtId", initialQueryName: "initialQueryName", initialQueryFamily: "initialQueryFamily", initialIgnoreTimeFilter: "initialIgnoreTimeFilter", initialEntitySelectorId: "initialEntitySelectorId", initialDateField: "initialDateField", initialDateEndField: "initialDateEndField", initialValueField: "initialValueField", initialAggregation: "initialAggregation", initialColorScheme: "initialColorScheme", initialShowLegend: "initialShowLegend", initialLegendPosition: "initialLegendPosition", initialDecimalPlaces: "initialDecimalPlaces", initialCompactNumbers: "initialCompactNumbers", initialValueMultiplier: "initialValueMultiplier", initialFilters: "initialFilters" }, viewQueries: [{ propertyName: "querySelector", first: true, predicate: ["querySelector"], descendants: true }], ngImport: i0, template: `
|
|
16397
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: HeatmapConfigDialogComponent, isStandalone: true, selector: "mm-heatmap-config-dialog", inputs: { initialQueryRtId: "initialQueryRtId", initialQueryName: "initialQueryName", initialQueryFamily: "initialQueryFamily", initialIgnoreTimeFilter: "initialIgnoreTimeFilter", initialEntitySelectorId: "initialEntitySelectorId", initialDateField: "initialDateField", initialDateEndField: "initialDateEndField", initialValueField: "initialValueField", initialAggregation: "initialAggregation", initialColorScheme: "initialColorScheme", initialColorMode: "initialColorMode", initialThresholdTarget: "initialThresholdTarget", initialShowLegend: "initialShowLegend", initialLegendPosition: "initialLegendPosition", initialDecimalPlaces: "initialDecimalPlaces", initialCompactNumbers: "initialCompactNumbers", initialValueMultiplier: "initialValueMultiplier", initialFilters: "initialFilters" }, viewQueries: [{ propertyName: "querySelector", first: true, predicate: ["querySelector"], descendants: true }], ngImport: i0, template: `
|
|
16340
16398
|
<div class="config-container">
|
|
16341
16399
|
|
|
16342
16400
|
<div class="config-form" [class.loading]="isLoadingInitial">
|
|
@@ -16467,24 +16525,63 @@ class HeatmapConfigDialogComponent {
|
|
|
16467
16525
|
<h3 class="section-title">Display Options</h3>
|
|
16468
16526
|
|
|
16469
16527
|
<div class="form-field">
|
|
16470
|
-
<label>Color
|
|
16528
|
+
<label>Color Mode</label>
|
|
16471
16529
|
<div class="color-scheme-grid">
|
|
16472
|
-
@for (
|
|
16530
|
+
@for (mode of colorModeOptions; track mode.value) {
|
|
16473
16531
|
<label class="radio-label">
|
|
16474
16532
|
<input type="radio"
|
|
16475
|
-
name="
|
|
16476
|
-
[value]="
|
|
16477
|
-
[(ngModel)]="form.
|
|
16533
|
+
name="colorMode"
|
|
16534
|
+
[value]="mode.value"
|
|
16535
|
+
[(ngModel)]="form.colorMode"
|
|
16478
16536
|
kendoRadioButton />
|
|
16479
|
-
<span class="color-scheme-preview">
|
|
16480
|
-
<span class="color-swatch" [style.background]="scheme.previewColor"></span>
|
|
16481
|
-
{{ scheme.label }}
|
|
16482
|
-
</span>
|
|
16537
|
+
<span class="color-scheme-preview">{{ mode.label }}</span>
|
|
16483
16538
|
</label>
|
|
16484
16539
|
}
|
|
16485
16540
|
</div>
|
|
16541
|
+
<p class="field-hint">
|
|
16542
|
+
Gradient colors relative to the data's min/max. Threshold colors each cell
|
|
16543
|
+
against an expected count: equal = green, below (incl. empty) = amber, above = red.
|
|
16544
|
+
</p>
|
|
16486
16545
|
</div>
|
|
16487
16546
|
|
|
16547
|
+
@if (form.colorMode === 'gradient') {
|
|
16548
|
+
<div class="form-field">
|
|
16549
|
+
<label>Color Scheme</label>
|
|
16550
|
+
<div class="color-scheme-grid">
|
|
16551
|
+
@for (scheme of colorSchemeOptions; track scheme.value) {
|
|
16552
|
+
<label class="radio-label">
|
|
16553
|
+
<input type="radio"
|
|
16554
|
+
name="colorScheme"
|
|
16555
|
+
[value]="scheme.value"
|
|
16556
|
+
[(ngModel)]="form.colorScheme"
|
|
16557
|
+
kendoRadioButton />
|
|
16558
|
+
<span class="color-scheme-preview">
|
|
16559
|
+
<span class="color-swatch" [style.background]="scheme.previewColor"></span>
|
|
16560
|
+
{{ scheme.label }}
|
|
16561
|
+
</span>
|
|
16562
|
+
</label>
|
|
16563
|
+
}
|
|
16564
|
+
</div>
|
|
16565
|
+
</div>
|
|
16566
|
+
} @else {
|
|
16567
|
+
<div class="form-field">
|
|
16568
|
+
<label>Target Value</label>
|
|
16569
|
+
<kendo-numerictextbox
|
|
16570
|
+
[(ngModel)]="form.thresholdTarget"
|
|
16571
|
+
[min]="0"
|
|
16572
|
+
[step]="1"
|
|
16573
|
+
[decimals]="0"
|
|
16574
|
+
format="n0"
|
|
16575
|
+
placeholder="Auto (number of scoped sources)">
|
|
16576
|
+
</kendo-numerictextbox>
|
|
16577
|
+
<p class="field-hint">
|
|
16578
|
+
Expected value per cell. Leave empty to auto-derive it from the number of
|
|
16579
|
+
asset-scoped sources (e.g. the EnergyMeasurements under the picked MeteringPoint),
|
|
16580
|
+
which requires a "Scope to entity selector" binding above.
|
|
16581
|
+
</p>
|
|
16582
|
+
</div>
|
|
16583
|
+
}
|
|
16584
|
+
|
|
16488
16585
|
<div class="form-field">
|
|
16489
16586
|
<label>Decimal Places</label>
|
|
16490
16587
|
<kendo-numerictextbox
|
|
@@ -16703,24 +16800,63 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
16703
16800
|
<h3 class="section-title">Display Options</h3>
|
|
16704
16801
|
|
|
16705
16802
|
<div class="form-field">
|
|
16706
|
-
<label>Color
|
|
16803
|
+
<label>Color Mode</label>
|
|
16707
16804
|
<div class="color-scheme-grid">
|
|
16708
|
-
@for (
|
|
16805
|
+
@for (mode of colorModeOptions; track mode.value) {
|
|
16709
16806
|
<label class="radio-label">
|
|
16710
16807
|
<input type="radio"
|
|
16711
|
-
name="
|
|
16712
|
-
[value]="
|
|
16713
|
-
[(ngModel)]="form.
|
|
16808
|
+
name="colorMode"
|
|
16809
|
+
[value]="mode.value"
|
|
16810
|
+
[(ngModel)]="form.colorMode"
|
|
16714
16811
|
kendoRadioButton />
|
|
16715
|
-
<span class="color-scheme-preview">
|
|
16716
|
-
<span class="color-swatch" [style.background]="scheme.previewColor"></span>
|
|
16717
|
-
{{ scheme.label }}
|
|
16718
|
-
</span>
|
|
16812
|
+
<span class="color-scheme-preview">{{ mode.label }}</span>
|
|
16719
16813
|
</label>
|
|
16720
16814
|
}
|
|
16721
16815
|
</div>
|
|
16816
|
+
<p class="field-hint">
|
|
16817
|
+
Gradient colors relative to the data's min/max. Threshold colors each cell
|
|
16818
|
+
against an expected count: equal = green, below (incl. empty) = amber, above = red.
|
|
16819
|
+
</p>
|
|
16722
16820
|
</div>
|
|
16723
16821
|
|
|
16822
|
+
@if (form.colorMode === 'gradient') {
|
|
16823
|
+
<div class="form-field">
|
|
16824
|
+
<label>Color Scheme</label>
|
|
16825
|
+
<div class="color-scheme-grid">
|
|
16826
|
+
@for (scheme of colorSchemeOptions; track scheme.value) {
|
|
16827
|
+
<label class="radio-label">
|
|
16828
|
+
<input type="radio"
|
|
16829
|
+
name="colorScheme"
|
|
16830
|
+
[value]="scheme.value"
|
|
16831
|
+
[(ngModel)]="form.colorScheme"
|
|
16832
|
+
kendoRadioButton />
|
|
16833
|
+
<span class="color-scheme-preview">
|
|
16834
|
+
<span class="color-swatch" [style.background]="scheme.previewColor"></span>
|
|
16835
|
+
{{ scheme.label }}
|
|
16836
|
+
</span>
|
|
16837
|
+
</label>
|
|
16838
|
+
}
|
|
16839
|
+
</div>
|
|
16840
|
+
</div>
|
|
16841
|
+
} @else {
|
|
16842
|
+
<div class="form-field">
|
|
16843
|
+
<label>Target Value</label>
|
|
16844
|
+
<kendo-numerictextbox
|
|
16845
|
+
[(ngModel)]="form.thresholdTarget"
|
|
16846
|
+
[min]="0"
|
|
16847
|
+
[step]="1"
|
|
16848
|
+
[decimals]="0"
|
|
16849
|
+
format="n0"
|
|
16850
|
+
placeholder="Auto (number of scoped sources)">
|
|
16851
|
+
</kendo-numerictextbox>
|
|
16852
|
+
<p class="field-hint">
|
|
16853
|
+
Expected value per cell. Leave empty to auto-derive it from the number of
|
|
16854
|
+
asset-scoped sources (e.g. the EnergyMeasurements under the picked MeteringPoint),
|
|
16855
|
+
which requires a "Scope to entity selector" binding above.
|
|
16856
|
+
</p>
|
|
16857
|
+
</div>
|
|
16858
|
+
}
|
|
16859
|
+
|
|
16724
16860
|
<div class="form-field">
|
|
16725
16861
|
<label>Decimal Places</label>
|
|
16726
16862
|
<kendo-numerictextbox
|
|
@@ -16816,6 +16952,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
16816
16952
|
type: Input
|
|
16817
16953
|
}], initialColorScheme: [{
|
|
16818
16954
|
type: Input
|
|
16955
|
+
}], initialColorMode: [{
|
|
16956
|
+
type: Input
|
|
16957
|
+
}], initialThresholdTarget: [{
|
|
16958
|
+
type: Input
|
|
16819
16959
|
}], initialShowLegend: [{
|
|
16820
16960
|
type: Input
|
|
16821
16961
|
}], initialLegendPosition: [{
|
|
@@ -29051,6 +29191,8 @@ function registerDefaultWidgets(registry) {
|
|
|
29051
29191
|
initialValueField: heatmapWidget.valueField,
|
|
29052
29192
|
initialAggregation: heatmapWidget.aggregation,
|
|
29053
29193
|
initialColorScheme: heatmapWidget.colorScheme,
|
|
29194
|
+
initialColorMode: heatmapWidget.colorMode,
|
|
29195
|
+
initialThresholdTarget: heatmapWidget.thresholdTarget,
|
|
29054
29196
|
initialShowLegend: heatmapWidget.showLegend,
|
|
29055
29197
|
initialLegendPosition: heatmapWidget.legendPosition,
|
|
29056
29198
|
initialDecimalPlaces: heatmapWidget.decimalPlaces,
|
|
@@ -29081,6 +29223,8 @@ function registerDefaultWidgets(registry) {
|
|
|
29081
29223
|
valueField: result.valueField,
|
|
29082
29224
|
aggregation: result.aggregation,
|
|
29083
29225
|
colorScheme: result.colorScheme,
|
|
29226
|
+
colorMode: result.colorMode,
|
|
29227
|
+
thresholdTarget: result.thresholdTarget,
|
|
29084
29228
|
showLegend: result.showLegend,
|
|
29085
29229
|
legendPosition: result.legendPosition,
|
|
29086
29230
|
decimalPlaces: result.decimalPlaces,
|
|
@@ -29112,6 +29256,8 @@ function registerDefaultWidgets(registry) {
|
|
|
29112
29256
|
valueField: widget.valueField,
|
|
29113
29257
|
aggregation: widget.aggregation,
|
|
29114
29258
|
colorScheme: widget.colorScheme,
|
|
29259
|
+
...(widget.colorMode && { colorMode: widget.colorMode }),
|
|
29260
|
+
...(widget.thresholdTarget != null && { thresholdTarget: widget.thresholdTarget }),
|
|
29115
29261
|
showLegend: widget.showLegend,
|
|
29116
29262
|
legendPosition: widget.legendPosition,
|
|
29117
29263
|
decimalPlaces: widget.decimalPlaces,
|
|
@@ -29145,6 +29291,8 @@ function registerDefaultWidgets(registry) {
|
|
|
29145
29291
|
valueField: config['valueField'],
|
|
29146
29292
|
aggregation: config['aggregation'] ?? 'count',
|
|
29147
29293
|
colorScheme: config['colorScheme'] ?? 'green',
|
|
29294
|
+
colorMode: config['colorMode'],
|
|
29295
|
+
thresholdTarget: config['thresholdTarget'],
|
|
29148
29296
|
showLegend: config['showLegend'] ?? true,
|
|
29149
29297
|
legendPosition: config['legendPosition'] ?? 'bottom',
|
|
29150
29298
|
decimalPlaces: config['decimalPlaces'],
|