snapshots: add label, comment, timestamp and user in sidebar (#50009)

This commit is contained in:
Lauréline Guérin 2021-01-12 14:55:54 +01:00
parent 115b0c8ef6
commit dd8f3d59f2
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
9 changed files with 42 additions and 8 deletions

View File

@ -12,6 +12,7 @@ from wcs.carddef import CardDef
from wcs.data_sources import NamedDataSource
from wcs.formdef import FormDef
from wcs.qommon.form import UploadedFile
from wcs.qommon.misc import localstrftime
from wcs.workflows import Workflow
from wcs.workflows import ExportToModel
from wcs.wscalls import NamedWsCall
@ -236,7 +237,8 @@ def test_block_snapshot_browse(pub, blocks_feature):
resp = app.get('/backoffice/forms/blocks/%s/history/' % blockdef.id)
snapshot = pub.snapshot_class.select_object_history(blockdef)[0]
resp = resp.click(href='%s/view/' % snapshot.id)
assert 'This block of fields is readonly.' in resp
assert 'This block of fields is readonly.' in resp.text
assert '<p>%s</p>' % localstrftime(snapshot.timestamp) in resp.text
def test_card_snapshot_browse(pub):
@ -274,7 +276,8 @@ def test_card_snapshot_browse(pub):
resp = app.get('/backoffice/cards/%s/history/' % carddef.id)
snapshot = pub.snapshot_class.select_object_history(carddef)[0]
resp = resp.click(href='%s/view/' % snapshot.id)
assert 'This card model is readonly' in resp
assert 'This card model is readonly' in resp.text
assert '<p>%s</p>' % localstrftime(snapshot.timestamp) in resp.text
resp = resp.click('Geolocation')
assert [x[0].name for x in resp.form.fields.values() if x[0].tag == 'button'] == ['cancel']
assert pub.custom_view_class.count() == 0 # custom views are not restore on preview
@ -299,7 +302,8 @@ def test_datasource_snapshot_browse(pub):
resp = app.get('/backoffice/forms/data-sources/%s/history/' % datasource.id)
snapshot = pub.snapshot_class.select_object_history(datasource)[0]
resp = resp.click(href='%s/view/' % snapshot.id)
assert 'This data source is readonly' in resp
assert 'This data source is readonly' in resp.text
assert '<p>%s</p>' % localstrftime(snapshot.timestamp) in resp.text
with pytest.raises(IndexError):
resp = resp.click('Edit')
@ -333,7 +337,8 @@ def test_form_snapshot_browse(pub, formdef_with_history):
resp = app.get('/backoffice/forms/%s/history/' % formdef_with_history.id)
snapshot = pub.snapshot_class.select_object_history(formdef_with_history)[0]
resp = resp.click(href='%s/view/' % snapshot.id)
assert 'This form is readonly' in resp
assert 'This form is readonly' in resp.text
assert '<p>%s</p>' % localstrftime(snapshot.timestamp) in resp.text
resp = resp.click('Description')
assert resp.form['description'].value == 'this is a description (5)'
assert [x[0].name for x in resp.form.fields.values() if x[0].tag == 'button'] == ['cancel']
@ -357,7 +362,8 @@ def test_workflow_snapshot_browse(pub):
resp = app.get('/backoffice/workflows/%s/history/' % workflow.id)
snapshot = pub.snapshot_class.select_object_history(workflow)[0]
resp = resp.click(href='%s/view/' % snapshot.id)
assert 'This workflow is readonly' in resp
assert 'This workflow is readonly' in resp.text
assert '<p>%s</p>' % localstrftime(snapshot.timestamp) in resp.text
def test_workflow_with_model_snapshot_browse(pub):
@ -397,7 +403,7 @@ def test_workflow_with_model_snapshot_browse(pub):
resp = app.get('/backoffice/workflows/%s/history/' % workflow.id)
snapshot = pub.snapshot_class.select_object_history(workflow)[0]
resp = resp.click(href='%s/view/' % snapshot.id)
assert 'This workflow is readonly' in resp
assert 'This workflow is readonly' in resp.text
assert len(os.listdir(os.path.join(pub.app_dir, 'models'))) == 3 + i
@ -418,7 +424,8 @@ def test_wscall_snapshot_browse(pub):
resp = app.get('/backoffice/settings/wscalls/%s/history/' % wscall.id)
snapshot = pub.snapshot_class.select_object_history(wscall)[0]
resp = resp.click(href='%s/view/' % snapshot.id)
assert 'This webservice call is readonly' in resp
assert 'This webservice call is readonly' in resp.text
assert '<p>%s</p>' % localstrftime(snapshot.timestamp) in resp.text
with pytest.raises(IndexError):
resp = resp.click('Edit')

View File

@ -20,6 +20,7 @@ from quixote import get_publisher, redirect
from quixote.directory import Directory
from quixote.html import TemplateIO, htmltext
from wcs.admin import utils
from wcs.qommon import _, force_str
from wcs.qommon import errors, template
from wcs.qommon.form import *
@ -207,6 +208,7 @@ class NamedDataSourcePage(Directory):
r = TemplateIO(html=True)
if self.datasource.is_readonly():
r += htmltext('<div class="infonotice"><p>%s</p></div>') % _('This data source is readonly.')
r += utils.snapshot_info_block(snapshot=self.datasource.snapshot_object)
r += htmltext('<ul id="sidebar-actions">')
if not self.datasource.is_readonly():
r += htmltext('<li><a href="delete" rel="popup">%s</a></li>') % _('Delete')

View File

@ -22,6 +22,7 @@ from quixote import redirect
from quixote.directory import Directory
from quixote.html import TemplateIO, htmltext, htmlescape
from wcs.admin import utils
from wcs.qommon import _
from wcs.qommon.form import *
from wcs.qommon import errors, misc
@ -337,7 +338,8 @@ class FieldsDirectory(Directory):
r += htmltext('</ul>')
if self.objectdef.is_readonly():
get_response().filter['sidebar'] = '<div class="infonotice"><p>%s</p></div>' % _(self.readonly_message)
get_response().filter['sidebar'] = htmltext('<div class="infonotice"><p>%s</p></div>') % _(self.readonly_message)
get_response().filter['sidebar'] += utils.snapshot_info_block(snapshot=self.objectdef.snapshot_object)
else:
get_response().filter['sidebar'] = str(self.get_new_field_form(self.page_id))
r += self.index_bottom()

View File

@ -676,6 +676,7 @@ class FormDefPage(Directory):
r = TemplateIO(html=True)
if self.formdef.is_readonly():
r += htmltext('<div class="infonotice"><p>%s</p></div>') % _('This form is readonly.')
r += utils.snapshot_info_block(snapshot=self.formdef.snapshot_object)
return r.getvalue()
r += htmltext('<ul id="sidebar-actions">')
r += htmltext('<li><a href="delete" rel="popup">%s</a></li>') % _('Delete')

View File

@ -46,3 +46,20 @@ def last_modification_block(obj):
r += htmltext('</p>')
return r.getvalue()
def snapshot_info_block(snapshot):
r = TemplateIO(html=True)
r += htmltext('<p>')
parts = []
if snapshot.label:
parts.append(htmltext('<strong>%s</strong>') % snapshot.label)
elif snapshot.comment:
parts.append(snapshot.comment)
if snapshot.user_id:
parts.append('%s (%s)' % (misc.localstrftime(snapshot.timestamp), snapshot.user))
else:
parts.append(misc.localstrftime(snapshot.timestamp))
r += htmltext('<br />').join(parts)
r += htmltext('</p>')
return r.getvalue()

View File

@ -1586,6 +1586,7 @@ class WorkflowPage(Directory):
r += htmltext('</p>')
elif self.workflow.is_readonly():
r += htmltext('<div class="infonotice"><p>%s</p></div>') % _('This workflow is readonly.')
r += utils.snapshot_info_block(snapshot=self.workflow.snapshot_object)
return r.getvalue()
r += htmltext('<ul id="sidebar-actions">')

View File

@ -20,6 +20,7 @@ from quixote import get_publisher, get_response, redirect
from quixote.directory import Directory
from quixote.html import TemplateIO, htmltext
from wcs.admin import utils
from wcs.qommon import _, errors, template
from wcs.qommon import misc
from wcs.qommon.form import *
@ -112,6 +113,7 @@ class NamedWsCallPage(Directory):
r = TemplateIO(html=True)
if self.wscall.is_readonly():
r += htmltext('<div class="infonotice"><p>%s</p></div>') % _('This webservice call is readonly.')
r += utils.snapshot_info_block(snapshot=self.wscall.snapshot_object)
r += htmltext('<ul id="sidebar-actions">')
if not self.wscall.is_readonly():
r += htmltext('<li><a href="export">%s</a></li>') % _('Export')

View File

@ -208,6 +208,7 @@ class CardDefPage(FormDefPage):
r = TemplateIO(html=True)
if self.formdef.is_readonly():
r += htmltext('<div class="infonotice"><p>%s</p></div>') % _('This card model is readonly.')
r += utils.snapshot_info_block(snapshot=self.formdef.snapshot_object)
return r.getvalue()
r += htmltext('<ul id="sidebar-actions">')
r += htmltext('<li><a href="delete" rel="popup">%s</a></li>') % _('Delete')

View File

@ -88,6 +88,7 @@ class Snapshot:
include_id=True,
snapshot=True)
self._instance.readonly = True
self._instance.snapshot_object = self
return self._instance
@property