[IMP] survey: improve survey usability in backend
PURPOSE
This commit globally improves the backend survey module usability, notably by
renaming labels, moving menu items around and cleaning unused features.
SPECIFICATIONS
These changes include (non-exhaustive list):
On questions
- Changing labels, action helpers and modules description to be clearer;
- Re-organizing the survey.question form view, notably to clearly distinguish
fields related to answers and validation options;
- Removing the "Clean test answers" server action as it can be done through
a search + unlink;
- Removing the allow_value_image field as we now always display the
image field. Users simply choose to let it blank;
On surveys
- Re-organizing the survey.survey form view fields to get a clear view of
the various options;
- automatically update scoring type when checking certification: if not one
linked to scoring, update to scoring without answers;
- set create as create_multi to speedup batch creation;
- Changes ACL rights for user_input_line. Now, only Survey Managers can
change answers. Survey users keep only a read access on answers, meaning
changing what customers / people answered is now limited to managers;
Globally
- Moving menu items and make them visible outside debug mode;
- Answer recap on print frontend page is now visible whenever a scoring is
applied, not only for certification, as if scoring is activated seeing
answers is probably wanted;
Task-2600241
closes odoo/odoo#79813
Related: odoo/upgrade#3033
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
committed by
Thibault Delavallée
parent
c704b3fb0b
commit
1fb99d79b1
@@ -14,7 +14,7 @@ each question may have multiple answers. Different users may give different
|
||||
answers of question and according to that survey is done. Partners are also
|
||||
sent mails with personal token for the invitation of the survey.
|
||||
""",
|
||||
'summary': 'Create surveys and analyze answers',
|
||||
'summary': 'Send your surveys or share them live.',
|
||||
'website': 'https://www.odoo.com/app/surveys',
|
||||
'depends': [
|
||||
'auth_signup',
|
||||
@@ -26,7 +26,6 @@ sent mails with personal token for the invitation of the survey.
|
||||
'views/survey_report_templates.xml',
|
||||
'views/survey_reports.xml',
|
||||
'data/mail_template_data.xml',
|
||||
'data/ir_actions_data.xml',
|
||||
'security/survey_security.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'views/survey_menus.xml',
|
||||
@@ -96,6 +95,7 @@ sent mails with personal token for the invitation of the survey.
|
||||
'survey/static/src/js/survey_renderers.js',
|
||||
'survey/static/src/js/survey_views.js',
|
||||
'survey/static/src/scss/survey_survey_views.scss',
|
||||
'survey/static/src/scss/survey_question_views.scss',
|
||||
],
|
||||
'web.assets_tests': [
|
||||
'survey/static/tests/**/*',
|
||||
|
||||
@@ -191,7 +191,7 @@ class Survey(http.Controller):
|
||||
values = {'survey': survey, 'answer': answer}
|
||||
if token:
|
||||
values['token'] = token
|
||||
if survey.scoring_type != 'no_scoring' and survey.certification:
|
||||
if survey.scoring_type != 'no_scoring':
|
||||
values['graph_data'] = json.dumps(answer._prepare_statistics()[answer])
|
||||
return values
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<record id="survey_action_server_clean_test_answers" model="ir.actions.server">
|
||||
<field name="name">Survey: Clean test answers</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_survey_survey" />
|
||||
<field name="binding_model_id" ref="model_survey_survey" />
|
||||
<field name="state">code</field>
|
||||
<field name="code">
|
||||
if records:
|
||||
env['survey.user_input'].search([('survey_id', 'in', records.ids), ('test_entry', '=', 'True')]).unlink()
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
@@ -30,7 +30,12 @@
|
||||
<t t-if="object.deadline">
|
||||
Please answer the survey for <t t-out="format_date(object.deadline) or ''">05/05/2021</t>.<br/><br/>
|
||||
</t>
|
||||
Thank you for your participation.
|
||||
<t t-if="object.survey_id.certification">
|
||||
We wish you good luck!
|
||||
</t>
|
||||
<t t-else="">
|
||||
Thank you in advance for your participation.
|
||||
</t>
|
||||
</p>
|
||||
</div>
|
||||
</field>
|
||||
@@ -62,10 +67,11 @@
|
||||
<tr><td style="padding:15px 20px 10px 20px;">
|
||||
<p>Dear <span t-out="object.partner_id.name or 'participant'">participant</span></p>
|
||||
<p>
|
||||
Here is, in attachment, your certification document for
|
||||
<strong t-out="object.survey_id.display_name or ''">Feedback Form</strong>
|
||||
Please find attached your
|
||||
<strong t-out="object.survey_id.display_name or ''">Furniture Creation</strong>
|
||||
certification
|
||||
</p>
|
||||
<p>Congratulations for succeeding the test!</p>
|
||||
<p>Congratulations for passing the test!</p>
|
||||
</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -406,7 +406,6 @@
|
||||
<field name="title">Which painting/drawing was not made by Pablo Picasso ?</field>
|
||||
<field name="question_type">simple_choice</field>
|
||||
<field name="constr_mandatory" eval="True"/>
|
||||
<field name="allow_value_image" eval="True"/>
|
||||
<field name="is_conditional" eval="True"/>
|
||||
<field name="triggering_question_id" ref="survey_demo_burger_quiz_p1_q1"/>
|
||||
<field name="triggering_answer_id" ref="survey_demo_burger_quiz_p1_q1_sug4"/>
|
||||
|
||||
@@ -331,7 +331,6 @@
|
||||
<field name="sequence">31</field>
|
||||
<field name="question_type">simple_choice</field>
|
||||
<field name="column_nb">6</field>
|
||||
<field name="allow_value_image" eval="True"/>
|
||||
<field name="constr_mandatory" eval="True"/>
|
||||
</record>
|
||||
<record id="survey_demo_quiz_p4_q1_sug1" model="survey.question.answer">
|
||||
@@ -367,7 +366,6 @@
|
||||
<field name="sequence">32</field>
|
||||
<field name="question_type">simple_choice</field>
|
||||
<field name="column_nb">6</field>
|
||||
<field name="allow_value_image" eval="True"/>
|
||||
<field name="constr_mandatory" eval="True"/>
|
||||
</record>
|
||||
<record id="survey_demo_quiz_p4_q2_sug1" model="survey.question.answer">
|
||||
@@ -429,7 +427,6 @@
|
||||
<field name="survey_id" ref="survey_demo_quiz"/>
|
||||
<field name="sequence">34</field>
|
||||
<field name="question_type">simple_choice</field>
|
||||
<field name="allow_value_image" eval="True"/>
|
||||
<field name="constr_mandatory" eval="True"/>
|
||||
<field name="description" type="html">
|
||||
<p>
|
||||
@@ -471,7 +468,6 @@
|
||||
<field name="sequence">35</field>
|
||||
<field name="question_type">multiple_choice</field>
|
||||
<field name="column_nb">6</field>
|
||||
<field name="allow_value_image" eval="True"/>
|
||||
<field name="constr_mandatory" eval="True"/>
|
||||
</record>
|
||||
<record id="survey_demo_quiz_p4_q5_sug1" model="survey.question.answer">
|
||||
|
||||
@@ -49,7 +49,7 @@ class SurveyQuestion(models.Model):
|
||||
def default_get(self, fields):
|
||||
defaults = super(SurveyQuestion, self).default_get(fields)
|
||||
if (not fields or 'question_type' in fields):
|
||||
defaults['question_type'] = False if defaults.get('is_page') == True else 'text_box'
|
||||
defaults['question_type'] = False if defaults.get('is_page') else 'simple_choice'
|
||||
return defaults
|
||||
|
||||
# question generic data
|
||||
@@ -70,18 +70,18 @@ class SurveyQuestion(models.Model):
|
||||
related='survey_id.questions_selection', readonly=True,
|
||||
help="If randomized is selected, add the number of random questions next to the section.")
|
||||
random_questions_count = fields.Integer(
|
||||
'Random questions count', default=1,
|
||||
'# Questions Randomly Picked', default=1,
|
||||
help="Used on randomized sections to take X random questions from all the questions of that section.")
|
||||
# question specific
|
||||
page_id = fields.Many2one('survey.question', string='Page', compute="_compute_page_id", store=True)
|
||||
question_type = fields.Selection([
|
||||
('simple_choice', 'Multiple choice: only one answer'),
|
||||
('multiple_choice', 'Multiple choice: multiple answers allowed'),
|
||||
('text_box', 'Multiple Lines Text Box'),
|
||||
('char_box', 'Single Line Text Box'),
|
||||
('numerical_box', 'Numerical Value'),
|
||||
('date', 'Date'),
|
||||
('datetime', 'Datetime'),
|
||||
('simple_choice', 'Multiple choice: only one answer'),
|
||||
('multiple_choice', 'Multiple choice: multiple answers allowed'),
|
||||
('matrix', 'Matrix')], string='Question Type',
|
||||
compute='_compute_question_type', readonly=False, store=True)
|
||||
is_scored_question = fields.Boolean(
|
||||
@@ -104,7 +104,6 @@ class SurveyQuestion(models.Model):
|
||||
suggested_answer_ids = fields.One2many(
|
||||
'survey.question.answer', 'question_id', string='Types of answers', copy=True,
|
||||
help='Labels used for proposed choices: simple choice, multiple choice and columns of matrix')
|
||||
allow_value_image = fields.Boolean('Images on answers', help='Display images in addition to answer label. Valid only for simple / multiple choice questions.')
|
||||
# -- matrix
|
||||
matrix_subtype = fields.Selection([
|
||||
('simple', 'One choice per row'),
|
||||
@@ -125,7 +124,7 @@ class SurveyQuestion(models.Model):
|
||||
comments_message = fields.Char('Comment Message', translate=True, default=lambda self: _("If other, please specify:"))
|
||||
comment_count_as_answer = fields.Boolean('Comment Field is an Answer Choice')
|
||||
# question validation
|
||||
validation_required = fields.Boolean('Validate entry')
|
||||
validation_required = fields.Boolean('Validate entry', compute='_compute_validation_required', readonly=False, store=True)
|
||||
validation_email = fields.Boolean('Input must be an email')
|
||||
validation_length_min = fields.Integer('Minimum Text Length', default=0)
|
||||
validation_length_max = fields.Integer('Maximum Text Length', default=0)
|
||||
@@ -260,6 +259,12 @@ class SurveyQuestion(models.Model):
|
||||
if question.question_type != 'char_box':
|
||||
question.save_as_nickname = False
|
||||
|
||||
@api.depends('question_type')
|
||||
def _compute_validation_required(self):
|
||||
for question in self:
|
||||
if not question.validation_required or question.question_type not in ['char_box', 'numerical_box', 'date', 'datetime']:
|
||||
question.validation_required = False
|
||||
|
||||
@api.depends('is_conditional')
|
||||
def _compute_triggering_question_id(self):
|
||||
""" Used as an 'onchange' : Reset the triggering question if user uncheck 'Conditional Display'
|
||||
@@ -584,13 +589,17 @@ class SurveyQuestionAnswer(models.Model):
|
||||
_order = 'sequence, id'
|
||||
_description = 'Survey Label'
|
||||
|
||||
# question and question related fields
|
||||
question_id = fields.Many2one('survey.question', string='Question', ondelete='cascade')
|
||||
matrix_question_id = fields.Many2one('survey.question', string='Question (as matrix row)', ondelete='cascade')
|
||||
question_type = fields.Selection(related='question_id.question_type')
|
||||
sequence = fields.Integer('Label Sequence order', default=10)
|
||||
scoring_type = fields.Selection(related='question_id.scoring_type')
|
||||
# answer related fields
|
||||
value = fields.Char('Suggested value', translate=True, required=True)
|
||||
value_image = fields.Image('Image', max_width=256, max_height=256)
|
||||
is_correct = fields.Boolean('Is a correct answer')
|
||||
answer_score = fields.Float('Score for this choice', help="A positive score indicates a correct choice; a negative or null score indicates a wrong answer")
|
||||
is_correct = fields.Boolean('Correct')
|
||||
answer_score = fields.Float('Score', help="A positive score indicates a correct choice; a negative or null score indicates a wrong answer")
|
||||
|
||||
@api.constrains('question_id', 'matrix_question_id')
|
||||
def _check_question_not_empty(self):
|
||||
|
||||
@@ -70,15 +70,15 @@ class Survey(models.Model):
|
||||
('one_page', 'One page with all the questions'),
|
||||
('page_per_section', 'One page per section'),
|
||||
('page_per_question', 'One page per question')],
|
||||
string="Layout", required=True, default='one_page')
|
||||
string="Pagination", required=True, default='one_page')
|
||||
questions_selection = fields.Selection([
|
||||
('all', 'All questions'),
|
||||
('random', 'Randomized per section')],
|
||||
string="Selection", required=True, default='all',
|
||||
('random', 'Randomized per Section')],
|
||||
string="Question Selection", required=True, default='all',
|
||||
help="If randomized is selected, you can configure the number of random questions by section. This mode is ignored in live session.")
|
||||
progression_mode = fields.Selection([
|
||||
('percent', 'Percentage'),
|
||||
('number', 'Number')], string='Progression Mode', default='percent',
|
||||
('percent', 'Percentage left'),
|
||||
('number', 'Number')], string='Display Progress as', default='percent',
|
||||
help="If Number is selected, it will display the number of questions answered on the total number of question to answer.")
|
||||
# attendees
|
||||
user_input_ids = fields.One2many('survey.user_input', 'survey_id', string='User responses', readonly=True, groups='survey.group_survey_user')
|
||||
@@ -88,23 +88,23 @@ class Survey(models.Model):
|
||||
('token', 'Invited people only')], string='Access Mode',
|
||||
default='public', required=True)
|
||||
access_token = fields.Char('Access Token', default=lambda self: self._get_default_access_token(), copy=False)
|
||||
users_login_required = fields.Boolean('Login Required', help="If checked, users have to login before answering even with a valid token.")
|
||||
users_login_required = fields.Boolean('Require Login', help="If checked, users have to login before answering even with a valid token.")
|
||||
users_can_go_back = fields.Boolean('Users can go back', help="If checked, users can go back to previous pages.")
|
||||
users_can_signup = fields.Boolean('Users can signup', compute='_compute_users_can_signup')
|
||||
# statistics
|
||||
answer_count = fields.Integer("Registered", compute="_compute_survey_statistic")
|
||||
answer_done_count = fields.Integer("Attempts", compute="_compute_survey_statistic")
|
||||
answer_score_avg = fields.Float("Avg Score %", compute="_compute_survey_statistic")
|
||||
answer_score_avg = fields.Float("Avg Score (%)", compute="_compute_survey_statistic")
|
||||
answer_duration_avg = fields.Float("Average Duration", compute="_compute_answer_duration_avg", help="Average duration of the survey (in hours)")
|
||||
success_count = fields.Integer("Success", compute="_compute_survey_statistic")
|
||||
success_ratio = fields.Integer("Success Ratio", compute="_compute_survey_statistic")
|
||||
success_ratio = fields.Integer("Success Ratio (%)", compute="_compute_survey_statistic")
|
||||
# scoring
|
||||
scoring_type = fields.Selection([
|
||||
('no_scoring', 'No scoring'),
|
||||
('scoring_with_answers', 'Scoring with answers at the end'),
|
||||
('scoring_without_answers', 'Scoring without answers at the end')],
|
||||
string="Scoring", required=True, default='no_scoring')
|
||||
scoring_success_min = fields.Float('Success %', default=80.0)
|
||||
string="Scoring", required=True, store=True, readonly=False, compute="_compute_scoring_type", precompute=True)
|
||||
scoring_success_min = fields.Float('Required Score (%)', default=80.0)
|
||||
# attendees context: attempts and time limitation
|
||||
is_attempts_limited = fields.Boolean('Limited number of attempts', help="Check this option if you want to limit the number of attempts per user",
|
||||
compute="_compute_is_attempts_limited", store=True, readonly=False)
|
||||
@@ -113,9 +113,9 @@ class Survey(models.Model):
|
||||
time_limit = fields.Float("Time limit (minutes)", default=10)
|
||||
# certification
|
||||
certification = fields.Boolean('Is a Certification', compute='_compute_certification',
|
||||
readonly=False, store=True)
|
||||
readonly=False, store=True, precompute=True)
|
||||
certification_mail_template_id = fields.Many2one(
|
||||
'mail.template', 'Email Template',
|
||||
'mail.template', 'Certified Email Template',
|
||||
domain="[('model', '=', 'survey.user_input')]",
|
||||
help="Automated email sent to the user when he succeeds the certification, containing his certification document.")
|
||||
certification_report_layout = fields.Selection([
|
||||
@@ -324,16 +324,24 @@ class Survey(models.Model):
|
||||
not survey.certification:
|
||||
survey.certification_give_badge = False
|
||||
|
||||
@api.depends('certification')
|
||||
def _compute_scoring_type(self):
|
||||
for survey in self:
|
||||
if survey.certification and survey.scoring_type not in ['scoring_without_answers', 'scoring_with_answers']:
|
||||
survey.scoring_type = 'scoring_without_answers'
|
||||
elif not survey.scoring_type:
|
||||
survey.scoring_type = 'no_scoring'
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# CRUD
|
||||
# ------------------------------------------------------------
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
survey = super(Survey, self).create(vals)
|
||||
if vals.get('certification_give_badge'):
|
||||
survey.sudo()._create_certification_badge_trigger()
|
||||
return survey
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
surveys = super(Survey, self).create(vals_list)
|
||||
for survey_sudo in surveys.filtered(lambda survey: survey.certification_give_badge).sudo():
|
||||
survey_sudo._create_certification_badge_trigger()
|
||||
return surveys
|
||||
|
||||
def write(self, vals):
|
||||
result = super(Survey, self).write(vals)
|
||||
|
||||
@@ -17,7 +17,7 @@ access_survey_user_input_survey_user,survey.user_input.survey.user,model_survey_
|
||||
access_survey_user_input_survey_manager,survey.user_input.survey.manager,model_survey_user_input,group_survey_manager,1,1,1,1
|
||||
access_survey_user_input_line_all,survey.user_input.line.all,model_survey_user_input_line,,0,0,0,0
|
||||
access_survey_user_input_line_user,survey.user_input.line.user,model_survey_user_input_line,base.group_user,0,0,0,0
|
||||
access_survey_user_input_line_survey_user,survey.user_input.line.survey.user,model_survey_user_input_line,group_survey_user,1,1,1,1
|
||||
access_survey_user_input_line_survey_user,survey.user_input.line.survey.user,model_survey_user_input_line,group_survey_user,1,0,0,0
|
||||
access_survey_user_input_line_survey_manager,survey.user_input.line.survey.manager,model_survey_user_input_line,group_survey_manager,1,1,1,1
|
||||
access_gamification_badge_survey_user,gamification.badge.survey.user,model_gamification_badge,group_survey_user,1,1,1,1
|
||||
access_survey_invite,access.survey.invite,model_survey_invite,survey.group_survey_user,1,1,1,0
|
||||
|
||||
|
@@ -54,24 +54,3 @@
|
||||
width: 1150px;
|
||||
}
|
||||
}
|
||||
|
||||
.o_preview_questions {
|
||||
border: 3px solid #C9C6C6;
|
||||
width: auto;
|
||||
padding: 10px 30px 5px;
|
||||
margin-top: 15px;
|
||||
color: #C9C6C6;
|
||||
}
|
||||
|
||||
.o_preview_questions .o_datetime {
|
||||
border: 1px solid #D8D7D7;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.o_preview_questions .o_matrix_head {
|
||||
border-bottom: 1px solid #D8D7D7;
|
||||
}
|
||||
|
||||
.o_preview_questions .o_matrix_row {
|
||||
border-top: 1px solid #D8D7D7;
|
||||
}
|
||||
|
||||
@@ -51,7 +51,11 @@ var SectionListRenderer = ListRenderer.extend({
|
||||
if (record.data.questions_selection === "random") {
|
||||
nbrColumns--;
|
||||
}
|
||||
// Render empty cells for buttons to avoid having unaligned elements
|
||||
nbrColumns -= this.columns.filter(elem => elem.tag === "button_group").length;
|
||||
$cell.attr('colspan', nbrColumns);
|
||||
} else if (node.tag === "button_group") {
|
||||
$cell.addClass('o_invisible_modifier');
|
||||
} else {
|
||||
$cell.removeClass('o_invisible_modifier');
|
||||
return $cell.addClass('o_hidden');
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
.o_survey_question_view_form {
|
||||
|
||||
.o_preview_questions {
|
||||
border: 3px solid #C9C6C6;
|
||||
width: auto;
|
||||
padding: 10px 20px 10px;
|
||||
margin-top: 15px;
|
||||
color: #C9C6C6;
|
||||
}
|
||||
|
||||
.o_preview_questions .o_datetime {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.o_preview_questions .o_matrix_head {
|
||||
border-bottom: 1px solid #D8D7D7;
|
||||
}
|
||||
|
||||
.o_preview_questions .o_matrix_row {
|
||||
border-top: 1px solid #D8D7D7;
|
||||
}
|
||||
|
||||
.o_preview_questions_choice {
|
||||
line-height: 1rem;
|
||||
}
|
||||
}
|
||||
@@ -85,7 +85,7 @@ class TestCertificationFlow(common.TestSurveyCommon, HttpCase):
|
||||
|
||||
# Employee opens start page
|
||||
response = self._access_start(certification)
|
||||
self.assertResponse(response, 200, [certification.title, 'Time limit for this survey', '10 minutes'])
|
||||
self.assertResponse(response, 200, [certification.title, 'Time limit for this certification', '10 minutes'])
|
||||
|
||||
# -> this should have generated a new user_input with a token
|
||||
user_inputs = self.env['survey.user_input'].search([('survey_id', '=', certification.id)])
|
||||
|
||||
@@ -256,19 +256,19 @@ class TestAccess(common.TestSurveyCommon):
|
||||
|
||||
# Create: own survey only
|
||||
answer_own = self.env['survey.user_input'].create({'survey_id': survey_own.id})
|
||||
answer_line_own = self.env['survey.user_input.line'].create({'question_id': question_own.id, 'answer_type': 'numerical_box', 'value_numerical_box': 3, 'user_input_id': answer_own.id})
|
||||
with self.assertRaises(AccessError):
|
||||
self.env['survey.user_input.line'].create({'question_id': question_own.id, 'answer_type': 'numerical_box', 'value_numerical_box': 3, 'user_input_id': answer_own.id})
|
||||
|
||||
# Read: always
|
||||
answers = self.env['survey.user_input'].search([('survey_id', 'in', [survey_own.id, self.survey.id])])
|
||||
self.assertEqual(answers, answer_own | self.answer_0)
|
||||
|
||||
answer_lines = self.env['survey.user_input.line'].search([('survey_id', 'in', [survey_own.id, self.survey.id])])
|
||||
self.assertEqual(answer_lines, answer_line_own | self.answer_0_0 | self.answer_0_1)
|
||||
self.assertEqual(answer_lines, self.answer_0_0 | self.answer_0_1)
|
||||
|
||||
self.env['survey.user_input'].browse(answer_own.ids).read(['state'])
|
||||
self.env['survey.user_input'].browse(self.answer_0.ids).read(['state'])
|
||||
|
||||
self.env['survey.user_input.line'].browse(answer_line_own.ids).read(['value_numerical_box'])
|
||||
self.env['survey.user_input.line'].browse(self.answer_0_0.ids).read(['value_numerical_box'])
|
||||
|
||||
# Create: own survey only (moved after read because DB not correctly rollbacked with assertRaises)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<record id="res_partner_action_certifications" model="ir.actions.act_window">
|
||||
<field name="name">Certifications Succeeded</field>
|
||||
<field name="res_model">survey.user_input</field>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="context">{'search_default_scoring_success': 1}</field>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -9,14 +9,9 @@
|
||||
web_icon="survey,static/description/icon.png"/>
|
||||
|
||||
<!-- Parent menus -->
|
||||
<menuitem name="Questions"
|
||||
<menuitem name="Questions & Answers"
|
||||
id="survey_menu_questions"
|
||||
parent="menu_surveys"
|
||||
groups="base.group_no_one"
|
||||
sequence="80"/>
|
||||
<menuitem name="Participations"
|
||||
id="survey_menu_user_inputs"
|
||||
parent="menu_surveys"
|
||||
sequence="90"/>
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<field name="name">Form view for survey question</field>
|
||||
<field name="model">survey.question</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Survey Question" create="false">
|
||||
<form string="Survey Question" create="false" class="o_survey_question_view_form">
|
||||
<field name="is_page" invisible="1"/>
|
||||
<field name="page_id" invisible="1" required="False"/>
|
||||
<field name="survey_id" invisible="1"/>
|
||||
@@ -20,9 +20,7 @@
|
||||
<div class="oe_title" style="width: 100%;">
|
||||
<label for="title" string="Section" attrs="{'invisible': [('is_page', '=', False)]}"/>
|
||||
<label for="title" string="Question" attrs="{'invisible': [('is_page', '=', True)]}"/>
|
||||
<separator />
|
||||
<field name="title" colspan="4"/>
|
||||
<separator />
|
||||
<field name="title" placeholder="e.g. "What is the..."" colspan="4"/>
|
||||
<field name="questions_selection" invisible="1"/>
|
||||
</div>
|
||||
<group class="o_label_nowrap" attrs="{'invisible': ['|', ('is_page', '=', False), ('questions_selection', '=', 'all')]}">
|
||||
@@ -33,43 +31,53 @@
|
||||
<field name="question_type" widget="radio" attrs="{'required': [('is_page', '=', False)]}" />
|
||||
</group>
|
||||
<group>
|
||||
<div class="col-lg-6 offset-lg-3 o_preview_questions">
|
||||
<div class="col-lg-6 offset-lg-3 w-100 o_preview_questions">
|
||||
<!-- Multiple choice: only one answer -->
|
||||
<div attrs="{'invisible': [('question_type', '!=', 'simple_choice')]}" role="img" aria-label="Multiple choice with one answer"
|
||||
title="Multiple choice with one answer">
|
||||
<span>Which is yellow?</span><br/>
|
||||
<div class="row o_preview_questions_choice mb-2"><i class="fa fa-circle-o fa-lg mr-2"/>answer</div>
|
||||
<div class="row o_preview_questions_choice mb-2"><i class="fa fa-dot-circle-o fa-lg mr-2"/>answer</div>
|
||||
<div class="row o_preview_questions_choice"><i class="fa fa-circle-o fa-lg mr-2"/>answer</div>
|
||||
</div>
|
||||
<!-- Multiple choice: multiple answers allowed -->
|
||||
<div attrs="{'invisible': [('question_type', '!=', 'multiple_choice')]}" role="img" aria-label="Multiple choice with multiple answers"
|
||||
title="Multiple choice with multiple answers">
|
||||
<span>Which are yellow?</span><br/>
|
||||
<div class="row o_preview_questions_choice mb-2"><i class="fa fa-square-o fa-lg mr-2"/>answer</div>
|
||||
<div class="row o_preview_questions_choice mb-2"><i class="fa fa-check-square-o fa-lg mr-2"/>answer</div>
|
||||
<div class="row o_preview_questions_choice"><i class="fa fa-square-o fa-lg mr-2"/>answer</div>
|
||||
</div>
|
||||
<!-- Multiple Lines Text Zone -->
|
||||
<div attrs="{'invisible': [('question_type', '!=', 'text_box')]}">
|
||||
<i class="fa fa-align-justify fa-4x" role="img" aria-label="Multiple lines" title="Multiple Lines"/>
|
||||
<span>Name all the animals</span><br/>
|
||||
<i class="fa fa-align-justify fa-4x" role="img" aria-label="Multiple lines" title="Multiple Lines"/>
|
||||
</div>
|
||||
<!-- Single Line Text Zone -->
|
||||
<div attrs="{'invisible': [('question_type', '!=', 'char_box')]}">
|
||||
<span>Name one animal</span><br/>
|
||||
<i class="fa fa-minus fa-4x" role="img" aria-label="Single Line" title="Single Line"/>
|
||||
</div>
|
||||
<!-- Numerical Value -->
|
||||
<div attrs="{'invisible': [('question_type', '!=', 'numerical_box')]}">
|
||||
<i class="fa fa-2x" role="img" aria-label="Numeric" title="Numeric">123..</i>
|
||||
<span>How many ...?</span><br/>
|
||||
<i class="fa fa-2x" role="img" aria-label="Numeric" title="Numeric">123 </i>
|
||||
<i class="fa fa-2x fa-sort" role="img" aria-label="Numeric"/>
|
||||
</div>
|
||||
<!-- Date -->
|
||||
<div attrs="{'invisible': [('question_type', '!=', 'date')]}">
|
||||
<p class="o_datetime">YYYY-MM-DD
|
||||
<i class="fa fa-calendar fa-2x" role="img" aria-label="Calendar" title="Calendar"/>
|
||||
<span>When is Christmas?</span><br/>
|
||||
<p class="o_datetime border-0" >YYYY-MM-DD
|
||||
<i class="fa fa-calendar" role="img" aria-label="Calendar" title="Calendar"/>
|
||||
</p>
|
||||
</div>
|
||||
<!-- Date and Time -->
|
||||
<div attrs="{'invisible': [('question_type', '!=', 'datetime')]}">
|
||||
<p class="o_datetime">YYYY-MM-DD hh:mm:ss
|
||||
<i class="fa fa-calendar fa-2x" role="img" aria-label="Calendar" title="Calendar"/>
|
||||
<span>When does ... start?</span><br/>
|
||||
<p class="o_datetime border-0">YYYY-MM-DD hh:mm:ss
|
||||
<i class="fa fa-calendar" role="img" aria-label="Calendar" title="Calendar"/>
|
||||
</p>
|
||||
</div>
|
||||
<!-- Multiple choice: only one answer -->
|
||||
<div attrs="{'invisible': [('question_type', '!=', 'simple_choice')]}" role="img" aria-label="Multiple choice with one answer" title="Multiple choice with one answer">
|
||||
<div class="row"><i class="fa fa-circle-o fa-lg"/> answer</div>
|
||||
<div class="row"><i class="fa fa-dot-circle-o fa-lg"/> answer</div>
|
||||
<div class="row"><i class="fa fa-circle-o fa-lg"/> answer</div>
|
||||
</div>
|
||||
<!-- Multiple choice: multiple answers allowed -->
|
||||
<div attrs="{'invisible': [('question_type', '!=', 'multiple_choice')]}" role="img" aria-label="Multiple choice with multiple answers" title="Multiple choice with multiple answers">
|
||||
<div class="row"><i class="fa fa-square-o fa-lg"/> answer</div>
|
||||
<div class="row"><i class="fa fa-check-square-o fa-lg"/> answer</div>
|
||||
<div class="row"><i class="fa fa-square-o fa-lg"/> answer</div>
|
||||
</div>
|
||||
<!-- Matrix -->
|
||||
<div attrs="{'invisible': [('question_type', '!=', 'matrix')]}">
|
||||
<div class="row o_matrix_head">
|
||||
@@ -101,65 +109,46 @@
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Answers" name="answers" attrs="{'invisible': [('is_page', '=', True)]}">
|
||||
<div class="row">
|
||||
<div class="col-6"
|
||||
attrs="{'invisible': [('question_type', 'not in', ['char_box', 'numerical_box', 'date', 'datetime'])]}">
|
||||
<div attrs="{'invisible': [('question_type', '!=', 'char_box')]}">
|
||||
<field name="validation_email" nolabel="1"/>
|
||||
<label for="validation_email"/><br />
|
||||
<page string="Answers" name="answers" attrs="{'invisible': ['|', ('is_page', '=', True), ('question_type', '=', 'text_box')]}">
|
||||
<group>
|
||||
<group attrs="{'invisible': [('question_type', 'not in', ['char_box', 'numerical_box', 'date', 'datetime'])]}">
|
||||
<field name="answer_numerical_box" string="Correct Answer"
|
||||
attrs="{'invisible': [('question_type', '!=', 'numerical_box')]}" class="oe_inline"/>
|
||||
<field name="answer_date" string="Correct Answer"
|
||||
attrs="{'invisible': [('question_type', '!=', 'date')]}" class="oe_inline"/>
|
||||
<field name="answer_datetime" string="Correct Answer"
|
||||
attrs="{'invisible': [('question_type', '!=', 'datetime')]}" class="oe_inline"/>
|
||||
|
||||
<field name="save_as_email" nolabel="1" attrs="{'invisible': [('validation_email', '=', False)]}"/>
|
||||
<label for="save_as_email" attrs="{'invisible': [('validation_email', '=', False)]}"/>
|
||||
<br attrs="{'invisible': [('validation_email', '=', False)]}"/>
|
||||
<field name="validation_email" attrs="{'invisible': [('question_type', '!=', 'char_box')]}"/>
|
||||
<field name="save_as_email" attrs="{'invisible': ['|', ('validation_email', '=', False), ('question_type', '!=', 'char_box')]}"/>
|
||||
<field name="save_as_nickname" attrs="{'invisible': [('question_type', '!=', 'char_box')]}"/>
|
||||
</group>
|
||||
|
||||
<field name="save_as_nickname" nolabel="1"/>
|
||||
<label for="save_as_nickname"/>
|
||||
</div>
|
||||
<div>
|
||||
<field name="validation_required" nolabel="1"/>
|
||||
<label for="validation_required"/>
|
||||
<group attrs="{'invisible': [('validation_required', '=', False)]}">
|
||||
<field name="validation_length_min" attrs="{'invisible': [('question_type', '!=', 'char_box')]}"/>
|
||||
<field name="validation_length_max" attrs="{'invisible': [('question_type', '!=', 'char_box')]}"/>
|
||||
<field name="validation_min_float_value" attrs="{'invisible': [('question_type', '!=', 'numerical_box')]}"/>
|
||||
<field name="validation_max_float_value" attrs="{'invisible': [('question_type', '!=', 'numerical_box')]}"/>
|
||||
<field name="validation_min_date" attrs="{'invisible': [('question_type', '!=', 'date')]}"/>
|
||||
<field name="validation_max_date" attrs="{'invisible': [('question_type', '!=', 'date')]}"/>
|
||||
<field name="validation_min_datetime" widget="datetime" attrs="{'invisible': [('question_type', '!=', 'datetime')]}"/>
|
||||
<field name="validation_max_datetime" widget="datetime" attrs="{'invisible': [('question_type', '!=', 'datetime')]}"/>
|
||||
<field name="validation_error_msg" attrs="{'required': [('validation_required', '=', True)]}"/>
|
||||
</group>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6" attrs="{'invisible': [
|
||||
'|', ('scoring_type', '=', 'no_scoring'),
|
||||
('question_type', 'not in', ['numerical_box', 'date', 'datetime'])]
|
||||
}">
|
||||
<group>
|
||||
<field name="answer_numerical_box" string="Correct Answer" attrs="{'invisible': [('question_type', '!=', 'numerical_box')]}"/>
|
||||
<field name="answer_date" string="Correct Answer" attrs="{'invisible': [('question_type', '!=', 'date')]}"/>
|
||||
<field name="answer_datetime" string="Correct Answer" attrs="{'invisible': [('question_type', '!=', 'datetime')]}"/>
|
||||
<field name="is_scored_question"/>
|
||||
<field name="answer_score"/>
|
||||
</group>
|
||||
</div>
|
||||
</div>
|
||||
<group attrs="{'invisible': ['|', ('scoring_type', '=', 'no_scoring'), ('question_type', 'not in', ['numerical_box', 'date', 'datetime'])]}">
|
||||
<label for="is_scored_question"/>
|
||||
<field name="is_scored_question"/>
|
||||
<field name="answer_score" nolabel="1" class="oe_inline" attrs="{'invisible': [('is_scored_question', '=', False)]}"/>
|
||||
<span class="oe_inline" attrs="{'invisible': [('is_scored_question', '=', False)]}">Points</span>
|
||||
</group>
|
||||
</group>
|
||||
<group attrs="{'invisible': [('question_type', 'not in', ['simple_choice', 'multiple_choice', 'matrix'])]}">
|
||||
<field name="suggested_answer_ids" string="Answers" context="{'default_question_id': active_id}">
|
||||
<field name="suggested_answer_ids" context="{'default_question_id': active_id}" nolabel="1">
|
||||
<tree editable="bottom">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="value" string="Choices"/>
|
||||
<field name="is_correct"
|
||||
attrs="{'column_invisible': ['|', ('parent.scoring_type', '=', 'no_scoring'), ('parent.question_type', '=', 'matrix')]}"/>
|
||||
<field name="answer_score"
|
||||
attrs="{'column_invisible': ['|', ('parent.scoring_type', '=', 'no_scoring'), ('parent.question_type', '=', 'matrix')]}"/>
|
||||
<field name="value_image" options="{'accepted_file_extensions': 'image/*'}"
|
||||
attrs="{'column_invisible': ['|', ('parent.allow_value_image', '=', False), ('parent.question_type', '=', 'matrix')]}"/>
|
||||
<field name="is_correct" attrs="{'column_invisible': ['|', ('parent.scoring_type', '=', 'no_scoring'), ('parent.question_type', '=', 'matrix')]}"/>
|
||||
<field name="answer_score" attrs="{'column_invisible': ['|', ('parent.scoring_type', '=', 'no_scoring'), ('parent.question_type', '=', 'matrix')]}"/>
|
||||
attrs="{'column_invisible': [('parent.question_type', '=', 'matrix')]}"/>
|
||||
</tree>
|
||||
</field>
|
||||
</group>
|
||||
|
||||
<group attrs="{'invisible': [('question_type', '!=', 'matrix')]}">
|
||||
<field name="matrix_row_ids" context="{'default_matrix_question_id': active_id}" attrs="{'invisible': [('question_type', '!=', 'matrix')]}">
|
||||
<field name="matrix_row_ids" context="{'default_matrix_question_id': active_id}"
|
||||
attrs="{'invisible': [('question_type', '!=', 'matrix')]}" nolabel="1">
|
||||
<tree editable="bottom">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="value" string="Rows"/>
|
||||
@@ -171,40 +160,63 @@
|
||||
<field name="description" widget="html"/>
|
||||
</page>
|
||||
<page string="Options" name="options" attrs="{'invisible': [('is_page', '=', True)]}">
|
||||
<group string="Constraints">
|
||||
<group>
|
||||
<field name="constr_mandatory" string="Mandatory Answer"/>
|
||||
<field name="constr_error_msg" attrs="{'invisible': [('constr_mandatory', '=', False)]}"/>
|
||||
<group>
|
||||
<group string="Answers">
|
||||
<!-- Global validation setting -->
|
||||
<field name="validation_required"
|
||||
attrs="{'invisible': [('question_type', 'not in', ['char_box', 'numerical_box', 'date', 'datetime'])]}"/>
|
||||
<!-- Char -->
|
||||
<field name="validation_length_min" attrs="{'invisible': ['|', ('question_type', '!=', 'char_box'), ('validation_required', '=', False)]}"/>
|
||||
<field name="validation_length_max" attrs="{'invisible': ['|', ('question_type', '!=', 'char_box'), ('validation_required', '=', False)]}"/>
|
||||
<!-- Numerical -->
|
||||
<field name="validation_min_float_value"
|
||||
attrs="{'invisible': ['|', ('question_type', '!=', 'numerical_box'), ('validation_required', '=', False)]}"/>
|
||||
<field name="validation_max_float_value"
|
||||
attrs="{'invisible': ['|', ('question_type', '!=', 'numerical_box'), ('validation_required', '=', False)]}"/>
|
||||
<!-- Date and datetime -->
|
||||
<field name="validation_min_date" attrs="{'invisible': ['|', ('question_type', '!=', 'date'), ('validation_required', '=', False)]}"/>
|
||||
<field name="validation_max_date" attrs="{'invisible': ['|', ('question_type', '!=', 'date'), ('validation_required', '=', False)]}"/>
|
||||
<field name="validation_min_datetime" widget="datetime"
|
||||
attrs="{'invisible': ['|', ('question_type', '!=', 'datetime'), ('validation_required', '=', False)]}"/>
|
||||
<field name="validation_max_datetime" widget="datetime"
|
||||
attrs="{'invisible': ['|', ('question_type', '!=', 'datetime'), ('validation_required', '=', False)]}"/>
|
||||
|
||||
<field name="validation_error_msg" attrs="{
|
||||
'required': [('validation_required', '=', True)],
|
||||
'invisible': [('validation_required', '=', False)]}"/>
|
||||
|
||||
<field name="column_nb" string="Number of columns" attrs="{'invisible':[('question_type','not in',['simple_choice', 'multiple_choice'])]}"/>
|
||||
<field name="matrix_subtype" attrs="{'invisible':[('question_type','not in',['matrix'])],'required':[('question_type','=','matrix')]}"/>
|
||||
<field name="question_placeholder"
|
||||
attrs="{'invisible': [('question_type', 'not in', ['text_box', 'char_box', 'date', 'datetime', 'numerical_box'])]}"
|
||||
placeholder="Help Participants know what to write"/>
|
||||
</group>
|
||||
<group string="Layout">
|
||||
<field name="is_conditional" attrs="{'invisible': [('questions_selection', '=', 'random')]}"/>
|
||||
<field name="triggering_question_id" options="{'no_open': True, 'no_create': True}"
|
||||
attrs="{'invisible': [('is_conditional','=', False)], 'required': [('is_conditional','=', True)]}"/>
|
||||
<field name="triggering_answer_id" options="{'no_open': True, 'no_create': True}"
|
||||
attrs="{'invisible': ['|', ('is_conditional','=', False), ('triggering_question_id','=', False)],
|
||||
'required': [('is_conditional','=', True)]}"/>
|
||||
<field name='comments_allowed' attrs="{'invisible':[('question_type','not in',['simple_choice','multiple_choice', 'matrix'])]}"/>
|
||||
<field name='comments_message'
|
||||
attrs="{'invisible': ['|', ('question_type', 'not in', ['simple_choice','multiple_choice', 'matrix']), ('comments_allowed', '=', False)]}"/>
|
||||
</group>
|
||||
</group>
|
||||
<group string="Display" attrs="{'invisible':[('question_type','=', 'matrix')]}">
|
||||
<field name="question_placeholder" attrs="{'invisible': [('question_type', 'not in', ['text_box', 'char_box', 'date', 'datetime', 'numerical_box'])]}"
|
||||
placeholder="When set, this text will appear in the field to help participants answer."/>
|
||||
<field name="column_nb" string="Number of columns" attrs="{'invisible':[('question_type','not in',['simple_choice', 'multiple_choice'])]}"/>
|
||||
<field name="allow_value_image" attrs="{'invisible':[('question_type','not in',['simple_choice', 'multiple_choice'])]}"/>
|
||||
</group>
|
||||
<group string="Conditional Display" attrs="{'invisible': [('questions_selection', '=', 'random')]}">
|
||||
<field name="is_conditional"/>
|
||||
<field name="triggering_question_id" options="{'no_open': True, 'no_create': True}"
|
||||
attrs="{'invisible': [('is_conditional','=', False)], 'required': [('is_conditional','=', True)]}"/>
|
||||
<field name="triggering_answer_id" options="{'no_open': True, 'no_create': True}"
|
||||
attrs="{'invisible': ['|', ('is_conditional','=', False), ('triggering_question_id','=', False)],
|
||||
'required': [('is_conditional','=', True)]}"/>
|
||||
</group>
|
||||
<group string="Allow Comments" attrs="{'invisible':[('question_type','not in',['simple_choice','multiple_choice', 'matrix'])]}">
|
||||
<field name='comments_allowed' />
|
||||
<field name='comments_message' attrs="{'invisible': [('comments_allowed', '=', False)]}"/>
|
||||
<field name='comment_count_as_answer' attrs="{'invisible': ['|', ('comments_allowed', '=', False), ('question_type', 'in', ['matrix'])]}" />
|
||||
</group>
|
||||
<group string="Live Sessions">
|
||||
<label for="is_time_limited" string="Question Time Limit"/>
|
||||
<div>
|
||||
<field name="is_time_limited" nolabel="1"/>
|
||||
<field name="time_limit" nolabel="1" class="oe_inline"
|
||||
attrs="{'invisible': [('is_time_limited', '=', False)]}" />
|
||||
<span attrs="{'invisible': [('is_time_limited', '=', False)]}"> seconds</span>
|
||||
</div>
|
||||
<group>
|
||||
<group string="Constraints">
|
||||
<field name="constr_mandatory" string="Mandatory Answer"/>
|
||||
<field name="constr_error_msg" attrs="{'invisible': [('constr_mandatory', '=', False)]}"/>
|
||||
</group>
|
||||
<group string="Live Sessions">
|
||||
<label for="is_time_limited" string="Question Time Limit"/>
|
||||
<div>
|
||||
<field name="is_time_limited" nolabel="1"/>
|
||||
<field name="time_limit" nolabel="1" class="oe_inline"
|
||||
attrs="{'invisible': [('is_time_limited', '=', False)]}" />
|
||||
<span attrs="{'invisible': [('is_time_limited', '=', False)]}"> seconds</span>
|
||||
</div>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
@@ -252,7 +264,9 @@
|
||||
<field name="domain">[('is_page', '=', False)]</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_empty_folder">
|
||||
No questions found
|
||||
No Questions yet!
|
||||
</p><p>
|
||||
Come back once you have added questions to your Surveys.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
@@ -271,6 +285,33 @@
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="survey_question_answer_view_form" model="ir.ui.view">
|
||||
<field name="name">survey.question.answer.view.form</field>
|
||||
<field name="model">survey.question.answer</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Question Answer Form">
|
||||
<sheet>
|
||||
<field name="question_type" invisible="1"/>
|
||||
<group>
|
||||
<group>
|
||||
<field name="scoring_type" invisible="1"/>
|
||||
<field name="question_id"/>
|
||||
<field name="is_correct" attrs="{'invisible': [('scoring_type', '=', 'no_scoring')]}"/>
|
||||
<field name="answer_score" attrs="{'invisible': ['|', ('scoring_type', '=', 'no_scoring'), ('question_type', '=', 'matrix')]}"/>
|
||||
<field name="value_image"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="value"/>
|
||||
<field name="matrix_question_id" attrs="{'invisible': [('question_type', '!=', 'matrix')]}"/>
|
||||
<field name="sequence"/>
|
||||
</group>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="survey_question_answer_view_search" model="ir.ui.view">
|
||||
<field name="name">survey.question.answer.view.search</field>
|
||||
<field name="model">survey.question.answer</field>
|
||||
@@ -307,5 +348,10 @@
|
||||
action="survey_question_answer_action"
|
||||
parent="survey_menu_questions"
|
||||
sequence="3"/>
|
||||
<menuitem name="Detailed Answers"
|
||||
id="menu_survey_response_line_form"
|
||||
action="survey_user_input_line_action"
|
||||
parent="survey_menu_questions"
|
||||
sequence="4"/>
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
<form string="Survey" class="o_survey_form">
|
||||
<field name="id" invisible="1"/>
|
||||
<field name="session_state" invisible="1"/>
|
||||
<field name="question_ids" invisible="1"/>
|
||||
<header>
|
||||
<button name="action_send_survey" string="Share" type="object" class="oe_highlight" attrs="{'invisible': [('active', '=', False)]}"/>
|
||||
<button name="action_result_survey" string="See results" type="object" class="oe_highlight"
|
||||
@@ -18,10 +19,10 @@
|
||||
attrs="{'invisible': [('session_state', '=', False)]}" />
|
||||
<button name="action_end_session" string="Close Live Session" type="object"
|
||||
attrs="{'invisible': [('session_state', 'not in', ['ready', 'in_progress'])]}" />
|
||||
<button name="action_test_survey" string="Test" type="object" attrs="{'invisible': [('active', '=', False)]}"/>
|
||||
<button name="action_print_survey" string="Print" type="object"/>
|
||||
<button name="action_test_survey" string="Test" type="object" attrs="{'invisible': ['|', ('active', '=', False), ('question_ids', '=', [])]}"/>
|
||||
<button name="action_unarchive" string="Reopen" class="btn-primary" type="object" attrs="{'invisible': [('active', '=', True)]}"/>
|
||||
<button name="action_print_survey" string="Print" type="object" attrs="{'invisible': [('active', '=', False)]}"/>
|
||||
<button name="action_archive" string="Close" type="object" attrs="{'invisible': [('active', '=', False)]}"/>
|
||||
<button name="action_unarchive" string="Reopen" type="object" attrs="{'invisible': [('active', '=', True)]}"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<div class="oe_button_box" name="button_box">
|
||||
@@ -42,7 +43,7 @@
|
||||
<button name="action_survey_user_input_completed"
|
||||
type="object"
|
||||
class="oe_stat_button"
|
||||
icon="fa-pencil-square-o">
|
||||
icon="fa-check-square-o">
|
||||
<field string="Answers" name="answer_done_count" widget="statinfo"/>
|
||||
</button>
|
||||
</div>
|
||||
@@ -57,7 +58,7 @@
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="user_id" domain="[('share', '=', False)]"/>
|
||||
<field name="user_id" domain="[('share', '=', False)]" widget="many2one_avatar_user"/>
|
||||
<field name="active" invisible="1"/>
|
||||
<field name="has_conditional_questions" invisible="1"/>
|
||||
</group>
|
||||
@@ -65,7 +66,7 @@
|
||||
<notebook>
|
||||
<page string="Questions" name="questions">
|
||||
<field name="question_and_page_ids" nolabel="1" widget="question_page_one2many" mode="tree,kanban" context="{'default_survey_id': active_id, 'default_questions_selection': questions_selection}">
|
||||
<tree decoration-bf="is_page" editable="bottom">
|
||||
<tree decoration-bf="is_page">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="title" widget="survey_description_page"/>
|
||||
<field name="background_image" invisible="1"/>
|
||||
@@ -74,7 +75,8 @@
|
||||
<field name="questions_selection" invisible="1"/>
|
||||
<field name="survey_id" invisible="1"/>
|
||||
<field name="triggering_question_id" invisible="1"/>
|
||||
<field name="random_questions_count" attrs="{'column_invisible': [('parent.questions_selection', '=', 'all')], 'invisible': [('is_page', '=', False)]}" />
|
||||
<field name="random_questions_count"
|
||||
attrs="{'column_invisible': [('parent.questions_selection', '=', 'all')], 'invisible': [('is_page', '=', False)]}"/>
|
||||
<button disabled="disabled" icon="fa-code-fork" attrs="{'invisible': [('triggering_question_id', '=', False)]}"
|
||||
title="This question depends on another question's answer." class="icon_rotates"/>
|
||||
<control>
|
||||
@@ -84,68 +86,68 @@
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
<page string="Description" name="description">
|
||||
<field name="description" nolabel="1"></field>
|
||||
</page>
|
||||
<page string="End Message" name="description_done">
|
||||
<field name="description_done" nolabel="1"></field>
|
||||
</page>
|
||||
<page string="Options" name="options">
|
||||
<group name="options">
|
||||
<group string="Questions" name="questions">
|
||||
<field name="questions_layout" widget="radio"
|
||||
attrs="{'readonly': [('session_state', 'in', ['ready', 'in_progress'])]}"/>
|
||||
<field name="progression_mode" widget="radio" />
|
||||
<field name="progression_mode" widget="radio" attrs="{'invisible': [('questions_layout', '=', 'one_page')]}"/>
|
||||
<field name="questions_selection" widget="radio" />
|
||||
<field name="users_can_go_back" string="Back Button" attrs="{'invisible': [('questions_layout', '=', 'one_page')]}"/>
|
||||
</group>
|
||||
<group string="Participants" name="participants">
|
||||
<field name="access_mode"/>
|
||||
<field name="users_login_required"/>
|
||||
<div colspan="2" class="o_checkbox_optional_field"
|
||||
attrs="{'invisible': ['|', ('has_conditional_questions', '=', True), '&', ('access_mode', '=', 'public'), ('users_login_required', '=', False)]}">
|
||||
<label for="is_attempts_limited" string="Limit Attempts"/>
|
||||
<field name="is_attempts_limited" nolabel="1"/>
|
||||
<div attrs="{'invisible': [('is_attempts_limited', '=', False)]}">
|
||||
to <field name="attempts_limit" nolabel="1" class="oe_inline"/> attempts
|
||||
</div>
|
||||
</div>
|
||||
</group>
|
||||
<group string="Time & Scoring" name="scoring">
|
||||
<div colspan="2" class="o_checkbox_optional_field">
|
||||
<label for="is_time_limited" string="Survey Time Limit"/>
|
||||
<field name="is_time_limited" nolabel="1"/>
|
||||
<div attrs="{'invisible': [('is_time_limited', '=', False)]}">
|
||||
<field name="time_limit" widget="float_time" nolabel="1" class="oe_inline"/> minutes
|
||||
</div>
|
||||
</div>
|
||||
<field name="questions_selection" widget="radio" />
|
||||
<field name="users_can_go_back" string="Back Button" attrs="{'invisible': [('questions_layout', '=', 'one_page')]}"/>
|
||||
</group>
|
||||
<group string="Candidates" name="candidates">
|
||||
<field name="access_mode"/>
|
||||
<field name="users_login_required"/>
|
||||
<div colspan="2" class="o_checkbox_optional_field"
|
||||
attrs="{'invisible': ['|', ('has_conditional_questions', '=', True), '&', ('access_mode', '=', 'public'), ('users_login_required', '=', False)]}">
|
||||
<label for="is_attempts_limited" string="Attempts Limit"/>
|
||||
<field name="is_attempts_limited" nolabel="1"/>
|
||||
<div attrs="{'invisible': [('is_attempts_limited', '=', False)]}">
|
||||
<field name="attempts_limit" nolabel="1" class="oe_inline"/> attempts
|
||||
</div>
|
||||
<field name="scoring_type" widget="radio" />
|
||||
<field name="scoring_success_min" attrs="{'invisible': [('scoring_type', '=', 'no_scoring')]}" />
|
||||
<div colspan="2" class="o_checkbox_optional_field">
|
||||
<label for="certification"/>
|
||||
<field name="certification" nolabel="1"/>
|
||||
<div attrs="{'invisible': [('certification', '=', False)]}" class="w-100">
|
||||
<field name="certification_report_layout" class="w-50"/>
|
||||
<button name="action_survey_preview_certification_template"
|
||||
string="Preview" type="object"
|
||||
icon="fa-external-link" target="_blank" class="btn-link pt-0"/>
|
||||
</div>
|
||||
</div>
|
||||
<field name="certification_mail_template_id" attrs="{'invisible': [('certification', '=', False)]}"/>
|
||||
<div colspan="2" class="float-left o_checkbox_optional_field"
|
||||
attrs="{'invisible': ['|', ('certification', '=', False), ('users_login_required', '=', False)]}">
|
||||
<label for="certification_give_badge"/>
|
||||
<field name="certification_give_badge"/>
|
||||
<div attrs="{'invisible': [('certification_give_badge', '=', False)]}">
|
||||
<field name="certification_badge_id"
|
||||
attrs="{'invisible': ['|', ('certification_give_badge', '=', False), ('certification_badge_id', '!=', False)], 'required': [('certification_give_badge', '=', True)]}"
|
||||
domain="[('survey_id', '=', active_id), ('survey_id', '!=', False)]"
|
||||
context="{'default_name': title,
|
||||
'default_description': 'Congratulations, you have succeeded this certification',
|
||||
'default_rule_auth': 'nobody',
|
||||
'default_level': None,
|
||||
'form_view_ref': 'survey.gamification_badge_form_view_simplified'}"/>
|
||||
<field name="certification_badge_id_dummy" attrs="{'invisible': ['|', ('certification_give_badge', '=', False), ('certification_badge_id', '=', False)]}"
|
||||
options="{'no_create': True}"
|
||||
context="{'form_view_ref': 'survey.gamification_badge_form_view_simplified'}"/>
|
||||
</div>
|
||||
</div>
|
||||
</group>
|
||||
<group string="Scoring" name="scoring">
|
||||
<field name="scoring_type" widget="radio" />
|
||||
<field name="scoring_success_min" attrs="{'invisible': [('scoring_type', '=', 'no_scoring')]}" />
|
||||
<field name="certification" attrs="{'invisible': [('scoring_type', '=', 'no_scoring')]}" />
|
||||
<field name="certification_mail_template_id" attrs="{'invisible': [('certification', '=', False)]}" />
|
||||
<label for="certification_report_layout" string="Certification Template" attrs="{'invisible': [('certification', '=', False)]}"/>
|
||||
<div attrs="{'invisible': [('certification', '=', False)]}" class="d-flex">
|
||||
<field name="certification_report_layout" class="oe_inline"/>
|
||||
<button name="action_survey_preview_certification_template"
|
||||
string="Preview" type="object"
|
||||
icon="fa-external-link" target="_blank" class="btn-link pt-0"/>
|
||||
</div>
|
||||
<field name="certification_give_badge" attrs="{'invisible': ['|', ('certification', '=', False), ('users_login_required', '=', False)]}" />
|
||||
<field name="certification_badge_id"
|
||||
attrs="{'invisible': ['|', ('certification_give_badge', '=', False), ('certification_badge_id', '!=', False)], 'required': [('certification_give_badge', '=', True)]}"
|
||||
domain="[('survey_id', '=', active_id), ('survey_id', '!=', False)]"
|
||||
context="{'default_name': title,
|
||||
'default_description': 'Congratulations, you have succeeded this certification',
|
||||
'default_rule_auth': 'nobody',
|
||||
'default_level': None,
|
||||
'form_view_ref': 'survey.gamification_badge_form_view_simplified',
|
||||
'default_website_published': True}"/>
|
||||
<field name="certification_badge_id_dummy" attrs="{'invisible': ['|', ('certification_give_badge', '=', False), ('certification_badge_id', '=', False)]}"
|
||||
options="{'no_create': True}"
|
||||
context="{'form_view_ref': 'survey.gamification_badge_form_view_simplified'}"/>
|
||||
</group>
|
||||
<group string="Live Session">
|
||||
<field name="session_speed_rating" />
|
||||
<div class="o_td_label">
|
||||
<label for="session_code" string="Session Code" class="oe_edit_only o_form_label" />
|
||||
<label for="session_link" string="Session Link" class="oe_read_only o_form_label" />
|
||||
@@ -154,9 +156,16 @@
|
||||
<field name="session_code" nolabel="1" class="mr-2 oe_edit_only" />
|
||||
<field name="session_link" nolabel="1" widget="CopyClipboardChar" class="oe_read_only" />
|
||||
</div>
|
||||
<field name="session_speed_rating" />
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
<page string="Description" name="description">
|
||||
<field name="description" placeholder="e.g. "The following Survey will help us..."" nolabel="1"></field>
|
||||
</page>
|
||||
<page string="End Message" name="description_done">
|
||||
<field name="description_done" placeholder="e.g. "Thank you very much for your feedback!"" nolabel="1"></field>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
@@ -175,16 +184,16 @@
|
||||
<field name="active" invisible="1"/>
|
||||
<field name="certification" invisible="1"/>
|
||||
<field name="title"/>
|
||||
<field name="user_id" widget="many2one_avatar_user"/>
|
||||
<field name="answer_duration_avg" widget="float_time"/>
|
||||
<field name="answer_count"/>
|
||||
<field name="answer_done_count"/>
|
||||
<field name="success_count"/>
|
||||
<field name="success_ratio"/>
|
||||
<field name="answer_score_avg"/>
|
||||
<button name="certification" type="button" disabled="disabled"
|
||||
icon="fa-trophy" title="Certification" aria-label="Certification"
|
||||
attrs="{'invisible': [('certification', '=', False)]}"/>
|
||||
<field name="user_id" widget="many2one_avatar_user"/>
|
||||
<field name="answer_duration_avg" widget="float_time"/>
|
||||
<field name="answer_count"/>
|
||||
<field name="answer_done_count" optional="hide"/>
|
||||
<field name="success_count" optional="hide"/>
|
||||
<field name="success_ratio"/>
|
||||
<field name="answer_score_avg"/>
|
||||
<!-- Tweak as icons aren't directly supported in xml -->
|
||||
</tree>
|
||||
</field>
|
||||
@@ -361,7 +370,9 @@
|
||||
<field name="arch" type="xml">
|
||||
<search string="Survey">
|
||||
<field string="Survey" name="title"/>
|
||||
<filter string="Certification" name="certification" domain="[('certification', '=', True)]"/>
|
||||
<field string="Question & Pages" name="question_and_page_ids"/>
|
||||
<filter string="Is a Certification" name="certification" domain="[('certification', '=', True)]"/>
|
||||
<filter string="Is not a Certification" name="not_certification" domain="[('certification', '=', False)]"/>
|
||||
<separator/>
|
||||
<filter string="Archived" name="inactive" domain="[('active', '=', False)]"/>
|
||||
<separator/>
|
||||
|
||||
@@ -151,7 +151,8 @@
|
||||
<t t-else="">
|
||||
<div t-if="survey.is_time_limited">
|
||||
<p>
|
||||
<span>Time limit for this survey: </span>
|
||||
<span t-if="not survey.certification">Time limit for this survey: </span>
|
||||
<span t-else="">Time limit for this certification: </span>
|
||||
<span class="font-weight-bold text-danger" t-field="survey.time_limit" t-options="{'widget': 'duration', 'unit': 'minute'}"></span>
|
||||
</p>
|
||||
</div>
|
||||
@@ -402,7 +403,7 @@
|
||||
</template>
|
||||
|
||||
<template id="question_suggested_value_image" name="Image from the question suggested answer">
|
||||
<t t-if="question.allow_value_image and label.value_image">
|
||||
<t t-if="label.value_image">
|
||||
<!-- Directly use field or route if the user doesn't have access rights -->
|
||||
<div t-if="not env.user.has_group('survey.group_survey_user')"
|
||||
class="d-flex my-3 justify-content-center">
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
<template id="survey_button_form_view" name="Survey: back to form view">
|
||||
<div groups="survey.group_survey_manager" t-ignore="true" class="alert alert-info alert-dismissible rounded-0 fade show d-print-none css_editable_mode_hidden mb-0">
|
||||
<div t-ignore="true" class="text-center">
|
||||
<a t-attf-href="/web#view_type=form&model=survey.survey&id=#{survey.id}&action=survey.action_survey_form"><i class="fa fa-fw fa-arrow-right"/><span t-if="answer and answer.test_entry">This is a test survey. </span>Edit Survey</a>
|
||||
<a t-attf-href="/web#view_type=form&model=survey.survey&id=#{survey.id}&action=survey.action_survey_form"><span t-if="answer and answer.test_entry">This is a Test Survey. </span><i class="fa fa-fw fa-arrow-right"/>Back to edit mode</a>
|
||||
</div>
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"> × </button>
|
||||
</div>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<filter string="Quizz passed" name="scoring_success" domain="[('scoring_success','=', True)]"/>
|
||||
<separator/>
|
||||
<filter string="Test Entries" name="test" domain="[('test_entry','=', True)]"/>
|
||||
<filter string="Except Test Entries" name="not_test" domain="[('test_entry','=', False)]" invisible="1"/>
|
||||
<filter string="Exclude Test Entries" name="not_test" domain="[('test_entry','=', False)]"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter name="group_by_survey" string="Survey" domain="[]" context="{'group_by': 'survey_id'}"/>
|
||||
<filter string="Email" name="group_by_email" domain="[]" context="{'group_by': 'email'}"/>
|
||||
@@ -63,7 +63,7 @@
|
||||
<field name="scoring_success" attrs="{'invisible': [('scoring_type', '=', 'no_scoring')]}"/>
|
||||
</group>
|
||||
</group>
|
||||
<field name="user_input_line_ids" mode="tree" attrs="{'readonly': False}">
|
||||
<field name="user_input_line_ids" mode="tree" attrs="{'readonly': True}">
|
||||
<tree>
|
||||
<field name="question_sequence" invisible="1"/>
|
||||
<field name="question_id"/>
|
||||
@@ -103,7 +103,7 @@
|
||||
<field name="name">survey.user_input.view.kanban</field>
|
||||
<field name="model">survey.user_input</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban create="false">
|
||||
<kanban create="false" group_create="false">
|
||||
<field name="survey_id"/>
|
||||
<field name="create_date"/>
|
||||
<field name="partner_id"/>
|
||||
@@ -140,9 +140,11 @@
|
||||
<field name="search_view_id" ref="survey_user_input_view_search"/>
|
||||
<field name="context">{'search_default_group_by_survey': True}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_empty_folder">
|
||||
Nobody has replied to your surveys yet
|
||||
</p>
|
||||
<p class="o_view_nocontent_empty_folder">
|
||||
No answers yet!
|
||||
</p><p>
|
||||
You can share your links through different means: email, invite shortcut, live presentation, ...
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -220,13 +222,7 @@
|
||||
<menuitem name="Participations"
|
||||
id="menu_survey_type_form1"
|
||||
action="action_survey_user_input"
|
||||
parent="survey_menu_user_inputs"
|
||||
parent="menu_surveys"
|
||||
sequence="1"/>
|
||||
<menuitem name="Detailed Answers"
|
||||
id="menu_survey_response_line_form"
|
||||
action="survey_user_input_line_action"
|
||||
parent="survey_menu_user_inputs"
|
||||
sequence="4"
|
||||
groups="base.group_no_one"/>
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
Reference in New Issue
Block a user