#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,44 +0,0 @@
{% extends "admin/change_form.html" %}
{% comment %}Admin edit template to edit pages.{% endcomment %}
{% load admin_urls i18n static %}
{% if not is_popup %}
{% block breadcrumbs %}
<div class="breadcrumbs">
<a href="{% url 'admin:index' %}">{% translate 'Home' %}</a>
&rsaquo; <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
&rsaquo; {% if has_view_permission %}<a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a>{% else %}{{ opts.verbose_name_plural|capfirst }}{% endif %}
{% if parent %}
&rsaquo; <a href="{% url opts|admin_urlname:"changelist" %}?parent={{parent.id}}">{{ parent.title }}</a>
{% endif %}
&rsaquo; {% if add %}{% blocktranslate with name=opts.verbose_name %}Add {{ name }}{% endblocktranslate %}{% else %}{{ original|truncatewords:"18" }}{% endif %}
</div>
{% endblock %}
{% endif %}
{% block submit_buttons_bottom %}
{% if has_change_permission %}
<div class="columns is-size-5">
<div class="column has-text-left">
{% if original and not original.is_trash %}
<button type="submit" name="status" value="32" class="button is-danger is-size-6">{% translate "Move to trash" %}</button>
{% endif %}
{% if original and not original.is_draft %}
<button type="submit" name="status" value="0" class="button is-warning is-size-6">{% translate "Mark as draft" %}</button>
{% endif %}
</div>
<div class="column has-text-right">
<button type="submit" class="button is-secondary is-size-6">{% translate "Save" %}</button>
<button type="submit" name="_continue" class="button is-secondary is-size-6">{% translate "Save and continue" %}</button>
{% if not original.is_published %}
<button type="submit" name="status" value="16" class="button is-primary is-size-6">{% translate "Publish" %}</button>
{% endif %}
</div>
{% endif %}
</div>
{% endblock %}

View File

@ -1,19 +0,0 @@
{% extends "admin/change_list.html" %}
{% load admin_urls i18n %}
{% if not is_popup %}
{% block breadcrumbs %}
<div class="breadcrumbs">
<a href="{% url 'admin:index' %}">{% translate 'Home' %}</a>
&rsaquo; <a href="{% url 'admin:app_list' app_label=cl.opts.app_label %}">{{ cl.opts.app_config.verbose_name }}</a>
{% if parent %}
&rsaquo; <a href="{% url cl.opts|admin_urlname:'changelist' %}">{{ cl.opts.verbose_name_plural|capfirst }}</a>
<b>&rsaquo; {{ parent.title }}</b>
{% else %}
&rsaquo; {{ cl.opts.verbose_name_plural|capfirst }}
{% endif %}
</div>
{% endblock %}
{% endif %}

View File

