@hitachivantara/app-shell-ui 1.14.0 → 2.0.0-next.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/AppShellProvider/AppShellProvider.js +149 -0
- package/dist/{esm/components → components}/AppShellRoutes/AppShellRoutes.js +48 -32
- package/dist/{esm/components → components}/layout/Header/Header.js +8 -8
- package/dist/{esm/components → components}/layout/Header/HeaderActions/HeaderActions.js +4 -5
- package/dist/{esm/components → components}/layout/Header/HeaderActions/InternalActions/AppSwitcherToggle/AppSwitcherToggle.js +3 -3
- package/dist/{esm/components → components}/layout/VerticalNavigation/NavigationHeader.js +3 -3
- package/dist/hooks/useConditionsEvaluator.js +87 -0
- package/dist/hooks/useFilteredModel.js +30 -0
- package/dist/hooks/useModelFromConfig.js +42 -0
- package/dist/{esm/hooks → hooks}/useNavigationMenuItems.js +2 -2
- package/dist/{esm/hooks → hooks}/useNotificationsEventListener.js +2 -2
- package/dist/{esm/hooks → hooks}/useThemeEventListener.js +4 -5
- package/dist/index.d.ts +9 -0
- package/dist/{esm/pages → pages}/ErrorPage/ErrorPage.js +1 -1
- package/dist/{esm/pages → pages}/ErrorPage/Footer.js +2 -2
- package/dist/pages/Root/Root.js +26 -0
- package/dist/{esm/providers → providers}/BannerProvider.js +1 -1
- package/dist/types/index.d.ts +4 -9
- package/dist/utils/CombinedProviders.js +20 -0
- package/dist/utils/filterModel.js +177 -0
- package/dist/utils/lazyImport.js +40 -0
- package/dist/utils/processConfig.js +158 -0
- package/package.json +13 -13
- package/dist/esm/components/AppShellProvider/AppShellProvider.js +0 -115
- package/dist/esm/pages/Root/Root.js +0 -21
- package/dist/esm/utils/CombinedProviders.js +0 -23
- /package/dist/{esm/components → components}/AppShell/AppShell.js +0 -0
- /package/dist/{esm/components → components}/AppShellViewProvider/AppShellViewProvider.js +0 -0
- /package/dist/{esm/components → components}/CustomHooksInitializer/CustomHooksInitializer.js +0 -0
- /package/dist/{esm/components → components}/GlobalStyles/GlobalStyles.js +0 -0
- /package/dist/{esm/components → components}/GlobalStyles/index.js +0 -0
- /package/dist/{esm/components → components}/IconUiKit/IconUiKit.js +0 -0
- /package/dist/{esm/components → components}/IconUiKit/index.js +0 -0
- /package/dist/{esm/components → components}/SnackbarProvider/SnackbarProvider.js +0 -0
- /package/dist/{esm/components → components}/hoc/withClickAwayListener.js +0 -0
- /package/dist/{esm/components → components}/hoc/withGlobalProvider.js +0 -0
- /package/dist/{esm/components → components}/layout/BrandLogo/BrandLogo.js +0 -0
- /package/dist/{esm/components → components}/layout/BrandLogo/logos.js +0 -0
- /package/dist/{esm/components → components}/layout/Header/HeaderActions/DynamicAction.js +0 -0
- /package/dist/{esm/components → components}/layout/Header/HeaderActions/InternalActions/AppSwitcherToggle/index.js +0 -0
- /package/dist/{esm/components → components}/layout/Header/HeaderActions/InternalActions/AppSwitcherToggle/styles.js +0 -0
- /package/dist/{esm/components → components}/layout/Header/HeaderActions/InternalActions/ColorModeSwitcher.js +0 -0
- /package/dist/{esm/components → components}/layout/Header/HeaderActions/InternalActions/HelpButton/HelpButton.js +0 -0
- /package/dist/{esm/components → components}/layout/Header/HeaderActions/InternalActions/HelpButton/index.js +0 -0
- /package/dist/{esm/components → components}/layout/Header/HeaderActions/InternalActions/InternalAction/InternalAction.js +0 -0
- /package/dist/{esm/components → components}/layout/Header/HeaderActions/index.js +0 -0
- /package/dist/{esm/components → components}/layout/Header/styles.js +0 -0
- /package/dist/{esm/components → components}/layout/Loading/Loading.js +0 -0
- /package/dist/{esm/components → components}/layout/Loading/styles.js +0 -0
- /package/dist/{esm/components → components}/layout/Main/Main.js +0 -0
- /package/dist/{esm/components → components}/layout/Main/styles.js +0 -0
- /package/dist/{esm/components → components}/layout/VerticalNavigation/NavigationCollapse.js +0 -0
- /package/dist/{esm/components → components}/layout/VerticalNavigation/VerticalNavigation.js +0 -0
- /package/dist/{esm/components → components}/layout/VerticalNavigation/styles.js +0 -0
- /package/dist/{esm/hooks → hooks}/useClearLocationState.js +0 -0
- /package/dist/{esm/hooks → hooks}/useCustomEventListener.js +0 -0
- /package/dist/{esm/hooks → hooks}/useLocalStorage.js +0 -0
- /package/dist/{esm/hooks → hooks}/useResizeObserver.js +0 -0
- /package/dist/{esm/i18n → i18n}/index.js +0 -0
- /package/dist/{esm/i18n → i18n}/localization/en.json.js +0 -0
- /package/dist/{esm/i18n → i18n}/localization/pt.json.js +0 -0
- /package/dist/{esm/index.js → index.js} +0 -0
- /package/dist/{esm/pages → pages}/ErrorPage/styles.js +0 -0
- /package/dist/{esm/pages → pages}/GenericError/500.svg.js +0 -0
- /package/dist/{esm/pages → pages}/GenericError/GenericError.js +0 -0
- /package/dist/{esm/pages → pages}/LoadingPage/LoadingPage.js +0 -0
- /package/dist/{esm/pages → pages}/LoadingPage/index.js +0 -0
- /package/dist/{esm/pages → pages}/LoadingPage/styles.js +0 -0
- /package/dist/{esm/pages → pages}/NotFound/404.svg.js +0 -0
- /package/dist/{esm/pages → pages}/NotFound/NotFound.js +0 -0
- /package/dist/{esm/pages → pages}/NotFound/index.js +0 -0
- /package/dist/{esm/providers → providers}/LayoutProvider.js +0 -0
- /package/dist/{esm/providers → providers}/NavigationProvider.js +0 -0
- /package/dist/{esm/utils → utils}/documentUtil.js +0 -0
- /package/dist/{esm/utils → utils}/navigationUtil.js +0 -0
|
@@ -3,7 +3,7 @@ import { useErrorBoundary } from "react-error-boundary";
|
|
|
3
3
|
import { useTranslation, Trans } from "react-i18next";
|
|
4
4
|
import styled from "@emotion/styled";
|
|
5
5
|
import { useHvNavigation } from "@hitachivantara/app-shell-navigation";
|
|
6
|
-
import {
|
|
6
|
+
import { useHvAppShellModel } from "@hitachivantara/app-shell-shared";
|
|
7
7
|
import { HvTypography } from "@hitachivantara/uikit-react-core";
|
|
8
8
|
import { useNavigationContext } from "../../providers/NavigationProvider.js";
|
|
9
9
|
const StyledFooterWrapper = styled("div")({
|
|
@@ -12,7 +12,7 @@ const StyledFooterWrapper = styled("div")({
|
|
|
12
12
|
const Footer = () => {
|
|
13
13
|
const { t } = useTranslation();
|
|
14
14
|
const { navigate } = useHvNavigation();
|
|
15
|
-
const { navigationMode } =
|
|
15
|
+
const { navigationMode } = useHvAppShellModel();
|
|
16
16
|
const { resetBoundary } = useErrorBoundary();
|
|
17
17
|
const { items, verticalNavigationItems, isCompactMode } = useNavigationContext();
|
|
18
18
|
const getFirstMenuItem = () => {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Suspense } from "react";
|
|
3
|
+
import { ErrorBoundary } from "react-error-boundary";
|
|
4
|
+
import { Outlet } from "react-router-dom";
|
|
5
|
+
import ServiceManagerProvider from "@hitachivantara/app-shell-services";
|
|
6
|
+
import { useHvAppShellModel, useHvAppShellCombinedProviders } from "@hitachivantara/app-shell-shared";
|
|
7
|
+
import { BannerProvider } from "../../providers/BannerProvider.js";
|
|
8
|
+
import { NavigationProvider } from "../../providers/NavigationProvider.js";
|
|
9
|
+
import CombinedProviders from "../../utils/CombinedProviders.js";
|
|
10
|
+
import LoadingPage from "../LoadingPage/LoadingPage.js";
|
|
11
|
+
import CustomHooksInitializer from "../../components/CustomHooksInitializer/CustomHooksInitializer.js";
|
|
12
|
+
import Header from "../../components/layout/Header/Header.js";
|
|
13
|
+
import Main from "../../components/layout/Main/Main.js";
|
|
14
|
+
import GenericError from "../GenericError/GenericError.js";
|
|
15
|
+
const Root = () => {
|
|
16
|
+
const { services } = useHvAppShellModel();
|
|
17
|
+
const { providers } = useHvAppShellCombinedProviders();
|
|
18
|
+
return /* @__PURE__ */ jsx(ErrorBoundary, { fallback: /* @__PURE__ */ jsx(GenericError, { fullPage: true }), children: /* @__PURE__ */ jsx(ServiceManagerProvider, { config: { services }, children: /* @__PURE__ */ jsx(CombinedProviders, { providers, children: /* @__PURE__ */ jsx(NavigationProvider, { children: /* @__PURE__ */ jsxs(BannerProvider, { children: [
|
|
19
|
+
/* @__PURE__ */ jsx(CustomHooksInitializer, {}),
|
|
20
|
+
/* @__PURE__ */ jsx(Header, {}),
|
|
21
|
+
/* @__PURE__ */ jsx(Main, { children: /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(LoadingPage, {}), children: /* @__PURE__ */ jsx(Outlet, {}) }) })
|
|
22
|
+
] }) }) }) }) });
|
|
23
|
+
};
|
|
24
|
+
export {
|
|
25
|
+
Root as default
|
|
26
|
+
};
|
|
@@ -100,7 +100,7 @@ const BannerProvider = ({ children }) => {
|
|
|
100
100
|
label: banner.message,
|
|
101
101
|
showIcon: true,
|
|
102
102
|
actions: banner.actions,
|
|
103
|
-
|
|
103
|
+
onAction: banner.onAction,
|
|
104
104
|
bannerContentProps: {
|
|
105
105
|
actionProps: { "aria-label": t("close") }
|
|
106
106
|
},
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
displayName: string;
|
|
6
|
-
};
|
|
7
|
-
export default _default;
|
|
8
|
-
|
|
9
|
-
export { }
|
|
1
|
+
export {}
|
|
2
|
+
import hitachivantaraappShellUi from '../packages/app-shell-ui/src/index'
|
|
3
|
+
export default hitachivantaraappShellUi
|
|
4
|
+
export {}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsx, Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo } from "react";
|
|
3
|
+
const CombinedProviders = ({
|
|
4
|
+
children: mainChildren,
|
|
5
|
+
providers
|
|
6
|
+
}) => {
|
|
7
|
+
const combined = useMemo(() => {
|
|
8
|
+
if (!providers || providers.length === 0) {
|
|
9
|
+
return mainChildren;
|
|
10
|
+
}
|
|
11
|
+
return providers.reduceRight(
|
|
12
|
+
(Acc, { component: Curr, config, key }) => /* @__PURE__ */ jsx(Curr, { ...config, children: Acc }, key),
|
|
13
|
+
mainChildren
|
|
14
|
+
);
|
|
15
|
+
}, [providers, mainChildren]);
|
|
16
|
+
return /* @__PURE__ */ jsx(Fragment, { children: combined });
|
|
17
|
+
};
|
|
18
|
+
export {
|
|
19
|
+
CombinedProviders as default
|
|
20
|
+
};
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
const shouldInclude = (conditions, conditionResults) => {
|
|
2
|
+
if (!conditions || conditions.length === 0) {
|
|
3
|
+
return true;
|
|
4
|
+
}
|
|
5
|
+
for (const condition of conditions) {
|
|
6
|
+
if (!conditionResults[condition.globalIndex]) {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
return true;
|
|
11
|
+
};
|
|
12
|
+
const filterViews = (views, conditionResults) => {
|
|
13
|
+
const filteredViews = [];
|
|
14
|
+
let hasChanged = false;
|
|
15
|
+
for (const view of views) {
|
|
16
|
+
const include = shouldInclude(view.conditions, conditionResults);
|
|
17
|
+
if (!include) {
|
|
18
|
+
hasChanged = true;
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
if (!view.views) {
|
|
22
|
+
filteredViews.push(view);
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
const [filteredSubViews, subViewsChanged] = filterViews(
|
|
26
|
+
view.views,
|
|
27
|
+
conditionResults
|
|
28
|
+
);
|
|
29
|
+
if (subViewsChanged) {
|
|
30
|
+
filteredViews.push({ ...view, views: filteredSubViews });
|
|
31
|
+
hasChanged = true;
|
|
32
|
+
} else {
|
|
33
|
+
filteredViews.push(view);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return [hasChanged ? filteredViews : views, hasChanged];
|
|
37
|
+
};
|
|
38
|
+
const filterMenus = (menus, conditionResults) => {
|
|
39
|
+
const filteredMenus = [];
|
|
40
|
+
let hasChanged = false;
|
|
41
|
+
for (const menu of menus) {
|
|
42
|
+
const include = shouldInclude(menu.conditions, conditionResults);
|
|
43
|
+
if (!include) {
|
|
44
|
+
hasChanged = true;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
if (!menu.submenus) {
|
|
48
|
+
filteredMenus.push(menu);
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
const [filteredSubmenus, submenusChanged] = filterMenus(
|
|
52
|
+
menu.submenus,
|
|
53
|
+
conditionResults
|
|
54
|
+
);
|
|
55
|
+
if (filteredSubmenus.length === 0) {
|
|
56
|
+
hasChanged = true;
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (submenusChanged) {
|
|
60
|
+
filteredMenus.push({
|
|
61
|
+
...menu,
|
|
62
|
+
submenus: filteredSubmenus
|
|
63
|
+
});
|
|
64
|
+
hasChanged = true;
|
|
65
|
+
} else {
|
|
66
|
+
filteredMenus.push(menu);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return [hasChanged ? filteredMenus : menus, hasChanged];
|
|
70
|
+
};
|
|
71
|
+
const filterActions = (actions, conditionResults) => {
|
|
72
|
+
const filteredHeaderActions = [];
|
|
73
|
+
for (const action of actions) {
|
|
74
|
+
const include = shouldInclude(action.conditions, conditionResults);
|
|
75
|
+
if (include) filteredHeaderActions.push(action);
|
|
76
|
+
}
|
|
77
|
+
const hasChanged = filteredHeaderActions.length !== actions.length;
|
|
78
|
+
return [hasChanged ? filteredHeaderActions : actions, hasChanged];
|
|
79
|
+
};
|
|
80
|
+
const filterProviders = (providers, conditionResults) => {
|
|
81
|
+
const filteredProviders = [];
|
|
82
|
+
for (const provider of providers) {
|
|
83
|
+
const include = shouldInclude(provider.conditions, conditionResults);
|
|
84
|
+
if (include) filteredProviders.push(provider);
|
|
85
|
+
}
|
|
86
|
+
const hasChanged = filteredProviders.length !== providers.length;
|
|
87
|
+
return [hasChanged ? filteredProviders : providers, hasChanged];
|
|
88
|
+
};
|
|
89
|
+
const filterServices = (services, conditionResults) => {
|
|
90
|
+
if (!services) {
|
|
91
|
+
return [services, false];
|
|
92
|
+
}
|
|
93
|
+
const filteredServices = {};
|
|
94
|
+
let hasChanged = false;
|
|
95
|
+
for (const [serviceId, serviceProviderModels] of Object.entries(services)) {
|
|
96
|
+
const result = [];
|
|
97
|
+
let localChanged = false;
|
|
98
|
+
for (const serviceConfigModel of serviceProviderModels) {
|
|
99
|
+
const include = shouldInclude(
|
|
100
|
+
serviceConfigModel.conditions,
|
|
101
|
+
conditionResults
|
|
102
|
+
);
|
|
103
|
+
if (include) {
|
|
104
|
+
result.push(serviceConfigModel);
|
|
105
|
+
} else {
|
|
106
|
+
localChanged = true;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (localChanged) hasChanged = true;
|
|
110
|
+
filteredServices[serviceId] = localChanged ? result : serviceProviderModels;
|
|
111
|
+
}
|
|
112
|
+
return [hasChanged ? filteredServices : services, hasChanged];
|
|
113
|
+
};
|
|
114
|
+
function filterModel(model, conditionResults) {
|
|
115
|
+
let hasChanged = false;
|
|
116
|
+
const filtered = { ...model };
|
|
117
|
+
if (model.mainPanel?.views) {
|
|
118
|
+
const [filteredViews, viewsChanged] = filterViews(
|
|
119
|
+
model.mainPanel.views,
|
|
120
|
+
conditionResults
|
|
121
|
+
);
|
|
122
|
+
if (viewsChanged) {
|
|
123
|
+
filtered.mainPanel = {
|
|
124
|
+
...model.mainPanel,
|
|
125
|
+
views: filteredViews
|
|
126
|
+
};
|
|
127
|
+
hasChanged = true;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (model.menu) {
|
|
131
|
+
const [filteredMenus, menusChanged] = filterMenus(
|
|
132
|
+
model.menu,
|
|
133
|
+
conditionResults
|
|
134
|
+
);
|
|
135
|
+
if (menusChanged) {
|
|
136
|
+
filtered.menu = filteredMenus;
|
|
137
|
+
hasChanged = true;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (model.header?.actions) {
|
|
141
|
+
const [filteredActions, actionsChanged] = filterActions(
|
|
142
|
+
model.header.actions,
|
|
143
|
+
conditionResults
|
|
144
|
+
);
|
|
145
|
+
if (actionsChanged) {
|
|
146
|
+
filtered.header = {
|
|
147
|
+
...model.header,
|
|
148
|
+
actions: filteredActions
|
|
149
|
+
};
|
|
150
|
+
hasChanged = true;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if (model.providers) {
|
|
154
|
+
const [filteredProviders, providersChanged] = filterProviders(
|
|
155
|
+
model.providers,
|
|
156
|
+
conditionResults
|
|
157
|
+
);
|
|
158
|
+
if (providersChanged) {
|
|
159
|
+
filtered.providers = filteredProviders;
|
|
160
|
+
hasChanged = true;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
if (model.services) {
|
|
164
|
+
const [filteredServices, servicesChanged] = filterServices(
|
|
165
|
+
model.services,
|
|
166
|
+
conditionResults
|
|
167
|
+
);
|
|
168
|
+
if (servicesChanged) {
|
|
169
|
+
filtered.services = filteredServices;
|
|
170
|
+
hasChanged = true;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return hasChanged ? filtered : model;
|
|
174
|
+
}
|
|
175
|
+
export {
|
|
176
|
+
filterModel as default
|
|
177
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
async function lazyImport(bundle) {
|
|
2
|
+
try {
|
|
3
|
+
const module = await import(
|
|
4
|
+
/* @vite-ignore */
|
|
5
|
+
bundle
|
|
6
|
+
);
|
|
7
|
+
return {
|
|
8
|
+
isPending: false,
|
|
9
|
+
error: null,
|
|
10
|
+
module: module.default
|
|
11
|
+
};
|
|
12
|
+
} catch (err) {
|
|
13
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
14
|
+
return {
|
|
15
|
+
isPending: false,
|
|
16
|
+
error,
|
|
17
|
+
module: void 0
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
async function importAllBundles(bundles) {
|
|
22
|
+
const results = await Promise.all(
|
|
23
|
+
bundles.map((bundle) => lazyImport(bundle))
|
|
24
|
+
);
|
|
25
|
+
const preloadedBundles = /* @__PURE__ */ new Map();
|
|
26
|
+
for (let i = 0; i < results.length; i++) {
|
|
27
|
+
const result = results[i];
|
|
28
|
+
const bundle = bundles[i];
|
|
29
|
+
if (result.error) {
|
|
30
|
+
console.error(`Failed to load bundle ${bundle}:`, result.error);
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
preloadedBundles.set(bundle, result.module);
|
|
34
|
+
}
|
|
35
|
+
return preloadedBundles;
|
|
36
|
+
}
|
|
37
|
+
export {
|
|
38
|
+
importAllBundles,
|
|
39
|
+
lazyImport
|
|
40
|
+
};
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
const generateKey = () => {
|
|
2
|
+
return `${Date.now()}-${Math.round(1e3 * Math.random())}`;
|
|
3
|
+
};
|
|
4
|
+
const createRouteConditionsMap = (views) => {
|
|
5
|
+
const map = /* @__PURE__ */ new Map();
|
|
6
|
+
const processView = (view) => {
|
|
7
|
+
if (view.route && view.conditions) {
|
|
8
|
+
const normalizedRoute = view.route.replace(/^\//, "");
|
|
9
|
+
map.set(normalizedRoute, view.conditions);
|
|
10
|
+
}
|
|
11
|
+
if (view.views) {
|
|
12
|
+
for (const nestedView of view.views) {
|
|
13
|
+
processView(nestedView);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
for (const view of views) {
|
|
18
|
+
processView(view);
|
|
19
|
+
}
|
|
20
|
+
return map;
|
|
21
|
+
};
|
|
22
|
+
const applyViewConditionsToMenus = (menus, routeConditionsMap) => {
|
|
23
|
+
return menus.map((menu) => {
|
|
24
|
+
let updatedMenu = menu;
|
|
25
|
+
if (menu.target) {
|
|
26
|
+
const normalizedTarget = menu.target.replace(/^\//, "");
|
|
27
|
+
const viewConditions = routeConditionsMap.get(normalizedTarget);
|
|
28
|
+
if (viewConditions) {
|
|
29
|
+
const mergedConditions = [
|
|
30
|
+
...menu.conditions || [],
|
|
31
|
+
...viewConditions
|
|
32
|
+
];
|
|
33
|
+
if (mergedConditions.length > 0) {
|
|
34
|
+
updatedMenu = { ...menu, conditions: mergedConditions };
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (menu.submenus) {
|
|
39
|
+
const updatedSubmenus = applyViewConditionsToMenus(
|
|
40
|
+
menu.submenus,
|
|
41
|
+
routeConditionsMap
|
|
42
|
+
);
|
|
43
|
+
if (updatedSubmenus !== menu.submenus) {
|
|
44
|
+
updatedMenu = { ...updatedMenu, submenus: updatedSubmenus };
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return updatedMenu;
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
function processConfig(appShellConfig) {
|
|
51
|
+
let globalIndex = 0;
|
|
52
|
+
const allConditions = [];
|
|
53
|
+
const registerElement = (configElement) => {
|
|
54
|
+
const key = generateKey();
|
|
55
|
+
const conditions = configElement.conditions?.map((condConfig) => {
|
|
56
|
+
const conditionModel = {
|
|
57
|
+
...condConfig,
|
|
58
|
+
globalIndex: globalIndex++
|
|
59
|
+
};
|
|
60
|
+
allConditions.push(conditionModel);
|
|
61
|
+
return conditionModel;
|
|
62
|
+
});
|
|
63
|
+
return {
|
|
64
|
+
...configElement,
|
|
65
|
+
key,
|
|
66
|
+
...conditions && { conditions }
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
const processViews = (viewsConfig) => {
|
|
70
|
+
if (!viewsConfig) {
|
|
71
|
+
return [];
|
|
72
|
+
}
|
|
73
|
+
return viewsConfig.map((viewConfig) => {
|
|
74
|
+
const viewModel = registerElement(viewConfig);
|
|
75
|
+
if (viewConfig.views) {
|
|
76
|
+
return {
|
|
77
|
+
...viewModel,
|
|
78
|
+
views: processViews(viewConfig.views)
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
return viewModel;
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
const processMenus = (menusConfig) => {
|
|
85
|
+
if (!menusConfig) {
|
|
86
|
+
return [];
|
|
87
|
+
}
|
|
88
|
+
return menusConfig.map((menuConfig) => {
|
|
89
|
+
const menuModel = registerElement(
|
|
90
|
+
menuConfig
|
|
91
|
+
);
|
|
92
|
+
if (menuConfig.submenus) {
|
|
93
|
+
return {
|
|
94
|
+
...menuModel,
|
|
95
|
+
submenus: processMenus(menuConfig.submenus)
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
return menuModel;
|
|
99
|
+
});
|
|
100
|
+
};
|
|
101
|
+
const config = { ...appShellConfig };
|
|
102
|
+
let viewsModel;
|
|
103
|
+
if (appShellConfig.mainPanel?.views) {
|
|
104
|
+
viewsModel = processViews(appShellConfig.mainPanel.views);
|
|
105
|
+
config.mainPanel = {
|
|
106
|
+
...appShellConfig.mainPanel,
|
|
107
|
+
views: viewsModel
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
if (appShellConfig.menu) {
|
|
111
|
+
let menusModel = processMenus(appShellConfig.menu);
|
|
112
|
+
if (viewsModel) {
|
|
113
|
+
const routeConditionsMap = createRouteConditionsMap(viewsModel);
|
|
114
|
+
menusModel = applyViewConditionsToMenus(menusModel, routeConditionsMap);
|
|
115
|
+
}
|
|
116
|
+
config.menu = menusModel;
|
|
117
|
+
}
|
|
118
|
+
if (appShellConfig.header?.actions) {
|
|
119
|
+
config.header = {
|
|
120
|
+
...appShellConfig.header,
|
|
121
|
+
actions: appShellConfig.header.actions.map(
|
|
122
|
+
(action) => registerElement(action)
|
|
123
|
+
)
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
if (appShellConfig.systemProviders) {
|
|
127
|
+
config.systemProviders = appShellConfig.systemProviders.map((provider) => ({
|
|
128
|
+
...provider,
|
|
129
|
+
key: generateKey()
|
|
130
|
+
}));
|
|
131
|
+
}
|
|
132
|
+
if (appShellConfig.providers) {
|
|
133
|
+
config.providers = appShellConfig.providers.map(
|
|
134
|
+
(provider) => registerElement(provider)
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
if (appShellConfig.services) {
|
|
138
|
+
const servicesModel = {};
|
|
139
|
+
for (const [serviceId, configs] of Object.entries(
|
|
140
|
+
appShellConfig.services
|
|
141
|
+
)) {
|
|
142
|
+
servicesModel[serviceId] = configs.map(
|
|
143
|
+
(serviceConfig) => registerElement(
|
|
144
|
+
serviceConfig
|
|
145
|
+
)
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
config.services = servicesModel;
|
|
149
|
+
}
|
|
150
|
+
return Object.freeze({
|
|
151
|
+
...config,
|
|
152
|
+
allConditions,
|
|
153
|
+
preloadedBundles: /* @__PURE__ */ new Map()
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
export {
|
|
157
|
+
processConfig as default
|
|
158
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hitachivantara/app-shell-ui",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0-next.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"private": false,
|
|
6
6
|
"author": "Hitachi Vantara UI Kit Team",
|
|
@@ -18,13 +18,13 @@
|
|
|
18
18
|
"@emotion/css": "^11.10.5",
|
|
19
19
|
"@emotion/react": "^11.10.5",
|
|
20
20
|
"@emotion/styled": "^11.10.5",
|
|
21
|
-
"@hitachivantara/app-shell-events": "^
|
|
22
|
-
"@hitachivantara/app-shell-navigation": "^
|
|
23
|
-
"@hitachivantara/app-shell-services": "^
|
|
24
|
-
"@hitachivantara/app-shell-shared": "^
|
|
25
|
-
"@hitachivantara/uikit-react-core": "^
|
|
26
|
-
"@hitachivantara/uikit-react-icons": "^
|
|
27
|
-
"@mui/material": "^
|
|
21
|
+
"@hitachivantara/app-shell-events": "^2.0.0-next.2",
|
|
22
|
+
"@hitachivantara/app-shell-navigation": "^2.0.0-next.2",
|
|
23
|
+
"@hitachivantara/app-shell-services": "^2.0.0-next.2",
|
|
24
|
+
"@hitachivantara/app-shell-shared": "^2.0.0-next.2",
|
|
25
|
+
"@hitachivantara/uikit-react-core": "^6.0.0-next.3",
|
|
26
|
+
"@hitachivantara/uikit-react-icons": "^6.0.0-next.3",
|
|
27
|
+
"@mui/material": "^7.0.2",
|
|
28
28
|
"i18next": "^24.2.2",
|
|
29
29
|
"i18next-browser-languagedetector": "^8.0.3",
|
|
30
30
|
"react-error-boundary": "^6.0.0",
|
|
@@ -44,15 +44,15 @@
|
|
|
44
44
|
"access": "public",
|
|
45
45
|
"directory": "package"
|
|
46
46
|
},
|
|
47
|
-
"gitHead": "
|
|
47
|
+
"gitHead": "f404f47dd2c0a9d4033b9acccc87282aa9e42119",
|
|
48
48
|
"exports": {
|
|
49
49
|
".": {
|
|
50
|
-
"types": "./dist/
|
|
51
|
-
"import": "./dist/
|
|
52
|
-
"default": "./dist/
|
|
50
|
+
"types": "./dist/index.d.ts",
|
|
51
|
+
"import": "./dist/index.js",
|
|
52
|
+
"default": "./dist/index.js"
|
|
53
53
|
},
|
|
54
54
|
"./package.json": "./package.json"
|
|
55
55
|
},
|
|
56
56
|
"types": "./dist/types/index.d.ts",
|
|
57
|
-
"module": "dist/
|
|
57
|
+
"module": "dist/index.js"
|
|
58
58
|
}
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import { jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useContext, useState, useEffect, useMemo } from "react";
|
|
3
|
-
import { I18nContext } from "react-i18next";
|
|
4
|
-
import { HvAppShellContext, HvAppShellRuntimeContext, HvAppShellCombinedProvidersContext, CONFIG_TRANSLATIONS_NAMESPACE } from "@hitachivantara/app-shell-shared";
|
|
5
|
-
import { themes, HvProvider } from "@hitachivantara/uikit-react-core";
|
|
6
|
-
import useLocalStorage from "../../hooks/useLocalStorage.js";
|
|
7
|
-
import { addResourceBundles } from "../../i18n/index.js";
|
|
8
|
-
const AppShellProvider = ({
|
|
9
|
-
children,
|
|
10
|
-
config: localConfig,
|
|
11
|
-
configUrl
|
|
12
|
-
}) => {
|
|
13
|
-
const { i18n } = useContext(I18nContext);
|
|
14
|
-
const { value: storedColorModeValue } = useLocalStorage("COLOR_MODE");
|
|
15
|
-
const [loadedConfig, setLoadedConfig] = useState(void 0);
|
|
16
|
-
const [hasError, setHasError] = useState(false);
|
|
17
|
-
useEffect(() => {
|
|
18
|
-
if (!localConfig && configUrl) {
|
|
19
|
-
fetch(new URL(configUrl)).then((result) => {
|
|
20
|
-
return result.json();
|
|
21
|
-
}).then((data) => setLoadedConfig(data)).catch((e) => {
|
|
22
|
-
console.error(
|
|
23
|
-
`It was not possible to obtain the context from: ${configUrl}`,
|
|
24
|
-
e
|
|
25
|
-
);
|
|
26
|
-
setLoadedConfig(void 0);
|
|
27
|
-
setHasError(true);
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
}, [localConfig, configUrl]);
|
|
31
|
-
const theConfig = useMemo(
|
|
32
|
-
() => localConfig ?? loadedConfig,
|
|
33
|
-
[localConfig, loadedConfig]
|
|
34
|
-
);
|
|
35
|
-
if (hasError) {
|
|
36
|
-
throw Error("It was not possible to obtain the configuration");
|
|
37
|
-
}
|
|
38
|
-
if (theConfig?.translations) {
|
|
39
|
-
addResourceBundles(
|
|
40
|
-
i18n,
|
|
41
|
-
theConfig.translations,
|
|
42
|
-
CONFIG_TRANSLATIONS_NAMESPACE
|
|
43
|
-
);
|
|
44
|
-
}
|
|
45
|
-
const [themes$1, setThemes] = useState(void 0);
|
|
46
|
-
const [providers, setProviders] = useState(void 0);
|
|
47
|
-
useEffect(() => {
|
|
48
|
-
if (theConfig?.theming?.themes) {
|
|
49
|
-
Promise.all(
|
|
50
|
-
theConfig.theming.themes?.map((bundle) => {
|
|
51
|
-
return themes[bundle] ?? import(
|
|
52
|
-
/* @vite-ignore */
|
|
53
|
-
bundle
|
|
54
|
-
).then((module) => module.default).catch((e) => {
|
|
55
|
-
console.error(`Import of theme bundle ${bundle} failed! ${e}`);
|
|
56
|
-
});
|
|
57
|
-
})
|
|
58
|
-
).then((loadedThemes) => {
|
|
59
|
-
setThemes(loadedThemes.filter((theme) => !!theme));
|
|
60
|
-
}).catch((e) => {
|
|
61
|
-
console.error(`Import of themes failed! ${e}`);
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
}, [theConfig?.theming?.themes]);
|
|
65
|
-
useEffect(() => {
|
|
66
|
-
if (theConfig?.providers) {
|
|
67
|
-
Promise.all(
|
|
68
|
-
theConfig.providers.map((provider) => {
|
|
69
|
-
return import(
|
|
70
|
-
/* @vite-ignore */
|
|
71
|
-
provider.bundle
|
|
72
|
-
).then((module) => ({
|
|
73
|
-
component: module.default,
|
|
74
|
-
config: provider.config
|
|
75
|
-
})).catch((e) => {
|
|
76
|
-
console.error(
|
|
77
|
-
`Import of provider '${provider.bundle}' failed! ${e}`
|
|
78
|
-
);
|
|
79
|
-
});
|
|
80
|
-
})
|
|
81
|
-
).then(
|
|
82
|
-
(loadedProviders) => setProviders(loadedProviders.filter((provider) => !!provider))
|
|
83
|
-
).catch((e) => {
|
|
84
|
-
console.error(`Import of providers failed!`, e);
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
}, [theConfig?.providers]);
|
|
88
|
-
const runtimeContext = useMemo(
|
|
89
|
-
() => ({
|
|
90
|
-
i18n
|
|
91
|
-
}),
|
|
92
|
-
[i18n]
|
|
93
|
-
);
|
|
94
|
-
const providersContext = useMemo(
|
|
95
|
-
() => ({
|
|
96
|
-
providers
|
|
97
|
-
}),
|
|
98
|
-
[providers]
|
|
99
|
-
);
|
|
100
|
-
if (!theConfig || theConfig.theming?.themes && !themes$1 || theConfig.providers != null && providers === void 0) {
|
|
101
|
-
return null;
|
|
102
|
-
}
|
|
103
|
-
return /* @__PURE__ */ jsx(HvAppShellContext.Provider, { value: theConfig, children: /* @__PURE__ */ jsx(HvAppShellRuntimeContext.Provider, { value: runtimeContext, children: /* @__PURE__ */ jsx(
|
|
104
|
-
HvProvider,
|
|
105
|
-
{
|
|
106
|
-
themes: themes$1,
|
|
107
|
-
theme: theConfig.theming?.theme,
|
|
108
|
-
colorMode: storedColorModeValue ?? theConfig.theming?.colorMode,
|
|
109
|
-
children: /* @__PURE__ */ jsx(HvAppShellCombinedProvidersContext.Provider, { value: providersContext, children })
|
|
110
|
-
}
|
|
111
|
-
) }) });
|
|
112
|
-
};
|
|
113
|
-
export {
|
|
114
|
-
AppShellProvider as default
|
|
115
|
-
};
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Suspense } from "react";
|
|
3
|
-
import { ErrorBoundary } from "react-error-boundary";
|
|
4
|
-
import { Outlet } from "react-router-dom";
|
|
5
|
-
import ServiceManagerProvider from "@hitachivantara/app-shell-services";
|
|
6
|
-
import { BannerProvider } from "../../providers/BannerProvider.js";
|
|
7
|
-
import { NavigationProvider } from "../../providers/NavigationProvider.js";
|
|
8
|
-
import CombinedProviders from "../../utils/CombinedProviders.js";
|
|
9
|
-
import LoadingPage from "../LoadingPage/LoadingPage.js";
|
|
10
|
-
import CustomHooksInitializer from "../../components/CustomHooksInitializer/CustomHooksInitializer.js";
|
|
11
|
-
import Header from "../../components/layout/Header/Header.js";
|
|
12
|
-
import Main from "../../components/layout/Main/Main.js";
|
|
13
|
-
import GenericError from "../GenericError/GenericError.js";
|
|
14
|
-
const Root = ({ providers, services }) => /* @__PURE__ */ jsx(ErrorBoundary, { fallback: /* @__PURE__ */ jsx(GenericError, { fullPage: true }), children: /* @__PURE__ */ jsx(ServiceManagerProvider, { config: { services }, children: /* @__PURE__ */ jsx(CombinedProviders, { providers, children: /* @__PURE__ */ jsx(NavigationProvider, { children: /* @__PURE__ */ jsxs(BannerProvider, { children: [
|
|
15
|
-
/* @__PURE__ */ jsx(CustomHooksInitializer, {}),
|
|
16
|
-
/* @__PURE__ */ jsx(Header, {}),
|
|
17
|
-
/* @__PURE__ */ jsx(Main, { children: /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(LoadingPage, {}), children: /* @__PURE__ */ jsx(Outlet, {}) }) })
|
|
18
|
-
] }) }) }) }) });
|
|
19
|
-
export {
|
|
20
|
-
Root as default
|
|
21
|
-
};
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useCallback } from "react";
|
|
3
|
-
const CombinedProviders = ({
|
|
4
|
-
providers,
|
|
5
|
-
children: mainChildren
|
|
6
|
-
}) => {
|
|
7
|
-
const Combined = useCallback(
|
|
8
|
-
({ children }) => {
|
|
9
|
-
let result = children;
|
|
10
|
-
if (providers && providers.length > 0) {
|
|
11
|
-
result = providers.reduceRight((Acc, { component: Curr, config }) => {
|
|
12
|
-
return /* @__PURE__ */ jsx(Curr, { ...config, children: Acc });
|
|
13
|
-
}, children);
|
|
14
|
-
}
|
|
15
|
-
return result;
|
|
16
|
-
},
|
|
17
|
-
[providers]
|
|
18
|
-
);
|
|
19
|
-
return /* @__PURE__ */ jsx(Combined, { children: mainChildren });
|
|
20
|
-
};
|
|
21
|
-
export {
|
|
22
|
-
CombinedProviders as default
|
|
23
|
-
};
|
|
File without changes
|
|
File without changes
|
/package/dist/{esm/components → components}/CustomHooksInitializer/CustomHooksInitializer.js
RENAMED
|
File without changes
|
|
File without changes
|