frontend-plus-react 0.1.16 → 0.1.18
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/dist/index.cjs +73 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -3
- package/dist/index.d.ts +17 -3
- package/dist/index.js +89 -35
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2527,8 +2527,8 @@ var GenericDataGrid = ({
|
|
|
2527
2527
|
var GenericDataGrid_default = GenericDataGrid;
|
|
2528
2528
|
|
|
2529
2529
|
// src/App.tsx
|
|
2530
|
-
import
|
|
2531
|
-
import { BrowserRouter, Routes, Route, useLocation as
|
|
2530
|
+
import React12, { useEffect as useEffect7 } from "react";
|
|
2531
|
+
import { BrowserRouter, Routes, Route, useLocation as useLocation5, Navigate as Navigate2, Outlet as Outlet2 } from "react-router-dom";
|
|
2532
2532
|
|
|
2533
2533
|
// src/components/MainLayout.tsx
|
|
2534
2534
|
import { useEffect as useEffect3 } from "react";
|
|
@@ -2547,8 +2547,8 @@ import {
|
|
|
2547
2547
|
} from "@mui/material";
|
|
2548
2548
|
|
|
2549
2549
|
// src/contexts/AppContext.tsx
|
|
2550
|
-
import { createContext as createContext2, useContext as useContext2, useState as useState6, useEffect as useEffect2, useCallback as useCallback5, useMemo as useMemo3 } from "react";
|
|
2551
|
-
import { useNavigate } from "react-router-dom";
|
|
2550
|
+
import { createContext as createContext2, useContext as useContext2, useState as useState6, useEffect as useEffect2, useCallback as useCallback5, useMemo as useMemo3, useRef as useRef2 } from "react";
|
|
2551
|
+
import { useLocation, useNavigate } from "react-router-dom";
|
|
2552
2552
|
import { useSelector as useSelector2, useDispatch as useDispatch2 } from "react-redux";
|
|
2553
2553
|
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
2554
2554
|
var AuthContext = createContext2(void 0);
|
|
@@ -2560,16 +2560,33 @@ var useApp = () => {
|
|
|
2560
2560
|
const clientContext = useSelector2((state) => state.clientContext);
|
|
2561
2561
|
return { ...context, clientContext };
|
|
2562
2562
|
};
|
|
2563
|
-
var AppProvider = ({ children }) => {
|
|
2563
|
+
var AppProvider = ({ children, publicPaths = [] }) => {
|
|
2564
2564
|
console.log("AppProvider rendered/re-rendered");
|
|
2565
2565
|
const [isLoggedIn, setIsLoggedIn] = useState6(false);
|
|
2566
2566
|
const [showSessionExpiredMessage, setShowSessionExpiredMessage] = useState6(false);
|
|
2567
|
+
const isRedirectingRef = useRef2(false);
|
|
2567
2568
|
const dispatch = useDispatch2();
|
|
2568
2569
|
const clientContext = useSelector2((state) => state.clientContext);
|
|
2569
2570
|
const navigate = useNavigate();
|
|
2571
|
+
const handleExpiredSessionRedirect = useCallback5(() => {
|
|
2572
|
+
isRedirectingRef.current = true;
|
|
2573
|
+
setShowSessionExpiredMessage(false);
|
|
2574
|
+
setIsLoggedIn(false);
|
|
2575
|
+
navigate("/login", { replace: true });
|
|
2576
|
+
setTimeout(() => {
|
|
2577
|
+
isRedirectingRef.current = false;
|
|
2578
|
+
}, 2e3);
|
|
2579
|
+
}, [navigate]);
|
|
2580
|
+
const location = useLocation();
|
|
2581
|
+
const isCurrentPathPublic = useCallback5(() => {
|
|
2582
|
+
const current = location.pathname;
|
|
2583
|
+
return publicPaths.some((path) => current === path || current.startsWith(`${path}/`));
|
|
2584
|
+
}, [location.pathname, publicPaths]);
|
|
2570
2585
|
const checkSession = useCallback5(async () => {
|
|
2586
|
+
if (isRedirectingRef.current) return;
|
|
2571
2587
|
try {
|
|
2572
2588
|
const response = await fetchApi("/keep-alive.json", { method: "GET" });
|
|
2589
|
+
if (isRedirectingRef.current) return;
|
|
2573
2590
|
if (response.ok) {
|
|
2574
2591
|
setIsLoggedIn(true);
|
|
2575
2592
|
setShowSessionExpiredMessage(false);
|
|
@@ -2585,15 +2602,19 @@ var AppProvider = ({ children }) => {
|
|
|
2585
2602
|
} else {
|
|
2586
2603
|
setIsLoggedIn(false);
|
|
2587
2604
|
dispatch(clearClientContext());
|
|
2588
|
-
if (!showSessionExpiredMessage &&
|
|
2605
|
+
if (!showSessionExpiredMessage && !isCurrentPathPublic()) {
|
|
2606
|
+
console.warn("Sesi\xF3n inv\xE1lida en ruta protegida. Mostrando modal.");
|
|
2589
2607
|
setShowSessionExpiredMessage(true);
|
|
2608
|
+
} else {
|
|
2609
|
+
console.log("Sesi\xF3n inv\xE1lida, pero estamos en ruta p\xFAblica. Todo bien.");
|
|
2590
2610
|
}
|
|
2591
2611
|
}
|
|
2592
2612
|
} catch (error) {
|
|
2593
2613
|
console.error("Error checking session:", error);
|
|
2594
2614
|
setIsLoggedIn(false);
|
|
2595
2615
|
dispatch(clearClientContext());
|
|
2596
|
-
|
|
2616
|
+
const isPublic = publicPaths.some((p) => location.pathname === p || location.pathname.startsWith(p + "/"));
|
|
2617
|
+
if (!showSessionExpiredMessage && !isCurrentPathPublic()) {
|
|
2597
2618
|
setShowSessionExpiredMessage(true);
|
|
2598
2619
|
}
|
|
2599
2620
|
}
|
|
@@ -2610,13 +2631,15 @@ var AppProvider = ({ children }) => {
|
|
|
2610
2631
|
setIsLoggedIn,
|
|
2611
2632
|
checkSession,
|
|
2612
2633
|
showSessionExpiredMessage,
|
|
2613
|
-
setShowSessionExpiredMessage
|
|
2634
|
+
setShowSessionExpiredMessage,
|
|
2635
|
+
handleExpiredSessionRedirect
|
|
2614
2636
|
}), [
|
|
2615
2637
|
isLoggedIn,
|
|
2616
2638
|
setIsLoggedIn,
|
|
2617
2639
|
checkSession,
|
|
2618
2640
|
showSessionExpiredMessage,
|
|
2619
|
-
setShowSessionExpiredMessage
|
|
2641
|
+
setShowSessionExpiredMessage,
|
|
2642
|
+
handleExpiredSessionRedirect
|
|
2620
2643
|
]);
|
|
2621
2644
|
return /* @__PURE__ */ jsx15(AuthContext.Provider, { value: authContextValue, children });
|
|
2622
2645
|
};
|
|
@@ -2638,7 +2661,7 @@ import WarningAmberIcon3 from "@mui/icons-material/WarningAmber";
|
|
|
2638
2661
|
import DesktopWindowsIcon from "@mui/icons-material/DesktopWindows";
|
|
2639
2662
|
import UnfoldMoreIcon from "@mui/icons-material/UnfoldMore";
|
|
2640
2663
|
import UnfoldLessIcon from "@mui/icons-material/UnfoldLess";
|
|
2641
|
-
import { useNavigate as useNavigate2, useLocation } from "react-router-dom";
|
|
2664
|
+
import { useNavigate as useNavigate2, useLocation as useLocation2 } from "react-router-dom";
|
|
2642
2665
|
import { blue, orange, teal, red, grey } from "@mui/material/colors";
|
|
2643
2666
|
|
|
2644
2667
|
// src/pages/WScreens.tsx
|
|
@@ -2682,7 +2705,7 @@ var extendWScreens = (newWScreens) => {
|
|
|
2682
2705
|
import { Fragment as Fragment2, jsx as jsx17, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
2683
2706
|
var MenuListItem = ({ item, level, onMenuItemClick }) => {
|
|
2684
2707
|
const navigate = useNavigate2();
|
|
2685
|
-
const location =
|
|
2708
|
+
const location = useLocation2();
|
|
2686
2709
|
const open = useSubMenuOpenState(item.name);
|
|
2687
2710
|
const dispatch = useAppDispatch();
|
|
2688
2711
|
const handleClick = () => {
|
|
@@ -2770,7 +2793,7 @@ var MenuListItem = ({ item, level, onMenuItemClick }) => {
|
|
|
2770
2793
|
var SideMenu = ({ onMenuItemClick }) => {
|
|
2771
2794
|
const { clientContext } = useApp();
|
|
2772
2795
|
const navigate = useNavigate2();
|
|
2773
|
-
const location =
|
|
2796
|
+
const location = useLocation2();
|
|
2774
2797
|
const dispatch = useAppDispatch();
|
|
2775
2798
|
const subMenuOpenStates = useAppSelector((state) => state.menuUi.subMenuOpenStates);
|
|
2776
2799
|
const allSubMenusKeys = Object.keys(subMenuOpenStates);
|
|
@@ -2991,7 +3014,6 @@ var MainLayout_default = MainLayout;
|
|
|
2991
3014
|
|
|
2992
3015
|
// src/components/SessionExpiredMessage.tsx
|
|
2993
3016
|
import { Box as Box12, Typography as Typography9, Button as Button5, Modal } from "@mui/material";
|
|
2994
|
-
import { useNavigate as useNavigate4 } from "react-router-dom";
|
|
2995
3017
|
import { jsx as jsx19, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
2996
3018
|
var style = {
|
|
2997
3019
|
position: "absolute",
|
|
@@ -3007,12 +3029,9 @@ var style = {
|
|
|
3007
3029
|
borderRadius: 2
|
|
3008
3030
|
};
|
|
3009
3031
|
var SessionExpiredMessage = () => {
|
|
3010
|
-
const { showSessionExpiredMessage, setShowSessionExpiredMessage, setIsLoggedIn } = useApp();
|
|
3011
|
-
const navigate = useNavigate4();
|
|
3032
|
+
const { showSessionExpiredMessage, setShowSessionExpiredMessage, setIsLoggedIn, handleExpiredSessionRedirect } = useApp();
|
|
3012
3033
|
const handleClose = () => {
|
|
3013
|
-
|
|
3014
|
-
setIsLoggedIn(false);
|
|
3015
|
-
navigate("/login", { replace: true });
|
|
3034
|
+
handleExpiredSessionRedirect();
|
|
3016
3035
|
};
|
|
3017
3036
|
return /* @__PURE__ */ jsx19(
|
|
3018
3037
|
Modal,
|
|
@@ -3085,7 +3104,7 @@ import { Button as Button6, TextField, Typography as Typography12, Alert as Aler
|
|
|
3085
3104
|
import { useForm, Controller } from "react-hook-form";
|
|
3086
3105
|
import { zodResolver } from "@hookform/resolvers/zod";
|
|
3087
3106
|
import * as z from "zod";
|
|
3088
|
-
import { useNavigate as
|
|
3107
|
+
import { useNavigate as useNavigate4 } from "react-router-dom";
|
|
3089
3108
|
import { useDispatch as useDispatch4 } from "react-redux";
|
|
3090
3109
|
import { Fragment as Fragment3, jsx as jsx22, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
3091
3110
|
var loginSchema = z.object({
|
|
@@ -3095,7 +3114,7 @@ var loginSchema = z.object({
|
|
|
3095
3114
|
// Añadir validación básica
|
|
3096
3115
|
});
|
|
3097
3116
|
var LoginPage = () => {
|
|
3098
|
-
const navigate =
|
|
3117
|
+
const navigate = useNavigate4();
|
|
3099
3118
|
const [loginError, setLoginError] = useState7(null);
|
|
3100
3119
|
const [isSubmitting, setIsSubmitting] = useState7(false);
|
|
3101
3120
|
const { setIsLoggedIn, checkSession } = useApp();
|
|
@@ -3695,10 +3714,10 @@ import { PersistGate } from "redux-persist/integration/react";
|
|
|
3695
3714
|
|
|
3696
3715
|
// src/components/PrivateRoute.tsx
|
|
3697
3716
|
import { useEffect as useEffect5 } from "react";
|
|
3698
|
-
import { Navigate, useLocation as
|
|
3717
|
+
import { Navigate, useLocation as useLocation3 } from "react-router-dom";
|
|
3699
3718
|
import { Fragment as Fragment4, jsx as jsx25 } from "react/jsx-runtime";
|
|
3700
3719
|
var PrivateRoute = ({ children }) => {
|
|
3701
|
-
const location =
|
|
3720
|
+
const location = useLocation3();
|
|
3702
3721
|
const dispatch = useAppDispatch();
|
|
3703
3722
|
const clientContextStatus = useClientContextStatus();
|
|
3704
3723
|
const isAuthenticated = clientContextStatus === "succeeded";
|
|
@@ -3733,10 +3752,10 @@ var PrivateRoute_default = PrivateRoute;
|
|
|
3733
3752
|
|
|
3734
3753
|
// src/components/InitialRedirectHandler.tsx
|
|
3735
3754
|
import { useEffect as useEffect6 } from "react";
|
|
3736
|
-
import { useLocation as
|
|
3755
|
+
import { useLocation as useLocation4, useNavigate as useNavigate5 } from "react-router-dom";
|
|
3737
3756
|
var InitialRedirectHandler = () => {
|
|
3738
|
-
const location =
|
|
3739
|
-
const navigate =
|
|
3757
|
+
const location = useLocation4();
|
|
3758
|
+
const navigate = useNavigate5();
|
|
3740
3759
|
const dispatch = useAppDispatch();
|
|
3741
3760
|
const redirectPath = useRedirectPath();
|
|
3742
3761
|
const clientContextStatus = useClientContextStatus();
|
|
@@ -3838,19 +3857,40 @@ var MenuTablePage_default = MenuTablePage;
|
|
|
3838
3857
|
|
|
3839
3858
|
// src/App.tsx
|
|
3840
3859
|
import { Box as Box20 } from "@mui/material";
|
|
3860
|
+
|
|
3861
|
+
// src/utils/routeUtils.ts
|
|
3862
|
+
import { Children, isValidElement } from "react";
|
|
3863
|
+
var extractPathsFromRoutes = (node) => {
|
|
3864
|
+
const paths = [];
|
|
3865
|
+
Children.forEach(node, (child) => {
|
|
3866
|
+
if (!isValidElement(child)) return;
|
|
3867
|
+
if (child.props.path) {
|
|
3868
|
+
paths.push(child.props.path);
|
|
3869
|
+
}
|
|
3870
|
+
if (child.props.children) {
|
|
3871
|
+
paths.push(...extractPathsFromRoutes(child.props.children));
|
|
3872
|
+
}
|
|
3873
|
+
});
|
|
3874
|
+
return paths;
|
|
3875
|
+
};
|
|
3876
|
+
|
|
3877
|
+
// src/App.tsx
|
|
3841
3878
|
import { jsx as jsx28, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
3842
3879
|
var LocationTracker = () => {
|
|
3843
|
-
const location =
|
|
3880
|
+
const location = useLocation5();
|
|
3844
3881
|
const dispatch = useAppDispatch();
|
|
3845
3882
|
useEffect7(() => {
|
|
3846
3883
|
dispatch(setCurrentPath(location.pathname + location.search));
|
|
3847
3884
|
}, [location, dispatch]);
|
|
3848
3885
|
return null;
|
|
3849
3886
|
};
|
|
3850
|
-
function FrontendPlusReactRoutes({ myRoutes, layout: Layout = MainLayout_default }) {
|
|
3887
|
+
function FrontendPlusReactRoutes({ myRoutes, myUnloggedRoutes, layout: Layout = MainLayout_default, unloggedLayout: UnloggedLayout }) {
|
|
3851
3888
|
return /* @__PURE__ */ jsxs18(Routes, { children: [
|
|
3852
|
-
/* @__PURE__ */
|
|
3853
|
-
|
|
3889
|
+
/* @__PURE__ */ jsxs18(Route, { element: UnloggedLayout ? /* @__PURE__ */ jsx28(UnloggedLayout, {}) : /* @__PURE__ */ jsx28(Outlet2, {}), children: [
|
|
3890
|
+
/* @__PURE__ */ jsx28(Route, { path: "/login", element: /* @__PURE__ */ jsx28(LoginPage_default, {}) }),
|
|
3891
|
+
/* @__PURE__ */ jsx28(Route, { path: "/logout", element: /* @__PURE__ */ jsx28(LogoutPage_default, {}) }),
|
|
3892
|
+
myUnloggedRoutes
|
|
3893
|
+
] }),
|
|
3854
3894
|
/* @__PURE__ */ jsxs18(Route, { element: /* @__PURE__ */ jsxs18(PrivateRoute_default, { children: [
|
|
3855
3895
|
/* @__PURE__ */ jsx28(InitialRedirectHandler_default, {}),
|
|
3856
3896
|
/* @__PURE__ */ jsx28(Layout, {})
|
|
@@ -3864,12 +3904,12 @@ function FrontendPlusReactRoutes({ myRoutes, layout: Layout = MainLayout_default
|
|
|
3864
3904
|
Route,
|
|
3865
3905
|
{
|
|
3866
3906
|
path: `/wScreens/${screenName}`,
|
|
3867
|
-
element:
|
|
3907
|
+
element: React12.createElement(
|
|
3868
3908
|
Box20,
|
|
3869
3909
|
{
|
|
3870
3910
|
sx: { pt: 3, pl: 4 }
|
|
3871
3911
|
},
|
|
3872
|
-
|
|
3912
|
+
React12.createElement(wScreens[screenName], { screenName })
|
|
3873
3913
|
)
|
|
3874
3914
|
},
|
|
3875
3915
|
screenName
|
|
@@ -3881,17 +3921,17 @@ function FrontendPlusReactRoutes({ myRoutes, layout: Layout = MainLayout_default
|
|
|
3881
3921
|
element: /* @__PURE__ */ jsx28(Box20, { sx: { p: 3 }, children: /* @__PURE__ */ jsx28(FallbackWScreen, { screenName: ":screenName" }) })
|
|
3882
3922
|
}
|
|
3883
3923
|
),
|
|
3924
|
+
myRoutes,
|
|
3884
3925
|
/* @__PURE__ */ jsx28(Route, { path: "*", element: /* @__PURE__ */ jsx28("div", { style: { marginTop: "20px", marginLeft: "10px" }, children: "404 - Recurso No Encontrado" }) })
|
|
3885
3926
|
] }),
|
|
3886
|
-
myRoutes,
|
|
3887
3927
|
/* @__PURE__ */ jsx28(Route, { path: "*", element: /* @__PURE__ */ jsx28(Navigate2, { to: "/", replace: true }) })
|
|
3888
3928
|
] });
|
|
3889
3929
|
}
|
|
3890
|
-
var FrontendPlusProviders = ({ children }) => {
|
|
3930
|
+
var FrontendPlusProviders = ({ children, publicPaths }) => {
|
|
3891
3931
|
return /* @__PURE__ */ jsx28(Provider, { store, children: /* @__PURE__ */ jsx28(PersistGate, { loading: null, persistor, children: /* @__PURE__ */ jsxs18(BrowserRouter, { children: [
|
|
3892
3932
|
/* @__PURE__ */ jsx28(LocationTracker, {}),
|
|
3893
3933
|
" ",
|
|
3894
|
-
/* @__PURE__ */ jsx28(AppProvider, { children: /* @__PURE__ */ jsxs18(SnackbarProvider, { children: [
|
|
3934
|
+
/* @__PURE__ */ jsx28(AppProvider, { publicPaths, children: /* @__PURE__ */ jsxs18(SnackbarProvider, { children: [
|
|
3895
3935
|
children,
|
|
3896
3936
|
/* @__PURE__ */ jsx28(SessionExpiredMessage_default, {})
|
|
3897
3937
|
] }) })
|
|
@@ -3899,6 +3939,8 @@ var FrontendPlusProviders = ({ children }) => {
|
|
|
3899
3939
|
};
|
|
3900
3940
|
var App = ({
|
|
3901
3941
|
myRoutes,
|
|
3942
|
+
myUnloggedRoutes,
|
|
3943
|
+
unloggedLayout,
|
|
3902
3944
|
myWScreens,
|
|
3903
3945
|
myClientSides,
|
|
3904
3946
|
myResultsOk
|
|
@@ -3914,7 +3956,18 @@ var App = ({
|
|
|
3914
3956
|
extendWScreens(myWScreens);
|
|
3915
3957
|
}
|
|
3916
3958
|
}, [myClientSides, myResultsOk, myWScreens]);
|
|
3917
|
-
|
|
3959
|
+
const safePaths = React12.useMemo(() => {
|
|
3960
|
+
const extracted = extractPathsFromRoutes(myUnloggedRoutes);
|
|
3961
|
+
return ["/login", "/logout", ...extracted];
|
|
3962
|
+
}, [myUnloggedRoutes]);
|
|
3963
|
+
return /* @__PURE__ */ jsx28(FrontendPlusProviders, { publicPaths: safePaths, children: /* @__PURE__ */ jsx28(
|
|
3964
|
+
FrontendPlusReactRoutes,
|
|
3965
|
+
{
|
|
3966
|
+
myRoutes,
|
|
3967
|
+
myUnloggedRoutes,
|
|
3968
|
+
unloggedLayout
|
|
3969
|
+
}
|
|
3970
|
+
) });
|
|
3918
3971
|
};
|
|
3919
3972
|
var App_default = App;
|
|
3920
3973
|
export {
|
|
@@ -3931,6 +3984,7 @@ export {
|
|
|
3931
3984
|
extendClientSides,
|
|
3932
3985
|
extendResultsOk,
|
|
3933
3986
|
extendWScreens,
|
|
3987
|
+
extractPathsFromRoutes,
|
|
3934
3988
|
resultsOk as resultComponents,
|
|
3935
3989
|
useApiCall,
|
|
3936
3990
|
useApiCallWithoutSnackbar,
|