kopia lustrzana https://github.com/OpenDroneMap/WebODM
Task moving functionality working
rodzic
9a70c07aca
commit
9bb8b1bed5
|
@ -310,9 +310,6 @@ class Task(models.Model):
|
|||
self.move_assets(self.__original_project_id, self.project.id)
|
||||
self.__original_project_id = self.project.id
|
||||
|
||||
# Autovalidate on save
|
||||
self.full_clean()
|
||||
|
||||
super(Task, self).save(*args, **kwargs)
|
||||
|
||||
def assets_path(self, *args):
|
||||
|
|
|
@ -123,7 +123,7 @@ def build_plugins():
|
|||
|
||||
# Check for webpack.config.js (if we need to build it)
|
||||
if plugin.path_exists("public/webpack.config.js"):
|
||||
if settings.DEV and webpack_watch_process_count() <= 2:
|
||||
if settings.DEV and webpack_watch_process_count() <= 2 and settings.DEV_WATCH_PLUGINS:
|
||||
logger.info("Running webpack with watcher for {}".format(plugin.get_name()))
|
||||
subprocess.Popen(['webpack-cli', '--watch'], cwd=plugin.get_path("public"))
|
||||
elif not plugin.path_exists("public/build"):
|
||||
|
|
|
@ -95,6 +95,10 @@ class FormDialog extends React.Component {
|
|||
hide(){
|
||||
this.setState({showModal: false});
|
||||
if (this.props.onHide) this.props.onHide();
|
||||
if (this.serverRequest){
|
||||
this.serverRequest.abort();
|
||||
this.serverRequest = null;
|
||||
}
|
||||
}
|
||||
|
||||
handleSave(e){
|
||||
|
@ -105,13 +109,20 @@ class FormDialog extends React.Component {
|
|||
let formData = {};
|
||||
if (this.props.getFormData) formData = this.props.getFormData();
|
||||
|
||||
this.props.saveAction(formData).fail(e => {
|
||||
this.setState({error: e.message || (e.responseJSON || {}).detail || e.responseText || _("Could not apply changes")});
|
||||
}).always(() => {
|
||||
this.serverRequest = this.props.saveAction(formData);
|
||||
if (this.serverRequest){
|
||||
this.serverRequest.fail(e => {
|
||||
this.setState({error: e.message || (e.responseJSON || {}).detail || e.responseText || _("Could not apply changes")});
|
||||
}).always(() => {
|
||||
this.setState({saving: false});
|
||||
this.serverRequest = null;
|
||||
}).done(() => {
|
||||
this.hide();
|
||||
});
|
||||
}else{
|
||||
this.setState({saving: false});
|
||||
}).done(() => {
|
||||
this.hide();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
handleDelete(){
|
||||
|
|
|
@ -27,7 +27,7 @@ class MoveTaskDialog extends React.Component {
|
|||
super(props);
|
||||
|
||||
this.state = {
|
||||
projectId: props.task.project.id,
|
||||
projectId: props.task.project,
|
||||
projects: [],
|
||||
loading: true
|
||||
};
|
||||
|
@ -37,7 +37,7 @@ class MoveTaskDialog extends React.Component {
|
|||
}
|
||||
|
||||
getFormData(){
|
||||
return this.state;
|
||||
return {project: this.state.projectId};
|
||||
}
|
||||
|
||||
onShow(){
|
||||
|
@ -82,20 +82,22 @@ class MoveTaskDialog extends React.Component {
|
|||
getFormData={this.getFormData}
|
||||
onShow={this.onShow}
|
||||
ref={(domNode) => { this.dialog = domNode; }}>
|
||||
{!this.state.loading ?
|
||||
<div className="form-group">
|
||||
<label className="col-sm-2 control-label">{_("Project")}</label>
|
||||
<div className="col-sm-10">
|
||||
<select className="form-control"
|
||||
value={this.state.projectId}
|
||||
onChange={this.handleProjectChange}>
|
||||
{this.state.projects.map(p =>
|
||||
<option value={p.id} key={p.id}>{p.name}</option>
|
||||
)}
|
||||
</select>
|
||||
<div style={{minHeight: '50px'}}>
|
||||
{!this.state.loading ?
|
||||
<div className="form-group">
|
||||
<label className="col-sm-2 control-label">{_("Project")}</label>
|
||||
<div className="col-sm-10">
|
||||
<select className="form-control"
|
||||
value={this.state.projectId}
|
||||
onChange={this.handleProjectChange}>
|
||||
{this.state.projects.map(p =>
|
||||
<option value={p.id} key={p.id}>{p.name}</option>
|
||||
)}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
: <i className="fa fa-circle-notch fa-spin fa-fw name-loading"></i>}
|
||||
</div>
|
||||
: <i className="fa fa-circle-notch fa-spin fa-fw name-loading"></i>}
|
||||
</FormDialog>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -85,6 +85,12 @@ class ProjectList extends Paginated {
|
|||
});
|
||||
}
|
||||
|
||||
handleTaskMoved = (task) => {
|
||||
if (this["projectListItem_" + task.project]){
|
||||
this["projectListItem_" + task.project].newTaskAdded();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.loading){
|
||||
return (<div className="project-list text-center"><i className="fa fa-sync fa-spin fa-2x fa-fw"></i></div>);
|
||||
|
@ -95,9 +101,11 @@ class ProjectList extends Paginated {
|
|||
<ul className={"list-group project-list " + (this.state.refreshing ? "refreshing" : "")}>
|
||||
{this.state.projects.map(p => (
|
||||
<ProjectListItem
|
||||
ref={(domNode) => { this["projectListItem_" + p.id] = domNode }}
|
||||
key={p.id}
|
||||
data={p}
|
||||
onDelete={this.handleDelete}
|
||||
onDelete={this.handleDelete}
|
||||
onTaskMoved={this.handleTaskMoved}
|
||||
history={this.props.history} />
|
||||
))}
|
||||
</ul>
|
||||
|
|
|
@ -20,7 +20,8 @@ class ProjectListItem extends React.Component {
|
|||
static propTypes = {
|
||||
history: PropTypes.object.isRequired,
|
||||
data: PropTypes.object.isRequired, // project json
|
||||
onDelete: PropTypes.func
|
||||
onDelete: PropTypes.func,
|
||||
onTaskMoved: PropTypes.func,
|
||||
}
|
||||
|
||||
constructor(props){
|
||||
|
@ -305,8 +306,9 @@ class ProjectListItem extends React.Component {
|
|||
this.refresh();
|
||||
}
|
||||
|
||||
taskMoved(){
|
||||
this.refresh();
|
||||
taskMoved(task){
|
||||
this.refresh();
|
||||
if (this.props.onTaskMoved) this.props.onTaskMoved(task);
|
||||
}
|
||||
|
||||
handleDelete(){
|
||||
|
@ -575,7 +577,7 @@ class ProjectListItem extends React.Component {
|
|||
ref={this.setRef("taskList")}
|
||||
source={`/api/projects/${data.id}/tasks/?ordering=-created_at`}
|
||||
onDelete={this.taskDeleted}
|
||||
onMove={this.taskMoved}
|
||||
onTaskMoved={this.taskMoved}
|
||||
hasPermission={this.hasPermission}
|
||||
history={this.props.history}
|
||||
/> : ""}
|
||||
|
|
|
@ -10,7 +10,7 @@ class TaskList extends React.Component {
|
|||
history: PropTypes.object.isRequired,
|
||||
source: PropTypes.string.isRequired, // URL where to load task list
|
||||
onDelete: PropTypes.func,
|
||||
onMove: PropTypes.func,
|
||||
onTaskMoved: PropTypes.func,
|
||||
hasPermission: PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
|
@ -71,11 +71,9 @@ class TaskList extends React.Component {
|
|||
if (this.props.onDelete) this.props.onDelete(id);
|
||||
}
|
||||
|
||||
moveTask(id){
|
||||
this.setState({
|
||||
tasks: this.state.tasks.filter(t => t.id !== id)
|
||||
});
|
||||
if (this.props.onMove) this.props.onMove(id);
|
||||
moveTask = (task) => {
|
||||
this.refresh();
|
||||
if (this.props.onTaskMoved) this.props.onTaskMoved(task);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -85,7 +83,7 @@ class TaskList extends React.Component {
|
|||
}else if (this.state.error){
|
||||
message = (<span>{interpolate(_("Error: %(error)s"), {error: this.state.error})} <a href="javascript:void(0);" onClick={this.retry}>{_("Try again")}</a></span>);
|
||||
}else if (this.state.tasks.length === 0){
|
||||
message = (<span>{_("This project has no tasks. Create one by uploading some images!")}</span>);
|
||||
message = (<span></span>);
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
@ -370,6 +370,18 @@ class TaskListItem extends React.Component {
|
|||
};
|
||||
}
|
||||
|
||||
moveTaskAction = (formData) => {
|
||||
if (formData.project !== this.state.task.project){
|
||||
return $.ajax({
|
||||
url: `/api/projects/${this.state.task.project}/tasks/${this.state.task.id}/`,
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify(formData),
|
||||
dataType: 'json',
|
||||
type: 'PATCH'
|
||||
}).done(this.props.onMove);
|
||||
}else return false;
|
||||
}
|
||||
|
||||
render() {
|
||||
const task = this.state.task;
|
||||
const name = task.name !== null ? task.name : interpolate(_("Task #%(number)s"), { number: task.id });
|
||||
|
@ -626,10 +638,9 @@ class TaskListItem extends React.Component {
|
|||
}
|
||||
|
||||
// Ability to change options
|
||||
const canAddDelPerms = this.props.hasPermission("add") && this.props.hasPermission("delete");
|
||||
const editable = [statusCodes.FAILED, statusCodes.COMPLETED, statusCodes.CANCELED].indexOf(task.status) !== -1;
|
||||
|
||||
if (canAddDelPerms){
|
||||
if (this.props.hasPermission("change")){
|
||||
if (editable || (!task.processing_node)){
|
||||
taskActions.push(<li key="edit"><a href="javascript:void(0)" onClick={this.startEditing}><i className="glyphicon glyphicon-pencil"></i>{_("Edit")}</a></li>);
|
||||
}
|
||||
|
@ -661,7 +672,7 @@ class TaskListItem extends React.Component {
|
|||
task={task}
|
||||
ref={(domNode) => { this.moveTaskDialog = domNode; }}
|
||||
onHide={() => this.setState({showMoveDialog: false})}
|
||||
saveAction={() => {}}
|
||||
saveAction={this.moveTaskAction}
|
||||
/>
|
||||
: ""}
|
||||
<div className="row">
|
||||
|
|
|
@ -32,6 +32,7 @@ services:
|
|||
- WO_DEBUG
|
||||
- WO_BROKER
|
||||
- WO_DEV
|
||||
- WO_DEV_WATCH_PLUGINS
|
||||
restart: unless-stopped
|
||||
oom_score_adj: 0
|
||||
broker:
|
||||
|
|
|
@ -82,6 +82,10 @@ case $key in
|
|||
export WO_DEBUG=YES
|
||||
shift # past argument
|
||||
;;
|
||||
--dev-watch-plugins)
|
||||
export WO_DEV_WATCH_PLUGINS=YES
|
||||
shift # past argument
|
||||
;;
|
||||
--dev)
|
||||
export WO_DEBUG=YES
|
||||
export WO_DEV=YES
|
||||
|
@ -148,6 +152,7 @@ usage(){
|
|||
echo " --ssl-insecure-port-redirect <port> Insecure port number to redirect from when SSL is enabled (default: $DEFAULT_SSL_INSECURE_PORT_REDIRECT)"
|
||||
echo " --debug Enable debug for development environments (default: disabled)"
|
||||
echo " --dev Enable development mode. In development mode you can make modifications to WebODM source files and changes will be reflected live. (default: disabled)"
|
||||
echo " --dev-watch-plugins Automatically build plugins while in dev mode. (default: disabled)"
|
||||
echo " --broker Set the URL used to connect to the celery broker (default: $DEFAULT_BROKER)"
|
||||
echo " --detached Run WebODM in detached mode. This means WebODM will run in the background, without blocking the terminal (default: disabled)"
|
||||
exit
|
||||
|
|
|
@ -52,6 +52,7 @@ WORKER_RUNNING = sys.argv[2:3] == ["worker"]
|
|||
# SECURITY WARNING: don't run with debug turned on a public facing server!
|
||||
DEBUG = os.environ.get('WO_DEBUG', 'YES') == 'YES' or TESTING
|
||||
DEV = os.environ.get('WO_DEV', 'NO') == 'YES' and not TESTING
|
||||
DEV_WATCH_PLUGINS = DEV and os.environ.get('WO_DEV_WATCH_PLUGINS', 'NO') == 'YES'
|
||||
SESSION_COOKIE_SECURE = CSRF_COOKIE_SECURE = os.environ.get('WO_SSL', 'NO') == 'YES'
|
||||
INTERNAL_IPS = ['127.0.0.1']
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue