~homeworkprod/byceps

1dc186052cb2be3a90cc2b7f4cfc71fe354751f9 — Jochen Kupperschmidt 8 months ago b94b8ed
Add admin UI to update ticket categories
M byceps/blueprints/admin/ticketing/category/forms.py => byceps/blueprints/admin/ticketing/category/forms.py +1 -1
@@ 13,7 13,7 @@ from wtforms.validators import InputRequired, Length
from .....util.l10n import LocalizedForm


class CreateForm(LocalizedForm):
class CreateOrUpdateForm(LocalizedForm):
    title = StringField(
        lazy_gettext('Title'),
        validators=[InputRequired(), Length(min=1, max=40)],

M byceps/blueprints/admin/ticketing/category/templates/admin/ticketing/category/index.html => byceps/blueprints/admin/ticketing/category/templates/admin/ticketing/category/index.html +8 -0
@@ 26,6 26,7 @@
      <tr>
        <th>Titel<br>ID</th>
        <th class="number">Tickets<sup>*</sup></th>
        <th></th>
      </tr>
    </thead>
    <tbody>


@@ 33,6 34,13 @@
        <tr>
          <td><strong>{{ category.title }}</strong><br><span class="dimmed">{{ category.id }}</span></td>
          <td class="bignumber number">{{ ticket_count }}</td>
          <td>
            {%- if g.user.has_permission(TicketingPermission.administrate) %}
            <div class="button-row button-row--compact button-row--right">
              <a href="{{ url_for('.update_form', category_id=category.id) }}" class="button" title="Bearbeiten">{{ render_icon('edit') }}</a>
            </div>
            {%- endif %}
          </td>
        </tr>
      {%- endfor %}
    </tbody>

A byceps/blueprints/admin/ticketing/category/templates/admin/ticketing/category/update_form.html => byceps/blueprints/admin/ticketing/category/templates/admin/ticketing/category/update_form.html +20 -0
@@ 0,0 1,20 @@
{% extends 'layout/admin/base.html' %}
{% from 'macros/forms.html' import form_buttons, form_field, form_fieldset %}
{% from 'macros/icons.html' import render_icon %}
{% set current_page = 'ticketing_admin' %}
{% set current_page_party = party %}
{% set title = 'Ticket-Kategorie bearbeiten' %}

{% block body %}

  <h1>{{ render_icon('edit') }} {{ title }}</h1>

  <form action="{{ url_for('.update', category_id=category.id) }}" method="post">
    {% call form_fieldset() %}
      {{ form_field(form.title, maxlength=40, autofocus='autofocus') }}
    {% endcall %}

    {{ form_buttons(_('Save'), cancel_url=url_for('.index', party_id=party.id)) }}
  </form>

{%- endblock %}

M byceps/blueprints/admin/ticketing/category/views.py => byceps/blueprints/admin/ticketing/category/views.py +56 -8
@@ 10,9 10,7 @@ from flask import abort, request
from flask_babel import gettext

from .....services.party import service as party_service
from .....services.ticketing import (
    category_service as ticketing_category_service,
)
from .....services.ticketing import category_service
from .....util.framework.blueprint import create_blueprint
from .....util.framework.flash import flash_success
from .....util.framework.templating import templated


@@ 20,7 18,7 @@ from .....util.views import permission_required, redirect_to

from ...ticketing.authorization import TicketingPermission

from .forms import CreateForm
from .forms import CreateOrUpdateForm


blueprint = create_blueprint('ticketing_category_admin', __name__)


@@ 34,7 32,7 @@ def index(party_id):
    party = _get_party_or_404(party_id)

    categories_with_ticket_counts = list(
        ticketing_category_service.get_categories_with_ticket_counts_for_party(
        category_service.get_categories_with_ticket_counts_for_party(
            party.id
        ).items()
    )


@@ 52,7 50,7 @@ def create_form(party_id, erroneous_form=None):
    """Show form to create a ticket category."""
    party = _get_party_or_404(party_id)

    form = erroneous_form if erroneous_form else CreateForm()
    form = erroneous_form if erroneous_form else CreateOrUpdateForm()

    return {
        'party': party,


@@ 66,13 64,13 @@ def create(party_id):
    """Create a ticket category."""
    party = _get_party_or_404(party_id)

    form = CreateForm(request.form)
    form = CreateOrUpdateForm(request.form)
    if not form.validate():
        return create_form(party.id, form)

    title = form.title.data.strip()

    category = ticketing_category_service.create_category(party.id, title)
    category = category_service.create_category(party.id, title)

    flash_success(
        gettext(


@@ 84,6 82,47 @@ def create(party_id):
    return redirect_to('.index', party_id=party.id)


@blueprint.route('/categories/<uuid:category_id>/update')
@permission_required(TicketingPermission.administrate)
@templated
def update_form(category_id, erroneous_form=None):
    """Show form to update the category."""
    category = _get_category_or_404(category_id)

    party = party_service.find_party(category.party_id)

    form = (
        erroneous_form if erroneous_form else CreateOrUpdateForm(obj=category)
    )

    return {
        'party': party,
        'category': category,
        'form': form,
    }


@blueprint.route('/categories/<uuid:category_id>', methods=['POST'])
@permission_required(TicketingPermission.administrate)
def update(category_id):
    """Update the category."""
    category = _get_category_or_404(category_id)

    form = CreateOrUpdateForm(request.form)
    if not form.validate():
        return update_form(category.id, form)

    title = form.title.data.strip()

    category = category_service.update_category(category.id, title)

    flash_success(
        gettext('Category "%(title)s" has been updated.', title=category.title)
    )

    return redirect_to('.index', party_id=category.party_id)


def _get_party_or_404(party_id):
    party = party_service.find_party(party_id)



@@ 91,3 130,12 @@ def _get_party_or_404(party_id):
        abort(404)

    return party


def _get_category_or_404(category_id):
    category = category_service.find_category(category_id)

    if category is None:
        abort(404)

    return category

M byceps/services/ticketing/category_service.py => byceps/services/ticketing/category_service.py +14 -0
@@ 26,6 26,20 @@ def create_category(party_id: PartyID, title: str) -> TicketCategory:
    return _db_entity_to_category(category)


def update_category(category_id: TicketCategoryID, title: str) -> TicketCategory:
    """Update a category."""
    category = DbCategory.query.get(category_id)

    if category is None:
        raise ValueError(f'Unknown category ID "{category_id}"')

    category.title = title

    db.session.commit()

    return _db_entity_to_category(category)


def delete_category(category_id: TicketCategoryID) -> None:
    """Delete a category."""
    db.session.query(DbCategory) \

M byceps/translations/de/LC_MESSAGES/messages.po => byceps/translations/de/LC_MESSAGES/messages.po +7 -1
@@ 202,6 202,7 @@ msgstr "Erstellen"
#: byceps/blueprints/admin/snippet/templates/admin/snippet/create_mountpoint_form.html:24
#: byceps/blueprints/admin/snippet/templates/admin/snippet/update_document_form.html:25
#: byceps/blueprints/admin/snippet/templates/admin/snippet/update_fragment_form.html:22
#: byceps/blueprints/admin/ticketing/category/templates/admin/ticketing/category/update_form.html:17
#: byceps/blueprints/admin/tourney/category/templates/admin/tourney/category/update_form.html:25
#: byceps/blueprints/admin/tourney/tourney/templates/admin/tourney/tourney/update_form.html:30
#: byceps/blueprints/admin/user/templates/admin/user/set_password_form.html:16


@@ 1092,11 1093,16 @@ msgstr ""
"%(screen_name)s wurde als Nutzer/in von Ticket %(ticket_code)s "
"eingetragen."

#: byceps/blueprints/admin/ticketing/category/views.py:78
#: byceps/blueprints/admin/ticketing/category/views.py:76
#, python-format
msgid "Ticket category \"%(title)s\" has been created."
msgstr "Ticket-Kategorie \"%(title)s\" wurde erstellt."

#: byceps/blueprints/admin/ticketing/category/views.py:120
#, python-format
msgid "Category \"%(title)s\" has been updated."
msgstr "Ticket-Kategorie \"%(title)s\" wurde aktualisiert."

#: byceps/blueprints/admin/ticketing/checkin/views.py:125
msgid ""
"The user account assigned to this ticket has been deleted. Check-in "

M tests/integration/blueprints/admin/ticketing/test_views.py => tests/integration/blueprints/admin/ticketing/test_views.py +6 -0
@@ 44,3 44,9 @@ def test_category_create_form(ticketing_admin_client, party):
    url = f'/admin/ticketing/categories/for_party/{party.id}/create'
    response = ticketing_admin_client.get(url)
    assert response.status_code == 200


def test_category_update_form(ticketing_admin_client, category):
    url = f'/admin/ticketing/categories/categories/{category.id}/update'
    response = ticketing_admin_client.get(url)
    assert response.status_code == 200