0001-backoffice-display-current-user-forms-in-the-sidebar.patch
tests/test_backoffice_pages.py | ||
---|---|---|
15 | 15 |
from wcs.workflows import (Workflow, CommentableWorkflowStatusItem, |
16 | 16 |
ChoiceWorkflowStatusItem) |
17 | 17 |
from wcs.wf.wscall import WebserviceCallStatusItem |
18 |
from wcs.categories import Category |
|
18 | 19 |
from wcs.formdef import FormDef |
19 | 20 |
from wcs import fields |
20 | 21 | |
... | ... | |
65 | 66 |
create_user(pub, is_admin=True) |
66 | 67 | |
67 | 68 |
def create_environment(pub, set_receiver=True): |
69 |
Category.wipe() |
|
68 | 70 |
FormDef.wipe() |
69 | 71 |
formdef = FormDef() |
70 | 72 |
formdef.name = 'form title' |
... | ... | |
877 | 879 |
assert resp.location == 'http://example.net/backoffice/management/listing' |
878 | 880 |
resp = resp.follow() |
879 | 881 |
assert 'No such code' in resp.body |
882 | ||
883 |
def test_backoffice_sidebar_user_context(pub): |
|
884 |
if not pub.is_using_postgresql(): |
|
885 |
pytest.skip('this requires SQL') |
|
886 |
return |
|
887 | ||
888 |
user = create_user(pub) |
|
889 |
create_environment(pub) |
|
890 |
form_class = FormDef.get_by_urlname('form-title').data_class() |
|
891 |
number31 = [x for x in form_class.select() if x.data['1'] == 'FOO BAR 30'][0] |
|
892 |
app = login(get_app(pub)) |
|
893 |
resp = app.get('/backoffice/management/form-title/') |
|
894 |
assert re.findall('<tbody.*\/tbody>', resp.body, re.DOTALL)[0].count('<tr') == 17 |
|
895 | ||
896 |
# click on a formdata |
|
897 |
resp = resp.click(href='%s/' % number31.id) |
|
898 |
assert (' with the number %s.' % number31.id) in resp.body |
|
899 | ||
900 |
# check there's nothing in the sidebar |
|
901 |
assert not 'User Pending Forms' in resp.body |
|
902 | ||
903 |
number31.user_id = user.id |
|
904 |
number31.store() |
|
905 |
resp = app.get('/backoffice/management/form-title/%s/' % number31.id) |
|
906 |
assert 'User Pending Forms' in resp.body |
|
907 |
assert '<span class="formname">%s</span>' % number31.formdef.name in resp.body |
|
908 |
assert not number31.get_url(backoffice=True) in resp.body |
|
909 | ||
910 |
# another item with status = new |
|
911 |
number34 = [x for x in form_class.select() if x.data['1'] == 'FOO BAR 33'][0] |
|
912 |
number34.user_id = user.id |
|
913 |
number34.store() |
|
914 | ||
915 |
resp = app.get('/backoffice/management/form-title/%s/' % number31.id) |
|
916 |
assert 'User Pending Forms' in resp.body |
|
917 |
assert not number31.get_url(backoffice=True) in resp.body |
|
918 |
assert number34.get_url(backoffice=True) in resp.body |
|
919 | ||
920 |
cat1 = Category(name='cat1') |
|
921 |
cat1.store() |
|
922 | ||
923 |
formdef = FormDef.get_by_urlname('other-form') |
|
924 |
formdef.category_id = cat1.id |
|
925 |
formdef.store() |
|
926 |
other_formdata = formdef.data_class().select()[0] |
|
927 |
other_formdata.user_id = user.id |
|
928 |
other_formdata.store() |
|
929 | ||
930 |
resp = app.get('/backoffice/management/form-title/%s/' % number31.id) |
|
931 |
assert 'User Pending Forms' in resp.body |
|
932 |
assert number34.get_url(backoffice=True) in resp.body |
|
933 |
assert other_formdata.get_url(backoffice=True) in resp.body |
|
934 |
# categories are displayed, and current formdata category is on top |
|
935 |
assert '>cat1<' in resp.body |
|
936 |
assert '>Misc<' in resp.body |
|
937 |
assert resp.body.index('>Misc<') < resp.body.index('>cat1<') |
wcs/backoffice/management.py | ||
---|---|---|
1251 | 1251 | |
1252 | 1252 |
def get_extra_context_bar(self): |
1253 | 1253 |
formdata = self.filled |
1254 |
if not formdata.submission_context: |
|
1255 |
return '' |
|
1256 | 1254 | |
1257 | 1255 |
r = TemplateIO(html=True) |
1258 |
extra_context = formdata.submission_context or {} |
|
1259 |
r += htmltext('<div class="extra-context">') |
|
1260 |
if extra_context.get('channel'): |
|
1261 |
channel_labels = { |
|
1262 |
'mail': _('Mail'), |
|
1263 |
} |
|
1264 |
r += htmltext('<h3>%s</h3>') % '%s: %s' % ( |
|
1265 |
_('Channel'), channel_labels.get(extra_context.get('channel'), '?')) |
|
1266 |
if extra_context.get('thumbnail_url'): |
|
1267 |
r += htmltext('<p class="thumbnail"><img src="%s" alt=""/></p>' |
|
1268 |
) % extra_context.get('thumbnail_url') |
|
1269 |
if extra_context.get('mail_url'): |
|
1270 |
r += htmltext('<p><a href="%s">%s</a></p>') % ( |
|
1271 |
extra_context.get('mail_url'), _('Open')) |
|
1272 |
if extra_context.get('user_id'): |
|
1273 |
r += htmltext('<h3>%s</h3>') % _('Associated User') |
|
1274 |
r += htmltext('<p>%s</p>') % get_publisher().user_class.get( |
|
1275 |
extra_context.get('user_id')).display_name |
|
1276 |
if extra_context.get('comments'): |
|
1277 |
r += htmltext('<h3>%s</h3>') % _('Comments') |
|
1278 |
r += htmltext('<p>%s</p>') % extra_context.get('comments') |
|
1279 |
if extra_context.get('summary_url'): |
|
1280 |
r += htmltext('<div data-content-url="%s"></div>' % |
|
1281 |
(extra_context.get('summary_url'))) |
|
1282 |
r += htmltext('</div>') |
|
1256 |
if formdata.submission_context: |
|
1257 |
extra_context = formdata.submission_context or {} |
|
1258 |
r += htmltext('<div class="extra-context">') |
|
1259 |
if extra_context.get('channel'): |
|
1260 |
channel_labels = { |
|
1261 |
'mail': _('Mail'), |
|
1262 |
} |
|
1263 |
r += htmltext('<h3>%s</h3>') % '%s: %s' % ( |
|
1264 |
_('Channel'), channel_labels.get(extra_context.get('channel'), '?')) |
|
1265 |
if extra_context.get('thumbnail_url'): |
|
1266 |
r += htmltext('<p class="thumbnail"><img src="%s" alt=""/></p>' |
|
1267 |
) % extra_context.get('thumbnail_url') |
|
1268 |
if extra_context.get('mail_url'): |
|
1269 |
r += htmltext('<p><a href="%s">%s</a></p>') % ( |
|
1270 |
extra_context.get('mail_url'), _('Open')) |
|
1271 |
if extra_context.get('user_id'): |
|
1272 |
r += htmltext('<h3>%s</h3>') % _('Associated User') |
|
1273 |
r += htmltext('<p>%s</p>') % get_publisher().user_class.get( |
|
1274 |
extra_context.get('user_id')).display_name |
|
1275 |
if extra_context.get('comments'): |
|
1276 |
r += htmltext('<h3>%s</h3>') % _('Comments') |
|
1277 |
r += htmltext('<p>%s</p>') % extra_context.get('comments') |
|
1278 |
if extra_context.get('summary_url'): |
|
1279 |
r += htmltext('<div data-content-url="%s"></div>' % |
|
1280 |
(extra_context.get('summary_url'))) |
|
1281 |
r += htmltext('</div>') |
|
1282 | ||
1283 |
if formdata.user_id and get_publisher().is_using_postgresql(): |
|
1284 |
# display list of open formdata for the same user |
|
1285 |
user_roles = [logged_users_role().id] + (get_request().user.roles or []) |
|
1286 |
criterias = [Equal('is_at_endpoint', False), |
|
1287 |
Equal('user_id', str(formdata.user_id)), |
|
1288 |
Intersects('concerned_roles_array', user_roles), |
|
1289 |
] |
|
1290 |
from wcs import sql |
|
1291 |
formdatas = sql.AnyFormData.select(criterias, order_by='-receipt_time', limit=50) |
|
1292 | ||
1293 |
if formdatas: |
|
1294 |
r += htmltext('<div class="user-pending-forms">') |
|
1295 |
r += htmltext('<h3>%s</h3>') % _('User Pending Forms') |
|
1296 |
categories = {} |
|
1297 |
formdata_by_category = {} |
|
1298 |
for formdata in formdatas: |
|
1299 |
if not formdata.formdef.category_id in categories: |
|
1300 |
categories[formdata.formdef.category_id] = formdata.formdef.category |
|
1301 |
formdata_by_category[formdata.formdef.category_id] = [] |
|
1302 |
formdata_by_category[formdata.formdef.category_id].append(formdata) |
|
1303 |
cats = categories.values() |
|
1304 |
Category.sort_by_position(cats) |
|
1305 |
if self.formdef.category_id in categories: |
|
1306 |
# move current category to the top |
|
1307 |
cats.remove(categories[self.formdef.category_id]) |
|
1308 |
cats.insert(0, categories[self.formdef.category_id]) |
|
1309 |
for cat in cats: |
|
1310 |
if len(cats) > 1: |
|
1311 |
if cat is None: |
|
1312 |
r += htmltext('<h4>%s</h4>') % _('Misc') |
|
1313 |
cat_formdatas = formdata_by_category[None] |
|
1314 |
else: |
|
1315 |
r += htmltext('<h4>%s</h4>') % cat.name |
|
1316 |
cat_formdatas = formdata_by_category[cat.id] |
|
1317 |
else: |
|
1318 |
cat_formdatas = formdatas |
|
1319 |
r += htmltext('<ul>') |
|
1320 |
for formdata in cat_formdatas: |
|
1321 |
status = formdata.get_status() |
|
1322 |
if status: |
|
1323 |
status_label = status.name |
|
1324 |
else: |
|
1325 |
status_label = _('Unknown') |
|
1326 |
submit_date = misc.strftime.strftime( |
|
1327 |
misc.date_format(), formdata.receipt_time) |
|
1328 |
if str(formdata.formdef_id) == str(self.formdef.id) and ( |
|
1329 |
str(formdata.id) == str(self.filled.id)): |
|
1330 |
r += htmltext('<li class="self"><span class="formname">%s</span>, ' |
|
1331 |
'<span class="datetime">%s</span> ' |
|
1332 |
'<span class="status">(%s)</span>' % ( |
|
1333 |
formdata.formdef.name, |
|
1334 |
submit_date, status_label)) |
|
1335 |
else: |
|
1336 |
r += htmltext('<li><a href="%s">%s</a>, ' |
|
1337 |
'<span class="datetime">%s</span> ' |
|
1338 |
'<span class="status">(%s)</span>' % ( |
|
1339 |
formdata.get_url(backoffice=True), |
|
1340 |
formdata.formdef.name, |
|
1341 |
submit_date, status_label)) |
|
1342 |
r += htmltext('</ul>') |
|
1343 |
r += htmltext('</div>') |
|
1344 | ||
1283 | 1345 |
return r.getvalue() |
1284 | 1346 | |
1285 | 1347 |
wcs/categories.py | ||
---|---|---|
65 | 65 | |
66 | 66 |
def sort_by_position(cls, categories): |
67 | 67 |
def cmp_position(x, y): |
68 |
if x is None and y is None: |
|
69 |
return 0 |
|
70 |
if y is None: |
|
71 |
return -1 |
|
72 |
if x is None: |
|
73 |
return 1 |
|
68 | 74 |
if x.position == y.position: |
69 | 75 |
return 0 |
70 | 76 |
if x.position is None: |
wcs/qommon/static/css/dc2/admin.css | ||
---|---|---|
1109 | 1109 |
div.bo-block.important { |
1110 | 1110 |
background: #fd6; |
1111 | 1111 |
border: 1px solid #ffae15; |
1112 |
} |
|
1113 | ||
1114 |
div.user-pending-forms ul { |
|
1115 |
margin-left: 0; |
|
1116 |
padding-left: 1.5em; |
|
1117 |
} |
|
1118 | ||
1119 |
div.user-pending-forms li { |
|
1120 |
line-height: 130%; |
|
1121 |
} |
|
1112 | 1122 | |
1123 |
div.user-pending-forms ul li.self span.formname { |
|
1124 |
font-weight: bold; |
|
1125 |
} |
|
1126 | ||
1127 |
div.user-pending-forms span.datetime, |
|
1128 |
div.user-pending-forms span.status { |
|
1129 |
font-size: 80%; |
|
1113 | 1130 |
} |
1114 |
- |