Skip to content
Snippets Groups Projects
Select Git revision
  • 68d0ccffc1db8c8229732a22db86e747cf2309bf
  • upstream default protected
  • master
3 results

webpack.config.js

Blame
  • org_contest.py NaN GiB
    from flask import render_template, g, redirect, url_for, flash, request
    from flask_wtf import FlaskForm
    import flask_wtf.file
    import locale
    import os
    import secrets
    from sqlalchemy.orm import joinedload
    from typing import List, Tuple, Optional, Sequence
    import werkzeug.exceptions
    import wtforms
    
    import mo
    import mo.csv
    import mo.db as db
    import mo.imports
    import mo.rights
    import mo.util
    from mo.web import app
    from mo.web.table import Table, Column, cell_place_link, cell_user_link, cell_email_link
    import wtforms.validators as validators
    
    
    class ImportForm(FlaskForm):
        file = flask_wtf.file.FileField("Soubor", validators=[flask_wtf.file.FileRequired()])
        submit = wtforms.SubmitField('Importovat')
    
    
    @app.route('/org/contest/')
    def org_contest_root():
        sess = db.get_session()
    
        rounds = sess.query(db.Round).filter_by(year=mo.current_year).order_by(db.Round.year, db.Round.category, db.Round.seq)
        return render_template('org_contest_root.html', rounds=rounds, level_names=mo.db.place_level_names)
    
    
    def get_round(id: int) -> db.Round:
        round = db.get_session().query(db.Round).get(id)
        if not round:
            raise werkzeug.exceptions.NotFound()
        return round
    
    
    def get_round_rr(id: int, right_needed: Optional[mo.rights.Right]) -> Tuple[db.Round, mo.rights.Rights]:
        round = get_round(id)
    
        rr = mo.rights.Rights(g.user)
        rr.get_for_round(round)
    
        if not (right_needed is None or rr.have_right(right_needed)):
            raise werkzeug.exceptions.Forbidden()
    
        return round, rr
    
    
    @app.route('/org/contest/r/<int:id>/')
    def org_round(id: int):
        sess = db.get_session()
        round, rr = get_round_rr(id, None)
    
        contests = (sess.query(db.Contest)
                    .filter_by(round=round)
                    .options(joinedload(db.Contest.place))
                    .all())
    
        contests.sort(key=lambda c: locale.strxfrm(c.place.name))
    
        return render_template(
            'org_round.html',
            round=round,
            contests=contests,
            level_names=mo.db.place_level_names,
            can_manage=rr.have_right(mo.rights.Right.manage_contest),
        )
    
    
    @app.route('/org/contest/r/<int:id>/list')
    def org_round_list(id: int):
        round, rr = get_round_rr(id, mo.rights.Right.manage_contest)
        format = request.args.get('format', "")
    
        table = make_contestant_table(round, None)
    
        if format == "":
            return render_template(
                'org_round_list.html',
                round=round,
                table=table,
            )
        else:
            return table.send_as(format)
    
    
    @app.route('/org/contest/r/<int:id>/import', methods=('GET', 'POST'))
    def org_round_import(id: int):
        round, rr = get_round_rr(id, mo.rights.Right.manage_contest)
    
        form = ImportForm()
        errs = []
        if form.validate_on_submit():
            tmp_name = secrets.token_hex(16) + '.csv'
            tmp_path = os.path.join(app.instance_path, 'imports', tmp_name)
            form.file.data.save(tmp_path)
            app.logger.info('Import: Zpracovávám soubor %s pro round=%s, uid=%s', tmp_name, round.round_code(), g.user.user_id)
    
            imp = mo.imports.Import(g.user)
            if imp.import_contest(round, None, tmp_path):
                mo.util.log(
                    type=db.LogType.round,
                    what=round.round_id,
                    details={'action': 'import'}
                )
                db.get_session().commit()
                flash('Účastníci importováni', 'success')
                return redirect(url_for('org_round', id=round.round_id))
            else:
                flash('Došlo k chybě při importu (detaily níže)', 'danger')
                errs = imp.errors
    
        return render_template(
            'org_round_import.html',
            round=round,
            form=form,
            errs=errs,
        )
    
    
    def get_contest(id: int) -> db.Contest:
        contest = (db.get_session().query(db.Contest)
                   .options(joinedload(db.Contest.place),
                            joinedload(db.Contest.round))
                   .get(id))
        if not contest:
            raise werkzeug.exceptions.NotFound()
        return contest
    
    
    def get_contest_rr(id: int, right_needed: Optional[mo.rights.Right]) -> Tuple[db.Contest, mo.rights.Rights]:
        contest = get_contest(id)
    
        rr = mo.rights.Rights(g.user)
        rr.get_for_contest(contest)
    
        if not (right_needed is None or rr.have_right(right_needed)):
            raise werkzeug.exceptions.Forbidden()
    
        return contest, rr
    
    
    @app.route('/org/contest/c/<int:id>')
    def org_contest(id: int):
        contest, rr = get_contest_rr(id, None)
    
        return render_template(
            'org_contest.html',
            contest=contest,
            rights=sorted(rr.current_rights, key=lambda r: r. name),
            can_manage=rr.have_right(mo.rights.Right.manage_contest),
        )
    
    
    @app.route('/org/contest/c/<int:id>/import', methods=('GET', 'POST'))
    def org_contest_import(id: int):
        contest, rr = get_contest_rr(id, mo.rights.Right.manage_contest)
    
        form = ImportForm()
        errs = []
        if form.validate_on_submit():
            tmp_name = secrets.token_hex(16) + '.csv'
            tmp_path = os.path.join(app.instance_path, 'imports', tmp_name)
            form.file.data.save(tmp_path)
            app.logger.info('Import: Zpracovávám soubor %s pro contest_id=%s, uid=%s', tmp_name, contest.contest_id, g.user.user_id)
    
            imp = mo.imports.Import(g.user)
            if imp.import_contest(contest.round, contest, tmp_path):
                mo.util.log(
                    type=db.LogType.contest,
                    what=contest.contest_id,
                    details={'action': 'import'}
                )
                db.get_session().commit()
                flash('Účastníci importováni', 'success')
                return redirect(url_for('org_contest', id=contest.contest_id))
            else:
                flash('Došlo k chybě při importu (detaily níže)', 'danger')
                errs = imp.errors
    
        return render_template(
            'org_contest_import.html',
            contest=contest,
            form=form,
            errs=errs,
        )
    
    
    @app.route('/org/contest/import/help.html')
    def org_contest_import_help():
        return render_template('org_contest_import_help.html')
    
    
    @app.route('/org/contest/import/sablona.csv')
    def org_contest_import_template():
        out = mo.imports.contest_template()
        resp = app.make_response(out)
        resp.content_type = 'text/csv; charset=utf=8'
        return resp
    
    
    @app.route('/org/contest/c/<int:id>/ucastnici')
    def org_contest_list(id: int):
        contest, rr = get_contest_rr(id, mo.rights.Right.manage_contest)
        format = request.args.get('format', "")
    
        table = make_contestant_table(contest.round, contest)
    
        if format == "":
            return render_template(
                'org_contest_list.html',
                contest=contest,
                table=table,
            )
        else:
            return table.send_as(format)
    
    
    contest_list_columns = (
        Column(key='first_name',    name='krestni',     title='Křestní jméno'),
        Column(key='last_name',     name='prijmeni',    title='Příjmení'),
        Column(key='email',         name='email',       title='E-mail'),
        Column(key='school',        name='skola',       title='Škola'),
        Column(key='school_code',   name='kod_skoly',   title='Kód školy'),
        Column(key='grade',         name='rocnik',      title='Ročník'),
        Column(key='born_year',     name='rok_naroz',   title='Rok naroz.'),
        Column(key='place_code',    name='kod_soutez_mista',  title='Sout. místo'),
        Column(key='status',        name='stav',        title='Stav'),
    )
    
    
    def make_contestant_table(round: db.Round, contest: Optional[db.Contest]) -> Table:
        query = (db.get_session()
                 .query(db.Participation, db.Participant, db.Contest)
                 .select_from(db.Participation)
                 .join(db.Participant, db.Participant.user_id == db.Participation.user_id)
                 .filter(db.Participant.year == round.year))
        if contest:
            query = query.join(db.Contest, db.Contest.contest_id == contest.contest_id)
        else:
            query = query.filter(db.Contest.round == round)
            query = query.options(joinedload(db.Contest.place))
        query = query.filter(db.Participation.contest_id == db.Contest.contest_id)
        query = query.options(joinedload(db.Participation.user),
                              joinedload(db.Participation.place),
                              joinedload(db.Participant.school_place))
    
        ctants = query.all()
    
        rows: List[dict] = []
        for pion, pant, ct in ctants:
            u = pion.user
            rows.append({
                'sort_key': (locale.strxfrm(u.last_name), locale.strxfrm(u.first_name), u.user_id),
                'first_name': cell_user_link(u, u.first_name),
                'last_name': cell_user_link(u, u.last_name),
                'email': cell_email_link(u),
                'school': pant.school_place.name,
                'school_code': cell_place_link(pant.school_place, pant.school_place.get_code()),
                'grade': pant.grade,
                'born_year': pant.birth_year,
                'region_code': cell_place_link(ct.place, ct.place.get_code()),
                'place_code': cell_place_link(pion.place, pion.place.get_code()),
                'status': pion.state.friendly_name(),
            })
    
        rows.sort(key=lambda r: r['sort_key'])
    
        cols: Sequence[Column] = contest_list_columns
        if not contest:
            cols = list(cols) + [Column(key='region_code', name='kod_oblasti', title='Oblast')]
    
        return Table(
            columns=cols,
            rows=rows,
            filename='ucastnici',
        )