work on logs, timetable, stats
This commit is contained in:
		@ -12,7 +12,7 @@ __all__ = ['ArticleAdmin']
 | 
			
		||||
@admin.register(Article)
 | 
			
		||||
class ArticleAdmin(PageAdmin):
 | 
			
		||||
    list_display = PageAdmin.list_display + ('program',)
 | 
			
		||||
    list_filter = ('program',)
 | 
			
		||||
    list_filter = PageAdmin.list_filter + ('program',)
 | 
			
		||||
    search_fields = PageAdmin.search_fields + ['program__title']
 | 
			
		||||
    # TODO: readonly field
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -49,7 +49,7 @@ class DiffusionInline(DiffusionBaseAdmin, admin.TabularInline):
 | 
			
		||||
@admin.register(Episode)
 | 
			
		||||
class EpisodeAdmin(PageAdmin):
 | 
			
		||||
    list_display = PageAdmin.list_display + ('program',)
 | 
			
		||||
    list_filter = ('program',)
 | 
			
		||||
    list_filter = PageAdmin.list_filter + ('program',)
 | 
			
		||||
    search_fields = PageAdmin.search_fields + ['program__title']
 | 
			
		||||
    readonly_fields = ('program',)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -24,10 +24,9 @@ class PageAdmin(admin.ModelAdmin):
 | 
			
		||||
    list_display = ('cover_thumb', 'title', 'status', 'category')
 | 
			
		||||
    list_display_links = ('cover_thumb', 'title')
 | 
			
		||||
    list_editable = ('status', 'category')
 | 
			
		||||
    list_filter = ('status', 'category')
 | 
			
		||||
    prepopulated_fields = {"slug": ("title",)}
 | 
			
		||||
 | 
			
		||||
    change_form_template = 'admin/aircox/page_change_form.html'
 | 
			
		||||
 | 
			
		||||
    search_fields = ['title', 'category__title']
 | 
			
		||||
    fieldsets = [
 | 
			
		||||
        ('', {
 | 
			
		||||
@ -39,6 +38,8 @@ class PageAdmin(admin.ModelAdmin):
 | 
			
		||||
        }),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    change_form_template = 'admin/aircox/page_change_form.html'
 | 
			
		||||
 | 
			
		||||
    def cover_thumb(self, obj):
 | 
			
		||||
        return mark_safe('<img src="{}"/>'.format(obj.cover.icons['64'])) \
 | 
			
		||||
            if obj.cover else ''
 | 
			
		||||
 | 
			
		||||
@ -3,6 +3,8 @@ import datetime
 | 
			
		||||
from django.utils.safestring import mark_safe
 | 
			
		||||
from django.urls.converters import StringConverter
 | 
			
		||||
 | 
			
		||||
from .utils import str_to_date
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PagePathConverter(StringConverter):
 | 
			
		||||
    """ Match path for pages, including surrounding slashes. """
 | 
			
		||||
@ -39,8 +41,7 @@ class DateConverter:
 | 
			
		||||
    regex = r'[0-9]{4}/[0-9]{2}/[0-9]{2}'
 | 
			
		||||
 | 
			
		||||
    def to_python(self, value):
 | 
			
		||||
        value = value.split('/')
 | 
			
		||||
        return datetime.date(int(value[0]), int(value[1]), int(value[2]))
 | 
			
		||||
        return str_to_date(value)
 | 
			
		||||
 | 
			
		||||
    def to_url(self, value):
 | 
			
		||||
        return '{:04d}/{:02d}/{:02d}'.format(value.year, value.month,
 | 
			
		||||
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							@ -221,6 +221,7 @@ class Log(models.Model):
 | 
			
		||||
    def related(self):
 | 
			
		||||
        return self.diffusion or self.sound or self.track
 | 
			
		||||
 | 
			
		||||
    # FIXME: required????
 | 
			
		||||
    @property
 | 
			
		||||
    def local_date(self):
 | 
			
		||||
        """
 | 
			
		||||
@ -230,6 +231,12 @@ class Log(models.Model):
 | 
			
		||||
        """
 | 
			
		||||
        return tz.localtime(self.date, tz.get_current_timezone())
 | 
			
		||||
 | 
			
		||||
    # prepare for the future on crash + ease the use in merged lists with
 | 
			
		||||
    # diffusions
 | 
			
		||||
    @property
 | 
			
		||||
    def start(self):
 | 
			
		||||
        return self.date
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return '#{} ({}, {}, {})'.format(
 | 
			
		||||
            self.pk, self.get_type_display(),
 | 
			
		||||
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -1,4 +1,159 @@
 | 
			
		||||
(window["webpackJsonp"] = window["webpackJsonp"] || []).push([["admin"],{
 | 
			
		||||
/******/ (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(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && 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 = {
 | 
			
		||||
/******/ 		"admin": 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/admin/index.js","vendor"]);
 | 
			
		||||
/******/ 	// run deferred modules when ready
 | 
			
		||||
/******/ 	return checkDeferredModules();
 | 
			
		||||
/******/ })
 | 
			
		||||
/************************************************************************/
 | 
			
		||||
/******/ ({
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/admin/admin.scss":
 | 
			
		||||
/*!*********************************!*\
 | 
			
		||||
@ -19,8 +174,175 @@ eval("// extracted by mini-css-extract-plugin\n\n//# sourceURL=webpack:///./asse
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("/* harmony import */ var _admin_scss__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./admin.scss */ \"./assets/admin/admin.scss\");\n/* harmony import */ var _admin_scss__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_admin_scss__WEBPACK_IMPORTED_MODULE_0__);\n\n\n\n\n\n//# sourceURL=webpack:///./assets/admin/index.js?");
 | 
			
		||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.browser.js\");\n/* harmony import */ var _admin_scss__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./admin.scss */ \"./assets/admin/admin.scss\");\n/* harmony import */ var _admin_scss__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_admin_scss__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _statistics_vue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./statistics.vue */ \"./assets/admin/statistics.vue\");\n/* harmony import */ var public__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! public */ \"./assets/public/index.js\");\n\n\n\n\n\n\nvue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].component('a-statistics', _statistics_vue__WEBPACK_IMPORTED_MODULE_2__[\"default\"])\n\n\n\n\n\n\n\n\n//# sourceURL=webpack:///./assets/admin/index.js?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/admin/statistics.vue":
 | 
			
		||||
/*!*************************************!*\
 | 
			
		||||
  !*** ./assets/admin/statistics.vue ***!
 | 
			
		||||
  \*************************************/
 | 
			
		||||
/*! exports provided: default */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _statistics_vue_vue_type_template_id_47005a51___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./statistics.vue?vue&type=template&id=47005a51& */ \"./assets/admin/statistics.vue?vue&type=template&id=47005a51&\");\n/* harmony import */ var _statistics_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./statistics.vue?vue&type=script&lang=js& */ \"./assets/admin/statistics.vue?vue&type=script&lang=js&\");\n/* empty/unused harmony star reexport *//* 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\"])(\n  _statistics_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n  _statistics_vue_vue_type_template_id_47005a51___WEBPACK_IMPORTED_MODULE_0__[\"render\"],\n  _statistics_vue_vue_type_template_id_47005a51___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"],\n  false,\n  null,\n  null,\n  null\n  \n)\n\n/* hot reload */\nif (false) { var api; }\ncomponent.options.__file = \"assets/admin/statistics.vue\"\n/* harmony default export */ __webpack_exports__[\"default\"] = (component.exports);\n\n//# sourceURL=webpack:///./assets/admin/statistics.vue?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/admin/statistics.vue?vue&type=script&lang=js&":
 | 
			
		||||
/*!**************************************************************!*\
 | 
			
		||||
  !*** ./assets/admin/statistics.vue?vue&type=script&lang=js& ***!
 | 
			
		||||
  \**************************************************************/
 | 
			
		||||
/*! exports provided: default */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_vue_loader_lib_index_js_vue_loader_options_statistics_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../node_modules/vue-loader/lib??vue-loader-options!./statistics.vue?vue&type=script&lang=js& */ \"./node_modules/vue-loader/lib/index.js?!./assets/admin/statistics.vue?vue&type=script&lang=js&\");\n/* empty/unused harmony star reexport */ /* harmony default export */ __webpack_exports__[\"default\"] = (_node_modules_vue_loader_lib_index_js_vue_loader_options_statistics_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__[\"default\"]); \n\n//# sourceURL=webpack:///./assets/admin/statistics.vue?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/admin/statistics.vue?vue&type=template&id=47005a51&":
 | 
			
		||||
/*!********************************************************************!*\
 | 
			
		||||
  !*** ./assets/admin/statistics.vue?vue&type=template&id=47005a51& ***!
 | 
			
		||||
  \********************************************************************/
 | 
			
		||||
/*! exports provided: render, staticRenderFns */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_statistics_vue_vue_type_template_id_47005a51___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!./statistics.vue?vue&type=template&id=47005a51& */ \"./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/vue-loader/lib/index.js?!./assets/admin/statistics.vue?vue&type=template&id=47005a51&\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_statistics_vue_vue_type_template_id_47005a51___WEBPACK_IMPORTED_MODULE_0__[\"render\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_statistics_vue_vue_type_template_id_47005a51___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"]; });\n\n\n\n//# sourceURL=webpack:///./assets/admin/statistics.vue?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/public/app.js":
 | 
			
		||||
/*!******************************!*\
 | 
			
		||||
  !*** ./assets/public/app.js ***!
 | 
			
		||||
  \******************************/
 | 
			
		||||
/*! exports provided: app, default */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"app\", function() { return app; });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.browser.js\");\n\n\n\nvar app = null;\n/* harmony default export */ __webpack_exports__[\"default\"] = (app);\n\nfunction loadApp() {\n    app = new vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"]({\n      el: '#app',\n      delimiters: [ '[[', ']]' ],\n    })\n}\n\nwindow.addEventListener('load', loadApp);\n\n\n\n\n\n//# sourceURL=webpack:///./assets/public/app.js?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/public/index.js":
 | 
			
		||||
/*!********************************!*\
 | 
			
		||||
  !*** ./assets/public/index.js ***!
 | 
			
		||||
  \********************************/
 | 
			
		||||
/*! no exports provided */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.browser.js\");\n/* harmony import */ var _fortawesome_fontawesome_free_css_all_min_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @fortawesome/fontawesome-free/css/all.min.css */ \"./node_modules/@fortawesome/fontawesome-free/css/all.min.css\");\n/* harmony import */ var _fortawesome_fontawesome_free_css_all_min_css__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_fortawesome_fontawesome_free_css_all_min_css__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _fortawesome_fontawesome_free_css_fontawesome_min_css__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @fortawesome/fontawesome-free/css/fontawesome.min.css */ \"./node_modules/@fortawesome/fontawesome-free/css/fontawesome.min.css\");\n/* harmony import */ var _fortawesome_fontawesome_free_css_fontawesome_min_css__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_fortawesome_fontawesome_free_css_fontawesome_min_css__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var buefy_dist_buefy_css__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! buefy/dist/buefy.css */ \"./node_modules/buefy/dist/buefy.css\");\n/* harmony import */ var buefy_dist_buefy_css__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(buefy_dist_buefy_css__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var _app__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./app */ \"./assets/public/app.js\");\n/* harmony import */ var _liveInfo__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./liveInfo */ \"./assets/public/liveInfo.js\");\n/* harmony import */ var _styles_scss__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./styles.scss */ \"./assets/public/styles.scss\");\n/* harmony import */ var _styles_scss__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(_styles_scss__WEBPACK_IMPORTED_MODULE_6__);\n/* harmony import */ var _player_vue__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./player.vue */ \"./assets/public/player.vue\");\n/**\n * This module includes code available for both the public website and\n * administration interface)\n */\n//-- vendor\n\n\n\n\n\n\n\n//-- aircox\n\n\n\n\n\n\n\nvue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].component('a-player', _player_vue__WEBPACK_IMPORTED_MODULE_7__[\"default\"])\n\n\nwindow.aircox = {\n    app: _app__WEBPACK_IMPORTED_MODULE_4__[\"default\"],\n    LiveInfo: _liveInfo__WEBPACK_IMPORTED_MODULE_5__[\"default\"],\n}\n\n\n\n//# sourceURL=webpack:///./assets/public/index.js?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/public/liveInfo.js":
 | 
			
		||||
/*!***********************************!*\
 | 
			
		||||
  !*** ./assets/public/liveInfo.js ***!
 | 
			
		||||
  \***********************************/
 | 
			
		||||
/*! exports provided: default */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("__webpack_require__.r(__webpack_exports__);\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (class {\n    constructor(url, timeout) {\n        this.url = url;\n        this.timeout = timeout;\n        this.promise = null;\n        this.items = [];\n    }\n\n    drop() {\n        this.promise = null;\n    }\n\n    fetch() {\n        const promise = fetch(this.url).then(response =>\n            response.ok ? response.json()\n                        : Promise.reject(response)\n        ).then(data => {\n            this.items = data;\n            return this.items\n        })\n\n        this.promise = promise;\n        return promise;\n    }\n\n    refresh() {\n        const promise = this.fetch();\n        promise.then(data => {\n            if(promise != this.promise)\n                return [];\n\n            window.setTimeout(() => this.refresh(), this.timeout*1000)\n        })\n        return promise\n    }\n});\n\n\n//# sourceURL=webpack:///./assets/public/liveInfo.js?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/public/player.vue":
 | 
			
		||||
/*!**********************************!*\
 | 
			
		||||
  !*** ./assets/public/player.vue ***!
 | 
			
		||||
  \**********************************/
 | 
			
		||||
/*! exports provided: default, State */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _player_vue_vue_type_template_id_42a56ec9___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./player.vue?vue&type=template&id=42a56ec9& */ \"./assets/public/player.vue?vue&type=template&id=42a56ec9&\");\n/* harmony import */ var _player_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./player.vue?vue&type=script&lang=js& */ \"./assets/public/player.vue?vue&type=script&lang=js&\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"State\", function() { return _player_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[\"State\"]; });\n\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\"])(\n  _player_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n  _player_vue_vue_type_template_id_42a56ec9___WEBPACK_IMPORTED_MODULE_0__[\"render\"],\n  _player_vue_vue_type_template_id_42a56ec9___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"],\n  false,\n  null,\n  null,\n  null\n  \n)\n\n/* hot reload */\nif (false) { var api; }\ncomponent.options.__file = \"assets/public/player.vue\"\n/* harmony default export */ __webpack_exports__[\"default\"] = (component.exports);\n\n//# sourceURL=webpack:///./assets/public/player.vue?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/public/player.vue?vue&type=script&lang=js&":
 | 
			
		||||
/*!***********************************************************!*\
 | 
			
		||||
  !*** ./assets/public/player.vue?vue&type=script&lang=js& ***!
 | 
			
		||||
  \***********************************************************/
 | 
			
		||||
/*! exports provided: default, State */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_vue_loader_lib_index_js_vue_loader_options_player_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../node_modules/vue-loader/lib??vue-loader-options!./player.vue?vue&type=script&lang=js& */ \"./node_modules/vue-loader/lib/index.js?!./assets/public/player.vue?vue&type=script&lang=js&\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"State\", function() { return _node_modules_vue_loader_lib_index_js_vue_loader_options_player_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__[\"State\"]; });\n\n /* harmony default export */ __webpack_exports__[\"default\"] = (_node_modules_vue_loader_lib_index_js_vue_loader_options_player_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__[\"default\"]); \n\n//# sourceURL=webpack:///./assets/public/player.vue?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/public/player.vue?vue&type=template&id=42a56ec9&":
 | 
			
		||||
/*!*****************************************************************!*\
 | 
			
		||||
  !*** ./assets/public/player.vue?vue&type=template&id=42a56ec9& ***!
 | 
			
		||||
  \*****************************************************************/
 | 
			
		||||
/*! exports provided: render, staticRenderFns */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_player_vue_vue_type_template_id_42a56ec9___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!./player.vue?vue&type=template&id=42a56ec9& */ \"./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/vue-loader/lib/index.js?!./assets/public/player.vue?vue&type=template&id=42a56ec9&\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_player_vue_vue_type_template_id_42a56ec9___WEBPACK_IMPORTED_MODULE_0__[\"render\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_player_vue_vue_type_template_id_42a56ec9___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"]; });\n\n\n\n//# sourceURL=webpack:///./assets/public/player.vue?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/public/styles.scss":
 | 
			
		||||
