mirror of
https://github.com/a-nyx/maputnik-with-pmtiles.git
synced 2024-12-27 08:45:28 +01:00
Group layers #66
This commit is contained in:
parent
76d2d06e77
commit
d0f047d88a
6 changed files with 142 additions and 38 deletions
20
src/components/layers/Collapser.jsx
Normal file
20
src/components/layers/Collapser.jsx
Normal file
|
@ -0,0 +1,20 @@
|
|||
import React from 'react'
|
||||
import CollapseOpenIcon from 'react-icons/lib/md/arrow-drop-down'
|
||||
import CollapseCloseIcon from 'react-icons/lib/md/arrow-drop-up'
|
||||
|
||||
export default class Collapser extends React.Component {
|
||||
static propTypes = {
|
||||
isCollapsed: React.PropTypes.bool.isRequired,
|
||||
style: React.PropTypes.object,
|
||||
}
|
||||
|
||||
render() {
|
||||
const iconStyle = {
|
||||
width: 20,
|
||||
height: 20,
|
||||
...this.props.style,
|
||||
}
|
||||
return this.props.isCollapsed ? <CollapseCloseIcon style={iconStyle}/> : <CollapseOpenIcon style={iconStyle} />
|
||||
}
|
||||
}
|
||||
|
|
@ -1,22 +1,6 @@
|
|||
import React from 'react'
|
||||
|
||||
import Collapse from 'react-collapse'
|
||||
import CollapseOpenIcon from 'react-icons/lib/md/arrow-drop-down'
|
||||
import CollapseCloseIcon from 'react-icons/lib/md/arrow-drop-up'
|
||||
|
||||
class Collapser extends React.Component {
|
||||
static propTypes = {
|
||||
isCollapsed: React.PropTypes.bool.isRequired,
|
||||
}
|
||||
|
||||
render() {
|
||||
const iconStyle = {
|
||||
width: 20,
|
||||
height: 20,
|
||||
}
|
||||
return this.props.isCollapsed ? <CollapseCloseIcon style={iconStyle}/> : <CollapseOpenIcon style={iconStyle} />
|
||||
}
|
||||
}
|
||||
import Collapser from './Collapser'
|
||||
|
||||
export default class LayerEditorGroup extends React.Component {
|
||||
static propTypes = {
|
||||
|
|
|
@ -2,6 +2,7 @@ import React from 'react'
|
|||
import cloneDeep from 'lodash.clonedeep'
|
||||
|
||||
import Button from '../Button'
|
||||
import LayerListGroup from './LayerListGroup'
|
||||
import LayerListItem from './LayerListItem'
|
||||
import AddIcon from 'react-icons/lib/md/add-circle-outline'
|
||||
import AddModal from '../modals/AddModal'
|
||||
|
@ -9,6 +10,8 @@ import AddModal from '../modals/AddModal'
|
|||
import style from '../../libs/style.js'
|
||||
import {SortableContainer, SortableHandle, arrayMove} from 'react-sortable-hoc';
|
||||
|
||||
const layerPrefix = name => name.replace(' ', '-').replace('_', '-').split('-')[0]
|
||||
|
||||
const layerListPropTypes = {
|
||||
layers: React.PropTypes.array.isRequired,
|
||||
selectedLayerIndex: React.PropTypes.number.isRequired,
|
||||
|
@ -73,22 +76,69 @@ class LayerListContainer extends React.Component {
|
|||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
const layerPanels = this.props.layers.map((layer, index) => {
|
||||
const layerId = layer.id
|
||||
return <LayerListItem
|
||||
index={index}
|
||||
key={layerId}
|
||||
layerId={layerId}
|
||||
layerType={layer.type}
|
||||
visibility={(layer.layout || {}).visibility}
|
||||
isSelected={index === this.props.selectedLayerIndex}
|
||||
onLayerSelect={this.props.onLayerSelect}
|
||||
onLayerDestroy={this.onLayerDestroy.bind(this)}
|
||||
onLayerCopy={this.onLayerCopy.bind(this)}
|
||||
onLayerVisibilityToggle={this.onLayerVisibilityToggle.bind(this)}
|
||||
/>
|
||||
groupedLayers() {
|
||||
const groups = []
|
||||
for (let i = 0; i < this.props.layers.length; i++) {
|
||||
const previousLayer = this.props.layers[i-1]
|
||||
const layer = this.props.layers[i]
|
||||
if(previousLayer && layerPrefix(previousLayer.id) == layerPrefix(layer.id)) {
|
||||
const lastGroup = groups[groups.length - 1]
|
||||
lastGroup.push(layer)
|
||||
} else {
|
||||
groups.push([layer])
|
||||
}
|
||||
}
|
||||
return groups
|
||||
}
|
||||
|
||||
toggleLayerGroup(groupPrefix) {
|
||||
groupedLayers().forEach(layers => {
|
||||
if(groupPrefix === layerPrefix(layers[0].id)) {
|
||||
layers.forEach(layer => {
|
||||
//HACK
|
||||
//In this case it is ok to modify the metadata
|
||||
//because no one else depends on it
|
||||
layer.metadata = {
|
||||
...layer.metadata,
|
||||
'maputnik:visible': false
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
const listItems = []
|
||||
let idx = 0
|
||||
this.groupedLayers().forEach(layers => {
|
||||
if(layers.length > 1) {
|
||||
const groupPrefix = layerPrefix(layers[0].id)
|
||||
const grp = <LayerListGroup
|
||||
key={'group-'+groupPrefix}
|
||||
title={groupPrefix}
|
||||
isActive={true}
|
||||
/>
|
||||
listItems.push(grp)
|
||||
}
|
||||
|
||||
layers.forEach(layer => {
|
||||
const listItem = <LayerListItem
|
||||
index={idx}
|
||||
key={layer.id}
|
||||
layerId={layer.id}
|
||||
layerType={layer.type}
|
||||
visibility={(layer.layout || {}).visibility}
|
||||
isSelected={idx === this.props.selectedLayerIndex}
|
||||
onLayerSelect={this.props.onLayerSelect}
|
||||
onLayerDestroy={this.onLayerDestroy.bind(this)}
|
||||
onLayerCopy={this.onLayerCopy.bind(this)}
|
||||
onLayerVisibilityToggle={this.onLayerVisibilityToggle.bind(this)}
|
||||
/>
|
||||
listItems.push(listItem)
|
||||
idx += 1
|
||||
})
|
||||
})
|
||||
|
||||
return <div className="maputnik-layer-list">
|
||||
<AddModal
|
||||
layers={this.props.layers}
|
||||
|
@ -107,7 +157,7 @@ class LayerListContainer extends React.Component {
|
|||
</Button>
|
||||
</header>
|
||||
<ul className="maputnik-layer-list-container">
|
||||
{layerPanels}
|
||||
{listItems}
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
|
|
26
src/components/layers/LayerListGroup.jsx
Normal file
26
src/components/layers/LayerListGroup.jsx
Normal file
|
@ -0,0 +1,26 @@
|
|||
import React from 'react'
|
||||
import Collapser from './Collapser'
|
||||
|
||||
export default class LayerEditorGroup extends React.Component {
|
||||
static propTypes = {
|
||||
title: React.PropTypes.string.isRequired,
|
||||
children: React.PropTypes.element.isRequired,
|
||||
isActive: React.PropTypes.bool.isRequired,
|
||||
onActiveToggle: React.PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div className="maputnik-layer-list-group">
|
||||
<div className="maputnik-layer-list-group-header"
|
||||
onClick={e => this.props.onActiveToggle(!this.props.isActive)}
|
||||
>
|
||||
<span className="maputnik-layer-list-group-title">{this.props.title}</span>
|
||||
<span className="maputnik-space" />
|
||||
<Collapser
|
||||
style={{ height: 14, width: 14 }}
|
||||
isCollapsed={this.props.isActive}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
|
@ -80,10 +80,6 @@ class LayerListItem extends React.Component {
|
|||
reactIconBase: React.PropTypes.object
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
|
||||
getChildContext() {
|
||||
return {
|
||||
reactIconBase: { size: 14 }
|
||||
|
|
|
@ -37,7 +37,6 @@
|
|||
cursor: pointer;
|
||||
position: relative;
|
||||
padding: 5px 10px;
|
||||
background-color: $color-black;
|
||||
line-height: 1.3;
|
||||
display: flex;
|
||||
display: -ms-flexbox;
|
||||
|
@ -69,6 +68,35 @@
|
|||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
&-group {
|
||||
//border-bottom: 2px solid $color-gray;
|
||||
}
|
||||
|
||||
&-group-header {
|
||||
font-size: $font-size-6;
|
||||
color: $color-lowgray;
|
||||
background-color: lighten($color-black, 2);
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
padding: $margin-2;
|
||||
display: flex;
|
||||
display: -ms-flexbox;
|
||||
@include vendor-prefix(flex-direction, row)
|
||||
|
||||
svg {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
&-group-title {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
&-group-content {
|
||||
margin-left: $margin-3;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue