Using patch to edit shots from web-frontend.
This commit is contained in:
@@ -29,6 +29,7 @@ VALID_PATCH_OPERATIONS = {
|
||||
u'from-web': {
|
||||
u'properties.status',
|
||||
u'properties.notes',
|
||||
u'description',
|
||||
},
|
||||
}
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -114,13 +115,17 @@ class ShotManager(object):
|
||||
"""
|
||||
|
||||
api = pillar_api()
|
||||
shot = pillarsdk.Node.find(shot_id, api=api)
|
||||
shot = pillarsdk.Node({'_id': shot_id})
|
||||
|
||||
shot._etag = fields.pop('_etag')
|
||||
shot.name = fields.pop('name')
|
||||
shot.description = fields.pop('description')
|
||||
shot.properties.status = fields.pop('status')
|
||||
shot.properties.notes = fields.pop('notes', '').strip() or None
|
||||
patch = {
|
||||
'op': 'from-web',
|
||||
'$set': {
|
||||
'description': fields.pop('description', '').strip() or None,
|
||||
'properties.notes': (fields.pop('notes', '') or '').strip() or None,
|
||||
'properties.status': fields.pop('status'),
|
||||
}
|
||||
}
|
||||
# shot._etag = fields.pop('_etag')
|
||||
|
||||
self._log.info('Saving shot %s', shot.to_dict())
|
||||
|
||||
@@ -128,8 +133,7 @@ class ShotManager(object):
|
||||
self._log.warning('edit_shot(%r, ...) called with unknown fields %r; ignoring them.',
|
||||
shot_id, fields)
|
||||
|
||||
shot.update(api=api)
|
||||
return shot
|
||||
shot.patch(patch, api=api)
|
||||
|
||||
|
||||
def node_setattr(node, key, value):
|
||||
|
@@ -92,8 +92,11 @@ def save(project, shot_id):
|
||||
log.debug('Form data: %s', request.form)
|
||||
|
||||
shot_dict = request.form.to_dict()
|
||||
shot = current_attract.shot_manager.edit_shot(shot_id, **shot_dict)
|
||||
current_attract.shot_manager.edit_shot(shot_id, **shot_dict)
|
||||
|
||||
# Return the patched node in all its glory.
|
||||
api = pillar_api()
|
||||
shot = pillarsdk.Node.find(shot_id, api=api)
|
||||
return pillar.api.utils.jsonify(shot.to_dict())
|
||||
|
||||
|
||||
|
@@ -2,12 +2,9 @@
|
||||
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",
|
||||
type="text",
|
||||
placeholder='Name',
|
||||
value="{{ shot.name | hide_none }}")
|
||||
h2 {{ shot.name | hide_none }}
|
||||
button.copy-to-clipboard.btn.item-id(
|
||||
style="margin-left: auto",
|
||||
name="Copy to Clipboard",
|
||||
type="button",
|
||||
data-clipboard-text="{{ shot._id }}",
|
||||
|
@@ -91,6 +91,7 @@ class ShotManagerTest(AbstractShotTest):
|
||||
@responses.activate
|
||||
def test_edit_shot(self):
|
||||
shot = self.create_shot()
|
||||
pre_edit_shot = shot.to_dict()
|
||||
|
||||
with self.app.test_request_context():
|
||||
# Log in as project admin user
|
||||
@@ -98,25 +99,27 @@ class ShotManagerTest(AbstractShotTest):
|
||||
|
||||
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')
|
||||
# No Etag checking, see T49555
|
||||
# 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',
|
||||
notes=None,
|
||||
_etag=shot._etag)
|
||||
|
||||
# Test directly with MongoDB
|
||||
with self.app.test_request_context():
|
||||
nodes_coll = self.app.data.driver.db['nodes']
|
||||
found = nodes_coll.find_one(ObjectId(shot['_id']))
|
||||
self.assertEqual(u'ผัดไทย', found['name'])
|
||||
self.assertEqual(pre_edit_shot['name'], found['name']) # shouldn't be edited.
|
||||
self.assertEqual(u'todo', found['properties']['status'])
|
||||
self.assertEqual(u'Shoot the Pad Thai', found['description'])
|
||||
self.assertNotIn(u'notes', found['properties'])
|
||||
@@ -189,14 +192,66 @@ class PatchShotTest(AbstractShotTest):
|
||||
patch = {
|
||||
'op': 'from-blender',
|
||||
'$set': {
|
||||
'name': u'"shot" is "geschoten" in Dutch',
|
||||
'properties.trim_start_in_frames': 123,
|
||||
'properties.duration_in_edit_in_frames': 4215,
|
||||
'properties.cut_in_timeline_in_frames': 1245,
|
||||
'properties.status': 'todo',
|
||||
'properties.status': u'on_hold',
|
||||
}
|
||||
}
|
||||
self.patch(url, json=patch, auth_token='token')
|
||||
|
||||
dbnode = self.get(url, auth_token='token').json()
|
||||
self.assertEqual(u'"shot" is "geschoten" in Dutch', dbnode['name'])
|
||||
self.assertEqual(123, dbnode['properties']['trim_start_in_frames'])
|
||||
self.assertEqual(u'on_hold', dbnode['properties']['status'])
|
||||
|
||||
@responses.activate
|
||||
def test_patch_from_web_happy(self):
|
||||
shot = self.create_shot()
|
||||
self.create_valid_auth_token(ctd.EXAMPLE_PROJECT_OWNER_ID, 'token')
|
||||
|
||||
url = '/api/nodes/%s' % shot._id
|
||||
patch = {
|
||||
'op': 'from-web',
|
||||
'$set': {
|
||||
'description': u'Таким образом, этот человек заходит в бар, и говорит…',
|
||||
'properties.notes': u'Два бокала вашей лучшей водки, пожалуйста.',
|
||||
'properties.status': u'final',
|
||||
}
|
||||
}
|
||||
self.patch(url, json=patch, auth_token='token')
|
||||
|
||||
dbnode = self.get(url, auth_token='token').json()
|
||||
self.assertEqual(u'Таким образом, этот человек заходит в бар, и говорит…',
|
||||
dbnode['description'])
|
||||
self.assertEqual(u'Два бокала вашей лучшей водки, пожалуйста.',
|
||||
dbnode['properties']['notes'])
|
||||
self.assertEqual(u'final', dbnode['properties']['status'])
|
||||
self.assertEqual(u'New shot', dbnode['name'])
|
||||
|
||||
@responses.activate
|
||||
def test_patch_from_web_happy_nones(self):
|
||||
shot = self.create_shot()
|
||||
self.create_valid_auth_token(ctd.EXAMPLE_PROJECT_OWNER_ID, 'token')
|
||||
|
||||
url = '/api/nodes/%s' % shot._id
|
||||
patch = {
|
||||
'op': 'from-web',
|
||||
'$set': {
|
||||
'description': None,
|
||||
'properties.notes': None,
|
||||
'properties.status': u'final',
|
||||
}
|
||||
}
|
||||
self.patch(url, json=patch, auth_token='token')
|
||||
|
||||
dbnode = self.get(url, auth_token='token').json()
|
||||
self.assertNotIn('description', dbnode)
|
||||
self.assertNotIn('notes', dbnode['properties'])
|
||||
self.assertEqual(u'final', dbnode['properties']['status'])
|
||||
self.assertEqual(u'New shot', dbnode['name'])
|
||||
|
||||
@responses.activate
|
||||
def test_patch_bad_op(self):
|
||||
shot = self.create_shot()
|
||||
|
Reference in New Issue
Block a user