@centreon/ui 24.5.1 → 24.5.2

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 (49) hide show
  1. package/package.json +3 -7
  2. package/public/mockServiceWorker.js +100 -81
  3. package/src/ActionsList/index.stories.tsx +1 -7
  4. package/src/Dashboard/Dashboard.styles.ts +2 -3
  5. package/src/Dashboard/Item.tsx +2 -11
  6. package/src/Dashboard/Layout.tsx +2 -4
  7. package/src/Graph/Tree/DescendantNodes.tsx +0 -1
  8. package/src/Graph/Tree/Links.tsx +2 -15
  9. package/src/Graph/Tree/Tree.cypress.spec.tsx +0 -24
  10. package/src/Graph/Tree/Tree.stories.tsx +1 -17
  11. package/src/Graph/Tree/models.ts +0 -3
  12. package/src/TopCounterElements/TopCounterLayout.tsx +4 -3
  13. package/src/TopCounterElements/useCloseOnLegacyPage.tsx +6 -9
  14. package/src/api/QueryProvider.tsx +1 -1
  15. package/src/api/useFetchQuery/index.test.ts +5 -0
  16. package/src/api/useFetchQuery/index.ts +5 -2
  17. package/src/api/useGraphQuery/index.ts +1 -7
  18. package/src/api/useMutationQuery/index.ts +5 -2
  19. package/src/api/useRequest/index.test.ts +3 -0
  20. package/src/api/useRequest/index.ts +6 -3
  21. package/src/components/Form/AccessRights/AccessRights.cypress.spec.tsx +13 -27
  22. package/src/components/Form/AccessRights/AccessRights.stories.tsx +19 -0
  23. package/src/components/Form/AccessRights/AccessRights.styles.ts +1 -1
  24. package/src/components/Form/AccessRights/AccessRights.tsx +5 -6
  25. package/src/components/Form/AccessRights/Actions/Actions.styles.ts +7 -3
  26. package/src/components/Form/AccessRights/Actions/Actions.tsx +32 -15
  27. package/src/components/Form/AccessRights/Actions/useActions.ts +37 -4
  28. package/src/components/Form/AccessRights/models.ts +3 -0
  29. package/src/components/Form/AccessRights/storiesData.ts +3 -0
  30. package/src/components/List/Item/ListItem.styles.ts +2 -2
  31. package/src/components/Zoom/Minimap.tsx +2 -4
  32. package/src/components/Zoom/Zoom.cypress.spec.tsx +13 -13
  33. package/src/components/Zoom/Zoom.tsx +1 -4
  34. package/src/components/Zoom/ZoomContent.tsx +2 -5
  35. package/src/components/index.ts +0 -1
  36. package/src/index.ts +1 -1
  37. package/src/utils/index.ts +0 -1
  38. package/src/utils/usePluralizedTranslation.ts +3 -20
  39. package/src/api/logger.ts +0 -11
  40. package/src/components/Form/AccessRights/useAccessRightsChange.ts +0 -30
  41. package/src/components/Form/AccessRights/utils.ts +0 -18
  42. package/src/components/Tabs/Tab.styles.ts +0 -25
  43. package/src/components/Tabs/TabPanel.tsx +0 -22
  44. package/src/components/Tabs/Tabs.cypress.spec.tsx +0 -70
  45. package/src/components/Tabs/Tabs.stories.tsx +0 -55
  46. package/src/components/Tabs/Tabs.tsx +0 -55
  47. package/src/components/Tabs/index.ts +0 -6
  48. package/src/utils/resourcesStatusURL.ts +0 -166
  49. package/src/utils/usePluralizedTranslation.test.ts +0 -159
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@centreon/ui",
3
- "version": "24.5.1",
3
+ "version": "24.5.2",
4
4
  "description": "Centreon UI Components",
