Skip to content

Commit

Permalink
Merge pull request #306 from orangemug/feature/accessibility-list-reo…
Browse files Browse the repository at this point in the history
…rder

Keyboard accessible layer options
  • Loading branch information
orangemug authored Jun 3, 2018
2 parents fd48d82 + 32edb48 commit edd09ef
Show file tree
Hide file tree
Showing 8 changed files with 245 additions and 57 deletions.
14 changes: 7 additions & 7 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ templates:
name: "Create artifacts directory"
command: mkdir /tmp/artifacts
- restore_cache:
key: v1-dependencies-{{ checksum "package.json" }}
key: v1-dependencies-{{ arch }}-{{ checksum "package.json" }}

- run: npm install

- save_cache:
paths:
- node_modules
key: v1-dependencies-{{ checksum "package.json" }}
key: v1-dependencies-{{ arch }}-{{ checksum "package.json" }}

- run: mkdir -p /tmp/artifacts/logs
- run: npm run build
Expand All @@ -30,14 +30,14 @@ templates:
name: "Create artifacts directory"
command: mkdir /tmp/artifacts
- restore_cache:
key: v1-dependencies-{{ checksum "package.json" }}
key: v1-dependencies-{{ arch }}-{{ checksum "package.json" }}

- run: npm install

- save_cache:
paths:
- node_modules
key: v1-dependencies-{{ checksum "package.json" }}
key: v1-dependencies-{{ arch }}-{{ checksum "package.json" }}

- run: mkdir -p /tmp/artifacts/logs
- run: npm run build
Expand Down Expand Up @@ -71,23 +71,23 @@ jobs:
dependencies:
override:
- brew install node@6
working_directory: ~/repo-linux-node-v6
working_directory: ~/repo-osx-node-v6
steps: *build-steps
build-osx-node-v8:
macos:
xcode: "9.0"
dependencies:
override:
- brew install node@8
working_directory: ~/repo-linux-node-v8
working_directory: ~/repo-osx-node-v8
steps: *build-steps
build-osx-node-v10:
macos:
xcode: "9.0"
dependencies:
override:
- brew install node@10
working_directory: ~/repo-linux-node-v10
working_directory: ~/repo-osx-node-v10
steps: *build-steps

workflows:
Expand Down
25 changes: 25 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"github-api": "^3.0.0",
"jsonlint": "github:josdejong/jsonlint#85a19d7",
"lodash.capitalize": "^4.2.1",
"lodash.clamp": "^4.0.3",
"lodash.clonedeep": "^4.5.0",
"lodash.isequal": "^4.5.0",
"lodash.throttle": "^4.1.1",
Expand All @@ -42,6 +43,7 @@
"prop-types": "^15.6.0",
"react": "^16.3.2",
"react-addons-pure-render-mixin": "^15.6.2",
"react-aria-menubutton": "^5.1.1",
"react-aria-modal": "^2.12.1",
"react-autocomplete": "^1.7.2",
"react-codemirror2": "^4.2.1",
Expand Down
66 changes: 66 additions & 0 deletions src/components/App.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import React from 'react'
import Mousetrap from 'mousetrap'
import cloneDeep from 'lodash.clonedeep'
import clamp from 'lodash.clamp'
import {arrayMove} from 'react-sortable-hoc';
import url from 'url'

import MapboxGlMap from './map/MapboxGlMap'
Expand Down Expand Up @@ -168,6 +171,24 @@ export default class App extends React.Component {
})
}

onMoveLayer(move) {
let { oldIndex, newIndex } = move;
let layers = this.state.mapStyle.layers;
oldIndex = clamp(oldIndex, 0, layers.length-1);
newIndex = clamp(newIndex, 0, layers.length-1);
if(oldIndex === newIndex) return;

if (oldIndex === this.state.selectedLayerIndex) {
this.setState({
selectedLayerIndex: newIndex
});
}

layers = layers.slice(0);
layers = arrayMove(layers, oldIndex, newIndex);
this.onLayersChange(layers);
}

