@genesislcap/blank-app-seed 3.33.3 → 3.34.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/.genx/package.json +1 -1
- package/.genx/prompts/api.js +2 -9
- package/.genx/static.js +0 -1
- package/.genx/versions.json +3 -3
- package/.gitignore +1 -0
- package/CHANGELOG.md +30 -0
- package/README.md +4 -4
- package/client-tmp/react/package.json +22 -7
- package/client-tmp/react/public/favicon.ico +0 -0
- package/client-tmp/react/public/index.html +13 -0
- package/client-tmp/react/src/App.tsx +95 -68
- package/client-tmp/react/src/config.ts +2 -16
- package/client-tmp/react/src/custom-elements.d.ts +3 -1
- package/client-tmp/react/src/environments/environment.prod.ts +8 -0
- package/client-tmp/react/src/environments/environment.ts +9 -0
- package/client-tmp/react/src/guards/ProtectedGuard.tsx +64 -0
- package/client-tmp/react/src/helpers/hasPermissionHelper.tsx +10 -0
- package/client-tmp/react/src/helpers/isAuthenticatedHelper.tsx +14 -0
- package/client-tmp/react/src/helpers/isConnectedHelper.tsx +16 -0
- package/client-tmp/react/src/layouts/blank/BlankLayout.tsx +1 -1
- package/client-tmp/react/src/layouts/default/DefaultLayout.tsx +26 -15
- package/client-tmp/react/src/main.tsx +21 -5
- package/client-tmp/react/src/pages/NotFoundPage/NotFoundPage.css +0 -0
- package/client-tmp/react/src/pages/NotFoundPage/NotFoundPage.tsx +14 -0
- package/client-tmp/react/src/pages/NotPermittedPage/NotPermittedPage.test.tsx +1 -1
- package/client-tmp/react/src/pages/NotPermittedPage/NotPermittedPage.tsx +1 -1
- package/client-tmp/react/src/pbc/README.md +7 -0
- package/client-tmp/react/src/pbc/container.tsx +44 -0
- package/client-tmp/react/src/pbc/elementsRenderer.tsx +40 -0
- package/client-tmp/react/src/pbc/utils.ts +121 -0
- package/client-tmp/react/src/services/store.service.ts +48 -0
- package/client-tmp/react/src/share/foundation-login.ts +13 -6
- package/client-tmp/react/src/share/genesis-components.ts +49 -23
- package/client-tmp/react/src/store/AuthContext.tsx +0 -2
- package/client-tmp/react/src/store/RoutesContext.tsx +74 -0
- package/client-tmp/react/src/types/LayoutName.ts +3 -0
- package/client-tmp/react/src/types/RouteLayouts.ts +3 -1
- package/client-tmp/react/src/utils/getLayoutNameByRoute.ts +5 -0
- package/client-tmp/react/src/utils/history.ts +4 -2
- package/client-tmp/react/src/utils/index.ts +2 -1
- package/client-tmp/react/test/e2e/fixture.ts +1 -1
- package/client-tmp/react/tsconfig.app.json +1 -22
- package/client-tmp/react/tsconfig.json +30 -10
- package/client-tmp/react/vite.config.ts +26 -15
- package/client-tmp/react/webpack.config.js +103 -0
- package/package.json +1 -1
- package/testData/excel/.gitkeep +0 -0
- package/client-tmp/react/env.development.json +0 -3
- package/client-tmp/react/src/guards/AuthGuard.tsx +0 -32
- package/client-tmp/react/src/guards/PermissionsGuard.tsx +0 -37
- package/client-tmp/react/src/index.ts +0 -21
- package/client-tmp/react/src/reportWebVitals.ts +0 -13
package/.genx/package.json
CHANGED
package/.genx/prompts/api.js
CHANGED
|
@@ -7,19 +7,12 @@ const ssoIntro = () => console.log(TEXTS.INTRO_API_SSO);
|
|
|
7
7
|
module.exports = async (inquirer, prevAns = {}) => {
|
|
8
8
|
apiHostIntro();
|
|
9
9
|
const { apiHost = prevAns.apiHost } = await inquirer.prompt([
|
|
10
|
-
{
|
|
11
|
-
name: 'setApiHost',
|
|
12
|
-
type: 'confirm',
|
|
13
|
-
message: TEXTS.MESSAGE_API_SET_HOST,
|
|
14
|
-
when: !prevAns.apiHost,
|
|
15
|
-
default: true,
|
|
16
|
-
},
|
|
17
10
|
{
|
|
18
11
|
name: 'apiHost',
|
|
19
12
|
type: 'input',
|
|
20
13
|
message: TEXTS.MESSAGE_API_HOST,
|
|
21
|
-
when:
|
|
22
|
-
default:
|
|
14
|
+
when: !prevAns.apiHost,
|
|
15
|
+
default: 'ws://localhost:9064',
|
|
23
16
|
validate: websocketValidator,
|
|
24
17
|
},
|
|
25
18
|
]);
|
package/.genx/static.js
CHANGED
|
@@ -67,7 +67,6 @@ const TEXTS = {
|
|
|
67
67
|
'You can override the default Genesis server URL used during local developent.',
|
|
68
68
|
INTRO_API_SSO:
|
|
69
69
|
'Optionally, you can enable the SSO function, which will redirect to identity provider before starting the application (given we only have one identity provider).',
|
|
70
|
-
MESSAGE_API_SET_HOST: 'Set API Host',
|
|
71
70
|
MESSAGE_API_HOST: 'API Host (with WebSocket prefix and suffix if any)',
|
|
72
71
|
MESSAGE_API_SSO: 'Init SSO connection before loading application',
|
|
73
72
|
MESSAGE_SERVER_DESCRIPTION: 'Project Description',
|
package/.genx/versions.json
CHANGED
package/.gitignore
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [3.34.0](https://github.com/genesiscommunitysuccess/blank-app-seed/compare/v3.33.3...v3.34.0) (2024-11-01)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* 8.5 release (#374) 6317469
|
|
9
|
+
* add genesis launcher (#356) 236417d
|
|
10
|
+
* add webpack builder in react (#350) 69c4c6b, closes FUI-2173 FUI-2173 FUI-2173 FUI-2157 FUI-2157 origin/ak/FUI-2173 ak/FUI-2157 FUI-2157 FUI-2157 FUI-2140 FUI-2140 FUI-2140 FUI-2140 FUI-2140 FUI-2140 FUI-2140 FUI-2140 FUI-2140 FUI-2140 FUI-2140 FUI-2140 FUI-2140 FUI-2140 FUI-2140 FUI-2140 FUI-2140
|
|
11
|
+
* adding support for comments/todos in generated UI files GENC-857 (#364) ba999e8
|
|
12
|
+
* allow excluding Gradle wrappers GENC-824 (#357) 5d90d1d
|
|
13
|
+
* allow to simply control layout persistence in dev [FUI-2211](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/2211) / GENC-871 (#363) c6fd6f5
|
|
14
|
+
* pbc support in react [FUI-2140](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/2140) (#347) 4c41243, closes FUI-2173 FUI-2173 FUI-2173 FUI-2157 FUI-2157 origin/ak/FUI-2173 ak/FUI-2157 FUI-2157 FUI-2157
|
|
15
|
+
* update react version (#358) 22bb0ad
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
20
|
+
* automated dependency version update [skip-ci] [PSD-9](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/9) (#354) d5b0de0
|
|
21
|
+
* automated dependency version update [skip-ci] [PSD-9](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/9) (#355) a33c5e8
|
|
22
|
+
* home page url - react (#369) 388cf04
|
|
23
|
+
* ignore project-zips folder CIDE-53 (#360) ddb86d5
|
|
24
|
+
* reduce apiHost steps when using genx in prompt mode - [FUI-2207](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/2207) (#343) f6ce411
|
|
25
|
+
* reformat ReadMe layout & allow markdown in description GENC-845 (#361) a1b8972
|
|
26
|
+
* updating server version information for Auth [PSD-0](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/0) 6f17702
|
|
27
|
+
* updating server version information for Auth [PSD-0](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/0) 31595f3
|
|
28
|
+
* updating server version information for Auth [PSD-0](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/0) 3ed1109
|
|
29
|
+
* updating server version information for GSF [PSD-0](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/0) d26e635
|
|
30
|
+
* updating server version information for GSF [PSD-0](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/0) 9dbc341
|
|
31
|
+
* updating server version information for GSF [PSD-0](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/0) a324936
|
|
32
|
+
|
|
3
33
|
## [3.33.3](https://github.com/genesiscommunitysuccess/blank-app-seed/compare/v3.33.2...v3.33.3) (2024-10-30)
|
|
4
34
|
|
|
5
35
|
|
package/README.md
CHANGED
|
@@ -31,9 +31,9 @@ npx -y @genesislcap/genx@latest init myapp -x -s ./blank-app-seed --enableSSO --
|
|
|
31
31
|
```
|
|
32
32
|
}}
|
|
33
33
|
|
|
34
|
-
#
|
|
34
|
+
# Getting started with development
|
|
35
35
|
|
|
36
|
-
## Next
|
|
36
|
+
## Next steps
|
|
37
37
|
|
|
38
38
|
To get a simple application running check the [Quick Start](https://learn.genesis.global/docs/getting-started/quick-start/) guide.
|
|
39
39
|
|
|
@@ -54,7 +54,7 @@ It is built using a DSL-like definition based on the Kotlin language: GPAL.
|
|
|
54
54
|
|
|
55
55
|
When first opening the project, if you receive a notification from IntelliJ IDE detecting Gradle project select the option to 'Load as gradle project'.
|
|
56
56
|
|
|
57
|
-
### Web
|
|
57
|
+
### Web client
|
|
58
58
|
|
|
59
59
|
The Web client for this project can be found [here](./client/README.md). It is built using Genesis's next
|
|
60
60
|
generation web development framework, which is based on Web Components.
|
|
@@ -66,4 +66,4 @@ This is free and unencumbered software released into the public domain. For full
|
|
|
66
66
|
**NOTE** This project uses licensed components listed in the next section, thus licenses for those components are required during development.
|
|
67
67
|
|
|
68
68
|
## Licensed components
|
|
69
|
-
Genesis
|
|
69
|
+
Genesis application platform
|
|
@@ -9,10 +9,13 @@
|
|
|
9
9
|
"baseline": "npm run clean && npm run bootstrap",
|
|
10
10
|
"bootstrap": "npm i --legacy-peer-deps",
|
|
11
11
|
"bootstrap:ci": "npm ci --no-fund --no-audit",
|
|
12
|
-
"build": "vite build",
|
|
13
12
|
"build:stats": "npm run build --stats-json",
|
|
14
13
|
"clean": "genx clean dist node_modules",
|
|
15
|
-
"dev": "
|
|
14
|
+
"dev": "webpack serve --mode development",
|
|
15
|
+
"build": "webpack --mode production",
|
|
16
|
+
"stats": "webpack --mode production --json > stats.json",
|
|
17
|
+
"build:vite": "vite build",
|
|
18
|
+
"dev:vite": "vite build && vite preview",
|
|
16
19
|
"dev:docker": "npm run dev -- --host 0.0.0.0",
|
|
17
20
|
"dev:no-open": "NO_OPEN=true npm run dev",
|
|
18
21
|
"dev:intellij": "npm run dev",
|
|
@@ -36,17 +39,21 @@
|
|
|
36
39
|
"@ag-grid-enterprise/core": "29.2.0",
|
|
37
40
|
"@ag-grid-enterprise/row-grouping": "29.2.0",
|
|
38
41
|
"@ag-grid-enterprise/server-side-row-model": "29.2.0",
|
|
42
|
+
"@genesislcap/foundation-comms": "{{versions.UI}}",
|
|
43
|
+
"@genesislcap/foundation-entity-management": "{{versions.UI}}",
|
|
39
44
|
{{#if FDC3.includeDependencies}}
|
|
40
45
|
"@genesislcap/foundation-fdc3": "{{versions.UI}}",
|
|
41
46
|
{{/if}}
|
|
42
|
-
"@genesislcap/foundation-comms": "{{versions.UI}}",
|
|
43
|
-
"@genesislcap/foundation-login": "{{versions.UI}}",
|
|
44
|
-
"@genesislcap/foundation-entity-management": "{{versions.UI}}",
|
|
45
47
|
"@genesislcap/foundation-header": "{{versions.UI}}",
|
|
48
|
+
"@genesislcap/foundation-layout": "{{versions.UI}}",
|
|
49
|
+
"@genesislcap/foundation-logger": "{{versions.UI}}",
|
|
50
|
+
"@genesislcap/foundation-login": "{{versions.UI}}",
|
|
51
|
+
"@genesislcap/foundation-shell": "{{versions.UI}}",
|
|
46
52
|
"@genesislcap/foundation-ui": "{{versions.UI}}",
|
|
53
|
+
"@genesislcap/foundation-utils": "{{versions.UI}}",
|
|
47
54
|
"@genesislcap/rapid-design-system": "{{versions.UI}}",
|
|
48
55
|
"@genesislcap/rapid-grid-pro": "{{versions.UI}}",
|
|
49
|
-
"@genesislcap/
|
|
56
|
+
"@genesislcap/web-core": "{{versions.UI}}",
|
|
50
57
|
"@genesislcap/g2plot-chart": "{{versions.UI}}",
|
|
51
58
|
"history": "^5.3.0",
|
|
52
59
|
"react": "^19.0.0-rc-ed966dac-20241007",
|
|
@@ -67,6 +74,7 @@
|
|
|
67
74
|
"@testing-library/dom": "^10.4.0",
|
|
68
75
|
"@testing-library/jest-dom": "^6.5.0",
|
|
69
76
|
"@testing-library/react": "^16.0.0",
|
|
77
|
+
"@types/css-modules": "^1.0.5",
|
|
70
78
|
"@types/jest": "^29.5.12",
|
|
71
79
|
"@types/node": "^20.14.10",
|
|
72
80
|
"@types/react": "npm:types-react@alpha",
|
|
@@ -74,16 +82,23 @@
|
|
|
74
82
|
"@typescript-eslint/eslint-plugin": "^7.13.1",
|
|
75
83
|
"@typescript-eslint/parser": "^7.13.1",
|
|
76
84
|
"@vitejs/plugin-react": "^4.3.1",
|
|
85
|
+
"babel-loader": "^9.2.1",
|
|
77
86
|
"babel-plugin-react-require": "^4.0.3",
|
|
87
|
+
"dotenv-webpack": "^8.1.0",
|
|
78
88
|
"eslint": "^8.57.0",
|
|
79
89
|
"eslint-plugin-react-hooks": "^4.6.2",
|
|
80
90
|
"eslint-plugin-react-refresh": "^0.4.7",
|
|
91
|
+
"file-loader": "^6.2.0",
|
|
81
92
|
"jest": "^29.7.0",
|
|
82
93
|
"jest-environment-jsdom": "^29.7.0",
|
|
83
94
|
"ts-jest": "^29.2.5",
|
|
84
95
|
"ts-node": "^10.9.2",
|
|
85
96
|
"typescript": "^5.2.2",
|
|
86
|
-
"vite": "^5.3.1"
|
|
97
|
+
"vite": "^5.3.1",
|
|
98
|
+
"vite-plugin-tsconfig-paths": "^1.4.1",
|
|
99
|
+
"webpack": "^5.94.0",
|
|
100
|
+
"webpack-cli": "^5.1.4",
|
|
101
|
+
"webpack-dev-server": "^5.1.0"
|
|
87
102
|
},
|
|
88
103
|
"overrides": {
|
|
89
104
|
"@types/react": "npm:types-react@alpha",
|
|
Binary file
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>{{capitalCase appName}}</title>
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<div id="root"></div>
|
|
11
|
+
<script src="/bundle.js"></script>
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|
|
@@ -1,31 +1,75 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import { unstable_HistoryRouter as HistoryRouter, Routes, Route, useLocation } from 'react-router-dom';
|
|
1
3
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
history,
|
|
5
|
+
setApiHost,
|
|
6
|
+
getLayoutNameByRoute,
|
|
7
|
+
{{#if FDC3.channels.length~}}
|
|
8
|
+
listenToChannel,
|
|
9
|
+
onFDC3Ready,
|
|
10
|
+
{{/if}}
|
|
11
|
+
} from './utils';
|
|
12
|
+
import { customEventFactory, registerStylesTarget } from '@/pbc/utils';
|
|
9
13
|
import LayoutWrapper from './layouts/LayoutWrapper';
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import PermissionsGuard from './guards/PermissionsGuard';
|
|
14
|
+
import LayoutName from '@/types/LayoutName';
|
|
15
|
+
import { AUTH_PATH, routeLayouts } from './config';
|
|
13
16
|
import { AuthProvider } from './store/AuthContext';
|
|
14
|
-
|
|
17
|
+
import { RoutesProvider, useRoutesContext } from './store/RoutesContext';
|
|
15
18
|
import AuthPage from './pages/AuthPage/AuthPage';
|
|
16
|
-
import
|
|
17
|
-
{
|
|
18
|
-
import
|
|
19
|
-
{
|
|
20
|
-
|
|
21
|
-
// Genesis Components
|
|
22
|
-
import './share/genesis-components';
|
|
19
|
+
import { registerComponents as genesisRegisterComponents } from './share/genesis-components';
|
|
20
|
+
import { configureFoundationLogin } from './share/foundation-login';
|
|
21
|
+
import ProtectedGuard from './guards/ProtectedGuard';
|
|
22
|
+
import { storeService } from '@/services/store.service';
|
|
23
23
|
|
|
24
|
-
const
|
|
24
|
+
const DynamicLayout = () => {
|
|
25
25
|
const location = useLocation();
|
|
26
|
-
const
|
|
27
|
-
{
|
|
26
|
+
const [layoutName, setLayoutName] = useState<LayoutName>(routeLayouts[location.pathname] || 'default');
|
|
27
|
+
const handleRouteChange = (location: any) => {
|
|
28
|
+
setLayoutName(getLayoutNameByRoute(location.pathname));
|
|
29
|
+
};
|
|
30
|
+
const route = useRoutesContext().find((r) => r.path === location.pathname);
|
|
31
|
+
let pageComponent;
|
|
32
|
+
let content;
|
|
33
|
+
|
|
28
34
|
useEffect(() => {
|
|
35
|
+
handleRouteChange(location);
|
|
36
|
+
const unlisten = history.listen(handleRouteChange);
|
|
37
|
+
|
|
38
|
+
return () => {
|
|
39
|
+
unlisten();
|
|
40
|
+
}
|
|
41
|
+
}, [location]);
|
|
42
|
+
|
|
43
|
+
if (route) {
|
|
44
|
+
pageComponent = route.element;
|
|
45
|
+
} else {
|
|
46
|
+
pageComponent = <AuthPage />;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (location.pathname === `/${AUTH_PATH}` || location.pathname === '/') {
|
|
50
|
+
content = pageComponent;
|
|
51
|
+
} else {
|
|
52
|
+
content = <ProtectedGuard>{pageComponent}</ProtectedGuard>
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return <LayoutWrapper layout={layoutName}>{content}</LayoutWrapper>
|
|
56
|
+
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
interface AppProps {
|
|
60
|
+
rootElement: HTMLElement;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const App: React.FC<AppProps> = ({ rootElement }) => {
|
|
64
|
+
const [isStoreConnected, setIsStoreConnected] = useState(false);
|
|
65
|
+
const dispatchCustomEvent = (type: string, detail?: any) => {
|
|
66
|
+
rootElement.dispatchEvent(customEventFactory(type, detail));
|
|
67
|
+
};
|
|
68
|
+
const handleStoreConnected = (event: CustomEvent) => {
|
|
69
|
+
storeService.onConnected(event);
|
|
70
|
+
};
|
|
71
|
+
{{#if FDC3.channels.length~}}
|
|
72
|
+
const FDC3ReadyHandler = () => {
|
|
29
73
|
{{#each FDC3.channels}}
|
|
30
74
|
listenToChannel('{{this.name}}', '{{this.type}}', (result) => {
|
|
31
75
|
console.log('Received FDC3 channel message on: {{this.name}} channel, type: {{this.type}}', result);
|
|
@@ -33,61 +77,44 @@ const LayoutWithLocation = () => {
|
|
|
33
77
|
// E.g. open a modal or route to specific page: Route.path.push(`[Route name]`);
|
|
34
78
|
});
|
|
35
79
|
{{/each}}
|
|
36
|
-
|
|
37
|
-
return () => {
|
|
38
|
-
console.log('Component is being unmounted');
|
|
39
|
-
};
|
|
40
|
-
}, []);
|
|
80
|
+
};
|
|
41
81
|
{{/if}}
|
|
42
82
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
switch (location.pathname) {
|
|
47
|
-
case `/${AUTH_PATH}`:
|
|
48
|
-
pageComponent = <AuthPage />;
|
|
49
|
-
break;
|
|
50
|
-
case `/${NOT_PERMITTED_PATH}`:
|
|
51
|
-
pageComponent = <NotPermittedPage />;
|
|
52
|
-
break;
|
|
53
|
-
{{#each routes}}
|
|
54
|
-
case '/{{kebabCase this.name}}':
|
|
55
|
-
pageComponent = <{{pascalCase this.name}} />;
|
|
56
|
-
permissionCode = '{{this.permissions.viewRight}}';
|
|
57
|
-
break;
|
|
58
|
-
{{/each}}
|
|
59
|
-
default:
|
|
60
|
-
pageComponent = <AuthPage />;
|
|
61
|
-
}
|
|
83
|
+
setApiHost();
|
|
84
|
+
genesisRegisterComponents();
|
|
85
|
+
configureFoundationLogin({ router: history });
|
|
62
86
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
</AuthGuard>
|
|
75
|
-
);
|
|
76
|
-
}
|
|
77
|
-
};
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
registerStylesTarget(document.body, 'main');
|
|
89
|
+
{{#if FDC3.channels.length~}}
|
|
90
|
+
onFDC3Ready(FDC3ReadyHandler);
|
|
91
|
+
{{/if}}
|
|
92
|
+
if (!isStoreConnected) {
|
|
93
|
+
rootElement.addEventListener('store-connected', handleStoreConnected);
|
|
94
|
+
dispatchCustomEvent('store-connected', rootElement);
|
|
95
|
+
dispatchCustomEvent('store-ready', true);
|
|
96
|
+
setIsStoreConnected(true);
|
|
97
|
+
}
|
|
78
98
|
|
|
79
|
-
|
|
80
|
-
|
|
99
|
+
return () => {
|
|
100
|
+
if (isStoreConnected) {
|
|
101
|
+
rootElement.removeEventListener('store-connected', handleStoreConnected);
|
|
102
|
+
dispatchCustomEvent('store-disconnected');
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
}, [isStoreConnected]);
|
|
81
106
|
|
|
82
107
|
return (
|
|
83
108
|
<AuthProvider>
|
|
84
|
-
<
|
|
85
|
-
<
|
|
86
|
-
<
|
|
87
|
-
|
|
88
|
-
|
|
109
|
+
<RoutesProvider>
|
|
110
|
+
<HistoryRouter history={history as any}>
|
|
111
|
+
<Routes>
|
|
112
|
+
<Route path="*" element={<DynamicLayout />} />
|
|
113
|
+
</Routes>
|
|
114
|
+
</HistoryRouter>
|
|
115
|
+
</RoutesProvider>
|
|
89
116
|
</AuthProvider>
|
|
90
117
|
);
|
|
91
118
|
};
|
|
92
119
|
|
|
93
|
-
export default App;
|
|
120
|
+
export default App;
|
|
@@ -1,32 +1,18 @@
|
|
|
1
1
|
import { RouteLayouts } from './types/RouteLayouts';
|
|
2
|
+
import { environment } from '@environment';
|
|
2
3
|
|
|
3
4
|
export const routeLayouts: RouteLayouts = {
|
|
4
|
-
'/auth-mock': 'blank',
|
|
5
5
|
'/auth': 'blank',
|
|
6
6
|
'/': 'blank',
|
|
7
7
|
};
|
|
8
8
|
|
|
9
|
-
import type { MainMenu } from './types/menu';
|
|
10
|
-
|
|
11
9
|
export const AUTH_PATH = 'auth';
|
|
12
10
|
export const NOT_PERMITTED_PATH = 'not-permitted';
|
|
13
11
|
|
|
14
12
|
export const API_DATA = {
|
|
15
|
-
URL:
|
|
13
|
+
URL: environment.API_HOST,
|
|
16
14
|
AUTH: {
|
|
17
15
|
username: '', // provide login to a user in given environment
|
|
18
16
|
password: '', // provide password to a user in given environment
|
|
19
17
|
},
|
|
20
18
|
};
|
|
21
|
-
|
|
22
|
-
export const mainMenu: MainMenu = [
|
|
23
|
-
{{#each routes}}
|
|
24
|
-
{
|
|
25
|
-
index: {{@index}},
|
|
26
|
-
path: '{{kebabCase this.name}}',
|
|
27
|
-
title: '{{#if this.title}}{{this.title}}{{else}}{{this.name}}{{/if}}',
|
|
28
|
-
icon: '{{this.icon}}',
|
|
29
|
-
variant: 'solid'
|
|
30
|
-
}{{#unless @last}},{{/unless}}
|
|
31
|
-
{{/each}}
|
|
32
|
-
];
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import React, { useState, DOMAttributes } from 'react';
|
|
2
2
|
|
|
3
|
-
type CustomElement<T = HTMLElement
|
|
3
|
+
type CustomElement<T = React.HTMLAttributes<HTMLElement>> = Partial<T & DOMAttributes<T> & { [key: string]: any }>;
|
|
4
4
|
|
|
5
5
|
declare module "react/jsx-runtime" {
|
|
6
6
|
namespace JSX {
|
|
7
7
|
interface IntrinsicElements {
|
|
8
|
+
'rapid-design-system-provider': CustomElement;
|
|
8
9
|
'entity-management': CustomElement;
|
|
9
10
|
'foundation-form': CustomElement;
|
|
10
11
|
'rapid-grid-pro': CustomElement;
|
|
@@ -16,6 +17,7 @@ declare module "react/jsx-runtime" {
|
|
|
16
17
|
'rapid-layout': CustomElement;
|
|
17
18
|
'rapid-layout-region': CustomElement;
|
|
18
19
|
'rapid-layout-item': CustomElement;
|
|
20
|
+
'foundation-header': CustomElement;
|
|
19
21
|
}
|
|
20
22
|
}
|
|
21
23
|
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { useState, useEffect, ReactNode } from 'react';
|
|
2
|
+
import { RouteObject } from 'react-router';
|
|
3
|
+
import isConnectedHelper from '@/helpers/isConnectedHelper';
|
|
4
|
+
import isAuthenticatedHelper from '@/helpers/isAuthenticatedHelper';
|
|
5
|
+
import hasPermissionHelper from '@/helpers/hasPermissionHelper';
|
|
6
|
+
import { useRoutesContext } from '@/store/RoutesContext';
|
|
7
|
+
import { NOT_PERMITTED_PATH, AUTH_PATH } from '@/config';
|
|
8
|
+
|
|
9
|
+
enum PermissionState {
|
|
10
|
+
ALLOWED = 'allowed',
|
|
11
|
+
DENIED = 'denied',
|
|
12
|
+
UNKNOWN = 'unknown',
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const redirectUrlByPermissionState: { [key in Partial<PermissionState>]?: string } = {
|
|
16
|
+
[PermissionState.DENIED]: NOT_PERMITTED_PATH,
|
|
17
|
+
[PermissionState.UNKNOWN]: AUTH_PATH,
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
type ExtendedRouteObject = RouteObject & {
|
|
21
|
+
data?: {
|
|
22
|
+
permissionCode?: string;
|
|
23
|
+
};
|
|
24
|
+
path: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const ProtectedGuard: React.FC<{ children: ReactNode }> = ({ children }: { children: ReactNode }) => {
|
|
28
|
+
const routes = useRoutesContext() as ExtendedRouteObject[];
|
|
29
|
+
const [isConnected, setIsConnected] = useState<boolean | null>(null);
|
|
30
|
+
const isAuthenticated: boolean | null = null;
|
|
31
|
+
const route = routes.find(({ path }) => path === location.pathname);
|
|
32
|
+
const hasPermission = route?.data?.permissionCode ? hasPermissionHelper(route.data?.permissionCode) : true;
|
|
33
|
+
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
isConnectedHelper().then((connectedState: boolean): void => {
|
|
36
|
+
setIsConnected(connectedState);
|
|
37
|
+
});
|
|
38
|
+
}, []);
|
|
39
|
+
|
|
40
|
+
useEffect((): void => {
|
|
41
|
+
if (isConnected === null) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const isAuthenticated = isAuthenticatedHelper();
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
let permissionState;
|
|
49
|
+
|
|
50
|
+
if (!isConnected || !isAuthenticated) {
|
|
51
|
+
permissionState = PermissionState.UNKNOWN;
|
|
52
|
+
} else if (hasPermission === false) {
|
|
53
|
+
permissionState = PermissionState.DENIED;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (permissionState) {
|
|
57
|
+
window.location.href = `/${redirectUrlByPermissionState[permissionState]}`;
|
|
58
|
+
}
|
|
59
|
+
}, [routes, isConnected, isAuthenticated, hasPermission]);
|
|
60
|
+
|
|
61
|
+
return children;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export default ProtectedGuard;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { getUser } from '@genesislcap/foundation-user';
|
|
2
|
+
|
|
3
|
+
const hasPermissionHelper = (permissionCode: string | undefined): boolean => {
|
|
4
|
+
const user = getUser();
|
|
5
|
+
|
|
6
|
+
return !!(permissionCode && !user.hasPermission(permissionCode))
|
|
7
|
+
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default hasPermissionHelper;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { getUser } from '@genesislcap/foundation-user';
|
|
2
|
+
|
|
3
|
+
const isAuthenticatedHelper = (): boolean => {
|
|
4
|
+
const user = getUser();
|
|
5
|
+
|
|
6
|
+
if (!user.isAuthenticated) {
|
|
7
|
+
user.trackPath();
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return true;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default isAuthenticatedHelper;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { getConnect } from '@genesislcap/foundation-comms';
|
|
2
|
+
|
|
3
|
+
const isConnectedHelper = (): Promise<boolean> => {
|
|
4
|
+
const connect = getConnect();
|
|
5
|
+
const hostUrl = sessionStorage.getItem('hostUrl');
|
|
6
|
+
|
|
7
|
+
if (connect.isConnected) {
|
|
8
|
+
return new Promise((resolve) => resolve(true));
|
|
9
|
+
}
|
|
10
|
+
if (!hostUrl) {
|
|
11
|
+
return new Promise((resolve) => resolve(false));
|
|
12
|
+
}
|
|
13
|
+
return connect.connect(hostUrl);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export default isConnectedHelper;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { ReactNode, useEffect, useRef } from 'react';
|
|
2
2
|
import { configureDesignSystem } from '@genesislcap/foundation-ui';
|
|
3
3
|
import styles from './BlankLayout.module.css';
|
|
4
|
-
import * as designTokens from '
|
|
4
|
+
import * as designTokens from '@/styles/design-tokens.json';
|
|
5
5
|
|
|
6
6
|
interface BlankLayoutProps {
|
|
7
7
|
children: ReactNode;
|