Added shot editing.
This commit is contained in:
@@ -4,6 +4,7 @@ from flask import Blueprint, render_template, request
|
|||||||
import flask
|
import flask
|
||||||
|
|
||||||
import pillarsdk
|
import pillarsdk
|
||||||
|
import pillar.api.utils
|
||||||
from pillar.web.system_util import pillar_api
|
from pillar.web.system_util import pillar_api
|
||||||
|
|
||||||
from attract.modules import attract_project_view
|
from attract.modules import attract_project_view
|
||||||
@@ -67,10 +68,17 @@ def view_shot(project, attract_props, shot_id):
|
|||||||
api = pillar_api()
|
api = pillar_api()
|
||||||
|
|
||||||
shot = pillarsdk.Node.find(shot_id, api=api)
|
shot = pillarsdk.Node.find(shot_id, api=api)
|
||||||
|
node_type = project.get_node_type(node_type_shot['name'])
|
||||||
|
|
||||||
return render_template('attract/shots/shot.html',
|
if request.is_xhr:
|
||||||
|
template = 'attract/shots/view_shot_embed.html'
|
||||||
|
else:
|
||||||
|
template = 'attract/shots/view_shot.html'
|
||||||
|
|
||||||
|
return render_template(template,
|
||||||
shot=shot,
|
shot=shot,
|
||||||
project=project,
|
project=project,
|
||||||
|
shot_node_type=node_type,
|
||||||
attract_props=attract_props)
|
attract_props=attract_props)
|
||||||
|
|
||||||
|
|
||||||
@@ -83,7 +91,7 @@ def save(project, shot_id):
|
|||||||
shot_dict = request.form.to_dict()
|
shot_dict = request.form.to_dict()
|
||||||
shot = current_attract.shot_manager.edit_shot(shot_id, **shot_dict)
|
shot = current_attract.shot_manager.edit_shot(shot_id, **shot_dict)
|
||||||
|
|
||||||
return flask.jsonify({'shot_id': shot_id, 'etag': shot._etag, 'time': shot._updated })
|
return pillar.api.utils.jsonify(shot.to_dict())
|
||||||
|
|
||||||
|
|
||||||
# TODO: remove GET method once Pablo has made a proper button to call this URL with a POST.
|
# TODO: remove GET method once Pablo has made a proper button to call this URL with a POST.
|
||||||
|
@@ -47,6 +47,32 @@ function task_open(task_id, project_url) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows a shot in the #task-details div.
|
||||||
|
*/
|
||||||
|
function shot_open(shot_id, project_url) {
|
||||||
|
if (shot_id === undefined || project_url === undefined) {
|
||||||
|
if (console) console.log("shot_open(", shot_id, project_url, ") called.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#shot-list').find('a').removeClass('active');
|
||||||
|
$('#shot-link' + shot_id).addClass('active');
|
||||||
|
|
||||||
|
var shot_url = '/attract/' + project_url + '/shots/' + shot_id;
|
||||||
|
console.log('shot_url is ' + shot_url);
|
||||||
|
|
||||||
|
$.get(shot_url, function(shot_data) {
|
||||||
|
$('#task-details').html(shot_data);
|
||||||
|
}).fail(function(xhr) {
|
||||||
|
if (console) {
|
||||||
|
console.log('Error fetching shot', shot_id, 'from', shot_url);
|
||||||
|
console.log('XHR:', xhr);
|
||||||
|
}
|
||||||
|
$('#task-details').html(xhr.responseText);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a task and show it in the #task-details div.
|
* Create a task and show it in the #task-details div.
|
||||||
*/
|
*/
|
||||||
@@ -75,48 +101,79 @@ function task_create(shot_id, project_url, task_type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function task_save(task_id, task_url) {
|
function attract_form_save(form_id, item_id, item_save_url, options={})
|
||||||
console.log('Saving task to', task_url);
|
{
|
||||||
|
var $form = $('#' + form_id);
|
||||||
var $form = $('#task-view form');
|
|
||||||
var $button = $form.find("button[type='submit']");
|
var $button = $form.find("button[type='submit']");
|
||||||
|
|
||||||
var payload = $form.serialize();
|
var payload = $form.serialize();
|
||||||
var task = '#task-' + task_id;
|
var $item = $('#' + item_id);
|
||||||
var $task = $(task);
|
|
||||||
|
|
||||||
$button.attr('disabled', true);
|
$button.attr('disabled', true);
|
||||||
$task.addClass('processing');
|
$item.addClass('processing');
|
||||||
$('#status-bar').text('Saving task...');
|
$('#status-bar').text('Saving task...');
|
||||||
|
|
||||||
if (console) console.log('Sending:', payload);
|
if (console) console.log('Sending:', payload);
|
||||||
|
|
||||||
$.post(task_url, payload)
|
$.post(item_save_url, payload)
|
||||||
.done(function(saved_task) {
|
.done(function(saved_item) {
|
||||||
if (console) console.log('Done saving', saved_task);
|
if (console) console.log('Done saving', saved_item);
|
||||||
|
$('#status-bar').text('Saved item. ' + saved_item._updated);
|
||||||
|
|
||||||
|
if (options.done) options.done($item, saved_item);
|
||||||
|
})
|
||||||
|
.fail(function(xhr_or_response_data) {
|
||||||
|
// jQuery sends the response data (if JSON), or an XHR object (if not JSON).
|
||||||
|
if (console) console.log('Failed saving', xhr_or_response_data);
|
||||||
|
$('#status-bar').text('Failed saving. ' + xhr_or_response_data.responseText);
|
||||||
|
|
||||||
|
if (options.fail) options.fail($item, xhr_or_response_data);
|
||||||
|
})
|
||||||
|
.always(function() {
|
||||||
|
$button.attr('disabled', false);
|
||||||
|
$item.removeClass('processing');
|
||||||
|
|
||||||
|
if (options.always) options.always($item);
|
||||||
|
})
|
||||||
|
;
|
||||||
|
|
||||||
|
return false; // prevent synchronous POST to current page.
|
||||||
|
}
|
||||||
|
|
||||||
|
function task_save(task_id, task_url) {
|
||||||
|
return attract_form_save('task_form', 'task-' + task_id, task_url, {
|
||||||
|
done: function($task, saved_task) {
|
||||||
// Update the task list.
|
// Update the task list.
|
||||||
// NOTE: this is tightly linked to the HTML of the task list in for_project.jade.
|
// NOTE: this is tightly linked to the HTML of the task list in for_project.jade.
|
||||||
$('.task-name-' + saved_task._id).text(saved_task.name).flashOnce();
|
$('.task-name-' + saved_task._id).text(saved_task.name).flashOnce();
|
||||||
$task.find('span.name').text(saved_task.name);
|
$task.find('span.name').text(saved_task.name);
|
||||||
$task.find('span.type').text(saved_task.task_type);
|
$task.find('span.type').text(saved_task.task_type);
|
||||||
$task.find('span.status').text(saved_task.properties.status.replace('_', ' '));
|
$task.find('span.status').text(saved_task.properties.status.replace('_', ' '));
|
||||||
|
|
||||||
|
// FIXME: remove all existing status-XXX classes.
|
||||||
$task
|
$task
|
||||||
.removeClass('col-list-item task-list-item')
|
.removeClass('col-list-item task-list-item')
|
||||||
.addClass('col-list-item task-list-item status-' + saved_task.properties.status);
|
.addClass('col-list-item task-list-item status-' + saved_task.properties.status);
|
||||||
|
},
|
||||||
$('#status-bar').text('Saved task. ' + saved_task._updated);
|
fail: function($item, xhr_or_response_data) {
|
||||||
})
|
|
||||||
.fail(function(xhr_or_response_data) {
|
|
||||||
// jQuery sends the response data (if JSON), or an XHR object (if not JSON).
|
|
||||||
if (console) console.log('Failed saving', xhr_or_response_data);
|
|
||||||
$('#task-details').html(xhr_or_response_data.responseText);
|
$('#task-details').html(xhr_or_response_data.responseText);
|
||||||
$('#status-bar').text('Failed saving. ' + xhr_or_response_data.responseText);
|
}
|
||||||
})
|
});
|
||||||
.always(function() {
|
}
|
||||||
$button.attr('disabled', false);
|
|
||||||
$task.removeClass('processing');
|
function shot_save(shot_id, shot_url) {
|
||||||
})
|
return attract_form_save('shot_form', 'shot-' + shot_id, shot_url, {
|
||||||
;
|
done: function($shot, saved_shot) {
|
||||||
|
// Update the shot list.
|
||||||
return false; // prevent synchronous POST to current page.
|
$('.shot-name-' + saved_shot._id).text(saved_shot.name).flashOnce();
|
||||||
|
|
||||||
|
// FIXME: remove all existing status-XXX classes.
|
||||||
|
$shot
|
||||||
|
.removeClass('col-list-item shot-list-item')
|
||||||
|
.addClass('col-list-item shot-list-item status-' + saved_shot.properties.status);
|
||||||
|
},
|
||||||
|
fail: function($item, xhr_or_response_data) {
|
||||||
|
$('#task-details').html(xhr_or_response_data.responseText);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
#task-view
|
.attract-form
|
||||||
margin: 10px
|
margin: 10px
|
||||||
padding: 0 10px 10px
|
padding: 0 10px 10px
|
||||||
+container-box
|
+container-box
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
a#task-add(href="javascript:task_create('{{ project.url }}');") + Create Shot
|
a#task-add(href="javascript:task_create('{{ project.url }}');") + Create Shot
|
||||||
|
|
||||||
.table
|
.table#shot-list
|
||||||
.table-head
|
.table-head
|
||||||
.table-row
|
.table-row
|
||||||
.table-cell.shot-thumbnail Thumbnail
|
.table-cell.shot-thumbnail Thumbnail
|
||||||
@@ -21,7 +21,12 @@
|
|||||||
.table-row
|
.table-row
|
||||||
.table-cell
|
.table-cell
|
||||||
img(src="http://placehold.it/100x60")
|
img(src="http://placehold.it/100x60")
|
||||||
.table-cell.shot-name {{ shot.name }}
|
.table-cell.shot-name
|
||||||
|
a(
|
||||||
|
id="shot-link-{{ shot._id }}"
|
||||||
|
href="javascript:shot_open('{{ shot._id }}', '{{ project.url }}');",
|
||||||
|
class="status-{{ shot.properties.status }}")
|
||||||
|
span(class="shot-name-{{ shot._id }}") {{ shot.name }}
|
||||||
| {% for task_type in task_types %}
|
| {% for task_type in task_types %}
|
||||||
.table-cell.task-name
|
.table-cell.task-name
|
||||||
| {% for task in tasks_for_shots[shot._id][task_type] %}
|
| {% for task in tasks_for_shots[shot._id][task_type] %}
|
||||||
|
@@ -2,7 +2,8 @@
|
|||||||
| {% block page_title %}Shot {{ shot.name }}{% endblock %}
|
| {% block page_title %}Shot {{ shot.name }}{% endblock %}
|
||||||
| {% block body %}
|
| {% block body %}
|
||||||
#col_main
|
#col_main
|
||||||
h1 Shot {{ shot.name }}
|
h1 Shot 
|
||||||
|
span(class="shot-name-{{ shot._id }}") {{ shot.name }}
|
||||||
#col_right
|
#col_right
|
||||||
h1 Right
|
| {% include "attract/shots/shot_embed.html" %}
|
||||||
| {% endblock %}
|
| {% endblock %}
|
33
src/templates/attract/shots/view_shot_embed.jade
Normal file
33
src/templates/attract/shots/view_shot_embed.jade
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
.attract-form
|
||||||
|
form#shot_form(onsubmit="return shot_save('{{shot._id}}', '{{ url_for('attract.shots.perproject.save', project_url=project['url'], shot_id=shot._id) }}')")
|
||||||
|
.input-transparent-group
|
||||||
|
input.input-transparent.shot-name(
|
||||||
|
name="name",
|
||||||
|
type=text,
|
||||||
|
placeholder='Name',
|
||||||
|
value="{{ shot.name | hide_none }}")
|
||||||
|
|
||||||
|
.input-transparent-group
|
||||||
|
textarea.input-transparent(
|
||||||
|
name="description",
|
||||||
|
type=text,
|
||||||
|
placeholder='Description') {{ shot.description | hide_none }}
|
||||||
|
|
||||||
|
.input-transparent-group
|
||||||
|
label(for="shot-status") Status:
|
||||||
|
select.input-transparent#shot-status(
|
||||||
|
name="status")
|
||||||
|
| {% for status in shot_node_type.dyn_schema.status.allowed %}
|
||||||
|
| <option value="{{ status }}" {% if status == shot.properties.status %}selected{% endif %}>{{ status | undertitle }}</option>
|
||||||
|
| {% endfor %}
|
||||||
|
|
||||||
|
.input-transparent-group
|
||||||
|
textarea.input-transparent(
|
||||||
|
name="notes",
|
||||||
|
type=text,
|
||||||
|
placeholder='Notes') {{ shot.properties.notes | hide_none }}
|
||||||
|
|
||||||
|
.input-group-separator
|
||||||
|
|
||||||
|
.input-transparent-group
|
||||||
|
button.btn.btn-default.btn-block(type=submit) Save Changes
|
@@ -1,5 +1,5 @@
|
|||||||
#task-view
|
.attract-form
|
||||||
form(onsubmit="return task_save('{{task._id}}', '{{ url_for('attract.tasks.perproject.save', project_url=project['url'], task_id=task._id) }}')")
|
form#task_form(onsubmit="return task_save('{{task._id}}', '{{ url_for('attract.tasks.perproject.save', project_url=project['url'], task_id=task._id) }}')")
|
||||||
.input-transparent-group
|
.input-transparent-group
|
||||||
input.input-transparent.task-name(
|
input.input-transparent.task-name(
|
||||||
name="name",
|
name="name",
|
||||||
|
Reference in New Issue
Block a user