work on design: items, components
This commit is contained in:
parent
5ea092dba6
commit
1661601caf
|
@ -30,9 +30,9 @@ class DiffusionAdmin(DiffusionBaseAdmin, admin.ModelAdmin):
|
|||
|
||||
end_date.short_description = _("end")
|
||||
|
||||
list_display = ("episode", "start_date", "end_date", "type", "initial")
|
||||
list_display = ("episode", "start", "end", "type", "initial")
|
||||
list_filter = ("type", "start", "program")
|
||||
list_editable = ("type",)
|
||||
list_editable = ("type", "start", "end")
|
||||
ordering = ("-start", "id")
|
||||
|
||||
fields = ("type", "start", "end", "initial", "program", "schedule")
|
||||
|
|
|
@ -137,8 +137,6 @@ class Diffusion(Rerun):
|
|||
# help_text = _('use this input port'),
|
||||
# )
|
||||
|
||||
item_template_name = "aircox/widgets/diffusion_item.html"
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Diffusion")
|
||||
verbose_name_plural = _("Diffusions")
|
||||
|
@ -208,6 +206,11 @@ class Diffusion(Rerun):
|
|||
and self.end >= now
|
||||
)
|
||||
|
||||
@property
|
||||
def is_today(self):
|
||||
"""True if diffusion is currently today."""
|
||||
return self.start.date() == datetime.date.today()
|
||||
|
||||
@property
|
||||
def is_live(self):
|
||||
"""True if Diffusion is live (False if there are sounds files)."""
|
||||
|
|
|
@ -13,7 +13,9 @@ __all__ = ("Episode",)
|
|||
class Episode(Page):
|
||||
objects = ProgramChildQuerySet.as_manager()
|
||||
detail_url_name = "episode-detail"
|
||||
template_prefix = "episode"
|
||||
item_template_name = "aircox/widgets/episode_item.html"
|
||||
card_template_name = "aircox/widgets/episode_card.html"
|
||||
|
||||
@property
|
||||
def program(self):
|
||||
|
|
|
@ -9,6 +9,7 @@ from django.utils.translation import gettext_lazy as _
|
|||
from .diffusion import Diffusion
|
||||
from .sound import Sound, Track
|
||||
from .station import Station
|
||||
from .page import Renderable
|
||||
|
||||
logger = logging.getLogger("aircox")
|
||||
|
||||
|
@ -54,13 +55,15 @@ class LogQuerySet(models.QuerySet):
|
|||
return self.filter(track__isnull=not with_it)
|
||||
|
||||
|
||||
class Log(models.Model):
|
||||
class Log(Renderable, models.Model):
|
||||
"""Log sounds and diffusions that are played on the station.
|
||||
|
||||
This only remember what has been played on the outputs, not on each
|
||||
source; Source designate here which source is responsible of that.
|
||||
"""
|
||||
|
||||
template_prefix = "log"
|
||||
|
||||
TYPE_STOP = 0x00
|
||||
"""Source has been stopped, e.g. manually."""
|
||||
# Rule: \/ diffusion != null \/ sound != null
|
||||
|
|
|
@ -16,6 +16,7 @@ from model_utils.managers import InheritanceQuerySet
|
|||
from .station import Station
|
||||
|
||||
__all__ = (
|
||||
"Renderable",
|
||||
"Category",
|
||||
"PageQuerySet",
|
||||
"Page",
|
||||
|
@ -30,6 +31,17 @@ headline_re = re.compile(
|
|||
)
|
||||
|
||||
|
||||
class Renderable:
|
||||
template_prefix = "page"
|
||||
template_name = "aircox/widgets/{prefix}.html"
|
||||
|
||||
def get_template_name(self, widget):
|
||||
"""Return template name for the provided widget."""
|
||||
return self.template_name.format(
|
||||
prefix=self.template_prefix, widget=widget
|
||||
)
|
||||
|
||||
|
||||
class Category(models.Model):
|
||||
title = models.CharField(_("title"), max_length=64)
|
||||
slug = models.SlugField(_("slug"), max_length=64, db_index=True)
|
||||
|
@ -68,7 +80,7 @@ class BasePageQuerySet(InheritanceQuerySet):
|
|||
return self.filter(title__icontains=q)
|
||||
|
||||
|
||||
class BasePage(models.Model):
|
||||
class BasePage(Renderable, models.Model):
|
||||
"""Base class for publishable content."""
|
||||
|
||||
STATUS_DRAFT = 0x00
|
||||
|
@ -112,7 +124,6 @@ class BasePage(models.Model):
|
|||
objects = BasePageQuerySet.as_manager()
|
||||
|
||||
detail_url_name = None
|
||||
item_template_name = "aircox/widgets/page_item.html"
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
@ -152,14 +163,14 @@ class BasePage(models.Model):
|
|||
|
||||
@property
|
||||
def display_title(self):
|
||||
if self.is_published():
|
||||
if self.is_published:
|
||||
return self.title
|
||||
return self.parent.display_title()
|
||||
return self.parent and self.parent.display_title or ""
|
||||
|
||||
@cached_property
|
||||
def headline(self):
|
||||
if not self.content:
|
||||
return ""
|
||||
def display_headline(self):
|
||||
if not self.content or not self.is_published:
|
||||
return self.parent and self.parent.display_headline or ""
|
||||
content = bleach.clean(self.content, tags=[], strip=True)
|
||||
headline = headline_re.search(content)
|
||||
return mark_safe(headline.groupdict()["headline"]) if headline else ""
|
||||
|
|
|
@ -43,6 +43,7 @@ def user_default_groups(sender, instance, created, *args, **kwargs):
|
|||
|
||||
@receiver(signals.post_save, sender=Page)
|
||||
def page_post_save(sender, instance, created, *args, **kwargs):
|
||||
return
|
||||
if not created and instance.cover:
|
||||
Page.objects.filter(parent=instance, cover__isnull=True).update(
|
||||
cover=instance.cover
|
||||
|
@ -67,6 +68,7 @@ def program_post_save(sender, instance, created, *args, **kwargs):
|
|||
|
||||
@receiver(signals.pre_save, sender=Schedule)
|
||||
def schedule_pre_save(sender, instance, *args, **kwargs):
|
||||
return
|
||||
if getattr(instance, "pk") is not None:
|
||||
instance._initial = Schedule.objects.get(pk=instance.pk)
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -29,6 +29,16 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _mod
|
|||
|
||||
/***/ }),
|
||||
|
||||
/***/ "./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/ADropdown.vue?vue&type=script&lang=js":
|
||||
/*!*******************************************************************************************************************************************************************************************!*\
|
||||
!*** ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/ADropdown.vue?vue&type=script&lang=js ***!
|
||||
\*******************************************************************************************************************************************************************************************/
|
||||
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n data() {\n return {\n \"active\": this.open\n };\n },\n props: {\n itemClass: String,\n buttonClass: String,\n buttonIconOpen: {\n type: String,\n default: \"fa fa-angle-down\"\n },\n buttonIconClose: {\n type: String,\n default: \"fa fa-angle-up\"\n },\n contentClass: String,\n open: {\n type: Boolean,\n default: false\n },\n noButton: {\n type: Boolean,\n default: false\n }\n },\n methods: {\n toggle() {\n this.active = !this.active;\n }\n }\n});\n\n//# sourceURL=webpack://aircox-assets/./src/components/ADropdown.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D");
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/AEpisode.vue?vue&type=script&lang=js":
|
||||
/*!******************************************************************************************************************************************************************************************!*\
|
||||
!*** ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/AEpisode.vue?vue&type=script&lang=js ***!
|
||||
|
@ -169,6 +179,16 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|||
|
||||
/***/ }),
|
||||
|
||||
/***/ "./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/ADropdown.vue?vue&type=template&id=a87ed2dc":
|
||||
/*!***********************************************************************************************************************************************************************************************************************************************************************!*\
|
||||
!*** ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/ADropdown.vue?vue&type=template&id=a87ed2dc ***!
|
||||
\***********************************************************************************************************************************************************************************************************************************************************************/
|
||||
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"render\": function() { return /* binding */ render; }\n/* harmony export */ });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm-bundler.js\");\n\nconst _hoisted_1 = {\n class: \"icon\"\n};\nfunction render(_ctx, _cache, $props, $setup, $data, $options) {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", null, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", {\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)($props.itemClass),\n onClick: _cache[1] || (_cache[1] = $event => $props.noButton && $options.toggle())\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, \"button\", {}, () => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", {\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(['float-right', $props.buttonClass]),\n onClick: _cache[0] || (_cache[0] = $event => $options.toggle())\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", _hoisted_1, [!$data.active ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"i\", {\n key: 0,\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)($props.buttonIconOpen)\n }, null, 2 /* CLASS */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), $data.active ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"i\", {\n key: 1,\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)($props.buttonIconClose)\n }, null, 2 /* CLASS */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true)])], 2 /* CLASS */)]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, \"item\")], 2 /* CLASS */), $data.active ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", {\n key: 0,\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)($props.contentClass)\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, \"default\")], 2 /* CLASS */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true)]);\n}\n\n//# sourceURL=webpack://aircox-assets/./src/components/ADropdown.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/templateLoader.js??ruleSet%5B1%5D.rules%5B3%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D");
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/AEpisode.vue?vue&type=template&id=2e4db98a":
|
||||
/*!**********************************************************************************************************************************************************************************************************************************************************************!*\
|
||||
!*** ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/AEpisode.vue?vue&type=template&id=2e4db98a ***!
|
||||
|
@ -295,7 +315,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|||
\********************/
|
||||
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"PlayerApp\": function() { return /* binding */ PlayerApp; }\n/* harmony export */ });\n/* harmony import */ var _components__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./components */ \"./src/components/index.js\");\n\nconst App = {\n el: '#app',\n delimiters: ['[[', ']]'],\n components: {\n ..._components__WEBPACK_IMPORTED_MODULE_0__[\"default\"]\n },\n computed: {\n player() {\n return window.aircox.player;\n }\n }\n};\nconst PlayerApp = {\n el: '#player',\n delimiters: ['[[', ']]'],\n components: {\n ..._components__WEBPACK_IMPORTED_MODULE_0__[\"default\"]\n }\n};\n/* harmony default export */ __webpack_exports__[\"default\"] = (App);\n\n//# sourceURL=webpack://aircox-assets/./src/app.js?");
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"PlayerApp\": function() { return /* binding */ PlayerApp; }\n/* harmony export */ });\n/* harmony import */ var vue3_carousel_dist_carousel_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue3-carousel/dist/carousel.css */ \"./node_modules/vue3-carousel/dist/carousel.css\");\n/* harmony import */ var _components__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./components */ \"./src/components/index.js\");\n/* harmony import */ var vue3_carousel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! vue3-carousel */ \"./node_modules/vue3-carousel/dist/carousel.es.js\");\n\n\n\nconst App = {\n el: '#app',\n delimiters: ['[[', ']]'],\n components: {\n ..._components__WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n Slide: vue3_carousel__WEBPACK_IMPORTED_MODULE_2__.Slide,\n Carousel: vue3_carousel__WEBPACK_IMPORTED_MODULE_2__.Carousel,\n Pagination: vue3_carousel__WEBPACK_IMPORTED_MODULE_2__.Pagination,\n Navigation: vue3_carousel__WEBPACK_IMPORTED_MODULE_2__.Navigation\n },\n computed: {\n player() {\n return window.aircox.player;\n }\n },\n data() {\n return {\n carouselBreakpoints: {\n 400: {\n itemsToShow: 1\n },\n 600: {\n itemsToShow: 1.75\n },\n 800: {\n itemsToShow: 3\n },\n 1024: {\n itemsToShow: 4\n },\n 1280: {\n itemsToShow: 4\n },\n 1380: {\n itemsToShow: 5\n }\n }\n };\n }\n};\nconst PlayerApp = {\n el: '#player',\n delimiters: ['[[', ']]'],\n components: {\n ..._components__WEBPACK_IMPORTED_MODULE_1__[\"default\"]\n }\n};\n/* harmony default export */ __webpack_exports__[\"default\"] = (App);\n\n//# sourceURL=webpack://aircox-assets/./src/app.js?");
|
||||
|
||||
/***/ }),
|
||||
|
||||
|
@ -305,7 +325,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|||
\***************************/
|
||||
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": function() { return /* binding */ Builder; }\n/* harmony export */ });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm-bundler.js\");\n\n\n/**\n * Utility class used to handle Vue applications. It provides way to load\n * remote application and update history.\n */\nclass Builder {\n constructor(config = {}) {\n this.config = config;\n this.title = null;\n this.app = null;\n this.vm = null;\n }\n\n /**\n * Fetch app from remote and mount application.\n */\n fetch(url, {\n el = '#app',\n ...options\n } = {}) {\n return fetch(url, options).then(response => response.text()).then(content => {\n let doc = new DOMParser().parseFromString(content, 'text/html');\n let app = doc.querySelector(el);\n content = app ? app.innerHTML : content;\n return this.mount({\n content,\n title: doc.title,\n reset: true,\n url\n });\n });\n }\n\n /**\n * Mount application, using `create_app` if required.\n *\n * @param {String} options.content: replace app container content with it\n * @param {String} options.title: set DOM document title.\n * @param {String} [options.el=this.config.el]: mount application on this element (querySelector argument)\n * @param {Boolean} [reset=False]: if True, force application recreation.\n * @return `app.mount`'s result.\n */\n mount({\n content = null,\n title = null,\n el = null,\n reset = false,\n props = null\n } = {}) {\n try {\n this.unmount();\n let config = this.config;\n if (el === null) el = config.el;\n if (reset || !this.app) this.app = this.createApp({\n title,\n content,\n el,\n ...config\n }, props);\n this.vm = this.app.mount(el);\n window.scroll(0, 0);\n return this.vm;\n } catch (error) {\n this.unmount();\n throw error;\n }\n }\n createApp({\n el,\n title = null,\n content = null,\n ...config\n }, props) {\n const container = document.querySelector(el);\n if (!container) return;\n if (content) container.innerHTML = content;\n if (title) document.title = title;\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.createApp)(config, props);\n }\n unmount() {\n this.app && this.app.unmount();\n this.app = null;\n this.vm = null;\n }\n\n /**\n * Enable hot reload: catch page change in order to fetch them and\n * load page without actually leaving current one.\n */\n enableHotReload(node = null, historySave = true) {\n if (historySave) this.historySave(document.location, true);\n node.addEventListener('click', event => this._onPageChange(event), true);\n node.addEventListener('submit', event => this._onPageChange(event), true);\n node.addEventListener('popstate', event => this._onPopState(event), true);\n }\n _onPageChange(event) {\n let submit = event.type == 'submit';\n let target = submit || event.target.tagName == 'A' ? event.target : event.target.closest('a');\n if (!target || target.hasAttribute('target')) return;\n let url = submit ? target.getAttribute('action') || '' : target.getAttribute('href');\n if (url === null || !(url === '' || url.startsWith('/') || url.startsWith('?'))) return;\n let options = {};\n if (submit) {\n let formData = new FormData(event.target);\n if (target.method == 'get') url += '?' + new URLSearchParams(formData).toString();else options = {\n ...options,\n method: target.method,\n body: formData\n };\n }\n this.fetch(url, options).then(() => this.historySave(url));\n event.preventDefault();\n event.stopPropagation();\n }\n _onPopState(event) {\n if (event.state && event.state.content)\n // document.title = this.title;\n this.historyLoad(event.state);\n }\n\n /// Save application state into browser history\n historySave(url, replace = false) {\n const el = document.querySelector(this.config.el);\n const state = {\n content: el.innerHTML,\n title: document.title\n };\n if (replace) history.replaceState(state, '', url);else history.pushState(state, '', url);\n }\n\n /// Load application from browser history's state\n historyLoad(state) {\n return this.mount({\n content: state.content,\n title: state.title\n });\n }\n}\n\n//# sourceURL=webpack://aircox-assets/./src/appBuilder.js?");
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": function() { return /* binding */ Builder; }\n/* harmony export */ });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm-bundler.js\");\n\n\n/**\n * Utility class used to handle Vue applications. It provides way to load\n * remote application and update history.\n */\nclass Builder {\n constructor(config = {}) {\n this.config = config;\n this.title = null;\n this.app = null;\n this.vm = null;\n }\n\n /**\n * Fetch app from remote and mount application.\n */\n fetch(url, {\n el = '#app',\n ...options\n } = {}) {\n return fetch(url, options).then(response => response.text()).then(content => {\n let doc = new DOMParser().parseFromString(content, 'text/html');\n let app = doc.querySelector(el);\n content = app ? app.innerHTML : content;\n return this.mount({\n content,\n title: doc.title,\n reset: true,\n url\n });\n });\n }\n\n /**\n * Mount application, using `create_app` if required.\n *\n * @param {String} options.content: replace app container content with it\n * @param {String} options.title: set DOM document title.\n * @param {String} [options.el=this.config.el]: mount application on this element (querySelector argument)\n * @param {Boolean} [reset=False]: if True, force application recreation.\n * @return `app.mount`'s result.\n */\n mount({\n content = null,\n title = null,\n el = null,\n reset = false,\n props = null\n } = {}) {\n try {\n this.unmount();\n let config = this.config;\n if (el === null) el = config.el;\n if (reset || !this.app) this.app = this.createApp({\n title,\n content,\n el,\n ...config\n }, props);\n this.vm = this.app.mount(el);\n window.scroll(0, 0);\n return this.vm;\n } catch (error) {\n this.unmount();\n throw error;\n }\n }\n createApp({\n el,\n title = null,\n content = null,\n ...config\n }, props) {\n const container = document.querySelector(el);\n if (!container) return;\n if (content) container.innerHTML = content;\n if (title) document.title = title;\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.createApp)(config, props);\n }\n unmount() {\n this.app && this.app.unmount();\n this.app = null;\n this.vm = null;\n }\n\n /**\n * Enable hot reload: catch page change in order to fetch them and\n * load page without actually leaving current one.\n */\n enableHotReload(node = null, historySave = true) {\n if (historySave) this.historySave(document.location, true);\n node.addEventListener('click', event => this.pageChanged(event), true);\n node.addEventListener('submit', event => this.pageChanged(event), true);\n node.addEventListener('popstate', event => this.statePopped(event), true);\n }\n pageChanged(event) {\n let submit = event.type == 'submit';\n let target = submit || event.target.tagName == 'A' ? event.target : event.target.closest('a');\n if (!target || target.hasAttribute('target')) return;\n let url = submit ? target.getAttribute('action') || '' : target.getAttribute('href');\n let domain = window.location.protocol + '//' + window.location.hostname;\n let stay = (url === '' || url.startsWith('/') || url.startsWith('?') || url.startsWith(domain)) && url.indexOf('wp-admin') == -1;\n if (url === null || !stay) {\n return;\n }\n let options = {};\n if (submit) {\n let formData = new FormData(event.target);\n if (target.method == 'get') url += '?' + new URLSearchParams(formData).toString();else options = {\n ...options,\n method: target.method,\n body: formData\n };\n }\n this.fetch(url, options).then(() => this.historySave(url));\n event.preventDefault();\n event.stopPropagation();\n }\n statePopped(event) {\n const state = event.state;\n if (state && state.content)\n // document.title = this.title;\n this.historyLoad(state);\n }\n\n /// Save application state into browser history\n historySave(url, replace = false) {\n const el = document.querySelector(this.config.el);\n const state = {\n content: el.innerHTML,\n title: document.title\n };\n if (replace) history.replaceState(state, '', url);else history.pushState(state, '', url);\n }\n\n /// Load application from browser history's state\n historyLoad(state) {\n return this.mount({\n content: state.content,\n title: state.title\n });\n }\n}\n\n//# sourceURL=webpack://aircox-assets/./src/appBuilder.js?");
|
||||
|
||||
/***/ }),
|
||||
|
||||
|
@ -315,7 +335,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|||
\*********************************/
|
||||
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"admin\": function() { return /* binding */ admin; },\n/* harmony export */ \"base\": function() { return /* binding */ base; }\n/* harmony export */ });\n/* harmony import */ var _AAutocomplete_vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AAutocomplete.vue */ \"./src/components/AAutocomplete.vue\");\n/* harmony import */ var _AEpisode_vue__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./AEpisode.vue */ \"./src/components/AEpisode.vue\");\n/* harmony import */ var _AList_vue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./AList.vue */ \"./src/components/AList.vue\");\n/* harmony import */ var _APage_vue__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./APage.vue */ \"./src/components/APage.vue\");\n/* harmony import */ var _APlayer_vue__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./APlayer.vue */ \"./src/components/APlayer.vue\");\n/* harmony import */ var _APlaylist_vue__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./APlaylist.vue */ \"./src/components/APlaylist.vue\");\n/* harmony import */ var _APlaylistEditor_vue__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./APlaylistEditor.vue */ \"./src/components/APlaylistEditor.vue\");\n/* harmony import */ var _AProgress_vue__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./AProgress.vue */ \"./src/components/AProgress.vue\");\n/* harmony import */ var _ASoundItem_vue__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./ASoundItem.vue */ \"./src/components/ASoundItem.vue\");\n/* harmony import */ var _AStatistics_vue__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./AStatistics.vue */ \"./src/components/AStatistics.vue\");\n/* harmony import */ var _AStreamer_vue__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./AStreamer.vue */ \"./src/components/AStreamer.vue\");\n\n\n\n\n\n\n\n\n\n\n\n\n/**\n * Core components\n */\nconst base = {\n AAutocomplete: _AAutocomplete_vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"],\n AEpisode: _AEpisode_vue__WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n AList: _AList_vue__WEBPACK_IMPORTED_MODULE_2__[\"default\"],\n APage: _APage_vue__WEBPACK_IMPORTED_MODULE_3__[\"default\"],\n APlayer: _APlayer_vue__WEBPACK_IMPORTED_MODULE_4__[\"default\"],\n APlaylist: _APlaylist_vue__WEBPACK_IMPORTED_MODULE_5__[\"default\"],\n AProgress: _AProgress_vue__WEBPACK_IMPORTED_MODULE_7__[\"default\"],\n ASoundItem: _ASoundItem_vue__WEBPACK_IMPORTED_MODULE_8__[\"default\"]\n};\n/* harmony default export */ __webpack_exports__[\"default\"] = (base);\nconst admin = {\n ...base,\n AStatistics: _AStatistics_vue__WEBPACK_IMPORTED_MODULE_9__[\"default\"],\n AStreamer: _AStreamer_vue__WEBPACK_IMPORTED_MODULE_10__[\"default\"],\n APlaylistEditor: _APlaylistEditor_vue__WEBPACK_IMPORTED_MODULE_6__[\"default\"]\n};\n\n//# sourceURL=webpack://aircox-assets/./src/components/index.js?");
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"admin\": function() { return /* binding */ admin; },\n/* harmony export */ \"base\": function() { return /* binding */ base; }\n/* harmony export */ });\n/* harmony import */ var _AAutocomplete_vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AAutocomplete.vue */ \"./src/components/AAutocomplete.vue\");\n/* harmony import */ var _ADropdown_vue__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ADropdown.vue */ \"./src/components/ADropdown.vue\");\n/* harmony import */ var _AEpisode_vue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./AEpisode.vue */ \"./src/components/AEpisode.vue\");\n/* harmony import */ var _AList_vue__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./AList.vue */ \"./src/components/AList.vue\");\n/* harmony import */ var _APage_vue__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./APage.vue */ \"./src/components/APage.vue\");\n/* harmony import */ var _APlayer_vue__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./APlayer.vue */ \"./src/components/APlayer.vue\");\n/* harmony import */ var _APlaylist_vue__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./APlaylist.vue */ \"./src/components/APlaylist.vue\");\n/* harmony import */ var _APlaylistEditor_vue__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./APlaylistEditor.vue */ \"./src/components/APlaylistEditor.vue\");\n/* harmony import */ var _AProgress_vue__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./AProgress.vue */ \"./src/components/AProgress.vue\");\n/* harmony import */ var _ASoundItem_vue__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./ASoundItem.vue */ \"./src/components/ASoundItem.vue\");\n/* harmony import */ var _AStatistics_vue__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./AStatistics.vue */ \"./src/components/AStatistics.vue\");\n/* harmony import */ var _AStreamer_vue__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./AStreamer.vue */ \"./src/components/AStreamer.vue\");\n\n\n\n\n\n\n\n\n\n\n\n\n\n/**\n * Core components\n */\nconst base = {\n AAutocomplete: _AAutocomplete_vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"],\n ADropdown: _ADropdown_vue__WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n AEpisode: _AEpisode_vue__WEBPACK_IMPORTED_MODULE_2__[\"default\"],\n AList: _AList_vue__WEBPACK_IMPORTED_MODULE_3__[\"default\"],\n APage: _APage_vue__WEBPACK_IMPORTED_MODULE_4__[\"default\"],\n APlayer: _APlayer_vue__WEBPACK_IMPORTED_MODULE_5__[\"default\"],\n APlaylist: _APlaylist_vue__WEBPACK_IMPORTED_MODULE_6__[\"default\"],\n AProgress: _AProgress_vue__WEBPACK_IMPORTED_MODULE_8__[\"default\"],\n ASoundItem: _ASoundItem_vue__WEBPACK_IMPORTED_MODULE_9__[\"default\"]\n};\n/* harmony default export */ __webpack_exports__[\"default\"] = (base);\nconst admin = {\n ...base,\n AStatistics: _AStatistics_vue__WEBPACK_IMPORTED_MODULE_10__[\"default\"],\n AStreamer: _AStreamer_vue__WEBPACK_IMPORTED_MODULE_11__[\"default\"],\n APlaylistEditor: _APlaylistEditor_vue__WEBPACK_IMPORTED_MODULE_7__[\"default\"]\n};\n\n//# sourceURL=webpack://aircox-assets/./src/components/index.js?");
|
||||
|
||||
/***/ }),
|
||||
|
||||
|
@ -419,6 +439,16 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _AAu
|
|||
|
||||
/***/ }),
|
||||
|
||||
/***/ "./src/components/ADropdown.vue":
|
||||
/*!**************************************!*\
|
||||
!*** ./src/components/ADropdown.vue ***!
|
||||
\**************************************/
|
||||
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _ADropdown_vue_vue_type_template_id_a87ed2dc__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ADropdown.vue?vue&type=template&id=a87ed2dc */ \"./src/components/ADropdown.vue?vue&type=template&id=a87ed2dc\");\n/* harmony import */ var _ADropdown_vue_vue_type_script_lang_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ADropdown.vue?vue&type=script&lang=js */ \"./src/components/ADropdown.vue?vue&type=script&lang=js\");\n/* harmony import */ var _media_data_code_projets_aircox_assets_node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./node_modules/vue-loader/dist/exportHelper.js */ \"./node_modules/vue-loader/dist/exportHelper.js\");\n\n\n\n\n;\nconst __exports__ = /*#__PURE__*/(0,_media_data_code_projets_aircox_assets_node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(_ADropdown_vue_vue_type_script_lang_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"], [['render',_ADropdown_vue_vue_type_template_id_a87ed2dc__WEBPACK_IMPORTED_MODULE_0__.render],['__file',\"src/components/ADropdown.vue\"]])\n/* hot reload */\nif (false) {}\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (__exports__);\n\n//# sourceURL=webpack://aircox-assets/./src/components/ADropdown.vue?");
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "./src/components/AEpisode.vue":
|
||||
/*!*************************************!*\
|
||||
!*** ./src/components/AEpisode.vue ***!
|
||||
|
@ -559,6 +589,16 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|||
|
||||
/***/ }),
|
||||
|
||||
/***/ "./src/components/ADropdown.vue?vue&type=script&lang=js":
|
||||
/*!**************************************************************!*\
|
||||
!*** ./src/components/ADropdown.vue?vue&type=script&lang=js ***!
|
||||
\**************************************************************/
|
||||
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": function() { return /* reexport safe */ _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ADropdown_vue_vue_type_script_lang_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]; }\n/* harmony export */ });\n/* harmony import */ var _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ADropdown_vue_vue_type_script_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!../../node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./ADropdown.vue?vue&type=script&lang=js */ \"./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/ADropdown.vue?vue&type=script&lang=js\");\n \n\n//# sourceURL=webpack://aircox-assets/./src/components/ADropdown.vue?");
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "./src/components/AEpisode.vue?vue&type=script&lang=js":
|
||||
/*!*************************************************************!*\
|
||||
!*** ./src/components/AEpisode.vue?vue&type=script&lang=js ***!
|
||||
|
@ -699,6 +739,16 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|||
|
||||
/***/ }),
|
||||
|
||||
/***/ "./src/components/ADropdown.vue?vue&type=template&id=a87ed2dc":
|
||||
/*!********************************************************************!*\
|
||||
!*** ./src/components/ADropdown.vue?vue&type=template&id=a87ed2dc ***!
|
||||
\********************************************************************/
|
||||
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"render\": function() { return /* reexport safe */ _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_3_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ADropdown_vue_vue_type_template_id_a87ed2dc__WEBPACK_IMPORTED_MODULE_0__.render; }\n/* harmony export */ });\n/* harmony import */ var _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_3_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ADropdown_vue_vue_type_template_id_a87ed2dc__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!../../node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!../../node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./ADropdown.vue?vue&type=template&id=a87ed2dc */ \"./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/ADropdown.vue?vue&type=template&id=a87ed2dc\");\n\n\n//# sourceURL=webpack://aircox-assets/./src/components/ADropdown.vue?");
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "./src/components/AEpisode.vue?vue&type=template&id=2e4db98a":
|
||||
/*!*******************************************************************!*\
|
||||
!*** ./src/components/AEpisode.vue?vue&type=template&id=2e4db98a ***!
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -49,7 +49,7 @@ Usefull context:
|
|||
</script>
|
||||
<div id="app">
|
||||
{% block top-nav-container %}
|
||||
<nav class="navbar has-shadow" role="navigation" aria-label="main navigation">
|
||||
<nav class="navbar" role="navigation" aria-label="main navigation">
|
||||
<div class="container">
|
||||
<div class="navbar-brand">
|
||||
<a href="/" title="{% translate "Home" %}" class="navbar-item">
|
||||
|
@ -87,81 +87,31 @@ Usefull context:
|
|||
</nav>
|
||||
{% endblock %}
|
||||
|
||||
<div class="container">
|
||||
<div class="columns is-desktop">
|
||||
<main class="column page">
|
||||
<header class="header">
|
||||
{% block main-container %}
|
||||
<main class="page">
|
||||
{% block main %}
|
||||
<header class="container header {% if cover %}has-cover{% endif %}">
|
||||
{% block header %}
|
||||
<h1 class="title is-1">
|
||||
{% block title %}
|
||||
{% if page and page.title %}
|
||||
{{ page.title }}
|
||||
{% if object %}
|
||||
{% include header_template_name|default:"./widgets/header.html" with title=object.title cover=object.cover.url %}
|
||||
{% else %}
|
||||
{% include header_template_name|default:"./widgets/header.html" %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
</h1>
|
||||
|
||||
<h3 class="subtitle is-3">
|
||||
{% block subtitle %}{% endblock %}
|
||||
</h3>
|
||||
|
||||
<div class="columns is-size-4">
|
||||
{% block header_nav %}
|
||||
<span class="column">
|
||||
{% block header_crumbs %}
|
||||
{% if parent %}
|
||||
<a href="{{ parent.get_absolute_url }}">
|
||||
{{ parent.title }}</a></li>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
</span>
|
||||
{% endblock %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
</header>
|
||||
|
||||
{% block main %}
|
||||
{% block content-container %}
|
||||
<div class="container content">
|
||||
{% block content %}
|
||||
{% if page and page.content %}
|
||||
<section class="page-content mb-2">{{ page.content|safe }}</section>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% endblock main %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
</main>
|
||||
|
||||
{% if has_sidebar %}
|
||||
{% comment %}Translators: main sidebar {% endcomment %}
|
||||
<aside class="column is-one-third-desktop">
|
||||
{# FIXME: block cover into sidebar one #}
|
||||
{% block cover %}
|
||||
{% if page and page.cover %}
|
||||
<img class="cover mb-4" src="{{ page.cover.url }}" class="cover"/>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% with is_thin=True %}
|
||||
{% block sidebar %}
|
||||
{% if sidebar_object_list %}
|
||||
{% with object_list=sidebar_object_list %}
|
||||
{% with list_url=sidebar_list_url %}
|
||||
{% with has_headline=False %}
|
||||
<section>
|
||||
<h4 class="title is-4">
|
||||
{% block sidebar_title %}{% translate "Recently" %}{% endblock %}
|
||||
</h4>
|
||||
{% include "aircox/widgets/page_list.html" %}
|
||||
{% endwith %}
|
||||
{% endwith %}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
</section>
|
||||
{% endblock %}
|
||||
{% endwith %}
|
||||
</aside>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
</div>
|
||||
{% block player-container %}
|
||||
<div id="player">{% include "aircox/widgets/player.html" %}</div>
|
||||
|
|
|
@ -22,7 +22,9 @@
|
|||
{{ station.name }}
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}{{ block.super }}
|
||||
{% block content-container %}
|
||||
{{ block.super }}
|
||||
<div class="container">
|
||||
|
||||
{% block before_list %}{% endblock %}
|
||||
|
||||
|
@ -31,7 +33,7 @@
|
|||
{% with has_headline=True %}
|
||||
{% for object in object_list %}
|
||||
{% block list_object %}
|
||||
{% include object.item_template_name|default:item_template_name %}
|
||||
{% page_widget item_widget|default:"item" object %}
|
||||
{% endblock %}
|
||||
{% empty %}
|
||||
{% blocktranslate %}There is nothing published here...{% endblocktranslate %}
|
||||
|
@ -83,4 +85,5 @@
|
|||
{% endwith %}
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
@ -12,18 +12,24 @@
|
|||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block subtitle %}{{ date|date:"l d F Y" }}{% endblock %}
|
||||
{% block filters-item %}
|
||||
<span class="control">
|
||||
<input type="date">
|
||||
</span>
|
||||
{% endblock %}
|
||||
|
||||
{% block before_list %}
|
||||
{% with "diffusion-list" as url_name %}
|
||||
{% include "aircox/widgets/dates_menu.html" %}
|
||||
{% block header %}
|
||||
{% with "./widgets/diffusion_list_header.html" as header_template_name %}
|
||||
{{ block.super }}
|
||||
{% endwith %}
|
||||
{% endblock %}
|
||||
|
||||
{% block pages_list %}
|
||||
{% with hide_schedule=True %}
|
||||
<section role="list">
|
||||
{% include 'aircox/widgets/diffusion_list.html' %}
|
||||
<section role="list" class="list">
|
||||
{% for object in object_list %}
|
||||
{% page_widget "item" object.episode diffusion=object timetable=True %}
|
||||
{% endfor %}
|
||||
</section>
|
||||
{% endwith %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -2,14 +2,32 @@
|
|||
{% comment %}List of a show's episodes for a specific{% endcomment %}
|
||||
{% load i18n aircox %}
|
||||
|
||||
{% include "aircox/program_sidebar.html" %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<a-episode :page="{title: "{{ page.title }}", podcasts: {{ object.podcasts|json }}}">
|
||||
<template v-slot="{podcasts,page}">
|
||||
{{ block.super }}
|
||||
|
||||
{% if tracks %}
|
||||
<section>
|
||||
<h3 class="title is-3">{% translate "Playlist" %}</h3>
|
||||
<table class="table is-hoverable is-fullwidth">
|
||||
<tbody>
|
||||
{% for track in tracks %}
|
||||
<tr>
|
||||
<td>{{ forloop.counter }}</td>
|
||||
<td>{{ track.artist }}</td>
|
||||
<td>{{ track.title }}</td>
|
||||
<td>{{ track.info|default:"" }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<ol>
|
||||
</ol>
|
||||
</section>
|
||||
{% endif %}
|
||||
|
||||
{% if object.podcasts %}
|
||||
<section>
|
||||
<a-playlist v-if="page" :set="podcasts"
|
||||
|
@ -18,63 +36,11 @@
|
|||
:player="player" :actions="['play']"
|
||||
@select="player.playItems('queue', $event.item)">
|
||||
<template v-slot:header>
|
||||
<h4 class="title is-4">{% translate "Podcasts" %}</h4>
|
||||
<h3 class="title is-3">{% translate "Podcasts" %}</h3>
|
||||
</template>
|
||||
</a-playlist>
|
||||
{% comment %}
|
||||
{% for object in podcasts %}
|
||||
{% include "aircox/widgets/podcast_item.html" %}
|
||||
{% endfor %}
|
||||
{% endcomment %}
|
||||
</section>
|
||||
{% endif %}
|
||||
|
||||
{% if tracks %}
|
||||
<section>
|
||||
<h4 class="title is-4">{% translate "Playlist" %}</h4>
|
||||
<ol>
|
||||
{% for track in tracks %}
|
||||
<li><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>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</section>
|
||||
{% endif %}
|
||||
|
||||
</template></a-episode>
|
||||
{% endblock %}
|
||||
|
||||
{% block sidebar %}
|
||||
<section>
|
||||
<h4 class="title is-4">{% translate "Diffusions" %}</h4>
|
||||
<ul>
|
||||
{% for diffusion in object.diffusion_set.all %}
|
||||
<li>
|
||||
{% with diffusion.start as start %}
|
||||
{% with diffusion.end as end %}
|
||||
<time datetime="{{ start }}">{{ start|date:"D. d F Y, H:i" }}</time>
|
||||
—
|
||||
<time datetime="{{ end }}">{{ end|date:"H:i" }}</time>
|
||||
{% endwith %}
|
||||
{% endwith %}
|
||||
|
||||
<small>
|
||||
{% if diffusion.initial %}
|
||||
{% with diffusion.initial.date as date %}
|
||||
<span title="{% blocktranslate %}Rerun of {{ date }}{% endblocktranslate %}">
|
||||
({% translate "rerun" %})
|
||||
</span>
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
</small>
|
||||
<br>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</section>
|
||||
{{ block.super }}
|
||||
</template>
|
||||
</a-episode>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,65 +1,46 @@
|
|||
{% extends "aircox/page_list.html" %}
|
||||
{% comment %}Home page{% endcomment %}
|
||||
{% load i18n %}
|
||||
{% load i18n aircox %}
|
||||
|
||||
{% block head_title %}{{ station.name }}{% endblock %}
|
||||
|
||||
{% block title %}
|
||||
{% if not page or not page.title %}{{ station.name }}
|
||||
{% else %}{{ block.super }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block before_list %}{% endblock %}
|
||||
|
||||
{% block pages_list %}
|
||||
{% if page and page.content %}<hr/>{% endif %}
|
||||
{% block content-container %}
|
||||
{% if next_diffs %}
|
||||
<div class="columns">
|
||||
{% with render_card=True %}
|
||||
{% for object in next_diffs %}
|
||||
{% with is_primary=object.is_now %}
|
||||
<div class="column is-relative">
|
||||
<h4 class="card-super-title" title="{{ object.start }}">
|
||||
{% if is_primary %}
|
||||
<span class="fas fa-play"></span>
|
||||
<time datetime="{{ object.start }}">
|
||||
{% translate "Currently" %}
|
||||
</time>
|
||||
{% else %}
|
||||
{{ object.start|date:"H:i" }}
|
||||
<section class="container card-grid">
|
||||
{% for obj in next_diffs|slice:"1:4" %}
|
||||
{% if object != diffusion %}
|
||||
{% page_widget "card" obj.episode diffusion=obj timetable=True %}
|
||||
{% endif %}
|
||||
|
||||
{% if object.episode.category %}
|
||||
// {{ object.episode.category.title }}
|
||||
{% endif %}
|
||||
</h4>
|
||||
{% include object.item_template_name %}
|
||||
</div>
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if object_list %}
|
||||
<h4 class="title is-4">{% translate "Today" %}</h4>
|
||||
<section role="list">
|
||||
{% include 'aircox/widgets/diffusion_list.html' %}
|
||||
</section>
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if object_list %}
|
||||
<section class="container">
|
||||
<h2 class="title is-3 p-2">
|
||||
{% with station.name as station %}
|
||||
{% blocktrans %}
|
||||
Today on {{ station }}
|
||||
{% endblocktrans %}
|
||||
{% endwith %}
|
||||
</h2>
|
||||
|
||||
<div role="list">
|
||||
{% for object in object_list %}
|
||||
{% page_widget "item" object.episode diffusion=object timetable=True open=True %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block pagination %}
|
||||
<ul class="pagination-list">
|
||||
<li>
|
||||
<a href="{% url "page-list" %}" class="pagination-link"
|
||||
aria-label="{% translate "Show all publication" %}">
|
||||
{% translate "More publications..." %}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
|
||||
{% block pages_list %}{% endblock %}
|
||||
|
||||
|
||||
{% block sidebar %}
|
||||
|
|
|
@ -15,15 +15,29 @@
|
|||
|
||||
{% block subtitle %}{{ date|date:"l d F Y" }}{% endblock %}
|
||||
|
||||
{% block before_list %}
|
||||
{% with "log-list" as url_name %}
|
||||
{% include "aircox/widgets/dates_menu.html" %}
|
||||
{% block header %}
|
||||
{% with "./widgets/log_list_header.html" as header_template_name %}
|
||||
{{ block.super }}
|
||||
{% endwith %}
|
||||
{% endblock %}
|
||||
|
||||
{% block pages_list %}
|
||||
{% block pages_list_ %}
|
||||
<section>
|
||||
{# <h4 class="subtitle size-4">{{ date }}</h4> #}
|
||||
{% include "aircox/widgets/log_list.html" %}
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
||||
{% block pages_list %}
|
||||
{% with hide_schedule=True %}
|
||||
<section role="list" class="list">
|
||||
{% for object in object_list %}
|
||||
{% if object.episode %}
|
||||
{% page_widget "item" object.episode diffusion=object timetable=True %}
|
||||
{% else %}
|
||||
{% page_widget "item" object timetable=True %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</section>
|
||||
{% endwith %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -33,7 +33,7 @@ Context:
|
|||
|
||||
{% block comments %}
|
||||
{% if comments or comment_form %}
|
||||
<section class="mt-6">
|
||||
<section class="container mt-6">
|
||||
<h4 class="title is-4">{% translate "Comments" %}</h4>
|
||||
|
||||
{% for comment in comments %}
|
||||
|
|
|
@ -2,11 +2,48 @@
|
|||
{% comment %}Display a list of Pages{% endcomment %}
|
||||
{% load i18n aircox %}
|
||||
|
||||
{% block before_list %}
|
||||
{% block header %}
|
||||
{% if page and not object %}
|
||||
{% with page as object %}
|
||||
{{ block.super }}
|
||||
{% endwith %}
|
||||
{% else %}
|
||||
{{ block.super }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block before_list %}
|
||||
{% if view.has_filters and object_list %}
|
||||
<form method="GET" action="" class="media">
|
||||
<form method="GET" action="" class="list-filters">
|
||||
<a-dropdown :item-class="dropdown-trigger" :content-class="dropdown-menu">
|
||||
<template #item>
|
||||
{% block filters-item %}
|
||||
<span class="icon">
|
||||
<i class="fa fa-search"></i>
|
||||
</span>
|
||||
{% endblock %}
|
||||
</template>
|
||||
|
||||
<template #default>
|
||||
<div class="dropdown-menu">
|
||||
{% block filters-content %}
|
||||
<div class="dropdown-item">
|
||||
<div class="field is-grouped is-grouped-right">
|
||||
<div class="control">
|
||||
<button class="button is-primary"/>{% translate "Apply" %}</button>
|
||||
</div>
|
||||
<div class="control">
|
||||
<a href="?" class="button is-secondary">{% translate "Reset" %}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
</div>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</form>
|
||||
|
||||
{% comment %}
|
||||
<div class="media-content">
|
||||
{% block filters %}
|
||||
<div class="field is-horizontal">
|
||||
|
@ -48,15 +85,8 @@
|
|||
{% endblock %}
|
||||
</div>
|
||||
<div class="media-right">
|
||||
<div class="field is-grouped is-grouped-right">
|
||||
<div class="control">
|
||||
<button class="button is-primary"/>{% translate "Apply" %}</button>
|
||||
</div>
|
||||
<div class="control">
|
||||
<a href="?" class="button is-secondary">{% translate "Reset" %}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endcomment %}
|
||||
</form>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
|
48
aircox/templates/aircox/widgets/basepage_card.html
Normal file
48
aircox/templates/aircox/widgets/basepage_card.html
Normal file
|
@ -0,0 +1,48 @@
|
|||
{% load i18n %}
|
||||
|
||||
{% block outer %}
|
||||
<article class="preview preview-card {% if wide %}wide{% endif %}{% if is_primary %}is-primary{% endif %}{% block card_class %}{% endblock %}"
|
||||
style="background-image: url({{ object.cover.url }})">
|
||||
{% if with_container %}
|
||||
<div class="container">
|
||||
{% endif %}
|
||||
|
||||
{% block inner %}
|
||||
<header class="headings" >
|
||||
{% block headings %}
|
||||
<div>
|
||||
<h2 class="heading title">{% block title %}{% endblock %}</h2>
|
||||
</div>
|
||||
<div>
|
||||
<span class="heading subtitle">{% block subtitle %}{% endblock %}</span>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
<summary class="heading-container">
|
||||
{% block content %}
|
||||
{% if content and with_content %}
|
||||
{% autoescape off %}
|
||||
{{ content|striptags|truncatewords:64|linebreaks }}
|
||||
{% endautoescape %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
</summary>
|
||||
|
||||
<div class="actions">
|
||||
{% block actions %}
|
||||
<a class="button btn-hg float-right" href="{{ object.get_absolute_url|escape }}">
|
||||
<span class="icon">
|
||||
<i class="fas fa-external-link"></i>
|
||||
</span>
|
||||
<label>{% translate "More infos" %}</label>
|
||||
</a>
|
||||
{% endblock %}
|
||||
</div>
|
||||
</header>
|
||||
{% endblock %}
|
||||
|
||||
{% if with_container %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</article>
|
||||
{% endblock %}
|
|
@ -11,63 +11,48 @@ Context variables:
|
|||
- is_thin (=False): if True, smaller cover and display less info
|
||||
{% endcomment %}
|
||||
|
||||
{% if render_card %}
|
||||
<article class="card {% if is_primary %}is-primary{% endif %}">
|
||||
<header class="card-image">
|
||||
<a href="{{ object.get_absolute_url }}">
|
||||
<figure class="image is-4by3">
|
||||
<img src="{% thumbnail object.cover|default:station.default_cover 480x480 %}">
|
||||
</figure>
|
||||
</a>
|
||||
{% block outer %}
|
||||
<article class="preview preview-item{% if is_primary %}is-primary{% endif %}{% block card_class %}{% endblock %}">
|
||||
{% block inner %}
|
||||
<header class="headings"
|
||||
style="background-image: url({{ object.cover.url }})">
|
||||
{% block headings %}
|
||||
<div>
|
||||
<span class="heading subtitle">{% block subtitle %}{% endblock %}</span>
|
||||
</div>
|
||||
{% endblock %}
|
||||
</header>
|
||||
<div class="card-header">
|
||||
<h4 class="title">
|
||||
<a href="{{ object.get_absolute_url }}">
|
||||
{% block card_title %}{{ object.title }}{% endblock %}
|
||||
|
||||
<div class="">
|
||||
<div>
|
||||
<h2 class="heading title">{% block title %}{% endblock %}</h2>
|
||||
</div>
|
||||
|
||||
<summary class="heading-container">
|
||||
{% block content %}
|
||||
{% if content and with_content %}
|
||||
{% autoescape off %}
|
||||
{{ content|striptags|truncatewords:64|linebreaks }}
|
||||
{% endautoescape %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
</summary>
|
||||
|
||||
<div class="actions">
|
||||
{% block actions %}
|
||||
<a class="button btn-hg float-right" href="{{ object.get_absolute_url|escape }}">
|
||||
<span class="icon">
|
||||
<i class="fas fa-external-link"></i>
|
||||
</span>
|
||||
<label>{% translate "More infos" %}</label>
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
|
||||
{% else %}
|
||||
<article class="media item {% block css %}{% endblock%}">
|
||||
{% if has_cover|default_if_none:True %}
|
||||
<div class="media-left">
|
||||
{% if is_thin %}
|
||||
<img src="{% thumbnail object.cover|default:station.default_cover 64x64 crop=scale %}"
|
||||
class="cover is-tiny">
|
||||
{% else %}
|
||||
<img src="{% thumbnail object.cover|default:station.default_cover 128x128 crop=scale %}"
|
||||
class="cover is-small">
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="media-content">
|
||||
<h5 class="title is-5 has-text-weight-normal">
|
||||
{% block title %}
|
||||
{% if object.is_published %}
|
||||
<a href="{{ object.get_absolute_url }}">{{ object.title }}</a>
|
||||
{% else %}
|
||||
{{ object.title }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
</h5>
|
||||
<div class="subtitle is-6 has-text-weight-light">
|
||||
{% block subtitle %}
|
||||
{% if object.category %}{{ object.category.title }}{% endif %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
|
||||
{% if has_headline|default_if_none:True %}
|
||||
<div class="headline">
|
||||
{% block headline %}{{ object.headline }}{% endblock %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% if not no_actions %}
|
||||
{% block actions %}{% endblock %}
|
||||
{% if with_container %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</article>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
|
23
aircox/templates/aircox/widgets/card.html
Normal file
23
aircox/templates/aircox/widgets/card.html
Normal file
|
@ -0,0 +1,23 @@
|
|||
{% load i18n %}
|
||||
|
||||
{% block outer %}
|
||||
<article class="preview preview-card {% if not cover %}no-cover {% endif %}{% if is_primary %}is-primary{% endif %}{% block container_class %}{% endblock %}"
|
||||
style="background-image: url({{ cover }})">
|
||||
{% block inner %}
|
||||
<header class="headings" >
|
||||
{% block headings %}
|
||||
<div>
|
||||
<a href="{{ url|escape }}" class="heading title">{% block title %}{{ title|default:"" }}{% endblock %}</a>
|
||||
</div>
|
||||
<div>
|
||||
<span class="heading subtitle">{% block subtitle %}{{ subtitle|default:"" }}{% endblock %}</span>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
<div class="actions">
|
||||
{% block actions %}{% endblock %}
|
||||
</div>
|
||||
</header>
|
||||
{% endblock %}
|
||||
</article>
|
||||
{% endblock %}
|
7
aircox/templates/aircox/widgets/carousel.html
Normal file
7
aircox/templates/aircox/widgets/carousel.html
Normal file
|
@ -0,0 +1,7 @@
|
|||
{% load aircox %}
|
||||
|
||||
<div class="card-grid">
|
||||
{% for object in object_list %}
|
||||
{% page_widget "card" object.episode diffusion=object %}
|
||||
{% endfor %}
|
||||
</div>
|
|
@ -11,36 +11,10 @@ An empty date results to a title or a separator
|
|||
{% endcomment %}
|
||||
{% load i18n %}
|
||||
|
||||
<div class="media" role="menu"
|
||||
aria-label="{% translate "pick a date" %}">
|
||||
<div class="media-content">
|
||||
<div class="tabs is-toggle">
|
||||
<ul>
|
||||
{% for day in dates %}
|
||||
<li class="{% if day == date %}is-active{% endif %}">
|
||||
<a href="{% url url_name date=day %}">
|
||||
{{ day|date:"D. d" }}
|
||||
<div>
|
||||
<a class="heading {% if day == date %}highlight{% endif %}" href="{% url url_name date=day %}">
|
||||
{{ day|date:"l d" }}
|
||||
</a>
|
||||
</li>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="media-right">
|
||||
<form action="{% url url_name %}" method="GET" class="navbar-body"
|
||||
aria-label="{% translate "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">
|
||||
{% comment %}Translators: form button to select a date{% endcomment %}
|
||||
<button class="button is-primary">{% translate "Go" %}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
10
aircox/templates/aircox/widgets/diffusion_card.html
Normal file
10
aircox/templates/aircox/widgets/diffusion_card.html
Normal file
|
@ -0,0 +1,10 @@
|
|||
{% comment %}
|
||||
Context:
|
||||
- object: diffusion
|
||||
- "episode_item"'s context (except object and diffusion)
|
||||
{% endcomment %}
|
||||
{% with object as diffusion %}
|
||||
{% with object.episode as object %}
|
||||
{% include "aircox/widgets/episode_card.html" %}
|
||||
{% endwith %}
|
||||
{% endwith %}
|
|
@ -3,19 +3,4 @@ Context:
|
|||
- object_list: object list
|
||||
- date: date for list
|
||||
{% endcomment %}
|
||||
<table id="timetable{% if date %}-{{ date|date:"Y-m-d" }}{% endif %}" class="timetable">
|
||||
{% for diffusion in object_list %}
|
||||
<tr class="{% if diffusion.is_now %}has-background-primary{% endif %}">
|
||||
<td class="pr-2 pb-2">
|
||||
<time datetime="{{ diffusion.start|date:"c" }}">
|
||||
{{ diffusion.start|date:"H:i" }} - {{ diffusion.end|date:"H:i" }}
|
||||
</time>
|
||||
</td>
|
||||
<td class="pb-2">
|
||||
{% with diffusion.episode as object %}
|
||||
{% include "aircox/widgets/episode_item.html" %}
|
||||
{% endwith %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% load aircox %}
|
||||
|
|
15
aircox/templates/aircox/widgets/diffusion_list_header.html
Normal file
15
aircox/templates/aircox/widgets/diffusion_list_header.html
Normal file
|
@ -0,0 +1,15 @@
|
|||
{% extends "./header.html" %}
|
||||
|
||||
{% block outer %}
|
||||
{% with date|date:"l d F Y" as subtitle %}
|
||||
{{ block.super }}
|
||||
{% endwith %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block header-nav %}
|
||||
<nav class="column has-text-right">
|
||||
{{ block.super }}
|
||||
{% include "./dates_menu.html" with url_name="diffusion-list" %}
|
||||
</nav>
|
||||
{% endblock %}
|
32
aircox/templates/aircox/widgets/episode.html
Normal file
32
aircox/templates/aircox/widgets/episode.html
Normal file
|
@ -0,0 +1,32 @@
|
|||
{% extends "./page.html" %}
|
||||
{% load i18n humanize aircox %}
|
||||
|
||||
{% block subtitle %}
|
||||
{% if diffusion %}
|
||||
{% if timetable %}
|
||||
{{ diffusion.start|date:"g:i" }}
|
||||
—
|
||||
{{ diffusion.end|date:"g:i" }}
|
||||
{% else %}
|
||||
{{ diffusion.start|naturalday }},
|
||||
{{ diffusion.start|date:"g:i" }}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{{ block.super }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block actions %}
|
||||
{{ block.super }}
|
||||
|
||||
{% if object.sound_set.count %}
|
||||
<button class="button action" @click="player.playButtonClick($event)"
|
||||
data-sounds="{{ object.podcasts|json }}">
|
||||
<span class="icon is-small">
|
||||
<span class="fas fa-play"></span>
|
||||
</span>
|
||||
<label>{% translate "Listen" %}</label>
|
||||
</button>
|
||||
{% endif %}
|
||||
{% endblock %}
|
36
aircox/templates/aircox/widgets/episode_card.html
Normal file
36
aircox/templates/aircox/widgets/episode_card.html
Normal file
|
@ -0,0 +1,36 @@
|
|||
{% extends "./basepage_card.html" %}
|
||||
{% load humanize %}
|
||||
|
||||
{% block title %}
|
||||
{% if not object.is_published and object.program.is_published %}
|
||||
<a href="{{ object.program.get_absolute_url }}">
|
||||
{{ object.program.title }}
|
||||
</a>
|
||||
{% else %}
|
||||
{{ block.super }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block class %}
|
||||
{% if object.is_now %}is-active{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block subtitle %}
|
||||
{% if diffusion %}
|
||||
{{ diffusion.start|naturalday }},
|
||||
{{ diffusion.start|date:"g:i" }}
|
||||
{% else %}
|
||||
{{ block.super }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
{% if not object.content %}
|
||||
{% with object.parent.content as content %}
|
||||
{{ block.super }}
|
||||
{% endwith %}
|
||||
{% else %}
|
||||
{{ block.super }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -1,58 +1,36 @@
|
|||
{% extends "aircox/widgets/page_item.html" %}
|
||||
{% comment %}
|
||||
List item for an episode.
|
||||
|
||||
Context variables:
|
||||
- object: episode
|
||||
- diffusion: episode's diffusion
|
||||
- hide_schedule: if True, do not display start time
|
||||
{% endcomment %}
|
||||
|
||||
{% load i18n easy_thumbnails_tags aircox %}
|
||||
{% extends "./basepage_item.html" %}
|
||||
{% load i18n humanize %}
|
||||
|
||||
{% block title %}
|
||||
{% if not object.is_published and object.program.is_published %}
|
||||
<a href="{{ object.program.get_absolute_url }}">
|
||||
{{ object.program.title }}
|
||||
{% if diffusion %}
|
||||
—
|
||||
{{ diffusion.start|date:"d F" }}
|
||||
{% endif %}
|
||||
</a>
|
||||
{% else %}
|
||||
{{ block.super }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block class %}
|
||||
{% if object.is_now %}is-active{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block subtitle %}
|
||||
{{ block.super }}
|
||||
|
||||
{% if diffusion %}
|
||||
{% if not hide_schedule %}
|
||||
{% if object.category %}—{% endif %}
|
||||
<time datetime="{{ diffusion.start|date:"c" }}" title="{{ diffusion.start }}">
|
||||
{{ diffusion.start|date:"d M, H:i" }}
|
||||
</time>
|
||||
{{ diffusion.start|naturalday }},
|
||||
{{ diffusion.start|date:"g:i" }}
|
||||
{% else %}
|
||||
{{ block.super }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% if diffusion.initial %}
|
||||
{% with diffusion.initial.date as date %}
|
||||
<span title="{% blocktranslate %}Rerun of {{ date }}{% endblocktranslate %}">
|
||||
{% translate "(rerun)" %}
|
||||
</span>
|
||||
|
||||
{% block content %}
|
||||
{% if not object.content %}
|
||||
{% with object.parent.content as content %}
|
||||
{{ block.super }}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block actions %}
|
||||
{% if object.sound_set.public.count %}
|
||||
<button class="button" @click="player.playButtonClick($event)"
|
||||
data-sounds="{{ object.podcasts|json }}">
|
||||
<span class="icon is-small">
|
||||
<span class="fas fa-play"></span>
|
||||
</span>
|
||||
</button>
|
||||
{% else %}
|
||||
{{ block.super }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
|
23
aircox/templates/aircox/widgets/header.html
Normal file
23
aircox/templates/aircox/widgets/header.html
Normal file
|
@ -0,0 +1,23 @@
|
|||
{% extends "./card.html" %}
|
||||
|
||||
{% block container_class %}wide{% endblock %}
|
||||
|
||||
|
||||
{% block headings %}
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
{{ block.super }}
|
||||
|
||||
<section class="heading content">
|
||||
{% block content %}
|
||||
{% if content and with_content %}
|
||||
{% autoescape off %}
|
||||
{{ content|linebreaks }}
|
||||
{% endautoescape %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
</section>
|
||||
</div>
|
||||
{% block header-nav %}{% endblock %}
|
||||
</div>
|
||||
{% endblock %}
|
38
aircox/templates/aircox/widgets/home_header.html
Normal file
38
aircox/templates/aircox/widgets/home_header.html
Normal file
|
@ -0,0 +1,38 @@
|
|||
{% extends "./base_header.html" %}
|
||||
{% load i18n humanize %}
|
||||
|
||||
|
||||
|
||||
{% block subtitle %}
|
||||
{% if diffusion %}
|
||||
{{ diffusion.start|naturalday }},
|
||||
{{ diffusion.start|date:"g:i" }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block headings %}
|
||||
{{ block.super }}
|
||||
{% with diffusion.episode.content|default:diffusion.episode.program.content|striptags|safe as content %}
|
||||
{% if content %}
|
||||
<div class="heading-container content">
|
||||
{{ content|truncatewords:64|linebreaks }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="actions">
|
||||
<button class="btn-outline-hg button">
|
||||
<span class="icon">
|
||||
<i class="fas fa-play"></i>
|
||||
</span>
|
||||
{% trans "Listen" %}
|
||||
</button>
|
||||
<a class="btn-outline-hg button" href="{{ diffusion.episode.get_absolute_url }}">
|
||||
<span class="icon">
|
||||
<i class="fas fa-external-link"></i>
|
||||
</span>
|
||||
{% trans "More informations" %}
|
||||
</a>
|
||||
</div>
|
||||
{% endwith %}
|
||||
{% endblock %}
|
42
aircox/templates/aircox/widgets/item.html
Normal file
42
aircox/templates/aircox/widgets/item.html
Normal file
|
@ -0,0 +1,42 @@
|
|||
{% load i18n aircox %}
|
||||
|
||||
{% block outer %}
|
||||
<article class="preview list-item {% if is_primary %}is-primary{% endif %}{% block card_class %}{% endblock %}">
|
||||
{% block inner %}
|
||||
|
||||
<a href="{{ url|escape }}" class="headings is-fullwidth columns">
|
||||
{% block headings %}
|
||||
<div class="column">
|
||||
<span class="heading title">{% block title %}{% endblock %}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="heading subtitle">{% block subtitle %}{% endblock %}</span>
|
||||
</div>
|
||||
{% endblock %}
|
||||
</a>
|
||||
|
||||
<div class="media">
|
||||
{% if object.cover %}
|
||||
<div class="media-left preview-cover small"
|
||||
style="background-image: url({{ object.cover.url }})">
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="media-content">
|
||||
<section class="content">
|
||||
{% block content %}
|
||||
{% if content and with_content %}
|
||||
{% autoescape off %}
|
||||
{{ content|striptags|linebreaks }}
|
||||
{% endautoescape %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
</section>
|
||||
|
||||
<div class="actions is-flex-grow-0">
|
||||
{% block actions %}{% endblock %}
|
||||
</div>
|
||||
</template>
|
||||
{% endblock %}
|
||||
</div>
|
||||
</article>
|
||||
{% endblock %}
|
|
@ -1,3 +1,4 @@
|
|||
{% extends "./page.html" %}
|
||||
{% load i18n aircox %}
|
||||
{% comment %}
|
||||
List item for a log, either for a logged track or diffusion (as diffusion).
|
||||
|
@ -11,12 +12,10 @@ for design review.
|
|||
|
||||
{% endcomment %}
|
||||
|
||||
{% block outer %}
|
||||
{% if object|is_diffusion %}
|
||||
{% with object as diffusion %}
|
||||
{% include "aircox/widgets/diffusion_item.html" %}
|
||||
{% endwith %}
|
||||
{% include "./diffusion.html" with object=diffusion.episode %}
|
||||
{% else %}
|
||||
{% with object.track as object %}
|
||||
{% include "aircox/widgets/track_item.html" %}
|
||||
{% endwith %}
|
||||
{% include "aircox/widgets/track_item.html" with object=object.track log=object %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -1,30 +0,0 @@
|
|||
{% comment %}
|
||||
Render list of logs (as widget).
|
||||
|
||||
Context:
|
||||
- object_list: list of logs to display
|
||||
- is_thin: if True, hide some information in order to fit in a thin container
|
||||
{% endcomment %}
|
||||
{% load aircox %}
|
||||
|
||||
{% with True as hide_schedule %}
|
||||
<table class="table is-striped is-hoverable is-fullwidth" role="list">
|
||||
{% for object in object_list %}
|
||||
<tr {% if object|is_diffusion and object.is_now %}class="is-selected"{% endif %}>
|
||||
<td>
|
||||
{% if object|is_diffusion %}
|
||||
<time datetime="{{ object.start }}" title="{{ object.start }}">
|
||||
{{ object.start|date:"H:i" }}
|
||||
{% if not is_thin %} - {{ object.end|date:"H:i" }}{% endif %}
|
||||
</time>
|
||||
{% else %}
|
||||
<time datetime="{{ object.date }}" title="{{ object.date }}">
|
||||
{{ object.date|date:"H:i" }}
|
||||
</time>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{% include "aircox/widgets/log_item.html" %}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endwith %}
|
15
aircox/templates/aircox/widgets/log_list_header.html
Normal file
15
aircox/templates/aircox/widgets/log_list_header.html
Normal file
|
@ -0,0 +1,15 @@
|
|||
{% extends "./header.html" %}
|
||||
|
||||
{% block outer %}
|
||||
{% with date|date:"l d F Y" as subtitle %}
|
||||
{{ block.super }}
|
||||
{% endwith %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block header-nav %}
|
||||
<nav class="column has-text-right">
|
||||
{{ block.super }}
|
||||
{% include "./dates_menu.html" with url_name="log-list" %}
|
||||
</nav>
|
||||
{% endblock %}
|
30
aircox/templates/aircox/widgets/page.html
Normal file
30
aircox/templates/aircox/widgets/page.html
Normal file
|
@ -0,0 +1,30 @@
|
|||
{% extends widget_template %}
|
||||
{% load i18n %}
|
||||
|
||||
|
||||
{% block outer %}
|
||||
{% with object.get_absolute_url as url %}
|
||||
{% with object.cover.url as cover %}
|
||||
{{ block.super }}
|
||||
{% endwith %}
|
||||
{% endwith %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block title %}
|
||||
{% if title %}
|
||||
{{ block.super }}
|
||||
{% elif object %}
|
||||
{{ object.display_title }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
{% if content %}
|
||||
{{ content }}
|
||||
{% elif object %}
|
||||
{{ block.super }}
|
||||
{{ object.display_headline }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
13
aircox/templates/aircox/widgets/page_card.html
Normal file
13
aircox/templates/aircox/widgets/page_card.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
{% extends widget|default:"./card.html" %}
|
||||
|
||||
{% block outer %}
|
||||
{% if object %}
|
||||
{% with content=object.get_display_excerpt() %}
|
||||
{% with title=object.get_display_title() %}
|
||||
{{ block.super }}
|
||||
{% endwith %}
|
||||
{% endwith %}
|
||||
{% else %}
|
||||
{{ block.super }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -3,3 +3,11 @@
|
|||
{% block card_title %}
|
||||
{% block title %}{{ block.super }}{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
{% block card_subtitle %}
|
||||
{% block subtitle %}{{ block.super }}{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
{% block card_class %}
|
||||
{% block class %}{{ block.super }}{% endblock %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -5,10 +5,10 @@ Context:
|
|||
- object_list: object list
|
||||
- list_url: url to complete list page
|
||||
{% endcomment %}
|
||||
{% load i18n %}
|
||||
{% load i18n aircox %}
|
||||
|
||||
{% for object in object_list %}
|
||||
{% include object.item_template_name %}
|
||||
{% widget object.item_template_name %}
|
||||
{% endfor %}
|
||||
|
||||
{% if list_url %}
|
||||
|
|
|
@ -5,9 +5,16 @@ Context:
|
|||
- object: track to render
|
||||
{% endcomment %}
|
||||
|
||||
<span class="content">
|
||||
<span class="has-text-info is-size-5">♬</span>
|
||||
<span>{{ object.title }}</span>
|
||||
<span class="has-text-grey-dark has-text-weight-light">
|
||||
{% if log %}
|
||||
<span>{{ log.date|date:"H:i" }} — </span>
|
||||
{% endif %}
|
||||
<span class="has-text-weight-bold">{{ object.title }}</span>
|
||||
{% if object.artist and object.artist != object.title %}
|
||||
<span>
|
||||
— {{ object.artist }}
|
||||
{% if object.info %}(<i>{{ object.info }}</i>){% endif %}
|
||||
</span>
|
||||
{% endif %}
|
||||
</span>
|
||||
|
|
42
aircox/templates/aircox/widgets/wide.html
Normal file
42
aircox/templates/aircox/widgets/wide.html
Normal file
|
@ -0,0 +1,42 @@
|
|||
{% load i18n %}
|
||||
|
||||
{% block outer %}
|
||||
<article class="preview preview-card columns wide{% if is_primary %}is-primary{% endif %}{% block card_class %}{% endblock %}">
|
||||
{% block inner %}
|
||||
<header class="headings column preview-cover"
|
||||
style="background-image: url({{ object.cover.url }})">
|
||||
{% block headings %}
|
||||
<div>
|
||||
<a href="{{ url|escape }}" class="heading title">{% block title %}{% endblock %}</a>
|
||||
</div>
|
||||
<div>
|
||||
<span class="heading subtitle">{% block subtitle %}{% endblock %}</span>
|
||||
</div>
|
||||
{% endblock %}
|
||||
</header>
|
||||
|
||||
<div class="height-full column">
|
||||
<section class="content headings-container">
|
||||
{% block content %}
|
||||
{% if content and with_content %}
|
||||
{% autoescape off %}
|
||||
{{ content|striptags|linebreaks }}
|
||||
{% endautoescape %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
</section>
|
||||
|
||||
<div class="actions">
|
||||
{% block actions %}
|
||||
<a class="button btn-hg float-right" href="{{ object.get_absolute_url|escape }}">
|
||||
<span class="icon">
|
||||
<i class="fas fa-external-link"></i>
|
||||
</span>
|
||||
<label>{% translate "More infos" %}</label>
|
||||
</a>
|
||||
{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
</article>
|
||||
{% endblock %}
|
|
@ -3,14 +3,32 @@ import random
|
|||
|
||||
from django import template
|
||||
from django.contrib.admin.templatetags.admin_urls import admin_urlname
|
||||
from django.template.loader import render_to_string
|
||||
from django.urls import reverse
|
||||
|
||||
from aircox.models import Diffusion, Log
|
||||
|
||||
|
||||
random.seed()
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.simple_tag(name="page_widget", takes_context=True)
|
||||
def do_page_widget(context, widget, object, dir="aircox/widgets", **ctx):
|
||||
"""Render widget for the provided page and context."""
|
||||
ctx["request"] = context["request"]
|
||||
ctx["object"] = object
|
||||
ctx["widget"] = widget
|
||||
ctx["widget_template"] = f"{dir}/{widget}.html"
|
||||
return render_to_string(object.get_template_name(widget), ctx)
|
||||
|
||||
|
||||
@register.filter(name="page_template")
|
||||
def do_page_template(self, page, component):
|
||||
"""For a provided page object and component name, return template name."""
|
||||
return page.get_template(component)
|
||||
|
||||
|
||||
@register.filter(name="admin_url")
|
||||
def do_admin_url(obj, arg, pass_id=True):
|
||||
"""Reverse admin url for object."""
|
||||
|
|
|
@ -8,6 +8,7 @@ __all__ = ("BaseView", "BaseAPIView")
|
|||
|
||||
|
||||
class BaseView(TemplateResponseMixin, ContextMixin):
|
||||
header_template_name = "aircox/widgets/header.html"
|
||||
has_sidebar = True
|
||||
"""Show side navigation."""
|
||||
has_filters = False
|
||||
|
@ -38,6 +39,7 @@ class BaseView(TemplateResponseMixin, ContextMixin):
|
|||
kwargs.setdefault("station", self.station)
|
||||
kwargs.setdefault("page", self.get_page())
|
||||
kwargs.setdefault("has_filters", self.has_filters)
|
||||
kwargs.setdefault("header_template_name", self.header_template_name)
|
||||
|
||||
has_sidebar = kwargs.setdefault("has_sidebar", self.has_sidebar)
|
||||
if has_sidebar and "sidebar_object_list" not in kwargs:
|
||||
|
|
|
@ -27,14 +27,15 @@ class HomeView(BaseView, ListView):
|
|||
|
||||
def get_next_diffs(self):
|
||||
now = tz.now()
|
||||
current_diff = Diffusion.objects.on_air().now(now).first()
|
||||
next_diffs = Diffusion.objects.on_air().after(now)
|
||||
query = Diffusion.objects.on_air().select_related("episode")
|
||||
current_diff = query.now(now).first()
|
||||
next_diffs = query.after(now)
|
||||
if current_diff:
|
||||
diffs = [current_diff] + list(
|
||||
next_diffs.exclude(pk=current_diff.pk)[:2]
|
||||
next_diffs.exclude(pk=current_diff.pk)[:9]
|
||||
)
|
||||
else:
|
||||
diffs = next_diffs[:3]
|
||||
diffs = next_diffs[:10]
|
||||
return diffs
|
||||
|
||||
def get_last_publications(self):
|
||||
|
@ -52,8 +53,16 @@ class HomeView(BaseView, ListView):
|
|||
return items
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["logs"] = self.get_logs(context["object_list"])
|
||||
context["next_diffs"] = self.get_next_diffs()
|
||||
context["last_publications"] = self.get_last_publications()[:5]
|
||||
return context
|
||||
next_diffs = self.get_next_diffs()
|
||||
current_diff = next_diffs and next_diffs[0]
|
||||
|
||||
kwargs.update(
|
||||
{
|
||||
"object": current_diff.episode,
|
||||
"diffusion": current_diff,
|
||||
"logs": self.get_logs(self.object_list),
|
||||
"next_diffs": next_diffs,
|
||||
"last_publications": self.get_last_publications()[:5],
|
||||
}
|
||||
)
|
||||
return super().get_context_data(**kwargs)
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
"@fortawesome/fontawesome-free": "^6.0.0",
|
||||
"core-js": "^3.8.3",
|
||||
"lodash": "^4.17.21",
|
||||
"vue": "^3.2.13"
|
||||
"vue": "^3.2.13",
|
||||
"vue3-carousel": "^0.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.12.16",
|
||||
|
@ -20,7 +21,7 @@
|
|||
"@vue/cli-plugin-babel": "~5.0.0",
|
||||
"@vue/cli-plugin-eslint": "~5.0.0",
|
||||
"@vue/cli-service": "~5.0.0",
|
||||
"bulma": "^0.9.3",
|
||||
"bulma": "^0.9.4",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-plugin-vue": "^8.0.3",
|
||||
"sass": "^1.49.9",
|
||||
|
|
|
@ -1,13 +1,47 @@
|
|||
import 'vue3-carousel/dist/carousel.css'
|
||||
import components from './components'
|
||||
|
||||
import { Carousel, Pagination, Navigation, Slide } from 'vue3-carousel'
|
||||
|
||||
const App = {
|
||||
el: '#app',
|
||||
delimiters: ['[[', ']]'],
|
||||
components: {...components},
|
||||
components: {
|
||||
...components,
|
||||
Slide,
|
||||
Carousel,
|
||||
Pagination,
|
||||
Navigation,
|
||||
},
|
||||
|
||||
computed: {
|
||||
player() { return window.aircox.player; },
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
carouselBreakpoints: {
|
||||
400: {
|
||||
itemsToShow: 1
|
||||
},
|
||||
600: {
|
||||
itemsToShow: 1.75
|
||||
},
|
||||
800: {
|
||||
itemsToShow: 3
|
||||
},
|
||||
1024: {
|
||||
itemsToShow: 4
|
||||
},
|
||||
1280: {
|
||||
itemsToShow: 4
|
||||
},
|
||||
1380: {
|
||||
itemsToShow: 5
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const PlayerApp = {
|
||||
|
|
|
@ -1,5 +1,50 @@
|
|||
@charset "utf-8";
|
||||
|
||||
|
||||
$font-special: "bagnard";
|
||||
$font-special-url: url("assets/Bagnard.otf");
|
||||
|
||||
$black: #000;
|
||||
$white: #fff;
|
||||
|
||||
$mp-1: 0.2em;
|
||||
$mp-2: 0.4em;
|
||||
$mp-3: 0.8em;
|
||||
$mp-4: 1.2em;
|
||||
$mp-5: 1.6em;
|
||||
$mp-6: 2em;
|
||||
$mp-7: 4em;
|
||||
|
||||
$text-size-small: 0.6em;
|
||||
$text-size-smaller: 0.8em;
|
||||
$text-size: 1em;
|
||||
$text-size-medium: 1.2em;
|
||||
$text-size-bigger: 1.6em;
|
||||
$text-size-big: 2em;
|
||||
|
||||
$h1-size: 40px;
|
||||
$h2-size: 32px;
|
||||
$h3-size: 28px;
|
||||
$h4-size: 24px;
|
||||
$h5-size: 20px;
|
||||
$h6-size: 14px;
|
||||
|
||||
$weight-light: 100;
|
||||
$weight-lighter: 300;
|
||||
$weight-normal: 400;
|
||||
$weight-bolder: 500;
|
||||
$weight-bold: 700;
|
||||
|
||||
$screen-very-small: 400px;
|
||||
//TODO: switch small & smaller
|
||||
$screen-small: 600px;
|
||||
$screen-smaller: 800px;
|
||||
$screen-normal: 1024px;
|
||||
$screen-wider: 1280px;
|
||||
$screen-wide: 1380px;
|
||||
|
||||
|
||||
|
||||
@import "~bulma/sass/utilities/_all.sass";
|
||||
@import "~bulma/sass/components/dropdown.sass";
|
||||
|
||||
|
@ -325,3 +370,324 @@ aside {
|
|||
width: 100%;
|
||||
border: none;
|
||||
}
|
||||
|
||||
|
||||
// -- layout
|
||||
|
||||
:root {
|
||||
--text-color: black;
|
||||
--highlight-color: rgba(255, 255, 0, 1);
|
||||
--highlight-color-alpha: rgba(255, 255, 0, 0.6);
|
||||
--highlight-color-2: rgb(0, 0, 254);
|
||||
--highlight-color-2-alpha: rgb(0, 0, 254, 0.6);
|
||||
--heading-height: 30em;
|
||||
--heading-title-bg-color: rgba(255, 255, 0, 1);
|
||||
--heading-bg-color: var(--highlight-color);
|
||||
--heading-bg-highlight-color: var(--highlight-color-2);
|
||||
|
||||
--preview-media-height: 10em;
|
||||
--preview-media-cover-size: 10em;
|
||||
|
||||
--preview-cover-size: 24em;
|
||||
--preview-cover-small-size: 14em;
|
||||
}
|
||||
|
||||
.page a {
|
||||
background-color: var(--highlight-color-alpha);
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
|
||||
// ---- helpers
|
||||
.d-inline { display: inline; }
|
||||
.d-block { display: block; }
|
||||
.d-inline-block { display: inline-block; }
|
||||
|
||||
.p-relative { position: relative }
|
||||
.p-absolute { position: absolute }
|
||||
.p-fixed { position: fixed }
|
||||
.p-sticky { position: sticky }
|
||||
.p-static { position: static }
|
||||
|
||||
.height-full { height: 100%; }
|
||||
.flex-push-right { margin-left: auto; }
|
||||
|
||||
|
||||
.is-clickable { cursor: pointer; }
|
||||
|
||||
// ---- components
|
||||
.btn-hg, .btn-outline-hg {
|
||||
border: 0.1em var(--highlight-color) solid;
|
||||
background-color: var(--highlight-color-alpha) !important;
|
||||
border-radius: 0.2em;
|
||||
}
|
||||
|
||||
|
||||
.button {
|
||||
&.action {
|
||||
border-color: var(--highlight-color-2-alpha);
|
||||
justify-content: center;
|
||||
padding: $mp-2 !important;
|
||||
min-width: 2em;
|
||||
|
||||
.icon { margin: 0em !important; }
|
||||
|
||||
label {
|
||||
margin-left: $mp-2;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.list-filters {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.content {
|
||||
font-size: $text-size-medium;
|
||||
}
|
||||
|
||||
|
||||
// ---- items
|
||||
|
||||
.preview {
|
||||
position: relative;
|
||||
background-size: cover;
|
||||
|
||||
&.preview-card {
|
||||
&:not(.wide) {
|
||||
max-width: 30em;
|
||||
}
|
||||
}
|
||||
|
||||
&.preview-item {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&.columns, .headings.columns {
|
||||
margin: 0em;
|
||||
.column { padding: 0em; }
|
||||
}
|
||||
|
||||
.title {
|
||||
font-weight: $weight-bold;
|
||||
font-size: $text-size-bigger;
|
||||
}
|
||||
.subtitle {
|
||||
font-weight: $weight-bolder;
|
||||
font-size: $text-size-bigger;
|
||||
}
|
||||
.content, .actions {
|
||||
font-size: $text-size-medium;
|
||||
}
|
||||
|
||||
.headings {
|
||||
background-size: cover;
|
||||
|
||||
* { margin: 0em; padding: 0em; }
|
||||
|
||||
a {
|
||||
color: var(--text-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.heading, .headings-container > * {
|
||||
display: inline-block;
|
||||
|
||||
&:not(:empty) {
|
||||
background-color: var(--heading-bg-color);
|
||||
padding: $mp-1;
|
||||
margin-top: 0em !important;
|
||||
vertical-align: top;
|
||||
|
||||
&.highlight {
|
||||
background-color: var(--heading-bg-highlight-color);
|
||||
color: var(--highlight-color);
|
||||
}
|
||||
}
|
||||
|
||||
&.title {
|
||||
background-color: var(--heading-title-bg-color);
|
||||
}
|
||||
}
|
||||
|
||||
.actions {
|
||||
&.no-label label {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.list-item {
|
||||
width: 100%;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-bottom: calc($mp-4 / 2);
|
||||
}
|
||||
|
||||
&:not(:first-child) {
|
||||
margin-top: calc($mp-4 / 2);
|
||||
}
|
||||
|
||||
.headings {
|
||||
padding-top: 0em;
|
||||
margin-bottom: $mp-3 !important;
|
||||
background-color: var(--heading-bg-color);
|
||||
}
|
||||
|
||||
.media-content {
|
||||
height: var(--preview-cover-small-size);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.content { flex-grow: 1; }
|
||||
|
||||
.actions {
|
||||
flex-grow: 0;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---- cards
|
||||
.preview-cover {
|
||||
background-size: cover;
|
||||
height: var(--preview-cover-size);
|
||||
width: var(--preview-cover-size);
|
||||
|
||||
&.small {
|
||||
min-width: unset;
|
||||
height: var(--preview-cover-small-size);
|
||||
width: var(--preview-cover-small-size) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.preview-card {
|
||||
height: var(--preview-cover-size);
|
||||
min-width: var(--preview-cover-size);
|
||||
|
||||
.card-grid & {
|
||||
min-width: unset;
|
||||
}
|
||||
|
||||
.headings {
|
||||
width: 100%;
|
||||
min-height: 100%;
|
||||
|
||||
padding-top: $mp-3;
|
||||
|
||||
& > div:not(:last-child) {
|
||||
margin-bottom: $mp-3;
|
||||
}
|
||||
|
||||
nav a {
|
||||
font-size: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
.heading {
|
||||
margin-bottom: $mp-3;
|
||||
}
|
||||
|
||||
.actions {
|
||||
position: absolute;
|
||||
bottom: $mp-3;
|
||||
right: $mp-3;
|
||||
|
||||
label {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.header {
|
||||
background-size: cover;
|
||||
|
||||
.preview {
|
||||
height: var(--heading-height);
|
||||
|
||||
&.no-cover {
|
||||
height: unset;
|
||||
}
|
||||
|
||||
.headings, > .container {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
> .container, {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.preview-card {
|
||||
max-width: unset;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: $h1-size;
|
||||
}
|
||||
.subtitle {
|
||||
font-size: $h2-size;
|
||||
}
|
||||
.content {
|
||||
display: inline !important;
|
||||
font-size: $text-size-medium;
|
||||
font-weight: $weight-bolder;
|
||||
text-align: right;
|
||||
|
||||
|
||||
p {
|
||||
margin-bottom: $mp-3
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// -- program grid
|
||||
.preview-card {
|
||||
header {
|
||||
.info {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-active {
|
||||
border-bottom: 1px var(--highlight-color) solid;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
.card-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
gap: $mp-4;
|
||||
}
|
||||
|
||||
@media screen and (max-width: $screen-wide) {
|
||||
.preview:not(.list-item) {
|
||||
height: 20em !important;
|
||||
}
|
||||
|
||||
.card-grid .preview-card {
|
||||
height: 20em;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: $screen-normal) {
|
||||
.card-grid {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
|
||||
.preview-card:nth-child(3) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
23
assets/src/components/ACarousel.vue
Normal file
23
assets/src/components/ACarousel.vue
Normal file
|
@ -0,0 +1,23 @@
|
|||
<template>
|
||||
<carousel :items-to-show="1.5">
|
||||
<slot></slot>
|
||||
<template #addons>
|
||||
<navigation />
|
||||
<pagination />
|
||||
</template>
|
||||
</carousel>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// If you are using PurgeCSS, make sure to whitelist the carousel CSS classes
|
||||
import 'vue3-carousel/dist/carousel.css'
|
||||
import { Carousel, Pagination, Navigation } from 'vue3-carousel'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Carousel,
|
||||
Pagination,
|
||||
Navigation,
|
||||
},
|
||||
}
|
||||
</script>
|
43
assets/src/components/ADropdown.vue
Normal file
43
assets/src/components/ADropdown.vue
Normal file
|
@ -0,0 +1,43 @@
|
|||
<template>
|
||||
<div>
|
||||
<div :class="itemClass" @click="noButton && toggle()">
|
||||
<slot name="button">
|
||||
<span :class="['float-right', buttonClass]" @click="toggle()">
|
||||
<span class="icon">
|
||||
<i v-if="!active" :class="buttonIconOpen"></i>
|
||||
<i v-if="active" :class="buttonIconClose"></i>
|
||||
</span>
|
||||
</span>
|
||||
</slot>
|
||||
<slot name="item"></slot>
|
||||
</div>
|
||||
<div :class="contentClass" v-if="active">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
"active": this.open,
|
||||
}
|
||||
},
|
||||
|
||||
props: {
|
||||
itemClass: String,
|
||||
buttonClass: String,
|
||||
buttonIconOpen: { type: String, default:"fa fa-angle-down"},
|
||||
buttonIconClose: { type: String, default:"fa fa-angle-up"},
|
||||
contentClass: String,
|
||||
open: {type: Boolean, default: false},
|
||||
noButton: {type: Boolean, default: false},
|
||||
},
|
||||
|
||||
methods: {
|
||||
toggle() {
|
||||
this.active = !this.active
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
|
@ -1,4 +1,5 @@
|
|||
import AAutocomplete from './AAutocomplete.vue'
|
||||
import ADropdown from "./ADropdown.vue"
|
||||
import AEpisode from './AEpisode.vue'
|
||||
import AList from './AList.vue'
|
||||
import APage from './APage.vue'
|
||||
|
@ -14,7 +15,7 @@ import AStreamer from './AStreamer.vue'
|
|||
* Core components
|
||||
*/
|
||||
export const base = {
|
||||
AAutocomplete, AEpisode, AList, APage, APlayer, APlaylist,
|
||||
AAutocomplete, ADropdown, AEpisode, AList, APage, APlayer, APlaylist,
|
||||
AProgress, ASoundItem,
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user