continue migration: make website working
This commit is contained in:
		@ -1,28 +1,7 @@
 | 
			
		||||
from django.contrib import admin
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
from .episode import DiffusionAdmin, EpisodeAdmin
 | 
			
		||||
from .log import LogAdmin
 | 
			
		||||
# from .playlist import PlaylistAdmin
 | 
			
		||||
from .program import ProgramAdmin, ScheduleAdmin, StreamAdmin
 | 
			
		||||
from .sound import SoundAdmin
 | 
			
		||||
 | 
			
		||||
from aircox.models import Log, Port, Station
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PortInline(admin.StackedInline):
 | 
			
		||||
    model = Port
 | 
			
		||||
    extra = 0
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@admin.register(Station)
 | 
			
		||||
class StationAdmin(admin.ModelAdmin):
 | 
			
		||||
    prepopulated_fields = {'slug': ('name',)}
 | 
			
		||||
    inlines = [PortInline]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@admin.register(Log)
 | 
			
		||||
class LogAdmin(admin.ModelAdmin):
 | 
			
		||||
    list_display = ['id', 'date', 'station', 'source', 'type', 'comment']
 | 
			
		||||
    list_filter = ['date', 'source', 'station']
 | 
			
		||||
 | 
			
		||||
from .station import StationAdmin
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							@ -7,6 +7,7 @@ from aircox.models import Episode, Diffusion, Sound, Track
 | 
			
		||||
 | 
			
		||||
from .page import PageAdmin
 | 
			
		||||
from .playlist import TracksInline
 | 
			
		||||
from .sound import SoundInline
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DiffusionBaseAdmin:
 | 
			
		||||
@ -46,14 +47,6 @@ class DiffusionInline(DiffusionBaseAdmin, admin.TabularInline):
 | 
			
		||||
        return request.user.has_perm('aircox_program.scheduling')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class SoundInline(admin.TabularInline):
 | 
			
		||||
    model = Sound
 | 
			
		||||
    fk_name = 'episode'
 | 
			
		||||
    fields = ['type', 'path', 'duration', 'is_public']
 | 
			
		||||
    readonly_fields = ['type']
 | 
			
		||||
    extra = 0
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@admin.register(Episode)
 | 
			
		||||
class EpisodeAdmin(PageAdmin):
 | 
			
		||||
    list_display = PageAdmin.list_display + ('program',)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										13
									
								
								aircox/admin/log.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								aircox/admin/log.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
			
		||||
from django.contrib import admin
 | 
			
		||||
 | 
			
		||||
from ..models import Log
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ['LogAdmin']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@admin.register(Log)
 | 
			
		||||
class LogAdmin(admin.ModelAdmin):
 | 
			
		||||
    list_display = ['id', 'date', 'station', 'source', 'type', 'comment']
 | 
			
		||||
    list_filter = ['date', 'source', 'station']
 | 
			
		||||
 | 
			
		||||
@ -2,6 +2,10 @@ from django.contrib import admin
 | 
			
		||||
from django.utils.safestring import mark_safe
 | 
			
		||||
from django.utils.translation import ugettext_lazy as _
 | 
			
		||||
 | 
			
		||||
from adminsortable2.admin import SortableInlineAdminMixin
 | 
			
		||||
 | 
			
		||||
from ..models import NavItem
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PageAdmin(admin.ModelAdmin):
 | 
			
		||||
    list_display = ('cover_thumb', 'title', 'status')
 | 
			
		||||
@ -24,5 +28,6 @@ class PageAdmin(admin.ModelAdmin):
 | 
			
		||||
            if obj.cover else ''
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NavItemInline(SortableInlineAdminMixin, admin.TabularInline):
 | 
			
		||||
    model = NavItem
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -5,6 +5,13 @@ from aircox.models import Sound
 | 
			
		||||
from .playlist import TracksInline
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class SoundInline(admin.TabularInline):
 | 
			
		||||
    model = Sound
 | 
			
		||||
    fields = ['type', 'path', 'duration', 'is_public']
 | 
			
		||||
    readonly_fields = ['type']
 | 
			
		||||
    extra = 0
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@admin.register(Sound)
 | 
			
		||||
class SoundAdmin(admin.ModelAdmin):
 | 
			
		||||
    def filename(self, obj):
 | 
			
		||||
@ -24,3 +31,4 @@ class SoundAdmin(admin.ModelAdmin):
 | 
			
		||||
    inlines = [TracksInline]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										20
									
								
								aircox/admin/station.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								aircox/admin/station.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
			
		||||
from django.contrib import admin
 | 
			
		||||
 | 
			
		||||
from ..models import Port, Station
 | 
			
		||||
from .page import NavItemInline
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ['PortInline', 'StationAdmin']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PortInline(admin.StackedInline):
 | 
			
		||||
    model = Port
 | 
			
		||||
    extra = 0
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@admin.register(Station)
 | 
			
		||||
class StationAdmin(admin.ModelAdmin):
 | 
			
		||||
    prepopulated_fields = {'slug': ('name',)}
 | 
			
		||||
    inlines = [PortInline, NavItemInline]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -15,6 +15,7 @@ from django.utils import timezone as tz
 | 
			
		||||
from . import settings
 | 
			
		||||
from .models import Port, Station, Sound
 | 
			
		||||
from .connector import Connector
 | 
			
		||||
from .utils import to_seconds
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# FIXME liquidsoap does not manage timezones -- we have to convert
 | 
			
		||||