/*!***********************************!*\
 | 
			
		||||
  !*** ./assets/public/styles.scss ***!
 | 
			
		||||
  \***********************************/
 | 
			
		||||
/*! no static exports found */
 | 
			
		||||
/***/ (function(module, exports, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
eval("// extracted by mini-css-extract-plugin\n\n//# sourceURL=webpack:///./assets/public/styles.scss?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./node_modules/vue-loader/lib/index.js?!./assets/admin/statistics.vue?vue&type=script&lang=js&":
 | 
			
		||||
/*!****************************************************************************************************************!*\
 | 
			
		||||
  !*** ./node_modules/vue-loader/lib??vue-loader-options!./assets/admin/statistics.vue?vue&type=script&lang=js& ***!
 | 
			
		||||
  \****************************************************************************************************************/
 | 
			
		||||
/*! exports provided: default */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("__webpack_require__.r(__webpack_exports__);\n//\n//\n//\n//\n//\n//\n\n\nconst splitReg = new RegExp(`,\\s*`, 'g');\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n    data() {\n        return {\n            counts: {},\n        }\n    },\n\n    methods: {\n        update() {\n            const items = this.$el.querySelectorAll('input[name=\"data\"]:checked')\n            const counts = {};\n\n            console.log(items)\n            for(var item of items)\n                if(item.value)\n                    for(var tag of item.value.split(splitReg))\n                        counts[tag.trim()] = (counts[tag.trim()] || 0) + 1;\n            this.counts = counts;\n            console.log('counts', this.counts)\n        }\n    },\n\n    mounted() {\n        this.$refs.form.addEventListener('change', () => this.update())\n        this.update()\n    }\n});\n\n\n//# sourceURL=webpack:///./assets/admin/statistics.vue?./node_modules/vue-loader/lib??vue-loader-options");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./node_modules/vue-loader/lib/index.js?!./assets/public/player.vue?vue&type=script&lang=js&":
 | 
			
		||||
/*!*************************************************************************************************************!*\
 | 
			
		||||
  !*** ./node_modules/vue-loader/lib??vue-loader-options!./assets/public/player.vue?vue&type=script&lang=js& ***!
 | 
			
		||||
  \*************************************************************************************************************/
 | 
			
		||||
/*! exports provided: State, default */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"State\", function() { return State; });\n/* harmony import */ var _liveInfo__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./liveInfo */ \"./assets/public/liveInfo.js\");\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n\n\n\nconst State = {\n    paused: 0,\n    playing: 1,\n    loading: 2,\n}\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n    data() {\n        return {\n            state: State.paused,\n            liveInfo: new _liveInfo__WEBPACK_IMPORTED_MODULE_0__[\"default\"](this.liveInfoUrl, this.liveInfoTimeout),\n        }\n    },\n\n    props: {\n        buttonTitle: String,\n        liveInfoUrl: String,\n        liveInfoTimeout: { type: Number, default: 5},\n        src: String,\n    },\n\n    computed: {\n        paused() { return this.state == State.paused; },\n        playing() { return this.state == State.playing; },\n        loading() { return this.state == State.loading; },\n\n        onAir() {\n            return this.liveInfo.items && this.liveInfo.items[0];\n        },\n\n        buttonStyle() {\n            if(!this.onAir)\n                return;\n            return { backgroundImage: `url(${this.onAir.cover})` }\n        }\n    },\n\n    methods: {\n        load(src) {\n            const audio = this.$refs.audio;\n            audio.src = src;\n            audio.load()\n        },\n\n        play(src) {\n            if(src)\n                this.load(src);\n            this.$refs.audio.play().catch(e => console.error(e))\n        },\n\n        pause() {\n            this.$refs.audio.pause()\n        },\n\n        toggle() {\n            if(this.paused)\n                this.play()\n            else\n                this.pause()\n        },\n\n        onChange(event) {\n            const audio = this.$refs.audio;\n            this.state = audio.paused ? State.paused : State.playing;\n        },\n    },\n\n    mounted() {\n        this.liveInfo.refresh()\n    },\n\n    destroyed() {\n        this.liveInfo.drop()\n    },\n});\n\n\n\n//# sourceURL=webpack:///./assets/public/player.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/admin/statistics.vue?vue&type=template&id=47005a51&":
 | 
			
		||||
/*!**************************************************************************************************************************************************************************************************!*\
 | 
			
		||||
  !*** ./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib??vue-loader-options!./assets/admin/statistics.vue?vue&type=template&id=47005a51& ***!
 | 
			
		||||
  \**************************************************************************************************************************************************************************************************/
 | 
			
		||||
/*! exports provided: render, staticRenderFns */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return render; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", 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    \"form\",\n    { ref: \"form\" },\n    [_vm._t(\"default\", null, { counts: _vm.counts })],\n    2\n  )\n}\nvar staticRenderFns = []\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./assets/admin/statistics.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/public/player.vue?vue&type=template&id=42a56ec9&":
 | 
			
		||||
/*!***********************************************************************************************************************************************************************************************!*\
 | 
			
		||||
  !*** ./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib??vue-loader-options!./assets/public/player.vue?vue&type=template&id=42a56ec9& ***!
 | 
			
		||||
  \***********************************************************************************************************************************************************************************************/
 | 
			
		||||
/*! exports provided: render, staticRenderFns */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return render; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", 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(\"div\", { staticClass: \"media\" }, [\n    _c(\"div\", { staticClass: \"media-left\" }, [\n      _c(\n        \"div\",\n        {\n          staticClass: \"button\",\n          attrs: { title: _vm.buttonTitle, \"aria-label\": _vm.buttonTitle },\n          on: {\n            click: function($event) {\n              return _vm.toggle()\n            }\n          }\n        },\n        [\n          _vm.playing\n            ? _c(\"span\", { staticClass: \"fas fa-pause\" })\n            : _c(\"span\", { staticClass: \"fas fa-play\" })\n        ]\n      ),\n      _vm._v(\" \"),\n      _c(\n        \"audio\",\n        {\n          ref: \"audio\",\n          on: {\n            playing: _vm.onChange,\n            ended: _vm.onChange,\n            pause: _vm.onChange\n          }\n        },\n        [_vm._t(\"sources\")],\n        2\n      )\n    ]),\n    _vm._v(\" \"),\n    _vm.onAir && _vm.onAir.cover\n      ? _c(\"div\", { staticClass: \"media-left media-cover\" }, [\n          _c(\"img\", { staticClass: \"cover\", attrs: { src: _vm.onAir.cover } })\n        ])\n      : _vm._e(),\n    _vm._v(\" \"),\n    _vm.onAir && _vm.onAir.type == \"track\"\n      ? _c(\n          \"div\",\n          { staticClass: \"media-content\" },\n          [_vm._t(\"track\", null, { onAir: _vm.onAir, liveInfo: _vm.liveInfo })],\n          2\n        )\n      : _vm.onAir && _vm.onAir.type == \"diffusion\"\n      ? _c(\n          \"div\",\n          { staticClass: \"media-content\" },\n          [\n            _vm._t(\"diffusion\", null, {\n              onAir: _vm.onAir,\n              liveInfo: _vm.liveInfo\n            })\n          ],\n          2\n        )\n      : _c(\"div\", { staticClass: \"media-content\" }, [_vm._t(\"empty\")], 2)\n  ])\n}\nvar staticRenderFns = []\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./assets/public/player.vue?./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib??vue-loader-options");
 | 
			
		||||
 | 
			
		||||
/***/ })
 | 
			
		||||
 | 
			
		||||
}]);
 | 
			
		||||
/******/ });
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@ -1,12 +1,12 @@
 | 
			
		||||
<?xml version="1.0" standalone="no"?>
 | 
			
		||||
<!--
 | 
			
		||||
Font Awesome Free 5.9.0 by @fontawesome - https://fontawesome.com
 | 
			
		||||
Font Awesome Free 5.10.2 by @fontawesome - https://fontawesome.com
 | 
			
		||||
License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
 | 
			
		||||
-->
 | 
			
		||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
 | 
			
		||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
 | 
			
		||||
<metadata>
 | 
			
		||||
Created by FontForge 20190112 at Tue Jun  4 15:16:44 2019
 | 
			
		||||
Created by FontForge 20190801 at Thu Aug 22 14:41:09 2019
 | 
			
		||||
 By Robert Madole
 | 
			
		||||
Copyright (c) Font Awesome
 | 
			
		||||
</metadata>
 | 
			
		||||
@ -22,8 +22,8 @@ Copyright (c) Font Awesome
 | 
			
		||||
    descent="-64"
 | 
			
		||||
    bbox="-0.200195 -66.9505 641.5 448.3"
 | 
			
		||||
    underline-thickness="25"
 | 
			
		||||
    underline-position="-51"
 | 
			
		||||
    unicode-range="U+0020-F842"
 | 
			
		||||
    underline-position="-50"
 | 
			
		||||
    unicode-range="U+0020-F89E"
 | 
			
		||||
  />
 | 
			
		||||
    <missing-glyph />
 | 
			
		||||
    <glyph glyph-name="twitter-square" unicode="" 
 | 
			
		||||
@ -2462,22 +2462,20 @@ l-10.9004 20.5996h37.5l54.9004 -109.9zM243.7 134.2c29.7998 0 50.2002 21.5 50.200
 | 
			
		||||
c-11.7998 0 -26.2998 -0.0996094 -39.3994 -0.599609c-29.1006 -0.900391 -47.2002 -6.2002 -47.2002 -25.2998c0 -12.4004 9.90039 -25.8008 35 -25.8008c33.7002 0 51.5996 18.4004 51.5996 48.4004zM32.7002 179.9c3.5 -58.3008 79.2002 -57.4004 91.2002 -21.6006
 | 
			
		||||
h33.0996c-6.40039 -34.3994 -43 -46.0996 -74.4004 -46.0996c-57.1992 0 -82.5 31.5 -82.5 74c0 46.7998 26.2002 77.5996 83 77.5996c45.3008 0 78.4004 -23.7002 78.4004 -75.3994v-8.5h-128.8zM127.7 201.3c-2.2998 54.7002 -87.5 56.6006 -94.4004 0h94.4004z" />
 | 
			
		||||
    <glyph glyph-name="keybase" unicode="" 
 | 
			
		||||
d="M195.21 17.2998c0 -9.8252 -7.97461 -17.7998 -17.7998 -17.7998c-9.82617 0 -17.7998 7.97461 -17.7998 17.7998c0 9.82617 7.97363 17.7998 17.7998 17.7998c9.80371 -0.0214844 17.7783 -7.99609 17.7998 -17.7998zM288 35.2002
 | 
			
		||||
c9.80371 -0.0224609 17.7783 -7.99609 17.7998 -17.7998c0 -9.82617 -7.97461 -17.8008 -17.7998 -17.8008s-17.7998 7.97461 -17.7998 17.8008c0 9.8252 7.97461 17.7998 17.7998 17.7998zM430.3 71.2002c0 -38.9004 -7.59961 -73.9004 -22.2002 -103h-27.2998
 | 
			
		||||
c23.5 38.7002 30.5 94.7998 22.4004 134.3c-16.1006 -29.5 -52.1006 -38.5996 -85.9004 -28.7998c-127.8 37.5 -192.5 -19.7002 -234.6 -50.2998l18.8994 59.2998l-39.8994 -42.2998c3.95605 -21.9639 17.9336 -54.3545 31.2002 -72.3008h-28.79
 | 
			
		||||
c-8.1543 13.2822 -18.0996 36.2646 -22.2002 51.3008l-23.7998 -25.2002c0 74.8994 -5.5 147.6 61.5 215.2c16.4688 16.7402 47.4248 37.6621 69.0996 46.6992c-6.7998 13.5 -9.5 29.2002 -7.7998 46l-19.9102 1.2002c-16.918 1.05371 -30.6484 15.666 -30.6484 32.6172
 | 
			
		||||
c0 0.492188 0.0214844 1.29102 0.0488281 1.7832v0.0996094l1.59961 26.2002c1.10449 16.7988 15.665 30.5078 32.5 30.5996c1.2998 0 -0.299805 0.100586 28.2002 -1.69922c7.65918 -0.414062 17.873 -5.52148 22.7998 -11.4004c7.11035 10.4004 14.5 20.5 24.6104 34.5
 | 
			
		||||
l20.5996 -12.0996c-13.5996 -29 -9.09961 -36.2002 -9 -36.3008c3.90039 0 13.9004 0.5 32.4004 -5.69922c28.8379 -9.54883 52.2422 -41.9512 52.2422 -72.3291c0 -8.61914 -2.75195 -22.0469 -6.14258 -29.9717c19 -6.09961 51.2998 -19.8994 82.4004 -51.7998
 | 
			
		||||
c36.5996 -37.5996 57.6992 -87.3994 57.6992 -136.6h-0.00976562zM146 325.9c2.80762 8.47461 8.67578 21.6455 13.0996 29.3994c0.100586 2 2.2002 13.1006 -7.7998 13.7998c-28.5 1.80078 -26.2998 1.60059 -26.7002 1.60059h-0.0429688
 | 
			
		||||
c-4.47754 0 -8.31152 -3.62891 -8.55664 -8.10059l-1.59961 -26.1992c-0.00683594 -0.121094 -0.0117188 -0.318359 -0.0117188 -0.439453c0 -4.48633 3.63379 -8.36719 8.11133 -8.66113zM171.8 264.1c4.50488 -7.35938 14.4951 -16.3193 22.2998 -20
 | 
			
		||||
c0 21.2002 28.5 41.9004 52.8008 17.5l8.39941 -10.2998c20.7998 18.7998 19.4004 45.2998 12.1006 60.9004c-13.8008 29.0996 -46.9004 32 -54.3008 31.7002c-0.319336 -0.015625 -0.837891 -0.0283203 -1.15723 -0.0283203c-9.09863 0 -19.1973 6.86719 -22.542 15.3281
 | 
			
		||||
c-13.6904 -21.2002 -37.1904 -62.5 -17.5908 -95.1006h-0.00976562zM254.7 195.7l-19.7002 -16.1006c-0.900391 -0.738281 -1.63086 -2.2832 -1.63086 -3.44727c0 -0.890625 0.461914 -2.16797 1.03125 -2.85254l8.89941 -10.8994
 | 
			
		||||
c0.742188 -0.896484 2.28809 -1.62305 3.45117 -1.62305c0.887695 0 2.16406 0.458008 2.84863 1.02246l19.6006 16l5.5 -6.7998c4.89941 -6 13.7998 1.40039 9 7.2998c-63.6006 78.2998 -41.5 51.1006 -55.2998 68.1006c-4.7002 6 -13.9004 -1.40039 -9 -7.30078
 | 
			
		||||
c1.89941 -2.2998 18.3994 -22.5996 19.7998 -24.2998l-9.60059 -7.89941c-4.59961 -3.80078 2.60059 -13.3008 7.40039 -9.40039l9.7002 8zM373.11 170c-16.9004 23.7002 -42.6006 46.7002 -73.4004 60.4004c-6.18359 2.73633 -16.4434 6.58887 -22.9004 8.59961
 | 
			
		||||
c-1.64355 -1.83789 -4.51074 -4.61523 -6.39941 -6.2002l31.8994 -39.2002c3.70605 -4.54102 6.71289 -12.9834 6.71289 -18.8447c0 -7.78906 -4.88867 -18.1172 -10.9121 -23.0547c-1.30078 -1.10059 -13.1006 -10.7002 -29 -4.90039
 | 
			
		||||
c-2.90039 -2.2998 -10.1006 -9.89941 -22.2002 -9.89941h-0.0419922c-7.46777 0 -17.3496 4.70312 -22.0586 10.5l-8.89941 10.8994c-3.5293 4.33984 -6.39355 12.4014 -6.39355 17.9951c0 2.49121 0.624023 6.43555 1.39355 8.80469
 | 
			
		||||
