kopia lustrzana https://github.com/OpenDroneMap/WebODM
Fixed processing nodes permissions display, readded processing node menu in backend via template tags
rodzic
66bae84aa9
commit
deac02c385
|
@ -1,8 +1,7 @@
|
|||
import django_filters
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django_filters.rest_framework import FilterSet
|
||||
from guardian.shortcuts import get_objects_for_user
|
||||
from rest_framework import serializers, viewsets, exceptions
|
||||
from rest_framework import serializers, viewsets
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ class ProjectListItem extends React.Component {
|
|||
this.handleEditProject = this.handleEditProject.bind(this);
|
||||
this.updateProject = this.updateProject.bind(this);
|
||||
this.taskDeleted = this.taskDeleted.bind(this);
|
||||
this.hasPermission = this.hasPermission.bind(this);
|
||||
}
|
||||
|
||||
refresh(){
|
||||
|
@ -87,81 +88,87 @@ class ProjectListItem extends React.Component {
|
|||
}));
|
||||
}
|
||||
|
||||
hasPermission(perm){
|
||||
return this.state.data.permissions.indexOf(perm) !== -1;
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
Dropzone.autoDiscover = false;
|
||||
|
||||
this.dz = new Dropzone(this.dropzone, {
|
||||
paramName: "images",
|
||||
url : `/api/projects/${this.state.data.id}/tasks/`,
|
||||
parallelUploads: 9999999,
|
||||
uploadMultiple: true,
|
||||
acceptedFiles: "image/*, .txt",
|
||||
autoProcessQueue: true,
|
||||
createImageThumbnails: false,
|
||||
clickable: this.uploadButton,
|
||||
|
||||
headers: {
|
||||
[csrf.header]: csrf.token
|
||||
}
|
||||
});
|
||||
|
||||
this.dz.on("totaluploadprogress", (progress, totalBytes, totalBytesSent) => {
|
||||
this.setUploadState({
|
||||
progress, totalBytes, totalBytesSent
|
||||
});
|
||||
})
|
||||
.on("addedfile", () => {
|
||||
this.setUploadState({
|
||||
totalCount: this.state.upload.totalCount + 1
|
||||
});
|
||||
})
|
||||
.on("processingmultiple", () => {
|
||||
this.setUploadState({
|
||||
uploading: true,
|
||||
showEditTask: true
|
||||
})
|
||||
})
|
||||
.on("completemultiple", (files) => {
|
||||
// Check
|
||||
let success = files.length > 0 && files.filter(file => file.status !== "success").length === 0;
|
||||
|
||||
// All files have uploaded!
|
||||
if (success){
|
||||
this.setUploadState({uploading: false});
|
||||
|
||||
try{
|
||||
let response = JSON.parse(files[0].xhr.response);
|
||||
if (!response.id) throw new Error(`Expected id field, but none given (${response})`);
|
||||
|
||||
let taskId = response.id;
|
||||
this.setUploadState({taskId});
|
||||
|
||||
// Update task information (if the user has completed this step)
|
||||
if (this.state.upload.savedTaskInfo){
|
||||
this.updateTaskInfo(taskId, this.editTaskPanel.getTaskInfo());
|
||||
}else{
|
||||
// Need to wait for user to confirm task options
|
||||
}
|
||||
}catch(e){
|
||||
this.setUploadState({error: `Invalid response from server: ${e.message}`})
|
||||
if (this.hasPermission("add")){
|
||||
this.dz = new Dropzone(this.dropzone, {
|
||||
paramName: "images",
|
||||
url : `/api/projects/${this.state.data.id}/tasks/`,
|
||||
parallelUploads: 9999999,
|
||||
uploadMultiple: true,
|
||||
acceptedFiles: "image/*, .txt",
|
||||
autoProcessQueue: true,
|
||||
createImageThumbnails: false,
|
||||
clickable: this.uploadButton,
|
||||
|
||||
headers: {
|
||||
[csrf.header]: csrf.token
|
||||
}
|
||||
|
||||
}else{
|
||||
this.setUploadState({
|
||||
uploading: false,
|
||||
error: "Could not upload all files. An error occured. Please try again."
|
||||
});
|
||||
}
|
||||
})
|
||||
.on("reset", () => {
|
||||
this.resetUploadState();
|
||||
})
|
||||
.on("dragenter", () => {
|
||||
this.resetUploadState();
|
||||
})
|
||||
.on("sending", (file, xhr, formData) => {
|
||||
formData.append('auto_processing_node', "false");
|
||||
});
|
||||
|
||||
this.dz.on("totaluploadprogress", (progress, totalBytes, totalBytesSent) => {
|
||||
this.setUploadState({
|
||||
progress, totalBytes, totalBytesSent
|
||||
});
|
||||
})
|
||||
.on("addedfile", () => {
|
||||
this.setUploadState({
|
||||
totalCount: this.state.upload.totalCount + 1
|
||||
});
|
||||
})
|
||||
.on("processingmultiple", () => {
|
||||
this.setUploadState({
|
||||
uploading: true,
|
||||
showEditTask: true
|
||||
})
|
||||
})
|
||||
.on("completemultiple", (files) => {
|
||||
// Check
|
||||
let success = files.length > 0 && files.filter(file => file.status !== "success").length === 0;
|
||||
|
||||
// All files have uploaded!
|
||||
if (success){
|
||||
this.setUploadState({uploading: false});
|
||||
|
||||
try{
|
||||
let response = JSON.parse(files[0].xhr.response);
|
||||
if (!response.id) throw new Error(`Expected id field, but none given (${response})`);
|
||||
|
||||
let taskId = response.id;
|
||||
this.setUploadState({taskId});
|
||||
|
||||
// Update task information (if the user has completed this step)
|
||||
if (this.state.upload.savedTaskInfo){
|
||||
this.updateTaskInfo(taskId, this.editTaskPanel.getTaskInfo());
|
||||
}else{
|
||||
// Need to wait for user to confirm task options
|
||||
}
|
||||
}catch(e){
|
||||
this.setUploadState({error: `Invalid response from server: ${e.message}`})
|
||||
}
|
||||
|
||||
}else{
|
||||
this.setUploadState({
|
||||
uploading: false,
|
||||
error: "Could not upload all files. An error occured. Please try again."
|
||||
});
|
||||
}
|
||||
})
|
||||
.on("reset", () => {
|
||||
this.resetUploadState();
|
||||
})
|
||||
.on("dragenter", () => {
|
||||
this.resetUploadState();
|
||||
})
|
||||
.on("sending", (file, xhr, formData) => {
|
||||
formData.append('auto_processing_node', "false");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
updateTaskInfo(taskId, taskInfo){
|
||||
|
@ -289,19 +296,21 @@ class ProjectListItem extends React.Component {
|
|||
projectName={data.name}
|
||||
projectDescr={data.description}
|
||||
saveAction={this.updateProject}
|
||||
deleteAction={this.handleDelete}
|
||||
deleteAction={this.hasPermission("delete") ? this.handleDelete : undefined}
|
||||
/>
|
||||
|
||||
<div className="row no-margin">
|
||||
<ErrorMessage bind={[this, 'error']} />
|
||||
<div className="btn-group pull-right">
|
||||
<button type="button"
|
||||
className={"btn btn-primary btn-sm " + (this.state.upload.uploading ? "hide" : "")}
|
||||
onClick={this.handleUpload}
|
||||
ref={this.setRef("uploadButton")}>
|
||||
<i className="glyphicon glyphicon-upload"></i>
|
||||
Upload Images and GCP
|
||||
</button>
|
||||
{this.hasPermission("add") ?
|
||||
<button type="button"
|
||||
className={"btn btn-primary btn-sm " + (this.state.upload.uploading ? "hide" : "")}
|
||||
onClick={this.handleUpload}
|
||||
ref={this.setRef("uploadButton")}>
|
||||
<i className="glyphicon glyphicon-upload"></i>
|
||||
Upload Images and GCP
|
||||
</button>
|
||||
: ""}
|
||||
|
||||
<button disabled={this.state.upload.error !== ""}
|
||||
type="button"
|
||||
|
|
|
@ -241,17 +241,23 @@
|
|||
<!--<li>
|
||||
<a href="#"><i class="fa fa-plane fa-fw"></i> Mission Planner</a>
|
||||
</li> -->
|
||||
{% if can_view_processingnode %}
|
||||
{% load processingnode_extras %}
|
||||
{% can_view_processing_nodes as view_nodes %}
|
||||
{% can_add_processing_nodes as add_nodes %}
|
||||
{% get_visible_processing_nodes as nodes %}
|
||||
|
||||
|
||||
{% if view_nodes %}
|
||||
<li>
|
||||
<a href="#"><i class="fa fa-wrench fa-fw"></i> Processing Nodes<span class="fa arrow"></span></a>
|
||||
<ul class="nav nav-second-level">
|
||||
{% for node in processingnodes %}
|
||||
{% for node in nodes %}
|
||||
<li>
|
||||
<a href="{% url 'processing_node' node.id %}"><span class="fa fa-laptop"></span> {{node}}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
|
||||
{% if can_add_processingnode %}
|
||||
{% if add_nodes %}
|
||||
<li>
|
||||
<a href="{% url 'admin:nodeodm_processingnode_add' %}"><span class="fa fa-plus-circle"></span> Add New</a>
|
||||
</li>
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
from django import template
|
||||
from guardian.shortcuts import get_objects_for_user
|
||||
|
||||
from app.models import ProcessingNode
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.assignment_tag(takes_context=True)
|
||||
def get_visible_processing_nodes(context):
|
||||
return get_objects_for_user(context['request'].user, "nodeodm.view_processingnode", ProcessingNode, accept_global_perms=False)
|
||||
|
||||
|
||||
@register.assignment_tag(takes_context=True)
|
||||
def can_view_processing_nodes(context):
|
||||
return context['request'].user.has_perm("nodeodm.view_processingnode")
|
||||
|
||||
|
||||
@register.assignment_tag(takes_context=True)
|
||||
def can_add_processing_nodes(context):
|
||||
return context['request'].user.has_perm("nodeodm.add_processingnode")
|
25
app/views.py
25
app/views.py
|
@ -33,8 +33,7 @@ def dashboard(request):
|
|||
|
||||
return render(request, 'app/dashboard.html', {'title': 'Dashboard',
|
||||
'no_processingnodes': no_processingnodes,
|
||||
'no_tasks': no_tasks,
|
||||
**get_view_params(request),
|
||||
'no_tasks': no_tasks
|
||||
})
|
||||
|
||||
|
||||
|
@ -60,8 +59,7 @@ def map(request, project_pk=None, task_pk=None):
|
|||
'title': title,
|
||||
'params': {
|
||||
'tiles': json.dumps(tiles)
|
||||
}.items(),
|
||||
**get_view_params(request),
|
||||
}.items()
|
||||
})
|
||||
|
||||
|
||||
|
@ -88,8 +86,7 @@ def model_display(request, project_pk=None, task_pk=None):
|
|||
'project': project.id,
|
||||
'available_assets': task.get_available_assets()
|
||||
})
|
||||
}.items(),
|
||||
**get_view_params(request),
|
||||
}.items()
|
||||
})
|
||||
|
||||
|
||||
|
@ -103,8 +100,7 @@ def processing_node(request, processing_node_id):
|
|||
{
|
||||
'title': 'Processing Node',
|
||||
'processing_node': pn,
|
||||
'available_options_json': pn.get_available_options_json(pretty=True),
|
||||
**get_view_params(request),
|
||||
'available_options_json': pn.get_available_options_json(pretty=True)
|
||||
})
|
||||
|
||||
class FirstUserForm(forms.ModelForm):
|
||||
|
@ -138,16 +134,3 @@ def welcome(request):
|
|||
'title': 'Welcome',
|
||||
'firstuserform': fuf
|
||||
})
|
||||
|
||||
|
||||
def get_view_params(request):
|
||||
"""
|
||||
Returns common parameters to pass to a view
|
||||
"""
|
||||
processingnodes = get_objects_for_user(request.user, "nodeodm.view_processingnode", ProcessingNode)
|
||||
|
||||
return {
|
||||
'can_view_processingnode': request.user.has_perm("nodeodm.view_processingnode"),
|
||||
'can_add_processingnode': request.user.has_perm("nodeodm.add_processingnode"),
|
||||
'processingnodes': processingnodes,
|
||||
}
|
Ładowanie…
Reference in New Issue