kopia lustrzana https://github.com/OpenDroneMap/WebODM
Working on share to ddb button
rodzic
6ad0bc9f7c
commit
5438577df0
|
@ -9,8 +9,13 @@ from app import models, pending_actions
|
||||||
from app.plugins.views import TaskView
|
from app.plugins.views import TaskView
|
||||||
from app.plugins.worker import run_function_async
|
from app.plugins.worker import run_function_async
|
||||||
from app.plugins import get_current_plugin
|
from app.plugins import get_current_plugin
|
||||||
|
from app.models import ImageUpload
|
||||||
|
from app.plugins import GlobalDataStore, get_site_settings, signals as plugin_signals
|
||||||
|
|
||||||
from coreplugins.dronedb.ddb import DEFAULT_HUB_URL, DroneDB, parse_url, verify_url
|
from coreplugins.dronedb.ddb import DEFAULT_HUB_URL, DroneDB, parse_url, verify_url
|
||||||
|
|
||||||
|
from django.dispatch import receiver
|
||||||
|
|
||||||
from worker.celery import app
|
from worker.celery import app
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
|
@ -81,7 +86,11 @@ class ImportDatasetTaskView(TaskView):
|
||||||
combined_id = "{}_{}".format(project_pk, pk)
|
combined_id = "{}_{}".format(project_pk, pk)
|
||||||
|
|
||||||
datastore = get_current_plugin().get_global_data_store()
|
datastore = get_current_plugin().get_global_data_store()
|
||||||
datastore.set_json(combined_id, {"ddbUrl": ddb_url, "token": ddb.token, "ddbWebUrl": "{}/r/{}/{}/{}".format(to_web_protocol(registry_url), orgSlug, dsSlug, folder.rstrip('/'))})
|
datastore.set_json(combined_id, {
|
||||||
|
"ddbUrl": ddb_url,
|
||||||
|
"token": ddb.token,
|
||||||
|
"ddbWebUrl": "{}/r/{}/{}/{}".format(to_web_protocol(registry_url), orgSlug, dsSlug, folder.rstrip('/'))
|
||||||
|
})
|
||||||
|
|
||||||
# Start importing the files in the background
|
# Start importing the files in the background
|
||||||
serialized = {'token': ddb.token, 'files': files}
|
serialized = {'token': ddb.token, 'files': files}
|
||||||
|
@ -252,3 +261,65 @@ class CheckUrlTaskView(TaskView):
|
||||||
return Response({'ddbWebUrl': None}, status=status.HTTP_200_OK)
|
return Response({'ddbWebUrl': None}, status=status.HTTP_200_OK)
|
||||||
else:
|
else:
|
||||||
return Response({'ddbUrl': data['ddbWebUrl']}, status=status.HTTP_200_OK)
|
return Response({'ddbUrl': data['ddbWebUrl']}, status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
|
||||||
|
@receiver(plugin_signals.task_removed, dispatch_uid="ddb_on_task_removed")
|
||||||
|
@receiver(plugin_signals.task_completed, dispatch_uid="ddb_on_task_completed")
|
||||||
|
def ddb_cleanup(sender, task_id, **kwargs):
|
||||||
|
|
||||||
|
from app.plugins import logger
|
||||||
|
|
||||||
|
# When a task is removed, simply remove clutter
|
||||||
|
# When a task is re-processed, make sure we can re-share it if we shared a task previously
|
||||||
|
|
||||||
|
logger.info("Cleaning up DroneDB datastore for task {}".format(str(task_id)))
|
||||||
|
#ds.del_key(get_key_for(task_id, "status"))
|
||||||
|
|
||||||
|
class StatusTaskView(TaskView):
|
||||||
|
def get(self, request, project_pk, pk):
|
||||||
|
|
||||||
|
task = self.get_and_check_task(request, pk)
|
||||||
|
|
||||||
|
# Associate the folder url with the project and task
|
||||||
|
combined_id = "{}_{}_ddb".format(project_pk, pk)
|
||||||
|
|
||||||
|
datastore = get_current_plugin().get_global_data_store()
|
||||||
|
|
||||||
|
task_info = datastore.get_json(combined_id, {
|
||||||
|
'status': 0, # Idle
|
||||||
|
'shareUrl': None,
|
||||||
|
'uploadedFiles': 0,
|
||||||
|
'totalFiles': 0,
|
||||||
|
'uploadedSize': 0,
|
||||||
|
'totalSize': 0,
|
||||||
|
'error': None
|
||||||
|
})
|
||||||
|
|
||||||
|
#task_info['title'] = task.name
|
||||||
|
#task_info['provider'] = get_site_settings().organization_name
|
||||||
|
|
||||||
|
return Response(task_info, status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
class ShareTaskView(TaskView):
|
||||||
|
def post(self, request, project_pk, pk):
|
||||||
|
|
||||||
|
task = self.get_and_check_task(request, pk)
|
||||||
|
|
||||||
|
# Associate the folder url with the project and task
|
||||||
|
combined_id = "{}_{}_ddb".format(project_pk, pk)
|
||||||
|
|
||||||
|
datastore = get_current_plugin().get_global_data_store()
|
||||||
|
|
||||||
|
data = {
|
||||||
|
'status': 1, # Running
|
||||||
|
'shareUrl': None,
|
||||||
|
'uploadedFiles': 3,
|
||||||
|
'totalFiles': 10,
|
||||||
|
'uploadedSize': 1244,
|
||||||
|
'totalSize': 234525,
|
||||||
|
'error': None
|
||||||
|
}
|
||||||
|
|
||||||
|
datastore.set_json(combined_id, data)
|
||||||
|
|
||||||
|
return Response(data, status=status.HTTP_200_OK)
|
|
@ -2,7 +2,18 @@ from app.plugins import PluginBase, Menu, MountPoint, logger
|
||||||
from coreplugins.dronedb.app_views import LoadButtonsView
|
from coreplugins.dronedb.app_views import LoadButtonsView
|
||||||
from coreplugins.dronedb.ddb import DEFAULT_HUB_URL
|
from coreplugins.dronedb.ddb import DEFAULT_HUB_URL
|
||||||
|
|
||||||
from .api_views import CheckUrlTaskView, FoldersTaskView, ImportDatasetTaskView, CheckCredentialsTaskView, OrganizationsTaskView, DatasetsTaskView, VerifyUrlTaskView, InfoTaskView
|
from .api_views import (
|
||||||
|
CheckUrlTaskView,
|
||||||
|
FoldersTaskView,
|
||||||
|
ImportDatasetTaskView,
|
||||||
|
CheckCredentialsTaskView,
|
||||||
|
OrganizationsTaskView,
|
||||||
|
DatasetsTaskView,
|
||||||
|
StatusTaskView,
|
||||||
|
VerifyUrlTaskView,
|
||||||
|
InfoTaskView,
|
||||||
|
ShareTaskView
|
||||||
|
)
|
||||||
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
|
@ -34,6 +45,8 @@ class Plugin(PluginBase):
|
||||||
return [
|
return [
|
||||||
MountPoint("projects/(?P<project_pk>[^/.]+)/tasks/(?P<pk>[^/.]+)/import", ImportDatasetTaskView.as_view()),
|
MountPoint("projects/(?P<project_pk>[^/.]+)/tasks/(?P<pk>[^/.]+)/import", ImportDatasetTaskView.as_view()),
|
||||||
MountPoint("projects/(?P<project_pk>[^/.]+)/tasks/(?P<pk>[^/.]+)/checkforurl", CheckUrlTaskView.as_view()),
|
MountPoint("projects/(?P<project_pk>[^/.]+)/tasks/(?P<pk>[^/.]+)/checkforurl", CheckUrlTaskView.as_view()),
|
||||||
|
MountPoint("projects/(?P<project_pk>[^/.]+)/tasks/(?P<pk>[^/.]+)/status", StatusTaskView.as_view()),
|
||||||
|
MountPoint("projects/(?P<project_pk>[^/.]+)/tasks/(?P<pk>[^/.]+)/share", ShareTaskView.as_view()),
|
||||||
MountPoint("checkcredentials", CheckCredentialsTaskView.as_view()),
|
MountPoint("checkcredentials", CheckCredentialsTaskView.as_view()),
|
||||||
MountPoint("organizations/(?P<org>[^/.]+)/datasets/(?P<ds>[^/.]+)/folders", FoldersTaskView.as_view()),
|
MountPoint("organizations/(?P<org>[^/.]+)/datasets/(?P<ds>[^/.]+)/folders", FoldersTaskView.as_view()),
|
||||||
MountPoint("organizations/(?P<org>[^/.]+)/datasets", DatasetsTaskView.as_view()),
|
MountPoint("organizations/(?P<org>[^/.]+)/datasets", DatasetsTaskView.as_view()),
|
||||||
|
|
|
@ -4,6 +4,11 @@ import Storage from 'webodm/classes/Storage';
|
||||||
import ErrorMessage from 'webodm/components/ErrorMessage';
|
import ErrorMessage from 'webodm/components/ErrorMessage';
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
|
|
||||||
|
const STATE_IDLE = 0;
|
||||||
|
const STATE_RUNNING = 1;
|
||||||
|
const STATE_ERROR = 2;
|
||||||
|
const STATE_DONE = 3;
|
||||||
|
|
||||||
const ICON_CLASS_MAPPER = [
|
const ICON_CLASS_MAPPER = [
|
||||||
// Idle
|
// Idle
|
||||||
'fas fa-cloud fa-fw',
|
'fas fa-cloud fa-fw',
|
||||||
|
@ -28,13 +33,11 @@ const BUTTON_TEXT_MAPPER = [
|
||||||
|
|
||||||
export default class ShareButton extends React.Component{
|
export default class ShareButton extends React.Component{
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
task: null,
|
task: null
|
||||||
token: ""
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
task: PropTypes.object.isRequired,
|
task: PropTypes.object.isRequired,
|
||||||
token: PropTypes.string.isRequired // OAM Token
|
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(props){
|
constructor(props){
|
||||||
|
@ -42,11 +45,13 @@ export default class ShareButton extends React.Component{
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
taskInfo: null,
|
taskInfo: null,
|
||||||
error: ''
|
error: '',
|
||||||
|
intervalId: null
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
componentDidMount(){
|
componentDidMount(){
|
||||||
this.updateTaskInfo(false);
|
this.updateTaskInfo(false);
|
||||||
}
|
}
|
||||||
|
@ -55,81 +60,76 @@ export default class ShareButton extends React.Component{
|
||||||
const { task } = this.props;
|
const { task } = this.props;
|
||||||
return $.ajax({
|
return $.ajax({
|
||||||
type: 'GET',
|
type: 'GET',
|
||||||
url: `/api/plugins/dronedb/task/${task.id}/status`,
|
url: `/api/plugins/dronedb/projects/${task.project}/tasks/${task.id}/status`,
|
||||||
contentType: 'application/json'
|
contentType: 'application/json'
|
||||||
}).done(taskInfo => {
|
}).done(taskInfo => {
|
||||||
// Allow a user to specify a better name for the sensor
|
|
||||||
// and remember it.
|
|
||||||
let sensor = Storage.getItem("oam_sensor_pref_" + taskInfo.sensor);
|
|
||||||
if (sensor) taskInfo.sensor = sensor;
|
|
||||||
|
|
||||||
// Allow a user to change the default provider name
|
console.log(taskInfo);
|
||||||
let provider = Storage.getItem("oam_provider_pref");
|
|
||||||
if (provider) taskInfo.provider = provider;
|
|
||||||
|
|
||||||
this.setState({taskInfo, loading: false});
|
this.setState({taskInfo});
|
||||||
if (taskInfo.error && showErrors) this.setState({error: taskInfo.error});
|
if (taskInfo.error && showErrors) this.setState({error: taskInfo.error});
|
||||||
}).fail(error => {
|
}).fail(error => {
|
||||||
this.setState({error: error.statusText, loading: false});
|
this.setState({error: error.statusText});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount(){
|
componentWillUnmount(){
|
||||||
if (this.monitorTimeout) clearTimeout(this.monitorTimeout);
|
if (this.intervalId) clearInterval(this.intervalId);
|
||||||
}
|
|
||||||
|
|
||||||
handleClick = () => {
|
|
||||||
const { taskInfo } = this.state;
|
|
||||||
if (!taskInfo.shared){
|
|
||||||
this.shareDialog.show();
|
|
||||||
}else if (taskInfo.oam_upload_id){
|
|
||||||
window.open(`https://map.openaerialmap.org/#/upload/status/${encodeURIComponent(taskInfo.oam_upload_id)}`, '_blank');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
shareToDdb = (formData) => {
|
shareToDdb = (formData) => {
|
||||||
const { task } = this.props;
|
const { task } = this.props;
|
||||||
|
|
||||||
const oamParams = {
|
|
||||||
token: this.props.token,
|
|
||||||
sensor: formData.sensor,
|
|
||||||
acquisition_start: formData.startDate,
|
|
||||||
acquisition_end: formData.endDate,
|
|
||||||
title: formData.title,
|
|
||||||
provider: formData.provider,
|
|
||||||
tags: formData.tags
|
|
||||||
};
|
|
||||||
|
|
||||||
return $.ajax({
|
return $.ajax({
|
||||||
url: `/api/plugins/dronedb/task/${task.id}/share`,
|
url: `/api/plugins/dronedb/projects/${task.project}/tasks/${task.id}/share`,
|
||||||
contentType: 'application/json',
|
contentType: 'application/json',
|
||||||
data: JSON.stringify({
|
//data: JSON.stringify({
|
||||||
oamParams: oamParams
|
// oamParams: oamParams
|
||||||
}),
|
//}),
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
type: 'POST'
|
type: 'POST'
|
||||||
}).done(taskInfo => {
|
}).done(taskInfo => {
|
||||||
// Allow a user to associate the sensor name coming from the EXIF tags
|
// Allow a user to associate the sensor name coming from the EXIF tags
|
||||||
// to one that perhaps is more human readable.
|
// to one that perhaps is more human readable.
|
||||||
Storage.setItem("oam_sensor_pref_" + taskInfo.sensor, formData.sensor);
|
|
||||||
Storage.setItem("oam_provider_pref", formData.provider);
|
|
||||||
|
|
||||||
this.setState({taskInfo});
|
this.setState({taskInfo});
|
||||||
this.monitorProgress();
|
|
||||||
|
if (this.state.intervalId) clearInterval(this.state.intervalId);
|
||||||
|
|
||||||
|
this.state.intervalId = setInterval(() => {
|
||||||
|
this.updateTaskInfo(true);
|
||||||
|
|
||||||
|
if (this.state.taskInfo.status == STATE_DONE || this.state.taskInfo.status == STATE_ERROR) {
|
||||||
|
clearInterval(this.state.intervalId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}, 3000);
|
||||||
|
|
||||||
|
//this.monitorProgress();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
monitorProgress = () => {
|
monitorProgress = () => {
|
||||||
if (this.state.taskInfo.sharing){
|
if (this.state.taskInfo.sharing){
|
||||||
// Monitor progress
|
// Monitor progress
|
||||||
this.monitorTimeout = setTimeout(() => {
|
this.monitorTimeout = setTimeout(() => {
|
||||||
this.updateTaskInfo(true).always(this.monitorProgress);
|
this.updateTaskInfo(true).always(this.monitorProgress);
|
||||||
}, 5000);
|
}, 3000);
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
handleClick = e => {
|
handleClick = e => {
|
||||||
console.log("Clicked");
|
console.log("Clicked");
|
||||||
|
|
||||||
|
if (this.state.taskInfo.status == STATE_IDLE){
|
||||||
|
this.shareToDdb();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.state.taskInfo.status == STATE_DONE){
|
||||||
|
window.open(this.state.taskInfo.shareUrl, '_blank');
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -154,8 +154,8 @@ export default class ShareButton extends React.Component{
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="share-button">
|
<div className="share-button">
|
||||||
<button className="btn btn-primary btn-sm" onClick={this.handleClick} disabled={taskInfo == null || taskInfo.error}>
|
<button className="btn btn-primary btn-sm" onClick={this.handleClick} disabled={this.state.taskInfo == null || this.state.taskInfo.error || this.state.taskInfo.status == 1 }>
|
||||||
<i className={getButtonIcon()}></i>
|
<i className={getButtonIcon()}></i>
|
||||||
{getButtonLabel()}
|
{getButtonLabel()}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
Ładowanie…
Reference in New Issue