@hestia-earth/ui-components 0.37.2 → 0.38.0
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/fesm2022/hestia-earth-ui-components.mjs +843 -903
- package/fesm2022/hestia-earth-ui-components.mjs.map +1 -1
- package/index.d.ts +1497 -169
- package/package.json +4 -2
|
@@ -6,17 +6,19 @@ import { UntypedFormBuilder, Validators, FormsModule, ReactiveFormsModule, NG_VA
|
|
|
6
6
|
import { NgTemplateOutlet, NgClass, DecimalPipe, KeyValuePipe, DOCUMENT, PlatformLocation, NgStyle, UpperCasePipe, JsonPipe, DatePipe, AsyncPipe } from '@angular/common';
|
|
7
7
|
import * as i1$2 from '@ng-bootstrap/ng-bootstrap';
|
|
8
8
|
import { NgbActiveModal, NgbHighlight, NgbTooltip, NgbDropdown, NgbDropdownMenu, NgbDropdownToggle, NgbDropdownItem, NgbTypeahead, NgbPopover, NgbModal, NgbTooltipModule, NgbDropdownModule, NgbPopoverModule } from '@ng-bootstrap/ng-bootstrap';
|
|
9
|
-
import { catchError, map, debounceTime, distinctUntilChanged, tap, switchMap, mergeMap, shareReplay, delay, take, first, filter,
|
|
10
|
-
import { of, zip, ReplaySubject, timer, Subject, combineLatest, pipe,
|
|
9
|
+
import { catchError, map, debounceTime, distinctUntilChanged, tap, switchMap, startWith, mergeMap, shareReplay, delay, take, first, filter, skip, throttleTime, skipUntil, reduce, mergeAll, toArray, distinct, groupBy } from 'rxjs/operators';
|
|
10
|
+
import { of, zip, fromEvent, ReplaySubject, timer, Subject, combineLatest, pipe, merge as merge$1, EMPTY, animationFrameScheduler, forkJoin, from } from 'rxjs';
|
|
11
11
|
import { HttpClient } from '@angular/common/http';
|
|
12
12
|
import get from 'lodash.get';
|
|
13
13
|
import { SCHEMA_VERSION, SchemaType, NodeType, TermTermType, productTermTermType, nestedSearchableKeys, SiteSiteType, EmissionMethodTier, isExpandable, sortKeysByType, isTypeNode, BlankNodesKey, impactAssessmentTermTermType, measurementTermTermType, emissionTermTermType, inputTermTermType, CycleFunctionalUnit, NonBlankNodesKey, jsonldPath, isTypeValid, isTypeBlankNode, typeToSchemaType, managementTermTermType } from '@hestia-earth/schema';
|
|
14
|
-
import { toPrecision,
|
|
14
|
+
import { isUndefined, isEmpty, toPrecision, ellipsis as ellipsis$1, sum, toComma, isNumber, getPercentileValue, unique, monthsBefore, keyToLabel, isEqual as isEqual$2, max, toDashCase, diffInDays } from '@hestia-earth/utils';
|
|
15
15
|
import Gradient from 'javascript-color-gradient';
|
|
16
16
|
import { ShadeGenerator } from 'shade-generator/dist/shadeGenerator';
|
|
17
|
-
import Chart,
|
|
18
|
-
import
|
|
17
|
+
import { Chart, BarController, LineController, CategoryScale, LinearScale, PointElement, BarElement, LineElement, Title, Tooltip, Legend, TimeScale } from 'chart.js';
|
|
18
|
+
import C2S from 'canvas-to-svg';
|
|
19
19
|
import merge from 'lodash.merge';
|
|
20
|
+
import 'chartjs-adapter-date-fns';
|
|
21
|
+
import { BreakpointObserver } from '@angular/cdk/layout';
|
|
20
22
|
import { select, selectAll } from 'd3-selection';
|
|
21
23
|
import { json2csv } from 'json-2-csv';
|
|
22
24
|
import { propertyValue as propertyValue$1, emptyValue } from '@hestia-earth/utils/dist/term';
|
|
@@ -30,12 +32,11 @@ import { trigger, state, transition, style, animate } from '@angular/animations'
|
|
|
30
32
|
import { signalStore, withState, withComputed, withMethods, patchState, withHooks } from '@ngrx/signals';
|
|
31
33
|
import { rxMethod } from '@ngrx/signals/rxjs-interop';
|
|
32
34
|
import { RouterLinkActive, RouterLink, ActivatedRoute } from '@angular/router';
|
|
33
|
-
import { BreakpointObserver } from '@angular/cdk/layout';
|
|
34
35
|
import { GoogleMap, MapMarker, MapPolygon } from '@angular/google-maps';
|
|
35
36
|
import { Meta, DomSanitizer } from '@angular/platform-browser';
|
|
36
37
|
import removeMd from 'remove-markdown';
|
|
37
38
|
import orderBy from 'lodash.orderby';
|
|
38
|
-
import { headersFromCsv, toCsv, toJson, toCsvPivot, ErrorKeys
|
|
39
|
+
import { headersFromCsv, toCsv, toJson, toCsvPivot, ErrorKeys } from '@hestia-earth/schema-convert';
|
|
39
40
|
import { moveItemInArray, CdkDropList, CdkDrag } from '@angular/cdk/drag-drop';
|
|
40
41
|
import { isCSVIncluded, isDefaultCSVSelected } from '@hestia-earth/json-schema/schema-utils';
|
|
41
42
|
import { recommendedProperties, loadSchemas } from '@hestia-earth/json-schema';
|
|
@@ -592,16 +593,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImpo
|
|
|
592
593
|
}], ctorParameters: () => [], propDecorators: { search: [{ type: i0.Input, args: [{ isSignal: true, alias: "search", required: false }] }, { type: i0.Output, args: ["searchChange"] }], searchSources: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchSources", required: false }] }, { type: i0.Output, args: ["searchSourcesChange"] }], searchBibliographies: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchBibliographies", required: false }] }, { type: i0.Output, args: ["searchBibliographiesChange"] }], searchBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchBy", required: false }] }, { type: i0.Output, args: ["searchByChange"] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
|
|
593
594
|
|
|
594
595
|
const defaultBarDrawSettings = {
|
|
595
|
-
xPosFn: x => x + 10,
|
|
596
|
+
xPosFn: (x, index, width, chart, data) => (data < 0 || isEmpty(data) ? chart.scales.x.getPixelForValue(0) : x) + 10,
|
|
596
597
|
yPosFn: y => y + 3,
|
|
597
|
-
colorFn: () => '
|
|
598
|
-
textFn:
|
|
598
|
+
colorFn: (m, index, chart, data) => (isUndefined(data) ? '#b5b5b5' : '#4a4a4a'),
|
|
599
|
+
textFn: ({ data }) => `${data}`,
|
|
599
600
|
font: '14px Lato',
|
|
600
601
|
maxWidth: 90,
|
|
601
602
|
emptyValueLabel: 'No data'
|
|
602
603
|
};
|
|
603
604
|
const afterBarDrawPlugin = settings => ({
|
|
604
|
-
|
|
605
|
+
id: 'afterBarDrawPlugin',
|
|
606
|
+
afterDatasetsDraw: (chart) => {
|
|
605
607
|
if (!chart.data.datasets?.length) {
|
|
606
608
|
return;
|
|
607
609
|
}
|
|
@@ -609,23 +611,23 @@ const afterBarDrawPlugin = settings => ({
|
|
|
609
611
|
...defaultBarDrawSettings,
|
|
610
612
|
...(settings ?? {})
|
|
611
613
|
};
|
|
612
|
-
const { ctx } = chart;
|
|
614
|
+
const { ctx, width, height } = chart;
|
|
613
615
|
ctx.save();
|
|
614
|
-
const
|
|
615
|
-
const
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
.
|
|
619
|
-
.forEach((
|
|
620
|
-
const { x, y } =
|
|
621
|
-
const label =
|
|
622
|
-
const data =
|
|
616
|
+
const meta = chart.getDatasetMeta(0);
|
|
617
|
+
const dataset = chart.data.datasets[0];
|
|
618
|
+
const elements = meta.data;
|
|
619
|
+
elements
|
|
620
|
+
.filter(element => !element.skip)
|
|
621
|
+
.forEach((element, index) => {
|
|
622
|
+
const { x, y } = element;
|
|
623
|
+
const label = chart.data.labels?.[index] ?? '';
|
|
624
|
+
const data = dataset.data[index];
|
|
623
625
|
const xPos = xPosFn(x, index, width, chart, data);
|
|
624
626
|
const yPos = yPosFn(y, index, height, chart, data);
|
|
625
627
|
const text = isUndefined(data) ? emptyValueLabel : textFn({ label, data }, index, chart);
|
|
626
628
|
if (text) {
|
|
627
629
|
ctx.font = font;
|
|
628
|
-
ctx.fillStyle = colorFn(
|
|
630
|
+
ctx.fillStyle = colorFn(element.options, index, chart, data);
|
|
629
631
|
if (Array.isArray(text)) {
|
|
630
632
|
ctx.fillText(text[0], xPos, yPos - 5, maxWidth);
|
|
631
633
|
ctx.fillText(text[1], xPos, yPos + 5, maxWidth);
|
|
@@ -736,6 +738,7 @@ const hexToRgba = (hex, aplha = 1) => {
|
|
|
736
738
|
};
|
|
737
739
|
const listColorWithAlpha = (alpha = 0.8) => (_v, index) => hexToRgba(getColor(index), alpha);
|
|
738
740
|
|
|
741
|
+
// ... createHoverGradient remains the same ...
|
|
739
742
|
const createHoverGradient = (ctx, chartArea, color) => {
|
|
740
743
|
const gradient = ctx.createLinearGradient(chartArea.left, 0, chartArea.right, 0);
|
|
741
744
|
gradient.addColorStop(0, colorToRgba(color, 0.05));
|
|
@@ -743,34 +746,53 @@ const createHoverGradient = (ctx, chartArea, color) => {
|
|
|
743
746
|
gradient.addColorStop(1, colorToRgba(color, 0.05));
|
|
744
747
|
return gradient;
|
|
745
748
|
};
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
const
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
749
|
+
// UPDATED: Use element properties instead of _model
|
|
750
|
+
const calculateBarBounds = (element, indexAxis = 'y') => {
|
|
751
|
+
const { x, y, base, width, height } = element;
|
|
752
|
+
// Handle Horizontal Bars (indexAxis: 'y')
|
|
753
|
+
if (indexAxis === 'y') {
|
|
754
|
+
const barHeight = height; // Thickness of the bar
|
|
755
|
+
const barTop = y - barHeight / 2;
|
|
756
|
+
const barBottom = y + barHeight / 2;
|
|
757
|
+
const barLeft = Math.min(base, x);
|
|
758
|
+
const barRight = Math.max(base, x);
|
|
759
|
+
return { barLeft, barRight, barTop, barBottom, thickness: barHeight };
|
|
760
|
+
}
|
|
761
|
+
// Handle Vertical Bars (indexAxis: 'x')
|
|
762
|
+
else {
|
|
763
|
+
const barWidth = width; // Thickness of the bar
|
|
764
|
+
const barLeft = x - barWidth / 2;
|
|
765
|
+
const barRight = x + barWidth / 2;
|
|
766
|
+
const barTop = Math.min(base, y);
|
|
767
|
+
const barBottom = Math.max(base, y);
|
|
768
|
+
return { barLeft, barRight, barTop, barBottom, thickness: barWidth };
|
|
769
|
+
}
|
|
770
|
+
};
|
|
771
|
+
// UPDATED: Calculate shadow bounds based on the bounds we just found
|
|
772
|
+
const calculateShadowBounds = (element, bounds, threshold) => {
|
|
756
773
|
return {
|
|
757
|
-
top: barTop - threshold,
|
|
758
|
-
bottom: barBottom + threshold,
|
|
759
|
-
left:
|
|
760
|
-
right:
|
|
761
|
-
width:
|
|
762
|
-
height: barBottom + threshold - (barTop - threshold)
|
|
774
|
+
top: bounds.barTop - threshold,
|
|
775
|
+
bottom: bounds.barBottom + threshold,
|
|
776
|
+
left: bounds.barLeft, // Usually we expand Y (thickness), but keep X (length) capped at value
|
|
777
|
+
right: bounds.barRight,
|
|
778
|
+
width: bounds.barRight - bounds.barLeft,
|
|
779
|
+
height: bounds.barBottom + threshold - (bounds.barTop - threshold)
|
|
763
780
|
};
|
|
764
781
|
};
|
|
765
|
-
const drawHoverEffect = (ctx, chartArea,
|
|
766
|
-
|
|
782
|
+
const drawHoverEffect = (ctx, chartArea, element, threshold, indexAxis) => {
|
|
783
|
+
// Access colors via options
|
|
784
|
+
const opts = element.options || null;
|
|
785
|
+
const barColor = (opts?.backgroundColor || opts?.borderColor || '#000000');
|
|
767
786
|
const color = parseColor(barColor);
|
|
768
|
-
const bounds =
|
|
787
|
+
const bounds = calculateBarBounds(element, indexAxis);
|
|
788
|
+
const shadow = calculateShadowBounds(element, bounds, threshold);
|
|
769
789
|
ctx.save();
|
|
770
|
-
|
|
790
|
+
// Draw Gradient Background
|
|
791
|
+
const gradient = createHoverGradient(ctx, { left: shadow.left, right: shadow.right }, color);
|
|
771
792
|
ctx.fillStyle = gradient;
|
|
772
|
-
ctx.fillRect(
|
|
773
|
-
|
|
793
|
+
ctx.fillRect(shadow.left, shadow.top, shadow.width, shadow.height);
|
|
794
|
+
// Draw Dashed Lines
|
|
795
|
+
drawHorizontalLines(ctx, { left: shadow.left, right: shadow.right }, shadow.top, shadow.bottom, color);
|
|
774
796
|
ctx.restore();
|
|
775
797
|
};
|
|
776
798
|
const drawHorizontalLines = (ctx, barArea, topY, bottomY, color) => {
|
|
@@ -784,45 +806,36 @@ const drawHorizontalLines = (ctx, barArea, topY, bottomY, color) => {
|
|
|
784
806
|
ctx.lineTo(barArea.right, bottomY);
|
|
785
807
|
ctx.stroke();
|
|
786
808
|
};
|
|
787
|
-
|
|
788
|
-
const barLeft = Math.min(model.base || 0, model.x);
|
|
789
|
-
const barRight = Math.max(model.base || 0, model.x);
|
|
790
|
-
const barHeight = model.height || 20;
|
|
791
|
-
const barTop = model.y - barHeight / 2;
|
|
792
|
-
const barBottom = model.y + barHeight / 2;
|
|
793
|
-
return { barLeft, barRight, barTop, barBottom };
|
|
794
|
-
};
|
|
809
|
+
// UPDATED: Distance calculation using the new bounds
|
|
795
810
|
const calculateDistanceToBar = (x, y, bounds) => {
|
|
796
811
|
let distance = 0;
|
|
797
|
-
|
|
812
|
+
// Horizontal distance
|
|
813
|
+
if (x < bounds.barLeft)
|
|
798
814
|
distance += Math.pow(bounds.barLeft - x, 2);
|
|
799
|
-
|
|
800
|
-
else if (x > bounds.barRight) {
|
|
815
|
+
else if (x > bounds.barRight)
|
|
801
816
|
distance += Math.pow(x - bounds.barRight, 2);
|
|
802
|
-
|
|
803
|
-
if (y < bounds.barTop)
|
|
817
|
+
// Vertical distance
|
|
818
|
+
if (y < bounds.barTop)
|
|
804
819
|
distance += Math.pow(bounds.barTop - y, 2);
|
|
805
|
-
|
|
806
|
-
else if (y > bounds.barBottom) {
|
|
820
|
+
else if (y > bounds.barBottom)
|
|
807
821
|
distance += Math.pow(y - bounds.barBottom, 2);
|
|
808
|
-
}
|
|
809
822
|
return Math.sqrt(distance);
|
|
810
823
|
};
|
|
824
|
+
// UPDATED: Hit area check
|
|
811
825
|
const isWithinHitArea = (x, y, bounds, threshold) => {
|
|
812
826
|
const hitLeft = bounds.barLeft - threshold;
|
|
813
827
|
const hitRight = bounds.barRight + threshold;
|
|
814
828
|
const hitTop = bounds.barTop - threshold;
|
|
815
829
|
const hitBottom = bounds.barBottom + threshold;
|
|
816
|
-
|
|
817
|
-
const withinVertical = y >= hitTop && y <= hitBottom;
|
|
818
|
-
return withinHorizontal && withinVertical;
|
|
830
|
+
return x >= hitLeft && x <= hitRight && y >= hitTop && y <= hitBottom;
|
|
819
831
|
};
|
|
820
|
-
const checkBarProximity = (element,
|
|
832
|
+
const checkBarProximity = (element, // Raw element
|
|
833
|
+
index, datasetIndex, x, y, threshold, currentClosest, indexAxis) => {
|
|
821
834
|
const bar = element;
|
|
822
|
-
|
|
823
|
-
if (
|
|
835
|
+
// V4 Safety check: Ensure the element has been drawn (has x/y)
|
|
836
|
+
if (bar.x == null || bar.y == null)
|
|
824
837
|
return;
|
|
825
|
-
const bounds = calculateBarBounds(
|
|
838
|
+
const bounds = calculateBarBounds(bar, indexAxis);
|
|
826
839
|
if (!isWithinHitArea(x, y, bounds, threshold))
|
|
827
840
|
return;
|
|
828
841
|
const distance = calculateDistanceToBar(x, y, bounds);
|
|
@@ -831,109 +844,115 @@ const checkBarProximity = (element, index, datasetIndex, x, y, threshold, curren
|
|
|
831
844
|
currentClosest.bar = {
|
|
832
845
|
datasetIndex,
|
|
833
846
|
index,
|
|
834
|
-
|
|
847
|
+
element: bar // Save the whole element
|
|
835
848
|
};
|
|
836
849
|
}
|
|
837
850
|
};
|
|
838
851
|
const findNearBar = (chart, x, y, threshold) => {
|
|
839
852
|
const closest = { bar: null, distance: Infinity };
|
|
853
|
+
// Determine orientation (horizontal bar vs vertical bar)
|
|
854
|
+
const indexAxis = chart.options.indexAxis || 'x';
|
|
840
855
|
chart.data.datasets?.forEach((dataset, datasetIndex) => {
|
|
856
|
+
// V4 Visibility check
|
|
857
|
+
if (!chart.isDatasetVisible(datasetIndex))
|
|
858
|
+
return;
|
|
841
859
|
const meta = chart.getDatasetMeta(datasetIndex);
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
860
|
+
meta.data.forEach((element, index) => {
|
|
861
|
+
// Skip hidden/skipped elements
|
|
862
|
+
if (element.hidden || element.skip)
|
|
863
|
+
return;
|
|
864
|
+
checkBarProximity(element, index, datasetIndex, x, y, threshold, closest, indexAxis);
|
|
865
|
+
});
|
|
847
866
|
});
|
|
848
867
|
return closest.distance <= threshold ? closest.bar : undefined;
|
|
849
868
|
};
|
|
850
869
|
const triggerBarClick = (chart, barData) => {
|
|
851
|
-
const
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
870
|
+
const activeElements = [
|
|
871
|
+
{
|
|
872
|
+
element: barData.element,
|
|
873
|
+
datasetIndex: barData.datasetIndex,
|
|
874
|
+
index: barData.index
|
|
875
|
+
}
|
|
876
|
+
];
|
|
877
|
+
// 1. Highlight visually
|
|
878
|
+
chart.setActiveElements(activeElements);
|
|
879
|
+
// 2. Show Tooltip
|
|
880
|
+
chart.tooltip?.setActiveElements(activeElements, { x: 0, y: 0 });
|
|
881
|
+
// 3. Fire Click Callback
|
|
882
|
+
const onClickHandler = chart.options.onClick;
|
|
883
|
+
if (onClickHandler) {
|
|
863
884
|
const mockEvent = {
|
|
864
885
|
type: 'click',
|
|
865
|
-
x: barData.
|
|
866
|
-
y: barData.
|
|
886
|
+
x: barData.element.x,
|
|
887
|
+
y: barData.element.y,
|
|
888
|
+
chart: chart,
|
|
867
889
|
native: {
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
}
|
|
872
|
-
originalEvent: {
|
|
873
|
-
offsetX: barData.model.x,
|
|
874
|
-
offsetY: barData.model.y,
|
|
875
|
-
clientX: barData.model.x,
|
|
876
|
-
clientY: barData.model.y,
|
|
877
|
-
target: chart.canvas
|
|
878
|
-
},
|
|
879
|
-
target: chart.canvas
|
|
890
|
+
target: chart.canvas,
|
|
891
|
+
preventDefault: () => { },
|
|
892
|
+
stopPropagation: () => { }
|
|
893
|
+
}
|
|
880
894
|
};
|
|
881
|
-
|
|
895
|
+
onClickHandler.call(chart, mockEvent, activeElements, chart);
|
|
882
896
|
}
|
|
883
897
|
chart.update();
|
|
884
898
|
};
|
|
885
899
|
const handleMouseMove = (chart, nearBar, threshold, e) => {
|
|
900
|
+
// Return object
|
|
886
901
|
const newNearBar = findNearBar(chart, e.x, e.y, threshold);
|
|
887
|
-
chart.canvas.style.cursor
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
902
|
+
const prevCursor = chart.canvas.style.cursor;
|
|
903
|
+
const newCursor = newNearBar ? 'pointer' : 'default';
|
|
904
|
+
// Optimization: Only touch DOM if necessary
|
|
905
|
+
if (prevCursor !== newCursor) {
|
|
906
|
+
chart.canvas.style.cursor = newCursor;
|
|
907
|
+
}
|
|
908
|
+
// Check if the "near bar" target has changed
|
|
909
|
+
const hasChanged = newNearBar?.datasetIndex !== nearBar?.datasetIndex || newNearBar?.index !== nearBar?.index;
|
|
910
|
+
return {
|
|
911
|
+
nearBar: hasChanged ? newNearBar || null : nearBar,
|
|
912
|
+
changed: hasChanged
|
|
913
|
+
};
|
|
893
914
|
};
|
|
894
915
|
const handleMouseOut = (chart, nearBar) => {
|
|
895
916
|
chart.canvas.style.cursor = 'default';
|
|
896
|
-
nearBar
|
|
917
|
+
return !!nearBar;
|
|
897
918
|
};
|
|
898
919
|
const handleClick = (chart, nearBar) => {
|
|
899
|
-
|
|
920
|
+
if (nearBar)
|
|
921
|
+
triggerBarClick(chart, nearBar);
|
|
900
922
|
};
|
|
901
923
|
const getActiveBar = (chart) => {
|
|
902
|
-
const
|
|
903
|
-
|
|
904
|
-
if (!activePoints || activePoints.length === 0) {
|
|
905
|
-
return undefined;
|
|
906
|
-
}
|
|
907
|
-
const activePoint = activePoints[0];
|
|
908
|
-
const meta = chart.getDatasetMeta(activePoint._datasetIndex);
|
|
909
|
-
const bar = meta.data[activePoint._index];
|
|
910
|
-
return bar._model || undefined;
|
|
924
|
+
const activeElements = chart.tooltip?.getActiveElements();
|
|
925
|
+
return activeElements?.[0]?.element;
|
|
911
926
|
};
|
|
912
|
-
const defaultSettings$4 = {
|
|
927
|
+
const defaultSettings$4 = { threshold: 10 };
|
|
913
928
|
const backgroundHoverPlugin = (settings = {}) => {
|
|
914
929
|
let nearBar = null;
|
|
915
|
-
const {
|
|
916
|
-
...defaultSettings$4,
|
|
917
|
-
...settings
|
|
918
|
-
};
|
|
930
|
+
const { threshold } = { ...defaultSettings$4, ...settings };
|
|
919
931
|
return {
|
|
920
932
|
id: 'backgroundHover',
|
|
921
|
-
afterEvent: (chart,
|
|
922
|
-
const e =
|
|
933
|
+
afterEvent: (chart, args) => {
|
|
934
|
+
const e = args.event;
|
|
935
|
+
let changed = false;
|
|
923
936
|
if (e.type === 'mousemove') {
|
|
924
|
-
|
|
937
|
+
const result = handleMouseMove(chart, nearBar, threshold || 10, e);
|
|
938
|
+
nearBar = result.nearBar;
|
|
939
|
+
changed = result.changed;
|
|
925
940
|
}
|
|
926
941
|
else if (e.type === 'mouseout') {
|
|
927
|
-
handleMouseOut(chart, nearBar);
|
|
942
|
+
changed = handleMouseOut(chart, nearBar);
|
|
928
943
|
nearBar = null;
|
|
929
944
|
}
|
|
930
945
|
else if (e.type === 'click') {
|
|
931
946
|
handleClick(chart, nearBar);
|
|
947
|
+
// Clicks usually trigger their own updates, but if you need one:
|
|
948
|
+
// changed = true;
|
|
932
949
|
}
|
|
950
|
+
args.changed = changed;
|
|
933
951
|
},
|
|
934
952
|
beforeDraw: (chart) => {
|
|
935
|
-
const
|
|
936
|
-
|
|
953
|
+
const indexAxis = chart.options.indexAxis || 'x';
|
|
954
|
+
const activeBar = nearBar ? nearBar.element : getActiveBar(chart);
|
|
955
|
+
activeBar && drawHoverEffect(chart.ctx, chart.chartArea, activeBar, threshold || 10, indexAxis);
|
|
937
956
|
}
|
|
938
957
|
};
|
|
939
958
|
};
|
|
@@ -967,6 +986,7 @@ const defaultLollipopSettings = {
|
|
|
967
986
|
isMouseInsideLollipopFn: () => null
|
|
968
987
|
};
|
|
969
988
|
const lollipopChartPlugin = settings => ({
|
|
989
|
+
id: 'lollipopChartPlugin',
|
|
970
990
|
afterDatasetsDraw: (chart) => {
|
|
971
991
|
if (!chart.data.datasets?.length) {
|
|
972
992
|
return;
|
|
@@ -984,12 +1004,13 @@ const lollipopChartPlugin = settings => ({
|
|
|
984
1004
|
if (meta.hidden)
|
|
985
1005
|
return;
|
|
986
1006
|
ctx.save();
|
|
987
|
-
meta.data
|
|
988
|
-
|
|
989
|
-
.
|
|
990
|
-
|
|
991
|
-
const { base, x, y } =
|
|
992
|
-
const
|
|
1007
|
+
const elements = meta.data;
|
|
1008
|
+
elements
|
|
1009
|
+
.filter(element => !element.skip)
|
|
1010
|
+
.forEach((element, index) => {
|
|
1011
|
+
const { base, x, y } = element;
|
|
1012
|
+
const color = colorFn(element.options, index);
|
|
1013
|
+
const data = dataset.data[index];
|
|
993
1014
|
clickableDictionary.push((clientX, clientY) => isMouseInsideCircle({ clientX, clientY }, { x, y }, circleRadius));
|
|
994
1015
|
clickableDictionary.push((clientX, clientY) => isMouseInsideCircle({ clientX, clientY }, { x: base, y }, circleRadius));
|
|
995
1016
|
circle(ctx, x, y, color, circleRadius);
|
|
@@ -1006,185 +1027,117 @@ const lollipopChartPlugin = settings => ({
|
|
|
1006
1027
|
|
|
1007
1028
|
const defaultChartWidth = 800;
|
|
1008
1029
|
const defaultChartHeight = 600;
|
|
1009
|
-
const
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
const modernizeChartConfig = (config) => {
|
|
1023
|
-
const modernized = { ...config };
|
|
1024
|
-
// For Chart.js v2, keep the configuration as-is since we're using the same version
|
|
1025
|
-
setDefaultOptions(modernized);
|
|
1026
|
-
return modernized;
|
|
1027
|
-
};
|
|
1028
|
-
const extractEssentialChartConfig = (config) => {
|
|
1029
|
-
const essentialConfig = {
|
|
1030
|
-
type: config.type,
|
|
1031
|
-
data: {
|
|
1032
|
-
labels: config.data?.labels || [],
|
|
1033
|
-
datasets: []
|
|
1030
|
+
const extractEssentialChartConfig = (config) => ({
|
|
1031
|
+
type: config.type || 'bar',
|
|
1032
|
+
data: config.data,
|
|
1033
|
+
options: {
|
|
1034
|
+
indexAxis: config.options?.indexAxis,
|
|
1035
|
+
responsive: false,
|
|
1036
|
+
maintainAspectRatio: false,
|
|
1037
|
+
devicePixelRatio: 1,
|
|
1038
|
+
animation: false,
|
|
1039
|
+
animations: {
|
|
1040
|
+
colors: false,
|
|
1041
|
+
x: false,
|
|
1042
|
+
y: false
|
|
1034
1043
|
},
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
legend: {
|
|
1040
|
-
display: false
|
|
1044
|
+
transitions: {
|
|
1045
|
+
active: {
|
|
1046
|
+
animation: {
|
|
1047
|
+
duration: 0
|
|
1041
1048
|
}
|
|
1042
1049
|
}
|
|
1043
|
-
}
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
backgroundColor: dataset.backgroundColor,
|
|
1050
|
-
borderColor: dataset.borderColor,
|
|
1051
|
-
borderWidth: dataset.borderWidth || 1,
|
|
1052
|
-
type: dataset.type
|
|
1053
|
-
}));
|
|
1054
|
-
}
|
|
1055
|
-
if (config.options?.plugins?.title) {
|
|
1056
|
-
essentialConfig.options.plugins.title = {
|
|
1057
|
-
display: config.options.plugins.title.display,
|
|
1058
|
-
text: config.options.plugins.title.text
|
|
1059
|
-
};
|
|
1060
|
-
}
|
|
1061
|
-
if (config.options?.scales) {
|
|
1062
|
-
essentialConfig.options.scales = {};
|
|
1063
|
-
Object.keys(config.options.scales).forEach(scaleKey => {
|
|
1064
|
-
const scale = config.options.scales[scaleKey];
|
|
1065
|
-
if (scale) {
|
|
1066
|
-
essentialConfig.options.scales[scaleKey] = {
|
|
1067
|
-
display: scale.display !== false,
|
|
1068
|
-
title: scale.title
|
|
1069
|
-
? {
|
|
1070
|
-
display: scale.title.display,
|
|
1071
|
-
text: scale.title.text
|
|
1072
|
-
}
|
|
1073
|
-
: undefined
|
|
1074
|
-
};
|
|
1075
|
-
}
|
|
1076
|
-
});
|
|
1077
|
-
}
|
|
1078
|
-
return setDefaultOptions(essentialConfig);
|
|
1079
|
-
};
|
|
1080
|
-
const sanitizeChartConfig = (config) => {
|
|
1081
|
-
try {
|
|
1082
|
-
const sanitized = {
|
|
1083
|
-
type: config.type,
|
|
1084
|
-
data: deepCloneSerializable(config.data),
|
|
1085
|
-
options: deepCloneSerializable(config.options)
|
|
1086
|
-
};
|
|
1087
|
-
if (sanitized.data?.datasets?.length) {
|
|
1088
|
-
return modernizeChartConfig(sanitized);
|
|
1089
|
-
}
|
|
1090
|
-
}
|
|
1091
|
-
catch (error) {
|
|
1092
|
-
console.error('Sanitizing chart failed, fallback to default config');
|
|
1093
|
-
}
|
|
1094
|
-
return modernizeChartConfig(extractEssentialChartConfig(config));
|
|
1095
|
-
};
|
|
1096
|
-
const deepCloneSerializable = (obj, visited = new WeakSet()) => {
|
|
1097
|
-
const simpleValue = getSimpleValue(obj, visited);
|
|
1098
|
-
if (simpleValue !== undefined) {
|
|
1099
|
-
return simpleValue.value;
|
|
1100
|
-
}
|
|
1101
|
-
visited.add(obj);
|
|
1102
|
-
try {
|
|
1103
|
-
return cloneComplexObject(obj, visited);
|
|
1104
|
-
}
|
|
1105
|
-
catch (error) {
|
|
1106
|
-
console.warn('Error cloning object:', error);
|
|
1107
|
-
return {};
|
|
1108
|
-
}
|
|
1109
|
-
finally {
|
|
1110
|
-
visited.delete(obj);
|
|
1111
|
-
}
|
|
1112
|
-
};
|
|
1113
|
-
const getSimpleValue = (obj, visited) => {
|
|
1114
|
-
if (obj === null || typeof obj !== 'object') {
|
|
1115
|
-
return { value: obj };
|
|
1116
|
-
}
|
|
1117
|
-
if (visited.has(obj)) {
|
|
1118
|
-
return { value: {} };
|
|
1119
|
-
}
|
|
1120
|
-
const specialValue = handleSpecialTypes(obj);
|
|
1121
|
-
return specialValue !== undefined ? { value: specialValue } : undefined;
|
|
1122
|
-
};
|
|
1123
|
-
const cloneComplexObject = (obj, visited) => Array.isArray(obj) ? obj.map(item => deepCloneSerializable(item, visited)) : cloneObject(obj, visited);
|
|
1124
|
-
const handleSpecialTypes = (obj) => isNonSerializableType(obj) || obj instanceof RegExp ? null : obj instanceof Date ? obj.toISOString() : undefined;
|
|
1125
|
-
const shouldSkipProperty = (key, value) => isNonSerializableType(value) || ['__ngContext__', 'chart', 'ctx', 'canvas'].includes(key) || key.startsWith('_');
|
|
1126
|
-
const cloneObject = (obj, visited) => {
|
|
1127
|
-
const cloned = {};
|
|
1128
|
-
for (const key in obj) {
|
|
1129
|
-
if (!Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
1130
|
-
continue;
|
|
1131
|
-
}
|
|
1132
|
-
const value = obj[key];
|
|
1133
|
-
if (shouldSkipProperty(key, value)) {
|
|
1134
|
-
continue;
|
|
1135
|
-
}
|
|
1136
|
-
const clonedValue = deepCloneSerializable(value, visited);
|
|
1137
|
-
if (clonedValue !== null) {
|
|
1138
|
-
cloned[key] = clonedValue;
|
|
1139
|
-
}
|
|
1050
|
+
},
|
|
1051
|
+
plugins: {
|
|
1052
|
+
legend: { display: false },
|
|
1053
|
+
title: config.options.plugins?.title || { display: false }
|
|
1054
|
+
},
|
|
1055
|
+
scales: config.options.scales
|
|
1140
1056
|
}
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
const stretchSvg = (svgString) => {
|
|
1057
|
+
});
|
|
1058
|
+
const stretchSvg = (svgString, width, height) => {
|
|
1144
1059
|
const parser = new DOMParser();
|
|
1145
1060
|
const doc = parser.parseFromString(svgString, 'image/svg+xml');
|
|
1146
1061
|
const svgElement = doc.documentElement;
|
|
1147
|
-
//
|
|
1148
|
-
svgElement.setAttribute('viewBox', `0 0 ${
|
|
1062
|
+
// Add 100px padding to ViewBox for overflow labels
|
|
1063
|
+
svgElement.setAttribute('viewBox', `0 0 ${width + 100} ${height}`);
|
|
1149
1064
|
svgElement.setAttribute('width', '100%');
|
|
1150
1065
|
svgElement.setAttribute('height', '100%');
|
|
1151
1066
|
svgElement.setAttribute('preserveAspectRatio', 'xMidYMid meet');
|
|
1152
1067
|
return svgElement.outerHTML;
|
|
1153
1068
|
};
|
|
1154
|
-
const convertToSvg = (config, metadata = {}) => {
|
|
1069
|
+
const convertToSvg = (config, metadata = {}) => new Promise((resolve, reject) => {
|
|
1155
1070
|
const width = metadata.width || defaultChartWidth;
|
|
1156
1071
|
const height = metadata.height || defaultChartHeight;
|
|
1157
|
-
|
|
1072
|
+
// 1. Create the SVG Context
|
|
1073
|
+
const svgContext = new C2S(width, height);
|
|
1074
|
+
svgContext.setTransform = () => { };
|
|
1075
|
+
svgContext.resetTransform = () => { };
|
|
1076
|
+
svgContext.roundRect = function (x, y, w, h) {
|
|
1077
|
+
this.rect(x, y, w, h);
|
|
1078
|
+
};
|
|
1079
|
+
// 2. Mock the Canvas Element
|
|
1158
1080
|
const mockCanvas = document.createElement('canvas');
|
|
1159
|
-
// Set dimensions to match the SVG context
|
|
1160
1081
|
mockCanvas.width = width;
|
|
1161
1082
|
mockCanvas.height = height;
|
|
1162
|
-
mockCanvas.style.width = width
|
|
1163
|
-
mockCanvas.style.height = height
|
|
1164
|
-
mockCanvas.
|
|
1083
|
+
mockCanvas.style.width = `${width}px`;
|
|
1084
|
+
mockCanvas.style.height = `${height}px`;
|
|
1085
|
+
mockCanvas.getBoundingClientRect = () => ({
|
|
1086
|
+
x: 0,
|
|
1087
|
+
y: 0,
|
|
1088
|
+
bottom: height,
|
|
1089
|
+
height: height,
|
|
1090
|
+
left: 0,
|
|
1091
|
+
right: width,
|
|
1092
|
+
top: 0,
|
|
1093
|
+
width: width,
|
|
1094
|
+
toJSON: () => { }
|
|
1095
|
+
});
|
|
1096
|
+
// Intercept getContext to return our SVG generator
|
|
1097
|
+
mockCanvas.getContext = (type) => {
|
|
1165
1098
|
if (type === '2d') {
|
|
1166
1099
|
svgContext.canvas = mockCanvas;
|
|
1167
1100
|
return svgContext;
|
|
1168
1101
|
}
|
|
1169
1102
|
return null;
|
|
1170
1103
|
};
|
|
1171
|
-
|
|
1104
|
+
// 3. Prepare Config
|
|
1105
|
+
const chartConfig = extractEssentialChartConfig(config);
|
|
1106
|
+
// eslint-disable-next-line prefer-const
|
|
1107
|
+
let chart;
|
|
1108
|
+
chartConfig.options.animation = {
|
|
1109
|
+
onComplete: () => {
|
|
1110
|
+
try {
|
|
1111
|
+
const svgString = svgContext.getSerializedSvg(true);
|
|
1112
|
+
const finalSvg = stretchSvg(svgString, width, height);
|
|
1113
|
+
chart.destroy();
|
|
1114
|
+
resolve(finalSvg);
|
|
1115
|
+
}
|
|
1116
|
+
catch (e) {
|
|
1117
|
+
reject(e);
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
};
|
|
1121
|
+
// 4. Register Export-Specific Plugins
|
|
1172
1122
|
chartConfig.plugins = [
|
|
1173
1123
|
afterBarDrawPlugin({
|
|
1174
1124
|
textFn: ({ data }) => [toPrecision(data), metadata.units].filter(Boolean).join(' '),
|
|
1175
|
-
xPosFn: (x, index, width, chart, data) => (data < 0 || isEmpty(data) ? chart.scales['x-axis-0'].getPixelForValue(0) : x) + 10,
|
|
1176
1125
|
emptyValueLabel: 'No data'
|
|
1177
1126
|
}),
|
|
1178
1127
|
metadata.lollipopConfig ? lollipopChartPlugin(metadata.lollipopConfig) : null
|
|
1179
|
-
].filter(Boolean);
|
|
1180
|
-
new Chart(mockCanvas, chartConfig);
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1128
|
+
].filter((p) => Boolean(p));
|
|
1129
|
+
chart = new Chart(mockCanvas, chartConfig);
|
|
1130
|
+
});
|
|
1131
|
+
const exportAsSVG = async (config, metadata) => {
|
|
1132
|
+
try {
|
|
1133
|
+
const content = await convertToSvg(config, metadata);
|
|
1134
|
+
const blob = new Blob([content], { type: 'image/svg+xml;charset=utf-8' });
|
|
1135
|
+
const url = URL.createObjectURL(blob);
|
|
1136
|
+
downloadFile(url, metadata.fileName || 'chart-export.svg');
|
|
1137
|
+
}
|
|
1138
|
+
catch (error) {
|
|
1139
|
+
console.error('Failed to export SVG', error);
|
|
1140
|
+
}
|
|
1188
1141
|
};
|
|
1189
1142
|
const downloadSvg = (svgElement) => {
|
|
1190
1143
|
const serializer = new XMLSerializer();
|
|
@@ -1197,6 +1150,11 @@ const downloadSvg = (svgElement) => {
|
|
|
1197
1150
|
return downloadFile(url, 'chart.svg');
|
|
1198
1151
|
};
|
|
1199
1152
|
|
|
1153
|
+
function registerChartDefaults() {
|
|
1154
|
+
// Register components only once to avoid warnings
|
|
1155
|
+
Chart.register(BarController, LineController, CategoryScale, LinearScale, PointElement, BarElement, LineElement, Title, Tooltip, Legend, TimeScale);
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1200
1158
|
class ChartConfigurationDirective {
|
|
1201
1159
|
constructor() {
|
|
1202
1160
|
this._zone = inject(NgZone);
|
|
@@ -1255,8 +1213,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImpo
|
|
|
1255
1213
|
type: Directive,
|
|
1256
1214
|
args: [{
|
|
1257
1215
|
selector: '[chartConfiguration]',
|
|
1258
|
-
exportAs: 'chart'
|
|
1259
|
-
standalone: true
|
|
1216
|
+
exportAs: 'chart'
|
|
1260
1217
|
}]
|
|
1261
1218
|
}], propDecorators: { chartConfiguration: [{
|
|
1262
1219
|
type: Input
|
|
@@ -1268,85 +1225,207 @@ const defaultSettings$3 = Object.freeze({
|
|
|
1268
1225
|
options: {
|
|
1269
1226
|
responsive: true,
|
|
1270
1227
|
maintainAspectRatio: false,
|
|
1271
|
-
|
|
1272
|
-
|
|
1228
|
+
plugins: {
|
|
1229
|
+
legend: {
|
|
1230
|
+
display: false
|
|
1231
|
+
}
|
|
1273
1232
|
}
|
|
1274
1233
|
}
|
|
1275
1234
|
});
|
|
1276
1235
|
class ChartComponent {
|
|
1277
1236
|
constructor() {
|
|
1278
|
-
this.data = input(
|
|
1237
|
+
this.data = input(undefined, ...(ngDevMode ? [{ debugName: "data" }] : []));
|
|
1279
1238
|
this.config = input({}, ...(ngDevMode ? [{ debugName: "config" }] : []));
|
|
1280
1239
|
this.showExportButton = input(true, ...(ngDevMode ? [{ debugName: "showExportButton" }] : []));
|
|
1240
|
+
this.exporting = signal(false, ...(ngDevMode ? [{ debugName: "exporting" }] : []));
|
|
1281
1241
|
this.configuration = computed(() => ({
|
|
1282
1242
|
...merge({}, defaultSettings$3, this.config()),
|
|
1283
1243
|
data: this.data()
|
|
1284
1244
|
}), ...(ngDevMode ? [{ debugName: "configuration" }] : []));
|
|
1245
|
+
registerChartDefaults();
|
|
1285
1246
|
}
|
|
1286
|
-
exportAsSvg(config = {}) {
|
|
1287
|
-
|
|
1247
|
+
async exportAsSvg(config = {}) {
|
|
1248
|
+
this.exporting.set(true);
|
|
1249
|
+
await exportAsSVG(this.configuration(), {
|
|
1288
1250
|
width: 600,
|
|
1289
1251
|
height: 400,
|
|
1290
1252
|
fileName: 'chart.svg',
|
|
1291
1253
|
...config
|
|
1292
1254
|
});
|
|
1255
|
+
this.exporting.set(false);
|
|
1293
1256
|
}
|
|
1294
1257
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: ChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1295
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.13", type: ChartComponent, isStandalone: true, selector: "he-chart", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, showExportButton: { classPropertyName: "showExportButton", publicName: "showExportButton", isSignal: true, isRequired: false, transformFunction: null } }, exportAs: ["chart"], ngImport: i0, template: "<div class=\"is-relative h-100 | chart-container\" #container>\n @if (showExportButton()) {\n <a
|
|
1258
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.13", type: ChartComponent, isStandalone: true, selector: "he-chart", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, showExportButton: { classPropertyName: "showExportButton", publicName: "showExportButton", isSignal: true, isRequired: false, transformFunction: null } }, exportAs: ["chart"], ngImport: i0, template: "<div class=\"is-relative h-100 | chart-container\" #container>\n @if (showExportButton()) {\n <a\n class=\"is-absolute | download\"\n (click)=\"!exporting() && exportAsSvg()\"\n [ngbTooltip]=\"exporting() ? null : 'Download Chart (SVG)'\"\n placement=\"top\">\n @if (exporting()) {\n <he-svg-icon name=\"loading\" animation=\"spin\" />\n } @else {\n <he-svg-icon name=\"download\" />\n }\n </a>\n }\n\n <ng-content />\n\n <canvas [chartConfiguration]=\"configuration()\" [chartContainer]=\"container\"></canvas>\n</div>\n", styles: [":host{display:block;height:100%;overflow:visible}.chart-container{min-height:50px}.download{top:-12px;right:-10px}\n"], dependencies: [{ kind: "directive", type: ChartConfigurationDirective, selector: "[chartConfiguration]", inputs: ["chartConfiguration", "chartContainer"], exportAs: ["chart"] }, { kind: "component", type: HESvgIconComponent, selector: "he-svg-icon", inputs: ["name", "size", "animation"] }, { kind: "directive", type: NgbTooltip, selector: "[ngbTooltip]", inputs: ["animation", "autoClose", "placement", "popperOptions", "triggers", "positionTarget", "container", "disableTooltip", "tooltipClass", "tooltipContext", "openDelay", "closeDelay", "ngbTooltip"], outputs: ["shown", "hidden"], exportAs: ["ngbTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1296
1259
|
}
|
|
1297
1260
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: ChartComponent, decorators: [{
|
|
1298
1261
|
type: Component$1,
|
|
1299
|
-
args: [{ selector: 'he-chart', exportAs: 'chart', changeDetection: ChangeDetectionStrategy.OnPush, imports: [ChartConfigurationDirective, HESvgIconComponent, NgbTooltip], template: "<div class=\"is-relative h-100 | chart-container\" #container>\n @if (showExportButton()) {\n <a
|
|
1300
|
-
}], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }], showExportButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showExportButton", required: false }] }] } });
|
|
1262
|
+
args: [{ selector: 'he-chart', exportAs: 'chart', changeDetection: ChangeDetectionStrategy.OnPush, imports: [ChartConfigurationDirective, HESvgIconComponent, NgbTooltip], template: "<div class=\"is-relative h-100 | chart-container\" #container>\n @if (showExportButton()) {\n <a\n class=\"is-absolute | download\"\n (click)=\"!exporting() && exportAsSvg()\"\n [ngbTooltip]=\"exporting() ? null : 'Download Chart (SVG)'\"\n placement=\"top\">\n @if (exporting()) {\n <he-svg-icon name=\"loading\" animation=\"spin\" />\n } @else {\n <he-svg-icon name=\"download\" />\n }\n </a>\n }\n\n <ng-content />\n\n <canvas [chartConfiguration]=\"configuration()\" [chartContainer]=\"container\"></canvas>\n</div>\n", styles: [":host{display:block;height:100%;overflow:visible}.chart-container{min-height:50px}.download{top:-12px;right:-10px}\n"] }]
|
|
1263
|
+
}], ctorParameters: () => [], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }], showExportButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showExportButton", required: false }] }] } });
|
|
1301
1264
|
|
|
1265
|
+
var Breakpoint;
|
|
1266
|
+
(function (Breakpoint) {
|
|
1267
|
+
Breakpoint["tablet"] = "tablet";
|
|
1268
|
+
Breakpoint["desktop"] = "desktop";
|
|
1269
|
+
Breakpoint["widescreen"] = "widescreen";
|
|
1270
|
+
Breakpoint["fullhd"] = "fullhd";
|
|
1271
|
+
})(Breakpoint || (Breakpoint = {}));
|
|
1272
|
+
const beakpointWidths = {
|
|
1273
|
+
[Breakpoint.tablet]: 768,
|
|
1274
|
+
[Breakpoint.desktop]: 1024,
|
|
1275
|
+
[Breakpoint.widescreen]: 1216,
|
|
1276
|
+
[Breakpoint.fullhd]: 1408
|
|
1277
|
+
};
|
|
1278
|
+
const toSize = (size, dir) => `(${dir}-width: ${dir === 'max' ? size - 1 : size}px)`;
|
|
1279
|
+
const toBreakpoint = ({ min, max }) => [min ? toSize(beakpointWidths[min], 'min') : '', max ? toSize(beakpointWidths[max], 'max') : '']
|
|
1280
|
+
.filter(Boolean)
|
|
1281
|
+
.join(' and ');
|
|
1282
|
+
class ResponsiveService {
|
|
1283
|
+
constructor() {
|
|
1284
|
+
this.breakPointObserver = inject(BreakpointObserver);
|
|
1285
|
+
this.windowWidth$ = fromEvent(window, 'resize').pipe(startWith(window.innerWidth), map(() => window.innerWidth));
|
|
1286
|
+
this.isMobile$ = this.breakPointObserver.observe(toBreakpoint({ max: Breakpoint.tablet })).pipe(map(state => state.matches), distinctUntilChanged());
|
|
1287
|
+
this.isTablet$ = this.breakPointObserver
|
|
1288
|
+
.observe(toBreakpoint({ min: Breakpoint.tablet, max: Breakpoint.desktop }))
|
|
1289
|
+
.pipe(map(state => state.matches), distinctUntilChanged());
|
|
1290
|
+
this.isDesktop$ = this.breakPointObserver
|
|
1291
|
+
.observe(toBreakpoint({ min: Breakpoint.desktop, max: Breakpoint.widescreen }))
|
|
1292
|
+
.pipe(map(state => state.matches), distinctUntilChanged());
|
|
1293
|
+
this.isWidescreen$ = this.breakPointObserver
|
|
1294
|
+
.observe(toBreakpoint({ min: Breakpoint.widescreen, max: Breakpoint.fullhd }))
|
|
1295
|
+
.pipe(map(state => state.matches), distinctUntilChanged());
|
|
1296
|
+
this.isFullHd$ = this.breakPointObserver.observe(toBreakpoint({ min: Breakpoint.fullhd })).pipe(map(state => state.matches), distinctUntilChanged());
|
|
1297
|
+
this.isTouch$ = this.breakPointObserver.observe(toBreakpoint({ max: Breakpoint.desktop })).pipe(map(state => state.matches), distinctUntilChanged());
|
|
1298
|
+
/**
|
|
1299
|
+
* Resolution for 1080p (or Full HD) on a normal screen, although bulma defines it differently.
|
|
1300
|
+
*/
|
|
1301
|
+
this.is1080p$ = this.breakPointObserver.observe(toSize(1920, 'min')).pipe(map(state => state.matches), distinctUntilChanged());
|
|
1302
|
+
this.isRetinaDisplay = () => {
|
|
1303
|
+
if (window.matchMedia) {
|
|
1304
|
+
const mq = window.matchMedia([
|
|
1305
|
+
'min--moz-device-pixel-ratio: 1.3',
|
|
1306
|
+
'-o-min-device-pixel-ratio: 2.6/2',
|
|
1307
|
+
'-webkit-min-device-pixel-ratio: 1.3',
|
|
1308
|
+
'min-device-pixel-ratio: 1.3',
|
|
1309
|
+
'min-resolution: 1.3dppx'
|
|
1310
|
+
]
|
|
1311
|
+
.map(v => `only screen and (${v})`)
|
|
1312
|
+
.join(', '));
|
|
1313
|
+
return mq?.matches || window.devicePixelRatio > 1;
|
|
1314
|
+
}
|
|
1315
|
+
return false;
|
|
1316
|
+
};
|
|
1317
|
+
this.isMobile = toSignal(this.isMobile$);
|
|
1318
|
+
this.isTablet = toSignal(this.isTablet$);
|
|
1319
|
+
this.isDesktop = toSignal(this.isDesktop$);
|
|
1320
|
+
this.isWidescreen = toSignal(this.isWidescreen$);
|
|
1321
|
+
this.isFullHd = toSignal(this.isFullHd$);
|
|
1322
|
+
this.isTouch = toSignal(this.isTouch$);
|
|
1323
|
+
this.is1080p = toSignal(this.is1080p$);
|
|
1324
|
+
this.resolutionName = computed(() => this.isMobile()
|
|
1325
|
+
? 'mobile'
|
|
1326
|
+
: this.isTablet()
|
|
1327
|
+
? 'tablet'
|
|
1328
|
+
: this.isDesktop()
|
|
1329
|
+
? 'desktop'
|
|
1330
|
+
: this.isWidescreen()
|
|
1331
|
+
? 'widescreen'
|
|
1332
|
+
: 'fullhd', ...(ngDevMode ? [{ debugName: "resolutionName" }] : []));
|
|
1333
|
+
this.resolutionName$ = toObservable(this.resolutionName);
|
|
1334
|
+
}
|
|
1335
|
+
isAboveBreakpoint$(breakpoint) {
|
|
1336
|
+
return typeof breakpoint === 'number'
|
|
1337
|
+
? this.windowWidth$.pipe(map(width => width >= breakpoint))
|
|
1338
|
+
: breakpoint === 'none'
|
|
1339
|
+
? of(false)
|
|
1340
|
+
: this._isAboveBreakpointName$(breakpoint);
|
|
1341
|
+
}
|
|
1342
|
+
_isAboveBreakpointName$(breakpoint) {
|
|
1343
|
+
return this.resolutionName$.pipe(map(resolutionName => {
|
|
1344
|
+
const width = beakpointWidths[resolutionName];
|
|
1345
|
+
const overlapBreakpointWidth = beakpointWidths[breakpoint];
|
|
1346
|
+
return width >= overlapBreakpointWidth;
|
|
1347
|
+
}));
|
|
1348
|
+
}
|
|
1349
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: ResponsiveService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1350
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: ResponsiveService, providedIn: 'root' }); }
|
|
1351
|
+
}
|
|
1352
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: ResponsiveService, decorators: [{
|
|
1353
|
+
type: Injectable,
|
|
1354
|
+
args: [{
|
|
1355
|
+
providedIn: 'root'
|
|
1356
|
+
}]
|
|
1357
|
+
}] });
|
|
1358
|
+
|
|
1359
|
+
class BarChartLegendComponent {
|
|
1360
|
+
constructor() {
|
|
1361
|
+
this.data = input([], ...(ngDevMode ? [{ debugName: "data" }] : []));
|
|
1362
|
+
}
|
|
1363
|
+
trackByItem(item) {
|
|
1364
|
+
return Object.values(item).join('-');
|
|
1365
|
+
}
|
|
1366
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: BarChartLegendComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1367
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.13", type: BarChartLegendComponent, isStandalone: true, selector: "he-bar-chart-legend", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\n class=\"is-hidden-tablet is-flex is-flex-direction-column is-align-items-flex-start is-gap-4 is-py-1 is-px-2 is-mt-3 is-radius-3 w-100 | breakdown-legend\">\n @for (value of data(); track trackByItem(value)) {\n @if (value.includedItems?.length) {\n <span class=\"has-text-secondary has-text-weight-bold is-size-7\">\n {{ value.includedItems.length }} others grouped together\n </span>\n }\n\n <div class=\"is-flex is-align-items-center is-gap-4 w-100\">\n <div class=\"breakdown-legend--color\" [style.backgroundColor]=\"value.backgroundColor || value.color\"></div>\n\n @if (value.includedItems?.length) {\n <div class=\"is-flex is-flex-direction-column is-gap-4\">\n @for (subValue of value.includedItems; track trackByItem(subValue)) {\n <span class=\"is-size-7\">{{ subValue.label }}</span>\n }\n </div>\n } @else {\n <span class=\"is-size-7\">{{ value.label }}</span>\n }\n </div>\n }\n</div>\n", styles: [":host{display:block}.breakdown-legend{background:#fafafa}.breakdown-legend--color{width:8px;height:8px;border-radius:50%}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1368
|
+
}
|
|
1369
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: BarChartLegendComponent, decorators: [{
|
|
1370
|
+
type: Component$1,
|
|
1371
|
+
args: [{ selector: 'he-bar-chart-legend', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"is-hidden-tablet is-flex is-flex-direction-column is-align-items-flex-start is-gap-4 is-py-1 is-px-2 is-mt-3 is-radius-3 w-100 | breakdown-legend\">\n @for (value of data(); track trackByItem(value)) {\n @if (value.includedItems?.length) {\n <span class=\"has-text-secondary has-text-weight-bold is-size-7\">\n {{ value.includedItems.length }} others grouped together\n </span>\n }\n\n <div class=\"is-flex is-align-items-center is-gap-4 w-100\">\n <div class=\"breakdown-legend--color\" [style.backgroundColor]=\"value.backgroundColor || value.color\"></div>\n\n @if (value.includedItems?.length) {\n <div class=\"is-flex is-flex-direction-column is-gap-4\">\n @for (subValue of value.includedItems; track trackByItem(subValue)) {\n <span class=\"is-size-7\">{{ subValue.label }}</span>\n }\n </div>\n } @else {\n <span class=\"is-size-7\">{{ value.label }}</span>\n }\n </div>\n }\n</div>\n", styles: [":host{display:block}.breakdown-legend{background:#fafafa}.breakdown-legend--color{width:8px;height:8px;border-radius:50%}\n"] }]
|
|
1372
|
+
}], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }] } });
|
|
1373
|
+
|
|
1374
|
+
const grey = '#4a4a4a';
|
|
1302
1375
|
const defaultSettings$2 = Object.freeze({
|
|
1303
|
-
type: '
|
|
1376
|
+
type: 'bar',
|
|
1304
1377
|
options: {
|
|
1305
1378
|
animation: {
|
|
1306
1379
|
duration: 0
|
|
1307
1380
|
},
|
|
1308
|
-
|
|
1309
|
-
|
|
1381
|
+
plugins: {
|
|
1382
|
+
legend: {
|
|
1383
|
+
align: 'start'
|
|
1384
|
+
},
|
|
1385
|
+
tooltip: {
|
|
1386
|
+
enabled: false
|
|
1387
|
+
}
|
|
1310
1388
|
},
|
|
1311
1389
|
scales: {
|
|
1312
|
-
|
|
1313
|
-
|
|
1390
|
+
x: {
|
|
1391
|
+
display: true,
|
|
1392
|
+
min: 0,
|
|
1393
|
+
title: {
|
|
1314
1394
|
display: false,
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
scaleLabel: {
|
|
1319
|
-
display: true,
|
|
1320
|
-
fontSize: 14,
|
|
1321
|
-
fontColor: '#4a4a4a'
|
|
1322
|
-
},
|
|
1323
|
-
gridLines: {
|
|
1324
|
-
drawOnChartArea: false
|
|
1395
|
+
color: grey,
|
|
1396
|
+
font: {
|
|
1397
|
+
size: 14
|
|
1325
1398
|
}
|
|
1326
1399
|
}
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1400
|
+
},
|
|
1401
|
+
y: {
|
|
1402
|
+
display: true,
|
|
1403
|
+
position: 'left',
|
|
1404
|
+
border: {
|
|
1405
|
+
display: true
|
|
1406
|
+
},
|
|
1407
|
+
grid: {
|
|
1330
1408
|
display: true,
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1409
|
+
drawOnChartArea: true,
|
|
1410
|
+
drawTicks: true,
|
|
1411
|
+
tickLength: 8,
|
|
1412
|
+
offset: false
|
|
1413
|
+
},
|
|
1414
|
+
ticks: {
|
|
1415
|
+
color: grey,
|
|
1416
|
+
padding: 4,
|
|
1417
|
+
crossAlign: 'center',
|
|
1418
|
+
font: {
|
|
1419
|
+
family: 'Lato',
|
|
1420
|
+
size: 12,
|
|
1421
|
+
weight: 400
|
|
1339
1422
|
},
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
fontSize: 12,
|
|
1344
|
-
fontStyle: '400',
|
|
1345
|
-
padding: 4,
|
|
1346
|
-
crossAlign: 'center'
|
|
1423
|
+
callback: function (value) {
|
|
1424
|
+
const label = this.getLabelForValue(value);
|
|
1425
|
+
return ellipsis$1(label, 50);
|
|
1347
1426
|
}
|
|
1348
1427
|
}
|
|
1349
|
-
|
|
1428
|
+
}
|
|
1350
1429
|
}
|
|
1351
1430
|
}
|
|
1352
1431
|
});
|
|
@@ -1357,43 +1436,93 @@ const defaultDatasets = {
|
|
|
1357
1436
|
};
|
|
1358
1437
|
class BarChartComponent {
|
|
1359
1438
|
constructor() {
|
|
1360
|
-
this.
|
|
1439
|
+
this.responsiveService = inject(ResponsiveService);
|
|
1440
|
+
/**
|
|
1441
|
+
* X-axis label.
|
|
1442
|
+
*/
|
|
1443
|
+
this.title = input('', ...(ngDevMode ? [{ debugName: "title" }] : []));
|
|
1444
|
+
/**
|
|
1445
|
+
* Maximum value of the chart. If not supplied, the maximum is the highest value from the datasets.
|
|
1446
|
+
*/
|
|
1361
1447
|
this.max = input(...(ngDevMode ? [undefined, { debugName: "max" }] : []));
|
|
1362
1448
|
this.datasets = input([], ...(ngDevMode ? [{ debugName: "datasets" }] : []));
|
|
1449
|
+
this.data = input([], ...(ngDevMode ? [{ debugName: "data" }] : []));
|
|
1450
|
+
/**
|
|
1451
|
+
* When `datasets` is not provided, a single dataset is used from the `data` parameter, and this label is used.
|
|
1452
|
+
*/
|
|
1453
|
+
this.datasetLabel = input('', ...(ngDevMode ? [{ debugName: "datasetLabel" }] : []));
|
|
1454
|
+
/**
|
|
1455
|
+
* If `data` is provided, the `labels` can be read from them. Otherwise use this to provide custom labels.
|
|
1456
|
+
*/
|
|
1363
1457
|
this.labels = input([], ...(ngDevMode ? [{ debugName: "labels" }] : []));
|
|
1458
|
+
/**
|
|
1459
|
+
* Override chart default configuration.
|
|
1460
|
+
*/
|
|
1364
1461
|
this.config = input({}, ...(ngDevMode ? [{ debugName: "config" }] : []));
|
|
1462
|
+
/**
|
|
1463
|
+
* Show default button for export, located on the top-right corner of the chart.
|
|
1464
|
+
*/
|
|
1365
1465
|
this.showExportButton = input(true, ...(ngDevMode ? [{ debugName: "showExportButton" }] : []));
|
|
1466
|
+
/**
|
|
1467
|
+
* If set to `false`, chart will show `0` instead if the value is negative.
|
|
1468
|
+
*/
|
|
1469
|
+
this.showNegativeValues = input(true, ...(ngDevMode ? [{ debugName: "showNegativeValues" }] : []));
|
|
1470
|
+
/**
|
|
1471
|
+
* Maximum values to display on the chart.
|
|
1472
|
+
* All values not dislayed will be grouped together into a "summed" value.
|
|
1473
|
+
* Default is `20`.
|
|
1474
|
+
*/
|
|
1475
|
+
this.maximumValues = input(20, ...(ngDevMode ? [{ debugName: "maximumValues" }] : []));
|
|
1476
|
+
this.hasNegativeContributions = computed(() => this.data()?.some(({ count }) => count < 0), ...(ngDevMode ? [{ debugName: "hasNegativeContributions" }] : []));
|
|
1366
1477
|
this.chart = viewChild.required(ChartComponent);
|
|
1478
|
+
this.exporting = computed(() => this.chart()?.exporting(), ...(ngDevMode ? [{ debugName: "exporting" }] : []));
|
|
1367
1479
|
this.defaultConfig = computed(() => ({
|
|
1368
1480
|
options: {
|
|
1369
|
-
legend: {
|
|
1370
|
-
align: 'start'
|
|
1371
|
-
},
|
|
1372
1481
|
scales: {
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1482
|
+
x: {
|
|
1483
|
+
display: !this.responsiveService.isMobile(),
|
|
1484
|
+
...(this.max() ? { max: this.max() } : {}),
|
|
1485
|
+
title: {
|
|
1486
|
+
display: !!this.title(),
|
|
1487
|
+
text: this.title()
|
|
1379
1488
|
}
|
|
1380
|
-
|
|
1489
|
+
}
|
|
1381
1490
|
}
|
|
1382
1491
|
}
|
|
1383
1492
|
}), ...(ngDevMode ? [{ debugName: "defaultConfig" }] : []));
|
|
1493
|
+
this.maximumData = computed(() => {
|
|
1494
|
+
const data = this.data();
|
|
1495
|
+
const includedData = data.slice(0, this.maximumValues());
|
|
1496
|
+
const excludedData = data.slice(this.maximumValues());
|
|
1497
|
+
return [
|
|
1498
|
+
...includedData,
|
|
1499
|
+
excludedData.length ? {
|
|
1500
|
+
label: `${excludedData.length} others`,
|
|
1501
|
+
count: sum(excludedData.map(({ count }) => count)),
|
|
1502
|
+
backgroundColor: excludedData[0].backgroundColor,
|
|
1503
|
+
borderColor: excludedData[0].borderColor,
|
|
1504
|
+
color: excludedData[0].color,
|
|
1505
|
+
includedItems: excludedData
|
|
1506
|
+
} : []
|
|
1507
|
+
].flat();
|
|
1508
|
+
}, ...(ngDevMode ? [{ debugName: "maximumData" }] : []));
|
|
1384
1509
|
this.defaultDatasets = computed(() => this.datasets()?.length
|
|
1385
|
-
? this.datasets()
|
|
1510
|
+
? this.datasets().map(dataset => ({
|
|
1511
|
+
...defaultDatasets,
|
|
1512
|
+
...dataset
|
|
1513
|
+
}))
|
|
1386
1514
|
: [
|
|
1387
1515
|
{
|
|
1388
|
-
defaultDatasets,
|
|
1389
|
-
backgroundColor: this.
|
|
1390
|
-
borderColor: this.
|
|
1391
|
-
data: this.
|
|
1516
|
+
...defaultDatasets,
|
|
1517
|
+
backgroundColor: this.maximumData().map(({ backgroundColor, color }) => backgroundColor || color),
|
|
1518
|
+
borderColor: this.maximumData().map(({ borderColor, color }) => borderColor || color),
|
|
1519
|
+
data: this.maximumData().map(({ count }) => toPrecision(this.showNegativeValues() ? count : Math.max(0, count))),
|
|
1520
|
+
label: this.datasetLabel()
|
|
1392
1521
|
}
|
|
1393
1522
|
], ...(ngDevMode ? [{ debugName: "defaultDatasets" }] : []));
|
|
1394
1523
|
this.dataConfig = computed(() => ({
|
|
1395
1524
|
datasets: this.defaultDatasets(),
|
|
1396
|
-
labels: this.labels().length ? this.labels() : this.
|
|
1525
|
+
labels: this.labels().length ? this.labels() : this.maximumData().map(({ label }) => label)
|
|
1397
1526
|
}), ...(ngDevMode ? [{ debugName: "dataConfig" }] : []));
|
|
1398
1527
|
this.configuration = computed(() => merge({}, defaultSettings$2, this.defaultConfig(), this.config()), ...(ngDevMode ? [{ debugName: "configuration" }] : []));
|
|
1399
1528
|
}
|
|
@@ -1401,12 +1530,12 @@ class BarChartComponent {
|
|
|
1401
1530
|
return this.chart().exportAsSvg(config);
|
|
1402
1531
|
}
|
|
1403
1532
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: BarChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1404
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.
|
|
1533
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.13", type: BarChartComponent, isStandalone: true, selector: "he-bar-chart", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, datasets: { classPropertyName: "datasets", publicName: "datasets", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, datasetLabel: { classPropertyName: "datasetLabel", publicName: "datasetLabel", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, showExportButton: { classPropertyName: "showExportButton", publicName: "showExportButton", isSignal: true, isRequired: false, transformFunction: null }, showNegativeValues: { classPropertyName: "showNegativeValues", publicName: "showNegativeValues", isSignal: true, isRequired: false, transformFunction: null }, maximumValues: { classPropertyName: "maximumValues", publicName: "maximumValues", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "chart", first: true, predicate: ChartComponent, descendants: true, isSignal: true }], exportAs: ["barChart"], ngImport: i0, template: "<he-chart [data]=\"dataConfig()\" [config]=\"configuration()\" [showExportButton]=\"showExportButton()\">\n <ng-content />\n</he-chart>\n\n@if (hasNegativeContributions()) {\n <p class=\"is-mt-2 is-italic is-size-7 has-text-center\">\n <span class=\"is-pr-1\">This chart includes negative contributions that will appear as</span>\n <b>0</b>\n <span>.</span>\n </p>\n}\n\n<he-bar-chart-legend [data]=\"maximumData()\" />\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "component", type: ChartComponent, selector: "he-chart", inputs: ["data", "config", "showExportButton"], exportAs: ["chart"] }, { kind: "component", type: BarChartLegendComponent, selector: "he-bar-chart-legend", inputs: ["data"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1405
1534
|
}
|
|
1406
1535
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: BarChartComponent, decorators: [{
|
|
1407
1536
|
type: Component$1,
|
|
1408
|
-
args: [{ selector: 'he-bar-chart', exportAs: 'barChart', changeDetection: ChangeDetectionStrategy.OnPush, imports: [ChartComponent], template: "<he-chart [data]=\"dataConfig()\" [config]=\"configuration()\" [showExportButton]=\"showExportButton()\">\n <ng-content />\n</he-chart>\n", styles: [":host{display:block}\n"] }]
|
|
1409
|
-
}], propDecorators: {
|
|
1537
|
+
args: [{ selector: 'he-bar-chart', exportAs: 'barChart', changeDetection: ChangeDetectionStrategy.OnPush, imports: [ChartComponent, BarChartLegendComponent], template: "<he-chart [data]=\"dataConfig()\" [config]=\"configuration()\" [showExportButton]=\"showExportButton()\">\n <ng-content />\n</he-chart>\n\n@if (hasNegativeContributions()) {\n <p class=\"is-mt-2 is-italic is-size-7 has-text-center\">\n <span class=\"is-pr-1\">This chart includes negative contributions that will appear as</span>\n <b>0</b>\n <span>.</span>\n </p>\n}\n\n<he-bar-chart-legend [data]=\"maximumData()\" />\n", styles: [":host{display:block}\n"] }]
|
|
1538
|
+
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], datasets: [{ type: i0.Input, args: [{ isSignal: true, alias: "datasets", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], datasetLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "datasetLabel", required: false }] }], labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: false }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }], showExportButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showExportButton", required: false }] }], showNegativeValues: [{ type: i0.Input, args: [{ isSignal: true, alias: "showNegativeValues", required: false }] }], maximumValues: [{ type: i0.Input, args: [{ isSignal: true, alias: "maximumValues", required: false }] }], chart: [{ type: i0.ViewChild, args: [i0.forwardRef(() => ChartComponent), { isSignal: true }] }] } });
|
|
1410
1539
|
|
|
1411
1540
|
const parsePrecision = (value, precision) => toPrecision(parseFloat(`${value}`), parseInt(`${precision}`, 10));
|
|
1412
1541
|
const transform = (value, precision = 3, enableComma = true) => typeof value !== 'boolean' && !isUndefined(value) && isNumber(value)
|
|
@@ -1422,8 +1551,7 @@ class PrecisionPipe {
|
|
|
1422
1551
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: PrecisionPipe, decorators: [{
|
|
1423
1552
|
type: Pipe,
|
|
1424
1553
|
args: [{
|
|
1425
|
-
name: 'precision'
|
|
1426
|
-
standalone: true
|
|
1554
|
+
name: 'precision'
|
|
1427
1555
|
}]
|
|
1428
1556
|
}] });
|
|
1429
1557
|
|
|
@@ -1437,27 +1565,27 @@ const defaultSettings$1 = Object.freeze({
|
|
|
1437
1565
|
options: {
|
|
1438
1566
|
events: [],
|
|
1439
1567
|
responsive: true,
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1568
|
+
plugins: {
|
|
1569
|
+
tooltip: {
|
|
1570
|
+
enabled: false
|
|
1571
|
+
},
|
|
1572
|
+
legend: {
|
|
1573
|
+
display: false,
|
|
1574
|
+
align: 'center'
|
|
1575
|
+
}
|
|
1446
1576
|
},
|
|
1447
1577
|
scales: {
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
crossAlign: 'center'
|
|
1458
|
-
}
|
|
1578
|
+
y: {
|
|
1579
|
+
display: true,
|
|
1580
|
+
position: 'left',
|
|
1581
|
+
grid: {
|
|
1582
|
+
display: true
|
|
1583
|
+
},
|
|
1584
|
+
beginAtZero: true,
|
|
1585
|
+
ticks: {
|
|
1586
|
+
crossAlign: 'center'
|
|
1459
1587
|
}
|
|
1460
|
-
|
|
1588
|
+
}
|
|
1461
1589
|
}
|
|
1462
1590
|
}
|
|
1463
1591
|
});
|
|
@@ -1541,41 +1669,40 @@ class DistributionChartComponent {
|
|
|
1541
1669
|
this.defaultConfig = computed(() => ({
|
|
1542
1670
|
options: {
|
|
1543
1671
|
scales: {
|
|
1544
|
-
|
|
1545
|
-
|
|
1672
|
+
x: {
|
|
1673
|
+
display: true,
|
|
1674
|
+
grid: {
|
|
1675
|
+
offset: true
|
|
1676
|
+
},
|
|
1677
|
+
min: 0,
|
|
1678
|
+
ticks: {
|
|
1679
|
+
callback: (label) => label
|
|
1680
|
+
.split(joinXLabel)
|
|
1681
|
+
.map(parseFloat)
|
|
1682
|
+
.map(v => transform(v, 3, true))
|
|
1683
|
+
// .map(v => v.toExponential())
|
|
1684
|
+
.join('-')
|
|
1685
|
+
},
|
|
1686
|
+
title: {
|
|
1546
1687
|
display: true,
|
|
1547
|
-
|
|
1548
|
-
offsetGridLines: true
|
|
1549
|
-
},
|
|
1550
|
-
ticks: {
|
|
1551
|
-
min: 0,
|
|
1552
|
-
userCallback: (label) => label
|
|
1553
|
-
.split(joinXLabel)
|
|
1554
|
-
.map(parseFloat)
|
|
1555
|
-
.map(v => transform(v, 3, true))
|
|
1556
|
-
// .map(v => v.toExponential())
|
|
1557
|
-
.join('-')
|
|
1558
|
-
},
|
|
1559
|
-
scaleLabel: {
|
|
1560
|
-
display: true,
|
|
1561
|
-
labelString: this.label()
|
|
1562
|
-
}
|
|
1688
|
+
text: this.label()
|
|
1563
1689
|
}
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
{
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1690
|
+
},
|
|
1691
|
+
y: {
|
|
1692
|
+
ticks: {
|
|
1693
|
+
font: {
|
|
1694
|
+
family: 'Lato',
|
|
1695
|
+
size: 10,
|
|
1696
|
+
style: 'normal',
|
|
1697
|
+
weight: 400
|
|
1572
1698
|
},
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1699
|
+
color: '#4A4A4A'
|
|
1700
|
+
},
|
|
1701
|
+
title: {
|
|
1702
|
+
display: true,
|
|
1703
|
+
text: 'Frequency of values'
|
|
1577
1704
|
}
|
|
1578
|
-
|
|
1705
|
+
}
|
|
1579
1706
|
}
|
|
1580
1707
|
}
|
|
1581
1708
|
}), ...(ngDevMode ? [{ debugName: "defaultConfig" }] : []));
|
|
@@ -1589,8 +1716,6 @@ class DistributionChartComponent {
|
|
|
1589
1716
|
backgroundColor: opaqueColor(colors.lightBlue),
|
|
1590
1717
|
borderColor: colors.lightBlue,
|
|
1591
1718
|
borderWidth: 1,
|
|
1592
|
-
fill: true,
|
|
1593
|
-
pointRadius: 0,
|
|
1594
1719
|
type: 'bar'
|
|
1595
1720
|
},
|
|
1596
1721
|
{
|
|
@@ -1604,7 +1729,7 @@ class DistributionChartComponent {
|
|
|
1604
1729
|
type: 'line'
|
|
1605
1730
|
}
|
|
1606
1731
|
]
|
|
1607
|
-
:
|
|
1732
|
+
: [],
|
|
1608
1733
|
this.singlePoint()?.length
|
|
1609
1734
|
? {
|
|
1610
1735
|
label: 'Value',
|
|
@@ -1617,10 +1742,8 @@ class DistributionChartComponent {
|
|
|
1617
1742
|
type: 'line',
|
|
1618
1743
|
tension: 0
|
|
1619
1744
|
}
|
|
1620
|
-
:
|
|
1621
|
-
]
|
|
1622
|
-
.filter(Boolean)
|
|
1623
|
-
.flat(),
|
|
1745
|
+
: []
|
|
1746
|
+
].flat(),
|
|
1624
1747
|
labels: this.groupedData().labels
|
|
1625
1748
|
}), ...(ngDevMode ? [{ debugName: "dataConfig" }] : []));
|
|
1626
1749
|
this.configuration = computed(() => merge({}, defaultSettings$1, this.defaultConfig(), this.config()), ...(ngDevMode ? [{ debugName: "configuration" }] : []));
|
|
@@ -1633,42 +1756,110 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImpo
|
|
|
1633
1756
|
args: [{ selector: 'he-distribution-chart', changeDetection: ChangeDetectionStrategy.OnPush, imports: [ChartComponent], template: "<he-chart [data]=\"dataConfig()\" [config]=\"configuration()\" />\n", styles: [":host{display:block}\n"] }]
|
|
1634
1757
|
}], propDecorators: { distribution: [{ type: i0.Input, args: [{ isSignal: true, alias: "distribution", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], nbBins: [{ type: i0.Input, args: [{ isSignal: true, alias: "nbBins", required: false }] }], maxPercentile: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxPercentile", required: false }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }] } });
|
|
1635
1758
|
|
|
1636
|
-
const defaultSettings = {
|
|
1759
|
+
const defaultSettings = Object.freeze({
|
|
1637
1760
|
type: 'line',
|
|
1638
1761
|
options: {
|
|
1639
1762
|
scales: {
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1763
|
+
x: {
|
|
1764
|
+
type: 'time',
|
|
1765
|
+
time: {
|
|
1766
|
+
unit: 'day'
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1770
|
+
}
|
|
1771
|
+
});
|
|
1772
|
+
class LineChartComponent {
|
|
1773
|
+
constructor() {
|
|
1774
|
+
this.datasets = input([], ...(ngDevMode ? [{ debugName: "datasets" }] : []));
|
|
1775
|
+
this.config = input({}, ...(ngDevMode ? [{ debugName: "config" }] : []));
|
|
1776
|
+
this.showExportButton = input(true, ...(ngDevMode ? [{ debugName: "showExportButton" }] : []));
|
|
1777
|
+
this.chart = viewChild.required(ChartComponent);
|
|
1778
|
+
this.exporting = computed(() => this.chart()?.exporting(), ...(ngDevMode ? [{ debugName: "exporting" }] : []));
|
|
1779
|
+
this.dataConfig = computed(() => ({
|
|
1780
|
+
datasets: this.datasets()
|
|
1781
|
+
}), ...(ngDevMode ? [{ debugName: "dataConfig" }] : []));
|
|
1782
|
+
this.configuration = computed(() => merge({}, defaultSettings, this.config()), ...(ngDevMode ? [{ debugName: "configuration" }] : []));
|
|
1783
|
+
}
|
|
1784
|
+
exportAsSvg(config = {}) {
|
|
1785
|
+
return this.chart().exportAsSvg(config);
|
|
1786
|
+
}
|
|
1787
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: LineChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1788
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.3.13", type: LineChartComponent, isStandalone: true, selector: "he-line-chart", inputs: { datasets: { classPropertyName: "datasets", publicName: "datasets", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, showExportButton: { classPropertyName: "showExportButton", publicName: "showExportButton", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "chart", first: true, predicate: ChartComponent, descendants: true, isSignal: true }], exportAs: ["lineChart"], ngImport: i0, template: "<he-chart [data]=\"dataConfig()\" [config]=\"configuration()\" [showExportButton]=\"showExportButton()\" />\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "component", type: ChartComponent, selector: "he-chart", inputs: ["data", "config", "showExportButton"], exportAs: ["chart"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1789
|
+
}
|
|
1790
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: LineChartComponent, decorators: [{
|
|
1791
|
+
type: Component$1,
|
|
1792
|
+
args: [{ selector: 'he-line-chart', exportAs: 'lineChart', changeDetection: ChangeDetectionStrategy.OnPush, imports: [ChartComponent], template: "<he-chart [data]=\"dataConfig()\" [config]=\"configuration()\" [showExportButton]=\"showExportButton()\" />\n", styles: [":host{display:block}\n"] }]
|
|
1793
|
+
}], propDecorators: { datasets: [{ type: i0.Input, args: [{ isSignal: true, alias: "datasets", required: false }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }], showExportButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showExportButton", required: false }] }], chart: [{ type: i0.ViewChild, args: [i0.forwardRef(() => ChartComponent), { isSignal: true }] }] } });
|
|
1794
|
+
|
|
1795
|
+
const defaultConfig = Object.freeze({
|
|
1796
|
+
options: {
|
|
1797
|
+
indexAxis: 'y',
|
|
1798
|
+
scales: {
|
|
1799
|
+
x: {
|
|
1800
|
+
grid: {
|
|
1801
|
+
drawOnChartArea: false
|
|
1802
|
+
},
|
|
1803
|
+
ticks: {
|
|
1804
|
+
callback: value => toPrecision(Number(value), 3)
|
|
1805
|
+
}
|
|
1806
|
+
},
|
|
1807
|
+
y: {
|
|
1808
|
+
grid: {
|
|
1809
|
+
drawOnChartArea: false
|
|
1810
|
+
},
|
|
1811
|
+
ticks: {
|
|
1812
|
+
crossAlign: 'near'
|
|
1813
|
+
}
|
|
1814
|
+
}
|
|
1815
|
+
}
|
|
1816
|
+
}
|
|
1817
|
+
});
|
|
1818
|
+
const defaultTooltipFn = ({ label, count, includedItems }) => includedItems.length ? includedItems.map(item => defaultTooltipFn(item)).join('</br>') : `${label}: ${count}`;
|
|
1819
|
+
class HorizontalBarChartComponent extends BarChartComponent {
|
|
1820
|
+
constructor() {
|
|
1821
|
+
super(...arguments);
|
|
1822
|
+
this.tooltipFn = input(defaultTooltipFn, ...(ngDevMode ? [{ debugName: "tooltipFn" }] : []));
|
|
1823
|
+
this.afterBarDrawSettings = input(...(ngDevMode ? [undefined, { debugName: "afterBarDrawSettings" }] : []));
|
|
1824
|
+
this.tooltip = viewChild.required('tooltip');
|
|
1825
|
+
this.horizontalConfiguration = computed(() => ({
|
|
1826
|
+
...merge(this.configuration(), defaultConfig, {
|
|
1827
|
+
options: {
|
|
1828
|
+
onClick: (event, activeElements) => {
|
|
1829
|
+
const index = activeElements?.[0]?.index;
|
|
1830
|
+
!isUndefined(index) && this.showTooltip(index, event.x, event.y);
|
|
1831
|
+
},
|
|
1832
|
+
scales: {
|
|
1833
|
+
y: {
|
|
1834
|
+
display: !this.responsiveService.isMobile()
|
|
1835
|
+
}
|
|
1645
1836
|
}
|
|
1646
1837
|
}
|
|
1838
|
+
}),
|
|
1839
|
+
plugins: [
|
|
1840
|
+
lollipopChartPlugin(),
|
|
1841
|
+
backgroundHoverPlugin({ threshold: 5 }),
|
|
1842
|
+
afterBarDrawPlugin(this.afterBarDrawSettings()),
|
|
1843
|
+
...(this.configuration().plugins ?? [])
|
|
1647
1844
|
]
|
|
1648
|
-
}
|
|
1649
|
-
|
|
1650
|
-
};
|
|
1651
|
-
class LineChartComponent {
|
|
1652
|
-
constructor() {
|
|
1653
|
-
this.datasets = input([], ...(ngDevMode ? [{ debugName: "datasets" }] : []));
|
|
1654
|
-
this.config = input({}, ...(ngDevMode ? [{ debugName: "config" }] : []));
|
|
1655
|
-
this.showExportButton = input(true, ...(ngDevMode ? [{ debugName: "showExportButton" }] : []));
|
|
1656
|
-
this.chart = viewChild.required(ChartComponent);
|
|
1657
|
-
this.dataConfig = computed(() => ({
|
|
1658
|
-
datasets: this.datasets()
|
|
1659
|
-
}), ...(ngDevMode ? [{ debugName: "dataConfig" }] : []));
|
|
1660
|
-
this.configuration = computed(() => merge({}, defaultSettings, this.config()), ...(ngDevMode ? [{ debugName: "configuration" }] : []));
|
|
1845
|
+
}), ...(ngDevMode ? [{ debugName: "horizontalConfiguration" }] : []));
|
|
1846
|
+
this.tooltipX = signal(0, ...(ngDevMode ? [{ debugName: "tooltipX" }] : []));
|
|
1847
|
+
this.tooltipY = signal(0, ...(ngDevMode ? [{ debugName: "tooltipY" }] : []));
|
|
1661
1848
|
}
|
|
1662
|
-
|
|
1663
|
-
|
|
1849
|
+
showTooltip(index, x, y) {
|
|
1850
|
+
this.tooltipX.set(x);
|
|
1851
|
+
this.tooltipY.set(y);
|
|
1852
|
+
const data = this.maximumData()[index];
|
|
1853
|
+
const text = this.tooltipFn()(data || {}, index);
|
|
1854
|
+
text && setTimeout(() => this.tooltip().open({ data: text }));
|
|
1664
1855
|
}
|
|
1665
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type:
|
|
1666
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.
|
|
1856
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: HorizontalBarChartComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
1857
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.13", type: HorizontalBarChartComponent, isStandalone: true, selector: "he-horizontal-bar-chart", inputs: { tooltipFn: { classPropertyName: "tooltipFn", publicName: "tooltipFn", isSignal: true, isRequired: false, transformFunction: null }, afterBarDrawSettings: { classPropertyName: "afterBarDrawSettings", publicName: "afterBarDrawSettings", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "tooltip", first: true, predicate: ["tooltip"], descendants: true, isSignal: true }], exportAs: ["horizontalBarChart"], usesInheritance: true, ngImport: i0, template: "<div class=\"chart-area-border\">\n <he-chart\n class=\"is-relative h-100\"\n [data]=\"dataConfig()\"\n [config]=\"horizontalConfiguration()\"\n [showExportButton]=\"showExportButton()\">\n <div\n class=\"is-invisible is-absolute | shadow-tooltip\"\n [style.left.px]=\"tooltipX()\"\n [style.top.px]=\"tooltipY()\"\n [ngbTooltip]=\"rawHtmlContent\"\n triggers=\"manual\"\n autoClose=\"outside\"\n placement=\"bottom\"\n #tooltip=\"ngbTooltip\"></div>\n\n <ng-template #rawHtmlContent let-rawString=\"data\">\n <div [innerHTML]=\"rawString\"></div>\n </ng-template>\n\n <ng-content />\n </he-chart>\n</div>\n\n@if (hasNegativeContributions()) {\n <p class=\"is-mt-2 is-italic is-size-7 has-text-center\">\n <span class=\"is-pr-1\">This chart includes negative contributions that will appear as</span>\n <b>0</b>\n <span>.</span>\n </p>\n}\n\n<he-bar-chart-legend [data]=\"maximumData()\" />\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "component", type: ChartComponent, selector: "he-chart", inputs: ["data", "config", "showExportButton"], exportAs: ["chart"] }, { kind: "directive", type: 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: BarChartLegendComponent, selector: "he-bar-chart-legend", inputs: ["data"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1667
1858
|
}
|
|
1668
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type:
|
|
1859
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: HorizontalBarChartComponent, decorators: [{
|
|
1669
1860
|
type: Component$1,
|
|
1670
|
-
args: [{ selector: 'he-
|
|
1671
|
-
}], propDecorators: {
|
|
1861
|
+
args: [{ selector: 'he-horizontal-bar-chart', exportAs: 'horizontalBarChart', changeDetection: ChangeDetectionStrategy.OnPush, imports: [ChartComponent, NgbTooltip, BarChartLegendComponent], template: "<div class=\"chart-area-border\">\n <he-chart\n class=\"is-relative h-100\"\n [data]=\"dataConfig()\"\n [config]=\"horizontalConfiguration()\"\n [showExportButton]=\"showExportButton()\">\n <div\n class=\"is-invisible is-absolute | shadow-tooltip\"\n [style.left.px]=\"tooltipX()\"\n [style.top.px]=\"tooltipY()\"\n [ngbTooltip]=\"rawHtmlContent\"\n triggers=\"manual\"\n autoClose=\"outside\"\n placement=\"bottom\"\n #tooltip=\"ngbTooltip\"></div>\n\n <ng-template #rawHtmlContent let-rawString=\"data\">\n <div [innerHTML]=\"rawString\"></div>\n </ng-template>\n\n <ng-content />\n </he-chart>\n</div>\n\n@if (hasNegativeContributions()) {\n <p class=\"is-mt-2 is-italic is-size-7 has-text-center\">\n <span class=\"is-pr-1\">This chart includes negative contributions that will appear as</span>\n <b>0</b>\n <span>.</span>\n </p>\n}\n\n<he-bar-chart-legend [data]=\"maximumData()\" />\n", styles: [":host{display:block}\n"] }]
|
|
1862
|
+
}], propDecorators: { tooltipFn: [{ type: i0.Input, args: [{ isSignal: true, alias: "tooltipFn", required: false }] }], afterBarDrawSettings: [{ type: i0.Input, args: [{ isSignal: true, alias: "afterBarDrawSettings", required: false }] }], tooltip: [{ type: i0.ViewChild, args: ['tooltip', { isSignal: true }] }] } });
|
|
1672
1863
|
|
|
1673
1864
|
const ignoreCompounds = (value) => typeof value !== 'string' ||
|
|
1674
1865
|
[
|
|
@@ -2703,8 +2894,7 @@ class ResizedDirective {
|
|
|
2703
2894
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: ResizedDirective, decorators: [{
|
|
2704
2895
|
type: Directive,
|
|
2705
2896
|
args: [{
|
|
2706
|
-
selector: '[resized]'
|
|
2707
|
-
standalone: true
|
|
2897
|
+
selector: '[resized]'
|
|
2708
2898
|
}]
|
|
2709
2899
|
}], ctorParameters: () => [], propDecorators: { resized: [{ type: i0.Output, args: ["resized"] }] } });
|
|
2710
2900
|
|
|
@@ -2898,7 +3088,7 @@ class BlankNodeStateNoticeComponent {
|
|
|
2898
3088
|
}
|
|
2899
3089
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: BlankNodeStateNoticeComponent, decorators: [{
|
|
2900
3090
|
type: Component$1,
|
|
2901
|
-
args: [{ selector: 'he-blank-node-state-notice', changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3091
|
+
args: [{ selector: 'he-blank-node-state-notice', changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (show()) {\n <div class=\"is-flex is-gap-8 is-align-items-center is-size-7 is-italic\">\n <span class=\"notice-data-unchaged\">\u2020 Data uploaded by the user</span>\n <span class=\"divider\"></span>\n <span class=\"notice-data-added\">* Data added by HESTIA</span>\n <span class=\"divider\"></span>\n <span class=\"notice-data-updated\">** Data updated by HESTIA</span>\n @if (showDeleted()) {\n <span class=\"divider\"></span>\n <span class=\"notice-data-deleted\">**** Data deleted by HESTIA</span>\n }\n </div>\n}\n", styles: ["@media screen and (max-width: 767px){:host div{flex-direction:column;align-items:flex-start!important}:host div .divider{display:none}}.divider{width:1px;height:20px;background:#4a4a4a}\n"] }]
|
|
2902
3092
|
}], propDecorators: { dataState: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataState", required: false }] }], showDeleted: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDeleted", required: false }] }] } });
|
|
2903
3093
|
|
|
2904
3094
|
class BlankNodeValueDeltaComponent {
|
|
@@ -3199,100 +3389,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImpo
|
|
|
3199
3389
|
}, template: "<aside\n class=\"is-flex is-flex-direction-column is-gap-12 is-overflow-hidden is-py-desktop-3 | menu\"\n [class.sticky]=\"sticky()\">\n <ng-content select=\"[header]\" />\n\n <div class=\"is-flex is-flex-direction-column is-gap-4\">\n @for (link of links(); track trackByLink(link)) {\n <ng-container *ngTemplateOutlet=\"linkItem; context: { link, parentLinks: [], level: 1 }\" />\n }\n </div>\n\n <ng-content select=\"[footer]\" />\n</aside>\n\n<ng-template #linkExpandIcon let-link>\n @if (isCollapsible(link)) {\n <he-svg-icon\n [name]=\"link.expanded ? 'chevron-down' : 'chevron-right'\"\n class=\"is-inline-block is-clickable\"\n size=\"20\"\n (click)=\"toggleLink($event, link)\" />\n }\n</ng-template>\n\n<ng-template #linkContent let-link=\"link\" let-level=\"level\">\n @if (level === 1) {\n @if (link.icon) {\n <he-svg-icon [name]=\"link.icon\" size=\"20\" class=\"is-inline-block has-text-secondary\" />\n } @else if (hasPrimaryIcons()) {\n <span class=\"primary-missing-icon\"> </span>\n }\n }\n <span class=\"is-flex is-flex-grow-1 is-align-self-center\" [innerHTML]=\"link.title\"></span>\n <ng-container *ngTemplateOutlet=\"linkExpandIcon; context: { $implicit: link }\" />\n</ng-template>\n\n<ng-template #linkItemChildren let-link=\"link\" let-parentLinks=\"parentLinks\" let-level=\"level\">\n @let childParents = concatLinks(link, parentLinks);\n @if (isCollapsible(link)) {\n <div\n class=\"is-flex is-flex-direction-column is-align-items-stretch | he-menu-child-items\"\n [class.is-hidden]=\"!link.expanded\">\n @for (childLink of link.links; track trackByLink(childLink)) {\n <ng-container\n *ngTemplateOutlet=\"linkItem; context: { link: childLink, parentLinks: childParents, level: level + 1 }\" />\n }\n </div>\n }\n</ng-template>\n\n<ng-template #linkItem let-link=\"link\" let-parentLinks=\"parentLinks\" let-level=\"level\">\n <div\n class=\"is-flex is-align-items-center is-gap-4 | he-menu-item\"\n [attr.data-menu-level]=\"level\"\n (click)=\"toggleLink($event, link)\"\n [class.with-border-color]=\"!!link.borderColor\">\n @if (link.borderColor) {\n <div class=\"he-menu-border\" [style.background-color]=\"link.borderColor\"></div>\n }\n <a\n class=\"is-flex is-flex-grow-1 is-align-self-stretch is-align-items-center is-gap-8 has-text-secondary | he-menu-label\"\n [class.he-menu-item-selectable]=\"!!link?.url\"\n (click)=\"link.url ? close() : null\"\n [routerLink]=\"link.url\"\n [queryParams]=\"link.queryParams\"\n [fragment]=\"link.fragment\"\n routerLinkActive=\"link-active\"\n [routerLinkActiveOptions]=\"linkActiveOptions(link, level)\"\n (isActiveChange)=\"$event && linksActiveChange(link, parentLinks)\">\n <ng-container *ngTemplateOutlet=\"linkContent; context: { link, level }\" />\n </a>\n </div>\n <ng-container *ngTemplateOutlet=\"linkItemChildren; context: { link, parentLinks, level }\" />\n</ng-template>\n", styles: [".navigation-menu{width:100%;display:block}.navigation-menu .menu{font-size:.875rem;line-height:16px;color:#193957;font-weight:400;width:100%!important;max-width:100%!important}@media screen and (min-width: 1024px){.navigation-menu .menu{width:14rem!important;min-width:14rem!important;max-width:14rem!important;border-style:solid;border-color:#ffc000;border-width:1px 0}}.navigation-menu .menu.fixed-top{transform:translate3d(0,6.75rem,0)}.navigation-menu .menu.sticky{position:sticky;top:6.75rem}.navigation-menu a{text-decoration:none!important}.navigation-menu a:focus,.navigation-menu a:active{outline:0!important}.navigation-menu .cursor-default{cursor:default!important}.navigation-menu .primary-missing-icon{height:20px;width:20px;min-width:20px}.navigation-menu .he-menu-item{padding:1px 0}.navigation-menu .he-menu-item .he-menu-label{height:28px;border-radius:3px;padding:4px}.navigation-menu .he-menu-item .he-menu-border{width:8px;height:28px}.navigation-menu .he-menu-item[data-menu-level=\"1\"] span{font-weight:700}.navigation-menu .he-menu-item[data-menu-level=\"1\"]+.he-menu-child-items{padding-left:14px}.navigation-menu .he-menu-item[data-menu-level=\"2\"]{padding-left:14px;border-left:1px solid #ffc000}.navigation-menu .he-menu-item[data-menu-level=\"2\"]+.he-menu-child-items{padding-left:28px}.navigation-menu .he-menu-item-selectable:not(.link-active):hover{background-color:#fefaef}.navigation-menu .he-menu-item.with-border-color .he-menu-label{border-radius:0}.navigation-menu .he-menu-item.with-border-color[data-menu-level=\"1\"]+.he-menu-child-items{padding-left:26px}.navigation-menu .he-menu-child-items{padding-left:14px}.navigation-menu .link-active{background-color:#ffe8a3;color:#193957!important}\n"] }]
|
|
3200
3390
|
}], propDecorators: { links: [{ type: i0.Input, args: [{ isSignal: true, alias: "links", required: false }] }], sticky: [{ type: i0.Input, args: [{ isSignal: true, alias: "sticky", required: false }] }], collapsible: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsible", required: false }] }], routerLinkMatchOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "routerLinkMatchOptions", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
|
|
3201
3391
|
|
|
3202
|
-
var Breakpoint;
|
|
3203
|
-
(function (Breakpoint) {
|
|
3204
|
-
Breakpoint["tablet"] = "tablet";
|
|
3205
|
-
Breakpoint["desktop"] = "desktop";
|
|
3206
|
-
Breakpoint["widescreen"] = "widescreen";
|
|
3207
|
-
Breakpoint["fullhd"] = "fullhd";
|
|
3208
|
-
})(Breakpoint || (Breakpoint = {}));
|
|
3209
|
-
const beakpointWidths = {
|
|
3210
|
-
[Breakpoint.tablet]: 768,
|
|
3211
|
-
[Breakpoint.desktop]: 1024,
|
|
3212
|
-
[Breakpoint.widescreen]: 1216,
|
|
3213
|
-
[Breakpoint.fullhd]: 1408
|
|
3214
|
-
};
|
|
3215
|
-
const toSize = (size, dir) => `(${dir}-width: ${dir === 'max' ? size - 1 : size}px)`;
|
|
3216
|
-
const toBreakpoint = ({ min, max }) => [min ? toSize(beakpointWidths[min], 'min') : '', max ? toSize(beakpointWidths[max], 'max') : '']
|
|
3217
|
-
.filter(Boolean)
|
|
3218
|
-
.join(' and ');
|
|
3219
|
-
class ResponsiveService {
|
|
3220
|
-
constructor() {
|
|
3221
|
-
this.breakPointObserver = inject(BreakpointObserver);
|
|
3222
|
-
this.windowWidth$ = fromEvent(window, 'resize').pipe(startWith(window.innerWidth), map(() => window.innerWidth));
|
|
3223
|
-
this.isMobile$ = this.breakPointObserver.observe(toBreakpoint({ max: Breakpoint.tablet })).pipe(map(state => state.matches), distinctUntilChanged());
|
|
3224
|
-
this.isTablet$ = this.breakPointObserver
|
|
3225
|
-
.observe(toBreakpoint({ min: Breakpoint.tablet, max: Breakpoint.desktop }))
|
|
3226
|
-
.pipe(map(state => state.matches), distinctUntilChanged());
|
|
3227
|
-
this.isDesktop$ = this.breakPointObserver
|
|
3228
|
-
.observe(toBreakpoint({ min: Breakpoint.desktop, max: Breakpoint.widescreen }))
|
|
3229
|
-
.pipe(map(state => state.matches), distinctUntilChanged());
|
|
3230
|
-
this.isWidescreen$ = this.breakPointObserver
|
|
3231
|
-
.observe(toBreakpoint({ min: Breakpoint.widescreen, max: Breakpoint.fullhd }))
|
|
3232
|
-
.pipe(map(state => state.matches), distinctUntilChanged());
|
|
3233
|
-
this.isFullHd$ = this.breakPointObserver.observe(toBreakpoint({ min: Breakpoint.fullhd })).pipe(map(state => state.matches), distinctUntilChanged());
|
|
3234
|
-
this.isTouch$ = this.breakPointObserver.observe(toBreakpoint({ max: Breakpoint.desktop })).pipe(map(state => state.matches), distinctUntilChanged());
|
|
3235
|
-
/**
|
|
3236
|
-
* Resolution for 1080p (or Full HD) on a normal screen, although bulma defines it differently.
|
|
3237
|
-
*/
|
|
3238
|
-
this.is1080p$ = this.breakPointObserver.observe(toSize(1920, 'min')).pipe(map(state => state.matches), distinctUntilChanged());
|
|
3239
|
-
this.isRetinaDisplay = () => {
|
|
3240
|
-
if (window.matchMedia) {
|
|
3241
|
-
const mq = window.matchMedia([
|
|
3242
|
-
'min--moz-device-pixel-ratio: 1.3',
|
|
3243
|
-
'-o-min-device-pixel-ratio: 2.6/2',
|
|
3244
|
-
'-webkit-min-device-pixel-ratio: 1.3',
|
|
3245
|
-
'min-device-pixel-ratio: 1.3',
|
|
3246
|
-
'min-resolution: 1.3dppx'
|
|
3247
|
-
]
|
|
3248
|
-
.map(v => `only screen and (${v})`)
|
|
3249
|
-
.join(', '));
|
|
3250
|
-
return mq?.matches || window.devicePixelRatio > 1;
|
|
3251
|
-
}
|
|
3252
|
-
return false;
|
|
3253
|
-
};
|
|
3254
|
-
this.isMobile = toSignal(this.isMobile$);
|
|
3255
|
-
this.isTablet = toSignal(this.isTablet$);
|
|
3256
|
-
this.isDesktop = toSignal(this.isDesktop$);
|
|
3257
|
-
this.isWidescreen = toSignal(this.isWidescreen$);
|
|
3258
|
-
this.isFullHd = toSignal(this.isFullHd$);
|
|
3259
|
-
this.isTouch = toSignal(this.isTouch$);
|
|
3260
|
-
this.is1080p = toSignal(this.is1080p$);
|
|
3261
|
-
this.resolutionName = computed(() => this.isMobile()
|
|
3262
|
-
? 'mobile'
|
|
3263
|
-
: this.isTablet()
|
|
3264
|
-
? 'tablet'
|
|
3265
|
-
: this.isDesktop()
|
|
3266
|
-
? 'desktop'
|
|
3267
|
-
: this.isWidescreen()
|
|
3268
|
-
? 'widescreen'
|
|
3269
|
-
: 'fullhd', ...(ngDevMode ? [{ debugName: "resolutionName" }] : []));
|
|
3270
|
-
this.resolutionName$ = toObservable(this.resolutionName);
|
|
3271
|
-
}
|
|
3272
|
-
isAboveBreakpoint$(breakpoint) {
|
|
3273
|
-
return typeof breakpoint === 'number'
|
|
3274
|
-
? this.windowWidth$.pipe(map(width => width >= breakpoint))
|
|
3275
|
-
: breakpoint === 'none'
|
|
3276
|
-
? of(false)
|
|
3277
|
-
: this._isAboveBreakpointName$(breakpoint);
|
|
3278
|
-
}
|
|
3279
|
-
_isAboveBreakpointName$(breakpoint) {
|
|
3280
|
-
return this.resolutionName$.pipe(map(resolutionName => {
|
|
3281
|
-
const width = beakpointWidths[resolutionName];
|
|
3282
|
-
const overlapBreakpointWidth = beakpointWidths[breakpoint];
|
|
3283
|
-
return width >= overlapBreakpointWidth;
|
|
3284
|
-
}));
|
|
3285
|
-
}
|
|
3286
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: ResponsiveService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
3287
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: ResponsiveService, providedIn: 'root' }); }
|
|
3288
|
-
}
|
|
3289
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: ResponsiveService, decorators: [{
|
|
3290
|
-
type: Injectable,
|
|
3291
|
-
args: [{
|
|
3292
|
-
providedIn: 'root'
|
|
3293
|
-
}]
|
|
3294
|
-
}] });
|
|
3295
|
-
|
|
3296
3392
|
const storageKey$2 = 'he-drawer-container';
|
|
3297
3393
|
const moveEvent = () => merge$1(fromEvent(window, 'mousemove').pipe(map(event => event.clientX)), fromEvent(window, 'touchmove', { passive: false }).pipe(map(event => event.touches[0].clientX)));
|
|
3298
3394
|
class DrawerContainerComponent {
|
|
@@ -3518,8 +3614,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImpo
|
|
|
3518
3614
|
type: Directive,
|
|
3519
3615
|
args: [{
|
|
3520
3616
|
selector: '[buttonScroller]',
|
|
3521
|
-
exportAs: 'buttonScroller'
|
|
3522
|
-
standalone: true
|
|
3617
|
+
exportAs: 'buttonScroller'
|
|
3523
3618
|
}]
|
|
3524
3619
|
}], propDecorators: { scrollUnit: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollUnit", required: false }] }] } });
|
|
3525
3620
|
|
|
@@ -3549,8 +3644,7 @@ class LongPressDirective {
|
|
|
3549
3644
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: LongPressDirective, decorators: [{
|
|
3550
3645
|
type: Directive,
|
|
3551
3646
|
args: [{
|
|
3552
|
-
selector: '[appLongPress]'
|
|
3553
|
-
standalone: true
|
|
3647
|
+
selector: '[appLongPress]'
|
|
3554
3648
|
}]
|
|
3555
3649
|
}], propDecorators: { longPress: [{ type: i0.Output, args: ["longPress"] }], intervalMs: [{ type: i0.Input, args: [{ isSignal: true, alias: "intervalMs", required: false }] }], onPressStart: [{
|
|
3556
3650
|
type: HostListener,
|
|
@@ -3590,8 +3684,7 @@ class IsEllipsisActiveDirective {
|
|
|
3590
3684
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: IsEllipsisActiveDirective, decorators: [{
|
|
3591
3685
|
type: Directive,
|
|
3592
3686
|
args: [{
|
|
3593
|
-
selector: '[isEllipsisActive]'
|
|
3594
|
-
standalone: true
|
|
3687
|
+
selector: '[isEllipsisActive]'
|
|
3595
3688
|
}]
|
|
3596
3689
|
}] });
|
|
3597
3690
|
|
|
@@ -4109,7 +4202,7 @@ class SkeletonTextComponent {
|
|
|
4109
4202
|
}
|
|
4110
4203
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: SkeletonTextComponent, decorators: [{
|
|
4111
4204
|
type: Component$1,
|
|
4112
|
-
args: [{ selector: 'he-skeleton-text',
|
|
4205
|
+
args: [{ selector: 'he-skeleton-text', template: "<span> </span>\n", styles: [":host{border-radius:3px;display:block;width:100%;height:inherit;margin-top:4px;margin-bottom:4px;background:#0001;line-height:10px;-webkit-user-select:none;user-select:none;pointer-events:none}span{display:inline-block}:host(.is-animated){position:relative;background:linear-gradient(to right,#0001 8%,#0002 18%,#0001 33%);background-size:800px 104px;animation-duration:1s;animation-fill-mode:forwards;animation-iteration-count:infinite;animation-name:shimmer;animation-timing-function:linear}@keyframes shimmer{0%{background-position:-468px 0}to{background-position:468px 0}}\n"] }]
|
|
4113
4206
|
}], propDecorators: { animated: [{ type: i0.Input, args: [{ isSignal: true, alias: "animated", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], _animated: [{
|
|
4114
4207
|
type: HostBinding,
|
|
4115
4208
|
args: ['class.is-animated']
|
|
@@ -4148,8 +4241,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImpo
|
|
|
4148
4241
|
args: [{
|
|
4149
4242
|
selector: 'he-social-tags',
|
|
4150
4243
|
template: '',
|
|
4151
|
-
changeDetection: ChangeDetectionStrategy.OnPush
|
|
4152
|
-
standalone: true
|
|
4244
|
+
changeDetection: ChangeDetectionStrategy.OnPush
|
|
4153
4245
|
}]
|
|
4154
4246
|
}], ctorParameters: () => [], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }], classes: [{
|
|
4155
4247
|
type: HostBinding,
|
|
@@ -4177,7 +4269,7 @@ class ToastComponent {
|
|
|
4177
4269
|
}
|
|
4178
4270
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: ToastComponent, decorators: [{
|
|
4179
4271
|
type: Component$1,
|
|
4180
|
-
args: [{ selector: 'he-toast',
|
|
4272
|
+
args: [{ selector: 'he-toast', template: "<div class=\"mb-3 columns is-centered is-vcentered\">\n @for (toast of toasts; track toast) {\n <div class=\"notification is-{{ toast.color }}\" role=\"alert\">\n <button class=\"delete\" (click)=\"dismiss(toast)\">\n <span aria-hidden=\"true\">×</span>\n </button>\n <strong>\n @switch (toast.color) {\n @case ('danger') {\n @switch (toast.message) {\n @case ('Unauthorized') {\n <span>You are not allowed to perform this action.</span>\n }\n @case ('form-invalid') {\n <span>Please fix all the errors on this page.</span>\n }\n @case ('users-email-already-taken') {\n <span>Email already taken.</span>\n }\n @case ('users-auth-already-taken') {\n <span>Account already connected.</span>\n }\n @default {\n <span>\n @if (toast.showRawMessage) {\n <span>{{ toast.message }}</span>\n }\n <span [class.is-hidden]=\"toast.showRawMessage\">\n An unknown error occurred. Please try again later.\n </span>\n </span>\n }\n }\n }\n @default {\n @if (toast.showRawMessage) {\n <span>{{ toast.message }}</span>\n }\n <span [class.is-hidden]=\"toast.showRawMessage\">An unknown error occurred. Please try again later.</span>\n }\n }\n </strong>\n </div>\n }\n</div>\n", styles: [":host{bottom:0;position:fixed;width:100%;z-index:1000}\n"] }]
|
|
4181
4273
|
}], ctorParameters: () => [] });
|
|
4182
4274
|
|
|
4183
4275
|
/* eslint-disable prefer-spread */
|
|
@@ -4198,8 +4290,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImpo
|
|
|
4198
4290
|
type: Pipe,
|
|
4199
4291
|
args: [{
|
|
4200
4292
|
name: 'applyPure',
|
|
4201
|
-
pure: true
|
|
4202
|
-
standalone: true
|
|
4293
|
+
pure: true
|
|
4203
4294
|
}]
|
|
4204
4295
|
}] });
|
|
4205
4296
|
|
|
@@ -4213,8 +4304,7 @@ class CapitalizePipe {
|
|
|
4213
4304
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: CapitalizePipe, decorators: [{
|
|
4214
4305
|
type: Pipe,
|
|
4215
4306
|
args: [{
|
|
4216
|
-
name: 'capitalize'
|
|
4217
|
-
standalone: true
|
|
4307
|
+
name: 'capitalize'
|
|
4218
4308
|
}]
|
|
4219
4309
|
}] });
|
|
4220
4310
|
|
|
@@ -4265,8 +4355,7 @@ class ClickOutsideDirective {
|
|
|
4265
4355
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: ClickOutsideDirective, decorators: [{
|
|
4266
4356
|
type: Directive,
|
|
4267
4357
|
args: [{
|
|
4268
|
-
selector: '[clickOutside]'
|
|
4269
|
-
standalone: true
|
|
4358
|
+
selector: '[clickOutside]'
|
|
4270
4359
|
}]
|
|
4271
4360
|
}], propDecorators: { clickOutsideListenAfter: [{ type: i0.Input, args: [{ isSignal: true, alias: "clickOutsideListenAfter", required: false }] }], clickOutside: [{ type: i0.Output, args: ["clickOutside"] }] } });
|
|
4272
4361
|
|
|
@@ -4285,8 +4374,7 @@ class CompoundDirective {
|
|
|
4285
4374
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: CompoundDirective, decorators: [{
|
|
4286
4375
|
type: Directive,
|
|
4287
4376
|
args: [{
|
|
4288
|
-
selector: '[appCompound]'
|
|
4289
|
-
standalone: true
|
|
4377
|
+
selector: '[appCompound]'
|
|
4290
4378
|
}]
|
|
4291
4379
|
}], ctorParameters: () => [], propDecorators: { appCompound: [{ type: i0.Input, args: [{ isSignal: true, alias: "appCompound", required: true }] }], compoundTermType: [{ type: i0.Input, args: [{ isSignal: true, alias: "compoundTermType", required: false }] }] } });
|
|
4292
4380
|
|
|
@@ -4300,8 +4388,7 @@ class CompoundPipe {
|
|
|
4300
4388
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: CompoundPipe, decorators: [{
|
|
4301
4389
|
type: Pipe,
|
|
4302
4390
|
args: [{
|
|
4303
|
-
name: 'compound'
|
|
4304
|
-
standalone: true
|
|
4391
|
+
name: 'compound'
|
|
4305
4392
|
}]
|
|
4306
4393
|
}] });
|
|
4307
4394
|
|
|
@@ -4315,8 +4402,7 @@ class DefaultPipe {
|
|
|
4315
4402
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: DefaultPipe, decorators: [{
|
|
4316
4403
|
type: Pipe,
|
|
4317
4404
|
args: [{
|
|
4318
|
-
name: 'default'
|
|
4319
|
-
standalone: true
|
|
4405
|
+
name: 'default'
|
|
4320
4406
|
}]
|
|
4321
4407
|
}] });
|
|
4322
4408
|
|
|
@@ -4350,8 +4436,7 @@ class DurationPipe {
|
|
|
4350
4436
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: DurationPipe, decorators: [{
|
|
4351
4437
|
type: Pipe,
|
|
4352
4438
|
args: [{
|
|
4353
|
-
name: 'duration'
|
|
4354
|
-
standalone: true
|
|
4439
|
+
name: 'duration'
|
|
4355
4440
|
}]
|
|
4356
4441
|
}] });
|
|
4357
4442
|
|
|
@@ -4365,8 +4450,7 @@ class EllipsisPipe {
|
|
|
4365
4450
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: EllipsisPipe, decorators: [{
|
|
4366
4451
|
type: Pipe,
|
|
4367
4452
|
args: [{
|
|
4368
|
-
name: 'ellipsis'
|
|
4369
|
-
standalone: true
|
|
4453
|
+
name: 'ellipsis'
|
|
4370
4454
|
}]
|
|
4371
4455
|
}] });
|
|
4372
4456
|
|
|
@@ -4380,8 +4464,7 @@ class FileSizePipe {
|
|
|
4380
4464
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: FileSizePipe, decorators: [{
|
|
4381
4465
|
type: Pipe,
|
|
4382
4466
|
args: [{
|
|
4383
|
-
name: 'fileSize'
|
|
4384
|
-
standalone: true
|
|
4467
|
+
name: 'fileSize'
|
|
4385
4468
|
}]
|
|
4386
4469
|
}] });
|
|
4387
4470
|
|
|
@@ -4395,8 +4478,7 @@ class GetPipe {
|
|
|
4395
4478
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: GetPipe, decorators: [{
|
|
4396
4479
|
type: Pipe,
|
|
4397
4480
|
args: [{
|
|
4398
|
-
name: 'get'
|
|
4399
|
-
standalone: true
|
|
4481
|
+
name: 'get'
|
|
4400
4482
|
}]
|
|
4401
4483
|
}] });
|
|
4402
4484
|
|
|
@@ -4410,8 +4492,7 @@ class IsArrayPipe {
|
|
|
4410
4492
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: IsArrayPipe, decorators: [{
|
|
4411
4493
|
type: Pipe,
|
|
4412
4494
|
args: [{
|
|
4413
|
-
name: 'isArray'
|
|
4414
|
-
standalone: true
|
|
4495
|
+
name: 'isArray'
|
|
4415
4496
|
}]
|
|
4416
4497
|
}] });
|
|
4417
4498
|
|
|
@@ -4425,8 +4506,7 @@ class IsObjectPipe {
|
|
|
4425
4506
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: IsObjectPipe, decorators: [{
|
|
4426
4507
|
type: Pipe,
|
|
4427
4508
|
args: [{
|
|
4428
|
-
name: 'isObject'
|
|
4429
|
-
standalone: true
|
|
4509
|
+
name: 'isObject'
|
|
4430
4510
|
}]
|
|
4431
4511
|
}] });
|
|
4432
4512
|
|
|
@@ -4484,8 +4564,7 @@ class KeyToLabelPipe {
|
|
|
4484
4564
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: KeyToLabelPipe, decorators: [{
|
|
4485
4565
|
type: Pipe,
|
|
4486
4566
|
args: [{
|
|
4487
|
-
name: 'keyToLabel'
|
|
4488
|
-
standalone: true
|
|
4567
|
+
name: 'keyToLabel'
|
|
4489
4568
|
}]
|
|
4490
4569
|
}] });
|
|
4491
4570
|
|
|
@@ -4499,8 +4578,7 @@ class NoExtPipe {
|
|
|
4499
4578
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: NoExtPipe, decorators: [{
|
|
4500
4579
|
type: Pipe,
|
|
4501
4580
|
args: [{
|
|
4502
|
-
name: 'noExt'
|
|
4503
|
-
standalone: true
|
|
4581
|
+
name: 'noExt'
|
|
4504
4582
|
}]
|
|
4505
4583
|
}] });
|
|
4506
4584
|
|
|
@@ -4514,8 +4592,7 @@ class PluralizePipe {
|
|
|
4514
4592
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: PluralizePipe, decorators: [{
|
|
4515
4593
|
type: Pipe,
|
|
4516
4594
|
args: [{
|
|
4517
|
-
name: 'pluralize'
|
|
4518
|
-
standalone: true
|
|
4595
|
+
name: 'pluralize'
|
|
4519
4596
|
}]
|
|
4520
4597
|
}] });
|
|
4521
4598
|
|
|
@@ -4529,8 +4606,7 @@ class RemoveMarkdownPipe {
|
|
|
4529
4606
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: RemoveMarkdownPipe, decorators: [{
|
|
4530
4607
|
type: Pipe,
|
|
4531
4608
|
args: [{
|
|
4532
|
-
name: 'removeMarkdown'
|
|
4533
|
-
standalone: true
|
|
4609
|
+
name: 'removeMarkdown'
|
|
4534
4610
|
}]
|
|
4535
4611
|
}] });
|
|
4536
4612
|
|
|
@@ -4544,8 +4620,7 @@ class RepeatPipe {
|
|
|
4544
4620
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: RepeatPipe, decorators: [{
|
|
4545
4621
|
type: Pipe,
|
|
4546
4622
|
args: [{
|
|
4547
|
-
name: 'repeat'
|
|
4548
|
-
standalone: true
|
|
4623
|
+
name: 'repeat'
|
|
4549
4624
|
}]
|
|
4550
4625
|
}] });
|
|
4551
4626
|
|
|
@@ -6103,8 +6178,7 @@ class TagsInputDirective {
|
|
|
6103
6178
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: TagsInputDirective, decorators: [{
|
|
6104
6179
|
type: Directive,
|
|
6105
6180
|
args: [{
|
|
6106
|
-
selector: '[appTagsInput]'
|
|
6107
|
-
standalone: true
|
|
6181
|
+
selector: '[appTagsInput]'
|
|
6108
6182
|
}]
|
|
6109
6183
|
}], propDecorators: { appTagsInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "appTagsInput", required: true }] }] } });
|
|
6110
6184
|
|
|
@@ -6118,8 +6192,7 @@ class ThousandSuffixesPipe {
|
|
|
6118
6192
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: ThousandSuffixesPipe, decorators: [{
|
|
6119
6193
|
type: Pipe,
|
|
6120
6194
|
args: [{
|
|
6121
|
-
name: 'thousandSuff'
|
|
6122
|
-
standalone: true
|
|
6195
|
+
name: 'thousandSuff'
|
|
6123
6196
|
}]
|
|
6124
6197
|
}] });
|
|
6125
6198
|
|
|
@@ -6133,8 +6206,7 @@ class ThousandsPipe {
|
|
|
6133
6206
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: ThousandsPipe, decorators: [{
|
|
6134
6207
|
type: Pipe,
|
|
6135
6208
|
args: [{
|
|
6136
|
-
name: 'thousands'
|
|
6137
|
-
standalone: true
|
|
6209
|
+
name: 'thousands'
|
|
6138
6210
|
}]
|
|
6139
6211
|
}] });
|
|
6140
6212
|
|
|
@@ -6148,8 +6220,7 @@ class TimesPipe {
|
|
|
6148
6220
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: TimesPipe, decorators: [{
|
|
6149
6221
|
type: Pipe,
|
|
6150
6222
|
args: [{
|
|
6151
|
-
name: 'times'
|
|
6152
|
-
standalone: true
|
|
6223
|
+
name: 'times'
|
|
6153
6224
|
}]
|
|
6154
6225
|
}] });
|
|
6155
6226
|
|
|
@@ -6163,8 +6234,7 @@ class UncapitalizePipe {
|
|
|
6163
6234
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: UncapitalizePipe, decorators: [{
|
|
6164
6235
|
type: Pipe,
|
|
6165
6236
|
args: [{
|
|
6166
|
-
name: 'uncapitalize'
|
|
6167
|
-
standalone: true
|
|
6237
|
+
name: 'uncapitalize'
|
|
6168
6238
|
}]
|
|
6169
6239
|
}] });
|
|
6170
6240
|
|
|
@@ -6178,8 +6248,7 @@ class SortByPipe {
|
|
|
6178
6248
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: SortByPipe, decorators: [{
|
|
6179
6249
|
type: Pipe,
|
|
6180
6250
|
args: [{
|
|
6181
|
-
name: 'sortBy'
|
|
6182
|
-
standalone: true
|
|
6251
|
+
name: 'sortBy'
|
|
6183
6252
|
}]
|
|
6184
6253
|
}] });
|
|
6185
6254
|
|
|
@@ -8012,7 +8081,11 @@ class NodeLogsModelsComponent {
|
|
|
8012
8081
|
this.nodeType = computed(() => nodeType(this.node()), ...(ngDevMode ? [{ debugName: "nodeType" }] : []));
|
|
8013
8082
|
this.logsResource = rxResource({
|
|
8014
8083
|
params: () => ({ node: this.node() }),
|
|
8015
|
-
stream: ({ params: { node } }) => this.nodeService.getLog$({
|
|
8084
|
+
stream: ({ params: { node } }) => this.nodeService.getLog$({
|
|
8085
|
+
'@type': node['@type'],
|
|
8086
|
+
'@id': node['@id'],
|
|
8087
|
+
dataState: node.aggregated ? DataState.original : DataState.recalculated
|
|
8088
|
+
})
|
|
8016
8089
|
});
|
|
8017
8090
|
this.allLogs = computed(() => this.logsResource.value() ?? '', ...(ngDevMode ? [{ debugName: "allLogs" }] : []));
|
|
8018
8091
|
this.hasLogs = computed(() => this.allLogs() !== '', ...(ngDevMode ? [{ debugName: "hasLogs" }] : []));
|
|
@@ -8285,20 +8358,34 @@ class CyclesCompletenessComponent {
|
|
|
8285
8358
|
component.headerKeys.set(headerKeys$1);
|
|
8286
8359
|
}
|
|
8287
8360
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: CyclesCompletenessComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
8288
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.13", type: CyclesCompletenessComponent, isStandalone: true, selector: "he-cycles-completeness", inputs: { dataState: { classPropertyName: "dataState", publicName: "dataState", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "
|
|
8361
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.13", type: CyclesCompletenessComponent, isStandalone: true, selector: "he-cycles-completeness", inputs: { dataState: { classPropertyName: "dataState", publicName: "dataState", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@switch (selectedView()) {\n @case (View.table) {\n @if (hasData()) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n <he-data-table class=\"is-mt-3 is-mb-1 is-bordered\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n <tr class=\"has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n @for (completeness of completenessKeys(); track completeness) {\n <th [attr.title]=\"completeness\">\n <a [href]=\"schemaBaseUrl + '/Completeness#' + completeness\" target=\"_blank\">\n {{ keyToLabel(completeness) }}\n </a>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (cycle of cycles(); track trackById(i, cycle); let i = $index) {\n <tr>\n <td class=\"width-auto has-border-right\" [attr.title]=\"defaultLabel(cycle)\">\n <he-node-link [node]=\"cycle\">\n <span>{{ i + 1 }}. {{ defaultLabel(cycle) }}</span>\n </he-node-link>\n </td>\n @for (key of completenessKeys(); track key) {\n <td class=\"is-nowrap\">\n <span>\n {{ getCompleteness(cycle)[key] ? 'Complete' : 'Incomplete' }}\n </span>\n <he-blank-node-state\n class=\"ml-1\"\n [dataState]=\"dataState()\"\n [node]=\"getCompleteness(cycle)\"\n [key]=\"key\" />\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n </he-data-table>\n <he-blank-node-state-notice [dataState]=\"dataState()\" />\n } @else {\n <div class=\"panel-block\">\n <span>No completeness data</span>\n </div>\n }\n }\n @case (View.logs) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (selectedNode()) {\n <he-node-logs-models\n class=\"is-mt-2\"\n [node]=\"selectedNode()\"\n [nodeKey]=\"nodeKey\"\n [logsKey]=\"selectedLogsKey()\"\n [originalValues]=\"selectedOriginalValues()\"\n [recalculatedValues]=\"selectedRecalculatedValues()\" />\n }\n }\n}\n\n<ng-template #selectView>\n <div class=\"is-flex is-gap-8 is-align-items-center is-justify-content-space-between\">\n <div class=\"is-flex is-gap-8 is-align-items-center\">\n @if (selectedView() === View.table) {\n @if (hasData()) {\n <button class=\"button is-small is-ghost\" (click)=\"showDownload()\">\n <he-svg-icon name=\"download\" />\n </button>\n }\n }\n </div>\n\n @if (views()?.length > 1) {\n <div class=\"field has-addons button-segments\">\n @for (view of views(); track view) {\n <div class=\"control\">\n <button\n class=\"button is-small\"\n [class.is-selected]=\"selectedView() === view\"\n (click)=\"selectedView.set(view)\">\n <he-svg-icon\n name=\"checkmark\"\n aria-hidden=\"true\"\n class=\"is-hidden-mobile\"\n [class.is-hidden-tablet]=\"selectedView() !== view\" />\n <he-svg-icon\n [name]=\"viewIcon[view]\"\n aria-hidden=\"true\"\n [class.is-hidden-tablet]=\"selectedView() === view\" />\n <span class=\"is-hidden-mobile\">{{ view }}</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n", styles: [""], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: HESvgIconComponent, selector: "he-svg-icon", inputs: ["name", "size", "animation"] }, { kind: "component", type: DataTableComponent, selector: "he-data-table", inputs: ["minHeight", "maxHeight", "small"] }, { kind: "component", type: NodeLinkComponent, selector: "he-node-link", inputs: ["node", "dataState", "showExternalLink", "linkClass"] }, { 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", "showDeleted"] }, { kind: "component", type: NodeLogsModelsComponent, selector: "he-node-logs-models", inputs: ["node", "nodeKey", "originalValues", "recalculatedValues", "terms", "filterTermTypes", "filterTermTypesLabel", "logsKey", "noDataMessage"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
8289
8362
|
}
|
|
8290
8363
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: CyclesCompletenessComponent, decorators: [{
|
|
8291
8364
|
type: Component$1,
|
|
8292
8365
|
args: [{ selector: 'he-cycles-completeness', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
|
|
8366
|
+
NgTemplateOutlet,
|
|
8293
8367
|
HESvgIconComponent,
|
|
8294
8368
|
DataTableComponent,
|
|
8295
8369
|
NodeLinkComponent,
|
|
8296
8370
|
BlankNodeStateComponent,
|
|
8297
8371
|
BlankNodeStateNoticeComponent,
|
|
8298
8372
|
NodeLogsModelsComponent
|
|
8299
|
-
], template: "
|
|
8373
|
+
], template: "@switch (selectedView()) {\n @case (View.table) {\n @if (hasData()) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n <he-data-table class=\"is-mt-3 is-mb-1 is-bordered\" [small]=\"true\" maxHeight=\"320\">\n <table class=\"table is-fullwidth is-narrow is-striped\">\n <thead>\n <tr class=\"has-text-weight-semibold\">\n <th class=\"width-auto has-border-right\"></th>\n @for (completeness of completenessKeys(); track completeness) {\n <th [attr.title]=\"completeness\">\n <a [href]=\"schemaBaseUrl + '/Completeness#' + completeness\" target=\"_blank\">\n {{ keyToLabel(completeness) }}\n </a>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (cycle of cycles(); track trackById(i, cycle); let i = $index) {\n <tr>\n <td class=\"width-auto has-border-right\" [attr.title]=\"defaultLabel(cycle)\">\n <he-node-link [node]=\"cycle\">\n <span>{{ i + 1 }}. {{ defaultLabel(cycle) }}</span>\n </he-node-link>\n </td>\n @for (key of completenessKeys(); track key) {\n <td class=\"is-nowrap\">\n <span>\n {{ getCompleteness(cycle)[key] ? 'Complete' : 'Incomplete' }}\n </span>\n <he-blank-node-state\n class=\"ml-1\"\n [dataState]=\"dataState()\"\n [node]=\"getCompleteness(cycle)\"\n [key]=\"key\" />\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n </he-data-table>\n <he-blank-node-state-notice [dataState]=\"dataState()\" />\n } @else {\n <div class=\"panel-block\">\n <span>No completeness data</span>\n </div>\n }\n }\n @case (View.logs) {\n <ng-container *ngTemplateOutlet=\"selectView\" />\n\n @if (selectedNode()) {\n <he-node-logs-models\n class=\"is-mt-2\"\n [node]=\"selectedNode()\"\n [nodeKey]=\"nodeKey\"\n [logsKey]=\"selectedLogsKey()\"\n [originalValues]=\"selectedOriginalValues()\"\n [recalculatedValues]=\"selectedRecalculatedValues()\" />\n }\n }\n}\n\n<ng-template #selectView>\n <div class=\"is-flex is-gap-8 is-align-items-center is-justify-content-space-between\">\n <div class=\"is-flex is-gap-8 is-align-items-center\">\n @if (selectedView() === View.table) {\n @if (hasData()) {\n <button class=\"button is-small is-ghost\" (click)=\"showDownload()\">\n <he-svg-icon name=\"download\" />\n </button>\n }\n }\n </div>\n\n @if (views()?.length > 1) {\n <div class=\"field has-addons button-segments\">\n @for (view of views(); track view) {\n <div class=\"control\">\n <button\n class=\"button is-small\"\n [class.is-selected]=\"selectedView() === view\"\n (click)=\"selectedView.set(view)\">\n <he-svg-icon\n name=\"checkmark\"\n aria-hidden=\"true\"\n class=\"is-hidden-mobile\"\n [class.is-hidden-tablet]=\"selectedView() !== view\" />\n <he-svg-icon\n [name]=\"viewIcon[view]\"\n aria-hidden=\"true\"\n [class.is-hidden-tablet]=\"selectedView() === view\" />\n <span class=\"is-hidden-mobile\">{{ view }}</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n" }]
|
|
8300
8374
|
}], ctorParameters: () => [], propDecorators: { dataState: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataState", required: false }] }] } });
|
|
8301
8375
|
|
|
8376
|
+
class ChartExportButtonComponent {
|
|
8377
|
+
constructor() {
|
|
8378
|
+
this.chart = input.required(...(ngDevMode ? [{ debugName: "chart" }] : []));
|
|
8379
|
+
this.config = input(...(ngDevMode ? [undefined, { debugName: "config" }] : []));
|
|
8380
|
+
}
|
|
8381
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: ChartExportButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
8382
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.13", type: ChartExportButtonComponent, isStandalone: true, selector: "he-chart-export-button", inputs: { chart: { classPropertyName: "chart", publicName: "chart", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<button\n class=\"button is-small is-ghost\"\n (click)=\"!chart().exporting() && chart().exportAsSvg(config())\"\n [ngbTooltip]=\"chart().exporting() ? null : 'Download Chart (SVG)'\"\n placement=\"right\">\n @if (chart().exporting()) {\n <he-svg-icon name=\"loading\" animation=\"spin\" />\n } @else {\n <he-svg-icon name=\"download\" />\n }\n</button>\n", styles: [""], dependencies: [{ kind: "component", type: HESvgIconComponent, selector: "he-svg-icon", inputs: ["name", "size", "animation"] }, { kind: "directive", type: NgbTooltip, selector: "[ngbTooltip]", inputs: ["animation", "autoClose", "placement", "popperOptions", "triggers", "positionTarget", "container", "disableTooltip", "tooltipClass", "tooltipContext", "openDelay", "closeDelay", "ngbTooltip"], outputs: ["shown", "hidden"], exportAs: ["ngbTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
8383
|
+
}
|
|
8384
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: ChartExportButtonComponent, decorators: [{
|
|
8385
|
+
type: Component$1,
|
|
8386
|
+
args: [{ selector: 'he-chart-export-button', changeDetection: ChangeDetectionStrategy.OnPush, imports: [HESvgIconComponent, NgbTooltip], template: "<button\n class=\"button is-small is-ghost\"\n (click)=\"!chart().exporting() && chart().exportAsSvg(config())\"\n [ngbTooltip]=\"chart().exporting() ? null : 'Download Chart (SVG)'\"\n placement=\"right\">\n @if (chart().exporting()) {\n <he-svg-icon name=\"loading\" animation=\"spin\" />\n } @else {\n <he-svg-icon name=\"download\" />\n }\n</button>\n" }]
|
|
8387
|
+
}], propDecorators: { chart: [{ type: i0.Input, args: [{ isSignal: true, alias: "chart", required: true }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }] } });
|
|
8388
|
+
|
|
8302
8389
|
const cycleValue = (cycle, values) => (values[cycle['@id']]?.nodes[0] || { value: [0] }).value;
|
|
8303
8390
|
const cycleName = (cycle, index) => `${index + 1}. ${defaultLabel(cycle)}`;
|
|
8304
8391
|
class CyclesEmissionsChartComponent {
|
|
@@ -8306,46 +8393,17 @@ class CyclesEmissionsChartComponent {
|
|
|
8306
8393
|
this.cycles = input.required(...(ngDevMode ? [{ debugName: "cycles" }] : []));
|
|
8307
8394
|
this.emissionPerCycle = computed(() => groupNodesByTerm(this.cycles(), 'emissions'), ...(ngDevMode ? [{ debugName: "emissionPerCycle" }] : []));
|
|
8308
8395
|
this.terms = computed(() => Object.values(this.emissionPerCycle() ?? {})
|
|
8309
|
-
.filter(({ values }) => Object.values(values).some(({ nodes: [{ value }] }) => propertyValue$1(value)
|
|
8396
|
+
.filter(({ values }) => Object.values(values).some(({ nodes: [{ value }] }) => propertyValue$1(value) > 0))
|
|
8310
8397
|
.map(({ term }) => term)
|
|
8311
8398
|
.sort((a, b) => a.name.localeCompare(b.name)), ...(ngDevMode ? [{ debugName: "terms" }] : []));
|
|
8312
8399
|
this.selectedTerm = signal(undefined, ...(ngDevMode ? [{ debugName: "selectedTerm" }] : []));
|
|
8313
8400
|
this.labels = computed(() => this.cycles().map(cycleName), ...(ngDevMode ? [{ debugName: "labels" }] : []));
|
|
8314
|
-
this.chartColors = computed(() => this.cycles().map(listColor), ...(ngDevMode ? [{ debugName: "chartColors" }] : []));
|
|
8315
8401
|
this.chartValues = computed(() => this.emissionPerCycle()?.[this.selectedTerm()?.name]?.values || {}, ...(ngDevMode ? [{ debugName: "chartValues" }] : []));
|
|
8316
|
-
this.
|
|
8317
|
-
|
|
8318
|
-
|
|
8319
|
-
|
|
8320
|
-
|
|
8321
|
-
borderColor: this.chartColors(),
|
|
8322
|
-
barThickness: 2,
|
|
8323
|
-
barPercentage: 1,
|
|
8324
|
-
categoryPercentage: 1
|
|
8325
|
-
}
|
|
8326
|
-
], ...(ngDevMode ? [{ debugName: "datasets" }] : []));
|
|
8327
|
-
this.chartConfig = computed(() => ({
|
|
8328
|
-
plugins: [
|
|
8329
|
-
lollipopChartPlugin(),
|
|
8330
|
-
afterBarDrawPlugin({
|
|
8331
|
-
xPosFn: (x, index, width, chart) => (x || chart.scales['x-axis-0'].getPixelForValue(0)) + 10,
|
|
8332
|
-
textFn: ({ data }) => `${data}`,
|
|
8333
|
-
colorFn: (m, index, chart, data) => (isUndefined(data) ? '#b5b5b5' : '#4a4a4a'),
|
|
8334
|
-
emptyValueLabel: 'No value'
|
|
8335
|
-
})
|
|
8336
|
-
],
|
|
8337
|
-
options: {
|
|
8338
|
-
scales: {
|
|
8339
|
-
xAxes: [
|
|
8340
|
-
{
|
|
8341
|
-
scaleLabel: {
|
|
8342
|
-
labelString: this.selectedTerm()?.units
|
|
8343
|
-
}
|
|
8344
|
-
}
|
|
8345
|
-
]
|
|
8346
|
-
}
|
|
8347
|
-
}
|
|
8348
|
-
}), ...(ngDevMode ? [{ debugName: "chartConfig" }] : []));
|
|
8402
|
+
this.chartData = computed(() => this.cycles().map((cycle, index) => ({
|
|
8403
|
+
label: cycleName(cycle, index),
|
|
8404
|
+
count: propertyValue$1(cycleValue(cycle, this.chartValues()), this.selectedTerm?.['@id']),
|
|
8405
|
+
color: listColor(cycle, index)
|
|
8406
|
+
})), ...(ngDevMode ? [{ debugName: "chartData" }] : []));
|
|
8349
8407
|
effect(() => {
|
|
8350
8408
|
// make sure selected term exists
|
|
8351
8409
|
const terms = this.terms();
|
|
@@ -8360,11 +8418,11 @@ class CyclesEmissionsChartComponent {
|
|
|
8360
8418
|
this.selectedTerm.set(term);
|
|
8361
8419
|
}
|
|
8362
8420
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: CyclesEmissionsChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
8363
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.13", type: CyclesEmissionsChartComponent, isStandalone: true, selector: "he-cycles-emissions-chart", inputs: { cycles: { classPropertyName: "cycles", publicName: "cycles", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"is-flex is-gap-8 is-justify-content-space-between is-align-items-center is-mb-3\">\n <button
|
|
8421
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.13", type: CyclesEmissionsChartComponent, isStandalone: true, selector: "he-cycles-emissions-chart", inputs: { cycles: { classPropertyName: "cycles", publicName: "cycles", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"is-flex is-gap-8 is-justify-content-space-between is-align-items-center is-mb-3\">\n <he-chart-export-button [chart]=\"chart\" [config]=\"{ lollipopConfig: {} }\" />\n\n <ng-content />\n</div>\n\n@if (terms().length) {\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"selectTerm($event)\" id=\"selectTerm\">\n @for (term of terms(); track term) {\n <option [value]=\"term['@id']\">{{ term.name }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n}\n\n<he-horizontal-bar-chart\n #chart=\"horizontalBarChart\"\n class=\"is-relative h-100\"\n [title]=\"selectedTerm()?.units\"\n [data]=\"chartData()\"\n [labels]=\"labels()\"\n [showExportButton]=\"false\" />\n", styles: [":host{display:block;overflow:visible}he-horizontal-bar-chart ::ng-deep .chart-container{min-height:400px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "component", type: HorizontalBarChartComponent, selector: "he-horizontal-bar-chart", inputs: ["tooltipFn", "afterBarDrawSettings"], exportAs: ["horizontalBarChart"] }, { kind: "component", type: ChartExportButtonComponent, selector: "he-chart-export-button", inputs: ["chart", "config"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
8364
8422
|
}
|
|
8365
8423
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: CyclesEmissionsChartComponent, decorators: [{
|
|
8366
8424
|
type: Component$1,
|
|
8367
|
-
args: [{ selector: 'he-cycles-emissions-chart', imports: [FormsModule,
|
|
8425
|
+
args: [{ selector: 'he-cycles-emissions-chart', changeDetection: ChangeDetectionStrategy.OnPush, imports: [FormsModule, HorizontalBarChartComponent, ChartExportButtonComponent], template: "<div class=\"is-flex is-gap-8 is-justify-content-space-between is-align-items-center is-mb-3\">\n <he-chart-export-button [chart]=\"chart\" [config]=\"{ lollipopConfig: {} }\" />\n\n <ng-content />\n</div>\n\n@if (terms().length) {\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"selectTerm($event)\" id=\"selectTerm\">\n @for (term of terms(); track term) {\n <option [value]=\"term['@id']\">{{ term.name }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n}\n\n<he-horizontal-bar-chart\n #chart=\"horizontalBarChart\"\n class=\"is-relative h-100\"\n [title]=\"selectedTerm()?.units\"\n [data]=\"chartData()\"\n [labels]=\"labels()\"\n [showExportButton]=\"false\" />\n", styles: [":host{display:block;overflow:visible}he-horizontal-bar-chart ::ng-deep .chart-container{min-height:400px}\n"] }]
|
|
8368
8426
|
}], ctorParameters: () => [], propDecorators: { cycles: [{ type: i0.Input, args: [{ isSignal: true, alias: "cycles", required: true }] }] } });
|
|
8369
8427
|
|
|
8370
8428
|
class CyclesFunctionalUnitMeasureComponent {
|
|
@@ -8378,7 +8436,7 @@ class CyclesFunctionalUnitMeasureComponent {
|
|
|
8378
8436
|
}
|
|
8379
8437
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: CyclesFunctionalUnitMeasureComponent, decorators: [{
|
|
8380
8438
|
type: Component$1,
|
|
8381
|
-
args: [{ selector: 'he-cycles-functional-unit-measure', changeDetection: ChangeDetectionStrategy.OnPush,
|
|
8439
|
+
args: [{ selector: 'he-cycles-functional-unit-measure', changeDetection: ChangeDetectionStrategy.OnPush, template: "<span class=\"is-nowrap has-text-ellipsis\" [attr.title]=\"functionalUnit()\">\n @switch (functionalUnit()) {\n @case (CycleFunctionalUnit['1 ha']) {\n 1 hectare\n }\n @default {\n relative\n }\n }\n</span>\n", styles: [":host{display:inline-block}\n"] }]
|
|
8382
8440
|
}], propDecorators: { cycle: [{ type: i0.Input, args: [{ isSignal: true, alias: "cycle", required: true }] }] } });
|
|
8383
8441
|
|
|
8384
8442
|
var View$3;
|
|
@@ -8651,7 +8709,7 @@ class CyclesNodesTimelineComponent {
|
|
|
8651
8709
|
this.maxChart = computed(() => formatDate(this.maxDate(), false), ...(ngDevMode ? [{ debugName: "maxChart" }] : []));
|
|
8652
8710
|
this.minChart = computed(() => this.minDate() ? formatDate(this.minDate(), true) : monthsBefore(this.maxChart(), 12), ...(ngDevMode ? [{ debugName: "minChart" }] : []));
|
|
8653
8711
|
this.chartConfig = computed(() => ({
|
|
8654
|
-
type: '
|
|
8712
|
+
type: 'bar',
|
|
8655
8713
|
plugins: [
|
|
8656
8714
|
lollipopChartPlugin({
|
|
8657
8715
|
circleRadius: 6,
|
|
@@ -8659,64 +8717,62 @@ class CyclesNodesTimelineComponent {
|
|
|
8659
8717
|
colorFn: () => colour
|
|
8660
8718
|
}),
|
|
8661
8719
|
afterBarDrawPlugin({
|
|
8662
|
-
xPosFn: (x, index, width, chart) => (x || chart.scales
|
|
8663
|
-
colorFn: () => '#b5b5b5',
|
|
8720
|
+
xPosFn: (x, index, width, chart) => (x || chart.scales.x.getPixelForValue(this.minChart().getTime())) + 10,
|
|
8664
8721
|
emptyValueLabel: 'No dates available'
|
|
8665
8722
|
})
|
|
8666
8723
|
],
|
|
8667
8724
|
options: {
|
|
8668
|
-
|
|
8669
|
-
|
|
8670
|
-
|
|
8671
|
-
|
|
8672
|
-
|
|
8673
|
-
|
|
8674
|
-
|
|
8675
|
-
|
|
8725
|
+
indexAxis: 'y',
|
|
8726
|
+
plugins: {
|
|
8727
|
+
legend: {
|
|
8728
|
+
display: false
|
|
8729
|
+
},
|
|
8730
|
+
tooltip: {
|
|
8731
|
+
mode: 'point',
|
|
8732
|
+
enabled: false,
|
|
8733
|
+
intersect: true,
|
|
8734
|
+
axis: 'y'
|
|
8735
|
+
}
|
|
8676
8736
|
},
|
|
8677
8737
|
scales: {
|
|
8678
|
-
|
|
8679
|
-
|
|
8680
|
-
|
|
8681
|
-
|
|
8682
|
-
|
|
8683
|
-
|
|
8684
|
-
|
|
8685
|
-
|
|
8686
|
-
|
|
8687
|
-
|
|
8688
|
-
stacked: false,
|
|
8689
|
-
gridLines: {
|
|
8690
|
-
drawOnChartArea: false
|
|
8691
|
-
}
|
|
8738
|
+
x: {
|
|
8739
|
+
type: 'time',
|
|
8740
|
+
time: {
|
|
8741
|
+
unit: 'month'
|
|
8742
|
+
},
|
|
8743
|
+
max: this.maxChart().getTime(),
|
|
8744
|
+
...(this.minChart() ? { min: this.minChart().getTime() } : {}),
|
|
8745
|
+
stacked: false,
|
|
8746
|
+
grid: {
|
|
8747
|
+
drawOnChartArea: false
|
|
8692
8748
|
}
|
|
8693
|
-
|
|
8694
|
-
|
|
8695
|
-
|
|
8696
|
-
|
|
8697
|
-
|
|
8698
|
-
|
|
8699
|
-
|
|
8700
|
-
|
|
8701
|
-
|
|
8702
|
-
|
|
8703
|
-
|
|
8704
|
-
|
|
8705
|
-
|
|
8706
|
-
|
|
8707
|
-
|
|
8749
|
+
},
|
|
8750
|
+
y: {
|
|
8751
|
+
stacked: true,
|
|
8752
|
+
border: {
|
|
8753
|
+
display: true
|
|
8754
|
+
},
|
|
8755
|
+
grid: {
|
|
8756
|
+
display: true,
|
|
8757
|
+
drawOnChartArea: false,
|
|
8758
|
+
drawTicks: true,
|
|
8759
|
+
tickLength: 8,
|
|
8760
|
+
offset: false
|
|
8761
|
+
},
|
|
8762
|
+
ticks: {
|
|
8763
|
+
padding: 4
|
|
8708
8764
|
}
|
|
8709
|
-
|
|
8765
|
+
}
|
|
8710
8766
|
}
|
|
8711
8767
|
}
|
|
8712
8768
|
}), ...(ngDevMode ? [{ debugName: "chartConfig" }] : []));
|
|
8713
8769
|
}
|
|
8714
8770
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: CyclesNodesTimelineComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
8715
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.13", type: CyclesNodesTimelineComponent, isStandalone: true, selector: "he-cycles-nodes-timeline", inputs: { values: { classPropertyName: "values", publicName: "values", isSignal: true, isRequired: true, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: true, isRequired: true, transformFunction: null }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ng-content />\n\n<div class=\"chart-area-border is-mt-3\">\n <he-chart class=\"is-relative\" [data]=\"chartData()\" [config]=\"chartConfig()\" />\n</div>\n", styles: ["he-chart ::ng-deep .chart-container{min-height:400px}\n"], dependencies: [{ kind: "component", type: ChartComponent, selector: "he-chart", inputs: ["data", "config", "showExportButton"], exportAs: ["chart"] }] }); }
|
|
8771
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.13", type: CyclesNodesTimelineComponent, isStandalone: true, selector: "he-cycles-nodes-timeline", inputs: { values: { classPropertyName: "values", publicName: "values", isSignal: true, isRequired: true, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: true, isRequired: true, transformFunction: null }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ng-content />\n\n<div class=\"chart-area-border is-mt-3\">\n <he-chart class=\"is-relative\" [data]=\"chartData()\" [config]=\"chartConfig()\" />\n</div>\n", styles: ["he-chart ::ng-deep .chart-container{min-height:400px}\n"], dependencies: [{ kind: "component", type: ChartComponent, selector: "he-chart", inputs: ["data", "config", "showExportButton"], exportAs: ["chart"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
8716
8772
|
}
|
|
8717
8773
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: CyclesNodesTimelineComponent, decorators: [{
|
|
8718
8774
|
type: Component$1,
|
|
8719
|
-
args: [{ selector: 'he-cycles-nodes-timeline', imports: [ChartComponent], template: "<ng-content />\n\n<div class=\"chart-area-border is-mt-3\">\n <he-chart class=\"is-relative\" [data]=\"chartData()\" [config]=\"chartConfig()\" />\n</div>\n", styles: ["he-chart ::ng-deep .chart-container{min-height:400px}\n"] }]
|
|
8775
|
+
args: [{ selector: 'he-cycles-nodes-timeline', changeDetection: ChangeDetectionStrategy.OnPush, imports: [ChartComponent], template: "<ng-content />\n\n<div class=\"chart-area-border is-mt-3\">\n <he-chart class=\"is-relative\" [data]=\"chartData()\" [config]=\"chartConfig()\" />\n</div>\n", styles: ["he-chart ::ng-deep .chart-container{min-height:400px}\n"] }]
|
|
8720
8776
|
}], propDecorators: { values: [{ type: i0.Input, args: [{ isSignal: true, alias: "values", required: true }] }], maxDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDate", required: true }] }], minDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "minDate", required: false }] }] } });
|
|
8721
8777
|
|
|
8722
8778
|
class TermsUnitsDescriptionComponent {
|
|
@@ -8809,7 +8865,7 @@ class CyclesNodesComponent {
|
|
|
8809
8865
|
this.View = View$2;
|
|
8810
8866
|
this.viewIcon = viewIcon$2;
|
|
8811
8867
|
this.showView = computed(() => ({
|
|
8812
|
-
[View$2.chart]: this.
|
|
8868
|
+
[View$2.chart]: [this.isEmission() && this.cycles().length > 1].some(Boolean),
|
|
8813
8869
|
[View$2.logs]: !this.isOriginal() && this.hasRecalculatedNodes(),
|
|
8814
8870
|
[View$2.table]: true,
|
|
8815
8871
|
[View$2.timeline]: this.enableTimeline()
|
|
@@ -8955,7 +9011,7 @@ class CyclesResultComponent {
|
|
|
8955
9011
|
backgroundColor: color,
|
|
8956
9012
|
borderColor: color,
|
|
8957
9013
|
barPercentage: 0.5,
|
|
8958
|
-
data: this.cycles().map(({ '@id': id }) =>
|
|
9014
|
+
data: this.cycles().map(({ '@id': id }) => values[id] ? propertyValue$1(values[id].value, termId) : 0)
|
|
8959
9015
|
};
|
|
8960
9016
|
}), ...(ngDevMode ? [{ debugName: "chartDatasets" }] : []));
|
|
8961
9017
|
this.chartData = computed(() => ({
|
|
@@ -8963,41 +9019,37 @@ class CyclesResultComponent {
|
|
|
8963
9019
|
labels: this.chartLabels()
|
|
8964
9020
|
}), ...(ngDevMode ? [{ debugName: "chartData" }] : []));
|
|
8965
9021
|
this.chartConfig = {
|
|
8966
|
-
type: '
|
|
9022
|
+
type: 'bar',
|
|
8967
9023
|
options: {
|
|
8968
|
-
|
|
8969
|
-
|
|
8970
|
-
|
|
8971
|
-
|
|
8972
|
-
|
|
8973
|
-
|
|
9024
|
+
indexAxis: 'y',
|
|
9025
|
+
plugins: {
|
|
9026
|
+
legend: {
|
|
9027
|
+
display: true
|
|
9028
|
+
},
|
|
9029
|
+
tooltip: {
|
|
9030
|
+
callbacks: {
|
|
9031
|
+
title: tooltipItems => tooltipItems[0].label
|
|
9032
|
+
}
|
|
8974
9033
|
}
|
|
8975
9034
|
},
|
|
8976
9035
|
scales: {
|
|
8977
|
-
|
|
8978
|
-
|
|
8979
|
-
|
|
8980
|
-
|
|
8981
|
-
|
|
8982
|
-
|
|
8983
|
-
|
|
8984
|
-
|
|
8985
|
-
{
|
|
8986
|
-
position: 'left',
|
|
8987
|
-
scaleLabel: {
|
|
8988
|
-
display: true,
|
|
8989
|
-
labelString: 'Cycle'
|
|
8990
|
-
}
|
|
9036
|
+
x: {
|
|
9037
|
+
min: 0
|
|
9038
|
+
},
|
|
9039
|
+
y: {
|
|
9040
|
+
position: 'left',
|
|
9041
|
+
title: {
|
|
9042
|
+
display: true,
|
|
9043
|
+
text: 'Cycle'
|
|
8991
9044
|
}
|
|
8992
|
-
|
|
9045
|
+
}
|
|
8993
9046
|
}
|
|
8994
9047
|
}
|
|
8995
9048
|
};
|
|
8996
|
-
Chart
|
|
8997
|
-
|
|
8998
|
-
|
|
8999
|
-
|
|
9000
|
-
});
|
|
9049
|
+
Chart.defaults.scales.category.ticks.callback = function (val) {
|
|
9050
|
+
const label = this.getLabelForValue(val);
|
|
9051
|
+
return ellipsis(`${label}`, 25);
|
|
9052
|
+
};
|
|
9001
9053
|
}
|
|
9002
9054
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: CyclesResultComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
9003
9055
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.13", type: CyclesResultComponent, isStandalone: true, selector: "he-cycles-result", inputs: { cycles: { classPropertyName: "cycles", publicName: "cycles", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<he-chart class=\"is-relative\" [data]=\"chartData()\" [config]=\"chartConfig\" />\n", styles: [":host{display:block}he-chart ::ng-deep .chart-container{min-height:300px}\n"], dependencies: [{ kind: "component", type: ChartComponent, selector: "he-chart", inputs: ["data", "config", "showExportButton"], exportAs: ["chart"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
@@ -9402,19 +9454,16 @@ class NodeAggregatedQualityScoreComponent {
|
|
|
9402
9454
|
: of(undefined)
|
|
9403
9455
|
});
|
|
9404
9456
|
this.countryId = computed(() => this.countryResource.value()?.['@id'], ...(ngDevMode ? [{ debugName: "countryId" }] : []));
|
|
9405
|
-
this.aggregationId = computed(() => [!!this.node(), !!this.countryId()].every(Boolean) ? nodeToAggregationFilename(this.node(), this.countryId()) : null, ...(ngDevMode ? [{ debugName: "aggregationId" }] : []));
|
|
9406
9457
|
this.logsResource = rxResource({
|
|
9407
9458
|
params: () => ({
|
|
9408
9459
|
showInfo: this.showInfo(),
|
|
9409
|
-
node: this.node()
|
|
9410
|
-
aggregationId: this.aggregationId()
|
|
9460
|
+
node: this.node()
|
|
9411
9461
|
}),
|
|
9412
|
-
stream: ({ params: { showInfo, node
|
|
9462
|
+
stream: ({ params: { showInfo, node } }) => showInfo
|
|
9413
9463
|
? this.nodeService
|
|
9414
9464
|
.getLog$({
|
|
9415
9465
|
'@type': node['@type'],
|
|
9416
|
-
'@id':
|
|
9417
|
-
aggregated: true
|
|
9466
|
+
'@id': node['@id']
|
|
9418
9467
|
})
|
|
9419
9468
|
.pipe(map(value => (value ? parseLines(value) : [])), mergeAll(), filter(({ data: { message } }) => !!message), map(({ data: { message } }) => parseMessage$1(message)), filter(({ id }) => id === this.node()['@id']), reduce((a, b) => ({ ...a, ...b }), {}))
|
|
9420
9469
|
: of({})
|
|
@@ -9845,7 +9894,7 @@ class EngineModelsStageComponent {
|
|
|
9845
9894
|
}
|
|
9846
9895
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: EngineModelsStageComponent, decorators: [{
|
|
9847
9896
|
type: Component$1,
|
|
9848
|
-
args: [{ selector: 'he-engine-models-stage', changeDetection: ChangeDetectionStrategy.OnPush,
|
|
9897
|
+
args: [{ selector: 'he-engine-models-stage', changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (inProgress()) {\n <span class=\"tag is-warning\">\n <span>Calculation in progress (stage {{ stage() }} out of {{ maxStage() }})</span>\n </span>\n}\n", styles: [":host{display:inline-block}\n"] }]
|
|
9849
9898
|
}], propDecorators: { node: [{ type: i0.Input, args: [{ isSignal: true, alias: "node", required: true }] }] } });
|
|
9850
9899
|
|
|
9851
9900
|
class EngineModelsVersionLinkComponent {
|
|
@@ -12035,31 +12084,31 @@ ${JSON.stringify(error)}
|
|
|
12035
12084
|
/label ~"Priority::MEDIUM"
|
|
12036
12085
|
/label ~"Tracking::Triage"
|
|
12037
12086
|
`.trim())}`;
|
|
12038
|
-
var
|
|
12039
|
-
(function (
|
|
12040
|
-
|
|
12041
|
-
|
|
12042
|
-
|
|
12043
|
-
|
|
12044
|
-
|
|
12045
|
-
|
|
12046
|
-
|
|
12047
|
-
|
|
12048
|
-
|
|
12049
|
-
|
|
12050
|
-
|
|
12051
|
-
|
|
12052
|
-
|
|
12053
|
-
|
|
12054
|
-
|
|
12055
|
-
|
|
12056
|
-
|
|
12057
|
-
|
|
12058
|
-
|
|
12059
|
-
|
|
12060
|
-
|
|
12061
|
-
|
|
12062
|
-
})(
|
|
12087
|
+
var FileUploadErrorKeys;
|
|
12088
|
+
(function (FileUploadErrorKeys) {
|
|
12089
|
+
FileUploadErrorKeys["PrivacyNotAllowed"] = "privacy-not-allowed";
|
|
12090
|
+
FileUploadErrorKeys["NoData"] = "no-data";
|
|
12091
|
+
FileUploadErrorKeys["NoHeaders"] = "no-headers";
|
|
12092
|
+
FileUploadErrorKeys["InvalidJSON"] = "invalid-json";
|
|
12093
|
+
FileUploadErrorKeys["InvalidSheetName"] = "invalid-sheet-name";
|
|
12094
|
+
FileUploadErrorKeys["InvalidFirstColumn"] = "invalid-first-column";
|
|
12095
|
+
FileUploadErrorKeys["InvalidExcelFile"] = "invalid-excel-file";
|
|
12096
|
+
FileUploadErrorKeys["DuplicatedHeaders"] = "duplicated-headers";
|
|
12097
|
+
FileUploadErrorKeys["DuplicatedIds"] = "duplicated-ids";
|
|
12098
|
+
FileUploadErrorKeys["PropertyRequired"] = "property-required";
|
|
12099
|
+
FileUploadErrorKeys["PropertyInternal"] = "property-internal";
|
|
12100
|
+
FileUploadErrorKeys["UploadsLimit"] = "upload-limit";
|
|
12101
|
+
FileUploadErrorKeys["NestedHeaders"] = "nested-headers";
|
|
12102
|
+
FileUploadErrorKeys["NestedNodes"] = "nested-nodes";
|
|
12103
|
+
FileUploadErrorKeys["ReferenceExistingHeaders"] = "reference-existing-headers";
|
|
12104
|
+
FileUploadErrorKeys["MultipleTermHeaders"] = "multiple-term-headers";
|
|
12105
|
+
FileUploadErrorKeys["MaxSize"] = "max-size";
|
|
12106
|
+
FileUploadErrorKeys["InvalidBlankNodeHeaders"] = "invalid-blank-node-headers";
|
|
12107
|
+
FileUploadErrorKeys["MaxRows"] = "max-rows";
|
|
12108
|
+
FileUploadErrorKeys["Mendeley"] = "'content-type'";
|
|
12109
|
+
FileUploadErrorKeys["Timeout"] = "TimeoutError: Timeout has occurred";
|
|
12110
|
+
FileUploadErrorKeys["SetValueError"] = "set-value-failed";
|
|
12111
|
+
})(FileUploadErrorKeys || (FileUploadErrorKeys = {}));
|
|
12063
12112
|
const valueToNodes = (value, type) => Array.isArray(value)
|
|
12064
12113
|
? isExpandable(value)
|
|
12065
12114
|
? value.map(val => ({
|
|
@@ -12107,14 +12156,14 @@ class FilesUploadErrorsComponent {
|
|
|
12107
12156
|
this.hasGeoJSONError = computed(() => this.error()?.error?.includes('Unable to parse GeoJSON value'), ...(ngDevMode ? [{ debugName: "hasGeoJSONError" }] : []));
|
|
12108
12157
|
this.schemaUrl = computed(() => [schemaBaseUrl(this.file()?.schemaVersion), this.error()?.schema].filter(Boolean).join('/'), ...(ngDevMode ? [{ debugName: "schemaUrl" }] : []));
|
|
12109
12158
|
this.schemaKeyUrl = computed(() => [this.schemaUrl(), this.error()?.schemaKey || this.error()?.key].filter(Boolean).join('#'), ...(ngDevMode ? [{ debugName: "schemaKeyUrl" }] : []));
|
|
12110
|
-
this.isSchemaError = computed(() => [ErrorKeys
|
|
12159
|
+
this.isSchemaError = computed(() => [ErrorKeys.PropertyNotFound, ErrorKeys.SchemaNotFound].includes(this.error()?.message), ...(ngDevMode ? [{ debugName: "isSchemaError" }] : []));
|
|
12111
12160
|
this.showJsonPreview = computed(() => !!this.error()?.node && this.isJSONFile(), ...(ngDevMode ? [{ debugName: "showJsonPreview" }] : []));
|
|
12112
12161
|
this.showCsvPreview = computed(() => this.headers().length && this.rows().length && !this.isSchemaError() && !this.isJSONFile(), ...(ngDevMode ? [{ debugName: "showCsvPreview" }] : []));
|
|
12113
12162
|
this.reportErrorUrl = computed(() => issueLink(this.file()?.pipelineStatus || this.file()?.status, this.message()), ...(ngDevMode ? [{ debugName: "reportErrorUrl" }] : []));
|
|
12114
12163
|
this.baseUrl = baseUrl();
|
|
12115
12164
|
this.nodeTypes = acceptedTypes;
|
|
12116
|
-
this.SchemaErrorKeys = ErrorKeys
|
|
12117
|
-
this.ErrorKeys =
|
|
12165
|
+
this.SchemaErrorKeys = ErrorKeys;
|
|
12166
|
+
this.ErrorKeys = FileUploadErrorKeys;
|
|
12118
12167
|
this.maxFileSizeMb = maxFileSizeMb;
|
|
12119
12168
|
this.columns = signal([], ...(ngDevMode ? [{ debugName: "columns" }] : []));
|
|
12120
12169
|
this.headers = signal([], ...(ngDevMode ? [{ debugName: "headers" }] : []));
|
|
@@ -13052,11 +13101,11 @@ class HierarchyChartComponent {
|
|
|
13052
13101
|
return downloadSvg(this.chart().nativeElement);
|
|
13053
13102
|
}
|
|
13054
13103
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: HierarchyChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
13055
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.13", type: HierarchyChartComponent, isStandalone: true, selector: "he-hierarchy-chart", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, terms: { classPropertyName: "terms", publicName: "terms", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { chartError: "chartError" }, viewQueries: [{ propertyName: "chart", first: true, predicate: ["chart"], descendants: true, isSignal: true }, { propertyName: "zoomContainer", first: true, predicate: ["zoomContainer"], descendants: true, isSignal: true }, { propertyName: "chartContainer", first: true, predicate: ["chartContainer"], descendants: true, isSignal: true }, { propertyName: "tooltipOperator", first: true, predicate: ["t"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"chart-area-border\">\n <div\n class=\"is-flex is-justify-content-center is-align-items-center is-flex-wrap-wrap is-gap-16 chart-area-border is-legend\">\n @for (legendItem of legend(); track legendItem.type) {\n <div class=\"is-flex is-align-items-center is-gap-8 | is-legend-item\">\n <span\n class=\"is-inline-block-tablet is-align-middle | key-colour\"\n [style.backgroundColor]=\"nodeColours[legendItem.type]\"\n [style.borderColor]=\"nodeBorderColours[legendItem.type]\"></span>\n <span class=\"is-size-7\">{{ legendItem.text }}</span>\n </div>\n }\n </div>\n\n <div class=\"chart-container is-relative w-100 is-mt-2\">\n <svg class=\"w-100 h-100\" #chart>\n <g #zoomContainer>\n <g #chartContainer></g>\n </g>\n </svg>\n\n <span\n class=\"is-hidden\"\n [ngbPopover]=\"tipContent\"\n triggers=\"manual\"\n placement=\"right left auto\"\n container=\"body\"\n #t=\"ngbPopover\"\n positionTarget=\".tip-target\"\n popoverClass=\"is-narrow driver-chart-tooltip\"\n [animation]=\"true\"></span>\n\n <div class=\"is-absolute | zoom-controls\">\n <div class=\"is-flex is-flex-direction-column is-gap-4\">\n <button class=\"button is-small\" (click)=\"zoomIn()\">\n <he-svg-icon name=\"plus\" size=\"20\" />\n </button>\n <button class=\"button is-small\" (click)=\"zoomOut()\">\n <he-svg-icon name=\"minus\" size=\"20\" />\n </button>\n <button class=\"button is-small\" (click)=\"downloadSvg()\">\n <he-svg-icon name=\"download\" size=\"20\" />\n </button>\n </div>\n </div>\n </div>\n</div>\n\n<ng-template #tipContent let-tipData=\"tipData\">\n @if (tipData.hasWeightedValue) {\n <p>contribution: {{ tipData.weightedValueText }}</p>\n }\n @if (tipData.valueValueText) {\n <p>\n <a class=\"is-dark\" target=\"_blank\" [href]=\"tipData.valueKeyHref\">value</a>\n <span class=\"is-pr-1\">:</span>\n <span>{{ tipData.valueValueText }}</span>\n @if (tipData.hasValue) {\n <a class=\"is-dark is-ml-2\" [href]=\"tipData.modelDocsHref\" target=\"_blank\">\n <span>Docs</span>\n <he-svg-icon name=\"external-link\" class=\"ml-2\" />\n </a>\n }\n </p>\n }\n <p>\n <a class=\"is-dark\" target=\"_blank\" [href]=\"tipData.modelKeyHref\">methodModel</a>\n <span class=\"is-pr-1\">:</span>\n <a class=\"is-dark\" target=\"_blank\" [href]=\"tipData.modelValueHref\">{{ tipData.modelValue }}</a>\n </p>\n <p>\n <a class=\"is-dark\" target=\"_blank\" [href]=\"tipData.termKeyHref\">terms</a>\n <span class=\"is-pr-1\">:</span>\n @for (term of tipData.terms; track term.text; let lastTerm = $last) {\n <a class=\"is-dark\" target=\"_blank\" [href]=\"term.href\">{{ term.text }}</a>\n @if (!lastTerm) {\n <span class=\"is-px-1\">;</span>\n }\n }\n </p>\n</ng-template>\n", styles: [".chart-container{height:500px}@media screen and (min-width: 1216px){.is-legend-item{min-width:130px}}.zoom-controls{top:0;right:0}.zoom-controls .button{width:36px;height:36px}.key-colour{border-radius:3px;border:1px solid transparent;height:20px;width:20px}svg{pointer-events:none}:host ::ng-deep .node-box{fill-opacity:.3;stroke-opacity:.3;pointer-events:auto}:host ::ng-deep .node-openable:not(.mask-openable){cursor:pointer;stroke-opacity:1;fill-opacity:1}:host ::ng-deep .group-button,:host ::ng-deep .group-button-text{display:inline!important;cursor:pointer
|
|
13104
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.13", type: HierarchyChartComponent, isStandalone: true, selector: "he-hierarchy-chart", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, terms: { classPropertyName: "terms", publicName: "terms", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { chartError: "chartError" }, viewQueries: [{ propertyName: "chart", first: true, predicate: ["chart"], descendants: true, isSignal: true }, { propertyName: "zoomContainer", first: true, predicate: ["zoomContainer"], descendants: true, isSignal: true }, { propertyName: "chartContainer", first: true, predicate: ["chartContainer"], descendants: true, isSignal: true }, { propertyName: "tooltipOperator", first: true, predicate: ["t"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"chart-area-border\">\n <div\n class=\"is-flex is-justify-content-center is-align-items-center is-flex-wrap-wrap is-gap-16 chart-area-border is-legend\">\n @for (legendItem of legend(); track legendItem.type) {\n <div class=\"is-flex is-align-items-center is-gap-8 | is-legend-item\">\n <span\n class=\"is-inline-block-tablet is-align-middle | key-colour\"\n [style.backgroundColor]=\"nodeColours[legendItem.type]\"\n [style.borderColor]=\"nodeBorderColours[legendItem.type]\"></span>\n <span class=\"is-size-7\">{{ legendItem.text }}</span>\n </div>\n }\n </div>\n\n <div class=\"chart-container is-relative w-100 is-mt-2\">\n <svg class=\"w-100 h-100\" #chart>\n <g #zoomContainer>\n <g #chartContainer></g>\n </g>\n </svg>\n\n <span\n class=\"is-hidden\"\n [ngbPopover]=\"tipContent\"\n triggers=\"manual\"\n placement=\"right left auto\"\n container=\"body\"\n #t=\"ngbPopover\"\n positionTarget=\".tip-target\"\n popoverClass=\"is-narrow driver-chart-tooltip\"\n [animation]=\"true\"></span>\n\n <div class=\"is-absolute | zoom-controls\">\n <div class=\"is-flex is-flex-direction-column is-gap-4\">\n <button class=\"button is-small\" (click)=\"zoomIn()\">\n <he-svg-icon name=\"plus\" size=\"20\" />\n </button>\n <button class=\"button is-small\" (click)=\"zoomOut()\">\n <he-svg-icon name=\"minus\" size=\"20\" />\n </button>\n <button class=\"button is-small\" (click)=\"downloadSvg()\">\n <he-svg-icon name=\"download\" size=\"20\" />\n </button>\n </div>\n </div>\n </div>\n</div>\n\n<ng-template #tipContent let-tipData=\"tipData\">\n @if (tipData.hasWeightedValue) {\n <p>contribution: {{ tipData.weightedValueText }}</p>\n }\n @if (tipData.valueValueText) {\n <p>\n <a class=\"is-dark\" target=\"_blank\" [href]=\"tipData.valueKeyHref\">value</a>\n <span class=\"is-pr-1\">:</span>\n <span>{{ tipData.valueValueText }}</span>\n @if (tipData.hasValue) {\n <a class=\"is-dark is-ml-2\" [href]=\"tipData.modelDocsHref\" target=\"_blank\">\n <span>Docs</span>\n <he-svg-icon name=\"external-link\" class=\"ml-2\" />\n </a>\n }\n </p>\n }\n <p>\n <a class=\"is-dark\" target=\"_blank\" [href]=\"tipData.modelKeyHref\">methodModel</a>\n <span class=\"is-pr-1\">:</span>\n <a class=\"is-dark\" target=\"_blank\" [href]=\"tipData.modelValueHref\">{{ tipData.modelValue }}</a>\n </p>\n <p>\n <a class=\"is-dark\" target=\"_blank\" [href]=\"tipData.termKeyHref\">terms</a>\n <span class=\"is-pr-1\">:</span>\n @for (term of tipData.terms; track term.text; let lastTerm = $last) {\n <a class=\"is-dark\" target=\"_blank\" [href]=\"term.href\">{{ term.text }}</a>\n @if (!lastTerm) {\n <span class=\"is-px-1\">;</span>\n }\n }\n </p>\n</ng-template>\n", styles: [".chart-container{height:500px}@media screen and (min-width: 1216px){.is-legend-item{min-width:130px}}.zoom-controls{top:0;right:0}.zoom-controls .button{width:36px;height:36px}.key-colour{border-radius:3px;border:1px solid transparent;height:20px;width:20px}svg{pointer-events:none}:host ::ng-deep .node-box{fill-opacity:.3;stroke-opacity:.3;pointer-events:auto}:host ::ng-deep .node-openable:not(.mask-openable){cursor:pointer;stroke-opacity:1;fill-opacity:1}:host ::ng-deep .group-button,:host ::ng-deep .group-button-text{display:inline!important;cursor:pointer}:host ::ng-deep .node-label tspan{alignment-baseline:inherit}:host ::ng-deep .sibling-mask{pointer-events:none}:host ::ng-deep .mask-openable{cursor:pointer;pointer-events:all}:host ::ng-deep .mask-openable:hover{fill:none;stroke:none}\n"], dependencies: [{ kind: "directive", type: 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: HESvgIconComponent, selector: "he-svg-icon", inputs: ["name", "size", "animation"] }] }); }
|
|
13056
13105
|
}
|
|
13057
13106
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: HierarchyChartComponent, decorators: [{
|
|
13058
13107
|
type: Component$1,
|
|
13059
|
-
args: [{ selector: 'he-hierarchy-chart', imports: [NgbPopover, HESvgIconComponent], template: "<div class=\"chart-area-border\">\n <div\n class=\"is-flex is-justify-content-center is-align-items-center is-flex-wrap-wrap is-gap-16 chart-area-border is-legend\">\n @for (legendItem of legend(); track legendItem.type) {\n <div class=\"is-flex is-align-items-center is-gap-8 | is-legend-item\">\n <span\n class=\"is-inline-block-tablet is-align-middle | key-colour\"\n [style.backgroundColor]=\"nodeColours[legendItem.type]\"\n [style.borderColor]=\"nodeBorderColours[legendItem.type]\"></span>\n <span class=\"is-size-7\">{{ legendItem.text }}</span>\n </div>\n }\n </div>\n\n <div class=\"chart-container is-relative w-100 is-mt-2\">\n <svg class=\"w-100 h-100\" #chart>\n <g #zoomContainer>\n <g #chartContainer></g>\n </g>\n </svg>\n\n <span\n class=\"is-hidden\"\n [ngbPopover]=\"tipContent\"\n triggers=\"manual\"\n placement=\"right left auto\"\n container=\"body\"\n #t=\"ngbPopover\"\n positionTarget=\".tip-target\"\n popoverClass=\"is-narrow driver-chart-tooltip\"\n [animation]=\"true\"></span>\n\n <div class=\"is-absolute | zoom-controls\">\n <div class=\"is-flex is-flex-direction-column is-gap-4\">\n <button class=\"button is-small\" (click)=\"zoomIn()\">\n <he-svg-icon name=\"plus\" size=\"20\" />\n </button>\n <button class=\"button is-small\" (click)=\"zoomOut()\">\n <he-svg-icon name=\"minus\" size=\"20\" />\n </button>\n <button class=\"button is-small\" (click)=\"downloadSvg()\">\n <he-svg-icon name=\"download\" size=\"20\" />\n </button>\n </div>\n </div>\n </div>\n</div>\n\n<ng-template #tipContent let-tipData=\"tipData\">\n @if (tipData.hasWeightedValue) {\n <p>contribution: {{ tipData.weightedValueText }}</p>\n }\n @if (tipData.valueValueText) {\n <p>\n <a class=\"is-dark\" target=\"_blank\" [href]=\"tipData.valueKeyHref\">value</a>\n <span class=\"is-pr-1\">:</span>\n <span>{{ tipData.valueValueText }}</span>\n @if (tipData.hasValue) {\n <a class=\"is-dark is-ml-2\" [href]=\"tipData.modelDocsHref\" target=\"_blank\">\n <span>Docs</span>\n <he-svg-icon name=\"external-link\" class=\"ml-2\" />\n </a>\n }\n </p>\n }\n <p>\n <a class=\"is-dark\" target=\"_blank\" [href]=\"tipData.modelKeyHref\">methodModel</a>\n <span class=\"is-pr-1\">:</span>\n <a class=\"is-dark\" target=\"_blank\" [href]=\"tipData.modelValueHref\">{{ tipData.modelValue }}</a>\n </p>\n <p>\n <a class=\"is-dark\" target=\"_blank\" [href]=\"tipData.termKeyHref\">terms</a>\n <span class=\"is-pr-1\">:</span>\n @for (term of tipData.terms; track term.text; let lastTerm = $last) {\n <a class=\"is-dark\" target=\"_blank\" [href]=\"term.href\">{{ term.text }}</a>\n @if (!lastTerm) {\n <span class=\"is-px-1\">;</span>\n }\n }\n </p>\n</ng-template>\n", styles: [".chart-container{height:500px}@media screen and (min-width: 1216px){.is-legend-item{min-width:130px}}.zoom-controls{top:0;right:0}.zoom-controls .button{width:36px;height:36px}.key-colour{border-radius:3px;border:1px solid transparent;height:20px;width:20px}svg{pointer-events:none}:host ::ng-deep .node-box{fill-opacity:.3;stroke-opacity:.3;pointer-events:auto}:host ::ng-deep .node-openable:not(.mask-openable){cursor:pointer;stroke-opacity:1;fill-opacity:1}:host ::ng-deep .group-button,:host ::ng-deep .group-button-text{display:inline!important;cursor:pointer
|
|
13108
|
+
args: [{ selector: 'he-hierarchy-chart', imports: [NgbPopover, HESvgIconComponent], template: "<div class=\"chart-area-border\">\n <div\n class=\"is-flex is-justify-content-center is-align-items-center is-flex-wrap-wrap is-gap-16 chart-area-border is-legend\">\n @for (legendItem of legend(); track legendItem.type) {\n <div class=\"is-flex is-align-items-center is-gap-8 | is-legend-item\">\n <span\n class=\"is-inline-block-tablet is-align-middle | key-colour\"\n [style.backgroundColor]=\"nodeColours[legendItem.type]\"\n [style.borderColor]=\"nodeBorderColours[legendItem.type]\"></span>\n <span class=\"is-size-7\">{{ legendItem.text }}</span>\n </div>\n }\n </div>\n\n <div class=\"chart-container is-relative w-100 is-mt-2\">\n <svg class=\"w-100 h-100\" #chart>\n <g #zoomContainer>\n <g #chartContainer></g>\n </g>\n </svg>\n\n <span\n class=\"is-hidden\"\n [ngbPopover]=\"tipContent\"\n triggers=\"manual\"\n placement=\"right left auto\"\n container=\"body\"\n #t=\"ngbPopover\"\n positionTarget=\".tip-target\"\n popoverClass=\"is-narrow driver-chart-tooltip\"\n [animation]=\"true\"></span>\n\n <div class=\"is-absolute | zoom-controls\">\n <div class=\"is-flex is-flex-direction-column is-gap-4\">\n <button class=\"button is-small\" (click)=\"zoomIn()\">\n <he-svg-icon name=\"plus\" size=\"20\" />\n </button>\n <button class=\"button is-small\" (click)=\"zoomOut()\">\n <he-svg-icon name=\"minus\" size=\"20\" />\n </button>\n <button class=\"button is-small\" (click)=\"downloadSvg()\">\n <he-svg-icon name=\"download\" size=\"20\" />\n </button>\n </div>\n </div>\n </div>\n</div>\n\n<ng-template #tipContent let-tipData=\"tipData\">\n @if (tipData.hasWeightedValue) {\n <p>contribution: {{ tipData.weightedValueText }}</p>\n }\n @if (tipData.valueValueText) {\n <p>\n <a class=\"is-dark\" target=\"_blank\" [href]=\"tipData.valueKeyHref\">value</a>\n <span class=\"is-pr-1\">:</span>\n <span>{{ tipData.valueValueText }}</span>\n @if (tipData.hasValue) {\n <a class=\"is-dark is-ml-2\" [href]=\"tipData.modelDocsHref\" target=\"_blank\">\n <span>Docs</span>\n <he-svg-icon name=\"external-link\" class=\"ml-2\" />\n </a>\n }\n </p>\n }\n <p>\n <a class=\"is-dark\" target=\"_blank\" [href]=\"tipData.modelKeyHref\">methodModel</a>\n <span class=\"is-pr-1\">:</span>\n <a class=\"is-dark\" target=\"_blank\" [href]=\"tipData.modelValueHref\">{{ tipData.modelValue }}</a>\n </p>\n <p>\n <a class=\"is-dark\" target=\"_blank\" [href]=\"tipData.termKeyHref\">terms</a>\n <span class=\"is-pr-1\">:</span>\n @for (term of tipData.terms; track term.text; let lastTerm = $last) {\n <a class=\"is-dark\" target=\"_blank\" [href]=\"term.href\">{{ term.text }}</a>\n @if (!lastTerm) {\n <span class=\"is-px-1\">;</span>\n }\n }\n </p>\n</ng-template>\n", styles: [".chart-container{height:500px}@media screen and (min-width: 1216px){.is-legend-item{min-width:130px}}.zoom-controls{top:0;right:0}.zoom-controls .button{width:36px;height:36px}.key-colour{border-radius:3px;border:1px solid transparent;height:20px;width:20px}svg{pointer-events:none}:host ::ng-deep .node-box{fill-opacity:.3;stroke-opacity:.3;pointer-events:auto}:host ::ng-deep .node-openable:not(.mask-openable){cursor:pointer;stroke-opacity:1;fill-opacity:1}:host ::ng-deep .group-button,:host ::ng-deep .group-button-text{display:inline!important;cursor:pointer}:host ::ng-deep .node-label tspan{alignment-baseline:inherit}:host ::ng-deep .sibling-mask{pointer-events:none}:host ::ng-deep .mask-openable{cursor:pointer;pointer-events:all}:host ::ng-deep .mask-openable:hover{fill:none;stroke:none}\n"] }]
|
|
13060
13109
|
}], ctorParameters: () => [], propDecorators: { chart: [{ type: i0.ViewChild, args: ['chart', { isSignal: true }] }], zoomContainer: [{ type: i0.ViewChild, args: ['zoomContainer', { isSignal: true }] }], chartContainer: [{ type: i0.ViewChild, args: ['chartContainer', { isSignal: true }] }], tooltipOperator: [{ type: i0.ViewChild, args: ['t', { isSignal: true }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], terms: [{ type: i0.Input, args: [{ isSignal: true, alias: "terms", required: false }] }], chartError: [{ type: i0.Output, args: ["chartError"] }] } });
|
|
13061
13110
|
|
|
13062
13111
|
const filterTermTypes$1 = [
|
|
@@ -13234,11 +13283,11 @@ class ImpactAssessmentsGraphComponent {
|
|
|
13234
13283
|
effect(() => this.showWarnings.set(this.warnings()?.length > 0));
|
|
13235
13284
|
}
|
|
13236
13285
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: ImpactAssessmentsGraphComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
13237
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.13", type: ImpactAssessmentsGraphComponent, isStandalone: true, selector: "he-impact-assessments-graph", inputs: { impactAssessments: { classPropertyName: "impactAssessments", publicName: "impactAssessments", isSignal: true, isRequired: false, transformFunction: null }, dataState: { classPropertyName: "dataState", publicName: "dataState", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (isRecalculated()) {\n @if (loading()) {\n <div class=\"loading-container has-text-center my-5 py-5\">\n <he-svg-icon name=\"loading\" animation=\"spin\" size=\"40\" />\n <p class=\"is-mt-2 is-italic is-size-7\">Loading chart, please wait...</p>\n </div>\n } @else {\n @if (filteredImpactAssessments().length > 1) {\n <div class=\"field is-horizontal\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary\" for=\"selectedImpactAssessmentId\">Impact Assessment</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth is-secondary\">\n <select [(ngModel)]=\"selectedImpactAssessmentId\" [disabled]=\"loading()\">\n @for (value of filteredImpactAssessments(); track value['@id']) {\n <option [value]=\"value['@id']\">\n {{ value.name || value['@id'] }}\n </option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n @if (!noData()) {\n <div class=\"field is-horizontal\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary\" for=\"selectedModelId\">Model</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth is-secondary\">\n <select [(ngModel)]=\"selectedModelId\" id=\"selectedModelId\" [disabled]=\"loading()\">\n @for (model of models(); track model['@id']) {\n <option [value]=\"model['@id']\">{{ model.name || model['@id'] }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n @if (showWarnings()) {\n <div class=\"has-text-warning py-3 has-text-centered\">\n @for (warning of warnings(); track warning) {\n <p class=\"is-mb-2\">\n <he-svg-icon name=\"exclamation-triangle\" class=\"pr-2\" />\n @switch (warning) {\n @case ('missing-terms') {\n <span>Calculations are not up to date. Some terms may not display correctly.</span>\n }\n }\n </p>\n }\n <p class=\"is-underlined is-size-7\"><a (click)=\"showWarnings.set(false)\">View chart anyway.</a></p>\n </div>\n }\n @if (error()) {\n <p class=\"has-text-danger py-3\">\n @switch (error()) {\n @case ('not-found') {\n <p>Impact Assessment not found</p>\n }\n @default {\n <div>\n <span>An unexpected error occurred:</span>\n <p class=\"mt-1\">{{ error() }}</p>\n </div>\n }\n }\n </p>\n }\n @if (noData()) {\n <div class=\"py-3\">\n <p class=\"has-text-centered\">No chart available.</p>\n </div>\n }\n }\n} @else {\n <p class=\"has-text-centered py-3\">\n No chart available. Switch to\n <code>recalculated</code>\n version.\n </p>\n}\n\n@if (showChart()) {\n <he-hierarchy-chart [data]=\"chartData()\" [terms]=\"allTerms()\" (chartError)=\"error.set($event)\" />\n}\n", styles: [".loading-container{min-height:200px}\n"], dependencies: [{ kind: "component", type: HESvgIconComponent, selector: "he-svg-icon", inputs: ["name", "size", "animation"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: HierarchyChartComponent, selector: "he-hierarchy-chart", inputs: ["data", "terms"], outputs: ["chartError"] }] }); }
|
|
13286
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.13", type: ImpactAssessmentsGraphComponent, isStandalone: true, selector: "he-impact-assessments-graph", inputs: { impactAssessments: { classPropertyName: "impactAssessments", publicName: "impactAssessments", isSignal: true, isRequired: false, transformFunction: null }, dataState: { classPropertyName: "dataState", publicName: "dataState", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (isRecalculated()) {\n @if (loading()) {\n <div class=\"loading-container has-text-center my-5 py-5\">\n <he-svg-icon name=\"loading\" animation=\"spin\" size=\"40\" />\n <p class=\"is-mt-2 is-italic is-size-7\">Loading chart, please wait...</p>\n </div>\n } @else {\n @if (filteredImpactAssessments().length > 1) {\n <div class=\"field is-horizontal\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary\" for=\"selectedImpactAssessmentId\">Impact Assessment</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth is-secondary\">\n <select [(ngModel)]=\"selectedImpactAssessmentId\" [disabled]=\"loading()\">\n @for (value of filteredImpactAssessments(); track value['@id']) {\n <option [value]=\"value['@id']\">\n {{ value.name || value['@id'] }}\n </option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n @if (!noData()) {\n <div class=\"field is-horizontal\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary\" for=\"selectedModelId\">Model</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth is-secondary\">\n <select [(ngModel)]=\"selectedModelId\" id=\"selectedModelId\" [disabled]=\"loading()\">\n @for (model of models(); track model['@id']) {\n <option [value]=\"model['@id']\">{{ model.name || model['@id'] }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n @if (showWarnings()) {\n <div class=\"has-text-warning py-3 has-text-centered\">\n @for (warning of warnings(); track warning) {\n <p class=\"is-mb-2\">\n <he-svg-icon name=\"exclamation-triangle\" class=\"pr-2\" />\n @switch (warning) {\n @case ('missing-terms') {\n <span>Calculations are not up to date. Some terms may not display correctly.</span>\n }\n }\n </p>\n }\n <p class=\"is-underlined is-size-7\"><a (click)=\"showWarnings.set(false)\">View chart anyway.</a></p>\n </div>\n }\n @if (error()) {\n <p class=\"has-text-danger py-3\">\n @switch (error()) {\n @case ('not-found') {\n <p>Impact Assessment not found</p>\n }\n @default {\n <div>\n <span>An unexpected error occurred:</span>\n <p class=\"mt-1\">{{ error() }}</p>\n </div>\n }\n }\n </p>\n }\n @if (noData()) {\n <div class=\"py-3\">\n <p class=\"has-text-centered\">No chart available.</p>\n </div>\n }\n }\n} @else {\n <p class=\"has-text-centered py-3\">\n No chart available. Switch to\n <code>recalculated</code>\n version.\n </p>\n}\n\n@if (showChart()) {\n <he-hierarchy-chart [data]=\"chartData()\" [terms]=\"allTerms()\" (chartError)=\"error.set($event)\" />\n}\n", styles: [".loading-container{min-height:200px}\n"], dependencies: [{ kind: "component", type: HESvgIconComponent, selector: "he-svg-icon", inputs: ["name", "size", "animation"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: HierarchyChartComponent, selector: "he-hierarchy-chart", inputs: ["data", "terms"], outputs: ["chartError"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
13238
13287
|
}
|
|
13239
13288
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: ImpactAssessmentsGraphComponent, decorators: [{
|
|
13240
13289
|
type: Component$1,
|
|
13241
|
-
args: [{ selector: 'he-impact-assessments-graph', imports: [HESvgIconComponent, FormsModule, HierarchyChartComponent], template: "@if (isRecalculated()) {\n @if (loading()) {\n <div class=\"loading-container has-text-center my-5 py-5\">\n <he-svg-icon name=\"loading\" animation=\"spin\" size=\"40\" />\n <p class=\"is-mt-2 is-italic is-size-7\">Loading chart, please wait...</p>\n </div>\n } @else {\n @if (filteredImpactAssessments().length > 1) {\n <div class=\"field is-horizontal\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary\" for=\"selectedImpactAssessmentId\">Impact Assessment</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth is-secondary\">\n <select [(ngModel)]=\"selectedImpactAssessmentId\" [disabled]=\"loading()\">\n @for (value of filteredImpactAssessments(); track value['@id']) {\n <option [value]=\"value['@id']\">\n {{ value.name || value['@id'] }}\n </option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n @if (!noData()) {\n <div class=\"field is-horizontal\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary\" for=\"selectedModelId\">Model</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth is-secondary\">\n <select [(ngModel)]=\"selectedModelId\" id=\"selectedModelId\" [disabled]=\"loading()\">\n @for (model of models(); track model['@id']) {\n <option [value]=\"model['@id']\">{{ model.name || model['@id'] }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n @if (showWarnings()) {\n <div class=\"has-text-warning py-3 has-text-centered\">\n @for (warning of warnings(); track warning) {\n <p class=\"is-mb-2\">\n <he-svg-icon name=\"exclamation-triangle\" class=\"pr-2\" />\n @switch (warning) {\n @case ('missing-terms') {\n <span>Calculations are not up to date. Some terms may not display correctly.</span>\n }\n }\n </p>\n }\n <p class=\"is-underlined is-size-7\"><a (click)=\"showWarnings.set(false)\">View chart anyway.</a></p>\n </div>\n }\n @if (error()) {\n <p class=\"has-text-danger py-3\">\n @switch (error()) {\n @case ('not-found') {\n <p>Impact Assessment not found</p>\n }\n @default {\n <div>\n <span>An unexpected error occurred:</span>\n <p class=\"mt-1\">{{ error() }}</p>\n </div>\n }\n }\n </p>\n }\n @if (noData()) {\n <div class=\"py-3\">\n <p class=\"has-text-centered\">No chart available.</p>\n </div>\n }\n }\n} @else {\n <p class=\"has-text-centered py-3\">\n No chart available. Switch to\n <code>recalculated</code>\n version.\n </p>\n}\n\n@if (showChart()) {\n <he-hierarchy-chart [data]=\"chartData()\" [terms]=\"allTerms()\" (chartError)=\"error.set($event)\" />\n}\n", styles: [".loading-container{min-height:200px}\n"] }]
|
|
13290
|
+
args: [{ selector: 'he-impact-assessments-graph', changeDetection: ChangeDetectionStrategy.OnPush, imports: [HESvgIconComponent, FormsModule, HierarchyChartComponent], template: "@if (isRecalculated()) {\n @if (loading()) {\n <div class=\"loading-container has-text-center my-5 py-5\">\n <he-svg-icon name=\"loading\" animation=\"spin\" size=\"40\" />\n <p class=\"is-mt-2 is-italic is-size-7\">Loading chart, please wait...</p>\n </div>\n } @else {\n @if (filteredImpactAssessments().length > 1) {\n <div class=\"field is-horizontal\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary\" for=\"selectedImpactAssessmentId\">Impact Assessment</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth is-secondary\">\n <select [(ngModel)]=\"selectedImpactAssessmentId\" [disabled]=\"loading()\">\n @for (value of filteredImpactAssessments(); track value['@id']) {\n <option [value]=\"value['@id']\">\n {{ value.name || value['@id'] }}\n </option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n @if (!noData()) {\n <div class=\"field is-horizontal\">\n <div class=\"field-label is-normal\">\n <label class=\"label has-text-secondary\" for=\"selectedModelId\">Model</label>\n </div>\n <div class=\"field-body\">\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth is-secondary\">\n <select [(ngModel)]=\"selectedModelId\" id=\"selectedModelId\" [disabled]=\"loading()\">\n @for (model of models(); track model['@id']) {\n <option [value]=\"model['@id']\">{{ model.name || model['@id'] }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n @if (showWarnings()) {\n <div class=\"has-text-warning py-3 has-text-centered\">\n @for (warning of warnings(); track warning) {\n <p class=\"is-mb-2\">\n <he-svg-icon name=\"exclamation-triangle\" class=\"pr-2\" />\n @switch (warning) {\n @case ('missing-terms') {\n <span>Calculations are not up to date. Some terms may not display correctly.</span>\n }\n }\n </p>\n }\n <p class=\"is-underlined is-size-7\"><a (click)=\"showWarnings.set(false)\">View chart anyway.</a></p>\n </div>\n }\n @if (error()) {\n <p class=\"has-text-danger py-3\">\n @switch (error()) {\n @case ('not-found') {\n <p>Impact Assessment not found</p>\n }\n @default {\n <div>\n <span>An unexpected error occurred:</span>\n <p class=\"mt-1\">{{ error() }}</p>\n </div>\n }\n }\n </p>\n }\n @if (noData()) {\n <div class=\"py-3\">\n <p class=\"has-text-centered\">No chart available.</p>\n </div>\n }\n }\n} @else {\n <p class=\"has-text-centered py-3\">\n No chart available. Switch to\n <code>recalculated</code>\n version.\n </p>\n}\n\n@if (showChart()) {\n <he-hierarchy-chart [data]=\"chartData()\" [terms]=\"allTerms()\" (chartError)=\"error.set($event)\" />\n}\n", styles: [".loading-container{min-height:200px}\n"] }]
|
|
13242
13291
|
}], ctorParameters: () => [], propDecorators: { impactAssessments: [{ type: i0.Input, args: [{ isSignal: true, alias: "impactAssessments", required: false }] }], dataState: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataState", required: false }] }] } });
|
|
13243
13292
|
|
|
13244
13293
|
const parseLog = (data) => ({
|
|
@@ -13263,13 +13312,12 @@ const logsTotalValue = (logs, includeNegativeValues) => sum((includeNegativeValu
|
|
|
13263
13312
|
const valueRatio = (value, total) => toPrecision((value * 100) / total, 2);
|
|
13264
13313
|
const chartLabel = (value, total) => {
|
|
13265
13314
|
const ratio = valueRatio(value, total);
|
|
13266
|
-
return value === 0 ? '0' : `${
|
|
13315
|
+
return value === 0 ? '0' : `${value}, ${ratio}%`;
|
|
13267
13316
|
};
|
|
13268
13317
|
const chartBreakdownLabel = (logs, total, maxValues) => {
|
|
13269
13318
|
const values = logs.slice(maxValues);
|
|
13270
13319
|
return values.map(({ blankNodeTermId, value }) => `${blankNodeTermId}: ${chartLabel(value, total)}`).join('</br>');
|
|
13271
13320
|
};
|
|
13272
|
-
const chartTextColor = (value) => (isUndefined(value) ? '#b5b5b5' : '#4a4a4a');
|
|
13273
13321
|
const logToCsv = (logs, impact) => [
|
|
13274
13322
|
csvHeaders.join(','),
|
|
13275
13323
|
...logs
|
|
@@ -13288,7 +13336,6 @@ class ImpactAssessmentsIndicatorBreakdownChartComponent {
|
|
|
13288
13336
|
this.responsiveService = inject(ResponsiveService);
|
|
13289
13337
|
this.impactAssessment = input.required(...(ngDevMode ? [{ debugName: "impactAssessment" }] : []));
|
|
13290
13338
|
this.indicators = input([], ...(ngDevMode ? [{ debugName: "indicators" }] : []));
|
|
13291
|
-
this.tooltip = viewChild.required('tooltip');
|
|
13292
13339
|
this.maximumValues = computed(() => (this.responsiveService.isMobile() ? 10 : 20), ...(ngDevMode ? [{ debugName: "maximumValues" }] : []));
|
|
13293
13340
|
this.logsResource = rxResource({
|
|
13294
13341
|
params: () => ({
|
|
@@ -13305,7 +13352,10 @@ class ImpactAssessmentsIndicatorBreakdownChartComponent {
|
|
|
13305
13352
|
].filter(v => v.term['@id'] === log.blankNodeTermId);
|
|
13306
13353
|
const inputs = blankNodes
|
|
13307
13354
|
.filter(v => v.inputs?.length)
|
|
13308
|
-
.map(v => ({
|
|
13355
|
+
.map(v => ({
|
|
13356
|
+
name: v.inputs.map(i => i['@id']).join(';'),
|
|
13357
|
+
value: toPrecision(v.value * log.coefficient, 3)
|
|
13358
|
+
}));
|
|
13309
13359
|
const inputsValue = inputs.reduce((prev, curr) => prev + curr.value, 0);
|
|
13310
13360
|
const impact = impacts?.find(v => v.term['@id'] === log.impactTermId);
|
|
13311
13361
|
// logs might exist but impact was not added => skip logs
|
|
@@ -13313,7 +13363,7 @@ class ImpactAssessmentsIndicatorBreakdownChartComponent {
|
|
|
13313
13363
|
? {
|
|
13314
13364
|
...log,
|
|
13315
13365
|
impactTermUnits: impact.term?.units,
|
|
13316
|
-
value: total,
|
|
13366
|
+
value: toPrecision(total, 3),
|
|
13317
13367
|
inputs,
|
|
13318
13368
|
inputsValue
|
|
13319
13369
|
}
|
|
@@ -13355,93 +13405,34 @@ class ImpactAssessmentsIndicatorBreakdownChartComponent {
|
|
|
13355
13405
|
...(this.impactAssessment()?.endpoints || [])
|
|
13356
13406
|
], ...(ngDevMode ? [{ debugName: "impacts" }] : []));
|
|
13357
13407
|
this.noData = computed(() => this.nonZeroLogs()?.length === 0, ...(ngDevMode ? [{ debugName: "noData" }] : []));
|
|
13358
|
-
this.
|
|
13359
|
-
|
|
13360
|
-
|
|
13361
|
-
|
|
13362
|
-
|
|
13363
|
-
...includedValues,
|
|
13364
|
-
excludedValues.length
|
|
13365
|
-
? {
|
|
13366
|
-
blankNodeTermId: `${excludedValues.length} others`,
|
|
13367
|
-
value: sum(excludedValues.map(({ value }) => value)),
|
|
13368
|
-
subLogs: excludedValues.map(value => ({
|
|
13369
|
-
...value,
|
|
13370
|
-
name: this.emissions()?.find(v => v['@id'] === value.blankNodeTermId)?.name || value.blankNodeTermId
|
|
13371
|
-
}))
|
|
13372
|
-
}
|
|
13373
|
-
: null
|
|
13374
|
-
]
|
|
13375
|
-
.filter(Boolean)
|
|
13376
|
-
.map((value, index) => ({
|
|
13377
|
-
...value,
|
|
13378
|
-
name: this.emissions()?.find(v => v['@id'] === value.blankNodeTermId)?.name || value.blankNodeTermId,
|
|
13379
|
-
color: listColor(value, index),
|
|
13380
|
-
secondaryColor: listColorWithAlpha()(value, index)
|
|
13381
|
-
}));
|
|
13382
|
-
}, ...(ngDevMode ? [{ debugName: "values" }] : []));
|
|
13408
|
+
this.values = computed(() => this.nonZeroLogs().map((value, index) => ({
|
|
13409
|
+
...value,
|
|
13410
|
+
name: this.emissions()?.find(v => v['@id'] === value.blankNodeTermId)?.name || value.blankNodeTermId,
|
|
13411
|
+
color: listColor(value, index)
|
|
13412
|
+
})), ...(ngDevMode ? [{ debugName: "values" }] : []));
|
|
13383
13413
|
this.csvContent = computed(() => this.domSanitizer.bypassSecurityTrustResourceUrl(`data:text/html;charset=utf-8,${encodeURIComponent(logToCsv(this.logs(), this.impactAssessment()))}`), ...(ngDevMode ? [{ debugName: "csvContent" }] : []));
|
|
13384
13414
|
this.id = computed(() => this.impactAssessment()?.['@id'] || this.impactAssessment()?.id, ...(ngDevMode ? [{ debugName: "id" }] : []));
|
|
13385
13415
|
this.downloadFilename = computed(() => `${this.id()}-logs.csv`, ...(ngDevMode ? [{ debugName: "downloadFilename" }] : []));
|
|
13386
13416
|
this.displayValue = signal(false, ...(ngDevMode ? [{ debugName: "displayValue" }] : []));
|
|
13387
13417
|
this.total = computed(() => logsTotalValue(this.nonZeroLogs(), false), ...(ngDevMode ? [{ debugName: "total" }] : []));
|
|
13388
|
-
this.
|
|
13389
|
-
|
|
13390
|
-
|
|
13391
|
-
|
|
13392
|
-
|
|
13393
|
-
|
|
13394
|
-
|
|
13395
|
-
|
|
13396
|
-
|
|
13397
|
-
|
|
13398
|
-
|
|
13399
|
-
|
|
13400
|
-
|
|
13401
|
-
|
|
13402
|
-
|
|
13403
|
-
|
|
13404
|
-
this.chartConfig = computed(() => ({
|
|
13405
|
-
plugins: [
|
|
13406
|
-
lollipopChartPlugin(),
|
|
13407
|
-
afterBarDrawPlugin({
|
|
13408
|
-
xPosFn: (x, index, width, chart) => (x || chart.scales['x-axis-0'].getPixelForValue(0)) + 10,
|
|
13409
|
-
colorFn: (m, index, chart, data) => chartTextColor(data),
|
|
13410
|
-
emptyValueLabel: 'No value',
|
|
13411
|
-
...(this.displayValue()
|
|
13412
|
-
? {
|
|
13413
|
-
textFn: ({ label, data }, index) => index === this.maximumValues()
|
|
13414
|
-
? `${label} at ${toPrecision(data)}`
|
|
13415
|
-
: `${toPrecision(data)}`
|
|
13416
|
-
}
|
|
13417
|
-
: { textFn: ({ data }) => `${valueRatio(data, this.total())}%` })
|
|
13418
|
-
}),
|
|
13419
|
-
backgroundHoverPlugin({ threshold: 5 })
|
|
13420
|
-
],
|
|
13421
|
-
options: {
|
|
13422
|
-
onClick: (event, activeElements) => {
|
|
13423
|
-
const index = activeElements?.[0]?.['_index'];
|
|
13424
|
-
!event.isTrusted && this.showTooltip(index, event.x, event.y);
|
|
13425
|
-
},
|
|
13426
|
-
scales: {
|
|
13427
|
-
xAxes: [
|
|
13428
|
-
{
|
|
13429
|
-
display: !this.responsiveService.isMobile(),
|
|
13430
|
-
scaleLabel: {
|
|
13431
|
-
labelString: this.selectedTerm()?.units
|
|
13432
|
-
}
|
|
13433
|
-
}
|
|
13434
|
-
],
|
|
13435
|
-
yAxes: [
|
|
13436
|
-
{
|
|
13437
|
-
display: !this.responsiveService.isMobile()
|
|
13438
|
-
}
|
|
13439
|
-
]
|
|
13440
|
-
}
|
|
13418
|
+
this.chartData = computed(() => this.values().map(value => ({
|
|
13419
|
+
label: value.name,
|
|
13420
|
+
count: value.value,
|
|
13421
|
+
backgroundColor: value.color
|
|
13422
|
+
})), ...(ngDevMode ? [{ debugName: "chartData" }] : []));
|
|
13423
|
+
this.chartTooltipFn = ({ includedItems }, index) => {
|
|
13424
|
+
const { value } = this.values()[index] || {};
|
|
13425
|
+
return !isUndefined(value)
|
|
13426
|
+
? includedItems?.length
|
|
13427
|
+
? chartBreakdownLabel(this.nonZeroLogs(), this.total(), this.maximumValues())
|
|
13428
|
+
: chartLabel(value, this.total())
|
|
13429
|
+
: '';
|
|
13430
|
+
};
|
|
13431
|
+
this.afterBarDrawSettings = computed(() => (this.displayValue()
|
|
13432
|
+
? {
|
|
13433
|
+
textFn: ({ label, data }, index) => (index === this.maximumValues() ? `${label} at ${data}` : `${data}`)
|
|
13441
13434
|
}
|
|
13442
|
-
|
|
13443
|
-
this.tooltipX = signal(0, ...(ngDevMode ? [{ debugName: "tooltipX" }] : []));
|
|
13444
|
-
this.tooltipY = signal(0, ...(ngDevMode ? [{ debugName: "tooltipY" }] : []));
|
|
13435
|
+
: { textFn: ({ data }) => `${valueRatio(data, this.total())}%` }), ...(ngDevMode ? [{ debugName: "afterBarDrawSettings" }] : []));
|
|
13445
13436
|
// make sure selected term exists
|
|
13446
13437
|
effect(() => {
|
|
13447
13438
|
const terms = this.terms();
|
|
@@ -13466,24 +13457,13 @@ class ImpactAssessmentsIndicatorBreakdownChartComponent {
|
|
|
13466
13457
|
trackByLog({ blankNodeTermId, modelId, impactTermId }) {
|
|
13467
13458
|
return [blankNodeTermId, modelId, impactTermId].join('-');
|
|
13468
13459
|
}
|
|
13469
|
-
showTooltip(index, x, y) {
|
|
13470
|
-
this.tooltipX.set(x);
|
|
13471
|
-
this.tooltipY.set(y);
|
|
13472
|
-
const { value } = this.values()[index] || {};
|
|
13473
|
-
const text = value
|
|
13474
|
-
? index === this.maximumValues()
|
|
13475
|
-
? chartBreakdownLabel(this.nonZeroLogs(), this.total(), this.maximumValues())
|
|
13476
|
-
: chartLabel(value, this.total())
|
|
13477
|
-
: '';
|
|
13478
|
-
text && setTimeout(() => this.tooltip().open({ data: text }));
|
|
13479
|
-
}
|
|
13480
13460
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: ImpactAssessmentsIndicatorBreakdownChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
13481
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.13", type: ImpactAssessmentsIndicatorBreakdownChartComponent, isStandalone: true, selector: "he-impact-assessments-indicator-breakdown-chart", inputs: { impactAssessment: { classPropertyName: "impactAssessment", publicName: "impactAssessment", isSignal: true, isRequired: true, transformFunction: null }, indicators: { classPropertyName: "indicators", publicName: "indicators", isSignal: true, isRequired: false, transformFunction: null } },
|
|
13461
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.13", type: ImpactAssessmentsIndicatorBreakdownChartComponent, isStandalone: true, selector: "he-impact-assessments-indicator-breakdown-chart", inputs: { impactAssessment: { classPropertyName: "impactAssessment", publicName: "impactAssessment", isSignal: true, isRequired: true, transformFunction: null }, indicators: { classPropertyName: "indicators", publicName: "indicators", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"is-mb-3\">\n <ng-content />\n</div>\n\n@if (logsResource.isLoading()) {\n <div class=\"has-text-center py-3\">\n <he-svg-icon name=\"loading\" animation=\"spin\" size=\"40\" />\n </div>\n} @else if (terms()?.length) {\n <div class=\"is-flex is-align-items-center is-gap-12 is-mb-2 | breakdown-actions-table\">\n @if (terms()?.length) {\n <div class=\"control is-expanded is-flex-grow-1\">\n <div class=\"select is-fullwidth is-small\">\n <select [(ngModel)]=\"selectedTermId\" name=\"selectedTermId\">\n @for (term of terms(); track term) {\n <option [value]=\"term['@id']\">{{ term.name }}</option>\n }\n </select>\n </div>\n </div>\n }\n @if (methods()?.length) {\n <div class=\"control is-expanded is-flex-shrink-0\">\n <div class=\"select is-fullwidth is-small\">\n <select [(ngModel)]=\"selectedMethodId\" name=\"selectedMethodId\">\n @if (methods().length > 1) {\n <option [ngValue]=\"undefined\">Filter Model</option>\n }\n @for (term of methods(); track term) {\n <option [value]=\"term['@id']\">{{ term.name }}</option>\n }\n </select>\n </div>\n </div>\n }\n\n <div class=\"is-flex is-justify-content-space-between w-100\">\n <div ngbDropdown #optionDd=\"ngbDropdown\" container=\"body\" placement=\"bottom-end\">\n <button\n ngbDropdownToggle\n class=\"button is-small\"\n type=\"button\"\n aria-haspopup=\"true\"\n aria-controls=\"download-menu\">\n <span class=\"is-pr-1 is-align-middle\">Download</span>\n <he-svg-icon name=\"chevron-down\" aria-hidden=\"true\" />\n </button>\n <div ngbDropdownMenu id=\"download-menu\" role=\"menu\">\n <div class=\"dropdown-content\">\n <a ngbDropdownItem (click)=\"chart.exportAsSvg({ lollipopConfig: {} })\">\n <he-svg-icon size=\"20\" name=\"chart\" />\n <span class=\"is-pl-2 is-size-7\">Chart Image (.svg)</span>\n </a>\n\n <a ngbDropdownItem [href]=\"csvContent()\" [download]=\"downloadFilename()\">\n <he-svg-icon size=\"20\" name=\"table\" />\n <span class=\"is-pl-2 is-size-7\">Chart Data (.csv)</span>\n </a>\n </div>\n </div>\n </div>\n\n <div class=\"field is-relative is-mb-0 is-hidden-tablet\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded is-secondary\"\n id=\"displayValue\"\n name=\"displayValue\"\n [(ngModel)]=\"displayValue\" />\n <label for=\"displayValue\">Show numerical value</label>\n </div>\n </div>\n </div>\n}\n\n@if (!logsResource.isLoading() && noData()) {\n <div class=\"chart-area-border\">\n <p class=\"has-text-centered\">\n <span>No breakdown available for</span>\n @if (selectedTerm()) {\n <span class=\"is-pl-1\">{{ selectedTerm().name }}</span>\n }\n @if (selectedMethod()) {\n <span class=\"is-pl-1\">({{ selectedMethod().name }})</span>\n }\n <span>.</span>\n </p>\n </div>\n}\n\n<he-horizontal-bar-chart\n #chart=\"horizontalBarChart\"\n class=\"is-relative h-100\"\n [title]=\"selectedTerm()?.units\"\n [data]=\"chartData()\"\n [max]=\"total()\"\n [maximumValues]=\"maximumValues()\"\n [showExportButton]=\"false\"\n [showNegativeValues]=\"false\"\n [tooltipFn]=\"chartTooltipFn\"\n [afterBarDrawSettings]=\"afterBarDrawSettings()\" />\n", styles: [":host{display:block;overflow:visible}.shadow-tooltip{width:1px;height:1px;pointer-events:none}he-horizontal-bar-chart ::ng-deep .chart-container{min-height:400px}@media screen and (max-width: 767px){he-horizontal-bar-chart ::ng-deep .chart-container{min-height:200px}}@media screen and (max-width: 767px){.chart-area-border{padding:0}}@media screen and (max-width: 767px){.breakdown-actions-table{flex-direction:column;align-items:flex-start!important}}.breakdown-legend{background:#fafafa}.breakdown-legend--color{width:8px;height:8px;border-radius:50%}\n"], dependencies: [{ kind: "component", type: HESvgIconComponent, selector: "he-svg-icon", inputs: ["name", "size", "animation"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: NgbDropdownModule }, { kind: "directive", type: i1$2.NgbDropdown, selector: "[ngbDropdown]", inputs: ["autoClose", "dropdownClass", "open", "placement", "popperOptions", "container", "display"], outputs: ["openChange"], exportAs: ["ngbDropdown"] }, { kind: "directive", type: i1$2.NgbDropdownToggle, selector: "[ngbDropdownToggle]" }, { kind: "directive", type: i1$2.NgbDropdownMenu, selector: "[ngbDropdownMenu]" }, { kind: "directive", type: i1$2.NgbDropdownItem, selector: "[ngbDropdownItem]", inputs: ["tabindex", "disabled"] }, { kind: "component", type: HorizontalBarChartComponent, selector: "he-horizontal-bar-chart", inputs: ["tooltipFn", "afterBarDrawSettings"], exportAs: ["horizontalBarChart"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
13482
13462
|
}
|
|
13483
13463
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: ImpactAssessmentsIndicatorBreakdownChartComponent, decorators: [{
|
|
13484
13464
|
type: Component$1,
|
|
13485
|
-
args: [{ selector: 'he-impact-assessments-indicator-breakdown-chart', changeDetection: ChangeDetectionStrategy.OnPush, imports: [HESvgIconComponent, FormsModule,
|
|
13486
|
-
}], ctorParameters: () => [], propDecorators: { impactAssessment: [{ type: i0.Input, args: [{ isSignal: true, alias: "impactAssessment", required: true }] }], indicators: [{ type: i0.Input, args: [{ isSignal: true, alias: "indicators", required: false }] }]
|
|
13465
|
+
args: [{ selector: 'he-impact-assessments-indicator-breakdown-chart', changeDetection: ChangeDetectionStrategy.OnPush, imports: [HESvgIconComponent, FormsModule, NgbDropdownModule, HorizontalBarChartComponent], template: "<div class=\"is-mb-3\">\n <ng-content />\n</div>\n\n@if (logsResource.isLoading()) {\n <div class=\"has-text-center py-3\">\n <he-svg-icon name=\"loading\" animation=\"spin\" size=\"40\" />\n </div>\n} @else if (terms()?.length) {\n <div class=\"is-flex is-align-items-center is-gap-12 is-mb-2 | breakdown-actions-table\">\n @if (terms()?.length) {\n <div class=\"control is-expanded is-flex-grow-1\">\n <div class=\"select is-fullwidth is-small\">\n <select [(ngModel)]=\"selectedTermId\" name=\"selectedTermId\">\n @for (term of terms(); track term) {\n <option [value]=\"term['@id']\">{{ term.name }}</option>\n }\n </select>\n </div>\n </div>\n }\n @if (methods()?.length) {\n <div class=\"control is-expanded is-flex-shrink-0\">\n <div class=\"select is-fullwidth is-small\">\n <select [(ngModel)]=\"selectedMethodId\" name=\"selectedMethodId\">\n @if (methods().length > 1) {\n <option [ngValue]=\"undefined\">Filter Model</option>\n }\n @for (term of methods(); track term) {\n <option [value]=\"term['@id']\">{{ term.name }}</option>\n }\n </select>\n </div>\n </div>\n }\n\n <div class=\"is-flex is-justify-content-space-between w-100\">\n <div ngbDropdown #optionDd=\"ngbDropdown\" container=\"body\" placement=\"bottom-end\">\n <button\n ngbDropdownToggle\n class=\"button is-small\"\n type=\"button\"\n aria-haspopup=\"true\"\n aria-controls=\"download-menu\">\n <span class=\"is-pr-1 is-align-middle\">Download</span>\n <he-svg-icon name=\"chevron-down\" aria-hidden=\"true\" />\n </button>\n <div ngbDropdownMenu id=\"download-menu\" role=\"menu\">\n <div class=\"dropdown-content\">\n <a ngbDropdownItem (click)=\"chart.exportAsSvg({ lollipopConfig: {} })\">\n <he-svg-icon size=\"20\" name=\"chart\" />\n <span class=\"is-pl-2 is-size-7\">Chart Image (.svg)</span>\n </a>\n\n <a ngbDropdownItem [href]=\"csvContent()\" [download]=\"downloadFilename()\">\n <he-svg-icon size=\"20\" name=\"table\" />\n <span class=\"is-pl-2 is-size-7\">Chart Data (.csv)</span>\n </a>\n </div>\n </div>\n </div>\n\n <div class=\"field is-relative is-mb-0 is-hidden-tablet\">\n <input\n type=\"checkbox\"\n class=\"switch is-small is-rounded is-secondary\"\n id=\"displayValue\"\n name=\"displayValue\"\n [(ngModel)]=\"displayValue\" />\n <label for=\"displayValue\">Show numerical value</label>\n </div>\n </div>\n </div>\n}\n\n@if (!logsResource.isLoading() && noData()) {\n <div class=\"chart-area-border\">\n <p class=\"has-text-centered\">\n <span>No breakdown available for</span>\n @if (selectedTerm()) {\n <span class=\"is-pl-1\">{{ selectedTerm().name }}</span>\n }\n @if (selectedMethod()) {\n <span class=\"is-pl-1\">({{ selectedMethod().name }})</span>\n }\n <span>.</span>\n </p>\n </div>\n}\n\n<he-horizontal-bar-chart\n #chart=\"horizontalBarChart\"\n class=\"is-relative h-100\"\n [title]=\"selectedTerm()?.units\"\n [data]=\"chartData()\"\n [max]=\"total()\"\n [maximumValues]=\"maximumValues()\"\n [showExportButton]=\"false\"\n [showNegativeValues]=\"false\"\n [tooltipFn]=\"chartTooltipFn\"\n [afterBarDrawSettings]=\"afterBarDrawSettings()\" />\n", styles: [":host{display:block;overflow:visible}.shadow-tooltip{width:1px;height:1px;pointer-events:none}he-horizontal-bar-chart ::ng-deep .chart-container{min-height:400px}@media screen and (max-width: 767px){he-horizontal-bar-chart ::ng-deep .chart-container{min-height:200px}}@media screen and (max-width: 767px){.chart-area-border{padding:0}}@media screen and (max-width: 767px){.breakdown-actions-table{flex-direction:column;align-items:flex-start!important}}.breakdown-legend{background:#fafafa}.breakdown-legend--color{width:8px;height:8px;border-radius:50%}\n"] }]
|
|
13466
|
+
}], ctorParameters: () => [], propDecorators: { impactAssessment: [{ type: i0.Input, args: [{ isSignal: true, alias: "impactAssessment", required: true }] }], indicators: [{ type: i0.Input, args: [{ isSignal: true, alias: "indicators", required: false }] }] } });
|
|
13487
13467
|
|
|
13488
13468
|
const impactValue = (impact, values) => (values[impact['@id']]?.nodes[0] || { value: 0 }).value;
|
|
13489
13469
|
const impactName = (impact, index) => `${index + 1}. ${defaultLabel(impact)}`;
|
|
@@ -13501,42 +13481,12 @@ class ImpactAssessmentsIndicatorsChartComponent {
|
|
|
13501
13481
|
.map(({ term }) => term)
|
|
13502
13482
|
.sort((a, b) => a.name.localeCompare(b.name)), ...(ngDevMode ? [{ debugName: "terms" }] : []));
|
|
13503
13483
|
this.selectedTerm = signal(undefined, ...(ngDevMode ? [{ debugName: "selectedTerm" }] : []));
|
|
13504
|
-
this.labels = computed(() => this.impactAssessments().map(impactName), ...(ngDevMode ? [{ debugName: "labels" }] : []));
|
|
13505
|
-
this.colors = computed(() => this.impactAssessments().map(listColor), ...(ngDevMode ? [{ debugName: "colors" }] : []));
|
|
13506
13484
|
this.values = computed(() => this.indicatorPerImpactAssessment()?.[this.selectedTerm()?.name]?.values || {}, ...(ngDevMode ? [{ debugName: "values" }] : []));
|
|
13507
|
-
this.
|
|
13508
|
-
|
|
13509
|
-
|
|
13510
|
-
|
|
13511
|
-
|
|
13512
|
-
borderColor: this.colors(),
|
|
13513
|
-
barThickness: 2,
|
|
13514
|
-
barPercentage: 1,
|
|
13515
|
-
categoryPercentage: 1
|
|
13516
|
-
}
|
|
13517
|
-
], ...(ngDevMode ? [{ debugName: "datasets" }] : []));
|
|
13518
|
-
this.chartConfig = computed(() => ({
|
|
13519
|
-
plugins: [
|
|
13520
|
-
lollipopChartPlugin(),
|
|
13521
|
-
afterBarDrawPlugin({
|
|
13522
|
-
xPosFn: (x, index, width, chart) => (x || chart.scales['x-axis-0'].getPixelForValue(0)) + 10,
|
|
13523
|
-
textFn: ({ data }) => `${data}`,
|
|
13524
|
-
colorFn: (m, index, chart, data) => (isUndefined(data) ? '#b5b5b5' : '#4a4a4a'),
|
|
13525
|
-
emptyValueLabel: 'No value'
|
|
13526
|
-
})
|
|
13527
|
-
],
|
|
13528
|
-
options: {
|
|
13529
|
-
scales: {
|
|
13530
|
-
xAxes: [
|
|
13531
|
-
{
|
|
13532
|
-
scaleLabel: {
|
|
13533
|
-
labelString: this.selectedTerm()?.units
|
|
13534
|
-
}
|
|
13535
|
-
}
|
|
13536
|
-
]
|
|
13537
|
-
}
|
|
13538
|
-
}
|
|
13539
|
-
}), ...(ngDevMode ? [{ debugName: "chartConfig" }] : []));
|
|
13485
|
+
this.chartData = computed(() => this.impactAssessments().map((impact, index) => ({
|
|
13486
|
+
label: impactName(impact, index),
|
|
13487
|
+
count: impactValue(impact, this.values()),
|
|
13488
|
+
color: listColor(impact, index)
|
|
13489
|
+
})), ...(ngDevMode ? [{ debugName: "chartData" }] : []));
|
|
13540
13490
|
effect(() => {
|
|
13541
13491
|
// make sure selected term exists
|
|
13542
13492
|
const terms = this.terms();
|
|
@@ -13551,11 +13501,11 @@ class ImpactAssessmentsIndicatorsChartComponent {
|
|
|
13551
13501
|
this.selectedTerm.set(term);
|
|
13552
13502
|
}
|
|
13553
13503
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: ImpactAssessmentsIndicatorsChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
13554
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.13", type: ImpactAssessmentsIndicatorsChartComponent, isStandalone: true, selector: "he-impact-assessments-indicators-chart", inputs: { key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: false, transformFunction: null }, filterTermTypes: { classPropertyName: "filterTermTypes", publicName: "filterTermTypes", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"is-flex is-gap-8 is-justify-content-space-between is-align-items-center is-mb-3\">\n <button
|
|
13504
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.13", type: ImpactAssessmentsIndicatorsChartComponent, isStandalone: true, selector: "he-impact-assessments-indicators-chart", inputs: { key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: false, transformFunction: null }, filterTermTypes: { classPropertyName: "filterTermTypes", publicName: "filterTermTypes", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"is-flex is-gap-8 is-justify-content-space-between is-align-items-center is-mb-3\">\n <he-chart-export-button [chart]=\"chart\" [config]=\"{ lollipopConfig: {} }\" />\n\n <ng-content />\n</div>\n\n@if (terms()?.length) {\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"selectTerm($event)\" id=\"selectTerm\">\n @for (term of terms(); track term) {\n <option [value]=\"term['@id']\">{{ term.name }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n}\n\n<he-horizontal-bar-chart\n #chart=\"horizontalBarChart\"\n class=\"is-relative h-100\"\n [title]=\"selectedTerm()?.units\"\n [data]=\"chartData()\"\n [showExportButton]=\"false\" />\n", styles: [":host{display:block;overflow:visible}he-horizontal-bar-chart ::ng-deep .chart-container{min-height:400px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "component", type: HorizontalBarChartComponent, selector: "he-horizontal-bar-chart", inputs: ["tooltipFn", "afterBarDrawSettings"], exportAs: ["horizontalBarChart"] }, { kind: "component", type: ChartExportButtonComponent, selector: "he-chart-export-button", inputs: ["chart", "config"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
13555
13505
|
}
|
|
13556
13506
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: ImpactAssessmentsIndicatorsChartComponent, decorators: [{
|
|
13557
13507
|
type: Component$1,
|
|
13558
|
-
args: [{ selector: 'he-impact-assessments-indicators-chart', changeDetection: ChangeDetectionStrategy.OnPush, imports: [FormsModule,
|
|
13508
|
+
args: [{ selector: 'he-impact-assessments-indicators-chart', changeDetection: ChangeDetectionStrategy.OnPush, imports: [FormsModule, HorizontalBarChartComponent, ChartExportButtonComponent], template: "<div class=\"is-flex is-gap-8 is-justify-content-space-between is-align-items-center is-mb-3\">\n <he-chart-export-button [chart]=\"chart\" [config]=\"{ lollipopConfig: {} }\" />\n\n <ng-content />\n</div>\n\n@if (terms()?.length) {\n <div class=\"field\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select (change)=\"selectTerm($event)\" id=\"selectTerm\">\n @for (term of terms(); track term) {\n <option [value]=\"term['@id']\">{{ term.name }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n}\n\n<he-horizontal-bar-chart\n #chart=\"horizontalBarChart\"\n class=\"is-relative h-100\"\n [title]=\"selectedTerm()?.units\"\n [data]=\"chartData()\"\n [showExportButton]=\"false\" />\n", styles: [":host{display:block;overflow:visible}he-horizontal-bar-chart ::ng-deep .chart-container{min-height:400px}\n"] }]
|
|
13559
13509
|
}], ctorParameters: () => [], propDecorators: { key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: false }] }], filterTermTypes: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterTermTypes", required: false }] }] } });
|
|
13560
13510
|
|
|
13561
13511
|
var View$1;
|
|
@@ -13785,8 +13735,7 @@ class InputIndeterminateDirective {
|
|
|
13785
13735
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: InputIndeterminateDirective, decorators: [{
|
|
13786
13736
|
type: Directive,
|
|
13787
13737
|
args: [{
|
|
13788
|
-
selector: 'input[indeterminate]'
|
|
13789
|
-
standalone: true
|
|
13738
|
+
selector: 'input[indeterminate]'
|
|
13790
13739
|
}]
|
|
13791
13740
|
}], ctorParameters: () => [], propDecorators: { indeterminate: [{ type: i0.Input, args: [{ isSignal: true, alias: "indeterminate", required: true }] }] } });
|
|
13792
13741
|
|
|
@@ -13852,8 +13801,7 @@ class FilterAccordionGroupPipe {
|
|
|
13852
13801
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: FilterAccordionGroupPipe, decorators: [{
|
|
13853
13802
|
type: Pipe,
|
|
13854
13803
|
args: [{
|
|
13855
|
-
name: 'filterAccordionGroup'
|
|
13856
|
-
standalone: true
|
|
13804
|
+
name: 'filterAccordionGroup'
|
|
13857
13805
|
}]
|
|
13858
13806
|
}] });
|
|
13859
13807
|
class FilterAccordionComponent extends ControlValueAccessor {
|
|
@@ -14036,8 +13984,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImpo
|
|
|
14036
13984
|
}], ctorParameters: () => [], propDecorators: { showHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "showHeader", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], tooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "tooltip", required: false }] }], showGlobalSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "showGlobalSearch", required: false }] }], globalSearchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "globalSearchPlaceholder", required: false }] }], showClearAll: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClearAll", required: false }] }], preserveOptionsOnSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "preserveOptionsOnSelection", required: false }] }], maintainPanelStates: [{ type: i0.Input, args: [{ isSignal: true, alias: "maintainPanelStates", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], showGroupCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "showGroupCount", required: false }] }], selectionChanged: [{ type: i0.Output, args: ["selectionChanged"] }] } });
|
|
14037
13985
|
|
|
14038
13986
|
const sortedPoints = (values) => Object.entries(values)
|
|
14039
|
-
.map(([x, y]) => ({ x, y }))
|
|
14040
|
-
.sort((a, b) =>
|
|
13987
|
+
.map(([x, y]) => ({ x: new Date(x).getTime(), y }))
|
|
13988
|
+
.sort((a, b) => a.x - b.x);
|
|
14041
13989
|
class SitesManagementChartComponent {
|
|
14042
13990
|
constructor() {
|
|
14043
13991
|
this.nodeService = inject(HeNodeService);
|
|
@@ -14100,26 +14048,18 @@ class SitesManagementChartComponent {
|
|
|
14100
14048
|
type: 'bar',
|
|
14101
14049
|
options: {
|
|
14102
14050
|
scales: {
|
|
14103
|
-
|
|
14104
|
-
|
|
14105
|
-
|
|
14106
|
-
|
|
14107
|
-
|
|
14108
|
-
|
|
14109
|
-
|
|
14110
|
-
|
|
14111
|
-
|
|
14112
|
-
|
|
14113
|
-
|
|
14114
|
-
|
|
14115
|
-
ticks: {
|
|
14116
|
-
min: 0
|
|
14117
|
-
// TODO: not all of them are in %
|
|
14118
|
-
// userCallback: (label: string) => `${label}%`
|
|
14119
|
-
},
|
|
14120
|
-
stacked: true
|
|
14121
|
-
}
|
|
14122
|
-
]
|
|
14051
|
+
x: {
|
|
14052
|
+
type: 'time',
|
|
14053
|
+
time: {
|
|
14054
|
+
unit: 'month'
|
|
14055
|
+
},
|
|
14056
|
+
stacked: true
|
|
14057
|
+
},
|
|
14058
|
+
y: {
|
|
14059
|
+
position: 'left',
|
|
14060
|
+
min: 0,
|
|
14061
|
+
stacked: true
|
|
14062
|
+
}
|
|
14123
14063
|
}
|
|
14124
14064
|
}
|
|
14125
14065
|
};
|
|
@@ -14133,11 +14073,11 @@ class SitesManagementChartComponent {
|
|
|
14133
14073
|
});
|
|
14134
14074
|
}
|
|
14135
14075
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: SitesManagementChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
14136
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.13", type: SitesManagementChartComponent, isStandalone: true, selector: "he-sites-management-chart", inputs: { site: { classPropertyName: "site", publicName: "site", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"is-flex is-gap-8 is-justify-content-space-between is-align-items-center is-mb-3\">\n <
|
|
14076
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.13", type: SitesManagementChartComponent, isStandalone: true, selector: "he-sites-management-chart", inputs: { site: { classPropertyName: "site", publicName: "site", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"is-flex is-gap-8 is-justify-content-space-between is-align-items-center is-mb-3\">\n <he-chart-export-button [chart]=\"chart\" />\n\n <ng-content />\n</div>\n\n@if (termTypes().length > 1) {\n <he-horizontal-buttons-group\n [buttons]=\"termTypeButtons()\"\n [(ngModel)]=\"termTypeModel\"\n styles=\"primary\"\n class=\"is-hidden-mobile\" />\n\n <div class=\"field is-hidden-tablet\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select [(ngModel)]=\"termTypeModel\" if=\"termTypeModel\">\n @for (button of termTypeButtons(); track button.id) {\n <option [value]=\"button.id\">{{ button.name }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n}\n\n<div class=\"chart-area-border\">\n <he-chart #chart=\"chart\" class=\"is-relative\" [data]=\"chartData()\" [config]=\"chartConfig\" [showExportButton]=\"false\" />\n</div>\n\n<div\n class=\"is-flex is-justify-content-center is-align-items-center is-flex-wrap-wrap is-gap-16 is-mt-2 chart-area-border is-legend\">\n @for (color of chartColors() | keyvalue; track color.key) {\n <div class=\"is-flex is-align-items-center is-gap-8\">\n <div class=\"legend-color\" [style.background-color]=\"color.value\"></div>\n <span class=\"is-size-7\">{{ color.key }}</span>\n </div>\n }\n</div>\n", styles: [":host{display:block;overflow:visible}he-chart ::ng-deep .chart-container{min-height:400px}he-horizontal-buttons-group ::ng-deep .tabs-list{border-bottom:none}.legend-container{background:#f5f7f9}.legend-color{width:20px;height:20px;border-radius:3px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ChartComponent, selector: "he-chart", inputs: ["data", "config", "showExportButton"], exportAs: ["chart"] }, { kind: "component", type: ChartExportButtonComponent, selector: "he-chart-export-button", inputs: ["chart", "config"] }, { kind: "component", type: HorizontalButtonsGroupComponent, selector: "he-horizontal-buttons-group", inputs: ["buttons", "defaultSelectedIndex", "removable", "styles"], outputs: ["termRemoved"] }, { kind: "pipe", type: KeyValuePipe, name: "keyvalue" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
14137
14077
|
}
|
|
14138
14078
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: SitesManagementChartComponent, decorators: [{
|
|
14139
14079
|
type: Component$1,
|
|
14140
|
-
args: [{ selector: 'he-sites-management-chart', imports: [FormsModule, KeyValuePipe,
|
|
14080
|
+
args: [{ selector: 'he-sites-management-chart', changeDetection: ChangeDetectionStrategy.OnPush, imports: [FormsModule, KeyValuePipe, ChartComponent, ChartExportButtonComponent, HorizontalButtonsGroupComponent], template: "<div class=\"is-flex is-gap-8 is-justify-content-space-between is-align-items-center is-mb-3\">\n <he-chart-export-button [chart]=\"chart\" />\n\n <ng-content />\n</div>\n\n@if (termTypes().length > 1) {\n <he-horizontal-buttons-group\n [buttons]=\"termTypeButtons()\"\n [(ngModel)]=\"termTypeModel\"\n styles=\"primary\"\n class=\"is-hidden-mobile\" />\n\n <div class=\"field is-hidden-tablet\">\n <div class=\"control is-expanded\">\n <div class=\"select is-small is-fullwidth\">\n <select [(ngModel)]=\"termTypeModel\" if=\"termTypeModel\">\n @for (button of termTypeButtons(); track button.id) {\n <option [value]=\"button.id\">{{ button.name }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n}\n\n<div class=\"chart-area-border\">\n <he-chart #chart=\"chart\" class=\"is-relative\" [data]=\"chartData()\" [config]=\"chartConfig\" [showExportButton]=\"false\" />\n</div>\n\n<div\n class=\"is-flex is-justify-content-center is-align-items-center is-flex-wrap-wrap is-gap-16 is-mt-2 chart-area-border is-legend\">\n @for (color of chartColors() | keyvalue; track color.key) {\n <div class=\"is-flex is-align-items-center is-gap-8\">\n <div class=\"legend-color\" [style.background-color]=\"color.value\"></div>\n <span class=\"is-size-7\">{{ color.key }}</span>\n </div>\n }\n</div>\n", styles: [":host{display:block;overflow:visible}he-chart ::ng-deep .chart-container{min-height:400px}he-horizontal-buttons-group ::ng-deep .tabs-list{border-bottom:none}.legend-container{background:#f5f7f9}.legend-color{width:20px;height:20px;border-radius:3px}\n"] }]
|
|
14141
14081
|
}], ctorParameters: () => [], propDecorators: { site: [{ type: i0.Input, args: [{ isSignal: true, alias: "site", required: true }] }] } });
|
|
14142
14082
|
|
|
14143
14083
|
var View;
|
|
@@ -14320,5 +14260,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImpo
|
|
|
14320
14260
|
* Generated bundle index. Do not edit.
|
|
14321
14261
|
*/
|
|
14322
14262
|
|
|
14323
|
-
export { ARRAY_DELIMITER, ApplyPurePipe, BarChartComponent, BibliographiesSearchConfirmComponent, BlankNodeStateComponent, BlankNodeStateNoticeComponent, BlankNodeValueDeltaComponent, CapitalizePipe, ChartComponent, ChartConfigurationDirective, ClickOutsideDirective, ClipboardComponent, CollapsibleBoxComponent, ColorPalette, CompoundDirective, CompoundPipe, ControlValueAccessor, CycleNodesKeyGroup, CyclesCompletenessComponent, CyclesEmissionsChartComponent, CyclesFunctionalUnitMeasureComponent, CyclesMetadataComponent, CyclesNodesComponent, CyclesNodesTimelineComponent, CyclesResultComponent, DataTableComponent, DefaultPipe, DeltaColour, DistributionChartComponent, DrawerContainerComponent, DurationPipe, EllipsisPipe, EngineModelsLinkComponent, EngineModelsLookupInfoComponent, EngineModelsStageComponent, EngineModelsStageDeepComponent, EngineModelsStageDeepService, EngineModelsVersionLinkComponent, EngineOrchestratorEditComponent, EngineRequirementsFormComponent, FileSizePipe, FilesErrorSummaryComponent, FilesFormComponent, FilesFormEditableComponent, FilesUploadErrorsComponent, FilterAccordionComponent, GUIDE_ENABLED, GetPipe, GlossaryMigrationFormat, GuideOverlayComponent, HESvgIconComponent, HE_API_BASE_URL, HE_CALCULATIONS_BASE_URL, HE_MAP_LOADED, HeAuthService, HeCommonService, HeEngineService, HeGlossaryService, HeMendeleyService, HeNodeCsvService, HeNodeService, HeNodeStoreService, HeSchemaService, HeSearchService, HeToastService, HorizontalButtonsGroupComponent, ImpactAssessmentsGraphComponent, ImpactAssessmentsIndicatorBreakdownChartComponent, ImpactAssessmentsIndicatorsChartComponent, ImpactAssessmentsProductsComponent, IsArrayPipe, IsObjectPipe, IssueConfirmComponent, KeyToLabelPipe, Level, LineChartComponent, LinkKeyValueComponent, LogStatus, LongPressDirective, MAX_RESULTS, MapsDrawingComponent, MapsDrawingConfirmComponent, MendeleySearchResult, MobileShellComponent, NavigationMenuComponent, NoExtPipe, NodeAggregatedComponent, NodeAggregatedInfoComponent, NodeAggregatedQualityScoreComponent, NodeCsvExportConfirmComponent, NodeCsvPreviewComponent, NodeCsvSelectHeadersComponent, NodeIconComponent, NodeJsonldComponent, NodeJsonldSchemaComponent, NodeKeyState, NodeLinkComponent, NodeLogsFileComponent, NodeLogsModelsComponent, NodeLogsTimeComponent, NodeMissingLookupFactorsComponent, NodeQualityScore, NodeRecommendationsComponent, NodeSelectComponent, NodeValueDetailsComponent, PluralizePipe, PopoverComponent, PopoverConfirmComponent, PrecisionPipe, RelatedNodeResult, RemoveMarkdownPipe, RepeatPipe, Repository, ResizedDirective, ResizedEvent, ResponsiveService, SchemaInfoComponent, SchemaVersionLinkComponent, SearchExtendComponent, ShelfDialogComponent, ShellComponent, SitesManagementChartComponent, SitesMapsComponent, SitesNodesComponent, SkeletonTextComponent, SocialTagsComponent, SortByPipe, SortSelectComponent, TagsInputDirective, Template, TermsPropertyContentComponent, TermsSubClassOfContentComponent, TermsUnitsDescriptionComponent, ThousandSuffixesPipe, ThousandsPipe, TimesPipe, ToastComponent, UncapitalizePipe, addPolygonToFeature, afterBarDrawPlugin, allCountriesQuery, allGroups, allOptions, arrayValue, availableProperties, backgroundHoverPlugin, baseApiUrl, baseUrl, bottom, buildSummary, bytesSize, calculateCycleDuration, calculateCycleDurationEnabled, calculateCycleStartDate, calculateCycleStartDateEnabled, capitalize, changelogUrl, clustererImage, code, colorToRgba, compoundToHtml, computeKeys, computeTerms, contactUsEmail, contactUsLink, convertToSvg, coordinatesToPoint, copyObject, countriesQuery, createMarker, cropsQuery, d3ellipse, d3wrap, dataPathLabel, dataPathToKey, defaultFeature, defaultLabel, defaultSuggestionType, defaultSvgIconSize, definitionToSchemaType, distinctUntilChangedDeep, downloadFile, downloadSvg, ellipsis, engineGitBaseUrl, engineGitUrl, errorHasError, errorHasWarning, errorText, evaluateSuccess, exportAsSVG, externalLink, externalNodeLink, fillColor, fillStyle, filterBlankNode$1 as filterBlankNode, filterError, filterParams, findConfigModels, findMatchingModel, findModels, findNodeModel, findOrchestratorModel, findProperty, findPropertyById, flatFilterData, flatFilterNode, formatCustomErrorMessage, formatDate, formatError, formatPropertyError, formatter, getColor, getDatesBetween, gitBranch, gitHome, gitlabRawUrl, glossaryBaseUrl, glossaryLink, groupChanged, groupLogsByModel, groupLogsByTerm, groupNodesByTerm, groupdLogsByKey, grouppedKeys, grouppedValueKeys, groupsLogsByFields, guideModelUrl, guideNamespace, guidePageId, handleAPIError, handleGuideEvent, hasError, hasValidationError, hasWarning, hexToRgba, iconSizes, icons, ignoreKeys$2 as ignoreKeys, initialFilterState, injectResizeEvent$, inputGroupsTermTypes, isAddPropertyEnabled, isChrome, isDateBetween, isEqual, isExternal, isGroupVisible, isKeyClosedVisible, isKeyHidden, isMaxStage, isMethodModelAllowed, isMigrationError, isMissingOneOfError, isMissingPropertyError, isNonNodeModelKey, isSchemaIri, isScrolledBelow, isState, isTermTypeAllowed, isValidKey, keyToDataPath, levels, listColor, listColorContinuous, listColorWithAlpha, loadMapApi, loadSvgSprite, localStorageSignal, locationQuery, logToCsv$1 as logToCsv, logValueArray, logsKey, lollipopChartPlugin, lookupUrl, mapFilterData, mapsUrl, markerIcon, markerPie, matchAggregatedQuery, matchAggregatedValidatedQuery, matchBoolPrefixQuery, matchCountry, matchExactQuery, matchGlobalRegion, matchId, matchNameNormalized, matchNestedKey, matchPhrasePrefixQuery, matchPhraseQuery, matchPrimaryProductQuery, matchQuery, matchRegex, matchRegion, matchTermType, matchType, maxAreaSize, measurementValue, mergeDataWithHeaders, methodTierOrder, migrationErrorMessage, migrationsUrl, missingNodeErrors, modelCount, modelKeyParams, modelParams, models, multiMatchQuery, nestedProperty, nestingEnabled, nestingTypeEnabled, nodeAvailableProperties, nodeById, nodeColours$1 as nodeColours, nodeDataState, nodeId, nodeIds, nodeLink, nodeLinkEnabled, nodeLinkTypeEnabled, nodeLogsUrl, nodeQualityScoreColor, nodeQualityScoreLevel, nodeQualityScoreMaxDefault, nodeQualityScoreOrder, nodeSecondaryColours, nodeToAggregationFilename, nodeType, nodeTypeDataState, nodeTypeIcon, nodeUrl, nodeUrlParams, nodeVersion, nodesByState, nodesByType, numberGte, optionsFromGroup, parentKey, parentProperty, parseColor, parseData, parseDataPath, parseLines, parseMessage$1 as parseMessage, parseNewValue, pluralize, pointToCoordinates, polygonBounds, polygonToCoordinates, polygonToMap, polygonsFromFeature, populateWithTrackIdsFilterData, postGuideEvent, primaryProduct, productsQuery, propertyError, propertyId, recursiveProperties, refToSchemaType, refreshPropertyKeys, regionsQuery, repeat, reportIssueLink, reportIssueUrl, safeJSONParse, safeJSONStringify, schemaBaseUrl, schemaDataBaseUrl, schemaLink, schemaRequiredProperties, schemaTypeToDefaultValue, scrollToEl, scrollTop, searchFilterData, searchableTypes, siblingProperty, singleProperty, siteTooBig, siteTypeToIcon, sortProperties, sortedDates, strokeColor, strokeStyle, suggestMatchQuery, suggestQuery, takeAfterViewInit, termLocation, termLocationName, termProperties, termTypeLabel, toSnakeCase, toThousands, typeToNewProperty, typeaheadFocus, uncapitalize, uniqueDatesBetween, updateProperties, valueTypeToDefault, waitFor, wildcardQuery };
|
|
14263
|
+
export { ARRAY_DELIMITER, ApplyPurePipe, BarChartComponent, BibliographiesSearchConfirmComponent, BlankNodeStateComponent, BlankNodeStateNoticeComponent, BlankNodeValueDeltaComponent, CapitalizePipe, ChartComponent, ChartConfigurationDirective, ClickOutsideDirective, ClipboardComponent, CollapsibleBoxComponent, ColorPalette, CompoundDirective, CompoundPipe, ControlValueAccessor, CycleNodesKeyGroup, CyclesCompletenessComponent, CyclesEmissionsChartComponent, CyclesFunctionalUnitMeasureComponent, CyclesMetadataComponent, CyclesNodesComponent, CyclesNodesTimelineComponent, CyclesResultComponent, DataTableComponent, DefaultPipe, DeltaColour, DistributionChartComponent, DrawerContainerComponent, DurationPipe, EllipsisPipe, EngineModelsLinkComponent, EngineModelsLookupInfoComponent, EngineModelsStageComponent, EngineModelsStageDeepComponent, EngineModelsStageDeepService, EngineModelsVersionLinkComponent, EngineOrchestratorEditComponent, EngineRequirementsFormComponent, FileSizePipe, FileUploadErrorKeys, FilesErrorSummaryComponent, FilesFormComponent, FilesFormEditableComponent, FilesUploadErrorsComponent, FilterAccordionComponent, GUIDE_ENABLED, GetPipe, GlossaryMigrationFormat, GuideOverlayComponent, HESvgIconComponent, HE_API_BASE_URL, HE_CALCULATIONS_BASE_URL, HE_MAP_LOADED, HeAuthService, HeCommonService, HeEngineService, HeGlossaryService, HeMendeleyService, HeNodeCsvService, HeNodeService, HeNodeStoreService, HeSchemaService, HeSearchService, HeToastService, HorizontalBarChartComponent, HorizontalButtonsGroupComponent, ImpactAssessmentsGraphComponent, ImpactAssessmentsIndicatorBreakdownChartComponent, ImpactAssessmentsIndicatorsChartComponent, ImpactAssessmentsProductsComponent, IsArrayPipe, IsObjectPipe, IssueConfirmComponent, KeyToLabelPipe, Level, LineChartComponent, LinkKeyValueComponent, LogStatus, LongPressDirective, MAX_RESULTS, MapsDrawingComponent, MapsDrawingConfirmComponent, MendeleySearchResult, MobileShellComponent, NavigationMenuComponent, NoExtPipe, NodeAggregatedComponent, NodeAggregatedInfoComponent, NodeAggregatedQualityScoreComponent, NodeCsvExportConfirmComponent, NodeCsvPreviewComponent, NodeCsvSelectHeadersComponent, NodeIconComponent, NodeJsonldComponent, NodeJsonldSchemaComponent, NodeKeyState, NodeLinkComponent, NodeLogsFileComponent, NodeLogsModelsComponent, NodeLogsTimeComponent, NodeMissingLookupFactorsComponent, NodeQualityScore, NodeRecommendationsComponent, NodeSelectComponent, NodeValueDetailsComponent, PluralizePipe, PopoverComponent, PopoverConfirmComponent, PrecisionPipe, RelatedNodeResult, RemoveMarkdownPipe, RepeatPipe, Repository, ResizedDirective, ResizedEvent, ResponsiveService, SchemaInfoComponent, SchemaVersionLinkComponent, SearchExtendComponent, ShelfDialogComponent, ShellComponent, SitesManagementChartComponent, SitesMapsComponent, SitesNodesComponent, SkeletonTextComponent, SocialTagsComponent, SortByPipe, SortSelectComponent, TagsInputDirective, Template, TermsPropertyContentComponent, TermsSubClassOfContentComponent, TermsUnitsDescriptionComponent, ThousandSuffixesPipe, ThousandsPipe, TimesPipe, ToastComponent, UncapitalizePipe, addPolygonToFeature, afterBarDrawPlugin, allCountriesQuery, allGroups, allOptions, arrayValue, availableProperties, backgroundHoverPlugin, baseApiUrl, baseUrl, bottom, buildSummary, bytesSize, calculateCycleDuration, calculateCycleDurationEnabled, calculateCycleStartDate, calculateCycleStartDateEnabled, capitalize, changelogUrl, clustererImage, code, colorToRgba, compoundToHtml, computeKeys, computeTerms, contactUsEmail, contactUsLink, convertToSvg, coordinatesToPoint, copyObject, countriesQuery, createMarker, cropsQuery, d3ellipse, d3wrap, dataPathLabel, dataPathToKey, defaultFeature, defaultLabel, defaultSuggestionType, defaultSvgIconSize, definitionToSchemaType, distinctUntilChangedDeep, downloadFile, downloadSvg, ellipsis, engineGitBaseUrl, engineGitUrl, errorHasError, errorHasWarning, errorText, evaluateSuccess, exportAsSVG, externalLink, externalNodeLink, fillColor, fillStyle, filterBlankNode$1 as filterBlankNode, filterError, filterParams, findConfigModels, findMatchingModel, findModels, findNodeModel, findOrchestratorModel, findProperty, findPropertyById, flatFilterData, flatFilterNode, formatCustomErrorMessage, formatDate, formatError, formatPropertyError, formatter, getColor, getDatesBetween, gitBranch, gitHome, gitlabRawUrl, glossaryBaseUrl, glossaryLink, groupChanged, groupLogsByModel, groupLogsByTerm, groupNodesByTerm, groupdLogsByKey, grouppedKeys, grouppedValueKeys, groupsLogsByFields, guideModelUrl, guideNamespace, guidePageId, handleAPIError, handleGuideEvent, hasError, hasValidationError, hasWarning, hexToRgba, iconSizes, icons, ignoreKeys$2 as ignoreKeys, initialFilterState, injectResizeEvent$, inputGroupsTermTypes, isAddPropertyEnabled, isChrome, isDateBetween, isEqual, isExternal, isGroupVisible, isKeyClosedVisible, isKeyHidden, isMaxStage, isMethodModelAllowed, isMigrationError, isMissingOneOfError, isMissingPropertyError, isNonNodeModelKey, isSchemaIri, isScrolledBelow, isState, isTermTypeAllowed, isValidKey, keyToDataPath, levels, listColor, listColorContinuous, listColorWithAlpha, loadMapApi, loadSvgSprite, localStorageSignal, locationQuery, logToCsv$1 as logToCsv, logValueArray, logsKey, lollipopChartPlugin, lookupUrl, mapFilterData, mapsUrl, markerIcon, markerPie, matchAggregatedQuery, matchAggregatedValidatedQuery, matchBoolPrefixQuery, matchCountry, matchExactQuery, matchGlobalRegion, matchId, matchNameNormalized, matchNestedKey, matchPhrasePrefixQuery, matchPhraseQuery, matchPrimaryProductQuery, matchQuery, matchRegex, matchRegion, matchTermType, matchType, maxAreaSize, measurementValue, mergeDataWithHeaders, methodTierOrder, migrationErrorMessage, migrationsUrl, missingNodeErrors, modelCount, modelKeyParams, modelParams, models, multiMatchQuery, nestedProperty, nestingEnabled, nestingTypeEnabled, nodeAvailableProperties, nodeById, nodeColours$1 as nodeColours, nodeDataState, nodeId, nodeIds, nodeLink, nodeLinkEnabled, nodeLinkTypeEnabled, nodeLogsUrl, nodeQualityScoreColor, nodeQualityScoreLevel, nodeQualityScoreMaxDefault, nodeQualityScoreOrder, nodeSecondaryColours, nodeToAggregationFilename, nodeType, nodeTypeDataState, nodeTypeIcon, nodeUrl, nodeUrlParams, nodeVersion, nodesByState, nodesByType, numberGte, optionsFromGroup, parentKey, parentProperty, parseColor, parseData, parseDataPath, parseLines, parseMessage$1 as parseMessage, parseNewValue, pluralize, pointToCoordinates, polygonBounds, polygonToCoordinates, polygonToMap, polygonsFromFeature, populateWithTrackIdsFilterData, postGuideEvent, primaryProduct, productsQuery, propertyError, propertyId, recursiveProperties, refToSchemaType, refreshPropertyKeys, regionsQuery, repeat, reportIssueLink, reportIssueUrl, safeJSONParse, safeJSONStringify, schemaBaseUrl, schemaDataBaseUrl, schemaLink, schemaRequiredProperties, schemaTypeToDefaultValue, scrollToEl, scrollTop, searchFilterData, searchableTypes, siblingProperty, singleProperty, siteTooBig, siteTypeToIcon, sortProperties, sortedDates, strokeColor, strokeStyle, suggestMatchQuery, suggestQuery, takeAfterViewInit, termLocation, termLocationName, termProperties, termTypeLabel, toSnakeCase, toThousands, typeToNewProperty, typeaheadFocus, uncapitalize, uniqueDatesBetween, updateProperties, valueTypeToDefault, waitFor, wildcardQuery };
|
|
14324
14264
|
//# sourceMappingURL=hestia-earth-ui-components.mjs.map
|