backoffice: display current user forms in the sidebar (#8879)
This commit is contained in:
parent
b6f08cfaf6
commit
07efca8dcc
|
@ -15,6 +15,7 @@ from wcs.roles import Role
|
|||
from wcs.workflows import (Workflow, CommentableWorkflowStatusItem,
|
||||
ChoiceWorkflowStatusItem)
|
||||
from wcs.wf.wscall import WebserviceCallStatusItem
|
||||
from wcs.categories import Category
|
||||
from wcs.formdef import FormDef
|
||||
from wcs import fields
|
||||
|
||||
|
@ -65,6 +66,7 @@ def create_superuser(pub):
|
|||
create_user(pub, is_admin=True)
|
||||
|
||||
def create_environment(pub, set_receiver=True):
|
||||
Category.wipe()
|
||||
FormDef.wipe()
|
||||
formdef = FormDef()
|
||||
formdef.name = 'form title'
|
||||
|
@ -877,3 +879,59 @@ def test_tracking_code_access(pub):
|
|||
assert resp.location == 'http://example.net/backoffice/management/listing'
|
||||
resp = resp.follow()
|
||||
assert 'No such code' in resp.body
|
||||
|
||||
def test_backoffice_sidebar_user_context(pub):
|
||||
if not pub.is_using_postgresql():
|
||||
pytest.skip('this requires SQL')
|
||||
return
|
||||
|
||||
user = create_user(pub)
|
||||
create_environment(pub)
|
||||
form_class = FormDef.get_by_urlname('form-title').data_class()
|
||||
number31 = [x for x in form_class.select() if x.data['1'] == 'FOO BAR 30'][0]
|
||||
app = login(get_app(pub))
|
||||
resp = app.get('/backoffice/management/form-title/')
|
||||
assert re.findall('<tbody.*\/tbody>', resp.body, re.DOTALL)[0].count('<tr') == 17
|
||||
|
||||
# click on a formdata
|
||||
resp = resp.click(href='%s/' % number31.id)
|
||||
assert (' with the number %s.' % number31.id) in resp.body
|
||||
|
||||
# check there's nothing in the sidebar
|
||||
assert not 'User Pending Forms' in resp.body
|
||||
|
||||
number31.user_id = user.id
|
||||
number31.store()
|
||||
resp = app.get('/backoffice/management/form-title/%s/' % number31.id)
|
||||
assert 'User Pending Forms' in resp.body
|
||||
assert '<span class="formname">%s</span>' % number31.formdef.name in resp.body
|
||||
assert not number31.get_url(backoffice=True) in resp.body
|
||||
|
||||
# another item with status = new
|
||||
number34 = [x for x in form_class.select() if x.data['1'] == 'FOO BAR 33'][0]
|
||||
number34.user_id = user.id
|
||||
number34.store()
|
||||
|
||||
resp = app.get('/backoffice/management/form-title/%s/' % number31.id)
|
||||
assert 'User Pending Forms' in resp.body
|
||||
assert not number31.get_url(backoffice=True) in resp.body
|
||||
assert number34.get_url(backoffice=True) in resp.body
|
||||
|
||||
cat1 = Category(name='cat1')
|
||||
cat1.store()
|
||||
|
||||
formdef = FormDef.get_by_urlname('other-form')
|
||||
formdef.category_id = cat1.id
|
||||
formdef.store()
|
||||
other_formdata = formdef.data_class().select()[0]
|
||||
other_formdata.user_id = user.id
|
||||
other_formdata.store()
|
||||
|
||||
resp = app.get('/backoffice/management/form-title/%s/' % number31.id)
|
||||
assert 'User Pending Forms' in resp.body
|
||||
assert number34.get_url(backoffice=True) in resp.body
|
||||
assert other_formdata.get_url(backoffice=True) in resp.body
|
||||
# categories are displayed, and current formdata category is on top
|
||||
assert '>cat1<' in resp.body
|
||||
assert '>Misc<' in resp.body
|
||||
assert resp.body.index('>Misc<') < resp.body.index('>cat1<')
|
||||
|
|
|
@ -1251,35 +1251,97 @@ class FormBackOfficeStatusPage(FormStatusPage):
|
|||
|
||||
def get_extra_context_bar(self):
|
||||
formdata = self.filled
|
||||
if not formdata.submission_context:
|
||||
return ''
|
||||
|
||||
r = TemplateIO(html=True)
|
||||
extra_context = formdata.submission_context or {}
|
||||
r += htmltext('<div class="extra-context">')
|
||||
if extra_context.get('channel'):
|
||||
channel_labels = {
|
||||
'mail': _('Mail'),
|
||||
}
|
||||
r += htmltext('<h3>%s</h3>') % '%s: %s' % (
|
||||
_('Channel'), channel_labels.get(extra_context.get('channel'), '?'))
|
||||
if extra_context.get('thumbnail_url'):
|
||||
r += htmltext('<p class="thumbnail"><img src="%s" alt=""/></p>'
|
||||
) % extra_context.get('thumbnail_url')
|
||||
if extra_context.get('mail_url'):
|
||||
r += htmltext('<p><a href="%s">%s</a></p>') % (
|
||||
extra_context.get('mail_url'), _('Open'))
|
||||
if extra_context.get('user_id'):
|
||||
r += htmltext('<h3>%s</h3>') % _('Associated User')
|
||||
r += htmltext('<p>%s</p>') % get_publisher().user_class.get(
|
||||
extra_context.get('user_id')).display_name
|
||||
if extra_context.get('comments'):
|
||||
r += htmltext('<h3>%s</h3>') % _('Comments')
|
||||
r += htmltext('<p>%s</p>') % extra_context.get('comments')
|
||||
if extra_context.get('summary_url'):
|
||||
r += htmltext('<div data-content-url="%s"></div>' %
|
||||
(extra_context.get('summary_url')))
|
||||
r += htmltext('</div>')
|
||||
if formdata.submission_context:
|
||||
extra_context = formdata.submission_context or {}
|
||||
r += htmltext('<div class="extra-context">')
|
||||
if extra_context.get('channel'):
|
||||
channel_labels = {
|
||||
'mail': _('Mail'),
|
||||
}
|
||||
r += htmltext('<h3>%s</h3>') % '%s: %s' % (
|
||||
_('Channel'), channel_labels.get(extra_context.get('channel'), '?'))
|
||||
if extra_context.get('thumbnail_url'):
|
||||
r += htmltext('<p class="thumbnail"><img src="%s" alt=""/></p>'
|
||||
) % extra_context.get('thumbnail_url')
|
||||
if extra_context.get('mail_url'):
|
||||
r += htmltext('<p><a href="%s">%s</a></p>') % (
|
||||
extra_context.get('mail_url'), _('Open'))
|
||||
if extra_context.get('user_id'):
|
||||
r += htmltext('<h3>%s</h3>') % _('Associated User')
|
||||
r += htmltext('<p>%s</p>') % get_publisher().user_class.get(
|
||||
extra_context.get('user_id')).display_name
|
||||
if extra_context.get('comments'):
|
||||
r += htmltext('<h3>%s</h3>') % _('Comments')
|
||||
r += htmltext('<p>%s</p>') % extra_context.get('comments')
|
||||
if extra_context.get('summary_url'):
|
||||
r += htmltext('<div data-content-url="%s"></div>' %
|
||||
(extra_context.get('summary_url')))
|
||||
r += htmltext('</div>')
|
||||
|
||||
if formdata.user_id and get_publisher().is_using_postgresql():
|
||||
# display list of open formdata for the same user
|
||||
user_roles = [logged_users_role().id] + (get_request().user.roles or [])
|
||||
criterias = [Equal('is_at_endpoint', False),
|
||||
Equal('user_id', str(formdata.user_id)),
|
||||
Intersects('concerned_roles_array', user_roles),
|
||||
]
|
||||
from wcs import sql
|
||||
formdatas = sql.AnyFormData.select(criterias, order_by='-receipt_time', limit=50)
|
||||
|
||||
if formdatas:
|
||||
r += htmltext('<div class="user-pending-forms">')
|
||||
r += htmltext('<h3>%s</h3>') % _('User Pending Forms')
|
||||
categories = {}
|
||||
formdata_by_category = {}
|
||||
for formdata in formdatas:
|
||||
if not formdata.formdef.category_id in categories:
|
||||
categories[formdata.formdef.category_id] = formdata.formdef.category
|
||||
formdata_by_category[formdata.formdef.category_id] = []
|
||||
formdata_by_category[formdata.formdef.category_id].append(formdata)
|
||||
cats = categories.values()
|
||||
Category.sort_by_position(cats)
|
||||
if self.formdef.category_id in categories:
|
||||
# move current category to the top
|
||||
cats.remove(categories[self.formdef.category_id])
|
||||
cats.insert(0, categories[self.formdef.category_id])
|
||||
for cat in cats:
|
||||
if len(cats) > 1:
|
||||
if cat is None:
|
||||
r += htmltext('<h4>%s</h4>') % _('Misc')
|
||||
cat_formdatas = formdata_by_category[None]
|
||||
else:
|
||||
r += htmltext('<h4>%s</h4>') % cat.name
|
||||
cat_formdatas = formdata_by_category[cat.id]
|
||||
else:
|
||||
cat_formdatas = formdatas
|
||||
r += htmltext('<ul>')
|
||||
for formdata in cat_formdatas:
|
||||
status = formdata.get_status()
|
||||
if status:
|
||||
status_label = status.name
|
||||
else:
|
||||
status_label = _('Unknown')
|
||||
submit_date = misc.strftime.strftime(
|
||||
misc.date_format(), formdata.receipt_time)
|
||||
if str(formdata.formdef_id) == str(self.formdef.id) and (
|
||||
str(formdata.id) == str(self.filled.id)):
|
||||
r += htmltext('<li class="self"><span class="formname">%s</span>, '
|
||||
'<span class="datetime">%s</span> '
|
||||
'<span class="status">(%s)</span>' % (
|
||||
formdata.formdef.name,
|
||||
submit_date, status_label))
|
||||
else:
|
||||
r += htmltext('<li><a href="%s">%s</a>, '
|
||||
'<span class="datetime">%s</span> '
|
||||
'<span class="status">(%s)</span>' % (
|
||||
formdata.get_url(backoffice=True),
|
||||
formdata.formdef.name,
|
||||
submit_date, status_label))
|
||||
r += htmltext('</ul>')
|
||||
r += htmltext('</div>')
|
||||
|
||||
return r.getvalue()
|
||||
|
||||
|
||||
|
|
|
@ -65,6 +65,12 @@ class Category(XmlStorableObject):
|
|||
|
||||
def sort_by_position(cls, categories):
|
||||
def cmp_position(x, y):
|
||||
if x is None and y is None:
|
||||
return 0
|
||||
if y is None:
|
||||
return -1
|
||||
if x is None:
|
||||
return 1
|
||||
if x.position == y.position:
|
||||
return 0
|
||||
if x.position is None:
|
||||
|
|
|
@ -1109,5 +1109,22 @@ div#tracking-code button {
|
|||
div.bo-block.important {
|
||||
background: #fd6;
|
||||
border: 1px solid #ffae15;
|
||||
|
||||
}
|
||||
|
||||
div.user-pending-forms ul {
|
||||
margin-left: 0;
|
||||
padding-left: 1.5em;
|
||||
}
|
||||
|
||||
div.user-pending-forms li {
|
||||
line-height: 130%;
|
||||
}
|
||||
|
||||
div.user-pending-forms ul li.self span.formname {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.user-pending-forms span.datetime,
|
||||
div.user-pending-forms span.status {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue