@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
@@ -36,6 +36,7 @@ interface UseMetricsQueryProps {
36
36
  start?: string | null;
37
37
  timePeriodType: number;
38
38
  };
39
+ isEnabled?: boolean;
39
40
  }
40
41
 
41
42
  interface UseMetricsQueryState {
@@ -46,6 +47,12 @@ interface UseMetricsQueryState {
46
47
  start: string;
47
48
  }
48
49
 
50
+ interface FormatLegend {
51
+ host?: string | null;
52
+ service?: string | null;
53
+ metric: string;
54
+ }
55
+
49
56
  const getStartEndFromTimePeriod = (
50
57
  timePeriod: number
51
58
  ): { end: string; start: string } => {
@@ -95,7 +102,8 @@ const useGraphQuery = ({
95
102
  refreshInterval = false,
96
103
  refreshCount,
97
104
  bypassQueryParams = false,
98
- prefix
105
+ prefix,
106
+ isEnabled = true
99
107
  }: UseMetricsQueryProps): UseMetricsQueryState => {
100
108
  const timePeriodToUse = equals(timePeriod?.timePeriodType, -1)
101
109
  ? {
@@ -152,7 +160,10 @@ const useGraphQuery = ({
152
160
  refreshCount || 0
153
161
  ],
154
162
  queryOptions: {
155
- enabled: areResourcesFullfilled(resources) && !isEmpty(definedMetrics),
163
+ enabled:
164
+ areResourcesFullfilled(resources) &&
165
+ !isEmpty(definedMetrics) &&
166
+ isEnabled,
156
167
  refetchInterval: refreshInterval,
157
168
  suspense: false
158
169
  },
@@ -164,22 +175,107 @@ const useGraphQuery = ({
164
175
  data.current = graphData;
165
176
  }
166
177
 
178
+ const getCurrentMetrics = () => {
179
+ if (!data.current) {
180
+ return undefined;
181
+ }
182
+
183
+ return bypassMetricsExclusion
184
+ ? data.current.metrics
185
+ : data.current.metrics.filter(({ metric_id }) => {
186
+ return pipe(
187
+ pluck('excludedMetrics'),
188
+ flatten,
189
+ includes(metric_id),
190
+ not
191
+ )(metrics);
192
+ });
193
+ };
194
+
195
+ const formatLegend = ({
196
+ host = null,
197
+ service = null,
198
+ metric
199
+ }: FormatLegend) => {
200
+ if (!host && !service) {
201
+ return metric;
202
+ }
203
+
204
+ if (!host) {
205
+ return `${service}: ${metric}`;
206
+ }
207
+
208
+ if (!service) {
209
+ return `${host}: ${metric}`;
210
+ }
211
+
212
+ return `${host} ${service}: ${metric}`;
213
+ };
214
+
215
+ const getFormattedMetrics = () => {
216
+ const metrics = getCurrentMetrics();
217
+
218
+ if (equals(metrics?.length, 1)) {
219
+ return metrics?.map((line) => {
220
+ const formattedLegend = formatLegend({
221
+ host: line?.host_name,
222
+ service: line?.service_name,
223
+ metric: line?.metric
224
+ });
225
+
226
+ return { ...line, legend: formattedLegend };
227
+ });
228
+ }
229
+
230
+ return metrics?.map((line) => {
231
+ const areHostNameRedundant = metrics.every(({ host_name }) =>
232
+ equals(host_name, line.host_name)
233
+ );
234
+ const areServiceNameRedundant = metrics.every(({ service_name }) =>
235
+ equals(service_name, line.service_name)
236
+ );
237
+
238
+ if (areHostNameRedundant && areServiceNameRedundant) {
239
+ const formattedLegend = formatLegend({ metric: line.metric });
240
+
241
+ return { ...line, legend: formattedLegend };
242
+ }
243
+
244
+ if (areHostNameRedundant) {
245
+ const formattedLegend = formatLegend({
246
+ service: line.service_name,
247
+ metric: line.metric
248
+ });
249
+
250
+ return { ...line, legend: formattedLegend };
251
+ }
252
+
253
+ if (areServiceNameRedundant) {
254
+ const formattedLegend = formatLegend({
255
+ host: line.host_name,
256
+ metric: line.metric
257
+ });
258
+
259
+ return { ...line, legend: formattedLegend };
260
+ }
261
+
262
+ const formattedLegend = formatLegend({
263
+ host: line.host_name,
264
+ service: line.service_name,
265
+ metric: line.metric
266
+ });
267
+
268
+ return { ...line, legend: formattedLegend };
269
+ });
270
+ };
271
+
167
272
  const formattedGraphData = data.current
168
273
  ? {
169
274
  global: {
170
275
  base: data.current.base,
171
276
  title: ''
172
277
  },
173
- metrics: bypassMetricsExclusion
174
- ? data.current.metrics
175
- : data.current.metrics.filter(({ metric_id }) => {
176
- return pipe(
177
- pluck('excludedMetrics'),
178
- flatten,
179
- includes(metric_id),
180
- not
181
- )(metrics);
182
- }),
278
+ metrics: getFormattedMetrics(),
183
279
  times: data.current.times
184
280
  }
185
281
  : undefined;
@@ -1,6 +1,7 @@
1
1
  import { Meta, StoryObj } from '@storybook/react';
2
2
 
3
3
  import Avatar from './Avatar';
4
+ import '../../ThemeProvider/tailwindcss.css';
4
5
 
5
6
  const meta: Meta<typeof Avatar> = {
6
7
  component: Avatar
@@ -0,0 +1,38 @@
1
+ .button {
2
+ &[data-size="medium"] {
3
+ font-size: 16px;
4
+ height: unset;
5
+ line-height: 24px;
6
+ }
7
+
8
+ &[data-size="small"] {
9
+ &[data-variant="primary"] {
10
+ padding-left: var(--spacing-4);
11
+ padding-right: var(--spacing-4);
12
+ }
13
+
14
+ font-size: 14px;
15
+ height: unset;
16
+ line-height: 22px;
17
+ }
18
+
19
+ &[data-variant="primary"]:not(:disabled) {
20
+ &[data-is-danger="true"] {
21
+ background-color: var(--color-error-main);
22
+ }
23
+
24
+ background-color: var(--color-primary-main);
25
+ }
26
+
27
+ &[data-variant="secondary"]:not(:disabled) {
28
+ &[data-is-danger="true"] {
29
+ border-color: var(--color-error-main);
30
+ color: var(--color-error-main);
31
+ }
32
+
33
+ border-color: var(--color-primary-main);
34
+ color: var(--color-primary-main);
35
+ }
36
+
37
+ text-wrap: nowrap;
38
+ }
@@ -1,3 +1,4 @@
1
+ import '../../ThemeProvider/tailwindcss.css';
1
2
  import { Meta, StoryObj } from '@storybook/react';
2
3
 
3
4
  import { Add as AddIcon } from '@mui/icons-material';
@@ -32,3 +33,27 @@ export const AsDanger: Story = {
32
33
  isDanger: true
33
34
  }
34
35
  };
36
+
37
+ export const small: Story = {
38
+ args: {
39
+ ...Default.args,
40
+ size: 'small'
41
+ }
42
+ };
43
+
44
+ export const smallWithIcon: Story = {
45
+ args: {
46
+ ...Default.args,
47
+ size: 'small',
48
+ icon: <AddIcon />,
49
+ iconVariant: 'start'
50
+ }
51
+ };
52
+
53
+ export const smallDanger: Story = {
54
+ args: {
55
+ ...Default.args,
56
+ size: 'small',
57
+ isDanger: true
58
+ }
59
+ };
@@ -7,8 +7,7 @@ import {
7
7
 
8
8
  import { AriaLabelingAttributes } from '../../@types/aria-attributes';
9
9
  import { DataTestAttributes } from '../../@types/data-attributes';
10
-
11
- import { useStyles } from './Button.styles';
10
+ import { button } from './Button.module.css';
12
11
 
13
12
  const muiVariantMap: Record<
14
13
  Required<ButtonProps>['variant'],
@@ -48,8 +47,6 @@ const Button = ({
48
47
  className = '',
49
48
  ...attr
50
49
  }: ButtonProps): ReactElement => {
51
- const { classes, cx } = useStyles();
52
-
53
50
  const MuiOverrideProps = useMemo(
54
51
  () => ({
55
52
  color: 'primary' as const,
@@ -61,7 +58,7 @@ const Button = ({
61
58
 
62
59
  return (
63
60
  <MuiButton
64
- className={cx(classes.button, className)}
61
+ className={`${button} ${className}`}
65
62
  data-icon-variant={iconVariant}
66
63
  data-is-danger={isDanger}
67
64
  data-size={size}
@@ -2,7 +2,21 @@ import { makeStyles } from 'tss-react/mui';
2
2
 
3
3
  export const useActionsStyles = makeStyles()((theme) => ({
4
4
  search: {
5
- maxWidth: theme.spacing(50)
5
+ maxWidth: theme.spacing(60),
6
+ minWidth: theme.spacing(20),
7
+ width: '100%'
8
+ },
9
+ filters: {
10
+ width: '100%',
11
+ paddingInline: theme.spacing(1),
12
+ display: 'flex',
13
+ alignItems: 'center',
14
+ justifyContent: 'center'
15
+ },
16
+ actions: {
17
+ display: 'grid',
18
+ gridTemplateColumns: 'min-content auto',
19
+ gap: theme.spacing(1)
6
20
  },
7
21
  clearButton: {
8
22
  alignSelf: 'flex-start'
@@ -1,4 +1,5 @@
1
1
  import { Box } from '@mui/material';
2
+ import { useActionsStyles } from './Actions.styles';
2
3
  import AddButton from './AddButton';
3
4
  import Search from './Search';
4
5
 
@@ -11,12 +12,14 @@ interface Props {
11
12
  }
12
13
 
13
14
  const Actions = ({ labels, filters }: Props): JSX.Element => {
15
+ const { classes } = useActionsStyles();
16
+
14
17
  return (
15
- <Box
16
- sx={{ display: 'grid', gridTemplateColumns: 'min-content auto', gap: 2 }}
17
- >
18
+ <Box className={classes.actions}>
18
19
  <AddButton label={labels.add} />
19
- <Search label={labels.search} filters={filters} />
20
+ <div className={classes.filters}>
21
+ <Search label={labels.search} filters={filters} />
22
+ </div>
20
23
  </Box>
21
24
  );
22
25
  };
@@ -14,21 +14,22 @@ const Search = ({ label, filters }: Props): JSX.Element => {
14
14
  const { change } = useSearch();
15
15
 
16
16
  return (
17
- <SearchField
18
- className={classes.search}
19
- debounced
20
- fullWidth
21
- dataTestId={label}
22
- placeholder={label}
23
- onChange={change}
24
- textFieldSlotsAndSlotProps={{
25
- slotProps: {
26
- input: {
27
- endAdornment: <Filters label="filters" filters={filters} />
17
+ <div className={classes.search}>
18
+ <SearchField
19
+ debounced
20
+ fullWidth
21
+ dataTestId={label}
22
+ placeholder={label}
23
+ onChange={change}
24
+ textFieldSlotsAndSlotProps={{
25
+ slotProps: {
26
+ input: {
27
+ endAdornment: <Filters label="filters" filters={filters} />
28
+ }
28
29
  }
29
- }
30
- }}
31
- />
30
+ }}
31
+ />
32
+ </div>
32
33
  );
33
34
  };
34
35
 
@@ -7,6 +7,7 @@ import { ChangeEvent, useEffect } from 'react';
7
7
  import { CrudPage } from '.';
8
8
  import { SnackbarProvider } from '../../';
9
9
  import { Column, ColumnType } from '../../Listing/models';
10
+ import '../../ThemeProvider/tailwindcss.css';
10
11
 
11
12
  interface Item {
12
13
  id: number;
@@ -97,7 +97,7 @@ export const CrudPageRoot = <
97
97
  {isDataEmpty && !isLoading ? (
98
98
  <DataTable.EmptyState
99
99
  aria-label="create"
100
- data-testid="create-agent-configuration"
100
+ buttonCreateTestId="create-crudpage"
101
101
  labels={{
102
102
  title: labels.welcome.title,
103
103
  description: labels.welcome.description,
@@ -5,6 +5,7 @@ import { Box } from '@mui/material';
5
5
  import { ColumnType } from '../../Listing/models';
6
6
 
7
7
  import { DataTable } from './index';
8
+ import '../../ThemeProvider/tailwindcss.css';
8
9
 
9
10
  const meta: Meta<typeof DataTable> = {
10
11
  component: DataTable
@@ -1,6 +1,7 @@
1
1
  import { Meta, StoryObj } from '@storybook/react';
2
2
 
3
3
  import { DataTableEmptyState } from './DataTableEmptyState';
4
+ import '../../../ThemeProvider/tailwindcss.css';
4
5
 
5
6
  const meta: Meta<typeof DataTableEmptyState> = {
6
7
  component: DataTableEmptyState
@@ -6,6 +6,7 @@ const useStyles = makeStyles()((theme) => ({
6
6
  flexDirection: 'row'
7
7
  },
8
8
  dataTableEmptyState: {
9
+ marginTop: theme.spacing(3),
9
10
  alignItems: 'center',
10
11
  display: 'flex',
11
12
  flexDirection: 'column',
@@ -21,7 +22,8 @@ const useStyles = makeStyles()((theme) => ({
21
22
  width: '100%'
22
23
  },
23
24
  description: {
24
- maxWidth: '65%'
25
+ maxWidth: '65%',
26
+ textAlign: 'center'
25
27
  }
26
28
  }));
27
29
 
@@ -19,12 +19,14 @@ type ListEmptyStateProps = {
19
19
  description?: string;
20
20
  };
21
21
  onCreate?: () => void;
22
+ buttonCreateTestId?: string;
22
23
  };
23
24
 
24
25
  const DataTableEmptyState = ({
25
26
  labels,
26
27
  onCreate,
27
- canCreate = true
28
+ canCreate = true,
29
+ buttonCreateTestId
28
30
  }: ListEmptyStateProps): ReactElement => {
29
31
  const { classes } = useStyles();
30
32
  const { t } = useTranslation();
@@ -47,6 +49,7 @@ const DataTableEmptyState = ({
47
49
  icon={<AddIcon />}
48
50
  iconVariant="start"
49
51
  onClick={() => onCreate?.()}
52
+ data-testid={buttonCreateTestId}
50
53
  >
51
54
  {t(labels.actions?.create || '')}
52
55
  </Button>
@@ -1,6 +1,7 @@
1
1
  import { Meta, StoryObj } from '@storybook/react';
2
2
 
3
3
  import { DataTableItem } from './DataTableItem';
4
+ import '../../../ThemeProvider/tailwindcss.css';
4
5
 
5
6
  const meta: Meta<typeof DataTableItem> = {
6
7
  component: DataTableItem
@@ -12,6 +12,7 @@ import {
12
12
  labels,
13
13
  roles
14
14
  } from './storiesData';
15
+ import '../../../ThemeProvider/tailwindcss.css';
15
16
 
16
17
  const meta: Meta<typeof AccessRights> = {
17
18
  component: AccessRights,
@@ -8,6 +8,7 @@ import { SelectEntry, SingleConnectedAutocompleteField } from '../../../..';
8
8
  import RoleSelectField from '../common/RoleSelectField';
9
9
  import { Endpoints, Labels } from '../models';
10
10
 
11
+ import { ReactElement } from 'react';
11
12
  import ContactSwitch from './ContactSwitch';
12
13
  import { useShareInputStyles } from './ShareInput.styles';
13
14
  import useShareInput from './useShareInput';
@@ -18,18 +19,18 @@ interface Props {
18
19
  roles: Array<SelectEntry>;
19
20
  }
20
21
 
21
- const ShareInput = ({ labels, endpoints, roles }: Props): JSX.Element => {
22
+ const ShareInput = ({ labels, endpoints, roles }: Props): ReactElement => {
22
23
  const { t } = useTranslation();
23
24
  const { classes } = useShareInputStyles();
24
25
 
25
26
  const {
26
- renderOption,
27
27
  selectedContact,
28
28
  getOptionDisabled,
29
29
  getEndpoint,
30
30
  selectContact,
31
31
  isContactGroup,
32
32
  selectedRole,
33
+ getRenderedOptionText,
33
34
  setSelectedRole,
34
35
  add,
35
36
  changeIdValue
@@ -46,6 +47,7 @@ const ShareInput = ({ labels, endpoints, roles }: Props): JSX.Element => {
46
47
  disableClearable={false}
47
48
  field="name"
48
49
  getEndpoint={getEndpoint}
50
+ getRenderedOptionText={getRenderedOptionText}
49
51
  getOptionDisabled={getOptionDisabled}
50
52
  label={t(
51
53
  isContactGroup
@@ -53,7 +55,6 @@ const ShareInput = ({ labels, endpoints, roles }: Props): JSX.Element => {
53
55
  : t(labels.autocompleteContact)
54
56
  )}
55
57
  queryKey={isContactGroup ? labels.contactGroup : labels.contact}
56
- renderOption={renderOption}
57
58
  value={selectedContact}
58
59
  onChange={selectContact}
59
60
  />
@@ -1,10 +1,15 @@
1
- import { Dispatch, SetStateAction, useEffect, useState } from 'react';
1
+ import {
2
+ Dispatch,
3
+ ReactElement,
4
+ SetStateAction,
5
+ useEffect,
6
+ useState
7
+ } from 'react';
2
8
 
3
9
  import { useAtomValue, useSetAtom } from 'jotai';
4
10
  import { equals, includes, isNil } from 'ramda';
5
11
 
6
12
  import CheckCircleIcon from '@mui/icons-material/CheckCircle';
7
- import { ListItemText, MenuItem } from '@mui/material';
8
13
 
9
14
  import { SelectEntry, buildListingEndpoint } from '../../../..';
10
15
  import {
@@ -20,7 +25,7 @@ interface UseShareInputState {
20
25
  getEndpoint: (parameters) => string;
21
26
  getOptionDisabled: (option) => boolean;
22
27
  isContactGroup: boolean;
23
- renderOption: (attr, option) => JSX.Element;
28
+ getRenderedOptionText: (option: unknown) => ReactElement | string;
24
29
  selectContact: (_, entry) => void;
25
30
  selectedContact: AccessRightInitialValues | null;
26
31
  selectedRole: string;
@@ -40,7 +45,7 @@ const useShareInput = (endpoints: Endpoints): UseShareInputState => {
40
45
 
41
46
  const selectContact = (_, entry): void => {
42
47
  setSelectedContact(entry);
43
- if (equals('editor', entry.most_permissive_role)) {
48
+ if (equals('editor', entry?.most_permissive_role)) {
44
49
  return;
45
50
  }
46
51
  setSelectedRole('viewer');
@@ -71,14 +76,14 @@ const useShareInput = (endpoints: Endpoints): UseShareInputState => {
71
76
  }
72
77
  });
73
78
 
74
- const renderOption = (attr, option): JSX.Element => {
79
+ const getRenderedOptionText = (option): ReactElement => {
75
80
  return (
76
- <MenuItem {...attr}>
77
- <ListItemText>{option.name}</ListItemText>
78
- {includes(option.id, accessRightIds) && (
81
+ <>
82
+ {option?.name}
83
+ {includes(option?.id, accessRightIds) && (
79
84
  <CheckCircleIcon color="success" />
80
85
  )}
81
- </MenuItem>
86
+ </>
82
87
  );
83
88
  };
84
89
 
@@ -102,7 +107,7 @@ const useShareInput = (endpoints: Endpoints): UseShareInputState => {
102
107
  getEndpoint,
103
108
  getOptionDisabled,
104
109
  isContactGroup,
105
- renderOption,
110
+ getRenderedOptionText,
106
111
  selectContact,
107
112
  selectedContact,
108
113
  selectedRole,
@@ -12,6 +12,8 @@ export type FormActionsProps = {
12
12
  labels: FormActionsLabels;
13
13
  onCancel: () => void;
14
14
  variant: FormVariant;
15
+ isCancelButtonVisible?: boolean;
16
+ disableSubmit?: boolean;
15
17
  };
16
18
 
17
19
  export type FormActionsLabels = {
@@ -23,27 +25,34 @@ const FormActions = <TResource extends object>({
23
25
  labels,
24
26
  onCancel,
25
27
  variant,
26
- enableSubmitWhenNotDirty
28
+ enableSubmitWhenNotDirty,
29
+ isCancelButtonVisible = true,
30
+ disableSubmit = false
27
31
  }: FormActionsProps): ReactElement => {
28
32
  const { classes } = useStyles();
29
33
  const { isSubmitting, dirty, isValid, submitForm } =
30
34
  useFormikContext<TResource>();
31
35
 
32
36
  const isSubmitDisabled =
33
- isSubmitting || (!dirty && !enableSubmitWhenNotDirty) || !isValid;
37
+ disableSubmit ||
38
+ isSubmitting ||
39
+ (!dirty && !enableSubmitWhenNotDirty) ||
40
+ !isValid;
34
41
 
35
42
  return (
36
43
  <div className={classes.actions}>
37
- <Button
38
- aria-label={labels.cancel}
39
- data-testid="cancel"
40
- disabled={isSubmitting}
41
- size="medium"
42
- variant="secondary"
43
- onClick={() => onCancel?.()}
44
- >
45
- {labels.cancel}
46
- </Button>
44
+ {isCancelButtonVisible && (
45
+ <Button
46
+ aria-label={labels.cancel}
47
+ data-testid="cancel"
48
+ disabled={isSubmitting}
49
+ size="medium"
50
+ variant="secondary"
51
+ onClick={() => onCancel?.()}
52
+ >
53
+ {labels.cancel}
54
+ </Button>
55
+ )}
47
56
  <Button
48
57
  aria-label={labels.submit[variant]}
49
58
  data-testid="submit"
@@ -25,9 +25,10 @@ const useStyles = makeStyles()((theme) => ({
25
25
  },
26
26
  pageHeader: {
27
27
  alignItems: 'center',
28
- borderBottom: `1px solid ${theme.palette.header.page.border}`,
28
+ borderBottom: `2px solid ${theme.palette.header.page.border}`,
29
29
  display: 'flex',
30
- gap: theme.spacing(4)
30
+ gap: theme.spacing(4),
31
+ paddingBottom: theme.spacing(0.5)
31
32
  },
32
33
  pageHeaderActions: {
33
34
  '& > button': {
@@ -46,8 +47,7 @@ const useStyles = makeStyles()((theme) => ({
46
47
  pageHeaderMain: {
47
48
  display: 'flex',
48
49
  flexGrow: 1,
49
- gap: theme.spacing(1),
50
- minHeight: theme.spacing(4.5)
50
+ gap: theme.spacing(1)
51
51
  },
52
52
  pageHeaderMenu: {
53
53
  alignItems: 'flex-start',
@@ -96,7 +96,7 @@ const useStyles = makeStyles()((theme) => ({
96
96
  alignSelf: 'flex-start',
97
97
  h1: {
98
98
  ...theme.typography.h5,
99
- fontWeight: theme.typography.fontWeightMedium,
99
+ fontWeight: theme.typography.fontWeightBold,
100
100
  margin: theme.spacing(0),
101
101
  lineHeight: '1'
102
102
  }
@@ -1,7 +1,5 @@
1
1
  import { ReactElement, ReactNode } from 'react';
2
2
 
3
- import { useStyles } from './AreaIndicator.styles';
4
-
5
3
  type AreaIndicatorProps = {
6
4
  children?: ReactNode | Array<ReactNode>;
7
5
  depth?: number;
@@ -17,16 +15,16 @@ const AreaIndicator = ({
17
15
  height = '100%',
18
16
  depth = 0
19
17
  }: AreaIndicatorProps): ReactElement => {
20
- const { classes } = useStyles();
21
-
22
18
  return (
23
19
  <div
24
- className={classes.areaIndicator}
20
+ className={'bg-secondary-main/25 min-h-8 grid grid-cols-[3fr_1fr]'}
25
21
  data-depth={depth}
26
22
  style={{ height, width }}
27
23
  >
28
24
  {/* biome-ignore lint/a11y: */}
29
- <label>{name}</label>
25
+ <label className="left-2 rounded-sm border border-[#9747FF7F] border-dashed text-[#9747FF] text-[0.75rem] font-medium left-2 top-1.5 px-2 py-0.5">
26
+ {name}
27
+ </label>
30
28
  {children}
31
29
  </div>
32
30
  );