Commit 0e2cd76a authored by jim's avatar jim

fix default setting bug

parent 255a70b6
......@@ -3,7 +3,7 @@ const path = require('path');
module.exports = {
plugins: [
[
'babel-plugin-module-resolver',
'module-resolver',
{
alias: {
components: path.join(__dirname, './src/components'),
......
......@@ -21,3 +21,4 @@ yarn.lock
package-lock.json
*bak
jsconfig.json
.vscode/settings.json
**/*.md
**/*.svg
**/*.ejs
**/*.html
package.json
{
"name": "ant-design-pro",
"version": "1.3.0",
"version": "2.0.0-beta.1",
"description": "An out-of-box UI solution for enterprise applications",
"private": true,
"scripts": {
......@@ -78,18 +78,18 @@
"pro-download": "^1.0.1",
"redbox-react": "^1.5.0",
"regenerator-runtime": "^0.11.1",
"roadhog": "^2.3.0",
"roadhog-api-doc": "^1.0.2",
"stylelint": "^9.2.0",
"roadhog": "^2.4.1",
"roadhog-api-doc": "^1.0.3",
"stylelint": "^8.4.0",
"stylelint-config-prettier": "^3.0.4",
"stylelint-config-standard": "^18.0.0"
},
"optionalDependencies": {
"puppeteer": "^1.3.0"
"puppeteer": "^1.4.0"
},
"lint-staged": {
"**/*.{js,jsx,less}": [
"prettier --wirter",
"prettier --write",
"git add"
],
"**/*.{js,jsx}": "npm run lint-staged:js",
......
......@@ -13,7 +13,7 @@ import WaterWave from './WaterWave';
import TagCloud from './TagCloud';
import TimelineChart from './TimelineChart';
const yuan = val => `¥ ${numeral(val).format('0,0')}`;
const yuan = val => `¥ ${numeral(val).format('0,0')}`;
const Charts = {
yuan,
......
......@@ -22,7 +22,10 @@ const DescriptionList = ({
<div className={clsString} {...restProps}>
{title ? <div className={styles.title}>{title}</div> : null}
<Row gutter={gutter}>
{React.Children.map(children, child => React.cloneElement(child, { column }))}
{React.Children.map(
children,
child => (child ? React.cloneElement(child, { column }) : child)
)}
</Row>
</div>
);
......
......@@ -18,6 +18,7 @@ export interface LoginItemProps {
rules?: any[];
style?: React.CSSProperties;
onGetCaptcha?: () => void;
placeholder?: string;
}
export class LoginItem extends React.Component<LoginItemProps, any> {}
......
......@@ -35,6 +35,7 @@
.getCaptcha {
display: block;
width: 100%;
height: 42px;
}
.submit {
......
......@@ -25,10 +25,12 @@ export default class PageHeader extends PureComponent {
componentDidMount() {
this.getBreadcrumbDom();
}
componentWillReceiveProps() {
this.getBreadcrumbDom();
}
componentDidUpdate(preProps) {
if (preProps.tabActiveKey !== this.props.tabActiveKey) {
this.getBreadcrumbDom();
}
}
onChange = key => {
if (this.props.onTabChange) {
this.props.onTabChange(key);
......
......@@ -4,6 +4,9 @@
text-align: center;
width: 72%;
margin: 0 auto;
@media screen and (max-width: @screen-xs) {
width: 100%;
}
.icon {
font-size: 72px;
......@@ -39,6 +42,10 @@
padding: 24px 40px;
border-radius: @border-radius-sm;
text-align: left;
@media screen and (max-width: @screen-xs) {
padding: 18px 20px;
}
}
.actions {
......
......@@ -87,7 +87,7 @@ class Sidebar extends PureComponent {
this.changeSetting('fixSiderbar', checked);
};
changeSetting = (key, value) => {
const nextState = {};
const nextState = { ...this.props.setting };
nextState[key] = value;
if (key === 'layout') {
if (value === 'topmenu') {
......
......@@ -67,7 +67,9 @@ export default class BaseMenu extends PureComponent {
};
// Get the currently selected menu
getSelectedMenuKeys = () => {
const { location: { pathname } } = this.props;
const {
location: { pathname },
} = this.props;
return urlToList(pathname).map(itemPath => getMenuMatches(this.flatMenuKeys, itemPath).pop());
};
/**
......@@ -148,20 +150,27 @@ export default class BaseMenu extends PureComponent {
}
};
render() {
const { openKeys } = this.props;
const { openKeys, theme, mode } = this.props;
// if pathname can't match, use the nearest parent's key
let selectedKeys = this.getSelectedMenuKeys();
if (!selectedKeys.length && openKeys) {
selectedKeys = [openKeys[openKeys.length - 1]];
}
let props = {};
if (openKeys) {
props = {
openKeys,
};
}
return (
<Menu
key="Menu"
mode="inline"
mode={mode}
theme={theme}
onOpenChange={this.props.handleOpenChange}
selectedKeys={selectedKeys}
style={this.props.style}
{...this.props}
{...props}
>
{this.getNavMenuItems(this.menus)}
</Menu>
......
import React, { PureComponent } from 'react';
import { Layout, Menu, Icon } from 'antd';
import pathToRegexp from 'path-to-regexp';
import { Link } from 'dva/router';
import styles from './index.less';
import BaseMenu, { getMenuMatches } from './BaseMenu';
......@@ -37,6 +38,32 @@ const getIcon = icon => {
return icon;
};
/**
* Recursively flatten the data
* [{path:string},{path:string}] => {path,path2}
* @param menu
*/
export const getFlatMenuKeys = menu =>
menu.reduce((keys, item) => {
keys.push(item.path);
if (item.children) {
return keys.concat(getFlatMenuKeys(item.children));
}
return keys;
}, []);
/**
* Find all matched menu keys based on paths
* @param flatMenuKeys: [/abc, /abc/:id, /abc/:id/info]
* @param paths: [/abc, /abc/11, /abc/11/info]
*/
export const getMenuMatchKeys = (flatMenuKeys, paths) =>
paths.reduce(
(matchKeys, path) =>
matchKeys.concat(flatMenuKeys.filter(item => pathToRegexp(item).test(path))),
[]
);
export default class SiderMenu extends PureComponent {
static getDerivedStateFromProps(nextProps) {
return {
......@@ -45,6 +72,8 @@ export default class SiderMenu extends PureComponent {
}
constructor(props) {
super(props);
this.menus = props.menuData;
this.flatMenuKeys = getFlatMenuKeys(props.menuData);
this.state = {
openKeys: getDefaultCollapsedSubMenus(props),
};
......@@ -54,6 +83,15 @@ export default class SiderMenu extends PureComponent {
* Convert pathname to openKeys
* /list/search/articles = > ['list','/list/search']
* @param props
*/
getDefaultCollapsedSubMenus(props) {
const {
location: { pathname },
} =
props || this.props;
return getMenuMatchKeys(this.flatMenuKeys, urlToList(pathname));
}
/**
* 判断是否是http链接.返回 Link 或 a
* Judge whether it is http link.return a or Link
* @memberof SiderMenu
......@@ -120,6 +158,47 @@ export default class SiderMenu extends PureComponent {
return <Menu.Item key={item.path}>{this.getMenuItemPath(item)}</Menu.Item>;
}
};
/**
* 获得菜单子节点
* @memberof SiderMenu
*/
getNavMenuItems = menusData => {
if (!menusData) {
return [];
}
return menusData
.filter(item => item.name && !item.hideInMenu)
.map(item => {
// make dom
const ItemDom = this.getSubMenuOrItem(item);
return this.checkPermissionItem(item.authority, ItemDom);
})
.filter(item => item);
};
// Get the currently selected menu
getSelectedMenuKeys = () => {
const {
location: { pathname },
} = this.props;
return getMenuMatchKeys(this.flatMenuKeys, urlToList(pathname));
};
// conversion Path
// 转化路径
conversionPath = path => {
if (path && path.indexOf('http') === 0) {
return path;
} else {
return `/${path || ''}`.replace(/\/+/g, '/');
}
};
// permission to check
checkPermissionItem = (authority, ItemDom) => {
if (this.props.Authorized && this.props.Authorized.check) {
const { check } = this.props.Authorized;
return check(authority, ItemDom);
}
return ItemDom;
};
isMainMenu = key => {
return this.props.menuData.some(item => key && (item.key === key || item.path === key));
};
......
import { urlToList } from '../_utils/pathTools';
import { getFlatMenuKeys, getMenuMatchKeys } from './SiderMenu';
const menu = [
{
path: '/dashboard',
children: [
{
path: '/dashboard/name',
},
],
},
{
path: '/userinfo',
children: [
{
path: '/userinfo/:id',
children: [
{
path: '/userinfo/:id/info',
},
],
},
],
},
];
const flatMenuKeys = getFlatMenuKeys(menu);
describe('test convert nested menu to flat menu', () => {
it('simple menu', () => {
expect(flatMenuKeys).toEqual([
'/dashboard',
'/dashboard/name',
'/userinfo',
'/userinfo/:id',
'/userinfo/:id/info',
]);
});
});
describe('test menu match', () => {
it('simple path', () => {
expect(getMenuMatchKeys(flatMenuKeys, urlToList('/dashboard'))).toEqual(['/dashboard']);
});
it('error path', () => {
expect(getMenuMatchKeys(flatMenuKeys, urlToList('/dashboardname'))).toEqual([]);
});
it('Secondary path', () => {
expect(getMenuMatchKeys(flatMenuKeys, urlToList('/dashboard/name'))).toEqual([
'/dashboard',
'/dashboard/name',
]);
});
it('Parameter path', () => {
expect(getMenuMatchKeys(flatMenuKeys, urlToList('/userinfo/2144'))).toEqual([
'/userinfo',
'/userinfo/:id',
]);
});
it('three parameter path', () => {
expect(getMenuMatchKeys(flatMenuKeys, urlToList('/userinfo/2144/info'))).toEqual([
'/userinfo',
'/userinfo/:id',
'/userinfo/:id/info',
]);
});
});
......@@ -2,7 +2,7 @@ import puppeteer from 'puppeteer';
describe('Homepage', () => {
it('it should have logo text', async () => {
const browser = await puppeteer.launch();
const browser = await puppeteer.launch({ args: ['--no-sandbox'] });
const page = await browser.newPage();
await page.goto('http://localhost:8000', { waitUntil: 'networkidle2' });
await page.waitForSelector('h1');
......
......@@ -5,7 +5,7 @@ describe('Login', () => {
let page;
beforeAll(async () => {
browser = await puppeteer.launch();
browser = await puppeteer.launch({ args: ['--no-sandbox'] });
});
beforeEach(async () => {
......
......@@ -5,6 +5,7 @@ import { connect } from 'dva';
import { Route, Redirect, Switch } from 'dva/router';
import { ContainerQuery } from 'react-container-query';
import classNames from 'classnames';
import pathToRegexp from 'path-to-regexp';
import SiderMenu from '../components/SiderMenu';
import NotFound from '../routes/Exception/404';
import { getRoutes } from '../utils/utils';
......@@ -70,8 +71,15 @@ class BasicLayout extends React.PureComponent {
const { routerData, location } = this.props;
const { pathname } = location;
let title = 'Ant Design Pro';
if (routerData[pathname] && routerData[pathname].name) {
title = `${routerData[pathname].name} - Ant Design Pro`;
let currRouterData = null;
// match params path
Object.keys(routerData).forEach(key => {
if (pathToRegexp(key).test(pathname)) {
currRouterData = routerData[key];
}
});
if (currRouterData && currRouterData.name) {
title = `${currRouterData.name} - Ant Design Pro`;
}
return title;
}
......
......@@ -2,7 +2,6 @@ import React, { PureComponent } from 'react';
import { Spin } from 'antd';
import { connect } from 'dva';
import { enquireScreen, unenquireScreen } from 'enquire-js';
import BasicLayout from './BasicLayout';
import { getMenuData } from '../common/menu';
/**
......@@ -35,7 +34,6 @@ class LoadingPage extends PureComponent {
loading: true,
isMobile: false,
};
componentDidMount() {
this.enquireHandler = enquireScreen(mobile => {
this.setState({
......@@ -45,8 +43,8 @@ class LoadingPage extends PureComponent {
this.props.dispatch({
type: 'user/fetchCurrent',
});
this.initSetting();
this.hideLoading();
this.initSetting();
}
componentWillUnmount() {
unenquireScreen(this.enquireHandler);
......
......@@ -11,19 +11,21 @@ const defaultSetting = {
};
export default {
namespace: 'setting',
state: defaultSetting,
reducers: {
getSetting(state) {
const setting = { ...state };
const setting = {};
const urlParams = new URL(window.location.href);
Object.keys(state).forEach(key => {
if (urlParams.searchParams.has(key)) {
const value = urlParams.searchParams.get(key);
setting[key] = value === '1' ? true : '1';
setting[key] = value === '1' ? true : value;
}
});
return setting;
return {
...state,
...setting,
};
},
changeSetting(state, { payload }) {
const urlParams = new URL(window.location.href);
......
......@@ -44,6 +44,12 @@ for (let i = 0; i < 7; i += 1) {
});
}
const Yuan = ({ children }) => (
<span
dangerouslySetInnerHTML={{ __html: yuan(children) }}
/> /* eslint-disable-line react/no-danger */
);
@connect(({ chart, loading }) => ({
chart,
loading: loading.effects['chart/fetch'],
......@@ -132,7 +138,9 @@ export default class Analysis extends Component {
const salesPieData =
salesType === 'all'
? salesTypeData
: salesType === 'online' ? salesTypeDataOnline : salesTypeDataOffline;
: salesType === 'online'
? salesTypeDataOnline
: salesTypeDataOffline;
const menu = (
<Menu>
......@@ -254,7 +262,7 @@ export default class Analysis extends Component {
<Icon type="info-circle-o" />
</Tooltip>
}
total={() => <span dangerouslySetInnerHTML={{ __html: yuan(126560) }} />}
total={() => <Yuan>126560</Yuan>}
footer={<Field label="日均销售额" value={`¥${numeral(12423).format('0,0')}`} />}
contentHeight={46}
>
......@@ -453,15 +461,9 @@ export default class Analysis extends Component {
<Pie
hasLegend
subTitle="销售额"
total={() => (
<span
dangerouslySetInnerHTML={{
__html: yuan(salesPieData.reduce((pre, now) => now.y + pre, 0)),
}}
/>
)}
total={() => <Yuan>{salesPieData.reduce((pre, now) => now.y + pre, 0)}</Yuan>}
data={salesPieData}
valueFormat={val => <span dangerouslySetInnerHTML={{ __html: yuan(val) }} />}
valueFormat={value => <Yuan>{value}</Yuan>}
height={248}
lineWidth={4}
/>
......
......@@ -14,28 +14,34 @@ class Step3 extends React.PureComponent {
const information = (
<div className={styles.information}>
<Row>
<Col span={8} className={styles.label}>
<Col xs={24} sm={8} className={styles.label}>
付款账户
</Col>
<Col span={16}>{data.payAccount}</Col>
<Col xs={24} sm={16}>
{data.payAccount}
</Col>
</Row>
<Row>
<Col span={8} className={styles.label}>
<Col xs={24} sm={8} className={styles.label}>
收款账户
</Col>
<Col span={16}>{data.receiverAccount}</Col>
<Col xs={24} sm={16}>
{data.receiverAccount}
</Col>
</Row>
<Row>
<Col span={8} className={styles.label}>
<Col xs={24} sm={8} className={styles.label}>
收款人姓名
</Col>
<Col span={16}>{data.receiverName}</Col>
<Col xs={24} sm={16}>
{data.receiverName}
</Col>
</Row>
<Row>
<Col span={8} className={styles.label}>
<Col xs={24} sm={8} className={styles.label}>
转账金额
</Col>
<Col span={16}>
<Col xs={24} sm={16}>
<span className={styles.money}>{data.amount}</span>
</Col>
</Row>
......
......@@ -24,10 +24,11 @@ export default class StepForm extends PureComponent {
}
}
render() {
const { match, routerData } = this.props;
const { match, routerData, location } = this.props;
return (
<PageHeaderLayout
title="分步表单"
tabActiveKey={location.pathname}
content="将一个冗长或用户不熟悉的表单任务分成多个步骤,指导用户完成。"
>
<Card bordered={false}>
......
......@@ -60,6 +60,9 @@
color: @heading-color;
text-align: right;
padding-right: 8px;
@media screen and (max-width: @screen-sm) {
text-align: left;
}
}
}
......
import React, { Fragment } from 'react';
import { Button, Row, Col, Icon, Steps, Card } from 'antd';
import Result from '../../components/Result';
import Result from 'components/Result';
import PageHeaderLayout from '../../layouts/PageHeaderLayout';
const { Step } = Steps;
......
......@@ -3,6 +3,9 @@
.main {
width: 368px;
margin: 0 auto;
@media screen and (max-width: @screen-sm) {
width: 95%;
}
.icon {
font-size: 24px;
......
......@@ -30,8 +30,9 @@ startServer.stdout.on('data', data => {
const testCmd = spawn(/^win/.test(process.platform) ? 'npm.cmd' : 'npm', ['test'], {
stdio: 'inherit',
});
testCmd.on('exit', () => {
testCmd.on('exit', code => {
startServer.kill();
process.exit(code);
});
}
});
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment