#132 | #121: backoffice / dev-1.0-121 (#131)

cfr #121

Co-authored-by: Christophe Siraut <d@tobald.eu.org>
Co-authored-by: bkfox <thomas bkfox net>
Co-authored-by: Thomas Kairos <thomas@bkfox.net>
Reviewed-on: rc/aircox#131
Co-authored-by: Chris Tactic <ctactic@noreply.git.radiocampus.be>
Co-committed-by: Chris Tactic <ctactic@noreply.git.radiocampus.be>
This commit is contained in:
2024-04-28 22:02:09 +02:00
committed by Thomas Kairos
parent 1e17a1334a
commit 55123c386d
348 changed files with 124397 additions and 17879 deletions

View File

@ -1,16 +1,62 @@
import json
import random
from django import template
from django import template, forms
from django.db import models
from django.contrib.admin.templatetags.admin_urls import admin_urlname
from django.template.loader import render_to_string
from django.urls import reverse
from aircox.models import Diffusion, Log
random.seed()
register = template.Library()
@register.simple_tag(name="form_field")
def form_field(field, name=None, value=None, **kwargs):
name = name or field.name
return field.widget.render(name=name, value=value, **kwargs)
@register.filter(name="admin_url")
def admin_url(obj, action):
meta = obj._meta
return reverse(f"admin:{meta.app_label}_{meta.model_name}_{action}", args=[obj.id])
@register.filter(name="model_label")
def model_label(obj):
if isinstance(obj, models.Model):
obj = type(obj)
return obj._meta.label_lower.replace(".", "-")
@register.filter(name="object_id")
def object_id(obj):
return f"{model_label(obj)}-{obj.pk}"
@register.simple_tag(name="page_widget", takes_context=True)
def do_page_widget(context, widget, object, dir="aircox/widgets", **ctx):
"""Render widget for the provided page and context."""
ctx["request"] = context["request"]
ctx["object"] = object
ctx["widget"] = widget
if object.pk and not ctx.get("tag_id"):
model = type(object)._meta.model_name
ctx["tag_id"] = f"{widget}_{model}_{object.pk}"
ctx["widget_template"] = f"{dir}/{widget}.html"
return render_to_string(object.get_template_name(widget), ctx)
@register.filter(name="page_template")
def do_page_template(self, page, component):
"""For a provided page object and component name, return template name."""
return page.get_template(component)
@register.filter(name="admin_url")
def do_admin_url(obj, arg, pass_id=True):
"""Reverse admin url for object."""
@ -29,11 +75,18 @@ def do_get_tracks(obj):
return obj.track_set.all()
@register.simple_tag(name="has_perm", takes_context=True)
def do_has_perm(context, obj, perm, user=None):
@register.filter(name="has_perm")
def do_has_perm(user, perm):
"""Return True if user has permission."""
return user.has_perm(perm)
@register.simple_tag(name="has_obj_perm", takes_context=True)
def do_has_obj_perm(context, obj, perm, user=None):
"""Return True if ``user.has_perm('[APP].[perm]_[MODEL]')``"""
if user is None:
user = context["request"].user
user = user or context["request"].user
if not obj:
return False
return user.has_perm("{}.{}_{}".format(obj._meta.app_label, perm, obj._meta.model_name))
@ -43,6 +96,12 @@ def do_is_diffusion(obj):
return isinstance(obj, Diffusion)
@register.filter(name="is_log")
def do_is_log(obj):
"""Return True if object is a Diffusion."""
return isinstance(obj, Log)
@register.filter(name="json")
def do_json(obj, fields=""):
"""Return object as json."""
@ -66,13 +125,25 @@ def do_player_live_attr(context):
@register.simple_tag(name="nav_items", takes_context=True)
def do_nav_items(context, menu, **kwargs):
"""Render navigation items for the provided menu name."""
if not getattr(context["request"], "station"):
return []
station, request = context["station"], context["request"]
return [(item, item.render(request, **kwargs)) for item in station.navitem_set.filter(menu=menu)]
@register.filter(name="nav_active")
def do_nav_active(obj, request):
if request.path.startswith(obj.get_url()):
return True
return False
@register.simple_tag(name="update_query")
def do_update_query(obj, **kwargs):
"""Replace provided querydict's values with **kwargs."""
"""Replace provided querydict's values with **kwargs.
Values set to ``None`` will be dropped.
"""
for k, v in kwargs.items():
if v is not None:
obj[k] = list(v) if hasattr(v, "__iter__") else [v]
@ -85,4 +156,28 @@ def do_update_query(obj, **kwargs):
def do_verbose_name(obj, plural=False):
"""Return model's verbose name (singular or plural) or `obj` if it is a
string (can act for default values)."""
return obj if isinstance(obj, str) else obj._meta.verbose_name_plural if plural else obj._meta.verbose_name
if isinstance(obj, str):
return obj
return obj._meta.verbose_name_plural if plural else obj._meta.verbose_name
@register.filter(name="edit_view")
def do_edit_view(obj):
return "%s-edit" % obj.split("-")[0]
@register.filter(name="detail_view")
def do_detail_view(obj):
return "%s-detail" % obj.split("-")[0]
@register.filter(name="is_checkbox")
def is_checkbox(field):
"""Return True if field is a checkbox."""
return isinstance(field.widget, forms.CheckboxInput)
@register.filter(name="is_select")
def is_select(field):
"""Return True if field is a select."""
return isinstance(field.widget, forms.Select)

