diff --git a/mo/web/org.py b/mo/web/org.py index d1b0087277136f9d741d7931e31b144634b16f7e..377f6ab34ef03b416f75c114c107405cb4ef6502 100644 --- a/mo/web/org.py +++ b/mo/web/org.py @@ -11,6 +11,7 @@ import mo.rights import mo.users from mo.web import app from mo.web.jinja import user_url +import mo.web.org_round from mo.web.table import Table, Row, Column @@ -25,6 +26,7 @@ class OrgOverview: contest_states: Set[db.RoundState] = field(default_factory=set) num_active_pants: int = 0 num_unconfirmed_pants: int = 0 + create: bool = False @app.route('/org/') @@ -68,7 +70,6 @@ def org_index(): .all()) # Soutěžní místa, ke kterým máme nějakou roli - contest_place = aliased(db.Place) place_rcu = (rcu_base .filter(not_(db.Round.state.in_([db.RoundState.preparing, db.RoundState.closed]))) # for performance .filter(db.Place.level >= db.Round.level) @@ -89,11 +90,11 @@ def org_index(): overview: List[OrgOverview] = [] for r, ct, ur in rcu: - if ct is None and ur.place.level == r.level: - continue o = overview[-1] if overview else None if not (o and o.round == r and o.place == ur.place and o.contest == ct): o = OrgOverview(round=r, place=ur.place, contest=ct) + if ct is None and ur.place.level == r.level: + o.create = True overview.append(o) o.role_set.add(ur.role) @@ -103,7 +104,14 @@ def org_index(): get_stats(overview) overview = filter_overview(overview) - return render_template('org_index.html', overview=overview, role_type_names=db.role_type_names) + form_add_contest = mo.web.org_round.AddContestForm() + + return render_template( + 'org_index.html', + overview=overview, + role_type_names=db.role_type_names, + form_add_contest=form_add_contest, + ) def get_stats(overview: List[OrgOverview]) -> None: @@ -113,6 +121,8 @@ def get_stats(overview: List[OrgOverview]) -> None: rcs_for: List[Tuple[int, int]] = [] rps_for: List[Tuple[int, int]] = [] for o in overview: + if o.create: + continue if o.contest: o.num_contests = 1 o.contest_states.add(o.contest.state) @@ -160,12 +170,40 @@ def filter_overview(overview: List[OrgOverview]) -> List[OrgOverview]: else: # Ostatní role (garanti a pozorovatelé) vidí všechny soutěže want = True + + if want and o.create and not want_create_contest(o): + want = False + if want: out.append(o) return out +def want_create_contest(o: OrgOverview) -> bool: + # Založení soutěže nabízíme jen tehdy, pokud už kolo běží. V opačném případě sice + # org také může mít právo soutěž založit, ale v tabulce by vznikala + # spousta balastu o budoucích kolech. + if o.round.state not in [db.RoundState.running, db.RoundState.delegate]: + return False + + # Pokud je soutěžní místo škola, omezujeme kategorie podle typu školy + if o.place.type == db.PlaceType.school: + cat = o.round.category + if o.place.school.is_zs: + if cat.startswith("Z"): + return True + if o.place.school.is_ss: + if cat in "ABC": + return True + + # Okresní a krajská kola jsou vždy OK + if o.place.level in [1, 2]: + return True + + return False + + school_export_columns = ( Column(key='code', name='kod'), Column(key='name', name='nazev'), diff --git a/mo/web/org_round.py b/mo/web/org_round.py index ff7c75198cc140d6d37455d0e19c39b9079c5c88..fec02c9526278dd38cc13074b99ca62bdbca776e 100644 --- a/mo/web/org_round.py +++ b/mo/web/org_round.py @@ -81,6 +81,7 @@ def delete_task(round_id: int, form: TaskDeleteForm) -> bool: return False +# Používá se i přehledu soutěží na orgovské hlavní stránce class AddContestForm(FlaskForm): place = mo_fields.Place('Nová soutěž v oblasti:', validators=[validators.DataRequired()]) create_contest = wtforms.SubmitField('Založit') @@ -702,3 +703,20 @@ def org_round_create_contests(round_id: int): form=form, num_new_places=len(new_places), ) + + +# Používá se v zakládacím tlačítku v přehledu soutěží na orgovské hlavní stránce +@app.route('/org/contests/r/<int:round_id>/create-contest', methods=('POST',)) +def org_round_create_contest(round_id: int): + sess = db.get_session() + ctx = get_context(round_id=round_id) + + form_add_contest = AddContestForm() + if not add_contest(ctx.round, form_add_contest): + return redirect(url_for('org_index')) + + # Je jednodušší soutěž znovu najít, než se ji snažit vydolovat z mechanismu + # zakládání soutěží v dělených kolech. + contest = sess.query(db.Contest).filter_by(round=ctx.round, place=form_add_contest.place.place).first() + assert contest is not None + return redirect(ctx.url_for('org_contest', ct_id=contest.contest_id)) diff --git a/mo/web/templates/org_index.html b/mo/web/templates/org_index.html index 4d75a3ee68a8914e6598fb782973d4fec9676864..a5962c432b06e1753b9f6c039ab227b24e6365ae 100644 --- a/mo/web/templates/org_index.html +++ b/mo/web/templates/org_index.html @@ -1,4 +1,5 @@ {% extends "base.html" %} +{% import "bootstrap/wtf.html" as wtf %} {% block title %}Přístup pro organizátory{% endblock %} {% block body %} @@ -22,6 +23,8 @@ {% set curr.category = o.round.category %} {% endif %} + {% set create = not o.contest and o.place.level == o.round.level %} + {% if o.contest %} {% if o.place == o.contest.place %} {% set detail_url = url_for('org_contest', ct_id=o.contest.contest_id) %} @@ -44,15 +47,30 @@ {% else %} <td>{{ o.contest.place.name }} {{ o.place.name_locative() }} {% endif %} + {% elif create %} + <td>{{ o.place.name }} {% else %} <td><i>{{ o.place.name_locative() }}</i> {% endif %} <td>{% for s in o.contest_states %}{% if not loop.first %}<br>{% endif %}<span class="rstate-{{s.name}}">{{ s.friendly_name() }}</span>{% endfor %} + {% if create %} + <td> + {% else %} <td>{% if not o.contest %}{{ o.num_contests }}S / {% endif %} {{- o.num_active_pants }}U {%- if o.num_unconfirmed_pants %} / <span class='warning-text'>{{ o.num_unconfirmed_pants }}P</span>{% endif %} + {% endif %} <td>{% for r in o.role_list %}{{ role_type_names[r] }}{% if not loop.last %}<br>{% endif %}{% endfor %} + {% if create %} + <td> + <form action="{{ url_for('org_round_create_contest', round_id=o.round.round_id) }}" method="POST" class="form-inline"> + {{ form_add_contest.csrf_token() }} + <input name="place" type=hidden value="{{ o.place.get_code() }}"> + <input class="btn btn-xs btn-success" name="create_contest" type="submit" value="Založit"> + </form> + {% else %} <td><a class="btn btn-xs btn-primary" href='{{ detail_url }}'>Detail</a> + {% endif %} {% endfor %} </table>