Compare commits
No commits in common. "eb5bdcf16742e119a600376d52bf75fc415ed059" and "7cdf44b901e448f63db2ebe28513fb1c4c160ef5" have entirely different histories.
eb5bdcf167
...
7cdf44b901
|
@ -1,23 +1,14 @@
|
||||||
import django_filters as filters
|
import django_filters as filters
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from . import models
|
from .models import Episode, Page
|
||||||
|
|
||||||
|
|
||||||
__all__ = (
|
|
||||||
"PageFilters",
|
|
||||||
"EpisodeFilters",
|
|
||||||
"ImageFilterSet",
|
|
||||||
"SoundFilterSet",
|
|
||||||
"TrackFilterSet",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class PageFilters(filters.FilterSet):
|
class PageFilters(filters.FilterSet):
|
||||||
q = filters.CharFilter(method="search_filter", label=_("Search"))
|
q = filters.CharFilter(method="search_filter", label=_("Search"))
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = models.Page
|
model = Page
|
||||||
fields = {
|
fields = {
|
||||||
"category__id": ["in", "exact"],
|
"category__id": ["in", "exact"],
|
||||||
"pub_date": ["exact", "gte", "lte"],
|
"pub_date": ["exact", "gte", "lte"],
|
||||||
|
@ -31,33 +22,10 @@ class EpisodeFilters(PageFilters):
|
||||||
podcast = filters.BooleanFilter(method="podcast_filter", label=_("Podcast"))
|
podcast = filters.BooleanFilter(method="podcast_filter", label=_("Podcast"))
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = models.Episode
|
model = Episode
|
||||||
fields = PageFilters.Meta.fields.copy()
|
fields = PageFilters.Meta.fields.copy()
|
||||||
|
|
||||||
def podcast_filter(self, queryset, name, value):
|
def podcast_filter(self, queryset, name, value):
|
||||||
if value:
|
if value:
|
||||||
return queryset.filter(sound__is_public=True).distinct()
|
return queryset.filter(sound__is_public=True).distinct()
|
||||||
return queryset.filter(sound__isnull=True)
|
return queryset.filter(sound__isnull=True)
|
||||||
|
|
||||||
|
|
||||||
class ImageFilterSet(filters.FilterSet):
|
|
||||||
search = filters.CharFilter(field_name="search", method="search_filter")
|
|
||||||
|
|
||||||
def search_filter(self, queryset, name, value):
|
|
||||||
return queryset.filter(original_filename__icontains=value)
|
|
||||||
|
|
||||||
|
|
||||||
class SoundFilterSet(filters.FilterSet):
|
|
||||||
station = filters.NumberFilter(field_name="program__station__id")
|
|
||||||
program = filters.NumberFilter(field_name="program_id")
|
|
||||||
episode = filters.NumberFilter(field_name="episode_id")
|
|
||||||
search = filters.CharFilter(field_name="search", method="search_filter")
|
|
||||||
|
|
||||||
def search_filter(self, queryset, name, value):
|
|
||||||
return queryset.search(value)
|
|
||||||
|
|
||||||
|
|
||||||
class TrackFilterSet(filters.FilterSet):
|
|
||||||
artist = filters.CharFilter(field_name="artist", lookup_expr="icontains")
|
|
||||||
album = filters.CharFilter(field_name="album", lookup_expr="icontains")
|
|
||||||
title = filters.CharFilter(field_name="title", lookup_expr="icontains")
|
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
from django import forms
|
from django import forms
|
||||||
|
from django.forms import ModelForm, ImageField, FileField
|
||||||
|
|
||||||
|
from ckeditor.fields import RichTextField
|
||||||
|
from filer.models.imagemodels import Image
|
||||||
from filer.models.filemodels import File
|
from filer.models.filemodels import File
|
||||||
|
|
||||||
from aircox import models
|
from aircox.models import Comment, Episode, Program
|
||||||
from aircox.controllers.sound_file import SoundFile
|
from aircox.controllers.sound_file import SoundFile
|
||||||
|
|
||||||
|
|
||||||
__all__ = ("CommentForm", "PageForm", "ProgramForm", "EpisodeForm")
|
class CommentForm(ModelForm):
|
||||||
|
|
||||||
|
|
||||||
class CommentForm(forms.ModelForm):
|
|
||||||
nickname = forms.CharField()
|
nickname = forms.CharField()
|
||||||
email = forms.EmailField(required=False)
|
email = forms.EmailField(required=False)
|
||||||
content = forms.CharField(widget=forms.Textarea())
|
content = forms.CharField(widget=forms.Textarea())
|
||||||
|
@ -19,31 +19,32 @@ class CommentForm(forms.ModelForm):
|
||||||
content.widget.attrs.update({"class": "textarea"})
|
content.widget.attrs.update({"class": "textarea"})
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = models.Comment
|
model = Comment
|
||||||
fields = ["nickname", "email", "content"]
|
fields = ["nickname", "email", "content"]
|
||||||
|
|
||||||
|
|
||||||
class ImageForm(forms.Form):
|
class ProgramForm(ModelForm):
|
||||||
file = forms.ImageField()
|
content = RichTextField()
|
||||||
|
new_cover = ImageField(required=False)
|
||||||
|
|
||||||
class PageForm(forms.ModelForm):
|
|
||||||
class Meta:
|
|
||||||
fields = ("title", "status", "cover", "content")
|
|
||||||
model = models.Page
|
|
||||||
|
|
||||||
|
|
||||||
class ProgramForm(PageForm):
|
|
||||||
class Meta:
|
|
||||||
fields = PageForm.Meta.fields
|
|
||||||
model = models.Program
|
|
||||||
|
|
||||||
|
|
||||||
class EpisodeForm(PageForm):
|
|
||||||
new_podcast = forms.FileField(required=False)
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = models.Episode
|
model = Program
|
||||||
|
fields = ["content"]
|
||||||
|
|
||||||
|
def save(self, commit=True):
|
||||||
|
file_obj = self.cleaned_data["new_cover"]
|
||||||
|
if file_obj:
|
||||||
|
obj, _ = Image.objects.get_or_create(original_filename=file_obj.name, file=file_obj)
|
||||||
|
self.instance.cover = obj
|
||||||
|
super().save(commit=commit)
|
||||||
|
|
||||||
|
|
||||||
|
class EpisodeForm(ModelForm):
|
||||||
|
content = RichTextField()
|
||||||
|
new_podcast = FileField(required=False)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Episode
|
||||||
fields = ["content"]
|
fields = ["content"]
|
||||||
|
|
||||||
def save(self, commit=True):
|
def save(self, commit=True):
|
||||||
|
|
|
@ -13,7 +13,6 @@ class AircoxMiddleware(object):
|
||||||
"""Middleware used to get default info for the given website.
|
"""Middleware used to get default info for the given website.
|
||||||
|
|
||||||
It provide following request attributes:
|
It provide following request attributes:
|
||||||
- ``mobile``: set to True if mobile device is detected
|
|
||||||
- ``station``: current Station
|
- ``station``: current Station
|
||||||
|
|
||||||
This middleware must be set after the middleware
|
This middleware must be set after the middleware
|
||||||
|
@ -25,11 +24,6 @@ class AircoxMiddleware(object):
|
||||||
def __init__(self, get_response):
|
def __init__(self, get_response):
|
||||||
self.get_response = get_response
|
self.get_response = get_response
|
||||||
|
|
||||||
def is_mobile(self, request):
|
|
||||||
if agent := request.META.get("HTTP_USER_AGENT"):
|
|
||||||
return " Mobi" in agent
|
|
||||||
return False
|
|
||||||
|
|
||||||
def get_station(self, request):
|
def get_station(self, request):
|
||||||
"""Return station for the provided request."""
|
"""Return station for the provided request."""
|
||||||
host = request.get_host()
|
host = request.get_host()
|
||||||
|
@ -51,7 +45,6 @@ class AircoxMiddleware(object):
|
||||||
def __call__(self, request):
|
def __call__(self, request):
|
||||||
self.init_timezone(request)
|
self.init_timezone(request)
|
||||||
request.station = self.get_station(request)
|
request.station = self.get_station(request)
|
||||||
request.is_mobile = self.is_mobile(request)
|
|
||||||
try:
|
try:
|
||||||
return self.get_response(request)
|
return self.get_response(request)
|
||||||
except Redirect:
|
except Redirect:
|
||||||
|
|
|
@ -127,9 +127,9 @@ class Program(Page):
|
||||||
self.editors = editors
|
self.editors = editors
|
||||||
super().save()
|
super().save()
|
||||||
permission, _ = Permission.objects.get_or_create(
|
permission, _ = Permission.objects.get_or_create(
|
||||||
|
name=f"change program {self.title}",
|
||||||
codename=self.change_permission_codename,
|
codename=self.change_permission_codename,
|
||||||
content_type=ContentType.objects.get_for_model(self),
|
content_type=ContentType.objects.get_for_model(self),
|
||||||
defaults={"name": f"change program {self.title}"},
|
|
||||||
)
|
)
|
||||||
if permission not in editors.permissions.all():
|
if permission not in editors.permissions.all():
|
||||||
editors.permissions.add(permission)
|
editors.permissions.add(permission)
|
||||||
|
|
|
@ -81,9 +81,6 @@ class Station(models.Model):
|
||||||
max_length=64,
|
max_length=64,
|
||||||
default=_("Music stream"),
|
default=_("Music stream"),
|
||||||
)
|
)
|
||||||
legal_label = models.CharField(
|
|
||||||
_("Legal label"), max_length=64, blank=True, default="", help_text=_("Displayed at the bottom of pages.")
|
|
||||||
)
|
|
||||||
|
|
||||||
objects = StationQuerySet.as_manager()
|
objects = StationQuerySet.as_manager()
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,9 @@
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from filer.models.imagemodels import Image
|
|
||||||
from taggit.serializers import TaggitSerializer, TagListSerializerField
|
from taggit.serializers import TaggitSerializer, TagListSerializerField
|
||||||
|
|
||||||
from ..models import Track, UserSettings
|
from ..models import Track, UserSettings
|
||||||
|
|
||||||
__all__ = ("ImageSerializer", "TrackSerializer", "UserSettingsSerializer")
|
__all__ = ("TrackSerializer", "UserSettingsSerializer")
|
||||||
|
|
||||||
|
|
||||||
class ImageSerializer(serializers.ModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = Image
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class TrackSerializer(TaggitSerializer, serializers.ModelSerializer):
|
class TrackSerializer(TaggitSerializer, serializers.ModelSerializer):
|
||||||
|
|
|
@ -27,8 +27,8 @@
|
||||||
--preview-cover-size: 14rem;
|
--preview-cover-size: 14rem;
|
||||||
--preview-cover-small-size: 10rem;
|
--preview-cover-small-size: 10rem;
|
||||||
--preview-cover-tiny-size: 4rem;
|
--preview-cover-tiny-size: 4rem;
|
||||||
--preview-wide-content-sz: 1.2rem;
|
--preview-wide-content-sz: 1.6rem;
|
||||||
--preview-heading-bg-color: var(--main-color);
|
--preview-heading-bg-color: var(--hg-color);
|
||||||
--header-height: var(--cover-h);
|
--header-height: var(--cover-h);
|
||||||
--a-carousel-p: 1.4rem;
|
--a-carousel-p: 1.4rem;
|
||||||
--a-carousel-ml: calc(1.2rem - 0.5rem);
|
--a-carousel-ml: calc(1.2rem - 0.5rem);
|
||||||
|
@ -76,6 +76,9 @@
|
||||||
--cover-tiny-w: 4rem;
|
--cover-tiny-w: 4rem;
|
||||||
--cover-tiny-h: 4rem;
|
--cover-tiny-h: 4rem;
|
||||||
--section-content-sz: 1rem;
|
--section-content-sz: 1rem;
|
||||||
|
--preview-title-sz: 1rem;
|
||||||
|
--preview-subtitle-sz: 0.8rem;
|
||||||
|
--preview-wide-content-sz: 1rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.title.is-1, .header.preview .title.is-1 {
|
.title.is-1, .header.preview .title.is-1 {
|
||||||
|
@ -121,10 +124,6 @@
|
||||||
color: var(--heading-hg-fg);
|
color: var(--heading-hg-fg);
|
||||||
}
|
}
|
||||||
|
|
||||||
.panels .panel:not(.active) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview {
|
.preview {
|
||||||
position: relative;
|
position: relative;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
|
@ -289,7 +288,7 @@
|
||||||
transition: box-shadow 0.2s;
|
transition: box-shadow 0.2s;
|
||||||
}
|
}
|
||||||
.preview-card:hover figure {
|
.preview-card:hover figure {
|
||||||
box-shadow: 0em 0em 1em rgba(0, 0, 0, 0.2);
|
box-shadow: 0em 0em 1.2em rgba(0, 0, 0, 0.4) !important;
|
||||||
}
|
}
|
||||||
.preview-card:hover a {
|
.preview-card:hover a {
|
||||||
color: var(--heading-link-hv-fg);
|
color: var(--heading-link-hv-fg);
|
||||||
|
@ -300,6 +299,9 @@
|
||||||
.preview-card .headings .heading {
|
.preview-card .headings .heading {
|
||||||
display: block !important;
|
display: block !important;
|
||||||
}
|
}
|
||||||
|
.preview-card .headings .title {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
.preview-card .headings .subtitle {
|
.preview-card .headings .subtitle {
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
}
|
}
|
||||||
|
@ -308,6 +310,7 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
.preview-card .card-content figure {
|
.preview-card .card-content figure {
|
||||||
|
box-shadow: 0em 0em 1em rgba(0, 0, 0, 0.2);
|
||||||
height: var(--cover-h);
|
height: var(--cover-h);
|
||||||
width: var(--cover-w);
|
width: var(--cover-w);
|
||||||
}
|
}
|
||||||
|
@ -318,6 +321,18 @@
|
||||||
right: 0rem;
|
right: 0rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.list-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
grid-auto-flow: dense;
|
||||||
|
gap: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 900px) {
|
||||||
|
.list-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
.a-carousel .a-carousel-viewport {
|
.a-carousel .a-carousel-viewport {
|
||||||
box-shadow: inset 0em 0em 20rem var(--a-carousel-bg);
|
box-shadow: inset 0em 0em 20rem var(--a-carousel-bg);
|
||||||
padding: 0rem;
|
padding: 0rem;
|
||||||
|
@ -529,34 +544,6 @@
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.a-select-file > *:not(:last-child) {
|
|
||||||
margin-bottom: 0.6rem;
|
|
||||||
}
|
|
||||||
.a-select-file .upload-preview {
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
.a-select-file .a-select-file-list {
|
|
||||||
max-height: 30rem;
|
|
||||||
overflow-y: auto;
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr 1fr 1fr 1fr;
|
|
||||||
gap: 0.6rem;
|
|
||||||
}
|
|
||||||
.a-select-file .file-preview {
|
|
||||||
width: 100%;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.a-select-file .file-preview:hover {
|
|
||||||
box-shadow: 0em 0em 1em rgba(0, 0, 0, 0.2);
|
|
||||||
}
|
|
||||||
.a-select-file .file-preview.active {
|
|
||||||
box-shadow: 0em 0em 1em rgba(0, 0, 0, 0.4);
|
|
||||||
}
|
|
||||||
.a-select-file .file-preview img {
|
|
||||||
width: 100%;
|
|
||||||
max-height: 10rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Bulma Utilities */
|
/* Bulma Utilities */
|
||||||
.button {
|
.button {
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
|
@ -2808,9 +2795,9 @@ a.navbar-item:focus, a.navbar-item:focus-within, a.navbar-item:hover, a.navbar-i
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
#player .button[disabled], #player .button.disabled, #player a.button[disabled], #player a.button.disabled, #player button.button[disabled], #player button.button.disabled, .ax .button[disabled], .ax .button.disabled, .ax a.button[disabled], .ax a.button.disabled, .ax button.button[disabled], .ax button.button.disabled {
|
#player .button[disabled], #player .button.disabled, #player a.button[disabled], #player a.button.disabled, #player button.button[disabled], #player button.button.disabled, .ax .button[disabled], .ax .button.disabled, .ax a.button[disabled], .ax a.button.disabled, .ax button.button[disabled], .ax button.button.disabled {
|
||||||
background-color: var(--text-color-light);
|
background-color: var(--hg-color-grey);
|
||||||
color: var(--secondary-color);
|
color: var(--hg-color-2);
|
||||||
border-color: var(--secondary-color-light);
|
border-color: var(--hg-color-2-alpha);
|
||||||
}
|
}
|
||||||
#player .button .dropdown-trigger, #player a.button .dropdown-trigger, #player button.button .dropdown-trigger, .ax .button .dropdown-trigger, .ax a.button .dropdown-trigger, .ax button.button .dropdown-trigger {
|
#player .button .dropdown-trigger, #player a.button .dropdown-trigger, #player button.button .dropdown-trigger, .ax .button .dropdown-trigger, .ax a.button .dropdown-trigger, .ax button.button .dropdown-trigger {
|
||||||
border-radius: 1.5em;
|
border-radius: 1.5em;
|
||||||
|
|
|
@ -98,7 +98,7 @@ fieldset[disabled] .file-name, fieldset[disabled] .select select, .select fields
|
||||||
width: 0.625em;
|
width: 0.625em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-container:not(:last-child), .table:not(:last-child), .box:not(:last-child), .message:not(:last-child) {
|
.table-container:not(:last-child), .table:not(:last-child), .content:not(:last-child), .box:not(:last-child), .message:not(:last-child) {
|
||||||
margin-bottom: 1.5rem;
|
margin-bottom: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6238,6 +6238,175 @@ a.box:active {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.content li + li {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
}
|
||||||
|
.content p:not(:last-child),
|
||||||
|
.content dl:not(:last-child),
|
||||||
|
.content ol:not(:last-child),
|
||||||
|
.content ul:not(:last-child),
|
||||||
|
.content blockquote:not(:last-child),
|
||||||
|
.content pre:not(:last-child),
|
||||||
|
.content table:not(:last-child) {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
.content h1,
|
||||||
|
.content h2,
|
||||||
|
.content h3,
|
||||||
|
.content h4,
|
||||||
|
.content h5,
|
||||||
|
.content h6 {
|
||||||
|
color: hsl(0deg, 0%, 21%);
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1.125;
|
||||||
|
}
|
||||||
|
.content h1 {
|
||||||
|
font-size: 2em;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
.content h1:not(:first-child) {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
.content h2 {
|
||||||
|
font-size: 1.75em;
|
||||||
|
margin-bottom: 0.5714em;
|
||||||
|
}
|
||||||
|
.content h2:not(:first-child) {
|
||||||
|
margin-top: 1.1428em;
|
||||||
|
}
|
||||||
|
.content h3 {
|
||||||
|
font-size: 1.5em;
|
||||||
|
margin-bottom: 0.6666em;
|
||||||
|
}
|
||||||
|
.content h3:not(:first-child) {
|
||||||
|
margin-top: 1.3333em;
|
||||||
|
}
|
||||||
|
.content h4 {
|
||||||
|
font-size: 1.25em;
|
||||||
|
margin-bottom: 0.8em;
|
||||||
|
}
|
||||||
|
.content h5 {
|
||||||
|
font-size: 1.125em;
|
||||||
|
margin-bottom: 0.8888em;
|
||||||
|
}
|
||||||
|
.content h6 {
|
||||||
|
font-size: 1em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
.content blockquote {
|
||||||
|
background-color: hsl(0deg, 0%, 96%);
|
||||||
|
border-left: 5px solid hsl(0deg, 0%, 86%);
|
||||||
|
padding: 1.25em 1.5em;
|
||||||
|
}
|
||||||
|
.content ol {
|
||||||
|
list-style-position: outside;
|
||||||
|
margin-left: 2em;
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
.content ol:not([type]) {
|
||||||
|
list-style-type: decimal;
|
||||||
|
}
|
||||||
|
.content ol:not([type]).is-lower-alpha {
|
||||||
|
list-style-type: lower-alpha;
|
||||||
|
}
|
||||||
|
.content ol:not([type]).is-lower-roman {
|
||||||
|
list-style-type: lower-roman;
|
||||||
|
}
|
||||||
|
.content ol:not([type]).is-upper-alpha {
|
||||||
|
list-style-type: upper-alpha;
|
||||||
|
}
|
||||||
|
.content ol:not([type]).is-upper-roman {
|
||||||
|
list-style-type: upper-roman;
|
||||||
|
}
|
||||||
|
.content ul {
|
||||||
|
list-style: disc outside;
|
||||||
|
margin-left: 2em;
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
.content ul ul {
|
||||||
|
list-style-type: circle;
|
||||||
|
margin-top: 0.5em;
|
||||||
|
}
|
||||||
|
.content ul ul ul {
|
||||||
|
list-style-type: square;
|
||||||
|
}
|
||||||
|
.content dd {
|
||||||
|
margin-left: 2em;
|
||||||
|
}
|
||||||
|
.content figure {
|
||||||
|
margin-left: 2em;
|
||||||
|
margin-right: 2em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.content figure:not(:first-child) {
|
||||||
|
margin-top: 2em;
|
||||||
|
}
|
||||||
|
.content figure:not(:last-child) {
|
||||||
|
margin-bottom: 2em;
|
||||||
|
}
|
||||||
|
.content figure img {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.content figure figcaption {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
.content pre {
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
overflow-x: auto;
|
||||||
|
padding: 1.25em 1.5em;
|
||||||
|
white-space: pre;
|
||||||
|
word-wrap: normal;
|
||||||
|
}
|
||||||
|
.content sup,
|
||||||
|
.content sub {
|
||||||
|
font-size: 75%;
|
||||||
|
}
|
||||||
|
.content table {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.content table td,
|
||||||
|
.content table th {
|
||||||
|
border: 1px solid hsl(0deg, 0%, 86%);
|
||||||
|
border-width: 0 0 1px;
|
||||||
|
padding: 0.5em 0.75em;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
.content table th {
|
||||||
|
color: hsl(0deg, 0%, 21%);
|
||||||
|
}
|
||||||
|
.content table th:not([align]) {
|
||||||
|
text-align: inherit;
|
||||||
|
}
|
||||||
|
.content table thead td,
|
||||||
|
.content table thead th {
|
||||||
|
border-width: 0 0 2px;
|
||||||
|
color: hsl(0deg, 0%, 21%);
|
||||||
|
}
|
||||||
|
.content table tfoot td,
|
||||||
|
.content table tfoot th {
|
||||||
|
border-width: 2px 0 0;
|
||||||
|
color: hsl(0deg, 0%, 21%);
|
||||||
|
}
|
||||||
|
.content table tbody tr:last-child td,
|
||||||
|
.content table tbody tr:last-child th {
|
||||||
|
border-bottom-width: 0;
|
||||||
|
}
|
||||||
|
.content .tabs li + li {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
.content.is-small {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
}
|
||||||
|
.content.is-normal {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
.content.is-medium {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
}
|
||||||
|
.content.is-large {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
@ -6643,11 +6812,6 @@ a.tag:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-light {
|
|
||||||
weight: 400;
|
|
||||||
color: var(--text-color-light);
|
|
||||||
}
|
|
||||||
|
|
||||||
.align-left {
|
.align-left {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
justify-content: left;
|
justify-content: left;
|
||||||
|
@ -6670,10 +6834,6 @@ a.tag:hover {
|
||||||
clear: both !important;
|
clear: both !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.clear-unset {
|
|
||||||
clear: unset !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.d-inline {
|
.d-inline {
|
||||||
display: inline !important;
|
display: inline !important;
|
||||||
}
|
}
|
||||||
|
@ -6686,58 +6846,21 @@ a.tag:hover {
|
||||||
display: inline-block !important;
|
display: inline-block !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.p-relative {
|
.push-right, .flex-push-right {
|
||||||
position: relative !important;
|
margin-left: auto !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.p-absolute {
|
.push-bottom {
|
||||||
position: absolute !important;
|
margin-top: auto !important;
|
||||||
}
|
|
||||||
|
|
||||||
.p-fixed {
|
|
||||||
position: fixed !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.p-sticky {
|
|
||||||
position: sticky !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.p-static {
|
|
||||||
position: static !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ws-nowrap {
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
grid-auto-flow: dense;
|
|
||||||
gap: 1.2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-1 {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
grid-auto-flow: dense;
|
|
||||||
gap: 1.2rem;
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-2 {
|
.grid-2 {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: 1fr 1fr;
|
||||||
grid-auto-flow: dense;
|
|
||||||
gap: 1.2rem;
|
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-3 {
|
.grid-3 {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
grid-auto-flow: dense;
|
|
||||||
gap: 1.2rem;
|
|
||||||
grid-template-columns: 1fr 1fr 1fr;
|
grid-template-columns: 1fr 1fr 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6782,8 +6905,8 @@ a.tag:hover {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.no-border {
|
.is-borderless {
|
||||||
border: 0px !important;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.overflow-hidden {
|
.overflow-hidden {
|
||||||
|
@ -6794,10 +6917,38 @@ a.tag:hover {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.p-relative {
|
||||||
|
position: relative !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-absolute {
|
||||||
|
position: absolute !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-fixed {
|
||||||
|
position: fixed !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-sticky {
|
||||||
|
position: sticky !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-static {
|
||||||
|
position: static !important;
|
||||||
|
}
|
||||||
|
|
||||||
.height-full {
|
.height-full {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ws-nowrap {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-border {
|
||||||
|
border: 0px !important;
|
||||||
|
}
|
||||||
|
|
||||||
*[draggable=true] {
|
*[draggable=true] {
|
||||||
cursor: move;
|
cursor: move;
|
||||||
}
|
}
|
||||||
|
@ -6818,12 +6969,12 @@ a.tag:hover {
|
||||||
animation: 1s ease-in-out 1s infinite alternate blink;
|
animation: 1s ease-in-out 1s infinite alternate blink;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-color {
|
.hg-color {
|
||||||
color: var(--main-color);
|
color: var(--highlight-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.secondary-color {
|
.hg-color-2 {
|
||||||
color: var(--secondary-color);
|
color: var(--highlight-color-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.bg-transparent {
|
.bg-transparent {
|
||||||
|
@ -6861,6 +7012,12 @@ input.half-field:not(:active):not(:hover) {
|
||||||
--disabled-bg: #eee;
|
--disabled-bg: #eee;
|
||||||
--link-fg: #00A6A6;
|
--link-fg: #00A6A6;
|
||||||
--link-hv-fg: var(--text-color);
|
--link-hv-fg: var(--text-color);
|
||||||
|
--hg-color: #EFCA08;
|
||||||
|
--hg-color-alpha: #EFCA08B3;
|
||||||
|
--hg-color-grey: rgba(230, 230, 60, 1);
|
||||||
|
--hg-color-2: #F49F0A;
|
||||||
|
--hg-color-2-alpha: #F49F0AB3;
|
||||||
|
--hg-color-2-grey: rgba(50, 200, 200, 1);
|
||||||
--nav-primary-height: 3rem;
|
--nav-primary-height: 3rem;
|
||||||
--nav-secondary-height: 2.5rem;
|
--nav-secondary-height: 2.5rem;
|
||||||
--nav-fg: var(--text-color);
|
--nav-fg: var(--text-color);
|
||||||
|
@ -6874,36 +7031,22 @@ input.half-field:not(:active):not(:hover) {
|
||||||
--nav-2-fs: 0.9rem;
|
--nav-2-fs: 0.9rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
:root {
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
font-size: 1.4em;
|
||||||
background-color: var(--body-bg);
|
background-color: var(--body-bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
body.mobile .grid {
|
@media screen and (max-width: 1280px) {
|
||||||
grid-template-columns: 1fr;
|
body {
|
||||||
}
|
font-size: 1.2em;
|
||||||
|
|
||||||
@media screen and (max-width: 900px) {
|
|
||||||
.grid {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@media screen and (max-width: 1024px) {
|
@media screen and (max-width: 1024px) {
|
||||||
html {
|
body {
|
||||||
font-size: 18px !important;
|
font-size: 1em;
|
||||||
}
|
}
|
||||||
}
|
:root {
|
||||||
@media screen and (max-width: 1280px) {
|
--header-height: 20rem;
|
||||||
html {
|
|
||||||
font-size: 20px !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@media screen and (min-width: 1280px) {
|
|
||||||
html {
|
|
||||||
font-size: 24px !important;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
h1, h2, h3, h4, h5, h6, .heading, .title, .subtitle {
|
h1, h2, h3, h4, h5, h6, .heading, .title, .subtitle {
|
||||||
|
@ -6913,8 +7056,3 @@ h1, h2, h3, h4, h5, h6, .heading, .title, .subtitle {
|
||||||
.container:empty {
|
.container:empty {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-cover {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1211,7 +1211,7 @@
|
||||||
background-color: var(--vc-bg);
|
background-color: var(--vc-bg);
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
-webkit-tap-highlight-color: transparent;
|
-webkit-tap-hg-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vc-container,
|
.vc-container,
|
||||||
|
|
|
@ -27,8 +27,8 @@
|
||||||
--preview-cover-size: 14rem;
|
--preview-cover-size: 14rem;
|
||||||
--preview-cover-small-size: 10rem;
|
--preview-cover-small-size: 10rem;
|
||||||
--preview-cover-tiny-size: 4rem;
|
--preview-cover-tiny-size: 4rem;
|
||||||
--preview-wide-content-sz: 1.2rem;
|
--preview-wide-content-sz: 1.6rem;
|
||||||
--preview-heading-bg-color: var(--main-color);
|
--preview-heading-bg-color: var(--hg-color);
|
||||||
--header-height: var(--cover-h);
|
--header-height: var(--cover-h);
|
||||||
--a-carousel-p: 1.4rem;
|
--a-carousel-p: 1.4rem;
|
||||||
--a-carousel-ml: calc(1.2rem - 0.5rem);
|
--a-carousel-ml: calc(1.2rem - 0.5rem);
|
||||||
|
@ -76,6 +76,9 @@
|
||||||
--cover-tiny-w: 4rem;
|
--cover-tiny-w: 4rem;
|
||||||
--cover-tiny-h: 4rem;
|
--cover-tiny-h: 4rem;
|
||||||
--section-content-sz: 1rem;
|
--section-content-sz: 1rem;
|
||||||
|
--preview-title-sz: 1rem;
|
||||||
|
--preview-subtitle-sz: 0.8rem;
|
||||||
|
--preview-wide-content-sz: 1rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.title.is-1, .header.preview .title.is-1 {
|
.title.is-1, .header.preview .title.is-1 {
|
||||||
|
@ -121,10 +124,6 @@
|
||||||
color: var(--heading-hg-fg);
|
color: var(--heading-hg-fg);
|
||||||
}
|
}
|
||||||
|
|
||||||
.panels .panel:not(.active) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview {
|
.preview {
|
||||||
position: relative;
|
position: relative;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
|
@ -289,7 +288,7 @@
|
||||||
transition: box-shadow 0.2s;
|
transition: box-shadow 0.2s;
|
||||||
}
|
}
|
||||||
.preview-card:hover figure {
|
.preview-card:hover figure {
|
||||||
box-shadow: 0em 0em 1em rgba(0, 0, 0, 0.2);
|
box-shadow: 0em 0em 1.2em rgba(0, 0, 0, 0.4) !important;
|
||||||
}
|
}
|
||||||
.preview-card:hover a {
|
.preview-card:hover a {
|
||||||
color: var(--heading-link-hv-fg);
|
color: var(--heading-link-hv-fg);
|
||||||
|
@ -300,6 +299,9 @@
|
||||||
.preview-card .headings .heading {
|
.preview-card .headings .heading {
|
||||||
display: block !important;
|
display: block !important;
|
||||||
}
|
}
|
||||||
|
.preview-card .headings .title {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
.preview-card .headings .subtitle {
|
.preview-card .headings .subtitle {
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
}
|
}
|
||||||
|
@ -308,6 +310,7 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
.preview-card .card-content figure {
|
.preview-card .card-content figure {
|
||||||
|
box-shadow: 0em 0em 1em rgba(0, 0, 0, 0.2);
|
||||||
height: var(--cover-h);
|
height: var(--cover-h);
|
||||||
width: var(--cover-w);
|
width: var(--cover-w);
|
||||||
}
|
}
|
||||||
|
@ -318,6 +321,18 @@
|
||||||
right: 0rem;
|
right: 0rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.list-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
grid-auto-flow: dense;
|
||||||
|
gap: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 900px) {
|
||||||
|
.list-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
.a-carousel .a-carousel-viewport {
|
.a-carousel .a-carousel-viewport {
|
||||||
box-shadow: inset 0em 0em 20rem var(--a-carousel-bg);
|
box-shadow: inset 0em 0em 20rem var(--a-carousel-bg);
|
||||||
padding: 0rem;
|
padding: 0rem;
|
||||||
|
@ -529,34 +544,6 @@
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.a-select-file > *:not(:last-child) {
|
|
||||||
margin-bottom: 0.6rem;
|
|
||||||
}
|
|
||||||
.a-select-file .upload-preview {
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
.a-select-file .a-select-file-list {
|
|
||||||
max-height: 30rem;
|
|
||||||
overflow-y: auto;
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr 1fr 1fr 1fr;
|
|
||||||
gap: 0.6rem;
|
|
||||||
}
|
|
||||||
.a-select-file .file-preview {
|
|
||||||
width: 100%;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.a-select-file .file-preview:hover {
|
|
||||||
box-shadow: 0em 0em 1em rgba(0, 0, 0, 0.2);
|
|
||||||
}
|
|
||||||
.a-select-file .file-preview.active {
|
|
||||||
box-shadow: 0em 0em 1em rgba(0, 0, 0, 0.4);
|
|
||||||
}
|
|
||||||
.a-select-file .file-preview img {
|
|
||||||
width: 100%;
|
|
||||||
max-height: 10rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Bulma Utilities */
|
/* Bulma Utilities */
|
||||||
.file-cta,
|
.file-cta,
|
||||||
.file-name, .select select, .textarea, .input {
|
.file-name, .select select, .textarea, .input {
|
||||||
|
@ -615,7 +602,7 @@ fieldset[disabled] .file-name, fieldset[disabled] .select select, .select fields
|
||||||
width: 0.625em;
|
width: 0.625em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-container:not(:last-child), .table:not(:last-child), .box:not(:last-child), .message:not(:last-child) {
|
.table-container:not(:last-child), .table:not(:last-child), .content:not(:last-child), .box:not(:last-child), .message:not(:last-child) {
|
||||||
margin-bottom: 1.5rem;
|
margin-bottom: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6755,6 +6742,175 @@ a.box:active {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.content li + li {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
}
|
||||||
|
.content p:not(:last-child),
|
||||||
|
.content dl:not(:last-child),
|
||||||
|
.content ol:not(:last-child),
|
||||||
|
.content ul:not(:last-child),
|
||||||
|
.content blockquote:not(:last-child),
|
||||||
|
.content pre:not(:last-child),
|
||||||
|
.content table:not(:last-child) {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
.content h1,
|
||||||
|
.content h2,
|
||||||
|
.content h3,
|
||||||
|
.content h4,
|
||||||
|
.content h5,
|
||||||
|
.content h6 {
|
||||||
|
color: hsl(0deg, 0%, 21%);
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1.125;
|
||||||
|
}
|
||||||
|
.content h1 {
|
||||||
|
font-size: 2em;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
.content h1:not(:first-child) {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
.content h2 {
|
||||||
|
font-size: 1.75em;
|
||||||
|
margin-bottom: 0.5714em;
|
||||||
|
}
|
||||||
|
.content h2:not(:first-child) {
|
||||||
|
margin-top: 1.1428em;
|
||||||
|
}
|
||||||
|
.content h3 {
|
||||||
|
font-size: 1.5em;
|
||||||
|
margin-bottom: 0.6666em;
|
||||||
|
}
|
||||||
|
.content h3:not(:first-child) {
|
||||||
|
margin-top: 1.3333em;
|
||||||
|
}
|
||||||
|
.content h4 {
|
||||||
|
font-size: 1.25em;
|
||||||
|
margin-bottom: 0.8em;
|
||||||
|
}
|
||||||
|
.content h5 {
|
||||||
|
font-size: 1.125em;
|
||||||
|
margin-bottom: 0.8888em;
|
||||||
|
}
|
||||||
|
.content h6 {
|
||||||
|
font-size: 1em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
.content blockquote {
|
||||||
|
background-color: hsl(0deg, 0%, 96%);
|
||||||
|
border-left: 5px solid hsl(0deg, 0%, 86%);
|
||||||
|
padding: 1.25em 1.5em;
|
||||||
|
}
|
||||||
|
.content ol {
|
||||||
|
list-style-position: outside;
|
||||||
|
margin-left: 2em;
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
.content ol:not([type]) {
|
||||||
|
list-style-type: decimal;
|
||||||
|
}
|
||||||
|
.content ol:not([type]).is-lower-alpha {
|
||||||
|
list-style-type: lower-alpha;
|
||||||
|
}
|
||||||
|
.content ol:not([type]).is-lower-roman {
|
||||||
|
list-style-type: lower-roman;
|
||||||
|
}
|
||||||
|
.content ol:not([type]).is-upper-alpha {
|
||||||
|
list-style-type: upper-alpha;
|
||||||
|
}
|
||||||
|
.content ol:not([type]).is-upper-roman {
|
||||||
|
list-style-type: upper-roman;
|
||||||
|
}
|
||||||
|
.content ul {
|
||||||
|
list-style: disc outside;
|
||||||
|
margin-left: 2em;
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
.content ul ul {
|
||||||
|
list-style-type: circle;
|
||||||
|
margin-top: 0.5em;
|
||||||
|
}
|
||||||
|
.content ul ul ul {
|
||||||
|
list-style-type: square;
|
||||||
|
}
|
||||||
|
.content dd {
|
||||||
|
margin-left: 2em;
|
||||||
|
}
|
||||||
|
.content figure {
|
||||||
|
margin-left: 2em;
|
||||||
|
margin-right: 2em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.content figure:not(:first-child) {
|
||||||
|
margin-top: 2em;
|
||||||
|
}
|
||||||
|
.content figure:not(:last-child) {
|
||||||
|
margin-bottom: 2em;
|
||||||
|
}
|
||||||
|
.content figure img {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.content figure figcaption {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
.content pre {
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
overflow-x: auto;
|
||||||
|
padding: 1.25em 1.5em;
|
||||||
|
white-space: pre;
|
||||||
|
word-wrap: normal;
|
||||||
|
}
|
||||||
|
.content sup,
|
||||||
|
.content sub {
|
||||||
|
font-size: 75%;
|
||||||
|
}
|
||||||
|
.content table {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.content table td,
|
||||||
|
.content table th {
|
||||||
|
border: 1px solid hsl(0deg, 0%, 86%);
|
||||||
|
border-width: 0 0 1px;
|
||||||
|
padding: 0.5em 0.75em;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
.content table th {
|
||||||
|
color: hsl(0deg, 0%, 21%);
|
||||||
|
}
|
||||||
|
.content table th:not([align]) {
|
||||||
|
text-align: inherit;
|
||||||
|
}
|
||||||
|
.content table thead td,
|
||||||
|
.content table thead th {
|
||||||
|
border-width: 0 0 2px;
|
||||||
|
color: hsl(0deg, 0%, 21%);
|
||||||
|
}
|
||||||
|
.content table tfoot td,
|
||||||
|
.content table tfoot th {
|
||||||
|
border-width: 2px 0 0;
|
||||||
|
color: hsl(0deg, 0%, 21%);
|
||||||
|
}
|
||||||
|
.content table tbody tr:last-child td,
|
||||||
|
.content table tbody tr:last-child th {
|
||||||
|
border-bottom-width: 0;
|
||||||
|
}
|
||||||
|
.content .tabs li + li {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
.content.is-small {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
}
|
||||||
|
.content.is-normal {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
.content.is-medium {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
}
|
||||||
|
.content.is-large {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
@ -7192,7 +7348,7 @@ a.tag:hover {
|
||||||
}
|
}
|
||||||
|
|
||||||
.vc-weekday-1, .vc-weekday-7 {
|
.vc-weekday-1, .vc-weekday-7 {
|
||||||
color: var(--secondary-color) !important;
|
color: var(--hg-color-2) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.schedules {
|
.schedules {
|
||||||
|
@ -7255,9 +7411,9 @@ a.tag:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.button[disabled], .button.disabled, a.button[disabled], a.button.disabled, button.button[disabled], button.button.disabled {
|
.button[disabled], .button.disabled, a.button[disabled], a.button.disabled, button.button[disabled], button.button.disabled {
|
||||||
background-color: var(--text-color-light);
|
background-color: var(--hg-color-grey);
|
||||||
color: var(--secondary-color);
|
color: var(--hg-color-2);
|
||||||
border-color: var(--secondary-color-light);
|
border-color: var(--hg-color-2-alpha);
|
||||||
}
|
}
|
||||||
.button .dropdown-trigger, a.button .dropdown-trigger, button.button .dropdown-trigger {
|
.button .dropdown-trigger, a.button .dropdown-trigger, button.button .dropdown-trigger {
|
||||||
border-radius: 1.5em;
|
border-radius: 1.5em;
|
||||||
|
@ -7325,8 +7481,8 @@ a.tag:hover {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navbar-item.active, .table tr.is-selected {
|
.navbar-item.active, .table tr.is-selected {
|
||||||
color: var(--secondary-color);
|
color: var(--hg-color-2);
|
||||||
background-color: var(--main-color);
|
background-color: var(--hg-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
|
@ -7587,6 +7743,15 @@ nav li a, nav li .button {
|
||||||
border-color: var(--secondary-color-dark) !important;
|
border-color: var(--secondary-color-dark) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-size: 1.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1380px) {
|
||||||
|
body {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
@media screen and (max-width: 1024px) {
|
@media screen and (max-width: 1024px) {
|
||||||
.page .container {
|
.page .container {
|
||||||
margin-left: 1.2rem;
|
margin-left: 1.2rem;
|
||||||
|
|
File diff suppressed because one or more lines are too long
29
aircox/static/aircox/js/ckeditor-init.js
Normal file
29
aircox/static/aircox/js/ckeditor-init.js
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
/* global CKEDITOR, django */
|
||||||
|
/* Modified in order to be manually loaded after vue.js */
|
||||||
|
|
||||||
|
function initialiseCKEditor() {
|
||||||
|
var textareas = Array.prototype.slice.call(
|
||||||
|
document.querySelectorAll("textarea[data-type=ckeditortype]"),
|
||||||
|
)
|
||||||
|
for (var i = 0; i < textareas.length; ++i) {
|
||||||
|
var t = textareas[i]
|
||||||
|
if (
|
||||||
|
t.getAttribute("data-processed") == "0" &&
|
||||||
|
t.id.indexOf("__prefix__") == -1
|
||||||
|
) {
|
||||||
|
t.setAttribute("data-processed", "1")
|
||||||
|
var ext = JSON.parse(t.getAttribute("data-external-plugin-resources"))
|
||||||
|
for (var j = 0; j < ext.length; ++j) {
|
||||||
|
CKEDITOR.plugins.addExternal(ext[j][0], ext[j][1], ext[j][2])
|
||||||
|
}
|
||||||
|
CKEDITOR.replace(t.id, JSON.parse(t.getAttribute("data-config")))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function initialiseCKEditorInInlinedForms() {
|
||||||
|
if (typeof django === "object" && django.jQuery) {
|
||||||
|
django.jQuery(document).on("formset:added", initialiseCKEditor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//})()
|
|
@ -7,6 +7,9 @@ Usefull context:
|
||||||
- cover: image cover
|
- cover: image cover
|
||||||
- site: current website
|
- site: current website
|
||||||
- model: view model or displayed `object`'s
|
- model: view model or displayed `object`'s
|
||||||
|
- sidebar_object_list: item to display in sidebar
|
||||||
|
- sidebar_url_name: url name sidebar item complete list
|
||||||
|
- sidebar_url_parent: parent page for sidebar items complete list
|
||||||
{% endcomment %}
|
{% endcomment %}
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
|
@ -36,7 +39,7 @@ Usefull context:
|
||||||
|
|
||||||
{% block head_extra %}{% endblock %}
|
{% block head_extra %}{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
<body {% if request.is_mobile %}class="mobile"{% endif %}>
|
<body>
|
||||||
<script id="init-script">
|
<script id="init-script">
|
||||||
window.addEventListener('load', function() {
|
window.addEventListener('load', function() {
|
||||||
{% block init-scripts %}
|
{% block init-scripts %}
|
||||||
|
@ -48,7 +51,7 @@ Usefull context:
|
||||||
<div class="navs">
|
<div class="navs">
|
||||||
{% block nav %}
|
{% block nav %}
|
||||||
<nav class="nav primary" role="navigation" aria-label="main navigation">
|
<nav class="nav primary" role="navigation" aria-label="main navigation">
|
||||||
{% block primary-nav %}
|
{% block nav-primary %}
|
||||||
<a class="nav-brand" href="{% url "home" %}">
|
<a class="nav-brand" href="{% url "home" %}">
|
||||||
<img src="{{ station.logo.url }}">
|
<img src="{{ station.logo.url }}">
|
||||||
</a>
|
</a>
|
||||||
|
@ -57,7 +60,7 @@ Usefull context:
|
||||||
aria-label="{% translate "Main menu" %}">
|
aria-label="{% translate "Main menu" %}">
|
||||||
</a-switch>
|
</a-switch>
|
||||||
<div class="nav-menu">
|
<div class="nav-menu">
|
||||||
{% block primary-nav-menu %}
|
{% block nav-primary-menu %}
|
||||||
{% nav_items "top" css_class="nav-item" active_class="active" as items %}
|
{% nav_items "top" css_class="nav-item" active_class="active" as items %}
|
||||||
{% for item, render in items %}
|
{% for item, render in items %}
|
||||||
{{ render }}
|
{{ render }}
|
||||||
|
@ -67,6 +70,9 @@ Usefull context:
|
||||||
{% translate "Admin" %}
|
{% translate "Admin" %}
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<a class="nav-item" href="{% url "profile" %}" target="new">
|
||||||
|
{% translate "Profile" %}
|
||||||
|
</a>
|
||||||
{% if user.is_authenticated %}
|
{% if user.is_authenticated %}
|
||||||
<a class="nav-item" href="{% url "logout" %}" title="{% translate "Disconnect" %}"
|
<a class="nav-item" href="{% url "logout" %}" title="{% translate "Disconnect" %}"
|
||||||
aria-label="{% translate "Disconnect" %}">
|
aria-label="{% translate "Disconnect" %}">
|
||||||
|
@ -93,23 +99,22 @@ Usefull context:
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% endspaceless %}
|
{% endspaceless %}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{% block header-container %}
|
{% block header-container %}
|
||||||
{% if page or cover or title %}
|
{% if page or cover or title %}
|
||||||
<header class="container header preview preview-header {% if cover %}has-cover{% endif %}">
|
<header class="container header preview preview-header {% if cover %}has-cover{% endif %}">
|
||||||
{% block header %}
|
{% block header %}
|
||||||
|
{% if cover %}
|
||||||
<figure class="header-cover">
|
<figure class="header-cover">
|
||||||
{% block header-cover %}
|
<img src="{{ cover }}" class="cover">
|
||||||
{% if cover %}
|
|
||||||
<img src="{{ cover }}" ref="cover" class="cover">
|
|
||||||
{% endif %}
|
|
||||||
{% endblock %}
|
|
||||||
</figure>
|
</figure>
|
||||||
|
{% endif %}
|
||||||
<div class="headings preview-card-headings">
|
<div class="headings preview-card-headings">
|
||||||
{% block headings %}
|
{% block headings %}
|
||||||
<div>
|
<div>
|
||||||
{% block title-container %}
|
|
||||||
<h1 class="title is-1 {% block title-class %}{% endblock %}">{% block title %}{{ title|default:"" }}{% endblock %}</h1>
|
<h1 class="title is-1 {% block title-class %}{% endblock %}">{% block title %}{{ title|default:"" }}{% endblock %}</h1>
|
||||||
{% endblock %}
|
{% include "aircox/edit-link.html" %}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
|
@ -142,33 +147,6 @@ Usefull context:
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</main>
|
</main>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block footer-container %}
|
|
||||||
<footer class="page-footer">
|
|
||||||
{% block footer %}
|
|
||||||
{% comment %}
|
|
||||||
{% nav_items "footer" css_class="nav-item" active_class="active" as items %}
|
|
||||||
{% for item, render in items %}
|
|
||||||
{{ render }}
|
|
||||||
{% endfor %}
|
|
||||||
{% endcomment %}
|
|
||||||
|
|
||||||
{% if not request.user.is_authenticated %}
|
|
||||||
<a class="nav-item" href="{% url "profile" %}" target="new"
|
|
||||||
title="{% translate "Profile" %}">
|
|
||||||
<span class="small icon">
|
|
||||||
<i class="fa fa-user"></i>
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
{% endif %}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% if request.station and request.station.legal_label %}
|
|
||||||
{{ request.station.legal_label }} —
|
|
||||||
{% endif %}
|
|
||||||
</footer>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{% block player-container %}
|
{% block player-container %}
|
||||||
<div id="player">{% include "aircox/widgets/player.html" %}</div>
|
<div id="player">{% include "aircox/widgets/player.html" %}</div>
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
{{ block.super }}
|
{{ block.super }}
|
||||||
|
|
||||||
{% block list-container %}
|
{% block list-container %}
|
||||||
<section class="container clear-both list grid {{ list_class|default:"" }}" role="list">
|
<section class="container clear-both list list-grid {{ list_class|default:"" }}" role="list">
|
||||||
{% block list %}
|
{% block list %}
|
||||||
{% with has_headline=True %}
|
{% with has_headline=True %}
|
||||||
{% for object in object_list %}
|
{% for object in object_list %}
|
||||||
|
|
24
aircox/templates/aircox/edit-link.html
Normal file
24
aircox/templates/aircox/edit-link.html
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
{% load aircox i18n %}
|
||||||
|
{% block user-actions-container %}
|
||||||
|
{% has_perm page page.program.change_permission_codename simple=True as can_edit %}
|
||||||
|
{% if user.is_authenticated and can_edit %}
|
||||||
|
{% with request.resolver_match.view_name as view_name %}
|
||||||
|
|
||||||
|
{% if view_name in 'page-edit,program-edit,episode-edit' %}
|
||||||
|
<a href="{% url view_name|detail_view page.slug %}" target="_self">
|
||||||
|
<small>
|
||||||
|
<span title="{% translate 'View' %} {{ page }}">{% translate 'View' %} </span>
|
||||||
|
<i class="fa-regular fa-eye"></i>
|
||||||
|
</small>
|
||||||
|
</a>
|
||||||
|
{% else %}
|
||||||
|
<a href="{% url view_name|edit_view page.pk %}" target="_self">
|
||||||
|
<small>
|
||||||
|
<span title="{% translate 'Edit' %} {{ page }}">{% translate 'Edit' %} </span>
|
||||||
|
<i class="fa-solid fa-pencil"></i>
|
||||||
|
</small>
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
{% endwith %}
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
|
@ -26,6 +26,7 @@
|
||||||
</table>
|
</table>
|
||||||
<br/>
|
<br/>
|
||||||
<input type="submit" value="Update" class="button is-success">
|
<input type="submit" value="Update" class="button is-success">
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
{% include "aircox/playlist_inline.html" %}
|
{% include "aircox/playlist_inline.html" %}
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
<section class="container">
|
<section class="container">
|
||||||
<h2 class="title">{% translate "It just happened" %}</h2>
|
<h2 class="title">{% translate "It just happened" %}</h2>
|
||||||
|
|
||||||
<div class="grid" role="list">
|
<div class="list-grid" role="list">
|
||||||
{% include "./widgets/logs.html" with object_list=logs %}
|
{% include "./widgets/logs.html" with object_list=logs %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -23,12 +23,6 @@ Context:
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block title-container %}
|
|
||||||
{{ block.super }}
|
|
||||||
{% block page-actions %}
|
|
||||||
{% include "aircox/widgets/page_actions.html" %}
|
|
||||||
{% endblock %}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
{{ block.super }}
|
{{ block.super }}
|
||||||
|
|
|
@ -1,71 +0,0 @@
|
||||||
{% extends "./page_detail.html" %}
|
|
||||||
{% load static i18n %}
|
|
||||||
|
|
||||||
{% block header-cover %}
|
|
||||||
<img src="{{ cover }}" ref="cover" class="cover">
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block content-container %}
|
|
||||||
<section class="container active">
|
|
||||||
<form method="post" enctype="multipart/form-data">
|
|
||||||
{% csrf_token %}
|
|
||||||
{% for field in form %}
|
|
||||||
<div class="field">
|
|
||||||
{% if field.name == "cover" %}
|
|
||||||
<input type="hidden" name="{{ field.name }}" value="{{ field.pk }}" ref="coverField"/>
|
|
||||||
{% else %}
|
|
||||||
<label class="label">{{ field.label }}</label>
|
|
||||||
<div class="control clear-unset">
|
|
||||||
{% if field.name == "pub_date" %}
|
|
||||||
<input type="datetime-local" name="{{ field.name }}"
|
|
||||||
value="{{ field.value|date:"Y-m-d" }}T{{ field.value|date:"H:i" }}"/>
|
|
||||||
{% elif field.name == "content" %}
|
|
||||||
<textarea name="{{ field.name }}" class="is-fullwidth">{{ field.value|striptags|safe }}</textarea>
|
|
||||||
{% else %}
|
|
||||||
{{ field }}
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
{% if field.errors %}
|
|
||||||
<p class="help is-danger">{{ field.errors }}</p>
|
|
||||||
{% endif %}
|
|
||||||
{% if field.help_text %}
|
|
||||||
<p class="help">{{ field.help_text|safe }}</p>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
<div class="has-text-right">
|
|
||||||
<button type="submit" class="button">{% translate "Update" %}</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="cover-modal" class="container page-edit-panel">
|
|
||||||
<h3 class="title">{% translate "Change cover" %}</h3>
|
|
||||||
<a-select-file list-url="{% url "api:image-list" %}" upload-url="{% url "api:image-list" %}"
|
|
||||||
prev-label="{% translate "Show previous" %}"
|
|
||||||
next-label="{% translate "Show next" %}"
|
|
||||||
>
|
|
||||||
<template #upload-preview="{item}">
|
|
||||||
<template v-if="item">
|
|
||||||
<img :src="item.src" class="upload-preview"/>
|
|
||||||
</template>
|
|
||||||
</template>
|
|
||||||
<template #default="{item}">
|
|
||||||
<div class="flex-column">
|
|
||||||
<div class="flex-grow-1">
|
|
||||||
<img :src="item.file"/>
|
|
||||||
</div>
|
|
||||||
<label class="label">[[ item.name || item.original_filename ]]</label>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template #footer="{item}">
|
|
||||||
<button type="button" class="button float-right"
|
|
||||||
@click="(event) => {$refs.cover.src = item.file; $refs.coverField.value = item.id}">
|
|
||||||
{% translate "Select" %}
|
|
||||||
</button>
|
|
||||||
</template>
|
|
||||||
</a-select-file>
|
|
||||||
</section>
|
|
||||||
{% endblock %}
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
|
|
||||||
{% block list-container %}
|
{% block list-container %}
|
||||||
{% with list_class="grid" %}
|
{% with list_class="list-grid" %}
|
||||||
{{ block.super }}
|
{{ block.super }}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -7,7 +7,7 @@ Context:
|
||||||
- url_label: label of url button
|
- url_label: label of url button
|
||||||
{% endcomment %}
|
{% endcomment %}
|
||||||
|
|
||||||
<a-carousel>
|
<a-carousel section-class="card-grid">
|
||||||
{% for object in objects %}
|
{% for object in objects %}
|
||||||
{% page_widget "card" object %}
|
{% page_widget "card" object %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
{% load aircox i18n %}
|
|
||||||
{% block user-actions-container %}
|
|
||||||
{% has_perm page page.program.change_permission_codename simple=True as can_edit %}
|
|
||||||
|
|
||||||
{% if user.is_authenticated %}
|
|
||||||
{{ object.get_status_display }}
|
|
||||||
({{ object.pub_date|date:"d/m/Y H:i" }})
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if user.is_authenticated and can_edit %}
|
|
||||||
{% with request.resolver_match.view_name as view_name %}
|
|
||||||
|
|
||||||
{% if "-edit" in view_name %}
|
|
||||||
<a href="{% url view_name|detail_view page.slug %}" target="_self" title="{% translate 'View' %} {{ page }}">
|
|
||||||
<span class="icon">
|
|
||||||
<i class="fa-regular fa-eye"></i>
|
|
||||||
</span>
|
|
||||||
<span>{% translate 'View' %} </span>
|
|
||||||
</a>
|
|
||||||
{% else %}
|
|
||||||
<a href="{% url view_name|edit_view page.pk %}" target="_self" title="{% translate 'Edit' %} {{ page }}">
|
|
||||||
<span class="icon">
|
|
||||||
<i class="fa-solid fa-pencil"></i>
|
|
||||||
</span>
|
|
||||||
<span>{% translate 'Edit' %} </span>
|
|
||||||
</a>
|
|
||||||
{% endif %}
|
|
||||||
{% endwith %}
|
|
||||||
{% endif %}
|
|
||||||
{% endblock %}
|
|
|
@ -30,7 +30,7 @@ The audio player
|
||||||
</h4>
|
</h4>
|
||||||
<h4 v-else-if="current && current.data.type == 'track'"
|
<h4 v-else-if="current && current.data.type == 'track'"
|
||||||
class="title" aria-description="{% translate "Track currently on air" %}">
|
class="title" aria-description="{% translate "Track currently on air" %}">
|
||||||
<span class="icon secondary-color mr-3">
|
<span class="icon hg-color-2 mr-3">
|
||||||
<i class="fas fa-music"></i>
|
<i class="fas fa-music"></i>
|
||||||
</span>
|
</span>
|
||||||
<span>[[ current.data.title ]]</span>
|
<span>[[ current.data.title ]]</span>
|
||||||
|
|
|
@ -6,7 +6,7 @@ Context:
|
||||||
{% endcomment %}
|
{% endcomment %}
|
||||||
|
|
||||||
<span class="track">
|
<span class="track">
|
||||||
<span class="icon secondary-color">
|
<span class="icon hg-color-2">
|
||||||
<i class="fas fa-music"></i>
|
<i class="fas fa-music"></i>
|
||||||
</span>
|
</span>
|
||||||
<label>
|
<label>
|
||||||
|
|
|
@ -59,8 +59,6 @@ def do_get_tracks(obj):
|
||||||
@register.simple_tag(name="has_perm", takes_context=True)
|
@register.simple_tag(name="has_perm", takes_context=True)
|
||||||
def do_has_perm(context, obj, perm, user=None, simple=False):
|
def do_has_perm(context, obj, perm, user=None, simple=False):
|
||||||
"""Return True if ``user.has_perm('[APP].[perm]_[MODEL]')``"""
|
"""Return True if ``user.has_perm('[APP].[perm]_[MODEL]')``"""
|
||||||
if not obj:
|
|
||||||
return
|
|
||||||
if user is None:
|
if user is None:
|
||||||
user = context["request"].user
|
user = context["request"].user
|
||||||
if simple:
|
if simple:
|
||||||
|
@ -104,8 +102,6 @@ def do_player_live_attr(context):
|
||||||
@register.simple_tag(name="nav_items", takes_context=True)
|
@register.simple_tag(name="nav_items", takes_context=True)
|
||||||
def do_nav_items(context, menu, **kwargs):
|
def do_nav_items(context, menu, **kwargs):
|
||||||
"""Render navigation items for the provided menu name."""
|
"""Render navigation items for the provided menu name."""
|
||||||
if not getattr(context["request"], "station"):
|
|
||||||
return []
|
|
||||||
station, request = context["station"], context["request"]
|
station, request = context["station"], context["request"]
|
||||||
return [(item, item.render(request, **kwargs)) for item in station.navitem_set.filter(menu=menu)]
|
return [(item, item.render(request, **kwargs)) for item in station.navitem_set.filter(menu=menu)]
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ from django.urls import include, path, register_converter
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from rest_framework.routers import DefaultRouter
|
from rest_framework.routers import DefaultRouter
|
||||||
|
|
||||||
from . import forms, models, views, viewsets
|
from . import models, views, viewsets
|
||||||
from .converters import DateConverter, PagePathConverter, WeekConverter
|
from .converters import DateConverter, PagePathConverter, WeekConverter
|
||||||
|
|
||||||
__all__ = ["api", "urls"]
|
__all__ = ["api", "urls"]
|
||||||
|
@ -21,7 +21,6 @@ register_converter(WeekConverter, "week")
|
||||||
|
|
||||||
|
|
||||||
router = DefaultRouter()
|
router = DefaultRouter()
|
||||||
router.register("images", viewsets.ImageViewSet, basename="image")
|
|
||||||
router.register("sound", viewsets.SoundViewSet, basename="sound")
|
router.register("sound", viewsets.SoundViewSet, basename="sound")
|
||||||
router.register("track", viewsets.TrackROViewSet, basename="track")
|
router.register("track", viewsets.TrackROViewSet, basename="track")
|
||||||
|
|
||||||
|
@ -133,12 +132,6 @@ urls = [
|
||||||
views.errors.NoStationErrorView.as_view(),
|
views.errors.NoStationErrorView.as_view(),
|
||||||
name="errors-no-station",
|
name="errors-no-station",
|
||||||
),
|
),
|
||||||
# ---- backoffice
|
path("gestion/", views.ProfileView.as_view(), name="profile"),
|
||||||
path(_("edit/"), views.ProfileView.as_view(), name="profile"),
|
|
||||||
path(
|
|
||||||
_("edit/programs/<slug:slug>"),
|
|
||||||
views.PageUpdateView.as_view(model=models.Program, form_class=forms.ProgramForm),
|
|
||||||
name="program-update",
|
|
||||||
),
|
|
||||||
path("accounts/profile/", views.ProfileView.as_view(), name="profile"),
|
path("accounts/profile/", views.ProfileView.as_view(), name="profile"),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from . import admin, errors
|
from . import admin, errors
|
||||||
from .article import ArticleDetailView, ArticleListView
|
from .article import ArticleDetailView, ArticleListView
|
||||||
|
from .base import BaseAPIView, BaseView
|
||||||
from .diffusion import DiffusionListView, TimeTableView
|
from .diffusion import DiffusionListView, TimeTableView
|
||||||
from .episode import EpisodeDetailView, EpisodeListView, PodcastListView, EpisodeUpdateView
|
from .episode import EpisodeDetailView, EpisodeListView, PodcastListView, EpisodeUpdateView
|
||||||
from .home import HomeView
|
from .home import HomeView
|
||||||
|
@ -9,7 +10,6 @@ from .page import (
|
||||||
BasePageListView,
|
BasePageListView,
|
||||||
PageDetailView,
|
PageDetailView,
|
||||||
PageListView,
|
PageListView,
|
||||||
PageUpdateView,
|
|
||||||
)
|
)
|
||||||
from .profile import ProfileView
|
from .profile import ProfileView
|
||||||
from .program import (
|
from .program import (
|
||||||
|
@ -20,12 +20,13 @@ from .program import (
|
||||||
ProgramUpdateView,
|
ProgramUpdateView,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
"admin",
|
"admin",
|
||||||
"errors",
|
"errors",
|
||||||
"ArticleDetailView",
|
"ArticleDetailView",
|
||||||
"ArticleListView",
|
"ArticleListView",
|
||||||
|
"BaseAPIView",
|
||||||
|
"BaseView",
|
||||||
"DiffusionListView",
|
"DiffusionListView",
|
||||||
"TimeTableView",
|
"TimeTableView",
|
||||||
"EpisodeDetailView",
|
"EpisodeDetailView",
|
||||||
|
@ -38,7 +39,6 @@ __all__ = (
|
||||||
"BasePageDetailView",
|
"BasePageDetailView",
|
||||||
"BasePageListView",
|
"BasePageListView",
|
||||||
"PageDetailView",
|
"PageDetailView",
|
||||||
"PageUpdateView",
|
|
||||||
"PageListView",
|
"PageListView",
|
||||||
"ProfileView",
|
"ProfileView",
|
||||||
"ProgramDetailView",
|
"ProgramDetailView",
|
||||||
|
|
|
@ -24,10 +24,7 @@ class BasePageMixin:
|
||||||
category = None
|
category = None
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
qs = super().get_queryset().select_subclasses().select_related("cover")
|
return super().get_queryset().select_subclasses().published().select_related("cover")
|
||||||
if self.request.user.is_authenticated:
|
|
||||||
return qs
|
|
||||||
return qs.published()
|
|
||||||
|
|
||||||
def get_category(self, page, **kwargs):
|
def get_category(self, page, **kwargs):
|
||||||
if page:
|
if page:
|
||||||
|
@ -156,8 +153,8 @@ class PageDetailView(BasePageDetailView):
|
||||||
return super().get_queryset().select_related("category")
|
return super().get_queryset().select_related("category")
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
if "comment_form" not in kwargs:
|
if self.object.allow_comments and "comment_form" not in kwargs:
|
||||||
kwargs["comment_form"] = self.get_comment_form()
|
kwargs["comment_form"] = CommentForm()
|
||||||
kwargs["comments"] = Comment.objects.filter(page=self.object).order_by("-date")
|
kwargs["comments"] = Comment.objects.filter(page=self.object).order_by("-date")
|
||||||
|
|
||||||
if self.object.parent_subclass:
|
if self.object.parent_subclass:
|
||||||
|
@ -170,11 +167,6 @@ class PageDetailView(BasePageDetailView):
|
||||||
kwargs["related_objects"] = related
|
kwargs["related_objects"] = related
|
||||||
return super().get_context_data(**kwargs)
|
return super().get_context_data(**kwargs)
|
||||||
|
|
||||||
def get_comment_form(self):
|
|
||||||
if self.object.allow_comments:
|
|
||||||
return CommentForm()
|
|
||||||
return None
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def as_view(cls, *args, **kwargs):
|
def as_view(cls, *args, **kwargs):
|
||||||
view = super(PageDetailView, cls).as_view(*args, **kwargs)
|
view = super(PageDetailView, cls).as_view(*args, **kwargs)
|
||||||
|
@ -194,14 +186,6 @@ class PageDetailView(BasePageDetailView):
|
||||||
|
|
||||||
class PageUpdateView(BaseView, UpdateView):
|
class PageUpdateView(BaseView, UpdateView):
|
||||||
context_object_name = "page"
|
context_object_name = "page"
|
||||||
template_name = "aircox/page_form.html"
|
|
||||||
|
|
||||||
# FIXME: remove?
|
|
||||||
def get_page(self):
|
def get_page(self):
|
||||||
return self.object
|
return self.object
|
||||||
|
|
||||||
def get_success_url(self):
|
|
||||||
return self.request.path
|
|
||||||
|
|
||||||
def get_comment_form(self):
|
|
||||||
return None
|
|
||||||
|
|
|
@ -56,6 +56,9 @@ class ProgramUpdateView(UserPassesTestMixin, BaseProgramMixin, PageUpdateView):
|
||||||
model = Program
|
model = Program
|
||||||
form_class = ProgramForm
|
form_class = ProgramForm
|
||||||
|
|
||||||
|
def get_sidebar_queryset(self):
|
||||||
|
return super().get_sidebar_queryset().filter(parent=self.program)
|
||||||
|
|
||||||
def test_func(self):
|
def test_func(self):
|
||||||
program = self.get_object()
|
program = self.get_object()
|
||||||
return self.request.user.has_perm("aircox.%s" % program.change_permission_codename)
|
return self.request.user.has_perm("aircox.%s" % program.change_permission_codename)
|
||||||
|
@ -91,3 +94,7 @@ class ProgramPageListView(BaseProgramMixin, PageListView):
|
||||||
|
|
||||||
def get_program(self):
|
def get_program(self):
|
||||||
return self.parent
|
return self.parent
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
kwargs.setdefault("sidebar_url_parent", None)
|
||||||
|
return super().get_context_data(**kwargs)
|
||||||
|
|
|
@ -1,46 +1,44 @@
|
||||||
from django_filters import rest_framework as drf_filters
|
from django_filters import rest_framework as filters
|
||||||
from rest_framework import status, viewsets
|
from rest_framework import status, viewsets
|
||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
from rest_framework.permissions import IsAuthenticated
|
from rest_framework.permissions import IsAuthenticated
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.parsers import MultiPartParser
|
|
||||||
|
|
||||||
from filer.models.imagemodels import Image
|
from .models import Sound, Track
|
||||||
|
|
||||||
from . import models, forms, filters
|
|
||||||
from .serializers import SoundSerializer, admin
|
from .serializers import SoundSerializer, admin
|
||||||
from .views import BaseAPIView
|
from .views import BaseAPIView
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
"ImageViewSet",
|
"SoundFilter",
|
||||||
"SoundViewSet",
|
"SoundViewSet",
|
||||||
|
"TrackFilter",
|
||||||
"TrackROViewSet",
|
"TrackROViewSet",
|
||||||
"UserSettingsViewSet",
|
"UserSettingsViewSet",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class ImageViewSet(viewsets.ModelViewSet):
|
class SoundFilter(filters.FilterSet):
|
||||||
parsers = (MultiPartParser,)
|
station = filters.NumberFilter(field_name="program__station__id")
|
||||||
serializer_class = admin.ImageSerializer
|
program = filters.NumberFilter(field_name="program_id")
|
||||||
queryset = Image.objects.all().order_by("-uploaded_at")
|
episode = filters.NumberFilter(field_name="episode_id")
|
||||||
filter_backends = (drf_filters.DjangoFilterBackend,)
|
search = filters.CharFilter(field_name="search", method="search_filter")
|
||||||
filterset_class = filters.ImageFilterSet
|
|
||||||
|
|
||||||
def create(self, request, **kwargs):
|
def search_filter(self, queryset, name, value):
|
||||||
# FIXME: to be replaced by regular DRF
|
return queryset.search(value)
|
||||||
form = forms.ImageForm(request.POST, request.FILES)
|
|
||||||
if form.is_valid():
|
|
||||||
file = form.cleaned_data["file"]
|
|
||||||
Image.objects.create(original_filename=file.name, file=file)
|
|
||||||
return Response({"status": "ok"})
|
|
||||||
return Response({"status": "error", "errors": form.errors})
|
|
||||||
|
|
||||||
|
|
||||||
class SoundViewSet(BaseAPIView, viewsets.ModelViewSet):
|
class SoundViewSet(BaseAPIView, viewsets.ModelViewSet):
|
||||||
serializer_class = SoundSerializer
|
serializer_class = SoundSerializer
|
||||||
queryset = models.Sound.objects.available().order_by("-pk")
|
queryset = Sound.objects.available().order_by("-pk")
|
||||||
filter_backends = (drf_filters.DjangoFilterBackend,)
|
filter_backends = (filters.DjangoFilterBackend,)
|
||||||
filterset_class = filters.SoundFilterSet
|
filterset_class = SoundFilter
|
||||||
|
|
||||||
|
|
||||||
|
# --- admin
|
||||||
|
class TrackFilter(filters.FilterSet):
|
||||||
|
artist = filters.CharFilter(field_name="artist", lookup_expr="icontains")
|
||||||
|
album = filters.CharFilter(field_name="album", lookup_expr="icontains")
|
||||||
|
title = filters.CharFilter(field_name="title", lookup_expr="icontains")
|
||||||
|
|
||||||
|
|
||||||
class TrackROViewSet(viewsets.ReadOnlyModelViewSet):
|
class TrackROViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
@ -48,9 +46,9 @@ class TrackROViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
|
||||||
serializer_class = admin.TrackSerializer
|
serializer_class = admin.TrackSerializer
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated]
|
||||||
filter_backends = (drf_filters.DjangoFilterBackend,)
|
filter_backends = (filters.DjangoFilterBackend,)
|
||||||
filterset_class = filters.TrackFilterSet
|
filterset_class = TrackFilter
|
||||||
queryset = models.Track.objects.all()
|
queryset = Track.objects.all()
|
||||||
|
|
||||||
@action(name="autocomplete", detail=False)
|
@action(name="autocomplete", detail=False)
|
||||||
def autocomplete(self, request):
|
def autocomplete(self, request):
|
||||||
|
@ -62,7 +60,6 @@ class TrackROViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
return self.list(request)
|
return self.list(request)
|
||||||
|
|
||||||
|
|
||||||
# --- admin
|
|
||||||
class UserSettingsViewSet(viewsets.ViewSet):
|
class UserSettingsViewSet(viewsets.ViewSet):
|
||||||
"""User's settings specific to aircox.
|
"""User's settings specific to aircox.
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,13 @@ input.half-field:not(:active):not(:hover) {
|
||||||
--link-fg: #00A6A6;
|
--link-fg: #00A6A6;
|
||||||
--link-hv-fg: var(--text-color);
|
--link-hv-fg: var(--text-color);
|
||||||
|
|
||||||
|
--hg-color: #EFCA08;
|
||||||
|
--hg-color-alpha: #EFCA08B3;
|
||||||
|
--hg-color-grey: rgba(230, 230, 60, 1);
|
||||||
|
--hg-color-2: #F49F0A;
|
||||||
|
--hg-color-2-alpha: #F49F0AB3;
|
||||||
|
--hg-color-2-grey: rgba(50, 200, 200, 1);
|
||||||
|
|
||||||
--nav-primary-height: 3rem;
|
--nav-primary-height: 3rem;
|
||||||
--nav-secondary-height: 2.5rem;
|
--nav-secondary-height: 2.5rem;
|
||||||
--nav-fg: var(--text-color);
|
--nav-fg: var(--text-color);
|
||||||
|
@ -44,38 +51,22 @@ input.half-field:not(:active):not(:hover) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
:root {
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
font-size: 1.4em;
|
||||||
background-color: var(--body-bg);
|
background-color: var(--body-bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@mixin mobile-small {
|
@media screen and (max-width: v.$screen-wider) {
|
||||||
.grid { @include grid-1; }
|
body { font-size: 1.2em; }
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
body.mobile {
|
|
||||||
@include mobile-small;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: v.$screen-smaller) {
|
|
||||||
@include mobile-small;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: v.$screen-normal) {
|
@media screen and (max-width: v.$screen-normal) {
|
||||||
html { font-size: 18px !important; }
|
body { font-size: 1em; }
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: v.$screen-wider) {
|
:root {
|
||||||
html { font-size: 20px !important; }
|
--header-height: 20rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (min-width: v.$screen-wider) {
|
|
||||||
html { font-size: 24px !important; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
h1, h2, h3, h4, h5, h6, .heading, .title, .subtitle {
|
h1, h2, h3, h4, h5, h6, .heading, .title, .subtitle {
|
||||||
|
@ -86,8 +77,3 @@ h1, h2, h3, h4, h5, h6, .heading, .title, .subtitle {
|
||||||
.container:empty {
|
.container:empty {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-cover {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
|
@ -31,8 +31,8 @@
|
||||||
--preview-cover-size: 14rem;
|
--preview-cover-size: 14rem;
|
||||||
--preview-cover-small-size: 10rem;
|
--preview-cover-small-size: 10rem;
|
||||||
--preview-cover-tiny-size: 4rem;
|
--preview-cover-tiny-size: 4rem;
|
||||||
--preview-wide-content-sz: #{v.$text-size-2};
|
--preview-wide-content-sz: #{v.$text-size-bigger};
|
||||||
--preview-heading-bg-color: var(--main-color);
|
--preview-heading-bg-color: var(--hg-color);
|
||||||
--header-height: var(--cover-h);
|
--header-height: var(--cover-h);
|
||||||
|
|
||||||
--a-carousel-p: #{v.$text-size-medium};
|
--a-carousel-p: #{v.$text-size-medium};
|
||||||
|
@ -89,9 +89,9 @@
|
||||||
|
|
||||||
--section-content-sz: 1rem;
|
--section-content-sz: 1rem;
|
||||||
|
|
||||||
// --preview-title-sz: #{v.$text-size};
|
--preview-title-sz: #{v.$text-size};
|
||||||
// --preview-subtitle-sz: #{v.$text-size-smaller};
|
--preview-subtitle-sz: #{v.$text-size-smaller};
|
||||||
// --preview-wide-content-sz: #{v.$text-size};
|
--preview-wide-content-sz: #{v.$text-size};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,11 +138,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ---- panels
|
|
||||||
.panels {
|
|
||||||
.panel:not(.active) { display: none; }
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---- button
|
// ---- button
|
||||||
@mixin button {
|
@mixin button {
|
||||||
.button, a.button, button.button {
|
.button, a.button, button.button {
|
||||||
|
@ -182,6 +177,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&.active:not(:hover) {
|
&.active:not(:hover) {
|
||||||
|
// border-color: var(--hg-color-alpha);
|
||||||
color: var(--button-active-fg);
|
color: var(--button-active-fg);
|
||||||
background-color: var(--button-active-bg);
|
background-color: var(--button-active-bg);
|
||||||
}
|
}
|
||||||
|
@ -191,9 +187,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&[disabled], &.disabled {
|
&[disabled], &.disabled {
|
||||||
background-color: var(--text-color-light);
|
background-color: var(--hg-color-grey);
|
||||||
color: var(--secondary-color);
|
color: var(--hg-color-2);
|
||||||
border-color: var(--secondary-color-light);
|
border-color: var(--hg-color-2-alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdown-trigger {
|
.dropdown-trigger {
|
||||||
|
@ -418,8 +414,7 @@
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
figure {
|
figure {
|
||||||
// box-shadow: 0em 0em 1.2em rgba(0, 0, 0, 0.4) !important;
|
box-shadow: 0em 0em 1.2em rgba(0, 0, 0, 0.4) !important;
|
||||||
box-shadow: 0em 0em 1em rgba(0,0,0,0.2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
|
@ -434,6 +429,10 @@
|
||||||
display: block !important;
|
display: block !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
.subtitle {
|
.subtitle {
|
||||||
font-size: v.$text-size-2;
|
font-size: v.$text-size-2;
|
||||||
}
|
}
|
||||||
|
@ -444,7 +443,7 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
figure {
|
figure {
|
||||||
// box-shadow: 0em 0em 1em rgba(0, 0, 0, 0.2);
|
box-shadow: 0em 0em 1em rgba(0, 0, 0, 0.2);
|
||||||
height: var(--cover-h);
|
height: var(--cover-h);
|
||||||
width: var(--cover-w);
|
width: var(--cover-w);
|
||||||
}
|
}
|
||||||
|
@ -460,6 +459,25 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ---- grid
|
||||||
|
.list-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
grid-auto-flow: dense;
|
||||||
|
gap: v.$mp-4;
|
||||||
|
|
||||||
|
// .grid-wide { grid-column: 1 / 3; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@media screen and (max-width: v.$screen-smaller) {
|
||||||
|
.list-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
// .grid-wide { grid-column: 1; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ---- ---- Carousel
|
// ---- ---- Carousel
|
||||||
.a-carousel {
|
.a-carousel {
|
||||||
.a-carousel-viewport {
|
.a-carousel-viewport {
|
||||||
|
@ -706,40 +724,3 @@
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ----------------
|
|
||||||
.a-select-file {
|
|
||||||
> *:not(:last-child) {
|
|
||||||
margin-bottom: v.$mp-3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-preview {
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.a-select-file-list {
|
|
||||||
max-height: 30rem;
|
|
||||||
overflow-y: auto;
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr 1fr 1fr 1fr;
|
|
||||||
gap: v.$mp-3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.file-preview {
|
|
||||||
width: 100%;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
box-shadow: 0em 0em 1em rgba(0,0,0,0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
box-shadow: 0em 0em 1em rgba(0,0,0,0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 100%;
|
|
||||||
max-height: 10rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,46 +1,23 @@
|
||||||
@use "./vars" as v;
|
@use "./vars";
|
||||||
|
|
||||||
.text-light { weight: 400; color: var(--text-color-light); }
|
|
||||||
|
|
||||||
// ---- layout
|
|
||||||
.align-left { text-align: left; justify-content: left; }
|
.align-left { text-align: left; justify-content: left; }
|
||||||
.align-right { text-align: right; justify-content: right; }
|
.align-right { text-align: right; justify-content: right; }
|
||||||
|
|
||||||
.clear-left { clear: left !important }
|
.clear-left { clear: left !important }
|
||||||
.clear-right { clear: right !important }
|
.clear-right { clear: right !important }
|
||||||
.clear-both { clear: both !important }
|
.clear-both { clear: both !important }
|
||||||
.clear-unset { clear: unset !important }
|
|
||||||
|
|
||||||
.d-inline { display: inline !important; }
|
.d-inline { display: inline !important; }
|
||||||
.d-block { display: block !important; }
|
.d-block { display: block !important; }
|
||||||
.d-inline-block { display: inline-block !important; }
|
.d-inline-block { display: inline-block !important; }
|
||||||
|
|
||||||
.p-relative { position: relative !important }
|
.push-right, .flex-push-right { margin-left: auto !important; }
|
||||||
.p-absolute { position: absolute !important }
|
.push-bottom { margin-top: auto !important; }
|
||||||
.p-fixed { position: fixed !important }
|
|
||||||
.p-sticky { position: sticky !important }
|
|
||||||
.p-static { position: static !important }
|
|
||||||
|
|
||||||
.ws-nowrap { white-space: nowrap; }
|
|
||||||
|
|
||||||
|
|
||||||
// ---- grid
|
.grid-2 { display: grid; grid-template-columns: 1fr 1fr }
|
||||||
@mixin grid {
|
.grid-3 { display: grid; grid-template-columns: 1fr 1fr 1fr }
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
grid-auto-flow: dense;
|
|
||||||
gap: v.$mp-4;
|
|
||||||
}
|
|
||||||
@mixin grid-1 { grid-template-columns: 1fr; }
|
|
||||||
@mixin grid-2 { grid-template-columns: 1fr 1fr; }
|
|
||||||
@mixin grid-3 { grid-template-columns: 1fr 1fr 1fr; }
|
|
||||||
|
|
||||||
.grid { @include grid; }
|
|
||||||
.grid-1 { @include grid; @include grid-1; }
|
|
||||||
.grid-2 { @include grid; @include grid-2; }
|
|
||||||
.grid-3 { @include grid; @include grid-3; }
|
|
||||||
|
|
||||||
// ---- flex
|
|
||||||
.flex-row { display: flex; flex-direction: row }
|
.flex-row { display: flex; flex-direction: row }
|
||||||
.flex-column { display: flex; flex-direction: column }
|
.flex-column { display: flex; flex-direction: column }
|
||||||
.flex-grow-0 { flex-grow: 0 !important; }
|
.flex-grow-0 { flex-grow: 0 !important; }
|
||||||
|
@ -49,7 +26,6 @@
|
||||||
.float-right { float: right }
|
.float-right { float: right }
|
||||||
.float-left { float: left }
|
.float-left { float: left }
|
||||||
|
|
||||||
// ---- boxing
|
|
||||||
.is-fullwidth { width: 100%; }
|
.is-fullwidth { width: 100%; }
|
||||||
.is-fullheight { height: 100%; }
|
.is-fullheight { height: 100%; }
|
||||||
.is-fixed-bottom {
|
.is-fixed-bottom {
|
||||||
|
@ -58,13 +34,23 @@
|
||||||
margin-bottom: 0px;
|
margin-bottom: 0px;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
.no-border { border: 0px !important; }
|
.is-borderless { border: none; }
|
||||||
|
|
||||||
.overflow-hidden { overflow: hidden }
|
.overflow-hidden { overflow: hidden }
|
||||||
.overflow-hidden.is-fullwidth { max-width: 100%; }
|
.overflow-hidden.is-fullwidth { max-width: 100%; }
|
||||||
|
|
||||||
|
.p-relative { position: relative !important }
|
||||||
|
.p-absolute { position: absolute !important }
|
||||||
|
.p-fixed { position: fixed !important }
|
||||||
|
.p-sticky { position: sticky !important }
|
||||||
|
.p-static { position: static !important }
|
||||||
|
|
||||||
.height-full { height: 100%; }
|
.height-full { height: 100%; }
|
||||||
|
|
||||||
|
.ws-nowrap { white-space: nowrap; }
|
||||||
|
.no-border { border: 0px !important; }
|
||||||
|
|
||||||
|
|
||||||
*[draggable="true"] {
|
*[draggable="true"] {
|
||||||
cursor: move;
|
cursor: move;
|
||||||
}
|
}
|
||||||
|
@ -81,16 +67,16 @@
|
||||||
|
|
||||||
|
|
||||||
// -- colors
|
// -- colors
|
||||||
.main-color { color: var(--main-color); }
|
.hg-color { color: var(--highlight-color); }
|
||||||
.secondary-color { color: var(--secondary-color); }
|
.hg-color-2 { color: var(--highlight-color-2); }
|
||||||
|
|
||||||
.bg-transparent { background-color: transparent; }
|
.bg-transparent { background-color: transparent; }
|
||||||
|
|
||||||
.is-success {
|
.is-success {
|
||||||
background-color: v.$green !important;
|
background-color: vars.$green !important;
|
||||||
border-color: v.$green-dark !important;
|
border-color: vars.$green-dark !important;
|
||||||
}
|
}
|
||||||
.is-danger {
|
.is-danger {
|
||||||
background-color: v.$red !important;
|
background-color: vars.$red !important;
|
||||||
border-color: v.$red-dark !important;
|
border-color: vars.$red-dark !important;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
|
|
||||||
// ---- main theme & layout
|
// ---- main theme & layout
|
||||||
|
|
||||||
.page {
|
.page {
|
||||||
padding-bottom: 5rem;
|
padding-bottom: 5rem;
|
||||||
|
|
||||||
|
@ -48,7 +47,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.vc-weekday-1, .vc-weekday-7 {
|
.vc-weekday-1, .vc-weekday-7 {
|
||||||
color: var(--secondary-color) !important;
|
color: var(--hg-color-2) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -125,15 +124,19 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.navbar-item.active, .table tr.is-selected {
|
.navbar-item.active, .table tr.is-selected {
|
||||||
color: var(--secondary-color);
|
color: var(--hg-color-2);
|
||||||
background-color: var(--main-color);
|
background-color: var(--hg-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// -- headings
|
// -- headings
|
||||||
.title {
|
.title {
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
&.is-3 { margin-top: v.$mp-3; }
|
|
||||||
|
&.is-3 {
|
||||||
|
margin-top: v.$mp-3;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -464,6 +467,12 @@ nav li {
|
||||||
|
|
||||||
|
|
||||||
// ---- responsive
|
// ---- responsive
|
||||||
|
body { font-size: 1.4em; }
|
||||||
|
|
||||||
|
@media screen and (max-width: v.$screen-wide) {
|
||||||
|
body { font-size: 1em; }
|
||||||
|
}
|
||||||
|
|
||||||
@media screen and (max-width: v.$screen-normal) {
|
@media screen and (max-width: v.$screen-normal) {
|
||||||
.page .container {
|
.page .container {
|
||||||
margin-left: v.$mp-4;
|
margin-left: v.$mp-4;
|
||||||
|
@ -476,4 +485,5 @@ nav li {
|
||||||
margin-left: v.$mp-2;
|
margin-left: v.$mp-2;
|
||||||
margin-right: v.$mp-2;
|
margin-right: v.$mp-2;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ $title-color: #000;
|
||||||
@import "~bulma/sass/elements/box";
|
@import "~bulma/sass/elements/box";
|
||||||
// @import "~bulma/sass/elements/button";
|
// @import "~bulma/sass/elements/button";
|
||||||
@import "~bulma/sass/elements/container";
|
@import "~bulma/sass/elements/container";
|
||||||
// @import "~bulma/sass/elements/content";
|
@import "~bulma/sass/elements/content";
|
||||||
@import "~bulma/sass/elements/icon";
|
@import "~bulma/sass/elements/icon";
|
||||||
// @import "~bulma/sass/elements/image";
|
// @import "~bulma/sass/elements/image";
|
||||||
// @import "~bulma/sass/elements/notification";
|
// @import "~bulma/sass/elements/notification";
|
||||||
|
|
|
@ -1,124 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="a-select-file">
|
|
||||||
<div class="a-select-file-list" ref="list">
|
|
||||||
<div class="flex-column file-preview">
|
|
||||||
<div class="field flex-grow-1" v-if="!uploadFile">
|
|
||||||
<label class="label">{{ uploadLabel }}</label>
|
|
||||||
<input type="file" @change="previewFile"/>
|
|
||||||
</div>
|
|
||||||
<slot name="upload-preview" :item="uploadFile"></slot>
|
|
||||||
<div v-if="uploadFile">
|
|
||||||
<button class="button secondary" @click="removeUpload">
|
|
||||||
<span class="icon">
|
|
||||||
<i class="fa fa-trash"></i>
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
<button class="button float-right" @click="doUpload">
|
|
||||||
<span class="icon">
|
|
||||||
<i class="fa fa-upload"></i>
|
|
||||||
</span>
|
|
||||||
Upload
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-if="prevUrl">
|
|
||||||
<a href="#" @click="load(prevUrl)">
|
|
||||||
{{ prevLabel }}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<template v-for="item in items" v-bind:key="item.id">
|
|
||||||
<div :class="['file-preview', this.item && item.id == this.item.id && 'active']" @click="select(item)">
|
|
||||||
<slot :item="item"></slot>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<div v-if="nextUrl">
|
|
||||||
<a href="#" @click="load(nextUrl)">
|
|
||||||
{{ nextLabel }}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="a-select-footer">
|
|
||||||
<slot name="footer" :item="item" :items="items"></slot>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
import {getCsrf} from "../model"
|
|
||||||
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
name: { type: String },
|
|
||||||
prevLabel: { type: String, default: "Prev" },
|
|
||||||
nextLabel: { type: String, default: "Next" },
|
|
||||||
listUrl: { type: String },
|
|
||||||
uploadLabel: { type: String, default: "Upload a file" },
|
|
||||||
},
|
|
||||||
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
item: null,
|
|
||||||
items: [],
|
|
||||||
uploadFile: null,
|
|
||||||
uploadUrl: null,
|
|
||||||
uploadFieldName: null,
|
|
||||||
uploadCSRF: null,
|
|
||||||
nextUrl: "",
|
|
||||||
prevUrl: "",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
previewFile(event) {
|
|
||||||
const [file] = event.target.files
|
|
||||||
this.uploadFile = file && {
|
|
||||||
file: file,
|
|
||||||
src: URL.createObjectURL(file)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
removeUpload() {
|
|
||||||
this.uploadFile = null;
|
|
||||||
},
|
|
||||||
|
|
||||||
doUpload() {
|
|
||||||
const formData = new FormData();
|
|
||||||
formData.append('file', this.uploadFile.file)
|
|
||||||
formData.append('original_filename', this.uploadFile.file.name)
|
|
||||||
formData.append('csrfmiddlewaretoken', getCsrf())
|
|
||||||
fetch(this.listUrl, {
|
|
||||||
method: "POST",
|
|
||||||
body: formData
|
|
||||||
}).then(
|
|
||||||
() => {
|
|
||||||
this.uploadFile = null;
|
|
||||||
this.load()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
},
|
|
||||||
|
|
||||||
load(url) {
|
|
||||||
fetch(url || this.listUrl).then(
|
|
||||||
response => response.ok ? response.json() : Promise.reject(response)
|
|
||||||
).then(data => {
|
|
||||||
this.nextUrl = data.next
|
|
||||||
this.prevUrl = data.previous
|
|
||||||
this.items = data.results
|
|
||||||
|
|
||||||
this.$forceUpdate()
|
|
||||||
this.$refs.list.scroll(0, 0)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
select(item) {
|
|
||||||
this.item = item;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
mounted() {
|
|
||||||
this.load()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
|
@ -1,6 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<button :title="ariaLabel"
|
<button :title="ariaLabel"
|
||||||
type="button"
|
|
||||||
:aria-label="ariaLabel || label" :aria-description="ariaDescription"
|
:aria-label="ariaLabel || label" :aria-description="ariaDescription"
|
||||||
@click="toggle" :class="buttonClass">
|
@click="toggle" :class="buttonClass">
|
||||||
<slot name="default" :active="active">
|
<slot name="default" :active="active">
|
||||||
|
@ -50,21 +49,17 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
set(active) {
|
set(active) {
|
||||||
if(this.el) {
|
const el = document.querySelector(this.el)
|
||||||
const el = document.querySelector(this.el)
|
if(active)
|
||||||
if(active)
|
el.classList.add(this.activeClass)
|
||||||
el.classList.add(this.activeClass)
|
else
|
||||||
else
|
el.classList.remove(this.activeClass)
|
||||||
el.classList.remove(this.activeClass)
|
|
||||||
}
|
|
||||||
this.active = active
|
this.active = active
|
||||||
if(active)
|
if(active)
|
||||||
this.resetGroup()
|
this.resetGroup()
|
||||||
},
|
},
|
||||||
|
|
||||||
resetGroup() {
|
resetGroup() {
|
||||||
if(!this.groupClass)
|
|
||||||
return
|
|
||||||
const els = document.querySelectorAll("." + this.groupClass)
|
const els = document.querySelectorAll("." + this.groupClass)
|
||||||
for(var el of els)
|
for(var el of els)
|
||||||
if(el != this.$el)
|
if(el != this.$el)
|
||||||
|
|
|
@ -12,15 +12,13 @@ import ASoundItem from './ASoundItem.vue'
|
||||||
import ASwitch from './ASwitch.vue'
|
import ASwitch from './ASwitch.vue'
|
||||||
import AStatistics from './AStatistics.vue'
|
import AStatistics from './AStatistics.vue'
|
||||||
import AStreamer from './AStreamer.vue'
|
import AStreamer from './AStreamer.vue'
|
||||||
import ASelectFile from "./ASelectFile.vue"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Core components
|
* Core components
|
||||||
*/
|
*/
|
||||||
export const base = {
|
export const base = {
|
||||||
AAutocomplete, ACarousel, ADropdown, AEpisode, AList, APage, APlayer, APlaylist,
|
AAutocomplete, ACarousel, ADropdown, AEpisode, AList, APage, APlayer, APlaylist,
|
||||||
AProgress, ASoundItem, ASwitch,
|
AProgress, ASoundItem, ASwitch
|
||||||
ASelectFile,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default base
|
export default base
|
||||||
|
|
|
@ -30,7 +30,6 @@ export default class Live {
|
||||||
response.ok ? response.json()
|
response.ok ? response.json()
|
||||||
: Promise.reject(response)
|
: Promise.reject(response)
|
||||||
).then(data => {
|
).then(data => {
|
||||||
data = data.results
|
|
||||||
data.forEach(item => {
|
data.forEach(item => {
|
||||||
if(item.start) item.start = new Date(item.start)
|
if(item.start) item.start = new Date(item.start)
|
||||||
if(item.end) item.end = new Date(item.end)
|
if(item.end) item.end = new Date(item.end)
|
||||||
|
|
|
@ -252,6 +252,3 @@ TEMPLATES = [
|
||||||
WSGI_APPLICATION = "instance.wsgi.application"
|
WSGI_APPLICATION = "instance.wsgi.application"
|
||||||
|
|
||||||
LOGOUT_REDIRECT_URL = "/"
|
LOGOUT_REDIRECT_URL = "/"
|
||||||
|
|
||||||
|
|
||||||
REST_FRAMEWORK = {"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.LimitOffsetPagination", "PAGE_SIZE": 50}
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user