Added etag checking when saving tasks & shots. Still a bit rough.
Needs nicer user interface stuff for explaining what's going on.
This commit is contained in:
@@ -92,6 +92,7 @@ class ShotManager(object):
|
||||
api = pillar_api()
|
||||
shot = pillarsdk.Node.find(shot_id, api=api)
|
||||
|
||||
shot._etag = fields.pop('_etag')
|
||||
shot.name = fields.pop('name')
|
||||
shot.description = fields.pop('description')
|
||||
shot.properties.status = fields.pop('status')
|
||||
|
@@ -133,13 +133,16 @@ function attract_form_save(form_id, item_id, item_save_url, options={})
|
||||
if (console) console.log('Done saving', saved_item);
|
||||
$('#status-bar')
|
||||
.text('Saved ' + options.type + '. ' + saved_item._updated);
|
||||
$form.find("input[name='_etag']").val(saved_item._etag);
|
||||
|
||||
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);
|
||||
|
||||
$button.removeClass('btn-default').addClass('btn-danger');
|
||||
$('#status-bar').text('Failed saving. ' + xhr_or_response_data.status);
|
||||
|
||||
if (options.fail) options.fail($item, xhr_or_response_data);
|
||||
})
|
||||
@@ -171,7 +174,12 @@ function task_save(task_id, task_url) {
|
||||
;
|
||||
},
|
||||
fail: function($item, xhr_or_response_data) {
|
||||
$('#task-details').html(xhr_or_response_data.responseText);
|
||||
if (xhr_or_response_data.status == 412) {
|
||||
// TODO: implement something nice here. Just make sure we don't throw
|
||||
// away the user's edits. It's up to the user to handle this.
|
||||
} else {
|
||||
$('#task-details').html(xhr_or_response_data.responseText);
|
||||
}
|
||||
},
|
||||
type: 'task'
|
||||
});
|
||||
@@ -189,7 +197,12 @@ function shot_save(shot_id, shot_url) {
|
||||
;
|
||||
},
|
||||
fail: function($item, xhr_or_response_data) {
|
||||
$('#task-details').html(xhr_or_response_data.responseText);
|
||||
if (xhr_or_response_data.status == 412) {
|
||||
// TODO: implement something nice here. Just make sure we don't throw
|
||||
// away the user's edits. It's up to the user to handle this.
|
||||
} else {
|
||||
$('#task-details').html(xhr_or_response_data.responseText);
|
||||
}
|
||||
},
|
||||
type: 'shot'
|
||||
});
|
||||
|
@@ -66,6 +66,7 @@ class TaskManager(object):
|
||||
api = pillar_api()
|
||||
task = pillarsdk.Node.find(task_id, api=api)
|
||||
|
||||
task._etag = fields.pop('_etag')
|
||||
task.name = fields.pop('name')
|
||||
task.description = fields.pop('description')
|
||||
task.properties.status = fields.pop('status')
|
||||
|
@@ -1,5 +1,6 @@
|
||||
.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(type='hidden',name='_etag',value='{{ shot._etag }}')
|
||||
.input-transparent-group
|
||||
input.input-transparent.item-name(
|
||||
name="name",
|
||||
@@ -30,4 +31,6 @@
|
||||
.input-group-separator
|
||||
|
||||
.input-transparent-group
|
||||
| {% if 'PUT' in shot.allowed_methods %}
|
||||
button.btn.btn-default.btn-block(type=submit) Save Changes
|
||||
| {% endif %}
|
||||
|
@@ -1,5 +1,6 @@
|
||||
.attract-form
|
||||
form#task_form(onsubmit="return task_save('{{task._id}}', '{{ url_for('attract.tasks.perproject.save', project_url=project['url'], task_id=task._id) }}')")
|
||||
input(type='hidden',name='_etag',value='{{ task._etag }}')
|
||||
.input-transparent-group
|
||||
input.input-transparent.item-name(
|
||||
name="name",
|
||||
@@ -47,7 +48,9 @@
|
||||
| {% endfor %}
|
||||
|
||||
.input-transparent-group
|
||||
button.btn.btn-default.btn-block(type=submit) Save Changes
|
||||
| {% if 'PUT' in task.allowed_methods %}
|
||||
button.btn.btn-default.btn-block(type='submit') Save Changes
|
||||
| {% endif %}
|
||||
|
||||
|
||||
#task-view-feed
|
||||
|
@@ -4,6 +4,7 @@ import responses
|
||||
from bson import ObjectId
|
||||
|
||||
import pillarsdk
|
||||
import pillarsdk.exceptions as sdk_exceptions
|
||||
import pillar.tests
|
||||
import pillar.auth
|
||||
import pillar.tests.common_test_data as ctd
|
||||
@@ -94,10 +95,19 @@ class ShotManagerTest(AbstractAttractTest):
|
||||
|
||||
self.mock_blenderid_validate_happy()
|
||||
|
||||
self.assertRaises(sdk_exceptions.PreconditionFailed,
|
||||
self.smngr.edit_shot,
|
||||
shot_id=shot['_id'],
|
||||
name=u'ผัดไทย',
|
||||
description=u'Shoot the Pad Thai',
|
||||
status='todo',
|
||||
_etag='jemoeder')
|
||||
|
||||
self.smngr.edit_shot(shot_id=shot['_id'],
|
||||
name=u'ผัดไทย',
|
||||
description=u'Shoot the Pad Thai',
|
||||
status='todo')
|
||||
status='todo',
|
||||
_etag=shot._etag)
|
||||
|
||||
# Test directly with MongoDB
|
||||
with self.app.test_request_context():
|
||||
@@ -107,4 +117,3 @@ class ShotManagerTest(AbstractAttractTest):
|
||||
self.assertEqual(u'todo', found['properties']['status'])
|
||||
self.assertEqual(u'Shoot the Pad Thai', found['description'])
|
||||
self.assertNotIn(u'notes', found['properties'])
|
||||
|
||||
|
@@ -4,6 +4,7 @@ import responses
|
||||
from bson import ObjectId
|
||||
|
||||
import pillarsdk
|
||||
import pillarsdk.exceptions as sdk_exceptions
|
||||
import pillar.api.utils
|
||||
import pillar.tests
|
||||
import pillar.auth
|
||||
@@ -59,11 +60,20 @@ class TaskWorkflowTest(AbstractAttractTest):
|
||||
pillar.auth.login_user(ctd.EXAMPLE_PROJECT_OWNER_ID)
|
||||
|
||||
self.mock_blenderid_validate_happy()
|
||||
self.assertRaises(sdk_exceptions.PreconditionFailed,
|
||||
self.mngr.edit_task,
|
||||
task._id,
|
||||
task_type=u'je møder',
|
||||
name=u'nööw name',
|
||||
description=u'€ ≠ ¥',
|
||||
status='todo',
|
||||
_etag='jemoeder')
|
||||
self.mngr.edit_task(task._id,
|
||||
task_type=u'je møder',
|
||||
name=u'nööw name',
|
||||
description=u'€ ≠ ¥',
|
||||
status='todo')
|
||||
status='todo',
|
||||
_etag=task._etag)
|
||||
|
||||
# Test directly with MongoDB
|
||||
with self.app.test_request_context():
|
||||
|
Reference in New Issue
Block a user