odex25_standard/odex25_base/tour_genius/views/quiz_views.xml

356 lines
20 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- ============================================================ -->
<!-- Quiz Views -->
<!-- ============================================================ -->
<record id="view_genius_quiz_tree" model="ir.ui.view">
<field name="name">genius.quiz.tree</field>
<field name="model">genius.quiz</field>
<field name="arch" type="xml">
<tree string="Quizzes">
<field name="name"/>
<field name="question_count"/>
<field name="passing_score"/>
<field name="attempt_count"/>
<field name="avg_score"/>
<field name="pass_rate"/>
</tree>
</field>
</record>
<record id="view_genius_quiz_form" model="ir.ui.view">
<field name="name">genius.quiz.form</field>
<field name="model">genius.quiz</field>
<field name="arch" type="xml">
<form string="Quiz">
<header>
<button name="action_analyze_difficulty" string="Analyze" type="object"
icon="fa-bar-chart"
attrs="{'invisible': [('attempt_count', '=', 0)]}"/>
<button name="action_reset_statistics" string="Reset Stats" type="object"
icon="fa-refresh"
confirm="This will delete all attempts and statistics. Continue?"
attrs="{'invisible': [('attempt_count', '=', 0)]}"/>
<button name="action_duplicate_quiz" string="Duplicate" type="object" icon="fa-copy"/>
</header>
<sheet>
<div class="oe_button_box" name="button_box">
<button class="oe_stat_button" icon="fa-question-circle">
<field name="question_count" widget="statinfo" string="Questions"/>
</button>
<button name="action_view_attempts" class="oe_stat_button" icon="fa-pencil-square" type="object">
<field name="attempt_count" widget="statinfo" string="Attempts"/>
</button>
<button class="oe_stat_button" icon="fa-check-circle">
<field name="pass_rate" widget="statinfo" string="Pass Rate"/>
</button>
</div>
<div class="oe_title d-flex align-items-center">
<div class="flex-grow-1">
<label for="name" class="oe_edit_only"/>
<h1>
<field name="name" placeholder="Quiz Title"/>
</h1>
</div>
<!-- Genius Test Button - Right side of title -->
<div class="genius-test-mode-container ml-auto" attrs="{'invisible': [('question_count', '=', 0)]}">
<field name="test_mode_opener" widget="genius_quiz_test_button"/>
</div>
</div>
<group>
<group string="Configuration">
<field name="passing_score"/>
<field name="time_limit_minutes"/>
<field name="max_attempts"/>
</group>
<group string="Behavior">
<field name="shuffle_questions"/>
<field name="show_correct_answers"/>
<field name="sample_size"/>
</group>
</group>
<notebook>
<page string="Questions" name="questions">
<field name="question_ids" context="{'default_quiz_id': active_id}">
<tree>
<field name="sequence" widget="handle"/>
<field name="question_text"/>
<field name="question_type"/>
<field name="points"/>
</tree>
</field>
</page>
<page string="Feedback &amp; Customization" name="feedback">
<group>
<separator string="Success Feedback" colspan="2"/>
<field name="success_message" nolabel="1" placeholder="Message shown when user passes..."/>
<separator string="Failure Feedback" colspan="2"/>
<field name="fail_message" nolabel="1" placeholder="Message shown when user fails..."/>
</group>
</page>
<page string="Description" name="description">
<field name="description" placeholder="Internal notes or description..."/>
</page>
<page string="Statistics" name="stats">
<group>
<group>
<field name="attempt_count" readonly="1"/>
<field name="avg_score" readonly="1"/>
</group>
<group>
<field name="pass_rate" readonly="1"/>
</group>
</group>
</page>
<page string="Certificate" name="certificate">
<group>
<group string="Branding">
<field name="certificate_logo" widget="image" class="oe_avatar" options="{'size': [90, 90]}"/>
<field name="certificate_secondary_logo" widget="image" class="oe_avatar" options="{'size': [90, 90]}"/>
<field name="certificate_title" placeholder="CERTIFICATE"/>
<field name="certificate_issuer" placeholder="Training Department"/>
</group>
<group string="Signature &amp; Stamp">
<field name="certificate_signature_image" widget="image" class="oe_avatar" options="{'size': [150, 60]}"/>
<field name="certificate_stamp" widget="image" class="oe_avatar" options="{'size': [90, 90]}"/>
<field name="certificate_signature_name" placeholder="Training Director"/>
<field name="certificate_signature_title" placeholder="Director of Training"/>
</group>
</group>
<group string="Achievement Description">
<field name="certificate_body_template" nolabel="1" colspan="2"
placeholder="has successfully completed the training course and demonstrated mastery..."/>
</group>
<div class="alert alert-info">
<i class="fa fa-info-circle"/> <strong>Variables:</strong>
<code>{user_name}</code> <code>{topic_name}</code> <code>{quiz_name}</code>
<br/><small class="text-muted">Note: Score and Date are displayed automatically in the certificate footer.</small>
</div>
<div class="mt-3">
<button name="action_preview_certificate" type="object" class="btn btn-primary" icon="fa-eye">
<i class="fa fa-eye"/> Preview Certificate
</button>
</div>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<record id="action_genius_quiz" model="ir.actions.act_window">
<field name="name">Quizzes</field>
<field name="res_model">genius.quiz</field>
<field name="view_mode">tree,form</field>
</record>
<!-- Menu Item -->
<menuitem id="menu_quizzes"
name="Quizzes"
parent="menu_tour_genius_root"
action="action_genius_quiz"
sequence="20"
groups="tour_genius.group_genius_instructor"/>
<record id="view_genius_question_form" model="ir.ui.view">
<field name="name">genius.quiz.question.form</field>
<field name="model">genius.quiz.question</field>
<field name="arch" type="xml">
<form string="Question">
<sheet>
<!-- Question Preview Title -->
<div class="oe_title">
<label for="name" class="oe_edit_only" string="Question Preview"/>
<h1>
<field name="name" readonly="1"/>
</h1>
</div>
<!-- Main Configuration -->
<group>
<group string="Configuration">
<field name="question_type" widget="radio"/>
<field name="points"/>
</group>
<group string="Status">
<field name="active" widget="boolean_toggle"/>
<field name="sequence" groups="base.group_no_one"/>
</group>
</group>
<!-- Question Content -->
<separator string="Question Content"/>
<field name="question_text" nolabel="1" placeholder="Enter your question here..."/>
<!-- Dynamic Hint Based on Type -->
<div class="alert alert-info" role="alert" attrs="{'invisible': [('question_type', 'not in', ['fill_blank'])]}">
<i class="fa fa-info-circle"/> <strong>Tip:</strong> Write your question with a blank to fill, e.g., "The capital of France is ___".
</div>
<div class="alert alert-info" role="alert" attrs="{'invisible': [('question_type', '!=', 'ordering')]}">
<i class="fa fa-info-circle"/> <strong>Tip:</strong> Add items below. The sequence order you set here is the <em>correct</em> order.
</div>
<notebook>
<!-- Answer Options (Single/Multiple Choice) -->
<page string="Answer Options" name="answers"
attrs="{'invisible': [('question_type', 'not in', ['single', 'multiple'])]}">
<field name="answer_ids">
<tree editable="bottom">
<field name="sequence" widget="handle"/>
<field name="answer_text" placeholder="Enter answer option..."/>
<field name="is_correct"/>
<field name="feedback" placeholder="Optional feedback..."/>
</tree>
</field>
<div class="text-muted mt-2">
<i class="fa fa-lightbulb-o"/>
<span attrs="{'invisible': [('question_type', '!=', 'single')]}">
Mark exactly <strong>one</strong> answer as correct.
</span>
<span attrs="{'invisible': [('question_type', '!=', 'multiple')]}">
Mark <strong>all</strong> correct answers.
</span>
</div>
</page>
<!-- Ordering Items -->
<page string="Items to Order" name="ordering"
attrs="{'invisible': [('question_type', '!=', 'ordering')]}">
<field name="answer_ids">
<tree editable="bottom">
<field name="sequence" widget="handle"/>
<field name="answer_text" placeholder="Enter item..."/>
</tree>
</field>
<div class="text-muted mt-2">
<i class="fa fa-lightbulb-o"/> Drag items to set the <strong>correct order</strong>. Users will see them shuffled.
</div>
</page>
<!-- Text Answer (Short Answer / Fill in the Blank) -->
<page string="Correct Answer" name="text_answer"
attrs="{'invisible': [('question_type', 'not in', ['short_answer', 'fill_blank'])]}">
<group>
<group>
<field name="correct_short_answer" placeholder="Expected answer..." attrs="{'required': [('question_type', 'in', ['short_answer', 'fill_blank'])]}"/>
<field name="answer_alternatives" placeholder="color, colour, Color"/>
</group>
<group>
<field name="case_sensitive"/>
</group>
</group>
<div class="text-muted">
<i class="fa fa-lightbulb-o"/> Use <strong>Alternative Answers</strong> for synonyms or spelling variations (comma-separated).
</div>
</page>
<!-- Explanation &amp; Media -->
<page string="Explanation &amp; Media" name="explanation">
<group>
<group string="Question Image">
<field name="image" widget="image" class="oe_avatar" options="{'size': [200, 200]}" nolabel="1"/>
</group>
<group string="Explanation">
<field name="explanation" nolabel="1" placeholder="Why is this the correct answer? (Shown after answering)"/>
</group>
</group>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<!-- Quiz Attempt Views -->
<record id="view_genius_quiz_attempt_tree" model="ir.ui.view">
<field name="name">genius.quiz.attempt.tree</field>
<field name="model">genius.quiz.attempt</field>
<field name="arch" type="xml">
<tree string="Quiz Attempts" create="false" edit="false">
<field name="user_id"/>
<field name="quiz_id"/>
<field name="started_at"/>
<field name="score"/>
<field name="is_passed"/>
<field name="state"/>
</tree>
</field>
</record>
<record id="view_genius_quiz_attempt_form" model="ir.ui.view">
<field name="name">genius.quiz.attempt.form</field>
<field name="model">genius.quiz.attempt</field>
<field name="arch" type="xml">
<form string="Quiz Attempt">
<header>
<button name="action_submit" string="Submit Quiz" type="object" state="in_progress" class="oe_highlight" attrs="{'invisible': [('state', '!=', 'in_progress')]}"/>
<field name="state" widget="statusbar" statusbar_visible="in_progress,submitted"/>
</header>
<sheet>
<group>
<group>
<field name="quiz_id" readonly="1"/>
<field name="user_id" readonly="1"/>
</group>
<group>
<field name="started_at" readonly="1"/>
<field name="score" attrs="{'invisible': [('state', '!=', 'submitted')]}"/>
<field name="is_passed" attrs="{'invisible': [('state', '!=', 'submitted')]}"/>
<field name="show_correct_answers" invisible="1"/>
</group>
</group>
<!-- Success Messages -->
<div class="alert alert-success" role="alert" attrs="{'invisible': ['|', '|', ('state', '!=', 'submitted'), ('is_passed', '=', False), ('success_message', '!=', False)]}">
<strong>Congratulations!</strong> You passed this quiz.
</div>
<field name="success_message" widget="html" class="alert alert-success" attrs="{'invisible': ['|', '|', ('state', '!=', 'submitted'), ('is_passed', '=', False), ('success_message', '=', False)]}"/>
<!-- Failure Messages -->
<div class="alert alert-danger" role="alert" attrs="{'invisible': ['|', '|', ('state', '!=', 'submitted'), ('is_passed', '=', True), ('fail_message', '!=', False)]}">
<strong>Try Again!</strong> Only <field name="points_earned"/> points earned.
</div>
<field name="fail_message" widget="html" class="alert alert-danger" attrs="{'invisible': ['|', '|', ('state', '!=', 'submitted'), ('is_passed', '=', True), ('fail_message', '=', False)]}"/>
<notebook>
<page string="Questions">
<field name="response_ids">
<tree editable="bottom" create="0" delete="0">
<field name="question_id" readonly="1"/>
<field name="text_answer" attrs="{'readonly': [('parent.state', '=', 'submitted')]}"/>
<!-- Assume we need a way to select answers. Standard Odoo tree generic is hard for M2M selection.
Ideally this should be a form view or web client.
For now, just showing structure. -->
<!-- Domain ensures we only see answers for THIS question -->
<field name="selected_answer_ids" widget="many2many_tags"
domain="[('question_id', '=', question_id)]"
attrs="{'readonly': [('parent.state', '=', 'submitted')]}"/>
<field name="is_correct" readonly="1" attrs="{'invisible': [('parent.show_correct_answers', '=', False)]}"/>
<field name="explanation" widget="html" optional="hide" readonly="1" attrs="{'invisible': [('parent.show_correct_answers', '=', False)]}"/>
</tree>
</field>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<record id="action_genius_quiz_attempt" model="ir.actions.act_window">
<field name="name">My Attempts</field>
<field name="res_model">genius.quiz.attempt</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('user_id', '=', uid)]</field>
</record>
<menuitem id="menu_genius_quiz_attempt"
name="My Quizzes"
parent="menu_training"
action="action_genius_quiz_attempt"
sequence="20"
groups="tour_genius.group_genius_user"/>
</odoo>