c-3.83398 4.43945 -6.94531 12.8018 -6.94531 18.667c0 3.26172 1.05078 8.33984 2.34473 11.333c-7.19922 1.30078 -26.6992 6.2002 -42.6992 21.4004c-55.8008 -20.7002 -88 -64.4004 -101.301 -91.2002c-14.8994 -30.2002 -18.7998 -60.8994 -19.8994 -90.2002
 | 
			
		||||
c8.2002 8.7002 -3.90039 -4.09961 114 120.9l-29.9004 -93.5996c57.7998 31.0996 124 36 197.4 14.3994c23.5996 -6.89941 45.0996 -1.59961 56 13.9004c11.0996 15.5996 8.5 37.7002 -6.7998 59.2998zM128.61 340.9l1 15.5996l15.5996 -1l-1 -15.5996z" />
 | 
			
		||||
d="M286.17 29c9.93652 0 18 -8.06445 18 -18s-8.06348 -18 -18 -18c-9.93555 0 -18 8.06445 -18 18s8.06445 18 18 18zM398.09 176.6c22.9102 -33.46 35.9102 -72.3398 35.9102 -110.92c0 -31.6797 -5 -60.6797 -14.5996 -86.2295
 | 
			
		||||
c-3.04004 -8.0498 -10.9502 -12.7197 -18.3701 -11.1504c-6.83984 1.24023 -11.1201 9.28027 -8.60059 15.7402c11.1904 28.71 14.8799 58.3398 14.8799 81.6396c-0.0517578 7.91797 -1.30566 20.6543 -2.7998 28.4307
 | 
			
		||||
c-0.649414 -1.06055 -1.12988 -2.2207 -1.84961 -3.2207c-17.29 -24.5293 -50.54 -33.8896 -84.7402 -23.8398c-78.8701 23.1699 -178.02 3.81055 -236.25 -38.5898l24.6602 74.1104l-46.8203 -59.8301c2.04297 -15.3486 9.10352 -39.1504 15.7598 -53.1299
 | 
			
		||||
c6.25 -13.1904 0.460938 -18.2402 -3.75 -20.1104c-4.76953 -2.12012 -13.8594 -2.7998 -19.6396 7.33008c-5.43652 9.81641 -11.96 26.6436 -14.5596 37.5596l-23.3203 -29.7998v33.6406c0 55.7695 0 125.109 62.6504 188.409c11.4258 11.5684 32.1631 27.4902 46.29 35.54
 | 
			
		||||
l-8.93066 0.540039c-27.8799 1.64062 -49.2402 24.8506 -47.6299 51.8506l2.36035 36.6797c0 -6.24023 0.139648 45.8799 50.75 45.8799c2.05957 0 -0.470703 0.120117 41.0596 -2.33008c2.31641 -0.15625 6.03027 -0.71582 8.29004 -1.25
 | 
			
		||||
c7.41992 11.3398 15.6504 22.8301 24.3398 34.8906l5.48047 7.55957l22.8994 -13.5195c-11.29 -24 -10 -33 -9.39941 -35c9.08008 0.229492 20 -1.6709 32.4102 -5.77051c29.6523 -9.84375 53.7188 -43.1914 53.7188 -74.4355
 | 
			
		||||
c0 -8.5127 -2.61621 -21.8154 -5.83887 -29.6943c6.18652 -2.13965 12.3135 -4.56348 18.3799 -7.27051c47.8896 -21.2598 77.7598 -59.0898 87.2598 -73.71zM142.37 319.42c1.55664 5.42773 4.69336 14.0156 7 19.1699l-29.1104 1.73047
 | 
			
		||||
c0.610352 -0.0507812 -12.2598 0.849609 -13.2598 -11.3203l-2.41016 -36.6602c-0.00585938 -0.143555 -0.0107422 -0.376953 -0.0107422 -0.520508c0 -6.50293 5.27344 -12 11.7705 -12.2695l22.3809 -1.33984c-0.380859 3.10645 -0.689453 8.16797 -0.689453 11.2969
 | 
			
		||||
c0 2.28809 0.165039 5.99414 0.369141 8.27344l-13.1299 0.779297l1.38965 21.79zM290.79 147.24c2.06152 1.58789 3.73438 4.9873 3.73438 7.58887c0 1.80273 -0.893555 4.42383 -1.99414 5.85059l-81.0898 96.3203c-1.71484 1.99023 -5.23828 3.60547 -7.86523 3.60547
 | 
			
		||||
c-1.99023 0 -4.87305 -1.00098 -6.43555 -2.23535c-2.05957 -1.58398 -3.73242 -4.97949 -3.73242 -7.57812c0 -1.7998 0.892578 -4.41699 1.99316 -5.8418c0.0898438 -0.140625 18.5996 -22.1406 18.5996 -22.1406l-16.9102 -13.29
 | 
			
		||||
c-1.59473 -1.22266 -2.88867 -3.8457 -2.88867 -5.85547c0 -1.37988 0.680664 -3.38867 1.51855 -4.48438c0.0800781 -0.109375 2.52246 -3.07324 3.7998 -4.5293c1.27832 -1.45703 3.8877 -2.63867 5.8252 -2.63867c1.4707 0 3.60547 0.734375 4.76562 1.63867
 | 
			
		||||
l17.0898 13.4492l14.1396 -16.7393l-34.5703 -27.1807c-1.58398 -1.22266 -2.86914 -3.83984 -2.86914 -5.84082c0 -1.38574 0.685547 -3.40039 1.5293 -4.49902l15.7803 -18.6396c1.33594 -1.55176 4.08203 -2.81055 6.12988 -2.81055
 | 
			
		||||
c1.54492 0 3.78516 0.775391 5 1.73047l34.4199 27l9.68066 -11.4902c1.7334 -1.98242 5.27832 -3.5918 7.91211 -3.5918c1.98438 0 4.86816 0.986328 6.4375 2.20215zM187.44 29c9.93555 0 18 -8.06445 18 -18s-8.06445 -18 -18 -18c-9.93652 0 -18 8.06445 -18 18
 | 
			
		||||
s8.06348 18 18 18z" />
 | 
			
		||||
    <glyph glyph-name="mastodon" unicode="" 
 | 
			
		||||
d="M433 268.89c0 0 0.799805 -71.6992 -9 -121.5c-6.23047 -31.5996 -55.1104 -66.1992 -111.23 -72.8994c-20.0996 -2.40039 -93.1191 -14.2002 -178.75 6.7002v-0.339844c0 -3.75977 0.40332 -9.83496 0.900391 -13.5605c6.62988 -49.5996 49.2197 -52.5996 89.6299 -54
 | 
			
		||||
c40.8105 -1.2998 77.1201 10.0996 77.1201 10.0996l1.7002 -36.8994s-28.5098 -15.2998 -79.3203 -18.1006c-28.0098 -1.59961 -62.8193 0.700195 -103.33 11.4004c-112.229 29.7002 -105.63 173.4 -105.63 289.1c0 97.2002 63.7197 125.7 63.7197 125.7
 | 
			
		||||
@ -3438,5 +3436,14 @@ c0 7.7207 7 14.6104 20.4102 14.6104c14.0898 0 20.79 -8.4502 20.79 -18.3496h30.70
 | 
			
		||||
c17.2598 -6.15039 21.9102 -10.4004 21.9102 -19.4795c0 -15.2002 -19.1309 -14.2305 -19.4707 -14.2305c-20.3994 0 -25.6494 9.09961 -25.6494 21.9004h-30.7998l-0.180664 -0.560547c-0.679688 -31.3203 28.3799 -45.2197 56.6299 -45.2197
 | 
			
		||||
c29.9805 0 51.1201 13.5498 51.1201 38.29zM276.68 215.79c0 25.2998 -18.4297 45.46 -53.4199 45.46h-51.7793v-138.18h32.1699v47.3594h19.6094c30.25 0 53.4199 15.9502 53.4199 45.3604zM297.94 123l49.0596 138.22h-31.0898l-47.9102 -138.22h29.9404zM404.46 261.22
 | 
			
		||||
h-31.0898l-47.9102 -138.22h29.9404z" />
 | 
			
		||||
    <glyph glyph-name="cotton-bureau" unicode="" horiz-adv-x="512" 
 | 
			
		||||
d="M474.31 117.59h25.1807c-25.7998 -109.78 -111.4 -173.59 -239.67 -173.59c-154.63 -0.339844 -247.82 92.8604 -247.82 248.18c0 154.63 93 247.82 247.82 247.82c128.399 0 214.06 -63.5098 240.18 -173.61h-25.2598
 | 
			
		||||
c-24.8506 95.6104 -99.9199 148.811 -214.69 148.811c-141.85 0 -223.2 -81.3799 -223.2 -223.2c0 -137.93 76.6699 -218 211.101 -223v49.2002c0 48.1602 -26.5498 74.3896 -74.5498 74.3896c-62.1309 0 -99.4004 37.2803 -99.4004 99.4102
 | 
			
		||||
c0 61.3701 36.5195 98.2803 97.3799 99.0596c30.7402 64.6504 144.24 69.3203 177.24 0c60.8496 -0.779297 97.3799 -37.6895 97.3799 -99.0596c0 -62.0098 -37.2002 -99.21 -99.2002 -99.21c-47.9795 0 -74.3896 -26.3896 -74.3896 -74.3896v-49.1602
 | 
			
		||||
c107.67 3.75977 178.24 56.5 201.899 148.35zM357 265.67c3.7998 -21.0801 11.2695 -104.2 -71.79 -120.75c12.2598 -17.7402 32.9805 -27.3301 61.5898 -27.3301c47.9697 0 74.4004 26.4102 74.4004 74.4102c0 44.6699 -22.8301 70.2197 -64.2002 73.6699zM275.32 168.31
 | 
			
		||||
c72.7803 9.89062 58.5 86.9102 56.2295 97c-72.5596 -10 -58.6895 -86.6592 -56.2295 -97zM260 316l-0.179688 -0.259766c-28.3008 0 -49.1602 -9.66016 -61.5703 -27.3506c28.3701 -5.44922 49.3701 -20.5898 61.5996 -43.4492
 | 
			
		||||
c12.2305 22.8594 33.2305 37.9697 61.5908 43.4492c-12.4404 17.9404 -32.8301 27.6104 -61.4404 27.6104zM188.48 265.28h0.239258c-2.75 -10.0498 -16.1602 -87.1602 56.25 -97c2.41992 10.1895 16.6807 86.4297 -56.4893 97zM173.2 117.59l0.330078 0.0302734
 | 
			
		||||
c28.2998 0 49 9.66992 61.1396 27.2998c-73.0303 14.2197 -78.4004 83.5498 -71.6504 120.75c-41.3594 -3.66992 -64.2197 -29.3096 -64.2197 -73.6699c0 -48.0098 26.4004 -74.4102 74.4004 -74.4102zM226.41 105.2h0.269531
 | 
			
		||||
c14.4902 -7.60059 25.5605 -19.3301 33.5605 -33.8301c6.36523 12.2188 21.4092 27.374 33.5801 33.8301c-14.4902 8.00977 -26.0508 19.0596 -33.8203 33.5498c-6.4248 -12.1094 -21.4736 -27.1396 -33.5898 -33.5498z" />
 | 
			
		||||
  </font>
 | 
			
		||||
</defs></svg>
 | 
			
		||||
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 674 KiB After Width: | Height: | Size: 675 KiB  | 
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							@ -1,12 +1,12 @@
 | 
			
		||||
<?xml version="1.0" standalone="no"?>
 | 
			
		||||
<!--
 | 
			
		||||
Font Awesome Free 5.9.0 by @fontawesome - https://fontawesome.com
 | 
			
		||||
Font Awesome Free 5.10.2 by @fontawesome - https://fontawesome.com
 | 
			
		||||
License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
 | 
			
		||||
-->
 | 
			
		||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
 | 
			
		||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
 | 
			
		||||
<metadata>
 | 
			
		||||
Created by FontForge 20190112 at Tue Jun  4 15:16:44 2019
 | 
			
		||||
Created by FontForge 20190801 at Thu Aug 22 14:41:09 2019
 | 
			
		||||
 By Robert Madole
 | 
			
		||||
Copyright (c) Font Awesome
 | 
			
		||||
</metadata>
 | 
			
		||||
@ -22,7 +22,7 @@ Copyright (c) Font Awesome
 | 
			
		||||
    descent="-64"
 | 
			
		||||
    bbox="-0.0663408 -64.0662 640.01 448.1"
 | 
			
		||||
    underline-thickness="25"
 | 
			
		||||
    underline-position="-51"
 | 
			
		||||
    underline-position="-50"
 | 
			
		||||
    unicode-range="U+0020-F5C8"
 | 
			
		||||
  />
 | 
			
		||||
    <missing-glyph />
 | 
			
		||||
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 141 KiB After Width: | Height: | Size: 141 KiB  | 
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							@ -1,12 +1,12 @@
 | 
			
		||||
<?xml version="1.0" standalone="no"?>
 | 
			
		||||
<!--
 | 
			
		||||
Font Awesome Free 5.9.0 by @fontawesome - https://fontawesome.com
 | 
			
		||||
Font Awesome Free 5.10.2 by @fontawesome - https://fontawesome.com
 | 
			
		||||
License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
 | 
			
		||||
-->
 | 
			
		||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
 | 
			
		||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
 | 
			
		||||
<metadata>
 | 
			
		||||
Created by FontForge 20190112 at Tue Jun  4 15:16:44 2019
 | 
			
		||||
Created by FontForge 20190801 at Thu Aug 22 14:41:09 2019
 | 
			
		||||
 By Robert Madole
 | 
			
		||||
Copyright (c) Font Awesome
 | 
			
		||||
</metadata>
 | 
			
		||||
@ -22,7 +22,7 @@ Copyright (c) Font Awesome
 | 
			
		||||
    descent="-64"
 | 
			
		||||
    bbox="-0.983398 -64.9834 640.104 448.427"
 | 
			
		||||
    underline-thickness="25"
 | 
			
		||||
    underline-position="-51"
 | 
			
		||||
    underline-position="-50"
 | 
			
		||||
    unicode-range="U+0020-F897"
 | 
			
		||||
  />
 | 
			
		||||
    <missing-glyph />
 | 
			
		||||
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 820 KiB After Width: | Height: | Size: 820 KiB  | 
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							@ -10,7 +10,7 @@
 | 
			
		||||
/******/ 		var moduleId, chunkId, i = 0, resolves = [];
 | 
			
		||||
/******/ 		for(;i < chunkIds.length; i++) {
 | 
			
		||||
/******/ 			chunkId = chunkIds[i];
 | 
			
		||||
/******/ 			if(installedChunks[chunkId]) {
 | 
			
		||||
/******/ 			if(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) {
 | 
			
		||||
/******/ 				resolves.push(installedChunks[chunkId][0]);
 | 
			
		||||
/******/ 			}
 | 
			
		||||
/******/ 			installedChunks[chunkId] = 0;
 | 
			
		||||
@ -148,278 +148,117 @@
 | 
			
		||||
/******/
 | 
			
		||||
/******/
 | 
			
		||||
/******/ 	// add entry module to deferred list
 | 
			
		||||
/******/ 	deferredModules.push(["./assets/index.js","vendor","admin"]);
 | 
			
		||||
/******/ 	deferredModules.push(["./assets/public/index.js","vendor"]);
 | 
			
		||||
/******/ 	// run deferred modules when ready
 | 
			
		||||
/******/ 	return checkDeferredModules();
 | 
			
		||||
/******/ })
 | 
			
		||||
/************************************************************************/
 | 
			
		||||
