@fluxo-dev/shell 25.3.9 โ†’ 25.4.0

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
@@ -2,8 +2,8 @@ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
3
  import React__default, { useState, useEffect, Suspense, useRef, useCallback as useCallback$1, forwardRef, createElement as createElement$2, useContext, useMemo as useMemo$1, createContext, useLayoutEffect, memo, isValidElement, cloneElement, useImperativeHandle, lazy } from 'react';
4
4
  import { useSelector, connect, Provider } from 'react-redux';
5
- import { Navigate, Outlet, useNavigate, useLocation, Link, useOutlet, matchPath, Route, useSearchParams, createBrowserRouter, RouterProvider } from 'react-router-dom';
6
- import { useFlxNavigate, DataCard, SessionIdContext, TabActiveContext, IconFactory, ShellConfigProvider, useShellLayout, ShellPage, NoData, ConfirmModal, CronGenerator, Datagrid, RichTextEditorInput, ErrorPage as ErrorPage$1, FlxRoutes, WaitData } from '@fluxo-dev/ui-components';
5
+ import { Navigate, Outlet, useNavigate, useLocation, Link, useOutlet, matchPath, useSearchParams, createBrowserRouter, RouterProvider } from 'react-router-dom';
6
+ import { useFlxNavigate, DataCard, SessionIdContext, TabActiveContext, IconFactory, ShellConfigProvider, useShellLayout, ShellPage, NoData, ConfirmModal, CronGenerator, Datagrid, RichTextEditorInput, ErrorPage as ErrorPage$1, WaitData } from '@fluxo-dev/ui-components';
7
7
  import { ModuleLoader } from '@fluxo-dev/shell-mfe';
8
8
  import { Text, Box, TextInput, Popover, Stack, UnstyledButton, Group, Highlight, ActionIcon, useMantineTheme, AppShell, Burger, Badge, Drawer, NavLink, Avatar, Center, Button, Divider, Modal, FocusTrap, Tabs, ScrollArea, ThemeIcon, Tooltip, Anchor, Space, useMantineColorScheme, Collapse, Menu, rem, Loader, Overlay, Grid, PasswordInput, Paper, Alert, Title, Card, ColorSwatch, FileButton, NumberInput, ColorInput, Checkbox, Switch, Select, Radio, LoadingOverlay, Chip, Image as Image$1, Table, SegmentedControl, MultiSelect, Code, Portal, useDirection, px as px$1, parseThemeColor, rgba as rgba$1, Breadcrumbs, TagsInput, Textarea, Accordion, useCombobox, Combobox, InputBase, Slider, MantineProvider } from '@mantine/core';
9
9
  import { MinimalStateViewer, RavifyProvider, JobsViewer } from '@fluxo-dev/shell-ravify';
