@fluxo-dev/shell 0.0.24 → 0.0.25

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/index.esm.js CHANGED
@@ -3,10 +3,10 @@ import * as React from 'react';
3
3
  import React__default, { useState, Suspense, forwardRef, createElement as createElement$2, useEffect, createContext, useContext, useLayoutEffect, useRef, useCallback, useMemo, memo, isValidElement, cloneElement, useImperativeHandle, lazy } from 'react';
4
4
  import { useSelector, Provider } from 'react-redux';
5
5
  import { useLocation, Navigate, matchPath, Outlet, useNavigate, Link, Route, useSearchParams, createBrowserRouter, RouterProvider } from 'react-router-dom';
6
- import { FluxoClientSys, AppType, AppState, FluxoStateDispatcher, UserService, AppMenuContextType, ApiKeyService, DomainRoleService } from '@fluxo-dev/api-client-base';
6
+ import { FluxoClientSys, AppType, AppState, FluxoStateDispatcher, UserService, AppMenuContextType, ApiKeyService, DomainRoleService, EmailServerProviderType } from '@fluxo-dev/api-client-base';
7
7
  import { AccessDenied, DataCard, NoData, ConfirmModal, ShellPage, ErrorPage as ErrorPage$1, WaitData, FlxRoutes } from '@fluxo-dev/ui-components';
8
8
  import { ModuleLoader } from '@fluxo-dev/shell-mfe';
9
- import { Text, TextInput, ActionIcon, useMantineTheme, AppShell, Stack, Group, Burger, Badge, Drawer, NavLink, Avatar, Anchor, Tooltip, Divider, Space, useMantineColorScheme, UnstyledButton, Box, ThemeIcon, Collapse, ScrollArea, rem, Loader, Grid, Center, PasswordInput, Button, ColorSwatch, FileButton, NumberInput, Alert, ColorInput, Checkbox, Modal, Switch, Select, Chip, LoadingOverlay, Image as Image$1, Menu, Textarea, Table, MultiSelect, MantineProvider } from '@mantine/core';
9
+ import { Text, TextInput, ActionIcon, useMantineTheme, AppShell, Stack, Group, Burger, Badge, Drawer, NavLink, Popover, Avatar, Center, Divider, Button, Anchor, Tooltip, Space, useMantineColorScheme, UnstyledButton, Box, ThemeIcon, Collapse, ScrollArea, rem, Loader, Grid, PasswordInput, ColorSwatch, FileButton, NumberInput, Alert, ColorInput, Checkbox, Modal, Switch, Select, Chip, LoadingOverlay, Image as Image$1, Menu, Textarea, Table, MultiSelect, Card, MantineProvider } from '@mantine/core';
10
10
  import { openSpotlight, Spotlight } from '@mantine/spotlight';
11
11
  import { useOs, useHotkeys, useIdle } from '@mantine/hooks';
12
12
  import { showNotification, Notifications } from '@mantine/notifications';
@@ -3985,6 +3985,21 @@ var IconLock = createReactComponent("lock", "IconLock", [
3985
3985
  ["path", { d: "M8 11v-4a4 4 0 1 1 8 0v4", key: "svg-2" }]
3986
3986
  ]);
3987
3987
 
3988
+ /**
3989
+ * @tabler/icons-react v2.42.0 - MIT
3990
+ */
3991
+
3992
+ var IconMail = createReactComponent("mail", "IconMail", [
3993
+ [
3994
+ "path",
3995
+ {
3996
+ d: "M3 7a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v10a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2v-10z",
3997
+ key: "svg-0"
3998
+ }
3999
+ ],
4000
+ ["path", { d: "M3 7l9 6l9 -6", key: "svg-1" }]
4001
+ ]);
4002
+
3988
4003
  /**
3989
4004
  * @tabler/icons-react v2.42.0 - MIT
3990
4005
  */
@@ -4412,6 +4427,7 @@ function AppBar(props) {
4412
4427
  },
