Skip to content

Commit

Permalink
Merge pull request #1823 from allyoucanmap/background-selector
Browse files Browse the repository at this point in the history
Fix #1672 BackgroundSwitcher review
  • Loading branch information
Simone Giannecchini authored May 18, 2017
2 parents d56ef58 + 3c7bf43 commit 0c7d62f
Show file tree
Hide file tree
Showing 32 changed files with 1,107 additions and 9 deletions.
1 change: 1 addition & 0 deletions docma-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@
"jsapi": "web/client/jsapi/MapStore2.js",
"plugins": [
"web/client/plugins/index.jsdoc",
"web/client/plugins/BackgroundSelector.jsx",
"web/client/plugins/BackgroundSwitcher.jsx",
"web/client/plugins/DrawerMenu.jsx",
"web/client/plugins/GlobeViewSwitcher.jsx",
Expand Down
149 changes: 149 additions & 0 deletions web/client/components/background/BackgroundSelector.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/*
* Copyright 2017, GeoSolutions Sas.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/

const React = require('react');
const assign = require('object-assign');
const {isEmpty} = require('lodash');

const PreviewButton = require('./PreviewButton');
const PreviewList = require('./PreviewList');
const PreviewIcon = require('./PreviewIcon');

require('./css/background.css');

const BackgroundSelector = React.createClass({
propTypes: {
start: React.PropTypes.number,
left: React.PropTypes.number,
bottom: React.PropTypes.number,
enabled: React.PropTypes.bool,
layers: React.PropTypes.array,
currentLayer: React.PropTypes.object,
tempLayer: React.PropTypes.object,
size: React.PropTypes.object,
dimensions: React.PropTypes.object,
thumbs: React.PropTypes.object,
onPropertiesChange: React.PropTypes.func,
onToggle: React.PropTypes.func,
onLayerChange: React.PropTypes.func,
onStartChange: React.PropTypes.func
},
getDefaultProps() {
return {
start: 0,
bottom: 0,
left: 0,
enabled: false,
layers: [],
currentLayer: {},
tempLayer: {},
size: {width: 0, height: 0},
dimensions: {},
thumbs: {
unknown: require('./img/dafault.jpg')
},
onPropertiesChange: () => {},
onToggle: () => {},
onLayerChange: () => {},
onStartChange: () => {}
};
},
componentWillUnmount() {
this.props.onLayerChange('currentLayer', {});
this.props.onLayerChange('tempLayer', {});
this.props.onStartChange(0);
},
componentWillUpdate(nextProps) {
if (this.props.size.width !== nextProps.size.width
|| this.props.size.height !== nextProps.size.height) {
this.props.onStartChange(0);
}
},
getThumb(layer) {
return this.props.thumbs[layer.source] && this.props.thumbs[layer.source][layer.name] || layer.thumbURL || this.props.thumbs.unknown;
},
getLayer() {
const tempLyr = isEmpty(this.props.tempLayer) ? this.props.layers.filter((layer) => { return layer.visibility === true; })[0] : this.props.tempLayer;
const currentLyr = isEmpty(this.props.currentLayer) ? this.props.layers.filter((layer) => { return layer.visibility === true; })[0] : this.props.currentLayer;
return this.props.enabled ? tempLyr : currentLyr;
},
getIcons(side, frame, margin, vertical) {
return this.props.enabled ? this.props.layers.map((layer, idx) => {
let thumb = this.getThumb(layer);
return <PreviewIcon vertical={vertical} key={idx} src={thumb} currentLayer={this.props.currentLayer} margin={margin} side={side} frame={frame} layer={layer} onToggle={this.props.onToggle} onPropertiesChange={this.props.onPropertiesChange} onLayerChange={this.props.onLayerChange}/>;
}) : [];
},
getDimensions(side, frame, margin, left, size, iconsLength) {
const openPreviewSize = (side + frame * 2 + margin * 2) + (side + frame * 2 + margin) * iconsLength + left;
const minSize = (size / 2) - (side + frame * 2 + margin * 2) - left;
const pagination = openPreviewSize > size / 2;
let visibleIconsLength = Math.floor(minSize / (side + frame * 2 + margin));
visibleIconsLength = visibleIconsLength > iconsLength ? iconsLength : visibleIconsLength;
const listSize = this.props.enabled ? (side + frame + margin) * visibleIconsLength + 52 : 0;

return {pagination, listSize, visibleIconsLength};
},
renderBackgroundSelector() {
const configuration = assign({
side: 78,
sidePreview: 104,
frame: 3,
margin: 5,
label: true,
vertical: false
}, this.props.dimensions);

const frame = configuration.frame * 2;
const side = configuration.side - frame;
const sideButton = this.props.enabled ? configuration.sidePreview - frame : side;
const margin = configuration.margin;

const labelHeight = this.props.enabled ? sideButton - frame * 2 : 0;
const layer = this.getLayer();
const src = this.getThumb(layer);
const icons = this.getIcons(side, frame, margin, configuration.vertical);

const {pagination, listSize, visibleIconsLength} = this.getDimensions(side, frame, margin, this.props.left, configuration.vertical ? this.props.size.height : this.props.size.width, icons.length);
const buttonSize = side + frame + margin;
const buttonSizeWithMargin = side + frame + margin * 2;

const listContainerStyle = configuration.vertical ? {
bottom: this.props.bottom + buttonSizeWithMargin,
left: this.props.left,
width: buttonSizeWithMargin,
height: listSize
} : {
bottom: this.props.bottom,
left: this.props.left + sideButton + margin * 2 + frame,
width: listSize,
height: buttonSize
};

const previewListStyle = configuration.vertical ? {
height: buttonSize * visibleIconsLength,
width: buttonSize
} : {
height: buttonSize,
width: buttonSize * visibleIconsLength
};

return visibleIconsLength <= 0 && this.props.enabled ? null : (
<div className="background-plugin-position" style={{left: this.props.left, bottom: this.props.bottom}}>
<PreviewButton showLabel={configuration.label} src={src} side={sideButton} frame={frame} margin={margin} labelHeight={labelHeight} label={layer.title} onToggle={this.props.onToggle}/>
<div className="background-list-container" style={listContainerStyle}>
<PreviewList vertical={configuration.vertical} start={this.props.start} bottom={0} height={previewListStyle.height} width={previewListStyle.width} icons={icons} pagination={pagination} length={visibleIconsLength} onStartChange={this.props.onStartChange} />
</div>
</div>
);
},
render() {
return this.props.layers.length > 0 ? this.renderBackgroundSelector() : null;
}
});

module.exports = BackgroundSelector;
50 changes: 50 additions & 0 deletions web/client/components/background/PaginationButton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 2017, GeoSolutions Sas.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/

const React = require('react');
const {Glyphicon} = require('react-bootstrap');

const PaginationButton = React.createClass({
propTypes: {
side: React.PropTypes.number,
direction: React.PropTypes.bool,
vertical: React.PropTypes.bool,
glyphs: React.PropTypes.object,
onClick: React.PropTypes.func
},
getDefaultProps() {
return {
side: 0,
direction: true,
vertical: false,
glyphs: {
horizontal: {
next: 'chevron-right',
back: 'chevron-left'
},
vertical: {
next: 'chevron-down',
back: 'chevron-up'
}
},
onClick: () => {}
};
},
render() {
const glyph = this.props.glyphs[this.props.vertical ? 'vertical' : 'horizontal'][this.props.direction ? 'next' : 'back'];
const paginationClass = this.props.vertical ? 'background-plugin-pagination-btn-vertical text-center' : 'background-plugin-pagination-btn-horizontal';
const style = this.props.vertical ? {width: this.props.side} : {height: this.props.side};
return (
<div className={paginationClass + ' text-primary'} style={style} onClick={this.props.onClick}>
<Glyphicon glyph={glyph} />
</div>
);
}
});

module.exports = PaginationButton;
50 changes: 50 additions & 0 deletions web/client/components/background/PreviewButton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 2017, GeoSolutions Sas.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/

const React = require('react');

require('./css/previewbutton.css');

const PreviewButton = React.createClass({
propTypes: {
src: React.PropTypes.string,
side: React.PropTypes.number,
frame: React.PropTypes.number,
margin: React.PropTypes.number,
labelHeight: React.PropTypes.number,
label: React.PropTypes.string,
showLabel: React.PropTypes.bool,
onToggle: React.PropTypes.func
},
getDefaultProps() {
return {
src: './images/mapthumbs/none.jpg',
side: 50,
frame: 4,
margin: 5,
labelHeight: 29,
label: '',
showLabel: true,
onToggle: () => {}
};
},
render() {
return (
<div className="background-preview-button" style={{margin: this.props.margin}}>
<div className="background-preview-button-container bg-body" onClick={this.props.onToggle} style={{padding: this.props.frame / 2, width: this.props.side + this.props.frame, height: this.props.side + this.props.frame}}>
{this.props.showLabel ? (<div className="background-preview-button-label" style={{width: this.props.side, height: this.props.labelHeight, marginTop: 0, padding: 0}} ><div className="bg-body bg-text" style={{padding: this.props.frame }}>{this.props.label}</div></div>) : null}
<div className="background-preview-button-frame" style={{width: this.props.side, height: this.props.side}}>
<img src={this.props.src}/>
</div>
</div>
</div>
);
}
});

module.exports = PreviewButton;
59 changes: 59 additions & 0 deletions web/client/components/background/PreviewIcon.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright 2017, GeoSolutions Sas.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/

const React = require('react');

require('./css/previewicon.css');

const PreviewIcon = React.createClass({
propTypes: {
side: React.PropTypes.number,
frame: React.PropTypes.number,
margin: React.PropTypes.number,
src: React.PropTypes.string,
vertical: React.PropTypes.bool,
layer: React.PropTypes.object,
currentLayer: React.PropTypes.object,
onPropertiesChange: React.PropTypes.func,
onToggle: React.PropTypes.func,
onLayerChange: React.PropTypes.func
},
getDefaultProps() {
return {
side: 50,
frame: 4,
margin: 5,
src: '',
vertical: false,
layer: {},
currentLayer: {},
onPropertiesChange: () => {},
onToggle: () => {},
onLayerChange: () => {}
};
},
render() {
const containerClass = this.props.vertical ? 'background-preview-icon-container-vertical' : 'background-preview-icon-container-horizontal';
const type = this.props.layer.visibility ? ' bg-primary' : ' bg-body';
const invalid = this.props.layer.invalid ? ' disabled-icon' : '';

const click = this.props.layer.invalid ? () => {} : () => { this.props.onToggle(); this.props.onPropertiesChange(this.props.layer.id, {visibility: true}); this.props.onLayerChange('currentLayer', this.props.layer); };
return (
<div className={containerClass + type + invalid} style={{padding: this.props.frame / 2, marginLeft: this.props.vertical ? this.props.margin : 0, marginRight: this.props.vertical ? 0 : this.props.margin, marginBottom: this.props.margin, width: this.props.side + this.props.frame, height: this.props.side + this.props.frame}}>
<div className="background-preview-icon-frame" style={{width: this.props.side, height: this.props.side}}>
<img
onMouseOver={() => { this.props.onLayerChange('tempLayer', this.props.layer); }}
onMouseOut={() => { this.props.onLayerChange('tempLayer', this.props.currentLayer); }}
onClick={click} src={this.props.src}/>
</div>
</div>
);
}
});

module.exports = PreviewIcon;
57 changes: 57 additions & 0 deletions web/client/components/background/PreviewList.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright 2017, GeoSolutions Sas.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/

const React = require('react');
const PaginationButton = require('./PaginationButton');

const PreviewList = React.createClass({
propTypes: {
bottom: React.PropTypes.number,
width: React.PropTypes.number,
height: React.PropTypes.number,
length: React.PropTypes.number,
start: React.PropTypes.number,
pagination: React.PropTypes.bool,
vertical: React.PropTypes.bool,
icons: React.PropTypes.array,
onStartChange: React.PropTypes.func
},
getDefaultProps() {
return {
bottom: 0,
width: 0,
height: 0,
length: 0,
start: 0,
pagination: false,
vertical: false,
icons: [],
onStartChange: () => {}
};
},
render() {
let iconButtons = [].concat(this.props.icons);
iconButtons = iconButtons.slice(this.props.start, this.props.start + this.props.length);
if (this.props.pagination) {
if (this.props.start !== 0) {
iconButtons.unshift(<PaginationButton key="pagination_0" vertical={this.props.vertical} side={this.props.vertical ? this.props.width : this.props.height} direction={false} onClick={ () => { this.props.onStartChange(this.props.start - 1); }} />);
}
if (this.props.start + this.props.length !== this.props.icons.length) {
iconButtons.push(<PaginationButton key="pagination_1" vertical={this.props.vertical} side={this.props.vertical ? this.props.width : this.props.height} direction={true} onClick={ () => { this.props.onStartChange(this.props.start + 1); } } />);
}
}
const style = this.props.vertical ? { height: this.props.pagination ? this.props.height + 50 : this.props.height, width: this.props.width, bottom: this.props.bottom} : { height: this.props.height, width: this.props.pagination ? this.props.width + 50 : this.props.width, bottom: this.props.bottom};
return (
<div style={style}>
{iconButtons}
</div>
);
}
});

module.exports = PreviewList;
Loading

0 comments on commit 0c7d62f

Please sign in to comment.