@centreon/ui 24.4.1-sync-release-34022.1 → 24.4.1-test-code-coverage.1

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 (220) hide show
  1. package/package.json +48 -40
  2. package/src/ActionsList/ActionsList.styles.ts +40 -71
  3. package/src/Button/Icon/index.stories.tsx +1 -1
  4. package/src/Button/Icon/index.tsx +1 -1
  5. package/src/Dashboard/Dashboard.styles.ts +6 -5
  6. package/src/Dialog/Confirm/index.tsx +10 -2
  7. package/src/Dialog/UnsavedChanges/index.tsx +21 -20
  8. package/src/Dialog/UnsavedChanges/translatedLabels.ts +4 -6
  9. package/src/Dialog/index.tsx +8 -1
  10. package/src/Form/Inputs/CheckboxGroup.tsx +4 -1
  11. package/src/Form/Inputs/Text.tsx +3 -1
  12. package/src/Form/Inputs/models.ts +1 -0
  13. package/src/Graph/BarStack/BarStack.cypress.spec.tsx +139 -0
  14. package/src/Graph/BarStack/BarStack.stories.tsx +123 -0
  15. package/src/Graph/BarStack/BarStack.styles.ts +37 -0
  16. package/src/Graph/BarStack/BarStack.tsx +14 -0
  17. package/src/Graph/BarStack/ResponsiveBarStack.tsx +209 -0
  18. package/src/Graph/BarStack/index.ts +1 -0
  19. package/src/Graph/BarStack/models.ts +19 -0
  20. package/src/Graph/BarStack/useResponsiveBarStack.ts +131 -0
  21. package/src/Graph/Gauge/Gauge.cypress.spec.tsx +102 -0
  22. package/src/Graph/Gauge/Gauge.tsx +1 -1
  23. package/src/Graph/HeatMap/HeatMap.cypress.spec.tsx +145 -0
  24. package/src/Graph/HeatMap/HeatMap.stories.tsx +0 -25
  25. package/src/Graph/HeatMap/ResponsiveHeatMap.tsx +8 -2
  26. package/src/Graph/Legend/Legend.tsx +21 -0
  27. package/src/Graph/Legend/index.ts +1 -0
  28. package/src/Graph/Legend/models.ts +11 -0
  29. package/src/Graph/LineChart/BasicComponents/Lines/Threshold/index.tsx +4 -5
  30. package/src/Graph/LineChart/BasicComponents/ThresholdLine.tsx +3 -1
  31. package/src/Graph/LineChart/Header/index.tsx +3 -31
  32. package/src/Graph/LineChart/InteractiveComponents/AnchorPoint/useTickGraph.ts +9 -11
  33. package/src/Graph/LineChart/InteractiveComponents/Annotations/Annotation/index.tsx +3 -2
  34. package/src/Graph/LineChart/InteractiveComponents/GraphValueTooltip/GraphValueTooltip.tsx +68 -0
  35. package/src/Graph/LineChart/InteractiveComponents/GraphValueTooltip/useGraphValueTooltip.ts +27 -0
  36. package/src/Graph/LineChart/InteractiveComponents/GraphValueTooltip/useGraphValueTooltipStyles.ts +31 -0
  37. package/src/Graph/LineChart/InteractiveComponents/index.tsx +132 -17
  38. package/src/Graph/LineChart/InteractiveComponents/interactionWithGraphAtoms.ts +7 -27
  39. package/src/Graph/LineChart/Legend/Legend.styles.ts +5 -9
  40. package/src/Graph/LineChart/Legend/LegendHeader.tsx +10 -22
  41. package/src/Graph/LineChart/Legend/index.tsx +17 -55
  42. package/src/Graph/LineChart/LineChart.cypress.spec.tsx +91 -0
  43. package/src/Graph/LineChart/LineChart.styles.ts +8 -0
  44. package/src/Graph/LineChart/LineChart.tsx +106 -116
  45. package/src/Graph/LineChart/LoadingSkeleton.tsx +2 -2
  46. package/src/Graph/LineChart/index.tsx +6 -7
  47. package/src/Graph/LineChart/mockedData/lastDayWithIncompleteValues.json +1320 -0
  48. package/src/Graph/LineChart/mockedData/lastDayWithNullValues.json +1314 -0
  49. package/src/Graph/LineChart/models.ts +12 -1
  50. package/src/Graph/PieChart/PieChart.cypress.spec.tsx +154 -0
  51. package/src/Graph/PieChart/PieChart.stories.tsx +194 -0
  52. package/src/Graph/PieChart/PieChart.styles.ts +39 -0
  53. package/src/Graph/PieChart/PieChart.tsx +14 -0
  54. package/src/Graph/PieChart/ResponsivePie.tsx +243 -0
  55. package/src/Graph/PieChart/index.ts +1 -0
  56. package/src/Graph/PieChart/models.ts +19 -0
  57. package/src/Graph/PieChart/useResponsivePie.ts +81 -0
  58. package/src/Graph/SingleBar/SingleBar.cypress.spec.tsx +121 -0
  59. package/src/Graph/Text/Text.cypress.spec.tsx +101 -0
  60. package/src/Graph/Text/Text.styles.ts +12 -1
  61. package/src/Graph/Text/Text.tsx +17 -12
  62. package/src/Graph/Tree/DescendantNodes.tsx +89 -0
  63. package/src/Graph/Tree/Links.tsx +77 -0
  64. package/src/Graph/Tree/StandaloneTree.tsx +32 -0
  65. package/src/Graph/Tree/Tree.cypress.spec.tsx +195 -0
  66. package/src/Graph/Tree/Tree.stories.tsx +160 -0
  67. package/src/Graph/Tree/Tree.tsx +116 -0
  68. package/src/Graph/Tree/constants.ts +2 -0
  69. package/src/Graph/Tree/index.ts +4 -0
  70. package/src/Graph/Tree/models.ts +55 -0
  71. package/src/Graph/Tree/stories/contents.tsx +164 -0
  72. package/src/Graph/Tree/stories/datas.ts +305 -0
  73. package/src/Graph/Tree/utils.ts +49 -0
  74. package/src/Graph/common/testUtils.ts +71 -0
  75. package/src/Graph/common/timeSeries/index.ts +50 -12
  76. package/src/Graph/common/utils.ts +19 -0
  77. package/src/Graph/index.ts +4 -0
  78. package/src/InputField/Number/Number.cypress.spec.tsx +85 -0
  79. package/src/InputField/Number/Number.stories.tsx +66 -0
  80. package/src/InputField/Number/Number.tsx +74 -0
  81. package/src/InputField/Search/index.tsx +2 -2
  82. package/src/InputField/Select/Autocomplete/Multi/index.tsx +4 -2
  83. package/src/InputField/Select/Autocomplete/index.tsx +10 -3
  84. package/src/InputField/Select/IconPopover/index.tsx +1 -1
  85. package/src/InputField/Select/index.tsx +14 -1
  86. package/src/InputField/Text/index.tsx +38 -38
  87. package/src/Listing/ActionBar/index.tsx +10 -10
  88. package/src/Listing/Cell/DataCell.styles.ts +3 -0
  89. package/src/Listing/Cell/DataCell.tsx +8 -4
  90. package/src/Listing/Listing.cypress.spec.tsx +217 -33
  91. package/src/Listing/Listing.styles.ts +3 -5
  92. package/src/Listing/Row/Row.tsx +7 -3
  93. package/src/Listing/index.stories.tsx +25 -2
  94. package/src/Listing/index.test.tsx +1 -1
  95. package/src/Listing/index.tsx +202 -143
  96. package/src/Listing/models.ts +1 -0
  97. package/src/Listing/useStyleTable.ts +1 -0
  98. package/src/Panel/index.tsx +1 -1
  99. package/src/PopoverMenu/index.tsx +6 -5
  100. package/src/ThemeProvider/index.tsx +3 -0
  101. package/src/TimePeriods/CustomTimePeriod/CompactCustomTimePeriod.styles.ts +6 -7
  102. package/src/TimePeriods/ResolutionTimePeriod.cypress.spec.tsx +12 -9
  103. package/src/Typography/FluidTypography/FluidTypography.cypress.spec.tsx +27 -0
  104. package/src/Typography/FluidTypography/index.stories.tsx +2 -2
  105. package/src/Typography/FluidTypography/index.tsx +21 -28
  106. package/src/api/index.ts +3 -3
  107. package/src/api/useGraphQuery/index.ts +26 -5
  108. package/src/api/useGraphQuery/models.ts +5 -0
  109. package/src/api/useMutationQuery/index.test.ts +4 -4
  110. package/src/api/useMutationQuery/index.ts +24 -13
  111. package/src/components/CollapsibleItem/CollapsibleItem.cypress.spec.tsx +76 -0
  112. package/src/components/CollapsibleItem/CollapsibleItem.stories.tsx +26 -0
  113. package/src/components/CollapsibleItem/CollapsibleItem.tsx +43 -14
  114. package/src/components/CollapsibleItem/useCollapsibleItemStyles.ts +24 -1
  115. package/src/components/DataTable/DataTable.cypress.spec.tsx +14 -33
  116. package/src/components/DataTable/Item/DataTableItem.tsx +4 -60
  117. package/src/components/Form/{AccessRightsV2 → AccessRights}/AccessRights.cypress.spec.tsx +36 -13
  118. package/src/components/Form/{AccessRightsV2 → AccessRights}/ShareInput/ContactSwitch.tsx +11 -3
  119. package/src/components/Form/{AccessRightsV2 → AccessRights}/ShareInput/ShareInput.styles.ts +8 -0
  120. package/src/components/Form/{AccessRightsV2 → AccessRights}/ShareInput/ShareInput.tsx +1 -0
  121. package/src/components/Form/{AccessRightsV2 → AccessRights}/ShareInput/useShareInput.tsx +4 -0
  122. package/src/components/Form/{AccessRightsV2 → AccessRights}/models.ts +1 -0
  123. package/src/components/Form/{AccessRightsV2 → AccessRights}/storiesData.ts +23 -22
  124. package/src/components/Form/Dashboard/DashboardDuplicationForm.tsx +85 -0
  125. package/src/components/Form/Dashboard/index.ts +1 -0
  126. package/src/components/Form/FormActions.tsx +7 -2
  127. package/src/components/Form/index.ts +2 -2
  128. package/src/components/ItemComposition/Item.tsx +1 -1
  129. package/src/components/ItemComposition/ItemComposition.cypress.spec.tsx +113 -0
  130. package/src/components/ItemComposition/ItemComposition.stories.tsx +14 -0
  131. package/src/components/ItemComposition/ItemComposition.styles.ts +36 -3
  132. package/src/components/ItemComposition/ItemComposition.tsx +41 -17
  133. package/src/components/List/Item/ListItem.tsx +3 -3
  134. package/src/components/Modal/ConfirmationModal/ConfirmationModal.cypress.spec.tsx +168 -0
  135. package/src/components/Modal/ConfirmationModal/ConfirmationModal.stories.tsx +62 -0
  136. package/src/components/Modal/ConfirmationModal/ConfirmationModal.tsx +87 -0
  137. package/src/components/Modal/Modal.styles.ts +8 -3
  138. package/src/components/Modal/index.ts +2 -0
  139. package/src/components/Tooltip/ConfirmationTooltip/ConfirmationTooltip.stories.tsx +3 -3
  140. package/src/components/Tooltip/ConfirmationTooltip/ConfirmationTooltip.tsx +1 -1
  141. package/src/components/Tooltip/ConfirmationTooltip/models.ts +1 -1
  142. package/src/components/Zoom/Minimap.tsx +129 -0
  143. package/src/components/Zoom/Zoom.cypress.spec.tsx +246 -0
  144. package/src/components/Zoom/Zoom.stories.tsx +115 -0
  145. package/src/components/Zoom/Zoom.styles.tsx +68 -0
  146. package/src/components/Zoom/Zoom.tsx +64 -0
  147. package/src/components/Zoom/ZoomContent.tsx +170 -0
  148. package/src/components/Zoom/constants.ts +2 -0
  149. package/src/components/Zoom/localPoint.ts +51 -0
  150. package/src/components/Zoom/models.ts +25 -0
  151. package/src/components/Zoom/useMinimap.ts +156 -0
  152. package/src/components/Zoom/useZoom.ts +70 -0
  153. package/src/components/Zoom/utils.ts +55 -0
  154. package/src/components/index.ts +1 -0
  155. package/src/index.ts +1 -0
  156. package/src/utils/index.ts +3 -0
  157. package/src/utils/resourcesStatusURL.ts +166 -0
  158. package/src/utils/useFullscreen/Fullscreen.cypress.spec.tsx +130 -0
  159. package/src/utils/useFullscreen/atoms.ts +3 -0
  160. package/src/utils/useFullscreen/index.ts +2 -0
  161. package/src/utils/useFullscreen/translatedLabels.ts +1 -0
  162. package/src/utils/useFullscreen/useFullscreen.ts +73 -0
  163. package/src/utils/useFullscreen/useFullscreenListener.ts +62 -0
  164. package/src/utils/useInfiniteScrollListing.ts +4 -1
  165. package/src/Graph/LineChart/BasicComponents/LoadingProgress.tsx +0 -46
  166. package/src/Graph/LineChart/InteractiveComponents/AnchorPoint/TooltipAnchorPoint.tsx +0 -96
  167. package/src/Graph/LineChart/InteractiveComponents/AnchorPoint/useTooltipAnchorPoint.ts +0 -107
  168. package/src/Graph/LineChart/Legend/InteractiveValue.tsx +0 -22
  169. package/src/Graph/LineChart/Legend/useInteractiveValues.ts +0 -99
  170. package/src/Typography/FluidTypography/useFluidResizeObserver.ts +0 -56
  171. package/src/components/Form/AccessRights/AccessRights.resource.ts +0 -45
  172. package/src/components/Form/AccessRights/AccessRightsForm.stories.tsx +0 -59
  173. package/src/components/Form/AccessRights/AccessRightsForm.styles.ts +0 -21
  174. package/src/components/Form/AccessRights/AccessRightsForm.tsx +0 -67
  175. package/src/components/Form/AccessRights/AccessRightsFormActions.tsx +0 -80
  176. package/src/components/Form/AccessRights/Input/AddAction.tsx +0 -31
  177. package/src/components/Form/AccessRights/Input/ContactAccessRightInput.stories.tsx +0 -54
  178. package/src/components/Form/AccessRights/Input/ContactAccessRightInput.tsx +0 -72
  179. package/src/components/Form/AccessRights/Input/ContactAccessRightsInput.styles.ts +0 -22
  180. package/src/components/Form/AccessRights/Input/ContactInputField.tsx +0 -105
  181. package/src/components/Form/AccessRights/Input/RoleInputField.tsx +0 -29
  182. package/src/components/Form/AccessRights/List/ContactAccessRightsList.stories.tsx +0 -97
  183. package/src/components/Form/AccessRights/List/ContactAccessRightsList.styles.ts +0 -71
  184. package/src/components/Form/AccessRights/List/ContactAccessRightsList.tsx +0 -51
  185. package/src/components/Form/AccessRights/List/ContactAccessRightsListItem.stories.tsx +0 -116
  186. package/src/components/Form/AccessRights/List/ContactAccessRightsListItem.tsx +0 -118
  187. package/src/components/Form/AccessRights/List/ContactAccessRightsListItemSkeleton.tsx +0 -26
  188. package/src/components/Form/AccessRights/List/ContactAccessRightsListSkeleton.tsx +0 -28
  189. package/src/components/Form/AccessRights/Stats/AccessRightsStats.styles.ts +0 -18
  190. package/src/components/Form/AccessRights/Stats/AccessRightsStats.tsx +0 -41
  191. package/src/components/Form/AccessRights/__fixtures__/contactAccessRight.mock.ts +0 -54
  192. package/src/components/Form/AccessRights/common/GroupLabel.styles.ts +0 -18
  193. package/src/components/Form/AccessRights/common/GroupLabel.tsx +0 -15
  194. package/src/components/Form/AccessRights/common/Input.styles.ts +0 -48
  195. package/src/components/Form/AccessRights/common/RoleInputSelect.styles.ts +0 -11
  196. package/src/components/Form/AccessRights/common/RoleInputSelect.tsx +0 -57
  197. package/src/components/Form/AccessRights/index.ts +0 -3
  198. package/src/components/Form/AccessRights/useAccessRightsForm.test.tsx +0 -531
  199. package/src/components/Form/AccessRights/useAccessRightsForm.tsx +0 -282
  200. package/src/components/Form/AccessRights/useAccessRightsForm.utils.ts +0 -41
  201. /package/src/components/Form/{AccessRightsV2 → AccessRights}/AccessRights.stories.tsx +0 -0
  202. /package/src/components/Form/{AccessRightsV2 → AccessRights}/AccessRights.styles.ts +0 -0
  203. /package/src/components/Form/{AccessRightsV2 → AccessRights}/AccessRights.tsx +0 -0
  204. /package/src/components/Form/{AccessRightsV2 → AccessRights}/Actions/Actions.styles.ts +0 -0
  205. /package/src/components/Form/{AccessRightsV2 → AccessRights}/Actions/Actions.tsx +0 -0
  206. /package/src/components/Form/{AccessRightsV2 → AccessRights}/Actions/useActions.ts +0 -0
  207. /package/src/components/Form/{AccessRightsV2 → AccessRights}/List/Item.tsx +0 -0
  208. /package/src/components/Form/{AccessRightsV2 → AccessRights}/List/List.styles.tsx +0 -0
  209. /package/src/components/Form/{AccessRightsV2 → AccessRights}/List/List.tsx +0 -0
  210. /package/src/components/Form/{AccessRightsV2 → AccessRights}/List/ListItemSkeleton.tsx +0 -0
  211. /package/src/components/Form/{AccessRightsV2 → AccessRights}/List/ListSkeleton.tsx +0 -0
  212. /package/src/components/Form/{AccessRightsV2 → AccessRights}/List/RemoveAccessRight.tsx +0 -0
  213. /package/src/components/Form/{AccessRightsV2 → AccessRights}/List/StateChip.tsx +0 -0
  214. /package/src/components/Form/{AccessRightsV2 → AccessRights}/List/useItem.ts +0 -0
  215. /package/src/components/Form/{AccessRightsV2 → AccessRights}/Provider.tsx +0 -0
  216. /package/src/components/Form/{AccessRightsV2 → AccessRights}/Stats/Stats.tsx +0 -0
  217. /package/src/components/Form/{AccessRightsV2 → AccessRights}/atoms.ts +0 -0
  218. /package/src/components/Form/{AccessRightsV2 → AccessRights}/common/RoleSelectField.styles.tsx +0 -0
  219. /package/src/components/Form/{AccessRightsV2 → AccessRights}/common/RoleSelectField.tsx +0 -0
  220. /package/src/components/Form/{AccessRightsV2 → AccessRights}/useAccessRightsInitValues.ts +0 -0
