Skip to content

Commit 41fa99b

Browse files
committed
added clone and remove functionality to dropdown menu in layer edit - closes #25
1 parent 8addc68 commit 41fa99b

File tree

9 files changed

+156
-123
lines changed

9 files changed

+156
-123
lines changed

src/App.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,10 @@ label .badge{position:relative;top:2px;}
144144
.md-shadow{text-shadow:1px 1px 2px rgba(0,0,0,0.2);}
145145
.md-muted{opacity:0.2;}
146146

147+
.modal-container{position:absolute;top:0;bottom:0;left:0;right:0;}
148+
.modal-backdrop{position:absolute;top:0;bottom:0;left:0;right:0;background-color:rgba(39,50,55,0.6);}
149+
.modal-content{position:relative;margin:0.75em;background:#fff;z-index:1041;width:inherit;}
150+
147151
.nav-link{border-bottom:3px solid transparent;cursor:pointer;position:relative;}
148152
.nav-item .active{}
149153
/*.nav-link.active{border-bottom:3px solid #FFF;}*/

src/model/Mlayer.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,36 @@ export default {
6262
return part;
6363
},
6464

65+
clone:function(layerId){
66+
67+
return new Promise((resolve,reject)=>{
68+
if (!layerId) return reject('no layerId');
69+
70+
const layer = this.get(layerId);
71+
72+
const idRoot = layer.get('id').replace(/_[0-9]+$/,'');
73+
74+
let num = 1,
75+
newId = layer.get('id'),
76+
existing;
77+
while (existing = this.get(newId)){
78+
num++;
79+
newId = idRoot+'_'+num;
80+
}
81+
const layerCopy = layer.setIn(['id'],newId);
82+
83+
Store.dispatch({
84+
type:'LAYER_ADD_AFTER',
85+
afterId:layerId,
86+
payload:layerCopy
87+
});
88+
89+
Mstyle.save();
90+
return resolve(layerCopy);
91+
});
92+
93+
},
94+
6595
set:function(layerId,layer){
6696
return new Promise((resolve,reject)=>{
6797
if (!layerId) return reject('no layerId');

src/reducer/Rstyle.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,21 @@ export default function(state = iState, action){
3838
const style = state.setIn(['rec','layers'],layers);
3939
return setUpdated(style);
4040
}
41+
case 'LAYER_ADD_AFTER':{
42+
// action afterId
43+
const afterInd = state.getIn(['rec','layers']).findIndex((layer)=>{
44+
return layer.get('id') === action.afterId;
45+
});
46+
47+
const layer = fromJS(action.payload);
48+
if (!state.hasIn(['rec','layers'])){
49+
const style = state.setIn(['rec','layers'],List([layer]));
50+
return setUpdated(style);
51+
}
52+
const layers = state.getIn(['rec','layers']).splice(afterInd+1,0,layer)
53+
const style = state.setIn(['rec','layers'],layers);
54+
return setUpdated(style);
55+
}
4156
case 'LAYER_REORDER':{
4257
const layer = state.getIn(['rec','layers',action.sourceIndex]);
4358
const layers = state.getIn(['rec','layers']).splice(action.sourceIndex,1).splice(action.destIndex,0,layer);

src/view/Vconfig/index.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export default class Vconfig extends React.Component {
2121
render (){
2222
const {config, error, handle} = this.props;
2323

24-
return <div className="p-2 bg-white">
24+
return <div className="p-2 bg-white container">
2525
<VconfigTokens config={config} error={error} handle={handle}/>
2626
</div>;
2727

src/view/Vlayer/VlayerDelete.jsx

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
4+
import Mlayer from '../../model/Mlayer';
5+
6+
export default class VlayerDelete extends React.Component {
7+
static propTypes = {
8+
layer: PropTypes.object.isRequired,
9+
handle: PropTypes.object
10+
}
11+
12+
constructor(props) {
13+
super(props);
14+
15+
const {handle,layer} = this.props;
16+
17+
this.handle = {
18+
deleteConfirm:()=>{
19+
handle.route('layer');
20+
Mlayer.remove(layer.get('id')).then(()=>{
21+
22+
});
23+
}
24+
};
25+
26+
for (let i in this.handle){
27+
this.handle[i] = this.handle[i].bind(this);
28+
}
29+
}
30+
31+
render (){
32+
const {style, layer} = this.props;
33+
34+
//console.log('source options:',sourceOptions);
35+
// loop through editable layer props and display edit interface for each
36+
37+
return <div>
38+
<div className="p-2">
39+
40+
<div className="form-group">
41+
<label>Are you sure you want to delete this layer?</label>
42+
<button onClick={this.handle.deleteConfirm} type="submit" className="btn btn-danger btn-sm">
43+
Delete Layer
44+
</button>
45+
</div>
46+
47+
</div>
48+
</div>;
49+
}
50+
};

src/view/Vlayer/VlayerEdit.jsx

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import Valert from '../Valert';
55
import VlayerEditId from './VlayerEditId';
66
import VlayerEditJSON from './VlayerEditJSON';
77
import VlayerEditor from './VlayerEditor';
8-
import VlayerOperation from './VlayerOperation';
8+
import VlayerDelete from './VlayerDelete';
99

1010
import Mlayer from '../../model/Mlayer';
1111
import Mstyle from '../../model/Mstyle';
@@ -51,11 +51,19 @@ export default class VlayerEdit extends React.Component {
5151
clickJson:()=>{
5252
this.setState({mode:'json'});
5353
},
54-
clickOperation:()=>{
55-
this.setState({mode:'operation'});
54+
clickDelete:()=>{
55+
this.setState({modal:'delete'});
5656
},
5757
editIdShow:()=>{
5858
this.setState({editId:true});
59+
},
60+
clone:()=>{
61+
Mlayer.clone(this.id).then((newLayer)=>{
62+
handle.routeReplace('layer/'+newLayer.get('id'));
63+
});
64+
},
65+
modalClose:()=>{
66+
this.setState({modal:null});
5967
}
6068
};
6169

@@ -83,20 +91,24 @@ export default class VlayerEdit extends React.Component {
8391
return <Valert message="no layer found"/>;
8492
}
8593

86-
let section;
94+
let section, modal;
8795
switch (this.state.mode){
8896
case 'json':
8997
section = <VlayerEditJSON handle={{...handle,change:this.handle.jsonChange}} error={layerError} layer={layer}/>;
9098
break;
9199
case 'edit':
92100
section = <VlayerEditor key={this.id} handle={handle} error={layerError} layer={layer}/>;
93101
break;
94-
case 'operation':
95-
section = <VlayerOperation key={this.id} handle={handle} error={layerError} layer={layer}/>;
102+
103+
}
104+
105+
switch (this.state.modal){
106+
case 'delete':
107+
modal = <VlayerDelete key={this.id} handle={handle} error={layerError} layer={layer}/>;
96108
break;
97109
}
98110

99-
return <div className="">
111+
return <div>
100112
<h2 className="px-2 py-1 m-0 text-nav bg-light row">
101113
<div className="text-overflow-ellipsis flex-2 edit-name mr-2" onClick={this.handle.editIdShow}>
102114
{this.state.editId ?
@@ -112,12 +124,31 @@ export default class VlayerEdit extends React.Component {
112124
<div onClick={this.handle.clickJson} className={'d-inline-block layer-nav-link px-1 '+(this.state.mode === 'json' ? 'active': '')}>
113125
<i className="material-icons md-18 icon-btn gray">code</i>
114126
</div>
127+
<div data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" className="d-inline-block layer-nav-link px-1">
128+
<i className="material-icons md-18 icon-btn gray">arrow_drop_down</i>
129+
</div>
130+
<div className="dropdown-menu" style={{lineHeight:1.5}} data-boundary="window">
131+
<a key="clone" onClick={this.handle.clone} className="dropdown-item" href="javascript:">clone layer</a>
132+
<a key="delete" onClick={this.handle.clickDelete} className="dropdown-item" href="javascript:">delete layer</a>
133+
</div>
115134

116135
</div>
117136
</h2>
118-
<div>
119-
{section}
137+
<div className="position-relative">
138+
{section}
139+
{modal &&
140+
<div className="modal-container">
141+
<div className="modal-backdrop"></div>
142+
<div className="modal-content pt-3">
143+
<button onClick={this.handle.modalClose} className="btn btn-light btn-xs position-absolute close-pos">
144+
<i className="material-icons md-14">close</i>
145+
</button>
146+
{modal}
147+
</div>
148+
</div>
149+
}
120150
</div>
151+
121152
</div>;
122153
}
123154
};

src/view/Vlayer/VlayerEditor.jsx

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -73,19 +73,6 @@ export default class VlayerEditor extends React.Component {
7373
Mlayer.removeIn(layer.get('id'),pos);
7474
},
7575

76-
deleteConfirm:()=>{
77-
handle.route('layer');
78-
Mlayer.remove(layer.get('id')).then(()=>{
79-
80-
});
81-
},
82-
deleteShow:()=>{
83-
this.setState({deleteShow:true});
84-
},
85-
deleteHide:()=>{
86-
this.setState({deleteShow:false});
87-
},
88-
8976
getScrollElem:()=>{
9077
return handle.getScrollElem();
9178
}
@@ -198,24 +185,6 @@ export default class VlayerEditor extends React.Component {
198185
<VlayerGroup type="settings" open={false} handle={this.handle} focus={this.state.focus} layer={layer} error={error}/>
199186
<VlayerGroup type="paint" open={true} handle={this.handle} focus={this.state.focus} layer={layer} error={error}/>
200187
<VlayerGroup type="layout" open={true} handle={this.handle} focus={this.state.focus} layer={layer} error={error}/>
201-
<div>
202-
{this.state.deleteShow ?
203-
<div className="form-group my-2 text-right">
204-
<button onClick={this.handle.deleteConfirm} type="submit" className="btn btn-danger btn-sm mr-2">
205-
Delete Layer
206-
</button>
207-
<button onClick={this.handle.deleteHide} type="submit" className="btn btn-light btn-sm">
208-
<i className="material-icons md-18">close</i>
209-
</button>
210-
</div>
211-
:
212-
<div className="form-group my-2 text-right">
213-
<button onClick={this.handle.deleteShow} type="submit" className="btn btn-light btn-sm">
214-
<i className="material-icons md-18">delete</i>
215-
</button>
216-
</div>
217-
}
218-
</div>
219188
</div>;
220189

221190
//

src/view/Vlayer/VlayerOperation.jsx

Lines changed: 0 additions & 68 deletions
This file was deleted.

src/view/Vnav/index.jsx

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,22 @@ export default class Vnav extends React.Component {
1818
*/
1919

2020
return <nav className="navbar navbar-expand-lg navbar-light bg-light">
21-
<Link to={paths.home} className="navbar-brand">
22-
<img src="/img/icon.png" width="30" height="30" className="d-inline-block align-top" alt=""/>
23-
</Link>
24-
<button className="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
25-
<span className="navbar-toggler-icon"></span>
26-
</button>
27-
<div className="collapse navbar-collapse">
28-
<ul className="navbar-nav">
29-
<li className="nav-item">
30-
<NavLink to={paths.config} className="nav-link" activeClassName="active">
31-
config
32-
</NavLink>
33-
</li>
34-
</ul>
21+
<div className="container-fluid">
22+
<Link to={paths.home} className="navbar-brand">
23+
<img src="/img/icon.png" width="30" height="30" className="d-inline-block align-top" alt=""/>
24+
</Link>
25+
<button className="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
26+
<span className="navbar-toggler-icon"></span>
27+
</button>
28+
<div className="collapse navbar-collapse">
29+
<ul className="navbar-nav">
30+
<li className="nav-item">
31+
<NavLink to={paths.config} className="nav-link" activeClassName="active">
32+
config
33+
</NavLink>
34+
</li>
35+
</ul>
36+
</div>
3537
</div>
3638
</nav>
3739

0 commit comments

Comments
 (0)