Ver código fonte

fix default setting bug

jim 7 anos atrás
pai
commit
0e2cd76a41

+ 1 - 1
.babelrc.js

@@ -3,7 +3,7 @@ const path = require('path');
 module.exports = {
   plugins: [
     [
-      'babel-plugin-module-resolver',
+      'module-resolver',
       {
         alias: {
           components: path.join(__dirname, './src/components'),

+ 1 - 0
.gitignore

@@ -21,3 +21,4 @@ yarn.lock
 package-lock.json
 *bak
 jsconfig.json
+.vscode/settings.json

+ 1 - 0
.prettierignore

@@ -1,4 +1,5 @@
 **/*.md
 **/*.svg
 **/*.ejs
+**/*.html
 package.json

+ 6 - 6
package.json

@@ -1,6 +1,6 @@
 {
   "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",

+ 1 - 1
src/components/Charts/index.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,

+ 4 - 1
src/components/DescriptionList/DescriptionList.js

@@ -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>
   );

+ 1 - 0
src/components/Login/index.d.ts

@@ -18,6 +18,7 @@ export interface LoginItemProps {
   rules?: any[];
   style?: React.CSSProperties;
   onGetCaptcha?: () => void;
+  placeholder?: string;
 }
 
 export class LoginItem extends React.Component<LoginItemProps, any> {}

+ 1 - 0
src/components/Login/index.less

@@ -35,6 +35,7 @@
   .getCaptcha {
     display: block;
     width: 100%;
+    height: 42px;
   }
 
   .submit {

+ 5 - 3
src/components/PageHeader/index.js

@@ -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);

+ 7 - 0
src/components/Result/index.less

@@ -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 {

+ 1 - 1
src/components/Sidebar/index.js

@@ -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') {

+ 13 - 4
src/components/SiderMenu/BaseMenu.js

@@ -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>

+ 79 - 0
src/components/SiderMenu/SiderMenu.js

@@ -1,5 +1,6 @@
 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));
   };

+ 72 - 0
src/components/SiderMenu/SilderMenu.test.js

@@ -0,0 +1,72 @@
+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',
+    ]);
+  });
+});

+ 1 - 1
src/e2e/home.e2e.js

@@ -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');

+ 1 - 1
src/e2e/login.e2e.js

@@ -5,7 +5,7 @@ describe('Login', () => {
   let page;
 
   beforeAll(async () => {
-    browser = await puppeteer.launch();
+    browser = await puppeteer.launch({ args: ['--no-sandbox'] });
   });
 
   beforeEach(async () => {

+ 10 - 2
src/layouts/BasicLayout.js

@@ -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;
   }

+ 1 - 3
src/layouts/LoadingPage.js

@@ -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);

+ 6 - 4
src/models/setting.js

@@ -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);

+ 12 - 10
src/routes/Dashboard/Analysis.js

@@ -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 - 8
src/routes/Forms/StepForm/Step3.js

@@ -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>

+ 2 - 1
src/routes/Forms/StepForm/index.js

@@ -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}>

+ 3 - 0
src/routes/Forms/StepForm/style.less

@@ -60,6 +60,9 @@
     color: @heading-color;
     text-align: right;
     padding-right: 8px;
+    @media screen and (max-width: @screen-sm) {
+      text-align: left;
+    }
   }
 }
 

+ 1 - 1
src/routes/Result/Success.js

@@ -1,6 +1,6 @@
 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 - 0
src/routes/User/Login.less

@@ -3,6 +3,9 @@
 .main {
   width: 368px;
   margin: 0 auto;
+  @media screen and (max-width: @screen-sm) {
+    width: 95%;
+  }
 
   .icon {
     font-size: 24px;

+ 2 - 1
tests/run-tests.js

@@ -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);
     });
   }
 });