@centreon/ui 24.5.0 → 24.5.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.
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@centreon/ui",
3
- "version": "24.5.0",
3
+ "version": "24.5.1",
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",
9
+ "storybook": "storybook dev -p 9001 -c .storybook -s ../public",
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,6 +53,8 @@
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",
56
58
  "@simonsmith/cypress-image-snapshot": "^9.0.1",
57
59
  "@storybook/addon-a11y": "^7.0.9",
58
60
  "@storybook/addon-docs": "^7.0.9",
@@ -169,6 +171,8 @@
169
171
  "output": "./junit.xml"
170
172
  },
171
173
  "msw": {
172
- "workerDirectory": "public"
174
+ "workerDirectory": [
175
+ "public"
176
+ ]
173
177
  }
174
178
  }
@@ -2,13 +2,15 @@
2
2
  /* tslint:disable */
3
3
 
4
4
  /**
5
- * Mock Service Worker (1.3.2).
5
+ * Mock Service Worker.
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 INTEGRITY_CHECKSUM = '3d6b9f06410d179a7f7404d4bf4c3c70'
11
+ const PACKAGE_VERSION = '2.2.14'
12
+ const INTEGRITY_CHECKSUM = '26357c79639bfa20d64c0efca2a87423'
13
+ const IS_MOCKED_RESPONSE = Symbol('isMockedResponse')
12
14
  const activeClientIds = new Set()
13
15
 
14
16
  self.addEventListener('install', function () {
@@ -47,7 +49,10 @@ self.addEventListener('message', async function (event) {
47
49
  case 'INTEGRITY_CHECK_REQUEST': {
48
50
  sendToClient(client, {
49
51
  type: 'INTEGRITY_CHECK_RESPONSE',
50
- payload: INTEGRITY_CHECKSUM,
52
+ payload: {
53
+ packageVersion: PACKAGE_VERSION,
54
+ checksum: INTEGRITY_CHECKSUM,
55
+ },
51
56
  })
52
57
  break
53
58
  }
@@ -86,12 +91,6 @@ self.addEventListener('message', async function (event) {
86
91
 
87
92
  self.addEventListener('fetch', function (event) {
88
93
  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
- }
95
94
 
96
95
  // Bypass navigation requests.
97
96
  if (request.mode === 'navigate') {
@@ -112,29 +111,8 @@ self.addEventListener('fetch', function (event) {
112
111
  }
113
112
 
114
113
  // Generate unique request ID.
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
- )
114
+ const requestId = crypto.randomUUID()
115
+ event.respondWith(handleRequest(event, requestId))
138
116
  })
139
117
 
140
118
  async function handleRequest(event, requestId) {
@@ -146,21 +124,24 @@ async function handleRequest(event, requestId) {
146
124
  // this message will pend indefinitely.
147
125
  if (client && activeClientIds.has(client.id)) {
148
126
  ;(async function () {
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,
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
+ },
162
142
  },
163
- })
143
+ [responseClone.body],
144
+ )
164
145
  })()
165
146
  }
166
147
 
@@ -196,20 +177,20 @@ async function resolveMainClient(event) {
196
177
 
197
178
  async function getResponse(event, client, requestId) {
198
179
  const { request } = event
199
- const clonedRequest = request.clone()
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()
200
184
 
201
185
  function passthrough() {
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())
186
+ const headers = Object.fromEntries(requestClone.headers.entries())
205
187
 
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']
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']
211
192
 
212
- return fetch(clonedRequest, { headers })
193
+ return fetch(requestClone, { headers })
213
194
  }
214
195
 
215
196
  // Bypass mocking when the client is not active.
@@ -225,57 +206,46 @@ async function getResponse(event, client, requestId) {
225
206
  return passthrough()
226
207
  }
227
208
 
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
-
234
209
  // Notify the client that a request has been intercepted.
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,
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
+ },
253
231
  },
254
- })
232
+ [requestBuffer],
233
+ )
255
234
 
256
235
  switch (clientMessage.type) {
257
236
  case 'MOCK_RESPONSE': {
258
237
  return respondWithMock(clientMessage.data)
259
238
  }
260
239
 
261
- case 'MOCK_NOT_FOUND': {
240
+ case 'PASSTHROUGH': {
262
241
  return passthrough()
263
242
  }
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
- }
273
243
  }
274
244
 
275
245
  return passthrough()
276
246
  }
277
247
 
278
- function sendToClient(client, message) {
248
+ function sendToClient(client, message, transferrables = []) {
279
249
  return new Promise((resolve, reject) => {
280
250
  const channel = new MessageChannel()
281
251
 
@@ -287,17 +257,28 @@ function sendToClient(client, message) {
287
257
  resolve(event.data)
288
258
  }
289
259
 
290
- client.postMessage(message, [channel.port2])
260
+ client.postMessage(
261
+ message,
262
+ [channel.port2].concat(transferrables.filter(Boolean)),
263
+ )
291
264
  })
292
265
  }
293
266
 
294
- function sleep(timeMs) {
295
- return new Promise((resolve) => {
296
- setTimeout(resolve, timeMs)
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,
297
281
  })
298
- }
299
282
 
300
- async function respondWithMock(response) {
301
- await sleep(response.delay)
302
- return new Response(response.body, response)
283
+ return mockedResponse
303
284
  }
@@ -4,6 +4,8 @@ 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
+
7
9
  import ActionsList from '.';
8
10
 
9
11
  const actions = [
@@ -24,7 +26,11 @@ const actions = [
24
26
  }
25
27
  ];
26
28
 
27
- const actionsWithVariants = [
29
+ const actionsWithVariants: Array<{
30
+ label: string;
31
+ onClick: () => void;
32
+ variant?: ActionVariants;
33
+ }> = [
28
34
  {
29
35
  label: 'No variant',
30
36
  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.7)
20
+ backgroundColor: alpha(theme.palette.primary.main, 0.2)
21
21
  },
22
22
  '& .react-grid-item.resizing': {
23
23
  boxShadow: theme.shadows[3]
@@ -61,7 +61,8 @@ export const useDashboardLayoutStyles = makeStyles<boolean>()(
61
61
  },
62
62
  '& .react-resizable-handle:hover': {
63
63
  opacity: 1
64
- }
64
+ },
65
+ position: 'relative'
65
66
  }
66
67
  })
67
68
  );
@@ -4,7 +4,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
4
4
 
5
5
  const defaultCacheTime = 5 * 1_000;
6
6
 
7
- const client = new QueryClient({
7
+ export const client = new QueryClient({
8
8
  defaultOptions: {
9
9
  queries: {
10
10
  gcTime: defaultCacheTime,
@@ -0,0 +1,11 @@
1
+ export const errorLog = (text: string): void => {
2
+ const { error: log } = console;
3
+
4
+ log(`API Request: ${text}`);
5
+ };
6
+
7
+ export const warnLog = (text: string): void => {
8
+ const { warn: log } = console;
9
+
10
+ log(`API Request: ${text}`);
11
+ };
@@ -1,6 +1,5 @@
1
1
  import { renderHook, waitFor, RenderHookResult } from '@testing-library/react';
2
2
  import fetchMock from 'jest-fetch-mock';
3
- import anyLogger from 'anylogger';
4
3
 
5
4
  import TestQueryProvider from '../TestQueryProvider';
6
5
 
@@ -77,8 +76,6 @@ describe('useFetchQuery', () => {
77
76
  expect(mockedShowErrorMessage).toHaveBeenCalledWith('custom message');
78
77
  });
79
78
 
80
- expect(anyLogger().error).toHaveBeenCalledWith('custom message');
81
-
82
79
  await waitFor(() => {
83
80
  expect(result.current.error).toStrictEqual({
84
81
  additionalInformation: {
@@ -102,8 +99,6 @@ describe('useFetchQuery', () => {
102
99
  await waitFor(() => {
103
100
  expect(mockedShowErrorMessage).toHaveBeenCalledWith('error');
104
101
  });
105
-
106
- expect(anyLogger().error).toHaveBeenCalledWith('error');
107
102
  });
108
103
 
109
104
  it('shows a default failure message via the Snackbar as fallback', async () => {
@@ -1,6 +1,5 @@
1
1
  import { useEffect, useMemo, useRef } from 'react';
2
2
 
3
- import 'ulog';
4
3
  import {
5
4
  QueryKey,
6
5
  QueryObserverBaseResult,
@@ -9,12 +8,12 @@ import {
9
8
  UseQueryOptions
10
9
  } from '@tanstack/react-query';
11
10
  import { JsonDecoder } from 'ts.data.json';
12
- import anylogger from 'anylogger';
13
11
  import { has, includes, isNil, not, omit } from 'ramda';
14
12
 
15
13
  import { CatchErrorProps, customFetch, ResponseError } from '../customFetch';
16
14
  import useSnackbar from '../../Snackbar/useSnackbar';
17
15
  import { useDeepCompare } from '../../utils';
16
+ import { errorLog } from '../logger';
18
17
 
19
18
  export interface UseFetchQueryProps<T> {
20
19
  baseEndpoint?: string;
@@ -48,8 +47,6 @@ export interface PrefetchEndpointParams {
48
47
  page: number;
49
48
  }
50
49
 
51
- const log = anylogger('API Request');
52
-
53
50
  const useFetchQuery = <T extends object>({
54
51
  getEndpoint,
55
52
  getQueryKey,
@@ -87,7 +84,7 @@ const useFetchQuery = <T extends object>({
87
84
  const manageError = (): void => {
88
85
  const data = queryData.data as ResponseError | undefined;
89
86
  if (data?.isError) {
90
- log.error(data.message);
87
+ errorLog(data.message);
91
88
  const hasACorrespondingHttpCode = includes(
92
89
  data?.statusCode || 0,
93
90
  httpCodesBypassErrorSnackbar
@@ -1,4 +1,3 @@
1
- import 'ulog';
2
1
  import { useEffect } from 'react';
3
2
 
4
3
  import {
@@ -7,12 +6,12 @@ import {
7
6
  UseMutationResult
8
7
  } from '@tanstack/react-query';
9
8
  import { JsonDecoder } from 'ts.data.json';
10
- import anylogger from 'anylogger';
11
9
  import { includes, omit } from 'ramda';
12
10
 
13
11
  import { CatchErrorProps, customFetch, ResponseError } from '../customFetch';
14
12
  import useSnackbar from '../../Snackbar/useSnackbar';
15
13
  import { useDeepCompare } from '../../utils';
14
+ import { errorLog } from '../logger';
16
15
 
17
16
  export enum Method {
18
17
  DELETE = 'DELETE',
@@ -52,8 +51,6 @@ export type UseMutationQueryProps<T, TMeta> = {
52
51
  'mutationFn' | 'onError' | 'onMutate' | 'onSuccess' | 'mutateAsync' | 'mutate'
53
52
  >;
54
53
 
55
- const log = anylogger('API Request');
56
-
57
54
  export type UseMutationQueryState<T, TMeta> = Omit<
58
55
  UseMutationResult<T | ResponseError>,
59
56
  'isError' | 'mutate' | 'mutateAsync'
@@ -127,7 +124,7 @@ const useMutationQuery = <T extends object, TMeta>({
127
124
  const manageError = (): void => {
128
125
  const data = queryData.data as ResponseError | undefined;
129
126
  if (data?.isError) {
130
- log.error(data.message);
127
+ errorLog(data.message);
131
128
  const hasACorrespondingHttpCode = includes(
132
129
  data?.statusCode || 0,
133
130
  httpCodesBypassErrorSnackbar
@@ -1,5 +1,4 @@
1
1
  import axios from 'axios';
2
- import anyLogger from 'anylogger';
3
2
  import { RenderHookResult, renderHook, act } from '@testing-library/react';
4
3
 
5
4
  import useRequest, { RequestResult, RequestParams } from '.';
@@ -77,8 +76,6 @@ describe(useRequest, () => {
77
76
  });
78
77
  });
79
78
 
80
- expect(anyLogger().error).toHaveBeenCalledWith(response);
81
-
82
79
  expect(mockedShowErrorMessage).toHaveBeenCalledWith('failure');
83
80
  });
84
81
 
@@ -1,15 +1,12 @@
1
1
  import { useState, useEffect } from 'react';
2
2
 
3
- import 'ulog';
4
3
  import axios from 'axios';
5
4
  import { pathOr, defaultTo, path, includes, or } from 'ramda';
6
- import anylogger from 'anylogger';
7
5
  import { JsonDecoder } from 'ts.data.json';
8
6
 
9
7
  import useCancelTokenSource from '../useCancelTokenSource';
10
8
  import useSnackbar from '../../Snackbar/useSnackbar';
11
-
12
- const log = anylogger('API Request');
9
+ import { errorLog, warnLog } from '../logger';
13
10
 
14
11
  export interface RequestParams<TResult> {
15
12
  decoder?: JsonDecoder.Decoder<TResult>;
@@ -41,7 +38,7 @@ const useRequest = <TResult>({
41
38
  }, []);
42
39
 
43
40
  const showRequestErrorMessage = (error): void => {
44
- log.error(error);
41
+ errorLog(error.message);
45
42
 
46
43
  const message = or(
47
44
  pathOr(undefined, ['response', 'data', 'message'], error),
@@ -68,7 +65,7 @@ const useRequest = <TResult>({
68
65
  .catch((error) => {
69
66
  setSending(false);
70
67
  if (axios.isCancel(error)) {
71
- log.warn(error);
68
+ warnLog(error);
72
69
 
73
70
  throw error;
74
71
  }
package/src/index.ts CHANGED
@@ -131,7 +131,7 @@ export {
131
131
  default as useGraphQuery,
132
132
  resourceTypeQueryParameter
133
133
  } from './api/useGraphQuery';
134
- export { default as QueryProvider } from './api/QueryProvider';
134
+ export { default as QueryProvider, client } from './api/QueryProvider';
135
135
  export {
136
136
  default as FileDropZone,
137
137
  transformFileListToArray