Before this commit, images displayed on survey question answers were small and hard to read, and nothing existed in order to zoom on them properly. AFTER THIS COMMIT Backend: A new field value_image_filename is added to store the names of the image fields. They are seen when editing an answer (line). The max_height and max_width of the images are raised to 1024 px on their field definition in survey.question.answer to compromise between image resolution and space, and in order to be able to zoom on them and still see details Survey: A hovering frame is visible on the images, as well as a zoom in cursor, to indicate we can click on them to zoom in. The rest of the answer frame is the selection area. Clicking anywhere on the modal closes it. Until then, a pointer cursor hints the feature. A new widget SurveyImageZoomer is added. Once the user has clicked on a choice image, a transparent modal is opened on the whole screen. This is thought for all size devices : it can be closed by clicking anywhere, or the cross button, or ESC key. It will always be destroyed. Also, for small width screens, we do not take the whole height but leave bands over and below to indicate the mobile users can leave by clicking out. The image will be displayed in the foreground, zooming on small images by default, by setting a min width depending on the screen width. We also avoid using a zoom too large to avoid very low resolution. The widget allows zooming as long as the image stays in the frame. The user can zoom both with the mouse scrolling and + and - buttons, sized to allow medium screen (tablets) to press them accurately. All keys are disabled but the 'ESC' one when the Zoomer is open to avoid (undesired) survey navigation. Task-2566584 closes odoo/odoo#73718 Signed-off-by: Warnon Aurélien (awa) <awa@odoo.com>
364 lines
25 KiB
XML
364 lines
25 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<odoo>
|
|
<data>
|
|
<!-- QUESTIONS -->
|
|
<record model="ir.ui.view" id="survey_question_form">
|
|
<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" 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"/>
|
|
<field name="sequence" invisible="1"/>
|
|
<field name="scoring_type" invisible="1"/>
|
|
<sheet>
|
|
<div class="float-end d-flex flex-column text-center" attrs="{'invisible': [('is_page', '=', False)]}">
|
|
<label for="background_image"/>
|
|
<field name="background_image" widget="image" class="oe_avatar"/>
|
|
</div>
|
|
<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)]}"/>
|
|
<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')]}">
|
|
<field name="random_questions_count"/>
|
|
</group>
|
|
<group attrs="{'invisible': [('is_page', '=', True)]}">
|
|
<group>
|
|
<field name="question_type" widget="radio" attrs="{'required': [('is_page', '=', False)]}" />
|
|
</group>
|
|
<group>
|
|
<div class="col-lg-6 offset-lg-3 d-none d-sm-block 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 me-2"/>answer</div>
|
|
<div class="row o_preview_questions_choice mb-2"><i class="fa fa-dot-circle-o fa-lg me-2"/>answer</div>
|
|
<div class="row o_preview_questions_choice"><i class="fa fa-circle-o fa-lg me-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 me-2"/>answer</div>
|
|
<div class="row o_preview_questions_choice mb-2"><i class="fa fa-check-square-o fa-lg me-2"/>answer</div>
|
|
<div class="row o_preview_questions_choice"><i class="fa fa-square-o fa-lg me-2"/>answer</div>
|
|
</div>
|
|
<!-- Multiple Lines Text Zone -->
|
|
<div attrs="{'invisible': [('question_type', '!=', 'text_box')]}">
|
|
<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')]}">
|
|
<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')]}">
|
|
<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')]}">
|
|
<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>
|
|
<!-- Matrix -->
|
|
<div attrs="{'invisible': [('question_type', '!=', 'matrix')]}">
|
|
<div class="row o_matrix_head">
|
|
<div class="col-lg-3"></div>
|
|
<div class="col-lg-3">ans</div>
|
|
<div class="col-lg-3">ans</div>
|
|
<div class="col-lg-3">ans</div>
|
|
</div>
|
|
<div class="row o_matrix_row">
|
|
<div class="col-lg-3">Row1</div>
|
|
<div class="col-lg-3"><i class="fa fa-circle-o fa-lg" role="img" aria-label="Not checked" title="Not checked"/></div>
|
|
<div class="col-lg-3"><i class="fa fa-dot-circle-o fa-lg" role="img" aria-label="Checked" title="Checked"/></div>
|
|
<div class="col-lg-3"><i class="fa fa-circle-o fa-lg" role="img" aria-label="Not checked" title="Not checked"/></div>
|
|
</div>
|
|
<div class="row o_matrix_row">
|
|
<div class="col-lg-3">Row2</div>
|
|
<div class="col-lg-3"><i class="fa fa-circle-o fa-lg" role="img" aria-label="Not checked" title="Not checked"/></div>
|
|
<div class="col-lg-3"><i class="fa fa-circle-o fa-lg" role="img" aria-label="Not checked" title="Not checked"/></div>
|
|
<div class="col-lg-3"><i class="fa fa-dot-circle-o fa-lg" role="img" aria-label="Checked" title="Checked"/></div>
|
|
</div>
|
|
<div class="row o_matrix_row">
|
|
<div class="col-lg-3">Row3</div>
|
|
<div class="col-lg-3"><i class="fa fa-dot-circle-o fa-lg" role="img" aria-label="Checked" title="Checked"/></div>
|
|
<div class="col-lg-3"><i class="fa fa-circle-o fa-lg" role="img" aria-label="Not checked" title="Not checked"/></div>
|
|
<div class="col-lg-3"><i class="fa fa-circle-o fa-lg" role="img" aria-label="Not checked" title="Not checked"/></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</group>
|
|
</group>
|
|
<notebook>
|
|
<page string="Answers" name="answers" attrs="{'invisible': ['|', '|',
|
|
('is_page', '=', True), ('question_type', '=', 'text_box'),
|
|
'&', ('scoring_type', '=', 'no_scoring'), ('question_type', 'in', ['numerical_box', 'date', 'datetime']),
|
|
]}">
|
|
<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')], 'required': [('is_scored_question', '=', True), ('question_type', '=', 'numerical_box')]}" class="oe_inline"/>
|
|
<field name="answer_date" string="Correct Answer"
|
|
attrs="{'invisible': [('question_type', '!=', 'date')], 'required': [('is_scored_question', '=', True), ('question_type', '=', 'date')]}" class="oe_inline"/>
|
|
<field name="answer_datetime" string="Correct Answer"
|
|
attrs="{'invisible': [('question_type', '!=', 'datetime')], 'required': [('is_scored_question', '=', True), ('question_type', '=', 'datetime')]}" class="oe_inline"/>
|
|
|
|
<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>
|
|
|
|
<group attrs="{'invisible': ['|', ('scoring_type', '=', 'no_scoring'), ('question_type', 'not in', ['numerical_box', 'date', 'datetime'])]}">
|
|
<label for="is_scored_question"/>
|
|
<div name="survey_scored_question">
|
|
<field name="is_scored_question" nolabel="1"/>
|
|
<field name="answer_score" class="w-50 mx-2" attrs="{'invisible': [('is_scored_question', '=', False)]}" nolabel="1"/>
|
|
<span attrs="{'invisible': [('is_scored_question', '!=', True)]}">Points</span>
|
|
</div>
|
|
</group>
|
|
</group>
|
|
<group attrs="{'invisible': [('question_type', 'not in', ['simple_choice', 'multiple_choice', 'matrix'])]}">
|
|
<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_filename" invisible="1"/>
|
|
<field name="value_image" filename="value_image_filename" options="{'accepted_file_extensions': 'image/*'}"
|
|
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')]}" nolabel="1">
|
|
<tree editable="bottom">
|
|
<field name="sequence" widget="handle"/>
|
|
<field name="value" string="Rows"/>
|
|
</tree>
|
|
</field>
|
|
</group>
|
|
</page>
|
|
<page string="Description" name="survey_description">
|
|
<field name="description" widget="html"
|
|
placeholder="e.g. Guidelines, instructions, picture, ... to help attendees answer"/>
|
|
</page>
|
|
<page string="Options" name="options" attrs="{'invisible': [('is_page', '=', True)]}">
|
|
<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="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"/>
|
|
<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 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)]}"/>
|
|
</group>
|
|
</group>
|
|
<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>
|
|
</sheet>
|
|
</form>
|
|
</field>
|
|
</record>
|
|
<record model="ir.ui.view" id="survey_question_tree">
|
|
<field name="name">Tree view for survey question</field>
|
|
<field name="model">survey.question</field>
|
|
<field name="arch" type="xml">
|
|
<tree string="Survey Question" create="false">
|
|
<field name="sequence" widget="handle"/>
|
|
<field name="title"/>
|
|
<field name="survey_id"/>
|
|
<field name="question_type"/>
|
|
<field name="triggering_question_id" invisible="1"/>
|
|
<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"/>
|
|
</tree>
|
|
</field>
|
|
</record>
|
|
<record model="ir.ui.view" id="survey_question_search">
|
|
<field name="name">Search view for survey question</field>
|
|
<field name="model">survey.question</field>
|
|
<field name="arch" type="xml">
|
|
<search string="Search Question">
|
|
<field name="title"/>
|
|
<field name="survey_id" string="Survey"/>
|
|
<field name="question_type" string="Type"/>
|
|
<group expand="1" string="Group By">
|
|
<filter name="group_by_type" string="Type" domain="[]" context="{'group_by':'question_type'}"/>
|
|
<filter name="group_by_survey" string="Survey" domain="[]" context="{'group_by':'survey_id'}"/>
|
|
</group>
|
|
</search>
|
|
</field>
|
|
</record>
|
|
|
|
<record model="ir.actions.act_window" id="action_survey_question_form">
|
|
<field name="name">Questions</field>
|
|
<field name="res_model">survey.question</field>
|
|
<field name="view_mode">tree,form</field>
|
|
<field name="search_view_id" ref="survey_question_search"/>
|
|
<field name="context">{'search_default_group_by_page': True}</field>
|
|
<field name="domain">[('is_page', '=', False)]</field>
|
|
<field name="help" type="html">
|
|
<p class="o_view_nocontent_empty_folder">
|
|
No Questions yet!
|
|
</p><p>
|
|
Come back once you have added questions to your Surveys.
|
|
</p>
|
|
</field>
|
|
</record>
|
|
|
|
<!-- LABELS -->
|
|
<record id="survey_question_answer_view_tree" model="ir.ui.view">
|
|
<field name="name">survey.question.answer.view.tree</field>
|
|
<field name="model">survey.question.answer</field>
|
|
<field name="arch" type="xml">
|
|
<tree string="Survey Label" create="false">
|
|
<field name="sequence" widget="handle"/>
|
|
<field name="question_id"/>
|
|
<field name="matrix_question_id"/>
|
|
<field name="value"/>
|
|
<field name="answer_score" groups="base.group_no_one"/>
|
|
</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>
|
|
<field name="arch" type="xml">
|
|
<search string="Search Label">
|
|
<field name="question_id"/>
|
|
<group expand="1" string="Group By">
|
|
<filter name="group_by_question" string="Question" domain="[]" context="{'group_by':'question_id'}"/>
|
|
</group>
|
|
</search>
|
|
</field>
|
|
</record>
|
|
|
|
<record id="survey_question_answer_action" model="ir.actions.act_window">
|
|
<field name="name">Suggested Values</field>
|
|
<field name="res_model">survey.question.answer</field>
|
|
<field name="view_mode">tree,form</field>
|
|
<field name="search_view_id" ref="survey_question_answer_view_search"/>
|
|
<field name="context">{'search_default_group_by_question': True}</field>
|
|
<field name="help" type="html">
|
|
<p class="o_view_nocontent_empty_folder">
|
|
No survey labels found
|
|
</p>
|
|
</field>
|
|
</record>
|
|
|
|
<menuitem name="Questions"
|
|
id="menu_survey_question_form1"
|
|
action="action_survey_question_form"
|
|
parent="survey_menu_questions"
|
|
sequence="2"/>
|
|
<menuitem name="Suggested Values"
|
|
id="menu_survey_label_form1"
|
|
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>
|