@ -1,85 +0,0 @@
{% comment %}Inline block to edit playlists{% endcomment %}
{% load aircox aircox_admin static i18n %}
{% with inline_admin_formset as admin_formset %}
{% with admin_formset.formset as formset %}
<div id="inline-tracks" class="box mb-5">
{{ admin_formset.non_form_errors }}
<a-playlist-editor
:labels="{% track_inline_labels %}"
:init-data="{% track_inline_data formset=formset %}"
settings-url="{% url "api:user-settings" %}"
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"/>
<input type="hidden" name="{{ formset.prefix }}-INITIAL_FORMS"
value="{{ formset.initial_form_count }}"/>
<input type="hidden" name="{{ formset.prefix }}-MIN_NUM_FORMS"
value="{{ formset.min_num }}"/>
<input type="hidden" name="{{ formset.prefix }}-MAX_NUM_FORMS"
value="{{ formset.max_num }}"/>
</template>
<template #rows-header-head>
<th style="max-width:2em" title="{% trans "Track Position" %}"
aria-description="{% trans "Track Position" %}">
<span class="icon">
<i class="fa fa-arrow-down-1-9"></i>
</span>
</th>
</template>
<template v-slot:row-head="{item,row}">
<td>
[[ row+1 ]]
<input type="hidden"
:name="'{{ formset.prefix }}-' + row + '-position'"
:value="row"/>
<input t-if="item.data.id" type="hidden"
:name="'{{ formset.prefix }}-' + row + '-id'"
:value="item.data.id || item.id"/>
{% for field in admin_formset.fields %}
{% if field.name != 'position' and field.widget.is_hidden %}
<input type="hidden"
:name="'{{ formset.prefix }}-' + row + '-{{ field.name }}'"
v-model="item.data[attr]"/>
{% endif %}
{% endfor %}
</td>
</template>
{% for field in admin_formset.fields %}
{% if not field.widget.is_hidden and not field.is_readonly %}
<template v-slot:row-{{ field.name }}="{item,cell,value,attr,emit}">
<div class="field">
{% if field.name in 'artist,title,album' %}
<a-autocomplete
:input-class="['input', item.error(attr) ? 'is-danger' : 'half-field']"
url="{% url 'api:track-autocomplete' %}?{{ field.name }}=${query}&field={{ field.name }}"
{% else %}
<div class="control">
<input type="{{ widget.type }}"
:class="['input', item.error(attr) ? 'is-danger' : 'half-field']"
{% endif %}
:name="'{{ formset.prefix }}-' + cell.row + '-{{ field.name }}'"
v-model="item.data[attr]"
title="{{ field.help }}"
@change="emit('change', col)"/>
{% if field.name not in 'artist,title,album' %}
</div>
{% endif %}
<p v-for="error in item.error(attr)" class="help is-danger">
[[ error ]] !
</p>
</div>
</template>
{% endif %}
{% endfor %}
</a-playlist-editor>
</div>
{% endwith %}
{% endwith %}

View File

