Skip to content

Commit db2ed23

Browse files
Update course admin and course UI
1 parent 8ecb3c4 commit db2ed23

27 files changed

Lines changed: 1638 additions & 329 deletions

cadmin/templates/cadmin/course_admin.html

Lines changed: 122 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -12,50 +12,154 @@
1212
<div>
1313
<p class="text-sm font-semibold uppercase tracking-wide app-muted">Admin Panel</p>
1414
<h1 class="mt-2 text-2xl font-semibold app-heading md:text-3xl">{{ course.title }}</h1>
15-
<p class="mt-1 text-sm app-muted">Operational controls for homework, projects, enrollments, and public course surfaces.</p>
15+
<p class="mt-1 text-sm app-muted">Start with operational tasks, then use the full lists for reference and maintenance.</p>
1616
</div>
1717
<div class="grid grid-cols-2 gap-2 sm:flex sm:flex-wrap lg:justify-end">
18-
<a href="{% url 'course' course.slug %}" class="primer-button primer-button-secondary">View Course Page</a>
19-
<a href="{% url 'dashboard' course.slug %}" class="primer-button primer-button-secondary">Course Dashboard</a>
18+
<a href="{% url 'course' course.slug %}" class="primer-button primer-button-secondary">Course Page</a>
19+
<a href="{% url 'dashboard' course.slug %}" class="primer-button primer-button-secondary">Dashboard</a>
2020
<a href="{% url 'leaderboard' course.slug %}" class="primer-button">Leaderboard</a>
2121
<a href="/admin/courses/course/{{ course.id }}/change/" class="primer-button primer-button-secondary">
2222
<i class="fas fa-edit"></i> Django Admin
2323
</a>
2424
</div>
2525
</div>
26+
</section>
2627

