Cleanup, UI polishing

pull/746/head
Piero Toffanin 2019-11-07 13:27:34 -05:00
rodzic c347e02a73
commit 115d860179
10 zmienionych plików z 77 dodań i 63 usunięć

Wyświetl plik

@ -1,4 +1,5 @@
import rasterio
import os
from django.http import HttpResponse
from rio_tiler.errors import TileOutsideBounds
from rio_tiler.mercator import get_zooms
@ -109,7 +110,11 @@ class Metadata(TaskNestedView):
raster_path = get_raster_path(task, tile_type)
info = main.metadata(raster_path, pmin=2.0, pmax=98.0)
info['address'] = get_tile_url(task, tile_type)
info['address'] = os.path.basename(info['address'])
info['name'] = task.name
info['scheme'] = 'xyz'
info['tiles'] = [get_tile_url(task, tile_type)]
return Response(info)
class Tiles(TaskNestedView):

Wyświetl plik

@ -703,17 +703,22 @@ class Task(models.Model):
def get_tile_path(self, tile_type, z, x, y):
return self.assets_path("{}_tiles".format(tile_type), z, x, "{}.png".format(y))
def get_tile_json_url(self, tile_type):
return "/api/projects/{}/tasks/{}/{}/tiles.json".format(self.project.id, self.id, tile_type)
def get_tile_base_url(self, tile_type):
# plant is just a special case of orthophoto
if tile_type == 'plant':
tile_type = 'orthophoto'
return "/api/projects/{}/tasks/{}/{}/".format(self.project.id, self.id, tile_type)
def get_map_items(self):
types = []
if 'orthophoto.tif' in self.available_assets: types.append('orthophoto')
if 'orthophoto.tif' in self.available_assets: types.append('plant')
if 'dsm.tif' in self.available_assets: types.append('dsm')
if 'dtm.tif' in self.available_assets: types.append('dtm')
return {
'tiles': [{'url': self.get_tile_json_url(t), 'type': t} for t in types],
'tiles': [{'url': self.get_tile_base_url(t), 'type': t} for t in types],
'meta': {
'task': {
'id': str(self.id),

Wyświetl plik

@ -23,12 +23,10 @@ class MapView extends React.Component {
super(props);
this.state = {
opacity: 100,
selectedMapType: props.selectedMapType,
tiles: this.getTilesByMapType(props.selectedMapType)
};
this.updateOpacity = this.updateOpacity.bind(this);
this.getTilesByMapType = this.getTilesByMapType.bind(this);
this.handleMapTypeButton = this.handleMapTypeButton.bind(this);
}
@ -44,13 +42,6 @@ class MapView extends React.Component {
url: tile.url,
meta: mapItem.meta
});
// Special case for plant
// if (tile.type === 'orthophoto') tiles.push({
// url: tile.url + "?expr=(b2-b1)/(b2+b1-b3)&rescale=0,1&color_map=rdylgn",
// meta: mapItem.meta
// });
console.log(mapItem.meta);
});
});
@ -66,14 +57,7 @@ class MapView extends React.Component {
};
}
updateOpacity(evt) {
this.setState({
opacity: parseFloat(evt.target.value),
});
}
render(){
const { opacity } = this.state;
let mapTypeButtons = [
{
label: "Orthophoto",
@ -113,15 +97,14 @@ class MapView extends React.Component {
{this.props.title ?
<h3><i className="fa fa-globe"></i> {this.props.title}</h3>
: ""}
<Map
tiles={this.state.tiles}
showBackground={true}
opacity={opacity}
mapType={this.state.selectedMapType}
public={this.props.public} />
<div className="opacity-slider theme-secondary hidden-xs">
Opacity: <input type="range" step="1" value={opacity} onChange={this.updateOpacity} />
<div className="map-container">
<Map
tiles={this.state.tiles}
showBackground={true}
mapType={this.state.selectedMapType}
public={this.props.public}
/>
</div>
</div>);
}

Wyświetl plik

@ -23,7 +23,6 @@ import update from 'immutability-helper';
class Map extends React.Component {
static defaultProps = {
showBackground: false,
opacity: 100,
mapType: "orthophoto",
public: false
};
@ -31,7 +30,6 @@ class Map extends React.Component {
static propTypes = {
showBackground: PropTypes.bool,
tiles: PropTypes.array.isRequired,
opacity: PropTypes.number,
mapType: PropTypes.oneOf(['orthophoto', 'plant', 'dsm', 'dtm']),
public: PropTypes.bool
};
@ -43,7 +41,8 @@ class Map extends React.Component {
error: "",
singleTask: null, // When this is set to a task, show a switch mode button to view the 3d model
pluginActionButtons: [],
showLoading: false
showLoading: false, // for drag&drop of files
opacity: 100
};
this.imageryLayers = [];
@ -56,6 +55,12 @@ class Map extends React.Component {
this.handleMapMouseDown = this.handleMapMouseDown.bind(this);
}
updateOpacity = (evt) => {
this.setState({
opacity: parseFloat(evt.target.value),
});
}
updatePopupFor(layer){
const popup = layer.getPopup();
$('#layerOpacity', popup.getContent()).val(layer.options.opacity);
@ -86,23 +91,25 @@ class Map extends React.Component {
async.each(tiles, (tile, done) => {
const { url, meta } = tile;
this.tileJsonRequests.push($.getJSON(url)
.done(info => {
this.tileJsonRequests.push($.getJSON(url + "metadata")
.done(mres => {
const { scheme, name, maxzoom } = mres;
const bounds = Leaflet.latLngBounds(
[info.bounds.slice(0, 2).reverse(), info.bounds.slice(2, 4).reverse()]
[mres.bounds.value.slice(0, 2).reverse(), mres.bounds.value.slice(2, 4).reverse()]
);
const layer = Leaflet.tileLayer(info.tiles[0], {
const layer = Leaflet.tileLayer(mres.tiles[0], {
bounds,
minZoom: 0,
maxZoom: info.maxzoom + 4,
maxNativeZoom: info.maxzoom,
tms: info.scheme === 'tms',
opacity: this.props.opacity / 100,
maxZoom: maxzoom + 4,
maxNativeZoom: maxzoom,
tms: scheme === 'tms',
opacity: this.state.opacity / 100,
detectRetina: true
});
// Associate metadata with this layer
meta.name = info.name;
meta.name = name;
layer[Symbol.for("meta")] = meta;
if (forceAddLayers || prevSelectedLayers.indexOf(layerId(layer)) !== -1){
@ -127,7 +134,7 @@ class Map extends React.Component {
var popup = L.DomUtil.create('div', 'infoWindow');
popup.innerHTML = `<div class="title">
${info.name}
${name}
</div>
<div class="popup-opacity-slider">Opacity: <input id="layerOpacity" type="range" value="${layer.options.opacity}" min="0" max="1" step="0.01" /></div>
<div>Bounds: [${layer.options.bounds.toBBoxString().split(",").join(", ")}]</div>
@ -155,7 +162,7 @@ class Map extends React.Component {
this.mapBounds = mapBounds;
// Add layer to layers control
this.autolayers.addOverlay(layer, info.name);
this.autolayers.addOverlay(layer, name);
done();
})
@ -333,7 +340,7 @@ https://a.tile.openstreetmap.org/{z}/{x}/{y}.png
componentDidUpdate(prevProps) {
this.imageryLayers.forEach(imageryLayer => {
imageryLayer.setOpacity(this.props.opacity / 100);
imageryLayer.setOpacity(this.state.opacity / 100);
this.updatePopupFor(imageryLayer);
});
@ -360,6 +367,10 @@ https://a.tile.openstreetmap.org/{z}/{x}/{y}.png
return (
<div style={{height: "100%"}} className="map">
<ErrorMessage bind={[this, 'error']} />
<div className="opacity-slider theme-secondary hidden-xs">
Opacity: <input type="range" step="1" value={this.state.opacity} onChange={this.updateOpacity} />
</div>
<Standby
message="Loading..."
show={this.state.showLoading}

Wyświetl plik

@ -5,12 +5,14 @@ import PropTypes from 'prop-types';
class Standby extends React.Component {
static defaultProps = {
message: "",
show: false
show: false,
opacity: 0.5
};
static propTypes = {
message: PropTypes.string,
show: PropTypes.bool
show: PropTypes.bool,
opacity: PropTypes.number
};
constructor(props){
@ -41,7 +43,7 @@ class Standby extends React.Component {
return (
<div className="standby"
style={{display: this.state.show ? "block" : "none"}}>
<div className="cover">&nbsp;</div>
<div className="cover" style={{opacity: this.props.opacity}}>&nbsp;</div>
<div className="content">
<i className="fa fa-spinner fa-spin fa-2x fa-fw"></i>
<p>{this.state.message}</p>

Wyświetl plik

@ -8,7 +8,7 @@ sinon.useFakeXMLHttpRequest();
describe('<Map />', () => {
it('renders without exploding', () => {
const wrapper = mount(<Map
tiles={['/tiles.json']} />);
tiles={['/']} />);
expect(wrapper.exists()).toBe(true);
})

Wyświetl plik

@ -1,6 +1,18 @@
.map{
position: relative;
.opacity-slider{
border-radius: 4px;
text-align: center;
width: 220px;
position: absolute;
bottom: 20px;
left: 50%;
margin-left: -100px;
z-index: 999;
padding-bottom: 6px;
}
.leaflet-popup-content{
.title{
font-weight: bold;

Wyświetl plik

@ -14,18 +14,15 @@
top: 6px;
}
.opacity-slider{
text-align: center;
width: 220px;
position: absolute;
bottom: -32px;
left: 50%;
margin-left: -100px;
z-index: 400;
padding-bottom: 6px;
}
.map-type-selector{
float: right;
}
.map-container{
height: 100%;
position: relative;
.standby{
z-index: 99999;
}
}
}

Wyświetl plik

@ -4,9 +4,8 @@
top: 0;
bottom: 0;
left: 0;
right: 0;
right: 0;
.cover{
opacity: 0.5;
background-color: #111;
position: absolute;
top: 0;
@ -23,5 +22,5 @@
right: 0;
padding: 0;
color: white;
}
}
}

Wyświetl plik

@ -2,7 +2,7 @@ import React, { Component, Fragment } from "react";
import PropTypes from 'prop-types';
import GoToFolderButton from "./components/GoToFolderButton";
import $ from "jquery"; // Fixes a AMD module definition error in webpack
import $ from "jquery"; // Fixes a AMD module definition error due to webpack
export default class TaskView extends Component {
static propTypes = {