@fluxo-dev/shell 0.0.8

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 (66) hide show
  1. package/.babelrc +12 -0
  2. package/.eslintrc.json +18 -0
  3. package/README.md +7 -0
  4. package/jest.config.ts +11 -0
  5. package/package.json +4 -0
  6. package/project.json +43 -0
  7. package/src/index.ts +1 -0
  8. package/src/lib/app.module.css +1 -0
  9. package/src/lib/app.spec.tsx +17 -0
  10. package/src/lib/app.tsx +374 -0
  11. package/src/lib/components/error-page/404.tsx +16 -0
  12. package/src/lib/components/routes/main-routes.tsx +26 -0
  13. package/src/lib/layouts/blank/blank-layout.tsx +10 -0
  14. package/src/lib/layouts/main/app-bar.tsx +192 -0
  15. package/src/lib/layouts/main/app-layout.tsx +52 -0
  16. package/src/lib/layouts/main/content.tsx +10 -0
  17. package/src/lib/layouts/main/footer-bar.tsx +76 -0
  18. package/src/lib/layouts/main/navbar-item.module.css +49 -0
  19. package/src/lib/layouts/main/navbar-item.tsx +129 -0
  20. package/src/lib/layouts/main/navbar.tsx +38 -0
  21. package/src/lib/layouts/main/search-bar.tsx +44 -0
  22. package/src/lib/layouts/main/shell-spotlight.tsx +58 -0
  23. package/src/lib/models/app-jit.ts +6 -0
  24. package/src/lib/pages/general/fluxo-plugin-loader.tsx +22 -0
  25. package/src/lib/pages/login/account-confirmation.tsx +86 -0
  26. package/src/lib/pages/login/change-password.tsx +58 -0
  27. package/src/lib/pages/login/forgot-password.tsx +53 -0
  28. package/src/lib/pages/login/login-page.tsx +70 -0
  29. package/src/lib/pages/login/reset-password.tsx +91 -0
  30. package/src/lib/pages/settings/apps/add-jit-app.tsx +79 -0
  31. package/src/lib/pages/settings/apps/app-item.tsx +157 -0
  32. package/src/lib/pages/settings/apps/app-jit-item.tsx +105 -0
  33. package/src/lib/pages/settings/apps/apps-list.tsx +171 -0
  34. package/src/lib/pages/settings/apps/embedded-module-item.tsx +66 -0
  35. package/src/lib/pages/settings/apps/install-or-upgrade-app.tsx +105 -0
  36. package/src/lib/pages/settings/menu-designer/custom-node.module.css +34 -0
  37. package/src/lib/pages/settings/menu-designer/custom-node.tsx +160 -0
  38. package/src/lib/pages/settings/menu-designer/menu-create-form.tsx +109 -0
  39. package/src/lib/pages/settings/menu-designer/menu-designer.module.css +19 -0
  40. package/src/lib/pages/settings/menu-designer/menu-designer.tsx +463 -0
  41. package/src/lib/pages/settings/menu-designer/menu-item-edit.tsx +115 -0
  42. package/src/lib/pages/settings/menu-designer/placeholder.module.css +8 -0
  43. package/src/lib/pages/settings/menu-designer/placeholder.tsx +13 -0
  44. package/src/lib/pages/settings/security/components/domani-role/domain-role-form.tsx +67 -0
  45. package/src/lib/pages/settings/security/components/domani-role/domain-role-grid.tsx +139 -0
  46. package/src/lib/pages/settings/security/components/permission/create-custom-permission-form.tsx +64 -0
  47. package/src/lib/pages/settings/security/components/permission/create-scope-form.tsx +158 -0
  48. package/src/lib/pages/settings/security/components/permission/permission-grid.tsx +304 -0
  49. package/src/lib/pages/settings/security/components/permission/permission-navigator.tsx +320 -0
  50. package/src/lib/pages/settings/security/components/permission/update-permission.tsx +54 -0
  51. package/src/lib/pages/settings/security/components/route-rule/route-rule-create-form.tsx +59 -0
  52. package/src/lib/pages/settings/security/components/route-rule/route-rule-grid.tsx +229 -0
  53. package/src/lib/pages/settings/security/components/user/user-form.tsx +123 -0
  54. package/src/lib/pages/settings/security/components/user/users-grid.tsx +127 -0
  55. package/src/lib/pages/settings/settings.tsx +298 -0
  56. package/src/lib/pages/settings/token/token-row.tsx +69 -0
  57. package/src/lib/pages/settings/token/tokens.tsx +73 -0
  58. package/src/lib/pages/settings/ui/ui.tsx +149 -0
  59. package/src/lib/services/app-jit-manager.ts +92 -0
  60. package/src/lib/services/app-menu.service.ts +35 -0
  61. package/src/lib/utils/icon-factory.tsx +25 -0
  62. package/src/lib/utils/security/only-not-logged-route.tsx +17 -0
  63. package/src/lib/utils/security/protected-route.tsx +47 -0
  64. package/tsconfig.json +20 -0
  65. package/tsconfig.lib.json +24 -0
  66. package/tsconfig.spec.json +20 -0
