From 49f3ca69373ff9c1cea093a3f0a404ac31a17edc Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Fri, 10 Feb 2017 12:28:32 -0500 Subject: [PATCH] Edit functionality working, fixed restart lock issue --- app/models.py | 4 +- .../app/js/components/EditTaskDialog.jsx | 7 ++- app/static/app/js/components/EditTaskForm.jsx | 9 ++-- app/static/app/js/components/TaskListItem.jsx | 54 +++++++++++++++---- 4 files changed, 57 insertions(+), 17 deletions(-) diff --git a/app/models.py b/app/models.py index 1427c6bb..5ee7b84b 100644 --- a/app/models.py +++ b/app/models.py @@ -237,7 +237,7 @@ class Task(models.Model): try: info = self.processing_node.get_task_info(self.uuid) uuid_still_exists = info['uuid'] == self.uuid - except ProcessingError: + except ProcessingException: pass if uuid_still_exists: @@ -257,7 +257,7 @@ class Task(models.Model): self.pending_action = None self.save() else: - raise ProcessingError("Cannot restart a task that has no processing node or UUID") + raise ProcessingError("Cannot restart a task that has no processing node") elif self.pending_action == pending_actions.REMOVE: logger.info("Removing {}".format(self)) diff --git a/app/static/app/js/components/EditTaskDialog.jsx b/app/static/app/js/components/EditTaskDialog.jsx index 33fb7c16..0e73d73b 100644 --- a/app/static/app/js/components/EditTaskDialog.jsx +++ b/app/static/app/js/components/EditTaskDialog.jsx @@ -13,7 +13,8 @@ class EditTaskDialog extends React.Component { show: React.PropTypes.bool, task: React.PropTypes.object.isRequired, onHide: React.PropTypes.func, - onShow: React.PropTypes.func + onShow: React.PropTypes.func, + saveAction: React.PropTypes.func.isRequired }; constructor(props){ @@ -61,7 +62,9 @@ class EditTaskDialog extends React.Component { save(taskInfo){ if (this.state.editTaskFormLoaded){ - console.log(taskInfo); + return this.props.saveAction(taskInfo); + }else{ + return $.Deferred().reject(new Error("The form has not loaded, please wait.")); } } diff --git a/app/static/app/js/components/EditTaskForm.jsx b/app/static/app/js/components/EditTaskForm.jsx index a2372fa7..a12940af 100644 --- a/app/static/app/js/components/EditTaskForm.jsx +++ b/app/static/app/js/components/EditTaskForm.jsx @@ -30,7 +30,7 @@ class EditTaskForm extends React.Component { this.state = { error: "", - name: props.task !== null ? props.task.name : "", + name: props.task !== null ? (props.task.name || "") : "", advancedOptions: props.task !== null ? props.task.options.length > 0 : false, loadedProcessingNodes: false, selectedNode: null, @@ -175,7 +175,8 @@ class EditTaskForm extends React.Component { } getOptions(){ - return Object.values(this.options) + if (!this.state.advancedOptions) return []; + else return Object.values(this.options) .map(option => { return { name: option.props.name, @@ -200,10 +201,10 @@ class EditTaskForm extends React.Component { options.forEach(opt => { if (!opt.defaultValue){ let taskOpt; - if (task){ + if (task && Array.isArray(task.options)){ taskOpt = task.options.find(to => to.name == opt.name); } - + if (taskOpt){ opt.defaultValue = opt.value; opt.value = taskOpt.value; diff --git a/app/static/app/js/components/TaskListItem.jsx b/app/static/app/js/components/TaskListItem.jsx index 5d24b915..4d45984c 100644 --- a/app/static/app/js/components/TaskListItem.jsx +++ b/app/static/app/js/components/TaskListItem.jsx @@ -27,6 +27,8 @@ class TaskListItem extends React.Component { this.toggleExpanded = this.toggleExpanded.bind(this); this.consoleOutputUrl = this.consoleOutputUrl.bind(this); this.stopEditing = this.stopEditing.bind(this); + this.startEditing = this.startEditing.bind(this); + this.updateTask = this.updateTask.bind(this); } shouldRefresh(){ @@ -173,10 +175,38 @@ class TaskListItem extends React.Component { } } + startEditing(){ + this.setState({editing: true}); + } + stopEditing(){ this.setState({editing: false}); } + updateTask(taskInfo){ + let d = $.Deferred(); + + taskInfo.uuid = ""; // TODO: we could reuse the UUID so that images don't need to be re-uploaded! This needs changes on node-odm as well. + + taskInfo.processing_node = taskInfo.selectedNode.id; + delete(taskInfo.selectedNode); + + $.ajax({ + url: `/api/projects/${this.state.task.project}/tasks/${this.state.task.id}/`, + contentType: 'application/json', + data: JSON.stringify(taskInfo), + dataType: 'json', + type: 'PATCH' + }).done((json) => { + this.setState({task: json}); + d.resolve(); + }).fail(() => { + d.reject(new Error("Could not update task information. Plese try again.")); + }); + + return d; + } + render() { const task = this.state.task; const name = task.name !== null ? task.name : `Task #${task.id}`; @@ -204,6 +234,14 @@ class TaskListItem extends React.Component { }); } + // Ability to change options + if ([statusCodes.FAILED, statusCodes.COMPLETED, statusCodes.CANCELED].indexOf(task.status) !== -1 || + (!task.processing_node)){ + addActionButton("Edit", "btn-primary", "glyphicon glyphicon-pencil", () => { + this.startEditing(); + }); + } + if ([statusCodes.QUEUED, statusCodes.RUNNING, null].indexOf(task.status) !== -1 && task.processing_node){ addActionButton("Cancel", "btn-primary", "glyphicon glyphicon-remove-circle", this.genActionApiCall("cancel")); @@ -220,13 +258,6 @@ class TaskListItem extends React.Component { )); } - // Ability to change options - if ([statusCodes.FAILED, statusCodes.COMPLETED, statusCodes.CANCELED, null].indexOf(task.status) !== -1){ - addActionButton("Edit", "btn-primary", "glyphicon glyphicon-pencil", () => { - this.setState({editing: !this.state.editing}); - }); - } - addActionButton("Delete", "btn-danger", "glyphicon glyphicon-trash", this.genActionApiCall("remove", { confirm: "All information related to this task, including images, maps and models will be deleted. Continue?" })); @@ -288,12 +319,14 @@ class TaskListItem extends React.Component { let statusLabel = ""; let statusIcon = statusCodes.icon(task.status); + let showEditLink = false; if (task.last_error){ statusLabel = getStatusLabel(task.last_error, "error"); }else if (!task.processing_node){ - statusLabel = getStatusLabel("Processing node not set"); + statusLabel = getStatusLabel("Set a processing node"); statusIcon = "fa fa-hourglass-3"; + showEditLink = true; }else{ statusLabel = getStatusLabel(status, task.status == 40 ? "done" : ""); } @@ -311,7 +344,9 @@ class TaskListItem extends React.Component { {this.hoursMinutesSecs(this.state.time)}
- {statusLabel} + {showEditLink ? + {statusLabel} + : statusLabel}
@@ -326,6 +361,7 @@ class TaskListItem extends React.Component { task={this.state.task} show={true} onHide={this.stopEditing} + saveAction={this.updateTask} /> : ""}