onLayersChange(changedLayers) {
const changedStyle = {
...this.state.mapStyle,
Expand All @@ -176,6 +197,40 @@ export default class App extends React.Component {
this.onStyleChanged(changedStyle)
}

onLayerDestroy(layerId) {
let layers = this.state.mapStyle.layers;
const remainingLayers = layers.slice(0);
const idx = style.indexOfLayer(remainingLayers, layerId)
remainingLayers.splice(idx, 1);
this.onLayersChange(remainingLayers);
}

onLayerCopy(layerId) {
let layers = this.state.mapStyle.layers;
const changedLayers = layers.slice(0)
const idx = style.indexOfLayer(changedLayers, layerId)

const clonedLayer = cloneDeep(changedLayers[idx])
clonedLayer.id = clonedLayer.id + "-copy"
changedLayers.splice(idx, 0, clonedLayer)
this.onLayersChange(changedLayers)
}

onLayerVisibilityToggle(layerId) {
let layers = this.state.mapStyle.layers;
const changedLayers = layers.slice(0)
const idx = style.indexOfLayer(changedLayers, layerId)

const layer = { ...changedLayers[idx] }
const changedLayout = 'layout' in layer ? {...layer.layout} : {}
changedLayout.visibility = changedLayout.visibility === 'none' ? 'visible' : 'none'

layer.layout = changedLayout
changedLayers[idx] = layer
this.onLayersChange(changedLayers)
}


onLayerIdChange(oldId, newId) {
const changedLayers = this.state.mapStyle.layers.slice(0)
const idx = style.indexOfLayer(changedLayers, oldId)
Expand Down Expand Up @@ -311,6 +366,10 @@ export default class App extends React.Component {
/>

const layerList = <LayerList
onMoveLayer={this.onMoveLayer.bind(this)}
onLayerDestroy={this.onLayerDestroy.bind(this)}
onLayerCopy={this.onLayerCopy.bind(this)}
onLayerVisibilityToggle={this.onLayerVisibilityToggle.bind(this)}
onLayersChange={this.onLayersChange.bind(this)}
onLayerSelect={this.onLayerSelect.bind(this)}
selectedLayerIndex={this.state.selectedLayerIndex}
Expand All @@ -320,10 +379,17 @@ export default class App extends React.Component {

const layerEditor = selectedLayer ? <LayerEditor
layer={selectedLayer}
layerIndex={this.state.selectedLayerIndex}
isFirstLayer={this.state.selectedLayerIndex < 1}
isLastLayer={this.state.selectedLayerIndex === this.state.mapStyle.layers.length-1}
sources={this.state.sources}
vectorLayers={this.state.vectorLayers}
spec={this.state.spec}
onMoveLayer={this.onMoveLayer.bind(this)}
onLayerChanged={this.onLayerChanged.bind(this)}
onLayerDestroy={this.onLayerDestroy.bind(this)}
onLayerCopy={this.onLayerCopy.bind(this)}
onLayerVisibilityToggle={this.onLayerVisibilityToggle.bind(this)}
onLayerIdChange={this.onLayerIdChange.bind(this)}
/> : null

Expand Down
82 changes: 82 additions & 0 deletions src/components/layers/LayerEditor.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react'
import PropTypes from 'prop-types'
import { Wrapper, Button, Menu, MenuItem } from 'react-aria-menubutton'

import JSONEditor from './JSONEditor'
import FilterEditor from '../filter/FilterEditor'
Expand All @@ -13,6 +14,8 @@ import CommentBlock from './CommentBlock'
import LayerSourceBlock from './LayerSourceBlock'
import LayerSourceLayerBlock from './LayerSourceLayerBlock'

import MoreVertIcon from 'react-icons/lib/md/more-vert'

import InputBlock from '../inputs/InputBlock'
import MultiButtonInput from '../inputs/MultiButtonInput'

Expand Down Expand Up @@ -45,6 +48,13 @@ export default class LayerEditor extends React.Component {
spec: PropTypes.object.isRequired,
onLayerChanged: PropTypes.func,
onLayerIdChange: PropTypes.func,
onMoveLayer: PropTypes.func,
onLayerDestroy: PropTypes.func,
onLayerCopy: PropTypes.func,
onLayerVisibilityToggle: PropTypes.func,
isFirstLayer: PropTypes.bool,
isLastLayer: PropTypes.bool,
layerIndex: PropTypes.number,
}

static defaultProps = {
Expand Down Expand Up @@ -176,6 +186,13 @@ export default class LayerEditor extends React.Component {
}
}

moveLayer(offset) {
this.props.onMoveLayer({
oldIndex: this.props.layerIndex,
newIndex: this.props.layerIndex+offset
})
}

render() {
const layerType = this.props.layer.type
const groups = layoutGroups(layerType).filter(group => {
Expand All @@ -192,8 +209,73 @@ export default class LayerEditor extends React.Component {
</LayerEditorGroup>
})

const layout = this.props.layer.layout || {}

const items = {
delete: {
text: "Delete",
handler: () => this.props.onLayerDestroy(this.props.layer.id)
},
duplicate: {
text: "Duplicate",
handler: () => this.props.onLayerCopy(this.props.layer.id)
},
hide: {
text: (layout.visibility === "none") ? "Show" : "Hide",
handler: () => this.props.onLayerVisibilityToggle(this.props.layer.id)
},
moveLayerUp: {
text: "Move layer up",
// Not actually used...
disabled: this.props.isFirstLayer,
handler: () => this.moveLayer(-1)
},
moveLayerDown: {
text: "Move layer down",
// Not actually used...
disabled: this.props.isLastLayer,
handler: () => this.moveLayer(+1)
}
}

function handleSelection(id, event) {
event.stopPropagation;
items[id].handler();
}

return <div className="maputnik-layer-editor"
>
<header>
<div className="layer-header">
<h2 className="layer-header__title">
Layer: {this.props.layer.id}
</h2>
<div className="layer-header__info">
<Wrapper
className='more-menu'
onSelection={handleSelection}
closeOnSelection={false}
>
<Button className='more-menu__button'>
<MoreVertIcon className="more-menu__button__svg" />
</Button>
<Menu>
<ul className="more-menu__menu">
{Object.keys(items).map((id, idx) => {
const item = items[id];
return <li key={id}>
<MenuItem value={id} className='more-menu__menu__item'>
{item.text}
</MenuItem>
</li>
})}
</ul>
</Menu>
</Wrapper>
</div>
</div>

</header>
{groups}
</div>
}
Expand Down
Loading

0 comments on commit edd09ef

Please sign in to comment.