Commit 23475abb authored by Martin Mareš's avatar Martin Mareš
Browse files

Merge branch 'master' of gitlab.kam.mff.cuni.cz:mj/owl

parents ca5c1147 714d89a8
......@@ -3,10 +3,10 @@ SET ROLE owl;
CREATE TABLE owl_users (
uid serial PRIMARY KEY,
ukco int UNIQUE DEFAULT NULL,
auth_token varchar(64) UNIQUE DEFAULT NULL,
full_name varchar(255) NOT NULL,
auth_token varchar(64) UNIQUE DEFAULT NULL, -- this is called "access key" in UI
first_name varchar(255) NOT NULL COLLATE "cs_CZ",
last_name varchar(255) NOT NULL COLLATE "cs_CZ",
email varchar(255) DEFAULT NULL,
-- we allow CAS's format "{email1,email2,...}"
created timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
is_admin boolean NOT NULL DEFAULT false,
notify boolean NOT NULL DEFAULT false,
......@@ -15,7 +15,7 @@ CREATE TABLE owl_users (
);
-- uid=-1 means "everybody"
INSERT INTO owl_users(uid, full_name) VALUES (-1, 'Everybody');
INSERT INTO owl_users(uid, full_name, first_name, last_name) VALUES (-1, 'Everybody', 'Every', 'Body');
CREATE TABLE owl_semesters (
semid serial PRIMARY KEY,
......@@ -27,11 +27,12 @@ CREATE TABLE owl_semesters (
CREATE TABLE owl_courses (
cid serial PRIMARY KEY,
semid int NOT NULL REFERENCES owl_semesters(semid) ON DELETE CASCADE,
ident varchar(255) UNIQUE NOT NULL,
ident varchar(255) NOT NULL,
name varchar(255) NOT NULL,
enroll_token varchar(255) UNIQUE NOT NULL,
student_grading boolean NOT NULL DEFAULT FALSE,
anon_grading boolean NOT NULL DEFAULT FALSE
anon_grading boolean NOT NULL DEFAULT FALSE,
UNIQUE(semid, cid)
);
CREATE TABLE owl_enroll (
......
This diff is collapsed.
......@@ -68,6 +68,14 @@ h1 {
margin-bottom: 3ex;
}
/* Footer */
footer {
margin-top: 4ex;
border-top: 1px solid black;
padding-top: 0.5ex;
}
/* Flashing messages */
.flash {
......
......@@ -11,6 +11,6 @@
</table>
<div class=buttons>
<a class=button href='{{ url_for('course_index', cident=g.course.ident) }}'>Back to the course&hellip;</a>
<a class=button href='{{ url_for('course_index', sident=g.course.sident, cident=g.course.ident) }}'>Back to the course&hellip;</a>
</div>
{% endblock %}
......@@ -4,6 +4,7 @@
<table class=data>
<thead><tr>
<th>Sem.
<th>Ident
<th>Name
<th>Teachers
......@@ -11,8 +12,9 @@
</thead>
{% for c in courses %}
<tr>
<td>{{ c.sident }}
<td style='white-space: nowrap'>{{ c.ident }}
<td><a href='{{ url_for('course_index', cident=c.ident) }}'>{{ c.name }}</a>
<td><a href='{{ url_for('course_index', sident=c.sident, cident=c.ident) }}'>{{ c.name }}</a>
{% if c.cid in teachers %}
<td>{{ teachers[c.cid]|sort|join(", ") }}
{% else %}
......
......@@ -26,7 +26,7 @@
</table>
<p class=buttons>{{ form.submit(class='ok') }}
{% if tid != None %}
<a class=button href='{{ url_for('admin_edit_topic', cident=g.course.ident, copy_tid=tid) }}'>Copy</a>
<a class=button href='{{ url_for('admin_edit_topic', sident=g.course.sident, cident=g.course.ident, copy_tid=tid) }}'>Copy</a>
<p>{{ form.delete(class='danger') }}&nbsp;&nbsp;(including {{ post_count }} posts)
{% endif %}
</form>
......
......@@ -3,7 +3,7 @@
<h2>Student graders of {{ topic.title }}</h2>
<div class="buttons">
<span class="button"><a href="{{url_for('admin_topics', cident=g.course.ident)}}">Back</a></span>
<span class="button"><a href="{{url_for('admin_topics', sident=g.course.sident, cident=g.course.ident)}}">Back</a></span>
</div>
<h3>Assigned graders</h3>
......@@ -12,7 +12,7 @@
<li><form method="POST" action="">
{{ form.csrf_token }}
{{ form.uid }}
<b>{{ s.full_name }}</b>:
<b>{{ s.first_name }} {{ s.last_name }}</b>:
{{ form.unassign(class='ok') }}
</form></li>
{% endfor %}
......@@ -24,7 +24,7 @@
<li><form method="POST" action="">
{{ form.csrf_token }}
{{ form.uid }}
<b>{{ s.full_name }}</b>:
<b>{{ s.first_name }} {{ s.last_name }}</b>:
{{ form.assign(class='ok') }}
</form></li>
{% endfor %}
......
......@@ -13,10 +13,10 @@
{% set cls = "thidden" %}
{% endif %}
<tr class={{ cls }}>
<td><a href='{{ url_for('admin_edit_topic', cident=g.course.ident, tid=t.tid) }}'>{{ t.rank }}</a>
<td><a href='{{ url_for('admin_edit_topic', sident=g.course.sident, cident=g.course.ident, tid=t.tid) }}'>{{ t.rank }}</a>
<td>{{ t.ident or "" }}
{% if t.ident %}
<td><a href='{{ url_for('topic_index', cident=g.course.ident, tident=t.ident) }}'>{{ t.title }}</a>
<td><a href='{{ url_for('topic_index', sident=g.course.sident, cident=g.course.ident, tident=t.ident) }}'>{{ t.title }}</a>
{% else %}
<td>{{ t.title }}
{% endif %}
......@@ -24,13 +24,13 @@
<td>{{ t.deadline|reltimeformat }}
<td class=pts>{{ t.max_points if t.max_points != None else "" }}
{% if g.course.student_grading %}
<td>{% if t.type == 'T' %}<a href='{{ url_for('admin_topic_graders', cident=g.course.ident, tid=t.tid) }}'>Assign</a>{% endif %}
<td>{% if t.type == 'T' %}<a href='{{ url_for('admin_topic_graders', sident=g.course.sident, cident=g.course.ident, tid=t.tid) }}'>Assign</a>{% endif %}
{% endif %}
{% endfor %}
</table>
<div class=buttons>
<a class=button href='{{ url_for('admin_edit_topic', cident=g.course.ident) }}'>New topic</a>
<a class=button href='{{ url_for('course_index', cident=g.course.ident) }}'>Back to the course</a>
<a class=button href='{{ url_for('admin_edit_topic', sident=g.course.sident, cident=g.course.ident) }}'>New topic</a>
<a class=button href='{{ url_for('course_index', sident=g.course.sident, cident=g.course.ident) }}'>Back to the course</a>
</div>
{% endblock %}
......@@ -3,7 +3,7 @@
<head>
<title>The Postal Owl</title>
<link rel="icon" type="image/png" href='{{ url_for('static', filename='favicon.png') }}'>
<link rel=stylesheet href="{{ url_for('static', filename='owl.css') }}?v=14" type='text/css' media=all>
<link rel=stylesheet href="{{ url_for('static', filename='owl.css') }}?v=15" type='text/css' media=all>
{% if need_js %}
<link rel="stylesheet" href='{{ url_for('static', filename='github.css') }}'>
<link rel="stylesheet" href='{{ url_for('static', filename='katex.min.css') }}'>
......@@ -38,5 +38,9 @@
{% endif %}
{% endwith %}
{% block body %}{% endblock %}
<footer>
<p>The Owl is maintained by <a href='https://mj.ucw.cz/'>Martin Mareš</a>.
Send all suggestions, bug reports, and requests for new courses to <a href='mailto:mj@ucw.cz'>mj@ucw.cz</a>.
</footer>
</body>
</html>
......@@ -7,9 +7,9 @@
{% if g.is_teacher %}
<div class=buttons>
<a class=button href='{{ url_for('admin_topics', cident=g.course.ident) }}'>Edit topics</a>
<a class=button href='{{ url_for('teacher', cident=g.course.ident) }}'>Teacher's summary</a>
<a class=button href='{{ url_for('admin_course', cident=g.course.ident) }}'>Details</a>
<a class=button href='{{ url_for('admin_topics', sident=g.course.sident, cident=g.course.ident) }}'>Edit topics</a>
<a class=button href='{{ url_for('teacher', sident=g.course.sident, cident=g.course.ident) }}'>Teacher's summary</a>
<a class=button href='{{ url_for('admin_course', sident=g.course.sident, cident=g.course.ident) }}'>Details</a>
</div>
{% endif %}
......@@ -30,13 +30,13 @@
{% else %}
{% set cls = 'told' %}
{% endif %}
<tr class={{ cls }}><td><a href="{{ url_for('topic_index', cident=g.course.ident, tident=t.ident) }}">{{ t.title }}</a>
<tr class={{ cls }}><td><a href="{{ url_for('topic_index', sident=g.course.sident, cident=g.course.ident, tident=t.ident) }}">{{ t.title }}</a>
<td>{{ t.deadline|reltimeformat }}
<td class=pts>{{ t.points if t.points != None else "" }}
<td class=pts>{{ t.max_points if t.max_points != None else "" }}
{% if is_grader %}
<td>{% if t.is_grader %}
<a href="{{ url_for('topic_student_grade', cident=g.course.ident, tident=t.ident) }}">Grade</a>
<a href="{{ url_for('topic_student_grade', sident=g.course.sident, cident=g.course.ident, tident=t.ident) }}">Grade</a>
{% endif %}
{% endif %}
{% else %}
......
......@@ -14,10 +14,7 @@
<form method="POST" action="?">
{{ form.csrf_token }}
{{ form.next() }}
Login by token: {{ form.token(size=64) }}
Login by access key: {{ form.key(size=64) }}
<input type=submit value='Go!'>
</form>
<p>If you have problems with logging in, please clear your cookies and tell Martin Mareš
if it helped.
{% endblock %}
......@@ -5,13 +5,13 @@
<h2>{{ s.name }}</h2>
<ul>
{% for c in courses[s.semid] %}
<li><a href="{{ url_for('course_index', cident=c.ident) }}">{{ c.name }}</a>{% if c.is_teacher %} (teacher){% endif %}
<li><a href="{{ url_for('course_index', sident=s.ident, cident=c.ident) }}">{{ c.name }}</a>{% if c.is_teacher %} (teacher){% endif %}
{% endfor %}
{% if loop.first %}
<li><a href='{{ url_for('enroll') }}'>Join a new course</a>
{% endif %}
{% if sem_teacher[s.semid] %}
<li><a href='{{ url_for('teacher', semident=s.ident) }}'>Teacher's summary</a>
<li><a href='{{ url_for('teacher', sident=s.ident) }}'>Teacher's summary</a>
{% endif %}
</ul>
{% endif %}
......@@ -28,6 +28,9 @@
<h2>News</h2>
<table class=news>
<tr><td>2021-09-28<td>We changed structure of URLs to include semester code,
so that we can recycle course IDs.
<tr><td>2021-05-21<td>Teachers can now download results in CSV or JSON.
<tr><td>2021-04-20<td>Added a Reply button for quoting of posts.
<tr><td>2021-03-13<td>Added syntax highlighting for C, C++, Python, Haskell, and Prolog.
Use <code>```python</code> in Markdown to start a code block. Ask for more languages
......@@ -38,7 +41,4 @@
<tr><td>2021-03-08<td>We now support grading of solutions by other students.
<tr><td>2021-02-19<td>The Owl has a <a href='{{ url_for('manual') }}'>manual</a>.
</table>
<p>The Owl was written by <a href='https://mj.ucw.cz/'>Martin Mareš</a>.
Send all suggestions and bug reports to <a href='mailto:mj@ucw.cz'>mj@ucw.cz</a>.
{% endblock %}
......@@ -5,8 +5,9 @@
<form method="POST" action="">
{{ form.csrf_token }}
<table class=settings>
<tr><td>Name:<td>{{ user.full_name }}
<tr><td>E-mail:<td>{{ "<br>".join(emails) }}
<tr><td>First name:<td>{{ user.first_name }}
<tr><td>Last name:<td>{{ user.last_name }}
<tr><td>E-mail:<td>{{ user.email }}
<tr><td>Notify by e-mail:<td>{{ form.notify() }}
<tr><td>Notify on own posts:<td>{{ form.notify_self() }}
<tr><td>Show PDF attachments inline:<td>{{ form.inline_att() }}
......
......@@ -4,7 +4,7 @@
<h2>Teacher's Summary</h2>
{% for c in courses.values() %}
<h3>{{ c.name }} (<a href='{{ url_for('course_index', cident=c.ident) }}'>{{ c.ident }}</a>)</h3>
<h3>{{ c.name }} (<a href='{{ url_for('course_index', sident=c.sident, cident=c.ident) }}'>{{ c.ident }}</a>)</h3>
<table class=results>
<tr><th class='tbeforehdr'>
......@@ -21,7 +21,7 @@
{% do cls.append("tbeforehdr") %}
{% endif %}
<th class='{{ cls|join(" ") }}' title='{{ t.title }}{% if t.deadline != None %} [{{ t.deadline|reltimeformat }}]{% endif %}'>
<a href='{{ url_for('topic_index', cident=c.ident, tident=t.ident) }}'>{{ t.ident }}</a>
<a href='{{ url_for('topic_index', sident=c.sident, cident=c.ident, tident=t.ident) }}'>{{ t.ident }}</a>
{% endfor %}
<th>Σ
<tr><th class='tbeforehdr'>max.
......@@ -34,7 +34,7 @@
{% endfor %}
<td class=pts>{{ course_totals[c.cid] }}
{% for s in students[c.cid].values() %}
<tr><td class='tbeforehdr'>{{ s.full_name }}
<tr><td class='tbeforehdr'>{{ s.first_name }} {{ s.last_name }}
{{ s.email|mailto('✉') }}
{% for t in topics[c.cid].values() %}
{% set sol=solutions[c.cid][s.uid][t.tid] %}
......@@ -46,7 +46,7 @@
{% do cls.append("snull") %}
{% if t.type == 'A' %}
{% do cls.append("pts") %}
<td class='{{ cls|join(" ") }}'><a href='{{ url_for('topic_index', cident=c.ident, tident=t.ident, student_uid=s.uid) }}'>+</a>
<td class='{{ cls|join(" ") }}'><a href='{{ url_for('topic_index', sident=c.sident, cident=c.ident, tident=t.ident, student_uid=s.uid) }}'>+</a>
{% else %}
<td class='{{ cls|join(" ") }}'>
{% endif %}
......@@ -61,7 +61,7 @@
{% else %}
{% do cls.append("sold") %}
{% endif %}
<td class="{{ cls|join(" ") }}"><a href='{{ url_for('topic_index', cident=c.ident, tident=t.ident, student_uid=s.uid) }}'>
<td class="{{ cls|join(" ") }}"><a href='{{ url_for('topic_index', sident=c.sident, cident=c.ident, tident=t.ident, student_uid=s.uid) }}'>
{% if sol.points != None %}
{{ sol.points }}
{% else %}
......@@ -73,6 +73,10 @@
<td class=pts>{{ totals[c.cid][s.uid] }}
{% endfor %}
</table>
<p>Download as
<a href='{{ url_for('results_json', sident=c.sident, cident=c.ident) }}'>JSON</a>,
<a href='{{ url_for('results_csv', sident=c.sident, cident=c.ident) }}'>CSV</a>.
{% endfor %}
{% endblock %}
......@@ -5,7 +5,7 @@
<h2>{{c.name}}</h2>
<div class="buttons">
<span class="button"><a href='{{ url_for('course_index', cident=c.ident) }}'>Return to course</a></span>
<span class="button"><a href='{{ url_for('course_index', sident=c.sident, cident=c.ident) }}'>Return to course</a></span>
</div>
<h3>Grade {{t.title}}</h3>
......@@ -19,7 +19,7 @@
{% if c.anon_grading and s.uid != g.uid %}
Student {{ s.uid }}
{% else %}
{{ s.full_name }}
{{ s.first_name }} {{ s.last_name }}
{% endif %}
{% set sol=solutions[s.uid] %}
{% set cls=[] %}
......@@ -33,7 +33,7 @@
{% else %}
{% do cls.append("sold") %}
{% endif %}
<td class="{{ cls|join(" ") }}"><a href='{{ url_for('topic_index', cident=c.ident, tident=t.ident, student_uid=s.uid) }}'>
<td class="{{ cls|join(" ") }}"><a href='{{ url_for('topic_index', sident=c.sident, cident=c.ident, tident=t.ident, student_uid=s.uid) }}'>
{% if sol.points != None %}
{{ sol.points }}
{% else %}
......
......@@ -8,12 +8,12 @@
<h2>{{ g.course.name }}</h2>
<div class="buttons">
<a class="button" href='{{ url_for('course_index', cident=g.course.ident) }}'>Back to the course</a>
<a class="button" href='{{ url_for('course_index', sident=g.course.sident, cident=g.course.ident) }}'>Back to the course</a>
{% if g.is_teacher %}
<a class="button" href='{{ url_for('teacher', cident=g.course.ident) }}'>Teacher's summary</a>
<a class="button" href='{{ url_for('admin_edit_topic', cident=g.course.ident, tid=g.topic.tid) }}'>Edit topic</a>
<a class="button" href='{{ url_for('teacher', sident=g.course.sident, cident=g.course.ident) }}'>Teacher's summary</a>
<a class="button" href='{{ url_for('admin_edit_topic', sident=g.course.sident, cident=g.course.ident, tid=g.topic.tid) }}'>Edit topic</a>
{% elif g.is_grader %}
<a class="button" href='{{ url_for('topic_student_grade', cident=g.course.ident, tident=g.topic.ident) }}'>Grade</a>
<a class="button" href='{{ url_for('topic_student_grade', sident=g.course.sident, cident=g.course.ident, tident=g.topic.ident) }}'>Grade</a>
{% endif %}
</div>
......@@ -57,7 +57,7 @@
<span class=phpast>(after deadline)</span>
{% endif %}
{% if g.is_teacher or p.author_uid == g.uid %}
<a href='{{ url_for('edit_post', cident=g.course.ident, pid=p.pid) }}'>edit</a>
<a href='{{ url_for('edit_post', sident=g.course.sident, cident=g.course.ident, pid=p.pid) }}'>edit</a>
{% endif %}
<a href="#comment" class="preply">reply</a>
{% if p.comment != None %}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment