@ebay/muse-lib-react 1.3.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.
Files changed (94) hide show
  1. package/README.md +19 -0
  2. package/build/dev/asset-manifest.json +11 -0
  3. package/build/dev/favicon.png +0 -0
  4. package/build/dev/lib-manifest.json +3374 -0
  5. package/build/dev/main.js +75839 -0
  6. package/build/dev/main.js.map +1 -0
  7. package/build/dev/muse.d.ts +170 -0
  8. package/build/dev/static/media/logo.b23b880b0dac2229042c.png +0 -0
  9. package/build/dev/static/media/subAppLoading2.bf08007b83457287ade1cedb71bc70f7.svg +7 -0
  10. package/build/dist/asset-manifest.json +11 -0
  11. package/build/dist/favicon.png +0 -0
  12. package/build/dist/lib-manifest.json +3603 -0
  13. package/build/dist/main.js +3 -0
  14. package/build/dist/main.js.LICENSE.txt +134 -0
  15. package/build/dist/main.js.map +1 -0
  16. package/build/dist/muse.d.ts +170 -0
  17. package/build/dist/static/media/logo.b23b880b0dac2229042c.png +0 -0
  18. package/build/dist/static/media/subAppLoading2.bf08007b83457287ade1cedb71bc70f7.svg +7 -0
  19. package/build/test/asset-manifest.json +11 -0
  20. package/build/test/favicon.png +0 -0
  21. package/build/test/lib-manifest.json +3587 -0
  22. package/build/test/main.js +3 -0
  23. package/build/test/main.js.LICENSE.txt +134 -0
  24. package/build/test/main.js.map +1 -0
  25. package/build/test/muse.d.ts +170 -0
  26. package/build/test/static/media/logo.b23b880b0dac2229042c.png +0 -0
  27. package/build/test/static/media/subAppLoading2.bf08007b83457287ade1cedb71bc70f7.svg +7 -0
  28. package/package.json +88 -0
  29. package/src/Root.js +195 -0
  30. package/src/common/configStore.js +40 -0
  31. package/src/common/history.js +25 -0
  32. package/src/common/rootReducer.js +40 -0
  33. package/src/common/routeConfig.js +135 -0
  34. package/src/common/store.js +21 -0
  35. package/src/features/common/ErrorBoundary.js +24 -0
  36. package/src/features/common/ErrorBoundary.less +6 -0
  37. package/src/features/common/Nodes.js +20 -0
  38. package/src/features/common/PageNotFound.js +3 -0
  39. package/src/features/common/PageNotFound.less +6 -0
  40. package/src/features/common/index.js +4 -0
  41. package/src/features/common/redux/actions.js +0 -0
  42. package/src/features/common/redux/constants.js +0 -0
  43. package/src/features/common/redux/initialState.js +12 -0
  44. package/src/features/common/redux/reducer.js +24 -0
  45. package/src/features/common/route.js +9 -0
  46. package/src/features/common/style.less +3 -0
  47. package/src/features/common/useExtPoint.js +28 -0
  48. package/src/features/common/utils.js +20 -0
  49. package/src/features/home/App.js +33 -0
  50. package/src/features/home/App.less +11 -0
  51. package/src/features/home/Homepage.js +46 -0
  52. package/src/features/home/Homepage.less +63 -0
  53. package/src/features/home/index.js +2 -0
  54. package/src/features/home/redux/actions.js +0 -0
  55. package/src/features/home/redux/constants.js +0 -0
  56. package/src/features/home/redux/initialState.js +4 -0
  57. package/src/features/home/redux/reducer.js +16 -0
  58. package/src/features/home/route.js +6 -0
  59. package/src/features/home/style.less +3 -0
  60. package/src/features/sub-app/C2SProxyFailed.js +10 -0
  61. package/src/features/sub-app/C2SProxyFailed.less +19 -0
  62. package/src/features/sub-app/FixedSubAppContainer.js +142 -0
  63. package/src/features/sub-app/FixedSubAppContainer.less +12 -0
  64. package/src/features/sub-app/LoadingSkeleton.js +21 -0
  65. package/src/features/sub-app/LoadingSkeleton.less +20 -0
  66. package/src/features/sub-app/SubAppContainer.js +203 -0
  67. package/src/features/sub-app/SubAppContainer.less +29 -0
  68. package/src/features/sub-app/SubAppContext.js +4 -0
  69. package/src/features/sub-app/hooks/useParentRouteChange.js +23 -0
  70. package/src/features/sub-app/index.js +5 -0
  71. package/src/features/sub-app/redux/actions.js +1 -0
  72. package/src/features/sub-app/redux/constants.js +2 -0
  73. package/src/features/sub-app/redux/hooks.js +1 -0
  74. package/src/features/sub-app/redux/initialState.js +12 -0
  75. package/src/features/sub-app/redux/reducer.js +25 -0
  76. package/src/features/sub-app/redux/setSubAppState.js +43 -0
  77. package/src/features/sub-app/route.js +43 -0
  78. package/src/features/sub-app/style.less +5 -0
  79. package/src/features/sub-app/subAppLoading.svg +7 -0
  80. package/src/features/sub-app/subAppLoading2.html +83 -0
  81. package/src/features/sub-app/subAppLoading2.svg +7 -0
  82. package/src/features/sub-app/subAppLoading3.svg +7 -0
  83. package/src/features/sub-app/subAppLoading4.svg +7 -0
  84. package/src/features/sub-app/urlUtils.js +101 -0
  85. package/src/images/logo.png +0 -0
  86. package/src/index.css +3 -0
  87. package/src/index.js +41 -0
  88. package/src/muse-ext.d.ts +1 -0
  89. package/src/muse.d.ts +163 -0
  90. package/src/react-app-env.d.ts +1 -0
  91. package/src/styles/global.less +9 -0
  92. package/src/styles/index.less +5 -0
  93. package/src/styles/mixins.less +0 -0
  94. package/src/utils.js +26 -0
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Allows a plugin to easily integrate a sub app. It does below things:
3
+ * - Load sub app
4
+ * - URL sync
5
+ * - SSO Check
6
+ * - Communication
7
+ *
8
+ * FixedSubAppContainer is usually only used programatically, not by configure.
9
+ *
10
+ * The owner should handle the size of the sub app.
11
+ */
12
+
13
+ import React, { useEffect, useMemo, useState, useCallback, useRef } from 'react';
14
+ import { useLocation } from 'react-use';
15
+ import _ from 'lodash';
16
+ import history from '../../common/history';
17
+ import urlUtils from './urlUtils';
18
+ import { LoadingSkeleton, C2SProxyFailed } from './';
19
+
20
+ const debouncedPush = _.debounce(url => {
21
+ history.push(url);
22
+ });
23
+
24
+ // Map a url pattern to load another muse app in iframe
25
+ // For example: /groot-ui => https://grootapp.muse.vip.ebay.com
26
+ // It will sync path, querystring, hash between the parent and iframe
27
+ const msgEngine = window.MUSE_GLOBAL.msgEngine;
28
+
29
+ // Fixed sub app container is usualle embeded into some part of an app but not the full page
30
+ export default function FixedSubAppContainer({ context = null, subApp }) {
31
+ const iframeWrapper = useRef();
32
+ const [subAppState, setSubAppState] = useState();
33
+ const loc = useLocation();
34
+ // parentFullPath: https://cloud.ebay.com/app/musemanager/ecdx => /app/musemanager/ecdx
35
+ const parentFullPath = loc.href.replace(loc.origin, '');
36
+
37
+ // Get the sub app's path
38
+ const subPath = urlUtils.getChildUrlPath(subApp);
39
+ console.log('subPath', subPath);
40
+ const currentIframe = iframeWrapper.current?.firstChild;
41
+
42
+ const subUrl = `${urlUtils.getOrigin(subApp.url)}${subPath}`;
43
+ // When context is changed, send message to the child app
44
+ useEffect(() => {
45
+ if (iframeWrapper.current && subAppState === 'app-loaded') {
46
+ msgEngine?.sendToChild(
47
+ {
48
+ type: 'sub-app-context-change',
49
+ data: context,
50
+ },
51
+ currentIframe,
52
+ );
53
+ }
54
+ }, [context, subApp, currentIframe, subAppState]);
55
+
56
+ // When sub app is first loaded, set the sub app url
57
+ useEffect(() => {
58
+ if (!subPath || !iframeWrapper.current) return;
59
+
60
+ // when first load, create iframe node to load sub app
61
+ let iframe = iframeWrapper.current?.firstChild;
62
+ if (!iframe) {
63
+ iframe = document.createElement('iframe');
64
+ iframe.src = subUrl;
65
+ iframeWrapper.current.appendChild(iframe);
66
+ }
67
+ }, [subUrl, subPath]);
68
+
69
+ // Whenever parent path is changed, notify child iframe (sub app)
70
+ useEffect(() => {
71
+ if (!currentIframe || !subPath) return;
72
+
73
+ msgEngine?.sendToChild(
74
+ {
75
+ type: 'parent-route-change',
76
+ path: subPath,
77
+ url: subPath, // use url to make it compatible with old muse-react
78
+ },
79
+ currentIframe,
80
+ );
81
+ }, [subPath, currentIframe]);
82
+
83
+ // handle sub app messages: route change, app load status, etc...
84
+ const handleSubAppMsg = useCallback(
85
+ msg => {
86
+ if (!msg.type) return;
87
+ // Here msg.path is the full path of sub app
88
+ if (msg.type === 'child-route-change' && msg.path) {
89
+ const newParentFullPath = urlUtils.getParentPath(msg.path, subApp);
90
+ if (newParentFullPath !== parentFullPath && newParentFullPath) {
91
+ // Need debounce because there maybe quick redirect of the sub app which may cause endless loop
92
+ debouncedPush(newParentFullPath);
93
+ }
94
+ } else if (msg.type === 'app-state-change') {
95
+ setSubAppState(msg.state);
96
+ if (msg.state === 'app-loaded') {
97
+ // for first load, need to set context to child
98
+ msgEngine?.sendToChild(
99
+ {
100
+ type: 'sub-app-context-change',
101
+ data: context,
102
+ },
103
+ currentIframe,
104
+ );
105
+ currentIframe.museLoaded = true;
106
+ }
107
+ }
108
+ },
109
+ [subApp, parentFullPath, setSubAppState, context, currentIframe],
110
+ );
111
+
112
+ useEffect(() => {
113
+ const k = Math.random();
114
+ msgEngine?.addListener(k, handleSubAppMsg);
115
+ return () => msgEngine?.removeListener(k);
116
+ }, [handleSubAppMsg]);
117
+
118
+ return (
119
+ <div className="muse-react_sub-app-fixed-sub-app-container">
120
+ {!currentIframe?.museLoaded &&
121
+ subAppState !== 'app-loaded' &&
122
+ subAppState !== 'app-failed' &&
123
+ subAppState !== 'login-page' &&
124
+ subAppState !== 'check-c2s-proxy-failed' && <LoadingSkeleton state={subAppState} />}
125
+
126
+ {subAppState === 'app-failed' && (
127
+ <div className="sub-app-sub-app-failed">
128
+ Failed to start sub app {subApp.name}: /{subApp.path} =&gt; {subApp.url}.
129
+ </div>
130
+ )}
131
+ {subAppState === 'check-c2s-proxy-failed' && <C2SProxyFailed />}
132
+
133
+ <div
134
+ ref={iframeWrapper}
135
+ style={{
136
+ visibility: ['app-loaded', 'login-page'].includes(subAppState) ? 'visible' : 'hidden',
137
+ }}
138
+ className="sub-app-iframe-wrapper"
139
+ />
140
+ </div>
141
+ );
142
+ }
@@ -0,0 +1,12 @@
1
+ .muse-react_sub-app-fixed-sub-app-container {
2
+ iframe {
3
+ width: 100%;
4
+ height: 100%;
5
+ border: none;
6
+ margin: 0;
7
+ }
8
+
9
+ > div {
10
+ height: ~'calc(100vh - 200px)';
11
+ }
12
+ }
@@ -0,0 +1,21 @@
1
+ /* eslint jsx-a11y/heading-has-content: 0*/
2
+ import React from 'react';
3
+ import { ReactComponent as LoadingSvg } from './subAppLoading2.svg';
4
+ const stateMap = {
5
+ 'app-starting': 'Loading sub app...',
6
+ 'app-loading': 'Starting sub app...',
7
+ 'fetch-user-info': 'Fetching user info...',
8
+ 'app-begin-login': 'Checking authentication...',
9
+ 'check-c2s-proxy': 'Checking c2s proxy...',
10
+ // 'redirect-login': 'Redirecting to login page...',
11
+ };
12
+ export default function LoadingSkeleton({ state }) {
13
+ return (
14
+ <div className="sub-app-loading-skeleton">
15
+ <div className="sub-app-loading-center-container">
16
+ {LoadingSvg ? React.createElement(LoadingSvg) : <></>}
17
+ <label>{stateMap[state] || 'Loading sub app...'}</label>
18
+ </div>
19
+ </div>
20
+ );
21
+ }
@@ -0,0 +1,20 @@
1
+ @import '../../styles/mixins';
2
+
3
+ .sub-app-loading-skeleton {
4
+ position: absolute;
5
+ width: 100%;
6
+ height: 100%;
7
+ z-index: 1200;
8
+ background: #fff;
9
+ display: grid;
10
+ place-items: center;
11
+ svg {
12
+ width: 80px;
13
+ height: 80px;
14
+ }
15
+ label {
16
+ color: #777;
17
+ display: inline-block;
18
+ margin-top: 10px;
19
+ }
20
+ }
@@ -0,0 +1,203 @@
1
+ /**
2
+ * Allows a plugin to easily integrate a sub app. It does below things:
3
+ * - Load sub app
4
+ * - URL sync
5
+ * - SSO Check
6
+ * - Communication
7
+ * - Cache pages
8
+ * - Auto resize iframe
9
+ *
10
+ * For example:
11
+ * Sub apps configured in muse-react plugin:
12
+ * [
13
+ * {
14
+ * path: '/muse-apps', // no array. Support regex: /app/.* /someapp
15
+ * url: 'https://demo.muse.vip.ebay.com/muse-apps',
16
+ * persist: false,
17
+ * name: 'musedemo',
18
+ * env: 'production',
19
+ * }
20
+ * ]
21
+ */
22
+ import React, { useEffect, useMemo, useState, useCallback, useRef } from 'react';
23
+ import { useLocation, useEvent } from 'react-use';
24
+ import _ from 'lodash';
25
+ import history from '../../common/history';
26
+ import urlUtils from './urlUtils';
27
+ import { LoadingSkeleton, C2SProxyFailed } from './';
28
+
29
+ const debouncedPush = _.debounce(url => {
30
+ history.push(url);
31
+ });
32
+
33
+ // Map a url pattern to load another muse app in iframe
34
+ // For example: /groot-ui => https://grootapp.muse.vip.ebay.com
35
+ // It will sync path, querystring, hash between the parent and iframe
36
+ const msgEngine = window.MUSE_GLOBAL.msgEngine;
37
+ const iframeCache = {};
38
+
39
+ export default function SubAppContainer({ context = null, subApp }) {
40
+ const iframeWrapper = useRef();
41
+ const [subAppState, setSubAppState] = useState();
42
+ const loc = useLocation();
43
+ const parentFullPath = loc.href.replace(loc.origin, '');
44
+ const subPath = urlUtils.getChildUrlPath(subApp);
45
+ const currentIframe = iframeCache[subApp.url];
46
+
47
+ const subUrl = `${urlUtils.getOrigin(subApp.url)}${subPath}`;
48
+ // When context is changed, send message to the child app
49
+ useEffect(() => {
50
+ if (iframeWrapper.current && subAppState === 'app-loaded') {
51
+ msgEngine?.sendToChild(
52
+ {
53
+ type: 'sub-app-context-change',
54
+ data: context,
55
+ },
56
+ currentIframe, //iframeWrapper.current.firstChild,
57
+ );
58
+ }
59
+ }, [context, subApp, currentIframe, subAppState]);
60
+
61
+ // When current sub app is changed
62
+ // If not persist, delete old app:
63
+ // - delete iframe
64
+ // - delete app state
65
+ // If persist:
66
+ // - cache iframe and state: but the post message will pause?
67
+
68
+ // while iframe is loaded, ensure it's a muse app
69
+ const assertMuseApp = useCallback(async ifr => {
70
+ try {
71
+ await window.MUSE_GLOBAL?.msgEngine.assertMuseApp(ifr);
72
+ } catch (err) {
73
+ console.log('Not a muse app: ', err);
74
+ setSubAppState('not-a-muse-app');
75
+ }
76
+ }, []);
77
+
78
+ // Handle subapp iframe visibility
79
+ useEffect(() => {
80
+ if (!subPath || !iframeWrapper.current) return;
81
+
82
+ // when first load, create iframe node to load sub app
83
+ let iframe = iframeCache[subApp.url];
84
+ const rect = iframeWrapper.current.getBoundingClientRect();
85
+ if (!iframe) {
86
+ iframe = document.createElement('iframe');
87
+ iframe.src = subUrl;
88
+ iframe.onload = () => assertMuseApp(iframe);
89
+ iframeCache[subApp.url] = iframe;
90
+ Object.assign(iframe.style, {
91
+ position: 'fixed',
92
+ top: rect.top + 'px',
93
+ left: rect.left + 'px',
94
+ width: rect.width + 'px',
95
+ height: rect.height + 'px',
96
+ border: 'none',
97
+ zIndex: 1000,
98
+ margin: 0,
99
+ });
100
+ document.body.appendChild(iframe);
101
+ } else {
102
+ iframe.style.left = rect.left + 'px';
103
+ }
104
+ }, [subUrl, assertMuseApp, subPath, subApp.url]);
105
+
106
+ // Whenever parent path is changed, notify child iframe (sub app)
107
+ useEffect(() => {
108
+ if (!currentIframe) return;
109
+ msgEngine?.sendToChild(
110
+ {
111
+ type: 'parent-route-change',
112
+ path: subPath,
113
+ },
114
+ currentIframe,
115
+ );
116
+ }, [subPath, currentIframe]);
117
+
118
+ useEffect(() => {
119
+ return () => {
120
+ const iframe = iframeCache[subApp.url];
121
+ if (iframe) {
122
+ iframe.style.left = '-100000px';
123
+ }
124
+ };
125
+ }, [subApp.url]);
126
+
127
+ const onWindowResize = useCallback(() => {
128
+ const iframe = iframeCache[subApp.url];
129
+
130
+ if (iframe && iframeWrapper.current) {
131
+ const rect = iframeWrapper.current.getBoundingClientRect();
132
+ Object.assign(iframe.style, {
133
+ width: rect.width + 'px',
134
+ height: rect.height + 'px',
135
+ });
136
+ }
137
+ }, [subApp.url]);
138
+
139
+ useEvent('resize', onWindowResize);
140
+
141
+ // handle sub app messages: route change, app load status, etc...
142
+ const handleSubAppMsg = useCallback(
143
+ msg => {
144
+ if (!msg.type) return;
145
+ // Here msg.path is the full path of sub app
146
+ if (msg.type === 'child-route-change' && msg.path) {
147
+ const newParentFullPath = urlUtils.getParentPath(msg.path, subApp);
148
+ if (newParentFullPath !== parentFullPath) {
149
+ // Need debounce because there maybe quick redirect of the sub app which may cause endless loop
150
+ debouncedPush(newParentFullPath);
151
+ }
152
+ } else if (msg.type === 'app-state-change') {
153
+ setSubAppState(msg.state);
154
+ if (msg.state === 'app-loaded') {
155
+ // for first load, need to set context to child
156
+ msgEngine?.sendToChild(
157
+ {
158
+ type: 'sub-app-context-change',
159
+ data: context,
160
+ },
161
+ currentIframe,
162
+ );
163
+ currentIframe.museLoaded = true;
164
+ }
165
+ }
166
+ },
167
+ [subApp, parentFullPath, setSubAppState, context, currentIframe],
168
+ );
169
+
170
+ useEffect(() => {
171
+ const k = Math.random();
172
+ msgEngine?.addListener(k, handleSubAppMsg);
173
+ return () => msgEngine?.removeListener(k);
174
+ }, [handleSubAppMsg]);
175
+
176
+ if (!subPath) {
177
+ return 'Error: can not detect a sub app. Are you using sub app container correctly?';
178
+ }
179
+ return (
180
+ <div className="muse-react_sub-app-sub-app-container">
181
+ {!currentIframe?.museLoaded &&
182
+ subAppState !== 'app-loaded' &&
183
+ subAppState !== 'app-failed' &&
184
+ subAppState !== 'login-page' &&
185
+ subAppState !== 'check-c2s-proxy-failed' && <LoadingSkeleton state={subAppState} />}
186
+
187
+ {subAppState === 'app-failed' && (
188
+ <div className="sub-app-sub-app-failed">
189
+ Failed to start sub app {subApp.name}: /{subApp.path} =&gt; {subApp.url}.
190
+ </div>
191
+ )}
192
+ {subAppState === 'check-c2s-proxy-failed' && <C2SProxyFailed />}
193
+
194
+ <div
195
+ ref={iframeWrapper}
196
+ style={{
197
+ visibility: ['app-loaded', 'login-page'].includes(subAppState) ? 'visible' : 'hidden',
198
+ }}
199
+ className="sub-app-iframe-wrapper"
200
+ />
201
+ </div>
202
+ );
203
+ }
@@ -0,0 +1,29 @@
1
+ @import '../../styles/mixins';
2
+
3
+ .muse-react_sub-app-sub-app-container {
4
+ height: 100vh;
5
+ position: relative;
6
+ .sub-app-sub-app-failed {
7
+ color: red;
8
+ padding: 16px;
9
+ }
10
+ .sub-app-iframe-wrapper {
11
+ position: absolute;
12
+ top: 0;
13
+ height: 100%;
14
+ width: 100%;
15
+ }
16
+
17
+ iframe {
18
+ margin: 0;
19
+ width: 100%;
20
+ height: 100%;
21
+ border: none;
22
+ }
23
+ }
24
+
25
+ .muse-layout_home-main-layout-page-container > .sub-app-sub-app-container {
26
+ margin: -30px;
27
+ width: ~'calc(100% + 60px)';
28
+ height: ~'calc(100vh - 50px)';
29
+ }
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+
3
+ const SubAppContext = React.createContext();
4
+ export default SubAppContext;
@@ -0,0 +1,23 @@
1
+ import { useEffect } from 'react';
2
+ import { useNavigate } from 'react-router-dom';
3
+
4
+ function useParentRouteChange() {
5
+ const navigate = useNavigate();
6
+
7
+ useEffect(() => {
8
+ window.MUSE_GLOBAL?.msgEngine?.addListener('muse-react_history', msg => {
9
+ // Parent may notify the child iframe to update url: implemented in SubAppContainer
10
+ // muse-boot will notify parent when child iframe url changed
11
+ const currentPath = document.location.href.replace(document.location.origin, '');
12
+ if (msg.type === 'parent-route-change' && msg.path !== currentPath) {
13
+ console.log('parent-route-change: ', msg.path);
14
+ navigate(msg.path);
15
+ }
16
+ });
17
+ return () => {
18
+ window.MUSE_GLOBAL?.msgEngine?.removeListener('muse-react_history');
19
+ };
20
+ }, [navigate]);
21
+ }
22
+
23
+ export default useParentRouteChange;
@@ -0,0 +1,5 @@
1
+ export { default as SubAppContainer } from './SubAppContainer';
2
+ export { default as FixedSubAppContainer } from './FixedSubAppContainer';
3
+ export { default as LoadingSkeleton } from './LoadingSkeleton';
4
+ export { default as SubAppContext } from './SubAppContext';
5
+ export { default as C2SProxyFailed } from './C2SProxyFailed';
@@ -0,0 +1 @@
1
+ export { setSubAppState } from './setSubAppState';
@@ -0,0 +1,2 @@
1
+ export const SUB_APP_SET_SUB_APP_STATE = 'SUB_APP_SET_SUB_APP_STATE';
2
+ export const SUB_APP_CLEAR_SUB_APP_STATE = 'SUB_APP_CLEAR_SUB_APP_STATE';
@@ -0,0 +1 @@
1
+ export { useSetSubAppState } from './setSubAppState';
@@ -0,0 +1,12 @@
1
+ // Initial state is the place you define all initial values for the Redux store of the feature.
2
+ // In the 'standard' way, initialState is defined in reducers: http://redux.js.org/docs/basics/Reducers.html
3
+ // But when application grows, there will be multiple reducers files, it's not intuitive what data is managed by the whole store.
4
+ // So Rekit extracts the initial state definition into a separate module so that you can have
5
+ // a quick view about what data is used for the feature, at any time.
6
+
7
+ // NOTE: initialState constant is necessary so that Rekit could auto add initial state when creating async actions.
8
+ const initialState = {
9
+ subAppState: {},
10
+ };
11
+
12
+ export default initialState;
@@ -0,0 +1,25 @@
1
+ // This is the root reducer of the feature. It is used for:
2
+ // 1. Load reducers from each action in the feature and process them one by one.
3
+ // Note that this part of code is mainly maintained by Rekit, you usually don't need to edit them.
4
+ // 2. Write cross-topic reducers. If a reducer is not bound to some specific action.
5
+ // Then it could be written here.
6
+ // Learn more from the introduction of this approach:
7
+ // https://medium.com/@nate_wang/a-new-approach-for-managing-redux-actions-91c26ce8b5da.
8
+
9
+ import initialState from './initialState';
10
+ import { reducer as setSubAppStateReducer } from './setSubAppState';
11
+
12
+ const reducers = [
13
+ setSubAppStateReducer,
14
+ ];
15
+
16
+ export default function reducer(state = initialState, action) {
17
+ let newState;
18
+ switch (action.type) {
19
+ // Handle cross-topic actions here
20
+ default:
21
+ newState = state;
22
+ break;
23
+ }
24
+ return reducers.reduce((s, r) => r(s, action), newState);
25
+ }
@@ -0,0 +1,43 @@
1
+ import { useCallback } from 'react';
2
+ import { useDispatch, useSelector } from 'react-redux';
3
+ import { SUB_APP_SET_SUB_APP_STATE, SUB_APP_CLEAR_SUB_APP_STATE } from './constants';
4
+
5
+ export function setSubAppState(state) {
6
+ return {
7
+ type: SUB_APP_SET_SUB_APP_STATE,
8
+ data: state,
9
+ };
10
+ }
11
+
12
+ export function clearSubAppState() {
13
+ return {
14
+ type: SUB_APP_CLEAR_SUB_APP_STATE,
15
+ };
16
+ }
17
+
18
+ export function useSetSubAppState() {
19
+ const dispatch = useDispatch();
20
+ const subAppState = useSelector(state => state.subApp.subAppState);
21
+ const boundAction = useCallback((...params) => dispatch(setSubAppState(...params)), [dispatch]);
22
+ const boundClearSubAppState = useCallback((...params) => dispatch(clearSubAppState(...params)), [
23
+ dispatch,
24
+ ]);
25
+ return { subAppState, setSubAppState: boundAction, clearSubAppState: boundClearSubAppState };
26
+ }
27
+
28
+ export function reducer(state, action) {
29
+ switch (action.type) {
30
+ case SUB_APP_SET_SUB_APP_STATE:
31
+ return {
32
+ ...state,
33
+ subAppState: action.data,
34
+ };
35
+ case SUB_APP_CLEAR_SUB_APP_STATE:
36
+ return {
37
+ ...state,
38
+ subAppState: {},
39
+ };
40
+ default:
41
+ return state;
42
+ }
43
+ }
@@ -0,0 +1,43 @@
1
+ import React from 'react';
2
+ import { SubAppContainer } from './';
3
+
4
+ // Get sub app route defined in muse-react plugin
5
+ const subAppsRoute = [];
6
+ const pMuseLibReact = window.MUSE_GLOBAL?.plugins?.find(p => p.name === '@ebay/muse-lib-react');
7
+ // pMuseLibReact.config = {
8
+ // subApps: [
9
+ // {
10
+ // mountPoint: 'default',
11
+ // name: 'musedemo',
12
+ // path: '/demo',
13
+ // // persist: true,
14
+ // url: 'https://demo.muse.qa.ebay.com',
15
+ // // url: 'http://local.cloud.ebay.com:3031',
16
+ // // url: 'https://sam.muse.vip.ebay.com',
17
+ // // url: 'https://besconsole.muse.qa.ebay.com',
18
+ // },
19
+ // ],
20
+ // };
21
+
22
+ pMuseLibReact?.subApps
23
+ ?.filter(s => s.mountPoint === 'default' || !s.mountPoint)
24
+ ?.forEach(subApp => {
25
+ // console.log('pushing sub app route: ', subApp);
26
+ subAppsRoute.push({
27
+ path: subApp.path + '/*',
28
+ component: () => (
29
+ <SubAppContainer
30
+ key={subApp.url} // ensure different sub apps have different iframes
31
+ subApps={pMuseLibReact?.config?.subApps || []}
32
+ subApp={subApp}
33
+ />
34
+ ),
35
+ });
36
+ });
37
+
38
+ const exportedRoute = {
39
+ path: 'sub-app',
40
+ childRoutes: [...subAppsRoute],
41
+ };
42
+
43
+ export default exportedRoute;
@@ -0,0 +1,5 @@
1
+ @import '../../styles/mixins';
2
+ @import './SubAppContainer';
3
+ @import './FixedSubAppContainer';
4
+ @import './LoadingSkeleton';
5
+ @import './C2SProxyFailed';
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="margin: auto; background: rgb(255, 255, 255); display: block; shape-rendering: auto;" width="200px" height="200px" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid">
3
+ <g transform="translate(50 50)"> <g transform="translate(-17 -17) scale(0.5)"> <g>
4
+ <animateTransform attributeName="transform" type="rotate" values="0;45" keyTimes="0;1" dur="0.2s" begin="0s" repeatCount="indefinite"></animateTransform><path d="M37.3496987939662 -7 L47.3496987939662 -7 L47.3496987939662 7 L37.3496987939662 7 A38 38 0 0 1 31.359972760794346 21.46047782418268 L31.359972760794346 21.46047782418268 L38.431040572659825 28.531545636048154 L28.531545636048154 38.431040572659825 L21.46047782418268 31.359972760794346 A38 38 0 0 1 7.0000000000000036 37.3496987939662 L7.0000000000000036 37.3496987939662 L7.000000000000004 47.3496987939662 L-6.999999999999999 47.3496987939662 L-7 37.3496987939662 A38 38 0 0 1 -21.46047782418268 31.35997276079435 L-21.46047782418268 31.35997276079435 L-28.531545636048154 38.431040572659825 L-38.43104057265982 28.531545636048158 L-31.359972760794346 21.460477824182682 A38 38 0 0 1 -37.3496987939662 7.000000000000007 L-37.3496987939662 7.000000000000007 L-47.3496987939662 7.000000000000008 L-47.3496987939662 -6.9999999999999964 L-37.3496987939662 -6.999999999999997 A38 38 0 0 1 -31.35997276079435 -21.460477824182675 L-31.35997276079435 -21.460477824182675 L-38.431040572659825 -28.531545636048147 L-28.53154563604818 -38.4310405726598 L-21.4604778241827 -31.35997276079433 A38 38 0 0 1 -6.999999999999992 -37.3496987939662 L-6.999999999999992 -37.3496987939662 L-6.999999999999994 -47.3496987939662 L6.999999999999977 -47.3496987939662 L6.999999999999979 -37.3496987939662 A38 38 0 0 1 21.460477824182686 -31.359972760794342 L21.460477824182686 -31.359972760794342 L28.531545636048158 -38.43104057265982 L38.4310405726598 -28.53154563604818 L31.35997276079433 -21.4604778241827 A38 38 0 0 1 37.3496987939662 -6.999999999999995 M0 -23A23 23 0 1 0 0 23 A23 23 0 1 0 0 -23" fill="#abbd81"></path></g></g> <g transform="translate(0 22) scale(0.4)"> <g>
5
+ <animateTransform attributeName="transform" type="rotate" values="45;0" keyTimes="0;1" dur="0.2s" begin="-0.1s" repeatCount="indefinite"></animateTransform><path d="M37.3496987939662 -7 L47.3496987939662 -7 L47.3496987939662 7 L37.3496987939662 7 A38 38 0 0 1 31.359972760794346 21.46047782418268 L31.359972760794346 21.46047782418268 L38.431040572659825 28.531545636048154 L28.531545636048154 38.431040572659825 L21.46047782418268 31.359972760794346 A38 38 0 0 1 7.0000000000000036 37.3496987939662 L7.0000000000000036 37.3496987939662 L7.000000000000004 47.3496987939662 L-6.999999999999999 47.3496987939662 L-7 37.3496987939662 A38 38 0 0 1 -21.46047782418268 31.35997276079435 L-21.46047782418268 31.35997276079435 L-28.531545636048154 38.431040572659825 L-38.43104057265982 28.531545636048158 L-31.359972760794346 21.460477824182682 A38 38 0 0 1 -37.3496987939662 7.000000000000007 L-37.3496987939662 7.000000000000007 L-47.3496987939662 7.000000000000008 L-47.3496987939662 -6.9999999999999964 L-37.3496987939662 -6.999999999999997 A38 38 0 0 1 -31.35997276079435 -21.460477824182675 L-31.35997276079435 -21.460477824182675 L-38.431040572659825 -28.531545636048147 L-28.53154563604818 -38.4310405726598 L-21.4604778241827 -31.35997276079433 A38 38 0 0 1 -6.999999999999992 -37.3496987939662 L-6.999999999999992 -37.3496987939662 L-6.999999999999994 -47.3496987939662 L6.999999999999977 -47.3496987939662 L6.999999999999979 -37.3496987939662 A38 38 0 0 1 21.460477824182686 -31.359972760794342 L21.460477824182686 -31.359972760794342 L28.531545636048158 -38.43104057265982 L38.4310405726598 -28.53154563604818 L31.35997276079433 -21.4604778241827 A38 38 0 0 1 37.3496987939662 -6.999999999999995 M0 -23A23 23 0 1 0 0 23 A23 23 0 1 0 0 -23" fill="#e15b64"></path></g></g> <g transform="translate(28 4) scale(0.3)"> <g>
6
+ <animateTransform attributeName="transform" type="rotate" values="0;45" keyTimes="0;1" dur="0.2s" begin="-0.1s" repeatCount="indefinite"></animateTransform><path d="M37.3496987939662 -7 L47.3496987939662 -7 L47.3496987939662 7 L37.3496987939662 7 A38 38 0 0 1 31.359972760794346 21.46047782418268 L31.359972760794346 21.46047782418268 L38.431040572659825 28.531545636048154 L28.531545636048154 38.431040572659825 L21.46047782418268 31.359972760794346 A38 38 0 0 1 7.0000000000000036 37.3496987939662 L7.0000000000000036 37.3496987939662 L7.000000000000004 47.3496987939662 L-6.999999999999999 47.3496987939662 L-7 37.3496987939662 A38 38 0 0 1 -21.46047782418268 31.35997276079435 L-21.46047782418268 31.35997276079435 L-28.531545636048154 38.431040572659825 L-38.43104057265982 28.531545636048158 L-31.359972760794346 21.460477824182682 A38 38 0 0 1 -37.3496987939662 7.000000000000007 L-37.3496987939662 7.000000000000007 L-47.3496987939662 7.000000000000008 L-47.3496987939662 -6.9999999999999964 L-37.3496987939662 -6.999999999999997 A38 38 0 0 1 -31.35997276079435 -21.460477824182675 L-31.35997276079435 -21.460477824182675 L-38.431040572659825 -28.531545636048147 L-28.53154563604818 -38.4310405726598 L-21.4604778241827 -31.35997276079433 A38 38 0 0 1 -6.999999999999992 -37.3496987939662 L-6.999999999999992 -37.3496987939662 L-6.999999999999994 -47.3496987939662 L6.999999999999977 -47.3496987939662 L6.999999999999979 -37.3496987939662 A38 38 0 0 1 21.460477824182686 -31.359972760794342 L21.460477824182686 -31.359972760794342 L28.531545636048158 -38.43104057265982 L38.4310405726598 -28.53154563604818 L31.35997276079433 -21.4604778241827 A38 38 0 0 1 37.3496987939662 -6.999999999999995 M0 -23A23 23 0 1 0 0 23 A23 23 0 1 0 0 -23" fill="#f8b26a"></path></g></g></g>
7
+ <!-- [ldio] generated by https://loading.io/ --></svg>