diff --git a/owl/course.py b/owl/course.py index 43f333d851dd4b377f6924e1da7df285926d23d6..72deb1aa11fd33542dc391af5b04898e7f6432a8 100644 --- a/owl/course.py +++ b/owl/course.py @@ -5,7 +5,7 @@ import datetime from decimal import Decimal from flask import Flask, render_template, request, make_response, g, request_tearing_down, redirect, url_for, flash from flask_wtf import FlaskForm -from sqlalchemy import select, and_, or_, false +from sqlalchemy import select, and_, or_, false, delete import sqlalchemy.sql.functions as func from sqlalchemy.orm import joinedload, aliased from typing import Optional, Tuple @@ -215,6 +215,40 @@ def enroll_commit(course: db.Course) -> None: sess.commit() +# Leaving + +class LeaveConfirmForm(FlaskForm): + pass + + +@app.route('/c/<sident>/<cident>/leave', methods=('GET', 'POST')) +def leave(sident: str, cident: str) -> str: + app.course_init(sident, cident) + sess = db.get_session() + + err = None + if g.is_teacher: + err = 'Teachers are not allowed to leave their courses.' + else: + if sess.scalar( + select(db.Post) + .join(db.Topic) + .filter(or_(db.Post.target_uid == g.uid, db.Post.author_uid == g.uid)) + .filter(db.Topic.course == g.course) + .limit(1) + ): + err = 'You cannot leave, because you already have posts in this course.' + + form = LeaveConfirmForm() + if err is None and form.validate_on_submit(): + sess.execute(delete(db.Enroll).where(and_(db.Enroll.uid == g.uid, db.Enroll.course == g.course))) + sess.commit() + flash(f'You left the course {g.course.name}.', 'info') + return redirect(url_for('index')) + + return render_template('leave.html', form=form, error=err) + + # Topics @app.route('/c/<sident>/<cident>/<tident>/', methods=('GET', 'POST')) diff --git a/owl/templates/course.html b/owl/templates/course.html index afd17f76f66123de8fdc2eccba359a28be1afc7f..07e2168c2eb3fb287aa30aeb6f9b7d041b3c779d 100644 --- a/owl/templates/course.html +++ b/owl/templates/course.html @@ -84,4 +84,9 @@ {% else %} <p>The course is empty. Come back in a couple of millifortnights. {% endif %} + {% if not g.is_teacher %} + <nav class=buttons> + <a class=button href='{{ url_for('leave', sident=g.course.semester.ident, cident=g.course.ident) }}'>Leave the course</a> + </nav> + {% endif %} {% endblock %} diff --git a/owl/templates/leave.html b/owl/templates/leave.html new file mode 100644 index 0000000000000000000000000000000000000000..6ad17195c0bc34863fcc31d874a05d3bc5ce36bf --- /dev/null +++ b/owl/templates/leave.html @@ -0,0 +1,21 @@ +{% set title = g.course.name %} +{% extends "base.html" %} +{% block body %} + <h2>{{ g.course.name }}</h2> + + {% if error %} + <p class="flash flash-error">{{ error }} + {% else %} + <p>Please confirm that you want to leave this course. + {% endif %} + + <nav class=buttons> + {% if not error %} + <form method="POST" action="?"> + {{ form.csrf_token }} + <input class=danger type=submit value='Leave'> + </form> + {% endif %} + <a class=button href='{{ url_for('course_index', sident=g.course.semester.ident, cident=g.course.ident) }}'>Back to the course</a> + </nav> +{% endblock %}