kopia lustrzana https://github.com/OpenDroneMap/WebODM
Added settings page
rodzic
a9a474ad46
commit
32863c7b33
|
@ -14,124 +14,125 @@ from rest_framework import status
|
||||||
|
|
||||||
#from .platform_helper import get_all_platforms, get_platform_by_name
|
#from .platform_helper import get_all_platforms, get_platform_by_name
|
||||||
|
|
||||||
class ImportFolderTaskView(TaskView):
|
# class ImportFolderTaskView(TaskView):
|
||||||
def post(self, request, project_pk=None, pk=None):
|
# def post(self, request, project_pk=None, pk=None):
|
||||||
task = self.get_and_check_task(request, pk)
|
# task = self.get_and_check_task(request, pk)
|
||||||
|
|
||||||
|
|
||||||
# Read form data
|
# Read form data
|
||||||
folder_url = request.data.get('selectedFolderUrl', None)
|
# folder_url = request.data.get('selectedFolderUrl', None)
|
||||||
platform_name = request.data.get('platform', None)
|
# platform_name = request.data.get('platform', None)
|
||||||
|
|
||||||
# Make sure both values are set
|
# # Make sure both values are set
|
||||||
if folder_url == None or platform_name == None:
|
# if folder_url == None or platform_name == None:
|
||||||
return Response({'error': 'Folder URL and platform name must be set.'}, status=status.HTTP_400_BAD_REQUEST)
|
# return Response({'error': 'Folder URL and platform name must be set.'}, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
# Fetch the platform by name
|
# # Fetch the platform by name
|
||||||
platform = get_platform_by_name(platform_name)
|
# platform = get_platform_by_name(platform_name)
|
||||||
|
|
||||||
# Make sure that the platform actually exists
|
# # Make sure that the platform actually exists
|
||||||
if platform == None:
|
# if platform == None:
|
||||||
return Response({'error': 'Failed to find a platform with the name \'{}\''.format(platform_name)}, status=status.HTTP_400_BAD_REQUEST)
|
# return Response({'error': 'Failed to find a platform with the name \'{}\''.format(platform_name)}, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
# Verify that the folder url is valid
|
# # Verify that the folder url is valid
|
||||||
if platform.verify_folder_url(folder_url) == None:
|
# if platform.verify_folder_url(folder_url) == None:
|
||||||
return Response({'error': 'Invalid URL'}, status=status.HTTP_400_BAD_REQUEST)
|
# return Response({'error': 'Invalid URL'}, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
# Get the files from the folder
|
# # Get the files from the folder
|
||||||
files = platform.import_from_folder(folder_url)
|
# files = platform.import_from_folder(folder_url)
|
||||||
|
|
||||||
# Update the task with the new information
|
# # Update the task with the new information
|
||||||
task.console_output += "Importing {} images...\n".format(len(files))
|
# task.console_output += "Importing {} images...\n".format(len(files))
|
||||||
task.images_count = len(files)
|
# task.images_count = len(files)
|
||||||
task.pending_action = pending_actions.IMPORT
|
# task.pending_action = pending_actions.IMPORT
|
||||||
task.save()
|
# task.save()
|
||||||
|
|
||||||
# Associate the folder url with the project and task
|
# # Associate the folder url with the project and task
|
||||||
combined_id = "{}_{}".format(project_pk, pk)
|
# combined_id = "{}_{}".format(project_pk, pk)
|
||||||
get_current_plugin().get_global_data_store().set_string(combined_id, folder_url)
|
# get_current_plugin().get_global_data_store().set_string(combined_id, folder_url)
|
||||||
|
|
||||||
# Start importing the files in the background
|
# # Start importing the files in the background
|
||||||
serialized = [file.serialize() for file in files]
|
# serialized = [file.serialize() for file in files]
|
||||||
run_function_async(import_files, task.id, serialized)
|
# run_function_async(import_files, task.id, serialized)
|
||||||
|
|
||||||
return Response({}, status=status.HTTP_200_OK)
|
# return Response({}, status=status.HTTP_200_OK)
|
||||||
|
|
||||||
class CheckUrlTaskView(TaskView):
|
# class CheckUrlTaskView(TaskView):
|
||||||
def get(self, request, project_pk=None, pk=None):
|
# def get(self, request, project_pk=None, pk=None):
|
||||||
|
|
||||||
# Assert that task exists
|
# # Assert that task exists
|
||||||
self.get_and_check_task(request, pk)
|
# self.get_and_check_task(request, pk)
|
||||||
|
|
||||||
# Check if there is an imported url associated with the project and task
|
# # Check if there is an imported url associated with the project and task
|
||||||
combined_id = "{}_{}".format(project_pk, pk)
|
# combined_id = "{}_{}".format(project_pk, pk)
|
||||||
folder_url = get_current_plugin().get_global_data_store().get_string(combined_id, default = None)
|
# folder_url = get_current_plugin().get_global_data_store().get_string(combined_id, default = None)
|
||||||
|
|
||||||
if folder_url == None:
|
# if folder_url == None:
|
||||||
return Response({}, status=status.HTTP_200_OK)
|
# return Response({}, status=status.HTTP_200_OK)
|
||||||
else:
|
# else:
|
||||||
return Response({'folder_url': folder_url}, status=status.HTTP_200_OK)
|
# return Response({'folder_url': folder_url}, status=status.HTTP_200_OK)
|
||||||
|
|
||||||
class PlatformsVerifyTaskView(TaskView):
|
# class PlatformsVerifyTaskView(TaskView):
|
||||||
def get(self, request, platform_name):
|
# def get(self, request, platform_name):
|
||||||
# Read the form data
|
# # Read the form data
|
||||||
folder_url = request.GET.get('folderUrl', None)
|
# folder_url = request.GET.get('folderUrl', None)
|
||||||
|
|
||||||
# Fetch the platform by name
|
# # Fetch the platform by name
|
||||||
platform = get_platform_by_name(platform_name)
|
# platform = get_platform_by_name(platform_name)
|
||||||
|
|
||||||
# Make sure that the platform actually exists
|
# # Make sure that the platform actually exists
|
||||||
if platform == None:
|
# if platform == None:
|
||||||
return Response({'error': 'Failed to find a platform with the name \'{}\''.format(platform_name)}, status=status.HTTP_400_BAD_REQUEST)
|
# return Response({'error': 'Failed to find a platform with the name \'{}\''.format(platform_name)}, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
# Verify that the folder url is valid
|
# # Verify that the folder url is valid
|
||||||
folder = platform.verify_folder_url(folder_url)
|
# folder = platform.verify_folder_url(folder_url)
|
||||||
if folder == None:
|
# if folder == None:
|
||||||
return Response({'error': 'Invalid URL'}, status=status.HTTP_400_BAD_REQUEST)
|
# return Response({'error': 'Invalid URL'}, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
# Return the folder
|
# # Return the folder
|
||||||
return Response({'folder': folder.serialize()}, status=status.HTTP_200_OK)
|
# return Response({'folder': folder.serialize()}, status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
|
||||||
class PlatformsTaskView(TaskView):
|
# # class PlatformsTaskView(TaskView):
|
||||||
def get(self, request):
|
# # def get(self, request):
|
||||||
# Fetch and return all platforms
|
# # # Fetch and return all platforms
|
||||||
platforms = get_all_platforms()
|
# # platforms = get_all_platforms()
|
||||||
return Response({'platforms': [platform.serialize(user = request.user) for platform in platforms]}, status=status.HTTP_200_OK)
|
# # return Response({'platforms': [platform.serialize(user = request.user) for platform in platforms]}, status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
|
||||||
def import_files(task_id, files):
|
# def import_files(task_id, files):
|
||||||
import requests
|
# import requests
|
||||||
from app import models
|
# from app import models
|
||||||
from app.plugins import logger
|
# from app.plugins import logger
|
||||||
|
|
||||||
def download_file(task, file):
|
# def download_file(task, file):
|
||||||
path = task.task_path(file['name'])
|
# path = task.task_path(file['name'])
|
||||||
download_stream = requests.get(file['url'], stream=True, timeout=60)
|
# download_stream = requests.get(file['url'], stream=True, timeout=60)
|
||||||
|
|
||||||
with open(path, 'wb') as fd:
|
# with open(path, 'wb') as fd:
|
||||||
for chunk in download_stream.iter_content(4096):
|
# for chunk in download_stream.iter_content(4096):
|
||||||
fd.write(chunk)
|
# fd.write(chunk)
|
||||||
|
|
||||||
models.ImageUpload.objects.create(task=task, image=path)
|
# models.ImageUpload.objects.create(task=task, image=path)
|
||||||
|
|
||||||
logger.info("Will import {} files".format(len(files)))
|
# logger.info("Will import {} files".format(len(files)))
|
||||||
task = models.Task.objects.get(pk=task_id)
|
# task = models.Task.objects.get(pk=task_id)
|
||||||
task.create_task_directories()
|
# task.create_task_directories()
|
||||||
task.save()
|
# task.save()
|
||||||
|
|
||||||
try:
|
# try:
|
||||||
downloaded_total = 0
|
# downloaded_total = 0
|
||||||
for file in files:
|
# for file in files:
|
||||||
download_file(task, file)
|
# download_file(task, file)
|
||||||
task.check_if_canceled()
|
# task.check_if_canceled()
|
||||||
models.Task.objects.filter(pk=task.id).update(upload_progress=(float(downloaded_total) / float(len(files))))
|
# models.Task.objects.filter(pk=task.id).update(upload_progress=(float(downloaded_total) / float(len(files))))
|
||||||
downloaded_total += 1
|
# downloaded_total += 1
|
||||||
|
|
||||||
except (requests.exceptions.Timeout, requests.exceptions.ConnectionError) as e:
|
# except (requests.exceptions.Timeout, requests.exceptions.ConnectionError) as e:
|
||||||
raise NodeServerError(e)
|
# raise NodeServerError(e)
|
||||||
|
|
||||||
task.refresh_from_db()
|
# task.refresh_from_db()
|
||||||
task.pending_action = None
|
# task.pending_action = None
|
||||||
task.processing_time = 0
|
# task.processing_time = 0
|
||||||
task.partial = False
|
# task.partial = False
|
||||||
task.save()
|
# task.save()
|
||||||
|
|
|
@ -10,57 +10,16 @@ from app.plugins import logger
|
||||||
|
|
||||||
#from .platform_helper import get_all_extended_platforms
|
#from .platform_helper import get_all_extended_platforms
|
||||||
|
|
||||||
""" class DynamicForm(forms.Form):
|
# def LoadButtonsView(plugin):
|
||||||
"""This dynamic form will go through all the extended platforms, and retrieve their fields"""
|
# def view(request):
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
ds = kwargs.pop('data_store')
|
|
||||||
super(DynamicForm, self).__init__(*args, **kwargs)
|
|
||||||
extended_platforms = get_all_extended_platforms()
|
|
||||||
|
|
||||||
for platform in extended_platforms:
|
|
||||||
for form_field in platform.get_form_fields():
|
|
||||||
django_field = form_field.get_django_field(ds)
|
|
||||||
django_field.group = platform.name
|
|
||||||
self.fields[form_field.field_id] = django_field
|
|
||||||
"""
|
|
||||||
|
|
||||||
def HomeView(plugin):
|
|
||||||
@login_required
|
|
||||||
def view(request):
|
|
||||||
""" ds = plugin.get_user_data_store(request.user)
|
|
||||||
|
|
||||||
# if this is a POST request we need to process the form data
|
# return render(
|
||||||
if request.method == "POST":
|
# request,
|
||||||
form = DynamicForm(request.POST, data_store = ds)
|
# plugin.template_path("load_buttons.js"),
|
||||||
if form.is_valid():
|
# {
|
||||||
extended_platforms = get_all_extended_platforms()
|
# "api_url": "/api" + plugin.public_url("").rstrip("/"),
|
||||||
for platform in extended_platforms:
|
# },
|
||||||
for form_field in platform.get_form_fields():
|
# content_type="text/javascript",
|
||||||
form_field.save_value(ds, form)
|
# )
|
||||||
|
|
||||||
messages.success(request, "Configuration updated successfuly!")
|
|
||||||
else:
|
|
||||||
form = DynamicForm(data_store = ds) """
|
|
||||||
|
|
||||||
return render(
|
# return view
|
||||||
request,
|
|
||||||
plugin.template_path("app.html"),
|
|
||||||
{"title": "DroneDB"},
|
|
||||||
)
|
|
||||||
|
|
||||||
return view
|
|
||||||
|
|
||||||
|
|
||||||
def LoadButtonsView(plugin):
|
|
||||||
def view(request):
|
|
||||||
|
|
||||||
return render(
|
|
||||||
request,
|
|
||||||
plugin.template_path("load_buttons.js"),
|
|
||||||
{
|
|
||||||
"api_url": "/api" + plugin.public_url("").rstrip("/"),
|
|
||||||
},
|
|
||||||
content_type="text/javascript",
|
|
||||||
)
|
|
||||||
|
|
||||||
return view
|
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"name": "DroneDB",
|
||||||
|
"webodmMinVersion": "1.1.2",
|
||||||
|
"description": "Integrate WebODM with DroneDB: import images and export results",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"author": "Luca Di Leo",
|
||||||
|
"email": "ldileo@digipa.it",
|
||||||
|
"repository": "https://github.com/OpenDroneMap/WebODM",
|
||||||
|
"tags": ["ddb", "DroneDB", "cloud"],
|
||||||
|
"homepage": "https://github.com/OpenDroneMap/WebODM",
|
||||||
|
"experimental": true,
|
||||||
|
"deprecated": false
|
||||||
|
}
|
|
@ -1,25 +1,33 @@
|
||||||
from app.plugins import PluginBase, Menu, MountPoint, logger
|
from app.plugins import PluginBase, Menu, MountPoint, logger
|
||||||
|
|
||||||
from .api_views import PlatformsTaskView, PlatformsVerifyTaskView, ImportFolderTaskView, CheckUrlTaskView
|
#from .api_views import PlatformsTaskView, PlatformsVerifyTaskView, ImportFolderTaskView, CheckUrlTaskView
|
||||||
from .app_views import HomeView, LoadButtonsView
|
#from .app_views import HomeView, LoadButtonsView
|
||||||
#from .platform_helper import get_all_extended_platforms
|
#from .platform_helper import get_all_extended_platforms
|
||||||
|
from django.contrib import messages
|
||||||
|
from django.shortcuts import render
|
||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
|
from django import forms
|
||||||
|
|
||||||
|
class SettingsForm(forms.Form):
|
||||||
|
registry_url = forms.CharField(label='Registry Url', required=False, max_length=1024, widget=forms.TextInput(attrs={'placeholder': 'Registry Url'}))
|
||||||
|
username = forms.CharField(label='Username', required=False, max_length=1024, widget=forms.TextInput(attrs={'placeholder': 'Username'}))
|
||||||
|
password = forms.CharField(label='Password', required=False, max_length=1024, widget=forms.PasswordInput(attrs={'placeholder': 'Password'}))
|
||||||
|
|
||||||
class Plugin(PluginBase):
|
class Plugin(PluginBase):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
def main_menu(self):
|
def main_menu(self):
|
||||||
return [Menu("DroneDB", self.public_url(""), "fa-cloud-download-alt fa fa-fw")]
|
return [Menu("DroneDB", self.public_url(""), "fas fa-cloud fa-fw")]
|
||||||
|
|
||||||
def include_js_files(self):
|
#def include_js_files(self):
|
||||||
return ["load_buttons.js"]
|
# return ["load_buttons.js"]
|
||||||
|
|
||||||
def include_css_files(self):
|
#def include_css_files(self):
|
||||||
return ["build/ImportView.css", "build/TaskView.css"]
|
# return ["build/ImportView.css", "build/TaskView.css"]
|
||||||
|
|
||||||
def build_jsx_components(self):
|
#def build_jsx_components(self):
|
||||||
return ["ImportView.jsx", "TaskView.jsx"]
|
# return ["ImportView.jsx", "TaskView.jsx"]
|
||||||
|
|
||||||
""" def api_mount_points(self):
|
""" def api_mount_points(self):
|
||||||
#api_views = [api_view for platform in get_all_extended_platforms() for api_view in platform.get_api_views()]
|
#api_views = [api_view for platform in get_all_extended_platforms() for api_view in platform.get_api_views()]
|
||||||
|
@ -33,8 +41,33 @@ class Plugin(PluginBase):
|
||||||
MountPoint("platforms", PlatformsTaskView.as_view()),
|
MountPoint("platforms", PlatformsTaskView.as_view()),
|
||||||
] """
|
] """
|
||||||
|
|
||||||
|
def HomeView(self):
|
||||||
|
@login_required
|
||||||
|
def home(request):
|
||||||
|
ds = self.get_user_data_store(request.user)
|
||||||
|
|
||||||
|
# if this is a POST request we need to process the form data
|
||||||
|
if request.method == 'POST':
|
||||||
|
form = SettingsForm(request.POST)
|
||||||
|
if form.is_valid():
|
||||||
|
ds.set_string('registry_url', form.cleaned_data['registry_url'])
|
||||||
|
ds.set_string('username', form.cleaned_data['username'])
|
||||||
|
ds.set_string('password', form.cleaned_data['password'])
|
||||||
|
messages.success(request, 'Settings updated.')
|
||||||
|
|
||||||
|
form = SettingsForm(initial={'username': ds.get_string('username', default=""),
|
||||||
|
'password': ds.get_string('password', default=""),
|
||||||
|
'registry_url': ds.get_string('registry_url', default="https://hub.dronedb.app")})
|
||||||
|
|
||||||
|
return render(request, self.template_path("app.html"), {
|
||||||
|
'title': 'DroneDB',
|
||||||
|
'form': form
|
||||||
|
})
|
||||||
|
|
||||||
|
return home
|
||||||
|
|
||||||
def app_mount_points(self):
|
def app_mount_points(self):
|
||||||
return [
|
return [
|
||||||
MountPoint("$", HomeView(self)),
|
MountPoint("$", self.HomeView()),
|
||||||
MountPoint("load_buttons.js$", LoadButtonsView(self)),
|
#MountPoint("load_buttons.js$", LoadButtonsView(self)),
|
||||||
]
|
]
|
|
@ -1,31 +1,16 @@
|
||||||
{% extends "app/plugins/templates/base.html" %}
|
{% extends "app/plugins/templates/base.html" %}
|
||||||
{% load bootstrap_extras %}
|
{% load bootstrap_extras %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h3>Welcome to Cloud Import!</h3>
|
<h3>Welcome to DroneDB!</h3>
|
||||||
<h5><strong>Instructions</strong></h5>
|
<h5><strong>Instructions</strong></h5>
|
||||||
On this screen, you will be able to configure everything that is necessary for your different platforms.<BR/>
|
On this screen, you can provide the registry url and credentials to access DroneDB
|
||||||
You might need to set up a server URL, an authentication token or something else. If so, this is the place!
|
<br/>
|
||||||
<BR/>
|
<br/>
|
||||||
<BR/>
|
<form action="" method="post" class="oam-form oam-token-form">
|
||||||
<h3>Platforms</h3>
|
<h4>Settings</h4>
|
||||||
<form action="" method="post" class="oam-form">
|
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{% regroup form by field.group as field_groups %}
|
{% include "app/plugins/templates/form.html" %}
|
||||||
{% for field_group in field_groups %}
|
<button type="submit" class="btn btn-primary"><i class="fa fa-save fa-fw"></i> Save Configuration</i></button>
|
||||||
<h4><strong>{{field_group.grouper}}</strong></h4>
|
|
||||||
{% for field in field_group.list %}
|
|
||||||
<div class="form-group {% if field.errors %}has-error{% endif %}">
|
|
||||||
<label for="{{ field.id_for_label }}" class="control-label">{{ field.label }}</label>
|
|
||||||
{{ field|with_class:'form-control' }}
|
|
||||||
{% if field.errors %}
|
|
||||||
<span class='text-danger'>{{ field.errors|join:'<br />' }}</span>
|
|
||||||
{% elif field.help_text %}
|
|
||||||
<span class="help-block ">{{ field.help_text }}</span>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
<button type="submit" class="btn btn-primary"><i class="fa fa-save fa-fw"></i> Save Configuration</button>
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
Ładowanie…
Reference in New Issue