Drag and drop layer order

This commit is contained in:
Lukas Martinelli 2016-12-17 19:58:30 +01:00
parent 7fae257130
commit b9d3886b50
4 changed files with 76 additions and 35 deletions

View file

@ -35,6 +35,7 @@
"react-height": "^2.1.1", "react-height": "^2.1.1",
"react-icons": "^2.2.1", "react-icons": "^2.2.1",
"react-motion": "^0.4.4", "react-motion": "^0.4.4",
"react-sortable-hoc": "^0.4.5",
"rebass": "^0.3.1", "rebass": "^0.3.1",
"request": "^2.79.0" "request": "^2.79.0"
}, },

View file

@ -86,8 +86,8 @@ export default class App extends React.Component {
} }
onLayersChanged(changedLayers) { onLayersChanged(changedLayers) {
const changedStyle = this.props.mapStyle.set('layers', changedLayers) const changedStyle = this.state.mapStyle.set('layers', changedLayers)
this.props.onStyleChanged(changedStyle) this.onStyleChanged(changedStyle)
} }
mapRenderer() { mapRenderer() {

View file

@ -12,14 +12,18 @@ import scrollbars from '../scrollbars.scss'
import PureRenderMixin from 'react-addons-pure-render-mixin'; import PureRenderMixin from 'react-addons-pure-render-mixin';
import theme from '../theme.js' import theme from '../theme.js'
// List of collapsible layer editors import {SortableContainer, SortableHandle, arrayMove} from 'react-sortable-hoc';
export class LayerList extends React.Component {
static propTypes = { const layerListPropTypes = {
layers: React.PropTypes.instanceOf(Immutable.OrderedMap), layers: React.PropTypes.instanceOf(Immutable.OrderedMap),
onLayersChanged: React.PropTypes.func.isRequired, onLayersChanged: React.PropTypes.func.isRequired,
onLayerSelected: React.PropTypes.func, onLayerSelected: React.PropTypes.func,
} }
// List of collapsible layer editors
@SortableContainer
class LayerListContainer extends React.Component {
static propTypes = {...layerListPropTypes}
static defaultProps = { static defaultProps = {
onLayerSelected: () => {}, onLayerSelected: () => {},
} }
@ -40,26 +44,55 @@ export class LayerList extends React.Component {
} }
render() { render() {
const layerPanels = this.props.layers.map(layer => { const layerPanels = this.props.layers.toIndexedSeq().map((layer, index) => {
const layerId = layer.get('id') const layerId = layer.get('id')
return <LayerListItem return <LayerListItem
index={index}
key={layerId} key={layerId}
layerId={layerId} layerId={layerId}
onLayerSelected={this.props.onLayerSelected} onLayerSelected={this.props.onLayerSelected}
/> />
}).toIndexedSeq() })
return <ul className={scrollbars.darkScrollbar} style={{
return <div>
<div className={scrollbars.darkScrollbar} style={{
overflowY: "scroll", overflowY: "scroll",
bottom:0, bottom:0,
left:0, left:0,
right:0, right:0,
top:1, top:1,
position: "absolute", position: "absolute",
padding: theme.scale[2],
}}> }}>
{layerPanels} {layerPanels}
</div> </ul>
</div> }
}
export class LayerList extends React.Component {
static propTypes = {...layerListPropTypes}
constructor(props) {
super(props)
this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
}
onSortEnd(move) {
const { oldIndex, newIndex } = move
if(oldIndex === newIndex) return
//TODO: Implement this more performant for immutable collections
// instead of converting back and forth
let layers = this.props.layers.toArray()
layers = arrayMove(layers, oldIndex, newIndex)
layers = Immutable.OrderedMap(layers.map(l => [l.get('id'), l]))
this.props.onLayersChanged(layers)
}
render() {
return <LayerListContainer
{...this.props}
onSortEnd={this.onSortEnd.bind(this)}
useDragHandle={true}
/>
} }
} }

View file

@ -12,11 +12,16 @@ import { LayerEditor } from './editor.jsx'
import scrollbars from '../scrollbars.scss' import scrollbars from '../scrollbars.scss'
import PureRenderMixin from 'react-addons-pure-render-mixin'; import PureRenderMixin from 'react-addons-pure-render-mixin';
import theme from '../theme.js' import theme from '../theme.js'
import {SortableElement, SortableHandle} from 'react-sortable-hoc';
import MdDragHandle from 'react-icons/lib/md/drag-handle'
const DragHandle = SortableHandle(() => <MdDragHandle />);
@SortableElement
@Radium @Radium
class LayerListItem extends React.Component { class LayerListItem extends React.Component {
static propTypes = { static propTypes = {
layerId: React.PropTypes.number.isRequired, layerId: React.PropTypes.string.isRequired,
onLayerSelected: React.PropTypes.func.isRequired, onLayerSelected: React.PropTypes.func.isRequired,
} }
@ -26,30 +31,32 @@ class LayerListItem extends React.Component {
} }
render() { render() {
return <div key={this.props.layerId} style={{ return <li
key={this.props.layerId}
onClick={() => this.props.onLayerSelected(this.props.layerId)}
style={{
fontWeight: 400,
color: theme.colors.lowgray,
fontSize: theme.fontSizes[5],
borderBottom: 1, borderBottom: 1,
borderLeft: 2, borderLeft: 2,
borderRight: 0, borderRight: 0,
borderStyle: "solid", borderStyle: "solid",
userSelect: 'none',
listStyle: 'none',
zIndex: 2000,
cursor: 'pointer',
position: 'relative',
padding: theme.scale[1],
borderColor: color(theme.colors.gray).lighten(0.1).hexString(), borderColor: color(theme.colors.gray).lighten(0.1).hexString(),
}}>
<div
onClick={() => this.props.onLayerSelected(this.props.layerId)}
style={{
backgroundColor: theme.colors.gray, backgroundColor: theme.colors.gray,
":hover": { ":hover": {
backgroundColor: color(theme.colors.gray).lighten(0.15).hexString(), backgroundColor: color(theme.colors.gray).lighten(0.15).hexString(),
} }
}}
>
<NavItem style={{
fontWeight: 400,
color: theme.colors.lowgray,
}}> }}>
#{this.props.layerId} <DragHandle />
</NavItem> <span>#{this.props.layerId}</span>
</div> </li>
</div>
} }
} }