@centreon/ui 25.3.3 → 25.4.0-MON-191119-npm-develop.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.
Files changed (187) hide show
  1. package/package.json +25 -11
  2. package/public/mockServiceWorker.js +8 -31
  3. package/src/ActionsList/index.tsx +1 -0
  4. package/src/Button/Icon/index.tsx +3 -1
  5. package/src/Button/Save/index.stories.tsx +1 -0
  6. package/src/Checkbox/Checkbox.tsx +3 -1
  7. package/src/Checkbox/CheckboxGroup/index.tsx +6 -1
  8. package/src/Colors/index.tsx +1 -1
  9. package/src/Dashboard/Dashboard.styles.ts +1 -1
  10. package/src/Dashboard/Layout.tsx +1 -1
  11. package/src/Dialog/UnsavedChanges/index.stories.tsx +1 -0
  12. package/src/Form/CollapsibleGroup.tsx +13 -13
  13. package/src/Form/Form.cypress.spec.tsx +137 -2
  14. package/src/Form/Form.stories.tsx +11 -31
  15. package/src/Form/Form.tsx +2 -0
  16. package/src/Form/Inputs/Checkbox.tsx +3 -2
  17. package/src/Form/Inputs/ConnectedAutocomplete.tsx +6 -1
  18. package/src/Form/Inputs/Grid.tsx +18 -29
  19. package/src/Form/Inputs/SubGroupDivider.tsx +7 -0
  20. package/src/Form/Inputs/Text.tsx +1 -0
  21. package/src/Form/Inputs/index.tsx +31 -24
  22. package/src/Form/Inputs/models.ts +8 -1
  23. package/src/Form/Section/FormSection.tsx +34 -0
  24. package/src/Form/Section/PanelTabs.tsx +13 -0
  25. package/src/Form/Section/navigateToSection.ts +9 -0
  26. package/src/Form/storiesData.tsx +14 -4
  27. package/src/Graph/BarChart/BarChart.cypress.spec.tsx +46 -6
  28. package/src/Graph/BarChart/BarChart.stories.tsx +60 -0
  29. package/src/Graph/BarChart/BarChart.tsx +56 -32
  30. package/src/Graph/BarChart/BarGroup.tsx +22 -32
  31. package/src/Graph/BarChart/MemoizedGroup.tsx +8 -11
  32. package/src/Graph/BarChart/ResponsiveBarChart.tsx +145 -32
  33. package/src/Graph/BarChart/Tooltip/BarChartTooltip.tsx +2 -2
  34. package/src/Graph/Chart/BasicComponents/Lines/StackedLines/index.tsx +7 -1
  35. package/src/Graph/Chart/BasicComponents/Lines/StackedLines/useStackedLines.ts +18 -45
  36. package/src/Graph/Chart/BasicComponents/Lines/index.tsx +42 -28
  37. package/src/Graph/Chart/Chart.cypress.spec.tsx +85 -15
  38. package/src/Graph/Chart/Chart.stories.tsx +84 -1
  39. package/src/Graph/Chart/Chart.tsx +17 -4
  40. package/src/Graph/Chart/InteractiveComponents/AnchorPoint/RegularAnchorPoint.tsx +8 -2
  41. package/src/Graph/Chart/InteractiveComponents/AnchorPoint/StackedAnchorPoint.tsx +10 -3
  42. package/src/Graph/Chart/InteractiveComponents/AnchorPoint/useTickGraph.ts +19 -2
  43. package/src/Graph/Chart/InteractiveComponents/Annotations/Annotation/index.tsx +1 -1
  44. package/src/Graph/Chart/InteractiveComponents/GraphValueTooltip/useGraphValueTooltip.ts +2 -4
  45. package/src/Graph/Chart/InteractiveComponents/ZoomPreview/index.tsx +14 -3
  46. package/src/Graph/Chart/InteractiveComponents/ZoomPreview/models.ts +3 -0
  47. package/src/Graph/Chart/InteractiveComponents/ZoomPreview/useZoomPreview.ts +12 -10
  48. package/src/Graph/Chart/InteractiveComponents/index.tsx +63 -5
  49. package/src/Graph/Chart/Legend/index.tsx +26 -2
  50. package/src/Graph/Chart/helpers/index.ts +4 -3
  51. package/src/Graph/Chart/index.tsx +45 -45
  52. package/src/Graph/Chart/models.ts +8 -0
  53. package/src/Graph/Chart/useChartData.ts +14 -2
  54. package/src/Graph/Gauge/Gauge.tsx +18 -14
  55. package/src/Graph/Gauge/ResponsiveGauge.tsx +10 -6
  56. package/src/Graph/Gauge/useResizeObserver.ts +68 -0
  57. package/src/Graph/SingleBar/ResponsiveSingleBar.tsx +18 -16
  58. package/src/Graph/SingleBar/ThresholdLine.tsx +4 -4
  59. package/src/Graph/SingleBar/models.ts +1 -0
  60. package/src/Graph/Text/Text.styles.ts +2 -2
  61. package/src/Graph/Text/Text.tsx +23 -10
  62. package/src/Graph/Timeline/ResponsiveTimeline.tsx +4 -0
  63. package/src/Graph/Timeline/Timeline.tsx +21 -4
  64. package/src/Graph/Tree/Links.tsx +2 -2
  65. package/src/Graph/Tree/Tree.tsx +2 -2
  66. package/src/Graph/Tree/constants.ts +1 -1
  67. package/src/Graph/common/BaseChart/BaseChart.tsx +6 -1
  68. package/src/Graph/common/BaseChart/ChartSvgWrapper.tsx +5 -4
  69. package/src/Graph/common/BaseChart/Header/index.tsx +3 -1
  70. package/src/Graph/common/BaseChart/useComputeBaseChartDimensions.ts +13 -9
  71. package/src/Graph/common/timeSeries/index.test.ts +20 -0
  72. package/src/Graph/common/timeSeries/index.ts +225 -44
  73. package/src/Graph/common/timeSeries/models.ts +6 -2
  74. package/src/Graph/common/utils.ts +45 -12
  75. package/src/Graph/index.ts +3 -1
  76. package/src/Graph/mockedData/dataWithMissingPoint.json +74 -0
  77. package/src/Graph/mockedData/pingServiceWithStackedKeys.json +205 -0
  78. package/src/Icon/RegexIcon.tsx +20 -0
  79. package/src/Icon/index.ts +1 -0
  80. package/src/InputField/Select/Autocomplete/Connected/Multi/MultiConnectedAutocompleteField.cypress.spec.tsx +68 -14
  81. package/src/InputField/Select/Autocomplete/Connected/index.tsx +49 -14
  82. package/src/InputField/Select/Autocomplete/Multi/Listbox.tsx +78 -0
  83. package/src/InputField/Select/Autocomplete/Multi/Multi.styles.ts +26 -0
  84. package/src/InputField/Select/Autocomplete/Multi/Multi.tsx +124 -0
  85. package/src/InputField/Select/Autocomplete/Multi/index.tsx +1 -117
  86. package/src/InputField/Select/Autocomplete/index.tsx +28 -17
  87. package/src/InputField/Select/Option.tsx +3 -3
  88. package/src/InputField/Select/index.tsx +4 -0
  89. package/src/InputField/Text/index.tsx +4 -2
  90. package/src/InputField/translatedLabels.ts +4 -0
  91. package/src/Listing/ActionBar/Pagination.tsx +10 -23
  92. package/src/Listing/ActionBar/PaginationActions.tsx +1 -10
  93. package/src/Listing/ActionBar/index.tsx +1 -1
  94. package/src/Listing/Cell/DataCell.tsx +6 -6
  95. package/src/Listing/Cell/EllipsisTypography.tsx +10 -32
  96. package/src/Listing/Cell/index.tsx +57 -89
  97. package/src/Listing/Checkbox.tsx +8 -20
  98. package/src/Listing/Header/Cell/ListingHeaderCell.tsx +17 -14
  99. package/src/Listing/Header/Cell/SelectActionListingHeaderCell.tsx +5 -9
  100. package/src/Listing/Header/ListingHeader.tsx +2 -5
  101. package/src/Listing/Header/_internals/Label.tsx +1 -17
  102. package/src/Listing/Row/EmptyRow.tsx +2 -6
  103. package/src/Listing/Row/Row.tsx +7 -36
  104. package/src/Listing/index.stories.tsx +1 -0
  105. package/src/Listing/index.tsx +26 -26
  106. package/src/Listing/useStyleTable.ts +58 -32
  107. package/src/ListingPage/index.stories.tsx +1 -0
  108. package/src/Module/index.tsx +8 -2
  109. package/src/MultiSelectEntries/index.stories.tsx +1 -0
  110. package/src/MultiSelectEntries/index.tsx +1 -1
  111. package/src/Pagination/Pagination.cypress.spec.tsx +137 -0
  112. package/src/Pagination/Pagination.stories.tsx +46 -0
  113. package/src/Pagination/Pagination.styles.ts +56 -0
  114. package/src/Pagination/Pagination.tsx +146 -0
  115. package/src/Pagination/index.ts +3 -0
  116. package/src/Pagination/utils.ts +7 -0
  117. package/src/SortableItems/index.stories.tsx +2 -2
  118. package/src/StoryBookThemeProvider/index.tsx +3 -1
  119. package/src/ThemeProvider/base.css +49 -0
  120. package/src/ThemeProvider/index.tsx +21 -47
  121. package/src/ThemeProvider/palettes.ts +5 -3
  122. package/src/ThemeProvider/tailwindcss.css +230 -0
  123. package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/PickersStartEndDate.tsx +9 -11
  124. package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/models.ts +1 -0
  125. package/src/TimePeriods/DateTimePickerInput.tsx +3 -1
  126. package/src/api/customFetch.ts +0 -9
  127. package/src/api/models.ts +9 -0
  128. package/src/api/useBulkResponse.ts +58 -0
  129. package/src/api/useGraphQuery/index.ts +108 -12
  130. package/src/components/Avatar/Avatar.stories.tsx +1 -0
  131. package/src/components/Button/Button.module.css +38 -0
  132. package/src/components/Button/Button.stories.tsx +25 -0
  133. package/src/components/Button/Button.tsx +2 -5
  134. package/src/components/CrudPage/Actions/Actions.styles.ts +15 -1
  135. package/src/components/CrudPage/Actions/Actions.tsx +7 -4
  136. package/src/components/CrudPage/Actions/Search.tsx +15 -14
  137. package/src/components/CrudPage/CrudPage.stories.tsx +1 -0
  138. package/src/components/CrudPage/CrudPageRoot.tsx +1 -1
  139. package/src/components/DataTable/DataTable.stories.tsx +1 -0
  140. package/src/components/DataTable/EmptyState/DataTableEmptyState.stories.tsx +1 -0
  141. package/src/components/DataTable/EmptyState/DataTableEmptyState.styles.ts +3 -1
  142. package/src/components/DataTable/EmptyState/DataTableEmptyState.tsx +4 -1
  143. package/src/components/DataTable/Item/DataTableItem.stories.tsx +1 -0
  144. package/src/components/Form/AccessRights/AccessRights.stories.tsx +1 -0
  145. package/src/components/Form/AccessRights/ShareInput/ShareInput.tsx +4 -3
  146. package/src/components/Form/AccessRights/ShareInput/useShareInput.tsx +15 -10
  147. package/src/components/Form/FormActions.tsx +21 -12
  148. package/src/components/Header/PageHeader/PageHeader.styles.ts +5 -5
  149. package/src/components/Layout/AreaIndicator.tsx +4 -6
  150. package/src/components/Layout/PageLayout/PageLayout.stories.tsx +1 -0
  151. package/src/components/Layout/PageLayout/PageLayout.styles.ts +1 -1
  152. package/src/components/Layout/PageLayout/PageLayout.tsx +9 -3
  153. package/src/components/Layout/PageLayout/PageLayoutActions.tsx +5 -3
  154. package/src/components/Layout/PageLayout/PageLayoutBody.tsx +5 -3
  155. package/src/components/Layout/PageLayout/PageLayoutHeader.tsx +5 -3
  156. package/src/components/Layout/PageLayout/PageQuickAccess.tsx +17 -17
  157. package/src/components/Menu/Button/MenuButton.tsx +6 -6
  158. package/src/components/Menu/MenuDivider.tsx +1 -5
  159. package/src/components/Menu/MenuItem.tsx +1 -5
  160. package/src/components/Menu/MenuItems.tsx +5 -4
  161. package/src/components/Modal/ConfirmationModal/ConfirmationModal.stories.tsx +1 -0
  162. package/src/components/Modal/ConfirmationModal/ConfirmationModal.tsx +4 -1
  163. package/src/components/Modal/Modal.stories.tsx +21 -0
  164. package/src/components/Modal/Modal.styles.ts +1 -19
  165. package/src/components/Modal/Modal.tsx +1 -1
  166. package/src/components/Modal/ModalBody.tsx +6 -4
  167. package/src/components/Modal/ModalHeader.tsx +9 -5
  168. package/src/components/Modal/modal.module.css +16 -0
  169. package/src/components/Tabs/Tab.styles.ts +0 -6
  170. package/src/components/Tabs/Tabs.tsx +37 -15
  171. package/src/index.ts +4 -0
  172. package/src/queryParameters/url/index.ts +7 -2
  173. package/src/utils/index.ts +1 -0
  174. package/src/utils/useLocale/index.ts +9 -0
  175. package/src/utils/useLocale/useLocale.cypress.spec.tsx +38 -0
  176. package/src/utils/useLocaleDateTimeFormat/index.ts +4 -2
  177. package/src/utils/usePluralizedTranslation.ts +2 -3
  178. package/src/Listing/Cell/DataCell.styles.ts +0 -27
  179. package/src/Listing/Header/Cell/ListingHeaderCell.styles.ts +0 -71
  180. package/src/Listing/Header/Cell/SelectActionListingHeaderCell.styles.ts +0 -26
  181. package/src/Listing/Header/ListingHeader.styles.ts +0 -16
  182. package/src/Listing/Listing.styles.ts +0 -78
  183. package/src/Listing/Row/EmptyRow.styles.ts +0 -14
  184. package/src/components/Button/Button.styles.ts +0 -44
  185. package/src/components/Layout/AreaIndicator.styles.ts +0 -33
  186. package/src/components/Menu/Button/MenuButton.styles.ts +0 -27
  187. package/src/components/Menu/Menu.styles.ts +0 -68
