kopia lustrzana https://github.com/OpenDroneMap/WebODM
UI improvements
rodzic
bdf9fcfebf
commit
f76077775e
|
@ -121,6 +121,8 @@ That's it! The certificate will automatically renew when needed.
|
||||||
|
|
||||||
If you want to specify your own key/certificate pair, simply pass the `--ssl-key` and `--ssl-cert` option to `./webodm.sh`. See `./webodm.sh --help` for more information.
|
If you want to specify your own key/certificate pair, simply pass the `--ssl-key` and `--ssl-cert` option to `./webodm.sh`. See `./webodm.sh --help` for more information.
|
||||||
|
|
||||||
|
Note! You cannot pass an IP address to the hostname parameter! You need a DNS record setup.
|
||||||
|
|
||||||
### Where Are My Files Stored?
|
### Where Are My Files Stored?
|
||||||
|
|
||||||
When using Docker, all processing results are stored in a docker volume and are not available on the host filesystem. If you want to store your files on the host filesystem instead of a docker volume, you need to pass a path via the `--media-dir` option:
|
When using Docker, all processing results are stored in a docker volume and are not available on the host filesystem. If you want to store your files on the host filesystem instead of a docker volume, you need to pass a path via the `--media-dir` option:
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
import os
|
||||||
|
|
||||||
|
from .tasks import TaskNestedView
|
||||||
|
from app.security import path_traversal_check
|
||||||
|
from django.core.exceptions import SuspiciousFileOperation
|
||||||
|
from rest_framework import exceptions
|
||||||
|
|
||||||
|
class Thumbnail(TaskNestedView):
|
||||||
|
def get(self, request, pk=None, project_pk=None, image_filename=""):
|
||||||
|
"""
|
||||||
|
Generate a thumbnail on the fly for a particular task's image
|
||||||
|
"""
|
||||||
|
task = self.get_and_check_task(request, pk)
|
||||||
|
|
||||||
|
image_path = task.task_path(image_filename)
|
||||||
|
|
||||||
|
try:
|
||||||
|
path_traversal_check(image_path, task.task_path(""))
|
||||||
|
except SuspiciousFileOperation:
|
||||||
|
raise exceptions.NotFound()
|
||||||
|
|
||||||
|
if not os.path.isfile(image_path):
|
||||||
|
raise exceptions.NotFound()
|
||||||
|
|
||||||
|
# TODO
|
||||||
|
|
||||||
|
return Response({
|
||||||
|
'tilejson': '2.1.0',
|
||||||
|
'name': task.name,
|
||||||
|
'version': '1.0.0',
|
||||||
|
'scheme': 'xyz',
|
||||||
|
'tiles': [get_tile_url(task, tile_type, self.request.query_params)],
|
||||||
|
'minzoom': minzoom - ZOOM_EXTRA_LEVELS,
|
||||||
|
'maxzoom': maxzoom + ZOOM_EXTRA_LEVELS,
|
||||||
|
'bounds': get_extent(task, tile_type).extent
|
||||||
|
})
|
|
@ -192,6 +192,7 @@ class Task(models.Model):
|
||||||
'deferred_compress_dir': 'orthophoto_tiles'
|
'deferred_compress_dir': 'orthophoto_tiles'
|
||||||
},
|
},
|
||||||
'cameras.json': 'cameras.json',
|
'cameras.json': 'cameras.json',
|
||||||
|
'shots.geojson': os.path.join('odm_report', 'shots.geojson'),
|
||||||
}
|
}
|
||||||
|
|
||||||
STATUS_CODES = (
|
STATUS_CODES = (
|
||||||
|
|
|
@ -44,7 +44,9 @@ const api = {
|
||||||
new AssetDownload("Point Cloud (PLY)","georeferenced_model.ply","fa fa-cube"),
|
new AssetDownload("Point Cloud (PLY)","georeferenced_model.ply","fa fa-cube"),
|
||||||
new AssetDownload("Point Cloud (CSV)","georeferenced_model.csv","fa fa-cube"),
|
new AssetDownload("Point Cloud (CSV)","georeferenced_model.csv","fa fa-cube"),
|
||||||
new AssetDownload("Textured Model","textured_model.zip","fab fa-connectdevelop"),
|
new AssetDownload("Textured Model","textured_model.zip","fab fa-connectdevelop"),
|
||||||
new AssetDownload("Camera Parameters","cameras.json","fa fa-camera-retro"),
|
new AssetDownload("Camera Parameters","cameras.json","fa fa-camera"),
|
||||||
|
new AssetDownload("Camera Shots (GeoJSON)","shots.geojson","fa fa-camera"),
|
||||||
|
|
||||||
new AssetDownloadSeparator(),
|
new AssetDownloadSeparator(),
|
||||||
new AssetDownload("All Assets","all.zip","far fa-file-archive")
|
new AssetDownload("All Assets","all.zip","far fa-file-archive")
|
||||||
];
|
];
|
||||||
|
|
|
@ -71,7 +71,7 @@ export function addTempLayer(file, cb) {
|
||||||
if (feature.properties) {
|
if (feature.properties) {
|
||||||
if (feature.properties) {
|
if (feature.properties) {
|
||||||
layer.bindPopup(Object.keys(feature.properties).map(function (k) {
|
layer.bindPopup(Object.keys(feature.properties).map(function (k) {
|
||||||
return k + ": " + feature.properties[k];
|
return "<strong>" + k + ":</strong> " + feature.properties[k];
|
||||||
}).join("<br />"), {
|
}).join("<br />"), {
|
||||||
maxHeight: 200
|
maxHeight: 200
|
||||||
});
|
});
|
||||||
|
|
|
@ -92,7 +92,7 @@ class EditPresetDialog extends React.Component {
|
||||||
show={true}
|
show={true}
|
||||||
onShow={this.onShow}
|
onShow={this.onShow}
|
||||||
saveIcon="far fa-edit"
|
saveIcon="far fa-edit"
|
||||||
title="Edit Options"
|
title="Edit Task Options"
|
||||||
saveAction={this.props.saveAction}
|
saveAction={this.props.saveAction}
|
||||||
deleteWarning={false}
|
deleteWarning={false}
|
||||||
deleteAction={(this.props.preset.id !== -1 && !this.props.preset.system) ? this.props.deleteAction : undefined}>
|
deleteAction={(this.props.preset.id !== -1 && !this.props.preset.system) ? this.props.deleteAction : undefined}>
|
||||||
|
@ -105,7 +105,7 @@ class EditPresetDialog extends React.Component {
|
||||||
</div>
|
</div>
|
||||||
: ""}
|
: ""}
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<label className="col-sm-2 control-label">Options</label>
|
<label className="col-sm-2 control-label"></label>
|
||||||
<div className="col-sm-10">
|
<div className="col-sm-10">
|
||||||
{options.map(option =>
|
{options.map(option =>
|
||||||
<ProcessingNodeOption {...option}
|
<ProcessingNodeOption {...option}
|
||||||
|
|
|
@ -503,8 +503,8 @@ class EditTaskForm extends React.Component {
|
||||||
|
|
||||||
{!this.state.presetActionPerforming ?
|
{!this.state.presetActionPerforming ?
|
||||||
<div className="btn-group presets-dropdown">
|
<div className="btn-group presets-dropdown">
|
||||||
<button type="button" className="btn btn-default" onClick={this.handleEditPreset}>
|
<button type="button" className="btn btn-default" title="Edit Task Options" onClick={this.handleEditPreset}>
|
||||||
<i className="fa fa-sliders-h"></i>
|
<i className="fa fa-sliders-h"></i> Edit
|
||||||
</button>
|
</button>
|
||||||
<button type="button" className="btn btn-default dropdown-toggle" data-toggle="dropdown">
|
<button type="button" className="btn btn-default dropdown-toggle" data-toggle="dropdown">
|
||||||
<span className="caret"></span>
|
<span className="caret"></span>
|
||||||
|
|
|
@ -14,12 +14,14 @@ export default class LayersControlLayer extends React.Component {
|
||||||
expanded: false,
|
expanded: false,
|
||||||
map: null,
|
map: null,
|
||||||
overlay: false,
|
overlay: false,
|
||||||
|
overlayIcon: "fa fa-vector-square fa-fw"
|
||||||
};
|
};
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
layer: PropTypes.object.isRequired,
|
layer: PropTypes.object.isRequired,
|
||||||
expanded: PropTypes.bool,
|
expanded: PropTypes.bool,
|
||||||
map: PropTypes.object.isRequired,
|
map: PropTypes.object.isRequired,
|
||||||
overlay: PropTypes.bool
|
overlay: PropTypes.bool,
|
||||||
|
overlayIcon: PropTypes.string
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props){
|
constructor(props){
|
||||||
|
@ -262,7 +264,7 @@ export default class LayersControlLayer extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (<div className="layers-control-layer">
|
return (<div className="layers-control-layer">
|
||||||
{!this.props.overlay ? <ExpandButton bind={[this, 'expanded']} /> : ""}<Checkbox bind={[this, 'visible']}/>
|
{!this.props.overlay ? <ExpandButton bind={[this, 'expanded']} /> : <div className="overlayIcon"><i className={this.props.overlayIcon}></i></div>}<Checkbox bind={[this, 'visible']}/>
|
||||||
<a className="layer-label" href="javascript:void(0);" onClick={this.handleLayerClick}>{meta.name}</a>
|
<a className="layer-label" href="javascript:void(0);" onClick={this.handleLayerClick}>{meta.name}</a>
|
||||||
|
|
||||||
{this.state.expanded ?
|
{this.state.expanded ?
|
||||||
|
|
|
@ -55,5 +55,15 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.overlayIcon{
|
||||||
|
float: left;
|
||||||
|
width: 22px;
|
||||||
|
|
||||||
|
i{
|
||||||
|
font-size: 16px;
|
||||||
|
margin-top: 4px;
|
||||||
|
margin-left: 1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -10,17 +10,6 @@
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.overlays{
|
|
||||||
border-bottom-width: 1px;
|
|
||||||
border-bottom-style: solid;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
padding-bottom: 10px;
|
|
||||||
|
|
||||||
a.toggle{
|
|
||||||
margin-left: 22px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.close-button{
|
.close-button{
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAQAAAD8x0bcAAAAkUlEQVR4AZWRxQGDUBAFJ9pMflNIP/iVSkIb2wgccXd7g7O+3JXCQUgqBAfFSl8CMooJGQHfuUlEwZpoahZQ7ODTSXWJQkxyioock7BL2tXmdF4moJNX6IDZfbUBQNrX7qfeXfPuqwBAQjEz60w64htGJ+luFH48gt+NYe6v5b/cnr9asM+HlRQ2Qlwh2CjuqQQ9vKsKTwhQ1wAAAABJRU5ErkJggg==);
|
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAQAAAD8x0bcAAAAkUlEQVR4AZWRxQGDUBAFJ9pMflNIP/iVSkIb2wgccXd7g7O+3JXCQUgqBAfFSl8CMooJGQHfuUlEwZpoahZQ7ODTSXWJQkxyioock7BL2tXmdF4moJNX6IDZfbUBQNrX7qfeXfPuqwBAQjEz60w64htGJ+luFH48gt+NYe6v5b/cnr9asM+HlRQ2Qlwh2CjuqQQ9vKsKTwhQ1wAAAABJRU5ErkJggg==);
|
||||||
|
|
Ładowanie…
Reference in New Issue