@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.
- package/README.md +19 -0
- package/build/dev/asset-manifest.json +11 -0
- package/build/dev/favicon.png +0 -0
- package/build/dev/lib-manifest.json +3374 -0
- package/build/dev/main.js +75839 -0
- package/build/dev/main.js.map +1 -0
- package/build/dev/muse.d.ts +170 -0
- package/build/dev/static/media/logo.b23b880b0dac2229042c.png +0 -0
- package/build/dev/static/media/subAppLoading2.bf08007b83457287ade1cedb71bc70f7.svg +7 -0
- package/build/dist/asset-manifest.json +11 -0
- package/build/dist/favicon.png +0 -0
- package/build/dist/lib-manifest.json +3603 -0
- package/build/dist/main.js +3 -0
- package/build/dist/main.js.LICENSE.txt +134 -0
- package/build/dist/main.js.map +1 -0
- package/build/dist/muse.d.ts +170 -0
- package/build/dist/static/media/logo.b23b880b0dac2229042c.png +0 -0
- package/build/dist/static/media/subAppLoading2.bf08007b83457287ade1cedb71bc70f7.svg +7 -0
- package/build/test/asset-manifest.json +11 -0
- package/build/test/favicon.png +0 -0
- package/build/test/lib-manifest.json +3587 -0
- package/build/test/main.js +3 -0
- package/build/test/main.js.LICENSE.txt +134 -0
- package/build/test/main.js.map +1 -0
- package/build/test/muse.d.ts +170 -0
- package/build/test/static/media/logo.b23b880b0dac2229042c.png +0 -0
- package/build/test/static/media/subAppLoading2.bf08007b83457287ade1cedb71bc70f7.svg +7 -0
- package/package.json +88 -0
- package/src/Root.js +195 -0
- package/src/common/configStore.js +40 -0
- package/src/common/history.js +25 -0
- package/src/common/rootReducer.js +40 -0
- package/src/common/routeConfig.js +135 -0
- package/src/common/store.js +21 -0
- package/src/features/common/ErrorBoundary.js +24 -0
- package/src/features/common/ErrorBoundary.less +6 -0
- package/src/features/common/Nodes.js +20 -0
- package/src/features/common/PageNotFound.js +3 -0
- package/src/features/common/PageNotFound.less +6 -0
- package/src/features/common/index.js +4 -0
- package/src/features/common/redux/actions.js +0 -0
- package/src/features/common/redux/constants.js +0 -0
- package/src/features/common/redux/initialState.js +12 -0
- package/src/features/common/redux/reducer.js +24 -0
- package/src/features/common/route.js +9 -0
- package/src/features/common/style.less +3 -0
- package/src/features/common/useExtPoint.js +28 -0
- package/src/features/common/utils.js +20 -0
- package/src/features/home/App.js +33 -0
- package/src/features/home/App.less +11 -0
- package/src/features/home/Homepage.js +46 -0
- package/src/features/home/Homepage.less +63 -0
- package/src/features/home/index.js +2 -0
- package/src/features/home/redux/actions.js +0 -0
- package/src/features/home/redux/constants.js +0 -0
- package/src/features/home/redux/initialState.js +4 -0
- package/src/features/home/redux/reducer.js +16 -0
- package/src/features/home/route.js +6 -0
- package/src/features/home/style.less +3 -0
- package/src/features/sub-app/C2SProxyFailed.js +10 -0
- package/src/features/sub-app/C2SProxyFailed.less +19 -0
- package/src/features/sub-app/FixedSubAppContainer.js +142 -0
- package/src/features/sub-app/FixedSubAppContainer.less +12 -0
- package/src/features/sub-app/LoadingSkeleton.js +21 -0
- package/src/features/sub-app/LoadingSkeleton.less +20 -0
- package/src/features/sub-app/SubAppContainer.js +203 -0
- package/src/features/sub-app/SubAppContainer.less +29 -0
- package/src/features/sub-app/SubAppContext.js +4 -0
- package/src/features/sub-app/hooks/useParentRouteChange.js +23 -0
- package/src/features/sub-app/index.js +5 -0
- package/src/features/sub-app/redux/actions.js +1 -0
- package/src/features/sub-app/redux/constants.js +2 -0
- package/src/features/sub-app/redux/hooks.js +1 -0
- package/src/features/sub-app/redux/initialState.js +12 -0
- package/src/features/sub-app/redux/reducer.js +25 -0
- package/src/features/sub-app/redux/setSubAppState.js +43 -0
- package/src/features/sub-app/route.js +43 -0
- package/src/features/sub-app/style.less +5 -0
- package/src/features/sub-app/subAppLoading.svg +7 -0
- package/src/features/sub-app/subAppLoading2.html +83 -0
- package/src/features/sub-app/subAppLoading2.svg +7 -0
- package/src/features/sub-app/subAppLoading3.svg +7 -0
- package/src/features/sub-app/subAppLoading4.svg +7 -0
- package/src/features/sub-app/urlUtils.js +101 -0
- package/src/images/logo.png +0 -0
- package/src/index.css +3 -0
- package/src/index.js +41 -0
- package/src/muse-ext.d.ts +1 -0
- package/src/muse.d.ts +163 -0
- package/src/react-app-env.d.ts +1 -0
- package/src/styles/global.less +9 -0
- package/src/styles/index.less +5 -0
- package/src/styles/mixins.less +0 -0
- package/src/utils.js +26 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import plugin from 'js-plugin';
|
|
3
|
+
import { App, Homepage } from '../features/home';
|
|
4
|
+
import { PageNotFound } from '../features/common';
|
|
5
|
+
import homeRoute from '../features/home/route';
|
|
6
|
+
import commonRoute from '../features/common/route';
|
|
7
|
+
import _ from 'lodash';
|
|
8
|
+
import subAppRoute from '../features/sub-app/route';
|
|
9
|
+
|
|
10
|
+
// NOTE: DO NOT CHANGE the 'childRoutes' name and the declaration pattern.
|
|
11
|
+
// This is used for Rekit cmds to register routes config for new features, and remove config when remove features, etc.
|
|
12
|
+
const childRoutes = [homeRoute, commonRoute, subAppRoute];
|
|
13
|
+
|
|
14
|
+
// Handle isIndex property of route config:
|
|
15
|
+
// Dupicate it and put it as the first route rule.
|
|
16
|
+
function handleIndexRoute(route) {
|
|
17
|
+
if (!route.childRoutes || !route.childRoutes.length) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const indexRoute = _.find(route.childRoutes, child => child.isIndex);
|
|
22
|
+
if (indexRoute) {
|
|
23
|
+
const first = { ...indexRoute };
|
|
24
|
+
first.path = '';
|
|
25
|
+
first.exact = true;
|
|
26
|
+
first.autoIndexRoute = true; // mark it so that the simple nav won't show it.
|
|
27
|
+
route.childRoutes.unshift(first);
|
|
28
|
+
}
|
|
29
|
+
route.childRoutes.forEach(handleIndexRoute);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const normalizeRoutes = routes => {
|
|
33
|
+
const byId = {};
|
|
34
|
+
const arr = [...routes];
|
|
35
|
+
const hasParent = [];
|
|
36
|
+
|
|
37
|
+
// traverse routes recursively
|
|
38
|
+
while (arr.length > 0) {
|
|
39
|
+
const r = arr.shift();
|
|
40
|
+
// allow a route point to a parent
|
|
41
|
+
if (r?.id) {
|
|
42
|
+
byId[r.id] = r;
|
|
43
|
+
}
|
|
44
|
+
if (r.childRoutes) {
|
|
45
|
+
_.forEachRight([...r.childRoutes], (cr, i) => {
|
|
46
|
+
// Support path as an array by expanding it to multiple rules
|
|
47
|
+
if (_.isArray(cr?.path)) {
|
|
48
|
+
r.childRoutes.splice(
|
|
49
|
+
i,
|
|
50
|
+
1,
|
|
51
|
+
...cr.path.map(p => {
|
|
52
|
+
return { ...r, path: p };
|
|
53
|
+
}),
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
arr.push(...r.childRoutes);
|
|
58
|
+
[...r.childRoutes].forEach(cr => {
|
|
59
|
+
// if a route has parent, move it to the correct parent
|
|
60
|
+
if (cr?.path?.startsWith('/')) {
|
|
61
|
+
// If it's an absolute path, move it to the top level
|
|
62
|
+
_.pull(r.childRoutes, cr);
|
|
63
|
+
routes.unshift(cr);
|
|
64
|
+
} else if (cr.parent) {
|
|
65
|
+
hasParent.push(cr);
|
|
66
|
+
_.pull(r.childRoutes, cr);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// for all routes which have parents, put them in the correct childRoutes
|
|
73
|
+
hasParent.forEach(r => {
|
|
74
|
+
const parentId = r.parent;
|
|
75
|
+
if (byId[parentId]) {
|
|
76
|
+
if (!byId[parentId].childRoutes) byId[parentId].childRoutes = [];
|
|
77
|
+
byId[parentId].childRoutes.unshift(r);
|
|
78
|
+
} else {
|
|
79
|
+
console.warn(`Warning: no parent route found with id ${parentId}.`, r);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const routeConfig = () => {
|
|
85
|
+
const newChildRoutes = [...childRoutes];
|
|
86
|
+
// Get routes from plugins
|
|
87
|
+
plugin.invoke('!route').forEach(route => {
|
|
88
|
+
newChildRoutes.push(..._.castArray(route));
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// Generate the root route '/'
|
|
92
|
+
const museGlobal = window.MUSE_GLOBAL || {};
|
|
93
|
+
|
|
94
|
+
// Find the homepage
|
|
95
|
+
let homepage = Homepage;
|
|
96
|
+
const homepagePlugins = plugin.getPlugins('home.homepage');
|
|
97
|
+
if (homepagePlugins.length === 1) {
|
|
98
|
+
homepage = homepagePlugins[0].home.homepage;
|
|
99
|
+
} else if (homepagePlugins.length > 1) {
|
|
100
|
+
const definedHomepagePlugin = _.find(homepagePlugins, { name: museGlobal.homepage });
|
|
101
|
+
if (definedHomepagePlugin) homepage = definedHomepagePlugin.home.homepage;
|
|
102
|
+
else {
|
|
103
|
+
homepage = () => (
|
|
104
|
+
<div style={{ color: 'red', padding: '20px' }}>
|
|
105
|
+
Failed to show homepage: multiple homepages found from:{' '}
|
|
106
|
+
{homepagePlugins.map(p => p.name).join(', ')}. You should load only one plugin which
|
|
107
|
+
defines homepage.
|
|
108
|
+
</div>
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
newChildRoutes.unshift({
|
|
114
|
+
path: '',
|
|
115
|
+
component: homepage,
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
const routes = [
|
|
119
|
+
{
|
|
120
|
+
path: '/',
|
|
121
|
+
component: App,
|
|
122
|
+
childRoutes: [
|
|
123
|
+
..._.cloneDeep(newChildRoutes),
|
|
124
|
+
{ path: '*', name: 'Page not found', component: PageNotFound },
|
|
125
|
+
].filter(r => r.component || r.render || (r.childRoutes && r.childRoutes.length > 0)),
|
|
126
|
+
},
|
|
127
|
+
];
|
|
128
|
+
routes.forEach(handleIndexRoute);
|
|
129
|
+
|
|
130
|
+
// Handle parent routes
|
|
131
|
+
normalizeRoutes(routes[0].childRoutes);
|
|
132
|
+
|
|
133
|
+
return routes;
|
|
134
|
+
};
|
|
135
|
+
export default routeConfig;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import configStore from './configStore';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
store: null,
|
|
5
|
+
getStore() {
|
|
6
|
+
if (!this.store) this.store = configStore();
|
|
7
|
+
return this.store;
|
|
8
|
+
},
|
|
9
|
+
getState() {
|
|
10
|
+
return this.getStore().getState();
|
|
11
|
+
},
|
|
12
|
+
dispatch(action) {
|
|
13
|
+
return this.getStore().dispatch(action);
|
|
14
|
+
},
|
|
15
|
+
subscribe(listener) {
|
|
16
|
+
return this.getStore().subscribe(listener);
|
|
17
|
+
},
|
|
18
|
+
replaceReducer(reducer) {
|
|
19
|
+
return this.getStore().replaceReducer(reducer);
|
|
20
|
+
},
|
|
21
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React, { Component } from 'react';
|
|
2
|
+
|
|
3
|
+
export default class ErrorBoundary extends React.Component {
|
|
4
|
+
constructor(props) {
|
|
5
|
+
super(props);
|
|
6
|
+
this.state = { hasError: false };
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
static getDerivedStateFromError(error) {
|
|
10
|
+
// Update state so the next render will show the fallback UI.
|
|
11
|
+
return { hasError: true };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
render() {
|
|
15
|
+
if (this.state.hasError) {
|
|
16
|
+
// You can render any custom fallback UI
|
|
17
|
+
return (
|
|
18
|
+
<div className="common-error-boundary">{this.props.message || 'Something went wrong.'}</div>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return this.props.children;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { extendArray } from './utils';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A component that renders a list of nodes with ability to extend the list.
|
|
6
|
+
* @param {Array} items - The list of nodes to render.
|
|
7
|
+
*/
|
|
8
|
+
export default function Nodes({ items = [], extName = 'items', extBase, extArgs }) {
|
|
9
|
+
extendArray(items, extName, extBase, extArgs);
|
|
10
|
+
const nodes = [];
|
|
11
|
+
items.filter(Boolean).forEach(n => {
|
|
12
|
+
let node;
|
|
13
|
+
if (n.render) node = n.render();
|
|
14
|
+
else if (n.content) node = n.content;
|
|
15
|
+
else if (n.component) node = <n.component key={n.key} {...n.props} />;
|
|
16
|
+
nodes.push(node);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
return nodes;
|
|
20
|
+
}
|
|
File without changes
|
|
File without changes
|
|
@@ -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
|
+
|
|
9
|
+
const initialState = {
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export default initialState;
|
|
@@ -0,0 +1,24 @@
|
|
|
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
|
+
|
|
11
|
+
const reducers = [
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
export default function reducer(state = initialState, action) {
|
|
15
|
+
let newState;
|
|
16
|
+
switch (action.type) {
|
|
17
|
+
// Handle cross-topic actions here
|
|
18
|
+
default:
|
|
19
|
+
newState = state;
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
/* istanbul ignore next */
|
|
23
|
+
return reducers.reduce((s, r) => r(s, action), newState);
|
|
24
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { useState, useCallback } from 'react';
|
|
2
|
+
import jsPlugin from 'js-plugin';
|
|
3
|
+
import _ from 'lodash';
|
|
4
|
+
|
|
5
|
+
// allow use hooks in ext points
|
|
6
|
+
// TODO: it always flatten items, which may not be what we want?
|
|
7
|
+
export default function useExtPoint(extPointName, extArgs) {
|
|
8
|
+
const components = jsPlugin.invoke('!' + extPointName, extArgs);
|
|
9
|
+
|
|
10
|
+
const [values, setValues] = useState([]);
|
|
11
|
+
const handleCallback = useCallback(
|
|
12
|
+
value => {
|
|
13
|
+
setValues(_.flatten([...values, value]));
|
|
14
|
+
},
|
|
15
|
+
[values],
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
extNode: (
|
|
20
|
+
<>
|
|
21
|
+
{components.map((Comp, index) => {
|
|
22
|
+
return <Comp key={index} callback={handleCallback} {...extArgs} />;
|
|
23
|
+
})}
|
|
24
|
+
</>
|
|
25
|
+
),
|
|
26
|
+
values,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import jsPlugin from 'js-plugin';
|
|
2
|
+
import _ from 'lodash';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @description Make an array extensible by js plugins.
|
|
6
|
+
* @param {*} arr
|
|
7
|
+
* @param {*} extName
|
|
8
|
+
* @param {*} extBase
|
|
9
|
+
* @param {...any} args
|
|
10
|
+
*/
|
|
11
|
+
export const extendArray = (arr, extName, extBase, ...args) => {
|
|
12
|
+
const capitalName = extName.charAt(0).toUpperCase() + extName.slice(1);
|
|
13
|
+
jsPlugin.invoke(`${extBase}.preProcess${capitalName}`, ...args);
|
|
14
|
+
const items = _.flatten(jsPlugin.invoke(`${extBase}.get${capitalName}`, ...args));
|
|
15
|
+
arr.push(...items);
|
|
16
|
+
jsPlugin.invoke(`${extBase}.process${capitalName}`, ...args);
|
|
17
|
+
jsPlugin.invoke(`${extBase}.postProcess${capitalName}`, ...args);
|
|
18
|
+
jsPlugin.sort(arr);
|
|
19
|
+
return arr;
|
|
20
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import plugin from 'js-plugin';
|
|
3
|
+
import useParentRouteChange from '../sub-app/hooks/useParentRouteChange';
|
|
4
|
+
|
|
5
|
+
export default function App({ children }) {
|
|
6
|
+
// home.rootComponent is used to define some global placeholder for something like Modals, Drawers, etc.
|
|
7
|
+
const rootComponentPlugins = plugin.getPlugins('rootComponent');
|
|
8
|
+
|
|
9
|
+
// home.mainLayout is used to define the main layout component
|
|
10
|
+
const layouts = plugin.invoke('!home.mainLayout');
|
|
11
|
+
useParentRouteChange();
|
|
12
|
+
if (layouts.length > 1) {
|
|
13
|
+
const ids = plugin.getPlugins('home.mainLayout').map(p => p.name);
|
|
14
|
+
return (
|
|
15
|
+
<div style={{ color: 'red', margin: '20px' }}>
|
|
16
|
+
Error: multiple layouts found from plugins: {ids.join(', ')}. Each application should only
|
|
17
|
+
have one main layout.
|
|
18
|
+
</div>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
const Layout = layouts[0];
|
|
22
|
+
const ele = Layout ? <Layout>{children}</Layout> : children;
|
|
23
|
+
return (
|
|
24
|
+
<div className="home-app muse-app">
|
|
25
|
+
<div className="muse-app_main-page-container">{ele}</div>
|
|
26
|
+
<div className="muse-app_plugin-root-placeholder">
|
|
27
|
+
{rootComponentPlugins.map(p => (
|
|
28
|
+
<p.rootComponent key={p.name} />
|
|
29
|
+
))}
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import logo from '../../images/logo.png';
|
|
3
|
+
|
|
4
|
+
export default function Homepage() {
|
|
5
|
+
return (
|
|
6
|
+
<div className="home-homepage">
|
|
7
|
+
<header className="app-header">
|
|
8
|
+
<img src={logo} className="app-logo" alt="logo" />
|
|
9
|
+
<h1 className="app-title">Welcome to Muse!</h1>
|
|
10
|
+
</header>
|
|
11
|
+
<div className="app-intro">
|
|
12
|
+
<p className="memo">This is the default homepage of a Muse application.</p>
|
|
13
|
+
<h3>To get started:</h3>
|
|
14
|
+
<ul>
|
|
15
|
+
<li>
|
|
16
|
+
<a href="https://go/muse">Read docs</a> for Muse.
|
|
17
|
+
</li>
|
|
18
|
+
<li>
|
|
19
|
+
Join the slack channel{' '}
|
|
20
|
+
<a href="https://ebay-eng.slack.com/archives/C0194Q1V8G1">#muse</a>.
|
|
21
|
+
</li>
|
|
22
|
+
<li>
|
|
23
|
+
<a href="https://pages.github.corp.ebay.com/muse/muse-site/docs/get-started/first-plugin">
|
|
24
|
+
Create a plugin
|
|
25
|
+
</a>{' '}
|
|
26
|
+
and{' '}
|
|
27
|
+
<a href="https://pages.github.corp.ebay.com/muse/muse-site/docs/get-started/customize-layout">
|
|
28
|
+
define the layout/homepage
|
|
29
|
+
</a>{' '}
|
|
30
|
+
for the application.
|
|
31
|
+
</li>
|
|
32
|
+
<li>
|
|
33
|
+
<a href="https://pages.github.corp.ebay.com/muse/muse-site/docs/muse-management/plugin-management#build-a-plugin">
|
|
34
|
+
Build
|
|
35
|
+
</a>{' '}
|
|
36
|
+
and{' '}
|
|
37
|
+
<a href="https://pages.github.corp.ebay.com/muse/muse-site/docs/muse-management/plugin-management#deploy-a-plugin">
|
|
38
|
+
deploy
|
|
39
|
+
</a>{' '}
|
|
40
|
+
the Muse plugin to the application.
|
|
41
|
+
</li>
|
|
42
|
+
</ul>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
@import '../../styles/mixins';
|
|
2
|
+
|
|
3
|
+
.home-homepage {
|
|
4
|
+
text-align: center;
|
|
5
|
+
min-width: 600px;
|
|
6
|
+
|
|
7
|
+
.app {
|
|
8
|
+
text-align: center;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.app-logo {
|
|
12
|
+
height: 80px;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.app-header {
|
|
16
|
+
padding: 40px 20px 20px 20px;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
h3 {
|
|
20
|
+
font-size: 20px;
|
|
21
|
+
font-weight: bold;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.app-title {
|
|
25
|
+
font-size: 26px;
|
|
26
|
+
margin-top: 10px;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.app-intro {
|
|
30
|
+
font-size: 16px;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
ul,
|
|
34
|
+
li {
|
|
35
|
+
list-style: none;
|
|
36
|
+
margin: 0;
|
|
37
|
+
padding: 0;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
ul {
|
|
41
|
+
margin-top: 20px;
|
|
42
|
+
}
|
|
43
|
+
li {
|
|
44
|
+
margin-top: 10px;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
a {
|
|
48
|
+
color: #0288d1;
|
|
49
|
+
text-decoration: none;
|
|
50
|
+
&:hover {
|
|
51
|
+
text-decoration: underline;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
p.memo {
|
|
56
|
+
color: #999;
|
|
57
|
+
line-height: 150%;
|
|
58
|
+
|
|
59
|
+
font-style: italic;
|
|
60
|
+
font-size: 14px;
|
|
61
|
+
margin: 20px auto;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import initialState from './initialState';
|
|
2
|
+
|
|
3
|
+
const reducers = [
|
|
4
|
+
];
|
|
5
|
+
|
|
6
|
+
export default function reducer(state = initialState, action) {
|
|
7
|
+
let newState;
|
|
8
|
+
switch (action.type) {
|
|
9
|
+
// Handle cross-topic actions here
|
|
10
|
+
default:
|
|
11
|
+
newState = state;
|
|
12
|
+
break;
|
|
13
|
+
}
|
|
14
|
+
/* istanbul ignore next */
|
|
15
|
+
return reducers.reduce((s, r) => r(s, action), newState);
|
|
16
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
export default function C2SProxyFailed() {
|
|
4
|
+
return (
|
|
5
|
+
<div className="sub-app-c-2-s-proxy-failed">
|
|
6
|
+
<h3>Error: failed to detect c2s proxy.</h3>
|
|
7
|
+
<p>This page needs c2s proxy, please config it and refresh the page.</p>
|
|
8
|
+
</div>
|
|
9
|
+
);
|
|
10
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
@import '../../styles/mixins';
|
|
2
|
+
|
|
3
|
+
.sub-app-c-2-s-proxy-failed {
|
|
4
|
+
position: absolute;
|
|
5
|
+
color: orange;
|
|
6
|
+
line-height: 150%;
|
|
7
|
+
margin: auto;
|
|
8
|
+
left: 50%;
|
|
9
|
+
margin-left: -300px;
|
|
10
|
+
top: 40%;
|
|
11
|
+
width: 600px;
|
|
12
|
+
padding: 20px;
|
|
13
|
+
border-radius: 4px;
|
|
14
|
+
border: 1px solid orange;
|
|
15
|
+
|
|
16
|
+
h3 {
|
|
17
|
+
color: orange;
|
|
18
|
+
}
|
|
19
|
+
}
|