admin: add snapshots on mail templates (#51685)

This commit is contained in:
Nicolas Roche 2021-04-14 18:07:13 +02:00
parent 93af4b0f10
commit b9d7aa9ee4
6 changed files with 89 additions and 8 deletions

View File

@ -11,6 +11,7 @@ from wcs.carddef import CardDef
from wcs.data_sources import NamedDataSource
from wcs.fields import ItemField
from wcs.formdef import FormDef
from wcs.mail_templates import MailTemplate
from wcs.qommon.form import UploadedFile
from wcs.qommon.misc import localstrftime
from wcs.wf.export_to_model import ExportToModel
@ -722,3 +723,60 @@ def test_pickle_erroneous_snapshot_object(pub):
formdef.store()
assert not hasattr(FormDef.get(formdef.id), 'snapshot_object')
def test_mail_template_snapshot_restore(pub):
create_superuser(pub)
create_role(pub)
app = login(get_app(pub))
mail_template = MailTemplate(name='test')
mail_template.store()
for i in range(2):
mail_template.name = 'test %s' % i
mail_template.store()
assert pub.snapshot_class.count() == 3
# restore as new
resp = app.get('/backoffice/workflows/mail-templates/%s/history/' % mail_template.id)
snapshot = pub.snapshot_class.select_object_history(mail_template)[2]
resp = resp.click(href='%s/restore' % snapshot.id)
assert resp.form['action'].value == 'as-new'
resp = resp.form.submit('submit')
assert MailTemplate.count() == 2
mail_template2 = MailTemplate.get(resp.location.split('/')[-2])
assert mail_template2.name == 'test'
assert mail_template2.id != mail_template.id
# restore over
resp = app.get('/backoffice/workflows/mail-templates/%s/history/' % mail_template.id)
snapshot = pub.snapshot_class.select_object_history(mail_template)[2]
resp = resp.click(href='%s/restore' % snapshot.id)
resp.form['action'].value = 'overwrite'
resp = resp.form.submit('submit')
assert MailTemplate.count() == 2
mail_template2 = MailTemplate.get(resp.location.split('/')[-2])
assert mail_template2.id == mail_template.id
def test_mail_template_snapshot_browse(pub):
create_superuser(pub)
create_role(pub)
MailTemplate.wipe()
mail_template = MailTemplate(name='test')
mail_template.store()
assert pub.snapshot_class.count() == 1
# check calling .store() without changes doesn't create snapshots
mail_template.store()
assert pub.snapshot_class.count() == 1
app = login(get_app(pub))
resp = app.get('/backoffice/workflows/mail-templates/%s/history/' % mail_template.id)
snapshot = pub.snapshot_class.select_object_history(mail_template)[0]
resp = resp.click(href='%s/view/' % snapshot.id)
assert 'This mail template 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

@ -18,6 +18,8 @@ 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.backoffice.snapshots import SnapshotsDirectory
from wcs.mail_templates import MailTemplate
from wcs.qommon import _, errors, misc, template
from wcs.qommon.backoffice.menu import html_top
@ -124,21 +126,30 @@ class MailTemplatePage(Directory):
'edit',
'delete',
'export',
('history', 'snapshots_dir'),
]
do_not_call_in_templates = True
def __init__(self, mail_template_id):
def __init__(self, component, instance=None):
try:
self.mail_template = MailTemplate.get(mail_template_id)
self.mail_template = instance or MailTemplate.get(component)
except KeyError:
raise errors.TraversalError()
get_response().breadcrumb.append((mail_template_id + '/', self.mail_template.name))
get_response().breadcrumb.append((component + '/', self.mail_template.name))
self.snapshots_dir = SnapshotsDirectory(self.mail_template)
def get_sidebar(self):
r = TemplateIO(html=True)
if self.mail_template.is_readonly():
r += htmltext('<div class="infonotice"><p>%s</p></div>') % _('This mail template is readonly.')
r += utils.snapshot_info_block(snapshot=self.mail_template.snapshot_object)
r += htmltext('<ul id="sidebar-actions">')
r += htmltext('<li><a href="export">%s</a></li>') % _('Export')
r += htmltext('<li><a href="delete" rel="popup">%s</a></li>') % _('Delete')
if not self.mail_template.is_readonly():
r += htmltext('<li><a href="export">%s</a></li>') % _('Export')
r += htmltext('<li><a href="delete" rel="popup">%s</a></li>') % _('Delete')
if get_publisher().snapshot_class:
r += htmltext('<li><a rel="popup" href="history/save">%s</a></li>') % _('Save snapshot')
r += htmltext('<li><a href="history/">%s</a></li>') % _('History')
r += htmltext('</ul>')
return r.getvalue()
@ -202,7 +213,8 @@ class MailTemplatePage(Directory):
advanced=True,
)
form.add_submit('submit', _('Submit'))
if not self.mail_template.is_readonly():
form.add_submit('submit', _('Submit'))
form.add_submit('cancel', _('Cancel'))
return form

View File

@ -22,6 +22,7 @@ from wcs.blocks import BlockDef
from wcs.carddef import CardDef
from wcs.data_sources import NamedDataSource
from wcs.formdef import FormDef, FormdefImportError
from wcs.mail_templates import MailTemplate
from wcs.qommon import _, errors, misc, template
from wcs.qommon.backoffice.menu import html_top
from wcs.qommon.form import Form, RadiobuttonsWidget, StringWidget
@ -195,3 +196,7 @@ class SnapshotDirectory(Directory):
from wcs.admin.wscalls import NamedWsCallPage
return NamedWsCallPage(component='view', instance=instance)
if klass is MailTemplate:
from wcs.admin.mail_templates import MailTemplatePage
return MailTemplatePage(component='view', instance=instance)

View File

@ -49,11 +49,14 @@ class MailTemplate(XmlStorableObject):
base_url = get_publisher().get_backoffice_url()
return '%s/workflows/mail-templates/%s/' % (base_url, self.id)
def store(self):
def store(self, comment=None):
assert not self.is_readonly()
if self.slug is None:
# set slug if it's not yet there
self.slug = self.get_new_slug()
super().store()
if get_publisher().snapshot_class:
get_publisher().snapshot_class.snap(instance=self, comment=comment)
def get_new_slug(self):
new_slug = misc.simplify(self.name, space='-')

View File

@ -71,10 +71,11 @@ class Snapshot:
from wcs.carddef import CardDef
from wcs.data_sources import NamedDataSource
from wcs.formdef import FormDef
from wcs.mail_templates import MailTemplate
from wcs.workflows import Workflow
from wcs.wscalls import NamedWsCall
for klass in (BlockDef, CardDef, NamedDataSource, FormDef, Workflow, NamedWsCall):
for klass in (BlockDef, CardDef, NamedDataSource, FormDef, Workflow, NamedWsCall, MailTemplate):
if klass.xml_root_node == self.object_type:
return klass
raise KeyError('no class for object type: %s' % self.object_type)

View File

@ -4,7 +4,9 @@
{% block appbar-title %}{% trans "Mail Template" %} - {{ mail_template.name }}{% endblock %}
{% block appbar-actions %}
{% if not mail_template.is_readonly %}
<a href="edit">{% trans "Edit" %}</a>
{% endif %}
{% endblock %}
{% block content %}