Task edit panel, upload improvements

pull/34/head
Piero Toffanin 2016-10-18 11:25:14 -04:00
rodzic 58a7f9ea4c
commit 6036e613f6
6 zmienionych plików z 170 dodań i 37 usunięć

Wyświetl plik

@ -24,7 +24,7 @@ class TaskViewSet(viewsets.ViewSet):
Once a processing node completes processing, results are stored in the task.
"""
queryset = models.Task.objects.all()
# We don't use object level permissions on tasks, relying on
# project's object permissions instead (but standard model permissions still apply)
permission_classes = (permissions.DjangoModelPermissions, )

Wyświetl plik

@ -0,0 +1,75 @@
import '../css/EditTaskPanel.scss';
import React from 'react';
class EditTaskPanel extends React.Component {
constructor(){
super();
this.namePlaceholder = "Task of " + (new Date()).toISOString();
this.state = {
name: "",
advancedOptions: false
};
this.handleNameChange = this.handleNameChange.bind(this);
this.setAdvancedOptions = this.setAdvancedOptions.bind(this);
this.save = this.save.bind(this);
}
handleNameChange(e){
this.setState({name: e.target.value});
}
setAdvancedOptions(flag){
return () => {
this.setState({advancedOptions: flag});
};
}
save(){
}
render() {
return (
<div className="edit-task-panel">
<form className="form-horizontal">
<p>Your images are being uploaded. In the meanwhile, set these additional options:</p>
<div className="form-group">
<label className="col-sm-2 control-label">Name</label>
<div className="col-sm-10">
<input type="text" onChange={this.handleNameChange} className="form-control" placeholder={this.namePlaceholder} />
</div>
</div>
<div className="form-group">
<label className="col-sm-2 control-label">Processing Node</label>
<div className="col-sm-10">
<select className="form-control">
<option>Auto</option>
<option>1</option>
<option>2</option>
</select>
</div>
</div>
<div className="form-group">
<label className="col-sm-2 control-label">Options</label>
<div className="col-sm-10">
<div className="btn-group" role="group">
<button type="button" className={"btn " + (!this.state.advancedOptions ? "btn-default" : "btn-secondary")} onClick={this.setAdvancedOptions(false)}>Default</button>
<button type="button" className={"btn " + (this.state.advancedOptions ? "btn-default" : "btn-secondary")} onClick={this.setAdvancedOptions(true)}>Advanced</button>
</div>
</div>
</div>
<div className="form-group">
<div className="col-sm-offset-2 col-sm-10 text-right">
<button type="submit" className="btn btn-default" onClick={this.save}>Save</button>
</div>
</div>
</form>
</div>
);
}
}
export default EditTaskPanel;

Wyświetl plik

@ -2,6 +2,7 @@ import '../css/ProjectListItem.scss';
import React from 'react';
import update from 'react-addons-update';
import ProjectListItemPanel from './ProjectListItemPanel';
import EditTaskPanel from './EditTaskPanel';
import UploadProgressBar from './UploadProgressBar';
import Dropzone from '../vendor/dropzone';
import csrf from '../django/csrf';
@ -13,16 +14,21 @@ class ProjectListItem extends React.Component {
this.state = {
showPanel: false,
upload: this.getDefaultUploadState()
upload: this.getDefaultUploadState(),
taskId: null
};
this.togglePanel = this.togglePanel.bind(this);
this.handleUpload = this.handleUpload.bind(this);
this.closeUploadError = this.closeUploadError.bind(this);
this.cancelUpload = this.cancelUpload.bind(this);
}
getDefaultUploadState(){
return {
uploading: false,
showEditTask: false,
error: "",
progress: 0,
totalCount: 0,
totalBytes: 0,
@ -45,7 +51,7 @@ class ProjectListItem extends React.Component {
componentDidMount(){
Dropzone.autoDiscover = false;
let dz = new Dropzone(this.dropzone, {
this.dz = new Dropzone(this.dropzone, {
paramName: "images",
url : `/api/projects/${this.props.data.id}/tasks/`,
parallelUploads: 9999999,
@ -60,7 +66,7 @@ class ProjectListItem extends React.Component {
}
});
dz.on("totaluploadprogress", (progress, totalBytes, totalBytesSent) => {
this.dz.on("totaluploadprogress", (progress, totalBytes, totalBytesSent) => {
this.setUploadState({
progress, totalBytes, totalBytesSent
});
@ -72,13 +78,22 @@ class ProjectListItem extends React.Component {
})
.on("processingmultiple", () => {
this.setUploadState({
uploading: true
uploading: true,
showEditTask: true
})
})
.on("completemultiple", () => {
this.setUploadState({
uploading: false
})
.on("completemultiple", (files) => {
// Check
let success = files.filter(file => file.status !== "success").length === 0;
if (success){
this.setUploadState({uploading: false});
}else{
this.setUploadState({
uploading: false,
error: "Could not upload all files. An error occured."
});
}
})
.on("reset", () => {
this.resetUploadState();
@ -97,46 +112,76 @@ class ProjectListItem extends React.Component {
});
}
closeUploadError(){
this.setUploadState({error: ""});
}
cancelUpload(e){
this.dz.removeAllFiles(true);
}
handleUpload(){
this.resetUploadState();
}
render() {
// TODO: Task Options Component
return (
<li className="project-list-item list-group-item"
href="javascript:void(0);">
<div className="row no-margin">
<div className="btn-group pull-right">
<button type="button" className="btn btn-primary btn-sm" onClick={this.handleUpload} ref={this.setRef("uploadButton")}>
<i className="glyphicon glyphicon-upload"></i>
Upload Images
</button>
<button type="button" className="btn btn-default btn-sm">
<i className="fa fa-globe"></i> Map View
</button>
<button type="button" className="btn btn-default btn-sm dropdown-toggle" data-toggle="dropdown">
<span className="caret"></span>
</button>
<ul className="dropdown-menu">
<li><a href="javascript:alert('TODO!');"><i className="fa fa-cube"></i> 3D View</a></li>
</ul>
</div>
<div className="row no-margin">
<div className="btn-group pull-right">
<button type="button"
className={"btn btn-primary btn-sm " + (this.state.upload.uploading ? "hide" : "")}
onClick={this.handleUpload}
ref={this.setRef("uploadButton")}>
<i className="glyphicon glyphicon-upload"></i>
Upload Images
</button>
<button disabled={this.state.upload.error !== ""}
type="button"
className={"btn btn-primary btn-sm " + (!this.state.upload.uploading ? "hide" : "")}
onClick={this.cancelUpload}>
<i className="glyphicon glyphicon-remove-circle"></i>
Cancel Upload
</button>
<i style={{width: 14}} className={'fa ' + (this.state.showPanel ? 'fa-caret-down' : 'fa-caret-right')}>
</i> <a href="javascript:void(0);" onClick={this.togglePanel}>
{this.props.data.name}
</a>
<button type="button" className="btn btn-default btn-sm">
<i className="fa fa-globe"></i> Map View
</button>
<button type="button" className="btn btn-default btn-sm dropdown-toggle" data-toggle="dropdown">
<span className="caret"></span>
</button>
<ul className="dropdown-menu">
<li><a href="javascript:alert('TODO!');"><i className="fa fa-cube"></i> 3D View</a></li>
</ul>
</div>
<div className="dropzone" ref={this.setRef("dropzone")}>
<div className="dz-default dz-message text-center">
</div>
<i style={{width: 14}} className={'fa ' + (this.state.showPanel ? 'fa-caret-down' : 'fa-caret-right')}>
</i> <a href="javascript:void(0);" onClick={this.togglePanel}>
{this.props.data.name}
</a>
</div>
<div className="row">
<div className="dropzone" ref={this.setRef("dropzone")}>
<div className="dz-default dz-message text-center">
</div>
</div>
{this.state.upload.uploading ? <UploadProgressBar {...this.state.upload}/> : ""}
{this.state.upload.uploading ? <UploadProgressBar {...this.state.upload}/> : ""}
{this.state.upload.error !== "" ?
<div className="alert alert-warning alert-dismissible">
<button type="button" className="close" aria-label="Close" onClick={this.closeUploadError}><span aria-hidden="true">&times;</span></button>
{this.state.upload.error}
</div>
: ""}
{this.state.showPanel ? <ProjectListItemPanel /> : ""}
<EditTaskPanel className={!this.state.upload.showEditTask ? "hide" : ""} />
{this.state.showPanel ? <ProjectListItemPanel /> : ""}
</div>
</li>
);
}

Wyświetl plik

@ -3,8 +3,10 @@
min-height: 100px;
}
.row.no-margin{
margin: 0;
.row{
&.no-margin{
margin: 0;
}
}
.progress{

Wyświetl plik

@ -0,0 +1,5 @@
.edit-task-panel{
background-color: #ecf0f1;
padding: 10px;
margin-top: 10px;
}

Wyświetl plik

@ -4,4 +4,10 @@
.dz-preview{
display: none;
}
.row{
margin-left: 0;
margin-right: 0;
margin-top: 10px;
}
}