backoffice: make it possible to submit forms from the backoffice (#7052)
This commit is contained in:
parent
7bd19acf00
commit
343a2d1150
|
@ -39,6 +39,7 @@ import wcs.admin.settings
|
|||
import wcs.admin.users
|
||||
import wcs.admin.workflows
|
||||
|
||||
from . import submission
|
||||
from . import management
|
||||
|
||||
|
||||
|
@ -54,9 +55,11 @@ class RootDirectory(BackofficeRootDirectory):
|
|||
users = wcs.admin.users.UsersDirectory()
|
||||
workflows = wcs.admin.workflows.WorkflowsDirectory()
|
||||
management = management.ManagementDirectory()
|
||||
submission = submission.SubmissionDirectory()
|
||||
|
||||
menu_items = [
|
||||
('management/', N_('Management')),
|
||||
('submission/', N_('Submission')),
|
||||
('forms/', N_('Forms Workshop')),
|
||||
('workflows/', N_('Workflows Workshop')),
|
||||
('users/', N_('Users')),
|
||||
|
@ -92,7 +95,7 @@ class RootDirectory(BackofficeRootDirectory):
|
|||
|
||||
# for some subdirectories, the user needs to be part of a role allowed
|
||||
# to go in the backoffice
|
||||
if subdirectory in ('management',):
|
||||
if subdirectory in ('management', 'submission'):
|
||||
return get_request().user.can_go_in_backoffice()
|
||||
|
||||
# for the other directories, an extra level is required, the user needs
|
||||
|
@ -252,6 +255,6 @@ class RootDirectory(BackofficeRootDirectory):
|
|||
'slug': slug,
|
||||
'url': backoffice_url + k})
|
||||
if slug in ('home', 'forms', 'workflows', 'users', 'roles',
|
||||
'categories', 'settings', 'management'):
|
||||
'categories', 'settings', 'management', 'submission'):
|
||||
menu_items[-1]['icon'] = k.strip('/')
|
||||
return menu_items
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
# w.c.s. - web application for online forms
|
||||
# Copyright (C) 2005-2015 Entr'ouvert
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import collections
|
||||
|
||||
from quixote import get_request, get_response, get_session, redirect
|
||||
from quixote.directory import Directory
|
||||
from quixote.html import TemplateIO, htmltext
|
||||
|
||||
from qommon.backoffice.menu import html_top
|
||||
from qommon import misc
|
||||
|
||||
from wcs.formdef import FormDef
|
||||
from wcs.categories import Category
|
||||
from wcs.forms.root import FormPage as PublicFormFillPage
|
||||
|
||||
ORIGINS = collections.OrderedDict()
|
||||
ORIGINS['counter'] = N_('Counter')
|
||||
ORIGINS['phone'] = N_('Phone')
|
||||
ORIGINS['mail'] = N_('Mail')
|
||||
ORIGINS['email'] = N_('Email')
|
||||
ORIGINS['fax'] = N_('Fax')
|
||||
ORIGINS['socialnetwork'] = N_('Social Network')
|
||||
ORIGINS['other'] = N_('Other')
|
||||
|
||||
|
||||
class FormFillPage(PublicFormFillPage):
|
||||
def html_top(self, *args, **kwargs):
|
||||
return html_top('submission', *args, **kwargs)
|
||||
|
||||
def get_sidebar(self, data):
|
||||
r = TemplateIO(html=True)
|
||||
|
||||
if self.formdef.enable_tracking_codes:
|
||||
draft_formdata_id = data.get('draft_formdata_id')
|
||||
r += htmltext('<h3>%s</h3>') % _('Tracking Code')
|
||||
tracking_code = None
|
||||
if draft_formdata_id:
|
||||
formdata = self.formdef.data_class().get(draft_formdata_id)
|
||||
if formdata.tracking_code:
|
||||
tracking_code = formdata.tracking_code
|
||||
if tracking_code:
|
||||
r += htmltext('<p>%s</p>') % tracking_code
|
||||
else:
|
||||
r += htmltext('<p>-</p>')
|
||||
|
||||
return r.getvalue()
|
||||
|
||||
def form_side(self, step_no, page_no=0, log_detail=None, data=None, editing=None):
|
||||
r = TemplateIO(html=True)
|
||||
get_response().filter['sidebar'] = self.get_sidebar(data)
|
||||
r += htmltext('<div id="side">')
|
||||
r += self.step(step_no, page_no, log_detail, data=data, editing=editing)
|
||||
r += htmltext('</div> <!-- #side -->')
|
||||
return r.getvalue()
|
||||
|
||||
def submitted(self, form, *args):
|
||||
filled = self.formdef.data_class()()
|
||||
filled.just_created()
|
||||
filled.data = self.formdef.get_data(form)
|
||||
filled.store()
|
||||
|
||||
self.keep_tracking_code(filled)
|
||||
get_session().remove_magictoken(get_request().form.get('magictoken'))
|
||||
|
||||
url = filled.perform_workflow()
|
||||
if not url:
|
||||
url = filled.get_url(backoffice=True)
|
||||
|
||||
return redirect(url)
|
||||
|
||||
|
||||
class SubmissionDirectory(Directory):
|
||||
_q_exports = ['']
|
||||
|
||||
def _q_index(self):
|
||||
get_response().breadcrumb.append(('submission/', _('Submission')))
|
||||
html_top('submission', _('Submission'))
|
||||
formdefs = FormDef.select(order_by='name', ignore_errors=True)
|
||||
formdefs = [x for x in formdefs if (not x.is_disabled() or x.disabled_redirection)]
|
||||
user = get_request().user
|
||||
from wcs.forms.root import RootDirectory
|
||||
root_directory = RootDirectory()
|
||||
list_forms, advertised_forms = root_directory.get_list_of_forms(formdefs, user)
|
||||
|
||||
r = TemplateIO(html=True)
|
||||
|
||||
cats = Category.select()
|
||||
Category.sort_by_position(cats)
|
||||
one = False
|
||||
for c in cats:
|
||||
l2 = [x for x in list_forms if str(x.category_id) == str(c.id)]
|
||||
if l2:
|
||||
r += self.form_list(l2, category=c)
|
||||
one = True
|
||||
|
||||
l2 = [x for x in list_forms if not x.category]
|
||||
if l2:
|
||||
if one:
|
||||
title = _('Misc')
|
||||
else:
|
||||
title = None
|
||||
r += self.form_list(l2, title=title)
|
||||
|
||||
return r.getvalue()
|
||||
|
||||
def form_list(self, formdefs, category=None, title=None):
|
||||
r = TemplateIO(html=True)
|
||||
if title:
|
||||
r += htmltext('<div class="bo-block category" id="category-%s">') % misc.simplify(title)
|
||||
r += htmltext('<h2>%s</h2>') % title
|
||||
elif category:
|
||||
r += htmltext('<div class="bo-block category" id="category-%s">') % category.url_name
|
||||
r += htmltext('<h2>%s</h2>') % category.name
|
||||
else:
|
||||
r += htmltext('<div class="bo-block category" id="category-misc">')
|
||||
|
||||
r += htmltext('<ul class="catforms">')
|
||||
for formdef in formdefs:
|
||||
r += htmltext('<li><a href="%s/">%s</a>') % (formdef.url_name, formdef.name)
|
||||
r += htmltext('</li>')
|
||||
r += htmltext('</ul>')
|
||||
r += htmltext('</div>')
|
||||
|
||||
return r.getvalue()
|
||||
|
||||
def _q_lookup(self, component):
|
||||
get_response().breadcrumb.append(('submission/', _('Submission')))
|
||||
return FormFillPage(component)
|
|
@ -232,6 +232,9 @@ class FormPage(Directory):
|
|||
self.user = get_request().user
|
||||
get_response().breadcrumb.append( (component + '/', self.formdef.name) )
|
||||
|
||||
def html_top(self, *args, **kwargs):
|
||||
html_top(*args, **kwargs)
|
||||
|
||||
def get_substitution_variables(self):
|
||||
return self.substvars
|
||||
|
||||
|
@ -363,6 +366,11 @@ class FormPage(Directory):
|
|||
v = data[k]
|
||||
elif field.prefill:
|
||||
v = field.get_prefill_value()
|
||||
if get_request().get_path().startswith('/backoffice/') and (
|
||||
field.prefill and field.prefill.get('type') in ('user', 'geoloc')):
|
||||
# turn off prefilling from user and geolocation
|
||||
# attributes if the form is filled from the backoffice
|
||||
v = None
|
||||
if v:
|
||||
prefilled = True
|
||||
form.get_widget('f%s' % k).set_message(
|
||||
|
@ -383,7 +391,7 @@ class FormPage(Directory):
|
|||
if not one:
|
||||
req.form = {}
|
||||
|
||||
html_top(self.formdef.name)
|
||||
self.html_top(self.formdef.name)
|
||||
r += self.form_side(0, page_no, log_detail=log_detail, data=data, editing=editing)
|
||||
|
||||
form.add_hidden('step', '0')
|
||||
|
@ -783,6 +791,9 @@ class FormPage(Directory):
|
|||
except AttributeError:
|
||||
filled.user_id = get_request().user.id
|
||||
|
||||
if get_request().get_path().startswith('/backoffice/'):
|
||||
filled.user_id = None
|
||||
|
||||
if self.formdef.only_allow_one:
|
||||
# this is already checked in _q_index but it's done a second time
|
||||
# just before a new form is to be stored.
|
||||
|
@ -812,7 +823,10 @@ class FormPage(Directory):
|
|||
get_session().mark_anonymous_formdata(filled)
|
||||
|
||||
if not url:
|
||||
url = filled.get_url()
|
||||
if get_request().get_path().startswith('/backoffice/'):
|
||||
url = filled.get_url(backoffice=True)
|
||||
else:
|
||||
url = filled.get_url()
|
||||
return redirect(url)
|
||||
|
||||
def keep_tracking_code(self, formdata):
|
||||
|
@ -862,7 +876,7 @@ class FormPage(Directory):
|
|||
return get_session().get_tempfile_content(t).get_file_pointer().read()
|
||||
|
||||
def validating(self, data):
|
||||
html_top(self.formdef.name)
|
||||
self.html_top(self.formdef.name)
|
||||
r = TemplateIO(html=True)
|
||||
r += htmltext('<div class="form-validation">')
|
||||
r += self.form_side(step_no=1, data=data)
|
||||
|
@ -885,7 +899,7 @@ class FormPage(Directory):
|
|||
return r.getvalue()
|
||||
|
||||
def error(self, msg):
|
||||
html_top(self.formdef.name)
|
||||
self.html_top(self.formdef.name)
|
||||
homepage = get_publisher().get_root_url()
|
||||
r = TemplateIO(html=True)
|
||||
r += htmltext('<div class="errornotice">%s</div>') % msg
|
||||
|
@ -896,7 +910,7 @@ class FormPage(Directory):
|
|||
if not self.formdef.is_user_allowed_read(get_request().user):
|
||||
raise errors.AccessForbiddenError()
|
||||
get_response().breadcrumb.append( ('listing', _('Listing')) )
|
||||
html_top('%s - %s' % (_('Listing'), self.formdef.name))
|
||||
self.html_top('%s - %s' % (_('Listing'), self.formdef.name))
|
||||
r = TemplateIO(html=True)
|
||||
|
||||
fields = []
|
||||
|
|
|
@ -765,6 +765,9 @@ li.zone-management a:hover { background-image: url(icon-management-hover.png); }
|
|||
li.zone-home a { background-image: url(icon-home.png); }
|
||||
li.zone-home a:hover { background-image: url(icon-home-hover.png); }
|
||||
|
||||
li.zone-submission a { background-image: url(icon-submission.png); }
|
||||
li.zone-submission a:hover { background-image: url(icon-submission-hover.png); }
|
||||
|
||||
ul.apps li.zone-no-icon a {
|
||||
height: 29px;
|
||||
padding-top: 24px;
|
||||
|
|
Loading…
Reference in New Issue