5
5
  "scripts": {
6
6
  "update:deps": "pnpx npm-check-updates -i --format group",
7
7
  "eslint": "eslint ./src --ext .js,.jsx,.ts,.tsx --max-warnings 0",
8
8
  "eslint:fix": "pnpm eslint --fix",
9
- "storybook": "storybook dev -p 9001 -c .storybook -s ../public",
9
+ "storybook": "storybook dev -p 9001 -c .storybook",
10
10
  "build:storybook": "storybook build -c .storybook -o .out",
11
11
  "test": "jest",
12
12
  "test:storybook:local": "test-storybook --url http://127.0.0.1:9001",
@@ -53,8 +53,6 @@
53
53
  "@cypress/webpack-dev-server": "^3.7.4",
54
54
  "@faker-js/faker": "^8.4.1",
55
55
  "@mdx-js/react": "^3.0.1",
56
- "@modern-js/prod-server": "^2.49.2",
57
- "@modern-js/storybook": "^2.49.2",
58
56
  "@simonsmith/cypress-image-snapshot": "^9.0.1",
59
57
  "@storybook/addon-a11y": "^7.0.9",
60
58
  "@storybook/addon-docs": "^7.0.9",
@@ -171,8 +169,6 @@
171
169
  "output": "./junit.xml"
172
170
  },
173
171
  "msw": {
174
- "workerDirectory": [
175
- "public"
176
- ]
172
+ "workerDirectory": "public"
177
173
  }
178
174
  }
@@ -2,15 +2,13 @@
2
2
  /* tslint:disable */
3
3
 
4
4
  /**
5
- * Mock Service Worker.
5
+ * Mock Service Worker (1.3.2).
6
6
  * @see https://github.com/mswjs/msw
7
7
  * - Please do NOT modify this file.
8
8
  * - Please do NOT serve this file on production.
9
9
  */
10
10
 
11
- const PACKAGE_VERSION = '2.2.14'
12
- const INTEGRITY_CHECKSUM = '26357c79639bfa20d64c0efca2a87423'
13
- const IS_MOCKED_RESPONSE = Symbol('isMockedResponse')
11
+ const INTEGRITY_CHECKSUM = '3d6b9f06410d179a7f7404d4bf4c3c70'
14
12
  const activeClientIds = new Set()
15
13
 