@@ -1,39 +1,14 @@
1
- import { makeStyles } from 'tss-react/mui';
2
-
3
1
  import { InputPropsWithoutGroup } from './models';
4
2
 
5
3
  import { Box, Typography } from '@mui/material';
6
4
  import { FormikValues, useFormikContext } from 'formik';
5
+ import { isNotEmpty, isNotNil } from 'ramda';
7
6
  import { getInput } from '.';
8
7
 
9
- interface StylesProps {
10
- alignItems?: string;
11
- columns?: number;
12
- gridTemplateColumns?: string;
13
- }
14
-
15
- const useStyles = makeStyles<StylesProps>()(
16
- (theme, { columns, gridTemplateColumns, alignItems }) => ({
17
- gridFields: {
18
- alignItems: alignItems || 'flex-start',
19
- columnGap: theme.spacing(4),
20
- display: 'grid',
21
- gridTemplateColumns: gridTemplateColumns || `repeat(${columns}, 1fr)`,
22
- rowGap: theme.spacing(2)
23
- }
24
- })
25
- );
26
-
27
8
  const Grid = ({
28
9
  grid,
29
10
  hideInput
30
11
  }: InputPropsWithoutGroup): JSX.Element | null => {
31
- const { classes, cx } = useStyles({
32
- alignItems: grid?.alignItems,
33
- columns: grid?.columns.length,
34
- gridTemplateColumns: grid?.gridTemplateColumns
35
- });
36
-
37
12
  const { values } = useFormikContext<FormikValues>();
38
13
 
39
14
  if (hideInput?.(values) ?? false) {
@@ -43,20 +18,34 @@ const Grid = ({
43
18
  const className = grid?.className || '';
44
19
 
45
20
  return (
46
- <div className={cx(classes.gridFields, className)}>
21
+ <div
22
+ className={`${className} grid gap-3`}
23
+ style={{
24
+ gridTemplateColumns: className
25
+ ? grid?.gridTemplateColumns || undefined
26
+ : grid?.gridTemplateColumns ||
27
+ `repeat(${grid?.columns.length || 1}, 1fr)`,
28
+ alignItems: grid?.alignItems || 'flex-start'
29
+ }}
30
+ >
47
31
  {grid?.columns.map((field) => {
48
32
  const Input = getInput(field.type);
49
33
 
34
+ const key =
35
+ isNotNil(field.label) || isNotEmpty(field.label)
36
+ ? field.label
37
+ : field.additionalLabel;
38
+
50
39
  if (field.hideInput?.(values) ?? false) {
51
40
  return null;
52
41
  }
53
42
 
54
43
  return (
55
- <Box sx={{ width: '100%' }} key={field.fieldName}>
44
+ <Box sx={{ width: '100%' }} key={key}>
56
45
  {field.additionalLabel && (
57
46
  <Typography
58
47
  sx={{ marginBottom: 0.5, color: 'primary.main' }}
59
- className={cx(field?.additionalLabelClassName)}
48
+ className={field?.additionalLabelClassName}
60
49
  variant="h6"
61
50
  >
62
51
  {field.additionalLabel}
@@ -0,0 +1,7 @@
1
+ import Divider from '@mui/material/Divider';
2
+
3
+ const SubgroupDivider = () => {
4
+ return <Divider className="border-dashed" />;
5
+ };
6
+
7
+ export { SubgroupDivider };
@@ -127,6 +127,7 @@ const Text = ({
127
127
  ariaLabel={t(label) || ''}
128
128
  autoFocus={autoFocus}
129
129
  dataTestId={dataTestId || label}
130
+ data-testid-suffix={`test-${label}`}
130
131
  disabled={disabled}
131
132
  error={error as string | undefined}
132
133
  label={t(label)}
@@ -20,6 +20,8 @@ import {
20
20
  groupBy,
21
21
  isEmpty,
22
22
  isNil,
23
+ isNotEmpty,
24
+ isNotNil,
23
25
  keys,
24
26
  last,
25
27
  not,
@@ -41,6 +43,7 @@ import Grid from './Grid';
41
43
  import List from './List/List';
42
44
  import LoadingSkeleton from './LoadingSkeleton';
43
45
  import RadioInput from './Radio';
46
+ import { SubgroupDivider } from './SubGroupDivider';
44
47
  import SwitchInput from './Switch';
45
48
  import TextInput from './Text';
46
49
  import { Group, InputProps, InputPropsWithoutGroup, InputType } from './models';
@@ -80,6 +83,11 @@ export const getInput = cond<
80
83
  ],
81
84
  [equals(InputType.List) as (b: InputType) => boolean, always(List)],
82
85
  [equals(InputType.File) as (b: InputType) => boolean, always(File)],
86
+ [equals(InputType.Text) as (b: InputType) => boolean, always(TextInput)],
87
+ [
88
+ equals(InputType.Divider) as (b: InputType) => boolean,
89
+ always(SubgroupDivider)
90
+ ],
83
91
  [T, always(TextInput)]
84
92
  ]);
85
93
 
@@ -114,9 +122,8 @@ const useStyles = makeStyles<StylesProps>()((theme, { groupDirection }) => ({
114
122
  inputs: {
115
123
  display: 'flex',
116
124
  flexDirection: 'column',
117
- marginTop: theme.spacing(1),
118
- rowGap: theme.spacing(2),
119
- marginBottom: theme.spacing(1)
125
+ margin: theme.spacing(2, 0),
126
+ rowGap: theme.spacing(2)
120
127
  }
121
128
  }));
122
129
 
@@ -203,6 +210,7 @@ const Inputs = ({
203
210
  ? find(propEq(groupName, 'name'), groups)
204
211
  : ({} as Group);
205
212
 
213
+ const hasGroupDivider = !groups[index]?.isDividerHidden;
206
214
  const isFirstElement = areGroupsOpen || equals(index, 0);
207
215
 
208
216
  return (
@@ -217,22 +225,19 @@ const Inputs = ({
217
225
  >
218
226
  <div className={classes.inputs}>
219
227
  {groupedInputs.map((inputProps) => {
228
+ const key =
229
+ isNotNil(inputProps.label) || isNotEmpty(inputProps.label)
230
+ ? inputProps.label
231
+ : inputProps.additionalLabel;
232
+
220
233
  if (isLoading) {
221
- return (
222
- <LoadingSkeleton
223
- input={inputProps}
224
- key={inputProps.label}
225
- />
226
- );
234
+ return <LoadingSkeleton input={inputProps} key={key} />;
227
235
  }
228
236
 
229
237
  const Input = getInput(inputProps.type);
230
238
 
231
239
  return (
232
- <div
233
- className={classes.inputWrapper}
234
- key={inputProps.label}
235
- >
240
+ <div className={classes.inputWrapper} key={key}>
236
241
  {inputProps.additionalLabel && (
237
242
  <Typography
238
243
  className={cx(
@@ -253,17 +258,19 @@ const Inputs = ({
253
258
  </div>
254
259
  </CollapsibleGroup>
255
260
  </div>
256
- {hasGroupTitle && not(equals(lastGroup, groupName as string)) && (
257
- <Divider
258
- flexItem
259
- className={classes.divider}
260
- orientation={
261
- equals(groupDirection, GroupDirection.Horizontal)
262
- ? 'vertical'
263
- : 'horizontal'
264
- }
265
- />
266
- )}
261
+ {hasGroupDivider &&
262
+ hasGroupTitle &&
263
+ not(equals(lastGroup, groupName as string)) && (
264
+ <Divider
265
+ flexItem
266
+ className={classes.divider}
267
+ orientation={
268
+ equals(groupDirection, GroupDirection.Horizontal)
269
+ ? 'vertical'
270
+ : 'horizontal'
271
+ }
272
+ />
273
+ )}
267
274
  </Fragment>
268
275
  );
269
276
  })}
@@ -4,6 +4,7 @@ import { SvgIconProps, TypographyProps } from '@mui/material';
4
4
 
5
5
  import { SelectEntry } from '../../InputField/Select';
6
6
  import { ConditionsSearchParameter } from '../../api/buildListingEndpoint/models';
7
+ import { QueryParameter } from '../../queryParameters/models';
7
8
 
8
9
  export enum InputType {
9
10
  Switch = 0,
@@ -20,7 +21,8 @@ export enum InputType {
20
21
  Checkbox = 11,
21
22
  CheckboxGroup = 12,
22
23
  List = 13,
23
- File = 14
24
+ File = 14,
25
+ Divider = 15
24
26
  }
25
27
 
26
28
  interface FieldsTableGetRequiredProps {
@@ -55,10 +57,14 @@ export interface InputProps {
55
57
  };
56
58
  connectedAutocomplete?: {
57
59
  additionalConditionParameters: Array<ConditionsSearchParameter>;
60
+ customQueryParameters: Array<QueryParameter>;
58
61
  chipColor?: string;
59
62
  endpoint?: string;
60
63
  filterKey?: string;
61
64
  getRenderedOptionText?: (option) => string | JSX.Element;
65
+ disableSelectAll?: boolean;
66
+ limitTags?: number;
67
+ decoder?;
62
68
  };
63
69
  file?: {
64
70
  multiple?: boolean;
@@ -133,4 +139,5 @@ export interface Group {
133
139
  name: string;
134
140
  order: number;
135
141
  titleAttributes?: TypographyProps;
142
+ isDividerHidden?: boolean;
136
143
  }
@@ -0,0 +1,34 @@
1
+ import { Box, TabsProps } from '@mui/material';
2
+ import { isNil } from 'ramda';
3
+ import { useMemo } from 'react';
4
+ import { Tabs } from '../../components/Tabs';
5
+ import { Group } from '../Inputs/models';
6
+ import { groupToTab } from './PanelTabs';
7
+ import { useNavigateToSection } from './navigateToSection';
8
+
9
+ export interface FormSectionProps extends TabsProps {
10
+ groups?: Group[];
11
+ }
12
+
13
+ const FormSection = ({ groups }: FormSectionProps) => {
14
+ if (isNil(groups) || groups.length < 4) {
15
+ return null;
16
+ }
17
+
18
+ const navigateToSection = useNavigateToSection();
19
+ const tabMemo = useMemo(() => groupToTab(groups), [groups]);
20
+
21
+ return (
22
+ <Box className="sticky top-0 bg-background-paper z-100">
23
+ <Tabs
24
+ variant="scrollable"
25
+ scrollButtons={false}
26
+ tabs={tabMemo}
27
+ defaultTab={tabMemo[0].value}
28
+ onChange={navigateToSection}
29
+ />
30
+ </Box>
31
+ );
32
+ };
33
+
34
+ export { FormSection };
@@ -0,0 +1,13 @@
1
+ import { prop, sortBy } from 'ramda';
2
+ import { TabI } from 'src/components/Tabs/Tabs';
3
+ import { Group } from '../Inputs/models';
4
+
5
+ const groupToTab = (groups: Array<Group>): Array<TabI> => {
6
+ const sortedGroups = sortBy(prop('order'), groups);
7
+
8
+ return sortedGroups.map((group) => {
9
+ return { value: group.name, label: group.name };
10
+ });
11
+ };
12
+
13
+ export { groupToTab };
@@ -0,0 +1,9 @@
1
+ export const useNavigateToSection = () => {
2
+ return (sectionName: string) => {
3
+ const section = document.querySelector(
4
+ `[data-section-group-form-id="${sectionName}"]`
5
+ );
6
+
7
+ section?.scrollIntoView({ behavior: 'smooth' });
8
+ };
9
+ };
@@ -157,12 +157,16 @@ export const basicFormGroups: Array<Group> = [
157
157
  {
158
158
  EndIcon: () => <HelpOutlineIcon />,
159
159
  TooltipContent: (): JSX.Element => <Typography>Tooltip content</Typography>,
160
+ name: 'Third group',
161
+ order: 3
162
+ },
163
+ {
160
164
  name: 'Second group',
161
165
  order: 2
162
166
  },
163
167
  {
164
- name: 'Third group',
165
- order: 3
168
+ name: 'Fourth group',
169
+ order: 4
166
170
  }
167
171
  ];
168
172
 
@@ -215,6 +219,12 @@ export const basicFormInputs: Array<InputProps> = [
215
219
  },
216
220
  type: InputType.Radio
217
221
  },
222
+ {
223
+ fieldName: 'div',
224
+ group: 'First group',
225
+ label: 'divider',
226
+ type: InputType.Divider
227
+ },
218
228
  {
219
229
  additionalLabel: 'Notifications',
220
230
  fieldName: '',
@@ -226,12 +236,12 @@ export const basicFormInputs: Array<InputProps> = [
226
236
  direction: 'horizontal'
227
237
  },
228
238
  fieldName: 'notifications.channels',
229
- label: 'channels',
239
+ label: 'mail',
230
240
  type: InputType.Checkbox
231
241
  },
232
242
  {
233
243
  fieldName: 'notifications.includeServices',
234
- label: 'Iclude services',
244
+ label: 'Include services for this host',
235
245
  type: InputType.Checkbox
236
246
  },
237
247
  {
@@ -4,10 +4,12 @@ import { useAtomValue } from 'jotai';
4
4
 
5
5
  import { userAtom } from '@centreon/ui-context';
6
6
 
7
+ import dataMissingPoint from '../mockedData/dataWithMissingPoint.json';
7
8
  import dataLastWeek from '../mockedData/lastWeek.json';
8
9
  import dataPingService from '../mockedData/pingService.json';
9
10
  import dataPingServiceMixedStacked from '../mockedData/pingServiceMixedStacked.json';
10
11
  import dataPingServiceStacked from '../mockedData/pingServiceStacked.json';
12
+ import dataPingServiceLinesStackKeys from '../mockedData/pingServiceWithStackedKeys.json';
11
13
 
12
14
  import BarChart, { BarChartProps } from './BarChart';
13
15
 
@@ -30,10 +32,20 @@ const initialize = ({
30
32
  tooltip,
31
33
  axis,
32
34
  orientation,
33
- barStyle
35
+ barStyle,
36
+ min,
37
+ max
34
38
  }: Pick<
35
39
  BarChartProps,
36
- 'data' | 'legend' | 'axis' | 'barStyle' | 'orientation' | 'tooltip' | 'start'
40
+ | 'data'
41
+ | 'legend'
42
+ | 'axis'
43
+ | 'barStyle'
44
+ | 'orientation'
45
+ | 'tooltip'
46
+ | 'start'
47
+ | 'min'
48
+ | 'max'
37
49
  >): void => {
38
50
  cy.adjustViewport();
39
51
 
@@ -47,6 +59,8 @@ const initialize = ({
47
59
  legend={legend}
48
60
  orientation={orientation ?? 'horizontal'}
49
61
  tooltip={tooltip}
62
+ min={min}
63
+ max={max}
50
64
  {...defaultArgs}
51
65
  />
52
66
  </div>
@@ -138,8 +152,6 @@ describe('Bar chart', () => {
138
152
  cy.contains(':40 AM').should('be.visible');
139
153
 
140
154
  cy.findByTestId('stacked-bar-3-0-0.16196').should('be.visible');
141
-
142
- cy.makeSnapshot();
143
155
  });
144
156
 
145
157
  it(`displays bar chart ${orientation}ly with a mix of stacked and non-stacked data centered in zero`, () => {
@@ -250,8 +262,6 @@ describe('Bar chart', () => {
250
262
  cy.contains('0.11 ms').should('be.visible');
251
263
 
252
264
  cy.findByTestId('stacked-bar-3-0-0.16196').should('be.visible');
253
-
254
- cy.makeSnapshot();
255
265
  });
256
266
 
257
267
  it('displays a tooltip with a single metric when a stacked bar is hovered and a prop is set', () => {
@@ -291,4 +301,34 @@ describe('Bar chart', () => {
291
301
  cy.contains('05/31/2023').should('be.visible');
292
302
  cy.contains('06/07/2023').should('be.visible');
293
303
  });
304
+
305
+ it('displays the bar chart according to min and max boundaries', () => {
306
+ initialize({
307
+ data: dataLastWeek,
308
+ min: -0.05,
309
+ max: 1
310
+ });
311
+
312
+ cy.contains('05/31/2023').should('be.visible');
313
+ cy.contains('06/07/2023').should('be.visible');
314
+ cy.contains('1 s').should('be.visible');
315
+ cy.contains('1%').should('be.visible');
316
+ });
317
+
318
+ it('displays the stacked bar chart correctly when a point is missing compare to the time serie', () => {
319
+ initialize({ data: dataMissingPoint });
320
+
321
+ cy.findByTestId('stacked-bar-2-0-139').should('be.visible');
322
+
323
+ cy.makeSnapshot();
324
+ });
325
+
326
+ it('displays the stacked bar chart with bars stacked together', () => {
327
+ initialize({ data: dataPingServiceLinesStackKeys });
328
+
329
+ cy.findByTestId('stacked-bar-3-0-0.05336').should('be.visible');
330
+ cy.findByTestId('stacked-bar-4-0-0.06684').should('be.visible');
331
+
332
+ cy.makeSnapshot();
333
+ });
294
334
  });
@@ -5,7 +5,10 @@ import { LineChartData } from '../common/models';
5
5
  import dataPingService from '../mockedData/pingService.json';
6
6
  import dataPingServiceMixedStacked from '../mockedData/pingServiceMixedStacked.json';
7
7
  import dataPingServiceStacked from '../mockedData/pingServiceStacked.json';
8
+ import dataPingServiceStackeKey from '../mockedData/pingServiceWithStackedKeys.json';
8
9
 
10
+ import { ClickAwayListener } from '@mui/material';
11
+ import { useState } from 'react';
9
12
  import BarChart from './BarChart';
10
13
 
11
14
  const meta: Meta<typeof BarChart> = {
@@ -250,3 +253,60 @@ export const mixedStackedVertical: Story = {
250
253
  },
251
254
  render: Template
252
255
  };
256
+
257
+ export const mixedStackedMinMax: Story = {
258
+ args: {
259
+ ...defaultArgs,
260
+ data: dataPingServiceMixedStacked,
261
+ min: 10,
262
+ max: 20
263
+ },
264
+ render: Template
265
+ };
266
+
267
+ const LegendSecondaryClick = (args) => {
268
+ const [position, setPosition] = useState<Array<[number, number]> | null>(
269
+ null
270
+ );
271
+
272
+ return (
273
+ <>
274
+ <Template
275
+ {...args}
276
+ legend={{
277
+ secondaryClick: ({ position }) => setPosition(position)
278
+ }}
279
+ />
280
+ {position && (
281
+ <ClickAwayListener onClickAway={() => setPosition(null)}>
282
+ <div
283
+ className="absolute py-1 px-2 rounded-sm bg-background-widget shadow-md"
284
+ style={{ left: position?.[0], top: position?.[1] }}
285
+ open={Boolean(position)}
286
+ onClose={() => setPosition(null)}
287
+ >
288
+ menu
289
+ </div>
290
+ </ClickAwayListener>
291
+ )}
292
+ </>
293
+ );
294
+ };
295
+
296
+ export const withLegendSecondaryClick: Story = {
297
+ args: defaultArgs,
298
+ render: (args) => (
299
+ <LegendSecondaryClick
300
+ {...args}
301
+ data={dataPingService as unknown as LineChartData}
302
+ />
303
+ )
304
+ };
305
+
306
+ export const stackKey: Story = {
307
+ args: {
308
+ ...defaultArgs,
309
+ data: dataPingServiceStackeKey
310
+ },
311
+ render: Template
312
+ };
@@ -1,5 +1,3 @@
1
- import { useRef } from 'react';
2
-
3
1
  import dayjs from 'dayjs';
4
2
  import 'dayjs/locale/en';
5
3
  import 'dayjs/locale/es';
@@ -12,12 +10,14 @@ import { Provider } from 'jotai';
12
10
 
13
11
  import { Box } from '@mui/material';
14
12
 
15
- import { ParentSize } from '../../ParentSize';
13
+ import Loading from '../../LoadingSkeleton';
16
14
  import LoadingSkeleton from '../Chart/LoadingSkeleton';
17
15
  import { LineChartProps } from '../Chart/models';
18
16
  import useChartData from '../Chart/useChartData';
19
17
  import { LineChartData, Thresholds } from '../common/models';
20
18
 
19
+ import { ReactElement } from 'react';
20
+ import useResizeObserver from 'use-resize-observer';
21
21
  import ResponsiveBarChart from './ResponsiveBarChart';
22
22
  import { BarStyle } from './models';
23
23
 
@@ -27,7 +27,20 @@ dayjs.extend(timezonePlugin);
27
27
 
28
28
  export interface BarChartProps
29
29
  extends Partial<
30
- Pick<LineChartProps, 'tooltip' | 'legend' | 'height' | 'axis' | 'header'>
30
+ Pick<
31
+ LineChartProps,
32
+ | 'tooltip'
33
+ | 'legend'
34
+ | 'height'
35
+ | 'axis'
36
+ | 'header'
37
+ | 'min'
38
+ | 'max'
39
+ | 'boundariesUnit'
40
+ | 'timeShiftZones'
41
+ | 'zoomPreview'
42
+ | 'annotationEvent'
43
+ >
31
44
  > {
32
45
  barStyle?: BarStyle;
33
46
  data?: LineChartData;
@@ -59,10 +72,16 @@ const BarChart = ({
59
72
  opacity: 1,
60
73
  radius: 0.2
61
74
  },
62
- skipIntersectionObserver
63
- }: BarChartProps): JSX.Element => {
64
- const { adjustedData } = useChartData({ data, end, start });
65
- const lineChartRef = useRef<HTMLDivElement | null>(null);
75
+ skipIntersectionObserver,
76
+ min,
77
+ max,
78
+ boundariesUnit,
79
+ zoomPreview,
80
+ timeShiftZones,
81
+ annotationEvent
82
+ }: BarChartProps): ReactElement => {
83
+ const { adjustedData } = useChartData({ data, end, start, min, max });
84
+ const { ref, width, height: responsiveHeight } = useResizeObserver();
66
85
 
67
86
  if (loading && !adjustedData) {
68
87
  return (
@@ -75,30 +94,35 @@ const BarChart = ({
75
94
 
76
95
  return (
77
96
  <Provider>
78
- <Box
79
- ref={lineChartRef}
80
- sx={{ height: '100%', overflow: 'hidden', width: '100%' }}
81
- >
82
- <ParentSize>
83
- {({ height: responsiveHeight, width }) => (
84
- <ResponsiveBarChart
85
- axis={axis}
86
- barStyle={barStyle}
87
- graphData={adjustedData}
88
- graphRef={lineChartRef}
89
- header={header}
90
- height={height || responsiveHeight}
91
- legend={legend}
92
- limitLegend={limitLegend}
93
- orientation={orientation}
94
- thresholdUnit={thresholdUnit}
95
- thresholds={thresholds}
96
- tooltip={tooltip}
97
- width={width}
98
- skipIntersectionObserver={skipIntersectionObserver}
99
- />
100
- )}
101
- </ParentSize>
97
+ <Box ref={ref} sx={{ height: '100%', overflow: 'hidden', width: '100%' }}>
98
+ {!responsiveHeight ? (
99
+ <Loading height={height || '100%'} width={width} />
100
+ ) : (
101
+ <ResponsiveBarChart
102
+ axis={axis}
103
+ barStyle={barStyle}
104
+ graphData={adjustedData}
105
+ graphRef={ref}
106
+ header={header}
107
+ height={height || responsiveHeight || 0}
108
+ legend={legend}
109
+ limitLegend={limitLegend}
110
+ orientation={orientation}
111
+ thresholdUnit={thresholdUnit}
112
+ thresholds={thresholds}
113
+ tooltip={tooltip}
114
+ width={width || 0}
115
+ skipIntersectionObserver={skipIntersectionObserver}
116
+ min={min}
117
+ max={max}
118
+ boundariesUnit={boundariesUnit}
119
+ zoomPreview={zoomPreview}
120
+ timeShiftZones={timeShiftZones}
121
+ annotationEvent={annotationEvent}
122
+ start={start}
123
+ end={end}
124
+ />
125
+ )}
102
126
  </Box>
103
127
  </Provider>
104
128
  );