4413
4428
  children: [jsxs(Group, {
4414
4429
  children: [jsx(Burger, {
4430
+ tabIndex: -1,
4415
4431
  disabled: props.previewMode !== undefined,
4416
4432
  color: '#fff',
4417
4433
  opened: navbarOpened,
@@ -4420,6 +4436,7 @@ function AppBar(props) {
4420
4436
  if (navbarOpened) FluxoStateDispatcher.dispatchCloseNavbar();else FluxoStateDispatcher.dispatchOpenNavbar();
4421
4437
  }
4422
4438
  }), jsx(Link, {
4439
+ tabIndex: -1,
4423
4440
  to: props.previewMode ? '' : '/',
4424
4441
  style: {
4425
4442
  maxHeight: (_d = (_c = props.previewMode) === null || _c === void 0 ? void 0 : _c.logoHeight) !== null && _d !== void 0 ? _d : configuration.logoHeight
@@ -4434,10 +4451,12 @@ function AppBar(props) {
4434
4451
  }), jsxs(Group, {
4435
4452
  wrap: "nowrap",
4436
4453
  children: [developmentMode && jsx(Badge, {
4454
+ tabIndex: -1,
4437
4455
  color: 'red',
4438
4456
  children: "Development mode"
4439
4457
  }), jsx(FrontendSwitch, {}), jitApps && jitApps.length > 0 && jsxs(Fragment, {
4440
4458
  children: [jsx(ActionIcon, {
4459
+ tabIndex: -1,
4441
4460
  variant: 'transparent',
4442
4461
  onClick: () => setJitAppsDrawerOpened(true),
4443
4462
  children: jsx(IconApps, {
@@ -4495,12 +4514,49 @@ function AppBar(props) {
4495
4514
  })]
4496
4515
  }), jsx(SearchBar, {
4497
4516
  disabled: props.previewMode !== undefined
4498
- }), jsxs(Avatar, {
4499
- onClick: () => props.previewMode ? undefined : logout(),
4500
- color: "cyan",
4501
- radius: "xl",
4502
- size: 32,
4503
- children: [userInfo.FirstName.substr(0, 1), userInfo.LastName.substr(0, 1)]
4517
+ }), jsxs(Popover, {
4518
+ disabled: props.previewMode !== undefined,
4519
+ children: [jsx(Popover.Target, {
4520
+ children: jsxs(Avatar, {
4521
+ tabIndex: -1,
4522
+ style: {
4523
+ cursor: 'pointer'
4524
+ },
4525
+ color: "cyan",
4526
+ radius: "xl",
4527
+ size: 32,
4528
+ children: [userInfo.FirstName.substr(0, 1), userInfo.LastName.substr(0, 1)]
4529
+ })
4530
+ }), jsx(Popover.Dropdown, {
4531
+ w: 300,
4532
+ children: jsxs(Stack, {
4533
+ gap: 12,
4534
+ children: [jsx(Center, {
4535
+ children: jsxs(Stack, {
4536
+ justify: 'center',
4537
+ align: 'center',
4538
+ children: [jsxs(Avatar, {
4539
+ color: "cyan",
4540
+ radius: "xl",
4541
+ size: 64,
4542
+ children: [userInfo.FirstName.substr(0, 1), userInfo.LastName.substr(0, 1)]
4543
+ }), jsxs(Text, {
4544
+ children: [userInfo.FirstName, " ", userInfo.LastName]
4545
+ })]
4546
+ })
4547
+ }), jsx(Divider, {}), jsx(Button, {
4548
+ variant: 'subtle',
4549
+ onClick: () => logout(),
4550
+ children: "Esci"
4551
+ }), jsx(Divider, {}), jsx(Center, {
4552
+ children: jsxs(Text, {
4553
+ c: "dimmed",
4554
+ fz: "xs",
4555
+ children: [props.brandName, " \u00A9", new Date().getFullYear()]
4556
+ })
4557
+ })]
4558
+ })
4559
+ })]
4504
4560
  })]
4505
4561
  })]
4506
4562
  })
@@ -4519,6 +4575,9 @@ function FooterBar(props) {
4519
4575
  const {
4520
4576
  userIdle
4521
4577
  } = useAppSelector(state => state.layout);
4578
+ const {
4579
+ hasAdminAccess
4580
+ } = useAppSelector(state => state.layout);
4522
4581
  const idle = useIdle(5000);
4523
4582
  useEffect(() => {
4524
4583
  if (idle) FluxoStateDispatcher.dispatchSetUserIdle();else FluxoStateDispatcher.dispatchUnsetUserIdle();
@@ -4584,18 +4643,20 @@ function FooterBar(props) {
4584
4643
  }), jsx(Space, {
4585
4644
  h: 'md'
4586
4645
  }), jsxs(Group, {
4587
- children: [jsx(Link, {
4588
- to: '/settings',
4589
- style: {
4590
- textDecoration: 'none'
4591
- },
4592
- children: jsx(Text, {
4593
- c: "dimmed",
4594
- fz: "xs",
4595
- children: "Amministrazione"
4596
- })
4597
- }), jsx(Divider, {
4598
- orientation: 'vertical'
4646
+ children: [hasAdminAccess && jsxs(Fragment, {
4647
+ children: [jsx(Link, {
4648
+ to: '/settings',
4649
+ style: {
4650
+ textDecoration: 'none'
4651
+ },
4652
+ children: jsx(Text, {
4653
+ c: "dimmed",
4654
+ fz: "xs",
4655
+ children: "Amministrazione"
4656
+ })
4657
+ }), jsx(Divider, {
4658
+ orientation: 'vertical'
4659
+ })]
4599
4660
  }), jsxs(Text, {
4600
4661
  c: "dimmed",
4601
4662
  fz: "xs",
@@ -4974,7 +5035,9 @@ function AppLayout(props) {
4974
5035
  },
4975
5036
  transitionDuration: 0,
4976
5037
  layout: 'default',
4977
- children: [jsx(AppBar, {}), jsx(Navbar, {}), jsx(AppShell.Main, {
5038
+ children: [jsx(AppBar, {
5039
+ brandName: props.brandName
5040
+ }), jsx(Navbar, {}), jsx(AppShell.Main, {
4978
5041
  children: jsx(Suspense, {
4979
5042
  fallback: jsx(Loader, {}),
4980
5043
  children: jsx(AppContent, {})
@@ -5085,6 +5148,7 @@ function LoginPage(props) {
5085
5148
  size: "sm",
5086
5149
  placeholder: "Email / Nome utente"
5087
5150
  }, form.getInputProps('username'))), jsx(PasswordInput, Object.assign({
5151
+ size: 'sm',
5088
5152
  withAsterisk: true,
5089
5153
  placeholder: "Password"
5090
5154
  }, form.getInputProps('password')))]
@@ -5398,7 +5462,8 @@ function Ui() {
5398
5462
  logo: newLogoBase64,
5399
5463
  logoHeight: newLogoHeight,
5400
5464
  headerColor: newBrandColors[6]
5401
- }
5465
+ },
5466
+ brandName: ''
5402
5467
  })
5403
5468
  })
5404
5469
  })
@@ -28557,14 +28622,123 @@ function DomainRoleForm(props) {
28557
28622
  });
28558
28623
  }
28559
28624
 
28625
+ function FrontendDomainRole(props) {
28626
+ const {
28627
+ frontends
28628
+ } = useAppSelector(state => state.layout);
28629
+ const [frontendDomainRole, setFrontendDomainRole] = useState();
28630
+ useEffect(() => {
28631
+ if (!frontends) return;
28632
+ FluxoClientSys.Instance.configuration.getFrontendByDomainRole(props.domainRoleId).then(a => {
28633
+ setFrontendDomainRole(frontends.map(b => {
28634
+ return {
28635
+ id: b.id,
28636
+ name: b.name,
28637
+ active: a.includes(b.id)
28638
+ };
28639
+ }));
28640
+ }).catch(e => {
28641
+ showNotification({
28642
+ title: 'Errore',
28643
+ message: e.message,
28644
+ color: 'red'
28645
+ });
28646
+ });
28647
+ }, [props.domainRoleId, frontends]);
28648
+ const updateFrontendDomainRole = () => {
28649
+ if (!frontendDomainRole) return;
28650
+ FluxoClientSys.Instance.configuration.updateFrontendDomainRole(props.domainRoleId, frontendDomainRole.filter(a => a.active).map(a => a.id)).then(() => {
28651
+ showNotification({
28652
+ title: 'Salvato',
28653
+ message: 'Ruoli frontend aggiornati',
28654
+ color: 'green'
28655
+ });
28656
+ props.onClosed();
28657
+ }).catch(e => {
28658
+ showNotification({
28659
+ title: 'Errore',
28660
+ message: e.message,
28661
+ color: 'red'
28662
+ });
28663
+ });
28664
+ };
28665
+ const isAllInactive = frontendDomainRole === null || frontendDomainRole === void 0 ? void 0 : frontendDomainRole.every(a => !a.active);
28666
+ return jsxs(Stack, {
28667
+ children: [isAllInactive && jsx(Alert, {
28668
+ color: 'yellow',
28669
+ title: 'Attenzione',
28670
+ children: "Se non selezioni alcuna area, gli utenti legati a questo ruolo non potranno accedere a nessuna area funzionale."
28671
+ }), jsxs(Table, {
28672
+ children: [jsx(Table.Thead, {
28673
+ children: jsxs(Table.Tr, {
28674
+ children: [jsx(Table.Th, {
28675
+ children: "Area"
28676
+ }), jsx(Table.Th, {
28677
+ w: 50,
28678
+ children: "Attivo"
28679
+ })]
28680
+ })
28681
+ }), jsx(Table.Tbody, {
28682
+ children: frontendDomainRole === null || frontendDomainRole === void 0 ? void 0 : frontendDomainRole.map(a => {
28683
+ return jsxs(Table.Tr, {
28684
+ children: [jsx(Table.Td, {
28685
+ children: a.name
28686
+ }), jsx(Table.Td, {
28687
+ w: 50,
28688
+ children: jsx(Switch, {
28689
+ checked: a.active,
28690
+ onChange: e => {
28691
+ setFrontendDomainRole(frontendDomainRole === null || frontendDomainRole === void 0 ? void 0 : frontendDomainRole.map(b => {
28692
+ if (b.id === a.id) b.active = e.target.checked;
28693
+ return b;
28694
+ }));
28695
+ }
28696
+ })
28697
+ })]
28698
+ });
28699
+ })
28700
+ })]
28701
+ }), jsx(Divider, {}), jsx(Group, {
28702
+ justify: 'right',
28703
+ children: jsx(Button, {
28704
+ onClick: updateFrontendDomainRole,
28705
+ children: "Salva"
28706
+ })
28707
+ })]
28708
+ });
28709
+ }
28710
+
28560
28711
  function DomainRoleGrid() {
28561
28712
  const [domainRoles, setDomainRoles] = useState([]);
28562
28713
  const [currentDomainRole, setCurrentDomainRole] = useState();
28563
28714
  const [domainRoleModalOpen, setDomainRoleModalOpen] = useState(false);
28715
+ const [updateDomainFrontendsModal, setUpdateDomainFrontendsModal] = useState(false);
28564
28716
  const [updateDomainRolePermissionsModal, setUpdateDomainRolePermissionsModal] = useState(false);
28717
+ const [allDomainRolesFrontends, setAllDomainRolesFrontends] = useState();
28718
+ const [loading, setLoading] = useState(true);
28565
28719
  useEffect(() => {
28566
- getAllDomainRoles();
28720
+ refreshDomainRoles();
28567
28721
  }, []);
28722
+ const refreshDomainRoles = () => {
28723
+ setLoading(true);
28724
+ Promise.all([getAllDomainRoles(), getAllDomainRoleFrontends()]).finally(() => setLoading(false));
28725
+ };
28726
+ const getAllDomainRoleFrontends = () => {
28727
+ FluxoClientSys.Instance.configuration.getAllDomainRoleFrontends().then(a => {
28728
+ setAllDomainRolesFrontends(a.map(b => {
28729
+ return {
28730
+ domainRoleId: b.domainRoleId,
28731
+ frontends: b.frontends
28732
+ };
28733
+ }));
28734
+ }).catch(e => {
28735
+ showNotification({
28736
+ title: 'Errore',
28737
+ message: e.message,
28738
+ color: 'red'
28739
+ });
28740
+ });
28741
+ };
28568
28742
  const getAllDomainRoles = () => {
28569
28743
  FluxoClientSys.Instance.security.domainRole.find(9999, 0, undefined, "DomainRolePermissions,DomainRolePermissions.Permission").then(res => {
28570
28744
  setDomainRoles(res.results);
@@ -28587,6 +28761,9 @@ function DomainRoleGrid() {
28587
28761
  });
28588
28762
  });
28589
28763
  };
28764
+ const checkIfExistDomainRoleWithoutFrontend = () => {
28765
+ return (allDomainRolesFrontends === null || allDomainRolesFrontends === void 0 ? void 0 : allDomainRolesFrontends.some(a => a.frontends.length === 0)) || false;
28766
+ };
28590
28767
  return jsxs(DataCard, {
28591
28768
  title: 'Ruoli utente',
28592
28769
  actions: [{
@@ -28594,89 +28771,133 @@ function DomainRoleGrid() {
28594
28771
  size: 18
28595
28772
  }),
28596
28773
  label: 'Nuovo ruolo',
28774
+ disabled: loading,
28597
28775
  onClick: () => {
28598
28776
  setCurrentDomainRole(undefined);
28599
28777
  setDomainRoleModalOpen(true);
28600
28778
  }
28601
28779
  }],
28602
- children: [jsxs(Table, {
28603
- highlightOnHover: true,
28604
- children: [jsx(Table.Thead, {
28605
- children: jsxs(Table.Tr, {
28606
- children: [jsx(Table.Th, {
28607
- w: 80,
28608
- children: "Id"
28609
- }), jsx(Table.Th, {
28610
- children: "Identificatore"
28611
- }), jsx(Table.Th, {
28612
- children: "Nome"
28613
- }), jsx(Table.Th, {
28614
- children: "Descrizione"
28615
- }), jsx(Table.Th, {
28616
- w: 100,
28617
- children: "Permessi"
28618
- }), jsx(Table.Th, {
28619
- w: 100
28620
- })]
28621
- })
28622
- }), jsx(Table.Tbody, {
28623
- children: domainRoles.map((element, i) => jsxs(Table.Tr, {
28624
- children: [jsx(Table.Td, {
28625
- w: 80,
28626
- children: element.id
28627
- }), jsx(Table.Td, {
28628
- children: element.identifier
28629
- }), jsx(Table.Td, {
28630
- children: element.name
28631
- }), jsx(Table.Td, {
28632
- children: element.description
28633
- }), jsx(Table.Td, {
28634
- w: 100,
28635
- children: element.permissionCount
28636
- }), jsx(Table.Td, {
28637
- w: 100,
28638
- align: "right",
28639
- children: jsxs(Menu, {
28640
- shadow: "md",
28641
- width: 200,
28642
- children: [jsx(Menu.Target, {
28643
- children: jsx(ActionIcon, {
28644
- children: jsx(IconDotsVertical, {
28645
- size: 18
28780
+ children: [jsxs(Box, {
28781
+ pos: "relative",
28782
+ children: [jsx(LoadingOverlay, {
28783
+ visible: loading,
28784
+ zIndex: 1000,
28785
+ overlayProps: {
28786
+ radius: "sm",
28787
+ blur: 2
28788
+ }
28789
+ }), jsxs(Stack, {
28790
+ children: [checkIfExistDomainRoleWithoutFrontend() && jsx(Alert, {
28791
+ color: 'yellow',
28792
+ title: 'Attenzione',
28793
+ children: "Esistono ruoli utente senza aree funzionali assegnate"
28794
+ }), jsxs(Table, {
28795
+ highlightOnHover: true,
28796
+ children: [jsx(Table.Thead, {
28797
+ children: jsxs(Table.Tr, {
28798
+ children: [jsx(Table.Th, {
28799
+ w: 50,
28800
+ children: "Id"
28801
+ }), jsx(Table.Th, {
28802
+ w: 150,
28803
+ children: "Identificatore"
28804
+ }), jsx(Table.Th, {
28805
+ w: 150,
28806
+ children: "Nome"
28807
+ }), jsx(Table.Th, {
28808
+ children: "Descrizione"
28809
+ }), jsx(Table.Th, {
28810
+ w: 100,
28811
+ children: "Permessi"
28812
+ }), jsx(Table.Th, {
28813
+ w: 100,
28814
+ children: "Aree"
28815
+ }), jsx(Table.Th, {
28816
+ w: 100
28817
+ })]
28818
+ })
28819
+ }), jsx(Table.Tbody, {
28820
+ children: domainRoles.map((element, i) => {
28821
+ var _a;
28822
+ return jsxs(Table.Tr, {
28823
+ children: [jsx(Table.Td, {
28824
+ w: 50,
28825
+ children: element.id
28826
+ }), jsx(Table.Td, {
28827
+ w: 150,
28828
+ children: element.identifier
28829
+ }), jsx(Table.Td, {
28830
+ w: 150,
28831
+ children: element.name
28832
+ }), jsx(Table.Td, {
28833
+ children: element.description
28834
+ }), jsx(Table.Td, {
28835
+ w: 100,
28836
+ children: element.permissionCount
28837
+ }), jsx(Table.Td, {
28838
+ w: 100,
28839
+ children: (_a = allDomainRolesFrontends === null || allDomainRolesFrontends === void 0 ? void 0 : allDomainRolesFrontends.find(a => a.domainRoleId === element.id)) === null || _a === void 0 ? void 0 : _a.frontends.map(f => {
28840
+ return jsx(Badge, {
28841
+ color: 'blue',
28842
+ children: f
28843
+ });
28844
+ })
28845
+ }), jsx(Table.Td, {
28846
+ w: 100,
28847
+ align: "right",
28848
+ children: jsxs(Menu, {
28849
+ shadow: "md",
28850
+ width: 200,
28851
+ children: [jsx(Menu.Target, {
28852
+ children: jsx(ActionIcon, {
28853
+ children: jsx(IconDotsVertical, {
28854
+ size: 18
28855
+ })
28856
+ })
28857
+ }), jsxs(Menu.Dropdown, {
28858
+ children: [jsx(Menu.Item, {
28859
+ leftSection: jsx(IconGridDots, {
28860
+ size: 14
28861
+ }),
28862
+ onClick: () => {
28863
+ setCurrentDomainRole(element);
28864
+ setUpdateDomainFrontendsModal(true);
28865
+ },
28866
+ children: "Aree funzionali"
28867
+ }), jsx(Menu.Item, {
28868
+ leftSection: jsx(IconLock, {
28869
+ size: 14
28870
+ }),
28871
+ onClick: () => {
28872
+ setCurrentDomainRole(element);
28873
+ setUpdateDomainRolePermissionsModal(true);
28874
+ },
28875
+ children: "Permessi"
28876
+ }), jsx(Menu.Item, {
28877
+ onClick: () => {
28878
+ setCurrentDomainRole(element);
28879
+ setDomainRoleModalOpen(true);
28880
+ },
28881
+ leftSection: jsx(IconEdit, {
28882
+ size: 14
28883
+ }),
28884
+ children: "Modifica"
28885
+ }), jsx(Menu.Divider, {}), jsx(Menu.Item, {
28886
+ color: 'red',
28887
+ onClick: () => deleteDomainRole(element.id),
28888
+ leftSection: jsx(IconTrash, {
28889
+ color: 'red',
28890
+ size: 14
28891
+ }),
28892
+ children: "Elimina"
28893
+ })]
28894
+ })]
28646
28895
  })
28647
- })
28648
- }), jsxs(Menu.Dropdown, {
28649
- children: [jsx(Menu.Item, {
28650
- leftSection: jsx(IconLock, {
28651
- size: 14
28652
- }),
28653
- onClick: () => {
28654
- setCurrentDomainRole(element);
28655
- setUpdateDomainRolePermissionsModal(true);
28656
- },
28657
- children: "Permessi"
28658
- }), jsx(Menu.Item, {
28659
- onClick: () => {
28660
- setCurrentDomainRole(element);
28661
- setDomainRoleModalOpen(true);
28662
- },
28663
- leftSection: jsx(IconEdit, {
28664
- size: 14
28665
- }),
28666
- children: "Modifica"
28667
- }), jsx(Menu.Divider, {}), jsx(Menu.Item, {
28668
- color: 'red',
28669
- onClick: () => deleteDomainRole(element.id),
28670
- leftSection: jsx(IconTrash, {
28671
- color: 'red',
28672
- size: 14
28673
- }),
28674
- children: "Elimina"
28675
28896
  })]
28676
- })]
28897
+ }, i);
28677
28898
  })
28678
28899
  })]
28679
- }, i))
28900
+ })]
28680
28901
  })]
28681
28902
  }), jsx(Modal, {
28682
28903
  centered: true,
@@ -28694,23 +28915,40 @@ function DomainRoleGrid() {
28694
28915
  },
28695
28916
  domainRole: currentDomainRole
28696
28917
  })
28697
- }), currentDomainRole && jsx(Modal, {
28698
- size: '60%',
28699
- centered: true,
28700
- opened: updateDomainRolePermissionsModal,
28701
- onClose: () => {
28702
- setUpdateDomainRolePermissionsModal(false);
28703
- setCurrentDomainRole(undefined);
28704
- getAllDomainRoles();
28705
- },
28706
- title: `Gestione permessi ${currentDomainRole.name}`,
28707
- children: jsx(PermissionNavigator, {
28708
- context: {
28709
- type: 'domainRole',
28710
- id: currentDomainRole.id.toString()
28918
+ }), currentDomainRole && jsxs(Fragment, {
28919
+ children: [jsx(Modal, {
28920
+ size: '60%',
28921
+ centered: true,
28922
+ opened: updateDomainRolePermissionsModal,
28923
+ onClose: () => {
28924
+ setUpdateDomainRolePermissionsModal(false);
28925
+ setCurrentDomainRole(undefined);
28926
+ getAllDomainRoles();
28711
28927
  },
28712
- onUpdate: () => {}
28713
- })
28928
+ title: `Gestione permessi ${currentDomainRole.name}`,
28929
+ children: jsx(PermissionNavigator, {
28930
+ context: {
28931
+ type: 'domainRole',
28932
+ id: currentDomainRole.id.toString()
28933
+ },
28934
+ onUpdate: () => {}
28935
+ })
28936
+ }), jsx(Modal, {
28937
+ size: '40%',
28938
+ opened: updateDomainFrontendsModal,
28939
+ onClose: () => {
28940
+ setUpdateDomainFrontendsModal(false);
28941
+ },
28942
+ centered: true,
28943
+ title: `Gestione aree funzionali ${currentDomainRole.name}`,
28944
+ children: jsx(FrontendDomainRole, {
28945
+ domainRoleId: currentDomainRole.id,
28946
+ onClosed: () => {
28947
+ setUpdateDomainFrontendsModal(false);
28948
+ refreshDomainRoles();
28949
+ }
28950
+ })
28951
+ })]
28714
28952
  })]
28715
28953
  });
28716
28954
  }
@@ -29298,6 +29536,286 @@ function RouteRuleGrid() {
29298
29536
  });
29299
29537
  }
29300
29538
 
29539
+ function EmailServerConfiguration() {
29540
+ var _a, _b;
29541
+ const [configExists, setConfigExists] = useState(false);
29542
+ const [loading, setLoading] = useState(true);
29543
+ const [testEmailAddress, setTestEmailAddress] = useState('');
29544
+ const [testEmailSending, setTestEmailSending] = useState(false);
29545
+ const directForm = useForm({
29546
+ initialValues: {
29547
+ type: undefined,
29548
+ directServer: '',
29549
+ directPort: 0,
29550
+ directUser: '',
29551
+ directPassword: '',
29552
+ directUseSsl: true,
29553
+ mailgunDomain: '',
29554
+ mailgunApiKey: '',
29555
+ mailgunBaseUrl: ''
29556
+ },
29557
+ validate: values => {
29558
+ const errors = {};
29559
+ if (!values.fromName) {
29560
+ errors.fromName = 'Il nome del mittente è obbligatorio';
29561
+ }
29562
+ if (!values.fromAddress) {
29563
+ errors.fromAddress = 'L\'indirizzo email del mittente è obbligatorio';
29564
+ }
29565
+ if (values.type === EmailServerProviderType.Direct.toString()) {
29566
+ if (!values.directServer) {
29567
+ errors.directServer = 'Il server è obbligatorio';
29568
+ }
29569
+ if (!values.directPort) {
29570
+ errors.directPort = 'La porta è obbligatoria';
29571
+ }
29572
+ if (!values.directUser) {
29573
+ errors.directUser = 'L\'utente è obbligatorio';
29574
+ }
29575
+ if (!values.directPassword) {
29576
+ errors.directPassword = 'La password è obbligatoria';
29577
+ }
29578
+ } else {
29579
+ if (!values.mailgunDomain) {
29580
+ errors.mailgunDomain = 'Il dominio è obbligatorio';
29581
+ }
29582
+ if (!values.mailgunApiKey) {
29583
+ errors.mailgunApiKey = 'L\'API Key è obbligatoria';
29584
+ }
29585
+ if (!values.mailgunBaseUrl) {
29586
+ errors.mailgunBaseUrl = 'La base URL è obbligatoria';
29587
+ }
29588
+ }
29589
+ return errors;
29590
+ },
29591
+ transformValues: values => {
29592
+ return Object.assign(Object.assign({}, values), {
29593
+ type: +values.type,
29594
+ directPort: values.directPort ? +values.directPort : undefined
29595
+ });
29596
+ }
29597
+ });
29598
+ useEffect(() => {
29599
+ FluxoClientSys.Instance.communication.mailServer.getConfiguration().then(c => {
29600
+ if (c) {
29601
+ setConfigExists(true);
29602
+ directForm.setFieldValue('fromName', c.fromName);
29603
+ directForm.setFieldValue('fromAddress', c.fromAddress);
29604
+ directForm.setFieldValue('type', c.type.toString());
29605
+ directForm.setFieldValue('directServer', c.directServer);
29606
+ directForm.setFieldValue('directPort', c.directPort);
29607
+ directForm.setFieldValue('directUser', c.directUser);
29608
+ directForm.setFieldValue('directPassword', c.directPassword);
29609
+ directForm.setFieldValue('directUseSsl', c.directUseSsl);
29610
+ directForm.setFieldValue('mailgunDomain', c.mailgunDomain);
29611
+ directForm.setFieldValue('mailgunApiKey', c.mailgunApiKey);
29612
+ directForm.setFieldValue('mailgunBaseUrl', c.mailgunBaseUrl);
29613
+ } else {
29614
+ setConfigExists(false);
29615
+ }
29616
+ }).catch(() => {
29617
+ setConfigExists(false);
29618
+ }).finally(() => {
29619
+ setLoading(false);
29620
+ });
29621
+ }, []);
29622
+ const saveConfig = values => {
29623
+ setLoading(true);
29624
+ FluxoClientSys.Instance.communication.mailServer.saveConfiguration({
29625
+ fromAddress: values.fromAddress,
29626
+ fromName: values.fromName,
29627
+ directServer: values.directServer,
29628
+ directPort: values.directPort,
29629
+ directUser: values.directUser,
29630
+ directPassword: values.directPassword,
29631
+ directUseSsl: values.directUseSsl,
29632
+ mailgunDomain: values.mailgunDomain,
29633
+ mailgunApiKey: values.mailgunApiKey,
29634
+ mailgunBaseUrl: values.mailgunBaseUrl,
29635
+ type: +values.type
29636
+ }).then(() => {
29637
+ showNotification({
29638
+ title: 'Configurazione salvata',
29639
+ message: 'La configurazione è stata salvata con successo',
29640
+ color: 'green'
29641
+ });
29642
+ }).catch(() => {
29643
+ showNotification({
29644
+ title: 'Errore',
29645
+ message: 'Si è verificato un errore durante il salvataggio della configurazione',
29646
+ color: 'red'
29647
+ });
29648
+ }).finally(() => {
29649
+ setLoading(false);
29650
+ });
29651
+ };
29652
+ const testSendEmail = () => {
29653
+ setTestEmailSending(true);
29654
+ FluxoClientSys.Instance.communication.mailServer.sendTestEmail({
29655
+ emailAddress: testEmailAddress
29656
+ }).then(() => {
29657
+ showNotification({
29658
+ title: 'Email inviata',
29659
+ message: 'L\'email è stata inviata con successo',
29660
+ color: 'green'
29661
+ });
29662
+ }).catch(() => {
29663
+ showNotification({
29664
+ title: 'Errore',
29665
+ message: 'Si è verificato un errore durante l\'invio dell\'email',
29666
+ color: 'red'
29667
+ });
29668
+ }).finally(() => {
29669
+ setTestEmailSending(false);
29670
+ });
29671
+ };
29672
+ const isTestEmailAddressValid = useCallback(() => {
29673
+ if (!testEmailAddress) return false;
29674
+ const re = /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/g;
29675
+ return re.test(testEmailAddress);
29676
+ }, [testEmailAddress]);
29677
+ return jsxs(Box, {
29678
+ pos: "relative",
29679
+ children: [jsx(LoadingOverlay, {
29680
+ visible: loading,
29681
+ zIndex: 1000,
29682
+ overlayProps: {
29683
+ radius: "sm",
29684
+ blur: 2
29685
+ }
29686
+ }), jsxs(Stack, {
29687
+ children: [jsx(DataCard, {
29688
+ title: "Configurazione server email",
29689
+ children: jsxs(Stack, {
29690
+ children: [!configExists && jsx(Alert, {
29691
+ color: "yellow",
29692
+ title: "Configurazione non trovata",
29693
+ children: "Non \u00E8 stata trovata alcuna configurazione per il server email. Si prega di configurare il server email prima di procedere."
29694
+ }), !directForm.values['type'] && jsxs(Fragment, {
29695
+ children: [jsx(Text, {
29696
+ size: 'lg',
29697
+ children: "Scegli il provider:"
29698
+ }), jsxs(Group, {
29699
+ children: [jsx(Button, {
29700
+ onClick: () => directForm.setFieldValue('type', EmailServerProviderType.Direct.toString()),
29701
+ children: "Server SMTP"
29702
+ }), jsx(Button, {
29703
+ onClick: () => directForm.setFieldValue('type', EmailServerProviderType.Mailgun.toString()),
29704
+ children: "Mailgun"
29705
+ })]
29706
+ })]
29707
+ }), jsxs("form", {
29708
+ id: 'providerForm',
29709
+ autoComplete: 'off',
29710
+ onSubmit: directForm.onSubmit((values, event) => {
29711
+ if (directForm.isValid()) saveConfig(values);
29712
+ }),
29713
+ children: [((_a = directForm.values['type']) === null || _a === void 0 ? void 0 : _a.toString()) === '0' && jsxs(Stack, {
29714
+ children: [jsx(Select, Object.assign({
29715
+ data: [{
29716
+ label: 'Server SMTP',
29717
+ value: '0'
29718
+ }, {
29719
+ label: 'Mailgun',
29720
+ value: '1'
29721
+ }],
29722
+ label: "Provider"
29723
+ }, directForm.getInputProps('type'), {
29724
+ placeholder: "Seleziona provider"
29725
+ })), jsx(TextInput, Object.assign({
29726
+ label: "Email Mittente",
29727
+ placeholder: "jhon@example.com"
29728
+ }, directForm.getInputProps('fromAddress'))), jsx(TextInput, Object.assign({
29729
+ label: "Nome Mittente",
29730
+ placeholder: "Jhon Red"
29731
+ }, directForm.getInputProps('fromName'))), jsx(TextInput, Object.assign({
29732
+ label: "Server SMTP",
29733
+ placeholder: "smtp.example.com"
29734
+ }, directForm.getInputProps('directServer'))), jsx(NumberInput, Object.assign({
29735
+ label: "Porta",
29736
+ placeholder: "587"
29737
+ }, directForm.getInputProps('directPort'))), jsx(TextInput, Object.assign({
29738
+ label: "Username",
29739
+ placeholder: "user@example.com"
29740
+ }, directForm.getInputProps('directUser'))), jsx(TextInput, Object.assign({
29741
+ label: "Password",
29742
+ type: "password"
29743
+ }, directForm.getInputProps('directPassword'))), jsx(Switch, Object.assign({
29744
+ label: 'SSL/TLS'
29745
+ }, directForm.getInputProps('directUseSsl', {
29746
+ type: 'checkbox'
29747
+ })))]
29748
+ }), ((_b = directForm.values['type']) === null || _b === void 0 ? void 0 : _b.toString()) === '1' && jsxs(Stack, {
29749
+ children: [jsx(Select, Object.assign({
29750
+ data: [{
29751
+ label: 'Server SMTP',
29752
+ value: '0'
29753
+ }, {
29754
+ label: 'Mailgun',
29755
+ value: '1'
29756
+ }],
29757
+ label: "Provider"
29758
+ }, directForm.getInputProps('type'), {
29759
+ placeholder: "Seleziona provider",
29760
+ autoComplete: 'off'
29761
+ })), jsx(TextInput, Object.assign({
29762
+ label: "Email Mittente",
29763
+ placeholder: "jhon@example.com"
29764
+ }, directForm.getInputProps('fromAddress'))), jsx(TextInput, Object.assign({
29765
+ label: "Nome Mittente",
29766
+ placeholder: "Jhon Red"
29767
+ }, directForm.getInputProps('fromName'))), jsx(TextInput, Object.assign({
29768
+ label: "Base URL",
29769
+ placeholder: 'Es: https://api.eu.mailgun.net/v3'
29770
+ }, directForm.getInputProps('mailgunBaseUrl'))), jsx(TextInput, Object.assign({
29771
+ label: "Dominio",
29772
+ placeholder: 'Es: mg.example.com'
29773
+ }, directForm.getInputProps('mailgunDomain'))), jsx(PasswordInput, Object.assign({
29774
+ autoComplete: 'off',
29775
+ label: "API Key"
29776
+ }, directForm.getInputProps('mailgunApiKey')))]
29777
+ }), directForm.values['type'] !== undefined && jsxs(Stack, {
29778
+ children: [jsx(Divider, {
29779
+ mt: 16
29780
+ }), jsx(Group, {
29781
+ justify: 'right',
29782
+ align: 'end',
29783
+ children: jsx(Button, {
29784
+ type: 'submit',
29785
+ children: "Salva"
29786
+ })
29787
+ })]
29788
+ })]
29789
+ })]
29790
+ })
29791
+ }), jsx(DataCard, {
29792
+ title: "Test invio email",
29793
+ children: jsxs(Stack, {
29794
+ children: [jsx(Alert, {
29795
+ color: "yellow",
29796
+ title: "Attenzione",
29797
+ children: "Questa funzione invier\u00E0 una email di test al destinatario specificato con l'ultima configurazione salvata"
29798
+ }), jsx(TextInput, {
29799
+ label: "Email destinatario",
29800
+ value: testEmailAddress,
29801
+ onChange: v => setTestEmailAddress(v.target.value),
29802
+ placeholder: "Es: jhon@example.com"
29803
+ }), jsx(Group, {
29804
+ justify: 'right',
29805
+ align: 'end',
29806
+ children: jsx(Button, {
29807
+ loading: testEmailSending,
29808
+ disabled: !isTestEmailAddressValid(),
29809
+ onClick: testSendEmail,
29810
+ children: "Invia"
29811
+ })
29812
+ })]
29813
+ })
29814
+ })]
29815
+ })]
29816
+ });
29817
+ }
29818
+
29301
29819
  function Settings(props) {
29302
29820
  const [currentTab, setCurrentTab] = useState('ui');
29303
29821
  const [apiRestDoc, setApiRestDoc] = useState();
@@ -29408,6 +29926,23 @@ function Settings(props) {
29408
29926
  }),
29409
29927
  description: 'Gestisci le regole sulle rotte'
29410
29928
  }]
29929
+ }, {
29930
+ name: 'Comunicazioni',
29931
+ items: [{
29932
+ key: 'email-configuration',
29933
+ title: jsx(Text, {
29934
+ children: "Configurazione e-mail"
29935
+ }),
29936
+ onClick: () => {
29937
+ window.location.hash = 'email-configuration';
29938
+ setCurrentTab('email-configuration');
29939
+ },
29940
+ disabled: false,
29941
+ icon: jsx(IconMail, {
29942
+ size: 18
29943
+ }),
29944
+ description: 'Configura il server di posta'
29945
+ }]
29411
29946
  }, {
29412
29947
  name: 'Integrazione',
29413
29948
  items: [{
@@ -29544,6 +30079,8 @@ function Settings(props) {
29544
30079
  return jsx(RouteRuleGrid, {});
29545
30080
  case 'print-server':
29546
30081
  return jsx(PrintServerList, {});
30082
+ case 'email-configuration':
30083
+ return jsx(EmailServerConfiguration, {});
29547
30084
  case 'apidoc':
29548
30085
  return apiRestDoc ? jsx(DataCard, {
29549
30086
  title: 'Documentazione API REST',
@@ -29580,7 +30117,7 @@ function MainRoutes(props) {
29580
30117
  default: KorebiIde
29581
30118
  })));
29582
30119
  return jsxs(FlxRoutes, {
29583
- children: [props.isAdminFrontend && jsxs(Fragment, {
30120
+ children: [props.isAdminFrontend && props.hasAdminAccess && jsxs(Fragment, {
29584
30121
  children: [jsx(Route, {
29585
30122
  path: 'settings',
29586
30123
  element: jsx(Settings, {
@@ -30143,6 +30680,47 @@ function FluxoShell(props) {
30143
30680
  checkFrontendSetup(props.frontends);
30144
30681
  // Get the initial configuration
30145
30682
  FluxoClientSys.Instance.configuration.getInitialConfiguration().then(res => {
30683
+ // If the user allowedFrontends is empty and user is logged, return a router with an error page (unauthorized)
30684
+ if (res.frontends.length === 0 && res.isUserLogged) {
30685
+ setRouter(createBrowserRouter([{
30686
+ path: '*',
30687
+ element: jsx(Center, {
30688
+ w: '100%',
30689
+ children: jsx(Card, {
30690
+ maw: 450,
30691
+ w: 450,
30692
+ withBorder: true,
30693
+ mt: 64,
30694
+ children: jsxs(Stack, {
30695
+ justify: 'center',
30696
+ align: 'center',
30697
+ children: [jsx(Text, {
30698
+ size: "xl",
30699
+ color: 'red',
30700
+ children: "Autorizzazioni mancanti"
30701
+ }), jsx(Text, {
30702
+ size: "sm",
30703
+ children: "Contatta l'amministratore di sistema"
30704
+ }), jsx(Divider, {
30705
+ w: '100%'
30706
+ }), jsx(Center, {
30707
+ children: jsx(Button, {
30708
+ onClick: () => {
30709
+ FluxoClientSys.Instance.auth.logout();
30710
+ window.location.reload();
30711
+ },
30712
+ children: "Esci"
30713
+ })
30714
+ })]
30715
+ })
30716
+ })
30717
+ })
30718
+ }], {
30719
+ basename: '/'
30720
+ }));
30721
+ setBrandColors(res.ui.colors);
30722
+ return;
30723
+ }
30146
30724
  // Get the frontend to render
30147
30725
  let frontendByRender = props.frontends.find(f => f.id === res.currentFrontend);
30148
30726
  // If no frontend to render is found, get the default one
@@ -30173,6 +30751,7 @@ function FluxoShell(props) {
30173
30751
  })));
30174
30752
  FluxoStateDispatcher.dispatchSetCurrentFrontend(res.currentFrontend);
30175
30753
  FluxoStateDispatcher.dispatchAllowedFrontends(res.frontends);
30754
+ FluxoStateDispatcher.dispatchHasAdminAccess(res.hasAdminAccess);
30176
30755
  const rObjs = [generateAuthRoutes(), {
30177
30756
  path: 'frontend-switcher',
30178
30757
  element: jsx(ProtectedRoute, {
@@ -30189,6 +30768,7 @@ function FluxoShell(props) {
30189
30768
  }, {
30190
30769
  path: '/*',
30191
30770
  element: jsx(MainRoutes, {
30771
+ hasAdminAccess: res.hasAdminAccess,
30192
30772
  isAdminFrontend: flxFrontend.id === 'admin',
30193
30773
  pluginEndpoint: props.pluginEndpoint,
30194
30774
  frontends: props.frontends
@@ -30268,6 +30848,12 @@ function FluxoShell(props) {
30268
30848
  fontSize: '10.5pt'
30269
30849
  }
30270
30850
  },
30851
+ PasswordInput: {
30852
+ defaultProps: {
30853
+ size: 'xs',
30854
+ fontSize: '10.5pt'
30855
+ }
30856
+ },
30271
30857
  Textarea: {
30272
30858
  defaultProps: {
30273
30859
  size: 'xs',
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@fluxo-dev/shell",
3
- "version": "0.0.24",
3
+ "version": "0.0.25",
4
4
  "peerDependencies": {
5
- "@fluxo-dev/shell-hub": "0.0.24",
6
- "@fluxo-dev/shell-korebi": "0.0.24",
7
- "@fluxo-dev/shell-mfe": "0.0.24",
8
- "@fluxo-dev/shell-printing": "0.0.24",
9
- "@fluxo-dev/shell-reporting": "0.0.24",
10
- "@fluxo-dev/shell-workflow": "0.0.24"
5
+ "@fluxo-dev/shell-hub": "0.0.25",
6
+ "@fluxo-dev/shell-korebi": "0.0.25",
7
+ "@fluxo-dev/shell-mfe": "0.0.25",
8
+ "@fluxo-dev/shell-printing": "0.0.25",
9
+ "@fluxo-dev/shell-reporting": "0.0.25",
10
+ "@fluxo-dev/shell-workflow": "0.0.25"
11
11
  },
12
12
  "module": "./index.esm.js",
13
13
  "type": "module",
@@ -3,5 +3,6 @@ export interface MainRoutesProps {
3
3
  pluginEndpoint: string;
4
4
  frontends: ShellFrontend[];
5
5
  isAdminFrontend: boolean;
6
+ hasAdminAccess: boolean;
6
7
  }
7
8
  export declare function MainRoutes(props: MainRoutesProps): import("react/jsx-runtime").JSX.Element;
@@ -4,6 +4,7 @@ export interface AppBarProps {
4
4
  logoHeight: number;
5
5
  headerColor: string;
6
6
  };
7
+ brandName: string;
7
8
  }
8
9
  declare function AppBar(props: AppBarProps): import("react/jsx-runtime").JSX.Element;
9
10
  export default AppBar;
@@ -0,0 +1 @@
1
+ export declare function EmailServerConfiguration(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,5 @@
1
+ export interface FrontendDomainRoleProps {
2
+ domainRoleId: number;
3
+ onClosed: () => void;
4
+ }
5
+ export declare function FrontendDomainRole(props: FrontendDomainRoleProps): import("react/jsx-runtime").JSX.Element;