TNCSC_Odoo/addons/community_school/views/portal_assignment_templates.xml
selvi 40f4b9dc81
Some checks failed
CI / Brand-leak check (push) Has been cancelled
CI / flake8 / pylint-odoo / manifest completeness (push) Has been cancelled
CI / Install all modules with --test-enable (push) Has been cancelled
assignment submission updated
2026-10-06 20:36:21 +05:30

438 lines
26 KiB
XML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- ═══════════════════════════════════════════════════════════
SHARED: No student record found
═══════════════════════════════════════════════════════════ -->
<template id="portal_no_student" name="School: No Student Profile">
<t t-call="website.layout">
<div class="container" style="max-width: 520px; margin-top: 60px;">
<p class="alert alert-info">
No student profile is linked to your account. Please contact the school coordinator.
</p>
</div>
</t>
</template>
<!-- ═══════════════════════════════════════════════════════════
TEACHER: Assignment List
═══════════════════════════════════════════════════════════ -->
<template id="portal_teacher_assignment_list" name="School: Teacher – My Assignments">
<t t-call="website.layout">
<div class="container o_school_assignments" style="max-width: 900px; margin-top: 32px; margin-bottom: 80px;">
<div class="d-flex justify-content-between align-items-center mb-4">
<h2 class="mb-0">My Assignments</h2>
<a href="/school/assignments/teacher/new" class="btn btn-primary">
<i class="fa fa-plus me-1"/> New Assignment
</a>
</div>
<t t-if="not assignments">
<div class="alert alert-info">
No assignments yet. Click <strong>New Assignment</strong> to create one.
</div>
</t>
<t t-if="assignments">
<div class="table-responsive">
<table class="table table-hover align-middle">
<thead class="table-light">
<tr>
<th>Title</th>
<th>Class</th>
<th>Due Date</th>
<th>Status</th>
<th>Submissions</th>
<th></th>
</tr>
</thead>
<tbody>
<t t-foreach="assignments" t-as="asgn">
<tr>
<td>
<strong t-out="asgn.name"/>
</td>
<td t-out="asgn.class_id.name"/>
<td t-out="asgn.due_date" t-options='{"widget": "datetime"}'/>
<td>
<t t-if="asgn.state == 'draft'">
<span class="badge bg-secondary">Draft</span>
</t>
<t t-elif="asgn.state == 'published'">
<span class="badge bg-success">Published</span>
</t>
<t t-elif="asgn.state == 'closed'">
<span class="badge bg-dark">Closed</span>
</t>
</td>
<td>
<a t-attf-href="/school/assignments/teacher/#{asgn.id}/submissions"
class="badge bg-primary text-decoration-none">
<t t-out="asgn.submission_count"/> submitted
</a>
</td>
<td class="text-end">
<a t-attf-href="/school/assignments/teacher/#{asgn.id}/edit"
class="btn btn-sm btn-outline-secondary">Edit</a>
</td>
</tr>
</t>
</tbody>
</table>
</div>
</t>
</div>
</t>
</template>
<!-- ═══════════════════════════════════════════════════════════
TEACHER: Create / Edit Assignment Form
═══════════════════════════════════════════════════════════ -->
<template id="portal_teacher_assignment_form" name="School: Teacher – Assignment Form">
<t t-call="website.layout">
<div class="container o_school_assignment_form" style="max-width: 700px; margin-top: 32px; margin-bottom: 80px;">
<h2>
<t t-if="not assignment">New Assignment</t>
<t t-else="">Edit Assignment</t>
</h2>
<form method="post" enctype="multipart/form-data" class="mt-4">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
<div class="mb-3">
<label class="form-label fw-semibold" for="asgn_title">Title <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="asgn_title" name="title" required="required"
t-att-value="assignment.name if assignment else ''"/>
</div>
<div class="mb-3">
<label class="form-label fw-semibold" for="asgn_class">Class <span class="text-danger">*</span></label>
<select class="form-select" id="asgn_class" name="class_id" required="required">
<option value="">-- Select Class --</option>
<t t-foreach="classes" t-as="klass">
<option t-att-value="klass.id"
t-att-selected="'selected' if assignment and assignment.class_id.id == klass.id else None"
t-out="klass.name"/>
</t>
</select>
</div>
<div class="mb-3">
<label class="form-label fw-semibold" for="asgn_due">Due Date &amp; Time <span class="text-danger">*</span></label>
<input type="datetime-local" class="form-control" id="asgn_due" name="due_date" required="required"
t-att-value="assignment.due_date.strftime('%Y-%m-%dT%H:%M') if assignment and assignment.due_date else ''"/>
</div>
<div class="mb-3">
<label class="form-label fw-semibold" for="asgn_score">Max Score</label>
<input type="number" class="form-control" id="asgn_score" name="max_score" min="1" max="1000"
t-att-value="assignment.max_score if assignment else 100"/>
</div>
<div class="mb-4">
<label class="form-label fw-semibold" for="asgn_desc">Instructions / Description</label>
<textarea class="form-control" id="asgn_desc" name="description" rows="6">
<t t-if="assignment and assignment.description" t-out="assignment.description"/>
</textarea>
</div>
<div class="d-flex gap-2 flex-wrap">
<button type="submit" class="btn btn-primary" name="action_state" value="publish">
<t t-if="not assignment">Create &amp; Publish</t>
<t t-else="">Save &amp; Publish</t>
</button>
<t t-if="assignment">
<t t-if="assignment.state != 'draft'">
<button type="submit" class="btn btn-outline-secondary" name="action_state" value="draft">
Set to Draft
</button>
</t>
<t t-if="assignment.state != 'closed'">
<button type="submit" class="btn btn-outline-dark" name="action_state" value="close">
Close Assignment
</button>
</t>
</t>
<a href="/school/assignments/teacher" class="btn btn-link text-muted">Cancel</a>
</div>
</form>
</div>
</t>
</template>
<!-- ═══════════════════════════════════════════════════════════
TEACHER: View Submissions for an Assignment
═══════════════════════════════════════════════════════════ -->
<template id="portal_teacher_submissions" name="School: Teacher – Submissions">
<t t-call="website.layout">
<div class="container o_school_submissions" style="max-width: 950px; margin-top: 32px; margin-bottom: 80px;">
<a href="/school/assignments/teacher" class="btn btn-sm btn-outline-secondary mb-3">
← Back to Assignments
</a>
<h2 t-out="assignment.name"/>
<p class="text-muted mb-1">
Class: <strong t-out="assignment.class_id.name"/>
· Due: <span t-out="assignment.due_date" t-options='{"widget": "datetime"}'/>
· Max Score: <strong t-out="assignment.max_score"/>
</p>
<t t-if="not submissions">
<div class="alert alert-info mt-4">No submissions received yet.</div>
</t>
<t t-if="submissions">
<div class="table-responsive mt-4">
<table class="table table-hover align-middle">
<thead class="table-light">
<tr>
<th>Student</th>
<th>Submitted On</th>
<th>Late?</th>
<th>File</th>
<th>Notes</th>
<th>Score</th>
<th>Status</th>
<th>Grade</th>
</tr>
</thead>
<tbody>
<t t-foreach="submissions" t-as="sub">
<tr>
<td t-out="sub.student_id.partner_id.name"/>
<td t-out="sub.submitted_on" t-options='{"widget": "datetime"}'/>
<td>
<t t-if="sub.is_late">
<span class="badge bg-warning text-dark">Late</span>
</t>
<t t-else="">
<span class="text-muted">—</span>
</t>
</td>
<td>
<t t-if="sub.attachment_name">
<a t-attf-href="/web/content/community.school.submission/#{sub.id}/attachment_data/#{sub.attachment_name}?download=true"
class="btn btn-sm btn-outline-primary">
<i class="fa fa-download me-1"/>
<t t-out="sub.attachment_name"/>
</a>
</t>
<t t-else=""><span class="text-muted">No file</span></t>
</td>
<td>
<t t-if="sub.notes">
<small t-out="sub.notes"/>
</t>
<t t-else=""><span class="text-muted">—</span></t>
</td>
<td>
<t t-if="sub.state == 'graded'">
<strong t-out="sub.score"/> / <t t-out="assignment.max_score"/>
</t>
<t t-else=""><span class="text-muted">—</span></t>
</td>
<td>
<t t-if="sub.state == 'graded'">
<span class="badge bg-success">Graded</span>
</t>
<t t-else="">
<span class="badge bg-secondary">Pending</span>
</t>
</td>
<td>
<!-- Inline grade form -->
<form t-attf-action="/school/assignments/teacher/submission/#{sub.id}/grade"
method="post" class="d-flex gap-1 align-items-center">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
<input type="number" name="score" class="form-control form-control-sm"
style="width: 64px;"
t-att-value="sub.score if sub.state == 'graded' else ''"
t-att-max="assignment.max_score" min="0" placeholder="Pts"/>
<input type="text" name="feedback" class="form-control form-control-sm"
style="width: 110px;"
t-att-value="sub.feedback or ''"
placeholder="Feedback"/>
<button type="submit" class="btn btn-sm btn-success">✓</button>
</form>
</td>
</tr>
</t>
</tbody>
</table>
</div>
</t>
</div>
</t>
</template>
<!-- ═══════════════════════════════════════════════════════════
STUDENT: Assignment List
═══════════════════════════════════════════════════════════ -->
<template id="portal_student_assignment_list" name="School: Student – Assignments">
<t t-call="website.layout">
<div class="container o_school_student_assignments" style="max-width: 860px; margin-top: 32px; margin-bottom: 80px;">
<h2 class="mb-4">My Assignments</h2>
<t t-if="not assignments">
<div class="alert alert-info">No assignments have been published for your class yet.</div>
</t>
<t t-if="assignments">
<div class="row g-3">
<t t-foreach="assignments" t-as="asgn">
<div class="col-md-6">
<t t-set="my_sub" t-value="submission_by_assignment.get(asgn.id)"/>
<div class="card h-100 shadow-sm border-0">
<div class="card-body">
<div class="d-flex justify-content-between align-items-start mb-2">
<h5 class="card-title mb-0" t-out="asgn.name"/>
<t t-if="my_sub and my_sub.state == 'graded'">
<span class="badge bg-success">Graded</span>
</t>
<t t-elif="my_sub">
<span class="badge bg-primary">Submitted</span>
</t>
<t t-else="">
<span class="badge bg-warning text-dark">Pending</span>
</t>
</div>
<p class="text-muted small mb-1">
Class: <strong t-out="asgn.class_id.name"/>
</p>
<p class="text-muted small mb-2">
Due: <strong t-out="asgn.due_date" t-options='{"widget": "datetime"}'/>
</p>
<t t-if="my_sub and my_sub.state == 'graded'">
<p class="mb-2">
Score: <strong t-out="my_sub.score"/> / <t t-out="asgn.max_score"/>
</p>
<t t-if="my_sub.feedback">
<p class="text-muted small mb-2">
Feedback: <em t-out="my_sub.feedback"/>
</p>
</t>
</t>
</div>
<div class="card-footer bg-transparent border-0 pt-0">
<a t-attf-href="/school/assignments/student/#{asgn.id}"
class="btn btn-sm btn-primary w-100">
<t t-if="not my_sub">View &amp; Submit</t>
<t t-else="">View Submission</t>
</a>
</div>
</div>
</div>
</t>
</div>
</t>
</div>
</t>
</template>
<!-- ═══════════════════════════════════════════════════════════
STUDENT: Assignment Detail & Upload Form
═══════════════════════════════════════════════════════════ -->
<template id="portal_student_assignment_detail" name="School: Student – Assignment Detail">
<t t-call="website.layout">
<div class="container o_school_assignment_detail" style="max-width: 720px; margin-top: 32px; margin-bottom: 80px;">
<a href="/school/assignments/student" class="btn btn-sm btn-outline-secondary mb-3">
← Back to Assignments
</a>
<!-- Assignment header -->
<div class="card border-0 shadow-sm mb-4">
<div class="card-body">
<h3 t-out="assignment.name"/>
<p class="text-muted mb-1">
Class: <strong t-out="assignment.class_id.name"/>
</p>
<p class="text-muted mb-1">
Due: <strong t-out="assignment.due_date" t-options='{"widget": "datetime"}'/>
</p>
<p class="text-muted mb-0">
Max Score: <strong t-out="assignment.max_score"/>
</p>
<t t-if="assignment.description">
<hr/>
<div t-out="assignment.description"/>
</t>
</div>
</div>
<!-- Already submitted view -->
<t t-if="submission">
<div class="card border-0 shadow-sm">
<div class="card-body">
<h5>Your Submission</h5>
<p class="text-muted small">
Submitted on: <t t-out="submission.submitted_on" t-options='{"widget": "datetime"}'/>
<t t-if="submission.is_late">
<span class="badge bg-warning text-dark ms-2">Late</span>
</t>
</p>
<t t-if="submission.notes">
<p><strong>Your Notes:</strong><br/><t t-out="submission.notes"/></p>
</t>
<t t-if="submission.attachment_name">
<a t-attf-href="/web/content/community.school.submission/#{submission.id}/attachment_data/#{submission.attachment_name}?download=true"
class="btn btn-outline-primary">
<i class="fa fa-download me-1"/> Download: <t t-out="submission.attachment_name"/>
</a>
</t>
<!-- Graded result -->
<t t-if="submission.state == 'graded'">
<hr/>
<div class="alert alert-success mb-0">
<h6 class="alert-heading">Graded ✓</h6>
<p class="mb-1">
Score: <strong t-out="submission.score"/> / <t t-out="assignment.max_score"/>
</p>
<t t-if="submission.feedback">
<p class="mb-0">Feedback: <em t-out="submission.feedback"/></p>
</t>
</div>
</t>
<t t-else="">
<div class="alert alert-info mt-3 mb-0">
Your submission is awaiting grading.
</div>
</t>
</div>
</div>
</t>
<!-- Submit form (shown only if not yet submitted) -->
<t t-if="not submission">
<div class="card border-0 shadow-sm">
<div class="card-body">
<h5>Submit Your Work</h5>
<form t-attf-action="/school/assignments/student/#{assignment.id}"
method="post" enctype="multipart/form-data">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
<div class="mb-3">
<label class="form-label fw-semibold" for="sub_file">
Upload File <span class="text-muted fw-normal">(PDF, DOC, JPG, PNG, etc.)</span>
</label>
<input type="file" class="form-control" id="sub_file" name="submission_file"/>
</div>
<div class="mb-4">
<label class="form-label fw-semibold" for="sub_notes">Notes (optional)</label>
<textarea class="form-control" id="sub_notes" name="notes" rows="4"
placeholder="Add any notes or comments for your teacher…"/>
</div>
<button type="submit" class="btn btn-primary">
<i class="fa fa-upload me-1"/> Submit Assignment
</button>
</form>
</div>
</div>
</t>
</div>
</t>
</template>
</odoo>