@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.
- package/package.json +3 -7
- package/public/mockServiceWorker.js +100 -81
- package/src/ActionsList/index.stories.tsx +1 -7
- package/src/Dashboard/Dashboard.styles.ts +2 -3
- package/src/Dashboard/Item.tsx +2 -11
- package/src/Dashboard/Layout.tsx +2 -4
- package/src/Graph/Tree/DescendantNodes.tsx +0 -1
- package/src/Graph/Tree/Links.tsx +2 -15
- package/src/Graph/Tree/Tree.cypress.spec.tsx +0 -24
- package/src/Graph/Tree/Tree.stories.tsx +1 -17
- package/src/Graph/Tree/models.ts +0 -3
- package/src/TopCounterElements/TopCounterLayout.tsx +4 -3
- package/src/TopCounterElements/useCloseOnLegacyPage.tsx +6 -9
- package/src/api/QueryProvider.tsx +1 -1
- package/src/api/useFetchQuery/index.test.ts +5 -0
- package/src/api/useFetchQuery/index.ts +5 -2
- package/src/api/useGraphQuery/index.ts +1 -7
- package/src/api/useMutationQuery/index.ts +5 -2
- package/src/api/useRequest/index.test.ts +3 -0
- package/src/api/useRequest/index.ts +6 -3
- package/src/components/Form/AccessRights/AccessRights.cypress.spec.tsx +13 -27
- package/src/components/Form/AccessRights/AccessRights.stories.tsx +19 -0
- package/src/components/Form/AccessRights/AccessRights.styles.ts +1 -1
- package/src/components/Form/AccessRights/AccessRights.tsx +5 -6
- package/src/components/Form/AccessRights/Actions/Actions.styles.ts +7 -3
- package/src/components/Form/AccessRights/Actions/Actions.tsx +32 -15
- package/src/components/Form/AccessRights/Actions/useActions.ts +37 -4
- package/src/components/Form/AccessRights/models.ts +3 -0
- package/src/components/Form/AccessRights/storiesData.ts +3 -0
- package/src/components/List/Item/ListItem.styles.ts +2 -2
- package/src/components/Zoom/Minimap.tsx +2 -4
- package/src/components/Zoom/Zoom.cypress.spec.tsx +13 -13
- package/src/components/Zoom/Zoom.tsx +1 -4
- package/src/components/Zoom/ZoomContent.tsx +2 -5
- package/src/components/index.ts +0 -1
- package/src/index.ts +1 -1
- package/src/utils/index.ts +0 -1
- package/src/utils/usePluralizedTranslation.ts +3 -20
- package/src/api/logger.ts +0 -11
- package/src/components/Form/AccessRights/useAccessRightsChange.ts +0 -30
- package/src/components/Form/AccessRights/utils.ts +0 -18
- package/src/components/Tabs/Tab.styles.ts +0 -25
- package/src/components/Tabs/TabPanel.tsx +0 -22
- package/src/components/Tabs/Tabs.cypress.spec.tsx +0 -70
- package/src/components/Tabs/Tabs.stories.tsx +0 -55
- package/src/components/Tabs/Tabs.tsx +0 -55
- package/src/components/Tabs/index.ts +0 -6
- package/src/utils/resourcesStatusURL.ts +0 -166
- 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.
|
|
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
|
|
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
|
|
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 =
|
|
115
|
-
|
|
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
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
type:
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
189
|
-
//
|
|
190
|
-
//
|
|
191
|
-
|
|
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(
|
|
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
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
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
|
-
|
|
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 '
|
|
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
|
|
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
|
-
|
|
268
|
-
|
|
269
|
-
|
|
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
|
-
|
|
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
|
|
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.
|
|
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
|
);
|
package/src/Dashboard/Item.tsx
CHANGED
|
@@ -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
|
);
|
package/src/Dashboard/Layout.tsx
CHANGED
|
@@ -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
|
|
75
|
+
memoProps: [columns, layout, displayGrid, isStatic]
|
|
78
76
|
});
|
|
79
77
|
};
|
|
80
78
|
|
package/src/Graph/Tree/Links.tsx
CHANGED
|
@@ -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
|
-
<
|
|
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
|
package/src/Graph/Tree/models.ts
CHANGED
|
@@ -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 {
|
|
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
|
|
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
|
|
19
|
+
if (!isLegacyRoute) {
|
|
23
20
|
return () => undefined;
|
|
24
21
|
}
|
|
25
22
|
|
|
26
23
|
const closeSubMenuOnLegacyPage = (): void => {
|
|
27
|
-
iframe
|
|
24
|
+
iframe.contentWindow?.document?.addEventListener('click', closeSubMenu);
|
|
28
25
|
};
|
|
29
26
|
|
|
30
|
-
iframe
|
|
27
|
+
iframe.addEventListener('load', closeSubMenuOnLegacyPage);
|
|
31
28
|
|
|
32
29
|
return () => {
|
|
33
|
-
iframe
|
|
34
|
-
iframe
|
|
30
|
+
iframe.removeEventListener('load', closeSubMenuOnLegacyPage);
|
|
31
|
+
iframe.contentWindow?.document?.removeEventListener(
|
|
35
32
|
'click',
|
|
36
33
|
closeSubMenu
|
|
37
34
|
);
|
|
@@ -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
|
-
|
|
90
|
+
log.error(data.message);
|
|
88
91
|
const hasACorrespondingHttpCode = includes(
|
|
89
92
|
data?.statusCode || 0,
|
|
90
93
|
httpCodesBypassErrorSnackbar
|