Nicer action on item list

This commit is contained in:
Lukas Martinelli 2016-12-20 19:20:56 +01:00
parent 6a129fcf3f
commit 6d9484ec5e
6 changed files with 141 additions and 41 deletions

View file

@ -27,7 +27,6 @@
"mapbox-gl-style-spec": "mapbox/mapbox-gl-style-spec#e85407a377510acb647161de6be6357ab4f606dd", "mapbox-gl-style-spec": "mapbox/mapbox-gl-style-spec#e85407a377510acb647161de6be6357ab4f606dd",
"ol-mapbox-style": "0.0.11", "ol-mapbox-style": "0.0.11",
"openlayers": "^3.19.1", "openlayers": "^3.19.1",
"radium": "^0.18.1",
"randomcolor": "^0.4.4", "randomcolor": "^0.4.4",
"react": "^15.4.0", "react": "^15.4.0",
"react-addons-pure-render-mixin": "^15.4.0", "react-addons-pure-render-mixin": "^15.4.0",

View file

@ -137,6 +137,7 @@ export default class App extends React.Component {
const layerList = <LayerList const layerList = <LayerList
onLayersChanged={this.onLayersChanged.bind(this)} onLayersChanged={this.onLayersChanged.bind(this)}
onLayerSelected={this.onLayerSelected.bind(this)} onLayerSelected={this.onLayerSelected.bind(this)}
selectedLayerIndex={this.state.selectedLayerIndex}
layers={layers} layers={layers}
/> />

View file

@ -37,7 +37,7 @@ export default class Layout extends React.Component {
top: 50, top: 50,
left: 0, left: 0,
zIndex: 100, zIndex: 100,
width: 180, width: 200,
overflow: "hidden", overflow: "hidden",
backgroundColor: colors.gray backgroundColor: colors.gray
}}> }}>
@ -48,7 +48,7 @@ export default class Layout extends React.Component {
bottom: 0, bottom: 0,
height: "100%", height: "100%",
top: 50, top: 50,
left: 180, left: 200,
zIndex: 100, zIndex: 100,
width: 300, width: 300,
backgroundColor: colors.gray} backgroundColor: colors.gray}

View file

@ -31,7 +31,6 @@ export default class LayerEditor extends React.Component {
sources: React.PropTypes.object, sources: React.PropTypes.object,
vectorLayers: React.PropTypes.object, vectorLayers: React.PropTypes.object,
onLayerChanged: React.PropTypes.func, onLayerChanged: React.PropTypes.func,
onLayerDestroyed: React.PropTypes.func,
} }
static defaultProps = { static defaultProps = {
@ -98,10 +97,6 @@ export default class LayerEditor extends React.Component {
/> />
}) })
let visibleIcon = <MdVisibilityOff />
if('layout' in this.props.layer && this.props.layer.layout.visibility === 'none') {
visibleIcon = <MdVisibility />
}
return <div style={{ return <div style={{
padding: theme.scale[0], padding: theme.scale[0],
}}> }}>
@ -109,13 +104,6 @@ export default class LayerEditor extends React.Component {
<NavItem style={{fontWeight: 400}}> <NavItem style={{fontWeight: 400}}>
{this.props.layer.id} {this.props.layer.id}
</NavItem> </NavItem>
<Space auto x={1} />
<NavItem onClick={this.toggleVisibility.bind(this)}>
{visibleIcon}
</NavItem>
<NavItem onClick={(e) => this.props.onLayerDestroyed(this.props.layer)}>
<MdDelete />
</NavItem>
</Toolbar> </Toolbar>
{propertyGroups} {propertyGroups}
{this.props.layer.type !== 'background' && <div> {this.props.layer.type !== 'background' && <div>

View file

@ -15,6 +15,7 @@ import {SortableContainer, SortableHandle, arrayMove} from 'react-sortable-hoc';
const layerListPropTypes = { const layerListPropTypes = {
layers: React.PropTypes.array.isRequired, layers: React.PropTypes.array.isRequired,
selectedLayerIndex: React.PropTypes.number.isRequired,
onLayersChanged: React.PropTypes.func.isRequired, onLayersChanged: React.PropTypes.func.isRequired,
onLayerSelected: React.PropTypes.func, onLayerSelected: React.PropTypes.func,
} }
@ -45,6 +46,7 @@ class LayerListContainer extends React.Component {
key={layerId} key={layerId}
layerId={layerId} layerId={layerId}
layerType={layer.type} layerType={layer.type}
isSelected={index === this.props.selectedLayerIndex}
onLayerSelected={this.props.onLayerSelected} onLayerSelected={this.props.onLayerSelected}
/> />
}) })

View file