27-
<div class="mt-4 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
28+
<section class="mt-6">
29+
<div class="mb-3 flex flex-col gap-2 sm:flex-row sm:items-end sm:justify-between">
2830
<div>
29-
<p class="text-xs font-semibold uppercase app-muted">Total Enrollments</p>
30-
<p class="mt-0.5 text-xl font-semibold app-heading">{{ total_enrollments }}</p>
31+
<h2 class="text-base font-semibold app-heading">Needs attention</h2>
32+
<p class="mt-1 text-sm app-muted">Operational work that is easy to miss in the full homework and project lists.</p>
3133
</div>
32-
<a href="{% url 'cadmin_enrollments' course.slug %}" class="primer-button w-fit">Manage Enrollments</a>
34+
<span class="inline-flex w-fit rounded-full app-badge-info px-2.5 py-1 text-xs font-semibold">
35+
{{ needs_attention_count }} items
36+
</span>
37+
</div>
38+
39+
<div class="grid gap-3 lg:grid-cols-2">
40+
<article class="rounded-md border app-border app-surface p-4">
41+
<div class="flex items-start justify-between gap-3">
42+
<div>
43+
<h3 class="font-semibold app-heading">Homework scoring</h3>
44+
<p class="mt-1 text-sm app-muted">Recalculate homework scores when submissions need staff attention.</p>
45+
</div>
46+
<span class="rounded-md app-surface-muted px-2 py-1 text-sm font-semibold app-heading">{{ homework_needing_score|length }}</span>
47+
</div>
48+
{% if homework_needing_score %}
49+
<div class="mt-3 divide-y app-divide">
50+
{% for hw in homework_needing_score %}
51+
<div class="py-3">
52+
<div class="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
53+
<div class="min-w-0">
54+
<a href="{% url 'cadmin_homework_submissions' course.slug hw.slug %}" class="font-medium app-link hover:underline">{{ hw.title }}</a>
55+
<p class="mt-1 text-xs app-muted">{{ hw.submissions_count }} submissions · due <span class="local-date" data-timestamp="{{ hw.due_date|date:'U' }}">{{ hw.due_date|date:"j F Y, H:i" }}</span></p>
56+
</div>
57+
<form method="post" action="{% url 'cadmin_homework_score' course.slug hw.slug %}" onsubmit="return confirm('Score all submissions for {{ hw.title }}?');">
58+
{% csrf_token %}
59+
<button type="submit" class="primer-button cadmin-primary">Score submissions</button>
60+
</form>
61+
</div>
62+
</div>
63+
{% endfor %}
64+
</div>
65+
{% else %}
66+
<p class="mt-3 text-sm app-muted">No homework with submissions is waiting for scoring.</p>
67+
{% endif %}
68+
</article>
69+
70+
<article class="rounded-md border app-border app-surface p-4">
71+
<div class="flex items-start justify-between gap-3">
72+
<div>
73+
<h3 class="font-semibold app-heading">Project review flow</h3>
74+
<p class="mt-1 text-sm app-muted">Assign peer reviews or score projects when the course reaches those stages.</p>
75+
</div>
76+
<span class="rounded-md app-surface-muted px-2 py-1 text-sm font-semibold app-heading">{{ project_action_count }}</span>
77+
</div>
78+
{% if projects_needing_reviews or projects_needing_score %}
79+
<div class="mt-3 divide-y app-divide">
80+
{% for proj in projects_needing_reviews %}
81+
<div class="flex flex-col gap-2 py-3 sm:flex-row sm:items-center sm:justify-between">
82+
<div class="min-w-0">
83+
<a href="{% url 'cadmin_project_submissions' course.slug proj.slug %}" class="font-medium app-link hover:underline">{{ proj.title }}</a>
84+
<p class="mt-1 text-xs app-muted">{{ proj.submissions_count }} submissions · collecting submissions</p>
85+
</div>
86+
<form method="post" action="{% url 'cadmin_project_assign_reviews' course.slug proj.slug %}" onsubmit="return confirm('Assign peer reviews for {{ proj.title }}?');">
87+
{% csrf_token %}
88+
<button type="submit" class="primer-button">Assign peer reviews</button>
89+
</form>
90+
</div>
91+
{% endfor %}
92+
{% for proj in projects_needing_score %}
93+
<div class="flex flex-col gap-2 py-3 sm:flex-row sm:items-center sm:justify-between">
94+
<div class="min-w-0">
95+
<a href="{% url 'cadmin_project_submissions' course.slug proj.slug %}" class="font-medium app-link hover:underline">{{ proj.title }}</a>
96+
<p class="mt-1 text-xs app-muted">{{ proj.submissions_count }} submissions · peer review finished</p>
97+
</div>
98+
<form method="post" action="{% url 'cadmin_project_score' course.slug proj.slug %}" onsubmit="return confirm('Score all submissions for {{ proj.title }}?');">
99+
{% csrf_token %}
100+
<button type="submit" class="primer-button cadmin-primary">Score projects</button>
101+
</form>
102+
</div>
103+
{% endfor %}
104+
</div>
105+
{% else %}
106+
<p class="mt-3 text-sm app-muted">No project review action is currently due.</p>
107+
{% endif %}
108+
</article>
33109
</div>
34110
</section>
35111

