@scality/core-ui 0.187.0 → 0.189.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/dist/components/charts/common/SharedComponents.d.ts.map +1 -1
- package/dist/components/charts/common/SharedComponents.js +19 -9
- package/dist/components/charts/linetimeseries/LineTimeSerieChart.d.ts.map +1 -1
- package/dist/components/charts/linetimeseries/LineTimeSerieChart.js +15 -8
- package/package.json +1 -1
- package/src/lib/components/charts/common/SharedComponents.tsx +40 -27
- package/src/lib/components/charts/linetimeseries/LineTimeSerieChart.tsx +15 -14
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SharedComponents.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/charts/common/SharedComponents.tsx"],"names":[],"mappings":"AAUA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpC;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,0OAMrC,CAAC;
|
|
1
|
+
{"version":3,"file":"SharedComponents.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/charts/common/SharedComponents.tsx"],"names":[],"mappings":"AAUA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpC;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,0OAMrC,CAAC;AAUF,UAAU,wBAAwB;IAChC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,eAAO,MAAM,UAAU,eAAgB,wBAAwB,4CAa9D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,YAAY,eAAgB,wBAAwB,4CAahE,CAAC;AAEF,UAAU,gBAAgB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC9B;AAED;;;GAGG;AACH,eAAO,MAAM,WAAW,wDAKrB,gBAAgB,4CA2BlB,CAAC;AAEF,UAAU,eAAe;IACvB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,OAAO,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,iBAAiB,EAAE,MAAM,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,QAAQ,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;GAGG;AACH,eAAO,MAAM,UAAU,wEAQpB,eAAe,4CAkDjB,CAAC"}
|
|
@@ -3,11 +3,11 @@ import { ResponsiveContainer } from 'recharts';
|
|
|
3
3
|
import styled, { useTheme } from 'styled-components';
|
|
4
4
|
import { spacing, Stack, Wrap } from '../../../spacing';
|
|
5
5
|
import { Box } from '../../box/Box';
|
|
6
|
-
import { ConstrainedText } from '../../constrainedtext/Constrainedtext.component';
|
|
7
|
-
import { FormattedDateTime } from '../../date/FormattedDateTime';
|
|
8
6
|
import { IconHelp } from '../../iconhelper/IconHelper';
|
|
9
7
|
import { Loader } from '../../loader/Loader.component';
|
|
10
8
|
import { Text } from '../../text/Text.component';
|
|
9
|
+
import { ConstrainedText } from '../../constrainedtext/Constrainedtext.component';
|
|
10
|
+
import { FormattedDateTime } from '../../date/FormattedDateTime';
|
|
11
11
|
import { formatXAxisDate, maxWidthTooltip } from './chartUtils';
|
|
12
12
|
/**
|
|
13
13
|
* Styled ResponsiveContainer for charts
|
|
@@ -21,6 +21,13 @@ export const StyledResponsiveContainer = styled(ResponsiveContainer) `
|
|
|
21
21
|
overflow: visible;
|
|
22
22
|
}
|
|
23
23
|
`;
|
|
24
|
+
const TickContainer = styled.div `
|
|
25
|
+
width: 100%;
|
|
26
|
+
height: 100%;
|
|
27
|
+
display: flex;
|
|
28
|
+
align-items: center;
|
|
29
|
+
justify-content: center;
|
|
30
|
+
`;
|
|
24
31
|
/**
|
|
25
32
|
* Error state component for charts
|
|
26
33
|
*/
|
|
@@ -63,11 +70,14 @@ export const CustomTick = ({ x, y, payload, visibleTicksCount, width, type, tick
|
|
|
63
70
|
type.timeRange.startDate.getTime()) /
|
|
64
71
|
1000
|
|
65
72
|
: 0;
|
|
66
|
-
return (_jsx("foreignObject", { x: centerX, y: y - 10, width: tickWidth,
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
+
return (_jsx("foreignObject", { x: centerX, y: y - 10, width: tickWidth, height: 30, style: {
|
|
74
|
+
overflow: 'visible',
|
|
75
|
+
pointerEvents: 'none',
|
|
76
|
+
}, children: _jsx(TickContainer, { children: _jsx(ConstrainedText, { color: "textSecondary", text: _jsx(Text, { variant: "Smaller", children: type.type === 'time' ? (_jsx(FormattedDateTime, { format: formatXAxisDate(duration), value: new Date(payload.value) })) : (String(payload.value)) }), centered: true, tooltipStyle: {
|
|
77
|
+
backgroundColor: theme.backgroundLevel1,
|
|
78
|
+
padding: spacing.r10,
|
|
79
|
+
borderRadius: spacing.r8,
|
|
80
|
+
border: `1px solid ${theme.border}`,
|
|
81
|
+
position: 'absolute',
|
|
82
|
+
} }) }) }));
|
|
73
83
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LineTimeSerieChart.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/charts/linetimeseries/LineTimeSerieChart.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAiD,MAAM,OAAO,CAAC;AACtE,OAAO,EAML,mBAAmB,EAGpB,MAAM,UAAU,CAAC;AAiClB,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,QAAQ,CAAC,EAAE,MAAM,KACd,KAAK,CAAC,SAAS,CAAC;CACtB,CAAC;AAiHF;;;;;;;;;GASG;AACH,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,
|
|
1
|
+
{"version":3,"file":"LineTimeSerieChart.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/charts/linetimeseries/LineTimeSerieChart.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAiD,MAAM,OAAO,CAAC;AACtE,OAAO,EAML,mBAAmB,EAGpB,MAAM,UAAU,CAAC;AAiClB,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,QAAQ,CAAC,EAAE,MAAM,KACd,KAAK,CAAC,SAAS,CAAC;CACtB,CAAC;AAiHF;;;;;;;;;GASG;AACH,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,2CA2VhB"}
|
|
@@ -44,7 +44,7 @@ const LineTimeSerieChartTooltip = ({ unitLabel, duration, isChartActive, tooltip
|
|
|
44
44
|
const isHovered = entry.name === hoveredValue;
|
|
45
45
|
const formattedValue = !Number.isFinite(entry.value)
|
|
46
46
|
? '-'
|
|
47
|
-
: `${entry.value.toFixed(2)} ${unitLabel}`;
|
|
47
|
+
: `${entry.value.toFixed(2)}${unitLabel ? ` ${unitLabel}` : ''}`;
|
|
48
48
|
return (_jsxs(React.Fragment, { children: [isSymmetrical &&
|
|
49
49
|
hasBothPositiveAndNegative &&
|
|
50
50
|
index === separatorIndex && _jsx(ChartTooltipSeparator, {}), _jsx(ChartTooltipItem, { label: entry.name, value: formattedValue, legendIcon: legendIcon, isHovered: isHovered })] }, index));
|
|
@@ -151,18 +151,21 @@ export function LineTimeSerieChart({ series, title, height, startingTimeStamp, i
|
|
|
151
151
|
}, [chartData]);
|
|
152
152
|
// 3. Transform the data base on the valuebase
|
|
153
153
|
const { topValue, unitLabel, rechartsData, topDomain } = useMemo(() => {
|
|
154
|
+
var _a;
|
|
154
155
|
const values = chartData.flatMap((dataPoint) => Object.entries(dataPoint)
|
|
155
156
|
.filter(([key]) => key !== 'timestamp')
|
|
156
157
|
.map(([_, value]) => {
|
|
157
|
-
|
|
158
|
-
|
|
158
|
+
if (value === null || value === undefined)
|
|
159
|
+
return null;
|
|
160
|
+
const num = typeof value === 'string' ? Number(value) : value;
|
|
161
|
+
return !isNaN(num) ? num : null;
|
|
159
162
|
})
|
|
160
163
|
.filter((value) => value !== null));
|
|
161
164
|
// Guard against empty values array
|
|
162
165
|
if (values.length === 0) {
|
|
163
166
|
return {
|
|
164
167
|
topValue: 100, // Default value for empty charts
|
|
165
|
-
unitLabel: yAxisType === 'percentage' ? '%' :
|
|
168
|
+
unitLabel: yAxisType === 'percentage' ? '%' : undefined,
|
|
166
169
|
rechartsData: [],
|
|
167
170
|
topDomain: 100,
|
|
168
171
|
};
|
|
@@ -172,11 +175,15 @@ export function LineTimeSerieChart({ series, title, height, startingTimeStamp, i
|
|
|
172
175
|
const maxValue = Math.max(top, bottom);
|
|
173
176
|
// Use shared normalization function
|
|
174
177
|
const result = normalizeChartDataWithUnits(chartData, maxValue, unitRange, 'timestamp');
|
|
178
|
+
// For percentage charts, ensure Y-axis goes to at least 100%
|
|
179
|
+
const topDomain = yAxisType === 'percentage'
|
|
180
|
+
? Math.max(result.topDomain, 100)
|
|
181
|
+
: result.topDomain;
|
|
175
182
|
return {
|
|
176
|
-
topValue: result.topValue,
|
|
177
|
-
unitLabel: result.unitLabel,
|
|
183
|
+
topValue: yAxisType === 'percentage' ? Math.max(result.topValue, 100) : result.topValue,
|
|
184
|
+
unitLabel: (_a = result.unitLabel) !== null && _a !== void 0 ? _a : (yAxisType === 'percentage' ? '%' : undefined),
|
|
178
185
|
rechartsData: result.rechartsData,
|
|
179
|
-
topDomain
|
|
186
|
+
topDomain,
|
|
180
187
|
};
|
|
181
188
|
}, [chartData, yAxisType, unitRange]);
|
|
182
189
|
// Group series by resource and create color mapping
|
|
@@ -217,7 +224,7 @@ export function LineTimeSerieChart({ series, title, height, startingTimeStamp, i
|
|
|
217
224
|
}, [series, getColor, selectedResources]);
|
|
218
225
|
// Format time for display the tick in the x axis
|
|
219
226
|
const formatXAxisLabelCallback = useCallback((timestamp) => formatXAxisLabel(timestamp, duration), [duration]);
|
|
220
|
-
return (_jsxs(LineTemporalChartWrapper, { children: [_jsxs(Stack, { gap: "r4", children: [_jsxs(ChartTitleText, { children: [title, " ", unitLabel && `(${unitLabel})`] }), helpText && (_jsx(IconHelp, { tooltipMessage: helpText, overlayStyle: maxWidthTooltip })), isLoading && _jsx(Loader, {})] }), _jsx("div", {
|
|
227
|
+
return (_jsxs(LineTemporalChartWrapper, { children: [_jsxs(Stack, { gap: "r4", children: [_jsxs(ChartTitleText, { children: [title, " ", unitLabel && `(${unitLabel})`] }), helpText && (_jsx(IconHelp, { tooltipMessage: helpText, overlayStyle: maxWidthTooltip })), isLoading && _jsx(Loader, {})] }), _jsx("div", { children: _jsx(StyledResponsiveContainer, { 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), accessibilityLayer: true, 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: {
|
|
221
228
|
fill: theme.textSecondary,
|
|
222
229
|
fontSize: fontSize.smaller,
|
|
223
230
|
}, axisLine: { stroke: theme.border } }), _jsx(YAxis, { orientation: "right", label: {
|
package/package.json
CHANGED
|
@@ -2,11 +2,11 @@ import { ResponsiveContainer } from 'recharts';
|
|
|
2
2
|
import styled, { useTheme } from 'styled-components';
|
|
3
3
|
import { spacing, Stack, Wrap } from '../../../spacing';
|
|
4
4
|
import { Box } from '../../box/Box';
|
|
5
|
-
import { ConstrainedText } from '../../constrainedtext/Constrainedtext.component';
|
|
6
|
-
import { FormattedDateTime } from '../../date/FormattedDateTime';
|
|
7
5
|
import { IconHelp } from '../../iconhelper/IconHelper';
|
|
8
6
|
import { Loader } from '../../loader/Loader.component';
|
|
9
7
|
import { Text } from '../../text/Text.component';
|
|
8
|
+
import { ConstrainedText } from '../../constrainedtext/Constrainedtext.component';
|
|
9
|
+
import { FormattedDateTime } from '../../date/FormattedDateTime';
|
|
10
10
|
import { formatXAxisDate, maxWidthTooltip } from './chartUtils';
|
|
11
11
|
import { TimeType } from '../types';
|
|
12
12
|
|
|
@@ -23,6 +23,14 @@ export const StyledResponsiveContainer = styled(ResponsiveContainer)`
|
|
|
23
23
|
}
|
|
24
24
|
`;
|
|
25
25
|
|
|
26
|
+
const TickContainer = styled.div`
|
|
27
|
+
width: 100%;
|
|
28
|
+
height: 100%;
|
|
29
|
+
display: flex;
|
|
30
|
+
align-items: center;
|
|
31
|
+
justify-content: center;
|
|
32
|
+
`;
|
|
33
|
+
|
|
26
34
|
interface ChartLoadingOrErrorProps {
|
|
27
35
|
height: number;
|
|
28
36
|
}
|
|
@@ -149,32 +157,37 @@ export const CustomTick = ({
|
|
|
149
157
|
x={centerX}
|
|
150
158
|
y={y - 10}
|
|
151
159
|
width={tickWidth}
|
|
152
|
-
|
|
153
|
-
|
|
160
|
+
height={30}
|
|
161
|
+
style={{
|
|
162
|
+
overflow: 'visible',
|
|
163
|
+
pointerEvents: 'none',
|
|
164
|
+
}}
|
|
154
165
|
>
|
|
155
|
-
<
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
166
|
+
<TickContainer>
|
|
167
|
+
<ConstrainedText
|
|
168
|
+
color="textSecondary"
|
|
169
|
+
text={
|
|
170
|
+
<Text variant="Smaller">
|
|
171
|
+
{type.type === 'time' ? (
|
|
172
|
+
<FormattedDateTime
|
|
173
|
+
format={formatXAxisDate(duration)}
|
|
174
|
+
value={new Date(payload.value)}
|
|
175
|
+
/>
|
|
176
|
+
) : (
|
|
177
|
+
String(payload.value)
|
|
178
|
+
)}
|
|
179
|
+
</Text>
|
|
180
|
+
}
|
|
181
|
+
centered
|
|
182
|
+
tooltipStyle={{
|
|
183
|
+
backgroundColor: theme.backgroundLevel1,
|
|
184
|
+
padding: spacing.r10,
|
|
185
|
+
borderRadius: spacing.r8,
|
|
186
|
+
border: `1px solid ${theme.border}`,
|
|
187
|
+
position: 'absolute',
|
|
188
|
+
}}
|
|
189
|
+
/>
|
|
190
|
+
</TickContainer>
|
|
178
191
|
</foreignObject>
|
|
179
192
|
);
|
|
180
193
|
};
|
|
@@ -172,7 +172,7 @@ const LineTimeSerieChartTooltip = ({
|
|
|
172
172
|
|
|
173
173
|
const formattedValue = !Number.isFinite(entry.value)
|
|
174
174
|
? '-'
|
|
175
|
-
: `${entry.value.toFixed(2)} ${unitLabel}`;
|
|
175
|
+
: `${entry.value.toFixed(2)}${unitLabel ? ` ${unitLabel}` : ''}`;
|
|
176
176
|
|
|
177
177
|
return (
|
|
178
178
|
<React.Fragment key={index}>
|
|
@@ -375,9 +375,9 @@ export function LineTimeSerieChart({
|
|
|
375
375
|
Object.entries(dataPoint)
|
|
376
376
|
.filter(([key]) => key !== 'timestamp')
|
|
377
377
|
.map(([_, value]) => {
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
return !isNaN(num)
|
|
378
|
+
if (value === null || value === undefined) return null;
|
|
379
|
+
const num = typeof value === 'string' ? Number(value) : value;
|
|
380
|
+
return !isNaN(num) ? num : null;
|
|
381
381
|
})
|
|
382
382
|
.filter((value): value is number => value !== null),
|
|
383
383
|
);
|
|
@@ -386,7 +386,7 @@ export function LineTimeSerieChart({
|
|
|
386
386
|
if (values.length === 0) {
|
|
387
387
|
return {
|
|
388
388
|
topValue: 100, // Default value for empty charts
|
|
389
|
-
unitLabel: yAxisType === 'percentage' ? '%' :
|
|
389
|
+
unitLabel: yAxisType === 'percentage' ? '%' : undefined,
|
|
390
390
|
rechartsData: [],
|
|
391
391
|
topDomain: 100,
|
|
392
392
|
};
|
|
@@ -404,11 +404,17 @@ export function LineTimeSerieChart({
|
|
|
404
404
|
'timestamp', // LineTimeSerieChart uses 'timestamp' as the key to exclude
|
|
405
405
|
);
|
|
406
406
|
|
|
407
|
+
// For percentage charts, ensure Y-axis goes to at least 100%
|
|
408
|
+
const topDomain =
|
|
409
|
+
yAxisType === 'percentage'
|
|
410
|
+
? Math.max(result.topDomain, 100)
|
|
411
|
+
: result.topDomain;
|
|
412
|
+
|
|
407
413
|
return {
|
|
408
|
-
topValue: result.topValue,
|
|
409
|
-
unitLabel: result.unitLabel,
|
|
414
|
+
topValue: yAxisType === 'percentage' ? Math.max(result.topValue, 100) : result.topValue,
|
|
415
|
+
unitLabel: result.unitLabel ?? (yAxisType === 'percentage' ? '%' : undefined),
|
|
410
416
|
rechartsData: result.rechartsData,
|
|
411
|
-
topDomain
|
|
417
|
+
topDomain,
|
|
412
418
|
};
|
|
413
419
|
}, [chartData, yAxisType, unitRange]);
|
|
414
420
|
|
|
@@ -473,12 +479,7 @@ export function LineTimeSerieChart({
|
|
|
473
479
|
)}
|
|
474
480
|
{isLoading && <Loader />}
|
|
475
481
|
</Stack>
|
|
476
|
-
<div
|
|
477
|
-
onFocus={() => setIsChartActive(true)}
|
|
478
|
-
onBlur={() => setIsChartActive(false)}
|
|
479
|
-
onFocusCapture={() => setIsChartActive(true)}
|
|
480
|
-
onBlurCapture={() => setIsChartActive(false)}
|
|
481
|
-
>
|
|
482
|
+
<div>
|
|
482
483
|
<StyledResponsiveContainer width="100%" height={height}>
|
|
483
484
|
<LineChart
|
|
484
485
|
data={rechartsData}
|