[IMP] Code cleaning and refactoring

bzr revid: rim@openerp.com-20131125080446-kail7m6xav7gf0xg
This commit is contained in:
Richard Mathot (OpenERP) 2013-11-25 09:04:46 +01:00
parent 72e33b8cfe
commit 5b92704e41
5 changed files with 357 additions and 454 deletions

View File

@ -1 +1,22 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-TODAY OpenERP S.A. <http://www.openerp.com>
#
# 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/>.
#
##############################################################################
import main import main

View File

@ -22,6 +22,7 @@
from openerp.addons.web import http from openerp.addons.web import http
from openerp.addons.web.http import request from openerp.addons.web.http import request
from openerp.addons.website.models import website from openerp.addons.website.models import website
from openerp.osv import fields
from openerp import SUPERUSER_ID from openerp import SUPERUSER_ID
import werkzeug import werkzeug
@ -48,9 +49,9 @@ class WebsiteSurvey(http.Controller):
surveys = survey_obj.browse(cr, uid, survey_ids, context=context) surveys = survey_obj.browse(cr, uid, survey_ids, context=context)
return request.website.render('survey.list', {'surveys': surveys}) return request.website.render('survey.list', {'surveys': surveys})
# Survey displaying # Survey displaying
@website.route(['/survey/fill/<model("survey.survey"):survey>', @website.route(['/survey/fill/<model("survey.survey"):survey>/<string:token>'],
'/survey/fill/<model("survey.survey"):survey>/<string:token>'],
type='http', auth='public', multilang=True) type='http', auth='public', multilang=True)
def fill_survey(self, survey, token=None, **post): def fill_survey(self, survey, token=None, **post):
'''Display and validates a survey''' '''Display and validates a survey'''
@ -58,6 +59,8 @@ class WebsiteSurvey(http.Controller):
survey_obj = request.registry['survey.survey'] survey_obj = request.registry['survey.survey']
user_input_obj = request.registry['survey.user_input'] user_input_obj = request.registry['survey.user_input']
# Mettre methode start survey sur objet survey
# In case of bad survey, redirect to surveys list # In case of bad survey, redirect to surveys list
if survey_obj.exists(cr, uid, survey.id, context=context) == []: if survey_obj.exists(cr, uid, survey.id, context=context) == []:
return werkzeug.utils.redirect("/survey/") return werkzeug.utils.redirect("/survey/")
@ -68,7 +71,7 @@ class WebsiteSurvey(http.Controller):
# In case of non open surveys # In case of non open surveys
if survey.state != 'open': if survey.state != 'open':
return request.website.render("survey.notopen") return request.website.render("survey.notopen")
# If enough surveys completed # If enough surveys completed
if survey.user_input_limit > 0: if survey.user_input_limit > 0:
@ -91,35 +94,34 @@ class WebsiteSurvey(http.Controller):
else: else:
user_input = user_input_obj.browse(cr, uid, [user_input_id], context=context)[0] user_input = user_input_obj.browse(cr, uid, [user_input_id], context=context)[0]
# Prevent opening of the survey if the deadline has turned out
# ! This will NOT disallow access to users who have already partially filled the survey !
# if user_input.deadline > fields.date.now() and user_input.state == 'new':
# return request.website.render("survey.notopen")
# TODO check if this is ok
_logger.debug('Incoming data: %s', post) _logger.debug('Incoming data: %s', post)
# if user input.state = new => page -1 # Select the right page
# sinon, chercher la dernière page sur laquelle on a des infos enregistrées
# si c'est la dernière, afficher la page de conclusion
# Display success message if totally succeeded # if user_input.state == 'new' and not post: # Intro page
if post and post['next'] == "finished": # data = {'survey': survey, 'page': None, 'token': user_input.token}
# return request.website.render('survey.survey', data)
if user_input.state == 'new': # First page
page, page_nr, last = self.find_next_page(survey, user_input)
data = {'survey': survey, 'page': page, 'page_nr': page_nr, 'token': user_input.token}
if last:
data.update({'last': True})
return request.website.render('survey.survey', data)
elif user_input.state == 'done': # Display success message
return request.website.render('survey.finished', {'survey': survey}) return request.website.render('survey.finished', {'survey': survey})
elif user_input.state == 'skip':
# Page selection page, page_nr, last = self.find_next_page(survey, user_input)
pagination = {'current': -1, 'next': 0} if last:
# Default pagination if first opening data.update({'last': True})
data = {'survey': survey, 'page': page, 'page_nr': page_nr, 'token': user_input.token}
if 'current' in post and 'next' in post and post['next'] != "finished": else:
oldnext = int(post['next']) return request.website.render("website.403")
if oldnext not in range(0, len(survey.page_ids)):
raise Exception("This page does not exist")
else:
pagination['current'] = oldnext
if oldnext == len(survey.page_ids) - 1:
pagination['next'] = 'finished'
else:
pagination['next'] = oldnext + 1
return request.website.render('survey.survey',
{'survey': survey,
'pagination': pagination,
'token': user_input.token})
# @website.route(['/survey/prefill/<model("survey.survey"):survey>'], type='json', auth='public', multilang=True): # @website.route(['/survey/prefill/<model("survey.survey"):survey>'], type='json', auth='public', multilang=True):
@ -134,21 +136,30 @@ class WebsiteSurvey(http.Controller):
type='http', auth='public', multilang=True) type='http', auth='public', multilang=True)
def submit(self, survey, **post): def submit(self, survey, **post):
_logger.debug('Incoming data: %s', post) _logger.debug('Incoming data: %s', post)
page_nr = int(post['current']) page_id = int(post['page_id'])
questions = survey.page_ids[page_nr].question_ids cr, uid, context = request.cr, request.uid, request.context
questions_obj = request.registry['survey.question']
questions_ids = questions_obj.search(cr, uid, [('page_id', '=', page_id)],
context=context)
questions = questions_obj.browse(cr, uid, questions_ids, context=context)
errors = {} errors = {}
for question in questions: for question in questions:
answer_tag = "%s_%s_%s" % (survey.id, page_nr, question.id) answer_tag = "%s_%s_%s" % (survey.id, page_id, question.id)
errors.update(self.validate_question(survey.id, page_nr, question, post, answer_tag)) errors.update(self.validate_question(question, post, answer_tag))
ret = {} ret = {}
if (len(errors) != 0): if (len(errors) != 0):
ret['errors'] = errors ret['errors'] = errors
else: else:
cr, uid, context = request.cr, request.uid, request.context cr, uid, context = request.cr, request.uid, request.context
user_input_obj = request.registry['survey.user_input']
try:
user_input_id = user_input_obj.search(cr, uid, [('token', '=', post['token'])])[0]
except IndexError: # Invalid token
return request.website.render("website.403")
# Store here data if allowed # Store here data if allowed
ret['redirect'] = "nexturl" ret['redirect'] = True
return json.dumps(ret) return json.dumps(ret)
# Printing routes # Printing routes
@ -161,9 +172,31 @@ class WebsiteSurvey(http.Controller):
{'survey': survey, {'survey': survey,
'pagination': pagination}) 'pagination': pagination})
# Pagination
def find_next_page(self, survey, user_input):
''' Find the browse record of the first unfilled page '''
if not user_input.user_input_line_ids:
return survey.page_ids[0], 0, len(survey.page_ids) == 1
else:
filled_pages = set()
for user_input_line in user_input.user_input_line_ids:
filled_pages.add(user_input_line.page_id)
last = False
page_nr = 0
nextpage = None
for page in survey.pages_ids:
if page in filled_pages:
page_nr = page_nr + 1
else:
nextpage = page
if page_nr == len(survey.pages_ids):
last = True
return nextpage, page_nr, last
# Validation methods # Validation methods
def validate_question(self, survey_id, page_nr, question, post, answer_tag): def validate_question(self, question, post, answer_tag):
''' Routing to the right question valider, depending on question type ''' ''' Routing to the right question valider, depending on question type '''
try: try:
checker = getattr(self, 'validate_' + question.type) checker = getattr(self, 'validate_' + question.type)
@ -171,9 +204,9 @@ class WebsiteSurvey(http.Controller):
_logger.warning(question.type + ": This type of question has no validation method") _logger.warning(question.type + ": This type of question has no validation method")
return {} return {}
else: else:
return checker(survey_id, page_nr, question, post, answer_tag) return checker(question, post, answer_tag)
def validate_free_text(self, survey_id, page_nr, question, post, answer_tag): def validate_free_text(self, question, post, answer_tag):
errors = {} errors = {}
answer = post[answer_tag].strip() answer = post[answer_tag].strip()
# Empty answer to mandatory question # Empty answer to mandatory question
@ -181,7 +214,7 @@ class WebsiteSurvey(http.Controller):
errors.update({answer_tag: question.constr_error_msg}) errors.update({answer_tag: question.constr_error_msg})
return errors return errors
def validate_textbox(self, survey_id, page_nr, question, post, answer_tag): def validate_textbox(self, question, post, answer_tag):
errors = {} errors = {}
answer = post[answer_tag].strip() answer = post[answer_tag].strip()
# Empty answer to mandatory question # Empty answer to mandatory question
@ -232,7 +265,7 @@ class WebsiteSurvey(http.Controller):
pass pass
return errors return errors
def validate_numerical_box(self, survey_id, page_nr, question, post, answer_tag): def validate_numerical_box(self, question, post, answer_tag):
errors = {} errors = {}
answer = post[answer_tag].strip() answer = post[answer_tag].strip()
# Empty answer to mandatory question # Empty answer to mandatory question
@ -246,7 +279,7 @@ class WebsiteSurvey(http.Controller):
errors.update({answer_tag: question.constr_error_msg}) errors.update({answer_tag: question.constr_error_msg})
return errors return errors
def validate_datetime(self, survey_id, page_nr, question, post, answer_tag): def validate_datetime(self, question, post, answer_tag):
errors = {} errors = {}
answer = post[answer_tag].strip() answer = post[answer_tag].strip()
# Empty answer to mandatory question # Empty answer to mandatory question
@ -256,20 +289,17 @@ class WebsiteSurvey(http.Controller):
# TODO when datepicker will be available # TODO when datepicker will be available
return errors return errors
# def validate_simple_choice(self, survey_id, page_nr, question, post, answer_tag): # def validate_simple_choice(self, question, post, answer_tag):
# answer_tag = survey_id.__str__() + '*' + page_nr + '*' + question.id.__str__()
# problems = [] # problems = []
# if question.constr_mandatory: # if question.constr_mandatory:
# problems = problems + self.__has_empty_input(question, post, answer_tag) # problems = problems + self.__has_empty_input(question, post, answer_tag)
# return problems # return problems
# def validate_multiple_choice(self, survey_id, page_nr, question, post, answer_tag): # def validate_multiple_choice(self, question, post, answer_tag):
# answer_tag = survey_id.__str__() + '*' + page_nr + '*' + question.id.__str__()
# problems = [] # problems = []
# return problems # return problems
# def validate_matrix(self, survey_id, page_nr, question, post, answer_tag): # def validate_matrix(self, question, post, answer_tag):
# answer_tag = survey_id.__str__() + '*' + page_nr + '*' + question.id.__str__()
# problems = [] # problems = []
# return problems # return problems