16
14
  self.addEventListener('install', function () {
@@ -49,10 +47,7 @@ self.addEventListener('message', async function (event) {
49
47
  case 'INTEGRITY_CHECK_REQUEST': {
50
48
  sendToClient(client, {
51
49
  type: 'INTEGRITY_CHECK_RESPONSE',
52
- payload: {
53
- packageVersion: PACKAGE_VERSION,
54
- checksum: INTEGRITY_CHECKSUM,
55
- },
50
+ payload: INTEGRITY_CHECKSUM,
56
51
  })
57
52
  break
58
53
  }
@@ -91,6 +86,12 @@ self.addEventListener('message', async function (event) {
91
86
 
92
87
  self.addEventListener('fetch', function (event) {
93
88
  const { request } = event
89
+ const accept = request.headers.get('accept') || ''
90
+
91
+ // Bypass server-sent events.
92
+ if (accept.includes('text/event-stream')) {
93
+ return
94
+ }
94
95
 
95
96
  // Bypass navigation requests.
96
97
  if (request.mode === 'navigate') {
@@ -111,8 +112,29 @@ self.addEventListener('fetch', function (event) {
111
112
  }
112
113
 
113
114
  // Generate unique request ID.
114
- const requestId = crypto.randomUUID()
115
- event.respondWith(handleRequest(event, requestId))
115
+ const requestId = Math.random().toString(16).slice(2)
116
+
117
+ event.respondWith(
118
+ handleRequest(event, requestId).catch((error) => {
119
+ if (error.name === 'NetworkError') {
120
+ console.warn(
121
+ '[MSW] Successfully emulated a network error for the "%s %s" request.',
122
+ request.method,
123
+ request.url,
124
+ )
125
+ return
126
+ }
127
+
128
+ // At this point, any exception indicates an issue with the original request/response.
129
+ console.error(
130
+ `\
131
+ [MSW] Caught an exception from the "%s %s" request (%s). This is probably not a problem with Mock Service Worker. There is likely an additional logging output above.`,
132
+ request.method,
133
+ request.url,
134
+ `${error.name}: ${error.message}`,
135
+ )
136
+ }),
137
+ )
116
138
  })
117
139
 
118
140
  async function handleRequest(event, requestId) {
@@ -124,24 +146,21 @@ async function handleRequest(event, requestId) {
124
146
  // this message will pend indefinitely.
125
147
  if (client && activeClientIds.has(client.id)) {
126
148
  ;(async function () {
127
- const responseClone = response.clone()
128
-
129
- sendToClient(
130
- client,
131
- {
132
- type: 'RESPONSE',
133
- payload: {
134
- requestId,
135
- isMockedResponse: IS_MOCKED_RESPONSE in response,
136
- type: responseClone.type,
137
- status: responseClone.status,
138
- statusText: responseClone.statusText,
139
- body: responseClone.body,
140
- headers: Object.fromEntries(responseClone.headers.entries()),
141
- },
149
+ const clonedResponse = response.clone()
150
+ sendToClient(client, {
151
+ type: 'RESPONSE',
152
+ payload: {
153
+ requestId,
154
+ type: clonedResponse.type,
155
+ ok: clonedResponse.ok,
156
+ status: clonedResponse.status,
157
+ statusText: clonedResponse.statusText,
158
+ body:
159
+ clonedResponse.body === null ? null : await clonedResponse.text(),
160
+ headers: Object.fromEntries(clonedResponse.headers.entries()),
161
+ redirected: clonedResponse.redirected,
142
162
  },
143
- [responseClone.body],
144
- )
163
+ })
145
164
  })()
146
165
  }
147
166
 
@@ -177,20 +196,20 @@ async function resolveMainClient(event) {
177
196
 
178
197
  async function getResponse(event, client, requestId) {
179
198
  const { request } = event
180
-
181
- // Clone the request because it might've been already used
182
- // (i.e. its body has been read and sent to the client).
183
- const requestClone = request.clone()
199
+ const clonedRequest = request.clone()
184
200
 
185
201
  function passthrough() {
186
- const headers = Object.fromEntries(requestClone.headers.entries())
202
+ // Clone the request because it might've been already used
203
+ // (i.e. its body has been read and sent to the client).
204
+ const headers = Object.fromEntries(clonedRequest.headers.entries())
187
205
 
188
- // Remove internal MSW request header so the passthrough request
189
- // complies with any potential CORS preflight checks on the server.
190
- // Some servers forbid unknown request headers.
191
- delete headers['x-msw-intention']
206
+ // Remove MSW-specific request headers so the bypassed requests
207
+ // comply with the server's CORS preflight check.
208
+ // Operate with the headers as an object because request "Headers"
209
+ // are immutable.
210
+ delete headers['x-msw-bypass']
192
211
 
193
- return fetch(requestClone, { headers })
212
+ return fetch(clonedRequest, { headers })
194
213
  }
195
214
 
196
215
  // Bypass mocking when the client is not active.
@@ -206,46 +225,57 @@ async function getResponse(event, client, requestId) {
206
225
  return passthrough()
207
226
  }
208
227
 
228
+ // Bypass requests with the explicit bypass header.
229
+ // Such requests can be issued by "ctx.fetch()".
230
+ if (request.headers.get('x-msw-bypass') === 'true') {
231
+ return passthrough()
232
+ }
233
+
209
234
  // Notify the client that a request has been intercepted.
210
- const requestBuffer = await request.arrayBuffer()
211
- const clientMessage = await sendToClient(
212
- client,
213
- {
214
- type: 'REQUEST',
215
- payload: {
216
- id: requestId,
217
- url: request.url,
218
- mode: request.mode,
219
- method: request.method,
220
- headers: Object.fromEntries(request.headers.entries()),
221
- cache: request.cache,
222
- credentials: request.credentials,
223
- destination: request.destination,
224
- integrity: request.integrity,
225
- redirect: request.redirect,
226
- referrer: request.referrer,
227
- referrerPolicy: request.referrerPolicy,
228
- body: requestBuffer,
229
- keepalive: request.keepalive,
230
- },
235
+ const clientMessage = await sendToClient(client, {
236
+ type: 'REQUEST',
237
+ payload: {
238
+ id: requestId,
239
+ url: request.url,
240
+ method: request.method,
241
+ headers: Object.fromEntries(request.headers.entries()),
242
+ cache: request.cache,
243
+ mode: request.mode,
244
+ credentials: request.credentials,
245
+ destination: request.destination,
246
+ integrity: request.integrity,
247
+ redirect: request.redirect,
248
+ referrer: request.referrer,
249
+ referrerPolicy: request.referrerPolicy,
250
+ body: await request.text(),
251
+ bodyUsed: request.bodyUsed,
252
+ keepalive: request.keepalive,
231
253
  },
232
- [requestBuffer],
233
- )
254
+ })
234
255
 
235
256
  switch (clientMessage.type) {
236
257
  case 'MOCK_RESPONSE': {
237
258
  return respondWithMock(clientMessage.data)
238
259
  }
239
260
 
240
- case 'PASSTHROUGH': {
261
+ case 'MOCK_NOT_FOUND': {
241
262
  return passthrough()
242
263
  }
264
+
265
+ case 'NETWORK_ERROR': {
266
+ const { name, message } = clientMessage.data
267
+ const networkError = new Error(message)
268
+ networkError.name = name
269
+
270
+ // Rejecting a "respondWith" promise emulates a network error.
271
+ throw networkError
272
+ }
243
273
  }
244
274
 
245
275
  return passthrough()
246
276
  }
247
277
 
248
- function sendToClient(client, message, transferrables = []) {
278
+ function sendToClient(client, message) {
249
279
  return new Promise((resolve, reject) => {
250
280
  const channel = new MessageChannel()
251
281
 
@@ -257,28 +287,17 @@ function sendToClient(client, message, transferrables = []) {
257
287
  resolve(event.data)
258
288
  }
259
289
 
260
- client.postMessage(
261
- message,
262
- [channel.port2].concat(transferrables.filter(Boolean)),
263
- )
290
+ client.postMessage(message, [channel.port2])
264
291
  })
265
292
  }
266
293
 
267
- async function respondWithMock(response) {
268
- // Setting response status code to 0 is a no-op.
269
- // However, when responding with a "Response.error()", the produced Response
270
- // instance will have status code set to 0. Since it's not possible to create
271
- // a Response instance with status code 0, handle that use-case separately.
272
- if (response.status === 0) {
273
- return Response.error()
274
- }
275
-
276
- const mockedResponse = new Response(response.body, response)
277
-
278
- Reflect.defineProperty(mockedResponse, IS_MOCKED_RESPONSE, {
279
- value: true,
280
- enumerable: true,
294
+ function sleep(timeMs) {
295
+ return new Promise((resolve) => {
296
+ setTimeout(resolve, timeMs)
281
297
  })
298
+ }
282
299
 
283
- return mockedResponse
300
+ async function respondWithMock(response) {
301
+ await sleep(response.delay)
302
+ return new Response(response.body, response)
284
303
  }
@@ -4,8 +4,6 @@ import DeleteIcon from '@mui/icons-material/Delete';
4
4
  import EditIcon from '@mui/icons-material/Edit';
5
5
  import CopyIcon from '@mui/icons-material/ContentCopy';
6
6
 
7
- import { ActionVariants } from './models';
8
-
9
7
  import ActionsList from '.';
10
8
 
11
9
  const actions = [
@@ -26,11 +24,7 @@ const actions = [
26
24
  }
27
25
  ];
28
26
 
29
- const actionsWithVariants: Array<{
30
- label: string;
31
- onClick: () => void;
32
- variant?: ActionVariants;
33
- }> = [
27
+ const actionsWithVariants = [
34
28
  {
35
29
  label: 'No variant',
36
30
  onClick: (): void => undefined
@@ -17,7 +17,7 @@ export const useDashboardLayoutStyles = makeStyles<boolean>()(
17
17
  boxShadow: theme.shadows[3]
18
18
  },
19
19
  '& .react-grid-item.react-grid-placeholder': {
20
- backgroundColor: alpha(theme.palette.primary.main, 0.2)
20
+ backgroundColor: alpha(theme.palette.primary.main, 0.7)
21
21
  },
22
22
  '& .react-grid-item.resizing': {
23
23
  boxShadow: theme.shadows[3]
@@ -61,8 +61,7 @@ export const useDashboardLayoutStyles = makeStyles<boolean>()(
61
61
  },
62
62
  '& .react-resizable-handle:hover': {
63
63
  opacity: 1
64
- },
65
- position: 'relative'
64
+ }
66
65
  }
67
66
  })
68
67
  );
@@ -15,7 +15,6 @@ import { useMemoComponent } from '../utils';
15
15
  import { useDashboardItemStyles } from './Dashboard.styles';
16
16
 
17
17
  interface DashboardItemProps {
18
- additionalMemoProps?: Array<unknown>;
19
18
  canMove?: boolean;
20
19
  children: ReactElement;
21
20
  className?: string;
@@ -40,8 +39,7 @@ const Item = forwardRef<HTMLDivElement, DashboardItemProps>(
40
39
  onTouchEnd,
41
40
  id,
42
41
  disablePadding = false,
43
- canMove = false,
44
- additionalMemoProps = []
42
+ canMove = false
45
43
  }: DashboardItemProps,
46
44
  ref: ForwardedRef<HTMLDivElement>
47
45
  ): ReactElement => {
@@ -94,14 +92,7 @@ const Item = forwardRef<HTMLDivElement, DashboardItemProps>(
94
92
  </Card>
95
93
  </div>
96
94
  ),
97
- memoProps: [
98
- style,
99
- className,
100
- header,
101
- theme.palette.mode,
102
- canMove,
103
- ...additionalMemoProps
104
- ]
95
+ memoProps: [style, className, header, theme.palette.mode, canMove]
105
96
  });
106
97
  }
107
98
  );
@@ -16,7 +16,6 @@ import Grid from './Grid';
16
16
  const ReactGridLayout = WidthProvider(GridLayout);
17
17
 
18
18
  interface DashboardLayoutProps<T> {
19
- additionalMemoProps?: Array<unknown>;
20
19
  changeLayout?: (newLayout: Array<Layout>) => void;
21
20
  children: Array<JSX.Element>;
22
21
  displayGrid?: boolean;
@@ -29,8 +28,7 @@ const DashboardLayout = <T extends Layout>({
29
28
  changeLayout,
30
29
  displayGrid,
31
30
  layout,
32
- isStatic = false,
33
- additionalMemoProps = []
31
+ isStatic = false
34
32
  }: DashboardLayoutProps<T>): JSX.Element => {
35
33
  const { classes } = useDashboardLayoutStyles(isStatic);
36
34
 
@@ -74,7 +72,7 @@ const DashboardLayout = <T extends Layout>({
74
72
  </ParentSize>
75
73
  </ResponsiveHeight>
76
74
  ),
77
- memoProps: [columns, layout, displayGrid, isStatic, ...additionalMemoProps]
75
+ memoProps: [columns, layout, displayGrid, isStatic]
78
76
  });
79
77
  };
80
78
 
@@ -65,7 +65,6 @@ const DescendantNodes = <TData extends BaseProp>({
65
65
  <Group key={key} left={left} top={top}>
66
66
  <foreignObject
67
67
  height={nodeSize.height}
68
- style={{ userSelect: 'none' }}
69
68
  width={nodeSize.width}
70
69
  x={-nodeSize.width / 2}
71
70
  y={-nodeSize.height / 2}
@@ -1,10 +1,5 @@
1
- import {
2
- LinkHorizontal,
3
- LinkHorizontalStep,
4
- LinkHorizontalLine
5
- } from '@visx/shape';
1
+ import { LinkHorizontal } from '@visx/shape';
6
2
  import { HierarchyPointLink } from '@visx/hierarchy/lib/types';
7
- import { always, cond, equals, T } from 'ramda';
8
3
 
9
4
  import { useTheme } from '@mui/material';
10
5
 
@@ -14,12 +9,6 @@ interface Props<TData> extends Pick<TreeProps<TData>, 'treeLink'> {
14
9
  links: Array<HierarchyPointLink<Node<TData>>>;
15
10
  }
16
11
 
17
- const getLinkComponent = cond([
18
- [equals('line'), always(LinkHorizontalLine)],
19
- [equals('step'), always(LinkHorizontalStep)],
20
- [T, always(LinkHorizontal)]
21
- ]);
22
-
23
12
  const Links = <TData extends BaseProp>({
24
13
  links,
25
14
  treeLink
@@ -35,12 +24,10 @@ const Links = <TData extends BaseProp>({
35
24
  .descendants()
36
25
  .map((ancestor) => ancestor.data.data.id);
37
26
 
38
- const LinkComponent = getLinkComponent(treeLink?.type);
39
-
40
27
  const key = `${link.source.data.data.id}-${link.source.data.data.name}-${ancestorIds}_${link.target.data.data.id}-${link.target.data.data.name}-${descendantIds}`;
41
28
 
42
29
  return (
43
- <LinkComponent
30
+ <LinkHorizontal
44
31
  data={link}
45
32
  data-testid={`${link.source.data.data.id}_to_${link.target.data.data.id}`}
46
33
  fill="none"
@@ -168,28 +168,4 @@ describe('Complex data tree', () => {
168
168
 
169
169
  cy.makeSnapshot();
170
170
  });
171
-
172
- it('displays the tree with step links when a prop is set', () => {
173
- initializeStandaloneTree({
174
- treeLink: {
175
- type: 'step'
176
- }
177
- });
178
-
179
- cy.contains('T').should('be.visible');
180
-
181
- cy.makeSnapshot();
182
- });
183
-
184
- it('displays the tree with line links when a prop is set', () => {
185
- initializeStandaloneTree({
186
- treeLink: {
187
- type: 'line'
188
- }
189
- });
190
-
191
- cy.contains('T').should('be.visible');
192
-
193
- cy.makeSnapshot();
194
- });
195
171
  });
@@ -82,21 +82,6 @@ export const WithDefaultExpandFilter: Story = {
82
82
  render: StandaloneTreeTemplate
83
83
  };
84
84
 
85
- export const WithStepLink: Story = {
86
- args: {
87
- children: SimpleContent,
88
- node: {
89
- height: 90,
90
- width: 90
91
- },
92
- tree: simpleData,
93
- treeLink: {
94
- type: 'step'
95
- }
96
- },
97
- render: StandaloneTreeTemplate
98
- };
99
-
100
85
  export const WithCustomLinks: Story = {
101
86
  args: {
102
87
  children: SimpleContent,
@@ -110,8 +95,7 @@ export const WithCustomLinks: Story = {
110
95
  getStrokeDasharray: ({ target }) =>
111
96
  target.status === 'ok' ? '5,5' : '0',
112
97
  getStrokeOpacity: ({ target }) => (target.status === 'ok' ? 0.8 : 1),
113
- getStrokeWidth: ({ target }) => (target.status === 'ok' ? 1 : 2),
114
- type: 'line'
98
+ getStrokeWidth: ({ target }) => (target.status === 'ok' ? 1 : 2)
115
99
  }
116
100
  },
117
101
  render: StandaloneTreeTemplate
@@ -14,8 +14,6 @@ export interface BaseProp {
14
14
  name: string;
15
15
  }
16
16
 
17
- export type Link = 'curve' | 'line' | 'step';
18
-
19
17
  export interface ChildrenProps<TData> {
20
18
  ancestors: Array<Node<TData>>;
21
19
  depth: number;
@@ -50,6 +48,5 @@ export interface TreeProps<TData> {
50
48
  ) => string | number | undefined;
51
49
  getStrokeOpacity?: (props: LinkProps<TData>) => string | number | undefined;
52
50
  getStrokeWidth?: (props: LinkProps<TData>) => string | number | undefined;
53
- type?: Link;
54
51
  };
55
52
  }
@@ -1,11 +1,11 @@
1
- import { useEffect, useState } from 'react';
1
+ import { useState, useEffect } from 'react';
2
2
 
3
3
  import { makeStyles } from 'tss-react/mui';
4
4
 
5
- import ExpandLessIcon from '@mui/icons-material/ExpandLess';
6
5
  import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
7
- import type { SvgIcon } from '@mui/material';
6
+ import ExpandLessIcon from '@mui/icons-material/ExpandLess';
8
7
  import { Badge, ClickAwayListener } from '@mui/material';
8
+ import type { SvgIcon } from '@mui/material';
9
9
 
10
10
  import useCloseOnLegacyPage from './useCloseOnLegacyPage';
11
11
 
@@ -115,6 +115,7 @@ const TopCounterLayout = ({
115
115
  }: TopCounterLayoutProps): JSX.Element => {
116
116
  const { classes, cx } = useStyles();
117
117
  const [toggled, setToggled] = useState(false);
118
+
118
119
  const subMenuId = title.replace(/[^A-Za-z]/, '-');
119
120
  useCloseOnLegacyPage({ setToggled });
120
121
 
@@ -1,6 +1,5 @@
1
1
  import { Dispatch, SetStateAction, useEffect } from 'react';
2
2
 
3
- import { isNil } from 'ramda';
4
3
  import { useLocation } from 'react-router-dom';
5
4
 
6
5
  interface Props {
@@ -15,23 +14,21 @@ const useCloseOnLegacyPage = ({ setToggled }: Props): void => {
15
14
  };
16
15
 
17
16
  useEffect(() => {
18
- const iframe = document.getElementById(
19
- 'main-content'
20
- ) as HTMLIFrameElement | null;
17
+ const iframe = document.getElementById('main-content') as HTMLIFrameElement;
21
18
 
22
- if (!isLegacyRoute || isNil(iframe)) {
19
+ if (!isLegacyRoute) {
23
20
  return () => undefined;
24
21
  }
25
22
 
26
23
  const closeSubMenuOnLegacyPage = (): void => {
27
- iframe?.contentWindow?.document?.addEventListener('click', closeSubMenu);
24
+ iframe.contentWindow?.document?.addEventListener('click', closeSubMenu);
28
25
  };
29
26
 
30
- iframe?.addEventListener('load', closeSubMenuOnLegacyPage);
27
+ iframe.addEventListener('load', closeSubMenuOnLegacyPage);
31
28
 
32
29
  return () => {
33
- iframe?.removeEventListener('load', closeSubMenuOnLegacyPage);
34
- iframe?.contentWindow?.document?.removeEventListener(
30
+ iframe.removeEventListener('load', closeSubMenuOnLegacyPage);
31
+ iframe.contentWindow?.document?.removeEventListener(
35
32
  'click',
36
33
  closeSubMenu
37
34
  );
@@ -4,7 +4,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
4
4
 
5
5
  const defaultCacheTime = 5 * 1_000;
6
6
 
7
- export const client = new QueryClient({
7
+ const client = new QueryClient({
8
8
  defaultOptions: {
9
9
  queries: {
10
10
  gcTime: defaultCacheTime,
@@ -1,5 +1,6 @@
1
1
  import { renderHook, waitFor, RenderHookResult } from '@testing-library/react';
2
2
  import fetchMock from 'jest-fetch-mock';
3
+ import anyLogger from 'anylogger';
3
4
 
4
5
  import TestQueryProvider from '../TestQueryProvider';
5
6
 
@@ -76,6 +77,8 @@ describe('useFetchQuery', () => {
76
77
  expect(mockedShowErrorMessage).toHaveBeenCalledWith('custom message');
77
78
  });
78
79
 
80
+ expect(anyLogger().error).toHaveBeenCalledWith('custom message');
81
+
79
82
  await waitFor(() => {
80
83
  expect(result.current.error).toStrictEqual({
81
84
  additionalInformation: {
@@ -99,6 +102,8 @@ describe('useFetchQuery', () => {
99
102
  await waitFor(() => {
100
103
  expect(mockedShowErrorMessage).toHaveBeenCalledWith('error');
101
104
  });
105
+
106
+ expect(anyLogger().error).toHaveBeenCalledWith('error');
102
107
  });
103
108
 
104
109
  it('shows a default failure message via the Snackbar as fallback', async () => {
@@ -1,5 +1,6 @@
1
1
  import { useEffect, useMemo, useRef } from 'react';
2
2
 
3
+ import 'ulog';
3
4
  import {
4
5
  QueryKey,
5
6
  QueryObserverBaseResult,
@@ -8,12 +9,12 @@ import {
8
9
  UseQueryOptions
9
10
  } from '@tanstack/react-query';
10
11
  import { JsonDecoder } from 'ts.data.json';
12
+ import anylogger from 'anylogger';
11
13
  import { has, includes, isNil, not, omit } from 'ramda';
12
14
 
13
15
  import { CatchErrorProps, customFetch, ResponseError } from '../customFetch';
14
16
  import useSnackbar from '../../Snackbar/useSnackbar';
15
17
  import { useDeepCompare } from '../../utils';
16
- import { errorLog } from '../logger';
17
18
 
18
19
  export interface UseFetchQueryProps<T> {
19
20
  baseEndpoint?: string;
@@ -47,6 +48,8 @@ export interface PrefetchEndpointParams {
47
48
  page: number;
48
49
  }
49
50
 
51
+ const log = anylogger('API Request');
52
+
50
53
  const useFetchQuery = <T extends object>({
51
54
  getEndpoint,
52
55
  getQueryKey,
@@ -84,7 +87,7 @@ const useFetchQuery = <T extends object>({
84
87
  const manageError = (): void => {
85
88
  const data = queryData.data as ResponseError | undefined;
86
89
  if (data?.isError) {
87
- errorLog(data.message);
90
+ log.error(data.message);
88
91
  const hasACorrespondingHttpCode = includes(
89
92
  data?.statusCode || 0,
90
93
  httpCodesBypassErrorSnackbar