@scality/core-ui 0.174.0 → 0.176.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/barchartv2/Barchart.component.d.ts +4 -4
- package/dist/components/barchartv2/Barchart.component.d.ts.map +1 -1
- package/dist/components/barchartv2/Barchart.component.js +22 -32
- package/dist/components/barchartv2/BarchartTooltip.d.ts +1 -1
- package/dist/components/barchartv2/BarchartTooltip.d.ts.map +1 -1
- package/dist/components/barchartv2/BarchartTooltip.js +6 -6
- package/dist/components/barchartv2/utils.d.ts.map +1 -1
- package/dist/components/chartlegend/ChartLegendWrapper.js +1 -1
- package/dist/components/charttooltip/ChartTooltip.d.ts +6 -0
- package/dist/components/charttooltip/ChartTooltip.d.ts.map +1 -1
- package/dist/components/charttooltip/ChartTooltip.js +22 -0
- package/dist/components/date/FormattedDateTime.d.ts +23 -8
- package/dist/components/date/FormattedDateTime.d.ts.map +1 -1
- package/dist/components/date/FormattedDateTime.js +51 -7
- package/dist/components/icon/Icon.component.d.ts +1 -0
- package/dist/components/icon/Icon.component.d.ts.map +1 -1
- package/dist/components/icon/Icon.component.js +1 -0
- package/dist/components/linetimeseriechart/linetimeseriechart.component.d.ts +2 -1
- package/dist/components/linetimeseriechart/linetimeseriechart.component.d.ts.map +1 -1
- package/dist/components/linetimeseriechart/linetimeseriechart.component.js +19 -17
- package/dist/components/linetimeseriechart/utils.d.ts +1 -1
- package/dist/components/linetimeseriechart/utils.d.ts.map +1 -1
- package/dist/components/linetimeseriechart/utils.js +13 -13
- package/dist/components/scrollbarwrapper/ScrollbarWrapper.component.d.ts.map +1 -1
- package/dist/components/scrollbarwrapper/ScrollbarWrapper.component.js +2 -0
- package/dist/components/sparkline/sparkline.component.d.ts +2 -1
- package/dist/components/sparkline/sparkline.component.d.ts.map +1 -1
- package/dist/components/sparkline/sparkline.component.js +3 -3
- package/package.json +1 -1
- package/src/lib/components/barchartv2/Barchart.component.test.tsx +23 -25
- package/src/lib/components/barchartv2/Barchart.component.tsx +36 -45
- package/src/lib/components/barchartv2/BarchartTooltip.test.tsx +3 -3
- package/src/lib/components/barchartv2/BarchartTooltip.tsx +14 -18
- package/src/lib/components/barchartv2/utils.ts +1 -5
- package/src/lib/components/chartlegend/ChartLegendWrapper.tsx +1 -1
- package/src/lib/components/charttooltip/ChartTooltip.tsx +40 -0
- package/src/lib/components/date/FormattedDateTime.tsx +73 -8
- package/src/lib/components/icon/Icon.component.tsx +1 -0
- package/src/lib/components/linetimeseriechart/linetimeseriechart.component.tsx +43 -34
- package/src/lib/components/linetimeseriechart/utils.test.ts +30 -68
- package/src/lib/components/linetimeseriechart/utils.ts +14 -18
- package/src/lib/components/scrollbarwrapper/ScrollbarWrapper.component.tsx +3 -1
- package/src/lib/components/sparkline/sparkline.component.tsx +5 -3
- package/stories/formattedate.stories.tsx +2 -0
- package/stories/linetimeseriechart.stories.tsx +1 -0
- package/stories/sparkline.stories.tsx +19 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/lib/components/linetimeseriechart/utils.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,qBAAqB,QAA4B,CAAC;AAE/D,MAAM,MAAM,cAAc,GAAG;IAC3B,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;AAElC;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,cAChB,MAAM,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/lib/components/linetimeseriechart/utils.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,qBAAqB,QAA4B,CAAC;AAE/D,MAAM,MAAM,cAAc,GAAG;IAC3B,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;AAElC;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,cAChB,MAAM,YACP,MAAM,KACf,MAaF,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TIME_FORMATER, DAY_MONTH_ABBREVIATED, DAY_MONTH_ABBREVIATED_YEAR, } from '../date/FormattedDateTime';
|
|
2
2
|
export const ONE_YEAR_MILLISECONDS = 366 * 24 * 60 * 60 * 1000;
|
|
3
3
|
/**
|
|
4
4
|
* Formats timestamp for X-axis labels based on time format and data range:
|
|
@@ -10,19 +10,19 @@ export const ONE_YEAR_MILLISECONDS = 366 * 24 * 60 * 60 * 1000;
|
|
|
10
10
|
* @param chartData - The chart data to determine time range for optimal formatting
|
|
11
11
|
* @returns Formatted string for display on X-axis
|
|
12
12
|
*/
|
|
13
|
-
export const formatXAxisLabel = (timestamp,
|
|
13
|
+
export const formatXAxisLabel = (timestamp, duration) => {
|
|
14
14
|
const date = new Date(timestamp);
|
|
15
|
-
if (
|
|
16
|
-
return
|
|
15
|
+
if (duration <= 24 * 60 * 60) {
|
|
16
|
+
return TIME_FORMATER.format(date);
|
|
17
17
|
}
|
|
18
|
-
if (
|
|
19
|
-
return
|
|
18
|
+
else if (duration <= 7 * 24 * 60 * 60) {
|
|
19
|
+
return DAY_MONTH_ABBREVIATED.format(date)
|
|
20
|
+
.replace(',', '')
|
|
21
|
+
.replace(/Sept/g, 'Sep');
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
return DAY_MONTH_ABBREVIATED_YEAR.format(date)
|
|
25
|
+
.replace(/[ ,]/g, '')
|
|
26
|
+
.replace(/Sept/g, 'Sep');
|
|
20
27
|
}
|
|
21
|
-
const timestamps = chartData.map((d) => d.timestamp);
|
|
22
|
-
const minTimestamp = Math.min(...timestamps);
|
|
23
|
-
const maxTimestamp = Math.max(...timestamps);
|
|
24
|
-
const timeRangeMilliseconds = maxTimestamp - minTimestamp;
|
|
25
|
-
return timeRangeMilliseconds >= ONE_YEAR_MILLISECONDS
|
|
26
|
-
? YEAR_MONTH_DAY_FORMATTER.format(date)
|
|
27
|
-
: MONTH_DAY_FORMATTER.format(date);
|
|
28
28
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ScrollbarWrapper.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/scrollbarwrapper/ScrollbarWrapper.component.tsx"],"names":[],"mappings":"AAEA,KAAK,KAAK,GAAG;IACX,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,CAAC;
|
|
1
|
+
{"version":3,"file":"ScrollbarWrapper.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/scrollbarwrapper/ScrollbarWrapper.component.tsx"],"names":[],"mappings":"AAEA,KAAK,KAAK,GAAG;IACX,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,CAAC;AAqDF,iBAAS,gBAAgB,CAAC,EAAE,QAAQ,EAAE,EAAE,KAAK,2CAO5C;AAED,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -20,6 +20,7 @@ ${(props) => {
|
|
|
20
20
|
width: 4px;
|
|
21
21
|
height: 4px;
|
|
22
22
|
min-height: 20px;
|
|
23
|
+
background: ${brand.border}; // fallback for gradient themes
|
|
23
24
|
background: ${brand.buttonSecondary};
|
|
24
25
|
border-radius: 4px;
|
|
25
26
|
-webkit-border-radius: 4px;
|
|
@@ -42,6 +43,7 @@ ${(props) => {
|
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
// Firefox
|
|
46
|
+
scrollbar-color: ${brand.border} ${brand.backgroundLevel3}; // fallback for gradient themes
|
|
45
47
|
scrollbar-color: ${brand.buttonSecondary} ${brand.backgroundLevel3};
|
|
46
48
|
scrollbar-width: thin;
|
|
47
49
|
}
|
|
@@ -6,11 +6,12 @@ type SparklineProps = {
|
|
|
6
6
|
startingTimeStamp: number;
|
|
7
7
|
sampleDuration: number;
|
|
8
8
|
sampleInterval: number;
|
|
9
|
+
yAxisType?: 'default' | 'percentage';
|
|
9
10
|
};
|
|
10
11
|
/**
|
|
11
12
|
* Sparkline is a simple dynamically sized area chart.
|
|
12
13
|
* Used to show trends in data over time.
|
|
13
14
|
*/
|
|
14
|
-
export declare function Sparkline({ serie, startingTimeStamp, sampleDuration, sampleInterval }: SparklineProps): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
export declare function Sparkline({ serie, startingTimeStamp, sampleDuration, sampleInterval, yAxisType }: SparklineProps): import("react/jsx-runtime").JSX.Element;
|
|
15
16
|
export {};
|
|
16
17
|
//# sourceMappingURL=sparkline.component.d.ts.map
|
|
@@ -1 +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,
|
|
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,CAAC;IACvB,SAAS,CAAC,EAAE,SAAS,GAAG,YAAY,CAAC;CACtC,CAAC;AAEF;;;GAGG;AACH,wBAAgB,SAAS,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,cAAc,EAAE,SAAS,EAAE,EAAE,cAAc,2CAkChH"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useMemo } from "react";
|
|
3
|
-
import { Area, AreaChart, CartesianGrid, ResponsiveContainer } from "recharts";
|
|
3
|
+
import { Area, AreaChart, CartesianGrid, ResponsiveContainer, YAxis } from "recharts";
|
|
4
4
|
import { useTheme } from "styled-components";
|
|
5
5
|
import { chartColors } from "../../style/theme";
|
|
6
6
|
import { addMissingDataPoint } from "../linetemporalchart/ChartUtil";
|
|
@@ -8,7 +8,7 @@ import { addMissingDataPoint } from "../linetemporalchart/ChartUtil";
|
|
|
8
8
|
* Sparkline is a simple dynamically sized area chart.
|
|
9
9
|
* Used to show trends in data over time.
|
|
10
10
|
*/
|
|
11
|
-
export function Sparkline({ serie, startingTimeStamp, sampleDuration, sampleInterval }) {
|
|
11
|
+
export function Sparkline({ serie, startingTimeStamp, sampleDuration, sampleInterval, yAxisType }) {
|
|
12
12
|
var _a;
|
|
13
13
|
const data = useMemo(() => {
|
|
14
14
|
const dataMdp = addMissingDataPoint(serie.data, startingTimeStamp, sampleDuration, sampleInterval);
|
|
@@ -16,5 +16,5 @@ export function Sparkline({ serie, startingTimeStamp, sampleDuration, sampleInte
|
|
|
16
16
|
}, [serie.data]);
|
|
17
17
|
const color = (_a = serie.color) !== null && _a !== void 0 ? _a : chartColors.lineColor1;
|
|
18
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 })] }) }));
|
|
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 }), yAxisType === 'percentage' && _jsx(YAxis, { domain: [0, 100], hide: true })] }) }));
|
|
20
20
|
}
|
package/package.json
CHANGED
|
@@ -89,9 +89,9 @@ describe('Barchart', () => {
|
|
|
89
89
|
</Wrapper>,
|
|
90
90
|
);
|
|
91
91
|
|
|
92
|
-
expect(screen.getByText('
|
|
93
|
-
expect(screen.getByText('
|
|
94
|
-
expect(screen.getByText('
|
|
92
|
+
expect(screen.getByText('05 Jul')).toBeInTheDocument();
|
|
93
|
+
expect(screen.getByText('06 Jul')).toBeInTheDocument();
|
|
94
|
+
expect(screen.getByText('07 Jul')).toBeInTheDocument();
|
|
95
95
|
});
|
|
96
96
|
it('should render the Barchart component with error state', async () => {
|
|
97
97
|
const { Wrapper } = getWrapper();
|
|
@@ -153,11 +153,11 @@ describe('Barchart', () => {
|
|
|
153
153
|
</ChartLegendWrapper>
|
|
154
154
|
</Wrapper>,
|
|
155
155
|
);
|
|
156
|
-
expect(screen.getByText('
|
|
157
|
-
expect(screen.getByText('
|
|
158
|
-
expect(screen.getByText('
|
|
159
|
-
expect(screen.getByText('
|
|
160
|
-
expect(screen.getByText('
|
|
156
|
+
expect(screen.getByText('03 Jul')).toBeInTheDocument();
|
|
157
|
+
expect(screen.getByText('04 Jul')).toBeInTheDocument();
|
|
158
|
+
expect(screen.getByText('05 Jul')).toBeInTheDocument();
|
|
159
|
+
expect(screen.getByText('06 Jul')).toBeInTheDocument();
|
|
160
|
+
expect(screen.getByText('07 Jul')).toBeInTheDocument();
|
|
161
161
|
});
|
|
162
162
|
it('should render when there are missing data in the time range', async () => {
|
|
163
163
|
const bars = [
|
|
@@ -203,10 +203,10 @@ describe('Barchart', () => {
|
|
|
203
203
|
|
|
204
204
|
// Check that all days are present
|
|
205
205
|
await waitFor(() => {
|
|
206
|
-
expect(screen.getByText('
|
|
207
|
-
expect(screen.getByText('
|
|
208
|
-
expect(screen.getByText('
|
|
209
|
-
expect(screen.getByText('
|
|
206
|
+
expect(screen.getByText('05 Jul')).toBeInTheDocument();
|
|
207
|
+
expect(screen.getByText('06 Jul')).toBeInTheDocument();
|
|
208
|
+
expect(screen.getByText('07 Jul')).toBeInTheDocument();
|
|
209
|
+
expect(screen.getByText('08 Jul')).toBeInTheDocument();
|
|
210
210
|
});
|
|
211
211
|
});
|
|
212
212
|
it('should render for a specific time range', async () => {
|
|
@@ -244,13 +244,13 @@ describe('Barchart', () => {
|
|
|
244
244
|
</Wrapper>,
|
|
245
245
|
);
|
|
246
246
|
await waitFor(() => {
|
|
247
|
-
expect(screen.getByText('
|
|
248
|
-
expect(screen.getByText('
|
|
249
|
-
expect(screen.getByText('
|
|
250
|
-
expect(screen.getByText('
|
|
251
|
-
expect(screen.getByText('
|
|
252
|
-
expect(screen.getByText('
|
|
253
|
-
expect(screen.getByText('
|
|
247
|
+
expect(screen.getByText('05 Jul')).toBeInTheDocument();
|
|
248
|
+
expect(screen.getByText('06 Jul')).toBeInTheDocument();
|
|
249
|
+
expect(screen.getByText('07 Jul')).toBeInTheDocument();
|
|
250
|
+
expect(screen.getByText('08 Jul')).toBeInTheDocument();
|
|
251
|
+
expect(screen.getByText('09 Jul')).toBeInTheDocument();
|
|
252
|
+
expect(screen.getByText('10 Jul')).toBeInTheDocument();
|
|
253
|
+
expect(screen.getByText('11 Jul')).toBeInTheDocument();
|
|
254
254
|
});
|
|
255
255
|
});
|
|
256
256
|
it('should render the Barchart component with hourly intervals', async () => {
|
|
@@ -411,7 +411,7 @@ describe('Barchart', () => {
|
|
|
411
411
|
/>
|
|
412
412
|
</Wrapper>,
|
|
413
413
|
);
|
|
414
|
-
expect(screen.getByText('
|
|
414
|
+
expect(screen.getByText('05 Jul')).toBeInTheDocument();
|
|
415
415
|
});
|
|
416
416
|
|
|
417
417
|
it('should render the CustomTick component with day format', () => {
|
|
@@ -435,7 +435,7 @@ describe('Barchart', () => {
|
|
|
435
435
|
/>
|
|
436
436
|
</Wrapper>,
|
|
437
437
|
);
|
|
438
|
-
expect(screen.getByText('
|
|
438
|
+
expect(screen.getByText('05 Jul')).toBeInTheDocument();
|
|
439
439
|
});
|
|
440
440
|
it('should render the CustomTick component with hour format', () => {
|
|
441
441
|
const { Wrapper } = getWrapper();
|
|
@@ -458,7 +458,7 @@ describe('Barchart', () => {
|
|
|
458
458
|
/>
|
|
459
459
|
</Wrapper>,
|
|
460
460
|
);
|
|
461
|
-
expect(screen.getByText('
|
|
461
|
+
expect(screen.getByText('05 Jul')).toBeInTheDocument();
|
|
462
462
|
});
|
|
463
463
|
it('should render the CustomTick component with minute format', () => {
|
|
464
464
|
const { Wrapper } = getWrapper();
|
|
@@ -481,9 +481,7 @@ describe('Barchart', () => {
|
|
|
481
481
|
/>
|
|
482
482
|
</Wrapper>,
|
|
483
483
|
);
|
|
484
|
-
expect(
|
|
485
|
-
screen.getByText(new Date('2024-07-05T10:00:00').getTime()),
|
|
486
|
-
).toBeInTheDocument();
|
|
484
|
+
expect(screen.getByText('05 Jul')).toBeInTheDocument();
|
|
487
485
|
});
|
|
488
486
|
});
|
|
489
487
|
});
|
|
@@ -3,7 +3,6 @@ import {
|
|
|
3
3
|
Bar,
|
|
4
4
|
BarChart,
|
|
5
5
|
CartesianGrid,
|
|
6
|
-
ReferenceLine,
|
|
7
6
|
ResponsiveContainer,
|
|
8
7
|
Tooltip,
|
|
9
8
|
TooltipContentProps,
|
|
@@ -112,33 +111,19 @@ interface CustomTickProps {
|
|
|
112
111
|
/* ---------------------------------- COMPONENTS ---------------------------------- */
|
|
113
112
|
|
|
114
113
|
/**
|
|
115
|
-
*
|
|
116
|
-
* @param
|
|
117
|
-
* @param interval - Interval in milliseconds
|
|
114
|
+
* Get the format of the date based on the duration
|
|
115
|
+
* @param duration - Duration in milliseconds
|
|
118
116
|
* @returns Formatted string
|
|
119
117
|
*/
|
|
120
118
|
export const formatDate = (
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
return (
|
|
128
|
-
<>
|
|
129
|
-
<FormattedDateTime format="chart-date" value={date} />{' '}
|
|
130
|
-
<FormattedDateTime format="time" value={date} />
|
|
131
|
-
</>
|
|
132
|
-
);
|
|
133
|
-
} else if (interval === 24 * 60 * 60 * 1000) {
|
|
134
|
-
// Daily interval - use day format
|
|
135
|
-
return <FormattedDateTime format="chart-date" value={date} />;
|
|
136
|
-
} else if (interval >= 60 * 1000) {
|
|
137
|
-
//Hourly and minute intervals - use minute format
|
|
138
|
-
return <FormattedDateTime format="time" value={date} />;
|
|
119
|
+
duration: number,
|
|
120
|
+
): 'time' | 'day-month-abbreviated' | 'chart-long-term-date' => {
|
|
121
|
+
if (duration <= 24 * 60 * 60 * 1000) {
|
|
122
|
+
return 'time';
|
|
123
|
+
} else if (duration <= 7 * 24 * 60 * 60 * 1000) {
|
|
124
|
+
return 'day-month-abbreviated';
|
|
139
125
|
} else {
|
|
140
|
-
|
|
141
|
-
return timestamp;
|
|
126
|
+
return 'chart-long-term-date';
|
|
142
127
|
}
|
|
143
128
|
};
|
|
144
129
|
|
|
@@ -155,10 +140,15 @@ export const CustomTick = ({
|
|
|
155
140
|
width / visibleTicksCount - CHART_CONSTANTS.TICK_WIDTH_OFFSET;
|
|
156
141
|
const centerX = x - tickWidth / 2;
|
|
157
142
|
|
|
143
|
+
const duration =
|
|
144
|
+
type.type === 'time'
|
|
145
|
+
? type.timeRange.endDate.getTime() - type.timeRange.startDate.getTime()
|
|
146
|
+
: 0;
|
|
147
|
+
|
|
158
148
|
return (
|
|
159
149
|
<foreignObject
|
|
160
150
|
x={centerX}
|
|
161
|
-
y={y}
|
|
151
|
+
y={y - 8}
|
|
162
152
|
width={tickWidth}
|
|
163
153
|
color={theme.textSecondary}
|
|
164
154
|
overflow="visible"
|
|
@@ -167,9 +157,14 @@ export const CustomTick = ({
|
|
|
167
157
|
color="textSecondary"
|
|
168
158
|
text={
|
|
169
159
|
<Text variant="Smaller">
|
|
170
|
-
{type.type === 'time'
|
|
171
|
-
|
|
172
|
-
|
|
160
|
+
{type.type === 'time' ? (
|
|
161
|
+
<FormattedDateTime
|
|
162
|
+
format={formatDate(duration)}
|
|
163
|
+
value={new Date(payload.value)}
|
|
164
|
+
/>
|
|
165
|
+
) : (
|
|
166
|
+
String(payload.value)
|
|
167
|
+
)}
|
|
173
168
|
</Text>
|
|
174
169
|
}
|
|
175
170
|
centered
|
|
@@ -185,7 +180,7 @@ export const CustomTick = ({
|
|
|
185
180
|
);
|
|
186
181
|
};
|
|
187
182
|
|
|
188
|
-
const StyledResponsiveContainer = styled(ResponsiveContainer)`
|
|
183
|
+
export const StyledResponsiveContainer = styled(ResponsiveContainer)`
|
|
189
184
|
// Avoid tooltip over constrained text to be cut off
|
|
190
185
|
& .recharts-surface {
|
|
191
186
|
overflow: visible;
|
|
@@ -304,7 +299,7 @@ export const Barchart = <T extends BarchartBars>(props: BarchartProps<T>) => {
|
|
|
304
299
|
);
|
|
305
300
|
|
|
306
301
|
return (
|
|
307
|
-
<Stack direction="vertical"
|
|
302
|
+
<Stack direction="vertical">
|
|
308
303
|
<ChartHeader
|
|
309
304
|
title={title}
|
|
310
305
|
secondaryTitle={secondaryTitle}
|
|
@@ -332,9 +327,13 @@ export const Barchart = <T extends BarchartBars>(props: BarchartProps<T>) => {
|
|
|
332
327
|
barCategoryGap={type.type === 'category' ? type.gap : undefined}
|
|
333
328
|
>
|
|
334
329
|
<CartesianGrid
|
|
335
|
-
vertical={
|
|
336
|
-
horizontal={
|
|
337
|
-
|
|
330
|
+
vertical={true}
|
|
331
|
+
horizontal={true}
|
|
332
|
+
verticalPoints={[0]}
|
|
333
|
+
horizontalPoints={[0]}
|
|
334
|
+
stroke={theme.border}
|
|
335
|
+
fill={theme.backgroundLevel4}
|
|
336
|
+
strokeWidth={1}
|
|
338
337
|
/>
|
|
339
338
|
{rechartsBars.map((bar) => {
|
|
340
339
|
const { fill, dataKey, stackId } = bar;
|
|
@@ -354,29 +353,21 @@ export const Barchart = <T extends BarchartBars>(props: BarchartProps<T>) => {
|
|
|
354
353
|
|
|
355
354
|
<YAxis
|
|
356
355
|
tickCount={1}
|
|
356
|
+
interval={0}
|
|
357
357
|
unit={` ${unitLabel}`}
|
|
358
358
|
domain={[0, roundReferenceValue]}
|
|
359
359
|
tickFormatter={
|
|
360
360
|
(value) =>
|
|
361
361
|
new Intl.NumberFormat('fr-FR').format(value.toFixed(0)) // Add a space as thousand separator
|
|
362
362
|
}
|
|
363
|
-
axisLine={
|
|
363
|
+
axisLine={{ stroke: theme.border }}
|
|
364
364
|
tick={{
|
|
365
365
|
fill: theme.textSecondary,
|
|
366
366
|
fontSize: fontSize.smaller,
|
|
367
367
|
}}
|
|
368
|
-
tickLine={false}
|
|
369
|
-
label={{
|
|
370
|
-
fill: theme.textSecondary,
|
|
371
|
-
}}
|
|
372
368
|
orientation="right"
|
|
373
369
|
/>
|
|
374
370
|
|
|
375
|
-
<ReferenceLine
|
|
376
|
-
y={roundReferenceValue}
|
|
377
|
-
fill={theme.border}
|
|
378
|
-
strokeWidth={0.5} // Reduce stroke width to make it less visible
|
|
379
|
-
/>
|
|
380
371
|
<XAxis
|
|
381
372
|
dataKey="category"
|
|
382
373
|
tick={(props) => <CustomTick {...props} type={type} />}
|
|
@@ -384,10 +375,10 @@ export const Barchart = <T extends BarchartBars>(props: BarchartProps<T>) => {
|
|
|
384
375
|
interval={0}
|
|
385
376
|
allowDataOverflow={true}
|
|
386
377
|
tickLine={{
|
|
387
|
-
stroke: theme.
|
|
378
|
+
stroke: theme.border,
|
|
388
379
|
}}
|
|
389
380
|
axisLine={{
|
|
390
|
-
stroke: theme.
|
|
381
|
+
stroke: theme.border,
|
|
391
382
|
}}
|
|
392
383
|
/>
|
|
393
384
|
|
|
@@ -30,6 +30,7 @@ describe('ChartTooltip', () => {
|
|
|
30
30
|
longDate: () => screen.queryByText(/01 July 2024/),
|
|
31
31
|
date: () => screen.queryByText(/\b01 Jul\b/),
|
|
32
32
|
time: () => screen.queryByText(/00:00:00/),
|
|
33
|
+
dateTime: () => screen.queryByText(/01 Jul 00:00:00/),
|
|
33
34
|
};
|
|
34
35
|
it('should render the BarchartTooltip component', () => {
|
|
35
36
|
render(
|
|
@@ -89,9 +90,8 @@ describe('ChartTooltip', () => {
|
|
|
89
90
|
expect(selectors.successValue()).toBeInTheDocument();
|
|
90
91
|
expect(selectors.failed()).toBeInTheDocument();
|
|
91
92
|
expect(selectors.failedValue()).toBeInTheDocument();
|
|
92
|
-
|
|
93
|
-
expect(selectors.
|
|
94
|
-
expect(selectors.time()).not.toBeInTheDocument();
|
|
93
|
+
|
|
94
|
+
expect(selectors.dateTime()).toBeInTheDocument();
|
|
95
95
|
});
|
|
96
96
|
it('should render time tooltip when type is time and interval is one hour', () => {
|
|
97
97
|
const label = date;
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
+
import { TooltipContentProps } from 'recharts';
|
|
2
|
+
import { LegendShape } from '../chartlegend/ChartLegend';
|
|
3
|
+
import {
|
|
4
|
+
ChartTooltipContainer,
|
|
5
|
+
ChartTooltipHeader,
|
|
6
|
+
ChartTooltipItem,
|
|
7
|
+
ChartTooltipItemsContainer,
|
|
8
|
+
TooltipHeader,
|
|
9
|
+
} from '../charttooltip/ChartTooltip';
|
|
1
10
|
import {
|
|
2
11
|
BarchartBars,
|
|
3
12
|
BarchartTooltipFn,
|
|
4
13
|
CategoryType,
|
|
5
14
|
TimeType,
|
|
6
15
|
} from './Barchart.component';
|
|
7
|
-
import { FormattedDateTime } from '../date/FormattedDateTime';
|
|
8
|
-
import { TooltipContentProps } from 'recharts';
|
|
9
16
|
import { getCurrentPoint } from './utils';
|
|
10
|
-
import {
|
|
11
|
-
ChartTooltipContainer,
|
|
12
|
-
ChartTooltipItem,
|
|
13
|
-
ChartTooltipHeader,
|
|
14
|
-
ChartTooltipItemsContainer,
|
|
15
|
-
} from '../charttooltip/ChartTooltip';
|
|
16
|
-
import { LegendShape } from '../chartlegend/ChartLegend';
|
|
17
17
|
|
|
18
18
|
export const BarchartTooltip = <T extends BarchartBars>({
|
|
19
19
|
type,
|
|
@@ -40,19 +40,15 @@ export const BarchartTooltip = <T extends BarchartBars>({
|
|
|
40
40
|
if (tooltip) {
|
|
41
41
|
return tooltip(currentPoint);
|
|
42
42
|
}
|
|
43
|
-
|
|
43
|
+
const duration =
|
|
44
|
+
type.type === 'time'
|
|
45
|
+
? type.timeRange.startDate.getTime() - type.timeRange.endDate.getTime()
|
|
46
|
+
: 0;
|
|
44
47
|
return (
|
|
45
48
|
<ChartTooltipContainer>
|
|
46
49
|
<ChartTooltipHeader>
|
|
47
50
|
{type.type === 'time' ? (
|
|
48
|
-
<
|
|
49
|
-
format={
|
|
50
|
-
type.timeRange.interval < 24 * 60 * 60 * 1000
|
|
51
|
-
? 'day-month-abbreviated-hour-minute-second'
|
|
52
|
-
: 'long-date-without-weekday'
|
|
53
|
-
}
|
|
54
|
-
value={new Date(currentPoint.category)}
|
|
55
|
-
/>
|
|
51
|
+
<TooltipHeader duration={duration} value={currentPoint.category} />
|
|
56
52
|
) : (
|
|
57
53
|
currentPoint.category
|
|
58
54
|
)}
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
BarchartProps,
|
|
3
|
-
BarchartBars,
|
|
4
|
-
BarchartTooltipFn,
|
|
5
|
-
} from './Barchart.component';
|
|
1
|
+
import { BarchartProps, BarchartBars } from './Barchart.component';
|
|
6
2
|
import { TooltipContentProps } from 'recharts';
|
|
7
3
|
import { chartColors, ChartColors } from '../../style/theme';
|
|
8
4
|
import { useChartLegend } from '../chartlegend/ChartLegendWrapper';
|
|
@@ -133,7 +133,7 @@ export const ChartLegendWrapper = ({
|
|
|
133
133
|
);
|
|
134
134
|
|
|
135
135
|
const listResources = useCallback(() => {
|
|
136
|
-
return Object.keys(internalColorSet);
|
|
136
|
+
return Object.keys(internalColorSet).sort();
|
|
137
137
|
}, [internalColorSet]);
|
|
138
138
|
|
|
139
139
|
const chartLegendState = useMemo(
|
|
@@ -2,6 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import styled from 'styled-components';
|
|
3
3
|
import { spacing } from '../../spacing';
|
|
4
4
|
import { fontSize, fontWeight } from '../../style/theme';
|
|
5
|
+
import { FormattedDateTime } from '../date/FormattedDateTime';
|
|
5
6
|
|
|
6
7
|
export const ChartTooltipContainer = styled.div`
|
|
7
8
|
border: 1px solid ${({ theme }) => theme.border};
|
|
@@ -81,3 +82,42 @@ export const ChartTooltipItemsContainer = styled.div`
|
|
|
81
82
|
gap: ${spacing.r8};
|
|
82
83
|
width: 100%;
|
|
83
84
|
`;
|
|
85
|
+
|
|
86
|
+
export const ChartTooltipSeparator = styled.div`
|
|
87
|
+
height: 1px;
|
|
88
|
+
background-color: ${({ theme }) => theme.border};
|
|
89
|
+
margin: ${spacing.r4} 0;
|
|
90
|
+
width: 100%;
|
|
91
|
+
`;
|
|
92
|
+
|
|
93
|
+
export type TooltipDateFormat =
|
|
94
|
+
| 'day-month-abbreviated-year-hour-minute'
|
|
95
|
+
| 'day-month-abbreviated-hour-minute-second'
|
|
96
|
+
| 'day-month-abbreviated-hour-minute';
|
|
97
|
+
|
|
98
|
+
const getTooltipDateFormat: (duration: number) => TooltipDateFormat = (
|
|
99
|
+
duration: number,
|
|
100
|
+
) => {
|
|
101
|
+
if (duration <= 60 * 60 * 1000) {
|
|
102
|
+
return 'day-month-abbreviated-hour-minute-second';
|
|
103
|
+
} else if (duration <= 7 * 24 * 60 * 60 * 1000) {
|
|
104
|
+
return 'day-month-abbreviated-hour-minute';
|
|
105
|
+
} else {
|
|
106
|
+
return 'day-month-abbreviated-year-hour-minute';
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
export const TooltipHeader = ({
|
|
111
|
+
duration,
|
|
112
|
+
value,
|
|
113
|
+
}: {
|
|
114
|
+
duration: number;
|
|
115
|
+
value: string | number;
|
|
116
|
+
}) => {
|
|
117
|
+
const timeFormat = getTooltipDateFormat(duration);
|
|
118
|
+
return (
|
|
119
|
+
<ChartTooltipHeader>
|
|
120
|
+
<FormattedDateTime format={timeFormat} value={new Date(value)} />
|
|
121
|
+
</ChartTooltipHeader>
|
|
122
|
+
);
|
|
123
|
+
};
|