Skip to content

Commit 6e77330

Browse files
committed
sync with antd-pro 1.0
1 parent 3b53190 commit 6e77330

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+1027
-625
lines changed

package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
{
22
"name": "react-script-antd-pro",
3-
"version": "0.3.1",
3+
"version": "1.0.0",
44
"private": true,
55
"dependencies": {
66
"@antv/data-set": "^0.8.3",
7-
"antd": "^3.0.3",
7+
"antd": "^3.1.1",
88
"bizcharts": "^3.1.0-beta.6",
99
"bizcharts-plugin-slider": "^2.0.1",
1010
"classnames": "^2.2.5",
1111
"dva": "^2.1.0",
12+
"dva-loading": "^1.0.4",
1213
"enquire-js": "^0.1.1",
1314
"fastclick": "^1.0.6",
1415
"history": "^4.7.2",
@@ -23,7 +24,7 @@
2324
"qs": "^6.5.1",
2425
"rc-drawer-menu": "^0.5.3",
2526
"react": "^16.2.0",
26-
"react-container-query": "^0.9.1",
27+
"react-container-query": "^0.10.0",
2728
"react-document-title": "^2.0.3",
2829
"react-dom": "^16.2.0",
2930
"react-fittext": "^1.0.0",
@@ -39,7 +40,7 @@
3940
"babel-plugin-import": "^1.6.3",
4041
"babel-plugin-transform-decorators-legacy": "^1.3.4",
4142
"less-loader": "^4.0.5",
42-
"prettier": "^1.9.2",
43+
"prettier": "^1.10.1",
4344
"react-app-rewire-less-modules": "https://github.com/WhatAKitty/react-app-rewire-less-modules",
4445
"react-app-rewired": "^1.4.0",
4546
"react-fetch-mock": "^0.4.1",

src/common/menu.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const menuData = [{
2525
path: 'step-form',
2626
}, {
2727
name: '高级表单',
28+
authority: 'admin',
2829
path: 'advanced-form',
2930
}],
3031
}, {
@@ -64,6 +65,7 @@ const menuData = [{
6465
}, {
6566
name: '高级详情页',
6667
path: 'advanced',
68+
authority: 'admin',
6769
}],
6870
}, {
6971
name: '结果页',
@@ -97,6 +99,7 @@ const menuData = [{
9799
name: '账户',
98100
icon: 'user',
99101
path: 'user',
102+
authority: 'guest',
100103
children: [{
101104
name: '登录',
102105
path: 'login',
@@ -114,14 +117,15 @@ const menuData = [{
114117
target: '_blank',
115118
}];
116119

117-
function formatter(data, parentPath = '') {
120+
function formatter(data, parentPath = '', parentAuthority) {
118121
return data.map((item) => {
119122
const result = {
120123
...item,
121124
path: `${parentPath}${item.path}`,
125+
authority: item.authority || parentAuthority,
122126
};
123127
if (item.children) {
124-
result.children = formatter(item.children, `${parentPath}${item.path}/`);
128+
result.children = formatter(item.children, `${parentPath}${item.path}/`, item.authority);
125129
}
126130
return result;
127131
});

src/common/router.js

Lines changed: 62 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,74 @@
1-
import React from 'react';
1+
import { createElement } from 'react';
22
import dynamic from 'dva/dynamic';
33
import { getMenuData } from './menu';
44

5+
let routerDataCache;
6+
7+
const modelNotExisted = (app, model) => (
8+
// eslint-disable-next-line
9+
!app._models.some(({ namespace }) => {
10+
return namespace === model.substring(model.lastIndexOf('/') + 1);
11+
})
12+
);
13+
514
// wrapper of dynamic
6-
const dynamicWrapper = (app, models, component) => dynamic({
7-
app,
8-
// eslint-disable-next-line no-underscore-dangle
9-
models: () => models.filter(m => !app._models.some(({ namespace }) => namespace === m)).map(m => import(`../models/${m}.js`)),
10-
// add routerData prop
11-
component: () => {
12-
const routerData = getRouterData(app);
13-
return component().then((raw) => {
14-
const Component = raw.default || raw;
15-
return props => <Component {...props} routerData={routerData} />;
15+
const dynamicWrapper = (app, models, component) => {
16+
// () => require('module')
17+
// transformed by babel-plugin-dynamic-import-node-sync
18+
if (component.toString().indexOf('.then(') < 0) {
19+
models.forEach((model) => {
20+
if (modelNotExisted(app, model)) {
21+
// eslint-disable-next-line
22+
app.model(require(`../models/${model}`).default);
23+
}
1624
});
17-
},
18-
});
25+
return (props) => {
26+
if (!routerDataCache) {
27+
routerDataCache = getRouterData(app);
28+
}
29+
return createElement(component().default, {
30+
...props,
31+
routerData: routerDataCache,
32+
});
33+
};
34+
}
35+
// () => import('module')
36+
return dynamic({
37+
app,
38+
models: () => models.filter(
39+
model => modelNotExisted(app, model)).map(m => import(`../models/${m}.js`)
40+
),
41+
// add routerData prop
42+
component: () => {
43+
if (!routerDataCache) {
44+
routerDataCache = getRouterData(app);
45+
}
46+
return component().then((raw) => {
47+
const Component = raw.default || raw;
48+
return props => createElement(Component, {
49+
...props,
50+
routerData: routerDataCache,
51+
});
52+
});
53+
},
54+
});
55+
};
1956

2057
function getFlatMenuData(menus) {
2158
let keys = {};
2259
menus.forEach((item) => {
2360
if (item.children) {
24-
keys[item.path] = item.name;
61+
keys[item.path] = { ...item };
2562
keys = { ...keys, ...getFlatMenuData(item.children) };
2663
} else {
27-
keys[item.path] = item.name;
64+
keys[item.path] = { ...item };
2865
}
2966
});
3067
return keys;
3168
}
3269

3370
export const getRouterData = (app) => {
34-
const routerData = {
71+
const routerConfig = {
3572
'/': {
3673
component: dynamicWrapper(app, ['user', 'login'], () => import('../layouts/BasicLayout')),
3774
},
@@ -45,6 +82,7 @@ export const getRouterData = (app) => {
4582
component: dynamicWrapper(app, ['project', 'activities', 'chart'], () => import('../routes/Dashboard/Workplace')),
4683
// hideInBreadcrumb: true,
4784
// name: '工作台',
85+
// authority: 'admin',
4886
},
4987
'/form/basic-form': {
5088
component: dynamicWrapper(app, ['form'], () => import('../routes/Forms/BasicForm')),
@@ -127,12 +165,14 @@ export const getRouterData = (app) => {
127165
};
128166
// Get name from ./menu.js or just set it in the router data.
129167
const menuData = getFlatMenuData(getMenuData());
130-
const routerDataWithName = {};
131-
Object.keys(routerData).forEach((item) => {
132-
routerDataWithName[item] = {
133-
...routerData[item],
134-
name: routerData[item].name || menuData[item.replace(/^\//, '')],
168+
const routerData = {};
169+
Object.keys(routerConfig).forEach((item) => {
170+
const menuItem = menuData[item.replace(/^\//, '')] || {};
171+
routerData[item] = {
172+
...routerConfig[item],
173+
name: routerConfig[item].name || menuItem.name,
174+
authority: routerConfig[item].authority || menuItem.authority,
135175
};
136176
});
137-
return routerDataWithName;
177+
return routerData;
138178
};
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import React from 'react';
2+
import CheckPermissions from './CheckPermissions';
3+
4+
class Authorized extends React.Component {
5+
render() {
6+
const { children, authority, noMatch = null } = this.props;
7+
const childrenRender = typeof children === 'undefined' ? null : children;
8+
return CheckPermissions(
9+
authority,
10+
childrenRender,
11+
noMatch
12+
);
13+
}
14+
}
15+
16+
export default Authorized;
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import React from 'react';
2+
import { Route, Redirect } from 'dva/router';
3+
import Authorized from './Authorized';
4+
5+
class AuthorizedRoute extends React.Component {
6+
render() {
7+
const { component: Component, render, authority,
8+
redirectPath, ...rest } = this.props;
9+
return (
10+
<Authorized
11+
authority={authority}
12+
noMatch={<Route {...rest} render={() => <Redirect to={{ pathname: redirectPath }} />} />}
13+
>
14+
<Route
15+
{...rest}
16+
render={props => (Component ? <Component {...props} /> : render(props))}
17+
/>
18+
</Authorized>
19+
);
20+
}
21+
}
22+
23+
export default AuthorizedRoute;
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import React from 'react';
2+
import PromiseRender from './PromiseRender';
3+
import { CURRENT } from './index';
4+
/**
5+
* 通用权限检查方法
6+
* Common check permissions method
7+
* @param { 权限判定 Permission judgment type string |array | Promise | Function } authority
8+
* @param { 你的权限 Your permission description type:string} currentAuthority
9+
* @param { 通过的组件 Passing components } target
10+
* @param { 未通过的组件 no pass components } Exception
11+
*/
12+
const checkPermissions = (authority, currentAuthority, target, Exception) => {
13+
// 没有判定权限.默认查看所有
14+
// Retirement authority, return target;
15+
if (!authority) {
16+
return target;
17+
}
18+
// 数组处理
19+
if (Array.isArray(authority)) {
20+
if (authority.indexOf(currentAuthority) >= 0) {
21+
return target;
22+
}
23+
return Exception;
24+
}
25+
26+
// string 处理
27+
if (typeof authority === 'string') {
28+
if (authority === currentAuthority) {
29+
return target;
30+
}
31+
return Exception;
32+
}
33+
34+
// Promise 处理
35+
if (authority.constructor.name === 'Promise') {
36+
return () => (
37+
<PromiseRender ok={target} error={Exception} promise={authority} />
38+
);
39+
}
40+
41+
// Function 处理
42+
if (typeof authority === 'function') {
43+
try {
44+
const bool = authority();
45+
if (bool) {
46+
return target;
47+
}
48+
return Exception;
49+
} catch (error) {
50+
throw error;
51+
}
52+
}
53+
throw new Error('unsupported parameters');
54+
};
55+
56+
export { checkPermissions };
57+
58+
const check = (authority, target, Exception) => {
59+
return checkPermissions(authority, CURRENT, target, Exception);
60+
};
61+
62+
export default check;
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { checkPermissions } from './CheckPermissions.js';
2+
3+
const target = 'ok';
4+
const error = 'error';
5+
6+
describe('test CheckPermissions', () => {
7+
it('Correct string permission authentication', () => {
8+
expect(checkPermissions('user', 'user', target, error)).toEqual('ok');
9+
});
10+
it('Correct string permission authentication', () => {
11+
expect(checkPermissions('user', 'NULL', target, error)).toEqual('error');
12+
});
13+
it('authority is undefined , return ok', () => {
14+
expect(checkPermissions(null, 'NULL', target, error)).toEqual('ok');
15+
});
16+
it('currentAuthority is undefined , return error', () => {
17+
expect(checkPermissions('admin', null, target, error)).toEqual('error');
18+
});
19+
it('Wrong string permission authentication', () => {
20+
expect(checkPermissions('admin', 'user', target, error)).toEqual('error');
21+
});
22+
it('Correct Array permission authentication', () => {
23+
expect(checkPermissions(['user', 'admin'], 'user', target, error)).toEqual(
24+
'ok'
25+
);
26+
});
27+
it('Wrong Array permission authentication,currentAuthority error', () => {
28+
expect(
29+
checkPermissions(['user', 'admin'], 'user,admin', target, error)
30+
).toEqual('error');
31+
});
32+
it('Wrong Array permission authentication', () => {
33+
expect(checkPermissions(['user', 'admin'], 'guest', target, error)).toEqual(
34+
'error'
35+
);
36+
});
37+
it('Wrong Function permission authentication', () => {
38+
expect(checkPermissions(() => false, 'guest', target, error)).toEqual(
39+
'error'
40+
);
41+
});
42+
it('Correct Function permission authentication', () => {
43+
expect(checkPermissions(() => true, 'guest', target, error)).toEqual('ok');
44+
});
45+
});
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import React from 'react';
2+
import { Spin } from 'antd';
3+
4+
export default class PromiseRender extends React.PureComponent {
5+
state = {
6+
component: false,
7+
};
8+
async componentDidMount() {
9+
this.props.promise
10+
.then(() => {
11+
this.setState({
12+
component: this.props.ok,
13+
});
14+
})
15+
.catch(() => {
16+
this.setState({
17+
component: this.props.error,
18+
});
19+
});
20+
}
21+
render() {
22+
const C = this.state.component;
23+
return C ? (
24+
<C {...this.props} />
25+
) : (
26+
<div
27+
style={{
28+
width: '100%',
29+
height: '100%',
30+
margin: 'auto',
31+
paddingTop: 50,
32+
textAlign: 'center',
33+
}}
34+
>
35+
<Spin size="large" />
36+
</div>
37+
);
38+
}
39+
}

0 commit comments

Comments
 (0)