View File

@ -76,7 +76,7 @@ class survey_survey(osv.osv):
base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, base_url = self.pool.get('ir.config_parameter').get_param(cr, uid,
'web.base.url') 'web.base.url')
for survey_browse in self.browse(cr, uid, ids, context=context): for survey_browse in self.browse(cr, uid, ids, context=context):
res[survey_browse.id] = urljoin(base_url, "survey/fill/%s/" res[survey_browse.id] = urljoin(base_url, "survey/start/%s/"
% survey_browse.id) % survey_browse.id)
return res return res
@ -96,7 +96,7 @@ class survey_survey(osv.osv):
[('draft', 'Draft'), ('open', 'Open'), ('close', 'Closed'), [('draft', 'Draft'), ('open', 'Open'), ('close', 'Closed'),
('cancel', 'Cancelled')], 'Status', required=1, readonly=1, ('cancel', 'Cancelled')], 'Status', required=1, readonly=1,
translate=1), translate=1),
'visible_to_user': fields.boolean('Visible in the Surveys menu', 'visible_to_user': fields.boolean('Public in website',
help="If unchecked, only invited users will be able to open the survey."), help="If unchecked, only invited users will be able to open the survey."),
'auth_required': fields.boolean('Login required', 'auth_required': fields.boolean('Login required',
help="Users with a public link will be requested to login before taking part to the survey", help="Users with a public link will be requested to login before taking part to the survey",
@ -113,7 +113,7 @@ class survey_survey(osv.osv):
'user_input_ids': fields.one2many('survey.user_input', 'survey_id', 'user_input_ids': fields.one2many('survey.user_input', 'survey_id',
'User responses', readonly=1), 'User responses', readonly=1),
'public_url': fields.function(_get_public_url, 'public_url': fields.function(_get_public_url,
string="Public link", searchable=True, type="char", store=True), string="Public link", type="char"),
'email_template_id': fields.many2one('email.template', 'email_template_id': fields.many2one('email.template',
'Email Template', ondelete='set null'), 'Email Template', ondelete='set null'),
'thank_you_message': fields.html('Thank you message', translate=True, 'thank_you_message': fields.html('Thank you message', translate=True,
@ -364,11 +364,15 @@ class survey_question(osv.osv):
'question_id', 'Suggested answers', oldname='answer_choice_ids'), 'question_id', 'Suggested answers', oldname='answer_choice_ids'),
# Display options # Display options
'simple_choice_display': fields.selection([('1col', '1 column choices'), 'column_nb': fields.selection([('12', '1 column choices'),
('2col', '2 columns choices'), ('6', '2 columns choices'),
('3col', '3 columns choices'), ('4', '3 columns choices'),
('horizontal', 'Horizontal choices'), ('3', '4 columns choices'),
('dropdown', 'Dropdown menu')], 'Display mode'), ('2', '6 columns choices')
], 'Number of columns'),
'display_mode': fields.selection([('columns', 'Columns'),
('dropdown', 'Dropdown menu')
], 'Display mode'),
# Comments # Comments
'comments_allowed': fields.boolean('Allow comments', 'comments_allowed': fields.boolean('Allow comments',
@ -417,7 +421,8 @@ class survey_question(osv.osv):
_defaults = { _defaults = {
'page_id': lambda s, cr, uid, c: c.get('page_id'), 'page_id': lambda s, cr, uid, c: c.get('page_id'),
'type': 'free_text', 'type': 'free_text',
'simple_choice_display': '1col', 'column_nb': '12',
'display_mode': 'dropdown',
'constr_type': 'at least', 'constr_type': 'at least',
'constr_minimum_req_ans': 1, 'constr_minimum_req_ans': 1,
'constr_error_msg': lambda s, cr, uid, c: 'constr_error_msg': lambda s, cr, uid, c:
@ -579,9 +584,9 @@ class survey_user_input(osv.osv):
'Answer Type', required=1, oldname="response_type"), 'Answer Type', required=1, oldname="response_type"),
'state': fields.selection([('new', 'Not started yet'), 'state': fields.selection([('new', 'Not started yet'),
('skip', 'Partially completed'), ('skip', 'Partially completed'),
('done', 'Completed'), ('done', 'Completed')], 'Status',
('test', 'Test')], 'Status',
readonly=True), readonly=True),
'test_entry': fields.boolean('Test entry'),
# Optional Identification data # Optional Identification data
'token': fields.char("Identification token", readonly=1), 'token': fields.char("Identification token", readonly=1),
@ -692,19 +697,20 @@ class survey_user_input_line(osv.osv):
_columns = { _columns = {
'user_input_id': fields.many2one('survey.user_input', 'User Input', 'user_input_id': fields.many2one('survey.user_input', 'User Input',
ondelete='cascade', required=1), ondelete='cascade', required=1),
'survey_id': fields.many2one('survey.survey', 'Survey', required=1, 'survey_id': fields.related('user_input_id', 'survey_id',
readonly=1, ondelete='cascade'), type="many2one", relation="survye.survey", string='Survey'),
'date_create': fields.datetime('Create Date', required=1), # drop
'skipped': fields.boolean('Skipped'),
'question_id': fields.many2one('survey.question', 'Question', 'question_id': fields.many2one('survey.question', 'Question',
ondelete='restrict'), ondelete='restrict'),
'page_id': fields.related('question_id', 'page_id', type='many2one',
relation='survey.page', string="Page"),
'date_create': fields.datetime('Create Date', required=1), # drop
'skipped': fields.boolean('Skipped'),
'answer_type': fields.selection([('textbox', 'Text box'), 'answer_type': fields.selection([('textbox', 'Text box'),
('numerical_box', 'Numerical box'), ('numerical_box', 'Numerical box'),
('free_text', 'Free Text'), ('free_text', 'Free Text'),
('datetime', 'Date and Time'), ('datetime', 'Date and Time'),
('checkbox', 'Checkbox'), ('checkbox', 'Checkbox')],
], 'Question Type', required=1), 'Question Type', required=1),
'value_text': fields.char("Text answer"), 'value_text': fields.char("Text answer"),
'value_number': fields.float("Numerical answer"), 'value_number': fields.float("Numerical answer"),
'value_date': fields.datetime("Date answer"), 'value_date': fields.datetime("Date answer"),

View File

@ -423,7 +423,9 @@
<!-- Labels --> <!-- Labels -->
<group colspan="2" string="Choice of answers" attrs="{'invisible':[('type','not in',['simple_choice', 'multiple_choice'])]}"> <group colspan="2" string="Choice of answers" attrs="{'invisible':[('type','not in',['simple_choice', 'multiple_choice'])]}">
<field colspan="2" name="simple_choice_display" string="Display mode" /> <field colspan="2" name="display_mode" string="Display mode" attrs="{'invisible':[('type','not in',['simple_choice'])]}"/>
<field colspan="2" name="column_nb" string="Number of columns" attrs="{'invisible':[('display_mode','=','dropdown'), ('type','=','simple_choice')]}"/>
<field colspan="2" name="labels_ids" nolabel="1" context="{'default_question_id': active_id}"> <field colspan="2" name="labels_ids" nolabel="1" context="{'default_question_id': active_id}">
<tree string="Suggested answers" editable="bottom"> <tree string="Suggested answers" editable="bottom">
<field name="sequence" widget="handle"/> <field name="sequence" widget="handle"/>

View File

@ -1,419 +1,263 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<openerp> <openerp>
<data> <data>
<!-- List of all the surveys --> <!-- List of all the surveys -->
<template id="list" name="Survey List"> <template id="list" name="Survey List">
<t t-call="website.layout"> <t t-call="website.layout">
<div class="wrap"> <div class="wrap">
<div class="container"> <div class="container">
<h1>Open surveys</h1> <h1>Open surveys</h1>
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-hover"> <table class="table table-hover">
<tr><th>Title</th><th>Category</th></tr> <tr><th>Title</th><th>Category</th></tr>
<t t-foreach="surveys" t-as="survey"> <t t-foreach="surveys" t-as="survey">
<tr> <tr>
<td><a t-att-href="survey.public_url"><span t-field="survey.title" /></a></td> <td><a t-att-href="survey.public_url" t-field="survey.title" /></td>
<td><span t-field="survey.category"/></td> <td><span t-field="survey.category"/></td>
</tr> </tr>
</t>
</table>
</div>
</div>
</div>
</t>
</template>
<!-- Thank you message when the survey is completed -->
<template id="finished" name="Survey Finished">
<t t-call="website.layout">
<div class="wrap">
<div class="container">
<div class="jumbotron">
<h1>Thank you!</h1>
<div t-field="survey.thank_you_message" />
</div>
</div>
</div>
</t>
</template>
<!-- Message when the survey is not open -->
<template id="notopen" name="Survey not open">
<t t-call="website.layout">
<div class="wrap">
<div class="container">
<div class="jumbotron">
<h1>Not open</h1>
<p>This survey is not open. Thank you for your interest!</p>
</div>
</div>
</div>
</t>
</template>
<!-- A survey -->
<template id="survey" name="Survey">
<t t-call="website.layout">
<t t-set="head">
<script type="text/javascript" src="/survey/static/src/js/survey.js" />
</t>
<div class="wrap">
<div class="container">
<div class="row">
<div class="col-md-12">
<t t-if="pagination['current'] == -1">
<div class='jumbotron'>
<h1><span t-field='survey.title'/></h1>
<div t-field='survey.description' />
<form role="form" method="post" t-att-name="survey.id.__str__() + '_-1'" t-att-action="'/survey/fill/%s/%s' % (survey.id, token)" target="">
<input type="hidden" name="current" t-att-value="pagination['current'].__str__()" />
<input type="hidden" name="next" t-att-value="pagination['next'].__str__()" />
<input type="submit" class="btn btn-primary btn-lg active" value="Take survey"/>
</form>
</div>
</t>
<t t-if="pagination['current'] != -1">
<t t-set='page' t-value="survey.page_ids[pagination['current']]" />
<t t-call="survey.page" />
</t>
</div>
</div>
</div>
</div>
</t>
</template>
<!-- Navigation & Submission -->
<template id="navsub" name="Footer for navigation and submission">
<div class="text-center">
<t t-if="pagination['current'] != -1 and survey.users_can_go_back"><input type="button" class="btn active survey-btn" value="Previous page"/></t>
<t t-if="pagination['current'] != -1 and pagination['next'] != 'finished'"><input type="submit" class="btn btn-primary active survey-btn" value="Next page"/></t>
<t t-if="pagination['next'] == 'finished'"><input type="submit" class="btn btn-success active survey-btn" value="Submit survey"/></t>
</div>
</template>
<!-- A page -->
<template id="page" name="Page">
<div class="page-header">
<h1><span t-field='page.title' /></h1>
<div t-field='page.description'/>
<progress t-att-value="pagination['current']+1" t-att-max="len(survey.page_ids)"><t t-raw='"Page %s on %s" % (pagination["current"]+1, len(survey.page_ids))' /></progress>
</div>
<form role="form" method="post" class="js_surveyform" t-att-name="survey.id.__str__() + '_' + pagination['current'].__str__()" t-att-action="'/survey/fill/' + survey.id.__str__()" t-att-data-prefill="'/survey/prefill/' + survey.id.__str__()" t-att-data-validate="'/survey/validate/' + survey.id.__str__()" t-att-data-submit="'/survey/submit/' + survey.id.__str__()">
<input type="hidden" name="current" t-att-value="pagination['current'].__str__()" />
<input type="hidden" name="next" t-att-value="pagination['next'].__str__()" />
<t t-foreach='page.question_ids' t-as='question'>
<t t-set="prefix" t-value="'%s_%s_%s' % (survey.id, pagination['current'], question.id)" />
<t t-call='survey.question'/>
</t>
<t t-call='survey.navsub' />
</form>
</template>
<!-- A question -->
<template id='question' name='Question'>
<div class="js_question-wrapper" t-att-id="prefix">
<t t-if="question.type in ['free_text']"><t t-call="survey.free_text"/></t>
<t t-if="question.type in ['textbox']"><t t-call="survey.textbox"/></t>
<t t-if="question.type in ['numerical_box']"><t t-call="survey.numerical_box"/></t>
<t t-if="question.type in ['datetime']"><t t-call="survey.datetime"/></t>
<t t-if="question.type in ['simple_choice']"><t t-call="survey.simple_choice"/></t>
<t t-if="question.type in ['multiple_choice']"><t t-call="survey.multiple_choice"/></t>
<t t-if="question.type in ['matrix']"><t t-call="survey.matrix"/></t>
<div class="js_errzone alert alert-danger" style="display:none;"></div>
</div>
</template>
<!-- Question widgets -->
<template id="free_text" name="Free text box">
<h2><span t-field='question.question' /><t t-if="question.constr_mandatory"><abbr title="This question is mandatory." class="text-danger">*</abbr></t></h2>
<p class="text-muted"><t t-if="question.description"><span t-field='question.description'/></t></p>
<textarea class="form-control" rows="3" t-att-name="prefix"></textarea>
</template>
<template id="textbox" name="Text box">
<h2><span t-field='question.question' /><t t-if="question.constr_mandatory"><abbr title="This question is mandatory." class="text-danger">*</abbr></t></h2>
<p class="text-muted"><t t-if="question.description"><span t-field='question.description'/></t></p>
<input type="text" class="form-control" t-att-name="prefix"/>
</template>
<template id="numerical_box" name="Numerical box">
<h2><span t-field='question.question' /><t t-if="question.constr_mandatory"><abbr title="This question is mandatory." class="text-danger">*</abbr></t></h2>
<p class="text-muted"><t t-if="question.description"><span t-field='question.description'/></t></p>
<input type="number" step=".1" class="form-control" t-att-name="prefix"/>
</template>
<template id="datetime" name="Numerical box">
<h2><span t-field='question.question' /><t t-if="question.constr_mandatory"><abbr title="This question is mandatory." class="text-danger">*</abbr></t></h2>
<p class="text-muted"><t t-if="question.description"><span t-field='question.description'/></t></p>
<input type="datetime-local" class="form-control" t-att-name="prefix" placeholder="jj-mm-aaaa hh:mm" />
</template>
<template id="simple_choice" name="Simple choice">
<h2><span t-field='question.question' /><t t-if="question.constr_mandatory"><abbr title="This question is mandatory." class="text-danger">*</abbr></t></h2>
<p class="text-muted"><t t-if="question.description"><span t-field='question.description'/></t></p>
<t t-if="question.simple_choice_display == 'dropdown'">
<div class="js_drop row">
<div class="col-md-6">
<select class="form-control" t-att-name="prefix">
<option disabled="1" selected="1">Choose...</option>
<t t-foreach='question.labels_ids' t-as='label'>
<option><t t-esc='label.value'/></option>
</t> </t>
<t t-if='question.comments_allowed and question.comment_count_as_answer'> </table>
<option class="js_other_option"><span t-esc="question.children_ids[0].question" /></option>
</t>
</select>
</div> </div>
<div class="col-md-6"> </div>
</div>
</t>
</template>
<!-- Thank you message when the survey is completed -->
<template id="finished" name="Survey Finished">
<t t-call="website.layout">
<div class="wrap">
<div class="container">
<div class="jumbotron">
<h1>Thank you!</h1>
<div t-field="survey.thank_you_message" />
</div>
</div>
</div>
</t>
</template>
<!-- Message when the survey is not open -->
<template id="notopen" name="Survey not open">
<t t-call="website.layout">
<div class="wrap">
<div class="container">
<div class="jumbotron">
<h1>Not open</h1>
<p>This survey is not open. Thank you for your interest!</p>
</div>
</div>
</div>
</t>
</template>
<!-- First page of a survey -->
<template id="survey_init" name="Survey">
<t t-call="website.layout">
<div class="wrap">
<div class="oe_structure" />
<div class="container">
<div class='jumbotron mt32'>
<h1 t-field='survey.title' />
<div t-field='survey.description' />
<a class="btn btn-primary btn-lg" t-att-href="'/survey/fill/%s/%s' % (survey.id, token)">
Start Survey
</a>
</div>
</div>
<div class="oe_structure" />
</div>
</t>
</template>
<!-- A survey -->
<template id="survey" name="Survey">
<t t-call="website.layout">
<t t-set="head">
<script type="text/javascript" src="/survey/static/src/js/survey.js" />
</t>
<div class="wrap">
<div class="oe_structure"/>
<div class="container">
<t t-call="survey.page" />
</div>
<div class="oe_structure"/>
</div>
</t>
</template>
<!-- A page -->
<template id="page" name="Page">
<div class="page-header">
<progress t-att-value="page_nr + 1" t-att-max="len(survey.page_ids)" class="pull-right">
Page <span t-raw='page_nr + 1'/> on <span t-raw="len(survey.page_ids)"/>
</progress>
<h1 t-field='page.title' />
<div t-field='page.description'/>
</div>
<form role="form" method="post" class="js_surveyform" t-att-name="'%s_%s' % (survey.id, page.id)" t-att-action="'/survey/fill/%s/%s' % (survey.id, token)" t-att-data-prefill="'/survey/prefill/%s' % (survey.id)" t-att-data-validate="'/survey/validate/%s' % (survey.id)" t-att-data-submit="'/survey/submit/%s' % (survey.id)">
<input type="hidden" name="page_id" t-att-value="page.id" />
<input type="hidden" name="token" t-att-value="token" />
<t t-foreach='page.question_ids' t-as='question'>
<t t-set="prefix" t-value="'%s_%s_%s' % (survey.id, page.id, question.id)" />
<div class="js_question-wrapper" t-att-id="prefix">
<h2>
<span t-field='question.question' />
<abbr t-if="question.constr_mandatory" title="This question is mandatory." class="text-danger">*</abbr>
</h2>
<p class="text-muted"><t t-if="question.description"><span t-field='question.description'/></t></p>
<t t-if="question.type in ['free_text']"><t t-call="survey.free_text"/></t>
<t t-if="question.type in ['textbox']"><t t-call="survey.textbox"/></t>
<t t-if="question.type in ['numerical_box']"><t t-call="survey.numerical_box"/></t>
<t t-if="question.type in ['datetime']"><t t-call="survey.datetime"/></t>
<t t-if="question.type in ['simple_choice']"><t t-call="survey.simple_choice"/></t>
<t t-if="question.type in ['multiple_choice']"><t t-call="survey.multiple_choice"/></t>
<t t-if="question.type in ['matrix']"><t t-call="survey.matrix"/></t>
<div class="js_errzone alert alert-danger" style="display:none;"></div>
</div>
</t>
<div class="text-center mt16 mb16">
<button t-if="survey.users_can_go_back and page_nr > 0" type="submit" class="btn btn-default">Previous page</button>
<button t-if="not last" type="submit" class="btn btn-primary">Next page</button>
<button type="submit" t-if="last" class="btn btn-primary">Submit survey</button>
</div>
</form>
</template>
<!-- Question widgets -->
<template id="free_text" name="Free text box">
<textarea class="form-control" rows="3" t-att-name="prefix"></textarea>
</template>
<template id="textbox" name="Text box">
<input type="text" class="form-control" t-att-name="prefix"/>
</template>
<template id="numerical_box" name="Numerical box">
<input type="number" step=".1" class="form-control" t-att-name="prefix"/>
</template>
<template id="datetime" name="Datetime box">
<input type="datetime-local" class="form-control" t-att-name="prefix" placeholder="jj-mm-aaaa hh:mm" />
</template>
<template id="simple_choice" name="Simple choice">
<div t-if="question.display_mode == 'dropdown'" class="js_drop row">
<div class="col-md-6">
<select class="form-control" t-att-name="prefix">
<option disabled="1" selected="1">Choose...</option>
<t t-foreach='question.labels_ids' t-as='label'>
<option><t t-esc='label.value'/></option>
</t>
<t t-if='question.comments_allowed and question.comment_count_as_answer'> <t t-if='question.comments_allowed and question.comment_count_as_answer'>
<input type="text" class="form-control" t-att-name="prefix+'_other'" data-oe-survey-othert="1"/> <option class="js_other_option"><span t-esc="question.children_ids[0].question" /></option>
</t> </t>
<t t-if='question.comments_allowed and not question.comment_count_as_answer'> </select>
<div>
<span t-field="question.children_ids[0].question" />
<input type="text" class="form-control" t-att-name="prefix+'_comments'"/>
</div>
</t>
</div>
</div> </div>
</t> <div class="col-md-6">
<t t-if="question.simple_choice_display == 'horizontal'">
<div class="js_radio">
<t t-foreach='question.labels_ids' t-as='label'>
<label class="radio-inline">
<input type="radio" t-att-name="prefix" t-att-value='label.id' />
<span t-field='label.value'/>
</label>
</t>
<t t-if='question.comments_allowed and question.comment_count_as_answer'> <t t-if='question.comments_allowed and question.comment_count_as_answer'>
<div class="input-group input-group-sm js_comments"> <input type="text" class="form-control" t-att-name="prefix+'_other'" data-oe-survey-othert="1"/>
<span class="input-group-addon"><input type="radio" t-att-name="prefix" data-oe-survey-otherr="1"/><span t-field="question.children_ids[0].question" /></span>
<input type="text" class="form-control" t-att-name="prefix" data-oe-survey-othert="1"/>
</div>
</t> </t>
<t t-if='question.comments_allowed and not question.comment_count_as_answer'> <t t-if='question.comments_allowed and not question.comment_count_as_answer'>
<div> <div>
<span t-field="question.children_ids[0].question" /> <span t-field="question.children_ids[0].question" />
<input type="text" class="form-control" t-att-name="prefix+'_comments'" data-oe-survey-othert="1"/> <input type="text" class="form-control" t-att-name="prefix+'_comments'"/>
</div> </div>
</t> </t>
</div> </div>
</t> </div>
<t t-if="question.simple_choice_display == '1col'"> <div t-if="question.display_mode == 'columns' " class="row js_radio">
<div class="js_radio"> <div t-foreach='question.labels_ids' t-as='label' t-attf-class="col-md-#{question.column_nb}">
<t t-foreach='question.labels_ids' t-as='label'> <label>
<div class="radio"> <input type="radio" t-att-name="prefix" t-att-value='label.value' />
<label> <span t-field='label.value'/>
<input type="radio" t-att-name="prefix" t-att-value='label.value' /> </label>
<span t-field='label.value'/> </div>
</label> <div t-if='question.comments_allowed and question.comment_count_as_answer' class="js_comments col-md-12" >
</div> <label>
</t> <input type="radio" t-att-name="prefix" />
<span t-field="question.children_ids[0].question" />
</label>
<input type="text" class="form-control" t-att-name="'%s_%s' % (prefix, question.children_ids[0].id)"/>
</div>
<div t-if='question.comments_allowed and not question.comment_count_as_answer' class="col-md-12">
<span t-field="question.children_ids[0].question"/>
<input type="text" class="form-control" t-att-name="prefix+'_comments'" data-oe-survey-othert="1"/>
</div>
</div>
</template>
<!--
<template id="simple_choice" name="Simple choice">
<t t-if="question.choices_display == 'dropdown'">
<div class="js_drop row">
<div class="col-md-6">
<select class="form-control" t-att-name="prefix">
<option disabled="1" selected="1">Choose...</option>
<t t-foreach='question.labels_ids' t-as='label'>
<option><t t-esc='label.value'/></option>
</t>
<t t-if='question.comments_allowed and question.comment_count_as_answer'>
<option class="js_other_option"><span t-esc="question.children_ids[0].question" /></option>
</t>
</select>
</div>
<div class="col-md-6">
<t t-if='question.comments_allowed and question.comment_count_as_answer'> <t t-if='question.comments_allowed and question.comment_count_as_answer'>
<div class="input-group input-group-sm js_comments"> <input type="text" class="form-control" t-att-name="prefix+'_other'" data-oe-survey-othert="1"/>
<span class="input-group-addon"><input type="radio" t-att-name="prefix" data-oe-survey-otherr="1"/><span t-field="question.children_ids[0].question" /></span>
<input type="text" class="form-control" t-att-name="prefix" data-oe-survey-othert="1"/>
</div>
</t> </t>
<t t-if='question.comments_allowed and not question.comment_count_as_answer'> <t t-if='question.comments_allowed and not question.comment_count_as_answer'>
<div> <div>
<span t-field="question.children_ids[0].question" /> <span t-field="question.children_ids[0].question" />
<input type="text" class="form-control" t-att-name="prefix+'_comments'" data-oe-survey-othert="1"/> <input type="text" class="form-control" t-att-name="prefix+'_comments'"/>
</div> </div>
</t> </t>
</div> </div>
</t> </div>
<t t-if="question.simple_choice_display == '2col'"> </t>
<div class="js_radio"> </template> -->
<template id="multiple_choice" name="Multiple choice">
<div class="row">
<div t-foreach='question.labels_ids' t-as='label' t-attf-class="col-md-#{question.column_nb}">
<label>
<input type="checkbox" t-att-name="'%s_%s' % (prefix, label.id)" t-att-value='label.value' />
<span t-field='label.value'/>
</label>
</div>
<div t-if='question.comments_allowed and question.comment_count_as_answer' class="js_ck_comments col-md-12" >
<label>
<input type="checkbox" t-att-name="prefix + '_other'" />
<span t-field="question.children_ids[0].question" />
</label>
<input type="text" class="form-control" t-att-name="'%s_%s' % (prefix, question.children_ids[0].id)"/>
</div>
<div t-if='question.comments_allowed and not question.comment_count_as_answer' class="col-md-12">
<span t-field="question.children_ids[0].question"/>
<input type="text" class="form-control" t-att-name="prefix+'_comments'" data-oe-survey-othert="1"/>
</div>
</div>
</template>
<!-- Printable view of a survey (all pages) -->
<template id="survey_print" name="Survey">
<t t-call="website.layout">
<div class="wrap">
<div class="container">
<div class="row"> <div class="row">
<t t-foreach='question.labels_ids' t-as='label'> <div class='jumbotron'>
<div class="radio col-md-6"> <h1><span t-field='survey.title'/></h1>
<label> <t t-if="survey.description is not False"><p><span t-field='survey.description'/></p></t>
<input type="radio" t-att-name="prefix" t-att-value='label.value' />
<span t-field='label.value'/>
</label>
</div>
</t>
</div>
<div class="row">
<t t-if='question.comments_allowed and question.comment_count_as_answer'>
<div class="input-group input-group-sm js_comments col-md-6">
<span class="input-group-addon"><input type="radio" t-att-name="prefix" data-oe-survey-otherr="1"/><span t-field="question.children_ids[0].question" /></span>
<input type="text" class="form-control" t-att-name="prefix" data-oe-survey-othert="1"/>
</div>
</t>
<t t-if='question.comments_allowed and not question.comment_count_as_answer'>
<div class="col-md-6">
<span t-field="question.children_ids[0].question" />
<input type="text" class="form-control" t-att-name="prefix+'_comments'" data-oe-survey-othert="1"/>
</div>
</t>
</div>
</div>
</t>
<t t-if="question.simple_choice_display == '3col'">
<div class="js_radio">
<div class="row">
<t t-foreach='question.labels_ids' t-as='label'>
<div class="radio col-md-4">
<label>
<input type="radio" t-att-name="prefix" t-att-value='label.value' />
<span t-field='label.value'/>
</label>
</div>
</t>
</div>
<div class="row">
<t t-if='question.comments_allowed and question.comment_count_as_answer'>
<div class="input-group input-group-sm js_comments col-md-4">
<span class="input-group-addon"><input type="radio" t-att-name="prefix" data-oe-survey-otherr="1"/><span t-field="question.children_ids[0].question" /></span>
<input type="text" class="form-control" t-att-name="prefix" data-oe-survey-othert="1"/>
</div>
</t>
<t t-if='question.comments_allowed and not question.comment_count_as_answer'>
<div class="col-md-4">
<span t-field="question.children_ids[0].question" />
<input type="text" class="form-control" t-att-name="prefix+'_comments'" data-oe-survey-othert="1"/>
</div>
</t>
</div>
</div>
</t>
</template>
<template id="multiple_choice" name="Multiple choice">
<h2><span t-field='question.question' /><t t-if="question.constr_mandatory"><abbr title="This question is mandatory." class="text-danger">*</abbr></t></h2>
<p class="text-muted"><t t-if="question.description"><span t-field='question.description'/></t></p>
<t t-if="question.simple_choice_display == 'horizontal'">
<div>
<t t-foreach='question.labels_ids' t-as='label'>
<label class="checkbox-inline">
<input type="checkbox" t-att-name="prefix + '_' + label.id.__str__()" t-att-value='label.value' />
<span t-field='label.value'/>
</label>
</t>
<div>
<t t-if='question.comments_allowed and question.comment_count_as_answer'>
<div class="input-group input-group-sm col-md-4 js_ck_comments">
<span class="input-group-addon"><input type="checkbox" t-att-name="prefix + '_other'" /> <span t-field="question.children_ids[0].question" /></span>
<input type="text" class="form-control" t-att-name="prefix + '_' + question.children_ids[0].id.__str__()"/>
</div>
</t>
<t t-if='question.comments_allowed and not question.comment_count_as_answer'>
<div class="row">
<span t-field="question.children_ids[0].question" class="col-md-4"/>
<input type="text" class="form-control col-md-4" t-att-name="prefix+'_comments'" data-oe-survey-othert="1"/>
</div>
</t>
</div>
</div>
</t>
<t t-if="question.simple_choice_display == '1col'">
<div>
<t t-foreach='question.labels_ids' t-as='label'>
<div class="checkbox">
<label>
<input type="checkbox" t-att-name="prefix + '_' + label.id.__str__()" t-att-value='label.value' />
<span t-field='label.value'/>
</label>
</div> </div>
</t> <t t-foreach="survey.page_ids" t-as="page">
<div> <t t-call="survey.page" />
<t t-if='question.comments_allowed and question.comment_count_as_answer'> <hr/>
<div class="input-group input-group-sm js_ck_comments">
<span class="input-group-addon"><input type="checkbox" t-att-name="prefix + '_other'" /> <span t-field="question.children_ids[0].question" /></span>
<input type="text" class="form-control" t-att-name="prefix + '_' + question.children_ids[0].id.__str__()"/>
</div>
</t>
<t t-if='question.comments_allowed and not question.comment_count_as_answer'>
<div class="row">
<span t-field="question.children_ids[0].question" class="col-md-4"/>
<input type="text" class="form-control col-md-4" t-att-name="prefix+'_comments'" data-oe-survey-othert="1"/>
</div>
</t> </t>
</div> </div>
</div> </div>
</t> </div>
<t t-if="question.simple_choice_display == '2col'"> </t>
<div class="row"> </template>
<t t-foreach='question.labels_ids' t-as='label'> </data>
<div class="checkbox col-md-6">
<label>
<input type="checkbox" t-att-name="prefix + '_' + label.id.__str__()" t-att-value='label.value' />
<span t-field='label.value'/>
</label>
</div>
</t>
<div>
<t t-if='question.comments_allowed and question.comment_count_as_answer'>
<div class="input-group input-group-sm col-md-6 js_ck_comments">
<span class="input-group-addon"><input type="checkbox" t-att-name="prefix + '_other'" /> <span t-field="question.children_ids[0].question" /></span>
<input type="text" class="form-control" t-att-name="prefix + '_' + question.children_ids[0].id.__str__()"/>
</div>
</t>
<t t-if='question.comments_allowed and not question.comment_count_as_answer'>
<div class="row">
<span t-field="question.children_ids[0].question" class="col-md-4"/>
<input type="text" class="form-control col-md-4" t-att-name="prefix+'_comments'" data-oe-survey-othert="1"/>
</div>
</t>
</div>
</div>
</t>
<t t-if="question.simple_choice_display == '3col'">
<div class="row">
<t t-foreach='question.labels_ids' t-as='label'>
<div class="checkbox col-md-4">
<label>
<input type="checkbox" t-att-name="prefix + '_' + label.id.__str__()" t-att-value='label.value' />
<span t-field='label.value'/>
</label>
</div>
</t>
<div>
<t t-if='question.comments_allowed and question.comment_count_as_answer'>
<div class="input-group input-group-sm col-md-4 js_ck_comments">
<span class="input-group-addon"><input type="checkbox" t-att-name="prefix + '_other'" /> <span t-field="question.children_ids[0].question" /></span>
<input type="text" class="form-control" t-att-name="prefix + '_' + question.children_ids[0].id.__str__()"/>
</div>
</t>
<t t-if='question.comments_allowed and not question.comment_count_as_answer'>
<div class="row">
<span t-field="question.children_ids[0].question" class="col-md-4"/>
<input type="text" class="form-control col-md-4" t-att-name="prefix+'_comments'" data-oe-survey-othert="1"/>
</div>
</t>
</div>
</div>
</t>
</template>
<!-- Printable view of a survey (all pages) -->
<template id="survey_print" name="Survey">
<t t-call="website.layout">
<div class="wrap">
<div class="container">
<div class="row">
<div class='jumbotron'>
<h1><span t-field='survey.title'/></h1>
<t t-if="survey.description is not False"><p><span t-field='survey.description'/></p></t>
</div>
<t t-foreach="survey.page_ids" t-as="page">
<t t-call="survey.page" />
<hr/>
</t>
</div>
</div>
</div>
</t>
</template>
</data>
</openerp> </openerp>