@ -297,9 +298,6 @@ class PlaylistSource(Source):
 | 
			
		||||
        if not stream or (not stream.begin and not stream.delay):
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        def to_seconds(time):
 | 
			
		||||
            return 3600 * time.hour + 60 * time.minute + time.second
 | 
			
		||||
 | 
			
		||||
        return {
 | 
			
		||||
            'begin': stream.begin.strftime('%Hh%M') if stream.begin else None,
 | 
			
		||||
            'end': stream.end.strftime('%Hh%M') if stream.end else None,
 | 
			
		||||
 | 
			
		||||
@ -12,7 +12,6 @@ used to:
 | 
			
		||||
# x cancel
 | 
			
		||||
# x when liquidsoap fails to start/exists: exit
 | 
			
		||||
# - handle restart after failure
 | 
			
		||||
# - file in queue without sound not logged?
 | 
			
		||||
# - is stream restart after live ok?
 | 
			
		||||
from argparse import RawTextHelpFormatter
 | 
			
		||||
import time
 | 
			
		||||
 | 
			
		||||
@ -1,25 +1,13 @@
 | 
			
		||||
import pytz
 | 
			
		||||
import django.utils.timezone as tz
 | 
			
		||||
from django import shortcuts
 | 
			
		||||
from django.db.models import Q, Case, Value, When
 | 
			
		||||
from django.utils import timezone as tz
 | 
			
		||||
 | 
			
		||||
import aircox.models as models
 | 
			
		||||
from .models import Station
 | 
			
		||||
from .utils import Redirect
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AircoxInfo:
 | 
			
		||||
    """
 | 
			
		||||
    Used to store informations about Aircox on a request. Some of theses
 | 
			
		||||
    information are None when user is anonymous.
 | 
			
		||||
    """
 | 
			
		||||
    station = None
 | 
			
		||||
    """
 | 
			
		||||
    Current station
 | 
			
		||||
    """
 | 
			
		||||
    default_station = False
 | 
			
		||||
    """
 | 
			
		||||
    Default station is used as the current station
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, **kwargs):
 | 
			
		||||
        self.__dict__.update(kwargs)
 | 
			
		||||
__all__ = ['AircoxMiddleware']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AircoxMiddleware(object):
 | 
			
		||||
@ -31,37 +19,19 @@ class AircoxMiddleware(object):
 | 
			
		||||
    def __init__(self, get_response):
 | 
			
		||||
        self.get_response = get_response
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def update_station(self, request):
 | 
			
		||||
        station = request.GET.get('aircox.station')
 | 
			
		||||
        pk = None
 | 
			
		||||
        try:
 | 
			
		||||
            if station is not None:
 | 
			
		||||
                pk = request.GET['aircox.station']
 | 
			
		||||
                if station:
 | 
			
		||||
                    pk = int(pk)
 | 
			
		||||
                    if models.Station.objects.filter(pk = station).exists():
 | 
			
		||||
                        request.session['aircox.station'] = pk
 | 
			
		||||
        except:
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
    def init_station(self, request, aircox):
 | 
			
		||||
        self.update_station(request)
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            pk = request.session.get('aircox.station')
 | 
			
		||||
            pk = int(pk) if pk else None
 | 
			
		||||
        except:
 | 
			
		||||
            pk = None
 | 
			
		||||
 | 
			
		||||
        aircox.station = models.Station.objects.default(pk)
 | 
			
		||||
        aircox.default_station = (pk is None)
 | 
			
		||||
    def get_station(self, request):
 | 
			
		||||
        """ Return station for the provided request """
 | 
			
		||||
        expr = Q(default=True) | Q(hosts__contains=request.get_host())
 | 
			
		||||
        #case = Case(When(hosts__contains=request.get_host(), then=Value(0)),
 | 
			
		||||
        #            When(default=True, then=Value(32)))
 | 
			
		||||
        return Station.objects.filter(expr).order_by('default').first()
 | 
			
		||||
        #              .annotate(resolve_priority=case) \
 | 
			
		||||
                      #.order_by('resolve_priority').first()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def init_timezone(self, request, aircox):
 | 
			
		||||
    def init_timezone(self, request):
 | 
			
		||||
        # note: later we can use http://freegeoip.net/ on user side if
 | 
			
		||||
        # required
 | 
			
		||||
        # TODO: add to request's session
 | 
			
		||||
        timezone = None
 | 
			
		||||
        try:
 | 
			
		||||
            timezone = request.session.get('aircox.timezone')
 | 
			
		||||
@ -76,14 +46,11 @@ class AircoxMiddleware(object):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def __call__(self, request):
 | 
			
		||||
        tz.activate(pytz.timezone('Europe/Brussels'))
 | 
			
		||||
        aircox = AircoxInfo()
 | 
			
		||||
 | 
			
		||||
        if request.user.is_authenticated:
 | 
			
		||||
            self.init_station(request, aircox)
 | 
			
		||||
        self.init_timezone(request, aircox)
 | 
			
		||||
 | 
			
		||||
        request.aircox = aircox
 | 
			
		||||
        self.init_timezone(request)
 | 
			
		||||
        request.station = self.get_station(request)
 | 
			
		||||
        try:
 | 
			
		||||
            return self.get_response(request)
 | 
			
		||||
        except Redirect as redirect:
 | 
			
		||||
            return 
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
from .page import Page
 | 
			
		||||
from .page import Page, NavItem
 | 
			
		||||
from .program import Program, Stream, Schedule
 | 
			
		||||
from .episode import Episode, Diffusion
 | 
			
		||||
from .log import Log
 | 
			
		||||
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							@ -25,6 +25,7 @@ class Episode(Page):
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    objects = InProgramQuerySet.as_manager()
 | 
			
		||||
    detail_url_name = 'episode-detail'
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        verbose_name = _('Episode')
 | 
			
		||||
@ -36,12 +37,18 @@ class Episode(Page):
 | 
			
		||||
        super().save(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def from_date(cls, program, date):
 | 
			
		||||
        title = settings.AIRCOX_EPISODE_TITLE.format(
 | 
			
		||||
    def get_default_title(cls, program, date):
 | 
			
		||||
        """ Get default Episode's title  """
 | 
			
		||||
        return settings.AIRCOX_EPISODE_TITLE.format(
 | 
			
		||||
            program=program,
 | 
			
		||||
            date=date.strftime(settings.AIRCOX_EPISODE_TITLE_DATE_FORMAT),
 | 
			
		||||
        )
 | 
			
		||||
        return cls(program=program, title=title)
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def from_date(cls, program, date):
 | 
			
		||||
        title = cls.get_default_title(program, date)
 | 
			
		||||
        return cls(program=program, title=title, cover=program.cover)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DiffusionQuerySet(BaseRerunQuerySet):
 | 
			
		||||
    def episode(self, episode=None, id=None):
 | 
			
		||||
 | 
			
		||||
@ -3,14 +3,20 @@ from enum import IntEnum
 | 
			
		||||
from django.db import models
 | 
			
		||||
from django.urls import reverse
 | 
			
		||||
from django.utils.text import slugify
 | 
			
		||||
from django.utils.html import format_html
 | 
			
		||||
from django.utils.translation import ugettext_lazy as _
 | 
			
		||||
 | 
			
		||||
from django.contrib.contenttypes.fields import GenericForeignKey
 | 
			
		||||
from django.contrib.contenttypes.models import ContentType
 | 
			
		||||
 | 
			
		||||
from ckeditor.fields import RichTextField
 | 
			
		||||
from filer.fields.image import FilerImageField
 | 
			
		||||
from model_utils.managers import InheritanceQuerySet
 | 
			
		||||
 | 
			
		||||
from .station import Station
 | 
			
		||||
 | 
			
		||||
__all__ = ['Page', 'PageQuerySet']
 | 
			
		||||
 | 
			
		||||
__all__ = ['PageQuerySet', 'Page', 'NavItem']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PageQuerySet(InheritanceQuerySet):
 | 
			
		||||
@ -48,8 +54,10 @@ class Page(models.Model):
 | 
			
		||||
 | 
			
		||||
    objects = PageQuerySet.as_manager()
 | 
			
		||||
 | 
			
		||||
    detail_url_name = None
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract=True
 | 
			
		||||
        abstract = True
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return '{}: {}'.format(self._meta.verbose_name,
 | 
			
		||||
@ -64,10 +72,53 @@ class Page(models.Model):
 | 
			
		||||
 | 
			
		||||
    def get_absolute_url(self):
 | 
			
		||||
        return reverse(self.detail_url_name, kwargs={'slug': self.slug}) \
 | 
			
		||||
            if self.is_published else ''
 | 
			
		||||
            if self.is_published else '#'
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def is_draft(self):
 | 
			
		||||
        return self.status == self.STATUS.draft
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def is_published(self):
 | 
			
		||||
        return self.status == self.STATUS.published
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def is_trash(self):
 | 
			
		||||
        return self.status == self.STATUS.trash
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NavItem(models.Model):
 | 
			
		||||
    """ Navigation menu items """
 | 
			
		||||
    station = models.ForeignKey(
 | 
			
		||||
        Station, models.CASCADE, verbose_name=_('station'))
 | 
			
		||||
    menu = models.SlugField(_('menu'), max_length=24)
 | 
			
		||||
    order = models.PositiveSmallIntegerField(_('order'))
 | 
			
		||||
    text = models.CharField(_('title'), max_length=64)
 | 
			
		||||
    url = models.CharField(_('url'), max_length=256, blank=True, null=True)
 | 
			
		||||
    #target_type = models.ForeignKey(
 | 
			
		||||
    #    ContentType, models.CASCADE, blank=True, null=True)
 | 
			
		||||
    #target_id = models.PositiveSmallIntegerField(blank=True, null=True)
 | 
			
		||||
    #target = GenericForeignKey('target_type', 'target_id')
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        verbose_name = _('Menu item')
 | 
			
		||||
        ordering = ('order', 'pk')
 | 
			
		||||
 | 
			
		||||
    is_active = False
 | 
			
		||||
 | 
			
		||||
    def get_is_active(self, url):
 | 
			
		||||
        """ Return True if navigation item is active for this url. """
 | 
			
		||||
        return self.url and url.startswith(self.url)
 | 
			
		||||
 | 
			
		||||
    def render(self, request, css_class='', active_class=''):
 | 
			
		||||
        if active_class and request.path.startswith(self.url):
 | 
			
		||||
            css_class += ' ' + active_class
 | 
			
		||||
 | 
			
		||||
        if not self.url:
 | 
			
		||||
            return self.text
 | 
			
		||||
        elif not css_class:
 | 
			
		||||
            return format_html('<a href="{}">{}</a>', self.url, self.text)
 | 
			
		||||
        else:
 | 
			
		||||
            return format_html('<a href="{}" class="{}">{}</a>', self.url,
 | 
			
		||||
                               css_class, self.text)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -62,6 +62,7 @@ class Program(Page):
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    objects = ProgramQuerySet.as_manager()
 | 
			
		||||
    detail_url_name = 'program-detail'
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def path(self):
 | 
			
		||||
 | 
			
		||||
@ -5,7 +5,9 @@ from django.db import models
 | 
			
		||||
from django.db.models import Q
 | 
			
		||||
from django.utils.translation import ugettext_lazy as _
 | 
			
		||||
 | 
			
		||||
import aircox.settings as settings
 | 
			
		||||
from filer.fields.image import FilerImageField
 | 
			
		||||
 | 
			
		||||
from .. import settings
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ['Station', 'StationQuerySet', 'Port']
 | 
			
		||||
@ -45,6 +47,14 @@ class Station(models.Model):
 | 
			
		||||
        default=True,
 | 
			
		||||
        help_text=_('if checked, this station is used as the main one')
 | 
			
		||||
    )
 | 
			
		||||
    logo = FilerImageField(
 | 
			
		||||
        on_delete=models.SET_NULL, null=True, blank=True,
 | 
			
		||||
        verbose_name=_('Logo'),
 | 
			
		||||
    )
 | 
			
		||||
    hosts = models.TextField(
 | 
			
		||||
        _("website's urls"), max_length=512, null=True, blank=True,
 | 
			
		||||
        help_text=_('specify one url per line')
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    objects = StationQuerySet.as_manager()
 | 
			
		||||
 | 
			
		||||
@ -58,15 +68,14 @@ class Station(models.Model):
 | 
			
		||||
 | 
			
		||||
        if self.default:
 | 
			
		||||
            qs = Station.objects.filter(default=True)
 | 
			
		||||
 | 
			
		||||
            if self.pk:
 | 
			
		||||
            if self.pk is not None:
 | 
			
		||||
                qs = qs.exclude(pk=self.pk)
 | 
			
		||||
            qs.update(default=False)
 | 
			
		||||
 | 
			
		||||
        super().save(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Port (models.Model):
 | 
			
		||||
class Port(models.Model):
 | 
			
		||||
    """
 | 
			
		||||
    Represent an audio input/output for the audio stream
 | 
			
		||||
    generation.
 | 
			
		||||
@ -147,4 +156,3 @@ class Port (models.Model):
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										7201
									
								
								aircox/static/aircox/main.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7201
									
								
								aircox/static/aircox/main.css
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										347
									
								
								aircox/static/aircox/main.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										347
									
								
								aircox/static/aircox/main.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,347 @@
 | 
			
		||||
/******/ (function(modules) { // webpackBootstrap
 | 
			
		||||
/******/ 	// install a JSONP callback for chunk loading
 | 
			
		||||
/******/ 	function webpackJsonpCallback(data) {
 | 
			
		||||
/******/ 		var chunkIds = data[0];
 | 
			
		||||
/******/ 		var moreModules = data[1];
 | 
			
		||||
/******/ 		var executeModules = data[2];
 | 
			
		||||
/******/
 | 
			
		||||
/******/ 		// add "moreModules" to the modules object,
 | 
			
		||||
/******/ 		// then flag all "chunkIds" as loaded and fire callback
 | 
			
		||||
/******/ 		var moduleId, chunkId, i = 0, resolves = [];
 | 
			
		||||
/******/ 		for(;i < chunkIds.length; i++) {
 | 
			
		||||
/******/ 			chunkId = chunkIds[i];
 | 
			
		||||
/******/ 			if(installedChunks[chunkId]) {
 | 
			
		||||
/******/ 				resolves.push(installedChunks[chunkId][0]);
 | 
			
		||||
/******/ 			}
 | 
			
		||||
/******/ 			installedChunks[chunkId] = 0;
 | 
			
		||||
/******/ 		}
 | 
			
		||||
/******/ 		for(moduleId in moreModules) {
 | 
			
		||||
/******/ 			if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
 | 
			
		||||
/******/ 				modules[moduleId] = moreModules[moduleId];
 | 
			
		||||
/******/ 			}
 | 
			
		||||
/******/ 		}
 | 
			
		||||
/******/ 		if(parentJsonpFunction) parentJsonpFunction(data);
 | 
			
		||||
/******/
 | 
			
		||||
/******/ 		while(resolves.length) {
 | 
			
		||||
/******/ 			resolves.shift()();
 | 
			
		||||
/******/ 		}
 | 
			
		||||
/******/
 | 
			
		||||
/******/ 		// add entry modules from loaded chunk to deferred list
 | 
			
		||||
/******/ 		deferredModules.push.apply(deferredModules, executeModules || []);
 | 
			
		||||
/******/
 | 
			
		||||
/******/ 		// run deferred modules when all chunks ready
 | 
			
		||||
/******/ 		return checkDeferredModules();
 | 
			
		||||
/******/ 	};
 | 
			
		||||
/******/ 	function checkDeferredModules() {
 | 
			
		||||
/******/ 		var result;
 | 
			
		||||
/******/ 		for(var i = 0; i < deferredModules.length; i++) {
 | 
			
		||||
/******/ 			var deferredModule = deferredModules[i];
 | 
			
		||||
/******/ 			var fulfilled = true;
 | 
			
		||||
/******/ 			for(var j = 1; j < deferredModule.length; j++) {
 | 
			
		||||
/******/ 				var depId = deferredModule[j];
 | 
			
		||||
/******/ 				if(installedChunks[depId] !== 0) fulfilled = false;
 | 
			
		||||
/******/ 			}
 | 
			
		||||
/******/ 			if(fulfilled) {
 | 
			
		||||
/******/ 				deferredModules.splice(i--, 1);
 | 
			
		||||
/******/ 				result = __webpack_require__(__webpack_require__.s = deferredModule[0]);
 | 
			
		||||
/******/ 			}
 | 
			
		||||
/******/ 		}
 | 
			
		||||
/******/
 | 
			
		||||
/******/ 		return result;
 | 
			
		||||
/******/ 	}
 | 
			
		||||
/******/
 | 
			
		||||
/******/ 	// The module cache
 | 
			
		||||
/******/ 	var installedModules = {};
 | 
			
		||||
/******/
 | 
			
		||||
/******/ 	// object to store loaded and loading chunks
 | 
			
		||||
/******/ 	// undefined = chunk not loaded, null = chunk preloaded/prefetched
 | 
			
		||||
/******/ 	// Promise = chunk loading, 0 = chunk loaded
 | 
			
		||||
/******/ 	var installedChunks = {
 | 
			
		||||
/******/ 		"main": 0
 | 
			
		||||
/******/ 	};
 | 
			
		||||
/******/
 | 
			
		||||
/******/ 	var deferredModules = [];
 | 
			
		||||
/******/
 | 
			
		||||
/******/ 	// The require function
 | 
			
		||||
/******/ 	function __webpack_require__(moduleId) {
 | 
			
		||||
/******/
 | 
			
		||||
/******/ 		// Check if module is in cache
 | 
			
		||||
/******/ 		if(installedModules[moduleId]) {
 | 
			
		||||
/******/ 			return installedModules[moduleId].exports;
 | 
			
		||||
/******/ 		}
 | 
			
		||||
/******/ 		// Create a new module (and put it into the cache)
 | 
			
		||||
/******/ 		var module = installedModules[moduleId] = {
 | 
			
		||||
/******/ 			i: moduleId,
 | 
			
		||||
/******/ 			l: false,
 | 
			
		||||
/******/ 			exports: {}
 | 
			
		||||
/******/ 		};
 | 
			
		||||
/******/
 | 
			
		||||
/******/ 		// Execute the module function
 | 
			
		||||
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
 | 
			
		||||
/******/
 | 
			
		||||
/******/ 		// Flag the module as loaded
 | 
			
		||||
/******/ 		module.l = true;
 | 
			
		||||
/******/
 | 
			
		||||
/******/ 		// Return the exports of the module
 | 
			
		||||
/******/ 		return module.exports;
 | 
			
		||||
/******/ 	}
 | 
			
		||||
/******/
 | 
			
		||||
/******/
 | 
			
		||||
/******/ 	// expose the modules object (__webpack_modules__)
 | 
			
		||||
/******/ 	__webpack_require__.m = modules;
 | 
			
		||||
/******/
 | 
			
		||||
/******/ 	// expose the module cache
 | 
			
		||||
/******/ 	__webpack_require__.c = installedModules;
 | 
			
		||||
/******/
 | 
			
		||||
/******/ 	// define getter function for harmony exports
 | 
			
		||||
/******/ 	__webpack_require__.d = function(exports, name, getter) {
 | 
			
		||||
/******/ 		if(!__webpack_require__.o(exports, name)) {
 | 
			
		||||
/******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
 | 
			
		||||
/******/ 		}
 | 
			
		||||
/******/ 	};
 | 
			
		||||
/******/
 | 
			
		||||
/******/ 	// define __esModule on exports
 | 
			
		||||
/******/ 	__webpack_require__.r = function(exports) {
 | 
			
		||||
/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
 | 
			
		||||
/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
 | 
			
		||||
/******/ 		}
 | 
			
		||||
/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
 | 
			
		||||
/******/ 	};
 | 
			
		||||
/******/
 | 
			
		||||
/******/ 	// create a fake namespace object
 | 
			
		||||
/******/ 	// mode & 1: value is a module id, require it
 | 
			
		||||
/******/ 	// mode & 2: merge all properties of value into the ns
 | 
			
		||||
/******/ 	// mode & 4: return value when already ns object
 | 
			
		||||
/******/ 	// mode & 8|1: behave like require
 | 
			
		||||
/******/ 	__webpack_require__.t = function(value, mode) {
 | 
			
		||||
/******/ 		if(mode & 1) value = __webpack_require__(value);
 | 
			
		||||
/******/ 		if(mode & 8) return value;
 | 
			
		||||
/******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
 | 
			
		||||
/******/ 		var ns = Object.create(null);
 | 
			
		||||
/******/ 		__webpack_require__.r(ns);
 | 
			
		||||
/******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
 | 
			
		||||
/******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
 | 
			
		||||
/******/ 		return ns;
 | 
			
		||||
/******/ 	};
 | 
			
		||||
/******/
 | 
			
		||||
/******/ 	// getDefaultExport function for compatibility with non-harmony modules
 | 
			
		||||
/******/ 	__webpack_require__.n = function(module) {
 | 
			
		||||
/******/ 		var getter = module && module.__esModule ?
 | 
			
		||||
/******/ 			function getDefault() { return module['default']; } :
 | 
			
		||||
/******/ 			function getModuleExports() { return module; };
 | 
			
		||||
/******/ 		__webpack_require__.d(getter, 'a', getter);
 | 
			
		||||
/******/ 		return getter;
 | 
			
		||||
/******/ 	};
 | 
			
		||||
/******/
 | 
			
		||||
/******/ 	// Object.prototype.hasOwnProperty.call
 | 
			
		||||
/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
 | 
			
		||||
/******/
 | 
			
		||||
/******/ 	// __webpack_public_path__
 | 
			
		||||
/******/ 	__webpack_require__.p = "";
 | 
			
		||||
/******/
 | 
			
		||||
/******/ 	var jsonpArray = window["webpackJsonp"] = window["webpackJsonp"] || [];
 | 
			
		||||
/******/ 	var oldJsonpFunction = jsonpArray.push.bind(jsonpArray);
 | 
			
		||||
/******/ 	jsonpArray.push = webpackJsonpCallback;
 | 
			
		||||
/******/ 	jsonpArray = jsonpArray.slice();
 | 
			
		||||
/******/ 	for(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);
 | 
			
		||||
/******/ 	var parentJsonpFunction = oldJsonpFunction;
 | 
			
		||||
/******/
 | 
			
		||||
/******/
 | 
			
		||||
/******/ 	// add entry module to deferred list
 | 
			
		||||
/******/ 	deferredModules.push(["./assets/index.js","vendor"]);
 | 
			
		||||
/******/ 	// run deferred modules when ready
 | 
			
		||||
/******/ 	return checkDeferredModules();
 | 
			
		||||
/******/ })
 | 
			
		||||
/************************************************************************/
 | 
			
		||||
/******/ ({
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/index.js":
 | 
			
		||||
/*!*************************!*\
 | 
			
		||||
  !*** ./assets/index.js ***!
 | 
			
		||||
  \*************************/
 | 
			
		||||
/*! no exports provided */
 | 
			
		||||
/*! all exports used */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./js */ \"./assets/js/index.js\");\n/* harmony import */ var _styles_scss__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./styles.scss */ \"./assets/styles.scss\");\n/* harmony import */ var _styles_scss__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_styles_scss__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _noscript_scss__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./noscript.scss */ \"./assets/noscript.scss\");\n/* harmony import */ var _noscript_scss__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_noscript_scss__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _vue__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./vue */ \"./assets/vue/index.js\");\n\n\n\n\n\n\n\n//# sourceURL=webpack:///./assets/index.js?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/js/index.js":
 | 
			
		||||
/*!****************************!*\
 | 
			
		||||
  !*** ./assets/js/index.js ***!
 | 
			
		||||
  \****************************/
 | 
			
		||||
/*! no exports provided */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.browser.js\");\n/* harmony import */ var buefy__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! buefy */ \"./node_modules/buefy/dist/buefy.js\");\n/* harmony import */ var buefy__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(buefy__WEBPACK_IMPORTED_MODULE_1__);\n\n\n\nvue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].use(buefy__WEBPACK_IMPORTED_MODULE_1___default.a);\n\nwindow.addEventListener('load', () => {\n    var app = new vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"]({\n      el: '#app',\n      delimiters: [ '[[', ']]' ],\n    })\n});\n\n\n\n\n\n//# sourceURL=webpack:///./assets/js/index.js?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/noscript.scss":
 | 
			
		||||
/*!******************************!*\
 | 
			
		||||
  !*** ./assets/noscript.scss ***!
 | 
			
		||||
  \******************************/
 | 
			
		||||
/*! no static exports found */
 | 
			
		||||
/***/ (function(module, exports, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
eval("// extracted by mini-css-extract-plugin\n\n//# sourceURL=webpack:///./assets/noscript.scss?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/styles.scss":
 | 
			
		||||
/*!****************************!*\
 | 
			
		||||
  !*** ./assets/styles.scss ***!
 | 
			
		||||
  \****************************/
 | 
			
		||||
/*! no static exports found */
 | 
			
		||||
/***/ (function(module, exports, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
eval("// extracted by mini-css-extract-plugin\n\n//# sourceURL=webpack:///./assets/styles.scss?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/vue/index.js":
 | 
			
		||||
/*!*****************************!*\
 | 
			
		||||
  !*** ./assets/vue/index.js ***!
 | 
			
		||||
  \*****************************/
 | 
			
		||||
/*! exports provided: Tab, Tabs */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.browser.js\");\n/* harmony import */ var _tab_vue__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./tab.vue */ \"./assets/vue/tab.vue\");\n/* harmony import */ var _tabs_vue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./tabs.vue */ \"./assets/vue/tabs.vue\");\n\n\n\n\n\nvue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].component('a-tab', _tab_vue__WEBPACK_IMPORTED_MODULE_1__[/* default */ \"a\"]);\nvue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].component('a-tabs', _tabs_vue__WEBPACK_IMPORTED_MODULE_2__[/* default */ \"a\"]);\n\n\n\n\n\n\n//# sourceURL=webpack:///./assets/vue/index.js?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/vue/tab.vue":
 | 
			
		||||
/*!****************************!*\
 | 
			
		||||
  !*** ./assets/vue/tab.vue ***!
 | 
			
		||||
  \****************************/
 | 
			
		||||
/*! exports provided: default */
 | 
			
		||||
/*! exports used: default */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("/* harmony import */ var _tab_vue_vue_type_template_id_65401e0e___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./tab.vue?vue&type=template&id=65401e0e& */ \"./assets/vue/tab.vue?vue&type=template&id=65401e0e&\");\n/* harmony import */ var _tab_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./tab.vue?vue&type=script&lang=js& */ \"./assets/vue/tab.vue?vue&type=script&lang=js&\");\n/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ \"./node_modules/vue-loader/lib/runtime/componentNormalizer.js\");\n\n\n\n\n\n/* normalize component */\n\nvar component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__[/* default */ \"a\"])(\n  _tab_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[/* default */ \"a\"],\n  _tab_vue_vue_type_template_id_65401e0e___WEBPACK_IMPORTED_MODULE_0__[/* render */ \"a\"],\n  _tab_vue_vue_type_template_id_65401e0e___WEBPACK_IMPORTED_MODULE_0__[/* staticRenderFns */ \"b\"],\n  false,\n  null,\n  null,\n  null\n  \n)\n\n/* hot reload */\nif (false) { var api; }\ncomponent.options.__file = \"assets/vue/tab.vue\"\n/* harmony default export */ __webpack_exports__[\"a\"] = (component.exports);\n\n//# sourceURL=webpack:///./assets/vue/tab.vue?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/vue/tab.vue?vue&type=script&lang=js&":
 | 
			
		||||
/*!*****************************************************!*\
 | 
			
		||||
  !*** ./assets/vue/tab.vue?vue&type=script&lang=js& ***!
 | 
			
		||||
  \*****************************************************/
 | 
			
		||||
/*! exports provided: default */
 | 
			
		||||
/*! exports used: default */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("/* harmony import */ var _node_modules_vue_loader_lib_index_js_vue_loader_options_tab_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../node_modules/vue-loader/lib??vue-loader-options!./tab.vue?vue&type=script&lang=js& */ \"./node_modules/vue-loader/lib/index.js?!./assets/vue/tab.vue?vue&type=script&lang=js&\");\n /* harmony default export */ __webpack_exports__[\"a\"] = (_node_modules_vue_loader_lib_index_js_vue_loader_options_tab_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__[/* default */ \"a\"]); \n\n//# sourceURL=webpack:///./assets/vue/tab.vue?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/vue/tab.vue?vue&type=template&id=65401e0e&":
 | 
			
		||||
/*!***********************************************************!*\
 | 
			
		||||
  !*** ./assets/vue/tab.vue?vue&type=template&id=65401e0e& ***!
 | 
			
		||||
  \***********************************************************/
 | 
			
		||||
/*! exports provided: render, staticRenderFns */
 | 
			
		||||
/*! exports used: render, staticRenderFns */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("/* harmony import */ var _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_tab_vue_vue_type_template_id_65401e0e___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!../../node_modules/vue-loader/lib??vue-loader-options!./tab.vue?vue&type=template&id=65401e0e& */ \"./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/vue-loader/lib/index.js?!./assets/vue/tab.vue?vue&type=template&id=65401e0e&\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"a\", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_tab_vue_vue_type_template_id_65401e0e___WEBPACK_IMPORTED_MODULE_0__[\"a\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"b\", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_tab_vue_vue_type_template_id_65401e0e___WEBPACK_IMPORTED_MODULE_0__[\"b\"]; });\n\n\n\n//# sourceURL=webpack:///./assets/vue/tab.vue?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/vue/tabs.vue":
 | 
			
		||||
/*!*****************************!*\
 | 
			
		||||
  !*** ./assets/vue/tabs.vue ***!
 | 
			
		||||
  \*****************************/
 | 
			
		||||
/*! exports provided: default */
 | 
			
		||||
/*! exports used: default */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("/* harmony import */ var _tabs_vue_vue_type_template_id_466f44d5___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./tabs.vue?vue&type=template&id=466f44d5& */ \"./assets/vue/tabs.vue?vue&type=template&id=466f44d5&\");\n/* harmony import */ var _tabs_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./tabs.vue?vue&type=script&lang=js& */ \"./assets/vue/tabs.vue?vue&type=script&lang=js&\");\n/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ \"./node_modules/vue-loader/lib/runtime/componentNormalizer.js\");\n\n\n\n\n\n/* normalize component */\n\nvar component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__[/* default */ \"a\"])(\n  _tabs_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[/* default */ \"a\"],\n  _tabs_vue_vue_type_template_id_466f44d5___WEBPACK_IMPORTED_MODULE_0__[/* render */ \"a\"],\n  _tabs_vue_vue_type_template_id_466f44d5___WEBPACK_IMPORTED_MODULE_0__[/* staticRenderFns */ \"b\"],\n  false,\n  null,\n  null,\n  null\n  \n)\n\n/* hot reload */\nif (false) { var api; }\ncomponent.options.__file = \"assets/vue/tabs.vue\"\n/* harmony default export */ __webpack_exports__[\"a\"] = (component.exports);\n\n//# sourceURL=webpack:///./assets/vue/tabs.vue?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/vue/tabs.vue?vue&type=script&lang=js&":
 | 
			
		||||
/*!******************************************************!*\
 | 
			
		||||
  !*** ./assets/vue/tabs.vue?vue&type=script&lang=js& ***!
 | 
			
		||||
  \******************************************************/
 | 
			
		||||
/*! exports provided: default */
 | 
			
		||||
/*! exports used: default */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("/* harmony import */ var _node_modules_vue_loader_lib_index_js_vue_loader_options_tabs_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../node_modules/vue-loader/lib??vue-loader-options!./tabs.vue?vue&type=script&lang=js& */ \"./node_modules/vue-loader/lib/index.js?!./assets/vue/tabs.vue?vue&type=script&lang=js&\");\n /* harmony default export */ __webpack_exports__[\"a\"] = (_node_modules_vue_loader_lib_index_js_vue_loader_options_tabs_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__[/* default */ \"a\"]); \n\n//# sourceURL=webpack:///./assets/vue/tabs.vue?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/vue/tabs.vue?vue&type=template&id=466f44d5&":
 | 
			
		||||
/*!************************************************************!*\
 | 
			
		||||
  !*** ./assets/vue/tabs.vue?vue&type=template&id=466f44d5& ***!
 | 
			
		||||
  \************************************************************/
 | 
			
		||||
/*! exports provided: render, staticRenderFns */
 | 
			
		||||
/*! exports used: render, staticRenderFns */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("/* harmony import */ var _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_tabs_vue_vue_type_template_id_466f44d5___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!../../node_modules/vue-loader/lib??vue-loader-options!./tabs.vue?vue&type=template&id=466f44d5& */ \"./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/vue-loader/lib/index.js?!./assets/vue/tabs.vue?vue&type=template&id=466f44d5&\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"a\", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_tabs_vue_vue_type_template_id_466f44d5___WEBPACK_IMPORTED_MODULE_0__[\"a\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"b\", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_tabs_vue_vue_type_template_id_466f44d5___WEBPACK_IMPORTED_MODULE_0__[\"b\"]; });\n\n\n\n//# sourceURL=webpack:///./assets/vue/tabs.vue?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./node_modules/vue-loader/lib/index.js?!./assets/vue/tab.vue?vue&type=script&lang=js&":
 | 
			
		||||
/*!*******************************************************************************************************!*\
 | 
			
		||||
  !*** ./node_modules/vue-loader/lib??vue-loader-options!./assets/vue/tab.vue?vue&type=script&lang=js& ***!
 | 
			
		||||
  \*******************************************************************************************************/
 | 
			
		||||
/*! exports provided: default */
 | 
			
		||||
/*! exports used: default */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("//\n//\n//\n//\n//\n//\n//\n\n/* harmony default export */ __webpack_exports__[\"a\"] = ({\n    props: {\n        value: { default: undefined },\n    },\n\n    methods: {\n        select() {\n            this.$parent.selectTab(this);\n        },\n\n        onclick(event) {\n            this.select();\n            /*if(event.target.href != document.location)\n                window.history.pushState(\n                    { url: event.target.href },\n                    event.target.innerText + ' - ' + document.title,\n                    event.target.href\n                ) */\n        }\n    }\n});\n\n\n//# sourceURL=webpack:///./assets/vue/tab.vue?./node_modules/vue-loader/lib??vue-loader-options");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./node_modules/vue-loader/lib/index.js?!./assets/vue/tabs.vue?vue&type=script&lang=js&":
 | 
			
		||||
/*!********************************************************************************************************!*\
 | 
			
		||||
  !*** ./node_modules/vue-loader/lib??vue-loader-options!./assets/vue/tabs.vue?vue&type=script&lang=js& ***!
 | 
			
		||||
  \********************************************************************************************************/
 | 
			
		||||
/*! exports provided: default */
 | 
			
		||||
/*! exports used: default */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n\n/* harmony default export */ __webpack_exports__[\"a\"] = ({\n    props: {\n        default: { default: null },\n    },\n\n    data() {\n        return {\n            value: this.default,\n        }\n    },\n\n    computed: {\n        tab() {\n            const vnode = this.$slots.default && this.$slots.default.find(\n                elm => elm.child && elm.child.value == this.value\n            );\n            return vnode && vnode.child;\n        }\n    },\n\n    methods: {\n        selectTab(tab) {\n            const value = tab.value;\n            if(this.value === value)\n                return;\n\n            this.value = value;\n            this.$emit('select', {target: this, value: value, tab: tab});\n        },\n    },\n});\n\n\n//# sourceURL=webpack:///./assets/vue/tabs.vue?./node_modules/vue-loader/lib??vue-loader-options");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/vue-loader/lib/index.js?!./assets/vue/tab.vue?vue&type=template&id=65401e0e&":
 | 
			
		||||
/*!*****************************************************************************************************************************************************************************************!*\
 | 
			
		||||
  !*** ./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib??vue-loader-options!./assets/vue/tab.vue?vue&type=template&id=65401e0e& ***!
 | 
			
		||||
  \*****************************************************************************************************************************************************************************************/
 | 
			
		||||
/*! exports provided: render, staticRenderFns */
 | 
			
		||||
/*! exports used: render, staticRenderFns */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"a\", function() { return render; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"b\", function() { return staticRenderFns; });\nvar render = function() {\n  var _vm = this\n  var _h = _vm.$createElement\n  var _c = _vm._self._c || _h\n  return _c(\n    \"li\",\n    {\n      class: { \"is-active\": _vm.$parent.value == _vm.value },\n      on: {\n        click: function($event) {\n          $event.preventDefault()\n          return _vm.onclick($event)\n        }\n      }\n    },\n    [_vm._t(\"default\")],\n    2\n  )\n}\nvar staticRenderFns = []\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./assets/vue/tab.vue?./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib??vue-loader-options");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/vue-loader/lib/index.js?!./assets/vue/tabs.vue?vue&type=template&id=466f44d5&":
 | 
			
		||||
/*!******************************************************************************************************************************************************************************************!*\
 | 
			
		||||
  !*** ./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib??vue-loader-options!./assets/vue/tabs.vue?vue&type=template&id=466f44d5& ***!
 | 
			
		||||
  \******************************************************************************************************************************************************************************************/
 | 
			
		||||
/*! exports provided: render, staticRenderFns */
 | 
			
		||||
/*! exports used: render, staticRenderFns */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"a\", function() { return render; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"b\", function() { return staticRenderFns; });\nvar render = function() {\n  var _vm = this\n  var _h = _vm.$createElement\n  var _c = _vm._self._c || _h\n  return _c(\n    \"div\",\n    [\n      _c(\"div\", { staticClass: \"tabs is-centered\" }, [\n        _c(\"ul\", [_vm._t(\"tabs\", null, { value: _vm.value })], 2)\n      ]),\n      _vm._v(\" \"),\n      _vm._t(\"default\", null, { value: _vm.value })\n    ],\n    2\n  )\n}\nvar staticRenderFns = []\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./assets/vue/tabs.vue?./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib??vue-loader-options");
 | 
			
		||||
 | 
			
		||||
/***/ })
 | 
			
		||||
 | 
			
		||||
/******/ });
 | 
			
		||||
							
								
								
									
										89
									
								
								aircox/static/aircox/vendor.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								aircox/static/aircox/vendor.js
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										84
									
								
								aircox/templates/aircox/base.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								aircox/templates/aircox/base.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,84 @@
 | 
			
		||||
{% load static i18n thumbnail aircox %}
 | 
			
		||||
{% comment %}
 | 
			
		||||
Context:
 | 
			
		||||
- site: current website
 | 
			
		||||
{% endcomment %}
 | 
			
		||||
<html>
 | 
			
		||||
    <head>
 | 
			
		||||
        <meta charset="utf-8">
 | 
			
		||||
        <meta name="application-name" content="aircox">
 | 
			
		||||
        <meta name="description" content="{{ site.description }}">
 | 
			
		||||
        <meta name="keywords" content="{{ site.tags }}">
 | 
			
		||||
        <link rel="icon" href="{% thumbnail site.favicon 32x32 crop %}" />
 | 
			
		||||
 | 
			
		||||
        {% block assets %}
 | 
			
		||||
        <link rel="stylesheet" type="text/css" href="{% static "aircox/main.css" %}"/>
 | 
			
		||||
        <script src="{% static "aircox/main.js" %}"></script>
 | 
			
		||||
        <script src="{% static "aircox/vendor.js" %}"></script>
 | 
			
		||||
        {% endblock %}
 | 
			
		||||
 | 
			
		||||
        <title>
 | 
			
		||||
            {% block head_title %}{{ site.title }}{% endblock %}
 | 
			
		||||
        </title>
 | 
			
		||||
 | 
			
		||||
        {% block head_extra %}{% endblock %}
 | 
			
		||||
    </head>
 | 
			
		||||
    <body>
 | 
			
		||||
        <div id="app">
 | 
			
		||||
            <nav class="navbar has-shadow" role="navigation" aria-label="main navigation">
 | 
			
		||||
                <div class="container">
 | 
			
		||||
                    <div class="navbar-brand">
 | 
			
		||||
                        <a href="/" title="{% trans "Home" %}" class="navbar-item">
 | 
			
		||||
                            <img src="{{ station.logo.url }}" class="logo"/>
 | 
			
		||||
                        </a>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="navbar-menu">
 | 
			
		||||
                        <div class="navbar-start">
 | 
			
		||||
                            {% block top-nav %}
 | 
			
		||||
                            {% nav_items "top" css_class="navbar-item" active_class="is-active" as items %}
 | 
			
		||||
                            {% for item, render in items %}
 | 
			
		||||
                            {{ render }}
 | 
			
		||||
                            {% endfor %}
 | 
			
		||||
                            {% endblock %}
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
            </nav>
 | 
			
		||||
 | 
			
		||||
            <div class="container">
 | 
			
		||||
                <div class="columns is-desktop">
 | 
			
		||||
                    <main class="column page">
 | 
			
		||||
                        <header class="header">
 | 
			
		||||
                            {% block header %}
 | 
			
		||||
                            <h1 class="title is-1">{% block title %}{% endblock %}</h1>
 | 
			
		||||
 | 
			
		||||
                            {% if parent %}
 | 
			
		||||
                            <h4 class="subtitle is-size-3">
 | 
			
		||||
                                <a href="{{ parent.get_absolute_url }}">
 | 
			
		||||
                                    ❬ {{ parent.title }}</a></li>
 | 
			
		||||
                            </h4>
 | 
			
		||||
                            {% endif %}
 | 
			
		||||
                            {% endblock %}
 | 
			
		||||
                        </header>
 | 
			
		||||
 | 
			
		||||
                        {% block main %}{% endblock main %}
 | 
			
		||||
                    </main>
 | 
			
		||||
                    {% if show_side_nav %}
 | 
			
		||||
                    <aside class="column is-one-third-desktop">
 | 
			
		||||
                        {% block cover %}
 | 
			
		||||
                        {% if cover is not None %}
 | 
			
		||||
                        <img class="cover" src="{{ cover.url }}" class="cover"/>
 | 
			
		||||
                        {% endif %}
 | 
			
		||||
                        {% endblock %}
 | 
			
		||||
 | 
			
		||||
                        {% block side_nav %}
 | 
			
		||||
                        {% endblock %}
 | 
			
		||||
                    </aside>
 | 
			
		||||
                    {% endif %}
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </body>
 | 
			
		||||
</html>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										59
									
								
								aircox/templates/aircox/diffusion_item.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								aircox/templates/aircox/diffusion_item.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,59 @@
 | 
			
		||||
{% load i18n easy_thumbnails_tags aircox %}
 | 
			
		||||
{% comment %}
 | 
			
		||||
Context variables:
 | 
			
		||||
- object: the actual diffusion
 | 
			
		||||
- page: current parent page in which item is rendered
 | 
			
		||||
- hide_schedule: if True, do not display start time
 | 
			
		||||
- hide_headline: if True, do not display headline
 | 
			
		||||
{% endcomment %}
 | 
			
		||||
 | 
			
		||||
{% with object.episode as episode %}
 | 
			
		||||
{% with episode.program as program %}
 | 
			
		||||
<article class="media">
 | 
			
		||||
    <div class="media-left">
 | 
			
		||||
        <img src="{% thumbnail episode.cover 128x128 crop=scale %}"
 | 
			
		||||
            class="small-cover">
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="media-content">
 | 
			
		||||
        <h5 class="subtitle is-size-5">
 | 
			
		||||
            {% if episode.is_published %}
 | 
			
		||||
            <a href="{{ episode.get_absolute_url }}">{{ episode.title }}</a>
 | 
			
		||||
            {% endif %}
 | 
			
		||||
        </h5>
 | 
			
		||||
 | 
			
		||||
        <div class="">
 | 
			
		||||
            {% if not page or program != page %}
 | 
			
		||||
            {% if program.is_published %}
 | 
			
		||||
            <a href="{{ program.get_absolute_url }}" class="has-text-grey-dark">
 | 
			
		||||
                {{ program.title }}</a>
 | 
			
		||||
            {% else %}{{ program.title }}
 | 
			
		||||
            {% endif %}
 | 
			
		||||
            {% if not hide_schedule %} — {% endif %}
 | 
			
		||||
            {% endif %}
 | 
			
		||||
 | 
			
		||||
            {% if not hide_schedule %}
 | 
			
		||||
            <time datetime="{{ object.start|date:"c" }}" title="{{ object.start }}"
 | 
			
		||||
                  class="has-text-weight-light is-size-6">
 | 
			
		||||
                  {{ object.start|date:"d M, H:i" }}
 | 
			
		||||
            </time>
 | 
			
		||||
            {% endif %}
 | 
			
		||||
 | 
			
		||||
            {% if object.initial %}
 | 
			
		||||
            {% with object.initial.date as date %}
 | 
			
		||||
            <span class="tag is-info" title="{% blocktrans %}Rerun of {{ date }}{% endblocktrans %}">
 | 
			
		||||
                {% trans "rerun" %}
 | 
			
		||||
            </span>
 | 
			
		||||
            {% endwith %}
 | 
			
		||||
            {% endif %}
 | 
			
		||||
            </span>
 | 
			
		||||
        </div>
 | 
			
		||||
        {% if not hide_headline %}
 | 
			
		||||
        <div class="content">
 | 
			
		||||
          {{ episode.headline }}
 | 
			
		||||
        </div>
 | 
			
		||||
        {% endif %}
 | 
			
		||||
    </div>
 | 
			
		||||
</article>
 | 
			
		||||
{% endwith %}
 | 
			
		||||
{% endwith %}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										51
									
								
								aircox/templates/aircox/diffusion_list.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								aircox/templates/aircox/diffusion_list.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,51 @@
 | 
			
		||||
{% extends "aircox/page.html" %}
 | 
			
		||||
{% load i18n aircox %}
 | 
			
		||||
 | 
			
		||||
{% block title %}
 | 
			
		||||
{% if program %}
 | 
			
		||||
    {% with program.name as program %}
 | 
			
		||||
    {% blocktrans %}Diffusions of {{ program }}{% endblocktrans %}
 | 
			
		||||
    {% endwith %}
 | 
			
		||||
{% else %}
 | 
			
		||||
    {% trans "All diffusions" %}
 | 
			
		||||
    {% endif %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
{% block content %}
 | 
			
		||||
<section>
 | 
			
		||||
    {% for object in object_list %}
 | 
			
		||||
    {% include "aircox/diffusion_item.html" %}
 | 
			
		||||
    {% endfor %}
 | 
			
		||||
</section>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
{% if is_paginated %}
 | 
			
		||||
<nav class="pagination is-centered" role="pagination" aria-label="{% trans "pagination" %}">
 | 
			
		||||
    {% if page_obj.has_previous %}
 | 
			
		||||
    <a href="?page={{ page_obj.previous_page_number }}" class="pagination-previous">
 | 
			
		||||
    {% else %}
 | 
			
		||||
    <a class="pagination-previous" disabled>
 | 
			
		||||
    {% endif %}
 | 
			
		||||
        {% trans "Previous" %}</a>
 | 
			
		||||
 | 
			
		||||
    {% if page_obj.has_next %}
 | 
			
		||||
    <a href="?page={{ page_obj.next_page_number }}" class="pagination-next">
 | 
			
		||||
    {% else %}
 | 
			
		||||
    <a class="pagination-next" disabled>
 | 
			
		||||
    {% endif %}
 | 
			
		||||
        {% trans "Next" %}</a>
 | 
			
		||||
 | 
			
		||||
    <ul class="pagination-list">
 | 
			
		||||
    {% for i in paginator.page_range %}
 | 
			
		||||
        <li>
 | 
			
		||||
            <a class="pagination-link {% if page_obj.number == i %}is-current{% endif %}"
 | 
			
		||||
               href="?page={{ i }}">{{ i }}</a>
 | 
			
		||||
        </li>
 | 
			
		||||
    {% endfor %}
 | 
			
		||||
    </ul>
 | 
			
		||||
</nav>
 | 
			
		||||
{% endif %}
 | 
			
		||||
</section>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										56
									
								
								aircox/templates/aircox/diffusion_timetable.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								aircox/templates/aircox/diffusion_timetable.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,56 @@
 | 
			
		||||
{% extends "aircox/page.html" %}
 | 
			
		||||
{% load i18n aircox %}
 | 
			
		||||
 | 
			
		||||
{% block title %}{% trans "Timetable" %}{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block main %}
 | 
			
		||||
{{ block.super }}
 | 
			
		||||
 | 
			
		||||
<section class="section">
 | 
			
		||||
    <h3 class="subtitle size-3">
 | 
			
		||||
        {% blocktrans %}From <b>{{ start }}</b> to <b>{{ end }}</b>{% endblocktrans %}
 | 
			
		||||
    </h3>
 | 
			
		||||
 | 
			
		||||
    {% unique_id "timetable" as timetable_id %}
 | 
			
		||||
    <a-tabs default="{{ date }}">
 | 
			
		||||
        <template v-slot:tabs="scope" noscript="hidden">
 | 
			
		||||
            <li><a href="{% url "timetable" date=prev_date %}"><</a></li>
 | 
			
		||||
 | 
			
		||||
            {% for day in by_date.keys %}
 | 
			
		||||
            <a-tab value="{{ day }}">
 | 
			
		||||
                <a href="{% url "timetable" date=day %}">
 | 
			
		||||
                    {{ day|date:"D. d" }}
 | 
			
		||||
                </a>
 | 
			
		||||
            </a-tab>
 | 
			
		||||
            {% endfor %}
 | 
			
		||||
 | 
			
		||||
            <li>
 | 
			
		||||
                <a href="{% url "timetable" date=next_date %}">></a>
 | 
			
		||||
            </li>
 | 
			
		||||
        </template>
 | 
			
		||||
 | 
			
		||||
        {% with True as hide_schedule %}
 | 
			
		||||
        <template v-slot:default="{value}">
 | 
			
		||||
            {% for day, diffusions in by_date.items %}
 | 
			
		||||
            <noscript><h4 class="subtitle is-4">{{ day|date:"l d F Y" }}</h4></noscript>
 | 
			
		||||
            <div id="{{timetable_id}}-{{ day|date:"Y-m-d" }}" v-if="value == '{{ day }}'">
 | 
			
		||||
                {% for object in diffusions %}
 | 
			
		||||
                <div class="columns">
 | 
			
		||||
                    <div class="column is-one-fifth has-text-right">
 | 
			
		||||
                        <time datetime="{{ object.start|date:"c" }}">
 | 
			
		||||
                            {{ object.start|date:"H:i" }} - {{ object.end|date:"H:i" }}
 | 
			
		||||
                        </time>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="column">
 | 
			
		||||
                        {% include "aircox/diffusion_item.html" %}
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                {% endfor %}
 | 
			
		||||
            </div>
 | 
			
		||||
            {% endfor %}
 | 
			
		||||
        </template>
 | 
			
		||||
        {% endwith %}
 | 
			
		||||
    </a-tabs>
 | 
			
		||||
</section>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										14
									
								
								aircox/templates/aircox/episode_detail.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								aircox/templates/aircox/episode_detail.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
			
		||||
{% extends "aircox/program_base.html" %}
 | 
			
		||||
{% load i18n %}
 | 
			
		||||
 | 
			
		||||
{% block main %}
 | 
			
		||||
{{ block.super }}
 | 
			
		||||
 | 
			
		||||
{% if podcasts %}
 | 
			
		||||
{% for object in podcasts %}
 | 
			
		||||
{% include "aircox/podcast_item.html" %}
 | 
			
		||||
{% endfor %}
 | 
			
		||||
{% endif %}
 | 
			
		||||
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										19
									
								
								aircox/templates/aircox/log_item.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								aircox/templates/aircox/log_item.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
			
		||||
{% load i18n %}
 | 
			
		||||
 | 
			
		||||
{% with object.track as track %}
 | 
			
		||||
<span class="has-text-info is-size-5">♬</span>
 | 
			
		||||
<span>{{ track.title }}</span>
 | 
			
		||||
{% with track.artist as artist %}
 | 
			
		||||
{% with track.info as info %}
 | 
			
		||||
<span class="has-text-grey-dark has-text-weight-light">
 | 
			
		||||
    {% blocktrans %}
 | 
			
		||||
    by {{ artist }}
 | 
			
		||||
    {% endblocktrans %}
 | 
			
		||||
    {% if info %}
 | 
			
		||||
    ({% blocktrans %}<i>{{ info }}</i>{% endblocktrans %})
 | 
			
		||||
    {% endif %}
 | 
			
		||||
</span>
 | 
			
		||||
{% endwith %}
 | 
			
		||||
{% endwith %}
 | 
			
		||||
{% endwith %}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										57
									
								
								aircox/templates/aircox/log_list.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								aircox/templates/aircox/log_list.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,57 @@
 | 
			
		||||
{% extends "aircox/page.html" %}
 | 
			
		||||
{% load i18n aircox %}
 | 
			
		||||
 | 
			
		||||
{% block title %}
 | 
			
		||||
{% trans "Logs" %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
{% block main %}
 | 
			
		||||
{{ block.super }}
 | 
			
		||||
 | 
			
		||||
<section class="section">
 | 
			
		||||
    {% if dates %}
 | 
			
		||||
    <nav class="tabs is-centered" aria-label="{% trans "Other days' logs" %}">
 | 
			
		||||
        <ul>
 | 
			
		||||
        {% for day in dates %}
 | 
			
		||||
            <li {% if day == date %}class="is-active"{% endif %}>
 | 
			
		||||
                <a href="{% url "logs" date=day %}">
 | 
			
		||||
                    {{ day|date:"d b" }}
 | 
			
		||||
                </a>
 | 
			
		||||
            </li>
 | 
			
		||||
 | 
			
		||||
        {% if forloop.last and day > min_date %}
 | 
			
		||||
            <li>...</li>
 | 
			
		||||
        {% endif %}
 | 
			
		||||
        {% endfor %}
 | 
			
		||||
        </ul>
 | 
			
		||||
    </nav>
 | 
			
		||||
    {% endif %}
 | 
			
		||||
 | 
			
		||||
    {# <h4 class="subtitle size-4">{{ date }}</h4> #}
 | 
			
		||||
    {% with True as hide_schedule %}
 | 
			
		||||
    <table class="table is-striped is-hoverable is-fullwidth">
 | 
			
		||||
        {% for object in object_list reversed %}
 | 
			
		||||
        <tr>
 | 
			
		||||
        {% if object|is_diffusion %}
 | 
			
		||||
            <td>
 | 
			
		||||
                <time datetime="{{ object.start }}" title="{{ object.start }}">
 | 
			
		||||
                    {{ object.start|date:"H:i" }} - {{ object.end|date:"H:i" }}
 | 
			
		||||
                </time>
 | 
			
		||||
            </td>
 | 
			
		||||
            <td>{% include "aircox/diffusion_item.html" %}</td>
 | 
			
		||||
        {% else %}
 | 
			
		||||
            <td>
 | 
			
		||||
                <time datetime="{{ object.date }}" title="{{ object.date }}">
 | 
			
		||||
                    {{ object.date|date:"H:i" }}
 | 
			
		||||
                </time>
 | 
			
		||||
            </td>
 | 
			
		||||
            <td>{% include "aircox/log_item.html" %}</td>
 | 
			
		||||
        {% endif %}
 | 
			
		||||
        </tr>
 | 
			
		||||
        {% endfor %}
 | 
			
		||||
    </table>
 | 
			
		||||
    {% endwith %}
 | 
			
		||||
</section>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										30
									
								
								aircox/templates/aircox/page.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								aircox/templates/aircox/page.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
			
		||||
{% extends "aircox/base.html" %}
 | 
			
		||||
{% load static i18n thumbnail %}
 | 
			
		||||
{% comment %}
 | 
			
		||||
Context:
 | 
			
		||||
- cover: cover image
 | 
			
		||||
- title: title
 | 
			
		||||
- page: page
 | 
			
		||||
{% endcomment %}
 | 
			
		||||
 | 
			
		||||
{% block head_title %}
 | 
			
		||||
    {% block title %}{{ title }}{% endblock %}
 | 
			
		||||
    {% if title %} — {% endif %}
 | 
			
		||||
    {{ site.title }}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
{% block main %}
 | 
			
		||||
{% block headline %}
 | 
			
		||||
{% if page and page.headline %}
 | 
			
		||||
<p class="headline">{{ page.headline }}</p>
 | 
			
		||||
{% endif %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block content %}
 | 
			
		||||
{{ page.content|default_if_none:''|safe }}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										8
									
								
								aircox/templates/aircox/podcast_item.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								aircox/templates/aircox/podcast_item.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
<div class="podcast">
 | 
			
		||||
    {% if object.embed %}
 | 
			
		||||
    {{ object.embed }}
 | 
			
		||||
    {% else %}
 | 
			
		||||
    <audio src="{{ object.url }}" controls>
 | 
			
		||||
    {% endif %}
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										29
									
								
								aircox/templates/aircox/program_base.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								aircox/templates/aircox/program_base.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
			
		||||
{% extends "aircox/page.html" %}
 | 
			
		||||
{% load i18n %}
 | 
			
		||||
 | 
			
		||||
{% block side_nav %}
 | 
			
		||||
{{ block.super }}
 | 
			
		||||
 | 
			
		||||
{% if diffusions %}
 | 
			
		||||
<section>
 | 
			
		||||
    <h4 class="subtitle is-size-4">{% trans "Last shows" %}</h4>
 | 
			
		||||
 | 
			
		||||
    {% for object in diffusions %}
 | 
			
		||||
    {% include "aircox/diffusion_item.html" %}
 | 
			
		||||
    {% endfor %}
 | 
			
		||||
 | 
			
		||||
    <br>
 | 
			
		||||
    <nav class="pagination is-centered">
 | 
			
		||||
        <ul class="pagination-list">
 | 
			
		||||
            <li>
 | 
			
		||||
                <a href="{% url "diffusion-list" program_slug=page.slug %}"
 | 
			
		||||
                    class="pagination-link"
 | 
			
		||||
                    aria-label="{% trans "Show all diffusions" %}">
 | 
			
		||||
                    {% trans "All diffusions" %}
 | 
			
		||||
                </a>
 | 
			
		||||
            </li>
 | 
			
		||||
        </ul>
 | 
			
		||||
</section>
 | 
			
		||||
{% endif %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										8
									
								
								aircox/templates/aircox/program_detail.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								aircox/templates/aircox/program_detail.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
{% extends "aircox/program_base.html" %}
 | 
			
		||||
{% load i18n %}
 | 
			
		||||
 | 
			
		||||
{% block header %}
 | 
			
		||||
{{ block.super }}
 | 
			
		||||
{% include "aircox/program_header.html" %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										25
									
								
								aircox/templates/aircox/program_header.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								aircox/templates/aircox/program_header.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,25 @@
 | 
			
		||||
{% load i18n %}
 | 
			
		||||
<section class="is-size-5">
 | 
			
		||||
    {% for schedule in program.schedule_set.all %}
 | 
			
		||||
    <p>
 | 
			
		||||
        {{ schedule.get_frequency_verbose }}
 | 
			
		||||
        {% with schedule.start|date:"H:i" as start %}
 | 
			
		||||
        {% with schedule.end|date:"H:i" as end %}
 | 
			
		||||
        <time datetime="{{ start }}">{{ start }}</time>
 | 
			
		||||
        —
 | 
			
		||||
        <time datetime="{{ end }}">{{ end }}</time>
 | 
			
		||||
        {% endwith %}
 | 
			
		||||
        {% endwith %}
 | 
			
		||||
        <small>
 | 
			
		||||
            {% if schedule.initial %}
 | 
			
		||||
            {% with schedule.initial.date as date %}
 | 
			
		||||
            <span title="{% blocktrans %}Rerun of {{ date }}{% endblocktrans %}">
 | 
			
		||||
                ({% trans "rerun" %})
 | 
			
		||||
            </span>
 | 
			
		||||
            {% endwith %}
 | 
			
		||||
            {% endif %}
 | 
			
		||||
        </small>
 | 
			
		||||
    </p>
 | 
			
		||||
    {% endfor %}
 | 
			
		||||
</section>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										28
									
								
								aircox/templatetags/aircox.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								aircox/templatetags/aircox.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
			
		||||
import random
 | 
			
		||||
 | 
			
		||||
from django import template
 | 
			
		||||
 | 
			
		||||
from aircox.models import Page, Diffusion
 | 
			
		||||
 | 
			
		||||
random.seed()
 | 
			
		||||
register = template.Library()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@register.simple_tag(name='unique_id')
 | 
			
		||||
def do_unique_id(prefix=''):
 | 
			
		||||
    value = str(random.random()).replace('.', '')
 | 
			
		||||
    return prefix + '_' + value if prefix else value
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@register.filter(name='is_diffusion')
 | 
			
		||||
def do_is_diffusion(obj):
 | 
			
		||||
    return isinstance(obj, Diffusion)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@register.simple_tag(name='nav_items', takes_context=True)
 | 
			
		||||
def do_nav_items(context, menu, **kwargs):
 | 
			
		||||
    station, request = context['station'], context['request']
 | 
			
		||||
    return [(item, item.render(request, **kwargs))
 | 
			
		||||
            for item in station.navitem_set.filter(menu=menu)]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,10 +1,40 @@
 | 
			
		||||
from django.urls import path
 | 
			
		||||
from django.urls import path, register_converter
 | 
			
		||||
from django.utils.translation import ugettext_lazy as _
 | 
			
		||||
 | 
			
		||||
from . import views
 | 
			
		||||
from .converters import PagePathConverter, DateConverter, WeekConverter
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
register_converter(PagePathConverter, 'page_path')
 | 
			
		||||
register_converter(DateConverter, 'date')
 | 
			
		||||
register_converter(WeekConverter, 'week')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#urls = [
 | 
			
		||||
#    path('on_air', views.on_air, name='aircox.on_air'),
 | 
			
		||||
#    path('monitor', views.Monitor.as_view(), name='aircox.monitor'),
 | 
			
		||||
#    path('stats', views.StatisticsView.as_view(), name='aircox.stats'),
 | 
			
		||||
#]
 | 
			
		||||
 | 
			
		||||
import aircox.views as views
 | 
			
		||||
 | 
			
		||||
urls = [
 | 
			
		||||
    path('on_air', views.on_air, name='aircox.on_air'),
 | 
			
		||||
    path('monitor', views.Monitor.as_view(), name='aircox.monitor'),
 | 
			
		||||
    path('stats', views.StatisticsView.as_view(), name='aircox.stats'),
 | 
			
		||||
    path(_('programs/<slug:slug>/'),
 | 
			
		||||
         views.ProgramDetailView.as_view(), name='program-detail'),
 | 
			
		||||
    path(_('programs/<slug:program_slug>/episodes/'),
 | 
			
		||||
         views.DiffusionListView.as_view(), name='diffusion-list'),
 | 
			
		||||
 | 
			
		||||
    path(_('episodes/'),
 | 
			
		||||
         views.DiffusionListView.as_view(), name='diffusion-list'),
 | 
			
		||||
    path(_('episodes/week/'),
 | 
			
		||||
         views.TimetableView.as_view(), name='timetable'),
 | 
			
		||||
    path(_('episodes/week/<week:date>/'),
 | 
			
		||||
         views.TimetableView.as_view(), name='timetable'),
 | 
			
		||||
    path(_('episodes/<slug:slug>/'),
 | 
			
		||||
         views.EpisodeDetailView.as_view(), name='episode-detail'),
 | 
			
		||||
 | 
			
		||||
    path(_('logs/'), views.LogListView.as_view(), name='logs'),
 | 
			
		||||
    path(_('logs/<date:date>/'), views.LogListView.as_view(), name='logs'),
 | 
			
		||||
    # path('<page_path:path>', views.route_page, name='page'),
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -2,6 +2,23 @@ import datetime
 | 
			
		||||
import django.utils.timezone as tz
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ['Redirect', 'redirect', 'date_range', 'cast_date',
 | 
			
		||||
           'date_or_default', 'to_timedelta', 'seconds_to_time']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Redirect(Exception):
 | 
			
		||||
    """ Redirect exception -- see `redirect()`. """
 | 
			
		||||
    def __init__(self, url):
 | 
			
		||||
        self.url = url
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def redirect(url):
 | 
			
		||||
    """
 | 
			
		||||
    Raise a Redirect exception in order to response a redirection to client.
 | 
			
		||||
    AircoxMiddleware must be enabled. """
 | 
			
		||||
    raise Redirect(url)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def date_range(date, delta=None, **delta_kwargs):
 | 
			
		||||
    """
 | 
			
		||||
    Return a range of provided date such as `[date-delta, date+delta]`.
 | 
			
		||||
@ -53,6 +70,11 @@ def to_timedelta(time):
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def to_seconds(time):
 | 
			
		||||
    """ Return total seconds for provided time """
 | 
			
		||||
    return 3600 * time.hour + 60 * time.minute + time.second
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def seconds_to_time(seconds):
 | 
			
		||||
    """
 | 
			
		||||
    Seconds to datetime.time
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,7 @@ import random
 | 
			
		||||
 | 
			
		||||
from django import template
 | 
			
		||||
 | 
			
		||||
from aircox import models as aircox
 | 
			
		||||
from aircox.models import Page, 
 | 
			
		||||
from aircox_web.models import Page
 | 
			
		||||
 | 
			
		||||
random.seed()
 | 
			
		||||
@ -12,11 +12,11 @@ register = template.Library()
 | 
			
		||||
@register.simple_tag(name='diffusion_page')
 | 
			
		||||
def do_diffusion_page(diffusion):
 | 
			
		||||
    """ Return page for diffusion. """
 | 
			
		||||
    diff = diffusion.initial if diffusion.initial is not None else diffusion
 | 
			
		||||
    for obj in (diff, diffusion.program):
 | 
			
		||||
        page = getattr(obj, 'page', None)
 | 
			
		||||
        if page is not None and page.status == Page.STATUS.published:
 | 
			
		||||
            return page
 | 
			
		||||
    episode = diffusion.episode
 | 
			
		||||
    if episode.is_publihed:
 | 
			
		||||
        return diff.episode
 | 
			
		||||
    program = episode.program
 | 
			
		||||
    return program if program.is_published else None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@register.simple_tag(name='unique_id')
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										5
									
								
								assets/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								assets/index.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
import './js';
 | 
			
		||||
import './styles.scss';
 | 
			
		||||
import './noscript.scss';
 | 
			
		||||
import './vue';
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										14
									
								
								assets/js/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								assets/js/index.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
			
		||||
import Vue from 'vue';
 | 
			
		||||
import Buefy from 'buefy';
 | 
			
		||||
 | 
			
		||||
Vue.use(Buefy);
 | 
			
		||||
 | 
			
		||||
window.addEventListener('load', () => {
 | 
			
		||||
    var app = new Vue({
 | 
			
		||||
      el: '#app',
 | 
			
		||||
      delimiters: [ '[[', ']]' ],
 | 
			
		||||
    })
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										6
									
								
								assets/noscript.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								assets/noscript.scss
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
 | 
			
		||||
/**[noscript="hidden"] {
 | 
			
		||||
    display: none;
 | 
			
		||||
}*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										75
									
								
								assets/styles.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								assets/styles.scss
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,75 @@
 | 
			
		||||
@charset "utf-8";
 | 
			
		||||
@import "~bulma/sass/utilities/_all.sass";
 | 
			
		||||
 | 
			
		||||
$body-background-color: $light;
 | 
			
		||||
 | 
			
		||||
@import "~bulma/bulma";
 | 
			
		||||
 | 
			
		||||
.navbar {
 | 
			
		||||
    margin-bottom: 1em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.navbar.has-shadow {
 | 
			
		||||
    box-shadow: 0em 0.05em 0.5em rgba(0,0,0,0.1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.navbar-brand img {
 | 
			
		||||
    min-height: 6em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.navbar-menu .navbar-item:not(:last-child) {
 | 
			
		||||
    border-right: 1px $grey solid;
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** page **/
 | 
			
		||||
.page {
 | 
			
		||||
    & > .cover {
 | 
			
		||||
        float: right;
 | 
			
		||||
        max-width: 45%;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    & > .header {
 | 
			
		||||
        margin-bottom: 1.5em;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .headline {
 | 
			
		||||
        font-size: 1.4em;
 | 
			
		||||
        padding: 0.2em 0em;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    p {
 | 
			
		||||
        padding: 0.4em 0em;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.cover {
 | 
			
		||||
    margin: 1em 0em;
 | 
			
		||||
    border: 0.2em black solid;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.small-cover {
 | 
			
		||||
    width: 10em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
aside {
 | 
			
		||||
    .small-cover {
 | 
			
		||||
        width: 4em;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .media .subtitle {
 | 
			
		||||
        font-size: 1em;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .media .content {
 | 
			
		||||
        display: none;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										28
									
								
								assets/vue/deck.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								assets/vue/deck.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div>
 | 
			
		||||
        <a-tabs class="tabs" @select="value = $event.value;">
 | 
			
		||||
            <template v-slot:default><slot name="tabs" :value="value"/></template>
 | 
			
		||||
        </a-tabs>
 | 
			
		||||
 | 
			
		||||
        <slot :value="value"></slot>
 | 
			
		||||
    </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import Tabs from './tabs.vue';
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
    props: ['default'],
 | 
			
		||||
 | 
			
		||||
    data() {
 | 
			
		||||
        return {
 | 
			
		||||
            value: this.default,
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    components: {
 | 
			
		||||
        'a-tabs': Tabs,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
							
								
								
									
										11
									
								
								assets/vue/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								assets/vue/index.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
			
		||||
import Vue from 'vue';
 | 
			
		||||
 | 
			
		||||
import Tab from './tab.vue';
 | 
			
		||||
import Tabs from './tabs.vue';
 | 
			
		||||
 | 
			
		||||
Vue.component('a-tab', Tab);
 | 
			
		||||
Vue.component('a-tabs', Tabs);
 | 
			
		||||
 | 
			
		||||
export {Tab, Tabs};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										31
									
								
								assets/vue/tab.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								assets/vue/tab.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <li @click.prevent="onclick"
 | 
			
		||||
        :class="{'is-active': $parent.value == value}">
 | 
			
		||||
        <slot></slot>
 | 
			
		||||
    </li>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
export default {
 | 
			
		||||
    props: {
 | 
			
		||||
        value: { default: undefined },
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    methods: {
 | 
			
		||||
        select() {
 | 
			
		||||
            this.$parent.selectTab(this);
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        onclick(event) {
 | 
			
		||||
            this.select();
 | 
			
		||||
            /*if(event.target.href != document.location)
 | 
			
		||||
                window.history.pushState(
 | 
			
		||||
                    { url: event.target.href },
 | 
			
		||||
                    event.target.innerText + ' - ' + document.title,
 | 
			
		||||
                    event.target.href
 | 
			
		||||
                ) */
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										45
									
								
								assets/vue/tabs.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								assets/vue/tabs.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,45 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div>
 | 
			
		||||
        <div class="tabs is-centered">
 | 
			
		||||
            <ul><slot name="tabs" :value="value" /></ul>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <slot :value="value"/>
 | 
			
		||||
    </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
export default {
 | 
			
		||||
    props: {
 | 
			
		||||
        default: { default: null },
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    data() {
 | 
			
		||||
        return {
 | 
			
		||||
            value: this.default,
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    computed: {
 | 
			
		||||
        tab() {
 | 
			
		||||
            const vnode = this.$slots.default && this.$slots.default.find(
 | 
			
		||||
                elm => elm.child && elm.child.value == this.value
 | 
			
		||||
            );
 | 
			
		||||
            return vnode && vnode.child;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    methods: {
 | 
			
		||||
        selectTab(tab) {
 | 
			
		||||
            const value = tab.value;
 | 
			
		||||
            if(this.value === value)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            this.value = value;
 | 
			
		||||
            this.$emit('select', {target: this, value: value, tab: tab});
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -13,12 +13,13 @@ Including another URLconf
 | 
			
		||||
    1. Add an import:  from blog import urls as blog_urls
 | 
			
		||||
    2. Add a URL to urlpatterns:  url(r'^blog/', include(blog_urls))
 | 
			
		||||
"""
 | 
			
		||||
# from django.conf.urls.i18n import i18n_patterns
 | 
			
		||||
from django.conf import settings
 | 
			
		||||
from django.urls import include, path, re_path
 | 
			
		||||
from django.contrib import admin
 | 
			
		||||
 | 
			
		||||
import aircox.urls
 | 
			
		||||
# import aircox_web.urls
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
try:
 | 
			
		||||
    urlpatterns = [
 | 
			
		||||
@ -35,7 +36,6 @@ try:
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    urlpatterns.append(path('filer/', include('filer.urls')))
 | 
			
		||||
    # urlpatterns += aircox_web.urls.urlpatterns
 | 
			
		||||
 | 
			
		||||
except Exception as e:
 | 
			
		||||
    import traceback
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										29
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "aircox-web-assets",
 | 
			
		||||
  "version": "0.0.0",
 | 
			
		||||
  "description": "Assets for Aircox Web",
 | 
			
		||||
  "main": "index.js",
 | 
			
		||||
  "author": "bkfox",
 | 
			
		||||
  "license": "AGPL",
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@fortawesome/fontawesome-free": "^5.8.2",
 | 
			
		||||
    "bulma": "^0.7.5",
 | 
			
		||||
    "css-loader": "^2.1.1",
 | 
			
		||||
    "extract-text-webpack-plugin": "^4.0.0-beta.0",
 | 
			
		||||
    "file-loader": "^3.0.1",
 | 
			
		||||
    "mini-css-extract-plugin": "^0.5.0",
 | 
			
		||||
    "node-sass": "^4.12.0",
 | 
			
		||||
    "sass-loader": "^7.1.0",
 | 
			
		||||
    "style-loader": "^0.23.1",
 | 
			
		||||
    "ttf-loader": "^1.0.2",
 | 
			
		||||
    "vue-loader": "^15.7.0",
 | 
			
		||||
    "vue-style-loader": "^4.1.2",
 | 
			
		||||
    "vue-template-compiler": "^2.6.10",
 | 
			
		||||
    "webpack": "^4.32.2",
 | 
			
		||||
    "webpack-cli": "^3.3.2"
 | 
			
		||||
  },
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "buefy": "^0.7.8",
 | 
			
		||||
    "vue": "^2.6.10"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										93
									
								
								webpack.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								webpack.config.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,93 @@
 | 
			
		||||
const path = require('path');
 | 
			
		||||
const webpack = require('webpack');
 | 
			
		||||
 | 
			
		||||
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
 | 
			
		||||
// const { createLodashAliases } = require('lodash-loader');
 | 
			
		||||
const VueLoaderPlugin = require('vue-loader/lib/plugin');
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
module.exports = (env, argv) => Object({
 | 
			
		||||
    context: __dirname,
 | 
			
		||||
    entry: './assets/index',
 | 
			
		||||
 | 
			
		||||
    output: {
 | 
			
		||||
        path: path.resolve('aircox/static/aircox'),
 | 
			
		||||
        filename: '[name].js',
 | 
			
		||||
        chunkFilename: '[name].js',
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    optimization: {
 | 
			
		||||
        usedExports: true,
 | 
			
		||||
        concatenateModules: argv.mode == 'production' ? true : false,
 | 
			
		||||
 | 
			
		||||
        splitChunks: {
 | 
			
		||||
            cacheGroups: {
 | 
			
		||||
                vendor: {
 | 
			
		||||
                    name: 'vendor',
 | 
			
		||||
                    chunks: 'initial',
 | 
			
		||||
                    enforce: true,
 | 
			
		||||
 | 
			
		||||
                    test: /[\\/]node_modules[\\/]/,
 | 
			
		||||
                },
 | 
			
		||||
 | 
			
		||||
                /*noscript: {
 | 
			
		||||
                    name: 'noscript',
 | 
			
		||||
                    chunks: 'initial',
 | 
			
		||||
                    enforce: true,
 | 
			
		||||
                    test: /noscript/,
 | 
			
		||||
                }*/
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    plugins: [
 | 
			
		||||
        new MiniCssExtractPlugin({
 | 
			
		||||
            filename: "[name].css",
 | 
			
		||||
            chunkFilename: "[id].css"
 | 
			
		||||
        }),
 | 
			
		||||
        new VueLoaderPlugin(),
 | 
			
		||||
    ],
 | 
			
		||||
 | 
			
		||||
    module: {
 | 
			
		||||
        rules: [
 | 
			
		||||
            { test: /\.vue$/, loader: 'vue-loader' },
 | 
			
		||||
            {
 | 
			
		||||
                test: /\/node_modules\//,
 | 
			
		||||
                sideEffects: false
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                test: /\.scss$/,
 | 
			
		||||
                use: [ { loader: MiniCssExtractPlugin.loader },
 | 
			
		||||
                       { loader: 'css-loader' },
 | 
			
		||||
                       { loader: 'sass-loader' , options: { sourceMap: true }} ],
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                // TODO: remove ttf eot svg
 | 
			
		||||
                test: /\.(ttf|eot|svg|woff2?)$/,
 | 
			
		||||
                use: [{
 | 
			
		||||
                    loader: 'file-loader',
 | 
			
		||||
                    options: {
 | 
			
		||||
                        name: '[name].[ext]',
 | 
			
		||||
                        outputPath: 'fonts/',
 | 
			
		||||
                    }
 | 
			
		||||
                }],
 | 
			
		||||
            },
 | 
			
		||||
        ],
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    resolve: {
 | 
			
		||||
        alias: {
 | 
			
		||||
            js: path.resolve(__dirname, 'assets/js'),
 | 
			
		||||
            vue: 'vue/dist/vue.esm.browser.js',
 | 
			
		||||
            // buefy: 'buefy/dist/buefy.js',
 | 
			
		||||
        },
 | 
			
		||||
        modules: [
 | 
			
		||||
            'assets/css',
 | 
			
		||||
            'assets/js',
 | 
			
		||||
            'assets/vue',
 | 
			
		||||
            './node_modules',
 | 
			
		||||
        ],
 | 
			
		||||
        extensions: ['.js', '.vue', '.css', '.styl', '.ttf']
 | 
			
		||||
    },
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user