@centreon/ui 24.4.59 → 24.4.61

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 (163) hide show
  1. package/package.json +50 -42
  2. package/public/mockServiceWorker.js +1 -1
  3. package/src/ActionsList/ActionsList.styles.ts +40 -71
  4. package/src/Button/Icon/index.tsx +1 -1
  5. package/src/Button/Save/StartIcon.tsx +3 -3
  6. package/src/Button/Save/index.tsx +9 -5
  7. package/src/Checkbox/Checkbox.tsx +2 -2
  8. package/src/Checkbox/CheckboxGroup/index.tsx +2 -2
  9. package/src/Dashboard/Item.tsx +1 -1
  10. package/src/Dashboard/Layout.tsx +2 -2
  11. package/src/Dialog/Confirm/index.tsx +10 -2
  12. package/src/Dialog/UnsavedChanges/index.tsx +21 -20
  13. package/src/Dialog/UnsavedChanges/translatedLabels.ts +4 -6
  14. package/src/Dialog/index.tsx +9 -2
  15. package/src/FallbackPage/FallbackPage.tsx +3 -3
  16. package/src/FileDropZone/index.tsx +3 -1
  17. package/src/Form/Form.cypress.spec.tsx +133 -0
  18. package/src/Form/Inputs/List/Content.tsx +62 -0
  19. package/src/Form/Inputs/List/List.styles.ts +29 -0
  20. package/src/Form/Inputs/List/List.tsx +58 -0
  21. package/src/Form/Inputs/List/useList.ts +81 -0
  22. package/src/Form/Inputs/Text.tsx +3 -1
  23. package/src/Form/Inputs/index.tsx +3 -1
  24. package/src/Form/Inputs/models.ts +10 -1
  25. package/src/Graph/BarStack/BarStack.cypress.spec.tsx +154 -0
  26. package/src/Graph/BarStack/BarStack.stories.tsx +123 -0
  27. package/src/Graph/BarStack/BarStack.styles.ts +37 -0
  28. package/src/Graph/BarStack/BarStack.tsx +14 -0
  29. package/src/Graph/BarStack/ResponsiveBarStack.tsx +222 -0
  30. package/src/Graph/BarStack/index.ts +1 -0
  31. package/src/Graph/BarStack/models.ts +20 -0
  32. package/src/Graph/BarStack/useResponsiveBarStack.ts +137 -0
  33. package/src/Graph/Gauge/Gauge.cypress.spec.tsx +102 -0
  34. package/src/Graph/Gauge/Gauge.tsx +1 -1
  35. package/src/Graph/HeatMap/HeatMap.cypress.spec.tsx +145 -0
  36. package/src/Graph/HeatMap/HeatMap.stories.tsx +0 -25
  37. package/src/Graph/HeatMap/ResponsiveHeatMap.tsx +8 -2
  38. package/src/Graph/Legend/Legend.tsx +21 -0
  39. package/src/Graph/Legend/index.ts +1 -0
  40. package/src/Graph/Legend/models.ts +11 -0
  41. package/src/Graph/LineChart/BasicComponents/Lines/Threshold/Circle.tsx +2 -2
  42. package/src/Graph/LineChart/BasicComponents/Thresholds.tsx +2 -2
  43. package/src/Graph/LineChart/BasicComponents/useFilterLines.ts +1 -1
  44. package/src/Graph/LineChart/InteractiveComponents/AnchorPoint/GuidingLines.tsx +2 -2
  45. package/src/Graph/LineChart/InteractiveComponents/Annotations/EventAnnotations.tsx +1 -1
  46. package/src/Graph/LineChart/Legend/Legend.styles.ts +1 -1
  47. package/src/Graph/LineChart/Legend/LegendHeader.tsx +1 -1
  48. package/src/Graph/LineChart/Legend/useInteractiveValues.ts +2 -2
  49. package/src/Graph/LineChart/Legend/useLegend.ts +3 -3
  50. package/src/Graph/LineChart/helpers/doc.ts +16 -13
  51. package/src/Graph/LineChart/helpers/index.ts +1 -1
  52. package/src/Graph/LineChart/index.stories.tsx +4 -2
  53. package/src/Graph/LineChart/index.tsx +1 -1
  54. package/src/Graph/PieChart/PieChart.cypress.spec.tsx +169 -0
  55. package/src/Graph/PieChart/PieChart.stories.tsx +194 -0
  56. package/src/Graph/PieChart/PieChart.styles.ts +39 -0
  57. package/src/Graph/PieChart/PieChart.tsx +14 -0
  58. package/src/Graph/PieChart/ResponsivePie.tsx +254 -0
  59. package/src/Graph/PieChart/index.ts +1 -0
  60. package/src/Graph/PieChart/models.ts +20 -0
  61. package/src/Graph/PieChart/useResponsivePie.ts +85 -0
  62. package/src/Graph/SingleBar/SingleBar.cypress.spec.tsx +121 -0
  63. package/src/Graph/SingleBar/Thresholds.tsx +2 -2
  64. package/src/Graph/Text/Text.cypress.spec.tsx +101 -0
  65. package/src/Graph/Text/Text.stories.tsx +60 -4
  66. package/src/Graph/Text/Text.tsx +1 -1
  67. package/src/Graph/common/testUtils.ts +71 -0
  68. package/src/Graph/common/timeSeries/index.ts +22 -14
  69. package/src/Graph/common/utils.ts +19 -0
  70. package/src/Graph/index.ts +3 -0
  71. package/src/Graph/translatedLabels.ts +1 -0
  72. package/src/InputField/Select/Autocomplete/Connected/index.tsx +10 -7
  73. package/src/InputField/Select/Autocomplete/Draggable/SortableList.tsx +1 -1
  74. package/src/InputField/Select/Autocomplete/Draggable/SortableListContent.tsx +1 -1
  75. package/src/InputField/Select/Autocomplete/Draggable/index.tsx +1 -1
  76. package/src/InputField/Select/Autocomplete/Multi/index.tsx +4 -2
  77. package/src/InputField/Select/Autocomplete/index.tsx +129 -116
  78. package/src/InputField/Select/IconPopover/index.tsx +2 -2
  79. package/src/InputField/Select/index.tsx +15 -2
  80. package/src/InputField/Text/index.tsx +2 -2
  81. package/src/Listing/ActionBar/index.tsx +9 -8
  82. package/src/Listing/Cell/DataCell.styles.ts +3 -0
  83. package/src/Listing/Cell/DataCell.tsx +23 -5
  84. package/src/Listing/Header/ListingHeader.tsx +1 -1
  85. package/src/Listing/Listing.cypress.spec.tsx +218 -33
  86. package/src/Listing/Listing.styles.ts +4 -7
  87. package/src/Listing/Row/Row.tsx +7 -3
  88. package/src/Listing/index.stories.tsx +37 -3
  89. package/src/Listing/index.test.tsx +1 -1
  90. package/src/Listing/index.tsx +80 -36
  91. package/src/Listing/models.ts +1 -0
  92. package/src/Listing/useStyleTable.ts +1 -0
  93. package/src/Module/Module.cypress.spec.tsx +129 -0
  94. package/src/Module/index.tsx +2 -4
  95. package/src/PopoverMenu/index.tsx +6 -5
  96. package/src/RichTextEditor/RichTextEditor.tsx +12 -1
  97. package/src/SortableItems/index.tsx +2 -7
  98. package/src/ThemeProvider/index.tsx +24 -0
  99. package/src/TimePeriods/CustomTimePeriod/CompactCustomTimePeriod.styles.ts +6 -7
  100. package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/PickersStartEndDate.tsx +8 -3
  101. package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/models.ts +0 -2
  102. package/src/TimePeriods/DateTimePickerInput.tsx +56 -19
  103. package/src/TimePeriods/ResolutionTimePeriod.cypress.spec.tsx +12 -9
  104. package/src/TimePeriods/TimePeriods.cypress.spec.tsx +9 -33
  105. package/src/TimePeriods/helpers/index.ts +1 -1
  106. package/src/TimePeriods/index.stories.tsx +12 -4
  107. package/src/TimePeriods/index.tsx +2 -2
  108. package/src/Typography/FluidTypography/FluidTypography.cypress.spec.tsx +27 -0
  109. package/src/Typography/FluidTypography/index.stories.tsx +2 -2
  110. package/src/Typography/FluidTypography/index.tsx +21 -28
  111. package/src/api/QueryProvider.tsx +1 -1
  112. package/src/api/TestQueryProvider.tsx +1 -1
  113. package/src/api/index.ts +3 -3
  114. package/src/api/useFetchQuery/index.ts +27 -23
  115. package/src/api/useMutationQuery/index.test.ts +4 -4
  116. package/src/api/useMutationQuery/index.ts +60 -25
  117. package/src/components/Button/Icon/IconButton.tsx +6 -2
  118. package/src/components/DataTable/DataListing.tsx +6 -0
  119. package/src/components/DataTable/DataTable.cypress.spec.tsx +174 -0
  120. package/src/components/DataTable/DataTable.stories.tsx +40 -0
  121. package/src/components/DataTable/DataTable.styles.ts +3 -0
  122. package/src/components/DataTable/DataTable.tsx +3 -3
  123. package/src/components/DataTable/Item/DataTableItem.styles.ts +7 -2
  124. package/src/components/DataTable/Item/DataTableItem.tsx +4 -60
  125. package/src/components/DataTable/index.ts +3 -1
  126. package/src/components/Form/AccessRights/AccessRights.cypress.spec.tsx +13 -13
  127. package/src/components/Form/AccessRights/ShareInput/ContactSwitch.tsx +3 -3
  128. package/src/components/Form/AccessRights/ShareInput/ShareInput.tsx +1 -0
  129. package/src/components/Form/AccessRights/storiesData.ts +22 -22
  130. package/src/components/Form/Dashboard/DashboardDuplicationForm.tsx +85 -0
  131. package/src/components/Form/Dashboard/DashboardForm.tsx +15 -12
  132. package/src/components/Form/Dashboard/index.ts +1 -0
  133. package/src/components/Form/FormActions.tsx +7 -2
  134. package/src/components/ItemComposition/ItemComposition.styles.ts +2 -2
  135. package/src/components/Layout/PageLayout/PageLayout.tsx +1 -1
  136. package/src/components/Layout/PageLayout/PageLayoutActions.tsx +1 -0
  137. package/src/components/Layout/PageLayout/PageLayoutBody.tsx +1 -0
  138. package/src/components/Layout/PageLayout/PageLayoutHeader.tsx +5 -1
  139. package/src/components/Layout/PageLayout/PageQuickAccess.tsx +76 -0
  140. package/src/components/Layout/PageLayout/index.ts +3 -1
  141. package/src/components/Layout/PageLayout.cypress.spec.tsx +66 -0
  142. package/src/components/List/Item/ListItem.tsx +3 -3
  143. package/src/components/Modal/ConfirmationModal/ConfirmationModal.cypress.spec.tsx +168 -0
  144. package/src/components/Modal/ConfirmationModal/ConfirmationModal.stories.tsx +62 -0
  145. package/src/components/Modal/ConfirmationModal/ConfirmationModal.tsx +87 -0
  146. package/src/components/Modal/Modal.styles.ts +8 -3
  147. package/src/components/Modal/index.ts +2 -0
  148. package/src/components/Tooltip/ConfirmationTooltip/ConfirmationTooltip.stories.tsx +3 -3
  149. package/src/components/Tooltip/ConfirmationTooltip/ConfirmationTooltip.tsx +1 -1
  150. package/src/components/Tooltip/ConfirmationTooltip/models.ts +1 -1
  151. package/src/index.ts +2 -2
  152. package/src/queryParameters/url/index.ts +5 -1
  153. package/src/utils/index.ts +1 -1
  154. package/src/utils/useFullscreen/Fullscreen.cypress.spec.tsx +1 -3
  155. package/src/utils/useFullscreen/useFullscreenListener.ts +10 -7
  156. package/src/utils/useInfiniteScrollListing.ts +4 -1
  157. package/src/utils/{useLicenseExpirationWarning.cypress.spec.tsx → useLicenseExpirationWarning.test.tsx} +48 -37
  158. package/src/utils/useLicenseExpirationWarning.ts +18 -18
  159. package/src/utils/usePluralizedTranslation.ts +21 -0
  160. package/src/Typography/FluidTypography/useFluidResizeObserver.ts +0 -56
  161. package/src/screens/dashboard/DashboardsDetail.stories.tsx +0 -108
  162. package/src/screens/dashboard/DashboardsOverview.stories.tsx +0 -281
  163. package/src/utils/useDateTimePickerAdapter.ts +0 -309
