Curriculum-Backend / backend /app /templates /jinja_diff.html
Lonelyguyse1's picture
deploy: restore with README
2ce19b1
Raw
History Blame Contribute Delete
12 kB
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<style>
@page { size: A4; margin: 14mm 12mm 18mm; }
* { box-sizing: border-box; }
body { margin: 0; padding: 16px; color: #000; font-family: Calibri, Arial, sans-serif; font-size: 10pt; line-height: 1.2; }
.course + .course { break-before: page; page-break-before: always; }
.letterhead { display: flex; align-items: center; justify-content: center; gap: 12pt; margin-bottom: 10pt; }
.seal { width: 41px; height: auto; }
.wordmark { width: 265px; height: auto; }
table { width: 100%; border-collapse: collapse; table-layout: fixed; }
.meta { margin-bottom: -1pt; }
th, td { border: 1pt solid #000; padding: 4pt 5pt; vertical-align: top; overflow-wrap: anywhere; }
th { font-weight: 700; text-align: left; }
.center { text-align: center; }
.label { width: 18%; }
.hour { width: 7%; }
p { margin: 0 0 5pt; }
p:last-child { margin-bottom: 0; }
ul, ol { margin: 0; padding-left: 16pt; }
li { margin-bottom: 3pt; }
li:last-child { margin-bottom: 0; }
.unit-title, .hours { font-weight: 700; }
.unit { margin-bottom: 8pt; }
.unit:last-child { margin-bottom: 0; }
.hours { text-align: right; }
.resource-link { color: inherit; text-decoration: underline; }
.semester-title { margin: 0 0 8pt; text-align: center; font-size: 11pt; font-weight: 700; }
.diff-removed { background: #ffeef0; border-left: 3px solid #b91c1c; padding: 4pt 8pt; margin: 2pt 0; }
.diff-removed .diff-sign { color: #b91c1c; font-weight: 700; margin-right: 4pt; }
.diff-removed .diff-value { text-decoration: line-through; }
.diff-added { background: #f0fdf4; border-left: 3px solid #15803d; padding: 4pt 8pt; margin: 2pt 0; }
.diff-added .diff-sign { color: #15803d; font-weight: 700; margin-right: 4pt; }
.diff-unchanged { margin: 4pt 0; }
.diff-list-item { margin: 2pt 0; padding: 2pt 8pt; }
.diff-list-item.removed { background: #ffeef0; border-left: 3px solid #b91c1c; }
.diff-list-item.added { background: #f0fdf4; border-left: 3px solid #15803d; }
.diff-list-item.unchanged { background: transparent; border-left: 3px solid transparent; padding-left: 5pt; }
.diff-list-item .diff-sign { font-weight: 700; margin-right: 4pt; }
.diff-list-item.removed .diff-sign { color: #b91c1c; }
.diff-list-item.added .diff-sign { color: #15803d; }
.diff-list-item.removed .diff-value { text-decoration: line-through; }
.diff-unit { margin-bottom: 8pt; }
.diff-unit.removed { background: #ffeef0; padding: 8pt; border-left: 3px solid #b91c1c; }
.diff-unit.added { background: #f0fdf4; padding: 8pt; border-left: 3px solid #15803d; }
.diff-unit.changed { background: #fffbeb; padding: 8pt; border-left: 3px solid #b45309; }
.diff-unit.unchanged { margin-bottom: 8pt; }
.diff-unit-header { font-weight: 700; margin-bottom: 4pt; }
.diff-unit-changes { margin-left: 12pt; }
.diff-unit-change { margin: 2pt 0; padding: 2pt 8pt; }
.diff-unit-change .diff-sign { font-weight: 700; margin-right: 4pt; }
.diff-unit-change.removed { background: #ffeef0; color: #b91c1c; }
.diff-unit-change.added { background: #f0fdf4; color: #15803d; }
.diff-unit-change.changed { background: #fffbeb; color: #b45309; }
.footer-bar { position: fixed; left: 0; right: 0; bottom: -14mm; height: 9mm; background: #000; }
</style>
</head>
<body>
<div class="footer-bar"></div>
{% macro diff_inline(diff, fallback="") %}
{% if diff %}
{% if diff.old != "" %}
<div class="diff-removed"><span class="diff-sign">&minus;</span><span class="diff-value">{{ diff.old }}</span></div>
{% endif %}
{% if diff.new != "" %}
<div class="diff-added"><span class="diff-sign">+</span><span class="diff-value">{{ diff.new }}</span></div>
{% endif %}
{% else %}
{{ fallback }}
{% endif %}
{% endmacro %}
{% macro diff_cell(diff, proposed_value) %}
<td>
{% if diff %}
{% if diff.old != "" %}
<div class="diff-removed"><span class="diff-sign">&minus;</span><span class="diff-value">{{ diff.old }}</span></div>
{% endif %}
{% if diff.new != "" %}
<div class="diff-added"><span class="diff-sign">+</span><span class="diff-value">{{ diff.new }}</span></div>
{% endif %}
{% else %}
{{ proposed_value }}
{% endif %}
</td>
{% endmacro %}
{% macro render_list(course_diff, proposed_course, field_name, ordered=false) %}
{% set diff = course_diff[field_name] %}
{% if diff %}
{% if ordered %}<ol>{% else %}<ul>{% endif %}
{% for item in diff.unchanged %}
<li class="diff-list-item unchanged"><span class="diff-sign"> </span><span class="diff-value">{{ item }}</span></li>
{% endfor %}
{% for item in diff.removed %}
<li class="diff-list-item removed"><span class="diff-sign">&minus;</span><span class="diff-value">{{ item }}</span></li>
{% endfor %}
{% for item in diff.added %}
<li class="diff-list-item added"><span class="diff-sign">+</span><span class="diff-value">{{ item }}</span></li>
{% endfor %}
{% if ordered %}</ol>{% else %}</ul>{% endif %}
{% else %}
{% if ordered %}<ol>{% else %}<ul>{% endif %}
{% for item in proposed_course[field_name] %}
<li>{{ item }}</li>
{% endfor %}
{% if ordered %}</ol>{% else %}</ul>{% endif %}
{% endif %}
{% endmacro %}
{% macro render_units(course_diff, proposed_course) %}
{% set units_diff = course_diff.units %}
{% if units_diff %}
{% for unit_entry in units_diff.units %}
{% if unit_entry.kind == "removed" %}
<div class="diff-unit removed">
<div class="diff-unit-header">&minus; {{ unit_entry.unit.title }} ({{ unit_entry.unit.hours }} Hours)</div>
<p>{{ unit_entry.unit.content }}</p>
</div>
{% elif unit_entry.kind == "added" %}
<div class="diff-unit added">
<div class="diff-unit-header">+ {{ unit_entry.unit.title }} ({{ unit_entry.unit.hours }} Hours)</div>
<p>{{ unit_entry.unit.content }}</p>
</div>
{% elif unit_entry.kind == "changed" %}
<div class="diff-unit changed">
<div class="diff-unit-header">~ {{ unit_entry.unit.title }} ({{ unit_entry.unit.hours }} Hours)</div>
<p>{{ unit_entry.unit.content }}</p>
<div class="diff-unit-changes">
{% for field, change in unit_entry.changes.items() %}
<div class="diff-unit-change removed">&minus; {{ field }}: {{ change.old }}</div>
<div class="diff-unit-change added">+ {{ field }}: {{ change.new }}</div>
{% endfor %}
</div>
</div>
{% else %}
<div class="diff-unit unchanged">
<div class="unit-title">{{ unit_entry.unit.title }}</div>
<p>{{ unit_entry.unit.content }}</p>
<p class="hours">{{ unit_entry.unit.hours }} Hours</p>
</div>
{% endif %}
{% endfor %}
{% else %}
{% for unit in proposed_course.units %}
<div class="unit">
<p class="unit-title">{{ unit.title }}</p>
<p>{{ unit.content }}</p>
<p class="hours">{{ unit.hours }} Hours</p>
</div>
{% endfor %}
{% endif %}
{% endmacro %}
{% macro render_course(course_diff, proposed_course) %}
<article class="course">
<header class="letterhead">
<img class="seal" src="{{ pes_logo }}" alt="PES University logo" />
<span class="wordmark">Computer Science and Engineering</span>
</header>
<table class="meta">
<colgroup>
<col class="label" />
<col />
<col class="label" />
<col class="hour" />
<col class="hour" />
<col class="hour" />
<col class="hour" />
<col class="hour" />
</colgroup>
<tbody>
<tr>
<th>Course Code</th>
{{ diff_cell(course_diff.course_code, proposed_course.course_code | course_code_for_year(proposed_course.semester, curriculum_year)) }}
<th>Course Title</th>
<td colspan="5">{{ diff_inline(course_diff.course_title, proposed_course.course_title) }}</td>
</tr>
<tr>
<th rowspan="2">Program</th>
<td rowspan="2">{{ proposed_course.program }}</td>
<th rowspan="2">Hours per week / Credit Assigned</th>
<th class="center">L</th><th class="center">T</th><th class="center">P</th><th class="center">S</th><th class="center">C</th>
</tr>
<tr>
<td class="center">{{ proposed_course.lecture_hours }}</td>
<td class="center">{{ proposed_course.tutorial_hours }}</td>
<td class="center">{{ proposed_course.practical_hours }}</td>
<td class="center">{{ proposed_course.self_study }}</td>
<td class="center">{{ proposed_course.credits }}</td>
</tr>
<tr>
<th>Semester</th>
<td>{{ proposed_course.semester }}</td>
<th>Type of Course</th>
<td colspan="5">{{ proposed_course.course_type }}</td>
</tr>
<tr>
<th>AI Tools / Tools / Languages</th>
{{ diff_cell(course_diff.tools_languages, proposed_course.tools_languages) }}
<th>Desirable Knowledge</th>
<td colspan="5">{{ diff_inline(course_diff.desirable_knowledge, proposed_course.desirable_knowledge) }}</td>
</tr>
</tbody>
</table>
<table>
<colgroup>
<col class="label" />
<col />
</colgroup>
<tbody>
<tr>
<th>Prelude</th>
<td>{{ diff_inline(course_diff.prelude, proposed_course.prelude) }}</td>
</tr>
<tr>
<th>Course Objectives:</th>
<td>{{ render_list(course_diff, proposed_course, "objectives") }}</td>
</tr>
<tr>
<th>Course Contents</th>
<td>{{ render_units(course_diff, proposed_course) }}</td>
</tr>
{% if proposed_course.lab_experiments %}
<tr>
<th>Laboratory</th>
<td>{{ render_list(course_diff, proposed_course, "lab_experiments", ordered=true) }}</td>
</tr>
{% endif %}
<tr>
<th>Text Book(s):</th>
<td>{{ render_list(course_diff, proposed_course, "text_books", ordered=true) }}</td>
</tr>
{% if proposed_course.reference_books %}
<tr>
<th>Reference Book(s):</th>
<td>{{ render_list(course_diff, proposed_course, "reference_books", ordered=true) }}</td>
</tr>
{% endif %}
{% if proposed_course.course_outcomes %}
<tr>
<th>Course Outcome</th>
<td>{{ render_list(course_diff, proposed_course, "course_outcomes") }}</td>
</tr>
{% endif %}
</tbody>
</table>
</article>
{% endmacro %}
{% if course_diff is defined and course_diff %}
{{ render_course(course_diff, proposed) }}
{% elif course_diffs is defined and course_diffs %}
{% for cd in course_diffs %}
{{ render_course(cd.course_diff, cd.proposed) }}
{% endfor %}
{% else %}
<div style="padding: 20pt; text-align: center; font-weight: 700;">No diff data available</div>
{% endif %}
</body>
</html>