~homeworkprod/byceps

867978381e58811d3878ce9aa2bf68873ed80caa — Jochen Kupperschmidt 1 year, 1 month ago e8cad0b
Implement functionality to update a brand

SQL:

    INSERT INTO authz_permissions (id, title) VALUES ('brand.update', 'Marken bearbeiten');
    INSERT INTO authz_role_permissions (role_id, permission_id) VALUES ('brand_admin', 'brand.update');
M byceps/blueprints/admin/brand/authorization.py => byceps/blueprints/admin/brand/authorization.py +1 -0
@@ 11,5 11,6 @@ from byceps.util.authorization import create_permission_enum

BrandPermission = create_permission_enum('brand', [
    'create',
    'update',
    'view',
])

M byceps/blueprints/admin/brand/forms.py => byceps/blueprints/admin/brand/forms.py +11 -4
@@ 7,11 7,18 @@ byceps.blueprints.admin.brand.forms
"""

from wtforms import StringField
from wtforms.validators import Length
from wtforms.validators import InputRequired, Length, Optional

from ....util.l10n import LocalizedForm


class CreateForm(LocalizedForm):
    id = StringField('ID', validators=[Length(min=1, max=20)])
    title = StringField('Titel', validators=[Length(min=1, max=40)])
class _BaseForm(LocalizedForm):
    title = StringField('Titel', validators=[InputRequired(), Length(min=1, max=40)])


class CreateForm(_BaseForm):
    id = StringField('ID', validators=[InputRequired(), Length(min=1, max=20)])


class UpdateForm(_BaseForm):
    image_filename = StringField('Bild-Dateiname', validators=[Optional()])

M byceps/blueprints/admin/brand/templates/admin/brand/create_form.html => byceps/blueprints/admin/brand/templates/admin/brand/create_form.html +2 -2
@@ 15,8 15,8 @@

  <form action="{{ url_for('.create') }}" method="post">
    {% call form_fieldset() %}
      {{ form_field(form.id, maxlength=40, required='required', placeholder='superlan', autofocus='autofocus') }}
      {{ form_field(form.title, maxlength=40, required='required', placeholder='SuperLAN') }}
      {{ form_field(form.id, maxlength=40, placeholder='superlan', autofocus='autofocus') }}
      {{ form_field(form.title, maxlength=40, placeholder='SuperLAN') }}
    {% endcall %}

    {{ form_buttons('Erstellen', cancel_url=url_for('.index')) }}

A byceps/blueprints/admin/brand/templates/admin/brand/update_form.html => byceps/blueprints/admin/brand/templates/admin/brand/update_form.html +27 -0
@@ 0,0 1,27 @@
{% 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 = 'brands_admin' %}
{% set current_page_brand = brand %}
{% set title = 'Marke bearbeiten' %}

{% block body %}

  <nav class="breadcrumbs">
    <ol>
      <li><a href="{{ url_for('.index') }}">Marken</a></li>
      <li><a href="{{ url_for('.view', brand_id=brand.id) }}">{{ brand.title }}</a></li>
    </ol>
  </nav>
  <h1>{{ render_icon('edit') }} {{ title }}</h1>

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

    {{ form_buttons('Speichern', cancel_url=url_for('.view', brand_id=brand.id)) }}
  </form>

{%- endblock %}

M byceps/blueprints/admin/brand/templates/admin/brand/view.html => byceps/blueprints/admin/brand/templates/admin/brand/view.html +6 -0
@@ 13,6 13,12 @@
  </nav>
  <h1>{{ brand.title }}</h1>

  {%- if g.current_user.has_permission(BrandPermission.update) %}
  <div class="button-row button-row--right">
    <a class="button" href="{{ url_for('.update_form', brand_id=brand.id) }}">{{ render_icon('edit') }} <span>Bearbeiten</span></a>
  </div>
  {%- endif %}

  <table class="index">
    <tr>
      <th>ID</th>

M byceps/blueprints/admin/brand/views.py => byceps/blueprints/admin/brand/views.py +51 -6
@@ 23,7 23,7 @@ from ...common.authorization.decorators import permission_required
from ...common.authorization.registry import permission_registry

from .authorization import BrandPermission
from .forms import CreateForm
from .forms import CreateForm, UpdateForm


blueprint = create_blueprint('brand_admin', __name__)


@@ 55,11 55,7 @@ def index():
@templated
def view(brand_id):
    """Show a brand."""
    brand = brand_service.find_brand(brand_id)

    if brand is None:
        abort(404)

    brand = _get_brand_or_404(brand_id)
    settings = brand_settings_service.get_settings(brand.id)

    return {


@@ 96,3 92,52 @@ def create():

    flash_success(f'Die Marke "{brand.title}" wurde angelegt.')
    return redirect_to('.index')


@blueprint.route('/brands/<brand_id>/update')
@permission_required(BrandPermission.update)
@templated
def update_form(brand_id, erroneous_form=None):
    """Show form to update a brand."""
    brand = _get_brand_or_404(brand_id)

    form = erroneous_form if erroneous_form else UpdateForm(obj=brand)

    return {
        'brand': brand,
        'form': form,
    }


@blueprint.route('/brands/<brand_id>', methods=['POST'])
@permission_required(BrandPermission.update)
def update(brand_id):
    """Update a brand."""
    brand = _get_brand_or_404(brand_id)

    form = UpdateForm(request.form)
    if not form.validate():
        return update_form(brand.id, form)

    title = form.title.data.strip()
    image_filename = form.image_filename.data.strip() or None

    brand = brand_service.update_brand(
        brand.id, title, image_filename=image_filename
    )

    flash_success(f'Die Marke "{brand.title}" wurde aktualisiert.')
    return redirect_to('.view', brand_id=brand_id)


# -------------------------------------------------------------------- #
# helpers


def _get_brand_or_404(brand_id):
    brand = brand_service.find_brand(brand_id)

    if brand is None:
        abort(404)

    return brand

M byceps/services/brand/service.py => byceps/services/brand/service.py +21 -1
@@ 26,6 26,20 @@ def create_brand(brand_id: BrandID, title: str) -> Brand:
    return _db_entity_to_brand(brand)


def update_brand(
    brand_id: BrandID, title: str, *, image_filename: Optional[str] = None
) -> Brand:
    """Update a brand."""
    brand = _get_db_brand(brand_id)

    brand.title = title
    brand.image_filename = image_filename

    db.session.commit()

    return _db_entity_to_brand(brand)


def delete_brand(brand_id: BrandID) -> None:
    """Delete a brand."""
    db.session.query(DbSetting) \


@@ 41,7 55,7 @@ def delete_brand(brand_id: BrandID) -> None:

def find_brand(brand_id: BrandID) -> Optional[Brand]:
    """Return the brand with that id, or `None` if not found."""
    brand = DbBrand.query.get(brand_id)
    brand = _get_db_brand(brand_id)

    if brand is None:
        return None


@@ 49,6 63,11 @@ def find_brand(brand_id: BrandID) -> Optional[Brand]:
    return _db_entity_to_brand(brand)


def _get_db_brand(brand_id: BrandID) -> DbBrand:
    """Return the brand with that ID."""
    return DbBrand.query.get(brand_id)


def get_brands() -> List[Brand]:
    """Return all brands, ordered by title."""
    brands = DbBrand.query \


@@ 72,5 91,6 @@ def _db_entity_to_brand(brand: DbBrand) -> Brand:
    return Brand(
        brand.id,
        brand.title,
        brand.image_filename,
        image_url_path,
    )

M byceps/services/brand/transfer/models.py => byceps/services/brand/transfer/models.py +1 -0
@@ 15,6 15,7 @@ from ....typing import BrandID
class Brand:
    id: BrandID
    title: str
    image_filename: str
    image_url_path: str



M scripts/data/permissions_and_roles.json => scripts/data/permissions_and_roles.json +5 -0
@@ 81,6 81,10 @@
      "title": "Marken erstellen"
    },
    {
      "id": "brand.update",
      "title": "Marken bearbeiten"
    },
    {
      "id": "brand.view",
      "title": "Marken anzeigen"
    },


@@ 370,6 374,7 @@
    {
      "assigned_permissions": [
        "brand.create",
        "brand.update",
        "brand.view"
      ],
      "id": "brand_admin",