Skip to content

Commit

Permalink
Merge pull request #444 from pierotofy/osm-editor-plugin
Browse files Browse the repository at this point in the history
OSM quick editor plugin
  • Loading branch information
pierotofy authored May 4, 2018
2 parents c21e7be + 6afba7e commit 5cd19f8
Show file tree
Hide file tree
Showing 58 changed files with 239 additions and 208 deletions.
9 changes: 6 additions & 3 deletions app/boot.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,18 +99,21 @@ def add_default_presets():
Preset.objects.update_or_create(name='DSM + DTM', system=True,
defaults={
'options': [{'name': 'dsm', 'value': True}, {'name': 'dtm', 'value': True},
{'name': 'mesh-octree-depth', 'value': 6}]})
{'name': 'mesh-octree-depth', 'value': 6},
{'name': 'mesh-solver-divide', 'value': 6}]})
Preset.objects.update_or_create(name='Fast Orthophoto', system=True,
defaults={'options': [{'name': 'fast-orthophoto', 'value': True}]})
Preset.objects.update_or_create(name='High Quality', system=True,
defaults={'options': [{'name': 'dsm', 'value': True},
{'name': 'mesh-octree-depth', 'value': "12"},
{'name': 'mesh-octree-depth', 'value': 6},
{'name': 'mesh-solver-divide', 'value': 6},
{'name': 'dem-resolution', 'value': "0.04"},
{'name': 'orthophoto-resolution', 'value': "40"},
]})
Preset.objects.update_or_create(name='Default', system=True,
defaults={'options': [{'name': 'dsm', 'value': True},
{'name': 'mesh-octree-depth', 'value': 6}]})
{'name': 'mesh-octree-depth', 'value': 6},
{'name': 'mesh-solver-divide', 'value': 6}]})
except MultipleObjectsReturned:
# Mostly to handle a legacy code problem where
# multiple system presets with the same name were
Expand Down
2 changes: 1 addition & 1 deletion app/static/app/js/MapView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class MapView extends React.Component {
opacity={opacity}
mapType={this.state.selectedMapType}
public={this.props.public} />
<div className="opacity-slider theme-secondary">
<div className="opacity-slider theme-secondary hidden-xs">
Opacity: <input type="range" step="1" value={opacity} onChange={this.updateOpacity} />
</div>
</div>);
Expand Down
1 change: 0 additions & 1 deletion app/static/app/js/ModelView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,6 @@ class ModelView extends React.Component {
{showSwitchModeButton ?
<SwitchModeButton
public={this.props.public}
style={{marginLeft: this.props.public ? '0' : '76px'}}
task={this.props.task}
type="modelToMap" /> : ""}
</div>
Expand Down
22 changes: 16 additions & 6 deletions app/static/app/js/classes/plugins/ApiFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,21 @@ export default class ApiFactory{

// @param api {Object}
create(api){

// Adds two functions to obj
// - eventName
// - triggerEventName
// We could just use events, but methods
// are more robust as we can detect more easily if
// things break
const addEndpoint = (obj, eventName, preTrigger = () => {}) => {
const emitResponse = (...args) => {
// Timeout needed for modules that have no dependencies
// and load synchronously. Gives time to setup the listeners.
setTimeout(() => {
this.events.emit(`${api.namespace}::${eventName}::Response`, ...args);
}, 0);
};

obj[eventName] = (callbackOrDeps, callbackOrUndef) => {
if (Array.isArray(callbackOrDeps)){
// Deps
Expand All @@ -24,20 +31,23 @@ export default class ApiFactory{
this.events.addListener(`${api.namespace}::${eventName}`, (...args) => {
Promise.all(callbackOrDeps.map(dep => SystemJS.import(dep)))
.then((...deps) => {
callbackOrUndef(...(Array.from(args).concat(...deps)));
emitResponse(callbackOrUndef(...(Array.from(args).concat(...deps))));
});
});
}else{
// Callback
this.events.addListener(`${api.namespace}::${eventName}`, callbackOrDeps);
this.events.addListener(`${api.namespace}::${eventName}`, (...args) => {
emitResponse(callbackOrDeps(...args));
});
}
}

const triggerEventName = "trigger" + eventName[0].toUpperCase() + eventName.slice(1);

obj[triggerEventName] = (...args) => {
preTrigger(...args);
this.events.emit(`${api.namespace}::${eventName}`, ...args);
obj[triggerEventName] = (params, responseCb) => {
preTrigger(params, responseCb);
this.events.emit(`${api.namespace}::${eventName}`, params);
if (responseCb) this.events.addListener(`${api.namespace}::${eventName}::Response`, responseCb);
};
}

Expand Down
4 changes: 3 additions & 1 deletion app/static/app/js/classes/plugins/Map.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@ const { assert } = Utils;

const leafletPreCheck = (options) => {
assert(options.map !== undefined);
assert(options.tiles !== undefined);
};

export default {
namespace: "Map",

endpoints: [
["willAddControls", leafletPreCheck],
["didAddControls", leafletPreCheck]
["didAddControls", leafletPreCheck],
["addActionButton", leafletPreCheck],
]
};

31 changes: 20 additions & 11 deletions app/static/app/js/components/Map.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import ShareButton from './ShareButton';
import AssetDownloads from '../classes/AssetDownloads';
import PropTypes from 'prop-types';
import PluginsAPI from '../classes/plugins/API';
import update from 'immutability-helper';

class Map extends React.Component {
static defaultProps = {
Expand All @@ -40,7 +41,8 @@ class Map extends React.Component {

this.state = {
error: "",
singleTask: null // When this is set to a task, show a switch mode button to view the 3d model
singleTask: null, // When this is set to a task, show a switch mode button to view the 3d model
pluginActionButtons: []
};

this.imageryLayers = [];
Expand Down Expand Up @@ -167,7 +169,7 @@ class Map extends React.Component {
}

componentDidMount() {
const { showBackground } = this.props;
const { showBackground, tiles } = this.props;

this.map = Leaflet.map(this.container, {
scrollWheelZoom: true,
Expand All @@ -176,7 +178,8 @@ class Map extends React.Component {
});

PluginsAPI.Map.triggerWillAddControls({
map: this.map
map: this.map,
tiles
});

Leaflet.control.scale({
Expand Down Expand Up @@ -236,11 +239,18 @@ class Map extends React.Component {
});
});

// PluginsAPI.events.addListener('Map::AddPanel', (e) => {
// console.log("Received response: " + e);
// });
PluginsAPI.Map.triggerDidAddControls({
map: this.map
map: this.map,
tiles: tiles
});

PluginsAPI.Map.triggerAddActionButton({
map: this.map,
tiles
}, (button) => {
this.setState(update(this.state, {
pluginActionButtons: {$push: [button]}
}));
});
}

Expand All @@ -251,9 +261,7 @@ class Map extends React.Component {
});

if (prevProps.tiles !== this.props.tiles){
this.loadImageryLayers().then(() => {
// console.log("GOT: ", this.autolayers, this.autolayers.selectedOverlays);
});
this.loadImageryLayers();
}
}

Expand All @@ -268,7 +276,7 @@ class Map extends React.Component {

handleMapMouseDown(e){
// Make sure the share popup closes
if (this.sharePopup) this.shareButton.hidePopup();
if (this.shareButton) this.shareButton.hidePopup();
}

render() {
Expand All @@ -285,6 +293,7 @@ class Map extends React.Component {


<div className="actionButtons">
{this.state.pluginActionButtons.map((button, i) => <div key={i}>{button}</div>)}
{(!this.props.public && this.state.singleTask !== null) ?
<ShareButton
ref={(ref) => { this.shareButton = ref; }}
Expand Down
111 changes: 56 additions & 55 deletions app/static/app/js/components/SharePopup.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,65 +71,66 @@ class SharePopup extends React.Component{
const iframeUrl = Utils.absoluteUrl(`public/task/${this.state.task.id}/iframe/${this.props.linksTarget}/`);
const iframeCode = `<iframe scrolling="no" title="WebODM" width="61.8033%" height="360" frameBorder="0" src="${iframeUrl}"></iframe>`;

return (<div onMouseDown={e => { e.stopPropagation(); }}
className={"sharePopup popover in " + this.props.placement}>
<div className="arrow"></div>
<h3 className="popover-title theme-background-highlight">Share This Task</h3>
<div className="popover-content theme-secondary">
<ErrorMessage bind={[this, 'error']} />
<div className="checkbox">
<button type="button"
className={"btn btn-qrcode btn-sm " +
(this.state.showQR ? "btn-primary " : "btn-default ") +
(!this.state.task.public ? "hide" : "")}
onClick={this.toggleQRCode}>
<i className="fa fa-qrcode"></i> QR
</button>
return (<div onMouseDown={e => { e.stopPropagation(); }} className={"sharePopup " + this.props.placement}>
<div className={"sharePopupContainer popover in " + this.props.placement}>
<div className="arrow"></div>
<h3 className="popover-title theme-background-highlight">Share This Task</h3>
<div className="popover-content theme-secondary">
<ErrorMessage bind={[this, 'error']} />
<div className="checkbox">
<button type="button"
className={"btn btn-qrcode btn-sm " +
(this.state.showQR ? "btn-primary " : "btn-default ") +
(!this.state.task.public ? "hide" : "")}
onClick={this.toggleQRCode}>
<i className="fa fa-qrcode"></i> QR
</button>

<label onClick={this.handleEnableSharing}>
{this.state.togglingShare ?
<i className="fa fa-refresh fa-spin fa-fw"></i>
: ""}
<label onClick={this.handleEnableSharing}>
{this.state.togglingShare ?
<i className="fa fa-refresh fa-spin fa-fw"></i>
: ""}

<input
className={this.state.togglingShare ? "hide" : ""}
type="checkbox"
checked={this.state.task.public}
onChange={() => {}}
/> Enabled
</label>
</div>
<div className={"share-links " + (this.state.task.public ? "show" : "")}>
<div className={"form-group " + (this.state.showQR ? "hide" : "")}>
<label>
Link:
<ClipboardInput
type="text"
className="form-control"
value={shareLink}
readOnly={true}
/>
</label>
</div>
<div className={"form-group " + (this.state.showQR ? "hide" : "")}>
<label>
HTML iframe:
<ClipboardInput
type="text"
className="form-control"
value={iframeCode}
readOnly={true}
/>
<input
className={this.state.togglingShare ? "hide" : ""}
type="checkbox"
checked={this.state.task.public}
onChange={() => {}}
/> Enabled
</label>
</div>
<div className={(this.state.showQR ? "" : "hide")}>
<QRCode
value={shareLink}
size={200}
bgColor={"#ffffff"}
fgColor={"#000000"}
level={"M"}
/>
<div className={"share-links " + (this.state.task.public ? "show" : "")}>
<div className={"form-group " + (this.state.showQR ? "hide" : "")}>
<label>
Link:
<ClipboardInput
type="text"
className="form-control"
value={shareLink}
readOnly={true}
/>
</label>
</div>
<div className={"form-group " + (this.state.showQR ? "hide" : "")}>
<label>
HTML iframe:
<ClipboardInput
type="text"
className="form-control"
value={iframeCode}
readOnly={true}
/>
</label>
</div>
<div className={(this.state.showQR ? "" : "hide")}>
<QRCode
value={shareLink}
size={200}
bgColor={"#ffffff"}
fgColor={"#000000"}
level={"M"}
/>
</div>
</div>
</div>
</div>
Expand Down
11 changes: 8 additions & 3 deletions app/static/app/js/css/Map.scss
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,14 @@
margin-bottom: 6px;
}

.shareButton{
.actionButtons{
position: absolute;
z-index: 2000;
bottom: 11px;
right: 38px;
right: 12px;
bottom: 20px;
& > *{
display: inline-block;
margin-left: 12px;
}
}
}
2 changes: 1 addition & 1 deletion app/static/app/js/css/ModelView.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
position: relative;
height: 100%;

canvas{
#potree_render_area > canvas{
width: 100% !important;
height: 100% !important;
}
Expand Down
1 change: 0 additions & 1 deletion app/static/app/js/css/ShareButton.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
.shareButton{
position: absolute;
button{
border-width: 1px;
}
Expand Down
Loading

0 comments on commit 5cd19f8

Please sign in to comment.