@@ -7,32 +7,15 @@ import {
7
7
  CardContent as MuiCardContent,
8
8
  Typography as MuiTypography
9
9
  } from '@mui/material';
10
- import {
11
- Delete as DeleteIcon,
12
- Settings as SettingsIcon,
13
- Share as ShareIcon
14
- } from '@mui/icons-material';
15
-
16
- import { IconButton } from '../../Button';
17
- import { ConfirmationTooltip } from '../../Tooltip/ConfirmationTooltip';
18
10
 
19
11
  import { useStyles } from './DataTableItem.styles';
20
12
 
21
13
  export interface DataTableItemProps {
14
+ Actions?: JSX.Element;
22
15
  description?: string;
23
16
  hasActions?: boolean;
24
17
  hasCardAction?: boolean;
25
- labelsDelete?: {
26
- cancel: string;
27
- confirm: {
28
- label: string;
29
- secondaryLabel?: string;
30
- };
31
- };
32
18
  onClick?: () => void;
33
- onDelete?: () => void;
34
- onEdit?: () => void;
35
- onEditAccessRights?: () => void;
36
19
  title: string;
37
20
  }
38
21
 
@@ -44,10 +27,7 @@ const DataTableItem = forwardRef(
44
27
  hasCardAction = false,
45
28
  hasActions = false,
46
29
  onClick,
47
- onEdit,
48
- onDelete,
49
- onEditAccessRights,
50
- labelsDelete
30
+ Actions
51
31
  }: DataTableItemProps,