@ -1,82 +0,0 @@
{% extends "admin/base_site.html" %}
{% comment %}Admin tool displaying logs statistics{% endcomment %}
{% load i18n aircox %}
{% block content %}{{ block.super }}
<div id="app">
{# TODO: date subtitle #}
<nav class="navbar" role="menu">
{% with "admin:tools-stats" as url_name %}
{% include "aircox/widgets/dates_menu.html" %}
{% endwith %}
</nav>
<a-statistics class="column">
<template v-slot="{counts}">
<table class="table is-hoverable is-fullwidth">
<thead>
<tr>
<th>{% translate "Time" %}</th>
<th>{% translate "Episode" %}</th>
<th>{% translate "Track" %}</th>
<th>{% translate "Tags" %}</th>
</tr>
</thead>
<tbody>
{% for object in object_list %}
{% with object|get_tracks as tracks %}
{% for track in tracks %}
<tr>
{% if forloop.first %}
<td rowspan="{{ tracks|length }}">{{ object.start|time:"H:i" }} {% if object|is_diffusion %} - {{ object.end|time:"H:i" }}{% endif %}</td>
<td rowspan="{{ tracks|length }}">{{ object.episode|default:"" }}</td>
{% endif %}
{% with track as object %}
<td>{% include "aircox/widgets/track_item.html" %}</td>
{% endwith %}
{% with track.tags.all|join:', ' as tags %}
<td>
{% if tags %}
<label class="checkbox">
<input type="checkbox" checked value="{{ tags|escape }}" name="data">
{{ tags }}
</label>
{% endif %}
</td>
{% endwith %}
</tr>
{% empty %}
{% if object|is_diffusion %}
<tr>
<td>{{ object.start|time:"H:i" }} - {{ object.end|time:"H:i" }}</td>
<td>{{ object.episode|default:"" }}</td>
<td></td>
<td></td>
</tr>
{% endif %}
{% endfor %}
{% endwith %}
{% endfor %}
</tbody>
<tfoot>
<tr>
<td class="is-size-6">{% translate "Total" %}</td>
<td colspan="100">
<div class="columns is-size-6">
<span v-for="(count, tag) in counts" class="column">
<b>[[ tag ]]</b>
[[ count ]]
</span>
</div>
</td>
</tr>
</tfoot>
</table>
</template>
</a-statistics>
</div>
{% endblock %}

View File

@ -1,224 +0,0 @@
{% load i18n static aircox_admin %}<!DOCTYPE html>
{% get_current_language as LANGUAGE_CODE %}{% get_current_language_bidi as LANGUAGE_BIDI %}
<html lang="{{ LANGUAGE_CODE|default:"en-us" }}" {% if LANGUAGE_BIDI %}dir="rtl"{% endif %}>
<head>
<title>{% block title %}{% endblock %}</title>
<!-- <link rel="stylesheet" type="text/css" href="{% static "aircox/vendor.css" %}"> -->
<link rel="stylesheet" type="text/css" href="{% static "admin/css/base.css" %}">
<link rel="stylesheet" type="text/css" href="{% static "aircox/css/chunk-common.css" %}"/>
<link rel="stylesheet" type="text/css" href="{% static "aircox/css/chunk-vendors.css" %}"/>
<link rel="stylesheet" type="text/css" href="{% static "aircox/css/admin.css" %}"/>
<script src="{% static "aircox/js/chunk-common.js" %}"></script>
<script src="{% static "aircox/js/chunk-vendors.js" %}"></script>
<script src="{% static "aircox/js/admin.js" %}"></script>
{% block extrastyle %}{% endblock %}
{% if LANGUAGE_BIDI %}<link rel="stylesheet" type="text/css" href="{% block stylesheet_rtl %}{% static "admin/css/rtl.css" %}{% endblock %}">{% endif %}
{% block extrahead %}{% endblock %}
{% block responsive %}
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0">
<link rel="stylesheet" type="text/css" href="{% static "admin/css/responsive.css" %}">
{% if LANGUAGE_BIDI %}<link rel="stylesheet" type="text/css" href="{% static "admin/css/responsive_rtl.css" %}">{% endif %}
{% endblock %}
{% block blockbots %}<meta name="robots" content="NONE,NOARCHIVE">{% endblock %}
</head>
{% load i18n %}
<body class="{% if is_popup %}popup {% endif %}{% block bodyclass %}{% endblock %}"
data-admin-utc-offset="{% now "Z" %}">
<script id="init-script">
function vuePre(selector) {
const elms = document.querySelectorAll(selector)
for(const elm of elms) {
elm.setAttribute('v-pre', true)
}
}
window.addEventListener('load', function() {
{% block init-scripts %}
aircox.init(null, {
hotReload: false,
{% if not init_app %}
initBuilder: false,
{% endif %}
{% if init_el %}
el: "{{ init_el }}",
{% endif %}
})
{% endblock %}
})
</script>
<!-- Container -->
<div class="admin">
{% if not is_popup %}
<!-- Header -->
<nav class="navbar is-dark has-shadow">
<div class="navbar-brand">
{% block branding %}{% endblock %}
</div>
<div class="navbar-menu">
{% block usertools %}
<div class="navbar-start">
{# Today's diffusions #}
<div class="navbar-item has-dropdown is-hoverable">
<span class="icon-text navbar-link">
<span class="icon"><i class="fa-regular fa-calendar-days"></i></span>
<span>{% translate "Today" %}</span>
</span>
<div class="navbar-dropdown is-boxed">
{% for diffusion in diffusions %}
<a class="navbar-item {% if diffusion.is_now %}has-background-primary{% endif %}" href="{% url "admin:aircox_episode_change" diffusion.episode.pk %}">
{{ diffusion.start|time }} |
{{ diffusion.episode.title }}
</a>
{% endfor %}
</div>
</div>
{# Articles #}
<div class="navbar-item has-dropdown is-hoverable">
<a class="icon-text navbar-link" href="{% url "admin:aircox_article_changelist" %}">
<span class="icon"><i class="fa fa-newspaper"></i></span>
<span>{% translate "Articles" %}</span>
</a>
<div class="navbar-dropdown is-boxed">
<input type="text" onkeyup="aircox.filter_menu(event)"
placeholder="{% translate "Search" %}" class="navbar-item input" />
<hr class="navbar-divider"/>
{% for program in programs %}
<a class="navbar-item" href="{% url "admin:aircox_article_changelist" %}?parent={{ program.pk }}">
{{ program.title }}</a>
{% endfor %}
</div>
</div>
{# Programs #}
<div class="navbar-item has-dropdown is-hoverable">
<a class="icon-text navbar-link" href="{% url "admin:aircox_program_changelist" %}">
<span class="icon"><i class="fa fa-folder"></i></span>
<span>{% translate "Programs" %}</span>
</a>
<div class="navbar-dropdown is-boxed">
<input type="text" onkeyup="aircox.filter_menu(event)"
placeholder="{% translate "Search" %}" class="navbar-item input" />
<hr class="navbar-divider"/>
{% for program in programs %}
<a class="navbar-item" href="{% url "admin:aircox_program_change" program.pk %}">
{{ program.title }}</a>
{% endfor %}
</div>
</div>
{# Episodes #}
<div class="navbar-item has-dropdown is-hoverable">
<a class="icon-text navbar-link" href="{% url "admin:aircox_episode_changelist" %}">
<span class="icon"><i class="fa fa-calendar-check"></i></span>
<span>{% translate "Episodes" %}</span>
</a>
<div class="navbar-dropdown is-boxed">
<input type="text" onkeyup="aircox.filter_menu(event)"
placeholder="{% translate "Search" %}" class="navbar-item input" />
<hr class="navbar-divider"/>
{% for program in programs %}
<a class="navbar-item" href="{% url "admin:aircox_episode_changelist" %}?parent={{ program.pk }}">
{{ program.title }}</a>
{% endfor %}
</div>
</div>
</div>
<div class="navbar-end">
<div class="navbar-item has-dropdown is-hoverable">
<a href="#" class="icon-text navbar-link">
<span class="icon"><i class="fa-solid fa-screwdriver-wrench"></i></span>
<span>{% translate "Tools" %}</span>
</a>
<div class="navbar-dropdown is-boxed is-right">
{% get_admin_tools as admin_tools %}
{% for label, url in admin_tools %}
<a href="{{ url }}" class="navbar-item">{{ label }}</a>
{% endfor %}
</div>
</div>
<div class="navbar-item has-dropdown is-hoverable">
<a href="{% url "admin:auth_user_change" user.pk %}" class="icon-text navbar-link">
<span class="icon"><i class="fa fa-user"></i></span>
<span>{% firstof user.get_short_name user.get_username %}</span>
</a>
<div class="navbar-dropdown is-boxed is-right">
{% block userlinks %}
{% if site_url %}
<a href="{{ site_url }}" class="navbar-item">{% translate 'View site' %}</a>
{% endif %}
{% if user.is_active and user.is_staff %}
{% url 'django-admindocs-docroot' as docsroot %}
{% if docsroot %}
<a href="{{ docsroot }}" class="navbar-item">{% translate 'Documentation' %}</a>
{% endif %}
{% endif %}
{% if user.has_usable_password %}
<a href="{% url 'admin:password_change' %}" class="navbar-item">{% translate 'Change password' %}</a>
{% endif %}
<hr class="navbar-divider" />
<a href="{% url 'admin:logout' %}" class="navbar-item">{% translate 'Log out' %}</a>
{% endblock %}
</div>
</div>
</div>
{% endblock %}
</div>
{% block nav-global %}{% endblock %}
</nav>
<!-- END Header -->
{% block breadcrumbs %}
<div class="breadcrumbs">
<a href="{% url 'admin:index' %}">{% translate 'Home' %}</a>
{% if title %} &rsaquo; {{ title }}{% endif %}
</div>
{% endblock %}
{% endif %}
{% block messages %}
{% if messages %}
<ul class="messagelist">{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message|capfirst }}</li>
{% endfor %}</ul>
{% endif %}
{% endblock messages %}
<!-- Content -->
<div id="app">
{% block app %}
<div id="content" class="{% block coltype %}colM{% endblock %}">
{% block pretitle %}{% endblock %}
{% block content_title %}{% if title %}<h1 class="title is-3">{{ title }}</h1>{% endif %}{% endblock %}
{% block content %}
{% block object-tools %}{% endblock %}
{{ content }}
{% endblock %}
{% block sidebar %}{% endblock %}
<br class="clear">
</div>
{% endblock %}
</div>
<!-- END Content -->
{% block footer %}<div id="footer"></div>{% endblock %}
</div>
<!-- END Container -->
{% block player %}
{% if request.station %}
<div id="player">{% include "aircox/widgets/player.html" %}</div>
{% endif %}
{% endblock %}
</body>
</html>

View File

@ -1,8 +0,0 @@
{% extends "admin/base_site.html" %}
{% load static %}
{% block branding %}
<a href="{% url 'admin:index' %}">
<img src="{% static "aircox/logo.png" %}"/>
</a>
{% endblock %}

View File

@ -1,5 +0,0 @@
{% extends "admin/change_form.html" %}
{% block content %}
<div v-pre>{{ block.super }}</div>
{% endblock %}

View File

@ -1,89 +0,0 @@
{% extends "admin/base_site.html" %}
{% load i18n admin_urls static admin_list %}
{% block extrastyle %}
{{ block.super }}
{% if cl.formset %}
<link rel="stylesheet" type="text/css" href="{% static "admin/css/forms.css" %}">
{% endif %}
{% if cl.formset or action_form %}
<script type="text/javascript" src="{% url 'admin:jsi18n' %}"></script>
{% endif %}
{{ media.css }}
{% if not actions_on_top and not actions_on_bottom %}
<style>
#changelist table thead th:first-child {width: inherit}
</style>
{% endif %}
{% endblock %}
{% block extrahead %}
{{ block.super }}
{{ media.js }}
{% endblock %}
{% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} change-list{% endblock %}
{% if not is_popup %}
{% block breadcrumbs %}
<div class="breadcrumbs">
<a href="{% url 'admin:index' %}">{% translate 'Home' %}</a>
&rsaquo; <a href="{% url 'admin:app_list' app_label=cl.opts.app_label %}">{{ cl.opts.app_config.verbose_name }}</a>
&rsaquo; {{ cl.opts.verbose_name_plural|capfirst }}
</div>
{% endblock %}
{% endif %}
{% block coltype %}flex{% endblock %}
{% block content %}
<div id="content-main">
{% block object-tools %}
<ul class="object-tools">
{% block object-tools-items %}
{% change_list_object_tools %}
{% endblock %}
</ul>
{% endblock %}
{% if cl.formset and cl.formset.errors %}
<p class="errornote">
{% if cl.formset.total_error_count == 1 %}{% translate "Please correct the error below." %}{% else %}{% trans "Please correct the errors below." %}{% endif %}
</p>
{{ cl.formset.non_form_errors }}
{% endif %}
<div class="columns is-fullwidth module {% if cl.has_filters %} filtered{% endif %}" id="changelist">
<div class="column">
<form id="changelist-form" method="post"{% if cl.formset and cl.formset.is_multipart %} enctype="multipart/form-data"{% endif %} novalidate>{% csrf_token %}
{% if cl.formset %}
<div>{{ cl.formset.management_form }}</div>
{% endif %}
{% block result_list %}
{% if action_form and actions_on_top and cl.show_admin_actions %}{% admin_actions %}{% endif %}
{% result_list cl %}
{% if action_form and actions_on_bottom and cl.show_admin_actions %}{% admin_actions %}{% endif %}
{% endblock %}
{% block pagination %}{% pagination cl %}{% endblock %}
</form>
</div>
<div class="column is-one-quarter">
{% block search %}{% search_form cl %}{% endblock %}
<hr>
{% block date_hierarchy %}{% if cl.date_hierarchy %}{% date_hierarchy cl %}{% endif %}{% endblock %}
{% block filters %}
{% if cl.has_filters %}
<div id="changelist-filter">
<h2>{% translate 'Filter' %}</h2>
{% for spec in cl.filter_specs %}{% admin_list_filter cl spec %}{% endfor %}
</div>
{% endif %}
{% endblock %}
</div>
</div>
</div>
{% endblock %}

View File

@ -1,94 +0,0 @@
{% extends "admin/index.html" %}
{% load i18n thumbnail %}
{% block app %}
<div class="section">
<div class="columns">
<div class="column">
<div class="box">
<h1 class="title icon-text is-4">
<span class="icon"><i class="fa-regular fa-calendar-days"></i></span>
<span>{% translate "Today" %}</span>
</h1>
{% if diffusions %}
<table class="table is-fullwidth is-striped">
<tbody>
{% for diffusion in diffusions %}
{% with episode=diffusion.episode %}
<tr {% if diffusion.is_now %}class="is-selected"{% endif %}>
<td>{{ diffusion.start|time }} - {{ diffusion.end|time }}</td>
<td><img src="{% thumbnail episode.cover 64x64 crop %}"/></td>
<td>
<a href="{% url "admin:aircox_episode_change" episode.pk %}">{{ episode.title }}</a>
&nbsp;
{% if diffusion.type == diffusion.TYPE_ON_AIR %}
<span class="tag is-info">
<span class="icon is-small">
{% if diffusion.is_live %}
<i class="fa fa-microphone"
title="{% translate "Live diffusion" %}"></i>
{% else %}
<i class="fa fa-music"
title="{% translate "Differed diffusion" %}"></i>
{% endif %}
</span>
&nbsp;
{{ diffusion.get_type_display }}
</span>
{% elif diffusion.type == diffusion.TYPE_CANCEL %}
<span class="tag is-danger">
{{ diffusion.get_type_display }}</span>
{% elif diffusion.type == diffusion.TYPE_UNCONFIRMED %}
<span class="tag is-warning">
{{ diffusion.get_type_display }}</span>
{% endif %}
</td>
</tr>
{% endwith %}
{% endfor %}
</tbody>
</table>
{% else %}
<div class="block has-text-centered">
{% trans "No diffusion is scheduled for today." %}
</div>
{% endif %}
</div>
<div class="box">
<h1 class="title is-4 icon-text">
<span class="icon"><i class="fa-regular fa-comments"></i></span>
<span>{% translate "Latest comments" %}</span>
</h1>
{% if comments %}
{% include "aircox/widgets/page_list.html" with object_list=comments with_title=True %}
<div class="has-text-centered">
<a href="{% url "admin:aircox_comment_changelist" %}" class="float-center">{% translate "All comments" %}</a>
</div>
{% else %}
<p class="block has-text-centered">{% trans "No comment posted yet" %}</p>
{% endif %}
</div>
</div>
<div class="column">
<div class="box">
<h1 class="title is-4 icon-text">
<span class="icon"><i class="fa-regular fa-newspaper"></i></span>
<span>{% translate "Latest publications" %}</span>
</h1>
{% if latests %}
{% include "aircox/widgets/page_list.html" with object_list=latests no_actions=True %}
{% endif %}
</div>
<div class="box">
<h1 class="title is-4 icon-text">
<span class="icon"><i class="fa fa-screwdriver-wrench"></i></span>
<span>{% translate "Administration" %}</span>
</h1>
{% include "admin/app_list.html" with app_list=app_list show_changelinks=True %}
</div>
</div>
</div>
</div>
{% endblock %}