Added ability to delete newly created invalid rule.

This commit is contained in:
Tomas Bures 2017-08-19 17:26:44 +02:00
parent 42338b0afa
commit e6bd9cd943
4 changed files with 36 additions and 71 deletions

View file

@ -51,7 +51,8 @@ class Button extends Component {
onClickAsync: PropTypes.func, onClickAsync: PropTypes.func,
label: PropTypes.string, label: PropTypes.string,
icon: PropTypes.string, icon: PropTypes.string,
className: PropTypes.string className: PropTypes.string,
type: PropTypes.string
} }
@withAsyncErrorHandler @withAsyncErrorHandler
@ -70,6 +71,8 @@ class Button extends Component {
className = className + ' ' + props.className; className = className + ' ' + props.className;
} }
let type = props.type || 'button';
let icon; let icon;
if (props.icon) { if (props.icon) {
icon = <Icon name={props.icon}/> icon = <Icon name={props.icon}/>
@ -81,7 +84,7 @@ class Button extends Component {
} }
return ( return (
<button type="button" className={className} onClick={::this.onClick}>{icon}{iconSpacer}{props.label}</button> <button type={type} className={className} onClick={::this.onClick}>{icon}{iconSpacer}{props.label}</button>
); );
} }
} }

View file

@ -10,7 +10,7 @@ import { withPageHelpers } from './page'
import { withErrorHandling, withAsyncErrorHandler } from './error-handling'; import { withErrorHandling, withAsyncErrorHandler } from './error-handling';
import { TreeTable, TreeSelectMode } from './tree'; import { TreeTable, TreeSelectMode } from './tree';
import { Table, TableSelectMode } from './table'; import { Table, TableSelectMode } from './table';
import { Button as ActionButton } from "./bootstrap-components"; import { Button } from "./bootstrap-components";
import brace from 'brace'; import brace from 'brace';
import AceEditor from 'react-ace'; import AceEditor from 'react-ace';
@ -498,57 +498,6 @@ class ButtonRow extends Component {
} }
} }
@withErrorHandling
class Button extends Component {
static propTypes = {
onClickAsync: PropTypes.func,
label: PropTypes.string,
icon: PropTypes.string,
className: PropTypes.string,
type: PropTypes.string
}
static contextTypes = {
formStateOwner: PropTypes.object.isRequired
}
@withAsyncErrorHandler
async onClick(evt) {
if (this.props.onClickAsync) {
evt.preventDefault();
this.context.formStateOwner.disableForm();
await this.props.onClickAsync(evt);
this.context.formStateOwner.enableForm();
}
}
render() {
const props = this.props;
let className = 'btn';
if (props.className) {
className = className + ' ' + props.className;
}
let type = props.type || 'button';
let icon;
if (props.icon) {
icon = <span className={'glyphicon glyphicon-' + props.icon}></span>
}
let iconSpacer;
if (props.icon && props.label) {
iconSpacer = ' ';
}
return (
<button type={type} className={className} onClick={::this.onClick}>{icon}{iconSpacer}{props.label}</button>
);
}
}
class TreeTableSelect extends Component { class TreeTableSelect extends Component {
static propTypes = { static propTypes = {
@ -670,7 +619,7 @@ class TableSelect extends Component {
<div className={`input-group ${styles.tableSelectDropdown}`}> <div className={`input-group ${styles.tableSelectDropdown}`}>
<input type="text" className="form-control" value={this.state.selectedLabel} readOnly onClick={::this.toggleOpen}/> <input type="text" className="form-control" value={this.state.selectedLabel} readOnly onClick={::this.toggleOpen}/>
<span className="input-group-btn"> <span className="input-group-btn">
<ActionButton label={t('Select')} className="btn-default" onClickAsync={::this.toggleOpen}/> <Button label={t('Select')} className="btn-default" onClickAsync={::this.toggleOpen}/>
</span> </span>
</div> </div>
<div className={styles.tableSelectTable + (this.state.open ? '' : ' ' + styles.tableSelectTableHidden)}> <div className={styles.tableSelectTable + (this.state.open ? '' : ' ' + styles.tableSelectTableHidden)}>

View file

@ -200,7 +200,7 @@ export default class CUD extends Component {
await this.formHandleChangedError(async () => await this.doSubmit(false)); await this.formHandleChangedError(async () => await this.doSubmit(false));
} }
async onRulesChanged(rulesTree) { onRulesChanged(rulesTree) {
// This assumes that !this.state.ruleOptionsVisible // This assumes that !this.state.ruleOptionsVisible
this.getFormValue('settings').rootRule.rules = this.getRulesFromTree(rulesTree); this.getFormValue('settings').rootRule.rules = this.getRulesFromTree(rulesTree);
@ -209,9 +209,7 @@ export default class CUD extends Component {
}) })
} }
async showRuleOptions(data) { showRuleOptions(rule) {
const rule = data.node.rule;
this.updateFormValue('selectedRule', rule); this.updateFormValue('selectedRule', rule);
this.setState({ this.setState({
@ -228,6 +226,17 @@ export default class CUD extends Component {
}); });
} }
onRuleSettingsPaneDelete() {
const selectedRule = this.getFormValue('selectedRule');
this.updateFormValue('selectedRule', null);
this.setState({
ruleOptionsVisible: false,
});
this.deleteRule(selectedRule);
}
onRuleSettingsPaneUpdated(hasErrors) { onRuleSettingsPaneUpdated(hasErrors) {
this.setState(previousState => ({ this.setState(previousState => ({
formState: previousState.formState.setIn(['data', 'selectedRule', 'error'], hasErrors) formState: previousState.formState.setIn(['data', 'selectedRule', 'error'], hasErrors)
@ -261,7 +270,7 @@ export default class CUD extends Component {
}); });
} }
async deleteRule(data) { deleteRule(ruleToDelete) {
let finishedSearching = false; let finishedSearching = false;
function childrenWithoutRule(rules) { function childrenWithoutRule(rules) {
@ -271,7 +280,7 @@ export default class CUD extends Component {
if (finishedSearching) { if (finishedSearching) {
newRules.push(rule); newRules.push(rule);
} else if (rule !== data.node.rule) { } else if (rule !== ruleToDelete) {
const newRule = Object.assign({}, rule); const newRule = Object.assign({}, rule);
if (rule.rules) { if (rule.rules) {
@ -288,15 +297,13 @@ export default class CUD extends Component {
return newRules; return newRules;
} }
if (!this.state.ruleOptionsVisible) { const rules = childrenWithoutRule(this.getFormValue('settings').rootRule.rules);
const rules = childrenWithoutRule(this.getFormValue('settings').rootRule.rules);
this.getFormValue('settings').rootRule.rules = rules; this.getFormValue('settings').rootRule.rules = rules;
this.setState({ this.setState({
rulesTree: this.getTreeFromRules(rules) rulesTree: this.getTreeFromRules(rules)
}); });
}
} }
@ -374,8 +381,8 @@ export default class CUD extends Component {
canDrop={ data => !data.nextParent || (ruleHelpers.isCompositeRuleType(data.nextParent.rule.type)) } canDrop={ data => !data.nextParent || (ruleHelpers.isCompositeRuleType(data.nextParent.rule.type)) }
generateNodeProps={data => ({ generateNodeProps={data => ({
buttons: [ buttons: [
<ActionLink onClickAsync={async () => await this.showRuleOptions(data)} className={styles.ruleActionLink}><Icon name="edit"/></ActionLink>, <ActionLink onClickAsync={async () => !this.state.ruleOptionsVisible && this.showRuleOptions(data.node.rule)} className={styles.ruleActionLink}><Icon name="edit"/></ActionLink>,
<ActionLink onClickAsync={async () => await this.deleteRule(data)} className={styles.ruleActionLink}><Icon name="remove"/></ActionLink> <ActionLink onClickAsync={async () => !this.state.ruleOptionsVisible && this.deleteRule(data.node.rule)} className={styles.ruleActionLink}><Icon name="remove"/></ActionLink>
] ]
})} })}
/> />
@ -392,7 +399,7 @@ export default class CUD extends Component {
<div className={styles.rightPane}> <div className={styles.rightPane}>
<div className={styles.rightPaneInner}> <div className={styles.rightPaneInner}>
{selectedRule && {selectedRule &&
<RuleSettingsPane rule={selectedRule} fields={this.props.fields} onChange={::this.onRuleSettingsPaneUpdated} onClose={::this.onRuleSettingsPaneClose} forceShowValidation={this.isFormValidationShown()}/>} <RuleSettingsPane rule={selectedRule} fields={this.props.fields} onChange={::this.onRuleSettingsPaneUpdated} onClose={::this.onRuleSettingsPaneClose} onDelete={::this.onRuleSettingsPaneDelete} forceShowValidation={this.isFormValidationShown()}/>}
</div> </div>
</div> </div>
</div> </div>

View file

@ -37,6 +37,7 @@ export default class CUD extends Component {
fields: PropTypes.array.isRequired, fields: PropTypes.array.isRequired,
onChange: PropTypes.func.isRequired, onChange: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired, onClose: PropTypes.func.isRequired,
onDelete: PropTypes.func.isRequired,
forceShowValidation: PropTypes.bool.isRequired forceShowValidation: PropTypes.bool.isRequired
} }
@ -158,6 +159,10 @@ export default class CUD extends Component {
} }
} }
async deleteRule() {
this.props.onDelete();
}
render() { render() {
const t = this.props.t; const t = this.props.t;
const rule = this.props.rule; const rule = this.props.rule;
@ -218,6 +223,7 @@ export default class CUD extends Component {
<ButtonRow> <ButtonRow>
<Button type="submit" className="btn-primary" icon="chevron-left" label={t('OK')}/> <Button type="submit" className="btn-primary" icon="chevron-left" label={t('OK')}/>
<Button className="btn-primary" icon="remove" label={t('Delete')} onClickAsync={::this.deleteRule}/>
</ButtonRow> </ButtonRow>
</Form> </Form>