kopia lustrzana https://github.com/OpenDroneMap/WebODM
Dropzone initialized proof of concept, task api (still need to test)
rodzic
c2e35d30d4
commit
d25556ceae
|
@ -1,8 +1,6 @@
|
|||
from django.contrib import admin
|
||||
from guardian.admin import GuardedModelAdmin
|
||||
from .models import Project
|
||||
from .models import Project, Task
|
||||
|
||||
class ProjectAdmin(GuardedModelAdmin):
|
||||
pass
|
||||
|
||||
admin.site.register(Project, ProjectAdmin)
|
||||
admin.site.register(Project, GuardedModelAdmin)
|
||||
admin.site.register(Task, GuardedModelAdmin)
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
from django.contrib.auth.models import User
|
||||
from rest_framework import serializers, viewsets, filters
|
||||
from app import models, permissions
|
||||
from guardian.shortcuts import get_objects_for_user
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.decorators import detail_route
|
||||
from app import models
|
||||
from .tasks import TaskIDsSerializer, TaskSerializer
|
||||
|
||||
class ProjectSerializer(serializers.HyperlinkedModelSerializer):
|
||||
|
||||
id = serializers.ReadOnlyField()
|
||||
class ProjectSerializer(serializers.ModelSerializer):
|
||||
owner = serializers.PrimaryKeyRelatedField(queryset=User.objects.all())
|
||||
tasks = TaskIDsSerializer(many=True)
|
||||
|
||||
class Meta:
|
||||
model = models.Project
|
||||
|
@ -14,8 +15,20 @@ class ProjectSerializer(serializers.HyperlinkedModelSerializer):
|
|||
|
||||
class ProjectViewSet(viewsets.ModelViewSet):
|
||||
"""
|
||||
Projects the current user has access to.
|
||||
Projects the current user has access to. Projects are the building blocks
|
||||
of processing. Each project can have zero or more tasks associated with it.
|
||||
Users can fine tune the permissions on projects, including whether users/groups have
|
||||
access to view, add, change or delete them.<br/><br/>
|
||||
- /api/projects/<projectId>/tasks : list all tasks belonging to a project<br/>
|
||||
- /api/projects/<projectId>/tasks/<taskId> : get task details
|
||||
|
||||
"""
|
||||
filter_fields = ('id', 'owner', 'name')
|
||||
serializer_class = ProjectSerializer
|
||||
queryset = models.Project.objects.all()
|
||||
|
||||
@detail_route(methods=['get'])
|
||||
def tasks(self, request, pk=None):
|
||||
tasks = self.get_object().tasks()
|
||||
serializer = TaskSerializer(tasks, many=True)
|
||||
return Response(serializer.data)
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
from django.contrib.auth.models import User
|
||||
from rest_framework import serializers, viewsets, filters
|
||||
from app import models
|
||||
from nodeodm.models import ProcessingNode
|
||||
|
||||
class TaskIDsSerializer(serializers.BaseSerializer):
|
||||
def to_representation(self, obj):
|
||||
return obj.id
|
||||
|
||||
class TaskSerializer(serializers.ModelSerializer):
|
||||
project = serializers.PrimaryKeyRelatedField(queryset=models.Project.objects.all())
|
||||
processing_node = serializers.PrimaryKeyRelatedField(queryset=ProcessingNode.objects.all())
|
||||
|
||||
class Meta:
|
||||
model = models.Task
|
||||
|
|
@ -14,8 +14,8 @@ def boot():
|
|||
if created:
|
||||
logger.info("Created default group")
|
||||
|
||||
# Add default permissions (view_project, change_project, delete_task, etc.)
|
||||
for permission in ('_project', '_task'):
|
||||
# Add default permissions (view_project, change_project, delete_project, etc.)
|
||||
for permission in ('_project'):
|
||||
default_group.permissions.add(
|
||||
*list(Permission.objects.filter(codename__endswith=permission))
|
||||
)
|
||||
|
|
|
@ -25,6 +25,9 @@ class Project(models.Model):
|
|||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def tasks(self):
|
||||
return Task.objects.filter(project=self);
|
||||
|
||||
class Meta:
|
||||
permissions = (
|
||||
('view_project', 'Can view project'),
|
||||
|
@ -60,15 +63,15 @@ class Task(models.Model):
|
|||
(50, 'CANCELED')
|
||||
)
|
||||
|
||||
uuid = models.CharField(max_length=255, primary_key=True, help_text="Unique identifier of the task (as returned by OpenDroneMap's REST API)")
|
||||
uuid = models.CharField(max_length=255, null=True, blank=True, unique=True, help_text="Unique identifier of the task (as returned by OpenDroneMap's REST API)")
|
||||
project = models.ForeignKey(Project, on_delete=models.CASCADE, help_text="Project that this task belongs to")
|
||||
name = models.CharField(max_length=255, help_text="A label for the task")
|
||||
name = models.CharField(max_length=255, null=True, blank=True, help_text="A label for the task")
|
||||
processing_time = models.IntegerField(default=-1, help_text="Number of milliseconds that elapsed since the beginning of this task (-1 indicates that no information is available)")
|
||||
processing_node = models.ForeignKey(ProcessingNode, null=True, help_text="Processing node assigned to this task (or null if this task has not been associated yet)")
|
||||
status = models.IntegerField(choices=STATUS_CODES, null=True, help_text="Current status of the task")
|
||||
options = fields.JSONField(default=dict(), help_text="Options that are being used to process this task")
|
||||
console_output = models.TextField(null=True, help_text="Console output of the OpenDroneMap's process")
|
||||
ground_control_points = models.FileField(null=True, upload_to=gcp_directory_path, help_text="Optional Ground Control Points file to use for processing")
|
||||
processing_node = models.ForeignKey(ProcessingNode, null=True, blank=True, help_text="Processing node assigned to this task (or null if this task has not been associated yet)")
|
||||
status = models.IntegerField(choices=STATUS_CODES, null=True, blank=True, help_text="Current status of the task")
|
||||
options = fields.JSONField(default=dict(), blank=True, help_text="Options that are being used to process this task")
|
||||
console_output = models.TextField(null=True, blank=True, help_text="Console output of the OpenDroneMap's process")
|
||||
ground_control_points = models.FileField(null=True, blank=True, upload_to=gcp_directory_path, help_text="Optional Ground Control Points file to use for processing")
|
||||
# georeferenced_model
|
||||
# orthophoto
|
||||
# textured_model
|
||||
|
|
|
@ -34,7 +34,7 @@ class ProjectList extends React.Component {
|
|||
error: `Could not load projects list: ${textStatus}`,
|
||||
loading: false
|
||||
});
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
componentWillUnmount(){
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import React from 'react';
|
||||
import ProjectListItemPanel from './ProjectListItemPanel';
|
||||
import Dropzone from '../vendor/dropzone';
|
||||
import $ from 'jquery';
|
||||
|
||||
class ProjectListItem extends React.Component {
|
||||
constructor(props){
|
||||
|
@ -8,10 +10,27 @@ class ProjectListItem extends React.Component {
|
|||
this.state = {
|
||||
showPanel: false
|
||||
};
|
||||
this.dropzoneInitialized = false;
|
||||
|
||||
this.togglePanel = this.togglePanel.bind(this);
|
||||
}
|
||||
|
||||
initializeDropzone(domNode){
|
||||
if (domNode != null && !this.dropzoneInitialized){
|
||||
Dropzone.autoDiscover = false;
|
||||
|
||||
let dropzone = new Dropzone(domNode, {
|
||||
url : '/api/upload'
|
||||
});
|
||||
|
||||
dropzone.on("complete", function(file) {
|
||||
console.log(file);
|
||||
});
|
||||
|
||||
this.dropzoneInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
togglePanel(){
|
||||
this.setState({
|
||||
showPanel: !this.state.showPanel
|
||||
|
@ -43,6 +62,12 @@ class ProjectListItem extends React.Component {
|
|||
{this.props.data.name}
|
||||
</a>
|
||||
|
||||
<div className="dropzone" ref={domNode => this.initializeDropzone(domNode)}>
|
||||
<div className="dz-default dz-message text-center">
|
||||
<i className="fa fa-cloud-upload fa-4x"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{this.state.showPanel ? <ProjectListItemPanel /> : ""}
|
||||
</li>
|
||||
);
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -21,22 +21,22 @@
|
|||
<button class="btn btn-primary" onclick="location.href='{% url "admin:nodeodm_processingnode_add" %}';"><i class="fa fa-plus-circle"></i> {{ add_processing_node }}</button>
|
||||
|
||||
{% else %}
|
||||
|
||||
{% trans 'Upload Images' as upload_images %}
|
||||
<p>
|
||||
{% blocktrans %} To create a new project, press the "{{ upload_images }}" button. {% endblocktrans %}
|
||||
</p>
|
||||
<button class="btn btn-primary"><i class="glyphicon glyphicon-upload"></i> {{ upload_images }}</button>
|
||||
|
||||
<p>
|
||||
<ul>
|
||||
<li>{% trans 'Need at least 5 images' %}</li>
|
||||
<li>{% trans 'Images must overlap by 60% or more' %}</li>
|
||||
</ul>
|
||||
</p>
|
||||
{% endif %}
|
||||
<!-- <h4>Projects</h4> -->
|
||||
{% if no_tasks %}
|
||||
{% trans 'Upload Images' as upload_images %}
|
||||
<p>
|
||||
{% blocktrans %} To create a map, press the "{{ upload_images }}" button. {% endblocktrans %}
|
||||
</p>
|
||||
<p>
|
||||
<ul>
|
||||
<li>{% trans 'You need at least 5 images' %}</li>
|
||||
<li>{% trans 'Images must overlap by 60% or more' %}</li>
|
||||
</ul>
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
<div id="dashboard-app"></div>
|
||||
{% render_bundle 'main' %}
|
||||
<div id="dashboard-app"></div>
|
||||
{% render_bundle 'main' %}
|
||||
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from django.shortcuts import render, redirect, get_object_or_404
|
||||
from django.http import HttpResponse
|
||||
from nodeodm.models import ProcessingNode
|
||||
from .models import Project
|
||||
from .models import Project, Task
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.utils.translation import ugettext as _
|
||||
|
@ -13,14 +13,15 @@ def index(request):
|
|||
@login_required
|
||||
def dashboard(request):
|
||||
no_processingnodes = ProcessingNode.objects.count() == 0
|
||||
no_tasks = Task.objects.filter(project__owner=request.user).count() == 0
|
||||
|
||||
# Create first project automatically
|
||||
if Project.objects.filter(owner=request.user).count() == 0:
|
||||
proj = Project(owner=request.user, name=_("First Project"))
|
||||
proj.save()
|
||||
Project.objects.create(owner=request.user, name=_("First Project"))
|
||||
|
||||
return render(request, 'app/dashboard.html', {'title': 'Dashboard',
|
||||
'no_processingnodes': no_processingnodes})
|
||||
'no_processingnodes': no_processingnodes,
|
||||
'no_tasks': no_tasks})
|
||||
|
||||
@login_required
|
||||
def processing_node(request, processing_node_id):
|
||||
|
|
Ładowanie…
Reference in New Issue