@ -1,5 +1,4 @@
import React from 'react' import React from 'react'
import Radium from 'radium'
import Color from 'color' import Color from 'color'
import Heading from 'rebass/dist/Heading' import Heading from 'rebass/dist/Heading'
@ -7,6 +6,11 @@ import Toolbar from 'rebass/dist/Toolbar'
import NavItem from 'rebass/dist/NavItem' import NavItem from 'rebass/dist/NavItem'
import Space from 'rebass/dist/Space' import Space from 'rebass/dist/Space'
import CopyIcon from 'react-icons/lib/md/content-copy'
import VisibilityIcon from 'react-icons/lib/md/visibility'
import VisibilityOffIcon from 'react-icons/lib/md/visibility-off'
import DeleteIcon from 'react-icons/lib/md/delete'
import LayerIcon from '../icons/LayerIcon' import LayerIcon from '../icons/LayerIcon'
import LayerEditor from './LayerEditor' import LayerEditor from './LayerEditor'
import {SortableElement, SortableHandle} from 'react-sortable-hoc' import {SortableElement, SortableHandle} from 'react-sortable-hoc'
@ -27,43 +31,149 @@ class LayerTypeDragHandle extends React.Component {
} }
} }
class IconAction extends React.Component {
static propTypes = {
action: React.PropTypes.string.isRequired,
active: React.PropTypes.bool,
}
constructor(props) {
super(props)
this.state = { hover: false }
}
renderIcon() {
const iconStyle = {
fill: this.props.active ? (this.state.hover ? colors.lowgray : colors.midgray) : colors.gray,
}
switch(this.props.action) {
case 'copy': return <CopyIcon style={iconStyle} />
case 'show': return <VisibilityOnIcon style={iconStyle} />
case 'hide': return <VisibilityOffIcon style={iconStyle} />
case 'delete': return <DeleteIcon style={iconStyle} />
default: return null
}
}
render() {
return <div
style={{
display: "inline",
marginLeft: margins[0],
...this.props.style
}}
onMouseOver={e => this.setState({hover: true})}
onMouseOut={e => this.setState({hover: false})}
>
{this.renderIcon()}
</div>
}
}
@SortableElement @SortableElement
@Radium
class LayerListItem extends React.Component { class LayerListItem extends React.Component {
static propTypes = { static propTypes = {
layerId: React.PropTypes.string.isRequired, layerId: React.PropTypes.string.isRequired,
layerType: React.PropTypes.string.isRequired, layerType: React.PropTypes.string.isRequired,
isSelected: React.PropTypes.bool,
visibility: React.PropTypes.bool,
onLayerSelected: React.PropTypes.func.isRequired, onLayerSelected: React.PropTypes.func.isRequired,
onLayerDestroyed: React.PropTypes.func,
onLayerVisibilityToggled: React.PropTypes.func,
}
static defaultProps = {
isSelected: false,
visibility: true,
onLayerDestroyed: () => {},
onLayerVisibilityToggled: () => {},
}
static childContextTypes = {
reactIconBase: React.PropTypes.object
}
constructor(props) {
super(props)
this.state = {
hover: false
}
}
getChildContext() {
return {
reactIconBase: { size: 12 }
}
} }
render() { render() {
const itemStyle = {
fontWeight: 400,
color: colors.lowgray,
fontSize: fontSizes[5],
borderLeft: 0,
borderTop: 0,
borderBottom: 1,
borderRight: 0,
borderStyle: "solid",
userSelect: 'none',
listStyle: 'none',
zIndex: 2000,
cursor: 'pointer',
position: 'relative',
padding: margins[1],
borderColor: Color(colors.gray).lighten(0.1).string(),
backgroundColor: colors.gray,
}
if(this.state.hover) {
console.log('hooover')
itemStyle.backgroundColor = Color(colors.gray).lighten(0.10)
}
if(this.props.isSelected) {
itemStyle.backgroundColor = Color(colors.gray).lighten(0.15)
}
const iconProps = {
active: this.state.hover || this.props.isSelected
}
return <li return <li
key={this.props.layerId} key={this.props.layerId}
onClick={() => this.props.onLayerSelected(this.props.layerId)} onClick={e => this.props.onLayerSelected(this.props.layerId)}
style={{ onMouseOver={e => this.setState({hover: true})}
fontWeight: 400, onMouseOut={e => this.setState({hover: false})}
color: colors.lowgray, style={itemStyle}>
fontSize: fontSizes[5], <div style={{
borderBottom: 1, display: 'flex',
borderLeft: 2, flexDirection: 'row'
borderRight: 0, }}>
borderStyle: "solid", <LayerTypeDragHandle type={this.props.layerType} />
userSelect: 'none', <span style={{
listStyle: 'none', width: 115,
zIndex: 2000, whiteSpace: 'nowrap',
cursor: 'pointer', overflow: 'hidden',
position: 'relative', textOverflow: 'ellipsis'
padding: margins[1], }}>{this.props.layerId}</span>
borderColor: Color(colors.gray).lighten(0.1).string(), <span style={{flexGrow: 1}} />
backgroundColor: colors.gray, <IconAction {...iconProps}
":hover": { action={'delete'}
backgroundColor: Color(colors.gray).lighten(0.15).string(), onClick={e => this.props.onLayerDestroyed(this.props.layerId)}
} />
}}> <IconAction {...iconProps}
<LayerTypeDragHandle type={this.props.layerType} /> action={'copy'}
<span>{this.props.layerId}</span> onClick={e => this.props.onLayerVisibilityToggled(this.props.layerId)}
/>
<IconAction {...iconProps}
action={this.props.visibility ? 'hide' : 'show'}
onClick={e => this.props.onLayerVisibilityToggled(this.props.layerId)}
/>
</div>
</li> </li>
} }
} }
export default Radium(LayerListItem); export default LayerListItem;