@@ -0,0 +1,304 @@
1
+ import {
2
+ ActionIcon,
3
+ Badge,
4
+ Button,
5
+ Center,
6
+ Divider,
7
+ Grid,
8
+ Group,
9
+ Loader,
10
+ Modal,
11
+ Select,
12
+ Stack,
13
+ Table,
14
+ Text
15
+ } from "@mantine/core";
16
+ import React, {useEffect, useState} from "react";
17
+ import {UpdatePermission} from "./update-permission";
18
+ import {FluxoClientSys, Permission, PermissionScope} from "@fluxo-dev/api-client-base";
19
+ import {IconArrowDown, IconCloudOff, IconPlus, IconRefresh, IconTrash} from '@tabler/icons-react';
20
+ import {DataCard, WaitData} from "@fluxo-dev/ui-components";
21
+ import {CreateScopeForm} from "./create-scope-form";
22
+ import {CreateCustomPermissionForm} from "./create-custom-permission-form";
23
+ import {showNotification} from "@mantine/notifications";
24
+
25
+ export function PermissionGrid() {
26
+
27
+ const [permissions, setPermissions] = useState<Permission[]>([]);
28
+ const [updatePermissionModal, setUpdatePermissionModal] = useState<boolean>(false);
29
+
30
+ const [permissionScopes, setPermissionScopes] = useState<PermissionScope[]>([]);
31
+ const [permissionScopesLoaded, setPermissionScopesLoaded] = useState<boolean>(false);
32
+
33
+ const [currentScope, setCurrentScope] = useState<string | null>(null);
34
+ const [currentPackageName, setCurrentPackageName] = useState<string | null>(null);
35
+ const [currentNamespace, setCurrentNamespace] = useState<string | null>(null);
36
+ const [permissionLoading, setPermissionLoading] = useState<boolean>(false);
37
+
38
+ const [createPermissionScopeModalOpened, setCreatePermissionScopeModalOpened] = useState<boolean>(false);
39
+ const [createCustomPermissionModalOpened, setCreateCustomPermissionModalOpened] = useState<boolean>(false);
40
+
41
+ useEffect(() => {
42
+ loadPermissionScopes();
43
+ }, [])
44
+
45
+ const loadPermissionScopes = () => {
46
+ FluxoClientSys.Instance.security.permission.getPermissionScopes()
47
+ .then((res) => {
48
+ setPermissionScopes(res);
49
+ setPermissionScopesLoaded(true);
50
+ })
51
+ }
52
+
53
+ useEffect(() => {
54
+ if(currentScope && currentPackageName && currentNamespace)
55
+ getPermissionInScope();
56
+ else
57
+ setPermissions([]);
58
+ }, [currentScope, currentPackageName, currentNamespace]);
59
+
60
+ const getPermissionInScope = () => {
61
+
62
+ if(!currentScope || !currentPackageName || !currentNamespace) {
63
+ return;
64
+ }
65
+
66
+ setPermissionLoading(true);
67
+
68
+ FluxoClientSys.Instance.security.permission.getPermissionsInScope(currentScope, currentPackageName, currentNamespace)
69
+ .then((res) => {
70
+ setPermissions(res);
71
+ setPermissionLoading(false);
72
+ })
73
+ }
74
+
75
+ const deleteCustomPermission = (permissionId: number) => {
76
+ FluxoClientSys.Instance.security.permission.deleteCustomPermission(permissionId)
77
+ .then(() => {
78
+ showNotification({
79
+ title: 'Operazione completata',
80
+ message: 'Il permesso è stato eliminato con successo',
81
+ color: 'green',
82
+ })
83
+ getPermissionInScope();
84
+ })
85
+ .catch(() => {
86
+ showNotification({
87
+ title: 'Operazione fallita',
88
+ message: 'Non è stato possibile eliminare il permesso',
89
+ color: 'red',
90
+ })
91
+ });
92
+ }
93
+
94
+ const deletePermissionScope = () => {
95
+
96
+ if(!currentScope || !currentPackageName || !currentNamespace) {
97
+ return;
98
+ }
99
+
100
+ FluxoClientSys.Instance.security.permission.deletePermissionScope(currentScope, currentPackageName, currentNamespace)
101
+ .then(() => {
102
+ showNotification({
103
+ title: 'Operazione completata',
104
+ message: 'Lo scope è stato eliminato con successo',
105
+ color: 'green',
106
+ })
107
+ setCurrentScope(null);
108
+ setCurrentPackageName(null);
109
+ setCurrentNamespace(null);
110
+ setPermissions([]);
111
+ loadPermissionScopes();
112
+ })
113
+ .catch(() => {
114
+ showNotification({
115
+ title: 'Operazione fallita',
116
+ message: 'Non è stato possibile eliminare lo scope',
117
+ color: 'red',
118
+ })
119
+ });
120
+ }
121
+
122
+ const getScopes = () => {
123
+ if(permissionScopes === undefined) return [];
124
+ return [...new Set(permissionScopes.map(a => a.scope))];
125
+ }
126
+
127
+ const getPackageNames = (scope: string | null) => {
128
+ if(permissionScopes === undefined || !scope) return [];
129
+ return [...new Set(permissionScopes.filter(a => a.scope === scope).map(a => a.packageName))];
130
+ }
131
+
132
+ const getNamespaces = (scope: string | null, packageName: string | null) => {
133
+ if(permissionScopes === undefined || !scope || !packageName) return [];
134
+ return [...new Set(permissionScopes.filter(a => a.scope === scope && a.packageName === packageName).map(a => a.namespace))];
135
+ }
136
+
137
+ return (
138
+ <DataCard title={'Permessi'}
139
+ actions={[
140
+ {
141
+ icon: <IconArrowDown size={18}/>,
142
+ label: 'Installa permessi',
143
+ onClick: () => {
144
+ setUpdatePermissionModal(true)
145
+ }
146
+ },
147
+ {
148
+ icon: <IconPlus size={18}/>,
149
+ label: 'Crea nuovo scope',
150
+ onClick: () => {
151
+ setCreatePermissionScopeModalOpened(true)
152
+ }
153
+ }]}>
154
+
155
+ <Stack>
156
+ <Grid>
157
+ <Grid.Col span={4}>
158
+ <Select
159
+ data={getScopes()}
160
+ searchable
161
+ placeholder={'Seleziona uno scope'}
162
+ value={currentScope}
163
+ label={'Scope'}
164
+ onChange={(v) => {
165
+ setCurrentScope(v)
166
+ setCurrentPackageName(null);
167
+ setCurrentNamespace(null);
168
+ }} />
169
+ </Grid.Col>
170
+ <Grid.Col span={4}>
171
+ <Select
172
+ disabled={!currentScope}
173
+ searchable
174
+ placeholder={'Seleziona un package name'}
175
+ data={getPackageNames(currentScope)}
176
+ value={currentPackageName}
177
+ label={'Package name'}
178
+ onChange={(v) => {
179
+ setCurrentPackageName(v)
180
+ setCurrentNamespace(null);
181
+ }} />
182
+ </Grid.Col>
183
+ <Grid.Col span={4}>
184
+ <Select
185
+ disabled={!currentPackageName}
186
+ searchable
187
+ placeholder={'Seleziona un namespace'}
188
+ data={getNamespaces(currentScope, currentPackageName)}
189
+ value={currentNamespace}
190
+ label={'Namespace'}
191
+ onChange={(v) => {
192
+ setCurrentNamespace(v)
193
+ }} />
194
+ </Grid.Col>
195
+ </Grid>
196
+
197
+ <Divider />
198
+
199
+ {permissionLoading &&
200
+ <Loader />
201
+ }
202
+
203
+ {(currentScope && currentPackageName && currentNamespace && !permissionLoading && permissions.length) === 0 &&
204
+ <Stack>
205
+ <Group justify={'right'} align={'center'}>
206
+ <Button color={'red'} disabled={permissions.length > 0} onClick={deletePermissionScope} leftSection={<IconTrash size={18}/>}>Elimina scope</Button>
207
+ <Button leftSection={<IconPlus size={18}/>} onClick={() => setCreateCustomPermissionModalOpened(true)}>Crea permesso custom</Button>
208
+ </Group>
209
+ <Center>
210
+ <Text size={'md'}>Nessun permesso esistente.</Text>
211
+ </Center>
212
+ </Stack>
213
+ }
214
+
215
+ {(!currentScope || !currentPackageName || !currentNamespace) &&
216
+ <Stack align={'center'} mt={32} mb={32}>
217
+ <IconCloudOff color={'gray'} size={64} />
218
+ <Center>
219
+ <Text size={'md'}>Seleziona uno scope, un package name e un namespace per visualizzare i permessi associati.</Text>
220
+ </Center>
221
+ </Stack>
222
+ }
223
+
224
+ {!permissionLoading && permissions.length > 0 &&
225
+ <Stack>
226
+ <Group justify={'right'} align={'center'}>
227
+ <Button disabled={permissions.length > 0} leftSection={<IconTrash size={18}/>}>Elimina scope</Button>
228
+ <Button leftSection={<IconPlus size={18}/>} onClick={() => setCreateCustomPermissionModalOpened(true)}>Crea permesso custom</Button>
229
+ </Group>
230
+ <Table highlightOnHover>
231
+ <Table.Thead>
232
+ <Table.Tr>
233
+ <Table.Th>Id</Table.Th>
234
+ <Table.Th>Scope</Table.Th>
235
+ <Table.Th>Identificatore</Table.Th>
236
+ <Table.Th>Descrizione</Table.Th>
237
+ <Table.Th style={{maxWidth: 130, width: 130}}>Personalizzato</Table.Th>
238
+ <Table.Th style={{maxWidth: 80, width: 80}}>Azioni</Table.Th>
239
+ </Table.Tr>
240
+ </Table.Thead>
241
+ <tbody>
242
+ {permissions.map((element, i) => {
243
+ return (
244
+ <Table.Tr key={i}>
245
+ <Table.Td>{element.id}</Table.Td>
246
+ <Table.Td>{`${element.scope}.${element.packageName}.${element.namespace}`}</Table.Td>
247
+ <Table.Td>{element.identifier}</Table.Td>
248
+ <Table.Td>{element.description}</Table.Td>
249
+ <Table.Td style={{maxWidth: 130, width: 130}}>
250
+ {element.isCustom ?
251
+ <Badge w={'100%'} color={'green'}>Si</Badge> :
252
+ <Badge w={'100%'} color={'red'}>No</Badge>
253
+ }
254
+ </Table.Td>
255
+ <Table.Td style={{maxWidth: 130, width: 130}}>
256
+ <ActionIcon
257
+ onClick={() => deleteCustomPermission(element.id)}
258
+ disabled={!element.isCustom}>
259
+ <IconTrash size={18} />
260
+ </ActionIcon>
261
+ </Table.Td>
262
+ </Table.Tr>
263
+ )
264
+ })}
265
+ </tbody>
266
+ </Table>
267
+ </Stack>
268
+ }
269
+
270
+
271
+
272
+ <Modal centered opened={updatePermissionModal} onClose={() => {
273
+ setUpdatePermissionModal(false);
274
+ }} title="Aggiorna permessi">
275
+ <UpdatePermission onUpdated={() => {
276
+ setUpdatePermissionModal(false)
277
+ }} onCanceled={() => setUpdatePermissionModal(false)} />
278
+ </Modal>
279
+
280
+ <Modal centered opened={createPermissionScopeModalOpened} onClose={() => {
281
+ setCreatePermissionScopeModalOpened(false);
282
+ }} title="Crea nuovo scope">
283
+ <CreateScopeForm
284
+ permissionScopes={permissionScopes}
285
+ onCreated={() => { setCreatePermissionScopeModalOpened(false); loadPermissionScopes() }}
286
+ onCanceled={() => {setCreatePermissionScopeModalOpened(false)}}
287
+ />
288
+ </Modal>
289
+
290
+ <Modal centered opened={createCustomPermissionModalOpened} onClose={() => {
291
+ setCreatePermissionScopeModalOpened(false);
292
+ }} title="Crea nuovo permesso custom">
293
+ <CreateCustomPermissionForm
294
+ permissionScope={permissionScopes.filter(a => a.scope === currentScope && a.packageName === currentPackageName && a.namespace === currentNamespace)[0]}
295
+ onCreated={() => {setCreateCustomPermissionModalOpened(false); getPermissionInScope()}}
296
+ onCanceled={() => {setCreateCustomPermissionModalOpened(false)}}
297
+ />
298
+ </Modal>
299
+
300
+ </Stack>
301
+
302
+ </DataCard>
303
+ )
304
+ }
@@ -0,0 +1,320 @@
1
+ import React, {useEffect, useState} from "react";
2
+ import {
3
+ FluxoClientSys,
4
+ Permission, PermissionScope
5
+ } from "@fluxo-dev/api-client-base";
6
+ import {Badge, Checkbox, Grid, Group, Loader, NavLink, ScrollArea, Stack, Text, TextInput} from "@mantine/core";
7
+ import {IconSearch} from '@tabler/icons-react';
8
+ import {NoData} from "@fluxo-dev/ui-components";
9
+ import {showNotification} from "@mantine/notifications";
10
+
11
+ export interface PermissionNavigatorProps {
12
+ context: {type: 'domainRole' | 'menu' | 'route-rule', id: string};
13
+ onUpdate: (currentPermissionCount: number) => void;
14
+ }
15
+
16
+ export function PermissionNavigator(props: PermissionNavigatorProps) {
17
+
18
+ const [structuredPermissions, setStructuredPermissions] = useState<PermissionScope[]>();
19
+ const [domainRolePermissions, setDomainRolePermissions] = useState<Permission[]>([]);
20
+
21
+ const [structuredPermissionLoaded, setStructuredPermissionLoaded] = useState<boolean>(false);
22
+ const [domainRolePermissionLoaded, setDomainRolePermissionLoaded] = useState<boolean>(false);
23
+
24
+ //const [currentPackageName, setCurrentPackageName] = useState<StructuredPermissionsPackageName>();
25
+
26
+ const [selectedPermissionsIds, setSelectedPermissionsIds] = useState<number[]>([]);
27
+
28
+ const [currentScope, setCurrentScope] = useState<string>();
29
+ const [currentPackageName, setCurrentPackageName] = useState<string>();
30
+ const [currentNamespace, setCurrentNamespace] = useState<string>();
31
+
32
+ const [currentPermissions, setCurrentPermissions] = useState<Permission[]>([]);
33
+
34
+
35
+ useEffect(() => {
36
+ props.onUpdate(selectedPermissionsIds.length);
37
+ }, [selectedPermissionsIds])
38
+
39
+ useEffect(() => {
40
+ FluxoClientSys.Instance.security.permission.getPermissionScopes()
41
+ .then((res) => {
42
+ setStructuredPermissions(res);
43
+ setStructuredPermissionLoaded(true);
44
+ })
45
+
46
+ if(props.context.type === 'domainRole') {
47
+
48
+ FluxoClientSys.Instance.security.domainRole.getPermissions(props.context.id)
49
+ .then((res) => {
50
+ setDomainRolePermissions(res);
51
+ setDomainRolePermissionLoaded(true);
52
+ });
53
+
54
+ } else if(props.context.type === 'menu') {
55
+
56
+ FluxoClientSys.Instance.configuration.getMenuItemPermissions(props.context.id)
57
+ .then((res) => {
58
+ setDomainRolePermissions(res);
59
+ setDomainRolePermissionLoaded(true);
60
+ });
61
+ } else {
62
+
63
+ FluxoClientSys.Instance.security.routeRule.getPermissions(props.context.id)
64
+ .then((res) => {
65
+ setDomainRolePermissions(res);
66
+ setDomainRolePermissionLoaded(true);
67
+ });
68
+ }
69
+
70
+ }, [])
71
+
72
+ useEffect(() => {
73
+ if(structuredPermissionLoaded && domainRolePermissionLoaded) {
74
+ const initPermissions = [...domainRolePermissions.map((p) => p.id)];
75
+ setSelectedPermissionsIds(initPermissions);
76
+ }
77
+ }, [structuredPermissionLoaded, domainRolePermissionLoaded])
78
+
79
+ const addOrRemovePermission = (permissionId: number) => {
80
+ if(props.context.type === 'domainRole') {
81
+ addOrRemovePermissionForDomainRole(permissionId);
82
+ } else if(props.context.type === 'menu') {
83
+ addOrRemovePermissionForMenu(permissionId);
84
+ } else if(props.context.type === 'route-rule') {
85
+ addOrRemovePermissionForRouteRule(permissionId);
86
+ }
87
+ }
88
+
89
+ const addOrRemovePermissionForRouteRule = (menuItemId: number) => {
90
+ if(selectedPermissionsIds.includes(menuItemId)) {
91
+
92
+ FluxoClientSys.Instance.security.routeRule.removePermission(+props.context.id, menuItemId)
93
+ .then((res) => {
94
+ setSelectedPermissionsIds(selectedPermissionsIds.filter((p) => p !== menuItemId));
95
+ showNotification({
96
+ title: "Permesso rimosso",
97
+ message: "Il permesso è stato rimosso correttamente",
98
+ color: "green",
99
+ });
100
+ })
101
+ .catch((err) => {
102
+ showNotification({
103
+ title: "Errore",
104
+ message: "Si è verificato un errore durante la rimozione del permesso",
105
+ color: "red",
106
+ });
107
+ });
108
+
109
+ } else {
110
+
111
+ FluxoClientSys.Instance.security.routeRule.addPermission(+props.context.id, menuItemId)
112
+ .then((res) => {
113
+ setSelectedPermissionsIds([...selectedPermissionsIds, menuItemId]);
114
+ showNotification({
115
+ title: "Permesso aggiunto",
116
+ message: "Il permesso è stato aggiunto correttamente",
117
+ color: "green",
118
+ });
119
+ })
120
+ .catch((err) => {
121
+ showNotification({
122
+ title: "Errore",
123
+ message: "Si è verificato un errore durante l'aggiunta del permesso",
124
+ color: "red",
125
+ });
126
+ });
127
+ }
128
+ }
129
+ const addOrRemovePermissionForMenu = (menuItemId: number) => {
130
+ if(selectedPermissionsIds.includes(menuItemId)) {
131
+
132
+ FluxoClientSys.Instance.configuration.removeMenuItemPermission(+props.context.id, menuItemId)
133
+ .then((res) => {
134
+ setSelectedPermissionsIds(selectedPermissionsIds.filter((p) => p !== menuItemId));
135
+ showNotification({
136
+ title: "Permesso rimosso",
137
+ message: "Il permesso è stato rimosso correttamente",
138
+ color: "green",
139
+ });
140
+ })
141
+ .catch((err) => {
142
+ showNotification({
143
+ title: "Errore",
144
+ message: "Si è verificato un errore durante la rimozione del permesso",
145
+ color: "red",
146
+ });
147
+ });
148
+
149
+ } else {
150
+
151
+ FluxoClientSys.Instance.configuration.addMenuItemPermission(+props.context.id, menuItemId)
152
+ .then((res) => {
153
+ setSelectedPermissionsIds([...selectedPermissionsIds, menuItemId]);
154
+ showNotification({
155
+ title: "Permesso aggiunto",
156
+ message: "Il permesso è stato aggiunto correttamente",
157
+ color: "green",
158
+ });
159
+ })
160
+ .catch((err) => {
161
+ showNotification({
162
+ title: "Errore",
163
+ message: "Si è verificato un errore durante l'aggiunta del permesso",
164
+ color: "red",
165
+ });
166
+ });
167
+ }
168
+ }
169
+
170
+ const addOrRemovePermissionForDomainRole = (permissionId: number) => {
171
+ if(selectedPermissionsIds.includes(permissionId)) {
172
+
173
+ FluxoClientSys.Instance.security.domainRole.removePermission(+props.context.id, permissionId)
174
+ .then((res) => {
175
+ setSelectedPermissionsIds(selectedPermissionsIds.filter((p) => p !== permissionId));
176
+ showNotification({
177
+ title: "Permesso rimosso",
178
+ message: "Il permesso è stato rimosso correttamente",
179
+ color: "green",
180
+ });
181
+ })
182
+ .catch((err) => {
183
+ showNotification({
184
+ title: "Errore",
185
+ message: "Si è verificato un errore durante la rimozione del permesso",
186
+ color: "red",
187
+ });
188
+ });
189
+
190
+ } else {
191
+
192
+ FluxoClientSys.Instance.security.domainRole.addPermission(+props.context.id, permissionId)
193
+ .then((res) => {
194
+ setSelectedPermissionsIds([...selectedPermissionsIds, permissionId]);
195
+ showNotification({
196
+ title: "Permesso aggiunto",
197
+ message: "Il permesso è stato aggiunto correttamente",
198
+ color: "green",
199
+ });
200
+ })
201
+ .catch((err) => {
202
+ showNotification({
203
+ title: "Errore",
204
+ message: "Si è verificato un errore durante l'aggiunta del permesso",
205
+ color: "red",
206
+ });
207
+ });
208
+ }
209
+ }
210
+
211
+ const getScopes = () => {
212
+ if(structuredPermissions === undefined) return [];
213
+ return [...new Set(structuredPermissions.map(a => a.scope))];
214
+ }
215
+
216
+ const getPackageNames = (scope: string) => {
217
+ if(structuredPermissions === undefined) return [];
218
+ return [...new Set(structuredPermissions.filter(a => a.scope === scope).map(a => a.packageName))];
219
+ }
220
+
221
+ const getNamespaces = (scope: string, packageName: string) => {
222
+ if(structuredPermissions === undefined) return [];
223
+ return [...new Set(structuredPermissions.filter(a => a.scope === scope && a.packageName === packageName).map(a => a.namespace))];
224
+ }
225
+
226
+ const getPermissions = (scope: string, packageName: string, namespace: string) => {
227
+ FluxoClientSys.Instance.security.permission.getPermissionsInScope(scope, packageName, namespace)
228
+ .then((res) => {
229
+ setCurrentPermissions(res);
230
+ })
231
+ .catch((err) => {
232
+ showNotification({
233
+ title: "Errore",
234
+ message: "Si è verificato un errore durante il caricamento dei permessi",
235
+ color: "red",
236
+ })
237
+ })
238
+ }
239
+
240
+ return (
241
+ <>
242
+ {!(structuredPermissionLoaded && domainRolePermissionLoaded) ?
243
+ <Loader /> :
244
+
245
+ <Stack gap={8}>
246
+
247
+ <Grid h={480} m={0} mt={1}>
248
+ <Grid.Col span={4} p={0} style={{border: '1px solid #ececec', borderRight: 'none'}}>
249
+
250
+ <ScrollArea h={430}>
251
+ {getScopes().map((s) => {
252
+ return (
253
+ <NavLink key={s} label={s} leftSection={<Badge size="xs" variant="filled" color="yellow" w={16} h={16} p={0}>{99}</Badge>}>
254
+ <>
255
+ {getPackageNames(s).map((n) => {
256
+ return (
257
+ <NavLink
258
+ key={n}
259
+ label={n}
260
+ leftSection={<Badge size="xs" variant="filled" color="yellow" w={16} h={16} p={0}>{99}</Badge>}>
261
+
262
+ {getNamespaces(s, n).map((ns) => {
263
+ return (
264
+ <NavLink
265
+ key={ns}
266
+ label={ns}
267
+ onClick={() => {
268
+ setCurrentScope(s);
269
+ setCurrentPackageName(n);
270
+ setCurrentNamespace(ns);
271
+ getPermissions(s, n, ns)
272
+ }}
273
+ leftSection={<Badge size="xs" variant="filled" color="yellow" w={16} h={16} p={0}>{99}</Badge>} />
274
+ )
275
+ })}
276
+
277
+ </NavLink>
278
+ )
279
+ })}
280
+ </>
281
+ </NavLink>
282
+ )
283
+ })}
284
+ </ScrollArea>
285
+ </Grid.Col>
286
+ <Grid.Col h={480} span={8} p={0} style={{border: '1px solid #ececec'}}>
287
+
288
+ {(currentPackageName && currentScope && currentNamespace) ?
289
+ <>
290
+ <Group justify={'space-between'} style={{background: '#ececec', marginBottom: 8}}>
291
+ <Text size={'md'} p={8}>{`${currentScope}.${currentPackageName}.${currentNamespace}`}</Text>
292
+ <TextInput pr={8} leftSection={<IconSearch size={16} />} placeholder={'Cerca'} />
293
+ </Group>
294
+ <ScrollArea h={430}>
295
+ <Stack style={{width: '100%'}} p={8}>
296
+ {currentPermissions?.map((p) => {
297
+ return (
298
+ <Checkbox
299
+ key={p.id}
300
+ description={p.identifier}
301
+ label={!p.isCustom ? p.description : <>{p.description}<Badge ml={8}>Personalizzato</Badge></>}
302
+ onChange={() => addOrRemovePermission(p.id)}
303
+ checked={selectedPermissionsIds.includes(p.id)}
304
+ />
305
+ )
306
+ })}
307
+ </Stack>
308
+ </ScrollArea>
309
+ </> :
310
+ <div style={{marginTop: 32}}>
311
+ <NoData message={'Seleziona un package'} />
312
+ </div>
313
+ }
314
+ </Grid.Col>
315
+ </Grid>
316
+ </Stack>
317
+ }
318
+ </>
319
+ )
320
+ }
@@ -0,0 +1,54 @@
1
+ import React from "react";
2
+ import {Button, Group, Stack, Textarea} from "@mantine/core";
3
+ import {FluxoClientSys, InstallPermissionCommand} from "@fluxo-dev/api-client-base";
4
+ import {showNotification} from "@mantine/notifications";
5
+
6
+ export interface UpdatePermissionProps {
7
+ onUpdated: () => void;
8
+ onCanceled: () => void;
9
+ }
10
+
11
+ export function UpdatePermission(props: UpdatePermissionProps) {
12
+
13
+ const [permissionsJson, setPermissionsJson] = React.useState<string>('');
14
+
15
+ const updatePermissions = () => {
16
+ try{
17
+ const data = JSON.parse(permissionsJson) as InstallPermissionCommand;
18
+
19
+ FluxoClientSys.Instance.security.permission.installPermissions(data)
20
+ .then(() => {
21
+
22
+ showNotification({
23
+ title: 'Operazione completata',
24
+ color: 'green',
25
+ message: `I permessi sono stati aggiornati con successo`,
26
+ })
27
+
28
+ props.onUpdated();
29
+ }, (err) => {
30
+ showNotification({
31
+ title: 'Operazione fallita',
32
+ color: 'red',
33
+ message: `Non è stato possibile aggiornare i permessi: ${err.message}`,
34
+ });
35
+ });
36
+ }catch (err) {
37
+ showNotification({
38
+ title: 'Operazione fallita',
39
+ color: 'red',
40
+ message: `Il file non è valido.`,
41
+ });
42
+ }
43
+ }
44
+
45
+ return (
46
+ <Stack>
47
+ <Textarea minRows={20} value={permissionsJson} onChange={(v) => setPermissionsJson(v.target.value)} />
48
+ <Group justify={'right'}>
49
+ <Button onClick={props.onCanceled}>Annulla</Button>
50
+ <Button onClick={updatePermissions} disabled={!permissionsJson}>Aggiorna</Button>
51
+ </Group>
52
+ </Stack>
53
+ )
54
+ }