@@ -13847,6 +13847,7 @@ function AppContent(props) {
13847
13847
  children: [props.withMultipleSessions ? jsxs(Tabs, {
13848
13848
  variant: 'none',
13849
13849
  value: currentSessionId,
13850
+ keepMounted: true,
13850
13851
  onChange: value => value && sessionContext.setCurrentSession(value),
13851
13852
  children: [jsx(Box, {
13852
13853
  style: {
@@ -60931,10 +60932,14 @@ function ConnectedUsers() {
60931
60932
  // Confirm modal state for force logout
60932
60933
  const [showForceLogoutModal, setShowForceLogoutModal] = useState(false);
60933
60934
  const [deviceToDisconnect, setDeviceToDisconnect] = useState(null);
60935
+ // Debounce timer per evitare troppi refresh consecutivi
60936
+ const [updateDebounceTimer, setUpdateDebounceTimer] = useState(null);
60934
60937
  // Memoizza la funzione di caricamento per poterla usare nell'event handler
60935
- const loadConnectedUsers = useCallback$1(() => __awaiter(this, void 0, void 0, function* () {
60938
+ const loadConnectedUsers = useCallback$1((...args_1) => __awaiter(this, [...args_1], void 0, function* (showLoader = true) {
60936
60939
  try {
60937
- setLoading(true);
60940
+ if (showLoader) {
60941
+ setLoading(true);
60942
+ }
60938
60943
  const users = yield FluxoClientSys.Instance.sessionHub.getConnectedUsers();
60939
60944
  setConnectedUsers(users);
60940
60945
  // Ottieni il connection ID corrente
@@ -60955,7 +60960,9 @@ function ConnectedUsers() {
60955
60960
  color: 'red'
60956
60961
  });
60957
60962
  } finally {
60958
- setLoading(false);
60963
+ if (showLoader) {
60964
+ setLoading(false);
60965
+ }
60959
60966
  }
60960
60967
  }), []);
60961
60968
  // Carica gli utenti connessi all'avvio
@@ -60985,8 +60992,17 @@ function ConnectedUsers() {
60985
60992
  // Ascolta l'evento OnConnectedUsersChanged e ricarica automaticamente la lista
60986
60993
  useEffect(() => {
60987
60994
  const handleConnectedUsersChanged = () => {
60988
- console.info('๐Ÿ‘ฅ Connected users changed, reloading list...');
60989
- loadConnectedUsers();
60995
+ console.info('๐Ÿ‘ฅ Connected users changed, scheduling reload...');
60996
+ // Cancella il timer precedente se esiste
60997
+ if (updateDebounceTimer) {
60998
+ clearTimeout(updateDebounceTimer);
60999
+ }
61000
+ // Imposta un nuovo timer con debounce di 500ms
61001
+ const timer = setTimeout(() => {
61002
+ console.info('๐Ÿ‘ฅ Executing debounced reload...');
61003
+ loadConnectedUsers(false); // false = non mostrare il loader
61004
+ }, 500);
61005
+ setUpdateDebounceTimer(timer);
60990
61006
  };
60991
61007
  // Registra l'event handler
60992
61008
  FluxoClientSys.Instance.sessionHub.on('OnConnectedUsersChanged', handleConnectedUsersChanged);
@@ -60995,8 +61011,12 @@ function ConnectedUsers() {
60995
61011
  return () => {
60996
61012
  FluxoClientSys.Instance.sessionHub.off('OnConnectedUsersChanged', handleConnectedUsersChanged);
60997
61013
  console.info('๐Ÿงน Stopped listening for OnConnectedUsersChanged events');
61014
+ // Pulisci il timer se esiste
61015
+ if (updateDebounceTimer) {
61016
+ clearTimeout(updateDebounceTimer);
61017
+ }
60998
61018
  };
60999
- }, [loadConnectedUsers]);
61019
+ }, [loadConnectedUsers, updateDebounceTimer]);
61000
61020
  const toggleUserExpand = userId => {
61001
61021
  const newExpanded = new Set(expandedUsers);
61002
61022
  if (newExpanded.has(userId)) {
@@ -61110,7 +61130,6 @@ function ConnectedUsers() {
61110
61130
  children: [jsx(Card, {
61111
61131
  withBorder: true,
61112
61132
  padding: "lg",
61113
- radius: "md",
61114
61133
  children: jsxs(Stack, {
61115
61134
  gap: "xs",
61116
61135
  children: [jsxs(Group, {
@@ -61145,7 +61164,6 @@ function ConnectedUsers() {
61145
61164
  }), jsx(Card, {
61146
61165
  withBorder: true,
61147
61166
  padding: "lg",
61148
- radius: "md",
61149
61167
  children: jsxs(Stack, {
61150
61168
  gap: "xs",
61151
61169
  children: [jsxs(Group, {
@@ -61180,7 +61198,6 @@ function ConnectedUsers() {
61180
61198
  }), jsx(Card, {
61181
61199
  withBorder: true,
61182
61200
  padding: "lg",
61183
- radius: "md",
61184
61201
  children: jsxs(Stack, {
61185
61202
  gap: "xs",
61186
61203
  children: [jsxs(Group, {
@@ -65042,7 +65059,7 @@ function McpServerManagement() {
65042
65059
  function Settings(props) {
65043
65060
  const [currentTab, setCurrentTab] = useState('ui');
65044
65061
  const [apiRestDoc, setApiRestDoc] = useState();
65045
- const navigate = useNavigate();
65062
+ const navigate = useFlxNavigate();
65046
65063
  const {
65047
65064
  hasAdminAccess,
65048
65065
  hasDeveloperAccess,
@@ -65054,6 +65071,9 @@ function Settings(props) {
65054
65071
  } = useAppSelector(state => state.layout.systemSettings);
65055
65072
  const [showBiEditorModal, setShowBiEditorModal] = useState(false);
65056
65073
  const isClosingRef = useRef(false);
65074
+ const {
65075
+ headerHeight
65076
+ } = useShellLayout();
65057
65077
  //useDocumentTitle('Amministrazione');
65058
65078
  // Intercetta il refresh e il cambio tab del browser
65059
65079
  useEffect(() => {
@@ -65277,7 +65297,7 @@ function Settings(props) {
65277
65297
  items: [{
65278
65298
  key: 'bi',
65279
65299
  title: jsx(Text, {
65280
- children: "BI Editor"
65300
+ children: "BI Designer"
65281
65301
  }),
65282
65302
  onClick: () => {
65283
65303
  //window.location.hash = 'bi';
@@ -65465,7 +65485,11 @@ function Settings(props) {
65465
65485
  children: "KOREBI"
65466
65486
  })]
65467
65487
  }),
65468
- onClick: () => navigate('/korebi-ide'),
65488
+ onClick: () => navigate('/korebi-ide', {
65489
+ state: {
65490
+ title: "Korebi IDE"
65491
+ }
65492
+ }),
65469
65493
  disabled: false,
65470
65494
  icon: jsx(IconCode, {
65471
65495
  size: 18
@@ -65540,32 +65564,27 @@ function Settings(props) {
65540
65564
  children: jsx(EmailTemplate, {})
65541
65565
  }) : jsx(ErrorPage$1, {});
65542
65566
  case 'apidoc':
65543
- return hasAdminAccess || hasDeveloperAccess ? jsx(ScrollArea, {
65544
- style: {
65545
- height: 'calc(100vh - 132px)'
65546
- },
65547
- children: jsx(ApiReferenceReact, {
65548
- configuration: {
65549
- darkMode: false,
65550
- customCss: '.darklight-reference {display: none !important} .references-navigation-list { height: calc(100vh - 132px) !important; }',
65551
- hideDarkModeToggle: true,
65552
- forceDarkModeState: 'light',
65553
- authentication: {
65554
- http: {
65555
- basic: {
65556
- username: "",
65557
- password: ""
65558
- },
65559
- bearer: {
65560
- token: localStorage.getItem('access-token')
65561
- }
65567
+ return hasAdminAccess || hasDeveloperAccess ? jsx(ApiReferenceReact, {
65568
+ configuration: {
65569
+ showDeveloperTools: 'never',
65570
+ darkMode: false,
65571
+ customCss: `.darklight-reference {display: none !important} aside {height: calc(100vh - 178px) !important; top: ${headerHeight + 40}px !important; } .open-api-client-button {display: none !important}`,
65572
+ hideDarkModeToggle: true,
65573
+ forceDarkModeState: 'light',
65574
+ authentication: {
65575
+ http: {
65576
+ bearer: {
65577
+ token: localStorage.getItem('access-token')
65562
65578
  }
65563
- },
65564
- spec: {
65565
- url: FluxoClientSys.Instance.clientConfig.fluxoInstanceUrl.replace('/api', '') + '/openapi/v1.json'
65566
65579
  }
65567
- }
65568
- })
65580
+ },
65581
+ sources: [{
65582
+ url: FluxoClientSys.Instance.clientConfig.fluxoInstanceUrl.replace('/api', '') + '/openapi/v1.json',
65583
+ agent: {
65584
+ disabled: true
65585
+ }
65586
+ }]
65587
+ }
65569
65588
  }) : jsx(ErrorPage$1, {});
65570
65589
  /*return apiRestDoc ? (
65571
65590
  <DataCard title={'Documentazione API REST'}>
@@ -65672,42 +65691,47 @@ function Settings(props) {
65672
65691
  });
65673
65692
  }
65674
65693
 
65675
- function MainRoutes(props) {
65676
- const {
65677
- hasAdminAccess,
65678
- hasDeveloperAccess,
65679
- hasDataAnalystAccess
65680
- } = useSelector(state => state.layout);
65681
- const KIde = /*#__PURE__*/lazy(() => import('@fluxo-dev/shell-korebi').then(({
65682
- KorebiIde
65683
- }) => ({
65684
- default: KorebiIde
65685
- })));
65686
- return jsxs(FlxRoutes, {
65687
- children: [props.isAdminFrontend && (hasDeveloperAccess || hasDataAnalystAccess || hasAdminAccess) && jsxs(Fragment, {
65688
- children: [jsx(Route, {
65689
- path: 'settings',
65690
- element: jsx(Settings, {
65691
- slots: props.fluxoShellProps.slots,
65692
- pluginEndpoint: props.pluginEndpoint,
65693
- frontends: props.frontends
65694
- })
65695
- }), jsx(Route, {
65696
- path: 'korebi-ide',
65697
- element: jsx(Suspense, {
65698
- children: jsx(KIde, {})
65699
- })
65700
- }), jsx(Route, {
65701
- path: 'ravify/jobs-viewer',
65702
- element: jsx(JobsViewer, {})
65703
- })]
65704
- }), props.fluxoShellProps.ui.security.showMyProfile && jsx(Route, {
65694
+ const KIde = /*#__PURE__*/lazy(() => import('@fluxo-dev/shell-korebi').then(({
65695
+ KorebiIde
65696
+ }) => ({
65697
+ default: KorebiIde
65698
+ })));
65699
+ /**
65700
+ * Genera le routes principali come RouteObject[] invece di componente wrapper
65701
+ * Questo evita il remount dei componenti quando si switcha tra sessioni
65702
+ */
65703
+ function generateMainRoutes(props, hasAdminAccess, hasDeveloperAccess, hasDataAnalystAccess) {
65704
+ const routes = [];
65705
+ if (props.isAdminFrontend && (hasDeveloperAccess || hasDataAnalystAccess || hasAdminAccess)) {
65706
+ routes.push({
65707
+ path: 'settings',
65708
+ element: jsx(Settings, {
65709
+ slots: props.fluxoShellProps.slots,
65710
+ pluginEndpoint: props.pluginEndpoint,
65711
+ frontends: props.frontends
65712
+ })
65713
+ }, {
65714
+ path: 'korebi-ide',
65715
+ element: jsx(Suspense, {
65716
+ fallback: jsx("div", {
65717
+ children: "Loading..."
65718
+ }),
65719
+ children: jsx(KIde, {})
65720
+ })
65721
+ }, {
65722
+ path: 'ravify/jobs-viewer',
65723
+ element: jsx(JobsViewer, {})
65724
+ });
65725
+ }
65726
+ if (props.fluxoShellProps.ui.security.showMyProfile) {
65727
+ routes.push({
65705
65728
  path: 'me',
65706
65729
  element: jsx(UserProfile, {
65707
65730
  slots: props.fluxoShellProps.slots
65708
65731
  })
65709
- })]
65710
- });
65732
+ });
65733
+ }
65734
+ return routes;
65711
65735
  }
65712
65736
 
65713
65737
  function ForgotPassword(props) {
@@ -78163,15 +78187,14 @@ function FluxoShell(props) {
78163
78187
  children: [{
78164
78188
  index: true,
78165
78189
  element: flxFrontend.dashboardComponent
78166
- }, {
78167
- path: '/*',
78168
- element: jsx(MainRoutes, {
78169
- fluxoShellProps: props,
78170
- isAdminFrontend: flxFrontend.id === 'admin',
78171
- pluginEndpoint: props.pluginEndpoint,
78172
- frontends: props.frontends
78173
- })
78174
- }, ...generateRoutesFromEmbeddedModules(flxFrontend, 'protected'), ...generateRoutesFromDeployedApps(flxFrontend, res.apps), ...generateRoutesFromJitApps(flxFrontend)]
78190
+ },
78191
+ // Espande le routes di MainRoutes direttamente qui per evitare il wrapper
78192
+ ...generateMainRoutes({
78193
+ fluxoShellProps: props,
78194
+ isAdminFrontend: flxFrontend.id === 'admin',
78195
+ pluginEndpoint: props.pluginEndpoint,
78196
+ frontends: props.frontends
78197
+ }, res.hasAdminAccess || false, res.hasDeveloperAccess || false, res.hasDataAnalystAccess || false), ...generateRoutesFromEmbeddedModules(flxFrontend, 'protected'), ...generateRoutesFromDeployedApps(flxFrontend, res.apps), ...generateRoutesFromJitApps(flxFrontend)]
78175
78198
  }, {
78176
78199
  path: '*',
78177
78200
  element: jsx(ErrorPage, {})
package/package.json CHANGED
@@ -1,23 +1,23 @@
1
1
  {
2
2
  "name": "@fluxo-dev/shell",
3
- "version": "25.3.9",
3
+ "version": "25.4.0",
4
4
  "peerDependencies": {
5
5
  "react": "^18.3.1",
6
6
  "@mantine/core": "^7.12.2",
7
7
  "react-router-dom": "^6.11.2",
8
8
  "react-redux": "^8.0.5",
9
9
  "@reduxjs/toolkit": "^1.9.1",
10
- "@fluxo-dev/api-client-base": "^25.3.9",
11
- "@fluxo-dev/shell-bi": "^25.3.9",
12
- "@fluxo-dev/shell-hub": "^25.3.9",
13
- "@fluxo-dev/shell-korebi": "^25.3.9",
14
- "@fluxo-dev/shell-mfe": "^25.3.9",
15
- "@fluxo-dev/shell-printing": "^25.3.9",
16
- "@fluxo-dev/shell-reporting": "^25.3.9",
17
- "@fluxo-dev/shell-workflow": "^25.3.9",
18
- "@fluxo-dev/shell-ravify": "^25.3.9",
19
- "@fluxo-dev/state": "^25.3.9",
20
- "@fluxo-dev/ui-components": "^25.3.9",
10
+ "@fluxo-dev/api-client-base": "^25.4.0",
11
+ "@fluxo-dev/shell-bi": "^25.4.0",
12
+ "@fluxo-dev/shell-hub": "^25.4.0",
13
+ "@fluxo-dev/shell-korebi": "^25.4.0",
14
+ "@fluxo-dev/shell-mfe": "^25.4.0",
15
+ "@fluxo-dev/shell-printing": "^25.4.0",
16
+ "@fluxo-dev/shell-reporting": "^25.4.0",
17
+ "@fluxo-dev/shell-workflow": "^25.4.0",
18
+ "@fluxo-dev/shell-ravify": "^25.4.0",
19
+ "@fluxo-dev/state": "^25.4.0",
20
+ "@fluxo-dev/ui-components": "^25.4.0",
21
21
  "@scalar/api-reference-react": "^0.3.142",
22
22
  "@devexpress/analytics-core": "23.1.3",
23
23
  "devexpress-dashboard": "23.1.3",
@@ -1,3 +1,4 @@
1
+ import { RouteObject } from "react-router-dom";
1
2
  import { FluxoShellProps, ShellFrontend } from '../../app';
2
3
  export interface MainRoutesProps {
3
4
  pluginEndpoint: string;
@@ -5,4 +6,8 @@ export interface MainRoutesProps {
5
6
  isAdminFrontend: boolean;
6
7
  fluxoShellProps: FluxoShellProps;
7
8
  }
8
- export declare function MainRoutes(props: MainRoutesProps): import("react/jsx-runtime").JSX.Element;
9
+ /**
10
+ * Genera le routes principali come RouteObject[] invece di componente wrapper
11
+ * Questo evita il remount dei componenti quando si switcha tra sessioni
12
+ */
13
+ export declare function generateMainRoutes(props: MainRoutesProps, hasAdminAccess: boolean, hasDeveloperAccess: boolean, hasDataAnalystAccess: boolean): RouteObject[];