@centreon/ui 24.4.57 → 24.4.59

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.
Files changed (147) hide show
  1. package/package.json +31 -38
  2. package/public/mockServiceWorker.js +1 -1
  3. package/src/Button/Icon/index.tsx +1 -1
  4. package/src/Button/Save/StartIcon.tsx +3 -3
  5. package/src/Button/Save/index.tsx +5 -9
  6. package/src/Checkbox/Checkbox.tsx +2 -2
  7. package/src/Checkbox/CheckboxGroup/index.tsx +2 -2
  8. package/src/Dashboard/Item.tsx +1 -1
  9. package/src/Dashboard/Layout.tsx +2 -2
  10. package/src/Dialog/Confirm/index.tsx +2 -10
  11. package/src/Dialog/index.tsx +2 -9
  12. package/src/FallbackPage/FallbackPage.tsx +3 -3
  13. package/src/FileDropZone/index.tsx +1 -3
  14. package/src/Form/Inputs/index.tsx +1 -3
  15. package/src/Form/Inputs/models.ts +1 -9
  16. package/src/Graph/Gauge/Gauge.tsx +1 -1
  17. package/src/Graph/HeatMap/HeatMap.stories.tsx +25 -0
  18. package/src/Graph/HeatMap/ResponsiveHeatMap.tsx +2 -8
  19. package/src/Graph/LineChart/BasicComponents/Lines/Threshold/Circle.tsx +2 -2
  20. package/src/Graph/LineChart/BasicComponents/Thresholds.tsx +2 -2
  21. package/src/Graph/LineChart/BasicComponents/useFilterLines.ts +1 -1
  22. package/src/Graph/LineChart/InteractiveComponents/AnchorPoint/GuidingLines.tsx +2 -2
  23. package/src/Graph/LineChart/InteractiveComponents/Annotations/EventAnnotations.tsx +1 -1
  24. package/src/Graph/LineChart/Legend/Legend.styles.ts +1 -1
  25. package/src/Graph/LineChart/Legend/LegendHeader.tsx +1 -1
  26. package/src/Graph/LineChart/Legend/useInteractiveValues.ts +2 -2
  27. package/src/Graph/LineChart/Legend/useLegend.ts +3 -3
  28. package/src/Graph/LineChart/helpers/doc.ts +13 -16
  29. package/src/Graph/LineChart/helpers/index.ts +1 -1
  30. package/src/Graph/LineChart/index.stories.tsx +2 -4
  31. package/src/Graph/LineChart/index.tsx +1 -1
  32. package/src/Graph/SingleBar/Thresholds.tsx +2 -2
  33. package/src/Graph/Text/Text.stories.tsx +4 -60
  34. package/src/Graph/Text/Text.tsx +1 -1
  35. package/src/Graph/common/timeSeries/index.ts +14 -22
  36. package/src/Graph/common/utils.ts +0 -19
  37. package/src/Graph/index.ts +0 -3
  38. package/src/InputField/Select/Autocomplete/Connected/index.tsx +7 -10
  39. package/src/InputField/Select/Autocomplete/Draggable/SortableList.tsx +1 -1
  40. package/src/InputField/Select/Autocomplete/Draggable/SortableListContent.tsx +1 -1
  41. package/src/InputField/Select/Autocomplete/Draggable/index.tsx +1 -1
  42. package/src/InputField/Select/Autocomplete/Multi/index.tsx +2 -4
  43. package/src/InputField/Select/Autocomplete/index.tsx +116 -129
  44. package/src/InputField/Select/IconPopover/index.tsx +2 -2
  45. package/src/InputField/Select/index.tsx +1 -12
  46. package/src/InputField/Text/index.tsx +2 -2
  47. package/src/Listing/ActionBar/index.tsx +8 -9
  48. package/src/Listing/Cell/DataCell.styles.ts +0 -3
  49. package/src/Listing/Cell/DataCell.tsx +5 -23
  50. package/src/Listing/Header/ListingHeader.tsx +1 -1
  51. package/src/Listing/Listing.cypress.spec.tsx +4 -80
  52. package/src/Listing/Listing.styles.ts +7 -4
  53. package/src/Listing/index.stories.tsx +3 -37
  54. package/src/Listing/index.test.tsx +1 -1
  55. package/src/Listing/index.tsx +3 -4
  56. package/src/Listing/models.ts +0 -1
  57. package/src/Module/index.tsx +4 -2
  58. package/src/PopoverMenu/index.tsx +5 -6
  59. package/src/RichTextEditor/RichTextEditor.tsx +1 -12
  60. package/src/SortableItems/index.tsx +7 -2
  61. package/src/ThemeProvider/index.tsx +0 -24
  62. package/src/TimePeriods/CustomTimePeriod/CompactCustomTimePeriod.styles.ts +7 -6
  63. package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/PickersStartEndDate.tsx +3 -8
  64. package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/models.ts +2 -0
  65. package/src/TimePeriods/DateTimePickerInput.tsx +19 -56
  66. package/src/TimePeriods/ResolutionTimePeriod.cypress.spec.tsx +9 -12
  67. package/src/TimePeriods/TimePeriods.cypress.spec.tsx +33 -9
  68. package/src/TimePeriods/helpers/index.ts +1 -1
  69. package/src/TimePeriods/index.stories.tsx +4 -12
  70. package/src/TimePeriods/index.tsx +2 -2
  71. package/src/Typography/FluidTypography/index.stories.tsx +2 -2
  72. package/src/Typography/FluidTypography/index.tsx +28 -21
  73. package/src/Typography/FluidTypography/useFluidResizeObserver.ts +56 -0
  74. package/src/api/QueryProvider.tsx +1 -1
  75. package/src/api/TestQueryProvider.tsx +1 -1
  76. package/src/api/index.ts +3 -3
  77. package/src/api/useFetchQuery/index.ts +23 -27
  78. package/src/api/useMutationQuery/index.test.ts +4 -4
  79. package/src/api/useMutationQuery/index.ts +25 -60
  80. package/src/components/Button/Icon/IconButton.tsx +2 -6
  81. package/src/components/DataTable/DataTable.stories.tsx +0 -40
  82. package/src/components/DataTable/DataTable.styles.ts +0 -3
  83. package/src/components/DataTable/DataTable.tsx +3 -3
  84. package/src/components/DataTable/Item/DataTableItem.styles.ts +2 -7
  85. package/src/components/DataTable/Item/DataTableItem.tsx +28 -9
  86. package/src/components/DataTable/index.ts +1 -3
  87. package/src/components/Form/AccessRights/ShareInput/ContactSwitch.tsx +3 -3
  88. package/src/components/Form/AccessRights/ShareInput/ShareInput.tsx +0 -1
  89. package/src/components/Form/Dashboard/DashboardForm.tsx +12 -15
  90. package/src/components/Layout/PageLayout/PageLayout.tsx +1 -1
  91. package/src/components/Layout/PageLayout/PageLayoutActions.tsx +0 -1
  92. package/src/components/Layout/PageLayout/PageLayoutBody.tsx +0 -1
  93. package/src/components/Layout/PageLayout/PageLayoutHeader.tsx +1 -5
  94. package/src/components/Layout/PageLayout/index.ts +1 -3
  95. package/src/components/List/Item/ListItem.tsx +3 -3
  96. package/src/components/Modal/Modal.styles.ts +3 -8
  97. package/src/components/Tooltip/ConfirmationTooltip/ConfirmationTooltip.stories.tsx +3 -3
  98. package/src/components/Tooltip/ConfirmationTooltip/ConfirmationTooltip.tsx +1 -1
  99. package/src/components/Tooltip/ConfirmationTooltip/models.ts +1 -1
  100. package/src/index.ts +2 -2
  101. package/src/queryParameters/url/index.ts +1 -5
  102. package/src/screens/dashboard/DashboardsDetail.stories.tsx +108 -0
  103. package/src/screens/dashboard/DashboardsOverview.stories.tsx +281 -0
  104. package/src/utils/index.ts +1 -1
  105. package/src/utils/useDateTimePickerAdapter.ts +309 -0
  106. package/src/utils/useFullscreen/Fullscreen.cypress.spec.tsx +3 -1
  107. package/src/utils/useFullscreen/useFullscreenListener.ts +7 -10
  108. package/src/utils/useInfiniteScrollListing.ts +1 -4
  109. package/src/utils/{useLicenseExpirationWarning.test.tsx → useLicenseExpirationWarning.cypress.spec.tsx} +37 -48
  110. package/src/utils/useLicenseExpirationWarning.ts +18 -18
  111. package/src/Form/Form.cypress.spec.tsx +0 -133
  112. package/src/Form/Inputs/List/Content.tsx +0 -62
  113. package/src/Form/Inputs/List/List.styles.ts +0 -29
  114. package/src/Form/Inputs/List/List.tsx +0 -58
  115. package/src/Form/Inputs/List/useList.ts +0 -81
  116. package/src/Graph/BarStack/BarStack.cypress.spec.tsx +0 -154
  117. package/src/Graph/BarStack/BarStack.stories.tsx +0 -123
  118. package/src/Graph/BarStack/BarStack.styles.ts +0 -37
  119. package/src/Graph/BarStack/BarStack.tsx +0 -14
  120. package/src/Graph/BarStack/ResponsiveBarStack.tsx +0 -222
  121. package/src/Graph/BarStack/index.ts +0 -1
  122. package/src/Graph/BarStack/models.ts +0 -20
  123. package/src/Graph/BarStack/useResponsiveBarStack.ts +0 -137
  124. package/src/Graph/Gauge/Gauge.cypress.spec.tsx +0 -102
  125. package/src/Graph/HeatMap/HeatMap.cypress.spec.tsx +0 -145
  126. package/src/Graph/Legend/Legend.tsx +0 -21
  127. package/src/Graph/Legend/index.ts +0 -1
  128. package/src/Graph/Legend/models.ts +0 -11
  129. package/src/Graph/PieChart/PieChart.cypress.spec.tsx +0 -169
  130. package/src/Graph/PieChart/PieChart.stories.tsx +0 -194
  131. package/src/Graph/PieChart/PieChart.styles.ts +0 -39
  132. package/src/Graph/PieChart/PieChart.tsx +0 -14
  133. package/src/Graph/PieChart/ResponsivePie.tsx +0 -254
  134. package/src/Graph/PieChart/index.ts +0 -1
  135. package/src/Graph/PieChart/models.ts +0 -20
  136. package/src/Graph/PieChart/useResponsivePie.ts +0 -85
  137. package/src/Graph/SingleBar/SingleBar.cypress.spec.tsx +0 -121
  138. package/src/Graph/Text/Text.cypress.spec.tsx +0 -101
  139. package/src/Graph/common/testUtils.ts +0 -71
  140. package/src/Graph/translatedLabels.ts +0 -1
  141. package/src/Module/Module.cypress.spec.tsx +0 -129
  142. package/src/Typography/FluidTypography/FluidTypography.cypress.spec.tsx +0 -27
  143. package/src/components/DataTable/DataListing.tsx +0 -6
  144. package/src/components/DataTable/DataTable.cypress.spec.tsx +0 -193
  145. package/src/components/Layout/PageLayout/PageQuickAccess.tsx +0 -76
  146. package/src/components/Layout/PageLayout.cypress.spec.tsx +0 -66
  147. package/src/utils/usePluralizedTranslation.ts +0 -21
