Browse Source
* short-term use of tslint * fix lint error * connect & dispatch definition * replace `SFC` with `FunctionComponent` * SiderMenu * TopNavHeader * HeaderSearch * components * layouts * layouts * pages * fix authorize fail * SettingDrawer * remove one `as any`pull/3851/head
committed by
陈小聪
45 changed files with 758 additions and 548 deletions
@ -1,36 +1,61 @@ |
|||
export declare type SiderTheme = 'light' | 'dark'; |
|||
import { MenuTheme } from 'antd/es/menu'; |
|||
|
|||
export type ContentWidth = 'Fluid' | 'Fixed'; |
|||
|
|||
export interface DefaultSettings { |
|||
navTheme: string | SiderTheme; |
|||
/** |
|||
* theme for nav menu |
|||
*/ |
|||
navTheme: MenuTheme; |
|||
/** |
|||
* primary color of ant design |
|||
*/ |
|||
primaryColor: string; |
|||
layout: string; |
|||
contentWidth: string; |
|||
/** |
|||
* nav menu position: `sidemenu` or `topmenu` |
|||
*/ |
|||
layout: 'sidemenu' | 'topmenu'; |
|||
/** |
|||
* layout of content: `Fluid` or `Fixed`, only works when layout is topmenu |
|||
*/ |
|||
contentWidth: ContentWidth; |
|||
/** |
|||
* sticky header |
|||
*/ |
|||
fixedHeader: boolean; |
|||
/** |
|||
* auto hide header |
|||
*/ |
|||
autoHideHeader: boolean; |
|||
/** |
|||
* sticky siderbar |
|||
*/ |
|||
fixSiderbar: boolean; |
|||
menu: { disableLocal: boolean }; |
|||
title: string; |
|||
pwa: boolean; |
|||
/** |
|||
* your iconfont Symbol Scrip Url |
|||
* eg:`//at.alicdn.com/t/font_1039637_btcrd5co4w.js` |
|||
* 注意:如果需要图标多色,Iconfont图标项目里要进行批量去色处理 |
|||
*/ |
|||
iconfontUrl: string; |
|||
colorWeak: boolean; |
|||
} |
|||
|
|||
export default { |
|||
navTheme: 'dark', // theme for nav menu
|
|||
primaryColor: '#1890FF', // primary color of ant design
|
|||
layout: 'sidemenu', // nav menu position: sidemenu or topmenu
|
|||
contentWidth: 'Fluid', // layout of content: Fluid or Fixed, only works when layout is topmenu
|
|||
fixedHeader: false, // sticky header
|
|||
autoHideHeader: false, // auto hide header
|
|||
fixSiderbar: false, // sticky siderbar
|
|||
navTheme: 'dark', |
|||
primaryColor: '#1890FF', |
|||
layout: 'sidemenu', |
|||
contentWidth: 'Fluid', |
|||
fixedHeader: false, |
|||
autoHideHeader: false, |
|||
fixSiderbar: false, |
|||
colorWeak: false, |
|||
menu: { |
|||
disableLocal: false, |
|||
}, |
|||
title: 'Ant Design Pro', |
|||
pwa: true, |
|||
// your iconfont Symbol Scrip Url
|
|||
// eg://at.alicdn.com/t/font_1039637_btcrd5co4w.js
|
|||
// 注意:如果需要图标多色,Iconfont图标项目里要进行批量去色处理
|
|||
iconfontUrl: '', |
|||
} as DefaultSettings; |
|||
|
|||
@ -1,22 +1,15 @@ |
|||
import React, { Component } from 'react'; |
|||
import React from 'react'; |
|||
import { Dropdown } from 'antd'; |
|||
import { DropDownProps } from 'antd/es/dropdown'; |
|||
import classNames from 'classnames'; |
|||
import styles from './index.less'; |
|||
|
|||
declare type OverlayFunc = () => React.ReactNode; |
|||
|
|||
interface HeaderDropdownProps { |
|||
export interface HeaderDropdownProps extends DropDownProps { |
|||
overlayClassName?: string; |
|||
overlay: React.ReactNode | OverlayFunc; |
|||
placement?: 'bottomLeft' | 'bottomRight' | 'topLeft' | 'topCenter' | 'topRight' | 'bottomCenter'; |
|||
} |
|||
|
|||
export default class HeaderDropdown extends Component<HeaderDropdownProps> { |
|||
render() { |
|||
const { overlayClassName, ...props } = this.props; |
|||
const HeaderDropdown: React.FC<HeaderDropdownProps> = ({ overlayClassName: cls, ...restProps }) => ( |
|||
<Dropdown overlayClassName={classNames(styles.container, cls)} {...restProps} /> |
|||
); |
|||
|
|||
return ( |
|||
<Dropdown overlayClassName={classNames(styles.container, overlayClassName)} {...props} /> |
|||
); |
|||
} |
|||
} |
|||
export default HeaderDropdown; |
|||
|
|||
@ -0,0 +1,18 @@ |
|||
import 'jest'; |
|||
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', |
|||
]); |
|||
}); |
|||
}); |
|||
@ -1,6 +1,6 @@ |
|||
// /userinfo/2144/id => ['/userinfo','/useinfo/2144,'/userindo/2144/id']
|
|||
// eslint-disable-next-line import/prefer-default-export
|
|||
export function urlToList(url) { |
|||
export function urlToList(url: string) { |
|||
const urllist = url.split('/').filter(i => i); |
|||
return urllist.map((urlItem, index) => `/${urllist.slice(0, index + 1).join('/')}`); |
|||
} |
|||
|
|||
@ -1,9 +1,5 @@ |
|||
import React, { ReactNode, SFC } from 'react'; |
|||
import React from 'react'; |
|||
|
|||
interface BlankLayoutProps { |
|||
children: ReactNode; |
|||
} |
|||
|
|||
const Layout: SFC<BlankLayoutProps> = ({ children }) => <div>{children}</div>; |
|||
const Layout: React.FC = ({ children }) => <div>{children}</div>; |
|||
|
|||
export default Layout; |
|||
|
|||
@ -0,0 +1,61 @@ |
|||
import { EffectsCommandMap } from 'dva'; |
|||
import { AnyAction } from 'redux'; |
|||
import { GlobalModelState } from './global'; |
|||
import { MenuModelState } from './menu'; |
|||
import { UserModelState } from './user'; |
|||
import { DefaultSettings as SettingModelState } from '../../config/defaultSettings'; |
|||
|
|||
export { GlobalModelState, MenuModelState, SettingModelState, UserModelState }; |
|||
|
|||
export type Effect = ( |
|||
action: AnyAction, |
|||
effects: EffectsCommandMap & { select: <T>(func: (state: ConnectState) => T) => T }, |
|||
) => void; |
|||
|
|||
/** |
|||
* @type P: Type of payload |
|||
* @type C: Type of callback |
|||
*/ |
|||
export type Dispatch = <P = any, C = (payload: P) => void>(action: { |
|||
type: string; |
|||
payload?: P; |
|||
callback?: C; |
|||
[key: string]: any; |
|||
}) => any; |
|||
|
|||
export interface Loading { |
|||
global: boolean; |
|||
effects: { [key: string]: boolean | undefined }; |
|||
models: { |
|||
global?: boolean; |
|||
menu?: boolean; |
|||
setting?: boolean; |
|||
user?: boolean; |
|||
}; |
|||
} |
|||
|
|||
export interface ConnectState { |
|||
global: GlobalModelState; |
|||
loading: Loading; |
|||
menu: MenuModelState; |
|||
setting: SettingModelState; |
|||
user: UserModelState; |
|||
} |
|||
|
|||
/** |
|||
* @type T: Params matched in dynamic routing |
|||
* @type R: Instance type of ref |
|||
*/ |
|||
export interface ConnectProps<T extends { [key: string]: any } = {}, R = any> |
|||
extends React.Props<R> { |
|||
dispatch?: Dispatch; |
|||
location?: Location; |
|||
match?: { |
|||
isExact: boolean; |
|||
params: T; |
|||
path: string; |
|||
url: string; |
|||
}; |
|||
} |
|||
|
|||
export default ConnectState; |
|||
@ -0,0 +1,38 @@ |
|||
import 'jest'; |
|||
import { isUrl } from './utils'; |
|||
|
|||
describe('isUrl tests', () => { |
|||
it('should return false for invalid and corner case inputs', () => { |
|||
expect(isUrl([] as any)).toBeFalsy(); |
|||
expect(isUrl({} as any)).toBeFalsy(); |
|||
expect(isUrl(false as any)).toBeFalsy(); |
|||
expect(isUrl(true as any)).toBeFalsy(); |
|||
expect(isUrl(NaN as any)).toBeFalsy(); |
|||
expect(isUrl(null as any)).toBeFalsy(); |
|||
expect(isUrl(void 0 as any)).toBeFalsy(); |
|||
expect(isUrl('')).toBeFalsy(); |
|||
}); |
|||
|
|||
it('should return false for invalid URLs', () => { |
|||
expect(isUrl('foo')).toBeFalsy(); |
|||
expect(isUrl('bar')).toBeFalsy(); |
|||
expect(isUrl('bar/test')).toBeFalsy(); |
|||
expect(isUrl('http:/example.com/')).toBeFalsy(); |
|||
expect(isUrl('ttp://example.com/')).toBeFalsy(); |
|||
}); |
|||
|
|||
it('should return true for valid URLs', () => { |
|||
expect(isUrl('http://example.com/')).toBeTruthy(); |
|||
expect(isUrl('https://example.com/')).toBeTruthy(); |
|||
expect(isUrl('http://example.com/test/123')).toBeTruthy(); |
|||
expect(isUrl('https://example.com/test/123')).toBeTruthy(); |
|||
expect(isUrl('http://example.com/test/123?foo=bar')).toBeTruthy(); |
|||
expect(isUrl('https://example.com/test/123?foo=bar')).toBeTruthy(); |
|||
expect(isUrl('http://www.example.com/')).toBeTruthy(); |
|||
expect(isUrl('https://www.example.com/')).toBeTruthy(); |
|||
expect(isUrl('http://www.example.com/test/123')).toBeTruthy(); |
|||
expect(isUrl('https://www.example.com/test/123')).toBeTruthy(); |
|||
expect(isUrl('http://www.example.com/test/123?foo=bar')).toBeTruthy(); |
|||
expect(isUrl('https://www.example.com/test/123?foo=bar')).toBeTruthy(); |
|||
}); |
|||
}); |
|||
@ -1,6 +1,6 @@ |
|||
/* eslint no-useless-escape:0 import/prefer-default-export:0 */ |
|||
const reg = /(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/; |
|||
|
|||
export function isUrl(path) { |
|||
export function isUrl(path: string) { |
|||
return reg.test(path); |
|||
} |
|||
|
|||
@ -1,13 +0,0 @@ |
|||
{ |
|||
"extends": ["tslint:latest", "tslint-react", "tslint-config-prettier"], |
|||
"rules": { |
|||
"no-var-requires": false, |
|||
"no-submodule-imports": false, |
|||
"object-literal-sort-keys": false, |
|||
"jsx-no-lambda": false, |
|||
"no-implicit-dependencies": false, |
|||
"no-console": false, |
|||
"member-access": false, |
|||
"prefer-conditional-expression": false |
|||
} |
|||
} |
|||
@ -0,0 +1,95 @@ |
|||
defaultSeverity: error |
|||
extends: |
|||
- tslint-react |
|||
- tslint-eslint-rules |
|||
- tslint-config-prettier |
|||
jsRules: |
|||
rules: |
|||
class-name: true |
|||
eofline: true |
|||
forin: true |
|||
jsdoc-format: false |
|||
label-position: true |
|||
member-ordering: |
|||
- true |
|||
- order: statics-first |
|||
new-parens: true |
|||
no-arg: true |
|||
no-bitwise: true |
|||
no-conditional-assignment: true |
|||
no-consecutive-blank-lines: true |
|||
no-console: |
|||
- true |
|||
- debug |
|||
- info |
|||
- log |
|||
- time |
|||
- timeEnd |
|||
- trace |
|||
- warn |
|||
no-construct: true |
|||
no-debugger: true |
|||
no-duplicate-variable: true |
|||
no-eval: true |
|||
no-internal-module: true |
|||
no-multi-spaces: true |
|||
no-namespace: true |
|||
no-reference: true |
|||
no-shadowed-variable: true |
|||
no-string-literal: true |
|||
no-trailing-whitespace: true |
|||
no-unused-expression: true |
|||
no-var-keyword: true |
|||
one-variable-per-declaration: |
|||
- true |
|||
- ignore-for-loop |
|||
prefer-const: |
|||
- true |
|||
- destructuring: all |
|||
radix: true |
|||
space-in-parens: true |
|||
switch-default: true |
|||
trailing-comma: |
|||
- true |
|||
- singleline: never |
|||
multiline: always |
|||
esSpecCompliant: true |
|||
triple-equals: |
|||
- true |
|||
- allow-null-check |
|||
typedef-whitespace: |
|||
- true |
|||
- call-signature: nospace |
|||
index-signature: nospace |
|||
parameter: nospace |
|||
property-declaration: nospace |
|||
variable-declaration: nospace |
|||
- call-signature: onespace |
|||
index-signature: onespace |
|||
parameter: onespace |
|||
property-declaration: onespace |
|||
variable-declaration: onespace |
|||
use-isnan: true |
|||
variable-name: |
|||
- true |
|||
- allow-leading-underscore |
|||
- ban-keywords |
|||
- check-format |
|||
- allow-pascal-case |
|||
jsx-no-lambda: false |
|||
jsx-no-string-ref: false |
|||
jsx-boolean-value: |
|||
- true |
|||
- never |
|||
jsx-no-multiline-js: false |
|||
whitespace: |
|||
- true |
|||
- check-branch |
|||
- check-decl |
|||
- check-operator |
|||
- check-module |
|||
- check-separator |
|||
- check-rest-spread |
|||
- check-type |
|||
- check-type-operator |
|||
- check-preblock |
|||
@ -0,0 +1,3 @@ |
|||
declare module 'slash2'; |
|||
declare module 'antd-pro-merge-less'; |
|||
declare module 'antd-theme-webpack-plugin'; |
|||
Loading…
Reference in new issue