@scality/core-ui 0.170.0 → 0.172.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/__mocks__/uuid.js +11 -0
- package/dist/components/barchartv2/Barchart.component.d.ts.map +1 -1
- package/dist/components/barchartv2/Barchart.component.js +4 -4
- package/dist/components/barchartv2/BarchartTooltip.d.ts +11 -0
- package/dist/components/barchartv2/BarchartTooltip.d.ts.map +1 -0
- package/dist/components/barchartv2/BarchartTooltip.js +27 -0
- package/dist/components/chartlegend/ChartLegend.d.ts +3 -1
- package/dist/components/chartlegend/ChartLegend.d.ts.map +1 -1
- package/dist/components/chartlegend/ChartLegend.js +2 -2
- package/dist/components/chartlegend/ChartLegendWrapper.d.ts +3 -1
- package/dist/components/chartlegend/ChartLegendWrapper.d.ts.map +1 -1
- package/dist/components/chartlegend/ChartLegendWrapper.js +43 -9
- package/dist/components/charttooltip/ChartTooltip.d.ts +13 -0
- package/dist/components/charttooltip/ChartTooltip.d.ts.map +1 -0
- package/dist/components/charttooltip/ChartTooltip.js +49 -0
- package/dist/components/globalhealthbar/GlobalHealthBar.component.d.ts +4 -0
- package/dist/components/globalhealthbar/GlobalHealthBar.component.d.ts.map +1 -1
- package/dist/components/globalhealthbar/GlobalHealthBar.component.js +4 -0
- package/dist/components/globalhealthbar/GlobalHealthBarRecharts.component.d.ts +10 -0
- package/dist/components/globalhealthbar/GlobalHealthBarRecharts.component.d.ts.map +1 -0
- package/dist/components/globalhealthbar/GlobalHealthBarRecharts.component.js +78 -0
- package/dist/components/globalhealthbar/components/GlobalHealthBarTooltip.d.ts +18 -0
- package/dist/components/globalhealthbar/components/GlobalHealthBarTooltip.d.ts.map +1 -0
- package/dist/components/globalhealthbar/components/GlobalHealthBarTooltip.js +95 -0
- package/dist/components/globalhealthbar/components/HealthBarXAxis.d.ts +7 -0
- package/dist/components/globalhealthbar/components/HealthBarXAxis.d.ts.map +1 -0
- package/dist/components/globalhealthbar/components/HealthBarXAxis.js +25 -0
- package/dist/components/globalhealthbar/healthBarUtils.d.ts +77 -0
- package/dist/components/globalhealthbar/healthBarUtils.d.ts.map +1 -0
- package/dist/components/globalhealthbar/healthBarUtils.js +196 -0
- package/dist/components/globalhealthbar/healthBarUtils.spec.d.ts +2 -0
- package/dist/components/globalhealthbar/healthBarUtils.spec.d.ts.map +1 -0
- package/dist/components/globalhealthbar/healthBarUtils.spec.js +391 -0
- package/dist/components/globalhealthbar/useHealthBarData.d.ts +18 -0
- package/dist/components/globalhealthbar/useHealthBarData.d.ts.map +1 -0
- package/dist/components/globalhealthbar/useHealthBarData.js +46 -0
- package/dist/components/globalhealthbar/useHealthBarData.spec.d.ts +2 -0
- package/dist/components/globalhealthbar/useHealthBarData.spec.d.ts.map +1 -0
- package/dist/components/globalhealthbar/useHealthBarData.spec.js +207 -0
- package/dist/components/icon/Icon.component.d.ts +2 -0
- package/dist/components/icon/Icon.component.d.ts.map +1 -1
- package/dist/components/icon/Icon.component.js +2 -0
- package/dist/components/linetemporalchart/ChartUtil.d.ts.map +1 -1
- package/dist/components/linetemporalchart/ChartUtil.js +12 -0
- package/dist/components/linetimeseriechart/linetimeseriechart.component.d.ts +8 -5
- package/dist/components/linetimeseriechart/linetimeseriechart.component.d.ts.map +1 -1
- package/dist/components/linetimeseriechart/linetimeseriechart.component.js +95 -100
- package/dist/components/sparkline/sparkline.component.d.ts +16 -0
- package/dist/components/sparkline/sparkline.component.d.ts.map +1 -0
- package/dist/components/sparkline/sparkline.component.js +20 -0
- package/dist/components/text/Text.component.d.ts +2 -1
- package/dist/components/text/Text.component.d.ts.map +1 -1
- package/dist/components/text/Text.component.js +6 -1
- package/dist/next.d.ts +4 -2
- package/dist/next.d.ts.map +1 -1
- package/dist/next.js +4 -2
- package/package.json +4 -2
- package/src/lib/components/barchartv2/Barchart.component.tsx +5 -4
- package/src/lib/components/barchartv2/{ChartTooltip.test.tsx → BarchartTooltip.test.tsx} +35 -12
- package/src/lib/components/barchartv2/BarchartTooltip.tsx +89 -0
- package/src/lib/components/chartlegend/ChartLegend.tsx +4 -2
- package/src/lib/components/chartlegend/ChartLegendWrapper.test.tsx +197 -0
- package/src/lib/components/chartlegend/ChartLegendWrapper.tsx +65 -9
- package/src/lib/components/charttooltip/ChartTooltip.tsx +83 -0
- package/src/lib/components/globalhealthbar/GlobalHealthBar.component.tsx +4 -1
- package/src/lib/components/globalhealthbar/GlobalHealthBarRecharts.component.tsx +203 -0
- package/src/lib/components/globalhealthbar/components/GlobalHealthBarTooltip.tsx +173 -0
- package/src/lib/components/globalhealthbar/components/HealthBarXAxis.tsx +94 -0
- package/src/lib/components/globalhealthbar/healthBarUtils.spec.ts +701 -0
- package/src/lib/components/globalhealthbar/healthBarUtils.ts +311 -0
- package/src/lib/components/globalhealthbar/useHealthBarData.spec.tsx +487 -0
- package/src/lib/components/globalhealthbar/useHealthBarData.ts +74 -0
- package/src/lib/components/icon/Icon.component.tsx +2 -0
- package/src/lib/components/linetemporalchart/ChartUtil.ts +26 -0
- package/src/lib/components/linetimeseriechart/linetimeseriechart.component.tsx +272 -229
- package/src/lib/components/sparkline/sparkline.component.tsx +54 -0
- package/src/lib/components/text/Text.component.tsx +15 -2
- package/src/lib/next.ts +12 -2
- package/stories/BarChart/barchart.stories.tsx +7 -1
- package/stories/GlobalHealthBar/globalhealthbarRecharts.stories.tsx +145 -0
- package/stories/GlobalHealthBar/globalheathbarrecharts.guideline.mdx +5 -0
- package/stories/InlineInput/InlineInput.stories.tsx +7 -1
- package/stories/globalhealthbar.stories.tsx +25 -5
- package/stories/linetimeseriechart.stories.tsx +217 -1
- package/stories/sparkline.stories.tsx +168 -0
- package/dist/components/barchartv2/ChartTooltip.d.ts +0 -14
- package/dist/components/barchartv2/ChartTooltip.d.ts.map +0 -1
- package/dist/components/barchartv2/ChartTooltip.js +0 -41
- package/src/lib/components/barchartv2/ChartTooltip.tsx +0 -106
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { useHealthBarData } from './useHealthBarData';
|
|
2
|
+
import { renderHook } from '@testing-library/react';
|
|
3
|
+
describe('useHealthBarData', () => {
|
|
4
|
+
const mockTimestamp = {
|
|
5
|
+
start: new Date('2023-12-01T00:00:00Z').getTime(),
|
|
6
|
+
end: new Date('2023-12-01T12:00:00Z').getTime(),
|
|
7
|
+
};
|
|
8
|
+
const createMockAlert = (severity, startsAt, endsAt, description = 'Test alert') => ({
|
|
9
|
+
description,
|
|
10
|
+
severity,
|
|
11
|
+
startsAt,
|
|
12
|
+
endsAt,
|
|
13
|
+
});
|
|
14
|
+
describe('Alert Filtering', () => {
|
|
15
|
+
it('should include alerts that are completely within the time range', () => {
|
|
16
|
+
const alerts = [
|
|
17
|
+
createMockAlert('critical', '2023-12-01T02:00:00Z', '2023-12-01T04:00:00Z'),
|
|
18
|
+
createMockAlert('warning', '2023-12-01T06:00:00Z', '2023-12-01T08:00:00Z'),
|
|
19
|
+
];
|
|
20
|
+
const { result } = renderHook(() => useHealthBarData(alerts, mockTimestamp.start, mockTimestamp.end, 'test-id'));
|
|
21
|
+
expect(result.current.chartData[0]).toHaveProperty('critical_0');
|
|
22
|
+
expect(result.current.chartData[0]).toHaveProperty('warning_1');
|
|
23
|
+
expect(result.current.alertKeys.criticalKeys).toContain('critical_0');
|
|
24
|
+
expect(result.current.alertKeys.warningKeys).toContain('warning_1');
|
|
25
|
+
});
|
|
26
|
+
it('should include alerts that start before and end within the time range', () => {
|
|
27
|
+
const alerts = [
|
|
28
|
+
createMockAlert('critical', '2023-11-30T22:00:00Z', '2023-12-01T04:00:00Z'),
|
|
29
|
+
];
|
|
30
|
+
const { result } = renderHook(() => useHealthBarData(alerts, mockTimestamp.start, mockTimestamp.end, 'test-id'));
|
|
31
|
+
expect(result.current.chartData[0]).toHaveProperty('critical_0');
|
|
32
|
+
expect(result.current.alertKeys.criticalKeys).toContain('critical_0');
|
|
33
|
+
});
|
|
34
|
+
it('should include alerts that start within and end after the time range', () => {
|
|
35
|
+
const alerts = [
|
|
36
|
+
createMockAlert('warning', '2023-12-01T10:00:00Z', '2023-12-01T14:00:00Z'),
|
|
37
|
+
];
|
|
38
|
+
const { result } = renderHook(() => useHealthBarData(alerts, mockTimestamp.start, mockTimestamp.end, 'test-id'));
|
|
39
|
+
expect(result.current.chartData[0]).toHaveProperty('warning_0');
|
|
40
|
+
expect(result.current.alertKeys.warningKeys).toContain('warning_0');
|
|
41
|
+
});
|
|
42
|
+
it('should include alerts that span the entire time range', () => {
|
|
43
|
+
const alerts = [
|
|
44
|
+
createMockAlert('critical', '2023-11-30T20:00:00Z', '2023-12-01T16:00:00Z'),
|
|
45
|
+
];
|
|
46
|
+
const { result } = renderHook(() => useHealthBarData(alerts, mockTimestamp.start, mockTimestamp.end, 'test-id'));
|
|
47
|
+
expect(result.current.chartData[0]).toHaveProperty('critical_0');
|
|
48
|
+
expect(result.current.alertKeys.criticalKeys).toContain('critical_0');
|
|
49
|
+
});
|
|
50
|
+
it('should exclude alerts that are completely before the time range', () => {
|
|
51
|
+
const alerts = [
|
|
52
|
+
createMockAlert('warning', '2023-11-30T10:00:00Z', '2023-11-30T20:00:00Z'),
|
|
53
|
+
];
|
|
54
|
+
const { result } = renderHook(() => useHealthBarData(alerts, mockTimestamp.start, mockTimestamp.end, 'test-id'));
|
|
55
|
+
expect(result.current.chartData[0]).not.toHaveProperty('warning_0');
|
|
56
|
+
expect(result.current.alertKeys.warningKeys).toHaveLength(0);
|
|
57
|
+
});
|
|
58
|
+
it('should exclude alerts that are completely after the time range', () => {
|
|
59
|
+
const alerts = [
|
|
60
|
+
createMockAlert('critical', '2023-12-01T14:00:00Z', '2023-12-01T18:00:00Z'),
|
|
61
|
+
];
|
|
62
|
+
const { result } = renderHook(() => useHealthBarData(alerts, mockTimestamp.start, mockTimestamp.end, 'test-id'));
|
|
63
|
+
expect(result.current.chartData[0]).not.toHaveProperty('critical_0');
|
|
64
|
+
expect(result.current.alertKeys.criticalKeys).toHaveLength(0);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
describe('Data Transformation', () => {
|
|
68
|
+
it('should create correct data structure with basic properties', () => {
|
|
69
|
+
const alerts = [
|
|
70
|
+
createMockAlert('warning', '2023-12-01T02:00:00Z', '2023-12-01T04:00:00Z'),
|
|
71
|
+
];
|
|
72
|
+
const { result } = renderHook(() => useHealthBarData(alerts, mockTimestamp.start, mockTimestamp.end, 'test-id'));
|
|
73
|
+
const data = result.current.chartData[0];
|
|
74
|
+
expect(data.range).toEqual([mockTimestamp.start, mockTimestamp.end]);
|
|
75
|
+
});
|
|
76
|
+
it('should create correct alert data keys with timestamps', () => {
|
|
77
|
+
const alerts = [
|
|
78
|
+
createMockAlert('critical', '2023-12-01T02:00:00Z', '2023-12-01T04:00:00Z'),
|
|
79
|
+
];
|
|
80
|
+
const { result } = renderHook(() => useHealthBarData(alerts, mockTimestamp.start, mockTimestamp.end, 'test-id'));
|
|
81
|
+
const data = result.current.chartData[0];
|
|
82
|
+
const expectedStartTime = new Date('2023-12-01T02:00:00Z').getTime();
|
|
83
|
+
const expectedEndTime = new Date('2023-12-01T04:00:00Z').getTime();
|
|
84
|
+
expect(data['critical_0']).toEqual([expectedStartTime, expectedEndTime]);
|
|
85
|
+
});
|
|
86
|
+
it('should create alert metadata with correct structure', () => {
|
|
87
|
+
const alerts = [
|
|
88
|
+
createMockAlert('warning', '2023-12-01T02:00:00Z', '2023-12-01T04:00:00Z', 'Test warning'),
|
|
89
|
+
];
|
|
90
|
+
const { result } = renderHook(() => useHealthBarData(alerts, mockTimestamp.start, mockTimestamp.end, 'test-id'));
|
|
91
|
+
expect(result.current.alertsMap['warning_0']).toEqual({
|
|
92
|
+
description: 'Test warning',
|
|
93
|
+
severity: 'warning',
|
|
94
|
+
startsAt: '2023-12-01T02:00:00Z',
|
|
95
|
+
endsAt: '2023-12-01T04:00:00Z',
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
it('should handle multiple alerts with correct indexing', () => {
|
|
99
|
+
const alerts = [
|
|
100
|
+
createMockAlert('warning', '2023-12-01T01:00:00Z', '2023-12-01T02:00:00Z'),
|
|
101
|
+
createMockAlert('critical', '2023-12-01T03:00:00Z', '2023-12-01T04:00:00Z'),
|
|
102
|
+
createMockAlert('warning', '2023-12-01T05:00:00Z', '2023-12-01T06:00:00Z'),
|
|
103
|
+
];
|
|
104
|
+
const { result } = renderHook(() => useHealthBarData(alerts, mockTimestamp.start, mockTimestamp.end, 'test-id'));
|
|
105
|
+
const data = result.current.chartData[0];
|
|
106
|
+
expect(data).toHaveProperty('warning_0');
|
|
107
|
+
expect(data).toHaveProperty('critical_1');
|
|
108
|
+
expect(data).toHaveProperty('warning_2');
|
|
109
|
+
expect(result.current.alertsMap).toHaveProperty('warning_0');
|
|
110
|
+
expect(result.current.alertsMap).toHaveProperty('critical_1');
|
|
111
|
+
expect(result.current.alertsMap).toHaveProperty('warning_2');
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
describe('Alert Key Categorization', () => {
|
|
115
|
+
it('should categorize alert keys by severity', () => {
|
|
116
|
+
const alerts = [
|
|
117
|
+
createMockAlert('warning', '2023-12-01T01:00:00Z', '2023-12-01T02:00:00Z'),
|
|
118
|
+
createMockAlert('critical', '2023-12-01T03:00:00Z', '2023-12-01T04:00:00Z'),
|
|
119
|
+
createMockAlert('warning', '2023-12-01T05:00:00Z', '2023-12-01T06:00:00Z'),
|
|
120
|
+
createMockAlert('critical', '2023-12-01T07:00:00Z', '2023-12-01T08:00:00Z'),
|
|
121
|
+
];
|
|
122
|
+
const { result } = renderHook(() => useHealthBarData(alerts, mockTimestamp.start, mockTimestamp.end, 'test-id'));
|
|
123
|
+
expect(result.current.alertKeys.warningKeys).toEqual([
|
|
124
|
+
'warning_0',
|
|
125
|
+
'warning_2',
|
|
126
|
+
]);
|
|
127
|
+
expect(result.current.alertKeys.criticalKeys).toEqual([
|
|
128
|
+
'critical_1',
|
|
129
|
+
'critical_3',
|
|
130
|
+
]);
|
|
131
|
+
expect(result.current.alertKeys.unavailableKeys).toEqual([]);
|
|
132
|
+
});
|
|
133
|
+
it('should handle only warning alerts', () => {
|
|
134
|
+
const alerts = [
|
|
135
|
+
createMockAlert('warning', '2023-12-01T01:00:00Z', '2023-12-01T02:00:00Z'),
|
|
136
|
+
createMockAlert('warning', '2023-12-01T03:00:00Z', '2023-12-01T04:00:00Z'),
|
|
137
|
+
];
|
|
138
|
+
const { result } = renderHook(() => useHealthBarData(alerts, mockTimestamp.start, mockTimestamp.end, 'test-id'));
|
|
139
|
+
expect(result.current.alertKeys.warningKeys).toEqual([
|
|
140
|
+
'warning_0',
|
|
141
|
+
'warning_1',
|
|
142
|
+
]);
|
|
143
|
+
expect(result.current.alertKeys.criticalKeys).toEqual([]);
|
|
144
|
+
expect(result.current.alertKeys.unavailableKeys).toEqual([]);
|
|
145
|
+
});
|
|
146
|
+
it('should handle only critical alerts', () => {
|
|
147
|
+
const alerts = [
|
|
148
|
+
createMockAlert('critical', '2023-12-01T01:00:00Z', '2023-12-01T02:00:00Z'),
|
|
149
|
+
createMockAlert('critical', '2023-12-01T03:00:00Z', '2023-12-01T04:00:00Z'),
|
|
150
|
+
];
|
|
151
|
+
const { result } = renderHook(() => useHealthBarData(alerts, mockTimestamp.start, mockTimestamp.end, 'test-id'));
|
|
152
|
+
expect(result.current.alertKeys.warningKeys).toEqual([]);
|
|
153
|
+
expect(result.current.alertKeys.criticalKeys).toEqual([
|
|
154
|
+
'critical_0',
|
|
155
|
+
'critical_1',
|
|
156
|
+
]);
|
|
157
|
+
expect(result.current.alertKeys.unavailableKeys).toEqual([]);
|
|
158
|
+
});
|
|
159
|
+
it('should only include alert bar keys and exclude metadata and basic properties', () => {
|
|
160
|
+
const alerts = [
|
|
161
|
+
createMockAlert('warning', '2023-12-01T01:00:00Z', '2023-12-01T02:00:00Z'),
|
|
162
|
+
];
|
|
163
|
+
const { result } = renderHook(() => useHealthBarData(alerts, mockTimestamp.start, mockTimestamp.end, 'test-id'));
|
|
164
|
+
// Should only contain the actual alert bar keys for rendering
|
|
165
|
+
expect(result.current.alertKeys.warningKeys).toEqual(['warning_0']);
|
|
166
|
+
// Should not contain basic data properties
|
|
167
|
+
expect(result.current.alertKeys.warningKeys).not.toContain('start');
|
|
168
|
+
expect(result.current.alertKeys.warningKeys).not.toContain('end');
|
|
169
|
+
expect(result.current.alertKeys.warningKeys).not.toContain('range');
|
|
170
|
+
expect(result.current.alertKeys.warningKeys).not.toContain('id');
|
|
171
|
+
// Should not contain alert metadata keys (used for tooltips, not bars)
|
|
172
|
+
expect(result.current.alertKeys.warningKeys).not.toContain('alert_warning_0');
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
describe('Edge Cases', () => {
|
|
176
|
+
it('should handle empty alerts array', () => {
|
|
177
|
+
const { result } = renderHook(() => useHealthBarData([], mockTimestamp.start, mockTimestamp.end, 'test-id'));
|
|
178
|
+
const data = result.current.chartData[0];
|
|
179
|
+
expect(data.range).toEqual([mockTimestamp.start, mockTimestamp.end]);
|
|
180
|
+
expect(result.current.alertKeys.warningKeys).toEqual([]);
|
|
181
|
+
expect(result.current.alertKeys.criticalKeys).toEqual([]);
|
|
182
|
+
expect(result.current.alertKeys.unavailableKeys).toEqual([]);
|
|
183
|
+
});
|
|
184
|
+
it('should handle overlapping alerts correctly', () => {
|
|
185
|
+
const alerts = [
|
|
186
|
+
createMockAlert('warning', '2023-12-01T01:00:00Z', '2023-12-01T04:00:00Z'),
|
|
187
|
+
createMockAlert('critical', '2023-12-01T02:00:00Z', '2023-12-01T05:00:00Z'),
|
|
188
|
+
];
|
|
189
|
+
const { result } = renderHook(() => useHealthBarData(alerts, mockTimestamp.start, mockTimestamp.end, 'test-id'));
|
|
190
|
+
expect(result.current.chartData[0]).toHaveProperty('warning_0');
|
|
191
|
+
expect(result.current.chartData[0]).toHaveProperty('critical_1');
|
|
192
|
+
expect(result.current.alertKeys.warningKeys).toContain('warning_0');
|
|
193
|
+
expect(result.current.alertKeys.criticalKeys).toContain('critical_1');
|
|
194
|
+
});
|
|
195
|
+
it('should handle alerts with same timestamps', () => {
|
|
196
|
+
const alerts = [
|
|
197
|
+
createMockAlert('warning', '2023-12-01T02:00:00Z', '2023-12-01T04:00:00Z'),
|
|
198
|
+
createMockAlert('critical', '2023-12-01T02:00:00Z', '2023-12-01T04:00:00Z'),
|
|
199
|
+
];
|
|
200
|
+
const { result } = renderHook(() => useHealthBarData(alerts, mockTimestamp.start, mockTimestamp.end, 'test-id'));
|
|
201
|
+
expect(result.current.chartData[0]).toHaveProperty('warning_0');
|
|
202
|
+
expect(result.current.chartData[0]).toHaveProperty('critical_1');
|
|
203
|
+
expect(result.current.alertKeys.warningKeys).toContain('warning_0');
|
|
204
|
+
expect(result.current.alertKeys.criticalKeys).toContain('critical_1');
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Icon.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/icon/Icon.component.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mCAAmC,CAAC;AAE7D,OAAO,EACL,aAAa,EAKd,MAAM,OAAO,CAAC;AAEf,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAOhD,eAAO,MAAM,SAAS
|
|
1
|
+
{"version":3,"file":"Icon.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/icon/Icon.component.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mCAAmC,CAAC;AAE7D,OAAO,EACL,aAAa,EAKd,MAAM,OAAO,CAAC;AAEf,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAOhD,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+HrB,CAAC;AAEF,KAAK,SAAS,GAAG;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,SAAS,KAAK,GAAG,CAAC,OAAO,CAAC,GAAG;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAOtG,CAAC;AAgBF,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,SAAS,GAAG,MAAM,OAAO,WAAW,CAAC;AACzE,MAAM,MAAM,SAAS,GAAG,MAAM,WAAW,CAAC;AAC1C,KAAK,KAAK,GAAG;IACX,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,KAAK,CAAC,EAAE,SAAS,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAiBF,eAAO,MAAM,WAAW;UAAsB,QAAQ;SAiCrD,CAAC;AA2DF,iBAAS,IAAI,CAAC,EAAE,WAAW,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,2CAU7C;AAED,OAAO,EAAE,IAAI,EAAE,CAAC"}
|
|
@@ -131,6 +131,8 @@ export const iconTable = {
|
|
|
131
131
|
Stop: 'fas faStop',
|
|
132
132
|
Play: 'fas faPlay',
|
|
133
133
|
Mail: 'fas faEnvelope',
|
|
134
|
+
ThumbsUp: 'far faThumbsUp',
|
|
135
|
+
ThumbsDown: 'far faThumbsDown',
|
|
134
136
|
};
|
|
135
137
|
export const customIcons = {
|
|
136
138
|
'Remote-user': ({ 'aria-label': ariaLabel, color, size }) => (_jsx(RemoteUser, { ariaLabel: ariaLabel, color: color, size: size })),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChartUtil.d.ts","sourceRoot":"","sources":["../../../src/lib/components/linetemporalchart/ChartUtil.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,+BAA+B,CAAC;AACtD,OAAO,+BAA+B,CAAC;AAEvC,MAAM,MAAM,QAAQ,GAAG;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IAEd,KAAK,EAAE,MAAM,GAAG,KAAK,CAAC;IAEtB,eAAe,EAAE,OAAO,CAAC;IAEzB,QAAQ,EAAE,OAAO,CAAC;CACnB,EAAE,CAAC;AAKJ,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,UAEtD;AACD,wBAAgB,gBAAgB,CAC9B,2BAA2B,EAAE,KAAK,EAAE,GACnC,QAAQ,CAqBV;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,QAAQ,CAU3E;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE;IACT,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf,EAAE,EACH,QAAQ,EAAE,MAAM,GACf;IACD,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB,CAwCA;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC,EAAE,EACjD,iBAAiB,CAAC,EAAE,MAAM,EAC1B,cAAc,CAAC,EAAE,MAAM,EACvB,cAAc,CAAC,EAAE,MAAM,GACtB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC,EAAE,
|
|
1
|
+
{"version":3,"file":"ChartUtil.d.ts","sourceRoot":"","sources":["../../../src/lib/components/linetemporalchart/ChartUtil.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,+BAA+B,CAAC;AACtD,OAAO,+BAA+B,CAAC;AAEvC,MAAM,MAAM,QAAQ,GAAG;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IAEd,KAAK,EAAE,MAAM,GAAG,KAAK,CAAC;IAEtB,eAAe,EAAE,OAAO,CAAC;IAEzB,QAAQ,EAAE,OAAO,CAAC;CACnB,EAAE,CAAC;AAKJ,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,UAEtD;AACD,wBAAgB,gBAAgB,CAC9B,2BAA2B,EAAE,KAAK,EAAE,GACnC,QAAQ,CAqBV;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,QAAQ,CAU3E;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE;IACT,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf,EAAE,EACH,QAAQ,EAAE,MAAM,GACf;IACD,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB,CAwCA;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC,EAAE,EACjD,iBAAiB,CAAC,EAAE,MAAM,EAC1B,cAAc,CAAC,EAAE,MAAM,EACvB,cAAc,CAAC,EAAE,MAAM,GACtB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC,EAAE,CAoEpC;AAID,eAAO,MAAM,gBAAgB,UAAW,MAAM,QAAQ,MAAM,WAE3D,CAAC;AACF,eAAO,MAAM,4BAA4B,GAAI,CAAC,SAAS,CAAC,QAAQ,MAAM,KAAG,CAQxE,CAAC;AACF,eAAO,MAAM,gBAAgB,kBAAmB,MAAM,QAAQ,MAAM,WAEnE,CAAC;AAEF,eAAO,MAAM,eAAe,WAAY,KAAK,EAAE,KAAG,MAAM,EAMvD,CAAC"}
|
|
@@ -94,8 +94,16 @@ export function addMissingDataPoint(orginalValues, startingTimeStamp, sampleDura
|
|
|
94
94
|
return [];
|
|
95
95
|
}
|
|
96
96
|
const newValues = [];
|
|
97
|
+
// add missing data points for the starting time
|
|
98
|
+
for (let i = startingTimeStamp; i < orginalValues[0][0]; i += sampleInterval) {
|
|
99
|
+
newValues.push([i, NAN_STRING]);
|
|
100
|
+
}
|
|
97
101
|
// Process all but the last element
|
|
98
102
|
for (let i = 0; i < orginalValues.length - 1; i++) {
|
|
103
|
+
if (orginalValues[i][0] < startingTimeStamp ||
|
|
104
|
+
orginalValues[i][0] > startingTimeStamp + sampleDuration) {
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
99
107
|
// Always add the current data point
|
|
100
108
|
newValues.push(orginalValues[i]);
|
|
101
109
|
const currentTimestamp = orginalValues[i][0];
|
|
@@ -111,6 +119,10 @@ export function addMissingDataPoint(orginalValues, startingTimeStamp, sampleDura
|
|
|
111
119
|
}
|
|
112
120
|
// Add the last element
|
|
113
121
|
newValues.push(orginalValues[orginalValues.length - 1]);
|
|
122
|
+
// add missing data points for the ending time
|
|
123
|
+
for (let i = orginalValues[orginalValues.length - 1][0] + sampleInterval; i < startingTimeStamp + sampleDuration; i += sampleInterval) {
|
|
124
|
+
newValues.push([i, NAN_STRING]);
|
|
125
|
+
}
|
|
114
126
|
return newValues;
|
|
115
127
|
}
|
|
116
128
|
// get the value for the based value
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { TooltipContentProps } from 'recharts';
|
|
1
2
|
export type Serie = {
|
|
2
3
|
resource: string;
|
|
3
4
|
data: [number, number | string | null][];
|
|
@@ -7,14 +8,14 @@ export type Serie = {
|
|
|
7
8
|
};
|
|
8
9
|
type NonSymmetricalChartSerie = {
|
|
9
10
|
yAxisType?: 'default' | 'percentage';
|
|
10
|
-
series: Serie[];
|
|
11
|
+
series: Serie[] | undefined;
|
|
11
12
|
};
|
|
12
13
|
type SymmetricalChartSerie = {
|
|
13
14
|
yAxisType: 'symmetrical';
|
|
14
15
|
series: {
|
|
15
|
-
above: Serie[];
|
|
16
|
-
below: Serie[];
|
|
17
|
-
};
|
|
16
|
+
above: Serie[] | undefined;
|
|
17
|
+
below: Serie[] | undefined;
|
|
18
|
+
} | undefined;
|
|
18
19
|
};
|
|
19
20
|
export type LineChartProps = (NonSymmetricalChartSerie | SymmetricalChartSerie) & {
|
|
20
21
|
title: string;
|
|
@@ -26,6 +27,7 @@ export type LineChartProps = (NonSymmetricalChartSerie | SymmetricalChartSerie)
|
|
|
26
27
|
threshold: number;
|
|
27
28
|
label: string;
|
|
28
29
|
}[];
|
|
30
|
+
syncId?: string;
|
|
29
31
|
isLoading?: boolean;
|
|
30
32
|
/**
|
|
31
33
|
* The format of the x axis, default is 'date-time' which is like 01 Sep 16:00
|
|
@@ -35,7 +37,8 @@ export type LineChartProps = (NonSymmetricalChartSerie | SymmetricalChartSerie)
|
|
|
35
37
|
timeFormat?: 'date-time' | 'date';
|
|
36
38
|
yAxisTitle?: string;
|
|
37
39
|
helpText?: string;
|
|
40
|
+
renderTooltip?: (tooltipProps: TooltipContentProps<number, string>, unitLabel?: string, timeFormat?: 'date-time' | 'date') => React.ReactNode;
|
|
38
41
|
};
|
|
39
|
-
export declare function LineTimeSerieChart({ series, title, height, startingTimeStamp, interval, duration, unitRange, isLoading, timeFormat, yAxisType, yAxisTitle, helpText, ...rest }: LineChartProps): import("react/jsx-runtime").JSX.Element;
|
|
42
|
+
export declare function LineTimeSerieChart({ series, title, height, startingTimeStamp, interval, duration, unitRange, isLoading, timeFormat, yAxisType, yAxisTitle, helpText, syncId, renderTooltip, ...rest }: LineChartProps): import("react/jsx-runtime").JSX.Element;
|
|
40
43
|
export {};
|
|
41
44
|
//# sourceMappingURL=linetimeseriechart.component.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"linetimeseriechart.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/linetimeseriechart/linetimeseriechart.component.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"linetimeseriechart.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/linetimeseriechart/linetimeseriechart.component.tsx"],"names":[],"mappings":"AAAA,OAAO,EAOL,mBAAmB,EAGpB,MAAM,UAAU,CAAC;AAqClB,MAAM,MAAM,KAAK,GAAG;IAElB,QAAQ,EAAE,MAAM,CAAC;IAEjB,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;IAEzC,eAAe,EAAE,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAEtE,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC;AAEF,KAAK,wBAAwB,GAAG;IAC9B,SAAS,CAAC,EAAE,SAAS,GAAG,YAAY,CAAC;IACrC,MAAM,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC;CAC7B,CAAC;AAGF,KAAK,qBAAqB,GAAG;IAC3B,SAAS,EAAE,aAAa,CAAC;IACzB,MAAM,EACF;QACE,KAAK,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC;QAC3B,KAAK,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC;KAC5B,GACD,SAAS,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,CACzB,wBAAwB,GACxB,qBAAqB,CACxB,GAAG;IACF,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE;QACV,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC;KACf,EAAE,CAAC;IACJ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,UAAU,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,CACd,YAAY,EAAE,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,EACjD,SAAS,CAAC,EAAE,MAAM,EAClB,UAAU,CAAC,EAAE,WAAW,GAAG,MAAM,KAC9B,KAAK,CAAC,SAAS,CAAC;CACtB,CAAC;AA6FF,wBAAgB,kBAAkB,CAAC,EACjC,MAAM,EACN,KAAK,EACL,MAAM,EACN,iBAAiB,EACjB,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,SAAiB,EACjB,UAAwB,EACxB,SAAqB,EACrB,UAAU,EACV,QAAQ,EACR,MAAM,EACN,aAAa,EACb,GAAG,IAAI,EACR,EAAE,cAAc,2CAwWhB"}
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Line, LineChart, ReferenceLine, ResponsiveContainer, Tooltip, XAxis, YAxis,
|
|
3
|
-
import { useCallback, useMemo, useRef } from 'react';
|
|
4
|
-
import { useTheme } from 'styled-components';
|
|
5
|
-
import { addMissingDataPoint } from '../linetemporalchart/ChartUtil';
|
|
6
|
-
import styled from 'styled-components';
|
|
7
|
-
import { fontSize, fontWeight } from '../../style/theme';
|
|
8
|
-
import { useChartLegend } from '../chartlegend/ChartLegendWrapper';
|
|
9
|
-
import { ChartTitleText, SmallerText } from '../text/Text.component';
|
|
10
|
-
import { Loader } from '../loader/Loader.component';
|
|
2
|
+
import { CartesianGrid, Line, LineChart, ReferenceLine, ResponsiveContainer, Tooltip, XAxis, YAxis, } from 'recharts';
|
|
3
|
+
import { useCallback, useMemo, useRef, useState } from 'react';
|
|
4
|
+
import styled, { useTheme } from 'styled-components';
|
|
11
5
|
import { spacing } from '../../spacing';
|
|
12
|
-
import {
|
|
6
|
+
import { fontSize } from '../../style/theme';
|
|
7
|
+
import { Box } from '../box/Box';
|
|
8
|
+
import { useChartLegend } from '../chartlegend/ChartLegendWrapper';
|
|
9
|
+
import { FormattedDateTime } from '../date/FormattedDateTime';
|
|
13
10
|
import { Icon } from '../icon/Icon.component';
|
|
11
|
+
import { addMissingDataPoint, getUnitLabel, } from '../linetemporalchart/ChartUtil';
|
|
12
|
+
import { Loader } from '../loader/Loader.component';
|
|
13
|
+
import { ChartTitleText, SmallerText } from '../text/Text.component';
|
|
14
14
|
import { Tooltip as TooltipComponent } from '../tooltip/Tooltip.component';
|
|
15
|
-
import { FormattedDateTime } from '../date/FormattedDateTime';
|
|
16
|
-
import { Box } from '../box/Box';
|
|
17
15
|
import { formatXAxisLabel } from './utils';
|
|
16
|
+
import { ChartTooltipContainer, ChartTooltipItem, ChartTooltipHeader, ChartTooltipItemsContainer, } from '../charttooltip/ChartTooltip';
|
|
17
|
+
import { LegendShape } from '../chartlegend/ChartLegend';
|
|
18
18
|
const LineTemporalChartWrapper = styled.div `
|
|
19
19
|
display: flex;
|
|
20
20
|
flex-direction: column;
|
|
@@ -25,57 +25,13 @@ const ChartHeader = styled.div `
|
|
|
25
25
|
display: flex;
|
|
26
26
|
align-items: center;
|
|
27
27
|
`;
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
border: 1px solid ${(props) => props.theme.border};
|
|
32
|
-
border-radius: 4px;
|
|
33
|
-
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
34
|
-
max-width: 250px;
|
|
35
|
-
`;
|
|
36
|
-
const TooltipTime = styled.div `
|
|
37
|
-
margin-bottom: ${spacing.r8};
|
|
38
|
-
color: ${(props) => props.theme.textPrimary};
|
|
39
|
-
font-size: ${fontSize.smaller};
|
|
40
|
-
font-weight: ${fontWeight.bold};
|
|
41
|
-
text-align: center;
|
|
42
|
-
`;
|
|
43
|
-
const TooltipValue = styled.div `
|
|
44
|
-
font-size: ${fontSize.smaller};
|
|
45
|
-
margin-top: 4px;
|
|
46
|
-
color: ${(props) => props.theme.textSecondary};
|
|
47
|
-
display: flex;
|
|
48
|
-
align-items: flex-start;
|
|
49
|
-
justify-content: space-between;
|
|
50
|
-
width: 100%;
|
|
51
|
-
`;
|
|
52
|
-
const TooltipLegend = styled.div `
|
|
53
|
-
width: 12px;
|
|
54
|
-
height: 3px;
|
|
55
|
-
background-color: ${(props) => props.color};
|
|
56
|
-
margin-right: 8px;
|
|
57
|
-
flex-shrink: 0;
|
|
58
|
-
margin-top: 8px;
|
|
59
|
-
`;
|
|
60
|
-
const TooltipLeftGroup = styled.div `
|
|
61
|
-
display: flex;
|
|
62
|
-
align-items: flex-start;
|
|
63
|
-
min-width: 0;
|
|
64
|
-
flex: 1;
|
|
65
|
-
`;
|
|
66
|
-
const TooltipName = styled.div `
|
|
67
|
-
word-wrap: break-word;
|
|
68
|
-
word-break: break-word;
|
|
69
|
-
flex: 1;
|
|
70
|
-
`;
|
|
71
|
-
const TooltipInstanceValue = styled.div `
|
|
72
|
-
margin-left: 16px;
|
|
73
|
-
flex-shrink: 0;
|
|
74
|
-
text-align: right;
|
|
75
|
-
`;
|
|
76
|
-
const CustomTooltip = ({ active, payload, label, unitLabel, timeFormat, }) => {
|
|
77
|
-
if (!active || !payload || !payload.length || !label)
|
|
28
|
+
const LineTimeSerieChartTooltip = ({ unitLabel, timeFormat, isChartActive, tooltipProps, renderTooltip, hoveredValue, }) => {
|
|
29
|
+
const { active, payload, label } = tooltipProps;
|
|
30
|
+
if (!active || !payload || !payload.length || !label || !isChartActive)
|
|
78
31
|
return null;
|
|
32
|
+
if (renderTooltip) {
|
|
33
|
+
return renderTooltip(tooltipProps, unitLabel, timeFormat);
|
|
34
|
+
}
|
|
79
35
|
// We can't use the default itemSorter method because it's a custom tooltip.
|
|
80
36
|
// Sort the payload here instead
|
|
81
37
|
const sortedPayload = [...payload].sort((a, b) => {
|
|
@@ -89,32 +45,57 @@ const CustomTooltip = ({ active, payload, label, unitLabel, timeFormat, }) => {
|
|
|
89
45
|
}
|
|
90
46
|
return bValue - aValue; // Positives before negatives
|
|
91
47
|
});
|
|
92
|
-
return (_jsxs(
|
|
48
|
+
return (_jsxs(ChartTooltipContainer, { children: [_jsx(ChartTooltipHeader, { children: _jsx(FormattedDateTime, { format: timeFormat === 'date-time'
|
|
93
49
|
? 'day-month-abbreviated-hour-minute-second'
|
|
94
|
-
: 'long-date-without-weekday', value: new Date(label) }) }),
|
|
95
|
-
|
|
96
|
-
|
|
50
|
+
: 'long-date-without-weekday', value: new Date(label) }) }), _jsx(ChartTooltipItemsContainer, { children: sortedPayload.map((entry, index) => {
|
|
51
|
+
const legendIcon = (_jsx(LegendShape, { color: entry.color, shape: "line", chartColors: { [entry.color]: entry.color } }));
|
|
52
|
+
const isHovered = entry.name === hoveredValue;
|
|
53
|
+
const formattedValue = !Number.isFinite(entry.value)
|
|
54
|
+
? '-'
|
|
55
|
+
: `${entry.value.toFixed(2)} ${unitLabel}`;
|
|
56
|
+
return (_jsx(ChartTooltipItem, { label: entry.name, value: formattedValue, legendIcon: legendIcon, isHovered: isHovered }, index));
|
|
57
|
+
}) })] }));
|
|
97
58
|
};
|
|
98
59
|
const isSymmetricalSeries = (series) => {
|
|
99
60
|
return 'above' in series && 'below' in series;
|
|
100
61
|
};
|
|
101
|
-
export function LineTimeSerieChart({ series, title, height, startingTimeStamp, interval, duration, unitRange, isLoading = false, timeFormat = 'date-time', yAxisType = 'default', yAxisTitle, helpText, ...rest }) {
|
|
62
|
+
export function LineTimeSerieChart({ series, title, height, startingTimeStamp, interval, duration, unitRange, isLoading = false, timeFormat = 'date-time', yAxisType = 'default', yAxisTitle, helpText, syncId, renderTooltip, ...rest }) {
|
|
102
63
|
const theme = useTheme();
|
|
103
|
-
const { getColor } = useChartLegend();
|
|
64
|
+
const { getColor, selectedResources } = useChartLegend();
|
|
104
65
|
const chartRef = useRef(null);
|
|
66
|
+
const [isChartActive, setIsChartActive] = useState(false);
|
|
67
|
+
const [hoveredValue, setHoveredValue] = useState(undefined);
|
|
105
68
|
const chartData = useMemo(() => {
|
|
69
|
+
// Guard against empty/undefined series data
|
|
70
|
+
if (!series || (Array.isArray(series) && series.length === 0)) {
|
|
71
|
+
return [];
|
|
72
|
+
}
|
|
73
|
+
// Handle symmetrical series with empty above/below arrays
|
|
74
|
+
if (isSymmetricalSeries(series)) {
|
|
75
|
+
if ((!series.above || series.above.length === 0) &&
|
|
76
|
+
(!series.below || series.below.length === 0)) {
|
|
77
|
+
return [];
|
|
78
|
+
}
|
|
79
|
+
}
|
|
106
80
|
// 1. Add missing data points
|
|
107
81
|
const normalizedSeries = yAxisType === 'symmetrical' && isSymmetricalSeries(series)
|
|
108
82
|
? {
|
|
109
|
-
above: series.above
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
83
|
+
above: series.above
|
|
84
|
+
? series.above.map((line) => ({
|
|
85
|
+
...line,
|
|
86
|
+
data: addMissingDataPoint(line.data, startingTimeStamp, duration, interval),
|
|
87
|
+
}))
|
|
88
|
+
: [],
|
|
113
89
|
// Convert positive values to negative values
|
|
114
|
-
below: series.below
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
90
|
+
below: series.below
|
|
91
|
+
? series.below.map((line) => ({
|
|
92
|
+
...line,
|
|
93
|
+
data: addMissingDataPoint(line.data, startingTimeStamp, duration, interval).map(([timestamp, value]) => [
|
|
94
|
+
timestamp,
|
|
95
|
+
value === null ? null : `-${Number(value)}`,
|
|
96
|
+
]),
|
|
97
|
+
}))
|
|
98
|
+
: [],
|
|
118
99
|
}
|
|
119
100
|
: series.map((line) => ({
|
|
120
101
|
...line,
|
|
@@ -177,6 +158,14 @@ export function LineTimeSerieChart({ series, title, height, startingTimeStamp, i
|
|
|
177
158
|
return !isNaN(num) && num !== null ? num : null;
|
|
178
159
|
})
|
|
179
160
|
.filter((value) => value !== null));
|
|
161
|
+
// Guard against empty values array
|
|
162
|
+
if (values.length === 0) {
|
|
163
|
+
return {
|
|
164
|
+
topValue: 100, // Default value for empty charts
|
|
165
|
+
unitLabel: '',
|
|
166
|
+
rechartsData: [],
|
|
167
|
+
};
|
|
168
|
+
}
|
|
180
169
|
const top = Math.abs(Math.max(...values));
|
|
181
170
|
const bottom = Math.abs(Math.min(...values));
|
|
182
171
|
const maxValue = Math.max(top, bottom);
|
|
@@ -196,11 +185,17 @@ export function LineTimeSerieChart({ series, title, height, startingTimeStamp, i
|
|
|
196
185
|
// Group series by resource and create color mapping
|
|
197
186
|
const { colorMapping, groupedSeries } = useMemo(() => {
|
|
198
187
|
const mapping = {};
|
|
188
|
+
// Guard against empty/undefined series
|
|
189
|
+
if (!series) {
|
|
190
|
+
return { colorMapping: mapping, groupedSeries: {} };
|
|
191
|
+
}
|
|
199
192
|
const allSeries = isSymmetricalSeries(series)
|
|
200
|
-
? [...series.above, ...series.below]
|
|
193
|
+
? [...(series.above || []), ...(series.below || [])]
|
|
201
194
|
: series;
|
|
202
195
|
// Group series by resource
|
|
203
|
-
const groups = allSeries
|
|
196
|
+
const groups = allSeries
|
|
197
|
+
.filter((serie) => selectedResources.includes(serie.resource))
|
|
198
|
+
.reduce((acc, serie) => {
|
|
204
199
|
const key = serie.resource;
|
|
205
200
|
if (!acc[key]) {
|
|
206
201
|
acc[key] = [];
|
|
@@ -222,30 +217,30 @@ export function LineTimeSerieChart({ series, title, height, startingTimeStamp, i
|
|
|
222
217
|
colorMapping: mapping,
|
|
223
218
|
groupedSeries: groups,
|
|
224
219
|
};
|
|
225
|
-
}, [series, getColor]);
|
|
220
|
+
}, [series, getColor, selectedResources]);
|
|
226
221
|
// Format time for display the tick in the x axis
|
|
227
222
|
const formatXAxisLabelCallback = useCallback((timestamp) => formatXAxisLabel(timestamp, timeFormat, chartData), [timeFormat, chartData]);
|
|
228
|
-
return (_jsxs(LineTemporalChartWrapper, { children: [_jsxs(ChartHeader, { children: [_jsxs(ChartTitleText, { children: [title, " ", unitLabel && `(${unitLabel})`] }), helpText && (_jsx(Box, { ml: spacing.r4, children: _jsx(TooltipComponent, { placement: 'right', overlay: _jsx(SmallerText, { children: helpText }), children: _jsx(Icon, { name: "Info", color: theme.buttonSecondary }) }) })), isLoading && _jsx(Loader, {})] }), _jsx(ResponsiveContainer, { width: "100%", height: height, children: _jsxs(LineChart, { data: rechartsData, ref: chartRef, margin: { top: 0, right: 0, bottom: 0, left: 0 }, "aria-label": `Time series chart for ${title}`, children: [_jsx(CartesianGrid, { vertical: true, horizontal: true, verticalPoints: [0], horizontalPoints: [0], stroke: theme.border, fill: theme.backgroundLevel4, strokeWidth: 1 }), _jsx(XAxis, { dataKey: "timestamp", type: "number", domain: ['dataMin', 'dataMax'], ticks: xAxisTicks, tickFormatter: formatXAxisLabelCallback, tickCount: 5, tick: {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
223
|
+
return (_jsxs(LineTemporalChartWrapper, { children: [_jsxs(ChartHeader, { children: [_jsxs(ChartTitleText, { children: [title, " ", unitLabel && `(${unitLabel})`] }), helpText && (_jsx(Box, { ml: spacing.r4, children: _jsx(TooltipComponent, { placement: 'right', overlay: _jsx(SmallerText, { children: helpText }), children: _jsx(Icon, { name: "Info", color: theme.buttonSecondary }) }) })), isLoading && _jsx(Loader, {})] }), _jsx("div", { onFocus: () => setIsChartActive(true), onBlur: () => setIsChartActive(false), onFocusCapture: () => setIsChartActive(true), onBlurCapture: () => setIsChartActive(false), children: _jsx(ResponsiveContainer, { width: "100%", height: height, children: _jsxs(LineChart, { data: rechartsData, ref: chartRef, margin: { top: 0, right: 0, bottom: 0, left: 0 }, "aria-label": `Time series chart for ${title}`, syncId: syncId, onMouseEnter: () => setIsChartActive(true), onMouseLeave: () => setIsChartActive(false), children: [_jsx(CartesianGrid, { vertical: true, horizontal: true, verticalPoints: [0], horizontalPoints: [0], stroke: theme.border, fill: theme.backgroundLevel4, strokeWidth: 1 }), _jsx(XAxis, { dataKey: "timestamp", type: "number", domain: ['dataMin', 'dataMax'], ticks: xAxisTicks, tickFormatter: formatXAxisLabelCallback, tickCount: 5, tick: {
|
|
224
|
+
fill: theme.textSecondary,
|
|
225
|
+
fontSize: fontSize.smaller,
|
|
226
|
+
}, axisLine: { stroke: theme.border } }), _jsx(YAxis, { orientation: "right", allowDataOverflow: false, label: {
|
|
227
|
+
value: yAxisTitle,
|
|
228
|
+
angle: 90,
|
|
229
|
+
position: 'insideRight',
|
|
230
|
+
style: {
|
|
231
|
+
textAnchor: 'middle',
|
|
232
|
+
fill: theme.textSecondary,
|
|
233
|
+
fontSize: fontSize.smaller,
|
|
234
|
+
},
|
|
235
|
+
}, domain: yAxisType === 'percentage'
|
|
236
|
+
? [0, 100]
|
|
237
|
+
: yAxisType === 'symmetrical'
|
|
238
|
+
? [-topValue, topValue]
|
|
239
|
+
: [0, topValue], axisLine: { stroke: theme.border }, tick: {
|
|
237
240
|
fill: theme.textSecondary,
|
|
238
241
|
fontSize: fontSize.smaller,
|
|
239
|
-
},
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
? [-topValue, topValue]
|
|
244
|
-
: [0, topValue], axisLine: { stroke: theme.border }, tick: {
|
|
245
|
-
fill: theme.textSecondary,
|
|
246
|
-
fontSize: fontSize.smaller,
|
|
247
|
-
}, tickFormatter: (value) => Math.round(value).toString(), tickCount: 5, interval: 'preserveStartEnd' }), _jsx(Tooltip, { content: _jsx(CustomTooltip, { unitLabel: unitLabel, timeFormat: timeFormat }) }), yAxisType === 'symmetrical' && (_jsx(ReferenceLine, { y: 0, stroke: theme.border })), Object.entries(groupedSeries).map(([resource, resourceSeries]) => resourceSeries.map((serie, serieIndex) => {
|
|
248
|
-
const label = serie.getTooltipLabel(serie.metricPrefix, serie.resource);
|
|
249
|
-
return (_jsx(Line, { type: "monotone", dataKey: label, stroke: colorMapping[resource], dot: false, isAnimationActive: false }, `${title}-${resource}-${serieIndex}`));
|
|
250
|
-
}))] }) })] }));
|
|
242
|
+
}, tickFormatter: (value) => Math.round(value).toString(), tickCount: 5, interval: 'preserveStartEnd' }), _jsx(Tooltip, { content: (props) => (_jsx(LineTimeSerieChartTooltip, { unitLabel: unitLabel, timeFormat: timeFormat, renderTooltip: renderTooltip, tooltipProps: props, isChartActive: isChartActive, hoveredValue: hoveredValue })) }), yAxisType === 'symmetrical' && (_jsx(ReferenceLine, { y: 0, stroke: theme.border })), Object.entries(groupedSeries).map(([resource, resourceSeries]) => resourceSeries.map((serie, serieIndex) => {
|
|
243
|
+
const label = serie.getTooltipLabel(serie.metricPrefix, serie.resource);
|
|
244
|
+
return (_jsx(Line, { type: "monotone", dataKey: label, stroke: colorMapping[resource], dot: false, isAnimationActive: false, onMouseEnter: () => setHoveredValue(label), onMouseLeave: () => setHoveredValue(undefined) }, `${title}-${resource}-${serieIndex}`));
|
|
245
|
+
}))] }) }) })] }));
|
|
251
246
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
type SparklineProps = {
|
|
2
|
+
serie: {
|
|
3
|
+
data: [number, number | null][];
|
|
4
|
+
color?: string;
|
|
5
|
+
};
|
|
6
|
+
startingTimeStamp: number;
|
|
7
|
+
sampleDuration: number;
|
|
8
|
+
sampleInterval: number;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Sparkline is a simple dynamically sized area chart.
|
|
12
|
+
* Used to show trends in data over time.
|
|
13
|
+
*/
|
|
14
|
+
export declare function Sparkline({ serie, startingTimeStamp, sampleDuration, sampleInterval }: SparklineProps): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=sparkline.component.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sparkline.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/sparkline/sparkline.component.tsx"],"names":[],"mappings":"AAMA,KAAK,cAAc,GAAG;IACpB,KAAK,EAAE;QACL,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,GAAC,IAAI,CAAC,EAAE,CAAC;QAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAA;CACvB,CAAC;AAEF;;;GAGG;AACH,wBAAgB,SAAS,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,cAAc,EAAE,EAAE,cAAc,2CAiCrG"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo } from "react";
|
|
3
|
+
import { Area, AreaChart, CartesianGrid, ResponsiveContainer } from "recharts";
|
|
4
|
+
import { useTheme } from "styled-components";
|
|
5
|
+
import { chartColors } from "../../style/theme";
|
|
6
|
+
import { addMissingDataPoint } from "../linetemporalchart/ChartUtil";
|
|
7
|
+
/**
|
|
8
|
+
* Sparkline is a simple dynamically sized area chart.
|
|
9
|
+
* Used to show trends in data over time.
|
|
10
|
+
*/
|
|
11
|
+
export function Sparkline({ serie, startingTimeStamp, sampleDuration, sampleInterval }) {
|
|
12
|
+
var _a;
|
|
13
|
+
const data = useMemo(() => {
|
|
14
|
+
const dataMdp = addMissingDataPoint(serie.data, startingTimeStamp, sampleDuration, sampleInterval);
|
|
15
|
+
return dataMdp.map(([x, y]) => ({ x, y }));
|
|
16
|
+
}, [serie.data]);
|
|
17
|
+
const color = (_a = serie.color) !== null && _a !== void 0 ? _a : chartColors.lineColor1;
|
|
18
|
+
const strokeGridColor = useTheme().border;
|
|
19
|
+
return (_jsx(ResponsiveContainer, { children: _jsxs(AreaChart, { data: data, children: [_jsx("defs", { children: _jsxs("linearGradient", { id: `gradient-${color}`, x1: "0", y1: "0", x2: "0", y2: "1", children: [_jsx("stop", { offset: "0%", stopColor: color, stopOpacity: 0.7 }), _jsx("stop", { offset: "100%", stopColor: color, stopOpacity: 0.1 })] }) }), _jsx(CartesianGrid, { horizontal: false, stroke: strokeGridColor, strokeOpacity: 0.5 }), _jsx(Area, { type: "linear", dataKey: "y", stroke: color, fill: `url(#gradient-${color})`, dot: false, activeDot: false, isAnimationActive: false })] }) }));
|
|
20
|
+
}
|