/******/ ({
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/index.js":
 | 
			
		||||
/*!*************************!*\
 | 
			
		||||
  !*** ./assets/index.js ***!
 | 
			
		||||
  \*************************/
 | 
			
		||||
/*! no exports provided */
 | 
			
		||||
/*! all exports used */
 | 
			
		||||
/***/ "./assets/public/app.js":
 | 
			
		||||
/*!******************************!*\
 | 
			
		||||
  !*** ./assets/public/app.js ***!
 | 
			
		||||
  \******************************/
 | 
			
		||||
/*! exports provided: app, default */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _fortawesome_fontawesome_free_css_all_min_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @fortawesome/fontawesome-free/css/all.min.css */ \"./node_modules/@fortawesome/fontawesome-free/css/all.min.css\");\n/* harmony import */ var _fortawesome_fontawesome_free_css_all_min_css__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_fortawesome_fontawesome_free_css_all_min_css__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _fortawesome_fontawesome_free_css_fontawesome_min_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @fortawesome/fontawesome-free/css/fontawesome.min.css */ \"./node_modules/@fortawesome/fontawesome-free/css/fontawesome.min.css\");\n/* harmony import */ var _fortawesome_fontawesome_free_css_fontawesome_min_css__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_fortawesome_fontawesome_free_css_fontawesome_min_css__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./js */ \"./assets/js/index.js\");\n/* harmony import */ var _vue__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./vue */ \"./assets/vue/index.js\");\n/* harmony import */ var _styles_scss__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./styles.scss */ \"./assets/styles.scss\");\n/* harmony import */ var _styles_scss__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_styles_scss__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var _admin__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./admin */ \"./assets/admin/index.js\");\n\n\n\n\n\n\n\n// import './noscript.scss';\n\n\n\n\n//# sourceURL=webpack:///./assets/index.js?");
 | 
			
		||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"app\", function() { return app; });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.browser.js\");\n\n\n\nvar app = null;\n/* harmony default export */ __webpack_exports__[\"default\"] = (app);\n\nfunction loadApp() {\n    app = new vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"]({\n      el: '#app',\n      delimiters: [ '[[', ']]' ],\n    })\n}\n\nwindow.addEventListener('load', loadApp);\n\n\n\n\n\n//# sourceURL=webpack:///./assets/public/app.js?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/js/app.js":
 | 
			
		||||
/*!**************************!*\
 | 
			
		||||
  !*** ./assets/js/app.js ***!
 | 
			
		||||
  \**************************/
 | 
			
		||||
/*! exports provided: app */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("/* unused harmony export app */\n/* 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\nvar app = null;\n\nfunction loadApp() {\n    app = new vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"]({\n      el: '#app',\n      delimiters: [ '[[', ']]' ],\n    })\n}\n\n\nwindow.addEventListener('load', loadApp);\n\n\n\n\n//# sourceURL=webpack:///./assets/js/app.js?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/js/index.js":
 | 
			
		||||
/*!****************************!*\
 | 
			
		||||
  !*** ./assets/js/index.js ***!
 | 
			
		||||
  \****************************/
 | 
			
		||||
/***/ "./assets/public/index.js":
 | 
			
		||||
/*!********************************!*\
 | 
			
		||||
  !*** ./assets/public/index.js ***!
 | 
			
		||||
  \********************************/
 | 
			
		||||
/*! no exports provided */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("/* harmony import */ var _app__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./app */ \"./assets/js/app.js\");\n/* harmony import */ var _liveInfo__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./liveInfo */ \"./assets/js/liveInfo.js\");\n\n\n\n\n\n\n//# sourceURL=webpack:///./assets/js/index.js?");
 | 
			
		||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.browser.js\");\n/* harmony import */ var _fortawesome_fontawesome_free_css_all_min_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @fortawesome/fontawesome-free/css/all.min.css */ \"./node_modules/@fortawesome/fontawesome-free/css/all.min.css\");\n/* harmony import */ var _fortawesome_fontawesome_free_css_all_min_css__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_fortawesome_fontawesome_free_css_all_min_css__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _fortawesome_fontawesome_free_css_fontawesome_min_css__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @fortawesome/fontawesome-free/css/fontawesome.min.css */ \"./node_modules/@fortawesome/fontawesome-free/css/fontawesome.min.css\");\n/* harmony import */ var _fortawesome_fontawesome_free_css_fontawesome_min_css__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_fortawesome_fontawesome_free_css_fontawesome_min_css__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var buefy_dist_buefy_css__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! buefy/dist/buefy.css */ \"./node_modules/buefy/dist/buefy.css\");\n/* harmony import */ var buefy_dist_buefy_css__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(buefy_dist_buefy_css__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var _app__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./app */ \"./assets/public/app.js\");\n/* harmony import */ var _liveInfo__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./liveInfo */ \"./assets/public/liveInfo.js\");\n/* harmony import */ var _styles_scss__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./styles.scss */ \"./assets/public/styles.scss\");\n/* harmony import */ var _styles_scss__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(_styles_scss__WEBPACK_IMPORTED_MODULE_6__);\n/* harmony import */ var _player_vue__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./player.vue */ \"./assets/public/player.vue\");\n/**\n * This module includes code available for both the public website and\n * administration interface)\n */\n//-- vendor\n\n\n\n\n\n\n\n//-- aircox\n\n\n\n\n\n\n\nvue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].component('a-player', _player_vue__WEBPACK_IMPORTED_MODULE_7__[\"default\"])\n\n\nwindow.aircox = {\n    app: _app__WEBPACK_IMPORTED_MODULE_4__[\"default\"],\n    LiveInfo: _liveInfo__WEBPACK_IMPORTED_MODULE_5__[\"default\"],\n}\n\n\n\n//# sourceURL=webpack:///./assets/public/index.js?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/js/liveInfo.js":
 | 
			
		||||
/*!*******************************!*\
 | 
			
		||||
  !*** ./assets/js/liveInfo.js ***!
 | 
			
		||||
  \*******************************/
 | 
			
		||||
/***/ "./assets/public/liveInfo.js":
 | 
			
		||||
/*!***********************************!*\
 | 
			
		||||
  !*** ./assets/public/liveInfo.js ***!
 | 
			
		||||
  \***********************************/
 | 
			
		||||
/*! exports provided: default */
 | 
			
		||||
/*! exports used: default */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("\n/* harmony default export */ __webpack_exports__[\"a\"] = (class {\n    constructor(url, timeout) {\n        this.url = url;\n        this.timeout = timeout;\n        this.promise = null;\n        this.items = [];\n    }\n\n    drop() {\n        this.promise = null;\n    }\n\n    fetch() {\n        const promise = fetch(this.url).then(response =>\n            response.ok ? response.json()\n                        : Promise.reject(response)\n        ).then(data => {\n            this.items = data;\n            return this.items\n        })\n\n        this.promise = promise;\n        return promise;\n    }\n\n    refresh() {\n        const promise = this.fetch();\n        promise.then(data => {\n            if(promise != this.promise)\n                return [];\n\n            window.setTimeout(() => this.refresh(), this.timeout*1000)\n        })\n        return promise\n    }\n});\n\n\n//# sourceURL=webpack:///./assets/js/liveInfo.js?");
 | 
			
		||||
eval("__webpack_require__.r(__webpack_exports__);\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (class {\n    constructor(url, timeout) {\n        this.url = url;\n        this.timeout = timeout;\n        this.promise = null;\n        this.items = [];\n    }\n\n    drop() {\n        this.promise = null;\n    }\n\n    fetch() {\n        const promise = fetch(this.url).then(response =>\n            response.ok ? response.json()\n                        : Promise.reject(response)\n        ).then(data => {\n            this.items = data;\n            return this.items\n        })\n\n        this.promise = promise;\n        return promise;\n    }\n\n    refresh() {\n        const promise = this.fetch();\n        promise.then(data => {\n            if(promise != this.promise)\n                return [];\n\n            window.setTimeout(() => this.refresh(), this.timeout*1000)\n        })\n        return promise\n    }\n});\n\n\n//# sourceURL=webpack:///./assets/public/liveInfo.js?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/styles.scss":
 | 
			
		||||
/*!****************************!*\
 | 
			
		||||
  !*** ./assets/styles.scss ***!
 | 
			
		||||
  \****************************/
 | 
			
		||||
/***/ "./assets/public/player.vue":
 | 
			
		||||
/*!**********************************!*\
 | 
			
		||||
  !*** ./assets/public/player.vue ***!
 | 
			
		||||
  \**********************************/
 | 
			
		||||
/*! exports provided: default, State */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _player_vue_vue_type_template_id_42a56ec9___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./player.vue?vue&type=template&id=42a56ec9& */ \"./assets/public/player.vue?vue&type=template&id=42a56ec9&\");\n/* harmony import */ var _player_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./player.vue?vue&type=script&lang=js& */ \"./assets/public/player.vue?vue&type=script&lang=js&\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"State\", function() { return _player_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[\"State\"]; });\n\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\"])(\n  _player_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n  _player_vue_vue_type_template_id_42a56ec9___WEBPACK_IMPORTED_MODULE_0__[\"render\"],\n  _player_vue_vue_type_template_id_42a56ec9___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"],\n  false,\n  null,\n  null,\n  null\n  \n)\n\n/* hot reload */\nif (false) { var api; }\ncomponent.options.__file = \"assets/public/player.vue\"\n/* harmony default export */ __webpack_exports__[\"default\"] = (component.exports);\n\n//# sourceURL=webpack:///./assets/public/player.vue?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/public/player.vue?vue&type=script&lang=js&":
 | 
			
		||||
/*!***********************************************************!*\
 | 
			
		||||
  !*** ./assets/public/player.vue?vue&type=script&lang=js& ***!
 | 
			
		||||
  \***********************************************************/
 | 
			
		||||
/*! exports provided: default, State */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_vue_loader_lib_index_js_vue_loader_options_player_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../node_modules/vue-loader/lib??vue-loader-options!./player.vue?vue&type=script&lang=js& */ \"./node_modules/vue-loader/lib/index.js?!./assets/public/player.vue?vue&type=script&lang=js&\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"State\", function() { return _node_modules_vue_loader_lib_index_js_vue_loader_options_player_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__[\"State\"]; });\n\n /* harmony default export */ __webpack_exports__[\"default\"] = (_node_modules_vue_loader_lib_index_js_vue_loader_options_player_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__[\"default\"]); \n\n//# sourceURL=webpack:///./assets/public/player.vue?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/public/player.vue?vue&type=template&id=42a56ec9&":
 | 
			
		||||
/*!*****************************************************************!*\
 | 
			
		||||
  !*** ./assets/public/player.vue?vue&type=template&id=42a56ec9& ***!
 | 
			
		||||
  \*****************************************************************/
 | 
			
		||||
/*! exports provided: render, staticRenderFns */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_player_vue_vue_type_template_id_42a56ec9___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!./player.vue?vue&type=template&id=42a56ec9& */ \"./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/vue-loader/lib/index.js?!./assets/public/player.vue?vue&type=template&id=42a56ec9&\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_player_vue_vue_type_template_id_42a56ec9___WEBPACK_IMPORTED_MODULE_0__[\"render\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_player_vue_vue_type_template_id_42a56ec9___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"]; });\n\n\n\n//# sourceURL=webpack:///./assets/public/player.vue?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/public/styles.scss":
 | 
			
		||||
/*!***********************************!*\
 | 
			
		||||
  !*** ./assets/public/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?");
 | 
			
		||||
eval("// extracted by mini-css-extract-plugin\n\n//# sourceURL=webpack:///./assets/public/styles.scss?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/vue/index.js":
 | 
			
		||||
/*!*****************************!*\
 | 
			
		||||
  !*** ./assets/vue/index.js ***!
 | 
			
		||||
  \*****************************/
 | 
			
		||||
/*! exports provided: Player, 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 _player_vue__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./player.vue */ \"./assets/vue/player.vue\");\n/* harmony import */ var _tab_vue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./tab.vue */ \"./assets/vue/tab.vue\");\n/* harmony import */ var _tabs_vue__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./tabs.vue */ \"./assets/vue/tabs.vue\");\n\n\n\n\n\n\nvue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].component('a-player', _player_vue__WEBPACK_IMPORTED_MODULE_1__[/* default */ \"a\"]);\nvue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].component('a-tab', _tab_vue__WEBPACK_IMPORTED_MODULE_2__[/* default */ \"a\"]);\nvue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].component('a-tabs', _tabs_vue__WEBPACK_IMPORTED_MODULE_3__[/* default */ \"a\"]);\n\n\n\n\n\n\n//# sourceURL=webpack:///./assets/vue/index.js?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/vue/player.vue":
 | 
			
		||||
/*!*******************************!*\
 | 
			
		||||
  !*** ./assets/vue/player.vue ***!
 | 
			
		||||
  \*******************************/
 | 
			
		||||
/*! exports provided: default, State */
 | 
			
		||||
/*! exports used: default */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("/* harmony import */ var _player_vue_vue_type_template_id_2882cef8___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./player.vue?vue&type=template&id=2882cef8& */ \"./assets/vue/player.vue?vue&type=template&id=2882cef8&\");\n/* harmony import */ var _player_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./player.vue?vue&type=script&lang=js& */ \"./assets/vue/player.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  _player_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[/* default */ \"a\"],\n  _player_vue_vue_type_template_id_2882cef8___WEBPACK_IMPORTED_MODULE_0__[/* render */ \"a\"],\n  _player_vue_vue_type_template_id_2882cef8___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/player.vue\"\n/* harmony default export */ __webpack_exports__[\"a\"] = (component.exports);\n\n//# sourceURL=webpack:///./assets/vue/player.vue?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/vue/player.vue?vue&type=script&lang=js&":
 | 
			
		||||
/*!********************************************************!*\
 | 
			
		||||
  !*** ./assets/vue/player.vue?vue&type=script&lang=js& ***!
 | 
			
		||||
  \********************************************************/
 | 
			
		||||
/*! exports provided: default, State */
 | 
			
		||||
/*! 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_player_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../node_modules/vue-loader/lib??vue-loader-options!./player.vue?vue&type=script&lang=js& */ \"./node_modules/vue-loader/lib/index.js?!./assets/vue/player.vue?vue&type=script&lang=js&\");\n /* harmony default export */ __webpack_exports__[\"a\"] = (_node_modules_vue_loader_lib_index_js_vue_loader_options_player_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__[/* default */ \"a\"]); \n\n//# sourceURL=webpack:///./assets/vue/player.vue?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./assets/vue/player.vue?vue&type=template&id=2882cef8&":
 | 
			
		||||
/*!**************************************************************!*\
 | 
			
		||||
  !*** ./assets/vue/player.vue?vue&type=template&id=2882cef8& ***!
 | 
			
		||||
  \**************************************************************/
 | 
			
		||||
/*! 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_player_vue_vue_type_template_id_2882cef8___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!./player.vue?vue&type=template&id=2882cef8& */ \"./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/vue-loader/lib/index.js?!./assets/vue/player.vue?vue&type=template&id=2882cef8&\");\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_player_vue_vue_type_template_id_2882cef8___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_player_vue_vue_type_template_id_2882cef8___WEBPACK_IMPORTED_MODULE_0__[\"b\"]; });\n\n\n\n//# sourceURL=webpack:///./assets/vue/player.vue?");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./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/player.vue?vue&type=script&lang=js&":
 | 
			
		||||
/*!**********************************************************************************************************!*\
 | 
			
		||||
  !*** ./node_modules/vue-loader/lib??vue-loader-options!./assets/vue/player.vue?vue&type=script&lang=js& ***!
 | 
			
		||||
  \**********************************************************************************************************/
 | 
			
		||||
/***/ "./node_modules/vue-loader/lib/index.js?!./assets/public/player.vue?vue&type=script&lang=js&":
 | 
			
		||||
/*!*************************************************************************************************************!*\
 | 
			
		||||
  !*** ./node_modules/vue-loader/lib??vue-loader-options!./assets/public/player.vue?vue&type=script&lang=js& ***!
 | 
			
		||||
  \*************************************************************************************************************/
 | 
			
		||||
/*! exports provided: State, default */
 | 
			
		||||
/*! exports used: default */
 | 
			
		||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
