0001-backoffice-allow-selecting-user-during-submission-81.patch
tests/test_backoffice_pages.py | ||
---|---|---|
87 | 87 | |
88 | 88 | |
89 | 89 |
def create_user(pub, is_admin=False): |
90 |
if pub.user_class.select(lambda x: x.name == 'admin'): |
|
91 |
user1 = pub.user_class.select(lambda x: x.name == 'admin')[0] |
|
92 |
user1.is_admin = is_admin |
|
93 |
user1.roles = [x.id for x in Role.select() if x.name == 'foobar'] |
|
94 |
user1.store() |
|
90 |
user1 = None |
|
91 |
for user in pub.user_class.select(): |
|
92 |
if user.name == 'admin': |
|
93 |
user1 = user |
|
94 |
user1.is_admin = is_admin |
|
95 |
user1.roles = [x.id for x in Role.select() if x.name == 'foobar'] |
|
96 |
user1.store() |
|
97 |
elif user.email == 'jean.darmette@triffouilis.fr': |
|
98 |
pass # don't remove user created by local_user fixture |
|
99 |
else: |
|
100 |
user.remove_self() |
|
101 |
if user1: |
|
95 | 102 |
return user1 |
96 | 103 |
user1 = pub.user_class(name='admin') |
97 | 104 |
user1.email = 'admin@localhost' |
... | ... | |
3527 | 3534 |
assert 'This form is limited to one per user' in resp |
3528 | 3535 | |
3529 | 3536 | |
3537 |
def test_backoffice_submission_user_selection(pub): |
|
3538 |
user = create_user(pub) |
|
3539 |
create_environment(pub) |
|
3540 | ||
3541 |
for i in range(10): |
|
3542 |
random_user = pub.user_class() |
|
3543 |
random_user.name = 'random user %s' % i |
|
3544 |
random_user.store() |
|
3545 | ||
3546 |
app = login(get_app(pub)) |
|
3547 | ||
3548 |
formdef = FormDef.get_by_urlname('form-title') |
|
3549 |
formdef.fields = [ |
|
3550 |
fields.PageField(id='0', label='1st page', type='page'), |
|
3551 |
fields.StringField(id='1', label='Field on 1st page', type='string'), |
|
3552 |
fields.PageField(id='2', label='2nd page', type='page'), |
|
3553 |
fields.StringField(id='3', label='Field on 2nd page', type='string'), |
|
3554 |
] |
|
3555 | ||
3556 |
formdef.backoffice_submission_roles = user.roles[:] |
|
3557 |
formdef.store() |
|
3558 |
resp = app.get('/backoffice/submission/') |
|
3559 |
resp = resp.click(formdef.name) |
|
3560 | ||
3561 |
assert resp.form['submission_channel'].attrs['type'] == 'hidden' |
|
3562 |
assert resp.pyquery('.submit-user-selection') |
|
3563 |
resp.form['user_id'] = str(random_user.id) # happens via javascript |
|
3564 |
resp.form['f1'] = 'test submission' |
|
3565 |
resp = resp.form.submit('submit') # -> 2nd page |
|
3566 |
assert not resp.pyquery('.submit-user-selection') |
|
3567 |
assert '>%s</p>' % random_user.name in resp |
|
3568 |
resp.form['f3'] = 'baz' |
|
3569 |
resp = resp.form.submit('submit') # -> validation page |
|
3570 |
assert 'Check values then click submit.' in resp |
|
3571 |
assert '<p>%s</p>' % random_user.name in resp |
|
3572 | ||
3573 |
# final submit |
|
3574 |
resp = resp.form.submit('submit') |
|
3575 | ||
3576 |
formdata_no = resp.location.split('/')[-2] |
|
3577 |
data_class = formdef.data_class() |
|
3578 |
assert data_class.get(formdata_no).user.name == random_user.name |
|
3579 | ||
3580 |
# select user on second page |
|
3581 |
resp = app.get('/backoffice/submission/') |
|
3582 |
resp = resp.click(formdef.name) |
|
3583 | ||
3584 |
assert resp.form['submission_channel'].attrs['type'] == 'hidden' |
|
3585 |
resp.form['f1'] = 'test submission' |
|
3586 |
resp = resp.form.submit('submit') # -> 2nd page |
|
3587 |
assert resp.pyquery('.submit-user-selection') |
|
3588 |
resp.form['user_id'] = str(random_user.id) # happens via javascript |
|
3589 |
resp.form['f3'] = 'baz' |
|
3590 |
resp = resp.form.submit('submit') # -> validation page |
|
3591 |
assert 'Check values then click submit.' in resp |
|
3592 |
assert '<p>%s</p>' % random_user.name in resp |
|
3593 | ||
3594 |
# final submit |
|
3595 |
resp = resp.form.submit('submit') |
|
3596 | ||
3597 |
formdata_no = resp.location.split('/')[-2] |
|
3598 |
data_class = formdef.data_class() |
|
3599 |
assert data_class.get(formdata_no).user.name == random_user.name |
|
3600 | ||
3601 | ||
3530 | 3602 |
def test_backoffice_wscall_failure_display(http_requests, pub): |
3531 | 3603 |
user = create_user(pub) |
3532 | 3604 |
create_environment(pub) |
wcs/api.py | ||
---|---|---|
44 | 44 | |
45 | 45 |
from .backoffice.management import FormPage as BackofficeFormPage |
46 | 46 |
from .backoffice.management import ManagementDirectory |
47 |
from .backoffice.submission import SubmissionDirectory |
|
47 | 48 | |
48 | 49 | |
49 | 50 |
def posted_json_data_to_formdata_data(formdef, data): |
... | ... | |
760 | 761 |
def _q_index(self): |
761 | 762 |
get_response().set_content_type('application/json') |
762 | 763 |
if not (is_url_signed() or ( |
763 |
get_request().user and get_request().user.can_go_in_admin())): |
|
764 |
get_request().user and ( |
|
765 |
get_request().user.can_go_in_admin() or |
|
766 |
SubmissionDirectory().is_accessible(get_request().user)))): |
|
767 |
# request must be signed, or user must be an administrator or |
|
768 |
# allowed to submit forms (as they have a form to select an user). |
|
764 | 769 |
raise AccessForbiddenError('unsigned request or user has no access to backoffice') |
765 | 770 | |
766 | 771 |
criterias = [] |
wcs/backoffice/data_management.py | ||
---|---|---|
305 | 305 | |
306 | 306 |
class CardFillPage(FormFillPage): |
307 | 307 |
formdef_class = CardDef |
308 |
has_channel_support = False |
|
309 |
has_user_support = False |
|
308 | 310 | |
309 | 311 |
def submitted(self, form, *args): |
310 | 312 |
super(CardFillPage, self).submitted(form, *args) |
wcs/backoffice/submission.py | ||
---|---|---|
95 | 95 |
filling_templates = ['wcs/formdata_filling.html'] |
96 | 96 |
validation_templates = ['wcs/formdata_validation.html'] |
97 | 97 |
steps_templates = ['wcs/formdata_steps.html'] |
98 |
has_channel_support = True |
|
99 |
has_user_support = True |
|
98 | 100 | |
99 | 101 |
def __init__(self, *args, **kwargs): |
100 | 102 |
super(FormFillPage, self).__init__(*args, **kwargs) |
101 | 103 |
self.selected_submission_channel = None |
104 |
self.selected_user_id = None |
|
102 | 105 |
self.remove_draft = RemoveDraftDirectory(self) |
106 |
if get_publisher().get_site_option('welco_url', 'options'): |
|
107 |
# when welco is deployed, do not let agent manually change the |
|
108 |
# submission channel |
|
109 |
self.has_channel_support = False |
|
103 | 110 | |
104 | 111 |
def _q_index(self, *args, **kwargs): |
105 | 112 |
# if NameID, return URL or submission channel are in query string, |
... | ... | |
126 | 133 |
self.set_tracking_code(formdata) |
127 | 134 |
return redirect('%s/' % formdata.id) |
128 | 135 | |
129 |
self.selected_submission_channel = get_request().form.get('submission_channel') or '' |
|
136 |
self.selected_submission_channel = get_request().form.get('channel') or get_request().form.get('submission_channel') |
|
137 |
self.selected_user_id = get_request().form.get('user_id') |
|
130 | 138 |
return super(FormFillPage, self)._q_index(*args, **kwargs) |
131 | 139 | |
132 | 140 |
def html_top(self, *args, **kwargs): |
... | ... | |
182 | 190 |
except KeyError: # it may not exist |
183 | 191 |
pass |
184 | 192 | |
193 |
if formdata and self.selected_user_id: |
|
194 |
formdata.user_id = self.selected_user_id |
|
195 | ||
185 | 196 |
if self.formdef.enable_tracking_codes and not self.edit_mode: |
186 | 197 |
r += htmltext('<h3>%s</h3>') % _('Tracking Code') |
187 | 198 |
if formdata and formdata.tracking_code: |
... | ... | |
189 | 200 |
else: |
190 | 201 |
r += htmltext('<p>-</p>') |
191 | 202 | |
192 |
welco_url = get_publisher().get_site_option('welco_url', 'options') |
|
193 |
if formdata and (formdata.submission_context or formdata.user_id): |
|
203 |
if formdata and self.on_validation_page: |
|
204 |
if self.has_channel_support and self.selected_submission_channel: |
|
205 |
formdata.submission_channel = self.selected_submission_channel |
|
206 |
if self.has_user_support and self.selected_user_id: |
|
207 |
formdata.user_id = self.selected_user_id |
|
208 | ||
209 |
if (formdata and (formdata.submission_context or formdata.user_id)) or self.on_validation_page: |
|
194 | 210 |
from .management import FormBackOfficeStatusPage |
195 | 211 |
r += FormBackOfficeStatusPage(self.formdef, formdata).get_extra_context_bar() |
196 |
elif not welco_url and not self.edit_mode: |
|
197 |
r += htmltext('<div class="submit-channel-selection" style="display: none;">') |
|
198 |
r += htmltext('<h3>%s</h3>') % _('Channel') |
|
199 |
r += htmltext('<select>') |
|
200 |
for channel_key, channel_label in [('', '-')] + list(FormData.get_submission_channels().items()): |
|
201 |
selected = '' |
|
202 |
if self.selected_submission_channel == channel_key: |
|
203 |
selected = 'selected="selected"' |
|
204 |
r += htmltext('<option value="%s" %s>' % (channel_key, selected)) |
|
205 |
r += htmltext('%s</option>') % channel_label |
|
206 |
r += htmltext('</select>') |
|
207 |
r += htmltext('</div>') |
|
212 |
elif not self.edit_mode: |
|
213 |
if self.has_channel_support: |
|
214 |
r += htmltext('<div class="submit-channel-selection" style="display: none;">') |
|
215 |
r += htmltext('<h3>%s</h3>') % _('Channel') |
|
216 |
r += htmltext('<select>') |
|
217 |
for channel_key, channel_label in [('', '-')] + list(FormData.get_submission_channels().items()): |
|
218 |
selected = '' |
|
219 |
if self.selected_submission_channel == channel_key: |
|
220 |
selected = 'selected="selected"' |
|
221 |
r += htmltext('<option value="%s" %s>' % (channel_key, selected)) |
|
222 |
r += htmltext('%s</option>') % channel_label |
|
223 |
r += htmltext('</select>') |
|
224 |
r += htmltext('</div>') |
|
225 | ||
226 |
if self.has_user_support: |
|
227 |
r += htmltext('<div class="submit-user-selection" style="display: none;">') |
|
228 |
get_response().add_javascript(['select2.js']) |
|
229 |
r += htmltext('<h3>%s</h3>') % _('Associated User') |
|
230 |
r += htmltext('<select>') |
|
231 |
if self.selected_user_id: |
|
232 |
r += htmltext('<option value="%s">%s</option>') % ( |
|
233 |
self.selected_user_id, |
|
234 |
get_publisher().user_class.get(self.selected_user_id) |
|
235 |
) |
|
236 |
r += htmltext('</select>') |
|
237 |
r += htmltext('</div>') |
|
208 | 238 | |
209 | 239 |
return r.getvalue() |
210 | 240 | |
211 | 241 |
def create_view_form(self, *args, **kwargs): |
212 | 242 |
form = super(FormFillPage, self).create_view_form(*args, **kwargs) |
213 |
welco_url = get_publisher().get_site_option('welco_url', 'options') |
|
214 |
if not welco_url: |
|
243 |
if self.has_channel_support: |
|
215 | 244 |
form.add_hidden('submission_channel', self.selected_submission_channel) |
245 |
if self.has_user_support: |
|
246 |
form.add_hidden('user_id', self.selected_user_id) |
|
216 | 247 |
return form |
217 | 248 | |
218 | 249 |
def create_form(self, *args, **kwargs): |
219 | 250 |
form = super(FormFillPage, self).create_form(*args, **kwargs) |
220 | 251 |
form.attrs['data-live-url'] = self.formdef.get_backoffice_submission_url() + 'live' |
221 |
welco_url = get_publisher().get_site_option('welco_url', 'options') |
|
222 |
if not welco_url: |
|
252 |
if self.has_channel_support: |
|
223 | 253 |
form.add_hidden('submission_channel', self.selected_submission_channel) |
254 |
if self.has_user_support: |
|
255 |
form.add_hidden('user_id', self.selected_user_id) |
|
224 | 256 |
return form |
225 | 257 | |
226 | 258 |
def form_side(self, step_no, page, data=None, magictoken=None): |
... | ... | |
248 | 280 |
filled.backoffice_submission = True |
249 | 281 |
if not filled.submission_context: |
250 | 282 |
filled.submission_context = {} |
251 |
if self.selected_submission_channel: |
|
283 |
if self.has_channel_support and self.selected_submission_channel:
|
|
252 | 284 |
filled.submission_channel = self.selected_submission_channel |
285 |
if self.has_user_support and self.selected_user_id: |
|
286 |
filled.user_id = self.selected_user_id |
|
253 | 287 |
filled.submission_agent_id = str(get_request().user.id) |
254 | 288 |
filled.store() |
255 | 289 |
wcs/forms/root.py | ||
---|---|---|
215 | 215 |
self.code = TrackingCodesDirectory(self.formdef) |
216 | 216 |
self.action_url = '.' |
217 | 217 |
self.edit_mode = False |
218 |
self.on_validation_page = False |
|
218 | 219 |
self.user = get_request().user |
219 | 220 |
get_response().breadcrumb.append( (component + '/', self.formdef.name) ) |
220 | 221 | |
... | ... | |
1371 | 1372 |
return get_session().get_tempfile_content(t).get_file_pointer().read() |
1372 | 1373 | |
1373 | 1374 |
def validating(self, data): |
1375 |
self.on_validation_page = True |
|
1374 | 1376 |
get_request().view_name = 'validation' |
1375 | 1377 |
self.html_top(self.formdef.name) |
1376 | 1378 |
# fake a GET request to avoid previous page POST data being carried |
wcs/qommon/static/css/dc2/admin.css | ||
---|---|---|
633 | 633 |
margin: 1px 0; |
634 | 634 |
} |
635 | 635 | |
636 |
aside#sidebar span.select2-container { |
|
637 |
width: 100% !important; |
|
638 |
min-width: auto !important; |
|
639 |
} |
|
640 | ||
636 | 641 |
div.TextWidget textarea:focus, |
637 | 642 |
div.widget input[type="text"]:focus, |
638 | 643 |
div.TextWidget textarea, |
wcs/qommon/static/js/qommon.admin.js | ||
---|---|---|
137 | 137 |
$('input[type=hidden][name=submission_channel]').val($(this).val()); |
138 | 138 |
}); |
139 | 139 | |
140 |
/* user id */ |
|
141 |
var select2_options = { |
|
142 |
language: { |
|
143 |
errorLoading: function() { return WCS_I18N.s2_errorloading; }, |
|
144 |
noResults: function () { return WCS_I18N.s2_nomatches; }, |
|
145 |
inputTooShort: function (input, min) { return WCS_I18N.s2_tooshort; }, |
|
146 |
loadingMore: function () { return WCS_I18N.s2_loadmore; }, |
|
147 |
searching: function () { return WCS_I18N.s2_searching; } |
|
148 |
}, |
|
149 |
ajax: { |
|
150 |
delay: 250, |
|
151 |
dataType: 'json', |
|
152 |
data: function(params) { |
|
153 |
return {q: params.term, page_limit: 10}; |
|
154 |
}, |
|
155 |
processResults: function (data, params) { |
|
156 |
return {results: data.data}; |
|
157 |
}, |
|
158 |
url: '/api/users/' |
|
159 |
}, |
|
160 |
placeholder: '-' |
|
161 |
} |
|
162 |
$('div.submit-user-selection select').select2(select2_options); |
|
163 |
$('div.submit-user-selection').show().find('select').on('change', function() { |
|
164 |
$('input[type=hidden][name=user_id]').val($(this).val()); |
|
165 |
}); |
|
166 | ||
140 | 167 |
/* new action form */ |
141 | 168 |
$('#new-action-form select').on('change', function() { |
142 | 169 |
if ($(this).val() == '') { |
143 |
- |