View File

@ -3,10 +3,11 @@ import json
from django import template
from django.contrib import admin
from django.utils.translation import gettext_lazy as _
from django.utils.safestring import mark_safe
from aircox.serializers.admin import UserSettingsSerializer
__all__ = ("register", "do_get_admin_tools", "do_track_inline_data")
__all__ = ("register", "do_get_admin_tools", "do_formset_inline_data", "do_inline_labels")
register = template.Library()
@ -17,26 +18,44 @@ def do_get_admin_tools():
return admin.site.get_tools()
@register.simple_tag(name="track_inline_data", takes_context=True)
def do_track_inline_data(context, formset):
"""Return initial data for playlist editor as dict. Keys are:
@register.simple_tag(name="formset_inline_data", takes_context=True)
def do_formset_inline_data(context, formset):
"""Return initial data of formset as dict (used by TrackListEditor and
PlaylistEditor). Keys are:
- ``items``: list of items. Extra keys:
- ``__error__``: dict of form fields errors
- ``settings``: user's settings
- ``fields``: dict of field name and label
"""
# --- get fields labels
model = formset.form.Meta.model
fields = {}
for field_name in formset.form.Meta.fields:
field = model._meta.get_field(field_name)
fields[field_name] = str(field.verbose_name).capitalize()
# --- get items
items = []
for form in formset.forms:
item = {name: form[name].value() for name in form.fields.keys()}
item["__errors__"] = form.errors
# hack for sound list
if duration := item.get("duration"):
item["duration"] = duration.strftime("%H:%M")
if sound := getattr(form.instance, "sound", None):
item["name"] = sound.name
fields["name"] = str(_("Sound")).capitalize()
# hack for playlist editor
tags = item.get("tags")
if tags and not isinstance(tags, str):
item["tags"] = ", ".join(tag.name for tag in tags)
items.append(item)
data = {"items": items}
data = {"items": items, "fields": fields, "initial": formset.initial and formset.initial[0]}
user = context["request"].user
settings = getattr(user, "aircox_settings", None)
data["settings"] = settings and UserSettingsSerializer(settings).data
@ -44,22 +63,32 @@ def do_track_inline_data(context, formset):
return source
track_inline_labels_ = {
"artist": _("Artist"),
"album": _("Album"),
"title": _("Title"),
"tags": _("Tags"),
"year": _("Year"),
inline_labels_ = {
# list editor
"add_item": _("Add an item"),
"remove_item": _("Remove"),
"settings": _("Settings"),
"save_settings": _("Save Settings"),
"discard_changes": _("Discard changes"),
"submit": _("Submit"),
"delete": _("Delete"),
# select file
"upload": _("Upload"),
"list": _("List"),
"confirm_delete": _("Are you sure to remove this element from the server?"),
"show_next": _("Show next"),
"show_previous": _("Show previous"),
"select_file": _("Select a file"),
# track list
"text": _("Text"),
"columns": _("Columns"),
"add_track": _("Add a track"),
"remove_track": _("Remove"),
"timestamp": _("Timestamp"),
# sound list
"add_sound": _("Add a sound"),
}
@register.simple_tag(name="track_inline_labels")
def do_track_inline_labels():
@register.simple_tag(name="inline_labels")
def do_inline_labels():
"""Return labels for columns in playlist editor as dict."""
return json.dumps({k: str(v) for k, v in track_inline_labels_.items()})
return mark_safe(json.dumps({k: str(v) for k, v in inline_labels_.items()}))