eval("/* unused harmony export State */\n/* harmony import */ var js_liveInfo__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! js/liveInfo */ \"./assets/js/liveInfo.js\");\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n\n\n\nconst State = {\n    paused: 0,\n    playing: 1,\n    loading: 2,\n}\n\n/* harmony default export */ __webpack_exports__[\"a\"] = ({\n    data() {\n        return {\n            state: State.paused,\n            liveInfo: new js_liveInfo__WEBPACK_IMPORTED_MODULE_0__[/* default */ \"a\"](this.liveInfoUrl, this.liveInfoTimeout),\n        }\n    },\n\n    props: {\n        buttonTitle: String,\n        liveInfoUrl: String,\n        liveInfoTimeout: { type: Number, default: 5},\n        src: String,\n    },\n\n    computed: {\n        paused() { return this.state == State.paused; },\n        playing() { return this.state == State.playing; },\n        loading() { return this.state == State.loading; },\n\n        onAir() {\n            return this.liveInfo.items && this.liveInfo.items[0];\n        },\n\n        buttonStyle() {\n            if(!this.onAir)\n                return;\n            return { backgroundImage: `url(${this.onAir.cover})` }\n        }\n    },\n\n    methods: {\n        load(src) {\n            const audio = this.$refs.audio;\n            audio.src = src;\n            audio.load()\n        },\n\n        play(src) {\n            if(src)\n                this.load(src);\n            this.$refs.audio.play().catch(e => console.error(e))\n        },\n\n        pause() {\n            this.$refs.audio.pause()\n        },\n\n        toggle() {\n            if(this.paused)\n                this.play()\n            else\n                this.pause()\n        },\n\n        onChange(event) {\n            const audio = this.$refs.audio;\n            this.state = audio.paused ? State.paused : State.playing;\n        },\n    },\n\n    mounted() {\n        this.liveInfo.refresh()\n    },\n\n    destroyed() {\n        this.liveInfo.drop()\n    },\n});\n\n\n\n//# sourceURL=webpack:///./assets/vue/player.vue?./node_modules/vue-loader/lib??vue-loader-options");
 | 
			
		||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"State\", function() { return State; });\n/* harmony import */ var _liveInfo__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./liveInfo */ \"./assets/public/liveInfo.js\");\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n\n\n\nconst State = {\n    paused: 0,\n    playing: 1,\n    loading: 2,\n}\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n    data() {\n        return {\n            state: State.paused,\n            liveInfo: new _liveInfo__WEBPACK_IMPORTED_MODULE_0__[\"default\"](this.liveInfoUrl, this.liveInfoTimeout),\n        }\n    },\n\n    props: {\n        buttonTitle: String,\n        liveInfoUrl: String,\n        liveInfoTimeout: { type: Number, default: 5},\n        src: String,\n    },\n\n    computed: {\n        paused() { return this.state == State.paused; },\n        playing() { return this.state == State.playing; },\n        loading() { return this.state == State.loading; },\n\n        onAir() {\n            return this.liveInfo.items && this.liveInfo.items[0];\n        },\n\n        buttonStyle() {\n            if(!this.onAir)\n                return;\n            return { backgroundImage: `url(${this.onAir.cover})` }\n        }\n    },\n\n    methods: {\n        load(src) {\n            const audio = this.$refs.audio;\n            audio.src = src;\n            audio.load()\n        },\n\n        play(src) {\n            if(src)\n                this.load(src);\n            this.$refs.audio.play().catch(e => console.error(e))\n        },\n\n        pause() {\n            this.$refs.audio.pause()\n        },\n\n        toggle() {\n            if(this.paused)\n                this.play()\n            else\n                this.pause()\n        },\n\n        onChange(event) {\n            const audio = this.$refs.audio;\n            this.state = audio.paused ? State.paused : State.playing;\n        },\n    },\n\n    mounted() {\n        this.liveInfo.refresh()\n    },\n\n    destroyed() {\n        this.liveInfo.drop()\n    },\n});\n\n\n\n//# sourceURL=webpack:///./assets/public/player.vue?./node_modules/vue-loader/lib??vue-loader-options");
 | 
			
		||||
 | 
			
		||||
/***/ }),
 | 
			
		||||
 | 
			
		||||
/***/ "./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/player.vue?vue&type=template&id=2882cef8&":
 | 
			
		||||
/*!********************************************************************************************************************************************************************************************!*\
 | 
			
		||||
  !*** ./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib??vue-loader-options!./assets/vue/player.vue?vue&type=template&id=2882cef8& ***!
 | 
			
		||||
  \********************************************************************************************************************************************************************************************/
 | 
			
		||||
/***/ "./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/vue-loader/lib/index.js?!./assets/public/player.vue?vue&type=template&id=42a56ec9&":
 | 
			
		||||
/*!***********************************************************************************************************************************************************************************************!*\
 | 
			
		||||
  !*** ./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib??vue-loader-options!./assets/public/player.vue?vue&type=template&id=42a56ec9& ***!
 | 
			
		||||
  \***********************************************************************************************************************************************************************************************/
 | 
			
		||||
/*! 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(\"div\", { staticClass: \"media\" }, [\n    _c(\"div\", { staticClass: \"media-left\" }, [\n      _c(\n        \"div\",\n        {\n          staticClass: \"button\",\n          attrs: { title: _vm.buttonTitle, \"aria-label\": _vm.buttonTitle },\n          on: {\n            click: function($event) {\n              return _vm.toggle()\n            }\n          }\n        },\n        [\n          _vm.playing\n            ? _c(\"span\", { staticClass: \"fas fa-pause\" })\n            : _c(\"span\", { staticClass: \"fas fa-play\" })\n        ]\n      ),\n      _vm._v(\" \"),\n      _c(\n        \"audio\",\n        {\n          ref: \"audio\",\n          on: {\n            playing: _vm.onChange,\n            ended: _vm.onChange,\n            pause: _vm.onChange\n          }\n        },\n        [_vm._t(\"sources\")],\n        2\n      )\n    ]),\n    _vm._v(\" \"),\n    _vm.onAir && _vm.onAir.cover\n      ? _c(\"div\", { staticClass: \"media-left media-cover\" }, [\n          _c(\"img\", { staticClass: \"cover\", attrs: { src: _vm.onAir.cover } })\n        ])\n      : _vm._e(),\n    _vm._v(\" \"),\n    _vm.onAir && _vm.onAir.type == \"track\"\n      ? _c(\n          \"div\",\n          { staticClass: \"media-content\" },\n          [_vm._t(\"track\", null, { onAir: _vm.onAir, liveInfo: _vm.liveInfo })],\n          2\n        )\n      : _vm.onAir && _vm.onAir.type == \"diffusion\"\n      ? _c(\n          \"div\",\n          { staticClass: \"media-content\" },\n          [\n            _vm._t(\"diffusion\", null, {\n              onAir: _vm.onAir,\n              liveInfo: _vm.liveInfo\n            })\n          ],\n          2\n        )\n      : _c(\"div\", { staticClass: \"media-content\" }, [_vm._t(\"empty\")], 2)\n  ])\n}\nvar staticRenderFns = []\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./assets/vue/player.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/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 is-medium\" }, [\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");
 | 
			
		||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return render; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", 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(\"div\", { staticClass: \"media\" }, [\n    _c(\"div\", { staticClass: \"media-left\" }, [\n      _c(\n        \"div\",\n        {\n          staticClass: \"button\",\n          attrs: { title: _vm.buttonTitle, \"aria-label\": _vm.buttonTitle },\n          on: {\n            click: function($event) {\n              return _vm.toggle()\n            }\n          }\n        },\n        [\n          _vm.playing\n            ? _c(\"span\", { staticClass: \"fas fa-pause\" })\n            : _c(\"span\", { staticClass: \"fas fa-play\" })\n        ]\n      ),\n      _vm._v(\" \"),\n      _c(\n        \"audio\",\n        {\n          ref: \"audio\",\n          on: {\n            playing: _vm.onChange,\n            ended: _vm.onChange,\n            pause: _vm.onChange\n          }\n        },\n        [_vm._t(\"sources\")],\n        2\n      )\n    ]),\n    _vm._v(\" \"),\n    _vm.onAir && _vm.onAir.cover\n      ? _c(\"div\", { staticClass: \"media-left media-cover\" }, [\n          _c(\"img\", { staticClass: \"cover\", attrs: { src: _vm.onAir.cover } })\n        ])\n      : _vm._e(),\n    _vm._v(\" \"),\n    _vm.onAir && _vm.onAir.type == \"track\"\n      ? _c(\n          \"div\",\n          { staticClass: \"media-content\" },\n          [_vm._t(\"track\", null, { onAir: _vm.onAir, liveInfo: _vm.liveInfo })],\n          2\n        )\n      : _vm.onAir && _vm.onAir.type == \"diffusion\"\n      ? _c(\n          \"div\",\n          { staticClass: \"media-content\" },\n          [\n            _vm._t(\"diffusion\", null, {\n              onAir: _vm.onAir,\n              liveInfo: _vm.liveInfo\n            })\n          ],\n          2\n        )\n      : _c(\"div\", { staticClass: \"media-content\" }, [_vm._t(\"empty\")], 2)\n  ])\n}\nvar staticRenderFns = []\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./assets/public/player.vue?./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib??vue-loader-options");
 | 
			
		||||
 | 
			
		||||
/***/ })
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@ -1,12 +1,67 @@
 | 
			
		||||
{% extends "admin/base_site.html" %}
 | 
			
		||||
{% load i18n %}
 | 
			
		||||
{% load i18n aircox %}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
{% block content %}{{ block.super }}
 | 
			
		||||
<table class="table">
 | 
			
		||||
{# TODO: date subtitle #}
 | 
			
		||||
<a-statistics>
 | 
			
		||||
<template v-slot:default="{counts}">
 | 
			
		||||
    <table class="table is-hoverable is-fullwidth">
 | 
			
		||||
        <thead>
 | 
			
		||||
            <tr>
 | 
			
		||||
                <th>{% trans "time" %}</th>
 | 
			
		||||
                <th>{% trans "episode" %}</th>
 | 
			
		||||
                <th>{% trans "track" %}</th>
 | 
			
		||||
                <th>{% trans "tags" %}</th>
 | 
			
		||||
            </tr>
 | 
			
		||||
        </thead>
 | 
			
		||||
        <tbody>
 | 
			
		||||
        {% for object in object_list %}
 | 
			
		||||
        {% with object|get_tracks as tracks %}
 | 
			
		||||
        {% for track in tracks %}
 | 
			
		||||
        <tr>
 | 
			
		||||
            {% if forloop.first %}
 | 
			
		||||
            <td rowspan="{{ tracks|length }}">{{ object.start|time:"H:i" }}</td>
 | 
			
		||||
            <td rowspan="{{ tracks|length }}">{{ object.episode|default:"" }}</td>
 | 
			
		||||
            {% endif %}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
</table>
 | 
			
		||||
            {% if not object|is_diffusion %}
 | 
			
		||||
            {% with track as object %}
 | 
			
		||||
            <td>{% include "aircox/track_item.html" %}</td>
 | 
			
		||||
            {% endwith %}
 | 
			
		||||
            {% with track.tags.all|join:', ' as tags %}
 | 
			
		||||
            <td>
 | 
			
		||||
                {% if tags %}
 | 
			
		||||
                <label class="checkbox">
 | 
			
		||||
                    <input type="checkbox" checked value="{{ tags|escape }}" name="data">
 | 
			
		||||
                    {{ tags }}
 | 
			
		||||
                </label>
 | 
			
		||||
                {% endif %}
 | 
			
		||||
            </td>
 | 
			
		||||
            {% endwith %}
 | 
			
		||||
        {% else %}
 | 
			
		||||
        {% endif %}
 | 
			
		||||
        {% endfor %}
 | 
			
		||||
        <tr>
 | 
			
		||||
        {% endwith %}
 | 
			
		||||
        {% endfor %}
 | 
			
		||||
        </tbody>
 | 
			
		||||
        <tfoot>
 | 
			
		||||
            <tr>
 | 
			
		||||
                <td class="is-size-6">{% trans "Totals" %}</td>
 | 
			
		||||
                <td colspan="100">
 | 
			
		||||
                    <div class="columns is-size-6">
 | 
			
		||||
                        <span v-for="(count, tag) in counts" class="column">
 | 
			
		||||
                            <b>[[ tag ]]</b>
 | 
			
		||||
                            [[ count ]]
 | 
			
		||||
                        </span>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </td>
 | 
			
		||||
            </tr>
 | 
			
		||||
        </tfoot>
 | 
			
		||||
    </table>
 | 
			
		||||
</template>
 | 
			
		||||
</a-statistics>
 | 
			
		||||
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -8,6 +8,9 @@
 | 
			
		||||
<link rel="stylesheet" type="text/css" href="{% static "aircox/main.css" %}">
 | 
			
		||||
<link rel="stylesheet" type="text/css" href="{% static "aircox/admin.css" %}">
 | 
			
		||||
 | 
			
		||||
<script src="{% static "aircox/vendor.js" %}"></script>
 | 
			
		||||
<script src="{% static "aircox/admin.js" %}"></script>
 | 
			
		||||
 | 
			
		||||
{% block extrastyle %}{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% if LANGUAGE_BIDI %}<link rel="stylesheet" type="text/css" href="{% block stylesheet_rtl %}{% static "admin/css/rtl.css" %}{% endblock %}">{% endif %}
 | 
			
		||||
@ -26,7 +29,7 @@
 | 
			
		||||
  data-admin-utc-offset="{% now "Z" %}">
 | 
			
		||||
 | 
			
		||||
<!-- Container -->
 | 
			
		||||
<div id="container">
 | 
			
		||||
<div id="app">
 | 
			
		||||
 | 
			
		||||
    {% if not is_popup %}
 | 
			
		||||
    <!-- Header -->
 | 
			
		||||
@ -59,16 +62,16 @@
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div class="navbar-end">
 | 
			
		||||
                <div class="navbar-item has-dropdown is-hoverable">
 | 
			
		||||
                    <a href="#" class="navbar-link">{% trans "Tools" %}</a>
 | 
			
		||||
                    <div class="navbar-dropdown is-boxed is-right">
 | 
			
		||||
                        <a href="{% url 'admin:tools-stats' %}" class="navbar-item">{% trans "Statistics" %}</a>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div class="navbar-end">
 | 
			
		||||
                <div class="navbar-item has-dropdown is-hoverable">
 | 
			
		||||
                    <a href="{% url "admin:auth_user_change" user.pk %}" class="navbar-link">
 | 
			
		||||
                        {% firstof user.get_short_name user.get_username %}
 | 
			
		||||
 | 
			
		||||
@ -14,10 +14,10 @@ Context:
 | 
			
		||||
        <link rel="icon" href="{% thumbnail site.favicon 32x32 crop %}" />
 | 
			
		||||
 | 
			
		||||
        {% block assets %}
 | 
			
		||||
        <link rel="stylesheet" type="text/css" href="{% static "aircox/main.css" %}"/>
 | 
			
		||||
        <link rel="stylesheet" type="text/css" href="{% static "aircox/vendor.css" %}"/>
 | 
			
		||||
        <script src="{% static "aircox/main.js" %}"></script>
 | 
			
		||||
        <link rel="stylesheet" type="text/css" href="{% static "aircox/main.css" %}"/>
 | 
			
		||||
        <script src="{% static "aircox/vendor.js" %}"></script>
 | 
			
		||||
        <script src="{% static "aircox/main.js" %}"></script>
 | 
			
		||||
        {% endblock %}
 | 
			
		||||
 | 
			
		||||
        <title>
 | 
			
		||||
@ -55,14 +55,19 @@ Context:
 | 
			
		||||
                            {% block header %}
 | 
			
		||||
                            <h1 class="title is-1">{% block title %}{% endblock %}</h1>
 | 
			
		||||
 | 
			
		||||
                            <h3 class="subtitle is-3 columns">
 | 
			
		||||
                                {% block subtitle %}
 | 
			
		||||
                                {% if parent %}
 | 
			
		||||
                                <a href="{{ parent.get_absolute_url }}" class="column">
 | 
			
		||||
                                    ❬ {{ parent.title }}</a></li>
 | 
			
		||||
                                {% endif %}
 | 
			
		||||
                                {% endblock %}
 | 
			
		||||
                            <h3 class="subtitle is-3">
 | 
			
		||||
                                {% block subtitle %}{% endblock %}
 | 
			
		||||
                            </h3>
 | 
			
		||||
 | 
			
		||||
                            <div class="columns is-size-4">
 | 
			
		||||
                            {% block header_meta %}
 | 
			
		||||
                            {% if parent %}
 | 
			
		||||
                            <a href="{{ parent.get_absolute_url }}" class="column">
 | 
			
		||||
                                ❬ {{ parent.title }}</a></li>
 | 
			
		||||
                            {% endif %}
 | 
			
		||||
                            {% endblock %}
 | 
			
		||||
                            </div>
 | 
			
		||||
 | 
			
		||||
                            {% endblock %}
 | 
			
		||||
                        </header>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										44
									
								
								aircox/templates/aircox/diffusion_list.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								aircox/templates/aircox/diffusion_list.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,44 @@
 | 
			
		||||
{% extends "aircox/page.html" %}
 | 
			
		||||
{% load i18n aircox %}
 | 
			
		||||
 | 
			
		||||
{% block title %}
 | 
			
		||||
{% with station.name as station %}
 | 
			
		||||
{% blocktrans %}Today on {{ station }}{% endblocktrans %}
 | 
			
		||||
{% endwith %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block subtitle %}{{ date|date:"l d F Y" }}{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block main %}{{ block.super }}
 | 
			
		||||
<div class="columns">
 | 
			
		||||
 | 
			
		||||
{% with True as hide_schedule %}
 | 
			
		||||
<section class="column">
 | 
			
		||||
    <div id="timetable-{{ date|date:"Y-m-d" }}">
 | 
			
		||||
        {% for diffusion in object_list %}
 | 
			
		||||
        <div class="columns">
 | 
			
		||||
            <div class="column is-one-fifth has-text-right">
 | 
			
		||||
                <time datetime="{{ diffusion.start|date:"c" }}">
 | 
			
		||||
                {{ diffusion.start|date:"H:i" }} - {{ diffusion.end|date:"H:i" }}
 | 
			
		||||
                </time>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="column">
 | 
			
		||||
                {% with diffusion.episode as object %}
 | 
			
		||||
                {% include "aircox/episode_item.html" %}
 | 
			
		||||
                {% endwith %}
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        {% endfor %}
 | 
			
		||||
    </div>
 | 
			
		||||
</section>
 | 
			
		||||
{% endwith %}
 | 
			
		||||
 | 
			
		||||
<nav class="column menu is-one-third-desktop" role="menu">
 | 
			
		||||
    {% with "diffusion-list" as url_name %}
 | 
			
		||||
    {% include "aircox/widgets/dates_menu.html" %}
 | 
			
		||||
    {% endwith %}
 | 
			
		||||
</nav>
 | 
			
		||||
 | 
			
		||||
</div>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
@ -1,62 +0,0 @@
 | 
			
		||||
{% extends "aircox/page.html" %}
 | 
			
		||||
{% load i18n aircox %}
 | 
			
		||||
 | 
			
		||||
{% block title %}
 | 
			
		||||
{% with station.name as station %}
 | 
			
		||||
{% blocktrans %}This week's shows... {% endblocktrans %}
 | 
			
		||||
{% endwith %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block subtitle %}
 | 
			
		||||
<div class="column">
 | 
			
		||||
{% blocktrans %}From <b>{{ start }}</b> to <b>{{ end }}</b>{% endblocktrans %}
 | 
			
		||||
</div>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block main %}{{ block.super }}
 | 
			
		||||
{% with True as hide_schedule %}
 | 
			
		||||
