Commit 92293e44 authored by ddcat1115's avatar ddcat1115

Merge branch 'master' into v2

parents 509e432c ebd6f2ff
...@@ -2,6 +2,10 @@ ...@@ -2,6 +2,10 @@
environment: environment:
nodejs_version: "8" nodejs_version: "8"
# this is how to allow failing jobs in the matrix
matrix:
fast_finish: true # set this flag to immediately finish build once one of the jobs fails.
# Install scripts. (runs after repo cloning) # Install scripts. (runs after repo cloning)
install: install:
# Get the latest stable version of Node.js or io.js # Get the latest stable version of Node.js or io.js
......
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
"react-document-title": "^2.0.3", "react-document-title": "^2.0.3",
"react-dom": "^16.2.0", "react-dom": "^16.2.0",
"react-fittext": "^1.0.0", "react-fittext": "^1.0.0",
"rollbar": "^2.3.4",
"url-polyfill": "^1.0.10" "url-polyfill": "^1.0.10"
}, },
"devDependencies": { "devDependencies": {
...@@ -72,7 +73,6 @@ ...@@ -72,7 +73,6 @@
"regenerator-runtime": "^0.11.1", "regenerator-runtime": "^0.11.1",
"roadhog": "^2.1.0", "roadhog": "^2.1.0",
"roadhog-api-doc": "^0.3.4", "roadhog-api-doc": "^0.3.4",
"rollbar": "^2.3.4",
"stylelint": "^8.4.0", "stylelint": "^8.4.0",
"stylelint-config-standard": "^18.0.0" "stylelint-config-standard": "^18.0.0"
}, },
......
...@@ -115,7 +115,7 @@ const menuData = [{ ...@@ -115,7 +115,7 @@ const menuData = [{
}], }],
}]; }];
function formatter(data, parentPath = '', parentAuthority) { function formatter(data, parentPath = '/', parentAuthority) {
return data.map((item) => { return data.map((item) => {
let { path } = item; let { path } = item;
if (!isUrl(path)) { if (!isUrl(path)) {
......
...@@ -92,12 +92,15 @@ export const getRouterData = (app) => { ...@@ -92,12 +92,15 @@ export const getRouterData = (app) => {
component: dynamicWrapper(app, ['form'], () => import('../routes/Forms/StepForm')), component: dynamicWrapper(app, ['form'], () => import('../routes/Forms/StepForm')),
}, },
'/form/step-form/info': { '/form/step-form/info': {
name: '分步表单(填写转账信息)',
component: dynamicWrapper(app, ['form'], () => import('../routes/Forms/StepForm/Step1')), component: dynamicWrapper(app, ['form'], () => import('../routes/Forms/StepForm/Step1')),
}, },
'/form/step-form/confirm': { '/form/step-form/confirm': {
name: '分步表单(确认转账信息)',
component: dynamicWrapper(app, ['form'], () => import('../routes/Forms/StepForm/Step2')), component: dynamicWrapper(app, ['form'], () => import('../routes/Forms/StepForm/Step2')),
}, },
'/form/step-form/result': { '/form/step-form/result': {
name: '分步表单(完成)',
component: dynamicWrapper(app, ['form'], () => import('../routes/Forms/StepForm/Step3')), component: dynamicWrapper(app, ['form'], () => import('../routes/Forms/StepForm/Step3')),
}, },
'/form/advanced-form': { '/form/advanced-form': {
...@@ -193,7 +196,7 @@ export const getRouterData = (app) => { ...@@ -193,7 +196,7 @@ export const getRouterData = (app) => {
// Regular match item name // Regular match item name
// eg. router /user/:id === /user/chen // eg. router /user/:id === /user/chen
const pathRegexp = pathToRegexp(path); const pathRegexp = pathToRegexp(path);
const menuKey = Object.keys(menuData).find(key => pathRegexp.test(`/${key}`)); const menuKey = Object.keys(menuData).find(key => pathRegexp.test(`${key}`));
let menuItem = {}; let menuItem = {};
// If menuKey is not empty // If menuKey is not empty
if (menuKey) { if (menuKey) {
......
...@@ -6,9 +6,17 @@ export default class PromiseRender extends React.PureComponent { ...@@ -6,9 +6,17 @@ export default class PromiseRender extends React.PureComponent {
component: null, component: null,
}; };
componentDidMount() { componentDidMount() {
const ok = this.checkIsInstantiation(this.props.ok); this.setRenderComponent(this.props);
const error = this.checkIsInstantiation(this.props.error); }
this.props.promise componentWillReceiveProps(nextProps) {
// new Props enter
this.setRenderComponent(nextProps);
}
// set render Component : ok or error
setRenderComponent(props) {
const ok = this.checkIsInstantiation(props.ok);
const error = this.checkIsInstantiation(props.error);
props.promise
.then(() => { .then(() => {
this.setState({ this.setState({
component: ok, component: ok,
......
...@@ -51,9 +51,8 @@ class CountDown extends Component { ...@@ -51,9 +51,8 @@ class CountDown extends Component {
} }
lastTime = targetTime - new Date().getTime(); lastTime = targetTime - new Date().getTime();
return { return {
lastTime, lastTime: lastTime < 0 ? 0 : lastTime,
}; };
} }
// defaultFormat = time => ( // defaultFormat = time => (
...@@ -63,11 +62,11 @@ class CountDown extends Component { ...@@ -63,11 +62,11 @@ class CountDown extends Component {
const hours = 60 * 60 * 1000; const hours = 60 * 60 * 1000;
const minutes = 60 * 1000; const minutes = 60 * 1000;
const h = fixedZero(Math.floor(time / hours)); const h = Math.floor(time / hours);
const m = fixedZero(Math.floor((time - (h * hours)) / minutes)); const m = Math.floor((time - (h * hours)) / minutes);
const s = fixedZero(Math.floor((time - (h * hours) - (m * minutes)) / 1000)); const s = Math.floor((time - (h * hours) - (m * minutes)) / 1000);
return ( return (
<span>{h}:{m}:{s}</span> <span>{fixedZero(h)}:{fixedZero(m)}:{fixedZero(s)}</span>
); );
} }
tick = () => { tick = () => {
...@@ -96,9 +95,8 @@ class CountDown extends Component { ...@@ -96,9 +95,8 @@ class CountDown extends Component {
} }
render() { render() {
const { format = this.defaultFormat, ...rest } = this.props; const { format = this.defaultFormat, onEnd, ...rest } = this.props;
const { lastTime } = this.state; const { lastTime } = this.state;
const result = format(lastTime); const result = format(lastTime);
return (<span {...rest}>{result}</span>); return (<span {...rest}>{result}</span>);
......
...@@ -4,7 +4,7 @@ import pathToRegexp from 'path-to-regexp'; ...@@ -4,7 +4,7 @@ import pathToRegexp from 'path-to-regexp';
import { Breadcrumb, Tabs } from 'antd'; import { Breadcrumb, Tabs } from 'antd';
import classNames from 'classnames'; import classNames from 'classnames';
import styles from './index.less'; import styles from './index.less';
import { urlToList } from '../utils/pathTools';
const { TabPane } = Tabs; const { TabPane } = Tabs;
export function getBreadcrumb(breadcrumbNameMap, url) { export function getBreadcrumb(breadcrumbNameMap, url) {
...@@ -19,14 +19,6 @@ export function getBreadcrumb(breadcrumbNameMap, url) { ...@@ -19,14 +19,6 @@ export function getBreadcrumb(breadcrumbNameMap, url) {
return breadcrumb || {}; return breadcrumb || {};
} }
// /userinfo/2144/id => ['/userinfo','/useinfo/2144,'/userindo/2144/id']
export function urlToList(url) {
const urllist = url.split('/').filter(i => i);
return urllist.map((urlItem, index) => {
return `/${urllist.slice(0, index + 1).join('/')}`;
});
}
export default class PageHeader extends PureComponent { export default class PageHeader extends PureComponent {
static contextTypes = { static contextTypes = {
routes: PropTypes.array, routes: PropTypes.array,
...@@ -44,29 +36,35 @@ export default class PageHeader extends PureComponent { ...@@ -44,29 +36,35 @@ export default class PageHeader extends PureComponent {
routes: this.props.routes || this.context.routes, routes: this.props.routes || this.context.routes,
params: this.props.params || this.context.params, params: this.props.params || this.context.params,
routerLocation: this.props.location || this.context.location, routerLocation: this.props.location || this.context.location,
breadcrumbNameMap: this.props.breadcrumbNameMap || this.context.breadcrumbNameMap, breadcrumbNameMap:
this.props.breadcrumbNameMap || this.context.breadcrumbNameMap,
}; };
}; };
// Generated according to props // Generated according to props
conversionFromProps= () => { conversionFromProps = () => {
const { const {
breadcrumbList, breadcrumbSeparator, linkElement = 'a', breadcrumbList,
breadcrumbSeparator,
linkElement = 'a',
} = this.props; } = this.props;
return ( return (
<Breadcrumb <Breadcrumb className={styles.breadcrumb} separator={breadcrumbSeparator}>
className={styles.breadcrumb}
separator={breadcrumbSeparator}
>
{breadcrumbList.map(item => ( {breadcrumbList.map(item => (
<Breadcrumb.Item key={item.title}> <Breadcrumb.Item key={item.title}>
{item.href ? (createElement(linkElement, { {item.href
[linkElement === 'a' ? 'href' : 'to']: item.href, ? createElement(
}, item.title)) : item.title} linkElement,
{
[linkElement === 'a' ? 'href' : 'to']: item.href,
},
item.title,
)
: item.title}
</Breadcrumb.Item> </Breadcrumb.Item>
))} ))}
</Breadcrumb> </Breadcrumb>
); );
} };
conversionFromLocation = (routerLocation, breadcrumbNameMap) => { conversionFromLocation = (routerLocation, breadcrumbNameMap) => {
const { breadcrumbSeparator, linkElement = 'a' } = this.props; const { breadcrumbSeparator, linkElement = 'a' } = this.props;
// Convert the url to an array // Convert the url to an array
...@@ -74,7 +72,8 @@ export default class PageHeader extends PureComponent { ...@@ -74,7 +72,8 @@ export default class PageHeader extends PureComponent {
// Loop data mosaic routing // Loop data mosaic routing
const extraBreadcrumbItems = pathSnippets.map((url, index) => { const extraBreadcrumbItems = pathSnippets.map((url, index) => {
const currentBreadcrumb = getBreadcrumb(breadcrumbNameMap, url); const currentBreadcrumb = getBreadcrumb(breadcrumbNameMap, url);
const isLinkable = (index !== pathSnippets.length - 1) && currentBreadcrumb.component; const isLinkable =
index !== pathSnippets.length - 1 && currentBreadcrumb.component;
return currentBreadcrumb.name && !currentBreadcrumb.hideInBreadcrumb ? ( return currentBreadcrumb.name && !currentBreadcrumb.hideInBreadcrumb ? (
<Breadcrumb.Item key={url}> <Breadcrumb.Item key={url}>
{createElement( {createElement(
...@@ -88,26 +87,33 @@ export default class PageHeader extends PureComponent { ...@@ -88,26 +87,33 @@ export default class PageHeader extends PureComponent {
// Add home breadcrumbs to your head // Add home breadcrumbs to your head
extraBreadcrumbItems.unshift( extraBreadcrumbItems.unshift(
<Breadcrumb.Item key="home"> <Breadcrumb.Item key="home">
{createElement(linkElement, { {createElement(
[linkElement === 'a' ? 'href' : 'to']: '/' }, '首页')} linkElement,
</Breadcrumb.Item> {
[linkElement === 'a' ? 'href' : 'to']: '/',
},
'首页',
)}
</Breadcrumb.Item>,
); );
return ( return (
<Breadcrumb <Breadcrumb className={styles.breadcrumb} separator={breadcrumbSeparator}>
className={styles.breadcrumb}
separator={breadcrumbSeparator}
>
{extraBreadcrumbItems} {extraBreadcrumbItems}
</Breadcrumb> </Breadcrumb>
); );
} };
/** /**
* 将参数转化为面包屑 * 将参数转化为面包屑
* Convert parameters into breadcrumbs * Convert parameters into breadcrumbs
*/ */
conversionBreadcrumbList = () => { conversionBreadcrumbList = () => {
const { breadcrumbList, breadcrumbSeparator } = this.props; const { breadcrumbList, breadcrumbSeparator } = this.props;
const { routes, params, routerLocation, breadcrumbNameMap } = this.getBreadcrumbProps(); const {
routes,
params,
routerLocation,
breadcrumbNameMap,
} = this.getBreadcrumbProps();
if (breadcrumbList && breadcrumbList.length) { if (breadcrumbList && breadcrumbList.length) {
return this.conversionFromProps(); return this.conversionFromProps();
} }
...@@ -126,28 +132,41 @@ export default class PageHeader extends PureComponent { ...@@ -126,28 +132,41 @@ export default class PageHeader extends PureComponent {
} }
// 根据 location 生成 面包屑 // 根据 location 生成 面包屑
// Generate breadcrumbs based on location // Generate breadcrumbs based on location
if (location && location.pathname) { if (routerLocation && routerLocation.pathname) {
return this.conversionFromLocation(routerLocation, breadcrumbNameMap); return this.conversionFromLocation(routerLocation, breadcrumbNameMap);
} }
return null; return null;
} };
// 渲染Breadcrumb 子节点 // 渲染Breadcrumb 子节点
// Render the Breadcrumb child node // Render the Breadcrumb child node
itemRender = (route, params, routes, paths) => { itemRender = (route, params, routes, paths) => {
const { linkElement = 'a' } = this.props; const { linkElement = 'a' } = this.props;
const last = routes.indexOf(route) === routes.length - 1; const last = routes.indexOf(route) === routes.length - 1;
return (last || !route.component) return last || !route.component ? (
? <span>{route.breadcrumbName}</span> <span>{route.breadcrumbName}</span>
: createElement(linkElement, { ) : (
href: paths.join('/') || '/', createElement(
to: paths.join('/') || '/', linkElement,
}, route.breadcrumbName); {
} href: paths.join('/') || '/',
to: paths.join('/') || '/',
},
route.breadcrumbName,
)
);
};
render() { render() {
const { const {
title, logo, action, content, extraContent, title,
tabList, className, tabActiveKey, tabBarExtraContent, logo,
action,
content,
extraContent,
tabList,
className,
tabActiveKey,
tabBarExtraContent,
} = this.props; } = this.props;
const clsString = classNames(styles.pageHeader, className); const clsString = classNames(styles.pageHeader, className);
...@@ -175,12 +194,13 @@ export default class PageHeader extends PureComponent { ...@@ -175,12 +194,13 @@ export default class PageHeader extends PureComponent {
</div> </div>
<div className={styles.row}> <div className={styles.row}>
{content && <div className={styles.content}>{content}</div>} {content && <div className={styles.content}>{content}</div>}
{extraContent && <div className={styles.extraContent}>{extraContent}</div>} {extraContent && (
<div className={styles.extraContent}>{extraContent}</div>
)}
</div> </div>
</div> </div>
</div> </div>
{ {tabList &&
tabList &&
tabList.length && ( tabList.length && (
<Tabs <Tabs
className={styles.tabs} className={styles.tabs}
...@@ -188,12 +208,9 @@ export default class PageHeader extends PureComponent { ...@@ -188,12 +208,9 @@ export default class PageHeader extends PureComponent {
onChange={this.onChange} onChange={this.onChange}
tabBarExtraContent={tabBarExtraContent} tabBarExtraContent={tabBarExtraContent}
> >
{ {tabList.map(item => <TabPane tab={item.tab} key={item.key} />)}
tabList.map(item => <TabPane tab={item.tab} key={item.key} />)
}
</Tabs> </Tabs>
) )}
}
</div> </div>
); );
} }
......
import { getBreadcrumb, urlToList } from './index'; import { getBreadcrumb } from './index';
import { urlToList } from '../utils/pathTools';
describe('test urlToList', () => {
it('A path', () => {
expect(urlToList('/userinfo')).toEqual(['/userinfo']);
});
it('Secondary path', () => {
expect(urlToList('/userinfo/2144')).toEqual([
'/userinfo',
'/userinfo/2144',
]);
});
it('Three paths', () => {
expect(urlToList('/userinfo/2144/addr')).toEqual([
'/userinfo',
'/userinfo/2144',
'/userinfo/2144/addr',
]);
});
});
const routerData = { const routerData = {
'/dashboard/analysis': { '/dashboard/analysis': {
...@@ -36,17 +18,17 @@ const routerData = { ...@@ -36,17 +18,17 @@ const routerData = {
describe('test getBreadcrumb', () => { describe('test getBreadcrumb', () => {
it('Simple url', () => { it('Simple url', () => {
expect(getBreadcrumb(routerData, '/dashboard/analysis').name).toEqual( expect(getBreadcrumb(routerData, '/dashboard/analysis').name).toEqual(
'分析页' '分析页',
); );
}); });
it('Parameters url', () => { it('Parameters url', () => {
expect(getBreadcrumb(routerData, '/userinfo/2144').name).toEqual( expect(getBreadcrumb(routerData, '/userinfo/2144').name).toEqual(
'用户信息' '用户信息',
); );
}); });
it('The middle parameter url', () => { it('The middle parameter url', () => {
expect(getBreadcrumb(routerData, '/userinfo/2144/addr').name).toEqual( expect(getBreadcrumb(routerData, '/userinfo/2144/addr').name).toEqual(
'收货订单' '收货订单',
); );
}); });
it('Loop through the parameters', () => { it('Loop through the parameters', () => {
......
...@@ -3,6 +3,7 @@ import { Layout, Menu, Icon } from 'antd'; ...@@ -3,6 +3,7 @@ import { Layout, Menu, Icon } from 'antd';
import pathToRegexp from 'path-to-regexp'; import pathToRegexp from 'path-to-regexp';
import { Link } from 'dva/router'; import { Link } from 'dva/router';
import styles from './index.less'; import styles from './index.less';
import { urlToList } from '../utils/pathTools';
const { Sider } = Layout; const { Sider } = Layout;
const { SubMenu } = Menu; const { SubMenu } = Menu;
...@@ -21,10 +22,17 @@ const getIcon = (icon) => { ...@@ -21,10 +22,17 @@ const getIcon = (icon) => {
return icon; return icon;
}; };
export const getMeunMatcheys = (flatMenuKeys, path) => {
return flatMenuKeys.filter((item) => {
return pathToRegexp(item).test(path);
});
};
export default class SiderMenu extends PureComponent { export default class SiderMenu extends PureComponent {
constructor(props) { constructor(props) {
super(props); super(props);
this.menus = props.menuData; this.menus = props.menuData;
this.flatMenuKeys = this.getFlatMenuKeys(props.menuData);
this.state = { this.state = {
openKeys: this.getDefaultCollapsedSubMenus(props), openKeys: this.getDefaultCollapsedSubMenus(props),
}; };
...@@ -43,30 +51,11 @@ export default class SiderMenu extends PureComponent { ...@@ -43,30 +51,11 @@ export default class SiderMenu extends PureComponent {
*/ */
getDefaultCollapsedSubMenus(props) { getDefaultCollapsedSubMenus(props) {
const { location: { pathname } } = props || this.props; const { location: { pathname } } = props || this.props;
// eg. /list/search/articles = > ['','list','search','articles'] return urlToList(pathname)
let snippets = pathname.split('/'); .map((item) => {
// Delete the end return getMeunMatcheys(this.flatMenuKeys, item)[0];
// eg. delete 'articles' })
snippets.pop(); .filter(item => item);
// Delete the head
// eg. delete ''
snippets.shift();
// eg. After the operation is completed, the array should be ['list','search']
// eg. Forward the array as ['list','list/search']
snippets = snippets.map((item, index) => {
// If the array length > 1
if (index > 0) {
// eg. search => ['list','search'].join('/')
return snippets.slice(0, index + 1).join('/');
}
// index 0 to not do anything
return item;
});
snippets = snippets.map((item) => {
return this.getSelectedMenuKeys(`/${item}`)[0];
});
// eg. ['list','list/search']
return snippets;
} }
/** /**
* Recursively flatten the data * Recursively flatten the data
...@@ -77,29 +66,17 @@ export default class SiderMenu extends PureComponent { ...@@ -77,29 +66,17 @@ export default class SiderMenu extends PureComponent {
let keys = []; let keys = [];
menus.forEach((item) => { menus.forEach((item) => {
if (item.children) { if (item.children) {
keys.push(item.path);
keys = keys.concat(this.getFlatMenuKeys(item.children)); keys = keys.concat(this.getFlatMenuKeys(item.children));
} else {
keys.push(item.path);
} }
keys.push(item.path);
}); });
return keys; return keys;
} }
/** /**
* Get selected child nodes * 判断是否是http链接.返回 Link 或 a
* /user/chen => ['user','/user/:id'] * Judge whether it is http link.return a or Link
* @memberof SiderMenu
*/ */
getSelectedMenuKeys = (path) => {
const flatMenuKeys = this.getFlatMenuKeys(this.menus);
return flatMenuKeys.filter((item) => {
return pathToRegexp(`/${item}(.*)`).test(path);
});
}
/**
* 判断是否是http链接.返回 Link 或 a
* Judge whether it is http link.return a or Link
* @memberof SiderMenu
*/
getMenuItemPath = (item) => { getMenuItemPath = (item) => {
const itemPath = this.conversionPath(item.path); const itemPath = this.conversionPath(item.path);
const icon = getIcon(item.icon); const icon = getIcon(item.icon);
...@@ -108,7 +85,8 @@ export default class SiderMenu extends PureComponent { ...@@ -108,7 +85,8 @@ export default class SiderMenu extends PureComponent {
if (/^https?:\/\//.test(itemPath)) { if (/^https?:\/\//.test(itemPath)) {
return ( return (
<a href={itemPath} target={target}> <a href={itemPath} target={target}>
{icon}<span>{name}</span> {icon}
<span>{name}</span>
</a> </a>
); );
} }
...@@ -117,16 +95,23 @@ export default class SiderMenu extends PureComponent { ...@@ -117,16 +95,23 @@ export default class SiderMenu extends PureComponent {
to={itemPath} to={itemPath}
target={target} target={target}
replace={itemPath === this.props.location.pathname} replace={itemPath === this.props.location.pathname}
onClick={this.props.isMobile ? () => { this.props.onCollapse(true); } : undefined} onClick={
this.props.isMobile
? () => {
this.props.onCollapse(true);
}
: undefined
}
> >
{icon}<span>{name}</span> {icon}
<span>{name}</span>
</Link> </Link>
); );
} };
/** /**
* get SubMenu or Item * get SubMenu or Item
*/ */
getSubMenuOrItem=(item) => { getSubMenuOrItem = (item) => {
if (item.children && item.children.some(child => child.name)) { if (item.children && item.children.some(child => child.name)) {
return ( return (
<SubMenu <SubMenu
...@@ -136,8 +121,10 @@ export default class SiderMenu extends PureComponent { ...@@ -136,8 +121,10 @@ export default class SiderMenu extends PureComponent {
{getIcon(item.icon)} {getIcon(item.icon)}
<span>{item.name}</span> <span>{item.name}</span>
</span> </span>
) : item.name ) : (
} item.name
)
}
key={item.path} key={item.path}
> >
{this.getNavMenuItems(item.children)} {this.getNavMenuItems(item.children)}
...@@ -145,16 +132,14 @@ export default class SiderMenu extends PureComponent { ...@@ -145,16 +132,14 @@ export default class SiderMenu extends PureComponent {
); );
} else { } else {
return ( return (
<Menu.Item key={item.path}> <Menu.Item key={item.path}>{this.getMenuItemPath(item)}</Menu.Item>
{this.getMenuItemPath(item)}
</Menu.Item>
); );
} }
} };
/** /**
* 获得菜单子节点 * 获得菜单子节点
* @memberof SiderMenu * @memberof SiderMenu
*/ */
getNavMenuItems = (menusData) => { getNavMenuItems = (menusData) => {
if (!menusData) { if (!menusData) {
return []; return [];
...@@ -162,49 +147,60 @@ export default class SiderMenu extends PureComponent { ...@@ -162,49 +147,60 @@ export default class SiderMenu extends PureComponent {
return menusData return menusData
.filter(item => item.name && !item.hideInMenu) .filter(item => item.name && !item.hideInMenu)
.map((item) => { .map((item) => {
// make dom
const ItemDom = this.getSubMenuOrItem(item); const ItemDom = this.getSubMenuOrItem(item);
return this.checkPermissionItem(item.authority, ItemDom); return this.checkPermissionItem(item.authority, ItemDom);
}) })
.filter(item => !!item); .filter(item => item);
} };
// Get the currently selected menu
getSelectedMenuKeys = () => {
const { location: { pathname } } = this.props;
return urlToList(pathname).map(itemPath =>
getMeunMatcheys(this.flatMenuKeys, itemPath).pop(),
);
};
// conversion Path // conversion Path
// 转化路径 // 转化路径
conversionPath=(path) => { conversionPath = (path) => {
if (path && path.indexOf('http') === 0) { if (path && path.indexOf('http') === 0) {
return path; return path;
} else { } else {
return `/${path || ''}`.replace(/\/+/g, '/'); return `/${path || ''}`.replace(/\/+/g, '/');
} }
} };
// permission to check // permission to check
checkPermissionItem = (authority, ItemDom) => { checkPermissionItem = (authority, ItemDom) => {
if (this.props.Authorized && this.props.Authorized.check) { if (this.props.Authorized && this.props.Authorized.check) {
const { check } = this.props.Authorized; const { check } = this.props.Authorized;
return check( return check(authority, ItemDom);
authority,
ItemDom
);
} }
return ItemDom; return ItemDom;
};
isMainMenu = (key) => {
return this.menus.some(
item =>
key && (item.key === key || item.path === key),
);
} }
handleOpenChange = (openKeys) => { handleOpenChange = (openKeys) => {
const lastOpenKey = openKeys[openKeys.length - 1]; const lastOpenKey = openKeys[openKeys.length - 1];
const isMainMenu = this.menus.some( const moreThanOne = openKeys.filter(openKey => this.isMainMenu(openKey)).length > 1;
item => lastOpenKey && (item.key === lastOpenKey || item.path === lastOpenKey)
);
this.setState({ this.setState({
openKeys: isMainMenu ? [lastOpenKey] : [...openKeys], openKeys: moreThanOne ? [lastOpenKey] : [...openKeys],
}); });
} };
render() { render() {
const { logo, collapsed, location: { pathname }, onCollapse } = this.props; const { logo, collapsed, onCollapse } = this.props;
const { openKeys } = this.state; const { openKeys } = this.state;
// Don't show popup menu when it is been collapsed // Don't show popup menu when it is been collapsed
const menuProps = collapsed ? {} : { const menuProps = collapsed
openKeys, ? {}
}; : {
openKeys,
};
// if pathname can't match, use the nearest parent's key // if pathname can't match, use the nearest parent's key
let selectedKeys = this.getSelectedMenuKeys(pathname); let selectedKeys = this.getSelectedMenuKeys();
if (!selectedKeys.length) { if (!selectedKeys.length) {
selectedKeys = [openKeys[openKeys.length - 1]]; selectedKeys = [openKeys[openKeys.length - 1]];
} }
......
import { getMeunMatcheys } from './SiderMenu';
const meun = [
'/dashboard',
'/userinfo',
'/dashboard/name',
'/userinfo/:id',
'/userinfo/:id/info',
];
describe('test meun match', () => {
it('simple path', () => {
expect(getMeunMatcheys(meun, '/dashboard')).toEqual(['/dashboard']);
});
it('error path', () => {
expect(getMeunMatcheys(meun, '/dashboardname')).toEqual([]);
});
it('Secondary path', () => {
expect(getMeunMatcheys(meun, '/dashboard/name')).toEqual([
'/dashboard/name',
]);
});
it('Parameter path', () => {
expect(getMeunMatcheys(meun, '/userinfo/2144')).toEqual([
'/userinfo/:id',
]);
});
it('three parameter path', () => {
expect(getMeunMatcheys(meun, '/userinfo/2144/info')).toEqual([
'/userinfo/:id/info',
]);
});
});
// /userinfo/2144/id => ['/userinfo','/useinfo/2144,'/userindo/2144/id']
export function urlToList(url) {
const urllist = url.split('/').filter(i => i);
return urllist.map((urlItem, index) => {
return `/${urllist.slice(0, index + 1).join('/')}`;
});
}
import { urlToList } from './pathTools';
describe('test urlToList', () => {
it('A path', () => {
expect(urlToList('/userinfo')).toEqual(['/userinfo']);
});
it('Secondary path', () => {
expect(urlToList('/userinfo/2144')).toEqual([
'/userinfo',
'/userinfo/2144',
]);
});
it('Three paths', () => {
expect(urlToList('/userinfo/2144/addr')).toEqual([
'/userinfo',
'/userinfo/2144',
'/userinfo/2144/addr',
]);
});
});
...@@ -27,8 +27,8 @@ const getRedirect = (item) => { ...@@ -27,8 +27,8 @@ const getRedirect = (item) => {
if (item && item.children) { if (item && item.children) {
if (item.children[0] && item.children[0].path) { if (item.children[0] && item.children[0].path) {
redirectData.push({ redirectData.push({
from: `/${item.path}`, from: `${item.path}`,
to: `/${item.children[0].path}`, to: `${item.children[0].path}`,
}); });
item.children.forEach((children) => { item.children.forEach((children) => {
getRedirect(children); getRedirect(children);
......
...@@ -14,6 +14,9 @@ ...@@ -14,6 +14,9 @@
.ant-card-actions { .ant-card-actions {
background: #f7f9fa; background: #f7f9fa;
} }
.ant-list .ant-list-item-content-single {
max-width: 100%;
}
} }
.cardInfo { .cardInfo {
.clearfix(); .clearfix();
......
...@@ -25,6 +25,12 @@ ...@@ -25,6 +25,12 @@
.item { .item {
height: 64px; height: 64px;
} }
:global {
.ant-list .ant-list-item-content-single {
max-width: 100%;
}
}
} }
.extraImg { .extraImg {
......
...@@ -6,6 +6,7 @@ import { Row, Col, Form, Card, Select, List } from 'antd'; ...@@ -6,6 +6,7 @@ import { Row, Col, Form, Card, Select, List } from 'antd';
import StandardFormRow from '../../components/StandardFormRow'; import StandardFormRow from '../../components/StandardFormRow';
import TagSelect from '../../components/TagSelect'; import TagSelect from '../../components/TagSelect';
import AvatarList from '../../components/AvatarList'; import AvatarList from '../../components/AvatarList';
import Ellipsis from '../../components/Ellipsis';
import styles from './Projects.less'; import styles from './Projects.less';
...@@ -54,7 +55,7 @@ export default class CoverCardList extends PureComponent { ...@@ -54,7 +55,7 @@ export default class CoverCardList extends PureComponent {
<List <List
rowKey="id" rowKey="id"
loading={loading} loading={loading}
grid={{ gutter: 24, lg: 4, md: 3, sm: 2, xs: 1 }} grid={{ gutter: 24, xl: 4, lg: 3, md: 3, sm: 2, xs: 1 }}
dataSource={list} dataSource={list}
renderItem={item => ( renderItem={item => (
<List.Item> <List.Item>
...@@ -65,7 +66,7 @@ export default class CoverCardList extends PureComponent { ...@@ -65,7 +66,7 @@ export default class CoverCardList extends PureComponent {
> >
<Card.Meta <Card.Meta
title={<a href="#">{item.title}</a>} title={<a href="#">{item.title}</a>}
description={item.subDescription} description={<Ellipsis lines={2}>{item.subDescription}</Ellipsis>}
/> />
<div className={styles.cardItemContent}> <div className={styles.cardItemContent}>
<span>{moment(item.updatedAt).fromNow()}</span> <span>{moment(item.updatedAt).fromNow()}</span>
......
...@@ -46,4 +46,10 @@ ...@@ -46,4 +46,10 @@
.cardList { .cardList {
margin-top: 24px; margin-top: 24px;
} }
:global {
.ant-list .ant-list-item-content-single {
max-width: 100%;
}
}
} }
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