Snapshot of incomplete DnD extension to tree.js.

It however is rather unintuitive how nodes can be put to the end. Dropping this direction in favor of https://github.com/fritz-c/react-sortable-tree
This commit is contained in:
Tomas Bures 2017-08-16 12:10:00 +02:00
parent 0bfb30817b
commit 6a7dab52eb
8 changed files with 999 additions and 135 deletions

View file

@ -37,7 +37,7 @@ class Form extends Component {
static propTypes = {
stateOwner: PropTypes.object.isRequired,
onSubmitAsync: PropTypes.func,
inline: PropTypes.bool
format: PropTypes.string
}
static childContextTypes = {
@ -70,6 +70,13 @@ class Form extends Component {
const statusMessageText = owner.getFormStatusMessageText();
const statusMessageSeverity = owner.getFormStatusMessageSeverity();
let formClass = 'form-horizontal';
if (props.format === 'wide') {
formClass = '';
} else if (props.format === 'inline') {
formClass = 'form-inline';
}
if (!owner.isFormReady()) {
if (owner.isFormWithLoadingNotice()) {
return <p className={`alert alert-info mt-form-status`} role="alert">{t('Loading ...')}</p>
@ -78,11 +85,15 @@ class Form extends Component {
}
} else {
return (
<form className={props.inline ? 'form-inline' : 'form-horizontal'} onSubmit={::this.onSubmit}>
<form className={formClass} onSubmit={::this.onSubmit}>
<fieldset disabled={owner.isFormDisabled()}>
{props.children}
</fieldset>
{statusMessageText && <p className={`col-sm-10 col-sm-offset-2 alert alert-${statusMessageSeverity} mt-form-status`} role="alert">{statusMessageText}</p>}
{statusMessageText &&
<AlignedRow htmlId="form-status-message">
<p className={`alert alert-${statusMessageSeverity} mt-form-status`} role="alert">{statusMessageText}</p>
</AlignedRow>
}
</form>
);
}
@ -106,27 +117,48 @@ class Fieldset extends Component {
}
}
function wrapInput(id, htmlId, owner, label, help, input, inline) {
function wrapInput(id, htmlId, owner, format, rightContainerClass, label, help, input) {
const className = id ? owner.addFormValidationClass('form-group', id) : 'form-group';
let colLeft = '';
let colRight = '';
let offsetRight = '';
switch (format) {
case 'wide':
colLeft = '';
colRight = '';
offsetRight = '';
break;
default:
colLeft = 'col-sm-2';
colRight = 'col-sm-10';
offsetRight = 'col-sm-offset-2';
break;
}
if (format === 'inline') {
}
let helpBlock = null;
if (help) {
helpBlock = <div className={'help-block' + (!inline ? ' col-sm-offset-2 col-sm-10' : '')}
id={htmlId + '_help'}>{help}</div>;
helpBlock = <div className={`help-block ${colRight} ${offsetRight}`} id={htmlId + '_help'}>{help}</div>;
}
let validationBlock = null;
if (id) {
const validationMsg = id && owner.getFormValidationMessage(id);
if (validationMsg) {
validationBlock = <div className={'help-block' + (!inline ? ' col-sm-offset-2 col-sm-10' : '')}
id={htmlId + '_help_validation'}>{validationMsg}</div>;
validationBlock = <div className={`help-block ${colRight} ${offsetRight}`} id={htmlId + '_help_validation'}>{validationMsg}</div>;
}
}
const labelBlock = <label htmlFor={htmlId} className="control-label">{label}</label>;
let labelBlock = null;
if (label) {
labelBlock = <label htmlFor={htmlId} className="control-label">{label}</label>;
}
if (inline) {
if (format === 'inline') {
return (
<div className={className} >
{labelBlock} &nbsp; {input}
@ -137,10 +169,10 @@ function wrapInput(id, htmlId, owner, label, help, input, inline) {
} else {
return (
<div className={className} >
<div className="col-sm-2">
<div className={colLeft}>
{labelBlock}
</div>
<div className="col-sm-10">
<div className={`${colRight} ${rightContainerClass}`}>
{input}
</div>
{helpBlock}
@ -150,30 +182,13 @@ function wrapInput(id, htmlId, owner, label, help, input, inline) {
}
}
function wrapInputWithText(id, htmlId, owner, containerClass, label, text, help, input) {
const helpBlock = help ? <div className="help-block col-sm-offset-2 col-sm-10" id={htmlId + '_help'}>{help}</div> : '';
const validationMsg = id && owner.getFormValidationMessage(id);
return (
<div className={id ? owner.addFormValidationClass('form-group', id) : 'form-group'} >
<div className="col-sm-2">
<label className="control-label">{label}</label>
</div>
<div className={"col-sm-10 " + containerClass }>
<label>{input} {text}</label>
</div>
{helpBlock}
{id && validationMsg && <div className="help-block col-sm-offset-2 col-sm-10" id={htmlId + '_help_validation'}>{validationMsg}</div>}
</div>
);
}
class StaticField extends Component {
static propTypes = {
id: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
help: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
className: PropTypes.string
className: PropTypes.string,
format: PropTypes.string
}
render() {
@ -187,7 +202,7 @@ class StaticField extends Component {
className += ' ' + props.className;
}
return wrapInput(null, htmlId, owner, props.label, props.help,
return wrapInput(null, htmlId, owner, props.format, '', props.label, props.help,
<div id={htmlId} className={className} aria-describedby={htmlId + '_help'}>{props.children}</div>
);
}
@ -199,7 +214,8 @@ class InputField extends Component {
label: PropTypes.string.isRequired,
placeholder: PropTypes.string,
type: PropTypes.string,
help: PropTypes.oneOfType([PropTypes.string, PropTypes.object])
help: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
format: PropTypes.string
}
static defaultProps = {
@ -221,7 +237,7 @@ class InputField extends Component {
type = 'password';
}
return wrapInput(id, htmlId, owner, props.label, props.help,
return wrapInput(id, htmlId, owner, props.format, '', props.label, props.help,
<input type={type} value={owner.getFormValue(id)} placeholder={props.placeholder} id={htmlId} className="form-control" aria-describedby={htmlId + '_help'} onChange={evt => owner.updateFormValue(id, evt.target.value)}/>
);
}
@ -232,7 +248,8 @@ class CheckBox extends Component {
id: PropTypes.string.isRequired,
text: PropTypes.string.isRequired,
label: PropTypes.string,
help: PropTypes.oneOfType([PropTypes.string, PropTypes.object])
help: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
format: PropTypes.string
}
static contextTypes = {
@ -245,8 +262,11 @@ class CheckBox extends Component {
const id = this.props.id;
const htmlId = 'form_' + id;
return wrapInputWithText(id, htmlId, owner, 'checkbox', props.label, props.text, props.help,
<input type="checkbox" checked={owner.getFormValue(id)} id={htmlId} aria-describedby={htmlId + '_help'} onChange={evt => owner.updateFormValue(id, !owner.getFormValue(id))}/>
return wrapInput(id, htmlId, owner, props.format, 'checkbox', props.label, props.help,
<label>
<input type="checkbox" checked={owner.getFormValue(id)} id={htmlId} aria-describedby={htmlId + '_help'} onChange={evt => owner.updateFormValue(id, !owner.getFormValue(id))}/>
{props.text}
</label>
);
}
}
@ -255,7 +275,8 @@ class TextArea extends Component {
static propTypes = {
id: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
help: PropTypes.oneOfType([PropTypes.string, PropTypes.object])
help: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
format: PropTypes.string
}
static contextTypes = {
@ -268,7 +289,7 @@ class TextArea extends Component {
const id = this.props.id;
const htmlId = 'form_' + id;
return wrapInput(id, htmlId, owner, props.label, props.help,
return wrapInput(id, htmlId, owner, props.format, '', props.label, props.help,
<textarea id={htmlId} value={owner.getFormValue(id)} className="form-control" aria-describedby={htmlId + '_help'} onChange={evt => owner.updateFormValue(id, evt.target.value)}></textarea>
);
}
@ -282,7 +303,7 @@ class Dropdown extends Component {
options: PropTypes.array,
optGroups: PropTypes.array,
className: PropTypes.string,
inline: PropTypes.bool
format: PropTypes.string
}
static contextTypes = {
@ -312,11 +333,10 @@ class Dropdown extends Component {
className += ' ' + props.className;
}
return wrapInput(id, htmlId, owner, props.label, props.help,
return wrapInput(id, htmlId, owner, props.format, '', props.label, props.help,
<select id={htmlId} className={className} aria-describedby={htmlId + '_help'} value={owner.getFormValue(id)} onChange={evt => owner.updateFormValue(id, evt.target.value)}>
{options}
</select>,
props.inline
</select>
);
}
}
@ -326,7 +346,12 @@ class AlignedRow extends Component {
static propTypes = {
className: PropTypes.string,
label: PropTypes.string,
htmlId: PropTypes.string
htmlId: PropTypes.string,
format: PropTypes.string
}
static contextTypes = {
formStateOwner: PropTypes.object.isRequired
}
static defaultProps = {
@ -334,33 +359,28 @@ class AlignedRow extends Component {
}
render() {
if (this.props.label) {
return (
<div className="form-group">
<label htmlFor={this.props.htmlId} className="col-sm-2 control-label">{this.props.label}</label>
<div className={"col-sm-10 " + this.props.className} id={this.props.htmlId}>
{this.props.children}
</div>
</div>
);
const props = this.props;
const owner = this.context.formStateOwner;
} else {
return (
<div className="form-group">
<div className={"col-sm-10 col-sm-offset-2 " + this.props.className} id={this.props.htmlId}>
{this.props.children}
</div>
</div>
);
}
return wrapInput(null, props.htmlId, owner, props.format, props.className, props.label, null, this.props.children);
}
}
class ButtonRow extends Component {
static propTypes = {
className: PropTypes.string,
format: PropTypes.string
}
render() {
let className = 'mt-button-row';
if (this.props.className) {
className += ' ' + this.props.className;
}
return (
<AlignedRow className="mt-button-row">{this.props.children}</AlignedRow>
<AlignedRow className={className} format={this.props.format}>{this.props.children}</AlignedRow>
);
}
}
@ -423,7 +443,8 @@ class TreeTableSelect extends Component {
label: PropTypes.string.isRequired,
dataUrl: PropTypes.string,
data: PropTypes.array,
help: PropTypes.oneOfType([PropTypes.string, PropTypes.object])
help: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
format: PropTypes.string
}
static contextTypes = {
@ -441,7 +462,7 @@ class TreeTableSelect extends Component {
const id = this.props.id;
const htmlId = 'form_' + id;
return wrapInput(id, htmlId, owner, props.label, props.help,
return wrapInput(id, htmlId, owner, props.format, '', props.label, props.help,
<TreeTable data={props.data} dataUrl={props.dataUrl} selectMode={TreeSelectMode.SINGLE} selection={owner.getFormValue(id)} onSelectionChangedAsync={::this.onSelectionChangedAsync}/>
);
}
@ -471,7 +492,8 @@ class TableSelect extends Component {
id: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
help: PropTypes.oneOfType([PropTypes.string, PropTypes.object])
help: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
format: PropTypes.string
}
static defaultProps = {
@ -530,7 +552,7 @@ class TableSelect extends Component {
const t = props.t;
if (props.dropdown) {
return wrapInput(id, htmlId, owner, props.label, props.help,
return wrapInput(id, htmlId, owner, props.format, '', props.label, props.help,
<div>
<div className="input-group mt-tableselect-dropdown">
<input type="text" className="form-control" value={this.state.selectedLabel} readOnly onClick={::this.toggleOpen}/>
@ -544,7 +566,7 @@ class TableSelect extends Component {
</div>
);
} else {
return wrapInput(id, htmlId, owner, props.label, props.help,
return wrapInput(id, htmlId, owner, props.format, '', props.label, props.help,
<div>
<div>
<Table ref={node => this.table = node} data={props.data} dataUrl={props.dataUrl} columns={props.columns} selectMode={props.selectMode} selectionAsArray={this.props.selectionAsArray} withHeader={props.withHeader} selection={owner.getFormValue(id)} onSelectionChangedAsync={::this.onSelectionChangedAsync}/>
@ -570,7 +592,8 @@ class ACEEditor extends Component {
label: PropTypes.string,
help: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
height: PropTypes.string,
mode: PropTypes.string
mode: PropTypes.string,
format: PropTypes.string
}
static contextTypes = {
@ -583,7 +606,7 @@ class ACEEditor extends Component {
const id = this.props.id;
const htmlId = 'form_' + id;
return wrapInput(id, htmlId, owner, props.label, props.help,
return wrapInput(id, htmlId, owner, props.format, '', props.label, props.help,
<AceEditor
id={htmlId}
mode={props.mode}

View file

@ -1,9 +1,50 @@
.mt-treetable-container .fancytree-container span.fancytree-node.mt-tree-end-drop {
height: 10px;
margin-top: 0px;
margin-bottom: -10px;
overflow: hidden;
min-height: 0px;
}
.mt-treetable-container .fancytree-container span.fancytree-node.mt-tree-end-drop span.fancytree-title {
width: 15px;
margin-left: 28px;
}
.mt-treetable-container .fancytree-container span.fancytree-node.mt-tree-end-drop.mt-tree-end-drop-wide span.fancytree-title {
width: 100%;
}
.mt-treetable-container .fancytree-container {
border: none;
}
.mt-treetable-container span.fancytree-expander {
color: #333333;
}
.mt-treetable-container.mt-treetable-inactivable>table.fancytree-ext-table.fancytree-container>tbody>tr.fancytree-active>td,
.mt-treetable-container.mt-treetable-inactivable>table.fancytree-ext-table.fancytree-container>tbody>tr.fancytree-active:hover>td {
.mt-treetable-container.mt-treetable-inactivable>table.fancytree-ext-table.fancytree-container>tbody>tr.fancytree-active:hover>td,
.mt-treetable-container.mt-treetable-inactivable .fancytree-container span.fancytree-node.fancytree-active span.fancytree-title,
.mt-treetable-container.mt-treetable-inactivable .fancytree-container span.fancytree-node.fancytree-active span.fancytree-title:hover,
.mt-treetable-container.mt-treetable-inactivable .fancytree-container span.fancytree-node.fancytree-active:hover span.fancytree-title,
.mt-treetable-container.mt-treetable-inactivable .fancytree-container span.fancytree-node span.fancytree-title:hover {
background-color: transparent;
}
.mt-treetable-container.mt-treetable-inactivable>table.fancytree-ext-table.fancytree-container>tbody>tr.fancytree-active>td span.fancytree-title {
.mt-treetable-container.mt-treetable-inactivable .fancytree-container span.fancytree-node span.fancytree-title {
cursor: default;
}
.mt-treetable-container.mt-treetable-inactivable .fancytree-container span.fancytree-node.fancytree-active span.fancytree-title,
.mt-treetable-container.mt-treetable-inactivable .fancytree-container span.fancytree-node.fancytree-active span.fancytree-title:hover {
border-color: transparent;
}
.mt-treetable-container.mt-treetable-inactivable>table.fancytree-ext-table.fancytree-container>tbody>tr.fancytree-active>td span.fancytree-title,
.mt-treetable-container.mt-treetable-inactivable>table.fancytree-ext-table.fancytree-container>tbody>tr.fancytree-active>td span.fancytree-expander,
.mt-treetable-container.mt-treetable-inactivable .fancytree-container span.fancytree-node.fancytree-active span.fancytree-title {
outline: 0px none;
color: #333333;
}
@ -28,6 +69,33 @@
min-width: 150px;
}
.mt-treetable-container span.fancytree-node.fancytree-drag-source {
background-color: transparent !important;
}
.mt-treetable-container #fancytree-drop-marker {
background-image: url("../../public/fancytree/skin-bootstrap/icons.gif");
height: 12px;
}
.mt-treetable-container #fancytree-drop-marker.fancytree-drop-over {
background-position: 0px -130px;
width: 22px;
}
.mt-treetable-container #fancytree-drop-marker.fancytree-drop-after, .mt-treetable-container #fancytree-drop-marker.fancytree-drop-before {
background-position: 0px -145px;
width: 64px;
}
.mt-treetable-container span.fancytree-node.fancytree-drop-accept fancytree-expander {
visibility: hidden;
}
.form-group .mt-treetable-container {
border: 1px solid #cccccc;
border-radius: 4px;
@ -49,3 +117,4 @@
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,0.075);
box-shadow: inset 0 1px 1px rgba(0,0,0,0.075);
}

View file

@ -69,7 +69,10 @@ class TreeTable extends Component {
onSelectionChangedAsync: PropTypes.func,
actions: PropTypes.func,
withHeader: PropTypes.bool,
withDescription: PropTypes.bool
withDescription: PropTypes.bool,
noTable: PropTypes.bool,
withDnd: PropTypes.bool,
withIcons: PropTypes.bool
}
componentWillReceiveProps(nextProps) {
@ -106,17 +109,6 @@ class TreeTable extends Component {
this.loadData(this.props.dataUrl);
}
const glyphOpts = {
map: {
expanderClosed: 'glyphicon glyphicon-menu-right',
expanderLazy: 'glyphicon glyphicon-menu-right', // glyphicon-plus-sign
expanderOpen: 'glyphicon glyphicon-menu-down', // glyphicon-collapse-down
checkbox: 'glyphicon glyphicon-unchecked',
checkboxSelected: 'glyphicon glyphicon-check',
checkboxUnknown: 'glyphicon glyphicon-share',
}
};
let createNodeFn;
createNodeFn = (event, data) => {
const node = data.node;
@ -148,22 +140,70 @@ class TreeTable extends Component {
}
};
this.tree = jQuery(this.domTable).fancytree({
extensions: ['glyph', 'table'],
glyph: glyphOpts,
const treeOpts = {
extensions: ['glyph'],
glyph: {
map: {
expanderClosed: 'glyphicon glyphicon-menu-right',
expanderLazy: 'glyphicon glyphicon-menu-right', // glyphicon-plus-sign
expanderOpen: 'glyphicon glyphicon-menu-down', // glyphicon-collapse-down
checkbox: 'glyphicon glyphicon-unchecked',
checkboxSelected: 'glyphicon glyphicon-check',
checkboxUnknown: 'glyphicon glyphicon-share',
folder: 'glyphicon glyphicon-folder-close',
folderOpen: 'glyphicon glyphicon-folder-open',
doc: 'glyphicon glyphicon-file',
docOpen: 'glyphicon glyphicon-file'
}
},
selectMode: (this.selectMode === TreeSelectMode.MULTI ? 2 : 1),
icon: false,
icon: !!this.props.withIcons,
autoScroll: true,
scrollParent: jQuery(this.domTableContainer),
source: this.sanitizeTreeData(this.state.treeData),
table: {
nodeColumnIdx: 0
},
toggleEffect: false,
createNode: createNodeFn,
checkbox: this.selectMode === TreeSelectMode.MULTI,
activate: (this.selectMode === TreeSelectMode.SINGLE ? ::this.onActivate : null),
select: (this.selectMode === TreeSelectMode.MULTI ? ::this.onSelect : null)
}).fancytree("getTree");
select: (this.selectMode === TreeSelectMode.MULTI ? ::this.onSelect : null),
};
if (!this.props.noTable) {
treeOpts.extensions.push('table');
treeOpts.table = {
nodeColumnIdx: 0
};
}
if (this.props.withDnd) {
treeOpts.extensions.push('dnd');
treeOpts.dnd = {
autoExpandMS: 400,
focusOnClick: true,
preventVoidMoves: true,
preventRecursiveMoves: true,
dropMarkerOffsetX: -46, // -22
dropMarkerInsertOffsetX: 0,
dragStart: (node, data) => {
return node.key !== '__mt-tree-end-drop__';
},
dragEnter: (node, data) => {
if (node.folder) {
return ['before', 'over'];
} else {
return ['before'];
}
},
dragDrop: (node, data) => {
console.log(node);
console.log(data);
data.otherNode.moveTo(node, data.hitMode);
}
};
}
this.tree = jQuery(this.domTable).fancytree(treeOpts).fancytree("getTree");
this.updateSelection();
}
@ -252,6 +292,10 @@ class TreeTable extends Component {
let containerClass = 'mt-treetable-container';
if (this.selectMode === TreeSelectMode.NONE) {
containerClass += ' mt-treetable-inactivable';
} else {
if (!props.noTable) {
containerClass += ' table-hover';
}
}
if (!this.withHeader) {
@ -260,31 +304,44 @@ class TreeTable extends Component {
// FIXME: style={{ height: '100px', overflow: 'auto'}}
const container =
<div className={containerClass} ref={(domElem) => { this.domTableContainer = domElem; }} >
<table ref={(domElem) => { this.domTable = domElem; }} className="table table-hover table-striped table-condensed">
{props.withHeader &&
<thead>
<tr>
<th className="mt-treetable-title">{t('Name')}</th>
{withDescription && <th>{t('Description')}</th>}
{actions && <th></th>}
</tr>
</thead>
}
<tbody>
<tr>
<td></td>
{withDescription && <td></td>}
{actions && <td></td>}
</tr>
</tbody>
</table>
</div>;
if (props.noTable) {
return (
<div className={containerClass} ref={(domElem) => { this.domTableContainer = domElem; }} >
<div ref={(domElem) => { this.domTable = domElem; }}>
</div>
</div>
);
} else {
let tableClass = 'table table-striped table-condensed';
if (this.selectMode !== TreeSelectMode.NONE) {
tableClass += ' table-hover';
}
return (
<div className={containerClass} ref={(domElem) => { this.domTableContainer = domElem; }} >
<table ref={(domElem) => { this.domTable = domElem; }} className={tableClass}>
{props.withHeader &&
<thead>
<tr>
<th className="mt-treetable-title">{t('Name')}</th>
{withDescription && <th>{t('Description')}</th>}
{actions && <th></th>}
</tr>
</thead>
}
<tbody>
<tr>
<td></td>
{withDescription && <td></td>}
{actions && <td></td>}
</tr>
</tbody>
</table>
</div>
);
}
return (
container
);
}
}

View file

@ -3,14 +3,14 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { translate, Trans } from 'react-i18next';
import {requiresAuthenticatedUser, withPageHelpers, Title, NavButton} from '../../lib/page';
import {requiresAuthenticatedUser, withPageHelpers, Title, NavButton, Toolbar} from '../../lib/page';
import {
withForm, Form, FormSendMethod, InputField, ButtonRow, Button
withForm, Form, FormSendMethod, InputField, ButtonRow, Button, Fieldset
} from '../../lib/form';
import { withErrorHandling, withAsyncErrorHandler } from '../../lib/error-handling';
import {DeleteModalDialog} from "../../lib/delete";
import interoperableErrors from '../../../../shared/interoperable-errors';
import {TreeTable} from "../../lib/tree";
import {TreeSelectMode, TreeTable} from "../../lib/tree";
@translate()
@withForm
@ -100,57 +100,131 @@ export default class CUD extends Component {
}
}
async onRuleSelectionChangedAsync(sel) {
this.setState({
selectedRule: sel
});
}
render() {
const t = this.props.t;
const isEdit = !!this.props.entity;
const treeEnd = {
key: '__mt-tree-end-drop__',
icon: false,
unselectable: true,
extraClasses: 'mt-tree-end-drop',
beforeActivate: () => false
};
const treeEndWide = { // This one is used after a non-folder sibling that has no children
key: '__mt-tree-end-drop__',
icon: false,
unselectable: true,
extraClasses: 'mt-tree-end-drop mt-tree-end-drop-wide',
beforeActivate: () => false
}
const sampleTreeData = [
{
key: 'a',
title: 'A',
expanded: true,
folder: true,
children: [
{
key: 'aa',
title: 'AA',
expanded: true,
folder: true,
children: [
{
key: 'aaa',
title: 'AAA',
expanded: true
},
{
key: 'aab',
title: 'AAB',
expanded: true
}
},
{
key: 'aab',
title: 'AAB',
folder: true
},
treeEnd
]
},
{
key: 'ab',
title: 'AB',
expanded: true,
folder: true,
children: [
{
key: 'aba',
title: 'ABA',
expanded: true
title: 'ABA'
},
{
key: 'abb',
title: 'ABB',
expanded: true
}
title: 'ABB'
},
treeEndWide
]
},
treeEnd
]
}
},
{
key: 'b',
title: 'B',
expanded: true,
folder: true,
children: [
{
key: 'ba',
title: 'BA',
expanded: true,
folder: true,
children: [
{
key: 'baa',
title: 'BAA'
},
{
key: 'bab',
title: 'BAB'
},
treeEndWide
]
},
{
key: 'bb',
title: 'BB',
expanded: true,
folder: true,
children: [
{
key: 'bba',
title: 'BBA'
},
{
key: 'bbb',
title: 'BBB'
},
treeEndWide
]
},
treeEnd
]
},
treeEnd
];
return (
<div>
{isEdit &&
<DeleteModalDialog
@ -165,17 +239,28 @@ export default class CUD extends Component {
<Title>{isEdit ? t('Edit Segment') : t('Create Segment')}</Title>
<Form stateOwner={this} onSubmitAsync={::this.submitHandler}>
<InputField id="name" label={t('Name')}/>
<ButtonRow>
<Form stateOwner={this} onSubmitAsync={::this.submitHandler} format="wide">
<ButtonRow format="wide" className="pull-right">
<Button type="submit" className="btn-primary" icon="ok" label={t('Save')}/>
{isEdit && <NavButton className="btn-danger" icon="remove" label={t('Delete')} linkTo={`/lists/fields/${this.props.list.id}/${this.props.entity.id}/delete`}/>}
</ButtonRow>
<h3>{t('Segment Options')}</h3>
<InputField id="name" label={t('Name')} format="wide"/>
<hr />
<TreeTable data={sampleTreeData} />
<div className="row">
<div className="col-sm-6">
<TreeTable data={sampleTreeData} noTable withIcons withDnd format="wide" selectMode={TreeSelectMode.SINGLE} selection={this.state.selectedRule} onSelectionChangedAsync={::this.onRuleSelectionChangedAsync} />
</div>
<div className="col-sm-6">
<h3>{t('Selected Rule Options')}</h3>
<InputField id="name" label={t('Name')} format="wide" />
</div>
</div>
</Form>
</div>
);

View file

@ -110,7 +110,7 @@ export default class List extends Component {
<div className="well well-sm">
<Form inline stateOwner={this}>
<Dropdown inline className="input-sm" id="segment" label={t('Segment')} options={this.state.segmentOptions}/>
<Dropdown format="inline" className="input-sm" id="segment" label={t('Segment')} options={this.state.segmentOptions}/>
</Form>
</div>