52
32
  ref
53
33
  ): ReactElement => {
@@ -75,44 +55,8 @@ const DataTableItem = forwardRef(
75
55
  </ActionArea>
76
56
  {hasActions && (
77
57
  <MuiCardActions>
78
- <span>
79
- {onDelete && labelsDelete && (
80
- <ConfirmationTooltip
81
- confirmVariant="error"
82
- labels={labelsDelete}
83
- onConfirm={onDelete}
84
- >
85
- {(openTooltip) => (
86
- <IconButton
87
- aria-label="delete"
88
- data-testid="delete"
89
- icon={<DeleteIcon />}
90
- size="small"
91
- variant="ghost"
92
- onClick={openTooltip}
93
- />
94
- )}
95
- </ConfirmationTooltip>
96
- )}
97
- </span>
98
- <span>
99
- <IconButton
100
- aria-label="edit access rights"
101
- data-testid="edit-access-rights"
102
- icon={<ShareIcon />}
103
- size="small"
104
- variant="primary"
105
- onClick={() => onEditAccessRights?.()}
106
- />
107
- <IconButton
108
- aria-label="edit"
109
- data-testid="edit"
110
- icon={<SettingsIcon />}
111
- size="small"
112
- variant="primary"
113
- onClick={() => onEdit?.()}
114
- />
115
- </span>
58
+ <span />
59
+ <span>{Actions}</span>
116
60
  </MuiCardActions>
117
61
  )}
118
62
  </MuiCard>
@@ -116,15 +116,15 @@ describe('Access rights', () => {
116
116
  it('displays a removed chip when the corresponding icon is clicked', () => {
117
117
  initialize({});
118
118
 
119
- cy.findByTestId(`remove-Leah McGlynn`).should(
119
+ cy.findByTestId(`remove-Kathy Schmitt`).should(
120
120
  'have.attr',
121
121
  'data-removed',
122
122
  'false'
123
123
  );
124
124
 
125
- cy.findByTestId(`remove-Leah McGlynn`).click();
125
+ cy.findByTestId(`remove-Kathy Schmitt`).click();
126
126
 
127
- cy.findByTestId(`remove-Leah McGlynn`).should(
127
+ cy.findByTestId(`remove-Kathy Schmitt`).should(
128
128
  'have.attr',
129
129
  'data-removed',
130
130
  'true'
@@ -137,18 +137,18 @@ describe('Access rights', () => {
137
137
  it('restores the contact when the contact is removed and the corresponding icon is clicked', () => {
138
138
  initialize({});
139
139
 
140
- cy.findByTestId(`remove-Leah McGlynn`).click();
140
+ cy.findByTestId(`remove-Kathy Schmitt`).click();
141
141
 
142
- cy.findByTestId(`remove-Leah McGlynn`).should(
142
+ cy.findByTestId(`remove-Kathy Schmitt`).should(
143
143
  'have.attr',
144
144
  'data-removed',
145
145
  'true'
146
146
  );
147
147
  cy.contains(labels.list.removed).should('be.visible');
148
148
 
149
- cy.findByTestId(`remove-Leah McGlynn`).click();
149
+ cy.findByTestId(`remove-Kathy Schmitt`).click();
150
150
 
151
- cy.findByTestId(`remove-Leah McGlynn`).should(
151
+ cy.findByTestId(`remove-Kathy Schmitt`).should(
152
152
  'have.attr',
153
153
  'data-removed',
154
154
  'false'
@@ -161,9 +161,9 @@ describe('Access rights', () => {
161
161
  it('submits the new acces rights list without the removed contact', () => {
162
162
  const { save } = initialize({});
163
163
 
164
- cy.findByTestId(`remove-Leah McGlynn`).click();
164
+ cy.findByTestId(`remove-Kathy Schmitt`).click();
165
165
 
166
- cy.findByTestId(`remove-Leah McGlynn`).should(
166
+ cy.findByTestId(`remove-Kathy Schmitt`).should(
167
167
  'have.attr',
168
168
  'data-removed',
169
169
  'true'
@@ -183,7 +183,7 @@ describe('Access rights', () => {
183
183
  it('submits the new acces rights list with the updated contact', () => {
184
184
  const { save } = initialize({});
185
185
 
186
- cy.findByTestId(`role-Leah McGlynn`).parent().click();
186
+ cy.findByTestId(`role-Kathy Schmitt`).parent().click();
187
187
 
188
188
  cy.get('li[data-value="editor"]').click();
189
189
  cy.contains(labels.list.updated).should('be.visible');
@@ -201,7 +201,7 @@ describe('Access rights', () => {
201
201
  it('removes the updated chip when the contact role is updated and its initial role is assigned back', () => {
202
202
  initialize({});
203
203
 
204
- cy.findByTestId(`role-Leah McGlynn`).parent().click();
204
+ cy.findByTestId(`role-Kathy Schmitt`).parent().click();
205
205
 
206
206
  cy.get('li[data-value="editor"]').click();
207
207
  cy.contains(labels.list.updated).should('be.visible');
@@ -291,10 +291,10 @@ describe('Access rights', () => {
291
291
 
292
292
  cy.contains('Entity Group 10').should('be.visible');
293
293
 
294
- cy.findByTestId(`role-Leah McGlynn`).parent().click();
294
+ cy.findByTestId(`role-Kathy Schmitt`).parent().click();
295
295
  cy.get('li[data-value="editor"]').click();
296
296
 
297
- cy.findByTestId('remove-Jody Blanda').click();
297
+ cy.findByTestId('remove-Linda Schultz').click();
298
298
 
299
299
  cy.contains('1 added | 1 updated | 1 removed').should('be.visible');
300
300
 
@@ -347,4 +347,27 @@ describe('Access rights', () => {
347
347
 
348
348
  cy.makeSnapshot();
349
349
  });
350
+
351
+ it('resets the role to "viewer" when the "editor" role is selected and a contact with "viewer" right is selected', () => {
352
+ initialize({});
353
+
354
+ cy.findByLabelText(labels.add.autocompleteContact).click();
355
+
356
+ cy.waitForRequest('@getContacts');
357
+
358
+ cy.contains('Entity 10').click();
359
+
360
+ cy.findByTestId('add_role').parent().click();
361
+ cy.get('li[data-value="editor"]').click();
362
+
363
+ cy.findByLabelText(labels.add.autocompleteContact).click();
364
+
365
+ cy.waitForRequest('@getContacts');
366
+
367
+ cy.contains('Entity 11').click();
368
+
369
+ cy.findByTestId('add_role').should('have.value', 'viewer');
370
+
371
+ cy.makeSnapshot();
372
+ });
350
373
  });
@@ -1,4 +1,4 @@
1
- import { useSetAtom } from 'jotai';
1
+ import { useAtom } from 'jotai';
2
2
  import { useTranslation } from 'react-i18next';
3
3
 
4
4
  import { FormControlLabel, Radio, RadioGroup } from '@mui/material';
@@ -7,14 +7,17 @@ import { ContactType, Labels } from '../models';
7
7
  import { contactTypeAtom } from '../atoms';
8
8
  import { Subtitle } from '../../../..';
9
9
 
10
+ import { useContactSwitchStyles } from './ShareInput.styles';
11
+
10
12
  interface Props {
11
13
  labels: Labels['add'];
12
14
  }
13
15
 
14
16
  const ContactSwitch = ({ labels }: Props): JSX.Element => {
17
+ const { classes } = useContactSwitchStyles();
15
18
  const { t } = useTranslation();
16
19
 
17
- const setContactType = useSetAtom(contactTypeAtom);
20
+ const [contactType, setContactType] = useAtom(contactTypeAtom);
18
21
 
19
22
  const change = (event: React.ChangeEvent<HTMLInputElement>): void => {
20
23
  setContactType(event.target.value as ContactType);
@@ -23,7 +26,12 @@ const ContactSwitch = ({ labels }: Props): JSX.Element => {
23
26
  return (
24
27
  <>
25
28
  <Subtitle>{t(labels.title)}</Subtitle>
26
- <RadioGroup row defaultValue={ContactType.Contact} onChange={change}>
29
+ <RadioGroup
30
+ row
31
+ className={classes.inputs}
32
+ value={contactType}
33
+ onChange={change}
34
+ >
27
35
  <FormControlLabel
28
36
  control={<Radio />}
29
37
  label={labels.contact}
@@ -7,3 +7,11 @@ export const useShareInputStyles = makeStyles()((theme) => ({
7
7
  gridTemplateColumns: `1fr min-content min-content`
8
8
  }
9
9
  }));
10
+
11
+ export const useContactSwitchStyles = makeStyles()((theme) => ({
12
+ inputs: {
13
+ display: 'flex',
14
+ flexDirection: 'row',
15
+ gap: theme.spacing(2)
16
+ }
17
+ }));
@@ -52,6 +52,7 @@ const ShareInput = ({ labels, endpoints, roles }: Props): JSX.Element => {
52
52
  ? t(labels.autocompleteContactGroup)
53
53
  : t(labels.autocompleteContact)
54
54
  )}
55
+ queryKey={isContactGroup ? labels.contactGroup : labels.contact}
55
56
  renderOption={renderOption}
56
57
  value={selectedContact}
57
58
  onChange={selectContact}
@@ -40,6 +40,10 @@ const useShareInput = (endpoints: Endpoints): UseShareInputState => {
40
40
 
41
41
  const selectContact = (_, entry): void => {
42
42
  setSelectedContact(entry);
43
+ if (equals('editor', entry.most_permissive_role)) {
44
+ return;
45
+ }
46
+ setSelectedRole('viewer');
43
47
  };
44
48
 
45
49
  const add = (): void => {
@@ -2,6 +2,7 @@ export interface AccessRightInitialValues {
2
2
  email?: string;
3
3
  id: number | string;
4
4
  isContactGroup: boolean;
5
+ most_permissive_role?: 'editor' | 'viewer';
5
6
  name: string;
6
7
  role: string;
7
8
  }
@@ -88,6 +88,7 @@ const buildEntities = (from, isGroup): Array<SelectEntry> => {
88
88
  .map((_, index) => ({
89
89
  email: isGroup ? undefined : faker.internet.email(),
90
90
  id: 1000 + index,
91
+ most_permissive_role: index % 3 === 0 ? 'editor' : 'viewer',
91
92
  name: `Entity ${isGroup ? 'Group' : ''} ${from + index}`
92
93
  }));
93
94
  };
@@ -139,83 +140,83 @@ export const roles = [
139
140
 
140
141
  export const removedAccessRights = [
141
142
  {
142
- email: 'Virgie14@yahoo.com',
143
+ email: 'Adrienne.Kassulke-Rutherford@gmail.com',
143
144
  id: 1,
144
145
  isContactGroup: false,
145
- name: 'Jody Blanda',
146
+ name: 'Linda Schultz',
146
147
  role: 'editor'
147
148
  },
148
149
  {
149
- email: 'Wyman29@yahoo.com',
150
+ email: 'Merle7@hotmail.com',
150
151
  id: 2,
151
152
  isContactGroup: false,
152
- name: 'Susan Dooley',
153
+ name: 'Lewis Buckridge PhD',
153
154
  role: 'viewer'
154
155
  },
155
156
  {
156
- email: 'Merle.Schamberger@hotmail.com',
157
+ email: 'Linda.Harris37@hotmail.com',
157
158
  id: 3,
158
159
  isContactGroup: false,
159
- name: 'Lewis Buckridge PhD',
160
+ name: "Jodi O'Reilly",
160
161
  role: 'editor'
161
162
  },
162
163
  {
163
- email: 'Rossie6@gmail.com',
164
+ email: 'Louvenia.Torphy@yahoo.com',
164
165
  id: 4,
165
166
  isContactGroup: false,
166
- name: 'Bertha Hane',
167
+ name: 'Mildred Ratke-Stanton',
167
168
  role: 'viewer'
168
169
  },
169
170
  {
170
- email: 'Monty_Nienow47@gmail.com',
171
+ email: 'Kelli.Russel4@hotmail.com',
171
172
  id: 5,
172
173
  isContactGroup: true,
173
- name: 'Mildred Ratke-Stanton',
174
+ name: 'Rudolph Brown',
174
175
  role: 'editor'
175
176
  }
176
177
  ];
177
178
 
178
179
  export const updatedAccessRights = [
179
180
  {
180
- email: 'Jovani.Willms74@gmail.com',
181
+ email: 'Kylie_Wintheiser54@hotmail.com',
181
182
  id: 0,
182
183
  isContactGroup: true,
183
- name: 'Leah McGlynn',
184
+ name: 'Kathy Schmitt',
184
185
  role: 'editor'
185
186
  },
186
187
  {
187
- email: 'Virgie14@yahoo.com',
188
+ email: 'Adrienne.Kassulke-Rutherford@gmail.com',
188
189
  id: 1,
189
190
  isContactGroup: false,
190
- name: 'Jody Blanda',
191
+ name: 'Linda Schultz',
191
192
  role: 'editor'
192
193
  },
193
194
  {
194
- email: 'Wyman29@yahoo.com',
195
+ email: 'Merle7@hotmail.com',
195
196
  id: 2,
196
197
  isContactGroup: false,
197
- name: 'Susan Dooley',
198
+ name: 'Lewis Buckridge PhD',
198
199
  role: 'viewer'
199
200
  },
200
201
  {
201
- email: 'Merle.Schamberger@hotmail.com',
202
+ email: 'Linda.Harris37@hotmail.com',
202
203
  id: 3,
203
204
  isContactGroup: false,
204
- name: 'Lewis Buckridge PhD',
205
+ name: "Jodi O'Reilly",
205
206
  role: 'editor'
206
207
  },
207
208
  {
208
- email: 'Rossie6@gmail.com',
209
+ email: 'Louvenia.Torphy@yahoo.com',
209
210
  id: 4,
210
211
  isContactGroup: false,
211
- name: 'Bertha Hane',
212
+ name: 'Mildred Ratke-Stanton',
212
213
  role: 'viewer'
213
214
  },
214
215
  {
215
- email: 'Monty_Nienow47@gmail.com',
216
+ email: 'Kelli.Russel4@hotmail.com',
216
217
  id: 5,
217
218
  isContactGroup: true,
218
- name: 'Mildred Ratke-Stanton',
219
+ name: 'Rudolph Brown',
219
220
  role: 'editor'
220
221
  }
221
222
  ];
@@ -0,0 +1,85 @@
1
+ import { ReactElement, useCallback, useMemo } from 'react';
2
+
3
+ import { string, object } from 'yup';
4
+ import { useTranslation } from 'react-i18next';
5
+
6
+ import { InputType } from '../../../Form/Inputs/models';
7
+ import { Form, FormProps } from '../../../Form';
8
+ import { FormVariant } from '../Form.models';
9
+ import { FormActions, FormActionsProps } from '../FormActions';
10
+
11
+ import { useStyles } from './DashboardForm.styles';
12
+ import {
13
+ labelMustBeAtLeast,
14
+ labelMustBeMost,
15
+ labelRequired
16
+ } from './translatedLabels';
17
+ import { DashboardResource } from './Dashboard.resource';
18
+
19
+ type DashboardFormProps = {
20
+ labels: DashboardFormLabels;
21
+ name: string;
22
+ onSubmit?: FormProps<DashboardResource>['submit'];
23
+ variant?: FormVariant;
24
+ } & Pick<FormActionsProps, 'onCancel'>;
25
+
26
+ type DashboardFormLabels = {
27
+ actions: FormActionsProps['labels'];
28
+ entity: Required<DashboardResource>;
29
+ };
30
+
31
+ const DashboardDuplicationForm = ({
32
+ variant = 'create',
33
+ labels,
34
+ onSubmit,
35
+ onCancel,
36
+ name
37
+ }: DashboardFormProps): ReactElement => {
38
+ const { classes } = useStyles();
39
+ const { t } = useTranslation();
40
+
41
+ const formProps = useMemo<FormProps<DashboardResource>>(
42
+ () => ({
43
+ initialValues: { name },
44
+ inputs: [
45
+ {
46
+ autoFocus: true,
47
+ fieldName: 'name',
48
+ group: 'main',
49
+ label: labels?.entity?.name,
50
+ required: true,
51
+ type: InputType.Text
52
+ }
53
+ ],
54
+ submit: (values, bag) => onSubmit?.(values, bag),
55
+ validationSchema: object({
56
+ name: string()
57
+ .label(labels?.entity?.name)
58
+ .min(3, ({ min, label }) => t(labelMustBeAtLeast, { label, min }))
59
+ .max(50, ({ max, label }) => t(labelMustBeMost, { label, max }))
60
+ .required(t(labelRequired) as string)
61
+ })
62
+ }),
63
+ [labels, onSubmit]
64
+ );
65
+
66
+ const Actions = useCallback(
67
+ () => (
68
+ <FormActions<DashboardResource>
69
+ enableSubmitWhenNotDirty
70
+ labels={labels?.actions}
71
+ variant={variant}
72
+ onCancel={onCancel}
73
+ />
74
+ ),
75
+ [labels, onCancel, variant]
76
+ );
77
+
78
+ return (
79
+ <div className={classes.dashboardForm}>
80
+ <Form<DashboardResource> {...formProps} Buttons={Actions} />
81
+ </div>
82
+ );
83
+ };
84
+
85
+ export { DashboardDuplicationForm };
@@ -1,2 +1,3 @@
1
1
  export * from './DashboardForm';
2
2
  export * from './Dashboard.resource';
3
+ export * from './DashboardDuplicationForm';
@@ -8,6 +8,7 @@ import { FormVariant } from './Form.models';
8
8
  import { useStyles } from './Form.styles';
9
9
 
10
10
  export type FormActionsProps = {
11
+ enableSubmitWhenNotDirty?: boolean;
11
12
  labels: FormActionsLabels;
12
13
  onCancel: () => void;
13
14
  variant: FormVariant;
@@ -21,12 +22,16 @@ export type FormActionsLabels = {
21
22
  const FormActions = <TResource extends object>({
22
23
  labels,
23
24
  onCancel,
24
- variant
25
+ variant,
26
+ enableSubmitWhenNotDirty
25
27
  }: FormActionsProps): ReactElement => {
26
28
  const { classes } = useStyles();
27
29
  const { isSubmitting, dirty, isValid, submitForm } =
28
30
  useFormikContext<TResource>();
29
31
 
32
+ const isSubmitDisabled =
33
+ isSubmitting || (!dirty && !enableSubmitWhenNotDirty) || !isValid;
34
+
30
35
  return (
31
36
  <div className={classes.actions}>
32
37
  <Button
@@ -42,7 +47,7 @@ const FormActions = <TResource extends object>({
42
47
  <Button
43
48
  aria-label={labels.submit[variant]}
44
49
  data-testid="submit"
45
- disabled={isSubmitting || !dirty || !isValid}
50
+ disabled={isSubmitDisabled}
46
51
  size="medium"
47
52
  type="submit"
48
53
  variant="primary"
@@ -1,4 +1,4 @@
1
1
  export * from './Form.models';
2
2
  export * from './Dashboard';
3
- export * from './AccessRights';
4
- export { default as AccessRightsV2 } from './AccessRightsV2/AccessRights';
3
+ export { default as AccessRights } from './AccessRights/AccessRights';
4
+ export { default as AccessRightsV2 } from './AccessRights/AccessRights';
@@ -7,7 +7,7 @@ import { IconButton } from '..';
7
7
  import { useItemStyles } from './ItemComposition.styles';
8
8
 
9
9
  type Props = {
10
- children: Array<ReactElement>;
10
+ children: ReactElement | Array<ReactElement>;
11
11
  className?: string;
12
12
  deleteButtonHidden?: boolean;
13
13
  labelDelete: string;
@@ -0,0 +1,113 @@
1
+ import { Props } from './ItemComposition';
2
+
3
+ import { ItemComposition } from '.';
4
+
5
+ const initialize = ({
6
+ deleteButtonHidden,
7
+ ...props
8
+ }: Partial<Props> & {
9
+ deleteButtonHidden?: boolean;
10
+ }): unknown => {
11
+ const addItem = cy.stub();
12
+ const deleteItem = cy.stub();
13
+
14
+ cy.mount({
15
+ Component: (
16
+ <ItemComposition {...props} labelAdd="Add" onAddItem={addItem}>
17
+ <ItemComposition.Item
18
+ deleteButtonHidden={deleteButtonHidden}
19
+ labelDelete="Delete"
20
+ onDeleteItem={deleteItem}
21
+ >
22
+ <div>Item 1</div>
23
+ </ItemComposition.Item>
24
+ <ItemComposition.Item
25
+ deleteButtonHidden={deleteButtonHidden}
26
+ labelDelete="Delete"
27
+ onDeleteItem={deleteItem}
28
+ >
29
+ <div>Item 2</div>
30
+ </ItemComposition.Item>
31
+ </ItemComposition>
32
+ )
33
+ });
34
+
35
+ return {
36
+ addItem,
37
+ deleteItem
38
+ };
39
+ };
40
+
41
+ describe('ItemComposition', () => {
42
+ it('displays the component', () => {
43
+ initialize({});
44
+
45
+ cy.contains('Item 1').should('be.visible');
46
+ cy.contains('Item 2').should('be.visible');
47
+ cy.findAllByTestId('Delete').should('have.length', 2);
48
+ cy.findByTestId('Add').should('be.enabled');
49
+
50
+ cy.makeSnapshot();
51
+ });
52
+
53
+ it('displays the component with a secondary label', () => {
54
+ initialize({ secondaryLabel: 'Secondary label' });
55
+
56
+ cy.contains('Secondary label').should('be.visible');
57
+
58
+ cy.makeSnapshot();
59
+ });
60
+
61
+ it('displays add button as hidden when the prop is set to true', () => {
62
+ initialize({ addbuttonDisabled: true });
63
+
64
+ cy.findByTestId('Add').should('be.disabled');
65
+
66
+ cy.makeSnapshot();
67
+ });
68
+
69
+ it('does not display the add button when the prop is set to true', () => {
70
+ initialize({ addButtonHidden: true });
71
+
72
+ cy.findByTestId('Add').should('not.exist');
73
+
74
+ cy.makeSnapshot();
75
+ });
76
+
77
+ it('does not display the delete button when the prop is set to true', () => {
78
+ initialize({ deleteButtonHidden: true });
79
+
80
+ cy.findByTestId('Delete').should('not.exist');
81
+
82
+ cy.makeSnapshot();
83
+ });
84
+
85
+ it('calls the add function when the button is clicked', () => {
86
+ const { addItem } = initialize({});
87
+
88
+ cy.findByTestId('Add')
89
+ .click()
90
+ .then(() => {
91
+ expect(addItem).to.have.been.calledWith();
92
+ });
93
+ });
94
+
95
+ it('calls the delete function when the button is clicked', () => {
96
+ const { deleteItem } = initialize({});
97
+
98
+ cy.findAllByTestId('Delete')
99
+ .eq(1)
100
+ .click()
101
+ .then(() => {
102
+ expect(deleteItem).to.have.been.calledWith();
103
+ });
104
+ });
105
+
106
+ it('displays items as linked when the prop is set to true', () => {
107
+ initialize({ displayItemsAsLinked: true });
108
+
109
+ cy.get('[data-linked]').should('be.visible');
110
+
111
+ cy.makeSnapshot();
112
+ });
113
+ });
@@ -76,3 +76,17 @@ export const WithSelectInputs: Story = {
76
76
  onAddItem: stub
77
77
  }
78
78
  };
79
+
80
+ export const WithLinkedItems: Story = {
81
+ args: {
82
+ children: [...Array(5)].map((_, i) => (
83
+ <ItemComposition.Item key={i} labelDelete="Delete" onDeleteItem={stub}>
84
+ <Typography>Item 1</Typography>
85
+ <Typography>Item 2</Typography>
86
+ </ItemComposition.Item>
87
+ )),
88
+ displayItemsAsLinked: true,
89
+ labelAdd: 'Add',
90
+ onAddItem: stub
91
+ }
92
+ };