Stubs for adding and deleting a rule

This commit is contained in:
Tomas Bures 2017-08-16 21:41:36 +02:00
parent e5cf2962dc
commit 6fbbe9a497
4 changed files with 117 additions and 25 deletions

View file

@ -45,6 +45,8 @@
"css-loader": "^0.28.4", "css-loader": "^0.28.4",
"i18next-conv": "^3.0.3", "i18next-conv": "^3.0.3",
"node-sass": "^4.5.3", "node-sass": "^4.5.3",
"react-dnd-html5-backend": "^2.4.1",
"react-dnd-touch-backend": "^0.3.13",
"sass-loader": "^6.0.6", "sass-loader": "^6.0.6",
"style-loader": "^0.18.2", "style-loader": "^0.18.2",
"url-loader": "^0.5.9", "url-loader": "^0.5.9",

View file

@ -12,11 +12,16 @@ import {DeleteModalDialog} from "../../lib/delete";
import interoperableErrors from '../../../../shared/interoperable-errors'; import interoperableErrors from '../../../../shared/interoperable-errors';
import styles from './CUD.scss'; import styles from './CUD.scss';
import { DragDropContext } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
import TouchBackend from 'react-dnd-touch-backend';
import SortableTree from 'react-sortable-tree'; import SortableTree from 'react-sortable-tree';
import {ActionLink, Icon} from "../../lib/bootstrap-components"; import {ActionLink, Icon} from "../../lib/bootstrap-components";
console.log(styles); // https://stackoverflow.com/a/4819886/1601953
const isTouchDevice = !!('ontouchstart' in window || navigator.maxTouchPoints);
@DragDropContext(isTouchDevice ? TouchBackend : HTML5Backend)
@translate() @translate()
@withForm @withForm
@withPageHelpers @withPageHelpers
@ -28,6 +33,7 @@ export default class CUD extends Component {
this.compoundRuleTypes = [ 'all', 'some', 'one', 'none' ]; this.compoundRuleTypes = [ 'all', 'some', 'one', 'none' ];
/*
const allRule = { const allRule = {
type: 'all' type: 'all'
}; };
@ -69,11 +75,11 @@ export default class CUD extends Component {
] ]
} }
]; ];
*/
this.state = { this.state = {
rules: sampleRules, rules: [],
rulesTree: this.getTreeFromRules(sampleRules) rulesTree: this.getTreeFromRules([])
}; };
this.initForm(); this.initForm();
@ -89,7 +95,7 @@ export default class CUD extends Component {
getRulesFromTree(tree) { getRulesFromTree(tree) {
const rules = []; const rules = [];
for (const node of tree) { for (const node of tree) {
const rule = Object.assign({}, node.rule); const rule = node.rule;
rule.rules = this.getRulesFromTree(node.children); rule.rules = this.getRulesFromTree(node.children);
rules.push(rule); rules.push(rule);
} }
@ -185,16 +191,49 @@ export default class CUD extends Component {
} }
async onRuleDelete(data) { async onRuleDelete(data) {
console.log(data); let finishedSearching = false;
function childrenWithoutRule(rules) {
console.log(rules);
const newRules = [];
for (const rule of rules) {
if (finishedSearching) {
newRules.push(rule);
} else if (rule !== data.node.rule) {
const newRule = Object.assign({}, rule);
if (rule.rules) {
newRule.rules = childrenWithoutRule(rule.rules);
}
newRules.push(newRule);
} else {
finishedSearching = true;
}
}
return newRules;
}
const rules = childrenWithoutRule(this.state.rules);
console.log(rules);
this.setState({
rules,
rulesTree: this.getTreeFromRules(rules)
});
} }
async onRuleOptions(data) { async showRuleOptions(data) {
this.setState({ this.setState({
ruleOptionsVisible: true ruleOptionsVisible: true
}); });
} }
async onRuleTree() { async hideRuleOptions() {
this.setState({ this.setState({
ruleOptionsVisible: false ruleOptionsVisible: false
}); });
@ -207,6 +246,28 @@ export default class CUD extends Component {
}) })
} }
_addRule(type) {
const rules = this.state.rules;
rules.push({
type,
rules: []
});
this.setState({
rules,
rulesTree: this.getTreeFromRules(rules)
});
}
async addCompositeRule() {
this._addRule('all');
}
async addRule() {
this._addRule('eq');
}
render() { render() {
const t = this.props.t; const t = this.props.t;
const isEdit = !!this.props.entity; const isEdit = !!this.props.entity;
@ -251,18 +312,31 @@ export default class CUD extends Component {
<div className={styles.rulePane + ruleOptionsVisibilityClass}> <div className={styles.rulePane + ruleOptionsVisibilityClass}>
<div className={styles.leftPane}> <div className={styles.leftPane}>
<SortableTree <div className={styles.leftPaneInner}>
treeData={this.state.rulesTree} <Toolbar>
onChange={rulesTree => this.onRulesChanged(rulesTree)} <Button className="btn-primary" label={t('Add Composite Rule')} onClickAsync={::this.addCompositeRule}/>
isVirtualized={false} <Button className="btn-primary" label={t('Add Rule')} onClickAsync={::this.addRule}/>
canDrop={ data => !data.nextParent || this.compoundRuleTypes.includes(data.nextParent.rule.type) } </Toolbar>
generateNodeProps={data => ({
buttons: [ <h3>{t('Rules')}</h3>
<ActionLink onClickAsync={async () => await this.onRuleOptions(data)} className={styles.ruleActionLink}><Icon name="edit"/></ActionLink>,
<ActionLink onClickAsync={async () => await this.onRuleDelete(data)} className={styles.ruleActionLink}><Icon name="remove"/></ActionLink> <div className="clearfix"/>
]
})} <div className={styles.ruleTree}>
/> <SortableTree
treeData={this.state.rulesTree}
onChange={rulesTree => this.onRulesChanged(rulesTree)}
isVirtualized={false}
canDrop={ data => !data.nextParent || this.compoundRuleTypes.includes(data.nextParent.rule.type) }
generateNodeProps={data => ({
buttons: [
<ActionLink onClickAsync={async () => await this.showRuleOptions(data)} className={styles.ruleActionLink}><Icon name="edit"/></ActionLink>,
<ActionLink onClickAsync={async () => await this.onRuleDelete(data)} className={styles.ruleActionLink}><Icon name="remove"/></ActionLink>
]
})}
/>
</div>
</div>
<div className={styles.leftPaneOverlay} /> <div className={styles.leftPaneOverlay} />
@ -272,13 +346,13 @@ export default class CUD extends Component {
</div> </div>
<div className={styles.rightPane}> <div className={styles.rightPane}>
<div className={styles.rulePaneRightInner}> <div className={styles.rightPaneInner}>
<div className={styles.ruleOptions}> <div className={styles.ruleOptions}>
<h3>{t('Rule Options')}</h3> <h3>{t('Rule Options')}</h3>
<InputField id="name" label={t('Name')}/> <InputField id="name" label={t('Name')}/>
<ButtonRow> <ButtonRow>
<Button className="btn-primary" icon="chevron-left" label={t('Back')} onClickAsync={::this.onRuleTree}/> <Button className="btn-primary" icon="chevron-left" label={t('Back')} onClickAsync={::this.hideRuleOptions}/>
</ButtonRow> </ButtonRow>
</div> </div>
</div> </div>

View file

@ -21,7 +21,23 @@ $desktopAnimationStartPosition: 300px;
.leftPane { .leftPane {
display: inline-block; display: inline-block;
width: 0px; width: 100%;
margin-right: -100%;
.leftPaneInner {
.ruleTree {
background: #fbfbfb;
border: #cfcfcf 1px solid;
border-radius: 3px;
padding: 10px 0px;
margin-top: 15px;
margin-bottom: 30px;
// Without this, the placeholders when rearranging the tree are not shown
position: relative;
z-index: 0;
}
}
.leftPaneOverlay { .leftPaneOverlay {
display: none; display: none;
@ -81,7 +97,7 @@ $desktopAnimationStartPosition: 300px;
opacity: 0; opacity: 0;
visibility: hidden; visibility: hidden;
.rulePaneRightInner { .rightPaneInner {
margin-right: $mobileLeftPaneResidualWidth; margin-right: $mobileLeftPaneResidualWidth;
@media (min-width: $desktopMinWidth) { @media (min-width: $desktopMinWidth) {
margin-right: $desktopLeftPaneResidualWidth; margin-right: $desktopLeftPaneResidualWidth;

View file

@ -18,7 +18,7 @@ module.exports = {
rules: [ rules: [
{ {
test: /\.(js|jsx)$/, test: /\.(js|jsx)$/,
exclude: /(disposables)/ /* https://github.com/react-dnd/react-dnd/issues/407 */, exclude: /(disposables|react-dnd-touch-backend)/ /* https://github.com/react-dnd/react-dnd/issues/407 */,
use: [ 'babel-loader' ] use: [ 'babel-loader' ]
}, },
{ {