<section>
 | 
			
		||||
    {% 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 %}">❬ {% trans "Before" %}</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 %}">{% trans "After" %} ❭</a>
 | 
			
		||||
            </li>
 | 
			
		||||
        </template>
 | 
			
		||||
 | 
			
		||||
        <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 diffusion in diffusions %}
 | 
			
		||||
                <div class="columns">
 | 
			
		||||
                    <div class="column is-one-fifth has-text-right">
 | 
			
		||||
                        <time datetime="{{ diffusion.start|date:"c" }}">
 | 
			
		||||
                        {{ diffusion.start|date:"H:i" }} - {{ diffusion.end|date:"H:i" }}
 | 
			
		||||
                        </time>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="column">
 | 
			
		||||
                        {% with diffusion.episode as object %}
 | 
			
		||||
                        {% include "aircox/episode_item.html" %}
 | 
			
		||||
                        {% endwith %}
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                {% endfor %}
 | 
			
		||||
            </div>
 | 
			
		||||
            {% endfor %}
 | 
			
		||||
        </template>
 | 
			
		||||
    </a-tabs>
 | 
			
		||||
</section>
 | 
			
		||||
{% endwith %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
@ -16,13 +16,8 @@ for design review.
 | 
			
		||||
    {% endwith %}
 | 
			
		||||
    {% endwith %}
 | 
			
		||||
{% else %}
 | 
			
		||||
    {% with object.track as track %}
 | 
			
		||||
    <span class="has-text-info is-size-5">♬</span>
 | 
			
		||||
    <span>{{ track.title }}</span>
 | 
			
		||||
    <span class="has-text-grey-dark has-text-weight-light">
 | 
			
		||||
    — {{ track.artist }}
 | 
			
		||||
    {% if track.info %}(<i>{{ track.info }}</i>){% endif %}
 | 
			
		||||
    </span>
 | 
			
		||||
    {% with object.track as object %}
 | 
			
		||||
    {% include "aircox/track_item.html" %}
 | 
			
		||||
    {% endwith %}
 | 
			
		||||
{% endif %}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,31 +1,20 @@
 | 
			
		||||
{% extends "aircox/page.html" %}
 | 
			
		||||
{% load i18n aircox %}
 | 
			
		||||
{% load i18n humanize aircox %}
 | 
			
		||||
 | 
			
		||||
{% block title %}
 | 
			
		||||
{% trans "Logs" %}
 | 
			
		||||
{% with station.name as station %}
 | 
			
		||||
{% blocktrans %}That happened on {{ station }}{% endblocktrans %}
 | 
			
		||||
{% endwith %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
{% block subtitle %}{{ date|date:"l d F Y" }}{% endblock %}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
{% block main %}
 | 
			
		||||
<section class="section">
 | 
			
		||||
    {% if dates %}
 | 
			
		||||
    <nav class="tabs is-medium 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 %}
 | 
			
		||||
<div class="columns">
 | 
			
		||||
 | 
			
		||||
<section class="section column">
 | 
			
		||||
    {# <h4 class="subtitle size-4">{{ date }}</h4> #}
 | 
			
		||||
    {% with True as hide_schedule %}
 | 
			
		||||
    <table class="table is-striped is-hoverable is-fullwidth has-background-transparent">
 | 
			
		||||
@ -48,5 +37,13 @@
 | 
			
		||||
    </table>
 | 
			
		||||
    {% endwith %}
 | 
			
		||||
</section>
 | 
			
		||||
 | 
			
		||||
<nav class="column menu is-one-third-desktop" role="menu">
 | 
			
		||||
    {% with "logs" as url_name %}
 | 
			
		||||
    {% include "aircox/widgets/dates_menu.html" %}
 | 
			
		||||
    {% endwith %}
 | 
			
		||||
</nav>
 | 
			
		||||
 | 
			
		||||
</div>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -6,12 +6,11 @@ Context:
 | 
			
		||||
- page: page
 | 
			
		||||
{% endcomment %}
 | 
			
		||||
 | 
			
		||||
{% block subtitle %}
 | 
			
		||||
{{ block.super }}
 | 
			
		||||
{% if page.category %}
 | 
			
		||||
{% block header_meta %}{{ block.super }}
 | 
			
		||||
<span class="column has-text-right">{{ object.category.title }}</span>
 | 
			
		||||
{% endif %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
{% endif %}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
{% block main %}
 | 
			
		||||
@ -51,7 +50,9 @@ Context:
 | 
			
		||||
        {% for field in comment_form %}
 | 
			
		||||
        <div class="field is-horizontal">
 | 
			
		||||
            <div class="field-label is-normal">
 | 
			
		||||
                <label class="label">{{ field.label_tag }}</label>
 | 
			
		||||
                <label class="label">
 | 
			
		||||
                    {{ field.label_tag }}
 | 
			
		||||
                </label>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="field-body">
 | 
			
		||||
                <div class="field">
 | 
			
		||||
 | 
			
		||||
@ -4,9 +4,8 @@
 | 
			
		||||
<br>
 | 
			
		||||
 | 
			
		||||
<div class="box is-fullwidth is-fixed-bottom is-paddingless player"
 | 
			
		||||
        aria-role="{% trans "player" %}"
 | 
			
		||||
        aria-description="{% trans "audio player used to listen to streams and podcasts" %}"
 | 
			
		||||
    >
 | 
			
		||||
    role="{% trans "player" %}"
 | 
			
		||||
    aria-description="{% trans "audio player used to listen to the radio" %}">
 | 
			
		||||
    <noscript>
 | 
			
		||||
        <audio src="{{ audio_streams.0 }}" controls>
 | 
			
		||||
            {% for stream in audio_streams %}
 | 
			
		||||
@ -18,7 +17,7 @@
 | 
			
		||||
 | 
			
		||||
    <a-player ref="player" src="{{ audio_streams.0 }}"
 | 
			
		||||
            live-info-url="{% url "api-live" %}" :live-info-timeout="15"
 | 
			
		||||
            button-title="{% trans "Play/pause audio" %}">
 | 
			
		||||
            button-title="{% trans "Play or pause audio" %}">
 | 
			
		||||
        <template v-slot:sources>
 | 
			
		||||
            {% for stream in audio_streams %}
 | 
			
		||||
            <source src="{{ stream }}" />
 | 
			
		||||
 | 
			
		||||
@ -16,7 +16,7 @@
 | 
			
		||||
    <nav class="pagination is-centered">
 | 
			
		||||
        <ul class="pagination-list">
 | 
			
		||||
            <li>
 | 
			
		||||
                <a href="{% url "diffusion-list" parent_slug=program.slug %}"
 | 
			
		||||
                <a href="{% url "episode-list" parent_slug=program.slug %}"
 | 
			
		||||
                    class="pagination-link"
 | 
			
		||||
                    aria-label="{% trans "Show all program's diffusions" %}">
 | 
			
		||||
                    {% trans "More shows" %}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										12
									
								
								aircox/templates/aircox/track_item.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								aircox/templates/aircox/track_item.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
			
		||||
{% comment %}
 | 
			
		||||
Context:
 | 
			
		||||
- object: track to render
 | 
			
		||||
{% endcomment %}
 | 
			
		||||
 | 
			
		||||
<span class="has-text-info is-size-5">♬</span>
 | 
			
		||||
<span>{{ track.title }}</span>
 | 
			
		||||
<span class="has-text-grey-dark has-text-weight-light">
 | 
			
		||||
— {{ track.artist }}
 | 
			
		||||
{% if track.info %}(<i>{{ track.info }}</i>){% endif %}
 | 
			
		||||
</span>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										48
									
								
								aircox/templates/aircox/widgets/dates_menu.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								aircox/templates/aircox/widgets/dates_menu.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,48 @@
 | 
			
		||||
{% comment %}
 | 
			
		||||
Render a navigation menu for dates
 | 
			
		||||
 | 
			
		||||
Context:
 | 
			
		||||
- url_name: url name
 | 
			
		||||
- date: current date
 | 
			
		||||
- input_type: date input type
 | 
			
		||||
- dates: dates to display as a list of `(date|None, title|None)`.
 | 
			
		||||
 | 
			
		||||
An empty date results to a title or a separator
 | 
			
		||||
{% endcomment %}
 | 
			
		||||
{% load i18n humanize %}
 | 
			
		||||
 | 
			
		||||
<nav class="menu is-one-third-desktop " role="menu"
 | 
			
		||||
        aria-label="{% trans "pick a date" %}">
 | 
			
		||||
    <p class="menu-label">{% trans "Pick a date" %}</p>
 | 
			
		||||
    <form action="{% url url_name %}" method="GET"
 | 
			
		||||
            aria-label="{% trans "Jump to date" %}">
 | 
			
		||||
        <div class="field has-addons">
 | 
			
		||||
            <div class="control has-icons-left">
 | 
			
		||||
                <span class="icon is-small is-left"><span class="far fa-calendar"></span></span>
 | 
			
		||||
                <input type="{{ date_input|default:"date" }}" class="input date"
 | 
			
		||||
                       name="date" value="{{ date|date:"Y-m-d" }}">
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="control">
 | 
			
		||||
                <button class="button is-primary">{% trans "Go" %}</button>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </form>
 | 
			
		||||
 | 
			
		||||
    <ul class="menu-list">
 | 
			
		||||
        {% for day, title in dates %}
 | 
			
		||||
        {% if not day %}
 | 
			
		||||
            {% if title %}
 | 
			
		||||
            </ul>
 | 
			
		||||
            <p class="menu-label">{{ title }}</p>
 | 
			
		||||
            <ul class="menu-list">
 | 
			
		||||
            {% else %}<hr class="dropdown-divider">{% endif %}
 | 
			
		||||
        {% else %}
 | 
			
		||||
        <li><a href="{% url url_name date=day %}" {% if day == date %}class="is-active"{% endif %}>
 | 
			
		||||
            {% if title %}{{ title }}{% else %}{{ day|naturalday:"l d" }}{% endif %}
 | 
			
		||||
            </a></li>
 | 
			
		||||
        {% endif %}
 | 
			
		||||
        {% endfor %}
 | 
			
		||||
    </ul>
 | 
			
		||||
</nav>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,7 @@ import random
 | 
			
		||||
 | 
			
		||||
from django import template
 | 
			
		||||
 | 
			
		||||
from aircox.models import Page, Diffusion
 | 
			
		||||
from aircox.models import Page, Diffusion, Log
 | 
			
		||||
 | 
			
		||||
random.seed()
 | 
			
		||||
register = template.Library()
 | 
			
		||||
@ -24,15 +24,21 @@ def do_update_query(obj, **kwargs):
 | 
			
		||||
            obj.pop(k)
 | 
			
		||||
    return obj
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@register.filter(name='is_diffusion')
 | 
			
		||||
def do_is_diffusion(obj):
 | 
			
		||||
    return isinstance(obj, Diffusion)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@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='get_tracks')
 | 
			
		||||
def do_get_tracks(obj):
 | 
			
		||||
    """ Get a list of track for the provided log, diffusion, or episode """
 | 
			
		||||
    if isinstance(obj, Log):
 | 
			
		||||
        return (obj.track,)
 | 
			
		||||
 | 
			
		||||
    if isinstance(obj, Diffusion):
 | 
			
		||||
        obj = obj.episode
 | 
			
		||||
    return obj.track_set.all()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@register.simple_tag(name='nav_items', takes_context=True)
 | 
			
		||||
@ -42,3 +48,12 @@ def do_nav_items(context, menu, **kwargs):
 | 
			
		||||
            for item in station.navitem_set.filter(menu=menu)]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# FIXME: used?
 | 
			
		||||
@register.simple_tag(name='unique_id')
 | 
			
		||||
def do_unique_id(prefix=''):
 | 
			
		||||
    value = str(random.random()).replace('.', '')
 | 
			
		||||
    return prefix + '_' + value if prefix else value
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -19,7 +19,7 @@ register_converter(WeekConverter, 'week')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
api = [
 | 
			
		||||
    path('live/', views.api.LiveAPIView.as_view(), name='api-live'),
 | 
			
		||||
    path('logs/', views.api.LogListAPIView.as_view(), name='api-live'),
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -40,18 +40,18 @@ urls = [
 | 
			
		||||
    path(_('programs/<slug:slug>/'),
 | 
			
		||||
         views.ProgramDetailView.as_view(), name='program-detail'),
 | 
			
		||||
    path(_('programs/<slug:parent_slug>/episodes/'),
 | 
			
		||||
         views.EpisodeListView.as_view(), name='diffusion-list'),
 | 
			
		||||
         views.EpisodeListView.as_view(), name='episode-list'),
 | 
			
		||||
    path(_('programs/<slug:parent_slug>/articles/'),
 | 
			
		||||
         views.ArticleListView.as_view(), name='article-list'),
 | 
			
		||||
 | 
			
		||||
    path(_('episodes/'),
 | 
			
		||||
         views.EpisodeListView.as_view(), name='diffusion-list'),
 | 
			
		||||
         views.EpisodeListView.as_view(), name='episode-list'),
 | 
			
		||||
    path(_('episodes/<slug:slug>/'),
 | 
			
		||||
         views.EpisodeDetailView.as_view(), name='episode-detail'),
 | 
			
		||||
    path(_('week/'),
 | 
			
		||||
         views.TimetableView.as_view(), name='timetable'),
 | 
			
		||||
    path(_('week/<week:date>/'),
 | 
			
		||||
         views.TimetableView.as_view(), name='timetable'),
 | 
			
		||||
         views.DiffusionListView.as_view(), name='diffusion-list'),
 | 
			
		||||
    path(_('week/<date:date>/'),
 | 
			
		||||
         views.DiffusionListView.as_view(), name='diffusion-list'),
 | 
			
		||||
 | 
			
		||||
    path(_('logs/'), views.LogListView.as_view(), name='logs'),
 | 
			
		||||
    path(_('logs/<date:date>/'), views.LogListView.as_view(), name='logs'),
 | 
			
		||||
 | 
			
		||||
@ -20,6 +20,19 @@ def redirect(url):
 | 
			
		||||
    raise Redirect(url)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def str_to_date(value, sep='/'):
 | 
			
		||||
    """
 | 
			
		||||
    Return a date from the provided `value` string, formated as "yyyy/mm/dd"
 | 
			
		||||
    (or "dd/mm/yyyy" if `reverse` is True).
 | 
			
		||||
 | 
			
		||||
    Raises ValueError for incorrect value format.
 | 
			
		||||
    """
 | 
			
		||||
    value = value.split(sep)[:3]
 | 
			
		||||
    if len(value) < 3:
 | 
			
		||||
        return ValueError('incorrect date format')
 | 
			
		||||
    return datetime.date(int(value[0]), int(value[1]), int(value[2]))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def date_range(date, delta=None, **delta_kwargs):
 | 
			
		||||
    """
 | 
			
		||||
    Return a range of provided date such as `[date-delta, date+delta]`.
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,7 @@ from . import api, admin
 | 
			
		||||
 | 
			
		||||
from .article import ArticleDetailView, ArticleListView
 | 
			
		||||
from .base import BaseView
 | 
			
		||||
from .episode import EpisodeDetailView, EpisodeListView, TimetableView
 | 
			
		||||
from .episode import EpisodeDetailView, EpisodeListView, DiffusionListView
 | 
			
		||||
from .log import LogListView
 | 
			
		||||
from .page import PageDetailView, PageListView
 | 
			
		||||
from .program import ProgramDetailView
 | 
			
		||||
 | 
			
		||||
@ -10,7 +10,7 @@ from django.utils.translation import ugettext_lazy as _
 | 
			
		||||
from django.views.generic import ListView
 | 
			
		||||
 | 
			
		||||
from ..models import Program
 | 
			
		||||
from .log import BaseLogListView
 | 
			
		||||
from .log import LogListView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BaseAdminView(LoginRequiredMixin, UserPassesTestMixin):
 | 
			
		||||
@ -25,20 +25,13 @@ class BaseAdminView(LoginRequiredMixin, UserPassesTestMixin):
 | 
			
		||||
        return super().get_context_data(**kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class StatisticsView(BaseAdminView, BaseLogListView, ListView):
 | 
			
		||||
class StatisticsView(BaseAdminView, LogListView, ListView):
 | 
			
		||||
    template_name = 'admin/aircox/statistics.html'
 | 
			
		||||
    title = _('Statistics')
 | 
			
		||||
    date = None
 | 
			
		||||
 | 
			
		||||
    def get_queryset(self):
 | 
			
		||||
        return super().get_queryset().today(self.date)
 | 
			
		||||
 | 
			
		||||
    def get_diffusions_queryset(self):
 | 
			
		||||
        return super().get_diffusions_queryset().today(self.date)
 | 
			
		||||
 | 
			
		||||
    def get(self, request, *args, date=None, **kwargs):
 | 
			
		||||
        self.date = datetime.date.today() if date is None else date
 | 
			
		||||
        return super().get(request, *args, date=date, **kwargs)
 | 
			
		||||
    def get_object_list(self, logs, *_):
 | 
			
		||||
        return super().get_object_list(logs, True)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AdminSite(admin.AdminSite):
 | 
			
		||||
 | 
			
		||||
@ -4,9 +4,10 @@ from django.utils import timezone as tz
 | 
			
		||||
 | 
			
		||||
from rest_framework.generics import ListAPIView
 | 
			
		||||
 | 
			
		||||
from ..utils import str_to_date
 | 
			
		||||
from ..models import Log
 | 
			
		||||
from ..serializers import LogInfo, LogInfoSerializer
 | 
			
		||||
from .log import BaseLogListView
 | 
			
		||||
from .log import LogListMixin
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BaseAPIView:
 | 
			
		||||
@ -18,28 +19,30 @@ class BaseAPIView:
 | 
			
		||||
        return super().get_queryset().station(self.station)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class LiveAPIView(BaseLogListView, BaseAPIView, ListAPIView):
 | 
			
		||||
class LogListAPIView(LogListMixin, BaseAPIView, ListAPIView):
 | 
			
		||||
    """
 | 
			
		||||
    Return logs list, including diffusions. By default return logs of
 | 
			
		||||
    the last 30 minutes.
 | 
			
		||||
 | 
			
		||||
    Available GET parameters:
 | 
			
		||||
    - "date": return logs for a specified date (
 | 
			
		||||
    - "full": (staff user only) don't merge diffusion and logs
 | 
			
		||||
    """
 | 
			
		||||
    serializer_class = LogInfoSerializer
 | 
			
		||||
    min_date = None
 | 
			
		||||
    queryset = Log.objects.all()
 | 
			
		||||
 | 
			
		||||
    def get(self, *args, **kwargs):
 | 
			
		||||
        self.min_date = tz.now() - tz.timedelta(minutes=20)
 | 
			
		||||
        self.date = self.get_date()
 | 
			
		||||
        if self.date is None:
 | 
			
		||||
            self.min_date = tz.now() - tz.timedelta(minutes=30)
 | 
			
		||||
        return super().get(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    def get_object_list(self, logs, full):
 | 
			
		||||
        return [LogInfo(obj) for obj in super().get_object_list(logs, full)]
 | 
			
		||||
 | 
			
		||||
    def get_serializer(self, queryset, *args, **kwargs):
 | 
			
		||||
        queryset = Log.merge_diffusions(self.get_queryset(),
 | 
			
		||||
                                        self.get_diffusions_queryset())
 | 
			
		||||
        queryset = [LogInfo(obj) for obj in queryset]
 | 
			
		||||
        return super().get_serializer(queryset, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    def get_queryset(self):
 | 
			
		||||
        return super().get_queryset().after(self.min_date)
 | 
			
		||||
 | 
			
		||||
    def get_diffusions_queryset(self):
 | 
			
		||||
        return super().get_diffusions_queryset().after(self.min_date)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Monitoring
 | 
			
		||||
        full = bool(self.request.GET.get('full'))
 | 
			
		||||
        return super().get_serializer(self.get_object_list(queryset, full),
 | 
			
		||||
                                      *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,6 @@
 | 
			
		||||
from ..models import Article, Program
 | 
			
		||||
from .page import ParentMixin, PageDetailView, PageListView
 | 
			
		||||
from .mixins import ParentMixin
 | 
			
		||||
from .page import PageDetailView, PageListView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ['ArticleDetailView', 'ArticleListView']
 | 
			
		||||
 | 
			
		||||
@ -2,15 +2,16 @@ from collections import OrderedDict
 | 
			
		||||
import datetime
 | 
			
		||||
 | 
			
		||||
from django.views.generic import ListView
 | 
			
		||||
from django.utils.translation import ugettext as _
 | 
			
		||||
 | 
			
		||||
from ..converters import WeekConverter
 | 
			
		||||
from ..models import Diffusion, Episode, Program, Sound
 | 
			
		||||
from .base import BaseView
 | 
			
		||||
from .program import ProgramPageDetailView
 | 
			
		||||
from .page import ParentMixin, PageListView
 | 
			
		||||
from .page import PageListView
 | 
			
		||||
from .mixins import GetDateMixin, ParentMixin
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ['EpisodeDetailView', 'EpisodeListView', 'TimetableView']
 | 
			
		||||
__all__ = ['EpisodeDetailView', 'EpisodeListView', 'DiffusionListView']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EpisodeDetailView(ProgramPageDetailView):
 | 
			
		||||
@ -32,7 +33,6 @@ class EpisodeDetailView(ProgramPageDetailView):
 | 
			
		||||
 | 
			
		||||
class EpisodeListView(ParentMixin, PageListView):
 | 
			
		||||
    model = Episode
 | 
			
		||||
    template_name = 'aircox/diffusion_list.html'
 | 
			
		||||
    item_template_name = 'aircox/episode_item.html'
 | 
			
		||||
    show_headline = True
 | 
			
		||||
 | 
			
		||||
@ -40,44 +40,35 @@ class EpisodeListView(ParentMixin, PageListView):
 | 
			
		||||
    fk_parent = 'program'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TimetableView(BaseView, ListView):
 | 
			
		||||
class DiffusionListView(GetDateMixin, BaseView, ListView):
 | 
			
		||||
    """ View for timetables """
 | 
			
		||||
    template_name_suffix = '_timetable'
 | 
			
		||||
    model = Diffusion
 | 
			
		||||
    # ordering = ('start',)
 | 
			
		||||
 | 
			
		||||
    date = None
 | 
			
		||||
    start = None
 | 
			
		||||
    end = None
 | 
			
		||||
 | 
			
		||||
    def get_date(self):
 | 
			
		||||
        date = super().get_date()
 | 
			
		||||
        return date if date is not None else datetime.date.today()
 | 
			
		||||
 | 
			
		||||
    def get_queryset(self):
 | 
			
		||||
        self.date = self.kwargs.get('date') or datetime.date.today()
 | 
			
		||||
        self.start = self.date - datetime.timedelta(days=self.date.weekday())
 | 
			
		||||
        self.end = self.start + datetime.timedelta(days=7)
 | 
			
		||||
        return super().get_queryset().range(self.start, self.end) \
 | 
			
		||||
                                     .order_by('start')
 | 
			
		||||
        return super().get_queryset().today(self.date).order_by('start')
 | 
			
		||||
 | 
			
		||||
    def get_context_data(self, **kwargs):
 | 
			
		||||
        # regoup by dates
 | 
			
		||||
        by_date = OrderedDict()
 | 
			
		||||
        date = self.start
 | 
			
		||||
        while date < self.end:
 | 
			
		||||
            by_date[date] = []
 | 
			
		||||
            date += datetime.timedelta(days=1)
 | 
			
		||||
 | 
			
		||||
        for diffusion in self.object_list:
 | 
			
		||||
            if diffusion.date not in by_date:
 | 
			
		||||
                continue
 | 
			
		||||
            by_date[diffusion.date].append(diffusion)
 | 
			
		||||
 | 
			
		||||
        return super().get_context_data(
 | 
			
		||||
            by_date=by_date,
 | 
			
		||||
            date=self.date,
 | 
			
		||||
            start=self.start,
 | 
			
		||||
            end=self.end - datetime.timedelta(days=1),
 | 
			
		||||
            prev_date=self.start - datetime.timedelta(days=1),
 | 
			
		||||
            next_date=self.end + datetime.timedelta(days=1),
 | 
			
		||||
            **kwargs
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        today = datetime.date.today()
 | 
			
		||||
        start = self.date - datetime.timedelta(days=self.date.weekday())
 | 
			
		||||
        dates = [
 | 
			
		||||
            (today, None),
 | 
			
		||||
            (today - datetime.timedelta(days=1), None),
 | 
			
		||||
            (today + datetime.timedelta(days=1), None),
 | 
			
		||||
            (today - datetime.timedelta(days=7), _('next week')),
 | 
			
		||||
            (today + datetime.timedelta(days=7), _('last week')),
 | 
			
		||||
            (None, None)
 | 
			
		||||
        ] + [
 | 
			
		||||
            (date, date.strftime('%A %d'))
 | 
			
		||||
            for date in (start + datetime.timedelta(days=i)
 | 
			
		||||
                         for i in range(0, 7)) if date != today
 | 
			
		||||
        ]
 | 
			
		||||
        return super().get_context_data(date=self.date, dates=dates, **kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -5,56 +5,61 @@ from django.views.generic import ListView
 | 
			
		||||
 | 
			
		||||
from ..models import Diffusion, Log
 | 
			
		||||
from .base import BaseView
 | 
			
		||||
from .mixins import GetDateMixin
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ['BaseLogListView', 'LogListView']
 | 
			
		||||
__all__ = ['LogListMixin', 'LogListView']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BaseLogListView:
 | 
			
		||||
class LogListMixin(GetDateMixin):
 | 
			
		||||
    model = Log
 | 
			
		||||
    date = None
 | 
			
		||||
 | 
			
		||||
    def get_date(self):
 | 
			
		||||
        date, today = super().get_date(), datetime.date.today()
 | 
			
		||||
        if date is not None and not self.request.user.is_staff:
 | 
			
		||||
            return min(date, today)
 | 
			
		||||
        return date
 | 
			
		||||
 | 
			
		||||
    def get_queryset(self):
 | 
			
		||||
        # only get logs for tracks: log for diffusion will be retrieved
 | 
			
		||||
        # by the diffusions' queryset.
 | 
			
		||||
        return super().get_queryset().on_air().filter(track__isnull=False)
 | 
			
		||||
        qs = super().get_queryset().on_air().filter(track__isnull=False)
 | 
			
		||||
        return qs.today(self.date) if self.date is not None else \
 | 
			
		||||
            qs.after(self.min_date) if self.min_date is not None else qs
 | 
			
		||||
 | 
			
		||||
    def get_diffusions_queryset(self):
 | 
			
		||||
        return Diffusion.objects.station(self.station).on_air()
 | 
			
		||||
        qs = Diffusion.objects.station(self.station).on_air()
 | 
			
		||||
        return qs.today(self.date) if self.date is not None else \
 | 
			
		||||
            qs.after(self.min_date) if self.min_date is not None else qs
 | 
			
		||||
 | 
			
		||||
    def get_object_list(self, logs, full=False):
 | 
			
		||||
        """
 | 
			
		||||
        Return diffusions merged to the provided logs queryset. If
 | 
			
		||||
        `full`, sort items by date without merging.
 | 
			
		||||
        """
 | 
			
		||||
        diffs = self.get_diffusions_queryset()
 | 
			
		||||
        if self.request.user.is_staff and full:
 | 
			
		||||
            return sorted(list(logs) + list(diffs), key=lambda obj: obj.start)
 | 
			
		||||
        return Log.merge_diffusions(logs, diffs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class LogListView(BaseView, BaseLogListView, ListView):
 | 
			
		||||
    date = None
 | 
			
		||||
    max_age = 10
 | 
			
		||||
    min_date = None
 | 
			
		||||
 | 
			
		||||
    def get(self, request, *args, **kwargs):
 | 
			
		||||
        today = datetime.date.today()
 | 
			
		||||
        self.min_date = today - datetime.timedelta(days=self.max_age)
 | 
			
		||||
        self.date = min(max(self.min_date, self.kwargs['date']), today) \
 | 
			
		||||
            if 'date' in self.kwargs else today
 | 
			
		||||
        return super().get(request, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    def get_queryset(self):
 | 
			
		||||
        return super().get_queryset().today(self.date)
 | 
			
		||||
 | 
			
		||||
    def get_diffusions_queryset(self):
 | 
			
		||||
        return super().get_diffusions_queryset().today(self.date)
 | 
			
		||||
class LogListView(BaseView, LogListMixin, ListView):
 | 
			
		||||
    """
 | 
			
		||||
    Return list of logs for the provided date (from `kwargs` or
 | 
			
		||||
    `request.GET`, defaults to today).
 | 
			
		||||
    """
 | 
			
		||||
    def get_date(self):
 | 
			
		||||
        date, today = super().get_date(), datetime.date.today()
 | 
			
		||||
        return today if date is None else min(date, today)
 | 
			
		||||
 | 
			
		||||
    def get_context_data(self, **kwargs):
 | 
			
		||||
        today = datetime.date.today()
 | 
			
		||||
        max_date = min(max(self.date + datetime.timedelta(days=3),
 | 
			
		||||
                           self.min_date + datetime.timedelta(days=6)), today)
 | 
			
		||||
 | 
			
		||||
        return super().get_context_data(
 | 
			
		||||
            date=self.date,
 | 
			
		||||
            min_date=self.min_date,
 | 
			
		||||
            dates=(date for date in (
 | 
			
		||||
                max_date - datetime.timedelta(days=i)
 | 
			
		||||
                for i in range(0, 7)) if date >= self.min_date),
 | 
			
		||||
            object_list=Log.merge_diffusions(self.object_list,
 | 
			
		||||
                                             self.get_diffusions_queryset()),
 | 
			
		||||
            **kwargs
 | 
			
		||||
        )
 | 
			
		||||
        kwargs.update({
 | 
			
		||||
            'date': self.date,
 | 
			
		||||
            'dates': ((today - datetime.timedelta(days=i), None)
 | 
			
		||||
                      for i in range(0, 7)),
 | 
			
		||||
            'object_list': self.get_object_list(self.object_list),
 | 
			
		||||
        })
 | 
			
		||||
        return super().get_context_data(**kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										67
									
								
								aircox/views/mixins.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								aircox/views/mixins.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,67 @@
 | 
			
		||||
from django.shortcuts import get_object_or_404
 | 
			
		||||
 | 
			
		||||
from ..utils import str_to_date
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ['GetDateMixin', 'ParentMixin']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class GetDateMixin:
 | 
			
		||||
    """
 | 
			
		||||
    Mixin offering utils to get date by `request.GET` or
 | 
			
		||||
    `kwargs['date']`
 | 
			
		||||
    """
 | 
			
		||||
    date = None
 | 
			
		||||
 | 
			
		||||
    def get_date(self):
 | 
			
		||||
        if 'date' in self.request.GET:
 | 
			
		||||
            return str_to_date(self.request.GET['date'], '-')
 | 
			
		||||
        return self.kwargs['date'] if 'date' in self.kwargs else None
 | 
			
		||||
 | 
			
		||||
    def get(self, *args, **kwargs):
 | 
			
		||||
        self.date = self.get_date()
 | 
			
		||||
        return super().get(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ParentMixin:
 | 
			
		||||
    """
 | 
			
		||||
    Optional parent page for a list view. Parent is fetched and passed to the
 | 
			
		||||
    template context when `parent_model` is provided (queryset is filtered by
 | 
			
		||||
    parent page in such case).
 | 
			
		||||
    """
 | 
			
		||||
    parent_model = None
 | 
			
		||||
    """ Parent model """
 | 
			
		||||
    parent_url_kwarg = 'parent_slug'
 | 
			
		||||
    """ Url lookup argument """
 | 
			
		||||
    parent_field = 'slug'
 | 
			
		||||
    """ Parent field for url lookup """
 | 
			
		||||
    fk_parent = 'page'
 | 
			
		||||
    """ Page foreign key to the parent """
 | 
			
		||||
    parent = None
 | 
			
		||||
    """ Parent page object """
 | 
			
		||||
 | 
			
		||||
    def get_parent(self, request, *args, **kwargs):
 | 
			
		||||
        if self.parent_model is None or self.parent_url_kwarg not in kwargs:
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        lookup = {self.parent_field: kwargs[self.parent_url_kwarg]}
 | 
			
		||||
        return get_object_or_404(
 | 
			
		||||
            self.parent_model.objects.select_related('cover'), **lookup)
 | 
			
		||||
 | 
			
		||||
    def get(self, request, *args, **kwargs):
 | 
			
		||||
        self.parent = self.get_parent(request, *args, **kwargs)
 | 
			
		||||
        return super().get(request, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    def get_queryset(self):
 | 
			
		||||
        if self.parent is not None:
 | 
			
		||||
            lookup = {self.fk_parent: self.parent}
 | 
			
		||||
            return super().get_queryset().filter(**lookup)
 | 
			
		||||
        return super().get_queryset()
 | 
			
		||||
 | 
			
		||||
    def get_context_data(self, **kwargs):
 | 
			
		||||
        parent = kwargs.setdefault('parent', self.parent)
 | 
			
		||||
        if parent is not None:
 | 
			
		||||
            kwargs.setdefault('cover', parent.cover)
 | 
			
		||||
        return super().get_context_data(**kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -12,49 +12,7 @@ from ..utils import Redirect
 | 
			
		||||
from .base import BaseView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ['ParentMixin', 'PageDetailView', 'PageListView']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ParentMixin:
 | 
			
		||||
    """
 | 
			
		||||
    Optional parent page for a list view. Parent is fetched and passed to the
 | 
			
		||||
    template context when `parent_model` is provided (queryset is filtered by
 | 
			
		||||
    parent page in such case).
 | 
			
		||||
    """
 | 
			
		||||
    parent_model = None
 | 
			
		||||
    """ Parent model """
 | 
			
		||||
    parent_url_kwarg = 'parent_slug'
 | 
			
		||||
    """ Url lookup argument """
 | 
			
		||||
    parent_field = 'slug'
 | 
			
		||||
    """ Parent field for url lookup """
 | 
			
		||||
    fk_parent = 'page'
 | 
			
		||||
    """ Page foreign key to the parent """
 | 
			
		||||
    parent = None
 | 
			
		||||
    """ Parent page object """
 | 
			
		||||
 | 
			
		||||
    def get_parent(self, request, *args, **kwargs):
 | 
			
		||||
        if self.parent_model is None or self.parent_url_kwarg not in kwargs:
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        lookup = {self.parent_field: kwargs[self.parent_url_kwarg]}
 | 
			
		||||
        return get_object_or_404(
 | 
			
		||||
            self.parent_model.objects.select_related('cover'), **lookup)
 | 
			
		||||
 | 
			
		||||
    def get(self, request, *args, **kwargs):
 | 
			
		||||
        self.parent = self.get_parent(request, *args, **kwargs)
 | 
			
		||||
        return super().get(request, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    def get_queryset(self):
 | 
			
		||||
        if self.parent is not None:
 | 
			
		||||
            lookup = {self.fk_parent: self.parent}
 | 
			
		||||
            return super().get_queryset().filter(**lookup)
 | 
			
		||||
        return super().get_queryset()
 | 
			
		||||
 | 
			
		||||
    def get_context_data(self, **kwargs):
 | 
			
		||||
        parent = kwargs.setdefault('parent', self.parent)
 | 
			
		||||
        if parent is not None:
 | 
			
		||||
            kwargs.setdefault('cover', parent.cover)
 | 
			
		||||
        return super().get_context_data(**kwargs)
 | 
			
		||||
__all__ = ['PageDetailView', 'PageListView']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# TODO: pagination: in template, only a limited number of pages displayed
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,13 @@
 | 
			
		||||
import Vue from 'vue';
 | 
			
		||||
 | 
			
		||||
import './admin.scss';
 | 
			
		||||
 | 
			
		||||
import Statistics from './statistics.vue';
 | 
			
		||||
 | 
			
		||||
Vue.component('a-statistics', Statistics)
 | 
			
		||||
 | 
			
		||||
import 'public';
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										39
									
								
								assets/admin/statistics.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								assets/admin/statistics.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,39 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <form ref="form">
 | 
			
		||||
        <slot :counts="counts"></slot>
 | 
			
		||||
    </form>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
 | 
			
		||||
const splitReg = new RegExp(`,\s*`, 'g');
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
    data() {
 | 
			
		||||
        return {
 | 
			
		||||
            counts: {},
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    methods: {
 | 
			
		||||
        update() {
 | 
			
		||||
            const items = this.$el.querySelectorAll('input[name="data"]:checked')
 | 
			
		||||
            const counts = {};
 | 
			
		||||
 | 
			
		||||
            console.log(items)
 | 
			
		||||
            for(var item of items)
 | 
			
		||||
                if(item.value)
 | 
			
		||||
                    for(var tag of item.value.split(splitReg))
 | 
			
		||||
                        counts[tag.trim()] = (counts[tag.trim()] || 0) + 1;
 | 
			
		||||
            this.counts = counts;
 | 
			
		||||
            console.log('counts', this.counts)
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    mounted() {
 | 
			
		||||
        this.$refs.form.addEventListener('change', () => this.update())
 | 
			
		||||
        this.update()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
@ -1,10 +0,0 @@
 | 
			
		||||
import '@fortawesome/fontawesome-free/css/all.min.css';
 | 
			
		||||
import '@fortawesome/fontawesome-free/css/fontawesome.min.css';
 | 
			
		||||
 | 
			
		||||
import './js';
 | 
			
		||||
import './vue';
 | 
			
		||||
 | 
			
		||||
import './styles.scss';
 | 
			
		||||
// import './noscript.scss';
 | 
			
		||||
import './admin';
 | 
			
		||||
 | 
			
		||||
@ -1,4 +0,0 @@
 | 
			
		||||
import app from './app';
 | 
			
		||||
import LiveInfo from './liveInfo';
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,6 +0,0 @@
 | 
			
		||||
 | 
			
		||||
/**[noscript="hidden"] {
 | 
			
		||||
    display: none;
 | 
			
		||||
}*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,8 @@
 | 
			
		||||
import Vue from 'vue';
 | 
			
		||||
import Buefy from 'buefy';
 | 
			
		||||
 | 
			
		||||
Vue.use(Buefy);
 | 
			
		||||
 | 
			
		||||
export var app = null;
 | 
			
		||||
export default app;
 | 
			
		||||
 | 
			
		||||
function loadApp() {
 | 
			
		||||
    app = new Vue({
 | 
			
		||||
@ -12,7 +11,7 @@ function loadApp() {
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
window.addEventListener('load', loadApp);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										28
									
								
								assets/public/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								assets/public/index.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
			
		||||
/**
 | 
			
		||||
 * This module includes code available for both the public website and
 | 
			
		||||
 * administration interface)
 | 
			
		||||
 */
 | 
			
		||||
//-- vendor
 | 
			
		||||
import Vue from 'vue';
 | 
			
		||||
 | 
			
		||||
import '@fortawesome/fontawesome-free/css/all.min.css';
 | 
			
		||||
import '@fortawesome/fontawesome-free/css/fontawesome.min.css';
 | 
			
		||||
import 'buefy/dist/buefy.css';
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//-- aircox
 | 
			
		||||
import app from './app';
 | 
			
		||||
import LiveInfo from './liveInfo';
 | 
			
		||||
 | 
			
		||||
import './styles.scss';
 | 
			
		||||
 | 
			
		||||
import Player from './player.vue';
 | 
			
		||||
 | 
			
		||||
Vue.component('a-player', Player)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
window.aircox = {
 | 
			
		||||
    app: app,
 | 
			
		||||
    LiveInfo: LiveInfo,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -26,7 +26,7 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import LiveInfo from 'js/liveInfo';
 | 
			
		||||
import LiveInfo from './liveInfo';
 | 
			
		||||
 | 
			
		||||
export const State = {
 | 
			
		||||
    paused: 0,
 | 
			
		||||
@ -1,28 +0,0 @@
 | 
			
		||||
<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>
 | 
			
		||||
@ -1,13 +0,0 @@
 | 
			
		||||
import Vue from 'vue';
 | 
			
		||||
 | 
			
		||||
import Player from './player.vue';
 | 
			
		||||
import Tab from './tab.vue';
 | 
			
		||||
import Tabs from './tabs.vue';
 | 
			
		||||
 | 
			
		||||
Vue.component('a-player', Player);
 | 
			
		||||
Vue.component('a-tab', Tab);
 | 
			
		||||
Vue.component('a-tabs', Tabs);
 | 
			
		||||
 | 
			
		||||
export {Player, Tab, Tabs};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,31 +0,0 @@
 | 
			
		||||
<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>
 | 
			
		||||
 | 
			
		||||
@ -1,45 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div>
 | 
			
		||||
        <div class="tabs is-centered is-medium">
 | 
			
		||||
            <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>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										12
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								package.json
									
									
									
									
									
								
							@ -6,24 +6,24 @@
 | 
			
		||||
  "author": "bkfox",
 | 
			
		||||
  "license": "AGPL",
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@fortawesome/fontawesome-free": "^5.8.2",
 | 
			
		||||
    "@fortawesome/fontawesome-free": "^5.10.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",
 | 
			
		||||
    "sass-loader": "^7.3.1",
 | 
			
		||||
    "style-loader": "^0.23.1",
 | 
			
		||||
    "ttf-loader": "^1.0.2",
 | 
			
		||||
    "vue-loader": "^15.7.0",
 | 
			
		||||
    "vue-loader": "^15.7.1",
 | 
			
		||||
    "vue-style-loader": "^4.1.2",
 | 
			
		||||
    "vue-template-compiler": "^2.6.10",
 | 
			
		||||
    "webpack": "^4.32.2",
 | 
			
		||||
    "webpack-cli": "^3.3.2"
 | 
			
		||||
    "webpack": "^4.39.3",
 | 
			
		||||
    "webpack-cli": "^3.3.8"
 | 
			
		||||
  },
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "buefy": "^0.7.8",
 | 
			
		||||
    "buefy": "^0.7.10",
 | 
			
		||||
    "vue": "^2.6.10"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -8,7 +8,10 @@ const VueLoaderPlugin = require('vue-loader/lib/plugin');
 | 
			
		||||
 | 
			
		||||
module.exports = (env, argv) => Object({
 | 
			
		||||
    context: __dirname,
 | 
			
		||||
    entry: './assets/index',
 | 
			
		||||
    entry: {
 | 
			
		||||
        main: './assets/public/index',
 | 
			
		||||
        admin: './assets/admin/index',
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    output: {
 | 
			
		||||
        path: path.resolve('aircox/static/aircox'),
 | 
			
		||||
@ -17,8 +20,8 @@ module.exports = (env, argv) => Object({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    optimization: {
 | 
			
		||||
        usedExports: true,
 | 
			
		||||
        concatenateModules: argv.mode == 'production' ? true : false,
 | 
			
		||||
        //usedExports: true,
 | 
			
		||||
        // concatenateModules: argv.mode == 'production' ? true : false,
 | 
			
		||||
 | 
			
		||||
        splitChunks: {
 | 
			
		||||
            cacheGroups: {
 | 
			
		||||
@ -29,12 +32,12 @@ module.exports = (env, argv) => Object({
 | 
			
		||||
 | 
			
		||||
                    test: /[\\/]node_modules[\\/]/,
 | 
			
		||||
                },
 | 
			
		||||
                admin: {
 | 
			
		||||
                /*admin: {
 | 
			
		||||
                    name: 'admin',
 | 
			
		||||
                    chunks: 'initial',
 | 
			
		||||
                    enforce: true,
 | 
			
		||||
                    enforce: false,
 | 
			
		||||
                    test: /assets[\\/]admin[\\/]/,
 | 
			
		||||
                },
 | 
			
		||||
                },*/
 | 
			
		||||
 | 
			
		||||
                /*noscript: {
 | 
			
		||||
                    name: 'noscript',
 | 
			
		||||
@ -82,13 +85,10 @@ module.exports = (env, argv) => Object({
 | 
			
		||||
 | 
			
		||||
    resolve: {
 | 
			
		||||
        alias: {
 | 
			
		||||
            js: path.resolve(__dirname, 'assets/js'),
 | 
			
		||||
            vue: 'vue/dist/vue.esm.browser.js',
 | 
			
		||||
            // buefy: 'buefy/dist/buefy.js',
 | 
			
		||||
        },
 | 
			
		||||
        modules: [
 | 
			
		||||
            'assets/js',
 | 
			
		||||
            'assets/vue',
 | 
			
		||||
            './assets',
 | 
			
		||||
            './node_modules',
 | 
			
		||||
        ],
 | 
			
		||||
        extensions: ['.js', '.vue', '.css', '.scss', '.styl', '.ttf']
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user