From 2bc180f202d964d22e702cc71e9bae9796358792 Mon Sep 17 00:00:00 2001 From: David Sehnal <david.sehnal@gmail.com> Date: Thu, 15 Nov 2018 22:08:51 +0100 Subject: [PATCH] mol-plugin: refactoring transform controls --- src/mol-plugin/spec.ts | 2 +- src/mol-plugin/ui/controls/parameters.tsx | 131 ++++++++---------- src/mol-plugin/ui/state/apply-action.tsx | 91 +++--------- .../ui/state/{parameters.tsx => common.tsx} | 95 +++++++++++-- src/mol-plugin/ui/state/update-transform.tsx | 68 ++------- 5 files changed, 166 insertions(+), 221 deletions(-) rename src/mol-plugin/ui/state/{parameters.tsx => common.tsx} (52%) diff --git a/src/mol-plugin/spec.ts b/src/mol-plugin/spec.ts index 2d2971909..40413fd87 100644 --- a/src/mol-plugin/spec.ts +++ b/src/mol-plugin/spec.ts @@ -6,7 +6,7 @@ import { StateAction } from 'mol-state/action'; import { Transformer } from 'mol-state'; -import { StateTransformParameters } from './ui/state/parameters'; +import { StateTransformParameters } from './ui/state/common'; export { PluginSpec } diff --git a/src/mol-plugin/ui/controls/parameters.tsx b/src/mol-plugin/ui/controls/parameters.tsx index 2ac820fcc..354bbf449 100644 --- a/src/mol-plugin/ui/controls/parameters.tsx +++ b/src/mol-plugin/ui/controls/parameters.tsx @@ -7,38 +7,34 @@ import * as React from 'react' import { ParamDefinition as PD } from 'mol-util/param-definition'; +import { camelCaseToWords } from 'mol-util/string'; export interface ParameterControlsProps<P extends PD.Params = PD.Params> { params: P, values: any, onChange: ParamOnChange, - isEnabled?: boolean, + isDisabled?: boolean, onEnter?: () => void } export class ParameterControls<P extends PD.Params> extends React.PureComponent<ParameterControlsProps<P>, {}> { render() { - const common = { - onChange: this.props.onChange, - isEnabled: this.props.isEnabled, - onEnter: this.props.onEnter, - } const params = this.props.params; const values = this.props.values; return <div style={{ width: '100%' }}> {Object.keys(params).map(key => { const param = params[key]; - if (param.type === 'value') return null; - if (param.type === 'mapped') return <MappedControl param={param} key={key} {...common} name={key} value={values[key]} /> - if (param.type === 'group') return <GroupControl param={param} key={key} {...common} name={key} value={values[key]} /> - return <ParamWrapper control={controlFor(param)} param={param} key={key} {...common} name={key} value={values[key]} /> + const Control = controlFor(param); + if (!Control) return null; + return <Control param={param} key={key} onChange={this.props.onChange} onEnter={this.props.onEnter} isDisabled={this.props.isDisabled} name={key} value={values[key]} /> })} </div>; } } -function controlFor(param: PD.Any): ValueControl { +function controlFor(param: PD.Any): ParamControl | undefined { switch (param.type) { + case 'value': return void 0; case 'boolean': return BoolControl; case 'number': return NumberControl; case 'multi-select': return MultiSelectControl; @@ -46,66 +42,57 @@ function controlFor(param: PD.Any): ValueControl { case 'select': return SelectControl; case 'text': return TextControl; case 'interval': return IntervalControl; - case 'group': throw Error('Must be handled separately'); - case 'mapped': throw Error('Must be handled separately'); + case 'group': return GroupControl; + case 'mapped': return MappedControl; + case 'line-graph': return void 0; } throw new Error('not supported'); } -type ParamWrapperProps = { name: string, value: any, param: PD.Base<any>, onChange: ParamOnChange, control: ValueControl, onEnter?: () => void, isEnabled?: boolean } +// type ParamWrapperProps = { name: string, value: any, param: PD.Base<any>, onChange: ParamOnChange, control: ValueControl, onEnter?: () => void, isEnabled?: boolean } + export type ParamOnChange = (params: { param: PD.Base<any>, name: string, value: any }) => void -type ValueControlProps<P extends PD.Base<any> = PD.Base<any>> = { value: any, param: P, isEnabled?: boolean, onChange: (v: any) => void, onEnter?: () => void } -type ValueControl = React.ComponentClass<ValueControlProps<any>> +export interface ParamProps<P extends PD.Base<any> = PD.Base<any>> { name: string, value: P['defaultValue'], param: P, isDisabled?: boolean, onChange: ParamOnChange, onEnter?: () => void } +export type ParamControl = React.ComponentClass<ParamProps<any>> -export class ParamWrapper extends React.PureComponent<ParamWrapperProps> { - onChange = (value: any) => { +export abstract class SimpleParam<P extends PD.Any> extends React.PureComponent<ParamProps<P>> { + protected update(value: any) { this.props.onChange({ param: this.props.param, name: this.props.name, value }); } + abstract renderControl(): JSX.Element; + render() { + const label = this.props.param.label || camelCaseToWords(this.props.name); return <div style={{ padding: '0 3px', borderBottom: '1px solid #ccc' }}> - <div style={{ lineHeight: '20px', float: 'left' }} title={this.props.param.description}>{this.props.param.label}</div> + <div style={{ lineHeight: '20px', float: 'left' }} title={this.props.param.description}>{label}</div> <div style={{ float: 'left', marginLeft: '5px' }}> - <this.props.control value={this.props.value} param={this.props.param} onChange={this.onChange} onEnter={this.props.onEnter} isEnabled={this.props.isEnabled} /> + {this.renderControl()} </div> <div style={{ clear: 'both' }} /> </div>; } } -export class BoolControl extends React.PureComponent<ValueControlProps> { - onClick = () => { - this.props.onChange(!this.props.value); - } - - render() { - return <button onClick={this.onClick} disabled={!this.props.isEnabled}>{this.props.value ? '✓ On' : '✗ Off'}</button>; +export class BoolControl extends SimpleParam<PD.Boolean> { + onClick = () => { this.update(!this.props.value); } + renderControl() { + return <button onClick={this.onClick} disabled={this.props.isDisabled}>{this.props.value ? '✓ On' : '✗ Off'}</button>; } } -export class NumberControl extends React.PureComponent<ValueControlProps<PD.Numeric>, { value: string }> { - // state = { value: this.props.value } - onChange = (e: React.ChangeEvent<HTMLInputElement>) => { - this.props.onChange(+e.target.value); - // this.setState({ value: e.target.value }); - } - - render() { - return <input type='range' - value={'' + this.props.value} - min={this.props.param.min} - max={this.props.param.max} - step={this.props.param.step} - onChange={this.onChange} - />; +export class NumberControl extends SimpleParam<PD.Numeric> { + onChange = (e: React.ChangeEvent<HTMLInputElement>) => { this.update(+e.target.value); } + renderControl() { + return <input type='range' value={'' + this.props.value} min={this.props.param.min} max={this.props.param.max} step={this.props.param.step} onChange={this.onChange} disabled={this.props.isDisabled} />; } } -export class TextControl extends React.PureComponent<ValueControlProps<PD.Text>> { +export class TextControl extends SimpleParam<PD.Text> { onChange = (e: React.ChangeEvent<HTMLInputElement>) => { const value = e.target.value; if (value !== this.props.value) { - this.props.onChange(value); + this.update(value); } } @@ -116,67 +103,60 @@ export class TextControl extends React.PureComponent<ValueControlProps<PD.Text>> } } - render() { + renderControl() { return <input type='text' value={this.props.value || ''} onChange={this.onChange} onKeyPress={this.props.onEnter ? this.onKeyPress : void 0} + disabled={this.props.isDisabled} />; } } -export class SelectControl extends React.PureComponent<ValueControlProps<PD.Select<any>>> { - onChange = (e: React.ChangeEvent<HTMLSelectElement>) => { - this.setState({ value: e.target.value }); - this.props.onChange(e.target.value); - } - - render() { - return <select value={this.props.value || ''} onChange={this.onChange}> +export class SelectControl extends SimpleParam<PD.Select<any>> { + onChange = (e: React.ChangeEvent<HTMLSelectElement>) => { this.update(e.target.value); } + renderControl() { + return <select value={this.props.value || ''} onChange={this.onChange} disabled={this.props.isDisabled}> {this.props.param.options.map(([value, label]) => <option key={value} value={value}>{label}</option>)} </select>; } } -export class MultiSelectControl extends React.PureComponent<ValueControlProps<PD.MultiSelect<any>>> { +export class MultiSelectControl extends SimpleParam<PD.MultiSelect<any>> { // onChange = (e: React.ChangeEvent<HTMLSelectElement>) => { // this.setState({ value: e.target.value }); // this.props.onChange(e.target.value); // } - render() { + renderControl() { return <span>multiselect TODO</span>; - // return <select value={this.props.value || ''} onChange={this.onChange}> - // {this.props.param.options.map(([value, label]) => <option key={label} value={value}>{label}</option>)} - // </select>; } } -export class IntervalControl extends React.PureComponent<ValueControlProps<PD.Interval>> { +export class IntervalControl extends SimpleParam<PD.Interval> { // onChange = (e: React.ChangeEvent<HTMLSelectElement>) => { // this.setState({ value: e.target.value }); // this.props.onChange(e.target.value); // } - render() { + renderControl() { return <span>interval TODO</span>; } } -export class ColorControl extends React.PureComponent<ValueControlProps<PD.Color>> { +export class ColorControl extends SimpleParam<PD.Color> { // onChange = (e: React.ChangeEvent<HTMLSelectElement>) => { // this.setState({ value: e.target.value }); // this.props.onChange(e.target.value); // } - render() { + renderControl() { return <span>color TODO</span>; } } -type GroupWrapperProps = { name: string, value: PD.Group<any>['defaultValue'], param: PD.Group<any>, onChange: ParamOnChange, onEnter?: () => void, isEnabled?: boolean } -export class GroupControl extends React.PureComponent<GroupWrapperProps> { +export class GroupControl extends React.PureComponent<ParamProps<PD.Group<any>>> { change(value: PD.Mapped<any>['defaultValue'] ) { this.props.onChange({ name: this.props.name, param: this.props.param, value }); } @@ -191,13 +171,12 @@ export class GroupControl extends React.PureComponent<GroupWrapperProps> { const params = this.props.param.params; return <div> - <ParameterControls params={params} onChange={this.onChangeParam} values={value.params} onEnter={this.props.onEnter} isEnabled={this.props.isEnabled} /> + <ParameterControls params={params} onChange={this.onChangeParam} values={value.params} onEnter={this.props.onEnter} isDisabled={this.props.isDisabled} /> </div> } } -type MappedWrapperProps = { name: string, value: PD.Mapped<any>['defaultValue'], param: PD.Mapped<any>, onChange: ParamOnChange, onEnter?: () => void, isEnabled?: boolean } -export class MappedControl extends React.PureComponent<MappedWrapperProps> { +export class MappedControl extends React.PureComponent<ParamProps<PD.Mapped<any>>> { change(value: PD.Mapped<any>['defaultValue'] ) { this.props.onChange({ name: this.props.name, param: this.props.param, value }); } @@ -214,16 +193,20 @@ export class MappedControl extends React.PureComponent<MappedWrapperProps> { render() { const value: PD.Mapped<any>['defaultValue'] = this.props.value; const param = this.props.param.map(value.name); + const Mapped = controlFor(param); + + const select = <SelectControl param={this.props.param.select} + isDisabled={this.props.isDisabled} onChange={this.onChangeName} onEnter={this.props.onEnter} + name={'name'} value={value.name} /> + + if (!Mapped) { + return select; + } return <div> - <ParamWrapper control={SelectControl} param={this.props.param.select} - isEnabled={this.props.isEnabled} onChange={this.onChangeName} onEnter={this.props.onEnter} - name={'name'} value={value.name} /> + {select} <div style={{ borderLeft: '5px solid #777', paddingLeft: '5px' }}> - {param.type === 'group' - ? <GroupControl param={param} value={value} name='param' onChange={this.onChangeParam} onEnter={this.props.onEnter} isEnabled={this.props.isEnabled} /> - : param.type === 'mapped' || param.type === 'value' ? null - : <ParamWrapper control={controlFor(param)} param={param} onChange={this.onChangeParam} onEnter={this.props.onEnter} isEnabled={this.props.isEnabled} name={'value'} value={value} />} + <Mapped param={param} value={value} name='param' onChange={this.onChangeParam} onEnter={this.props.onEnter} isDisabled={this.props.isDisabled} /> </div> </div> } diff --git a/src/mol-plugin/ui/state/apply-action.tsx b/src/mol-plugin/ui/state/apply-action.tsx index 4e34aced2..2c616a6be 100644 --- a/src/mol-plugin/ui/state/apply-action.tsx +++ b/src/mol-plugin/ui/state/apply-action.tsx @@ -4,15 +4,12 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as React from 'react'; import { PluginCommands } from 'mol-plugin/command'; +import { PluginContext } from 'mol-plugin/context'; import { State, Transform } from 'mol-state'; import { StateAction } from 'mol-state/action'; -import { Subject } from 'rxjs'; -import { PurePluginComponent } from '../base'; -import { StateTransformParameters } from './parameters'; import { memoizeOne } from 'mol-util/memoize'; -import { PluginContext } from 'mol-plugin/context'; +import { StateTransformParameters, TransformContolBase } from './common'; export { ApplyActionContol }; @@ -33,62 +30,23 @@ namespace ApplyActionContol { } } -class ApplyActionContol extends PurePluginComponent<ApplyActionContol.Props, ApplyActionContol.ComponentState> { - private busy: Subject<boolean>; - - onEnter = () => { - if (this.state.error) return; - this.apply(); - } - - source = this.props.state.cells.get(this.props.nodeRef)!.obj!; - - getInfo = memoizeOne((t: Transform.Ref) => StateTransformParameters.infoFromAction(this.plugin, this.props.state, this.props.action, this.props.nodeRef)); - - events: StateTransformParameters.Props['events'] = { - onEnter: this.onEnter, - onChange: (params, isInitial, errors) => { - this.setState({ params, isInitial, error: errors && errors[0] }) - } - } - - // getInitialParams() { - // const p = this.props.action.definition.params; - // if (!p || !p.default) return {}; - // return p.default(this.source, this.plugin); - // } - - // initialErrors() { - // const p = this.props.action.definition.params; - // if (!p || !p.validate) return void 0; - // const errors = p.validate(this.info.initialValues, this.source, this.plugin); - // return errors && errors[0]; - // } - - state = { nodeRef: this.props.nodeRef, error: void 0, isInitial: true, params: this.getInfo(this.props.nodeRef).initialValues, busy: false }; - - apply = async () => { - this.setState({ busy: true }); - - try { - await PluginCommands.State.ApplyAction.dispatch(this.plugin, { - state: this.props.state, - action: this.props.action.create(this.state.params), - ref: this.props.nodeRef - }); - } finally { - this.busy.next(false); - } +class ApplyActionContol extends TransformContolBase<ApplyActionContol.Props, ApplyActionContol.ComponentState> { + applyAction() { + return PluginCommands.State.ApplyAction.dispatch(this.plugin, { + state: this.props.state, + action: this.props.action.create(this.state.params), + ref: this.props.nodeRef + }); } + getInfo() { return this._getInfo(this.props.nodeRef); } + getHeader() { return this.props.action.definition.display; } + getHeaderFallback() { return this.props.action.id; } + isBusy() { return !!this.state.error || this.state.busy; } + applyText() { return 'Apply'; } - init() { - this.busy = new Subject(); - this.subscribe(this.busy, busy => this.setState({ busy })); - } + private _getInfo = memoizeOne((t: Transform.Ref) => StateTransformParameters.infoFromAction(this.plugin, this.props.state, this.props.action, this.props.nodeRef)); - refresh = () => { - this.setState({ params: this.getInfo(this.props.nodeRef).initialValues, isInitial: true, error: void 0 }); - } + state = { nodeRef: this.props.nodeRef, error: void 0, isInitial: true, params: this.getInfo().initialValues, busy: false }; static getDerivedStateFromProps(props: ApplyActionContol.Props, state: ApplyActionContol.ComponentState) { if (props.nodeRef === state.nodeRef) return null; @@ -104,21 +62,4 @@ class ApplyActionContol extends PurePluginComponent<ApplyActionContol.Props, App }; return newState; } - - render() { - const info = this.getInfo(this.props.nodeRef); - const action = this.props.action; - - return <div> - <div style={{ borderBottom: '1px solid #999', marginBottom: '5px' }}><h3>{(action.definition.display && action.definition.display.name) || action.id}</h3></div> - - <StateTransformParameters info={info} events={this.events} params={this.state.params} isEnabled={!this.state.busy} /> - - <div style={{ textAlign: 'right' }}> - <span style={{ color: 'red' }}>{this.state.error}</span> - {this.state.isInitial ? void 0 : <button title='Refresh Params' onClick={this.refresh} disabled={this.state.busy}>↻</button>} - <button onClick={this.apply} disabled={!!this.state.error || this.state.busy}>Create</button> - </div> - </div> - } } \ No newline at end of file diff --git a/src/mol-plugin/ui/state/parameters.tsx b/src/mol-plugin/ui/state/common.tsx similarity index 52% rename from src/mol-plugin/ui/state/parameters.tsx rename to src/mol-plugin/ui/state/common.tsx index 86d6727bd..3ce020388 100644 --- a/src/mol-plugin/ui/state/parameters.tsx +++ b/src/mol-plugin/ui/state/common.tsx @@ -5,15 +5,15 @@ */ import { StateObject, State, Transform, StateObjectCell, Transformer } from 'mol-state'; -import { shallowEqual } from 'mol-util/object'; import * as React from 'react'; import { PurePluginComponent } from '../base'; import { ParameterControls, ParamOnChange } from '../controls/parameters'; import { StateAction } from 'mol-state/action'; import { PluginContext } from 'mol-plugin/context'; import { ParamDefinition as PD } from 'mol-util/param-definition'; +import { Subject } from 'rxjs'; -export { StateTransformParameters }; +export { StateTransformParameters, TransformContolBase }; class StateTransformParameters extends PurePluginComponent<StateTransformParameters.Props> { getDefinition() { @@ -25,18 +25,10 @@ class StateTransformParameters extends PurePluginComponent<StateTransformParamet validate(params: any) { // TODO return void 0; - - // const validate = this.props.info.definition.validate; - // if (!validate) return void 0; - // const result = validate(params, this.props.info.source, this.plugin); - // if (!result || result.length === 0) return void 0; - // return result.map(r => r[0]); } areInitial(params: any) { - const areEqual = this.props.info.definition.areEqual; - if (!areEqual) return shallowEqual(params, this.props.info.initialValues); - return areEqual(params, this.props.info.initialValues); + return PD.areEqual(this.props.info.params, params, this.props.info.initialValues); } onChange: ParamOnChange = ({ name, value }) => { @@ -45,7 +37,7 @@ class StateTransformParameters extends PurePluginComponent<StateTransformParamet }; render() { - return <ParameterControls params={this.props.info.params} values={this.props.params} onChange={this.onChange} onEnter={this.props.events.onEnter} isEnabled={this.props.isEnabled} />; + return <ParameterControls params={this.props.info.params} values={this.props.params} onChange={this.onChange} onEnter={this.props.events.onEnter} isDisabled={this.props.isDisabled} />; } } @@ -64,7 +56,7 @@ namespace StateTransformParameters { onEnter: () => void, } params: any, - isEnabled?: boolean + isDisabled?: boolean } export type Class = React.ComponentClass<Props> @@ -96,4 +88,81 @@ namespace StateTransformParameters { isEmpty: Object.keys(params).length === 0 } } +} + +namespace TransformContolBase { + export interface State { + params: any, + error?: string, + busy: boolean, + isInitial: boolean + } +} + +abstract class TransformContolBase<P, S extends TransformContolBase.State> extends PurePluginComponent<P, S> { + abstract applyAction(): Promise<void>; + abstract getInfo(): StateTransformParameters.Props['info']; + abstract getHeader(): Transformer.Definition['display']; + abstract getHeaderFallback(): string; + abstract isBusy(): boolean; + abstract applyText(): string; + abstract state: S; + + private busy: Subject<boolean>; + + private onEnter = () => { + if (this.state.error) return; + this.apply(); + } + + events: StateTransformParameters.Props['events'] = { + onEnter: this.onEnter, + onChange: (params, isInitial, errors) => this.setState({ params, isInitial, error: errors && errors[0] }) + } + + apply = async () => { + this.setState({ busy: true }); + try { + await this.applyAction(); + } finally { + this.busy.next(false); + } + } + + init() { + this.busy = new Subject(); + this.subscribe(this.busy, busy => this.setState({ busy })); + } + + refresh = () => { + this.setState({ params: this.getInfo().initialValues, isInitial: true, error: void 0 }); + } + + setDefault = () => { + const info = this.getInfo(); + const params = PD.getDefaultValues(info.params); + this.setState({ params, isInitial: PD.areEqual(info.params, params, info.initialValues), error: void 0 }); + } + + render() { + const info = this.getInfo(); + if (info.isEmpty) return <div>Nothing to update</div>; + + const display = this.getHeader(); + + return <div> + <div style={{ borderBottom: '1px solid #999', marginBottom: '5px' }}> + <button onClick={this.setDefault} disabled={this.state.busy} style={{ float: 'right'}} title='Set default params'>↻</button> + <h3>{(display && display.name) || this.getHeaderFallback()}</h3> + </div> + + <StateTransformParameters info={info} events={this.events} params={this.state.params} isDisabled={this.state.busy} /> + + <div style={{ textAlign: 'right' }}> + <span style={{ color: 'red' }}>{this.state.error}</span> + {this.state.isInitial ? void 0 : <button title='Refresh params' onClick={this.refresh} disabled={this.state.busy}>↶</button>} + <button onClick={this.apply} disabled={this.isBusy()}>{this.applyText()}</button> + </div> + </div> + } } \ No newline at end of file diff --git a/src/mol-plugin/ui/state/update-transform.tsx b/src/mol-plugin/ui/state/update-transform.tsx index 591e1f755..1452b9dfe 100644 --- a/src/mol-plugin/ui/state/update-transform.tsx +++ b/src/mol-plugin/ui/state/update-transform.tsx @@ -5,11 +5,8 @@ */ import { State, Transform } from 'mol-state'; -import * as React from 'react'; -import { Subject } from 'rxjs'; -import { PurePluginComponent } from '../base'; -import { StateTransformParameters } from './parameters'; import { memoizeOne } from 'mol-util/memoize'; +import { StateTransformParameters, TransformContolBase } from './common'; export { UpdateTransformContol }; @@ -28,43 +25,17 @@ namespace UpdateTransformContol { } } -class UpdateTransformContol extends PurePluginComponent<UpdateTransformContol.Props, UpdateTransformContol.ComponentState> { - private busy: Subject<boolean>; +class UpdateTransformContol extends TransformContolBase<UpdateTransformContol.Props, UpdateTransformContol.ComponentState> { + applyAction() { return this.plugin.updateTransform(this.props.state, this.props.transform.ref, this.state.params); } + getInfo() { return this._getInfo(this.props.transform); } + getHeader() { return this.props.transform.transformer.definition.display; } + getHeaderFallback() { return this.props.transform.transformer.definition.name; } + isBusy() { return !!this.state.error || this.state.busy || this.state.isInitial; } + applyText() { return 'Update'; } - onEnter = () => { - if (this.state.error) return; - this.apply(); - } - - getInfo = memoizeOne((t: Transform) => StateTransformParameters.infoFromTransform(this.plugin, this.props.state, this.props.transform)); - - events: StateTransformParameters.Props['events'] = { - onEnter: this.onEnter, - onChange: (params, isInitial, errors) => { - this.setState({ params, isInitial, error: errors && errors[0] }) - } - } - - state: UpdateTransformContol.ComponentState = { transform: this.props.transform, error: void 0, isInitial: true, params: this.getInfo(this.props.transform).initialValues, busy: false }; + private _getInfo = memoizeOne((t: Transform) => StateTransformParameters.infoFromTransform(this.plugin, this.props.state, this.props.transform)); - apply = async () => { - this.setState({ busy: true }); - - try { - await this.plugin.updateTransform(this.props.state, this.props.transform.ref, this.state.params); - } finally { - this.busy.next(false); - } - } - - init() { - this.busy = new Subject(); - this.subscribe(this.busy, busy => this.setState({ busy })); - } - - refresh = () => { - this.setState({ params: this.props.transform.params, isInitial: true, error: void 0 }); - } + state: UpdateTransformContol.ComponentState = { transform: this.props.transform, error: void 0, isInitial: true, params: this.getInfo().initialValues, busy: false }; static getDerivedStateFromProps(props: UpdateTransformContol.Props, state: UpdateTransformContol.ComponentState) { if (props.transform === state.transform) return null; @@ -76,23 +47,4 @@ class UpdateTransformContol extends PurePluginComponent<UpdateTransformContol.Pr }; return newState; } - - render() { - const info = this.getInfo(this.props.transform); - if (info.isEmpty) return <div>Nothing to update</div>; - - const tr = this.props.transform.transformer; - - return <div> - <div style={{ borderBottom: '1px solid #999', marginBottom: '5px' }}><h3>{(tr.definition.display && tr.definition.display.name) || tr.id}</h3></div> - - <StateTransformParameters info={info} events={this.events} params={this.state.params} isEnabled={!this.state.busy} /> - - <div style={{ textAlign: 'right' }}> - <span style={{ color: 'red' }}>{this.state.error}</span> - {this.state.isInitial ? void 0 : <button title='Refresh Params' onClick={this.refresh} disabled={this.state.busy}>↻</button>} - <button onClick={this.apply} disabled={!!this.state.error || this.state.busy || this.state.isInitial}>Update</button> - </div> - </div> - } } \ No newline at end of file -- GitLab