diff --git a/.prettierrc b/.prettierrc index a654c4fa0..690cb3a3b 100644 --- a/.prettierrc +++ b/.prettierrc @@ -6,5 +6,6 @@ "semi": true, "trailingComma": "es5", "bracketSpacing": false, - "arrowParens": "avoid" + "arrowParens": "avoid", + "jsxBracketSameLine": false } diff --git a/package.json b/package.json index 24f9548f8..2eb6902b5 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "start": "fis3 server start --www ./public --port 8888 --no-daemon --no-browse", "stop": "fis3 server stop", "dev": "fis3 release -cwd ./public", - "publish2npm": "sh publish.sh && npm publish" + "publish2npm": "sh publish.sh && npm publish", + "prettier": "prettier --write src/**/*.tsx" }, "repository": { "type": "git", @@ -120,6 +121,7 @@ "lint-staged": "^8.1.6", "marked": "^0.3.7", "mobx-wiretap": "^0.12.0", + "prettier": "1.17.0", "react-frame-component": "^2.0.0", "react-router": "3.2.0", "react-test-renderer": "^16.8.6", diff --git a/src/renderers/Action.tsx b/src/renderers/Action.tsx index fcb0d5449..35554dde1 100644 --- a/src/renderers/Action.tsx +++ b/src/renderers/Action.tsx @@ -1,23 +1,46 @@ import * as React from 'react'; -import { - Renderer, - RendererProps -} from '../factory'; -import { - filter -} from '../utils/tpl'; +import {Renderer, RendererProps} from '../factory'; +import {filter} from '../utils/tpl'; import Button from '../components/Button'; import pick = require('lodash/pick'); const ActionProps = [ - 'dialog', 'drawer', 'url', 'link', 'confirmText', 'tooltip', 'disabledTip', 'className', 'asyncApi', 'redirect', - 'size', 'level', 'primary', 'feedback', 'api', 'blank', 'tooltipPlacement', 'to', 'content', 'required', - 'type', 'actionType', 'label', 'icon', 'reload', 'target', 'close', 'messages', 'mergeData', 'index', - 'copy', 'content' + 'dialog', + 'drawer', + 'url', + 'link', + 'confirmText', + 'tooltip', + 'disabledTip', + 'className', + 'asyncApi', + 'redirect', + 'size', + 'level', + 'primary', + 'feedback', + 'api', + 'blank', + 'tooltipPlacement', + 'to', + 'content', + 'required', + 'type', + 'actionType', + 'label', + 'icon', + 'reload', + 'target', + 'close', + 'messages', + 'mergeData', + 'index', + 'copy', + 'content', ]; -import { filterContents } from './Remark'; -import { ClassNamesFn, themeable } from '../theme'; -import { Omit } from '../types'; -import { autobind } from '../utils/helper'; +import {filterContents} from './Remark'; +import {ClassNamesFn, themeable} from '../theme'; +import {Omit} from '../types'; +import {autobind} from '../utils/helper'; export interface ActionProps { className?: string; @@ -28,13 +51,13 @@ export interface ActionProps { iconClassName?: string; size?: 'xs' | 'sm' | 'md' | 'lg'; level?: 'info' | 'success' | 'warning' | 'danger' | 'link'; - onAction?: (e: React.MouseEvent | void | null, action:object) => void; + onAction?: (e: React.MouseEvent | void | null, action: object) => void; isCurrentUrl?: (link: string) => boolean; - onClick?: (e:React.MouseEvent) => void; + onClick?: (e: React.MouseEvent) => void; primary?: boolean; activeClassName: string; componentClass: React.ReactType; - tooltipPlacement: "bottom" | "top" | "right" | "left" | undefined; + tooltipPlacement: 'bottom' | 'top' | 'right' | 'left' | undefined; disabled?: boolean; block?: boolean; data?: any; @@ -52,22 +75,18 @@ export interface ActionProps { const allowedType = ['button', 'submit', 'reset']; export class Action extends React.Component { - static defaultProps:Pick = { + static defaultProps: Pick = { type: 'button', componentClass: 'button', tooltipPlacement: 'bottom', - activeClassName: 'is-active' + activeClassName: 'is-active', }; - dom:any; + dom: any; @autobind - handleAction(e:React.MouseEvent) { - const { - onAction, - onClick, - disabled - } = this.props; + handleAction(e: React.MouseEvent) { + const {onAction, onClick, disabled} = this.props; onClick && onClick(e); @@ -105,7 +124,7 @@ export class Action extends React.Component { active, activeLevel, tooltipContainer, - classnames: cx + classnames: cx, } = this.props; let isActive = !!active; @@ -118,20 +137,20 @@ export class Action extends React.Component { {label} - {icon ? : null} + {icon ? : null} ) : ( ); @@ -154,53 +173,43 @@ export default themeable(Action); @Renderer({ test: /(^|\/)action$/, - name: 'action' + name: 'action', }) -export class ActionRenderer extends React.Component & { - onAction: (e: React.MouseEvent | void | null, action:object, data:any) => void; - btnDisabled?: boolean; -}> { - +export class ActionRenderer extends React.Component< + RendererProps & + Omit & { + onAction: (e: React.MouseEvent | void | null, action: object, data: any) => void; + btnDisabled?: boolean; + } +> { @autobind - handleAction(e: React.MouseEvent | void | null, action:any) { - const { - env, - onAction, - data - } = this.props; + handleAction(e: React.MouseEvent | void | null, action: any) { + const {env, onAction, data} = this.props; if (action.confirmText && env.confirm) { - env - .confirm(filter(action.confirmText, data)) - .then((confirmed:boolean) => confirmed && onAction(e, action, data)); + env.confirm(filter(action.confirmText, data)).then( + (confirmed: boolean) => confirmed && onAction(e, action, data) + ); } else { onAction(e, action, data); } } @autobind - isCurrentAction(link:string) { - const { - env, - data - } = this.props; + isCurrentAction(link: string) { + const {env, data} = this.props; return env.isCurrentUrl(filter(link, data)); } render() { - const { - env, - disabled, - btnDisabled, - ...rest - } = this.props; - + const {env, disabled, btnDisabled, ...rest} = this.props; + return ( - ); @@ -209,18 +218,18 @@ export class ActionRenderer extends React.Component { render() { - const { - render, - body, - ...rest - } = this.props; - return ( - - {render('body', body)} - - ); + const {render, body, ...rest} = this.props; + return {render('body', body)}; } -}; +} diff --git a/src/renderers/Audio.tsx b/src/renderers/Audio.tsx index f2af98d09..1c38b9111 100644 --- a/src/renderers/Audio.tsx +++ b/src/renderers/Audio.tsx @@ -1,32 +1,29 @@ import * as React from 'react'; -import { - Renderer, - RendererProps -} from '../factory'; -import { autobind } from '../utils/helper'; -import { volumeIcon, muteIcon, playIcon, pauseIcon} from '../components/icons'; +import {Renderer, RendererProps} from '../factory'; +import {autobind} from '../utils/helper'; +import {volumeIcon, muteIcon, playIcon, pauseIcon} from '../components/icons'; export interface AudioProps extends RendererProps { className?: string; - inline?: boolean, - src?: string, - autoPlay?: boolean, - loop?: boolean, - rates?: number[] + inline?: boolean; + src?: string; + autoPlay?: boolean; + loop?: boolean; + rates?: number[]; } export interface AudioState { - isReady?: boolean, - muted?: boolean, - playing?: boolean, - played: number, - seeking?: boolean, - volume: number, - prevVolume: number, - loaded?: number, - playbackRate: number, - showHandlePlaybackRate: boolean, - showHandleVolume: boolean + isReady?: boolean; + muted?: boolean; + playing?: boolean; + played: number; + seeking?: boolean; + volume: number; + prevVolume: number; + loaded?: number; + playbackRate: number; + showHandlePlaybackRate: boolean; + showHandleVolume: boolean; } export class Audio extends React.Component { @@ -34,16 +31,19 @@ export class Audio extends React.Component { progressTimeout: any; durationTimeout: any; - static defaultProps:Pick = { + static defaultProps: Pick< + AudioProps, + 'inline' | 'autoPlay' | 'playbackRate' | 'loop' | 'rates' | 'progressInterval' + > = { inline: true, autoPlay: false, playbackRate: 1, loop: false, rates: [1.0, 2.0, 4.0], - progressInterval: 1000 + progressInterval: 1000, }; - state:AudioState = { + state: AudioState = { isReady: false, muted: false, playing: false, @@ -54,19 +54,22 @@ export class Audio extends React.Component { loaded: 0, playbackRate: 1.0, showHandlePlaybackRate: false, - showHandleVolume: false - } + showHandleVolume: false, + }; - componentWillUnmount () { + componentWillUnmount() { clearTimeout(this.progressTimeout); } componentDidMount() { const autoPlay = this.props.autoPlay; const playing = autoPlay ? true : false; - this.setState({ - playing: playing - }, this.progress); + this.setState( + { + playing: playing, + }, + this.progress + ); } @autobind @@ -77,33 +80,33 @@ export class Audio extends React.Component { const duration = this.audio.duration; const played = currentTime / duration; let playing = this.state.playing; - playing = (played != 1 && playing) ? true : false; + playing = played != 1 && playing ? true : false; this.setState({ played, - playing + playing, }); - this.progressTimeout = setTimeout(this.progress, (this.props.progressInterval / this.state.playbackRate)) + this.progressTimeout = setTimeout(this.progress, this.props.progressInterval / this.state.playbackRate); } } @autobind - audioRef(audio:any) { + audioRef(audio: any) { this.audio = audio; } @autobind load() { this.setState({ - isReady: true + isReady: true, }); } @autobind - handlePlaybackRate(rate:number) { + handlePlaybackRate(rate: number) { this.audio.playbackRate = rate; this.setState({ playbackRate: rate, - showHandlePlaybackRate: false + showHandlePlaybackRate: false, }); } @@ -117,7 +120,7 @@ export class Audio extends React.Component { this.audio.muted = !muted; this.setState({ muted: !muted, - volume: curVolume + volume: curVolume, }); } @@ -129,7 +132,7 @@ export class Audio extends React.Component { let playing = this.state.playing; playing ? this.audio.pause() : this.audio.play(); this.setState({ - playing: !playing + playing: !playing, }); } @@ -144,7 +147,7 @@ export class Audio extends React.Component { } @autobind - getDuration () { + getDuration() { if (!this.audio || !this.props.src) { return '0:00'; } @@ -152,11 +155,11 @@ export class Audio extends React.Component { this.onDurationCheck(); return '0:00'; } - const { duration, seekable } = this.audio; + const {duration, seekable} = this.audio; // on iOS, live streams return Infinity for the duration // so instead we use the end of the seekable timerange if (duration === Infinity && seekable.length > 0) { - return seekable.end(seekable.length - 1) + return seekable.end(seekable.length - 1); } return this.formatTime(duration); } @@ -172,21 +175,21 @@ export class Audio extends React.Component { } @autobind - onSeekChange(e:any) { + onSeekChange(e: any) { if (!this.props.src) { return; } const played = e.target.value; - this.setState({ played: played }); + this.setState({played: played}); } @autobind onSeekMouseDown() { - this.setState({ seeking: true }); + this.setState({seeking: true}); } @autobind - onSeekMouseUp(e:any) { + onSeekMouseUp(e: any) { if (!this.state.seeking) { return; } @@ -196,15 +199,15 @@ export class Audio extends React.Component { const loop = this.props.loop; let playing = this.state.playing; - playing = (played < 1 || loop) ? playing : false; + playing = played < 1 || loop ? playing : false; this.setState({ playing: playing, - seeking: false + seeking: false, }); } @autobind - setVolume(e:any) { + setVolume(e: any) { if (!this.props.src) { return; } @@ -212,12 +215,12 @@ export class Audio extends React.Component { this.audio.volume = volume; this.setState({ volume: volume, - prevVolume: volume + prevVolume: volume, }); } @autobind - formatTime(seconds:number) { + formatTime(seconds: number) { const date = new Date(seconds * 1000); const hh = date.getUTCHours(); const mm = date.getUTCMinutes(); @@ -229,8 +232,8 @@ export class Audio extends React.Component { } @autobind - pad(string:number) { - return ('0' + string).slice(-2) + pad(string: number) { + return ('0' + string).slice(-2); } @autobind @@ -239,39 +242,23 @@ export class Audio extends React.Component { return; } this.setState({ - showHandlePlaybackRate: !this.state.showHandlePlaybackRate + showHandlePlaybackRate: !this.state.showHandlePlaybackRate, }); } @autobind - toggleHandleVolume(type:boolean) { + toggleHandleVolume(type: boolean) { if (!this.props.src) { return; } this.setState({ - showHandleVolume: type + showHandleVolume: type, }); } render() { - const { - className, - inline, - src, - autoPlay, - loop, - rates, - classnames: cx - } = this.props; - const { - playing, - played, - volume, - muted, - playbackRate, - showHandlePlaybackRate, - showHandleVolume - } = this.state; + const {className, inline, src, autoPlay, loop, rates, classnames: cx} = this.props; + const {playing, played, volume, muted, playbackRate, showHandlePlaybackRate, showHandleVolume} = this.state; return (
@@ -282,55 +269,75 @@ export class Audio extends React.Component { autoPlay={autoPlay} controls muted={muted} - loop={loop}> - + loop={loop} + > +
- {rates && rates.length ? - (
-
+ {rates && rates.length ? ( +
+
x{playbackRate.toFixed(1)}
- {showHandlePlaybackRate ? - (
- {rates.map((rate, index) => - this.handlePlaybackRate(rate)}> + {showHandlePlaybackRate ? ( +
+ {rates.map((rate, index) => ( + this.handlePlaybackRate(rate)} + > x{rate.toFixed(1)} - - )}
) - : null} -
) - : (
) } + + ))}{' '} +
+ ) : null} +
+ ) : ( +
+ )}
{playing ? pauseIcon : playIcon}
-
{this.getCurrentTime()} / {this.getDuration()}
+
+ {this.getCurrentTime()} / {this.getDuration()} +
+ onMouseUp={this.onSeekMouseUp} + />
-
this.toggleHandleVolume(true)} - onMouseLeave={() => this.toggleHandleVolume(false)}> - {showHandleVolume ? - (
+
this.toggleHandleVolume(true)} + onMouseLeave={() => this.toggleHandleVolume(false)} + > + {showHandleVolume ? ( +
-
+ onChange={this.setVolume} + /> +
{volume > 0 ? volumeIcon : muteIcon} -
) - : volume > 0 ? volumeIcon : muteIcon} +
+
+ ) : volume > 0 ? ( + volumeIcon + ) : ( + muteIcon + )}
@@ -340,6 +347,6 @@ export class Audio extends React.Component { @Renderer({ test: /(^|\/)audio/, - name: 'audio' + name: 'audio', }) -export class AudioRenderer extends Audio {}; +export class AudioRenderer extends Audio {} diff --git a/src/renderers/ButtonGroup.tsx b/src/renderers/ButtonGroup.tsx index 31c0f519e..29c4369ff 100644 --- a/src/renderers/ButtonGroup.tsx +++ b/src/renderers/ButtonGroup.tsx @@ -1,16 +1,11 @@ import * as React from 'react'; import ButtonGroup from './Form/ButtonGroup'; -import { - Renderer -} from '../factory'; - +import {Renderer} from '../factory'; export default ButtonGroup; @Renderer({ test: /(^|\/)(?:button|action)\-group$/, - name: 'button-group' + name: 'button-group', }) -export class ButtonGroupRenderer extends ButtonGroup { - -} +export class ButtonGroupRenderer extends ButtonGroup {} diff --git a/src/renderers/ButtonToolbar.tsx b/src/renderers/ButtonToolbar.tsx index f4ad38050..f79c0c20c 100644 --- a/src/renderers/ButtonToolbar.tsx +++ b/src/renderers/ButtonToolbar.tsx @@ -1,36 +1,26 @@ import * as React from 'react'; -import { - Renderer, - RendererProps -} from '../factory'; -import { - Action -} from '../types'; +import {Renderer, RendererProps} from '../factory'; +import {Action} from '../types'; export interface ButtonToolbarProps extends RendererProps { buttons: Array; } export default class ButtonToolbar extends React.Component { - static propsList: Array = [ - "buttons", - ]; + static propsList: Array = ['buttons']; render() { - const { - buttons, - className, - classnames: cx, - render - } = this.props; + const {buttons, className, classnames: cx, render} = this.props; return ( -
- {Array.isArray(buttons) ? buttons.map((button, key) => render(`${key}`, button, { - key - })) : null} +
+ {Array.isArray(buttons) + ? buttons.map((button, key) => + render(`${key}`, button, { + key, + }) + ) + : null}
); } @@ -38,6 +28,6 @@ export default class ButtonToolbar extends React.Component { - static propsList:Array = [ + static propsList: Array = [ 'bulkActions', 'itemActions', 'mode', @@ -102,7 +107,7 @@ export default class CRUD extends React.Component { 'syncResponse2Query', 'keepItemSelectionOnPageChange', 'labelTpl', - 'labelField' + 'labelField', ]; static defaultProps: Partial = { toolbarInline: true, @@ -116,12 +121,12 @@ export default class CRUD extends React.Component { autoJumpToTopOnPagerChange: true, silentPolling: false, filterTogglable: false, - filterDefaultVisible: true + filterDefaultVisible: true, }; - control:any; - lastQuery:any; - dataInvalid:boolean = false; + control: any; + lastQuery: any; + dataInvalid: boolean = false; timer: NodeJS.Timer; mounted: boolean; constructor(props: CRUDProps) { @@ -151,20 +156,24 @@ export default class CRUD extends React.Component { } componentWillMount() { - const { - location, - store, - pageField, - perPageField, - syncLocation - } = this.props; + const {location, store, pageField, perPageField, syncLocation} = this.props; this.mounted = true; if (syncLocation && location && (location.query || location.search)) { - store.updateQuery(location.query || qs.parse(location.search.substring(1)), undefined, pageField, perPageField); + store.updateQuery( + location.query || qs.parse(location.search.substring(1)), + undefined, + pageField, + perPageField + ); } else if (syncLocation && !location && window.location.search) { - store.updateQuery(qs.parse(window.location.search.substring(1)) as object, undefined, pageField, perPageField); + store.updateQuery( + qs.parse(window.location.search.substring(1)) as object, + undefined, + pageField, + perPageField + ); } this.props.store.setFilterTogglable(!!this.props.filterTogglable, this.props.filterDefaultVisible); @@ -173,7 +182,7 @@ export default class CRUD extends React.Component { componentDidMount() { const store = this.props.store; - if (!this.props.filter || store.filterTogggable && !store.filterVisible) { + if (!this.props.filter || (store.filterTogggable && !store.filterVisible)) { this.handleFilterInit({}); } @@ -182,7 +191,7 @@ export default class CRUD extends React.Component { } } - componentWillReceiveProps(nextProps:CRUDProps) { + componentWillReceiveProps(nextProps: CRUDProps) { const props = this.props; const store = props.store; @@ -196,31 +205,32 @@ export default class CRUD extends React.Component { store.setFilterTogglable(!!nextProps.filterTogglable, nextProps.filterDefaultVisible); } - if ( - props.syncLocation - && props.location - && props.location.search !== nextProps.location.search - ) { - + if (props.syncLocation && props.location && props.location.search !== nextProps.location.search) { // 同步地址栏,那么直接检测 query 是否变了,变了就重新拉数据 - store.updateQuery(nextProps.location.query || qs.parse(nextProps.location.search.substring(1)), undefined, nextProps.pageField, nextProps.perPageField); + store.updateQuery( + nextProps.location.query || qs.parse(nextProps.location.search.substring(1)), + undefined, + nextProps.pageField, + nextProps.perPageField + ); this.dataInvalid = isObjectShallowModified(store.query, this.lastQuery, false); } else if (!props.syncLocation && props.api && nextProps.api) { - // 如果不同步地址栏,则直接看api上是否绑定参数,结果变了就重新刷新。 let prevApi = buildApi(props.api, props.data as object, {ignoreData: true}); let nextApi = buildApi(nextProps.api, nextProps.data as object, {ignoreData: true}); - if (prevApi.url !== nextApi.url && isValidApi(nextApi.url) && (!nextApi.sendOn || evalExpression(nextApi.sendOn, nextProps.data))) { + if ( + prevApi.url !== nextApi.url && + isValidApi(nextApi.url) && + (!nextApi.sendOn || evalExpression(nextApi.sendOn, nextProps.data)) + ) { this.dataInvalid = true; } } } componentDidUpdate() { - if ( - this.dataInvalid - ) { + if (this.dataInvalid) { this.dataInvalid = false; this.search(); } @@ -231,7 +241,7 @@ export default class CRUD extends React.Component { clearTimeout(this.timer); } - controlRef(control:any) { + controlRef(control: any) { // 因为 control 有可能被 n 层 hoc 包裹。 while (control && control.getWrappedInstance) { control = control.getWrappedInstance(); @@ -240,29 +250,21 @@ export default class CRUD extends React.Component { this.control = control; } - handleAction(e:React.UIEvent|undefined, action: Action, ctx: object, delegate?: boolean):any { - const { - onAction, - store, - messages, - pickerMode, - env, - pageField, - stopAutoRefreshWhenModalIsOpen - } = this.props; + handleAction(e: React.UIEvent | undefined, action: Action, ctx: object, delegate?: boolean): any { + const {onAction, store, messages, pickerMode, env, pageField, stopAutoRefreshWhenModalIsOpen} = this.props; delegate || store.setCurrentAction(action); if (action.actionType === 'dialog') { - const idx:number = (ctx as any).index; - const length = store.data.items.length; + const idx: number = (ctx as any).index; + const length = store.data.items.length; stopAutoRefreshWhenModalIsOpen && clearTimeout(this.timer); store.openDialog(ctx, { hasNext: idx < length - 1, nextIndex: idx + 1, hasPrev: idx > 0, - prevIndex: idx -1, - index: idx + prevIndex: idx - 1, + index: idx, }); } else if (action.actionType === 'ajax') { const data = ctx; @@ -272,10 +274,10 @@ export default class CRUD extends React.Component { return store .saveRemote(action.api as string, data, { - successMessage: action.messages && action.messages.success || messages && messages.saveSuccess, - errorMessage: action.messages && action.messages.failed || messages && messages.saveFailed + successMessage: (action.messages && action.messages.success) || (messages && messages.saveSuccess), + errorMessage: (action.messages && action.messages.failed) || (messages && messages.saveFailed), }) - .then(async (payload:object) => { + .then(async (payload: object) => { const data = createObject(ctx, payload); if (action.feedback && isVisible(action.feedback, data)) { @@ -286,32 +288,25 @@ export default class CRUD extends React.Component { action.redirect && !action.blank && env.jumpTo(filter(action.redirect, data), action); action.reload ? this.reloadTarget(action.reload, data) : this.search(undefined, undefined, true); }) - .catch(() => { }); + .catch(() => {}); } else if (pickerMode && (action.actionType === 'confirm' || action.actionType === 'submit')) { return Promise.resolve({ - items: store.selectedItems.concat() + items: store.selectedItems.concat(), }); } else { onAction(e, action, ctx); } } - handleBulkAction(selectedItems: Array, unSelectedItems: Array, e:React.UIEvent, action: Action) { - const { - store, - primaryField, - onAction, - messages, - pageField, - stopAutoRefreshWhenModalIsOpen - } = this.props; + handleBulkAction(selectedItems: Array, unSelectedItems: Array, e: React.UIEvent, action: Action) { + const {store, primaryField, onAction, messages, pageField, stopAutoRefreshWhenModalIsOpen} = this.props; if (!selectedItems.length) { return; } let ids = selectedItems - .map(item => item.hasOwnProperty(primaryField) ? item[primaryField as string] : null) + .map(item => (item.hasOwnProperty(primaryField) ? item[primaryField as string] : null)) .filter(item => item) .join(','); @@ -320,19 +315,23 @@ export default class CRUD extends React.Component { rows: selectedItems, items: selectedItems, unSelectedItems: unSelectedItems, - ids + ids, }); if (action.actionType === 'dialog') { - return this.handleAction(e, { - ...action, - __from: 'bulkAction' - }, ctx); + return this.handleAction( + e, + { + ...action, + __from: 'bulkAction', + }, + ctx + ); } else if (action.actionType === 'ajax') { store .saveRemote(action.api as string, ctx, { - successMessage: action.messages && action.messages.success || messages && messages.saveSuccess, - errorMessage: action.messages && action.messages.failed || messages && messages.saveFailed + successMessage: (action.messages && action.messages.success) || (messages && messages.saveSuccess), + errorMessage: (action.messages && action.messages.failed) || (messages && messages.saveFailed), }) .then(async () => { if (action.feedback && isVisible(action.feedback, store.data)) { @@ -340,7 +339,9 @@ export default class CRUD extends React.Component { stopAutoRefreshWhenModalIsOpen && clearTimeout(this.timer); } - action.reload ? this.reloadTarget(action.reload, store.data) : this.search({ [pageField || 'page']: 1 }, undefined, true); + action.reload + ? this.reloadTarget(action.reload, store.data) + : this.search({[pageField || 'page']: 1}, undefined, true); }) .catch(() => null); } else if (onAction) { @@ -348,65 +349,70 @@ export default class CRUD extends React.Component { } } - handleItemAction(action:Action, ctx:any) { + handleItemAction(action: Action, ctx: any) { this.doAction(action, ctx); } - handleFilterInit(values:object) { - const { - defaultParams, - data, - store - } = this.props; + handleFilterInit(values: object) { + const {defaultParams, data, store} = this.props; - this.handleFilterSubmit({ - ...defaultParams, - ...values, - ...store.query - }, false, true, this.props.initFetch !== false); + this.handleFilterSubmit( + { + ...defaultParams, + ...values, + ...store.query, + }, + false, + true, + this.props.initFetch !== false + ); store.setPristineQuery(); - const { - pickerMode, - options - } = this.props; + const {pickerMode, options} = this.props; - pickerMode && store.updateData({ - items: options || [] - }); + pickerMode && + store.updateData({ + items: options || [], + }); // 只执行一次。 this.handleFilterInit = noop; } - handleFilterReset(values:object) { - const { - store, - syncLocation, - env, - pageField, - perPageField - } = this.props; + handleFilterReset(values: object) { + const {store, syncLocation, env, pageField, perPageField} = this.props; - store.updateQuery(store.pristineQuery, syncLocation && env && env.updateLocation ? (location:any) => env.updateLocation(location) : undefined, pageField, perPageField, true); + store.updateQuery( + store.pristineQuery, + syncLocation && env && env.updateLocation ? (location: any) => env.updateLocation(location) : undefined, + pageField, + perPageField, + true + ); this.lastQuery = store.query; this.search(); } - handleFilterSubmit(values:object, jumpToFirstPage:boolean = true, replaceLocation:boolean = false, search:boolean = true) { - const { - store, - syncLocation, - env, + handleFilterSubmit( + values: object, + jumpToFirstPage: boolean = true, + replaceLocation: boolean = false, + search: boolean = true + ) { + const {store, syncLocation, env, pageField, perPageField} = this.props; + + store.updateQuery( + { + ...values, + [pageField || 'page']: jumpToFirstPage ? 1 : store.page, + }, + syncLocation && env && env.updateLocation + ? (location: any) => env.updateLocation(location, replaceLocation) + : undefined, pageField, perPageField - } = this.props; - - store.updateQuery({ - ...values, - [pageField || 'page']: jumpToFirstPage ? 1 : store.page - }, syncLocation && env && env.updateLocation ? (location:any) => env.updateLocation(location, replaceLocation) : undefined, pageField, perPageField); + ); this.lastQuery = store.query; search && this.search(); } @@ -416,20 +422,19 @@ export default class CRUD extends React.Component { const env = this.props.env; if (action.confirmText) { - return env.confirm(action.confirmText).then((confirmed:boolean) => confirmed && this.handleBulkAction(selectedItems, unSelectedItems, e as any, action)); + return env + .confirm(action.confirmText) + .then( + (confirmed: boolean) => + confirmed && this.handleBulkAction(selectedItems, unSelectedItems, e as any, action) + ); } return this.handleBulkAction(selectedItems, unSelectedItems, e as any, action); } handleDialogConfirm(values: object[], action: Action, ctx: any, components: Array) { - const { - store, - pageField, - stopAutoRefreshWhenModalIsOpen, - interval, - silentPolling - } = this.props; + const {store, pageField, stopAutoRefreshWhenModalIsOpen, interval, silentPolling} = this.props; store.closeDialog(); const dialogAction = store.action as Action; @@ -439,28 +444,43 @@ export default class CRUD extends React.Component { } if (action.actionType === 'next' && typeof ctx.nextIndex === 'number' && store.data.items[ctx.nextIndex]) { - return this.handleAction(undefined, { - ...dialogAction - }, createObject(store.data.items[ctx.nextIndex], { - index: ctx.nextIndex - })); - } else if (action.actionType === 'prev' && typeof ctx.prevIndex === 'number' && store.data.items[ctx.prevIndex]) { - return this.handleAction(undefined, { - ...dialogAction - }, createObject(store.data.items[ctx.prevIndex], { - index: ctx.prevIndex - })); + return this.handleAction( + undefined, + { + ...dialogAction, + }, + createObject(store.data.items[ctx.nextIndex], { + index: ctx.nextIndex, + }) + ); + } else if ( + action.actionType === 'prev' && + typeof ctx.prevIndex === 'number' && + store.data.items[ctx.prevIndex] + ) { + return this.handleAction( + undefined, + { + ...dialogAction, + }, + createObject(store.data.items[ctx.prevIndex], { + index: ctx.prevIndex, + }) + ); } else if (values.length) { const value = values[0]; const component = components[0]; // 提交来自 form if (component && component.props.type === 'form') { - // 数据保存了,说明列表数据已经无效了,重新刷新。 if (value && (value as any).__saved) { - this.search(dialogAction.__from ? { [pageField || 'page']: 1 } : undefined, undefined, true); - } else if (value && (value.hasOwnProperty('items') && (value as any).items || value.hasOwnProperty('ids')) && this.control.bulkUpdate) { + this.search(dialogAction.__from ? {[pageField || 'page']: 1} : undefined, undefined, true); + } else if ( + value && + ((value.hasOwnProperty('items') && (value as any).items) || value.hasOwnProperty('ids')) && + this.control.bulkUpdate + ) { this.control.bulkUpdate(value, (value as any).items); } } @@ -472,12 +492,7 @@ export default class CRUD extends React.Component { } handleDialogClose() { - const { - store, - stopAutoRefreshWhenModalIsOpen, - silentPolling, - interval - } = this.props; + const {store, stopAutoRefreshWhenModalIsOpen, silentPolling, interval} = this.props; store.closeDialog(); if (stopAutoRefreshWhenModalIsOpen && interval) { @@ -485,20 +500,18 @@ export default class CRUD extends React.Component { } } - openFeedback(dialog:any, ctx:any) { - return new Promise((resolve) => { - const { - store - } = this.props; + openFeedback(dialog: any, ctx: any) { + return new Promise(resolve => { + const {store} = this.props; store.setCurrentAction({ type: 'button', actionType: 'dialog', - dialog: dialog + dialog: dialog, }); - store.openDialog(ctx, undefined, (confirmed) => { - resolve(confirmed) + store.openDialog(ctx, undefined, confirmed => { + resolve(confirmed); }); - }) + }); } search(values?: any, silent?: boolean, clearSelection?: boolean) { @@ -516,7 +529,7 @@ export default class CRUD extends React.Component { syncResponse2Query, keepItemSelectionOnPageChange, pickerMode, - env + env, } = this.props; // reload 需要清空用户选择。 @@ -526,56 +539,71 @@ export default class CRUD extends React.Component { } let loadDataMode = ''; - if (values && typeof(values.loadDataMode) === 'string') { + if (values && typeof values.loadDataMode === 'string') { loadDataMode = 'load-more'; delete values.loadDataMode; } clearTimeout(this.timer); - values && store.updateQuery(values, !loadDataMode && syncLocation && env && env.updateLocation ? env.updateLocation : undefined, pageField, perPageField); + values && + store.updateQuery( + values, + !loadDataMode && syncLocation && env && env.updateLocation ? env.updateLocation : undefined, + pageField, + perPageField + ); this.lastQuery = store.query; const data = createObject(store.data, store.query); - api && (!(api as ApiObject).sendOn || evalExpression((api as ApiObject).sendOn as string, data)) && store.fetchInitData(api, data, { - successMessage: messages && messages.fetchSuccess, - errorMessage: messages && messages.fetchFailed, - autoAppend: true, - silent, - pageField, - perPageField, - loadDataMode, - syncResponse2Query - }).then((value) => { - interval - && this.mounted - && (!stopAutoRefreshWhen || !(stopAutoRefreshWhenModalIsOpen && store.hasModalOpened || evalExpression(stopAutoRefreshWhen, data))) - && (this.timer = setTimeout(silentPolling ? this.silentSearch : this.search, Math.max(interval, 3000))); - return value; - }); + api && + (!(api as ApiObject).sendOn || evalExpression((api as ApiObject).sendOn as string, data)) && + store + .fetchInitData(api, data, { + successMessage: messages && messages.fetchSuccess, + errorMessage: messages && messages.fetchFailed, + autoAppend: true, + silent, + pageField, + perPageField, + loadDataMode, + syncResponse2Query, + }) + .then(value => { + interval && + this.mounted && + (!stopAutoRefreshWhen || + !( + (stopAutoRefreshWhenModalIsOpen && store.hasModalOpened) || + evalExpression(stopAutoRefreshWhen, data) + )) && + (this.timer = setTimeout( + silentPolling ? this.silentSearch : this.search, + Math.max(interval, 3000) + )); + return value; + }); } silentSearch(values?: object) { return this.search(values, true); } - handleChangePage(page:number, perPage?: number) { - const { - store, - syncLocation, - env, - pageField, - perPageField, - autoJumpToTopOnPagerChange - } = this.props; + handleChangePage(page: number, perPage?: number) { + const {store, syncLocation, env, pageField, perPageField, autoJumpToTopOnPagerChange} = this.props; - let query:any = { - [pageField || 'page']: page + let query: any = { + [pageField || 'page']: page, }; if (perPage) { query[perPageField || 'perPage'] = perPage; } - store.updateQuery(query, syncLocation && env && env.updateLocation ? env.updateLocation : undefined, pageField, perPageField); + store.updateQuery( + query, + syncLocation && env && env.updateLocation ? env.updateLocation : undefined, + pageField, + perPageField + ); this.search(); if (autoJumpToTopOnPagerChange && this.control) { @@ -585,15 +613,13 @@ export default class CRUD extends React.Component { } } - handleSave(rows:Array | object, diff:Array | object, indexes:Array, unModifiedItems?:Array) { - const { - store, - quickSaveApi, - quickSaveItemApi, - primaryField, - env, - messages - } = this.props; + handleSave( + rows: Array | object, + diff: Array | object, + indexes: Array, + unModifiedItems?: Array + ) { + const {store, quickSaveApi, quickSaveItemApi, primaryField, env, messages} = this.props; if (Array.isArray(rows)) { if (!quickSaveApi) { @@ -601,10 +627,10 @@ export default class CRUD extends React.Component { return; } - const data:any = createObject(store.data, { + const data: any = createObject(store.data, { rows, rowsDiff: diff, - indexes: indexes + indexes: indexes, }); if (rows.length && rows[0].hasOwnProperty(primaryField || 'id')) { @@ -618,7 +644,7 @@ export default class CRUD extends React.Component { store .saveRemote(quickSaveApi, data, { successMessage: messages && messages.saveFailed, - errorMessage: messages && messages.saveSuccess + errorMessage: messages && messages.saveSuccess, }) .then(() => { if ((quickSaveApi as ApiObject).reload) { @@ -626,7 +652,7 @@ export default class CRUD extends React.Component { } this.search(); }) - .catch(() => { }); + .catch(() => {}); } else { if (!quickSaveItemApi) { env && env.alert('CRUD quickSaveItemApi is required!'); @@ -635,7 +661,7 @@ export default class CRUD extends React.Component { const data = createObject(store.data, { item: rows, - modified: diff + modified: diff, }); store @@ -646,18 +672,12 @@ export default class CRUD extends React.Component { } this.search(); }) - .catch(() => { }); + .catch(() => {}); } } - handleSaveOrder(moved:Array, rows:Array) { - const { - store, - saveOrderApi, - orderField, - primaryField, - env - } = this.props; + handleSaveOrder(moved: Array, rows: Array) { + const {store, saveOrderApi, orderField, primaryField, env} = this.props; if (!saveOrderApi) { env && env.alert('CRUD saveOrderApi is required!'); @@ -673,9 +693,9 @@ export default class CRUD extends React.Component { order?: any; } = createObject(store.data); - let insertAfter:any; - let insertBefore:any; - const holding:Array = []; + let insertAfter: any; + let insertBefore: any; + const holding: Array = []; const hasIdField = primaryField && rows[0] && (rows[0] as object).hasOwnProperty(primaryField); hasIdField || (model.idMap = {}); @@ -684,7 +704,9 @@ export default class CRUD extends React.Component { rows.forEach((item: any) => { if (~moved.indexOf(item)) { if (insertAfter) { - let insertAfterId = hasIdField ? (insertAfter as any)[primaryField as string] : rows.indexOf(insertAfter); + let insertAfterId = hasIdField + ? (insertAfter as any)[primaryField as string] + : rows.indexOf(insertAfter); model.insertAfter[insertAfterId] = (model as any).insertAfter[insertAfterId] || []; hasIdField || (model.idMap[insertAfterId] = insertAfter); @@ -702,24 +724,30 @@ export default class CRUD extends React.Component { let insertBeforeId = hasIdField ? insertBefore[primaryField as string] : rows.indexOf(insertBefore); hasIdField || (model.idMap[insertBeforeId] = insertBefore); model.insertBefore = {}; - model.insertBefore[insertBeforeId] = holding.map((item:any) => hasIdField ? item[primaryField as string] : item); + model.insertBefore[insertBeforeId] = holding.map((item: any) => + hasIdField ? item[primaryField as string] : item + ); } else if (holding.length) { - const first:any = holding[0]; + const first: any = holding[0]; const firstId = hasIdField ? first[primaryField as string] : rows.indexOf(first); hasIdField || (model.idMap[firstId] = first); - model.insertAfter[firstId] = holding.slice(1).map((item:any) => hasIdField ? item[primaryField as string] : item); + model.insertAfter[firstId] = holding + .slice(1) + .map((item: any) => (hasIdField ? item[primaryField as string] : item)); } if (orderField) { const start = (store.page - 1) * store.perPage || 0; - rows = rows.map((item, key) => extendObject(item, { - [orderField]: start + key + 1 - })); + rows = rows.map((item, key) => + extendObject(item, { + [orderField]: start + key + 1, + }) + ); } model.rows = rows.concat(); - hasIdField && (model.ids = rows.map((item:any) => item[primaryField as string]).join(',')); + hasIdField && (model.ids = rows.map((item: any) => item[primaryField as string]).join(',')); hasIdField && orderField && (model.order = rows.map(item => pick(item, [primaryField as string, orderField]))); store @@ -731,55 +759,46 @@ export default class CRUD extends React.Component { this.search(); }) - .catch(() => { }); + .catch(() => {}); } - handleSelect(items:Array, unSelectedItems:Array) { - const { - store, - keepItemSelectionOnPageChange, - primaryField, - multiple, - pickerMode - } = this.props; + handleSelect(items: Array, unSelectedItems: Array) { + const {store, keepItemSelectionOnPageChange, primaryField, multiple, pickerMode} = this.props; let newItems = items; let newUnSelectedItems = unSelectedItems; if (keepItemSelectionOnPageChange && store.selectedItems.length) { const thisBatch = items.concat(unSelectedItems); - let notInThisBatch = (item:any) => !find(thisBatch, a => a[primaryField || 'id'] == item[primaryField || 'id']); - + let notInThisBatch = (item: any) => + !find(thisBatch, a => a[primaryField || 'id'] == item[primaryField || 'id']); + newItems = store.selectedItems.filter(notInThisBatch); newUnSelectedItems = store.unSelectedItems.filter(notInThisBatch); - + newItems.push(...items); newUnSelectedItems.push(...unSelectedItems); } if (pickerMode && !multiple && newItems.length > 1) { - newUnSelectedItems.push(...newItems.splice(0, newItems.length -1)); + newUnSelectedItems.push(...newItems.splice(0, newItems.length - 1)); } - + store.setSelectedItems(newItems); store.setUnSelectedItems(newUnSelectedItems); } - handleChildPopOverOpen(popOver:any) { - if (this.props.interval && popOver && ~["dialog", "drawer"].indexOf(popOver.mode)) { + handleChildPopOverOpen(popOver: any) { + if (this.props.interval && popOver && ~['dialog', 'drawer'].indexOf(popOver.mode)) { clearTimeout(this.timer); this.props.store.setInnerModalOpened(true); } } - handleChildPopOverClose(popOver:any) { - const { - stopAutoRefreshWhenModalIsOpen, - silentPolling, - interval - } = this.props; + handleChildPopOverClose(popOver: any) { + const {stopAutoRefreshWhenModalIsOpen, silentPolling, interval} = this.props; - if (popOver && ~["dialog", "drawer"].indexOf(popOver.mode)) { + if (popOver && ~['dialog', 'drawer'].indexOf(popOver.mode)) { this.props.store.setInnerModalOpened(false); if (stopAutoRefreshWhenModalIsOpen && interval) { @@ -788,35 +807,34 @@ export default class CRUD extends React.Component { } } - handlQuery(values:object) { - const { - store, - syncLocation, - env, + handlQuery(values: object) { + const {store, syncLocation, env, pageField, perPageField} = this.props; + + store.updateQuery( + { + ...values, + [pageField || 'page']: 1, + }, + syncLocation && env && env.updateLocation ? env.updateLocation : undefined, pageField, perPageField - } = this.props; - - store.updateQuery({ - ...values, - [pageField || 'page']: 1 - }, syncLocation && env && env.updateLocation ? env.updateLocation : undefined, pageField, perPageField) + ); this.search(); } - reload(subpath?: string, query?:any) { + reload(subpath?: string, query?: any) { if (query) { return this.receive(query); } else { - this.search(undefined, undefined, true) - }; + this.search(undefined, undefined, true); + } } - receive(values:object) { + receive(values: object) { this.handlQuery(values); } - reloadTarget(target:string, data:any) { + reloadTarget(target: string, data: any) { // implement this. } @@ -824,7 +842,7 @@ export default class CRUD extends React.Component { return this.handleAction(undefined, action, data, throwErrors); } - unSelectItem(item:any, index:number) { + unSelectItem(item: any, index: number) { const {store} = this.props; const selected = store.selectedItems.concat(); const unSelected = store.unSelectedItems.concat(); @@ -846,46 +864,42 @@ export default class CRUD extends React.Component { } hasBulkActionsToolbar() { - const { - headerToolbar, - footerToolbar - } = this.props; + const {headerToolbar, footerToolbar} = this.props; - const isBulkActions = (item:any) => ~['bulkActions', 'bulk-actions'].indexOf(item.type || item); - return Array.isArray(headerToolbar) && find(headerToolbar, isBulkActions) || Array.isArray(footerToolbar) && find(footerToolbar, isBulkActions); + const isBulkActions = (item: any) => ~['bulkActions', 'bulk-actions'].indexOf(item.type || item); + return ( + (Array.isArray(headerToolbar) && find(headerToolbar, isBulkActions)) || + (Array.isArray(footerToolbar) && find(footerToolbar, isBulkActions)) + ); } hasBulkActions() { - const { - bulkActions, - itemActions, - store - } = this.props; + const {bulkActions, itemActions, store} = this.props; if ((!bulkActions || !bulkActions.length) && (!itemActions || !itemActions.length)) { return false; } - let bulkBtns:Array = []; - let itemBtns:Array = []; + let bulkBtns: Array = []; + let itemBtns: Array = []; const ctx = store.mergedData; if (bulkActions && bulkActions.length) { bulkBtns = bulkActions .map(item => ({ ...item, - ...getExprProperties(item as Schema, ctx) + ...getExprProperties(item as Schema, ctx), })) .filter(item => !item.hidden && item.visible !== false); } const itemData = createObject(store.data, store.selectedItems.length ? store.selectedItems[0] : {}); - + if (itemActions && itemActions.length) { itemBtns = itemActions .map(item => ({ ...item, - ...getExprProperties(item as Schema, itemData) + ...getExprProperties(item as Schema, itemData), })) .filter(item => !item.hidden && item.visible !== false); } @@ -893,31 +907,20 @@ export default class CRUD extends React.Component { return bulkBtns.length || itemBtns.length; } - renderBulkActions(childProps:any) { - let { - bulkActions, - itemActions, - store, - render, - classnames: cx - } = this.props; + renderBulkActions(childProps: any) { + let {bulkActions, itemActions, store, render, classnames: cx} = this.props; const items = childProps.items; - if ( - !items.length - || (!bulkActions || !bulkActions.length) - && (!itemActions || !itemActions.length) - ) { + if (!items.length || ((!bulkActions || !bulkActions.length) && (!itemActions || !itemActions.length))) { return null; } - const selectedItems = store.selectedItems; const unSelectedItems = store.unSelectedItems; - - let bulkBtns:Array = []; - let itemBtns:Array = []; + + let bulkBtns: Array = []; + let itemBtns: Array = []; const ctx = store.mergedData; @@ -928,108 +931,113 @@ export default class CRUD extends React.Component { // unSelectedItems: childProps.unSelectedItems // }); - if (bulkActions && bulkActions.length && ((!itemActions || !itemActions.length) || selectedItems.length > 1)) { + if (bulkActions && bulkActions.length && (!itemActions || !itemActions.length || selectedItems.length > 1)) { bulkBtns = bulkActions .map(item => ({ ...item, - ...getExprProperties(item as Schema, ctx) + ...getExprProperties(item as Schema, ctx), })) .filter(item => !item.hidden && item.visible !== false); } const itemData = createObject(store.data, selectedItems.length ? selectedItems[0] : {}); - + if (itemActions && selectedItems.length === 1) { itemBtns = itemActions .map(item => ({ ...item, - ...getExprProperties(item as Schema, itemData) + ...getExprProperties(item as Schema, itemData), })) .filter(item => !item.hidden && item.visible !== false); } return ( -
- {bulkBtns.map((btn, index) => render(`bulk-action/${index}`, { - size: 'sm', - ...omit(btn, ['visibileOn', 'hiddenOn', 'disabledOn']), - type: 'button' - }, { - key: `bulk-${index}`, - data: ctx, - disabled: btn.disabled || !selectedItems.length, - onAction: this.handleBulkAction.bind(this, selectedItems.concat(), unSelectedItems.concat()) - }))} +
+ {bulkBtns.map((btn, index) => + render( + `bulk-action/${index}`, + { + size: 'sm', + ...omit(btn, ['visibileOn', 'hiddenOn', 'disabledOn']), + type: 'button', + }, + { + key: `bulk-${index}`, + data: ctx, + disabled: btn.disabled || !selectedItems.length, + onAction: this.handleBulkAction.bind( + this, + selectedItems.concat(), + unSelectedItems.concat() + ), + } + ) + )} - {itemBtns.map((btn, index) => render(`bulk-action/${index}`, { - size: 'sm', - ...omit(btn, ['visibileOn', 'hiddenOn', 'disabledOn']), - type: 'button' - }, { - key: `item-${index}`, - data: itemData, - disabled: btn.disabled, - onAction: this.handleItemAction.bind(this, btn, itemData) - }))} + {itemBtns.map((btn, index) => + render( + `bulk-action/${index}`, + { + size: 'sm', + ...omit(btn, ['visibileOn', 'hiddenOn', 'disabledOn']), + type: 'button', + }, + { + key: `item-${index}`, + data: itemData, + disabled: btn.disabled, + onAction: this.handleItemAction.bind(this, btn, itemData), + } + ) + )}
); } renderPagination() { - const { - store, - render, - classnames: cx - } = this.props; + const {store, render, classnames: cx} = this.props; - const{ - page, - lastPage, - } = store; + const {page, lastPage} = store; if (store.mode !== 'simple' && store.lastPage < 2) { return null; } return ( -
- {render('pagination', { - type: 'pagination' - }, { - activePage: page, - items: lastPage, - hasNext: store.hasNext, - mode: store.mode, - onPageChange: this.handleChangePage, - pageNum: store.pageNum, - changePageNum: store.changePageNum - })} +
+ {render( + 'pagination', + { + type: 'pagination', + }, + { + activePage: page, + items: lastPage, + hasNext: store.hasNext, + mode: store.mode, + onPageChange: this.handleChangePage, + pageNum: store.pageNum, + changePageNum: store.changePageNum, + } + )}
); } renderStatistics() { - const { - store, - classnames: cx - } = this.props; + const {store, classnames: cx} = this.props; if (store.lastPage <= 1) { return null; } return ( -
{`${store.page + '/' + store.lastPage}总共${store.total}项。`}
+
{`${store.page + '/' + store.lastPage}总共${store.total}项。`}
); } - renderSwitchPerPage(childProps:any) { - const { - store, - pagePageAvailable, - classnames: cx, - classPrefix: ns - } = this.props; + renderSwitchPerPage(childProps: any) { + const {store, pagePageAvailable, classnames: cx, classPrefix: ns} = this.props; const items = childProps.items; @@ -1037,22 +1045,21 @@ export default class CRUD extends React.Component { return null; } - const perPages = (pagePageAvailable || [5, 10, 20, 50, 100]).map((item:any) => ({ + const perPages = (pagePageAvailable || [5, 10, 20, 50, 100]).map((item: any) => ({ label: item, - value: item + '' + value: item + '', })); return ( -
+
每页显示 - + e.currentTarget.select()} - onKeyUp={(e: any) => e.keyCode == 13 && onPageChange(parseInt(e.currentTarget.value, 10))} + onKeyUp={(e: any) => + e.keyCode == 13 && onPageChange(parseInt(e.currentTarget.value, 10)) + } value={pageNum} /> - +
) : null} -
); } render() { - const { - mode - } = this.props; + const {mode} = this.props; return mode === 'simple' ? this.renderSimple() : this.renderNormal(); } @@ -233,6 +237,6 @@ export default class Pagination extends React.PureComponent { - static propsList: Array = [ - "headerClassName", - "footerClassName", - "actionsClassName", - "bodyClassName" - ]; + static propsList: Array = ['headerClassName', 'footerClassName', 'actionsClassName', 'bodyClassName']; static defaultProps = { // className: 'Panel--default', // headerClassName: 'Panel-heading', @@ -46,7 +35,7 @@ export default class Panel extends React.Component { componentDidMount() { const dom = findDOMNode(this) as HTMLElement; - let parent:HTMLElement | Window | null = dom ? getScrollParent(dom) : null; + let parent: HTMLElement | Window | null = dom ? getScrollParent(dom) : null; if (!parent || parent === document.body) { parent = window; } @@ -73,11 +62,11 @@ export default class Panel extends React.Component { const clip = footerDom.getBoundingClientRect(); const clientHeight = window.innerHeight; const affixed = clip.top > clientHeight; - + footerDom.offsetWidth && (affixDom.style.cssText = `width: ${footerDom.offsetWidth}px;`); affixed ? affixDom.classList.add('in') : affixDom.classList.remove('in'); } - + renderBody(): JSX.Element | null { const { type, @@ -100,27 +89,28 @@ export default class Panel extends React.Component { const subProps = { data, - ...rest + ...rest, }; return children ? ( -
{typeof children === 'function' ? children(this.props) : children}
+
+ {typeof children === 'function' ? children(this.props) : children} +
) : body ? (
{render('body', body, subProps)}
) : null; } renderActions() { - const { - actions, - render, - } = this.props; - + const {actions, render} = this.props; + if (Array.isArray(actions) && actions.length) { - return actions.map((action, key) => render('action', action, { - type: action.type || 'button', - key: key - })); + return actions.map((action, key) => + render('action', action, { + type: action.type || 'button', + key: key, + }) + ); } return null; @@ -149,38 +139,35 @@ export default class Panel extends React.Component { const subProps = { data, - ...rest + ...rest, }; const footerDoms = []; const actions = this.renderActions(); - actions && footerDoms.push( -
- {actions} -
- ); + actions && + footerDoms.push( +
+ {actions} +
+ ); - footer && footerDoms.push( -
- {render('footer', footer, subProps)} -
- ); + footer && + footerDoms.push( +
+ {render('footer', footer, subProps)} +
+ ); - let footerDom = footerDoms.length ? ( -
- {footerDoms} -
- ) : null; - + let footerDom = footerDoms.length ?
{footerDoms}
: null; return ( -
+
{header ? (
{render('header', header, subProps)}
) : title ? ( -

{render('title', title, subProps)}

+
+

{render('title', title, subProps)}

+
) : null} {this.renderBody()} @@ -188,7 +175,7 @@ export default class Panel extends React.Component { {footerDom} {affixFooter && footerDoms.length ? ( -
+
{footerDoms}
) : null} @@ -199,6 +186,6 @@ export default class Panel extends React.Component { @Renderer({ test: /(^|\/)panel$/, - name: 'panel' + name: 'panel', }) export class PanelRenderer extends Panel {} diff --git a/src/renderers/Plain.tsx b/src/renderers/Plain.tsx index ede660e1d..900e93088 100644 --- a/src/renderers/Plain.tsx +++ b/src/renderers/Plain.tsx @@ -1,11 +1,6 @@ import * as React from 'react'; -import { - Renderer, - RendererProps -} from '../factory'; -import { - filter -} from '../utils/tpl'; +import {Renderer, RendererProps} from '../factory'; +import {filter} from '../utils/tpl'; import * as cx from 'classnames'; export interface PlainProps extends RendererProps { @@ -19,30 +14,26 @@ export interface PlainProps extends RendererProps { } export class Plain extends React.Component { - static defaultProps:Partial = { + static defaultProps: Partial = { wrapperComponent: '', inline: true, - placeholder: '-' + placeholder: '-', }; render() { - const { - className, - wrapperComponent, - value, - text, - data, - tpl, - inline, - placeholder, - classnames: cx - } = this.props; + const {className, wrapperComponent, value, text, data, tpl, inline, placeholder, classnames: cx} = this.props; const Component = wrapperComponent || (inline ? 'span' : 'div'); return ( - {tpl || text ? filter((tpl || text as string), data) : (typeof value === 'undefined' || value === '' || value === null ? {placeholder} : String(value))} + {tpl || text ? ( + filter(tpl || (text as string), data) + ) : typeof value === 'undefined' || value === '' || value === null ? ( + {placeholder} + ) : ( + String(value) + )} ); } @@ -50,6 +41,6 @@ export class Plain extends React.Component { @Renderer({ test: /(^|\/)(?:plain|text)$/, - name: 'plain' + name: 'plain', }) -export class PlainRenderer extends Plain {}; +export class PlainRenderer extends Plain {} diff --git a/src/renderers/PopOver.tsx b/src/renderers/PopOver.tsx index ddf13e4b1..66143567b 100644 --- a/src/renderers/PopOver.tsx +++ b/src/renderers/PopOver.tsx @@ -1,53 +1,57 @@ /** -* @file scoped.jsx. -* @author fex -*/ + * @file scoped.jsx. + * @author fex + */ import * as React from 'react'; import {findDOMNode} from 'react-dom'; -import { RendererProps } from '../factory'; +import {RendererProps} from '../factory'; import * as cx from 'classnames'; import hoistNonReactStatic = require('hoist-non-react-statics'); -import { RootCloseWrapper} from 'react-overlays'; +import {RootCloseWrapper} from 'react-overlays'; import PopOver from '../components/PopOver'; import Overlay from '../components/Overlay'; -export interface PopOverConfig { -} +export interface PopOverConfig {} -const allowedPositions = [ - 'center', - 'top' -]; +const allowedPositions = ['center', 'top']; export interface PopOverConfig { saveImmediately?: boolean; mode?: 'dialog' | 'drawer' | 'popOver'; title?: string; size?: 'sm' | 'md' | 'lg' | 'xl'; - position: 'center' | 'left-top' | 'right-top' | 'left-bottom' | 'right-bottom' - | 'fixed-center' | 'fixed-left-top' | 'fixed-right-top' | 'fixed-left-bottom' | 'fixed-right-bottom'; - [propName:string]: any; -}; + position: + | 'center' + | 'left-top' + | 'right-top' + | 'left-bottom' + | 'right-bottom' + | 'fixed-center' + | 'fixed-left-top' + | 'fixed-right-top' + | 'fixed-left-bottom' + | 'fixed-right-bottom'; + [propName: string]: any; +} export interface PopOverProps extends RendererProps { name?: string; label?: string; popOver: boolean | PopOverConfig; - onPopOverOpen: (popover:any) => void; - onPopOverClose: (popover:any) => void; -}; + onPopOverOpen: (popover: any) => void; + onPopOverClose: (popover: any) => void; +} export interface PopOverState { isOpened: boolean; -}; - -export const HocPopOver = (config:Partial = {}) => (Component: React.ComponentType):any => { +} +export const HocPopOver = (config: Partial = {}) => (Component: React.ComponentType): any => { class PopOverComponent extends React.Component { - target:HTMLElement; + target: HTMLElement; static ComposedComponent = Component; - constructor(props:PopOverProps) { + constructor(props: PopOverProps) { super(props); this.openPopOver = this.openPopOver.bind(this); @@ -55,19 +59,22 @@ export const HocPopOver = (config:Partial = {}) => (Component: Re this.targetRef = this.targetRef.bind(this); // this.handleClickOutside = this.handleClickOutside.bind(this); this.state = { - isOpened: false + isOpened: false, }; } - targetRef(ref:any) { + targetRef(ref: any) { this.target = ref; } openPopOver() { const onPopOverOpen = this.props.onPopOverOpen; - this.setState({ - isOpened: true - }, () => onPopOverOpen && onPopOverOpen(this.props.popOver)); + this.setState( + { + isOpened: true, + }, + () => onPopOverOpen && onPopOverOpen(this.props.popOver) + ); } closePopOver() { @@ -76,24 +83,23 @@ export const HocPopOver = (config:Partial = {}) => (Component: Re } const onPopOverClose = this.props.onPopOverClose; - this.setState({ - isOpened: false - }, () => onPopOverClose && onPopOverClose(this.props.popOver)); + this.setState( + { + isOpened: false, + }, + () => onPopOverClose && onPopOverClose(this.props.popOver) + ); } buildSchema() { - const { - popOver, - name, - label - } = this.props; + const {popOver, name, label} = this.props; let schema; if (popOver === true) { schema = { type: 'panel', - body: '${name}' + body: '${name}', }; } else if (popOver && (popOver.mode === 'dialog' || popOver.mode === 'drawer')) { schema = { @@ -102,15 +108,15 @@ export const HocPopOver = (config:Partial = {}) => (Component: Re { label: '关闭', type: 'button', - actionType: 'cancel' - } + actionType: 'cancel', + }, ], - ...popOver + ...popOver, }; } else if (popOver) { schema = { type: 'panel', - ...popOver + ...popOver, }; } @@ -118,41 +124,33 @@ export const HocPopOver = (config:Partial = {}) => (Component: Re } renderPopOver() { - let { - popOver, - render, - popOverContainer, - classnames: cx, - classPrefix: ns - } = this.props; + let {popOver, render, popOverContainer, classnames: cx, classPrefix: ns} = this.props; - if (popOver && ((popOver as PopOverConfig).mode === 'dialog' - || (popOver as PopOverConfig).mode === 'drawer')) { + if ( + popOver && + ((popOver as PopOverConfig).mode === 'dialog' || (popOver as PopOverConfig).mode === 'drawer') + ) { return render('popover-detail', this.buildSchema(), { show: true, onClose: this.closePopOver, - onConfirm: this.closePopOver + onConfirm: this.closePopOver, }); } const content = render('popover-detail', this.buildSchema(), { - className: cx((popOver as PopOverConfig).className) + className: cx((popOver as PopOverConfig).className), }) as JSX.Element; if (!popOverContainer) { popOverContainer = () => findDOMNode(this); } - const position = popOver && (popOver as PopOverConfig).position || ''; + const position = (popOver && (popOver as PopOverConfig).position) || ''; const isFixed = /^fixed\-/.test(position); return isFixed ? ( -
- {content} -
+ +
{content}
) : ( = {}) => (Component: Re rootClose show > - + {content} @@ -174,31 +169,25 @@ export const HocPopOver = (config:Partial = {}) => (Component: Re } render() { - const { - onQuickChange, - popOver, - popOverEnabled, - className, - noHoc, - classnames: cx, - render - } = this.props; + const {onQuickChange, popOver, popOverEnabled, className, noHoc, classnames: cx, render} = this.props; if (!popOver || popOverEnabled === false || noHoc) { - return ( - - ); + return ; } return ( - - + {this.state.isOpened ? this.renderPopOver() : null} ); diff --git a/src/renderers/Progress.tsx b/src/renderers/Progress.tsx index dc452a412..35e09a168 100644 --- a/src/renderers/Progress.tsx +++ b/src/renderers/Progress.tsx @@ -1,17 +1,8 @@ import * as React from 'react'; -import { - Renderer, - RendererProps -} from '../factory'; +import {Renderer, RendererProps} from '../factory'; import {ServiceStore, IServiceStore} from '../store/service'; -import { - Api, - SchemaNode, - PlainObject -} from '../types'; -import { - filter -} from '../utils/tpl'; +import {Api, SchemaNode, PlainObject} from '../types'; +import {filter} from '../utils/tpl'; import * as cx from 'classnames'; export interface ProgressProps extends RendererProps { @@ -23,23 +14,17 @@ export interface ProgressProps extends RendererProps { } export class ProgressField extends React.Component { - static defaultProps:Partial = { + static defaultProps: Partial = { placeholder: '-', progressClassName: 'progress-xs progress-striped active m-b-none', progressBarClassName: '', - map: [ - 'bg-danger', - 'bg-warning', - 'bg-info', - 'bg-success', - 'bg-success' - ], - showLabel: true + map: ['bg-danger', 'bg-warning', 'bg-info', 'bg-success', 'bg-success'], + showLabel: true, }; - autoClassName(value:number) { + autoClassName(value: number) { const map = this.props.map; - let index = Math.floor(value * map.length / 100); + let index = Math.floor((value * map.length) / 100); index = Math.max(0, Math.min(map.length - 1, index)); return map[index]; } @@ -52,11 +37,11 @@ export class ProgressField extends React.Component { progressBarClassName, map, showLabel, - classnames: cx + classnames: cx, } = this.props; let value = this.props.value; - let viewValue:React.ReactNode = {placeholder}; + let viewValue: React.ReactNode = {placeholder}; if (/^\d*\.?\d+$/.test(value)) { value = parseFloat(value); @@ -64,30 +49,25 @@ export class ProgressField extends React.Component { if (typeof value === 'number') { viewValue = [ -
+
-
+ />
, - showLabel ?
{value}%
: null + showLabel ?
{value}%
: null, ]; } - return ( - - {viewValue} - - ); + return {viewValue}; } } @Renderer({ test: /(^|\/)progress$/, - name: 'progress' + name: 'progress', }) -export class ProgressFieldRenderer extends ProgressField {}; +export class ProgressFieldRenderer extends ProgressField {} diff --git a/src/renderers/QRCode.tsx b/src/renderers/QRCode.tsx index 6e4a074d9..418e7701b 100644 --- a/src/renderers/QRCode.tsx +++ b/src/renderers/QRCode.tsx @@ -1,33 +1,25 @@ import * as React from 'react'; import * as cx from 'classnames'; -import { - Renderer, - RendererProps, -} from '../factory'; -import { - FormItem, - FormControlProps -} from './Form/Item'; -import { - filter -} from '../utils/tpl'; +import {Renderer, RendererProps} from '../factory'; +import {FormItem, FormControlProps} from './Form/Item'; +import {filter} from '../utils/tpl'; import QrCode = require('qrcode.react'); export interface QRCodeProps extends FormControlProps { codeSize?: number; backgroundColor?: string; foregroundColor?: string; - level?: string + level?: string; placeholder: string; } -export default class QRCode extends React.Component{ +export default class QRCode extends React.Component { static defaultProps: Partial = { codeSize: 128, backgroundColor: '#fff', foregroundColor: '#000', level: 'L', - placeholder: '-' + placeholder: '-', }; render() { @@ -40,7 +32,7 @@ export default class QRCode extends React.Component{ level, value, data, - classPrefix: ns + classPrefix: ns, } = this.props; return ( @@ -52,20 +44,23 @@ export default class QRCode extends React.Component{ bgColor={backgroundColor} fgColor={foregroundColor} level={level || 'L'} - />) : {placeholder}} + /> + ) : ( + {placeholder} + )}
- ) + ); } } @Renderer({ test: /(^|\/)qr\-?code$/, - name: 'qrcode' + name: 'qrcode', }) -export class QRCodeRenderer extends QRCode { } +export class QRCodeRenderer extends QRCode {} @FormItem({ type: 'qr-code', - sizeMutable: false + sizeMutable: false, }) -export class QRCodeControlRenderer extends QRCode {} \ No newline at end of file +export class QRCodeControlRenderer extends QRCode {} diff --git a/src/renderers/QuickEdit.tsx b/src/renderers/QuickEdit.tsx index 5d8bc76da..30b820133 100644 --- a/src/renderers/QuickEdit.tsx +++ b/src/renderers/QuickEdit.tsx @@ -1,25 +1,24 @@ /** -* @file scoped.jsx. -* @author fex -*/ + * @file scoped.jsx. + * @author fex + */ import * as React from 'react'; import {findDOMNode} from 'react-dom'; import find = require('lodash/find'); import * as PropTypes from 'prop-types'; import isPlainObject = require('lodash/isPlainObject'); -import { RendererProps } from '../factory'; +import {RendererProps} from '../factory'; import * as cx from 'classnames'; import hoistNonReactStatic = require('hoist-non-react-statics'); -import onClickOutside from "react-onclickoutside"; -import { Action } from '../types'; +import onClickOutside from 'react-onclickoutside'; +import {Action} from '../types'; import * as keycode from 'keycode'; import matches = require('dom-helpers/query/matches'); import Overlay from '../components/Overlay'; import PopOver from '../components/PopOver'; -export interface QuickEditConfig { -} +export interface QuickEditConfig {} export interface QuickEditConfig { saveImmediately?: boolean; @@ -30,31 +29,29 @@ export interface QuickEditConfig { fieldSet?: any; focusable?: boolean; popOverClassName?: string; - [propName:string]: any; -}; + [propName: string]: any; +} export interface QuickEditProps extends RendererProps { name?: string; label?: string; quickEdit: boolean | QuickEditConfig; quickEditEnabled?: boolean; -}; +} export interface QuickEditState { isOpened: boolean; -}; +} +let inited: boolean = false; +let currentOpened: any; -let inited:boolean = false; -let currentOpened:any; - -export const HocQuickEdit = (config:Partial = {}) => (Component: React.ComponentType):any => { - +export const HocQuickEdit = (config: Partial = {}) => (Component: React.ComponentType): any => { class QuickEditComponent extends React.PureComponent { - target:HTMLElement; + target: HTMLElement; overlay: HTMLElement; static ComposedComponent = Component; - constructor(props:QuickEditProps) { + constructor(props: QuickEditProps) { super(props); this.openQuickEdit = this.openQuickEdit.bind(this); @@ -65,9 +62,9 @@ export const HocQuickEdit = (config:Partial = {}) => (Component this.overlayRef = this.overlayRef.bind(this); this.handleWindowKeyPress = this.handleWindowKeyPress.bind(this); this.handleWindowKeyDown = this.handleWindowKeyDown.bind(this); - + this.state = { - isOpened: false + isOpened: false, }; } @@ -83,9 +80,9 @@ export const HocQuickEdit = (config:Partial = {}) => (Component document.body.addEventListener('keydown', this.handleWindowKeyDown); } - handleWindowKeyPress(e:Event) { + handleWindowKeyPress(e: Event) { const ns = this.props.classPrefix; - let el:HTMLElement = (e.target as HTMLElement).closest(`.${ns}Field--quickEditable`) as HTMLElement; + let el: HTMLElement = (e.target as HTMLElement).closest(`.${ns}Field--quickEditable`) as HTMLElement; if (!el) { return; } @@ -93,104 +90,111 @@ export const HocQuickEdit = (config:Partial = {}) => (Component if (!table) { return; } - + if (keycode(e) === 'space' && !~['INPUT', 'TEXTAREA'].indexOf(el.tagName)) { e.preventDefault(); e.stopPropagation(); } } - - handleWindowKeyDown(e:Event) { + + handleWindowKeyDown(e: Event) { const code = keycode(e); - + if (code === 'esc' && currentOpened) { currentOpened.closeQuickEdit(); } else if ( - ~['INPUT', 'TEXTAREA'].indexOf((e.target as HTMLElement).tagName) - || (e.target as HTMLElement).contentEditable === 'true' - || !~['up', 'down', 'left', 'right'].indexOf(code) + ~['INPUT', 'TEXTAREA'].indexOf((e.target as HTMLElement).tagName) || + (e.target as HTMLElement).contentEditable === 'true' || + !~['up', 'down', 'left', 'right'].indexOf(code) ) { return; } - + e.preventDefault(); const ns = this.props.classPrefix; - let el:HTMLElement = (e.target as HTMLElement).closest(`.${ns}Field--quickEditable`) as HTMLElement || document.querySelector(`.${ns}Field--quickEditable`); + let el: HTMLElement = + ((e.target as HTMLElement).closest(`.${ns}Field--quickEditable`) as HTMLElement) || + document.querySelector(`.${ns}Field--quickEditable`); if (!el) { return; } - + let table = el.closest('table'); if (!table) { return; } - + let current = table.querySelector(`.${ns}Field--quickEditable:focus`) as HTMLTableDataCellElement; - + if (!current) { - let dom = table.querySelector(`.${ns}Field--quickEditable[tabindex]`) as HTMLElement; - dom && dom.focus(); + let dom = table.querySelector(`.${ns}Field--quickEditable[tabindex]`) as HTMLElement; + dom && dom.focus(); } else { - let prevTr, nextTr, prevTd, nextTd; - - switch (code) { - case 'up': - prevTr = (current.parentNode as HTMLElement).previousSibling as HTMLTableCellElement; - - if (prevTr) { - let index = current.cellIndex; - (prevTr.children[index] as HTMLElement).focus(); - } - break; - case 'down': - nextTr = (current.parentNode as HTMLElement).nextSibling as HTMLTableCellElement; - - if (nextTr) { - let index = current.cellIndex; - (nextTr.children[index] as HTMLElement).focus(); - } - break; - case 'left': - prevTd = current.previousElementSibling as HTMLTableCellElement; - - while (prevTd) { - if (matches(prevTd, `.${ns}Field--quickEditable[tabindex]`)) { - break; - } - prevTd = prevTd.previousElementSibling; - } - - if (prevTd) { - (prevTd as HTMLElement).focus(); - } else if ((current.parentNode as HTMLElement).previousSibling) { - let tds = ((current.parentNode as HTMLElement).previousSibling as HTMLElement).querySelectorAll(`.${ns}Field--quickEditable[tabindex]`); - - if (tds.length) { - (tds[tds.length - 1] as HTMLElement).focus(); - } - } - break; - case 'right': - nextTd = current.nextSibling; - while (nextTd) { - if (matches(nextTd, `.${ns}Field--quickEditable[tabindex]`)) { - break; - } - - nextTd = nextTd.nextSibling; - } - - if (nextTd) { - (nextTd as HTMLElement).focus(); - } else if ((current.parentNode as HTMLElement).nextSibling) { - nextTd = ((current.parentNode as HTMLElement).nextSibling as HTMLElement).querySelector(`.${ns}Field--quickEditable[tabindex]`); - - if (nextTd) { - nextTd.focus(); - } - } - break; - } + let prevTr, nextTr, prevTd, nextTd; + + switch (code) { + case 'up': + prevTr = (current.parentNode as HTMLElement).previousSibling as HTMLTableCellElement; + + if (prevTr) { + let index = current.cellIndex; + (prevTr.children[index] as HTMLElement).focus(); + } + break; + case 'down': + nextTr = (current.parentNode as HTMLElement).nextSibling as HTMLTableCellElement; + + if (nextTr) { + let index = current.cellIndex; + (nextTr.children[index] as HTMLElement).focus(); + } + break; + case 'left': + prevTd = current.previousElementSibling as HTMLTableCellElement; + + while (prevTd) { + if (matches(prevTd, `.${ns}Field--quickEditable[tabindex]`)) { + break; + } + prevTd = prevTd.previousElementSibling; + } + + if (prevTd) { + (prevTd as HTMLElement).focus(); + } else if ((current.parentNode as HTMLElement).previousSibling) { + let tds = ((current.parentNode as HTMLElement) + .previousSibling as HTMLElement).querySelectorAll( + `.${ns}Field--quickEditable[tabindex]` + ); + + if (tds.length) { + (tds[tds.length - 1] as HTMLElement).focus(); + } + } + break; + case 'right': + nextTd = current.nextSibling; + while (nextTd) { + if (matches(nextTd, `.${ns}Field--quickEditable[tabindex]`)) { + break; + } + + nextTd = nextTd.nextSibling; + } + + if (nextTd) { + (nextTd as HTMLElement).focus(); + } else if ((current.parentNode as HTMLElement).nextSibling) { + nextTd = ((current.parentNode as HTMLElement).nextSibling as HTMLElement).querySelector( + `.${ns}Field--quickEditable[tabindex]` + ); + + if (nextTd) { + nextTd.focus(); + } + } + break; + } } } @@ -198,14 +202,12 @@ export const HocQuickEdit = (config:Partial = {}) => (Component // this.closeQuickEdit(); // } - overlayRef(ref:any) { + overlayRef(ref: any) { this.overlay = ref; } - handleAction(e:any, action:Action, ctx:object) { - const { - onAction - } = this.props; + handleAction(e: any, action: Action, ctx: object) { + const {onAction} = this.props; if (action.actionType === 'cancel' || action.actionType === 'close') { this.closeQuickEdit(); @@ -215,11 +217,8 @@ export const HocQuickEdit = (config:Partial = {}) => (Component onAction && onAction(e, action, ctx); } - handleSubmit(values:object) { - const { - onQuickChange, - quickEdit - } = this.props; + handleSubmit(values: object) { + const {onQuickChange, quickEdit} = this.props; this.closeQuickEdit(); onQuickChange(values, (quickEdit as QuickEditConfig).saveImmediately); @@ -228,7 +227,7 @@ export const HocQuickEdit = (config:Partial = {}) => (Component openQuickEdit() { currentOpened = this; this.setState({ - isOpened: true + isOpened: true, }); } @@ -238,21 +237,21 @@ export const HocQuickEdit = (config:Partial = {}) => (Component } currentOpened = null; const ns = this.props.classPrefix; - this.setState({ - isOpened: false - }, () => { - let el = findDOMNode(this) as HTMLElement; - let table = el.closest('table') as HTMLElement; - (table && table.querySelectorAll(`td.${ns}Field--quickEditable:focus`).length || el) && el.focus(); - }); + this.setState( + { + isOpened: false, + }, + () => { + let el = findDOMNode(this) as HTMLElement; + let table = el.closest('table') as HTMLElement; + ((table && table.querySelectorAll(`td.${ns}Field--quickEditable:focus`).length) || el) && + el.focus(); + } + ); } buildSchema() { - const { - quickEdit, - name, - label - } = this.props; + const {quickEdit, name, label} = this.props; let schema; @@ -266,18 +265,23 @@ export const HocQuickEdit = (config:Partial = {}) => (Component type: 'text', name, placeholder: label, - label: false - } - ] + label: false, + }, + ], }; } else if (quickEdit) { - if ((quickEdit.controls && !~['combo', 'group', 'panel', 'fieldSet'].indexOf((quickEdit as any).type)) || quickEdit.tabs || quickEdit.fieldSet) { + if ( + (quickEdit.controls && + !~['combo', 'group', 'panel', 'fieldSet'].indexOf((quickEdit as any).type)) || + quickEdit.tabs || + quickEdit.fieldSet + ) { schema = { title: '', autoFocus: (quickEdit as QuickEditConfig).mode !== 'inline', mode: (quickEdit as QuickEditConfig).mode === 'inline' ? 'inline' : 'normal', ...quickEdit, - type: 'form' + type: 'form', }; } else { schema = { @@ -292,9 +296,9 @@ export const HocQuickEdit = (config:Partial = {}) => (Component name: quickEdit.name || name, placeholder: label, label: false, - ...quickEdit - } - ] + ...quickEdit, + }, + ], }; } } @@ -303,26 +307,29 @@ export const HocQuickEdit = (config:Partial = {}) => (Component schema = { ...schema, wrapWithPanel: (quickEdit as QuickEditConfig).mode !== 'inline', - actions: (quickEdit as QuickEditConfig).mode === 'inline' ? [] : [ - { - type: 'button', - label: '取消', - actionType: 'cancel' - }, + actions: + (quickEdit as QuickEditConfig).mode === 'inline' + ? [] + : [ + { + type: 'button', + label: '取消', + actionType: 'cancel', + }, - { - label: '确认', - type: 'submit', - primary: true - } - ] - } + { + label: '确认', + type: 'submit', + primary: true, + }, + ], + }; } return schema || 'error'; } - handleKeyUp(e:Event) { + handleKeyUp(e: Event) { const code = keycode(e); if (code === 'space' && !~['INPUT', 'TEXTAREA'].indexOf((e.target as HTMLElement).tagName)) { e.preventDefault(); @@ -332,13 +339,7 @@ export const HocQuickEdit = (config:Partial = {}) => (Component } renderPopOver() { - let { - quickEdit, - render, - popOverContainer, - classPrefix: ns, - classnames: cx - } = this.props; + let {quickEdit, render, popOverContainer, classPrefix: ns, classnames: cx} = this.props; const content = (
@@ -346,7 +347,7 @@ export const HocQuickEdit = (config:Partial = {}) => (Component onSubmit: this.handleSubmit, onAction: this.handleAction, onChange: null, - popOverContainer: popOverContainer ? () => this.overlay : null + popOverContainer: popOverContainer ? () => this.overlay : null, })}
); @@ -375,20 +376,10 @@ export const HocQuickEdit = (config:Partial = {}) => (Component } render() { - const { - onQuickChange, - quickEdit, - quickEditEnabled, - className, - classnames: cx, - render, - noHoc - } = this.props; + const {onQuickChange, quickEdit, quickEditEnabled, className, classnames: cx, render, noHoc} = this.props; if (!quickEdit || !onQuickChange || quickEditEnabled === false || noHoc) { - return ( - - ); + return ; } if ((quickEdit as QuickEditConfig).mode === 'inline') { @@ -397,22 +388,27 @@ export const HocQuickEdit = (config:Partial = {}) => (Component {render('inline-form', this.buildSchema(), { wrapperComponent: 'div', className: cx('Form--quickEdit'), - onChange: (values:object) => onQuickChange(values, (quickEdit as QuickEditConfig).saveImmediately) + onChange: (values: object) => + onQuickChange(values, (quickEdit as QuickEditConfig).saveImmediately), })} - ) + ); } else { return ( - - + {this.state.isOpened ? this.renderPopOver() : null} ); diff --git a/src/renderers/Remark.tsx b/src/renderers/Remark.tsx index 6ceb94d68..59cbcf774 100644 --- a/src/renderers/Remark.tsx +++ b/src/renderers/Remark.tsx @@ -1,18 +1,26 @@ -import * as React from "react"; -import { Renderer, RendererProps } from "../factory"; -import { Api, SchemaNode, Schema, Action } from "../types"; -import * as cx from "classnames"; +import * as React from 'react'; +import {Renderer, RendererProps} from '../factory'; +import {Api, SchemaNode, Schema, Action} from '../types'; +import * as cx from 'classnames'; import TooltipWrapper from '../components/TooltipWrapper'; -import { filter } from "../utils/tpl"; +import {filter} from '../utils/tpl'; -export function filterContents(tooltip:string | undefined | {title?: string; content?: string; body?: string}, data:any) { +export function filterContents( + tooltip: string | undefined | {title?: string; content?: string; body?: string}, + data: any +) { if (typeof tooltip === 'string') { return filter(tooltip, data); } else if (tooltip) { - return tooltip.title ? { - title: filter(tooltip.title, data), - content: tooltip.content || tooltip.body ? filter(tooltip.content || tooltip.body || '', data) : undefined, - } : (tooltip.content || tooltip.body ? filter(tooltip.content || tooltip.body || '', data) : undefined); + return tooltip.title + ? { + title: filter(tooltip.title, data), + content: + tooltip.content || tooltip.body ? filter(tooltip.content || tooltip.body || '', data) : undefined, + } + : tooltip.content || tooltip.body + ? filter(tooltip.content || tooltip.body || '', data) + : undefined; } return tooltip; } @@ -45,7 +53,7 @@ export default class Remark extends React.Component { classPrefix: ns, classnames: cx, content, - data + data, } = this.props; return ( @@ -53,14 +61,14 @@ export default class Remark extends React.Component { classPrefix={ns} classnames={cx} tooltip={filterContents(tooltip || content, data)} - placement={tooltip && tooltip.placement || placement} - rootClose={tooltip && tooltip.rootClose || rootClose} - trigger={tooltip && tooltip.trigger || trigger} + placement={(tooltip && tooltip.placement) || placement} + rootClose={(tooltip && tooltip.rootClose) || rootClose} + trigger={(tooltip && tooltip.trigger) || trigger} container={container} delay={tooltip && tooltip.delay} > -
- +
+
); @@ -69,6 +77,6 @@ export default class Remark extends React.Component { @Renderer({ test: /(^|\/)remark$/, - name: 'remark' + name: 'remark', }) export class RemarkRenderer extends Remark {} diff --git a/src/renderers/Service.tsx b/src/renderers/Service.tsx index 0c7a4f064..94e64ddb1 100644 --- a/src/renderers/Service.tsx +++ b/src/renderers/Service.tsx @@ -1,23 +1,13 @@ import * as React from 'react'; import * as PropTypes from 'prop-types'; -import { - Renderer, - RendererProps -} from '../factory'; +import {Renderer, RendererProps} from '../factory'; import {ServiceStore, IServiceStore} from '../store/service'; -import { - Api, - SchemaNode, - ApiObject, - RendererData -} from '../types'; -import { - filter, evalExpression -} from '../utils/tpl'; +import {Api, SchemaNode, ApiObject, RendererData} from '../types'; +import {filter, evalExpression} from '../utils/tpl'; import * as cx from 'classnames'; -import Scoped, { ScopedContext, IScopedContext } from '../Scoped'; -import { observer } from 'mobx-react'; -import { isApiOutdated } from '../utils/api'; +import Scoped, {ScopedContext, IScopedContext} from '../Scoped'; +import {observer} from 'mobx-react'; +import {isApiOutdated} from '../utils/api'; export interface ServiceProps extends RendererProps { api?: Api; @@ -34,15 +24,11 @@ export default class Service extends React.Component { timer: NodeJS.Timeout; mounted: boolean; - static defaultProps:Partial = { - - }; + static defaultProps: Partial = {}; - static propsList:Array = [ - - ]; + static propsList: Array = []; - constructor(props:ServiceProps) { + constructor(props: ServiceProps) { super(props); this.handleQuery = this.handleQuery.bind(this); @@ -52,40 +38,36 @@ export default class Service extends React.Component { } componentDidMount() { - const { - schemaApi, - initFetchSchema, - api, - initFetch, - store - } = this.props; + const {schemaApi, initFetchSchema, api, initFetch, store} = this.props; this.mounted = true; - if (schemaApi && initFetchSchema !== false && (!(schemaApi as ApiObject).sendOn || evalExpression((schemaApi as ApiObject).sendOn as string, store.data))) { - store - .fetchSchema(schemaApi, store.data) - .then(this.initInterval); + if ( + schemaApi && + initFetchSchema !== false && + (!(schemaApi as ApiObject).sendOn || evalExpression((schemaApi as ApiObject).sendOn as string, store.data)) + ) { + store.fetchSchema(schemaApi, store.data).then(this.initInterval); } - if (api && initFetch !== false && (!(api as ApiObject).sendOn || evalExpression((api as ApiObject).sendOn as string, store.data))) { - store - .fetchInitData(api, store.data) - .then(this.initInterval); + if ( + api && + initFetch !== false && + (!(api as ApiObject).sendOn || evalExpression((api as ApiObject).sendOn as string, store.data)) + ) { + store.fetchInitData(api, store.data).then(this.initInterval); } } - componentDidUpdate(prevProps:ServiceProps) { + componentDidUpdate(prevProps: ServiceProps) { const props = this.props; const store = props.store; - isApiOutdated(prevProps.api, props.api, prevProps.data, props.data) && store - .fetchData(props.api as Api, store.data) - .then(this.initInterval); + isApiOutdated(prevProps.api, props.api, prevProps.data, props.data) && + store.fetchData(props.api as Api, store.data).then(this.initInterval); - isApiOutdated(prevProps.schemaApi, props.schemaApi, prevProps.data, props.data) && store - .fetchSchema(props.schemaApi as Api, store.data) - .then(this.initInterval); + isApiOutdated(prevProps.schemaApi, props.schemaApi, prevProps.data, props.data) && + store.fetchSchema(props.schemaApi as Api, store.data).then(this.initInterval); } componentWillUnmount() { @@ -94,46 +76,40 @@ export default class Service extends React.Component { } initInterval(value: any) { - const { - interval, - silentPolling, - stopAutoRefreshWhen, - data - } = this.props; + const {interval, silentPolling, stopAutoRefreshWhen, data} = this.props; - interval - && this.mounted - && (!stopAutoRefreshWhen || !evalExpression(stopAutoRefreshWhen, data)) - && (this.timer = setTimeout(silentPolling ? this.silentReload : this.reload, Math.max(interval, 3000))); + interval && + this.mounted && + (!stopAutoRefreshWhen || !evalExpression(stopAutoRefreshWhen, data)) && + (this.timer = setTimeout(silentPolling ? this.silentReload : this.reload, Math.max(interval, 3000))); return value; } reload(subpath?: string, query?: any, ctx?: RendererData, silent?: boolean) { - if (query) { return this.receive(query); } - - const { - schemaApi, - fetchSchema, - api, - fetch, - store - } = this.props; + + const {schemaApi, fetchSchema, api, fetch, store} = this.props; clearTimeout(this.timer); - if (schemaApi && fetchSchema !== false && (!(schemaApi as ApiObject).sendOn || evalExpression((schemaApi as ApiObject).sendOn as string, store.data))) { - store - .fetchSchema(schemaApi, store.data) - .then(this.initInterval); + if ( + schemaApi && + fetchSchema !== false && + (!(schemaApi as ApiObject).sendOn || evalExpression((schemaApi as ApiObject).sendOn as string, store.data)) + ) { + store.fetchSchema(schemaApi, store.data).then(this.initInterval); } - if (api && fetch !== false && (!(api as ApiObject).sendOn || evalExpression((api as ApiObject).sendOn as string, store.data))) { + if ( + api && + fetch !== false && + (!(api as ApiObject).sendOn || evalExpression((api as ApiObject).sendOn as string, store.data)) + ) { store .fetchData(api, store.data, { - silent + silent, }) .then(this.initInterval); } @@ -143,66 +119,61 @@ export default class Service extends React.Component { this.reload(target, query, undefined, true); } - receive(values:object) { - const { - store - } = this.props; + receive(values: object) { + const {store} = this.props; store.updateData(values); this.reload(); } - handleQuery(query:any) { + handleQuery(query: any) { this.receive(query); } renderBody() { - const { - render, - store, - body: schema, - classnames: cx - } = this.props; + const {render, store, body: schema, classnames: cx} = this.props; return ( -
- {render('body', store.schema || schema, { - key: store.schemaKey || 'body', - onQuery: this.handleQuery - }) as JSX.Element} +
+ { + render('body', store.schema || schema, { + key: store.schemaKey || 'body', + onQuery: this.handleQuery, + }) as JSX.Element + }
); } render() { - const { - className, - store, - render, - classPrefix: ns, - classnames: cx - } = this.props; + const {className, store, render, classPrefix: ns, classnames: cx} = this.props; return ( -
+
{store.error ? (
- + {store.msg}
) : null} {this.renderBody()} - {store.loading ? render('info', { - type: 'spinner', - overlay: true - }, { - key: 'info', - size: 'lg', - }) : null} + {store.loading + ? render( + 'info', + { + type: 'spinner', + overlay: true, + }, + { + key: 'info', + size: 'lg', + } + ) + : null}
); } @@ -211,7 +182,7 @@ export default class Service extends React.Component { @Renderer({ test: /(^|\/)service$/, storeType: ServiceStore.name, - name: 'service' + name: 'service', }) export class ServiceRenderer extends Service { static contextType = ScopedContext; @@ -227,4 +198,4 @@ export class ServiceRenderer extends Service { const scoped = this.context as IScopedContext; scoped.unRegisterComponent(this); } -}; +} diff --git a/src/renderers/Spinner.tsx b/src/renderers/Spinner.tsx index d3741b97e..4d4f7bdd5 100644 --- a/src/renderers/Spinner.tsx +++ b/src/renderers/Spinner.tsx @@ -1,9 +1,8 @@ -import Spinner from "../components/Spinner"; -import { Renderer } from "../factory"; - +import Spinner from '../components/Spinner'; +import {Renderer} from '../factory'; @Renderer({ test: /(^|\/)spinner$/, - name: 'spinner' + name: 'spinner', }) -export class SpinnerRenderer extends Spinner {} \ No newline at end of file +export class SpinnerRenderer extends Spinner {} diff --git a/src/renderers/Status.tsx b/src/renderers/Status.tsx index c9a6ff6a2..3a8d12e8c 100644 --- a/src/renderers/Status.tsx +++ b/src/renderers/Status.tsx @@ -1,17 +1,8 @@ import * as React from 'react'; -import { - Renderer, - RendererProps -} from '../factory'; +import {Renderer, RendererProps} from '../factory'; import {ServiceStore, IServiceStore} from '../store/service'; -import { - Api, - SchemaNode, - PlainObject -} from '../types'; -import { - filter -} from '../utils/tpl'; +import {Api, SchemaNode, PlainObject} from '../types'; +import {filter} from '../utils/tpl'; import * as cx from 'classnames'; export interface StatusProps extends RendererProps { @@ -21,11 +12,11 @@ export interface StatusProps extends RendererProps { } export class StatusField extends React.Component { - static defaultProps:Partial = { + static defaultProps: Partial = { placeholder: '-', map: { 0: 'fa fa-times text-danger', - 1: 'fa fa-check text-success' + 1: 'fa fa-check text-success', }, labelMap: { // 0: '失败', @@ -34,19 +25,12 @@ export class StatusField extends React.Component { }; render() { - const { - className, - placeholder, - map, - labelMap, - classnames: cx, - data - } = this.props; + const {className, placeholder, map, labelMap, classnames: cx, data} = this.props; let value = this.props.value; - let viewValue:React.ReactNode = {placeholder}; - let wrapClassName:string = ''; + let viewValue: React.ReactNode = {placeholder}; + let wrapClassName: string = ''; - if (value !== undefined && value !== "" && map) { + if (value !== undefined && value !== '' && map) { if (typeof value === 'boolean') { value = value ? 1 : 0; } else if (/^\d+$/.test(value)) { @@ -54,23 +38,24 @@ export class StatusField extends React.Component { } wrapClassName = `StatusField--${value}`; - viewValue = (); + viewValue = ; if (labelMap && labelMap[value]) { - viewValue = [viewValue, ({filter(labelMap[value], data)})]; + viewValue = [ + viewValue, + + {filter(labelMap[value], data)} + , + ]; } } - return ( - - {viewValue} - - ); + return {viewValue}; } } @Renderer({ test: /(^|\/)status$/, - name: 'status' + name: 'status', }) -export class StatusFieldRenderer extends StatusField {}; +export class StatusFieldRenderer extends StatusField {} diff --git a/src/renderers/Switch.tsx b/src/renderers/Switch.tsx index 37381d06b..c5b6597ae 100644 --- a/src/renderers/Switch.tsx +++ b/src/renderers/Switch.tsx @@ -1,17 +1,8 @@ import * as React from 'react'; -import { - Renderer, - RendererProps -} from '../factory'; +import {Renderer, RendererProps} from '../factory'; import {ServiceStore, IServiceStore} from '../store/service'; -import { - Api, - SchemaNode, - PlainObject -} from '../types'; -import { - filter -} from '../utils/tpl'; +import {Api, SchemaNode, PlainObject} from '../types'; +import {filter} from '../utils/tpl'; import * as cx from 'classnames'; import Switch from '../components/Switch'; @@ -24,34 +15,32 @@ export interface SwitchProps extends RendererProps { } export class SwitchField extends React.Component { - static defaultProps:Partial = { + static defaultProps: Partial = { placeholder: '-', trueValue: true, falseValue: false, readOnly: true, - saveImmediately: false + saveImmediately: false, }; - constructor(props:SwitchProps) { + constructor(props: SwitchProps) { super(props); this.handleChange = this.handleChange.bind(this); } - handleChange(checked:boolean) { - const { - onQuickChange, - name, - trueValue, - falseValue, - saveImmediately, - readOnly, - disabled - } = this.props; + handleChange(checked: boolean) { + const {onQuickChange, name, trueValue, falseValue, saveImmediately, readOnly, disabled} = this.props; - onQuickChange && !readOnly && !disabled && onQuickChange({ - [name as string]: checked ? trueValue : falseValue - }, saveImmediately); + onQuickChange && + !readOnly && + !disabled && + onQuickChange( + { + [name as string]: checked ? trueValue : falseValue, + }, + saveImmediately + ); } render() { @@ -64,19 +53,19 @@ export class SwitchField extends React.Component { falseValue, onQuickChange, option, - disabled + disabled, } = this.props; - let viewValue:React.ReactNode = {placeholder}; + let viewValue: React.ReactNode = {placeholder}; let showOption = false; if (value == trueValue || value == falseValue) { showOption = !!option; viewValue = ( - @@ -94,6 +83,6 @@ export class SwitchField extends React.Component { @Renderer({ test: /(^|\/)switch$/, - name: 'switch' + name: 'switch', }) -export class SwitchFieldRenderer extends SwitchField {}; +export class SwitchFieldRenderer extends SwitchField {} diff --git a/src/renderers/Table.tsx b/src/renderers/Table.tsx index f7f304312..aa35d9c2b 100644 --- a/src/renderers/Table.tsx +++ b/src/renderers/Table.tsx @@ -1,29 +1,17 @@ import * as React from 'react'; -import { - findDOMNode -} from 'react-dom'; -import { - Renderer, - RendererProps -} from '../factory'; -import { - SchemaNode, - Action, - Schema, - Api -} from '../types'; +import {findDOMNode} from 'react-dom'; +import {Renderer, RendererProps} from '../factory'; +import {SchemaNode, Action, Schema, Api} from '../types'; import forEach = require('lodash/forEach'); -import { - filter -} from '../utils/tpl'; +import {filter} from '../utils/tpl'; import * as cx from 'classnames'; import DropDownButton from './DropDownButton'; import Checkbox from '../components/Checkbox'; import Button from '../components/Button'; -import { TableStore, ITableStore, IColumn, IRow } from '../store/table'; -import { observer } from 'mobx-react'; -import { anyChanged, getScrollParent, difference, noop } from '../utils/helper'; -import { resolveVariable } from '../utils/tpl-builtin'; +import {TableStore, ITableStore, IColumn, IRow} from '../store/table'; +import {observer} from 'mobx-react'; +import {anyChanged, getScrollParent, difference, noop} from '../utils/helper'; +import {resolveVariable} from '../utils/tpl-builtin'; import debounce = require('lodash/debounce'); import xor = require('lodash/xor'); import QuickEdit from './QuickEdit'; @@ -38,8 +26,8 @@ import PopOverable from './PopOver'; export interface Column { type: string; - [propName:string]: any; -}; + [propName: string]: any; +} export interface TableProps extends RendererProps { title?: string; // 标题 @@ -54,11 +42,11 @@ export interface TableProps extends RendererProps { store: ITableStore; columns?: Array; tableClassName?: string; - source?:string; + source?: string; selectable?: boolean; selected?: Array; valueField?: string; - draggable?:boolean; + draggable?: boolean; columnsTogglable?: boolean | 'auto'; affixHeader?: boolean; combineNum?: number; @@ -66,11 +54,16 @@ export interface TableProps extends RendererProps { itemCheckableOn?: string; itemDraggableOn?: string; itemActions?: Array; - onSelect: (selectedItems:Array, unSelectedItems:Array) => void; - onSave?: (items:Array | object, diff: Array | object, rowIndexes: Array | number, unModifiedItems?:Array) => void; - onSaveOrder?: (moved: Array, items:Array) => void; - onQuery: (values:object) => void; - buildItemProps?: (item:any, index:number) => any; + onSelect: (selectedItems: Array, unSelectedItems: Array) => void; + onSave?: ( + items: Array | object, + diff: Array | object, + rowIndexes: Array | number, + unModifiedItems?: Array + ) => void; + onSaveOrder?: (moved: Array, items: Array) => void; + onQuery: (values: object) => void; + buildItemProps?: (item: any, index: number) => any; checkOnItemClick?: boolean; hideCheckToggler?: boolean; } @@ -99,10 +92,10 @@ export default class Table extends React.Component { 'hideCheckToggler', 'itemActions', 'combineNum', - "items", - "valueField" + 'items', + 'valueField', ]; - static defaultProps:Partial= { + static defaultProps: Partial = { className: '', placeholder: '暂无数据', tableClassName: '', @@ -117,37 +110,37 @@ export default class Table extends React.Component { itemCheckableOn: '', itemDraggableOn: '', hideCheckToggler: false, - dragIcon: 'glyphicon glyphicon-sort' + dragIcon: 'glyphicon glyphicon-sort', }; - table?:HTMLTableElement; + table?: HTMLTableElement; sortable?: Sortable; dragTip?: HTMLElement; - affixedTable?:HTMLTableElement; + affixedTable?: HTMLTableElement; parentNode?: HTMLElement | Window; lastScrollLeft: number = -1; totalWidth: number = 0; totalHeight: number = 0; outterWidth: number = 0; outterHeight: number = 0; - unSensor:Function; + unSensor: Function; updateTableInfoLazy: () => void; widths: { - [propName:string]: number; + [propName: string]: number; } = {}; heights: { - [propName:string]: number; + [propName: string]: number; } = {}; - renderedToolbars:Array = []; + renderedToolbars: Array = []; - constructor(props:TableProps) { + constructor(props: TableProps) { super(props); this.handleOutterScroll = this.handleOutterScroll.bind(this); this.affixDetect = this.affixDetect.bind(this); this.updateTableInfoLazy = debounce(this.updateTableInfo.bind(this), 250, { trailing: true, - leading: false + leading: false, }); this.tableRef = this.tableRef.bind(this); this.affxiedTableRef = this.affxiedTableRef.bind(this); @@ -166,10 +159,10 @@ export default class Table extends React.Component { this.handleMouseLeave = this.handleMouseLeave.bind(this); } - static syncRows(store:ITableStore, props:TableProps, prevProps?:TableProps) { + static syncRows(store: ITableStore, props: TableProps, prevProps?: TableProps) { const source = props.source; const value = props.value || props.items; - let rows:Array = []; + let rows: Array = []; let updateRows = true; if (Array.isArray(value)) { @@ -204,7 +197,7 @@ export default class Table extends React.Component { itemCheckableOn, itemDraggableOn, hideCheckToggler, - combineNum + combineNum, } = this.props; store.update({ @@ -220,7 +213,7 @@ export default class Table extends React.Component { itemCheckableOn, itemDraggableOn, hideCheckToggler, - combineNum + combineNum, }); Table.syncRows(store, this.props); @@ -228,7 +221,7 @@ export default class Table extends React.Component { } componentDidMount() { - let parent:HTMLElement | Window | null = getScrollParent(findDOMNode(this) as HTMLElement); + let parent: HTMLElement | Window | null = getScrollParent(findDOMNode(this) as HTMLElement); if (!parent || parent === document.body) { parent = window; @@ -246,27 +239,32 @@ export default class Table extends React.Component { this.affixDetect(); parent.addEventListener('scroll', this.affixDetect); window.addEventListener('resize', this.affixDetect); - } - componentWillReceiveProps(nextProps:TableProps) { + componentWillReceiveProps(nextProps: TableProps) { const props = this.props; const store = nextProps.store; - if (anyChanged([ - 'selectable', - 'columnsTogglable', - 'draggable', - 'orderBy', - 'orderDir', - 'multiple', - 'footable', - 'primaryField', - 'itemCheckableOn', - 'itemDraggableOn', - 'hideCheckToggler', - 'combineNum' - ], props, nextProps)) { + if ( + anyChanged( + [ + 'selectable', + 'columnsTogglable', + 'draggable', + 'orderBy', + 'orderDir', + 'multiple', + 'footable', + 'primaryField', + 'itemCheckableOn', + 'itemDraggableOn', + 'hideCheckToggler', + 'combineNum', + ], + props, + nextProps + ) + ) { store.update({ selectable: nextProps.selectable, columnsTogglable: nextProps.columnsTogglable, @@ -279,21 +277,20 @@ export default class Table extends React.Component { itemCheckableOn: nextProps.itemCheckableOn, itemDraggableOn: nextProps.itemDraggableOn, hideCheckToggler: nextProps.hideCheckToggler, - combineNum: nextProps.combineNum - }) + combineNum: nextProps.combineNum, + }); } if (props.columns !== nextProps.columns) { store.update({ - columns: nextProps.columns + columns: nextProps.columns, }); } - if (anyChanged([ - 'source', - 'value', - 'items' - ], props, nextProps) || !nextProps.value && !nextProps.items && nextProps.data !== props.data) { + if ( + anyChanged(['source', 'value', 'items'], props, nextProps) || + (!nextProps.value && !nextProps.items && nextProps.data !== props.data) + ) { Table.syncRows(store, nextProps, props); this.syncSelected(); } else if (props.selected !== nextProps.selected) { @@ -315,10 +312,8 @@ export default class Table extends React.Component { this.unSensor && this.unSensor(); } - handleAction(e:React.UIEvent, action: Action, ctx: object) { - const { - onAction - } = this.props; + handleAction(e: React.UIEvent, action: Action, ctx: object) { + const {onAction} = this.props; // todo onAction(e, action, ctx); @@ -326,23 +321,19 @@ export default class Table extends React.Component { handleCheck(item: IRow) { item.toggle(); - this.syncSelected() + this.syncSelected(); } handleCheckAll() { - const { - store, - } = this.props; + const {store} = this.props; store.toggleAll(); this.syncSelected(); } - handleQuickChange(item: IRow, values:object, saveImmediately?: boolean | any, savePristine?: boolean) { - const { - onSave - } = this.props; - + handleQuickChange(item: IRow, values: object, saveImmediately?: boolean | any, savePristine?: boolean) { + const {onSave} = this.props; + item.change(values, savePristine); // 值发生变化了,需要通过 onSelect 通知到外面,否则会出现数据不同步的问题 @@ -353,10 +344,14 @@ export default class Table extends React.Component { } if (saveImmediately && saveImmediately.api) { - this.props.onAction(null, { - actionType: 'ajax', - api: saveImmediately.api - }, values); + this.props.onAction( + null, + { + actionType: 'ajax', + api: saveImmediately.api, + }, + values + ); return; } @@ -368,10 +363,7 @@ export default class Table extends React.Component { } handleSave() { - const { - store, - onSave - } = this.props; + const {store, onSave} = this.props; if (!onSave || !store.modifiedRows.length) { return; @@ -385,10 +377,7 @@ export default class Table extends React.Component { } handleSaveOrder() { - const { - store, - onSaveOrder - } = this.props; + const {store, onSaveOrder} = this.props; if (!onSaveOrder || !store.movedRows.length) { return; @@ -398,43 +387,33 @@ export default class Table extends React.Component { } syncSelected() { - const { - store, - onSelect - } = this.props; - + const {store, onSelect} = this.props; + onSelect && onSelect(store.selectedRows.map(item => item.data), store.unSelectedRows.map(item => item.data)); } reset() { - const { - store - } = this.props; + const {store} = this.props; store.reset(); } - bulkUpdate(value:any, items:Array) { - const { - store, - primaryField - } = this.props; + bulkUpdate(value: any, items: Array) { + const {store, primaryField} = this.props; if (primaryField && value.ids) { const ids = value.ids.split(','); - const rows = store.rows.filter(item => find(ids, (id:any) => id && id == item.data[primaryField])); + const rows = store.rows.filter(item => find(ids, (id: any) => id && id == item.data[primaryField])); const newValue = {...value, ids: undefined}; rows.forEach(row => row.change(newValue)); } else { const rows = store.rows.filter(item => ~items.indexOf(item.pristine)); - rows.forEach(row => row.change(value)) + rows.forEach(row => row.change(value)); } } getSelected() { - const { - store - } = this.props; + const {store} = this.props; return store.selectedRows.map(item => item.data); } @@ -448,10 +427,9 @@ export default class Table extends React.Component { const dom = findDOMNode(this) as HTMLElement; const clip = (this.table as HTMLElement).getBoundingClientRect(); const offsetY = this.props.env.affixOffsetTop || 0; - const affixed = clip.top < offsetY && (clip.top + clip.height - 40) > offsetY; + const affixed = clip.top < offsetY && clip.top + clip.height - 40 > offsetY; const afixedDom = dom.querySelector(`:scope>.${ns}Table-fixedTop`) as HTMLElement; - afixedDom.style.cssText = `top: ${offsetY}px;width: ${(this.table.parentNode as HTMLElement).offsetWidth}px`; affixed ? afixedDom.classList.add('in') : afixedDom.classList.remove('in'); // store.markHeaderAffix(clip.top < offsetY && (clip.top + clip.height - 40) > offsetY); @@ -477,51 +455,64 @@ export default class Table extends React.Component { this.outterWidth = outter.offsetWidth; this.outterHeight = outter.offsetHeight; - let widths:{ - [propName:string]: number; - } = this.widths = {}; - let heights:{ - [propName:string]: number; - } = this.heights = {}; - forEach(table.querySelectorAll('thead>tr:first-child>th'), (item:HTMLElement) => { + let widths: { + [propName: string]: number; + } = (this.widths = {}); + let heights: { + [propName: string]: number; + } = (this.heights = {}); + forEach(table.querySelectorAll('thead>tr:first-child>th'), (item: HTMLElement) => { heights.header || (heights.header = item.offsetHeight); - widths[item.getAttribute('index') as string] = item.offsetWidth + widths[item.getAttribute('index') as string] = item.offsetWidth; }); - forEach(table.querySelectorAll('tbody>tr>*:first-child'), (item:HTMLElement, index:number) => heights[index] = item.offsetHeight); + forEach( + table.querySelectorAll('tbody>tr>*:first-child'), + (item: HTMLElement, index: number) => (heights[index] = item.offsetHeight) + ); // 让 react 去更新非常慢,还是手动更新吧。 const dom = findDOMNode(this) as HTMLElement; - forEach(dom.querySelectorAll(`:scope>.${ns}Table-fixedLeft, :scope>.${ns}Table-fixedRight`), (item:HTMLElement) => item.style.cssText = `height:${this.totalHeight}px;`); - + forEach( + dom.querySelectorAll(`:scope>.${ns}Table-fixedLeft, :scope>.${ns}Table-fixedRight`), + (item: HTMLElement) => (item.style.cssText = `height:${this.totalHeight}px;`) + ); + if (affixHeader) { - (dom.querySelector(`.${ns}Table-fixedTop>.${ns}Table-wrapper`) as HTMLElement).style.cssText = `width: ${this.outterWidth}px`; - let affixedTable = (dom.querySelector(`.${ns}Table-wrapper table`) as HTMLElement); + (dom.querySelector(`.${ns}Table-fixedTop>.${ns}Table-wrapper`) as HTMLElement).style.cssText = `width: ${ + this.outterWidth + }px`; + let affixedTable = dom.querySelector(`.${ns}Table-wrapper table`) as HTMLElement; affixedTable.style.cssText = `width: ${this.totalWidth}px`; } - forEach(dom.querySelectorAll(`.${ns}Table-fixedTop table, .${ns}Table-fixedLeft table, .${ns}Table-fixedRight table`), table => { - forEach(table.querySelectorAll('thead>tr>th'), (item:HTMLElement) => { - item.style.cssText = `width: ${this.widths[parseInt(item.getAttribute('index') as string, 10)]}px`; - }); + forEach( + dom.querySelectorAll( + `.${ns}Table-fixedTop table, .${ns}Table-fixedLeft table, .${ns}Table-fixedRight table` + ), + table => { + forEach(table.querySelectorAll('thead>tr>th'), (item: HTMLElement) => { + item.style.cssText = `width: ${this.widths[parseInt(item.getAttribute('index') as string, 10)]}px`; + }); - forEach(table.querySelectorAll('tbody>tr'), (item:HTMLElement, index) => { - item.style.cssText = `height: ${this.heights[index]}px`; - }); - }); + forEach(table.querySelectorAll('tbody>tr'), (item: HTMLElement, index) => { + item.style.cssText = `height: ${this.heights[index]}px`; + }); + } + ); } handleOutterScroll() { const outter = (this.table as HTMLElement).parentNode as HTMLElement; const scrollLeft = outter.scrollLeft; - + if (scrollLeft === this.lastScrollLeft) { return; } - + this.lastScrollLeft = scrollLeft; - let leading = (scrollLeft === 0); - let trailing = (scrollLeft + this.outterWidth) === this.totalWidth; + let leading = scrollLeft === 0; + let trailing = scrollLeft + this.outterWidth === this.totalWidth; // console.log(scrollLeft, store.outterWidth, store.totalWidth, (scrollLeft + store.outterWidth) === store.totalWidth); // store.setLeading(leading); // store.setTrailing(trailing); @@ -550,7 +541,7 @@ export default class Table extends React.Component { } } - tableRef(ref:HTMLTableElement) { + tableRef(ref: HTMLTableElement) { this.table = ref; if (ref) { @@ -561,7 +552,7 @@ export default class Table extends React.Component { } } - dragTipRef(ref:any) { + dragTipRef(ref: any) { if (!this.dragTip && ref) { this.initDragging(); } else if (this.dragTip && !ref) { @@ -571,8 +562,7 @@ export default class Table extends React.Component { this.dragTip = ref; } - - affxiedTableRef(ref:HTMLTableElement) { + affxiedTableRef(ref: HTMLTableElement) { this.affixedTable = ref; } @@ -583,21 +573,21 @@ export default class Table extends React.Component { group: 'table', handle: `.${ns}Table-dragCell`, ghostClass: 'is-dragging', - onEnd: (e:any) => { + onEnd: (e: any) => { // 没有移动 if (e.newIndex === e.oldIndex) { return; } const parent = e.to as HTMLElement; - if (e.oldIndex < parent.childNodes.length -1) { + if (e.oldIndex < parent.childNodes.length - 1) { parent.insertBefore(e.item, parent.childNodes[e.oldIndex]); } else { parent.appendChild(e.item); } store.exchange(e.oldIndex, e.newIndex); - } + }, }); } @@ -609,8 +599,8 @@ export default class Table extends React.Component { return findDOMNode(this); } - handleMouseMove(e:React.MouseEvent) { - const tr:HTMLElement = (e.target as HTMLElement).closest('tr[data-index]') as HTMLElement; + handleMouseMove(e: React.MouseEvent) { + const tr: HTMLElement = (e.target as HTMLElement).closest('tr[data-index]') as HTMLElement; if (!tr) { return; @@ -625,49 +615,63 @@ export default class Table extends React.Component { handleMouseLeave() { const store = this.props.store; - + if (~store.hoverIndex) { store.rows[store.hoverIndex].setIsHover(false); } } renderHeading() { - let { - title, - store, - hideQuickSaveBtn, - data, - classnames: cx - } = this.props; + let {title, store, hideQuickSaveBtn, data, classnames: cx} = this.props; - if (title || store.modified && !hideQuickSaveBtn || store.moved) { + if (title || (store.modified && !hideQuickSaveBtn) || store.moved) { return ( -
+
{store.modified && !hideQuickSaveBtn ? ( {`当前有 ${store.modified} 条记录修改了内容, 但并没有提交。请选择:`} - - - ) : store.moved ? ( + ) : store.moved ? ( {`当前有 ${store.moved} 条记录修改了顺序, 但并没有提交。请选择:`} - - - ) : title ? filter(title, data) : ''} + ) : title ? ( + filter(title, data) + ) : ( + '' + )}
); } @@ -675,44 +679,29 @@ export default class Table extends React.Component { return null; } - renderHeadCell(column: IColumn, props?:any) { - const { - store, - query, - onQuery, - multiple, - env, - render, - classPrefix: ns, - classnames: cx - } = this.props; + renderHeadCell(column: IColumn, props?: any) { + const {store, query, onQuery, multiple, env, render, classPrefix: ns, classnames: cx} = this.props; if (column.type === '__checkme') { return ( - - {store.rows.length && multiple ? : null} + + {store.rows.length && multiple ? ( + + ) : null} ); } else if (column.type === '__dragme') { - return ( - - - - ); + return ; } else if (column.type === '__expandme') { return ( - +