From dece3c21bae0e8bd25ce93e9d42b32d7a1e85556 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= Date: Thu, 5 Nov 2015 15:22:45 +0100 Subject: [PATCH] backoffice: display current user forms in the sidebar (#8879) --- tests/test_backoffice_pages.py | 58 ++++++++++++++++++ wcs/backoffice/management.py | 116 +++++++++++++++++++++++++++--------- wcs/categories.py | 6 ++ wcs/qommon/static/css/dc2/admin.css | 17 ++++++ 4 files changed, 170 insertions(+), 27 deletions(-) diff --git a/tests/test_backoffice_pages.py b/tests/test_backoffice_pages.py index c7393e7..b6700b7 100644 --- a/tests/test_backoffice_pages.py +++ b/tests/test_backoffice_pages.py @@ -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('', resp.body, re.DOTALL)[0].count('%s' % 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<') diff --git a/wcs/backoffice/management.py b/wcs/backoffice/management.py index a36b132..c513707 100644 --- a/wcs/backoffice/management.py +++ b/wcs/backoffice/management.py @@ -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('
') - if extra_context.get('channel'): - channel_labels = { - 'mail': _('Mail'), - } - r += htmltext('

%s

') % '%s: %s' % ( - _('Channel'), channel_labels.get(extra_context.get('channel'), '?')) - if extra_context.get('thumbnail_url'): - r += htmltext('

' - ) % extra_context.get('thumbnail_url') - if extra_context.get('mail_url'): - r += htmltext('

%s

') % ( - extra_context.get('mail_url'), _('Open')) - if extra_context.get('user_id'): - r += htmltext('

%s

') % _('Associated User') - r += htmltext('

%s

') % get_publisher().user_class.get( - extra_context.get('user_id')).display_name - if extra_context.get('comments'): - r += htmltext('

%s

') % _('Comments') - r += htmltext('

%s

') % extra_context.get('comments') - if extra_context.get('summary_url'): - r += htmltext('
' % - (extra_context.get('summary_url'))) - r += htmltext('
') + if formdata.submission_context: + extra_context = formdata.submission_context or {} + r += htmltext('
') + if extra_context.get('channel'): + channel_labels = { + 'mail': _('Mail'), + } + r += htmltext('

%s

') % '%s: %s' % ( + _('Channel'), channel_labels.get(extra_context.get('channel'), '?')) + if extra_context.get('thumbnail_url'): + r += htmltext('

' + ) % extra_context.get('thumbnail_url') + if extra_context.get('mail_url'): + r += htmltext('

%s

') % ( + extra_context.get('mail_url'), _('Open')) + if extra_context.get('user_id'): + r += htmltext('

%s

') % _('Associated User') + r += htmltext('

%s

') % get_publisher().user_class.get( + extra_context.get('user_id')).display_name + if extra_context.get('comments'): + r += htmltext('

%s

') % _('Comments') + r += htmltext('

%s

') % extra_context.get('comments') + if extra_context.get('summary_url'): + r += htmltext('
' % + (extra_context.get('summary_url'))) + r += htmltext('
') + + 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('
') + r += htmltext('

%s

') % _('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('

%s

') % _('Misc') + cat_formdatas = formdata_by_category[None] + else: + r += htmltext('

%s

') % cat.name + cat_formdatas = formdata_by_category[cat.id] + else: + cat_formdatas = formdatas + r += htmltext('
    ') + 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('
  • %s, ' + '%s ' + '(%s)' % ( + formdata.formdef.name, + submit_date, status_label)) + else: + r += htmltext('
  • %s, ' + '%s ' + '(%s)' % ( + formdata.get_url(backoffice=True), + formdata.formdef.name, + submit_date, status_label)) + r += htmltext('
') + r += htmltext('
') + return r.getvalue() diff --git a/wcs/categories.py b/wcs/categories.py index a1f7373..946d6fa 100644 --- a/wcs/categories.py +++ b/wcs/categories.py @@ -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: diff --git a/wcs/qommon/static/css/dc2/admin.css b/wcs/qommon/static/css/dc2/admin.css index 4a9260d..5132251 100644 --- a/wcs/qommon/static/css/dc2/admin.css +++ b/wcs/qommon/static/css/dc2/admin.css @@ -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%; } -- 2.6.2