backoffice: allow selecting user during submission (#8177)
This commit is contained in:
parent
ea1255b9dd
commit
f03e42545e
|
@ -84,11 +84,18 @@ coucou = 1234
|
|||
|
||||
|
||||
def create_user(pub, is_admin=False):
|
||||
if pub.user_class.select(lambda x: x.name == 'admin'):
|
||||
user1 = pub.user_class.select(lambda x: x.name == 'admin')[0]
|
||||
user1.is_admin = is_admin
|
||||
user1.roles = [x.id for x in Role.select() if x.name == 'foobar']
|
||||
user1.store()
|
||||
user1 = None
|
||||
for user in pub.user_class.select():
|
||||
if user.name == 'admin':
|
||||
user1 = user
|
||||
user1.is_admin = is_admin
|
||||
user1.roles = [x.id for x in Role.select() if x.name == 'foobar']
|
||||
user1.store()
|
||||
elif user.email == 'jean.darmette@triffouilis.fr':
|
||||
pass # don't remove user created by local_user fixture
|
||||
else:
|
||||
user.remove_self()
|
||||
if user1:
|
||||
return user1
|
||||
user1 = pub.user_class(name='admin')
|
||||
user1.email = 'admin@localhost'
|
||||
|
@ -3237,6 +3244,71 @@ def test_backoffice_submission_only_one_check(pub, local_user):
|
|||
assert 'This form is limited to one per user' in resp
|
||||
|
||||
|
||||
def test_backoffice_submission_user_selection(pub):
|
||||
user = create_user(pub)
|
||||
create_environment(pub)
|
||||
|
||||
for i in range(10):
|
||||
random_user = pub.user_class()
|
||||
random_user.name = 'random user %s' % i
|
||||
random_user.store()
|
||||
|
||||
app = login(get_app(pub))
|
||||
|
||||
formdef = FormDef.get_by_urlname('form-title')
|
||||
formdef.fields = [
|
||||
fields.PageField(id='0', label='1st page', type='page'),
|
||||
fields.StringField(id='1', label='Field on 1st page', type='string'),
|
||||
fields.PageField(id='2', label='2nd page', type='page'),
|
||||
fields.StringField(id='3', label='Field on 2nd page', type='string'),
|
||||
]
|
||||
|
||||
formdef.backoffice_submission_roles = user.roles[:]
|
||||
formdef.store()
|
||||
resp = app.get('/backoffice/submission/')
|
||||
resp = resp.click(formdef.name)
|
||||
|
||||
assert resp.form['submission_channel'].attrs['type'] == 'hidden'
|
||||
assert resp.pyquery('.submit-user-selection')
|
||||
resp.form['user_id'] = str(random_user.id) # happens via javascript
|
||||
resp.form['f1'] = 'test submission'
|
||||
resp = resp.form.submit('submit') # -> 2nd page
|
||||
assert not resp.pyquery('.submit-user-selection')
|
||||
assert '>%s</p>' % random_user.name in resp
|
||||
resp.form['f3'] = 'baz'
|
||||
resp = resp.form.submit('submit') # -> validation page
|
||||
assert 'Check values then click submit.' in resp
|
||||
assert '<p>%s</p>' % random_user.name in resp
|
||||
|
||||
# final submit
|
||||
resp = resp.form.submit('submit')
|
||||
|
||||
formdata_no = resp.location.split('/')[-2]
|
||||
data_class = formdef.data_class()
|
||||
assert data_class.get(formdata_no).user.name == random_user.name
|
||||
|
||||
# select user on second page
|
||||
resp = app.get('/backoffice/submission/')
|
||||
resp = resp.click(formdef.name)
|
||||
|
||||
assert resp.form['submission_channel'].attrs['type'] == 'hidden'
|
||||
resp.form['f1'] = 'test submission'
|
||||
resp = resp.form.submit('submit') # -> 2nd page
|
||||
assert resp.pyquery('.submit-user-selection')
|
||||
resp.form['user_id'] = str(random_user.id) # happens via javascript
|
||||
resp.form['f3'] = 'baz'
|
||||
resp = resp.form.submit('submit') # -> validation page
|
||||
assert 'Check values then click submit.' in resp
|
||||
assert '<p>%s</p>' % random_user.name in resp
|
||||
|
||||
# final submit
|
||||
resp = resp.form.submit('submit')
|
||||
|
||||
formdata_no = resp.location.split('/')[-2]
|
||||
data_class = formdef.data_class()
|
||||
assert data_class.get(formdata_no).user.name == random_user.name
|
||||
|
||||
|
||||
def test_backoffice_wscall_failure_display(http_requests, pub):
|
||||
user = create_user(pub)
|
||||
create_environment(pub)
|
||||
|
|
|
@ -44,6 +44,7 @@ from wcs.api_utils import sign_url_auto_orig, is_url_signed, get_user_from_api_q
|
|||
from .backoffice.management import FormPage as BackofficeFormPage
|
||||
from .backoffice.management import ManagementDirectory
|
||||
from .backoffice.data_management import CardPage as BackofficeCardPage
|
||||
from .backoffice.submission import SubmissionDirectory
|
||||
|
||||
|
||||
def posted_json_data_to_formdata_data(formdef, data):
|
||||
|
@ -791,7 +792,11 @@ class ApiUsersDirectory(Directory):
|
|||
def _q_index(self):
|
||||
get_response().set_content_type('application/json')
|
||||
if not (is_url_signed() or (
|
||||
get_request().user and get_request().user.can_go_in_admin())):
|
||||
get_request().user and (
|
||||
get_request().user.can_go_in_admin() or
|
||||
SubmissionDirectory().is_accessible(get_request().user)))):
|
||||
# request must be signed, or user must be an administrator or
|
||||
# allowed to submit forms (as they have a form to select an user).
|
||||
raise AccessForbiddenError('unsigned request or user has no access to backoffice')
|
||||
|
||||
criterias = []
|
||||
|
|
|
@ -313,6 +313,8 @@ class CardPage(FormPage):
|
|||
|
||||
class CardFillPage(FormFillPage):
|
||||
formdef_class = CardDef
|
||||
has_channel_support = False
|
||||
has_user_support = False
|
||||
|
||||
def submitted(self, form, *args):
|
||||
super(CardFillPage, self).submitted(form, *args)
|
||||
|
|
|
@ -95,11 +95,18 @@ class FormFillPage(PublicFormFillPage):
|
|||
filling_templates = ['wcs/formdata_filling.html']
|
||||
validation_templates = ['wcs/formdata_validation.html']
|
||||
steps_templates = ['wcs/formdata_steps.html']
|
||||
has_channel_support = True
|
||||
has_user_support = True
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(FormFillPage, self).__init__(*args, **kwargs)
|
||||
self.selected_submission_channel = None
|
||||
self.selected_user_id = None
|
||||
self.remove_draft = RemoveDraftDirectory(self)
|
||||
if get_publisher().get_site_option('welco_url', 'options'):
|
||||
# when welco is deployed, do not let agent manually change the
|
||||
# submission channel
|
||||
self.has_channel_support = False
|
||||
|
||||
def _q_index(self, *args, **kwargs):
|
||||
# if NameID, return URL or submission channel are in query string,
|
||||
|
@ -126,7 +133,8 @@ class FormFillPage(PublicFormFillPage):
|
|||
self.set_tracking_code(formdata)
|
||||
return redirect('%s/' % formdata.id)
|
||||
|
||||
self.selected_submission_channel = get_request().form.get('submission_channel') or ''
|
||||
self.selected_submission_channel = get_request().form.get('channel') or get_request().form.get('submission_channel')
|
||||
self.selected_user_id = get_request().form.get('user_id')
|
||||
return super(FormFillPage, self)._q_index(*args, **kwargs)
|
||||
|
||||
def html_top(self, *args, **kwargs):
|
||||
|
@ -182,6 +190,9 @@ class FormFillPage(PublicFormFillPage):
|
|||
except KeyError: # it may not exist
|
||||
pass
|
||||
|
||||
if formdata and self.selected_user_id:
|
||||
formdata.user_id = self.selected_user_id
|
||||
|
||||
if self.formdef.enable_tracking_codes and not self.edit_mode:
|
||||
r += htmltext('<h3>%s</h3>') % _('Tracking Code')
|
||||
if formdata and formdata.tracking_code:
|
||||
|
@ -189,38 +200,59 @@ class FormFillPage(PublicFormFillPage):
|
|||
else:
|
||||
r += htmltext('<p>-</p>')
|
||||
|
||||
welco_url = get_publisher().get_site_option('welco_url', 'options')
|
||||
if formdata and (formdata.submission_context or formdata.user_id):
|
||||
if formdata and self.on_validation_page:
|
||||
if self.has_channel_support and self.selected_submission_channel:
|
||||
formdata.submission_channel = self.selected_submission_channel
|
||||
if self.has_user_support and self.selected_user_id:
|
||||
formdata.user_id = self.selected_user_id
|
||||
|
||||
if (formdata and (formdata.submission_context or formdata.user_id)) or self.on_validation_page:
|
||||
from .management import FormBackOfficeStatusPage
|
||||
r += FormBackOfficeStatusPage(self.formdef, formdata).get_extra_context_bar()
|
||||
elif not welco_url and not self.edit_mode:
|
||||
r += htmltext('<div class="submit-channel-selection" style="display: none;">')
|
||||
r += htmltext('<h3>%s</h3>') % _('Channel')
|
||||
r += htmltext('<select>')
|
||||
for channel_key, channel_label in [('', '-')] + list(FormData.get_submission_channels().items()):
|
||||
selected = ''
|
||||
if self.selected_submission_channel == channel_key:
|
||||
selected = 'selected="selected"'
|
||||
r += htmltext('<option value="%s" %s>' % (channel_key, selected))
|
||||
r += htmltext('%s</option>') % channel_label
|
||||
r += htmltext('</select>')
|
||||
r += htmltext('</div>')
|
||||
elif not self.edit_mode:
|
||||
if self.has_channel_support:
|
||||
r += htmltext('<div class="submit-channel-selection" style="display: none;">')
|
||||
r += htmltext('<h3>%s</h3>') % _('Channel')
|
||||
r += htmltext('<select>')
|
||||
for channel_key, channel_label in [('', '-')] + list(FormData.get_submission_channels().items()):
|
||||
selected = ''
|
||||
if self.selected_submission_channel == channel_key:
|
||||
selected = 'selected="selected"'
|
||||
r += htmltext('<option value="%s" %s>' % (channel_key, selected))
|
||||
r += htmltext('%s</option>') % channel_label
|
||||
r += htmltext('</select>')
|
||||
r += htmltext('</div>')
|
||||
|
||||
if self.has_user_support:
|
||||
r += htmltext('<div class="submit-user-selection" style="display: none;">')
|
||||
get_response().add_javascript(['select2.js'])
|
||||
r += htmltext('<h3>%s</h3>') % _('Associated User')
|
||||
r += htmltext('<select>')
|
||||
if self.selected_user_id:
|
||||
r += htmltext('<option value="%s">%s</option>') % (
|
||||
self.selected_user_id,
|
||||
get_publisher().user_class.get(self.selected_user_id, ignore_errors=True)
|
||||
)
|
||||
r += htmltext('</select>')
|
||||
r += htmltext('</div>')
|
||||
|
||||
return r.getvalue()
|
||||
|
||||
def create_view_form(self, *args, **kwargs):
|
||||
form = super(FormFillPage, self).create_view_form(*args, **kwargs)
|
||||
welco_url = get_publisher().get_site_option('welco_url', 'options')
|
||||
if not welco_url:
|
||||
if self.has_channel_support:
|
||||
form.add_hidden('submission_channel', self.selected_submission_channel)
|
||||
if self.has_user_support:
|
||||
form.add_hidden('user_id', self.selected_user_id)
|
||||
return form
|
||||
|
||||
def create_form(self, *args, **kwargs):
|
||||
form = super(FormFillPage, self).create_form(*args, **kwargs)
|
||||
form.attrs['data-live-url'] = self.formdef.get_backoffice_submission_url() + 'live'
|
||||
welco_url = get_publisher().get_site_option('welco_url', 'options')
|
||||
if not welco_url:
|
||||
if self.has_channel_support:
|
||||
form.add_hidden('submission_channel', self.selected_submission_channel)
|
||||
if self.has_user_support:
|
||||
form.add_hidden('user_id', self.selected_user_id)
|
||||
return form
|
||||
|
||||
def form_side(self, step_no, page, data=None, magictoken=None):
|
||||
|
@ -248,8 +280,10 @@ class FormFillPage(PublicFormFillPage):
|
|||
filled.backoffice_submission = True
|
||||
if not filled.submission_context:
|
||||
filled.submission_context = {}
|
||||
if self.selected_submission_channel:
|
||||
if self.has_channel_support and self.selected_submission_channel:
|
||||
filled.submission_channel = self.selected_submission_channel
|
||||
if self.has_user_support and self.selected_user_id:
|
||||
filled.user_id = self.selected_user_id
|
||||
filled.submission_agent_id = str(get_request().user.id)
|
||||
filled.store()
|
||||
|
||||
|
|
|
@ -215,6 +215,7 @@ class FormPage(Directory, FormTemplateMixin):
|
|||
self.code = TrackingCodesDirectory(self.formdef)
|
||||
self.action_url = '.'
|
||||
self.edit_mode = False
|
||||
self.on_validation_page = False
|
||||
self.user = get_request().user
|
||||
get_response().breadcrumb.append( (component + '/', self.formdef.name) )
|
||||
|
||||
|
@ -1375,6 +1376,7 @@ class FormPage(Directory, FormTemplateMixin):
|
|||
return get_session().get_tempfile_content(t).get_file_pointer().read()
|
||||
|
||||
def validating(self, data):
|
||||
self.on_validation_page = True
|
||||
get_request().view_name = 'validation'
|
||||
self.html_top(self.formdef.name)
|
||||
# fake a GET request to avoid previous page POST data being carried
|
||||
|
|
|
@ -633,6 +633,11 @@ aside#sidebar select {
|
|||
margin: 1px 0;
|
||||
}
|
||||
|
||||
aside#sidebar span.select2-container {
|
||||
width: 100% !important;
|
||||
min-width: auto !important;
|
||||
}
|
||||
|
||||
div.TextWidget textarea:focus,
|
||||
div.widget input[type="text"]:focus,
|
||||
div.TextWidget textarea,
|
||||
|
|
|
@ -137,6 +137,35 @@ $(function() {
|
|||
$('input[type=hidden][name=submission_channel]').val($(this).val());
|
||||
});
|
||||
|
||||
/* user id */
|
||||
var select2_options = {
|
||||
language: {
|
||||
errorLoading: function() { return WCS_I18N.s2_errorloading; },
|
||||
noResults: function () { return WCS_I18N.s2_nomatches; },
|
||||
inputTooShort: function (input, min) { return WCS_I18N.s2_tooshort; },
|
||||
loadingMore: function () { return WCS_I18N.s2_loadmore; },
|
||||
searching: function () { return WCS_I18N.s2_searching; }
|
||||
},
|
||||
ajax: {
|
||||
delay: 250,
|
||||
dataType: 'json',
|
||||
data: function(params) {
|
||||
return {q: params.term, page_limit: 10};
|
||||
},
|
||||
processResults: function (data, params) {
|
||||
return {results: data.data};
|
||||
},
|
||||
url: '/api/users/'
|
||||
},
|
||||
placeholder: '-'
|
||||
}
|
||||
if ($('div.submit-user-selection').length) {
|
||||
$('div.submit-user-selection select').select2(select2_options);
|
||||
$('div.submit-user-selection').show().find('select').on('change', function() {
|
||||
$('input[type=hidden][name=user_id]').val($(this).val());
|
||||
});
|
||||
}
|
||||
|
||||
/* new action form */
|
||||
$('#new-action-form select').on('change', function() {
|
||||
if ($(this).val() == '') {
|
||||
|
|
Loading…
Reference in New Issue