backoffice: make it possible to submit forms from the backoffice (#7052)

This commit is contained in:
Frédéric Péters 2015-04-30 20:17:37 +02:00
parent 7bd19acf00
commit 343a2d1150
4 changed files with 169 additions and 7 deletions

View File

@ -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

View File

@ -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)

View File

@ -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 = []

View File

@ -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;