feat(v3): restructure project + add complete frontend
- Restructure: move backend from new_project/ to backend/ - Add full React/TypeScript frontend (37 pages, 17 services, 16 type defs, 11 query hooks) - Add docs/ with SRS specs, user stories, and workflow documentation - Update .gitignore for new directory layout Workflows implemented: WF1 User Signup, WF2 Placement Test, WF3 Exam Configuration, WF4 General English Exam, WF5 Course Generation, WF6 Entity Student Onboarding, AI Course Generation, Adaptive Learning Engine UI, White-Label Branding, Score Release Made-with: Cursor
This commit is contained in:
100
custom_addons/encoach_exam_template/views/audio_file_views.xml
Normal file
100
custom_addons/encoach_exam_template/views/audio_file_views.xml
Normal file
@@ -0,0 +1,100 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- Audio File Views -->
|
||||
<!-- ============================================================ -->
|
||||
|
||||
<record id="view_audio_file_form" model="ir.ui.view">
|
||||
<field name="name">encoach.audio.file.form</field>
|
||||
<field name="model">encoach.audio.file</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Audio File">
|
||||
<sheet>
|
||||
<div class="oe_title">
|
||||
<h1>
|
||||
<field name="topic" placeholder="Audio Topic"/>
|
||||
</h1>
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="exam_type"/>
|
||||
<field name="part"/>
|
||||
<field name="context_type"/>
|
||||
<field name="difficulty"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="audio_url" widget="url"/>
|
||||
<field name="ai_generated"/>
|
||||
<field name="approved"/>
|
||||
<field name="ielts_certified"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Transcript" name="transcript">
|
||||
<field name="transcript" widget="text" placeholder="Audio transcript..."/>
|
||||
</page>
|
||||
<page string="Validation" name="validation">
|
||||
<group>
|
||||
<field name="generation_brief"/>
|
||||
<field name="validation_errors"/>
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_audio_file_list" model="ir.ui.view">
|
||||
<field name="name">encoach.audio.file.list</field>
|
||||
<field name="model">encoach.audio.file</field>
|
||||
<field name="arch" type="xml">
|
||||
<list string="Audio Files" decoration-success="approved == True">
|
||||
<field name="topic"/>
|
||||
<field name="exam_type"/>
|
||||
<field name="part"/>
|
||||
<field name="context_type"/>
|
||||
<field name="difficulty"/>
|
||||
<field name="approved"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_audio_file_search" model="ir.ui.view">
|
||||
<field name="name">encoach.audio.file.search</field>
|
||||
<field name="model">encoach.audio.file</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Audio Files">
|
||||
<field name="topic"/>
|
||||
<separator/>
|
||||
<filter string="Academic" name="filter_academic" domain="[('exam_type', '=', 'academic')]"/>
|
||||
<filter string="General Training" name="filter_general" domain="[('exam_type', '=', 'general_training')]"/>
|
||||
<filter string="General English" name="filter_general_eng" domain="[('exam_type', '=', 'general_english')]"/>
|
||||
<separator/>
|
||||
<filter string="Part 1" name="filter_part1" domain="[('part', '=', 1)]"/>
|
||||
<filter string="Part 2" name="filter_part2" domain="[('part', '=', 2)]"/>
|
||||
<filter string="Part 3" name="filter_part3" domain="[('part', '=', 3)]"/>
|
||||
<filter string="Part 4" name="filter_part4" domain="[('part', '=', 4)]"/>
|
||||
<separator/>
|
||||
<filter string="Approved" name="filter_approved" domain="[('approved', '=', True)]"/>
|
||||
<filter string="Exam Type" name="group_exam_type" context="{'group_by': 'exam_type'}"/>
|
||||
<filter string="Part" name="group_part" context="{'group_by': 'part'}"/>
|
||||
<filter string="Difficulty" name="group_difficulty" context="{'group_by': 'difficulty'}"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_audio_file" model="ir.actions.act_window">
|
||||
<field name="name">Audio Files</field>
|
||||
<field name="res_model">encoach.audio.file</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="search_view_id" ref="view_audio_file_search"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Upload your first audio file
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="action_content_pool" model="ir.actions.client">
|
||||
<field name="name">Content Pool</field>
|
||||
<field name="tag">encoach_content_pool</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="menu_content_pool_browser"
|
||||
name="Content Pool Browser"
|
||||
parent="encoach_core.menu_encoach_content"
|
||||
action="action_content_pool"
|
||||
sequence="5"/>
|
||||
|
||||
</odoo>
|
||||
@@ -0,0 +1,80 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- Exam Assignment Views -->
|
||||
<!-- ============================================================ -->
|
||||
|
||||
<record id="view_exam_assignment_form" model="ir.ui.view">
|
||||
<field name="name">encoach.exam.assignment.form</field>
|
||||
<field name="model">encoach.exam.assignment</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Exam Assignment">
|
||||
<header>
|
||||
<field name="status" widget="statusbar" statusbar_visible="assigned,started,completed,expired"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<group>
|
||||
<group>
|
||||
<field name="exam_id"/>
|
||||
<field name="student_id"/>
|
||||
<field name="batch_id"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="access_start"/>
|
||||
<field name="access_end"/>
|
||||
</group>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_exam_assignment_list" model="ir.ui.view">
|
||||
<field name="name">encoach.exam.assignment.list</field>
|
||||
<field name="model">encoach.exam.assignment</field>
|
||||
<field name="arch" type="xml">
|
||||
<list string="Exam Assignments" decoration-info="status == 'assigned'" decoration-warning="status == 'started'" decoration-success="status == 'completed'" decoration-muted="status == 'expired'">
|
||||
<field name="exam_id"/>
|
||||
<field name="student_id"/>
|
||||
<field name="batch_id"/>
|
||||
<field name="access_start"/>
|
||||
<field name="access_end"/>
|
||||
<field name="status"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_exam_assignment_search" model="ir.ui.view">
|
||||
<field name="name">encoach.exam.assignment.search</field>
|
||||
<field name="model">encoach.exam.assignment</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Exam Assignments">
|
||||
<field name="exam_id"/>
|
||||
<field name="student_id"/>
|
||||
<field name="batch_id"/>
|
||||
<separator/>
|
||||
<filter string="Assigned" name="filter_assigned" domain="[('status', '=', 'assigned')]"/>
|
||||
<filter string="Started" name="filter_started" domain="[('status', '=', 'started')]"/>
|
||||
<filter string="Completed" name="filter_completed" domain="[('status', '=', 'completed')]"/>
|
||||
<filter string="Expired" name="filter_expired" domain="[('status', '=', 'expired')]"/>
|
||||
<filter string="Status" name="group_status" context="{'group_by': 'status'}"/>
|
||||
<filter string="Exam" name="group_exam" context="{'group_by': 'exam_id'}"/>
|
||||
<filter string="Batch" name="group_batch" context="{'group_by': 'batch_id'}"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_exam_assignment" model="ir.actions.act_window">
|
||||
<field name="name">Exam Assignments</field>
|
||||
<field name="res_model">encoach.exam.assignment</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="search_view_id" ref="view_exam_assignment_search"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Assign your first exam to students
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
105
custom_addons/encoach_exam_template/views/exam_custom_views.xml
Normal file
105
custom_addons/encoach_exam_template/views/exam_custom_views.xml
Normal file
@@ -0,0 +1,105 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- Custom Exam Views -->
|
||||
<!-- ============================================================ -->
|
||||
|
||||
<record id="view_exam_custom_form" model="ir.ui.view">
|
||||
<field name="name">encoach.exam.custom.form</field>
|
||||
<field name="model">encoach.exam.custom</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Custom Exam">
|
||||
<header>
|
||||
<field name="status" widget="statusbar" statusbar_visible="draft,published,archived"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<div class="oe_title">
|
||||
<h1>
|
||||
<field name="title" placeholder="Exam Title"/>
|
||||
</h1>
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="template_id"/>
|
||||
<field name="subject_id"/>
|
||||
<field name="entity_id"/>
|
||||
<field name="teacher_id"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="total_time_min"/>
|
||||
<field name="pass_threshold"/>
|
||||
<field name="results_release_mode"/>
|
||||
<field name="randomize_questions"/>
|
||||
</group>
|
||||
</group>
|
||||
<group>
|
||||
<field name="description" placeholder="Exam description..."/>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Sections" name="sections">
|
||||
<field name="section_ids">
|
||||
<list editable="bottom">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="title"/>
|
||||
<field name="skill"/>
|
||||
<field name="question_count"/>
|
||||
<field name="time_limit_min" string="Time (min)"/>
|
||||
<field name="scoring_method"/>
|
||||
</list>
|
||||
</field>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_exam_custom_list" model="ir.ui.view">
|
||||
<field name="name">encoach.exam.custom.list</field>
|
||||
<field name="model">encoach.exam.custom</field>
|
||||
<field name="arch" type="xml">
|
||||
<list string="Custom Exams" decoration-info="status == 'draft'" decoration-success="status == 'published'">
|
||||
<field name="title"/>
|
||||
<field name="subject_id"/>
|
||||
<field name="entity_id"/>
|
||||
<field name="teacher_id"/>
|
||||
<field name="total_time_min" string="Time (min)"/>
|
||||
<field name="status"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_exam_custom_search" model="ir.ui.view">
|
||||
<field name="name">encoach.exam.custom.search</field>
|
||||
<field name="model">encoach.exam.custom</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Custom Exams">
|
||||
<field name="title"/>
|
||||
<field name="subject_id"/>
|
||||
<field name="entity_id"/>
|
||||
<field name="teacher_id"/>
|
||||
<separator/>
|
||||
<filter string="Draft" name="filter_draft" domain="[('status', '=', 'draft')]"/>
|
||||
<filter string="Published" name="filter_published" domain="[('status', '=', 'published')]"/>
|
||||
<filter string="Archived" name="filter_archived" domain="[('status', '=', 'archived')]"/>
|
||||
<filter string="Status" name="group_status" context="{'group_by': 'status'}"/>
|
||||
<filter string="Subject" name="group_subject" context="{'group_by': 'subject_id'}"/>
|
||||
<filter string="Entity" name="group_entity" context="{'group_by': 'entity_id'}"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_exam_custom" model="ir.actions.act_window">
|
||||
<field name="name">Custom Exams</field>
|
||||
<field name="res_model">encoach.exam.custom</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="search_view_id" ref="view_exam_custom_search"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Create your first custom exam
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- Exam Template Module Menu Items -->
|
||||
<!-- ============================================================ -->
|
||||
|
||||
<menuitem id="menu_exam_templates"
|
||||
name="Templates"
|
||||
parent="encoach_core.menu_encoach_exams"
|
||||
action="action_exam_template"
|
||||
sequence="1"/>
|
||||
|
||||
<menuitem id="menu_exam_question_bank"
|
||||
name="Question Bank"
|
||||
parent="encoach_core.menu_encoach_exams"
|
||||
action="action_question"
|
||||
sequence="2"/>
|
||||
|
||||
<menuitem id="menu_exam_passages"
|
||||
name="Passages"
|
||||
parent="encoach_core.menu_encoach_exams"
|
||||
action="action_passage"
|
||||
sequence="3"/>
|
||||
|
||||
<menuitem id="menu_exam_audio_files"
|
||||
name="Audio Files"
|
||||
parent="encoach_core.menu_encoach_exams"
|
||||
action="action_audio_file"
|
||||
sequence="4"/>
|
||||
|
||||
<menuitem id="menu_exam_writing_prompts"
|
||||
name="Writing Prompts"
|
||||
parent="encoach_core.menu_encoach_exams"
|
||||
action="action_writing_prompt"
|
||||
sequence="5"/>
|
||||
|
||||
<menuitem id="menu_exam_speaking_cards"
|
||||
name="Speaking Cards"
|
||||
parent="encoach_core.menu_encoach_exams"
|
||||
action="action_speaking_card"
|
||||
sequence="6"/>
|
||||
|
||||
<menuitem id="menu_exam_rubrics"
|
||||
name="Rubrics"
|
||||
parent="encoach_core.menu_encoach_exams"
|
||||
action="action_rubric"
|
||||
sequence="7"/>
|
||||
|
||||
<menuitem id="menu_exam_custom_exams"
|
||||
name="Custom Exams"
|
||||
parent="encoach_core.menu_encoach_exams"
|
||||
action="action_exam_custom"
|
||||
sequence="8"/>
|
||||
|
||||
<menuitem id="menu_exam_assignments"
|
||||
name="Exam Assignments"
|
||||
parent="encoach_core.menu_encoach_exams"
|
||||
action="action_exam_assignment"
|
||||
sequence="9"/>
|
||||
|
||||
</odoo>
|
||||
@@ -0,0 +1,101 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- Exam Template Views -->
|
||||
<!-- ============================================================ -->
|
||||
|
||||
<record id="view_exam_template_form" model="ir.ui.view">
|
||||
<field name="name">encoach.exam.template.form</field>
|
||||
<field name="model">encoach.exam.template</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Exam Template">
|
||||
<sheet>
|
||||
<div class="oe_button_box" name="button_box"/>
|
||||
<widget name="web_ribbon" title="Archived" bg_color="text-bg-danger" invisible="active"/>
|
||||
<div class="oe_title">
|
||||
<h1>
|
||||
<field name="name" placeholder="Template Name"/>
|
||||
</h1>
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="code"/>
|
||||
<field name="type"/>
|
||||
<field name="subject_id"/>
|
||||
<field name="entity_id"/>
|
||||
<field name="teacher_id"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="total_time_min"/>
|
||||
<field name="pass_threshold"/>
|
||||
<field name="results_release_mode"/>
|
||||
<field name="randomize_questions"/>
|
||||
<field name="editable"/>
|
||||
<field name="active" invisible="1"/>
|
||||
</group>
|
||||
</group>
|
||||
<group>
|
||||
<field name="description" placeholder="Describe this exam template..."/>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Structure" name="structure">
|
||||
<field name="structure" widget="text"/>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_exam_template_list" model="ir.ui.view">
|
||||
<field name="name">encoach.exam.template.list</field>
|
||||
<field name="model">encoach.exam.template</field>
|
||||
<field name="arch" type="xml">
|
||||
<list string="Exam Templates">
|
||||
<field name="name"/>
|
||||
<field name="code"/>
|
||||
<field name="type"/>
|
||||
<field name="subject_id"/>
|
||||
<field name="entity_id"/>
|
||||
<field name="total_time_min" string="Time (min)"/>
|
||||
<field name="active"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_exam_template_search" model="ir.ui.view">
|
||||
<field name="name">encoach.exam.template.search</field>
|
||||
<field name="model">encoach.exam.template</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Exam Templates">
|
||||
<field name="name"/>
|
||||
<field name="code"/>
|
||||
<field name="subject_id"/>
|
||||
<field name="entity_id"/>
|
||||
<separator/>
|
||||
<filter string="International" name="filter_international" domain="[('type', '=', 'international')]"/>
|
||||
<filter string="Custom" name="filter_custom" domain="[('type', '=', 'custom')]"/>
|
||||
<separator/>
|
||||
<filter string="Active" name="filter_active" domain="[('active', '=', True)]"/>
|
||||
<filter string="Archived" name="filter_archived" domain="[('active', '=', False)]"/>
|
||||
<filter string="Type" name="group_type" context="{'group_by': 'type'}"/>
|
||||
<filter string="Subject" name="group_subject" context="{'group_by': 'subject_id'}"/>
|
||||
<filter string="Entity" name="group_entity" context="{'group_by': 'entity_id'}"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_exam_template" model="ir.actions.act_window">
|
||||
<field name="name">Exam Templates</field>
|
||||
<field name="res_model">encoach.exam.template</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="search_view_id" ref="view_exam_template_search"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Create your first exam template
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="action_exam_validation" model="ir.actions.client">
|
||||
<field name="name">Exam Validation</field>
|
||||
<field name="tag">encoach_exam_validation</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="menu_exam_validation"
|
||||
name="Exam Validation"
|
||||
parent="encoach_core.menu_encoach_content"
|
||||
action="action_exam_validation"
|
||||
sequence="10"/>
|
||||
|
||||
</odoo>
|
||||
105
custom_addons/encoach_exam_template/views/passage_views.xml
Normal file
105
custom_addons/encoach_exam_template/views/passage_views.xml
Normal file
@@ -0,0 +1,105 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- Passage Views -->
|
||||
<!-- ============================================================ -->
|
||||
|
||||
<record id="view_passage_form" model="ir.ui.view">
|
||||
<field name="name">encoach.passage.form</field>
|
||||
<field name="model">encoach.passage</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Reading Passage">
|
||||
<sheet>
|
||||
<div class="oe_title">
|
||||
<h1>
|
||||
<field name="topic_category" placeholder="Topic Category"/>
|
||||
</h1>
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="exam_type"/>
|
||||
<field name="section_num"/>
|
||||
<field name="difficulty"/>
|
||||
<field name="status"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="cefr_level"/>
|
||||
<field name="word_count"/>
|
||||
<field name="ai_generated"/>
|
||||
<field name="approved"/>
|
||||
<field name="ielts_certified"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Body Text" name="body_text">
|
||||
<field name="body_text" widget="text" placeholder="Paste or write the passage text..."/>
|
||||
</page>
|
||||
<page string="Validation" name="validation">
|
||||
<group>
|
||||
<field name="generation_brief"/>
|
||||
<field name="validation_errors"/>
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_passage_list" model="ir.ui.view">
|
||||
<field name="name">encoach.passage.list</field>
|
||||
<field name="model">encoach.passage</field>
|
||||
<field name="arch" type="xml">
|
||||
<list string="Passages" decoration-success="approved == True" decoration-muted="status == 'retired'">
|
||||
<field name="topic_category"/>
|
||||
<field name="exam_type"/>
|
||||
<field name="difficulty"/>
|
||||
<field name="status"/>
|
||||
<field name="word_count"/>
|
||||
<field name="approved"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_passage_search" model="ir.ui.view">
|
||||
<field name="name">encoach.passage.search</field>
|
||||
<field name="model">encoach.passage</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Passages">
|
||||
<field name="topic_category"/>
|
||||
<separator/>
|
||||
<filter string="Academic" name="filter_academic" domain="[('exam_type', '=', 'academic')]"/>
|
||||
<filter string="General Training" name="filter_general" domain="[('exam_type', '=', 'general_training')]"/>
|
||||
<filter string="General English" name="filter_general_eng" domain="[('exam_type', '=', 'general_english')]"/>
|
||||
<separator/>
|
||||
<filter string="Draft" name="filter_draft" domain="[('status', '=', 'draft')]"/>
|
||||
<filter string="Active" name="filter_active" domain="[('status', '=', 'active')]"/>
|
||||
<filter string="Flagged" name="filter_flagged" domain="[('status', '=', 'flagged')]"/>
|
||||
<separator/>
|
||||
<filter string="Easy" name="filter_easy" domain="[('difficulty', '=', 'easy')]"/>
|
||||
<filter string="Medium" name="filter_medium" domain="[('difficulty', '=', 'medium')]"/>
|
||||
<filter string="Hard" name="filter_hard" domain="[('difficulty', '=', 'hard')]"/>
|
||||
<separator/>
|
||||
<filter string="Approved" name="filter_approved" domain="[('approved', '=', True)]"/>
|
||||
<filter string="Not Approved" name="filter_not_approved" domain="[('approved', '=', False)]"/>
|
||||
<filter string="Exam Type" name="group_exam_type" context="{'group_by': 'exam_type'}"/>
|
||||
<filter string="Status" name="group_status" context="{'group_by': 'status'}"/>
|
||||
<filter string="Difficulty" name="group_difficulty" context="{'group_by': 'difficulty'}"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_passage" model="ir.actions.act_window">
|
||||
<field name="name">Passages</field>
|
||||
<field name="res_model">encoach.passage</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="search_view_id" ref="view_passage_search"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Create your first reading passage
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
128
custom_addons/encoach_exam_template/views/question_views.xml
Normal file
128
custom_addons/encoach_exam_template/views/question_views.xml
Normal file
@@ -0,0 +1,128 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- Question Views -->
|
||||
<!-- ============================================================ -->
|
||||
|
||||
<record id="view_question_form" model="ir.ui.view">
|
||||
<field name="name">encoach.question.form</field>
|
||||
<field name="model">encoach.question</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Question">
|
||||
<sheet>
|
||||
<group>
|
||||
<group string="Classification">
|
||||
<field name="skill"/>
|
||||
<field name="question_type"/>
|
||||
<field name="difficulty"/>
|
||||
<field name="status"/>
|
||||
</group>
|
||||
<group string="Taxonomy">
|
||||
<field name="subject_id"/>
|
||||
<field name="topic_id"/>
|
||||
<field name="marks"/>
|
||||
<field name="source_type"/>
|
||||
<field name="source_id" invisible="not source_type"/>
|
||||
</group>
|
||||
</group>
|
||||
<group string="Question Content">
|
||||
<field name="stem" widget="text" placeholder="Enter the question stem..."/>
|
||||
</group>
|
||||
<group>
|
||||
<group>
|
||||
<field name="options" widget="text" placeholder='JSON array: ["A", "B", "C", "D"]'/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="correct_answer" widget="text"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="IRT Parameters" name="irt">
|
||||
<group>
|
||||
<group>
|
||||
<field name="irt_a" string="Discrimination (a)"/>
|
||||
<field name="irt_b" string="Difficulty (b)"/>
|
||||
<field name="irt_c" string="Guessing (c)"/>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
<page string="Flags" name="flags">
|
||||
<group>
|
||||
<group>
|
||||
<field name="ai_generated"/>
|
||||
<field name="ielts_certified"/>
|
||||
<field name="format_validated"/>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_question_list" model="ir.ui.view">
|
||||
<field name="name">encoach.question.list</field>
|
||||
<field name="model">encoach.question</field>
|
||||
<field name="arch" type="xml">
|
||||
<list string="Questions" decoration-muted="status == 'retired'" decoration-danger="status == 'flagged'">
|
||||
<field name="stem" string="Question" widget="char"/>
|
||||
<field name="skill"/>
|
||||
<field name="question_type"/>
|
||||
<field name="difficulty"/>
|
||||
<field name="status"/>
|
||||
<field name="marks"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_question_search" model="ir.ui.view">
|
||||
<field name="name">encoach.question.search</field>
|
||||
<field name="model">encoach.question</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Questions">
|
||||
<field name="stem"/>
|
||||
<field name="subject_id"/>
|
||||
<field name="topic_id"/>
|
||||
<separator/>
|
||||
<filter string="Listening" name="filter_listening" domain="[('skill', '=', 'listening')]"/>
|
||||
<filter string="Reading" name="filter_reading" domain="[('skill', '=', 'reading')]"/>
|
||||
<filter string="Writing" name="filter_writing" domain="[('skill', '=', 'writing')]"/>
|
||||
<filter string="Speaking" name="filter_speaking" domain="[('skill', '=', 'speaking')]"/>
|
||||
<filter string="Grammar" name="filter_grammar" domain="[('skill', '=', 'grammar')]"/>
|
||||
<filter string="Vocabulary" name="filter_vocabulary" domain="[('skill', '=', 'vocabulary')]"/>
|
||||
<separator/>
|
||||
<filter string="MCQ" name="filter_mcq" domain="[('question_type', '=', 'mcq')]"/>
|
||||
<filter string="Gap Fill" name="filter_gap_fill" domain="[('question_type', '=', 'gap_fill')]"/>
|
||||
<filter string="Matching" name="filter_matching" domain="[('question_type', '=', 'matching')]"/>
|
||||
<separator/>
|
||||
<filter string="Easy" name="filter_easy" domain="[('difficulty', '=', 'easy')]"/>
|
||||
<filter string="Medium" name="filter_medium" domain="[('difficulty', '=', 'medium')]"/>
|
||||
<filter string="Hard" name="filter_hard" domain="[('difficulty', '=', 'hard')]"/>
|
||||
<separator/>
|
||||
<filter string="Draft" name="filter_draft" domain="[('status', '=', 'draft')]"/>
|
||||
<filter string="Active" name="filter_active" domain="[('status', '=', 'active')]"/>
|
||||
<filter string="Flagged" name="filter_flagged" domain="[('status', '=', 'flagged')]"/>
|
||||
<filter string="Skill" name="group_skill" context="{'group_by': 'skill'}"/>
|
||||
<filter string="Type" name="group_type" context="{'group_by': 'question_type'}"/>
|
||||
<filter string="Difficulty" name="group_difficulty" context="{'group_by': 'difficulty'}"/>
|
||||
<filter string="Status" name="group_status" context="{'group_by': 'status'}"/>
|
||||
<filter string="Subject" name="group_subject" context="{'group_by': 'subject_id'}"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_question" model="ir.actions.act_window">
|
||||
<field name="name">Question Bank</field>
|
||||
<field name="res_model">encoach.question</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="search_view_id" ref="view_question_search"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Add your first question to the bank
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
77
custom_addons/encoach_exam_template/views/rubric_views.xml
Normal file
77
custom_addons/encoach_exam_template/views/rubric_views.xml
Normal file
@@ -0,0 +1,77 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- Rubric Views -->
|
||||
<!-- ============================================================ -->
|
||||
|
||||
<record id="view_rubric_form" model="ir.ui.view">
|
||||
<field name="name">encoach.rubric.form</field>
|
||||
<field name="model">encoach.rubric</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Rubric">
|
||||
<sheet>
|
||||
<div class="oe_title">
|
||||
<h1>
|
||||
<field name="name" placeholder="Rubric Name"/>
|
||||
</h1>
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="skill"/>
|
||||
<field name="exam_type"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Criteria" name="criteria">
|
||||
<field name="criteria" widget="text" placeholder="Define rubric criteria (JSON or structured text)..."/>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_rubric_list" model="ir.ui.view">
|
||||
<field name="name">encoach.rubric.list</field>
|
||||
<field name="model">encoach.rubric</field>
|
||||
<field name="arch" type="xml">
|
||||
<list string="Rubrics">
|
||||
<field name="name"/>
|
||||
<field name="skill"/>
|
||||
<field name="exam_type"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_rubric_search" model="ir.ui.view">
|
||||
<field name="name">encoach.rubric.search</field>
|
||||
<field name="model">encoach.rubric</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Rubrics">
|
||||
<field name="name"/>
|
||||
<separator/>
|
||||
<filter string="Writing" name="filter_writing" domain="[('skill', '=', 'writing')]"/>
|
||||
<filter string="Speaking" name="filter_speaking" domain="[('skill', '=', 'speaking')]"/>
|
||||
<separator/>
|
||||
<filter string="Academic" name="filter_academic" domain="[('exam_type', '=', 'academic')]"/>
|
||||
<filter string="General Training" name="filter_general" domain="[('exam_type', '=', 'general_training')]"/>
|
||||
<filter string="Skill" name="group_skill" context="{'group_by': 'skill'}"/>
|
||||
<filter string="Exam Type" name="group_exam_type" context="{'group_by': 'exam_type'}"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_rubric" model="ir.actions.act_window">
|
||||
<field name="name">Rubrics</field>
|
||||
<field name="res_model">encoach.rubric</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="search_view_id" ref="view_rubric_search"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Create your first scoring rubric
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -0,0 +1,103 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- Speaking Card Views -->
|
||||
<!-- ============================================================ -->
|
||||
|
||||
<record id="view_speaking_card_form" model="ir.ui.view">
|
||||
<field name="name">encoach.speaking.card.form</field>
|
||||
<field name="model">encoach.speaking.card</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Speaking Card">
|
||||
<sheet>
|
||||
<div class="oe_title">
|
||||
<h1>
|
||||
<field name="topic" placeholder="Speaking Topic"/>
|
||||
</h1>
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="part"/>
|
||||
<field name="difficulty"/>
|
||||
<field name="linked_card_id"/>
|
||||
<field name="rubric_id"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="ai_generated"/>
|
||||
<field name="approved"/>
|
||||
<field name="ielts_certified"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Questions" name="questions">
|
||||
<field name="questions" widget="text" placeholder="Questions for the candidate..."/>
|
||||
</page>
|
||||
<page string="Bullet Points" name="bullet_points">
|
||||
<field name="bullet_points" widget="text"/>
|
||||
</page>
|
||||
<page string="Model Response" name="model_response">
|
||||
<field name="model_response" widget="text"/>
|
||||
</page>
|
||||
<page string="Validation" name="validation">
|
||||
<group>
|
||||
<field name="generation_brief"/>
|
||||
<field name="validation_errors"/>
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_speaking_card_list" model="ir.ui.view">
|
||||
<field name="name">encoach.speaking.card.list</field>
|
||||
<field name="model">encoach.speaking.card</field>
|
||||
<field name="arch" type="xml">
|
||||
<list string="Speaking Cards" decoration-success="approved == True">
|
||||
<field name="topic"/>
|
||||
<field name="part"/>
|
||||
<field name="difficulty"/>
|
||||
<field name="linked_card_id"/>
|
||||
<field name="approved"/>
|
||||
<field name="ielts_certified"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_speaking_card_search" model="ir.ui.view">
|
||||
<field name="name">encoach.speaking.card.search</field>
|
||||
<field name="model">encoach.speaking.card</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Speaking Cards">
|
||||
<field name="topic"/>
|
||||
<separator/>
|
||||
<filter string="Part 1" name="filter_part1" domain="[('part', '=', 1)]"/>
|
||||
<filter string="Part 2" name="filter_part2" domain="[('part', '=', 2)]"/>
|
||||
<filter string="Part 3" name="filter_part3" domain="[('part', '=', 3)]"/>
|
||||
<separator/>
|
||||
<filter string="Easy" name="filter_easy" domain="[('difficulty', '=', 'easy')]"/>
|
||||
<filter string="Medium" name="filter_medium" domain="[('difficulty', '=', 'medium')]"/>
|
||||
<filter string="Hard" name="filter_hard" domain="[('difficulty', '=', 'hard')]"/>
|
||||
<separator/>
|
||||
<filter string="Approved" name="filter_approved" domain="[('approved', '=', True)]"/>
|
||||
<filter string="Part" name="group_part" context="{'group_by': 'part'}"/>
|
||||
<filter string="Difficulty" name="group_difficulty" context="{'group_by': 'difficulty'}"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_speaking_card" model="ir.actions.act_window">
|
||||
<field name="name">Speaking Cards</field>
|
||||
<field name="res_model">encoach.speaking.card</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="search_view_id" ref="view_speaking_card_search"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Create your first speaking cue card
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -0,0 +1,95 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- Writing Prompt Views -->
|
||||
<!-- ============================================================ -->
|
||||
|
||||
<record id="view_writing_prompt_form" model="ir.ui.view">
|
||||
<field name="name">encoach.writing.prompt.form</field>
|
||||
<field name="model">encoach.writing.prompt</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Writing Prompt">
|
||||
<sheet>
|
||||
<group>
|
||||
<group>
|
||||
<field name="exam_type"/>
|
||||
<field name="task"/>
|
||||
<field name="writing_type"/>
|
||||
<field name="min_words"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="rubric_id"/>
|
||||
<field name="visual_url" widget="url"/>
|
||||
<field name="ai_generated"/>
|
||||
<field name="approved"/>
|
||||
<field name="ielts_certified"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Prompt" name="prompt">
|
||||
<field name="prompt_text" widget="text" placeholder="Write the prompt instructions..."/>
|
||||
</page>
|
||||
<page string="Model Answer" name="model_answer">
|
||||
<field name="model_answer" widget="text"/>
|
||||
</page>
|
||||
<page string="Validation" name="validation">
|
||||
<group>
|
||||
<field name="generation_brief"/>
|
||||
<field name="validation_errors"/>
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_writing_prompt_list" model="ir.ui.view">
|
||||
<field name="name">encoach.writing.prompt.list</field>
|
||||
<field name="model">encoach.writing.prompt</field>
|
||||
<field name="arch" type="xml">
|
||||
<list string="Writing Prompts" decoration-success="approved == True">
|
||||
<field name="exam_type"/>
|
||||
<field name="task"/>
|
||||
<field name="writing_type"/>
|
||||
<field name="min_words"/>
|
||||
<field name="rubric_id"/>
|
||||
<field name="approved"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_writing_prompt_search" model="ir.ui.view">
|
||||
<field name="name">encoach.writing.prompt.search</field>
|
||||
<field name="model">encoach.writing.prompt</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Writing Prompts">
|
||||
<field name="writing_type"/>
|
||||
<separator/>
|
||||
<filter string="Academic" name="filter_academic" domain="[('exam_type', '=', 'academic')]"/>
|
||||
<filter string="General Training" name="filter_general" domain="[('exam_type', '=', 'general_training')]"/>
|
||||
<separator/>
|
||||
<filter string="Task 1" name="filter_task1" domain="[('task', '=', 'task1')]"/>
|
||||
<filter string="Task 2" name="filter_task2" domain="[('task', '=', 'task2')]"/>
|
||||
<separator/>
|
||||
<filter string="Approved" name="filter_approved" domain="[('approved', '=', True)]"/>
|
||||
<filter string="Exam Type" name="group_exam_type" context="{'group_by': 'exam_type'}"/>
|
||||
<filter string="Task" name="group_task" context="{'group_by': 'task'}"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_writing_prompt" model="ir.actions.act_window">
|
||||
<field name="name">Writing Prompts</field>
|
||||
<field name="res_model">encoach.writing.prompt</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="search_view_id" ref="view_writing_prompt_search"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Create your first writing prompt
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user