@@ -98,7 +98,9 @@ const getExtensions = cond([
98
98
  [T, identity]
99
99
  ]) as (accept: string) => Array<string>;
100
100
 
101
- export const transformFileListToArray = (files: FileList | null): Array<File> =>
101
+ export const transformFileListToArray = (
102
+ files: FileList | null
103
+ ): Array<File> =>
102
104
  isNil(files)
103
105
  ? []
104
106
  : (Array(files.length)
@@ -0,0 +1,133 @@
1
+ import { object } from 'yup';
2
+ import { faker } from '@faker-js/faker';
3
+ import { useFormikContext } from 'formik';
4
+
5
+ import { Typography } from '@mui/material';
6
+
7
+ import { Button } from '../components';
8
+
9
+ import { Form } from './Form';
10
+ import { InputType } from './Inputs/models';
11
+
12
+ faker.seed(42);
13
+
14
+ const AddItem = ({ addItem }: { addItem: (item) => void }): JSX.Element => {
15
+ const { values } = useFormikContext();
16
+ const add = (): void => {
17
+ addItem({
18
+ alias: faker.company.name(),
19
+ id: values.list.length,
20
+ name: faker.person.firstName()
21
+ });
22
+ };
23
+
24
+ return (
25
+ <Button variant="ghost" onClick={add}>
26
+ Add item
27
+ </Button>
28
+ );
29
+ };
30
+
31
+ const SortContent = ({
32
+ name,
33
+ alias
34
+ }: {
35
+ alias: string;
36
+ name: string;
37
+ }): JSX.Element => (
38
+ <Typography>
39
+ {name} ({alias})
40
+ </Typography>
41
+ );
42
+
43
+ const initializeFormList = (): void => {
44
+ cy.mount({
45
+ Component: (
46
+ <Form
47
+ initialValues={{
48
+ list: []
49
+ }}
50
+ inputs={[
51
+ {
52
+ fieldName: 'list',
53
+ group: '',
54
+ label: '',
55
+ list: {
56
+ AddItem,
57
+ SortContent,
58
+ addItemLabel: 'Add an item to the list',
59
+ itemProps: ['id', 'name', 'alias'],
60
+ sortLabel: 'Sort items'
61
+ },
62
+ type: InputType.List
63
+ }
64
+ ]}
65
+ submit={cy.stub()}
66
+ validationSchema={object()}
67
+ />
68
+ )
69
+ });
70
+ };
71
+
72
+ describe('Form list', () => {
73
+ beforeEach(initializeFormList);
74
+
75
+ it('adds an element to the list', () => {
76
+ cy.contains('Add an item to the list').should('be.visible');
77
+ cy.contains('Sort items').should('be.visible');
78
+
79
+ cy.contains('Add item').click();
80
+
81
+ cy.findByLabelText('sort-0').should('be.visible');
82
+ cy.findByLabelText('delete-0').should('be.visible');
83
+ cy.contains('Christelle (Schinner - Wiegand)').should('be.visible');
84
+
85
+ cy.makeSnapshot();
86
+ });
87
+
88
+ it('sorts elements in the list', () => {
89
+ cy.contains('Add an item to the list').should('be.visible');
90
+ cy.contains('Sort items').should('be.visible');
91
+
92
+ cy.contains('Add item').click();
93
+ cy.contains('Add item').click();
94
+
95
+ cy.findByLabelText('sort-0').should('be.visible');
96
+ cy.findByLabelText('delete-0').should('be.visible');
97
+ cy.contains('Carley (Satterfield, Miller and Metz)').should('be.visible');
98
+ cy.findByLabelText('sort-1').should('be.visible');
99
+ cy.findByLabelText('delete-1').should('be.visible');
100
+ cy.contains('Anderson (Crist - Bradtke)').should('be.visible');
101
+
102
+ cy.moveSortableElementUsingAriaLabel({
103
+ ariaLabel: 'sort-0',
104
+ direction: 'down'
105
+ });
106
+
107
+ cy.contains('Carley (Satterfield, Miller and Metz)').should('be.visible');
108
+ cy.contains('Anderson (Crist - Bradtke)').should('be.visible');
109
+
110
+ cy.makeSnapshot();
111
+ });
112
+
113
+ it('removes an element from the list', () => {
114
+ cy.contains('Add an item to the list').should('be.visible');
115
+ cy.contains('Sort items').should('be.visible');
116
+
117
+ cy.contains('Add item').click();
118
+ cy.contains('Add item').click();
119
+
120
+ cy.findByLabelText('sort-0').should('be.visible');
121
+ cy.findByLabelText('delete-0').should('be.visible');
122
+ cy.contains('Lea (Streich - Hartmann)').should('be.visible');
123
+ cy.findByLabelText('sort-1').should('be.visible');
124
+ cy.findByLabelText('delete-1').should('be.visible');
125
+ cy.contains('Akeem (Quigley LLC)').should('be.visible');
126
+
127
+ cy.findByLabelText('delete-0').click();
128
+
129
+ cy.contains('Lea (Streich - Hartmann)').should('not.exist');
130
+
131
+ cy.makeSnapshot();
132
+ });
133
+ });
@@ -0,0 +1,62 @@
1
+ import { ReactNode } from 'react';
2
+
3
+ import { DraggableSyntheticListeners } from '@dnd-kit/core';
4
+
5
+ import KrilinIndicatorIcon from '@mui/icons-material/DragIndicator';
6
+ import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline';
7
+
8
+ import { IconButton } from '../../../components';
9
+
10
+ import { useListStyles } from './List.styles';
11
+
12
+ export interface ContentProps {
13
+ attributes;
14
+ children: ReactNode;
15
+ deleteItem: (id: string) => () => void;
16
+ id: string;
17
+ isDragging: boolean;
18
+ isInDragOverlay?: boolean;
19
+ itemRef: React.RefObject<HTMLDivElement>;
20
+ listeners: DraggableSyntheticListeners;
21
+ name: string;
22
+ style;
23
+ }
24
+
25
+ const Content = ({
26
+ listeners,
27
+ itemRef,
28
+ attributes,
29
+ style,
30
+ isDragging,
31
+ id,
32
+ children,
33
+ deleteItem
34
+ }: ContentProps): JSX.Element => {
35
+ const { classes } = useListStyles();
36
+
37
+ return (
38
+ <div
39
+ className={classes.content}
40
+ ref={itemRef}
41
+ {...attributes}
42
+ style={style}
43
+ >
44
+ <IconButton
45
+ data-dragging={isDragging}
46
+ size="small"
47
+ {...listeners}
48
+ aria-label={`sort-${id}`}
49
+ icon={<KrilinIndicatorIcon fontSize="small" />}
50
+ />
51
+ <div className={classes.innerContent}>{children}</div>
52
+ <IconButton
53
+ aria-label={`delete-${id}`}
54
+ icon={<DeleteOutlineIcon color="error" fontSize="small" />}
55
+ size="small"
56
+ onClick={deleteItem(id)}
57
+ />
58
+ </div>
59
+ );
60
+ };
61
+
62
+ export default Content;
@@ -0,0 +1,29 @@
1
+ import { makeStyles } from 'tss-react/mui';
2
+
3
+ export const useListStyles = makeStyles()((theme) => ({
4
+ content: {
5
+ '& [data-dragging="false"]': {
6
+ cursor: 'grab'
7
+ },
8
+ '& [data-dragging="true"]': {
9
+ cursor: 'grabbing'
10
+ },
11
+ alignItems: 'center',
12
+ borderBottom: `1px dashed ${theme.palette.action.disabledBackground}`,
13
+ display: 'flex',
14
+ flexDirection: 'row',
15
+ padding: theme.spacing(1, 0)
16
+ },
17
+ innerContent: {
18
+ flexGrow: 1
19
+ },
20
+ items: {
21
+ maxHeight: theme.spacing(16),
22
+ overflowY: 'auto'
23
+ },
24
+ list: {
25
+ display: 'flex',
26
+ flexDirection: 'column',
27
+ gap: theme.spacing(1)
28
+ }
29
+ }));
@@ -0,0 +1,58 @@
1
+ import { ComponentType } from 'react';
2
+
3
+ import { closestCenter } from '@dnd-kit/core';
4
+ import { verticalListSortingStrategy } from '@dnd-kit/sortable';
5
+ import { useTranslation } from 'react-i18next';
6
+
7
+ import { InputPropsWithoutGroup } from '../models';
8
+ import { SortableItems, Subtitle } from '../../..';
9
+
10
+ import { useList } from './useList';
11
+ import { useListStyles } from './List.styles';
12
+ import Content, { ContentProps } from './Content';
13
+
14
+ const List = ({
15
+ list,
16
+ fieldName
17
+ }: InputPropsWithoutGroup): JSX.Element | null => {
18
+ const { t } = useTranslation();
19
+ const { classes } = useListStyles();
20
+
21
+ const { addItem, sortList, sortedList, deleteItem } = useList({ fieldName });
22
+
23
+ const { AddItem, addItemLabel, sortLabel, SortContent, itemProps } = list as {
24
+ AddItem: ComponentType<{ addItem }>;
25
+ SortContent: ComponentType;
26
+ addItemLabel?: string;
27
+ itemProps: Array<string>;
28
+ sortLabel?: string;
29
+ };
30
+
31
+ return (
32
+ <div className={classes.list}>
33
+ {addItemLabel && <Subtitle>{t(addItemLabel)}</Subtitle>}
34
+ <AddItem addItem={addItem} />
35
+ {sortLabel && <Subtitle>{t(sortLabel)}</Subtitle>}
36
+ <div className={classes.items}>
37
+ <SortableItems
38
+ updateSortableItemsOnItemsChange
39
+ // eslint-disable-next-line react/no-unstable-nested-components
40
+ Content={(props: Omit<ContentProps, 'children' | 'deleteItem'>) => (
41
+ <Content {...props} deleteItem={deleteItem}>
42
+ <SortContent {...props} />
43
+ </Content>
44
+ )}
45
+ collisionDetection={closestCenter}
46
+ itemProps={itemProps}
47
+ items={sortedList}
48
+ sortingStrategy={verticalListSortingStrategy}
49
+ onDragEnd={({ items }): void => {
50
+ sortList(items);
51
+ }}
52
+ />
53
+ </div>
54
+ </div>
55
+ );
56
+ };
57
+
58
+ export default List;
@@ -0,0 +1,81 @@
1
+ import { useMemo, useRef } from 'react';
2
+
3
+ import { FormikValues, useFormikContext } from 'formik';
4
+ import {
5
+ append,
6
+ equals,
7
+ inc,
8
+ isEmpty,
9
+ pluck,
10
+ prop,
11
+ reject,
12
+ sortBy
13
+ } from 'ramda';
14
+
15
+ import { SelectEntry } from '../../..';
16
+
17
+ interface UseListState {
18
+ addItem: (newItem: SelectEntry) => void;
19
+ deleteItem: (id: string) => () => void;
20
+ sortList: (items: Array<string>) => void;
21
+ sortedList: Array<unknown>;
22
+ }
23
+
24
+ export const useList = ({ fieldName }): UseListState => {
25
+ const { values, setFieldValue } = useFormikContext<FormikValues>();
26
+ const maxOrder = useRef(0);
27
+
28
+ const list = values[fieldName];
29
+
30
+ const sortedList = useMemo(
31
+ () =>
32
+ sortBy(prop('order'), list).map(({ id, ...props }) => ({
33
+ id: `${id}`,
34
+ ...props
35
+ })),
36
+ [list]
37
+ );
38
+
39
+ const addItem = (newItem: SelectEntry): void => {
40
+ setFieldValue(
41
+ fieldName,
42
+ append(
43
+ {
44
+ ...newItem,
45
+ id: (newItem as SelectEntry).id as number,
46
+ order: inc(maxOrder.current)
47
+ },
48
+ list
49
+ )
50
+ );
51
+ };
52
+
53
+ const deleteItem = (id: string) => (): void => {
54
+ const newItems = reject((item) => equals(Number(id), item.id))(list);
55
+
56
+ setFieldValue(fieldName, newItems);
57
+ };
58
+
59
+ const sortList = (items: Array<string>): void => {
60
+ const newOrderedList = items.map((itemId, idx) => {
61
+ const item = sortedList.find(({ id }) => equals(id, itemId));
62
+
63
+ return {
64
+ ...item,
65
+ id: Number(item?.id),
66
+ order: inc(idx)
67
+ };
68
+ });
69
+
70
+ setFieldValue(fieldName, newOrderedList);
71
+ };
72
+
73
+ maxOrder.current = isEmpty(list) ? 0 : Math.max(...pluck('order', list));
74
+
75
+ return {
76
+ addItem,
77
+ deleteItem,
78
+ sortList,
79
+ sortedList
80
+ };
81
+ };
@@ -29,7 +29,8 @@ const Text = ({
29
29
  getRequired,
30
30
  change,
31
31
  additionalMemoProps,
32
- text
32
+ text,
33
+ autoFocus
33
34
  }: InputPropsWithoutGroup): JSX.Element => {
34
35
  const { t } = useTranslation();
35
36
 
@@ -109,6 +110,7 @@ const Text = ({
109
110
  fullWidth
110
111
  EndAdornment={EndAdornment}
111
112
  ariaLabel={t(label) || ''}
113
+ autoFocus={autoFocus}
112
114
  dataTestId={dataTestId || ''}
113
115
  disabled={disabled}
114
116
  error={error as string | undefined}
@@ -21,6 +21,7 @@ import CheckboxGroup from './CheckboxGroup';
21
21
  import Checkbox from './Checkbox';
22
22
  import Custom from './Custom';
23
23
  import LoadingSkeleton from './LoadingSkeleton';
24
+ import List from './List/List';
24
25
 
25
26
  export const getInput = R.cond<
26
27
  Array<InputType>,
@@ -66,6 +67,7 @@ export const getInput = R.cond<
66
67
  R.equals(InputType.CheckboxGroup) as (b: InputType) => boolean,
67
68
  R.always(CheckboxGroup)
68
69
  ],
70
+ [R.equals(InputType.List) as (b: InputType) => boolean, R.always(List)],
69
71
  [R.T, R.always(TextInput)]
70
72
  ]);
71
73
 
@@ -185,7 +187,7 @@ const Inputs = ({
185
187
  const hasGroupTitle = R.not(R.isNil(groupName));
186
188
 
187
189
  const groupProps = hasGroupTitle
188
- ? R.find(R.propEq('name', groupName), groups)
190
+ ? R.find(R.propEq(groupName, 'name'), groups)
189
191
  : ({} as Group);
190
192
 
191
193
  const isFirstElement = areGroupsOpen || R.equals(index, 0);
@@ -18,7 +18,8 @@ export enum InputType {
18
18
  Grid,
19
19
  Custom,
20
20
  Checkbox,
21
- CheckboxGroup
21
+ CheckboxGroup,
22
+ List
22
23
  }
23
24
 
24
25
  interface FieldsTableGetRequiredProps {
@@ -32,6 +33,7 @@ export interface InputProps {
32
33
  additionalLabel?: string | JSX.Element;
33
34
  additionalLabelClassName?: string;
34
35
  additionalMemoProps?: Array<unknown>;
36
+ autoFocus?: boolean;
35
37
  autocomplete?: {
36
38
  creatable?: boolean;
37
39
  options: Array<SelectEntry>;
@@ -76,6 +78,13 @@ export interface InputProps {
76
78
  hideInput?: (values: FormikValues) => boolean;
77
79
  inputClassName?: string;
78
80
  label: string;
81
+ list?: {
82
+ AddItem: React.ComponentType<{ addItem }>;
83
+ SortContent: React.ComponentType<object>;
84
+ addItemLabel?: string;
85
+ itemProps: Array<string>;
86
+ sortLabel?: string;
87
+ };
79
88
  radio?: {
80
89
  options?: Array<{
81
90
  label: string | JSX.Element;
@@ -0,0 +1,154 @@
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
+ });