Theming for Segment options

This commit is contained in:
Tomas Bures 2017-08-16 20:48:51 +02:00
parent baf9f61465
commit e5cf2962dc
10 changed files with 1822 additions and 671 deletions

View file

@ -32,6 +32,19 @@ class DismissibleAlert extends Component {
}
}
class Icon extends Component {
static propTypes = {
name: PropTypes.string,
className: PropTypes.string
}
render() {
const props = this.props;
return <span className={'glyphicon glyphicon-' + props.name + (props.className ? ' ' + props.className : '')}></span>;
}
}
@withErrorHandling
class Button extends Component {
static propTypes = {
@ -59,7 +72,7 @@ class Button extends Component {
let icon;
if (props.icon) {
icon = <span className={'glyphicon glyphicon-' + props.icon}></span>
icon = <Icon name={props.icon}/>
}
let iconSpacer;
@ -240,5 +253,6 @@ export {
DropdownMenu,
ActionLink,
DismissibleAlert,
ModalDialog
ModalDialog,
Icon
};

View file

@ -11,7 +11,6 @@ import 'datatables.net';
import 'datatables.net-bs';
import 'datatables.net-bs/css/dataTables.bootstrap.css';
import './table.css';
import axios from './axios';
import { withPageHelpers } from '../lib/page'

View file

@ -11,8 +11,11 @@ import { withErrorHandling, withAsyncErrorHandler } from '../../lib/error-handli
import {DeleteModalDialog} from "../../lib/delete";
import interoperableErrors from '../../../../shared/interoperable-errors';
import styles from './CUD.scss';
import SortableTree from 'react-sortable-tree';
import { getRuleTreeNodeRenderer } from './RuleTreeNodeRenderer';
import {ActionLink, Icon} from "../../lib/bootstrap-components";
console.log(styles);
@translate()
@withForm
@ -23,7 +26,7 @@ export default class CUD extends Component {
constructor(props) {
super(props);
this.compoundRuleTypes = [ 'all', 'some', 'none' ];
this.compoundRuleTypes = [ 'all', 'some', 'one', 'none' ];
const allRule = {
type: 'all'
@ -33,99 +36,44 @@ export default class CUD extends Component {
type: 'eq'
};
const sampleRules = [
{
type: 'all',
rules: [
{
type: 'some',
rules: [
{
type: 'eq',
value: 11
},
{
type: 'eq',
value: 9
}
]
},
{
type: 'some',
rules: [
{
type: 'eq',
value: 3
},
{
type: 'eq',
value: 7
}
]
}
]
}
];
this.state = {
rules: [
{
key: 'a',
title: 'A',
expanded: true,
rule: allRule,
children: [
{
key: 'aa',
title: 'AA',
expanded: true,
rule: allRule,
children: [
{
key: 'aaa',
title:
<div><h4>sdfsdf</h4><div>xxx</div><div>yyy<NavButton label="ZZZ" linkTo="/lists"/></div></div>,
rule: otherRule
},
{
key: 'aab',
title: 'AAB',
subtitle: 'sdfwere',
rule: otherRule
}
]
},
{
key: 'ab',
title: 'AB',
expanded: true,
rule: allRule,
children: [
{
key: 'aba',
title: 'ABA',
rule: otherRule
},
{
key: 'abb',
title: 'ABB',
rule: otherRule
}
]
}
]
},
{
key: 'b',
title: 'B',
expanded: true,
rule: allRule,
children: [
{
key: 'ba',
title: 'BA',
expanded: true,
rule: allRule,
children: [
{
key: 'baa',
title: 'BAA',
rule: otherRule
},
{
key: 'bab',
title: 'BAB',
rule: otherRule
}
]
},
{
key: 'bb',
title: 'BB',
expanded: true,
rule: allRule,
children: [
{
key: 'bba',
title: 'BBA',
rule: otherRule
},
{
key: 'bbb',
title: 'BBB',
rule: otherRule
}
]
}
]
}
]
rules: sampleRules,
rulesTree: this.getTreeFromRules(sampleRules)
};
this.initForm();
@ -138,6 +86,37 @@ export default class CUD extends Component {
entity: PropTypes.object
}
getRulesFromTree(tree) {
const rules = [];
for (const node of tree) {
const rule = Object.assign({}, node.rule);
rule.rules = this.getRulesFromTree(node.children);
rules.push(rule);
}
return rules;
}
getTreeFromRules(rules) {
const tree = [];
for (const rule of rules) {
let title, subtitle;
title = rule.type; // FIXME
subtitle = null;
tree.push({
rule,
title,
subtitle,
expanded: true,
children: this.getTreeFromRules(rule.rules || [])
});
}
return tree;
}
componentDidMount() {
if (this.props.entity) {
this.getFormValuesFromEntity(this.props.entity, data => {
@ -205,16 +184,42 @@ export default class CUD extends Component {
}
}
onRuleSelectionClick(data) {
async onRuleDelete(data) {
console.log(data);
}
async onRuleOptions(data) {
this.setState({
selectedRule: data.node.key
ruleOptionsVisible: true
});
}
async onRuleTree() {
this.setState({
ruleOptionsVisible: false
});
}
async onRulesChanged(rulesTree) {
this.setState({
rulesTree,
rules: this.getRulesFromTree(rulesTree)
})
}
render() {
const t = this.props.t;
const isEdit = !!this.props.entity;
let ruleOptionsVisibilityClass = '';
if ('ruleOptionsVisible' in this.state) {
if (this.state.ruleOptionsVisible) {
ruleOptionsVisibilityClass = ' ' + styles.ruleOptionsVisible;
} else {
ruleOptionsVisibilityClass = ' ' + styles.ruleOptionsHidden;
}
}
return (
<div>
@ -231,35 +236,52 @@ export default class CUD extends Component {
<Title>{isEdit ? t('Edit Segment') : t('Create Segment')}</Title>
<Form stateOwner={this} onSubmitAsync={::this.submitHandler} format="wide">
<ButtonRow format="wide" className="pull-right">
<Form stateOwner={this} onSubmitAsync={::this.submitHandler}>
<ButtonRow format="wide" className={`col-xs-12 ${styles.toolbar}`}>
<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"/>
<InputField id="name" label={t('Name')}/>
<hr />
<div className="row">
<div className="col-md-6" >
<div className={styles.rulePane + ruleOptionsVisibilityClass}>
<div className={styles.leftPane}>
<SortableTree
treeData={this.state.rules}
onChange={ rules => this.setState({rules}) }
treeData={this.state.rulesTree}
onChange={rulesTree => this.onRulesChanged(rulesTree)}
isVirtualized={false}
nodeContentRenderer={getRuleTreeNodeRenderer({
onClick: ::this.onRuleSelectionClick,
isSelected: data => data.node.key === this.state.selectedRule
canDrop={ data => !data.nextParent || this.compoundRuleTypes.includes(data.nextParent.rule.type) }
generateNodeProps={data => ({
buttons: [
<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>
]
})}
canDrop={data => data.nextParent && this.compoundRuleTypes.includes(data.nextParent.rule.type)}
/>
<div className={styles.leftPaneOverlay} />
<div className={styles.paneDivider}>
<div className={styles.paneDividerSolidBackground}/>
</div>
</div>
<div className="col-md-6">
<h3>{t('Selected Rule Options')}</h3>
<InputField id="name" label={t('Name')} format="wide" />
<div className={styles.rightPane}>
<div className={styles.rulePaneRightInner}>
<div className={styles.ruleOptions}>
<h3>{t('Rule Options')}</h3>
<InputField id="name" label={t('Name')}/>
<ButtonRow>
<Button className="btn-primary" icon="chevron-left" label={t('Back')} onClickAsync={::this.onRuleTree}/>
</ButtonRow>
</div>
</div>
</div>
</div>
</Form>

View file

@ -0,0 +1,134 @@
$desktopMinWidth: 768px;
$mobileLeftPaneResidualWidth: 0px;
$mobileAnimationStartPosition: 100px;
$desktopLeftPaneResidualWidth: 200px;
$desktopAnimationStartPosition: 300px;
.toolbar {
text-align: right;
}
.ruleActionLink {
padding-right: 5px;
}
.rulePane {
position: relative;
width: 100%;
overflow: hidden;
.leftPane {
display: inline-block;
width: 0px;
.leftPaneOverlay {
display: none;
position: absolute;
left: 0px;
top: 0px;
height: 100%;
z-index: 1;
width: $mobileLeftPaneResidualWidth;
@media (min-width: $desktopMinWidth) {
width: $desktopLeftPaneResidualWidth;
}
}
.paneDivider {
display: block;
position: absolute;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
background: url('./divider.png') repeat-y;
transform: translateX($mobileAnimationStartPosition);
@media (min-width: $desktopMinWidth) {
transform: translateX($desktopAnimationStartPosition);
}
padding-left: 50px;
z-index: 1;
opacity: 0;
visibility: hidden;
.paneDividerSolidBackground {
position: absolute;
width: 100%;
height: 100%;
background: white;
}
}
}
.rightPane {
display: inline-block;
width: 100%;
vertical-align: top;
z-index: 2;
position: relative;
transform: translateX($mobileAnimationStartPosition);
@media (min-width: $desktopMinWidth) {
transform: translateX($desktopAnimationStartPosition);
}
opacity: 0;
visibility: hidden;
.rulePaneRightInner {
margin-right: $mobileLeftPaneResidualWidth;
@media (min-width: $desktopMinWidth) {
margin-right: $desktopLeftPaneResidualWidth;
}
.ruleOptions {
margin-left: 60px;
}
}
}
&.ruleOptionsVisible {
.leftPaneOverlay {
display: block;
}
.paneDivider {
transition: transform 300ms ease-out, opacity 100ms ease-out;
opacity: 1;
visibility: visible;
transform: translateX($mobileLeftPaneResidualWidth);
@media (min-width: $desktopMinWidth) {
transform: translateX($desktopLeftPaneResidualWidth);
}
}
.rightPane {
transition: transform 300ms ease-out, opacity 100ms ease-out;
opacity: 1;
visibility: visible;
transform: translateX($mobileLeftPaneResidualWidth);
@media (min-width: $desktopMinWidth) {
transform: translateX($desktopLeftPaneResidualWidth);
}
}
}
&.ruleOptionsHidden {
.paneDivider {
transition: visibility 0s linear 300ms, transform 300ms ease-in, opacity 100ms ease-in 200ms;
}
.rightPane {
transition: visibility 0s linear 300ms, transform 300ms ease-in, opacity 100ms ease-in 200ms;
}
}
}

View file

@ -1,252 +0,0 @@
"use strict";
// Taken and adapted from https://github.com/fritz-c/react-sortable-tree/blob/cbca55b9c9800a114fa2749866fd057fc1eaeb9c/src/node-renderer-default.js
// It adds the onClick listener to .rowContents and wraps the whole class to a function to allow parameterization by the onClickHandler
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import baseStyles from './rule-tree.scss';
function getIEVersion() {
const match = navigator.userAgent.match(/(?:MSIE |Trident\/.*; rv:)(\d+)/);
return match ? parseInt(match[1], 10) : undefined;
}
function isDescendant(older, younger) {
return (
!!older.children &&
typeof older.children !== 'function' &&
older.children.some(
child => child === younger || isDescendant(child, younger)
)
);
}
let styles = baseStyles;
// Add extra classes in browsers that don't support flex
if (getIEVersion < 10) {
styles = {
...baseStyles,
row: `${styles.row} ${styles.row_NoFlex}`,
rowContents: `${styles.rowContents} ${styles.rowContents_NoFlex}`,
rowLabel: `${styles.rowLabel} ${styles.rowLabel_NoFlex}`,
rowToolbar: `${styles.rowToolbar} ${styles.rowToolbar_NoFlex}`,
};
}
export function getRuleTreeNodeRenderer(options) {
class RuleTreeNodeRenderer extends Component {
render() {
const {
scaffoldBlockPxWidth,
toggleChildrenVisibility,
connectDragPreview,
connectDragSource,
isDragging,
canDrop,
canDrag,
node,
title,
subtitle,
draggedNode,
path,
treeIndex,
isSearchMatch,
isSearchFocus,
buttons,
className,
style,
didDrop,
isOver, // Not needed, but preserved for other renderers
parentNode, // Needed for dndManager
...otherProps
} = this.props;
const nodeTitle = title || node.title;
const nodeSubtitle = subtitle || node.subtitle;
let handle;
if (canDrag) {
if (typeof node.children === 'function' && node.expanded) {
// Show a loading symbol on the handle when the children are expanded
// and yet still defined by a function (a callback to fetch the children)
handle = (
<div className={styles.loadingHandle}>
<div className={styles.loadingCircle}>
<div className={styles.loadingCirclePoint}/>
<div className={styles.loadingCirclePoint}/>
<div className={styles.loadingCirclePoint}/>
<div className={styles.loadingCirclePoint}/>
<div className={styles.loadingCirclePoint}/>
<div className={styles.loadingCirclePoint}/>
<div className={styles.loadingCirclePoint}/>
<div className={styles.loadingCirclePoint}/>
<div className={styles.loadingCirclePoint}/>
<div className={styles.loadingCirclePoint}/>
<div className={styles.loadingCirclePoint}/>
<div className={styles.loadingCirclePoint}/>
</div>
</div>
);
} else {
// Show the handle used to initiate a drag-and-drop
handle = connectDragSource(<div className={styles.moveHandle}/>, {
dropEffect: 'copy',
});
}
}
const isDraggedDescendant = draggedNode && isDescendant(draggedNode, node);
const isLandingPadActive = !didDrop && isDragging;
return (
<div style={{height: '100%'}} {...otherProps}>
{toggleChildrenVisibility &&
node.children &&
node.children.length > 0 &&
<div>
<button
type="button"
aria-label={node.expanded ? 'Collapse' : 'Expand'}
className={
node.expanded ? styles.collapseButton : styles.expandButton
}
style={{left: -0.5 * scaffoldBlockPxWidth}}
onClick={() =>
toggleChildrenVisibility({
node,
path,
treeIndex,
})}
/>
{node.expanded &&
!isDragging &&
<div
style={{width: scaffoldBlockPxWidth}}
className={styles.lineChildren}
/>}
</div>}
<div className={styles.rowWrapper}>
{/* Set the row preview to be used during drag and drop */}
{connectDragPreview(
<div
className={
styles.row +
(isLandingPadActive ? ` ${styles.rowLandingPad}` : '') +
(isLandingPadActive && !canDrop
? ` ${styles.rowCancelPad}`
: '') +
(isSearchMatch ? ` ${styles.rowSearchMatch}` : '') +
(isSearchFocus ? ` ${styles.rowSearchFocus}` : '') +
(className ? ` ${className}` : '')
}
style={{
opacity: isDraggedDescendant ? 0.5 : 1,
...style,
}}
>
{handle}
<div
className={
styles.rowContents +
(!canDrag ? ` ${styles.rowContentsDragDisabled}` : '') +
(options && options.isSelected && options.isSelected({path, node}) ? ` ${styles.rowContentsSelected}` : '') // This has been added compared to the original file
}
onClick={() => options && options.onClick && options.onClick({path, node})} // This has been added compared to the original file
>
<div className={styles.rowLabel}>
<span
className={
styles.rowTitle +
(node.subtitle ? ` ${styles.rowTitleWithSubtitle}` : '')
}
>
{typeof nodeTitle === 'function'
? nodeTitle({
node,
path,
treeIndex,
})
: nodeTitle}
</span>
{nodeSubtitle &&
<span className={styles.rowSubtitle}>
{typeof nodeSubtitle === 'function'
? nodeSubtitle({
node,
path,
treeIndex,
})
: nodeSubtitle}
</span>}
</div>
<div className={styles.rowToolbar}>
{buttons.map((btn, index) =>
<div
key={index} // eslint-disable-line react/no-array-index-key
className={styles.toolbarButton}
>
{btn}
</div>
)}
</div>
</div>
</div>
)}
</div>
</div>
);
}
}
RuleTreeNodeRenderer.defaultProps = {
isSearchMatch: false,
isSearchFocus: false,
canDrag: false,
toggleChildrenVisibility: null,
buttons: [],
className: '',
style: {},
parentNode: null,
draggedNode: null,
canDrop: false,
title: null,
subtitle: null,
};
RuleTreeNodeRenderer.propTypes = {
node: PropTypes.shape({}).isRequired,
title: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),
subtitle: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),
path: PropTypes.arrayOf(
PropTypes.oneOfType([PropTypes.string, PropTypes.number])
).isRequired,
treeIndex: PropTypes.number.isRequired,
isSearchMatch: PropTypes.bool,
isSearchFocus: PropTypes.bool,
canDrag: PropTypes.bool,
scaffoldBlockPxWidth: PropTypes.number.isRequired,
toggleChildrenVisibility: PropTypes.func,
buttons: PropTypes.arrayOf(PropTypes.node),
className: PropTypes.string,
style: PropTypes.shape({}),
// Drag and drop API functions
// Drag source
connectDragPreview: PropTypes.func.isRequired,
connectDragSource: PropTypes.func.isRequired,
parentNode: PropTypes.shape({}), // Needed for dndManager
isDragging: PropTypes.bool.isRequired,
didDrop: PropTypes.bool.isRequired,
draggedNode: PropTypes.shape({}),
// Drop target
isOver: PropTypes.bool.isRequired,
canDrop: PropTypes.bool
};
return RuleTreeNodeRenderer;
}

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 B

View file

@ -1,300 +0,0 @@
// Taken from https://github.com/fritz-c/react-sortable-tree/blob/d6a9be9e4931b5f0dac7b87511d309694f42355e/src/node-renderer-default.scss
$row-padding: 10px;
.rowWrapper {
padding: $row-padding $row-padding $row-padding 0;
height: 100%;
box-sizing: border-box;
}
.row {
height: 100%;
white-space: nowrap;
display: flex;
& > * {
box-sizing: border-box;
}
}
/**
* The outline of where the element will go if dropped, displayed while dragging
*/
.rowLandingPad {
border: none !important;
box-shadow: none !important;
outline: none !important;
* {
opacity: 0 !important;
}
&::before {
background-color: lightblue;
border: 3px dashed white;
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: -1;
}
}
/**
* Alternate appearance of the landing pad when the dragged location is invalid
*/
.rowCancelPad {
@extend .rowLandingPad;
&::before {
background-color: #e6a8ad;
}
}
/**
* Nodes matching the search conditions are highlighted
*/
.rowSearchMatch {
outline: solid 3px #0080ff;
}
/**
* The node that matches the search conditions and is currently focused
*/
.rowSearchFocus {
outline: solid 3px #fc6421;
}
%rowItem {
display: inline-block;
vertical-align: middle;
}
.rowContents {
@extend %rowItem;
position: relative;
height: 100%;
border: solid #bbb 1px;
border-left: none;
box-shadow: 0 2px 2px -2px;
padding: 0 5px 0 10px;
border-radius: 2px;
min-width: 230px;
flex: 1 0 auto;
display: flex;
align-items: center;
justify-content: space-between;
background-color: white;
}
.rowContentsDragDisabled {
border-left: solid #bbb 1px;
}
.rowLabel {
@extend %rowItem;
flex: 0 1 auto;
padding-right: 20px;
}
.rowToolbar {
@extend %rowItem;
flex: 0 1 auto;
display: flex;
}
.moveHandle {
@extend %rowItem;
height: 100%;
width: 44px;
background: #d9d9d9
url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0MiIgaGVpZ2h0PSI0MiI+PGcgc3Ryb2tlPSIjRkZGIiBzdHJva2Utd2lkdGg9IjIuOSIgPjxwYXRoIGQ9Ik0xNCAxNS43aDE0LjQiLz48cGF0aCBkPSJNMTQgMjEuNGgxNC40Ii8+PHBhdGggZD0iTTE0IDI3LjFoMTQuNCIvPjwvZz4KPC9zdmc+')
no-repeat center;
border: solid #aaa 1px;
box-shadow: 0 2px 2px -2px;
cursor: move;
border-radius: 1px;
z-index: 1;
}
.loadingHandle {
@extend .moveHandle;
cursor: default;
background: #d9d9d9;
}
@keyframes pointFade {
0%,
19.999%,
100% {
opacity: 0;
}
20% {
opacity: 1;
}
}
.loadingCircle {
width: 80%;
height: 80%;
margin: 10%;
position: relative;
}
.loadingCirclePoint {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
$point-count: 12;
$spin-animation-time: 800ms;
&:before {
content: '';
display: block;
margin: 0 auto;
width: 11%;
height: 30%;
background-color: #fff;
border-radius: 30%;
animation: pointFade $spin-animation-time infinite ease-in-out both;
}
@for $i from 1 through (($point-count + 1) / 2) {
&:nth-of-type(#{$i}) {
transform: rotate(360deg / $point-count * ($i - 1));
}
&:nth-of-type(#{$i + $point-count / 2}) {
transform: rotate(180deg + 360deg / $point-count * ($i - 1));
}
&:nth-of-type(#{$i}),
&:nth-of-type(#{$i + $point-count / 2}) {
&:before {
animation-delay: - $spin-animation-time + ($spin-animation-time /
$point-count * 2 * ($i - 1));
}
}
}
}
.toolbarButton {
@extend %rowItem;
}
.rowTitle {
font-weight: bold;
}
.rowTitleWithSubtitle {
font-size: 85%;
display: block;
height: 0.8rem;
}
.rowSubtitle {
font-size: 70%;
line-height: 1;
}
.collapseButton,
.expandButton {
appearance: none;
border: none;
position: absolute;
border-radius: 100%;
box-shadow: 0 0 0 1px #000;
width: 16px;
height: 16px;
top: 50%;
transform: translate(-50%, -50%);
cursor: pointer;
&:focus {
outline: none;
box-shadow: 0 0 0 1px #000, 0 0 1px 3px #83bef9;
}
&:hover:not(:active) {
background-size: 24px;
height: 20px;
width: 20px;
}
}
.collapseButton {
background: #fff
url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxOCIgaGVpZ2h0PSIxOCI+PGNpcmNsZSBjeD0iOSIgY3k9IjkiIHI9IjgiIGZpbGw9IiNGRkYiLz48ZyBzdHJva2U9IiM5ODk4OTgiIHN0cm9rZS13aWR0aD0iMS45IiA+PHBhdGggZD0iTTQuNSA5aDkiLz48L2c+Cjwvc3ZnPg==')
no-repeat center;
}
.expandButton {
background: #fff
url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxOCIgaGVpZ2h0PSIxOCI+PGNpcmNsZSBjeD0iOSIgY3k9IjkiIHI9IjgiIGZpbGw9IiNGRkYiLz48ZyBzdHJva2U9IiM5ODk4OTgiIHN0cm9rZS13aWR0aD0iMS45IiA+PHBhdGggZD0iTTQuNSA5aDkiLz48cGF0aCBkPSJNOSA0LjV2OSIvPjwvZz4KPC9zdmc+')
no-repeat center;
}
/**
* Classes for IE9 and below
*/
%fixVertAlign {
&::before {
content: '';
display: inline-block;
vertical-align: middle;
height: 100%;
}
}
.row_NoFlex {
@extend %fixVertAlign;
}
.rowContents_NoFlex {
@extend %fixVertAlign;
display: inline-block;
&::after {
content: '';
display: inline-block;
width: 100%;
}
}
.rowLabel_NoFlex {
@extend %rowItem;
width: 50%;
}
.rowToolbar_NoFlex {
@extend %rowItem;
text-align: right;
width: 50%;
}
/**
* Line for under a node with children
*/
.lineChildren {
height: 100%;
display: inline-block;
position: absolute;
&::after {
content: '';
position: absolute;
background-color: black;
width: 1px;
left: 50%;
bottom: 0;
height: $row-padding;
}
}

View file

@ -1,5 +0,0 @@
@import './node-renderer-default';
.rowContents.rowContentsSelected {
background-color: #d3d3ff;
}

View file

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