This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
asec/extra/modules/backoffice.py

278 lines
10 KiB
Python

# w.c.s. (asec) - w.c.s. extension for poll & survey service
# Copyright (C) 2010-2011 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 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 Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from quixote import get_publisher, get_request, get_response, get_session, redirect
from quixote.directory import Directory, AccessControlled
from quixote.html import TemplateIO, htmltext
from qommon import errors
from qommon.admin.texts import TextsDirectory
import qommon.backoffice.menu
from qommon.backoffice.menu import html_top
from qommon.form import *
from wcs import workflows
from wcs.formdef import FormDef
from boforms import FormsDirectory
from boconfig import ConfigDirectory
import quota
def generate_user_info():
# same as backoffice.menu.generate_user_info, without the admin link, but
# with a configuration link
if not get_request().user:
return ''
user = get_request().user
if user:
user = get_session().get_user_object()
username = user.display_name
else:
username = _('Unknown')
logout_url = get_publisher().get_root_url() + 'logout'
config_url = get_publisher().get_root_url() + 'backoffice/config/'
r = TemplateIO(html=True)
r += htmltext('<ul class="user-info">')
r += htmltext('<li class="ui-name">%s</li>') % username
r += htmltext('<li class="ui-logout"><a href="%s">%s</a></li>') % (logout_url, _('logout'))
if get_publisher().backoffice_help_url and \
get_request().language in get_publisher().backoffice_help_url:
help_url = get_publisher().backoffice_help_url[get_request().language]
r += htmltext('<li class="ui-help"><a href="%s">%s</a></li>') % (help_url, _('help'))
r += htmltext('</ul>')
return r.getvalue()
qommon.backoffice.menu.generate_user_info = generate_user_info
def generate_header_menu(selected = None):
s = ['<ul id="menu">\n']
base_url = get_publisher().get_root_url() + 'backoffice'
for item in get_publisher().get_backoffice_root().items:
if len(item) == 2:
k, v = item
display_function = None
elif len(item) == 3:
k, v, display_function = item
if k is None: # heading
s.append('<li><strong>%s</strong></li>' % v)
continue
if display_function and not display_function(k):
continue
if k.rstrip('/') == selected:
s.append('<li class="active">')
else:
s.append('<li>')
s.append('<a href="%s/%s">%s</a></li>\n' % (base_url, k, _(v)))
s.append('</ul>\n')
return ''.join(s)
qommon.backoffice.menu.generate_header_menu = generate_header_menu
class RootDirectory(AccessControlled, Directory):
_q_exports = ['', 'forms', 'config', 'new']
forms = FormsDirectory()
config = ConfigDirectory()
def get_items(self):
if get_response().filter.get('objectdef'):
id = get_response().filter.get('objectdef').id
return [('forms/%s/' % id, N_('Design')),
('forms/%s/diffusion/' % id, N_('Diffusion')),
('forms/%s/results/' % id, N_('Analysis'))]
return [ ('', N_('Welcome')), ]
items = property(get_items)
def register_directory(cls, *args):
pass
register_directory = classmethod(register_directory)
def register_menu_item(cls, *args):
pass
register_menu_item = classmethod(register_menu_item)
def _q_access(self):
get_response().breadcrumb = [ ('backoffice/', _('Back Office')) ]
user = get_request().user
if not user:
raise errors.AccessUnauthorizedError(
public_msg = _('Access to backoffice is restricted to authorized persons only. '\
'Please login.'))
if user and not ((hasattr(user, 'is_asec_admin') and user.is_asec_admin) or user.is_admin):
raise errors.AccessForbiddenError()
self.create_asec_objects()
def _q_index(self):
get_response().breadcrumb = [ ('backoffice/', _('Back Office of your site')) ]
html_top('', _('Questionnaires'))
r = TemplateIO(html=True)
if quota.is_expired():
r += TextsDirectory.get_html_text('asec-expired-site-backoffice')
formdefs = FormDef.select(order_by='name', ignore_errors=True)
if formdefs:
r += htmltext('<h2>%s</h2>') % _('Existing Questionnaires')
r += htmltext('<ul class="biglist" id="all-forms">')
for formdef in formdefs:
if formdef.disabled:
r += htmltext('<li class="disabled">')
else:
r += htmltext('<li>')
r += htmltext('<strong class="label"><a href="forms/%s/">%s</a></strong>') % (formdef.id, formdef.name)
r += htmltext('</li>')
r += htmltext('</ul>')
if quota.may_add_a_new_form():
r += htmltext('<h2>%s</h2>') % _('New Questionnaire')
form = Form(enctype='multipart/form-data', action='new')
form.add(StringWidget, 'name', title=_('Title'), size=40, required=True)
form.add_submit('submit', _('Create New Questionnaire'))
r += form.render()
get_response().filter['sidebar'] = self.get_sidebar()
return r.getvalue()
def get_sidebar(self):
# manually add those scripts, as the sidebar is not parsed when looking
# for popup links
get_response().add_javascript(['jquery.js', 'simplemodal/jquery.simplemodal.js', 'popup.js'])
r = TemplateIO(html=True)
r += htmltext('<div class="bo-block">')
r += htmltext('<h3>%s</h3>') % _('Your Profile')
# TODO: possiblity to create additional administrator accounts?
r += htmltext('<ul>')
r += htmltext(' <li><a href="config/contact" rel="popup">%s</a></li>') % _('Contact Information')
r += htmltext(' <li><a href="config/password" rel="popup">%s</a></li>') % _('Password Change')
r += htmltext('</ul>')
r += htmltext('</div>')
r += htmltext('<div class="bo-block">')
r += htmltext('<h3>%s</h3>') % _('Site Settings')
r += htmltext('<ul>')
r += htmltext(' <li><a href="config/sitetitle" rel="popup">%s</a></li>') % _('Title')
r += htmltext(' <li><a href="config/homepage">%s</a></li>') % _('Welcome Text')
r += htmltext(' <li><a href="config/texts/asec-recorded-vote">%s</a></li>') % _('End Text')
if quota.can_logo() or quota.can_theme():
r += htmltext(' <li><a href="config/appearance">%s</a></li>') % _('Appearance')
r += htmltext('</ul>')
r += htmltext('</div>')
return r.getvalue()
def new(self):
if not quota.may_add_a_new_form():
raise quota.QuotaExceeded()
form = Form(enctype='multipart/form-data', action='new')
form.add(StringWidget, 'name', title=_('Title'), size=40, required=True)
form.add_submit('submit', _('Submit'))
if form.has_errors():
return redirect('.')
formdef = FormDef()
name = form.get_widget('name').parse()
formdefs_name = [x.name for x in FormDef.select(ignore_errors=True) if x.id != formdef.id]
if name in formdefs_name:
form.get_widget('name').set_error(_('This name is already used'))
raise ValueError()
formdef.name = form.get_widget('name').parse()
formdef.fields = []
formdef.disabled = True
formdef.asec_status = 'soon-available'
try:
formdef.workflow_id = 'asec-default'
except IndexError:
pass
formdef.disabled = True
formdef.store() # this makes sure the form has a correct id
formdef.private = False
formdef.disabled = False
formdef.store()
return redirect('forms/%s/' % formdef.id)
def create_asec_objects(self):
if not workflows.Workflow.has_key('asec-default'):
workflow = workflows.Workflow(name=_('Default Workflow'))
workflow._version = 1
workflow.id = 'asec-default'
status = workflow.add_status(_('Done'))
status.id = 'done'
workflow.store()
if not workflows.Workflow.has_key('asec-default+anonymous'):
import anonymity
workflow = workflows.Workflow(name=_('Default Workflow, Anonymous'))
workflow._version = 1
workflow.id = 'asec-default+anonymous'
status = workflow.add_status(_('Done'))
status.items = [anonymity.AnonymiseStatusItem()]
status.id = 'done'
workflow.store()
wf1 = workflows.Workflow.get('asec-default')
wf2 = workflows.Workflow.get('asec-default+anonymous')
# fix workflows created in the first versions of asec, to have them
# versioned like new ones.
if not hasattr(wf1, 'version'):
wf1.version = 1
wf1.possible_status[0].id = 'done'
if not hasattr(wf2, 'version'):
wf2.version = 1
wf2.possible_status[0].id = 'done'
for wf in (wf1, wf2):
if wf.version < 2:
# add a Sendmail action, left blank
wf.version = 2
status = wf.get_status('done')
sendmail_item = workflows.SendmailWorkflowStatusItem()
sendmail_item.id = 'mail-on-filled'
sendmail_item.subject = _('New questionnaire ([name]) has been filled')
sendmail_item.body = _('''\
A new questionnaire ([name]) has been filled.
[details]
''')
status.items.append(sendmail_item)
wf.store()
TextsDirectory.register('asec-expired-site-backoffice',
N_('Text displayed on the backoffice when the site has expired'),
default=N_('''<p>
This site has expired. You still have access to all of your data but
your questionnaires are no longer published.
</p>
'''))