forked from rc/aircox
- save & load
- key navigation - ui improvements
This commit is contained in:
@ -9,7 +9,7 @@ from adminsortable2.admin import SortableAdminBase, SortableInlineAdminMixin
|
||||
from ..models import Sound, Track
|
||||
|
||||
|
||||
class TrackInline(SortableInlineAdminMixin, admin.TabularInline):
|
||||
class TrackInline(admin.TabularInline):
|
||||
template = 'admin/aircox/playlist_inline.html'
|
||||
model = Track
|
||||
extra = 0
|
||||
|
File diff suppressed because one or more lines are too long
@ -4,21 +4,18 @@
|
||||
{# include "adminsortable2/edit_inline/tabular-django-4.1.html" #}
|
||||
{% with inline_admin_formset as admin_formset %}
|
||||
{% with admin_formset.formset as formset %}
|
||||
|
||||
<script id="{{ formset.prefix }}-init-data">
|
||||
{{ formset|inline_data|json }}
|
||||
</script>
|
||||
<div id="inline-tracks" class="box mb-5">
|
||||
<h5 class="title is-4">{% trans "Playlist" %}</h5>
|
||||
<script id="{{ formset.prefix }}-init-data">{
|
||||
"items": [
|
||||
{% for form in formset.forms %}
|
||||
{{ form.initial|json }}
|
||||
{% if not forloop.last %},{% endif %}
|
||||
{% endfor %}
|
||||
]
|
||||
}
|
||||
</script>
|
||||
{{ admin_formset.non_form_errors }}
|
||||
|
||||
|
||||
<a-playlist-editor>
|
||||
<a-playlist-editor data-el="{{ formset.prefix }}-init-data"
|
||||
data-prefix="{{ formset.prefix }}-">
|
||||
<template #title>
|
||||
<h5 class="title is-4">{% trans "Playlist" %}</h5>
|
||||
</template>
|
||||
<template v-slot:top="{items}">
|
||||
<input type="hidden" name="{{ formset.prefix }}-TOTAL_FORMS"
|
||||
:value="items.length || 0"/>
|
||||
@ -43,7 +40,7 @@
|
||||
<input type="hidden"
|
||||
:name="'{{ formset.prefix }}-' + row + '-position'"
|
||||
:value="row"/>
|
||||
<input t-if="item.data.id" type="hidden"
|
||||
<input t-if="item.id" type="hidden"
|
||||
:name="'{{ formset.prefix }}-' + row + '-id'"
|
||||
:value="item.data.id"/>
|
||||
|
||||
@ -59,11 +56,17 @@
|
||||
{% for field in admin_formset.fields %}
|
||||
{% if not field.widget.is_hidden and not field.is_readonly %}
|
||||
<template v-slot:row-{{ field.name }}="{item,col,row,value,attr,emit}">
|
||||
<div class="control">
|
||||
<input type="{{ widget.type }}" class="input half-field"
|
||||
:name="'{{ formset.prefix }}-' + row + '-{{ field.name }}'"
|
||||
v-model="item.data[attr]"
|
||||
@change="emit('change', col)"/>
|
||||
<div class="field">
|
||||
<div class="control">
|
||||
<input type="{{ widget.type }}"
|
||||
:class="['input', item.error(attr) ? 'is-danger' : 'half-field']"
|
||||
:name="'{{ formset.prefix }}-' + row + '-{{ field.name }}'"
|
||||
v-model="item.data[attr]"
|
||||
@change="emit('change', col)"/>
|
||||
</div>
|
||||
<p v-for="error in item.error(attr)" class="help is-danger">
|
||||
[[ error ]] !
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
{% endif %}
|
||||
|
@ -18,7 +18,7 @@ The audio player
|
||||
</noscript>
|
||||
|
||||
<a-player ref="player"
|
||||
:live-args="{url: '{% url "api:live" %}', timeout:10, src: {{ audio_streams|json }} || []}"
|
||||
:live-args="{url: '{% url "api:live" %}', timeout:10, src: {{ audio_streams|json|force_escape }} || []}"
|
||||
button-title="{% translate "Play or pause audio" %}">
|
||||
<template v-slot:content="{ loaded, live, current }">
|
||||
<h4 v-if="loaded" class="title is-4">
|
||||
|
@ -6,7 +6,7 @@ from django.contrib.admin.templatetags.admin_urls import admin_urlname
|
||||
from django.urls import reverse
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from aircox.models import Page, Diffusion, Log
|
||||
from aircox.models import Diffusion, Log
|
||||
|
||||
random.seed()
|
||||
register = template.Library()
|
||||
@ -17,7 +17,8 @@ def do_admin_url(obj, arg, pass_id=True):
|
||||
""" Reverse admin url for object """
|
||||
name = admin_urlname(obj._meta, arg)
|
||||
return reverse(name, args=(obj.id,)) if pass_id else reverse(name)
|
||||
|
||||
|
||||
|
||||
@register.filter(name='get_tracks')
|
||||
def do_get_tracks(obj):
|
||||
""" Get a list of track for the provided log, diffusion, or episode """
|
||||
@ -28,6 +29,7 @@ def do_get_tracks(obj):
|
||||
obj = obj.episode
|
||||
return obj.track_set.all()
|
||||
|
||||
|
||||
@register.simple_tag(name='has_perm', takes_context=True)
|
||||
def do_has_perm(context, obj, perm, user=None):
|
||||
""" Return True if ``user.has_perm('[APP].[perm]_[MODEL]')`` """
|
||||
@ -36,17 +38,21 @@ def do_has_perm(context, obj, perm, user=None):
|
||||
return user.has_perm('{}.{}_{}'.format(
|
||||
obj._meta.app_label, perm, obj._meta.model_name))
|
||||
|
||||
|
||||
@register.filter(name='is_diffusion')
|
||||
def do_is_diffusion(obj):
|
||||
""" Return True if object is a Diffusion. """
|
||||
return isinstance(obj, Diffusion)
|
||||
|
||||
|
||||
@register.filter(name='json')
|
||||
def do_json(obj,fields=""):
|
||||
def do_json(obj, fields=""):
|
||||
""" Return object as json """
|
||||
if fields:
|
||||
obj = { k: getattr(obj,k,None) for k in ','.split(fields) }
|
||||
return json.dumps(obj)
|
||||
obj = {k: getattr(obj, k, None)
|
||||
for k in ','.split(fields)}
|
||||
return mark_safe(json.dumps(obj))
|
||||
|
||||
|
||||
@register.simple_tag(name='nav_items', takes_context=True)
|
||||
def do_nav_items(context, menu, **kwargs):
|
||||
@ -55,6 +61,7 @@ def do_nav_items(context, menu, **kwargs):
|
||||
return [(item, item.render(request, **kwargs))
|
||||
for item in station.navitem_set.filter(menu=menu)]
|
||||
|
||||
|
||||
@register.simple_tag(name='update_query')
|
||||
def do_update_query(obj, **kwargs):
|
||||
""" Replace provided querydict's values with **kwargs. """
|
||||
@ -65,6 +72,7 @@ def do_update_query(obj, **kwargs):
|
||||
obj.pop(k)
|
||||
return obj
|
||||
|
||||
|
||||
@register.filter(name='verbose_name')
|
||||
def do_verbose_name(obj, plural=False):
|
||||
"""
|
||||
@ -72,6 +80,5 @@ def do_verbose_name(obj, plural=False):
|
||||
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
|
||||
|
||||
obj._meta.verbose_name_plural if plural else \
|
||||
obj._meta.verbose_name
|
||||
|
@ -1,16 +1,27 @@
|
||||
from django import template
|
||||
from django.contrib import admin
|
||||
|
||||
from ..serializers import AdminTrackSerializer
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.simple_tag(name='get_admin_tools')
|
||||
def do_get_admin_tools():
|
||||
return admin.site.get_tools()
|
||||
|
||||
|
||||
@register.filter(name='serialize_track')
|
||||
def do_serialize_track(instance):
|
||||
ser = AdminTrackSerializer(instance=instance)
|
||||
return ser.data
|
||||
@register.filter(name='inline_data')
|
||||
def do_inline_data(formset):
|
||||
items = []
|
||||
for form in formset.forms:
|
||||
item = {name: form[name].value()
|
||||
for name in form.fields.keys()}
|
||||
item['__errors__'] = form.errors
|
||||
|
||||
# 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)
|
||||
return {"items": items}
|
||||
|
||||
|
Reference in New Issue
Block a user