Skip to content

Commit 6254362

Browse files
authored
Merge pull request #98 from go-spatial/dev
Clone functionality
2 parents f42fbd7 + 6528d06 commit 6254362

15 files changed

+305
-42
lines changed

src/App.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ label .badge{position:relative;top:2px;}
245245
.modal{background-color:rgba(39,50,55,0.75);}
246246
.modal-container{position:absolute;top:0;bottom:0;left:0;right:0;}
247247
.modal-backdrop{position:absolute;top:0;bottom:0;left:0;right:0;background-color:rgba(39,50,55,0.6);}
248-
.modal-content{position:relative;margin:0.75em;background:#fff;z-index:1041;width:inherit;}
248+
.modal-content{position:relative;margin:0.75em;background:#fff;z-index:1041;}
249249

250250
.navbar-pill{display:inline-block;border-radius:0.25rem 0.25rem 0 0;padding:0.25rem;
251251
margin:0.5rem 0 0 0.5rem;}

src/component/Field/FieldSelect.jsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import React from 'react'
22
import PropTypes from 'prop-types'
33

4+
import modelLayer from '../../model/layer'
5+
46
class FieldSelect extends React.Component {
57

68
handleChange = (e)=>{
@@ -21,6 +23,11 @@ class FieldSelect extends React.Component {
2123
handle.blur && handle.blur(name)
2224
}
2325

26+
handleSubmit = async ()=>{
27+
const {layer, path, style} = this.props
28+
await modelLayer.actions.clone({layer, path, style})
29+
}
30+
2431
render (){
2532
const {autoFocus, helper, label, name, options, placeholder, value} = this.props
2633

src/component/Infotip/InfotipMessage.jsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ class InfotipMessage extends React.Component {
3939
}
4040

4141
componentWillUnmount (){
42-
console.log('cleanup:',this.parentEl)
4342
document.body.removeChild(this.parentEl)
4443
}
4544

src/component/LayerAdd/index.jsx

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import PropTypes from 'prop-types'
22
import React from 'react'
3+
import {withRouter} from 'react-router-dom'
34

45
import utilUrl from '../../utility/utilUrl'
56

67
import modelApp from '../../model/app'
78
import modelLayer from '../../model/layer'
89
import modelSource from '../../model/source'
10+
import modelStyle from '../../model/style'
911

1012
import Alert from '../Alert'
1113
import Property from '../Property'
@@ -15,29 +17,36 @@ class LayerAdd extends React.Component {
1517
constructor(props) {
1618
super(props)
1719

20+
// check for query params
21+
const query = new URLSearchParams(window.location.search)
22+
1823
this.state = {
1924
rec:{
20-
id:'',
21-
source:'',
22-
'source-layer':'',
23-
type:''
25+
id:query.has('source-layer')? query.get('source-layer'): '',
26+
source:query.has('source')? query.get('source'): '',
27+
'source-layer':query.has('source-layer')? query.get('source-layer'): '',
28+
type:query.has('type')? query.get('type'): '',
2429
},
2530
error:null
2631
}
2732
}
2833

2934
handleSubmit = async (e)=>{
3035
e.preventDefault()
31-
const {path, style} = this.props,
36+
const {history, path, style} = this.props,
3237
{rec} = this.state
3338

3439
try{
40+
41+
if (style.getIn(['current','layers']).find(layer => layer.get('id') === rec.id)){
42+
throw new Error(`LayerAdd.submit: layerId already exists`)
43+
}
3544
await modelApp.actions.setLoading(true)
3645
await modelLayer.actions.add({path, rec, style})
3746
await modelApp.actions.setLoading(false)
3847

39-
// route user to layer
40-
// handle.route('layer/'+layer.id)
48+
const route = `layers/${rec.id}`
49+
history.push(modelStyle.helpers.getRouteFromPath({path, route}))
4150
} catch(e){
4251
await modelApp.actions.setLoading(false)
4352
await modelApp.actions.setError(e)
@@ -53,8 +62,6 @@ class LayerAdd extends React.Component {
5362

5463
let id = parts.join('.')
5564

56-
// TODO: check for layer id collisions
57-
5865
this.setState({rec:{
5966
...rec,
6067
id
@@ -86,9 +93,9 @@ class LayerAdd extends React.Component {
8693
{rec} = this.state
8794

8895
const typeOptions = modelLayer.helpers.getTypeOptions()
89-
const sourceOptions = modelSource.helpers.getOptions({style})
90-
const sourceLayerOptions = (this.state.source)? modelSource.helpers.getLayerOptions({style, sourceId:this.state.source}):
91-
null
96+
const sourceOptions = modelSource.helpers.getOptions({style}) || []
97+
const sourceLayerOptions = rec.source? modelSource.helpers.getLayerOptions({style, sourceId:rec.source}):
98+
[]
9299

93100
const handle = {
94101
change: this.handleChange
@@ -165,10 +172,11 @@ class LayerAdd extends React.Component {
165172
}
166173

167174
LayerAdd.propTypes = {
175+
history: PropTypes.object,
168176
handle: PropTypes.object,
169177
match: PropTypes.object,
170178
path: PropTypes.array,
171179
style: PropTypes.object,
172180
}
173181

174-
export default LayerAdd
182+
export default withRouter(LayerAdd)

src/component/LayerEdit/LayerEditActions.jsx

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import React from 'react'
22
import PropTypes from 'prop-types'
3-
import {withRouter} from 'react-router-dom'
43

54
import utilPath from '../../utility/utilPath'
65

76
import Icon from '../Icon'
87
import LayerEditModalRemove from './LayerEditModalRemove'
9-
10-
import modelLayer from '../../model/layer'
8+
import LayerEditModalClone from './LayerEditModalClone'
119

1210
class LayerEditActions extends React.Component {
1311
constructor (props){
@@ -19,8 +17,9 @@ class LayerEditActions extends React.Component {
1917
}
2018

2119
handleClone = async ()=>{
22-
const {layer} = this.props
23-
await modelLayer.actions.clone({layer})
20+
this.setState({
21+
modal: 'cloneDone'
22+
})
2423
}
2524

2625
handleModalSet = (modal)=>{
@@ -46,7 +45,7 @@ class LayerEditActions extends React.Component {
4645
</h2>
4746
<div className="content-body">
4847
<div className="content-body-row">
49-
<button disabled="disabled" onClick={()=>this.handleClone()} className="btn btn-sm btn-outline-dark btn-block">
48+
<button onClick={()=>this.handleClone()} className="btn btn-sm btn-outline-dark btn-block">
5049
<Icon className="mr-1" icon={'clone'}/>
5150
Clone Layer
5251
</button>
@@ -65,15 +64,23 @@ class LayerEditActions extends React.Component {
6564
}
6665

6766
renderModal (){
68-
const {path, style} = this.props,
67+
const {layer, path, style} = this.props,
6968
{modal} = this.state
7069

7170
switch (modal){
7271
case 'remove':
7372
return (
7473
<LayerEditModalRemove
7574
handleClose={()=>this.handleModalSet(null)}
76-
handleDone={this.handleRemoveDone}
75+
layer={layer}
76+
path={path}
77+
style={style}/>
78+
)
79+
case 'cloneDone':
80+
return (
81+
<LayerEditModalClone
82+
handleClose={()=>this.handleModalSet(null)}
83+
layer={layer}
7784
path={path}
7885
style={style}/>
7986
)
@@ -92,4 +99,4 @@ LayerEditActions.propTypes = {
9299
style: PropTypes.object,
93100
}
94101

95-
export default withRouter(LayerEditActions)
102+
export default LayerEditActions
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
import React from 'react'
2+
import PropTypes from 'prop-types'
3+
import Modal from '../Modal'
4+
import {withRouter} from 'react-router-dom'
5+
6+
import modelApp from '../../model/app'
7+
import modelLayer from '../../model/layer'
8+
import modelStyle from '../../model/style'
9+
10+
import Property from '../Property'
11+
12+
class LayerEditModalClone extends React.Component {
13+
14+
constructor(props) {
15+
super(props)
16+
const {layer, style} = props
17+
18+
const cloneId = modelLayer.helpers.getLayerCloneId({layer, style})
19+
20+
this.state = {
21+
id: cloneId,
22+
placement: '',
23+
}
24+
}
25+
26+
handleClone = async ()=>{
27+
const {history, layer, path, style} = this.props,
28+
{id, placement} = this.state
29+
30+
try{
31+
await modelApp.actions.setLoading(true)
32+
33+
const clone = await modelLayer.actions.clone({cloneId: id, layer, path, placement, style})
34+
await modelApp.actions.setLoading(false)
35+
36+
// send user to newly created layer
37+
const route = `layers/${clone.get('id')}`
38+
history.push(modelStyle.helpers.getRouteFromPath({path, route}))
39+
40+
} catch(e){
41+
await modelApp.actions.setLoading(false)
42+
await modelApp.actions.setError(e)
43+
}
44+
45+
this.setState({
46+
modal: 'cloneDone'
47+
})
48+
}
49+
50+
handleChange = ({name, value})=>{
51+
let state = {}
52+
state[name] = value
53+
54+
this.setState(state)
55+
}
56+
57+
render (){
58+
const {handleClose} = this.props,
59+
{id, placement} = this.state
60+
61+
//const stylePath = modelStyle.helpers.getRouteFromPath({path})
62+
63+
const handle = {
64+
change: this.handleChange
65+
}
66+
67+
const options = [
68+
{name:'at the bottom', value:'bottom'},
69+
{name:'after cloned layer', value:'after'},
70+
]
71+
72+
return (
73+
<Modal>
74+
<div className="modal-header text-dark">
75+
<h5 className="modal-title">CLONE LAYER</h5>
76+
<button type="button" className="close" data-dismiss="modal" aria-label="Close" onClick={handleClose}>
77+
<span aria-hidden="true">&times;</span>
78+
</button>
79+
</div>
80+
<div className="modal-body text-left text-dark">
81+
82+
<Property
83+
handle={handle}
84+
info={'id for the layer clone'}
85+
key={'id'}
86+
label={'new layer id'}
87+
name={'id'}
88+
path={null}
89+
required={true}
90+
type={'string'}
91+
value={id}
92+
/>
93+
<Property
94+
handle={handle}
95+
info={'placement of the cloned layer'}
96+
key={'placement'}
97+
label={'placement'}
98+
name={'placement'}
99+
options={options}
100+
path={null}
101+
required={true}
102+
type={'enum'}
103+
value={placement}
104+
/>
105+
106+
</div>
107+
<div className="modal-footer">
108+
<button onClick={this.handleClone} className="btn btn-outline-dark">Create</button>
109+
</div>
110+
</Modal>
111+
)
112+
}
113+
114+
}
115+
116+
LayerEditModalClone.propTypes = {
117+
handleClose: PropTypes.func.isRequired,
118+
handleDone: PropTypes.func,
119+
history: PropTypes.object,
120+
layer: PropTypes.object,
121+
path: PropTypes.array,
122+
style: PropTypes.object,
123+
}
124+
125+
export default withRouter(LayerEditModalClone)
126+

src/component/LayerEdit/LayerEditModalRemove.jsx

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,36 @@
11
import React from 'react'
22
import PropTypes from 'prop-types'
33
import Modal from '../Modal'
4+
import {withRouter} from 'react-router-dom'
45

56
import modelApp from '../../model/app'
7+
import modelLayer from '../../model/layer'
68
import modelStyle from '../../model/style'
79

810
class LayerEditModalRemove extends React.Component {
911

1012
handleRemove = async ()=>{
11-
const {handleDone, path} = this.props
13+
const {history, layer, path, style} = this.props
1214

1315
try{
1416
await modelApp.actions.setLoading(true)
17+
18+
const layerIndex = modelLayer.helpers.getIndexById({layerId: layer.get('id'), style})
19+
if (layerIndex === -1) throw new Error(`LayerEditModalRemove.handleRemove: no layer found to clone`)
20+
1521
await modelStyle.actions.removeIn({
1622
path
1723
})
1824
await modelApp.actions.setLoading(false)
19-
handleDone()
25+
26+
// send user to prev layer
27+
const prevIndex = layerIndex === 0? 1: layerIndex - 1
28+
// get prev layer
29+
const prevLayer = style.getIn(['current','layers', prevIndex])
30+
const route = prevLayer? `layers/${prevLayer.get('id')}`: 'layers'
31+
32+
history.push(modelStyle.helpers.getRouteFromPath({path, route}))
33+
2034
} catch(e){
2135
await modelApp.actions.setLoading(false)
2236
await modelApp.actions.setError(e)
@@ -35,7 +49,7 @@ class LayerEditModalRemove extends React.Component {
3549
</button>
3650
</div>
3751
<div className="modal-body text-left text-dark">
38-
<p>Are you sure you want to remove this layer?</p>
52+
<p className="mb-0">Are you sure you want to remove this layer?</p>
3953

4054
</div>
4155
<div className="modal-footer">
@@ -50,8 +64,11 @@ class LayerEditModalRemove extends React.Component {
5064
LayerEditModalRemove.propTypes = {
5165
handleClose: PropTypes.func.isRequired,
5266
handleDone: PropTypes.func,
67+
history: PropTypes.object,
68+
layer: PropTypes.object,
5369
path: PropTypes.array,
70+
style: PropTypes.object,
5471
}
5572

56-
export default LayerEditModalRemove
73+
export default withRouter(LayerEditModalRemove)
5774

0 commit comments

Comments
 (0)