From 13cbf2115921b64dbd8ec4bd5574949917a1bc0b Mon Sep 17 00:00:00 2001 From: Mathias Biilmann Christensen Date: Fri, 28 Oct 2016 19:13:26 +0200 Subject: [PATCH] Implement list control with fields --- src/components/ControlPanel/ControlPane.css | 56 ++++++++++++- src/components/Widgets/ListControl.css | 68 +++++++++++++++ src/components/Widgets/ListControl.js | 91 ++++++++++++++++++++- src/valueObjects/Collection.js | 2 +- 4 files changed, 210 insertions(+), 7 deletions(-) create mode 100644 src/components/Widgets/ListControl.css diff --git a/src/components/ControlPanel/ControlPane.css b/src/components/ControlPanel/ControlPane.css index 1f614ecd..25973c88 100644 --- a/src/components/ControlPanel/ControlPane.css +++ b/src/components/ControlPanel/ControlPane.css @@ -1,6 +1,54 @@ -.root { +.control { + color: #7c8382; position: relative; - margin-bottom: 20px; - padding: 20px; - border: 1px solid #e8eae8; + padding: 20px 0; + + & input, + & textarea, + & select { + font-family: monospace; + display: block; + width: 100%; + padding: 0; + margin: 0; + border: none; + outline: 0; + box-shadow: none; + background: 0 0; + font-size: 18px; + color: #7c8382; + } +} +.label { + display: block; + color: #AAB0AF; + font-size: 12px; + margin-bottom: 18px; +} +.widget { + border-bottom: 1px solid #e8eae8; + position: relative; + + &:after { + content: ''; + position: absolute; + left: 42px; + bottom: -7px; + width: 12px; + height: 12px; + background-color: #f2f5f4; + -webkit-transform: rotate(45deg); + transform: rotate(45deg); + z-index: 1; + border-right: 1px solid #e8eae8; + border-bottom: 1px solid #e8eae8; + } + + &:last-child { + border-bottom: none; + } + + &:last-child:after { + display: none; + } } diff --git a/src/components/Widgets/ListControl.css b/src/components/Widgets/ListControl.css new file mode 100644 index 00000000..fedcd1dc --- /dev/null +++ b/src/components/Widgets/ListControl.css @@ -0,0 +1,68 @@ +.addButton { + display: block; + cursor: pointer; + margin: 20px 0; + border: none; + background: transparent; + &::before { + content: "+"; + display: inline-block; + margin-right: 5px; + width: 15px; + height: 15px; + border: 1px solid #444; + border-radius: 100%; + background: transparent; + line-height: 13px; + } +} + +.removeButton { + position: absolute; + top: 5px; + right: 5px; + display: inline-block; + cursor: pointer; + border: none; + background: transparent; + width: 15px; + height: 15px; + border: 1px solid #444; + border-radius: 100%; + line-height: 13px; +} + +.toggleButton { + position: absolute; + top: 5px; + left: 5px; +} + +.item { + position: relative; + padding-left: 20px; + cursor: move; +} + +.objectLabel { + border: 1px solid #e8eae8; + margin-bottom: 20px; + padding: 20px; + display: none; +} + +.objectControl { + display: block; +} + +.expanded { +} + +.collapsed { + & .objectLabel { + display: block; + } + & .objectControl { + display: none; + } +} diff --git a/src/components/Widgets/ListControl.js b/src/components/Widgets/ListControl.js index 7d58de07..50a9ec35 100644 --- a/src/components/Widgets/ListControl.js +++ b/src/components/Widgets/ListControl.js @@ -1,17 +1,104 @@ import React, { Component, PropTypes } from 'react'; +import { List, Map } from 'immutable'; +import ObjectControl from './ObjectControl'; +import styles from './ListControl.css'; export default class ListControl extends Component { - static propTypes = { onChange: PropTypes.func.isRequired, value: PropTypes.node, }; + + constructor(props) { + super(props); + this.state = {itemStates: Map()}; + } + handleChange = (e) => { this.props.onChange(e.target.value.split(',').map(item => item.trim())); }; - render() { + handleAdd = (e) => { + e.preventDefault(); + const { value, onChange } = this.props; + + onChange((value || List()).push(Map())); + }; + + handleChangeFor(index) { + return (newValue) => { + const { value, onChange } = this.props; + onChange(value.set(index, newValue)); + }; + } + + handleRemove(index) { + return (e) => { + e.preventDefault(); + const { value, onChange } = this.props; + onChange(value.remove(index)); + }; + } + + handleToggle(index) { + return (e) => { + e.preventDefault(); + const { itemStates } = this.state; + this.setState({ + itemStates: itemStates.setIn([index, 'collapsed'], !itemStates.getIn([index, 'collapsed'])), + }); + }; + } + + objectLabel(item) { + const { field } = this.props; + const fields = field.get('fields'); + const first = fields.first(); + const value = item.get(first.get('name')); + return value || `No ${first.get('name')}`; + } + + renderItem(item, index) { + const { field, getMedia, onAddMedia, onRemoveMedia } = this.props; + const { itemStates } = this.state; + const collapsed = itemStates.getIn([index, 'collapsed']); + const classNames = [styles.item, collapsed ? styles.collapsed : styles.expanded]; + + return (
+
{this.objectLabel(item)}
+
+ +
+ + +
); + } + + renderListControl() { const { value } = this.props; + return (
+ {value && value.map((item, index) => this.renderItem(item, index))} +
+
); + } + + render() { + const { value, field } = this.props; + console.log('field: %o', field.toJS()); + + if (field.get('fields')) { + return this.renderListControl(); + } + return ; } } diff --git a/src/valueObjects/Collection.js b/src/valueObjects/Collection.js index a8b5c220..d4daaa64 100644 --- a/src/valueObjects/Collection.js +++ b/src/valueObjects/Collection.js @@ -39,7 +39,7 @@ class FolderCollection { } templateName() { - return this.props.collection.get('name'); + return this.collection.get('name'); } }