Fixed processing nodes permissions display, readded processing node menu in backend via template tags

pull/209/head
Piero Toffanin 2017-06-15 15:47:00 -04:00
rodzic 66bae84aa9
commit deac02c385
5 zmienionych plików z 122 dodań i 104 usunięć

Wyświetl plik

@ -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

Wyświetl plik

@ -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"

Wyświetl plik

@ -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>

Wyświetl plik

@ -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")

Wyświetl plik

@ -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,
}