36112
<section class="mt-6">
113+
<article class="rounded-md border app-border app-surface p-4">
114+
<h2 class="text-base font-semibold app-heading">Student support</h2>
115+
<p class="mt-1 text-sm app-muted">Find students, inspect score breakdowns, and handle Learning in Public exceptions.</p>
116+
<div class="mt-4 grid grid-cols-2 gap-2 text-sm sm:grid-cols-4">
117+
<div class="rounded-md app-surface-muted p-3">
118+
<p class="text-xs font-semibold uppercase app-muted">Enrollments</p>
119+
<p class="mt-1 text-lg font-semibold app-heading">{{ total_enrollments }}</p>
120+
</div>
121+
<div class="rounded-md app-surface-muted p-3">
122+
<p class="text-xs font-semibold uppercase app-muted">LiP disabled</p>
123+
<p class="mt-1 text-lg font-semibold app-heading">{{ support_metrics.disabled_lip }}</p>
124+
</div>
125+
<div class="rounded-md app-surface-muted p-3">
126+
<p class="text-xs font-semibold uppercase app-muted">Zero score</p>
127+
<p class="mt-1 text-lg font-semibold app-heading">{{ support_metrics.zero_score }}</p>
128+
</div>
129+
<div class="rounded-md app-surface-muted p-3">
130+
<p class="text-xs font-semibold uppercase app-muted">Hidden</p>
131+
<p class="mt-1 text-lg font-semibold app-heading">{{ support_metrics.hidden_leaderboard }}</p>
132+
</div>
133+
</div>
134+
<div class="mt-4 flex flex-wrap gap-2">
135+
<a href="{% url 'cadmin_enrollments' course.slug %}" class="primer-button cadmin-primary">Find student</a>
136+
<a href="{% url 'leaderboard' course.slug %}" class="primer-button primer-button-secondary">Open leaderboard</a>
137+
</div>
138+
</article>
139+
</section>
140+
141+
<section class="mt-6 border-t app-border pt-5">
37142
<div class="mb-3">
38-
<h2 class="text-base font-semibold app-heading">Homework</h2>
39-
<p class="mt-1 text-sm app-muted">Review submissions first; scoring actions are grouped at the end of each row.</p>
143+
<h2 class="text-base font-semibold app-heading">All homework</h2>
144+
<p class="mt-1 text-sm app-muted">Reference list for public pages, Django edits, submissions, and per-homework operations.</p>
40145
</div>
41146

42147
{% if homeworks %}
43-
<div class="hidden border-b app-border pb-2 text-xs font-semibold uppercase app-muted md:grid md:grid-cols-[minmax(0,1fr)_14rem_7rem_14rem] md:gap-3">
148+
<div class="hidden border-b app-border pb-2 text-xs font-semibold uppercase app-muted md:grid md:grid-cols-[minmax(0,1fr)_14rem_7rem] md:gap-3">
44149
<div>Homework</div>
45150
<div>Due date</div>
46151
<div class="text-right">State</div>
47-
<div class="text-right">Actions</div>
48152
</div>
49153

50154
<div class="divide-y app-divide">
51155
{% for hw in homeworks %}
52156
<article class="py-2.5 md:py-3">
53-
<div class="grid gap-2.5 md:grid-cols-[minmax(0,1fr)_14rem_7rem_14rem] md:items-center md:gap-3">
157+
<div class="grid gap-2.5 md:grid-cols-[minmax(0,1fr)_14rem_7rem] md:items-center md:gap-3">
54158
<div class="flex min-w-0 items-start justify-between gap-3 md:block">
55159
<div class="min-w-0">
56160
<a href="{% url 'cadmin_homework_submissions' course.slug hw.slug %}" class="block truncate font-medium app-link hover:underline">{{ hw.title }}</a>
57161
<div class="dense-utility-links mt-1 flex flex-wrap gap-x-3 gap-y-1 text-xs">
58-
<a href="{% url 'homework' course.slug hw.slug %}" title="View Public Homework Page" class="app-link">
162+
<a href="{% url 'homework' course.slug hw.slug %}" title="View public homework page" class="app-link">
59163
<i class="fas fa-external-link-alt"></i> Public
60164
</a>
61165
<a href="/admin/courses/homework/{{ hw.id }}/change/" title="Edit in Django Admin" class="app-link">
@@ -95,20 +199,6 @@ <h2 class="text-base font-semibold app-heading">Homework</h2>
95199
{% endif %}
96200
</div>
97201

98-
<div class="cadmin-row-actions flex flex-wrap justify-start gap-2 md:justify-end">
99-
{% if hw.state == 'OP' or hw.state == 'CL' %}
100-
<form method="post" action="{% url 'cadmin_homework_score' course.slug hw.slug %}" onsubmit="return confirm('Score all submissions for {{ hw.title }}?');">
101-
{% csrf_token %}
102-
<button type="submit" class="primer-button primer-button-success">Score</button>
103-
</form>
104-
<form method="post" action="{% url 'cadmin_homework_set_correct_answers' course.slug hw.slug %}" onsubmit="return confirm('Set correct answers to most popular for {{ hw.title }}?');">
105-
{% csrf_token %}
106-
<button type="submit" class="primer-button primer-button-secondary">Answers</button>
107-
</form>
108-
{% else %}
109-
<span class="hidden text-sm app-muted md:inline">No action</span>
110-
{% endif %}
111-
</div>
112202
</div>
113203
</article>
114204
{% endfor %}
@@ -120,27 +210,26 @@ <h2 class="text-base font-semibold app-heading">Homework</h2>
120210