@@ -1,154 +0,0 @@
1
- import numeral from 'numeral';
2
-
3
- import BarStack from './BarStack';
4
- import { BarType, BarStackProps } from './models';
5
-
6
- const defaultData = [
7
- { color: '#88B922', label: 'Ok', value: 148 },
8
- { color: '#999999', label: 'Unknown', value: 13 },
9
- { color: '#F7931A', label: 'Warning', value: 16 },
10
- { color: '#FF6666', label: 'Down', value: 62 }
11
- ];
12
-
13
- const dataWithNullValues = [
14
- { color: '#88B922', label: 'Ok', value: 0 },
15
- { color: '#999999', label: 'Unknown', value: 0 },
16
- { color: '#F7931A', label: 'Warning', value: 0 },
17
- { color: '#FF6666', label: 'Down', value: 0 }
18
- ];
19
-
20
- const total = Math.floor(
21
- defaultData.reduce((acc, { value }) => acc + value, 0)
22
- );
23
-
24
- const TooltipContent = ({ label, color, value }: BarType): JSX.Element => {
25
- return (
26
- <div data-testid={`tooltip-${label}`} style={{ color }}>
27
- {label} : {value}
28
- </div>
29
- );
30
- };
31
-
32
- const initialize = ({
33
- width = '400px',
34
- height = '400px',
35
- data = defaultData,
36
- ...args
37
- }: Omit<BarStackProps, 'data'> & {
38
- data?;
39
- height?: string;
40
- width?: string;
41
- }): void => {
42
- cy.mount({
43
- Component: (
44
- <div style={{ height, width }}>
45
- <BarStack {...args} data={data} />
46
- </div>
47
- )
48
- });
49
- };
50
-
51
- describe('Bar stack', () => {
52
- it('renders Bar stack correctly with provided data', () => {
53
- initialize({});
54
-
55
- defaultData.forEach(({ label }) => {
56
- cy.findByTestId(label).should('be.visible');
57
- });
58
-
59
- cy.makeSnapshot();
60
- });
61
-
62
- it('adjusts size based on the provided width and height', () => {
63
- initialize({ displayLegend: false, height: '300px', width: '300px' });
64
-
65
- cy.findByTestId('barStack').should('have.css', 'height', '300px');
66
-
67
- cy.makeSnapshot();
68
- });
69
-
70
- it('renders as a horizontal bar when variant is set to "horizontal"', () => {
71
- initialize({ variant: 'horizontal' });
72
- cy.get('[data-variant="horizontal"]').should('exist');
73
-
74
- cy.makeSnapshot();
75
- });
76
-
77
- it('renders as a vertical bar when variant is set to "vertical"', () => {
78
- initialize({ variant: 'vertical' });
79
- cy.get('[data-variant="vertical"]').should('exist');
80
-
81
- cy.makeSnapshot();
82
- });
83
-
84
- it('displays tooltip with correct information on hover', () => {
85
- initialize({ TooltipContent });
86
-
87
- defaultData.forEach(({ label, value }) => {
88
- cy.findByTestId(label).trigger('mouseover', { force: true });
89
-
90
- cy.findByTestId(`tooltip-${label}`)
91
- .should('contain', label)
92
- .and('contain', numeral(value).format('0a').toUpperCase());
93
- });
94
-
95
- cy.makeSnapshot();
96
- });
97
-
98
- it('conditionally displays values on rects based on displayValues prop', () => {
99
- initialize({ displayValues: true });
100
- defaultData.forEach(({ value }, index) => {
101
- cy.findAllByTestId('value')
102
- .eq(index)
103
- .children()
104
- .eq(0)
105
- .should('have.text', value);
106
- });
107
-
108
- initialize({ displayValues: false });
109
- cy.findAllByTestId('value').should('not.exist');
110
-
111
- cy.makeSnapshot();
112
- });
113
-
114
- it('displays values on rects in percentage unit when displayValues is set to true and unit to percentage', () => {
115
- initialize({ displayValues: true, unit: 'percentage' });
116
- defaultData.forEach(({ value }, index) => {
117
- cy.findAllByTestId('value')
118
- .eq(index)
119
- .children()
120
- .eq(0)
121
- .should('have.text', `${((value * 100) / total).toFixed(1)}%`);
122
- });
123
-
124
- cy.makeSnapshot();
125
- });
126
-
127
- it('displays Legend component based on displayLegend prop', () => {
128
- initialize({ displayLegend: true });
129
- cy.findByTestId('Legend').should('be.visible');
130
-
131
- initialize({ displayLegend: false });
132
- cy.findByTestId('Legend').should('not.exist');
133
-
134
- cy.makeSnapshot();
135
- });
136
-
137
- it('displays the title when the title is giving', () => {
138
- initialize({ title: 'host' });
139
- cy.findByTestId('Title').should('be.visible');
140
-
141
- initialize({});
142
- cy.findByTestId('Title').should('not.exist');
143
-
144
- cy.makeSnapshot();
145
- });
146
-
147
- it('displays a message "No Data Available" when all values are null', () => {
148
- initialize({ data: dataWithNullValues, title: 'host' });
149
-
150
- cy.contains('No Data Available');
151
-
152
- cy.makeSnapshot();
153
- });
154
- });
@@ -1,123 +0,0 @@
1
- import { Meta, StoryObj } from '@storybook/react';
2
-
3
- import { BarType } from './models';
4
-
5
- import { BarStack } from '.';
6
-
7
- const data = [
8
- { color: '#88B922', label: 'Ok', value: 148 },
9
- { color: '#999999', label: 'Unknown', value: 63 },
10
- { color: '#F7931A', label: 'Warning', value: 16 },
11
- { color: '#FF6666', label: 'Down', value: 13 }
12
- ];
13
-
14
- const dataWithBigNumbers = [
15
- { color: '#88B922', label: 'Ok', value: 260000 },
16
- { color: '#999999', label: 'Unknown', value: 1010900 },
17
- { color: '#F7931A', label: 'Warning', value: 63114 },
18
- { color: '#FF6666', label: 'Down', value: 122222 }
19
- ];
20
-
21
- const dataWithSmallNumber = [
22
- { color: '#88B922', label: 'Ok', value: 148 },
23
- { color: '#999999', label: 'Unknown', value: 42 },
24
- { color: '#F7931A', label: 'Warning', value: 7 },
25
- { color: '#FF6666', label: 'Down', value: 5 }
26
- ];
27
-
28
- const meta: Meta<typeof BarStack> = {
29
- component: BarStack
30
- };
31
-
32
- export default meta;
33
- type Story = StoryObj<typeof BarStack>;
34
-
35
- const TooltipContent = ({ label, color, value }: BarType): JSX.Element => {
36
- return (
37
- <div style={{ color }}>
38
- {label} : {value}
39
- </div>
40
- );
41
- };
42
-
43
- const Template = (args): JSX.Element => {
44
- return (
45
- <div style={{ height: '300px', width: '500px' }}>
46
- <BarStack {...args} />
47
- </div>
48
- );
49
- };
50
-
51
- export const Vertical: Story = {
52
- args: { data, title: 'hosts' },
53
- render: Template
54
- };
55
-
56
- export const WithoutTitle: Story = {
57
- args: { data },
58
- render: Template
59
- };
60
-
61
- export const WithoutLegend: Story = {
62
- args: { data, displayLegend: false, title: 'hosts' },
63
-
64
- render: Template
65
- };
66
-
67
- export const withDisplayedValues: Story = {
68
- args: { data, displayValues: true, title: 'hosts' },
69
- render: Template
70
- };
71
-
72
- export const WithPencentage: Story = {
73
- args: { data, displayValues: true, title: 'hosts', unit: 'percentage' },
74
- render: Template
75
- };
76
-
77
- export const WithTooltip: Story = {
78
- args: { TooltipContent, data, title: 'hosts' },
79
- render: Template
80
- };
81
-
82
- export const WithBigNumbers: Story = {
83
- args: {
84
- TooltipContent,
85
- data: dataWithBigNumbers,
86
- displayValues: true,
87
- title: 'hosts'
88
- },
89
- render: Template
90
- };
91
-
92
- export const WithSmallNumbers: Story = {
93
- args: {
94
- TooltipContent,
95
- data: dataWithSmallNumber,
96
- displayValues: true,
97
- title: 'hosts'
98
- },
99
- render: Template
100
- };
101
-
102
- export const Horizontal: Story = {
103
- args: {
104
- TooltipContent,
105
- data,
106
- displayValues: true,
107
- title: 'hosts',
108
- variant: 'horizontal'
109
- },
110
- render: Template
111
- };
112
-
113
- export const HorizontalWithoutLegend: Story = {
114
- args: {
115
- TooltipContent,
116
- data,
117
- displayLegend: false,
118
- displayValues: true,
119
- title: 'hosts',
120
- variant: 'horizontal'
121
- },
122
- render: Template
123
- };
@@ -1,37 +0,0 @@
1
- import { makeStyles } from 'tss-react/mui';
2
-
3
- export const useBarStackStyles = makeStyles()((theme) => ({
4
- barStackTooltip: {
5
- backgroundColor: theme.palette.background.paper,
6
- color: theme.palette.text.primary,
7
- padding: 0,
8
- position: 'relative'
9
- },
10
- container: {
11
- alignItems: 'center',
12
- display: 'flex',
13
- gap: theme.spacing(1.5),
14
- justifyContent: 'center'
15
- },
16
- svgContainer: {
17
- alignItems: 'center',
18
- backgroundColor: theme.palette.background.panelGroups,
19
- borderRadius: theme.spacing(1.25),
20
- display: 'flex',
21
- justifyContent: 'center'
22
- },
23
- svgWrapper: {
24
- alignItems: 'center',
25
- display: 'flex',
26
- flexDirection: 'column',
27
- gap: theme.spacing(1),
28
- justifyContent: 'center'
29
- },
30
- title: {
31
- fontSize: theme.typography.h6.fontSize,
32
- fontWeight: theme.typography.fontWeightMedium,
33
- margin: 0,
34
- padding: 0,
35
- textAlign: 'center'
36
- }
37
- }));
@@ -1,14 +0,0 @@
1
- import { ParentSize } from '../..';
2
-
3
- import ResponsiveBarStack from './ResponsiveBarStack';
4
- import { BarStackProps } from './models';
5
-
6
- const Bar = (props: BarStackProps): JSX.Element => (
7
- <ParentSize>
8
- {({ width, height }) => (
9
- <ResponsiveBarStack {...props} height={height} width={width} />
10
- )}
11
- </ParentSize>
12
- );
13
-
14
- export default Bar;
@@ -1,222 +0,0 @@
1
- import { useRef } from 'react';
2
-
3
- import { BarStack as BarStackVertical, BarStackHorizontal } from '@visx/shape';
4
- import { Group } from '@visx/group';
5
- import numeral from 'numeral';
6
- import { Text } from '@visx/text';
7
- import { useTranslation } from 'react-i18next';
8
- import { equals } from 'ramda';
9
-
10
- import { Typography } from '@mui/material';
11
-
12
- import { Tooltip } from '../../components';
13
- import { LegendProps } from '../Legend/models';
14
- import { Legend as LegendComponent } from '../Legend';
15
- import { getValueByUnit } from '../common/utils';
16
- import { labelNoDataFound as defaultlabelNoDataFound } from '../translatedLabels';
17
-
18
- import { BarStackProps } from './models';
19
- import { useBarStackStyles } from './BarStack.styles';
20
- import useResponsiveBarStack from './useResponsiveBarStack';
21
-
22
- const DefaultLengd = ({ scale, direction }: LegendProps): JSX.Element => (
23
- <LegendComponent direction={direction} scale={scale} />
24
- );
25
-
26
- const BarStack = ({
27
- title,
28
- data,
29
- width,
30
- height,
31
- size = 72,
32
- onSingleBarClick,
33
- displayLegend = true,
34
- TooltipContent,
35
- Legend = DefaultLengd,
36
- unit = 'number',
37
- displayValues,
38
- variant = 'vertical',
39
- legendDirection = 'column',
40
- labelNoDataFound = defaultlabelNoDataFound
41
- }: BarStackProps & { height: number; width: number }): JSX.Element => {
42
- const { t } = useTranslation();
43
- const { classes } = useBarStackStyles();
44
-
45
- const titleRef = useRef(null);
46
- const legendRef = useRef(null);
47
-
48
- const {
49
- barSize,
50
- colorScale,
51
- input,
52
- keys,
53
- legendScale,
54
- total,
55
- xScale,
56
- yScale,
57
- svgWrapperWidth,
58
- svgContainerSize,
59
- isVerticalBar,
60
- areAllValuesNull
61
- } = useResponsiveBarStack({
62
- data,
63
- height,
64
- legendRef,
65
- size,
66
- titleRef,
67
- unit,
68
- variant,
69
- width
70
- });
71
-
72
- const BarStackComponent = isVerticalBar
73
- ? BarStackVertical
74
- : BarStackHorizontal;
75
-
76
- if (areAllValuesNull) {
77
- return (
78
- <div className={classes.container} style={{ height, width }}>
79
- <Typography variant="h3">{t(labelNoDataFound)}</Typography>
80
- </div>
81
- );
82
- }
83
-
84
- return (
85
- <div className={classes.container} style={{ height, width }}>
86
- <div
87
- className={classes.svgWrapper}
88
- style={{
89
- height,
90
- width: svgWrapperWidth
91
- }}
92
- >
93
- {title && (
94
- <div className={classes.title} data-testid="Title" ref={titleRef}>
95
- {`${numeral(total).format('0a').toUpperCase()} `} {t(title)}
96
- </div>
97
- )}
98
- <div
99
- className={classes.svgContainer}
100
- data-testid="barStack"
101
- style={svgContainerSize}
102
- >
103
- <svg
104
- data-variant={variant}
105
- height={barSize.height}
106
- width={barSize.width}
107
- >
108
- <Group>
109
- <BarStackComponent
110
- color={colorScale}
111
- data={[input]}
112
- keys={keys}
113
- {...(isVerticalBar
114
- ? { x: () => undefined }
115
- : { y: () => undefined })}
116
- xScale={xScale}
117
- yScale={yScale}
118
- >
119
- {(barStacks) =>
120
- barStacks.map((barStack) =>
121
- barStack.bars.map((bar) => {
122
- const shouldDisplayValues = (): boolean => {
123
- if (bar.height < 10) {
124
- return false;
125
- }
126
-
127
- return (
128
- (equals(unit, 'number') && bar.width > 10) ||
129
- (equals(unit, 'percentage') && bar.width > 25)
130
- );
131
- };
132
-
133
- const TextX = bar.x + bar.width / 2;
134
- const TextY = bar.y + bar.height / 2;
135
-
136
- const onClick = (): void => {
137
- onSingleBarClick?.(bar);
138
- };
139
-
140
- return (
141
- <Tooltip
142
- hasCaret
143
- classes={{
144
- tooltip: classes.barStackTooltip
145
- }}
146
- followCursor={false}
147
- key={`bar-stack-${barStack.index}-${bar.index}`}
148
- label={
149
- TooltipContent && (
150
- <TooltipContent
151
- color={bar.color}
152
- label={bar.key}
153
- title={title}
154
- total={total}
155
- value={barStack.bars[0].bar.data[barStack.key]}
156
- />
157
- )
158
- }
159
- position={
160
- isVerticalBar ? 'right-start' : 'bottom-start'
161
- }
162
- >
163
- <g data-testid={bar.key} onClick={onClick}>
164
- <rect
165
- cursor="pointer"
166
- fill={bar.color}
167
- height={
168
- isVerticalBar ? bar.height - 1 : bar.height
169
- }
170
- key={`bar-stack-${barStack.index}-${bar.index}`}
171
- ry={10}
172
- width={isVerticalBar ? bar.width : bar.width - 1}
173
- x={bar.x}
174
- y={bar.y}
175
- />
176
- {displayValues && shouldDisplayValues() && (
177
- <Text
178
- cursor="pointer"
179
- data-testid="value"
180
- fill="#000"
181
- fontSize={12}
182
- fontWeight={600}
183
- textAnchor="middle"
184
- verticalAnchor="middle"
185
- x={TextX}
186
- y={TextY}
187
- >
188
- {getValueByUnit({
189
- total,
190
- unit,
191
- value: barStack.bars[0].bar.data[barStack.key]
192
- })}
193
- </Text>
194
- )}
195
- </g>
196
- </Tooltip>
197
- );
198
- })
199
- )
200
- }
201
- </BarStackComponent>
202
- </Group>
203
- </svg>
204
- </div>
205
- </div>
206
- {displayLegend && (
207
- <div data-testid="Legend" ref={legendRef}>
208
- <Legend
209
- data={data}
210
- direction={legendDirection}
211
- scale={legendScale}
212
- title={title}
213
- total={total}
214
- unit={unit}
215
- />
216
- </div>
217
- )}
218
- </div>
219
- );
220
- };
221
-
222
- export default BarStack;
@@ -1 +0,0 @@
1
- export { default as BarStack } from './BarStack';
@@ -1,20 +0,0 @@
1
- export interface BarType {
2
- color: string;
3
- label: string;
4
- value: number;
5
- }
6
-
7
- export type BarStackProps = {
8
- Legend?: ({ scale, data, title, total, unit, direction }) => JSX.Element;
9
- TooltipContent?: (barData) => JSX.Element | boolean | null;
10
- data: Array<BarType>;
11
- displayLegend?: boolean;
12
- displayValues?: boolean;
13
- labelNoDataFound?: string;
14
- legendDirection?: 'row' | 'column';
15
- onSingleBarClick?: (barData) => void;
16
- size?: number;
17
- title?: string;
18
- unit?: 'percentage' | 'number';
19
- variant?: 'vertical' | 'horizontal';
20
- };
@@ -1,137 +0,0 @@
1
- import { scaleBand, scaleLinear, scaleOrdinal } from '@visx/scale';
2
- import { equals, isEmpty, pluck, reject } from 'ramda';
3
-
4
- import { getValueByUnit } from '../common/utils';
5
- import { LegendScale } from '../Legend/models';
6
-
7
- import { BarType } from './models';
8
-
9
- interface Size {
10
- height: number;
11
- width: number;
12
- }
13
-
14
- interface useBarStackProps {
15
- data: Array<BarType>;
16
- height: number;
17
- legendRef;
18
- size: number;
19
- titleRef;
20
- unit?: 'percentage' | 'number';
21
- variant?: 'vertical' | 'horizontal';
22
- width: number;
23
- }
24
- interface useBarStackState {
25
- areAllValuesNull: boolean;
26
- barSize: Size;
27
- colorScale;
28
- input;
29
- isVerticalBar: boolean;
30
- keys: Array<string>;
31
- legendScale: LegendScale;
32
- svgContainerSize: Size;
33
- svgWrapperWidth: number;
34
- total: number;
35
- xScale;
36
- yScale;
37
- }
38
-
39
- const useResponsiveBarStack = ({
40
- data,
41
- variant,
42
- height,
43
- width,
44
- unit = 'number',
45
- titleRef,
46
- legendRef,
47
- size
48
- }: useBarStackProps): useBarStackState => {
49
- const isVerticalBar = equals(variant, 'vertical');
50
-
51
- const heightOfTitle = titleRef.current?.offsetHeight || 0;
52
- const widthOfLegend = legendRef.current?.offsetWidth || 0;
53
-
54
- const horizontalGap = widthOfLegend > 0 ? 12 : 0;
55
- const verticalGap = heightOfTitle > 0 ? 8 : 0;
56
-
57
- const svgWrapperWidth = isVerticalBar
58
- ? size + 36
59
- : width - widthOfLegend - horizontalGap;
60
-
61
- const svgContainerSize = {
62
- height: isVerticalBar ? height - heightOfTitle - verticalGap : size,
63
- width: isVerticalBar ? size : width - widthOfLegend - horizontalGap
64
- };
65
-
66
- const barSize = {
67
- height: svgContainerSize.height - 16,
68
- width: svgContainerSize.width - 16
69
- };
70
-
71
- const total = Math.floor(data.reduce((acc, { value }) => acc + value, 0));
72
-
73
- const yScale = isVerticalBar
74
- ? scaleLinear({
75
- domain: [0, total]
76
- })
77
- : scaleBand({
78
- domain: [0, 0],
79
- padding: 0
80
- });
81
-
82
- const xScale = isVerticalBar
83
- ? scaleBand({
84
- domain: [0, 0],
85
- padding: 0
86
- })
87
- : scaleLinear({
88
- domain: [0, total]
89
- });
90
-
91
- const keys = pluck('label', data);
92
-
93
- const colorsRange = pluck('color', data);
94
-
95
- const colorScale = scaleOrdinal({
96
- domain: keys,
97
- range: colorsRange
98
- });
99
-
100
- const legendScale = {
101
- domain: data.map(({ value }) => getValueByUnit({ total, unit, value })),
102
- range: colorsRange
103
- };
104
-
105
- const xMax = barSize.width;
106
- const yMax = barSize.height;
107
-
108
- xScale.rangeRound([0, xMax]);
109
- yScale.range([yMax, 0]);
110
-
111
- const input = data.reduce((acc, { label, value }) => {
112
- acc[label] = value;
113
-
114
- return acc;
115
- }, {});
116
-
117
- const values = pluck('value', data);
118
-
119
- const areAllValuesNull = isEmpty(reject((value) => equals(value, 0), values));
120
-
121
- return {
122
- areAllValuesNull,
123
- barSize,
124
- colorScale,
125
- input,
126
- isVerticalBar,
127
- keys,
128
- legendScale,
129
- svgContainerSize,
130
- svgWrapperWidth,
131
- total,
132
- xScale,
133
- yScale
134
- };
135
- };
136
-
137
- export default useResponsiveBarStack;