121211
<section class="mt-6 border-t app-border pt-5">
122212
<div class="mb-3">
123-
<h2 class="text-base font-semibold app-heading">Projects</h2>
124-
<p class="mt-1 text-sm app-muted">Keep peer-review operations separate from public project links and Django Admin edits.</p>
213+
<h2 class="text-base font-semibold app-heading">All projects</h2>
214+
<p class="mt-1 text-sm app-muted">Reference list for public pages, Django edits, submissions, and review operations.</p>
125215
</div>
126216

127217
{% if projects %}
128-
<div class="hidden border-b app-border pb-2 text-xs font-semibold uppercase app-muted md:grid md:grid-cols-[minmax(0,1fr)_14rem_8rem_12rem] md:gap-3">
218+
<div class="hidden border-b app-border pb-2 text-xs font-semibold uppercase app-muted md:grid md:grid-cols-[minmax(0,1fr)_14rem_8rem] md:gap-3">
129219
<div>Project</div>
130220
<div>Due dates</div>
131221
<div class="text-right">State</div>
132-
<div class="text-right">Actions</div>
133222
</div>
134223

135224
<div class="divide-y app-divide">
136225
{% for proj in projects %}
137226
<article class="py-2.5 md:py-3">
138-
<div class="grid gap-2.5 md:grid-cols-[minmax(0,1fr)_14rem_8rem_12rem] md:items-center md:gap-3">
227+
<div class="grid gap-2.5 md:grid-cols-[minmax(0,1fr)_14rem_8rem] md:items-center md:gap-3">
139228
<div class="flex min-w-0 items-start justify-between gap-3 md:block">
140229
<div class="min-w-0">
141230
<a href="{% url 'cadmin_project_submissions' course.slug proj.slug %}" class="block truncate font-medium app-link hover:underline">{{ proj.title }}</a>
142231
<div class="dense-utility-links mt-1 flex flex-wrap gap-x-3 gap-y-1 text-xs">
143-
<a href="{% url 'project' course.slug proj.slug %}" title="View Public Project Page" class="app-link">
232+
<a href="{% url 'project' course.slug proj.slug %}" title="View public project page" class="app-link">
144233
<i class="fas fa-external-link-alt"></i> Public
145234
</a>
146235
<a href="/admin/courses/project/{{ proj.id }}/change/" title="Edit in Django Admin" class="app-link">
@@ -185,23 +274,6 @@ <h2 class="text-base font-semibold app-heading">Projects</h2>
185274
{% endif %}
186275
</div>
187276

188-
<div class="cadmin-row-actions flex flex-wrap justify-start gap-2 md:justify-end">
189-
{% if proj.state == 'CS' %}
190-
<form method="post" action="{% url 'cadmin_project_assign_reviews' course.slug proj.slug %}" onsubmit="return confirm('Assign peer reviews for {{ proj.title }}?');">
191-
{% csrf_token %}
192-
<button type="submit" class="primer-button primer-button-secondary">Assign Reviews</button>
193-
</form>
194-
{% endif %}
195-
{% if proj.state == 'PR' %}
196-
<form method="post" action="{% url 'cadmin_project_score' course.slug proj.slug %}" onsubmit="return confirm('Score all submissions for {{ proj.title }}?');">
197-
{% csrf_token %}
198-
<button type="submit" class="primer-button primer-button-success">Score</button>
199-
</form>
200-
{% endif %}
201-
{% if proj.state != 'CS' and proj.state != 'PR' %}
202-
<span class="hidden text-sm app-muted md:inline">No action</span>
203-
{% endif %}
204-
</div>
205277
</div>
206278
</article>
207279
{% endfor %}

0 commit comments

Comments
 (0)