work on home page, fix views & templates issues
This commit is contained in:
parent
215a6ac331
commit
e30d1b54ef
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.
|
@ -19,7 +19,7 @@ __all__ = ['Episode', 'Diffusion', 'DiffusionQuerySet']
|
|||
class Episode(Page):
|
||||
objects = ProgramChildQuerySet.as_manager()
|
||||
detail_url_name = 'episode-detail'
|
||||
item_template_name = 'aircox/episode_item.html'
|
||||
item_template_name = 'aircox/widgets/episode_item.html'
|
||||
|
||||
@property
|
||||
def program(self):
|
||||
|
@ -75,7 +75,9 @@ class DiffusionQuerySet(BaseRerunQuerySet):
|
|||
def today(self, today=None, order=True):
|
||||
""" Diffusions occuring today. """
|
||||
today = today or datetime.date.today()
|
||||
qs = self.filter(Q(start__date=today) | Q(end__date=today))
|
||||
start = tz.datetime.combine(today, datetime.time())
|
||||
end = tz.datetime.combine(today, datetime.time(23, 59, 59, 999))
|
||||
qs = self.filter(start__range = (start, end))
|
||||
return qs.order_by('start') if order else qs
|
||||
|
||||
def at(self, date, order=True):
|
||||
|
@ -90,9 +92,9 @@ class DiffusionQuerySet(BaseRerunQuerySet):
|
|||
"""
|
||||
date = utils.date_or_default(date)
|
||||
if isinstance(date, tz.datetime):
|
||||
qs = self.filter(start__gte=date)
|
||||
qs = self.filter(Q(start__gte=date) | Q(end__gte=date))
|
||||
else:
|
||||
qs = self.filter(start__date__gte=date)
|
||||
qs = self.filter(Q(start__date__gte=date) | Q(end__date__gte=date))
|
||||
return qs.order_by('start')
|
||||
|
||||
def before(self, date=None):
|
||||
|
@ -157,7 +159,7 @@ class Diffusion(BaseRerun):
|
|||
# help_text = _('use this input port'),
|
||||
# )
|
||||
|
||||
item_template_name = 'aircox/diffusion_item.html'
|
||||
item_template_name = 'aircox/widgets/diffusion_item.html'
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('Diffusion')
|
||||
|
@ -181,12 +183,10 @@ class Diffusion(BaseRerun):
|
|||
# self.check_conflicts()
|
||||
|
||||
def save_rerun(self):
|
||||
print('rerun save', self)
|
||||
self.episode = self.initial.episode
|
||||
self.program = self.episode.program
|
||||
|
||||
def save_initial(self):
|
||||
print('initial save', self)
|
||||
self.program = self.episode.program
|
||||
if self.episode != self._initial['episode']:
|
||||
self.rerun_set.update(episode=self.episode, program=self.program)
|
||||
|
@ -221,6 +221,13 @@ class Diffusion(BaseRerun):
|
|||
|
||||
return tz.localtime(self.end, tz.get_current_timezone())
|
||||
|
||||
@property
|
||||
def is_now(self):
|
||||
""" True if diffusion is currently running """
|
||||
now = tz.now()
|
||||
return self.type == self.TYPE_ON_AIR and \
|
||||
self.start <= now and self.end >= now
|
||||
|
||||
# TODO: property?
|
||||
def is_live(self):
|
||||
""" True if Diffusion is live (False if there are sounds files). """
|
||||
|
|
|
@ -271,21 +271,22 @@ class Log(models.Model):
|
|||
object_list += logs[:index]
|
||||
logs = logs[index:]
|
||||
|
||||
# - last log while diff is running
|
||||
if logs[0].date > diff.start:
|
||||
object_list.append(logs[0])
|
||||
if len(logs):
|
||||
# FIXME
|
||||
# - last log while diff is running
|
||||
#if logs[0].date > diff.start:
|
||||
# object_list.append(logs[0])
|
||||
|
||||
# - skips logs while diff is running
|
||||
index = next((i for i, v in enumerate(logs)
|
||||
if v.date < diff.start), len(logs))
|
||||
if index is not None and index > 0:
|
||||
logs = logs[index:]
|
||||
# - skips logs while diff is running
|
||||
index = next((i for i, v in enumerate(logs)
|
||||
if v.date < diff.start), len(logs))
|
||||
if index is not None and index > 0:
|
||||
logs = logs[index:]
|
||||
|
||||
# - add diff
|
||||
object_list.append(diff)
|
||||
|
||||
return object_list
|
||||
|
||||
return object_list if count is None else object_list[:count]
|
||||
|
||||
def print(self):
|
||||
r = []
|
||||
|
|
|
@ -92,7 +92,7 @@ class Page(models.Model):
|
|||
objects = PageQuerySet.as_manager()
|
||||
|
||||
detail_url_name = None
|
||||
item_template_name = 'aircox/page_item.html'
|
||||
item_template_name = 'aircox/widgets/page_item.html'
|
||||
|
||||
def __str__(self):
|
||||
return '{}'.format(self.title or self.pk)
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
.navbar {
|
||||
box-shadow: 0em 0em 0.6em rgba(0, 0, 0, 0.4); }
|
||||
|
||||
.navbar .navbar-brand {
|
||||
padding-right: 1em; }
|
||||
|
||||
|
@ -7211,6 +7208,28 @@ a.navbar-item.is-active {
|
|||
margin: 0em;
|
||||
padding: 0em; }
|
||||
|
||||
.card .title {
|
||||
padding: 0.2em;
|
||||
font-size: 1.25rem;
|
||||
font-weight: 500; }
|
||||
.card .title a {
|
||||
color: #363636; }
|
||||
|
||||
.card.is-primary {
|
||||
box-shadow: 0em 0em 0.5em #0a0a0a; }
|
||||
|
||||
.card-super-title {
|
||||
position: absolute;
|
||||
z-index: 1000;
|
||||
font-size: 1.2em;
|
||||
font-weight: 700;
|
||||
padding: 0.2em;
|
||||
top: 1em;
|
||||
background-color: white; }
|
||||
.card-super-title .fas {
|
||||
padding: 0.1em;
|
||||
font-size: 0.8em; }
|
||||
|
||||
.filters {
|
||||
margin: 1em 0em;
|
||||
background-color: transparent;
|
||||
|
@ -7223,16 +7242,6 @@ a.navbar-item.is-active {
|
|||
color: #7a7a7a;
|
||||
font-weight: 300; }
|
||||
|
||||
/*
|
||||
.navbar-brand img {
|
||||
min-height: 6em;
|
||||
}
|
||||
|
||||
.navbar-menu .navbar-item:not(:last-child) {
|
||||
border-right: 1px $grey solid;
|
||||
}
|
||||
*/
|
||||
/** page **/
|
||||
.page > .cover {
|
||||
float: right;
|
||||
max-width: 45%; }
|
||||
|
@ -7247,26 +7256,23 @@ a.navbar-item.is-active {
|
|||
.page p {
|
||||
padding: 0.4em 0em; }
|
||||
|
||||
section > .toolbar {
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
padding: 1em;
|
||||
margin-bottom: 1.5em; }
|
||||
|
||||
main .cover {
|
||||
margin: 1em 0em;
|
||||
border: 0.2em black solid; }
|
||||
|
||||
main .small-cover {
|
||||
width: 10em; }
|
||||
|
||||
aside .small-cover {
|
||||
width: 4em; }
|
||||
|
||||
aside .media .subtitle {
|
||||
font-size: 1em; }
|
||||
|
||||
aside .media .content {
|
||||
display: none; }
|
||||
.media.item .headline {
|
||||
line-height: 1.2em;
|
||||
max-height: calc(1.2em * 3);
|
||||
overflow: hidden; }
|
||||
.media.item .headline + .headline-overflow {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 2em;
|
||||
margin-top: -2em; }
|
||||
.media.item .headline + .headline-overflow:before {
|
||||
content: '';
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(transparent 1em, whitesmoke); }
|
||||
|
||||
.player {
|
||||
box-shadow: 0em 1.5em 2.5em rgba(0, 0, 0, 0.6); }
|
||||
|
@ -7287,3 +7293,37 @@ aside .media .content {
|
|||
.player .title {
|
||||
margin: 0em; }
|
||||
|
||||
.media .subtitle {
|
||||
margin-bottom: 0.4em; }
|
||||
|
||||
.media .media-content .headline {
|
||||
font-size: 1em;
|
||||
font-weight: 400; }
|
||||
|
||||
body {
|
||||
background-color: whitesmoke; }
|
||||
|
||||
section > .toolbar {
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
padding: 1em;
|
||||
margin-bottom: 1.5em; }
|
||||
|
||||
main .cover {
|
||||
margin: 1em 0em;
|
||||
border: 0.2em black solid; }
|
||||
|
||||
main .small-cover {
|
||||
width: 10em; }
|
||||
|
||||
aside > section {
|
||||
margin-bottom: 2em; }
|
||||
|
||||
aside .cover {
|
||||
margin-bottom: 2em; }
|
||||
|
||||
aside .small-cover {
|
||||
width: 4em; }
|
||||
|
||||
aside .media .subtitle {
|
||||
font-size: 1em; }
|
||||
|
||||
|
|
|
@ -305,7 +305,7 @@ eval("// extracted by mini-css-extract-plugin\n\n//# sourceURL=webpack:///./asse
|
|||
/***/ (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 }\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");
|
||||
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 },\n\n onclick(event) {\n // TODO: row click => check checkbox\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");
|
||||
|
||||
/***/ }),
|
||||
|
||||
|
@ -317,7 +317,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n//\n//\n//\n//\n//\n//\n\n\nc
|
|||
/***/ (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");
|
||||
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 console.log('tooogle', this.paused, '-', this.$refs.audio.src)\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");
|
||||
|
||||
/***/ }),
|
||||
|
||||
|
|
|
@ -7190,6 +7190,28 @@ a.navbar-item.is-active {
|
|||
margin: 0em;
|
||||
padding: 0em; }
|
||||
|
||||
.card .title {
|
||||
padding: 0.2em;
|
||||
font-size: 1.25rem;
|
||||
font-weight: 500; }
|
||||
.card .title a {
|
||||
color: #363636; }
|
||||
|
||||
.card.is-primary {
|
||||
box-shadow: 0em 0em 0.5em #0a0a0a; }
|
||||
|
||||
.card-super-title {
|
||||
position: absolute;
|
||||
z-index: 1000;
|
||||
font-size: 1.2em;
|
||||
font-weight: 700;
|
||||
padding: 0.2em;
|
||||
top: 1em;
|
||||
background-color: white; }
|
||||
.card-super-title .fas {
|
||||
padding: 0.1em;
|
||||
font-size: 0.8em; }
|
||||
|
||||
.filters {
|
||||
margin: 1em 0em;
|
||||
background-color: transparent;
|
||||
|
@ -7202,16 +7224,6 @@ a.navbar-item.is-active {
|
|||
color: #7a7a7a;
|
||||
font-weight: 300; }
|
||||
|
||||
/*
|
||||
.navbar-brand img {
|
||||
min-height: 6em;
|
||||
}
|
||||
|
||||
.navbar-menu .navbar-item:not(:last-child) {
|
||||
border-right: 1px $grey solid;
|
||||
}
|
||||
*/
|
||||
/** page **/
|
||||
.page > .cover {
|
||||
float: right;
|
||||
max-width: 45%; }
|
||||
|
@ -7226,26 +7238,23 @@ a.navbar-item.is-active {
|
|||
.page p {
|
||||
padding: 0.4em 0em; }
|
||||
|
||||
section > .toolbar {
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
padding: 1em;
|
||||
margin-bottom: 1.5em; }
|
||||
|
||||
main .cover {
|
||||
margin: 1em 0em;
|
||||
border: 0.2em black solid; }
|
||||
|
||||
main .small-cover {
|
||||
width: 10em; }
|
||||
|
||||
aside .small-cover {
|
||||
width: 4em; }
|
||||
|
||||
aside .media .subtitle {
|
||||
font-size: 1em; }
|
||||
|
||||
aside .media .content {
|
||||
display: none; }
|
||||
.media.item .headline {
|
||||
line-height: 1.2em;
|
||||
max-height: calc(1.2em * 3);
|
||||
overflow: hidden; }
|
||||
.media.item .headline + .headline-overflow {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 2em;
|
||||
margin-top: -2em; }
|
||||
.media.item .headline + .headline-overflow:before {
|
||||
content: '';
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(transparent 1em, whitesmoke); }
|
||||
|
||||
.player {
|
||||
box-shadow: 0em 1.5em 2.5em rgba(0, 0, 0, 0.6); }
|
||||
|
@ -7266,3 +7275,37 @@ aside .media .content {
|
|||
.player .title {
|
||||
margin: 0em; }
|
||||
|
||||
.media .subtitle {
|
||||
margin-bottom: 0.4em; }
|
||||
|
||||
.media .media-content .headline {
|
||||
font-size: 1em;
|
||||
font-weight: 400; }
|
||||
|
||||
body {
|
||||
background-color: whitesmoke; }
|
||||
|
||||
section > .toolbar {
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
padding: 1em;
|
||||
margin-bottom: 1.5em; }
|
||||
|
||||
main .cover {
|
||||
margin: 1em 0em;
|
||||
border: 0.2em black solid; }
|
||||
|
||||
main .small-cover {
|
||||
width: 10em; }
|
||||
|
||||
aside > section {
|
||||
margin-bottom: 2em; }
|
||||
|
||||
aside .cover {
|
||||
margin-bottom: 2em; }
|
||||
|
||||
aside .small-cover {
|
||||
width: 4em; }
|
||||
|
||||
aside .media .subtitle {
|
||||
font-size: 1em; }
|
||||
|
||||
|
|
|
@ -246,7 +246,7 @@ eval("// extracted by mini-css-extract-plugin\n\n//# sourceURL=webpack:///./asse
|
|||
/***/ (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");
|
||||
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 console.log('tooogle', this.paused, '-', this.$refs.audio.src)\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");
|
||||
|
||||
/***/ }),
|
||||
|
||||
|
|
|
@ -3,8 +3,14 @@
|
|||
|
||||
|
||||
{% block content %}{{ block.super }}
|
||||
<div id="app">
|
||||
|
||||
{# TODO: date subtitle #}
|
||||
<div class="columns">
|
||||
<nav class="navbar" role="menu">
|
||||
{% with "admin:tools-stats" as url_name %}
|
||||
{% include "aircox/widgets/dates_menu.html" %}
|
||||
{% endwith %}
|
||||
</nav>
|
||||
|
||||
<a-statistics class="column">
|
||||
<template v-slot:default="{counts}">
|
||||
|
@ -23,13 +29,12 @@
|
|||
{% for track in tracks %}
|
||||
<tr>
|
||||
{% if forloop.first %}
|
||||
<td rowspan="{{ tracks|length }}">{{ object.start|time:"H:i" }}</td>
|
||||
<td rowspan="{{ tracks|length }}">{{ object.start|time:"H:i" }} {% if object|is_diffusion %} - {{ object.end|time:"H:i" }}{% endif %}</td>
|
||||
<td rowspan="{{ tracks|length }}">{{ object.episode|default:"" }}</td>
|
||||
{% endif %}
|
||||
|
||||
{% if not object|is_diffusion %}
|
||||
{% with track as object %}
|
||||
<td>{% include "aircox/track_item.html" %}</td>
|
||||
<td>{% include "aircox/widgets/track_item.html" %}</td>
|
||||
{% endwith %}
|
||||
{% with track.tags.all|join:', ' as tags %}
|
||||
<td>
|
||||
|
@ -41,10 +46,17 @@
|
|||
{% endif %}
|
||||
</td>
|
||||
{% endwith %}
|
||||
{% else %}
|
||||
</tr>
|
||||
{% empty %}
|
||||
{% if object|is_diffusion %}
|
||||
<tr>
|
||||
<td>{{ object.start|time:"H:i" }} - {{ object.end|time:"H:i" }}</td>
|
||||
<td>{{ object.episode|default:"" }}</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<tr>
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
@ -65,14 +77,6 @@
|
|||
</template>
|
||||
</a-statistics>
|
||||
|
||||
|
||||
<nav class="column menu is-one-fifth-desktop" role="menu">
|
||||
{% with "admin:tools-stats" as url_name %}
|
||||
{% include "aircox/widgets/dates_menu.html" %}
|
||||
{% endwith %}
|
||||
</nav>
|
||||
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
|
|
@ -29,11 +29,10 @@
|
|||
data-admin-utc-offset="{% now "Z" %}">
|
||||
|
||||
<!-- Container -->
|
||||
<div id="app">
|
||||
|
||||
<div>
|
||||
{% if not is_popup %}
|
||||
<!-- Header -->
|
||||
<nav class="navbar is-dark">
|
||||
<nav class="navbar is-dark has-shadow">
|
||||
<div class="navbar-brand">
|
||||
{% block branding %}{% endblock %}
|
||||
</div>
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
{% block coltype %}flex{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div id="content-main">
|
||||
<div id="content-main">
|
||||
{% block object-tools %}
|
||||
<ul class="object-tools">
|
||||
{% block object-tools-items %}
|
||||
|
@ -74,16 +74,16 @@
|
|||
{% block date_hierarchy %}{% if cl.date_hierarchy %}{% date_hierarchy cl %}{% endif %}{% endblock %}
|
||||
|
||||
{% block filters %}
|
||||
{% if cl.has_filters %}
|
||||
<div id="changelist-filter">
|
||||
<h2>{% trans 'Filter' %}</h2>
|
||||
{% for spec in cl.filter_specs %}{% admin_list_filter cl spec %}{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if cl.has_filters %}
|
||||
<div id="changelist-filter">
|
||||
<h2>{% trans 'Filter' %}</h2>
|
||||
{% for spec in cl.filter_specs %}{% admin_list_filter cl spec %}{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
{% block sidebar %}
|
||||
{{ block.super }}
|
||||
|
||||
{% if sidebar_items %}
|
||||
{% if sidebar_object_list %}
|
||||
<section>
|
||||
<h4 class="title is-4">{% trans "Latest news" %}</h4>
|
||||
|
||||
{% for object in sidebar_items %}
|
||||
{% include "aircox/page_item.html" %}
|
||||
{% for object in sidebar_object_list %}
|
||||
{% include "aircox/widgets/page_item.html" %}
|
||||
{% endfor %}
|
||||
|
||||
<br>
|
||||
|
|
|
@ -1,10 +1,29 @@
|
|||
{% load static i18n thumbnail aircox %}
|
||||
{% comment %}
|
||||
Context:
|
||||
- cover: image cover
|
||||
- site: current website
|
||||
- has_filters: display filter bar (using block "filters")
|
||||
- sidebar_object_list: item to display in sidebar
|
||||
- sidebar_url_name: url name sidebar item complete list
|
||||
- sidebar_url_parent: parent page for sidebar items complete list
|
||||
|
||||
Blocks:
|
||||
- assets
|
||||
- head_title
|
||||
- head_extra
|
||||
- top_nav
|
||||
- header:
|
||||
- title
|
||||
- subtitle
|
||||
- header_meta
|
||||
- main:
|
||||
- filters
|
||||
- cover
|
||||
- sidebar:
|
||||
- sidebar_title
|
||||
{% endcomment %}
|
||||
{% load static i18n thumbnail aircox %}
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
|
@ -72,14 +91,14 @@ Context:
|
|||
{% endblock %}
|
||||
</header>
|
||||
|
||||
{% if has_filters %}
|
||||
<nav class="navbar filters"
|
||||
aria-label="{% trans "list filters" %}">
|
||||
{% block filters %}{% endblock %}
|
||||
</nav>
|
||||
{% endif %}
|
||||
|
||||
{% block main %}{% endblock main %}
|
||||
{% block main %}
|
||||
{% if has_filters %}
|
||||
<nav class="navbar filters"
|
||||
aria-label="{% trans "list filters" %}">
|
||||
{% block filters %}{% endblock %}
|
||||
</nav>
|
||||
{% endif %}
|
||||
{% endblock main %}
|
||||
</main>
|
||||
|
||||
{% if has_sidebar %}
|
||||
|
@ -92,28 +111,18 @@ Context:
|
|||
{% endblock %}
|
||||
|
||||
{% block sidebar %}
|
||||
{% if sidebar_items %}
|
||||
{% 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 %}{% trans "Recently" %}{% endblock %}
|
||||
</h4>
|
||||
|
||||
{% for object in sidebar_items %}
|
||||
{% include "aircox/episode_item.html" %}
|
||||
{% endfor %}
|
||||
|
||||
<br>
|
||||
<nav class="pagination is-centered">
|
||||
<ul class="pagination-list">
|
||||
<li>
|
||||
<a {% if parent %}href="{% url "page-list" parent_slug=parent.slug %}"{% else %}href="{% url "page-list" %}"{% endif %}
|
||||
class="pagination-link"
|
||||
aria-label="{% trans "Show all program's diffusions" %}">
|
||||
{% trans "Show more" %}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
{% include "aircox/widgets/page_list.html" %}
|
||||
{% endwith %}
|
||||
{% endwith %}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block main %}{{ block.super }}
|
||||
{% with True as hide_schedule %}
|
||||
{% with hide_schedule=True %}
|
||||
<section role="list">
|
||||
<div id="timetable-{{ date|date:"Y-m-d" }}">
|
||||
{% for diffusion in object_list %}
|
||||
|
@ -24,12 +24,12 @@
|
|||
<div class="columns {% if diffusion.start.date != date and diffusion.start.end <= date %}is-opacity-light{% endif %}">
|
||||
<div class="column is-one-fifth has-text-right">
|
||||
<time datetime="{{ diffusion.start|date:"c" }}">
|
||||
{{ diffusion.start|date:"d H:i" }} - {{ diffusion.end|date:"d H:i" }}
|
||||
{{ 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" %}
|
||||
{% include "aircox/widgets/episode_item.html" %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
<section class="column">
|
||||
<h4 class="title is-4">{% trans "Podcasts" %}</h4>
|
||||
{% for object in podcasts %}
|
||||
{% include "aircox/podcast_item.html" %}
|
||||
{% include "aircox/widgets/podcast_item.html" %}
|
||||
{% endfor %}
|
||||
</section>
|
||||
{% endif %}
|
||||
|
|
83
aircox/templates/aircox/home.html
Normal file
83
aircox/templates/aircox/home.html
Normal file
|
@ -0,0 +1,83 @@
|
|||
{% extends "aircox/page_list.html" %}
|
||||
{% comment %}
|
||||
Context:
|
||||
-
|
||||
-
|
||||
|
||||
TODO:
|
||||
- sidebar:
|
||||
- logs
|
||||
- diffusions
|
||||
- main:
|
||||
- focused
|
||||
- nav to 'publications' view
|
||||
-
|
||||
|
||||
{% endcomment %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block head_title %}{% block title %}{{ station.name }}{% endblock %}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<div class="columns">
|
||||
{% with render_card=True %}
|
||||
{% for object in top_diffs %}
|
||||
{% with is_primary=object.is_now %}
|
||||
<div class="column is-relative">
|
||||
<h4 class="card-super-title">
|
||||
{% if is_primary %}
|
||||
<span class="fas fa-play"></span>
|
||||
{% trans "Currently" %}
|
||||
{% else %}{{ object.start|date:"H:i" }}{% endif %}
|
||||
</h4>
|
||||
{% include object.item_template_name %}
|
||||
</div>
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<h4 class="title is-4">{% trans "Last publications" %}</h4>
|
||||
{{ block.super }}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block pagination %}
|
||||
<ul class="pagination-list">
|
||||
<li>
|
||||
<a href="{% url "page-list" %}" class="pagination-link"
|
||||
aria-label="{% trans "Show all publication" %}">
|
||||
{% trans "More publications..." %}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block sidebar %}
|
||||
<section>
|
||||
<h4 class="title is-4">{% trans "Previously on air" %}</h4>
|
||||
{% with logs as object_list %}
|
||||
{% include "aircox/widgets/log_list.html" %}
|
||||
{% endwith %}
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h4 class="title is-4">{% trans "Today" %}</h4>
|
||||
{% with hide_schedule=True %}
|
||||
{% with has_headline=False %}
|
||||
<table class="table is-fullwidth has-background-transparent">
|
||||
{% for object in sidebar_object_list %}
|
||||
<tr>
|
||||
<td>{{ object.start|date:"H:i" }}</td>
|
||||
<td>{% include "aircox/widgets/diffusion_item.html" %}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endwith %}
|
||||
{% endwith %}
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
||||
|
|
@ -16,29 +16,10 @@
|
|||
{% endwith %}
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
{% block main %}{{ block.super }}
|
||||
<section>
|
||||
{# <h4 class="subtitle size-4">{{ date }}</h4> #}
|
||||
{% with True as hide_schedule %}
|
||||
<table class="table is-striped is-hoverable is-fullwidth">
|
||||
{% for object in object_list %}
|
||||
<tr>
|
||||
<td>
|
||||
{% if object|is_diffusion %}
|
||||
<time datetime="{{ object.start }}" title="{{ object.start }}">
|
||||
{{ object.start|date:"H:i" }} - {{ object.end|date:"H:i" }}
|
||||
</time>
|
||||
{% else %}
|
||||
<time datetime="{{ object.date }}" title="{{ object.date }}">
|
||||
{{ object.date|date:"H:i" }}
|
||||
</time>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{% include "aircox/log_item.html" %}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endwith %}
|
||||
{% include "aircox/widgets/log_list.html" %}
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
||||
|
|
|
@ -56,21 +56,23 @@
|
|||
{% endblock %}
|
||||
|
||||
|
||||
{% block main %}
|
||||
{% block main %}{{ block.super }}
|
||||
<section role="list">
|
||||
{% with has_headline=True %}
|
||||
{% for object in object_list %}
|
||||
{% block list_object %}
|
||||
{% include object.item_template_name|default:item_template_name %}
|
||||
{% endblock %}
|
||||
{% endfor %}
|
||||
{% endwith %}
|
||||
</section>
|
||||
|
||||
{% if is_paginated %}
|
||||
<hr>
|
||||
|
||||
{% update_query request.GET.copy page=None as GET %}
|
||||
{% with GET.urlencode as GET %}
|
||||
<nav class="pagination is-centered" role="pagination" aria-label="{% trans "pagination" %}">
|
||||
{% block pagination %}
|
||||
{% if page_obj.has_previous %}
|
||||
<a href="?{{ GET }}&page={{ page_obj.previous_page_number }}" class="pagination-previous">
|
||||
{% else %}
|
||||
|
@ -93,6 +95,7 @@
|
|||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endblock %}
|
||||
</nav>
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
|
|
|
@ -3,13 +3,7 @@
|
|||
|
||||
{% block sidebar_title %}
|
||||
{% with program.title as program %}
|
||||
{% blocktrans %} Recently on {{ program }}{% endblocktrans %}
|
||||
{% endwith %}
|
||||
{% endblock %}
|
||||
|
||||
{% block sidebar %}
|
||||
{% with program as parent %}
|
||||
{{ block.super }}
|
||||
{% blocktrans %}Recently on {{ program }}{% endblocktrans %}
|
||||
{% endwith %}
|
||||
{% endblock %}
|
||||
|
||||
|
|
|
@ -10,15 +10,14 @@
|
|||
{% block content %}{{ block.super }}
|
||||
|
||||
<br>
|
||||
|
||||
{% with show_headline=False %}
|
||||
{% with has_headline=False %}
|
||||
<div class="columns is-desktop">
|
||||
{% if articles %}
|
||||
<section class="column">
|
||||
<h4 class="title is-4">{% trans "Articles" %}</h4>
|
||||
|
||||
{% for object in articles %}
|
||||
{% include "aircox/page_item.html" %}
|
||||
{% include "aircox/widgets/page_item.html" %}
|
||||
{% endfor %}
|
||||
|
||||
<br>
|
||||
|
|
|
@ -5,7 +5,7 @@ Context:
|
|||
{% endcomment %}
|
||||
{% with object as diffusion %}
|
||||
{% with object.episode as object %}
|
||||
{% include "aircox/episode_item.html" %}
|
||||
{% include "aircox/widgets/episode_item.html" %}
|
||||
{% endwith %}
|
||||
{% endwith %}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
{% extends "aircox/page_item.html" %}
|
||||
{% extends "aircox/widgets/page_item.html" %}
|
||||
{% load i18n easy_thumbnails_tags aircox %}
|
||||
|
||||
{% comment %}
|
|
@ -11,11 +11,11 @@ for design review.
|
|||
|
||||
{% if object|is_diffusion %}
|
||||
{% with object as diffusion %}
|
||||
{% include "aircox/diffusion_item.html" %}
|
||||
{% include "aircox/widgets/diffusion_item.html" %}
|
||||
{% endwith %}
|
||||
{% else %}
|
||||
{% with object.track as object %}
|
||||
{% include "aircox/track_item.html" %}
|
||||
{% include "aircox/widgets/track_item.html" %}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
|
29
aircox/templates/aircox/widgets/log_list.html
Normal file
29
aircox/templates/aircox/widgets/log_list.html
Normal file
|
@ -0,0 +1,29 @@
|
|||
{% comment %}
|
||||
Render list of logs (as widget).
|
||||
|
||||
Context:
|
||||
- object_list: list of logs to display
|
||||
{% 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>
|
||||
<td>
|
||||
{% if object|is_diffusion %}
|
||||
<time datetime="{{ object.start }}" title="{{ object.start }}">
|
||||
{{ object.start|date:"H:i" }} - {{ object.end|date:"H:i" }}
|
||||
</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 %}
|
||||
|
|
@ -1,15 +1,36 @@
|
|||
{% load i18n easy_thumbnails_tags aircox %}
|
||||
{% comment %}
|
||||
Context variables:
|
||||
- object: the actual diffusion
|
||||
- show_headline: if True, display headline
|
||||
- object: the object to render
|
||||
- render_card: render as card
|
||||
- is-primary: render as primary
|
||||
- has_headline (=False): if True, display headline
|
||||
- has_cover (=True): hide page cover
|
||||
{% endcomment %}
|
||||
|
||||
<article class="media">
|
||||
{% if render_card %}
|
||||
<article class="card {% if is_primary %}is-primary{% endif %}">
|
||||
<header class="card-image">
|
||||
<figure class="image is-4by3">
|
||||
<img src="{% thumbnail object.cover 480x480 %}">
|
||||
</figure>
|
||||
</header>
|
||||
<div class="card-header">
|
||||
<h4 class="title">
|
||||
<a href="{{ object.get_absolute_url }}">{{ object.title }}</a>
|
||||
</h4>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
|
||||
{% else %}
|
||||
<article class="media item {% if is_primary %}is-primary{% endif %}">
|
||||
{% if has_cover|default_if_none:True %}
|
||||
<div class="media-left">
|
||||
<img src="{% thumbnail object.cover 128x128 crop=scale %}"
|
||||
class="small-cover">
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="media-content">
|
||||
<h5 class="title is-5 has-text-weight-normal">
|
||||
{% block title %}
|
||||
|
@ -26,8 +47,8 @@ Context variables:
|
|||
{% endblock %}
|
||||
</div>
|
||||
|
||||
{% if show_headline %}
|
||||
<div class="">
|
||||
{% if has_headline|default_if_none:True %}
|
||||
<div class="headline">
|
||||
{% block headline %}
|
||||
{{ object.headline|safe }}
|
||||
{% endblock %}
|
||||
|
@ -35,4 +56,5 @@ Context variables:
|
|||
{% endif %}
|
||||
</div>
|
||||
</article>
|
||||
{% endif %}
|
||||
|
28
aircox/templates/aircox/widgets/page_list.html
Normal file
28
aircox/templates/aircox/widgets/page_list.html
Normal file
|
@ -0,0 +1,28 @@
|
|||
{% comment %}
|
||||
Display list of items as small list
|
||||
|
||||
Context:
|
||||
- object_list: object list
|
||||
- list_url: url to complete list page
|
||||
{% endcomment %}
|
||||
{% load i18n %}
|
||||
|
||||
{% for object in object_list %}
|
||||
{% include object.item_template_name %}
|
||||
{% endfor %}
|
||||
|
||||
{% if list_url %}
|
||||
<br>
|
||||
<nav class="pagination is-centered">
|
||||
<ul class="pagination-list">
|
||||
<li>
|
||||
<a href="{{ list_url }}" class="pagination-link"
|
||||
aria-label="{% trans "Show all publications" %}">
|
||||
{% trans "Show more" %}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
{% endif %}
|
||||
|
||||
|
|
@ -24,8 +24,7 @@ api = [
|
|||
|
||||
|
||||
urls = [
|
||||
path(_(''),
|
||||
views.DiffusionListView.as_view(), name='home'),
|
||||
path('', views.HomeView.as_view(), name='home'),
|
||||
path('api/', include(api)),
|
||||
|
||||
# path('', views.PageDetailView.as_view(model=models.Article),
|
||||
|
@ -51,9 +50,9 @@ urls = [
|
|||
# path('<page_path:path>', views.route_page, name='page'),
|
||||
|
||||
path(_('publications/'),
|
||||
views.ProgramPageListView.as_view(), name='page-list'),
|
||||
views.PageListView.as_view(model=models.Page), name='page-list'),
|
||||
|
||||
path(_('programs/'), views.PageListView.as_view(model=models.Program),
|
||||
path(_('programs/'), views.ProgramListView.as_view(model=models.Program),
|
||||
name='program-list'),
|
||||
path(_('programs/<slug:slug>/'),
|
||||
views.ProgramDetailView.as_view(), name='program-detail'),
|
||||
|
@ -62,7 +61,7 @@ urls = [
|
|||
path(_('programs/<slug:parent_slug>/articles/'),
|
||||
views.ArticleListView.as_view(), name='article-list'),
|
||||
path(_('programs/<slug:parent_slug>/publications/'),
|
||||
views.ProgramPageListView.as_view(), name='page-list'),
|
||||
views.ProgramPageListView.as_view(), name='program-page-list'),
|
||||
|
||||
|
||||
]
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
from . import api, admin
|
||||
|
||||
from .article import ArticleDetailView, ArticleListView
|
||||
from .base import BaseView
|
||||
from .home import HomeView
|
||||
|
||||
from .article import ArticleDetailView, ArticleListView
|
||||
from .episode import EpisodeDetailView, EpisodeListView, DiffusionListView
|
||||
from .log import LogListView
|
||||
from .page import PageDetailView, PageListView
|
||||
from .program import ProgramDetailView, ProgramPageListView
|
||||
from .program import ProgramDetailView, ProgramListView, \
|
||||
ProgramPageDetailView, ProgramPageListView
|
||||
|
||||
|
|
|
@ -44,8 +44,7 @@ class AdminSite(admin.AdminSite):
|
|||
|
||||
def get_urls(self):
|
||||
from django.urls import path, include
|
||||
urls = super().get_urls()
|
||||
urls += [
|
||||
urls = super().get_urls() + [
|
||||
path('tools/statistics/',
|
||||
self.admin_view(StatisticsView.as_view()),
|
||||
name='tools-stats'),
|
||||
|
|
|
@ -4,7 +4,6 @@ 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 LogListMixin
|
||||
|
|
|
@ -25,7 +25,7 @@ class ArticleDetailView(PageDetailView):
|
|||
class ArticleListView(ParentMixin, PageListView):
|
||||
model = Article
|
||||
template_name = 'aircox/article_list.html'
|
||||
show_headline = True
|
||||
has_headline = True
|
||||
is_static = False
|
||||
parent_model = Program
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
from django.http import Http404
|
||||
from django.views.generic import DetailView, ListView
|
||||
from django.views.generic.base import TemplateResponseMixin, ContextMixin
|
||||
from django.urls import reverse
|
||||
|
||||
from ..models import Page
|
||||
from ..utils import Redirect
|
||||
|
@ -35,21 +36,25 @@ class BaseView(TemplateResponseMixin, ContextMixin):
|
|||
return Page.objects.select_subclasses().published() \
|
||||
.order_by('-pub_date')
|
||||
|
||||
def get_context_data(self, sidebar_items=None, **kwargs):
|
||||
def get_sidebar_url(self):
|
||||
return reverse('page-list')
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
kwargs.setdefault('station', self.station)
|
||||
kwargs.setdefault('cover', self.cover)
|
||||
kwargs.setdefault('has_filters', self.has_filters)
|
||||
|
||||
has_sidebar = kwargs.setdefault('has_sidebar', self.has_sidebar)
|
||||
if has_sidebar and sidebar_items is None:
|
||||
sidebar_items = self.get_sidebar_queryset()
|
||||
sidebar_items = None if sidebar_items is None else \
|
||||
sidebar_items[:self.list_count]
|
||||
if has_sidebar and 'sidebar_object_list' not in kwargs:
|
||||
sidebar_object_list = self.get_sidebar_queryset()
|
||||
if sidebar_object_list is not None:
|
||||
kwargs['sidebar_object_list'] = sidebar_object_list[:self.list_count]
|
||||
kwargs['sidebar_list_url'] = self.get_sidebar_url()
|
||||
|
||||
if not 'audio_streams' in kwargs:
|
||||
streams = self.station.audio_streams
|
||||
streams = streams and streams.split('\n')
|
||||
kwargs['audio_streams'] = streams
|
||||
|
||||
return super().get_context_data(sidebar_items=sidebar_items, **kwargs)
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
|
|
@ -21,9 +21,6 @@ class EpisodeDetailView(ProgramPageDetailView):
|
|||
return Sound.objects.diffusion(diffusion).podcasts()
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
self.program = kwargs.setdefault('program', self.object.program)
|
||||
|
||||
kwargs.setdefault('parent', self.program)
|
||||
if not 'tracks' in kwargs:
|
||||
kwargs['tracks'] = self.object.track_set.order_by('position')
|
||||
if not 'podcasts' in kwargs:
|
||||
|
@ -33,8 +30,8 @@ class EpisodeDetailView(ProgramPageDetailView):
|
|||
|
||||
class EpisodeListView(ParentMixin, PageListView):
|
||||
model = Episode
|
||||
item_template_name = 'aircox/episode_item.html'
|
||||
show_headline = True
|
||||
item_template_name = 'aircox/widgets/episode_item.html'
|
||||
has_headline = True
|
||||
parent_model = Program
|
||||
|
||||
|
||||
|
|
44
aircox/views/home.py
Normal file
44
aircox/views/home.py
Normal file
|
@ -0,0 +1,44 @@
|
|||
import datetime
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils import timezone as tz
|
||||
|
||||
from ..models import Diffusion, Log, Page
|
||||
from .page import PageListView
|
||||
|
||||
class HomeView(PageListView):
|
||||
template_name = 'aircox/home.html'
|
||||
model = Page
|
||||
queryset = Page.objects.select_subclasses()
|
||||
paginate_by = 10
|
||||
list_count = 40
|
||||
logs_count = 5
|
||||
has_filters = False
|
||||
|
||||
def get_logs(self):
|
||||
today = datetime.date.today()
|
||||
logs = Log.objects.on_air().today(today).filter(track__isnull=False)
|
||||
diffs = Diffusion.objects.on_air().today(today)
|
||||
return Log.merge_diffusions(logs, diffs, self.logs_count)
|
||||
|
||||
def get_sidebar_queryset(self):
|
||||
today = datetime.date.today()
|
||||
return Diffusion.objects.on_air().today(today)
|
||||
|
||||
def get_top_diffs(self):
|
||||
now = tz.now()
|
||||
current_diff = Diffusion.objects.on_air().now(now).first()
|
||||
next_diffs = Diffusion.objects.on_air().after(now)
|
||||
if current_diff:
|
||||
diffs = [current_diff] + list(next_diffs.exclude(pk=current_diff.pk)[:2])
|
||||
else:
|
||||
diffs = next_diffs[:3]
|
||||
return diffs
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
kwargs['logs'] = self.get_logs()
|
||||
kwargs['top_diffs'] = self.get_top_diffs()
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
||||
|
|
@ -2,6 +2,7 @@ from collections import deque
|
|||
import datetime
|
||||
|
||||
from django.views.generic import ListView
|
||||
from django.utils import timezone as tz
|
||||
|
||||
from ..models import Diffusion, Log
|
||||
from .base import BaseView
|
||||
|
@ -23,12 +24,14 @@ class LogListMixin(GetDateMixin):
|
|||
def get_queryset(self):
|
||||
# only get logs for tracks: log for diffusion will be retrieved
|
||||
# by the diffusions' queryset.
|
||||
qs = super().get_queryset().on_air().filter(track__isnull=False)
|
||||
qs = super().get_queryset().on_air().filter(track__isnull=False) \
|
||||
.filter(date__lte=tz.now())
|
||||
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):
|
||||
qs = Diffusion.objects.station(self.station).on_air()
|
||||
qs = Diffusion.objects.station(self.station).on_air() \
|
||||
.filter(start__lte=tz.now())
|
||||
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
|
||||
|
||||
|
|
|
@ -63,9 +63,9 @@ class ParentMixin:
|
|||
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)
|
||||
self.parent = kwargs.setdefault('parent', self.parent)
|
||||
if self.parent is not None:
|
||||
kwargs.setdefault('cover', self.parent.cover)
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ from django.views.generic import DetailView, ListView
|
|||
from honeypot.decorators import check_honeypot
|
||||
|
||||
from ..forms import CommentForm
|
||||
from ..models import Category, Comment
|
||||
from ..models import Category, Comment, Page
|
||||
from ..utils import Redirect
|
||||
from .base import BaseView
|
||||
|
||||
|
@ -17,12 +17,12 @@ __all__ = ['PageDetailView', 'PageListView']
|
|||
# TODO: pagination: in template, only a limited number of pages displayed
|
||||
class PageListView(BaseView, ListView):
|
||||
template_name = 'aircox/page_list.html'
|
||||
item_template_name = 'aircox/page_item.html'
|
||||
item_template_name = 'aircox/widgets/page_item.html'
|
||||
has_sidebar = True
|
||||
has_filters = True
|
||||
|
||||
paginate_by = 20
|
||||
show_headline = True
|
||||
has_headline = True
|
||||
categories = None
|
||||
|
||||
def get(self, *args, **kwargs):
|
||||
|
@ -30,7 +30,7 @@ class PageListView(BaseView, ListView):
|
|||
return super().get(*args, **kwargs)
|
||||
|
||||
def get_queryset(self):
|
||||
qs = super().get_queryset().published() \
|
||||
qs = super().get_queryset().select_subclasses().published() \
|
||||
.select_related('cover', 'category')
|
||||
|
||||
# category can be filtered based on request.GET['categories']
|
||||
|
@ -50,7 +50,7 @@ class PageListView(BaseView, ListView):
|
|||
kwargs.setdefault('item_template_name', self.item_template_name)
|
||||
kwargs.setdefault('filter_categories', self.get_categories_queryset())
|
||||
kwargs.setdefault('categories', self.categories)
|
||||
kwargs.setdefault('show_headline', self.show_headline)
|
||||
kwargs.setdefault('has_headline', self.has_headline)
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from django.db.models import Q
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.urls import reverse
|
||||
|
||||
from ..models import Episode, Program, Page
|
||||
from .mixins import ParentMixin
|
||||
|
@ -10,30 +11,54 @@ from .page import PageDetailView, PageListView
|
|||
__all__ = ['ProgramPageDetailView', 'ProgramDetailView', 'ProgramPageListView']
|
||||
|
||||
|
||||
class ProgramPageDetailView(PageDetailView):
|
||||
class BaseProgramMixin:
|
||||
def get_program(self):
|
||||
return self.object
|
||||
|
||||
def get_sidebar_url(self):
|
||||
return reverse('program-page-list',
|
||||
kwargs={"parent_slug": self.program.slug})
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
self.program = self.get_program()
|
||||
kwargs['program'] = self.program
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
||||
class ProgramDetailView(BaseProgramMixin, PageDetailView):
|
||||
model = Program
|
||||
|
||||
def get_sidebar_queryset(self):
|
||||
return super().get_sidebar_queryset().filter(parent=self.program)
|
||||
|
||||
|
||||
class ProgramListView(PageListView):
|
||||
model = Program
|
||||
|
||||
|
||||
class ProgramPageDetailView(BaseProgramMixin, ParentMixin, PageDetailView):
|
||||
"""
|
||||
Base view class for a page that is displayed as a program's child page.
|
||||
"""
|
||||
program = None
|
||||
has_sidebar = True
|
||||
list_count = 5
|
||||
parent_model = Program
|
||||
|
||||
def get_program(self):
|
||||
self.parent = self.object.program
|
||||
return self.object.program
|
||||
|
||||
def get_sidebar_queryset(self):
|
||||
return super().get_sidebar_queryset().filter(parent=self.object)
|
||||
return super().get_sidebar_queryset().filter(parent=self.program)
|
||||
|
||||
|
||||
class ProgramPageListView(ParentMixin, PageListView):
|
||||
class ProgramPageListView(BaseProgramMixin, ParentMixin, PageListView):
|
||||
model = Page
|
||||
parent_model = Program
|
||||
queryset = Page.objects.select_subclasses()
|
||||
|
||||
|
||||
class ProgramDetailView(ProgramPageDetailView):
|
||||
model = Program
|
||||
def get_program(self):
|
||||
return self.parent
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
self.program = kwargs.setdefault('program', self.object)
|
||||
kwargs.setdefault('sidebar_url_parent', None)
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,10 +1,4 @@
|
|||
|
||||
// @import './bulmacolors';
|
||||
|
||||
.navbar {
|
||||
box-shadow: 0em 0em 0.6em rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.navbar .navbar-brand {
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,10 @@ export default {
|
|||
for(var tag of item.value.split(splitReg))
|
||||
counts[tag.trim()] = (counts[tag.trim()] || 0) + 1;
|
||||
this.counts = counts;
|
||||
},
|
||||
|
||||
onclick(event) {
|
||||
// TODO: row click => check checkbox
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -83,6 +83,7 @@ export default {
|
|||
},
|
||||
|
||||
toggle() {
|
||||
console.log('tooogle', this.paused, '-', this.$refs.audio.src)
|
||||
if(this.paused)
|
||||
this.play()
|
||||
else
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
$body-background-color: $light;
|
||||
|
||||
@import "~bulma/bulma";
|
||||
@import "~bulma";
|
||||
|
||||
//-- helpers/modifiers
|
||||
.is-fullwidth { width: 100%; }
|
||||
|
@ -58,6 +58,38 @@ a.navbar-item.is-active {
|
|||
}
|
||||
}
|
||||
|
||||
//-- cards
|
||||
.card {
|
||||
.title {
|
||||
a {
|
||||
color: $dark;
|
||||
}
|
||||
|
||||
padding: 0.2em;
|
||||
font-size: $size-5;
|
||||
font-weight: $weight-medium;
|
||||
}
|
||||
|
||||
&.is-primary {
|
||||
box-shadow: 0em 0em 0.5em $black
|
||||
}
|
||||
}
|
||||
|
||||
.card-super-title {
|
||||
position: absolute;
|
||||
z-index: 1000;
|
||||
font-size: 1.2em;
|
||||
font-weight: $weight-bold;
|
||||
padding: 0.2em;
|
||||
top: 1em;
|
||||
background-color: $white;
|
||||
|
||||
.fas {
|
||||
padding: 0.1em;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-- filters
|
||||
.filters {
|
||||
|
@ -77,18 +109,7 @@ a.navbar-item.is-active {
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
.navbar-brand img {
|
||||
min-height: 6em;
|
||||
}
|
||||
|
||||
.navbar-menu .navbar-item:not(:last-child) {
|
||||
border-right: 1px $grey solid;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/** page **/
|
||||
//-- page
|
||||
.page {
|
||||
& > .cover {
|
||||
float: right;
|
||||
|
@ -109,39 +130,33 @@ a.navbar-item.is-active {
|
|||
}
|
||||
}
|
||||
|
||||
section > .toolbar {
|
||||
background-color: rgba(0,0,0,0.05);
|
||||
padding: 1em;
|
||||
margin-bottom: 1.5em;
|
||||
}
|
||||
|
||||
.media.item .headline {
|
||||
line-height: 1.2em;
|
||||
max-height: calc(1.2em * 3);
|
||||
overflow: hidden;
|
||||
|
||||
main {
|
||||
.cover {
|
||||
margin: 1em 0em;
|
||||
border: 0.2em black solid;
|
||||
& + .headline-overflow {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 2em;
|
||||
margin-top: -2em;
|
||||
}
|
||||
|
||||
.small-cover {
|
||||
width: 10em;
|
||||
}
|
||||
}
|
||||
|
||||
aside {
|
||||
.small-cover {
|
||||
width: 4em;
|
||||
}
|
||||
|
||||
.media .subtitle {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.media .content {
|
||||
display: none;
|
||||
& + .headline-overflow:before {
|
||||
content:'';
|
||||
width:100%;
|
||||
height:100%;
|
||||
position:absolute;
|
||||
left:0;
|
||||
bottom:0;
|
||||
background:linear-gradient(transparent 1em, $body-background-color);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-- player
|
||||
.player {
|
||||
box-shadow: 0em 1.5em 2.5em rgba(0, 0, 0, 0.6);
|
||||
|
||||
|
@ -175,4 +190,57 @@ aside {
|
|||
|
||||
}
|
||||
|
||||
//-- media
|
||||
.media {
|
||||
.subtitle {
|
||||
margin-bottom: 0.4em;
|
||||
}
|
||||
.media-content .headline {
|
||||
font-size: 1em;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
|
||||
//-- general
|
||||
body {
|
||||
background-color: $body-background-color;
|
||||
}
|
||||
|
||||
section > .toolbar {
|
||||
background-color: rgba(0,0,0,0.05);
|
||||
padding: 1em;
|
||||
margin-bottom: 1.5em;
|
||||
}
|
||||
|
||||
|
||||
main {
|
||||
.cover {
|
||||
margin: 1em 0em;
|
||||
border: 0.2em black solid;
|
||||
}
|
||||
|
||||
.small-cover {
|
||||
width: 10em;
|
||||
}
|
||||
}
|
||||
|
||||
aside {
|
||||
& > section {
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
.cover {
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
.small-cover {
|
||||
width: 4em;
|
||||
}
|
||||
|
||||
.media .subtitle {
|
||||
font-size: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -22,9 +22,8 @@ import aircox.urls
|
|||
|
||||
|
||||
try:
|
||||
urlpatterns = [
|
||||
urlpatterns = aircox.urls.urls + [
|
||||
path('admin/', admin.site.urls),
|
||||
path('aircox/', include(aircox.urls.urls)),
|
||||
]
|
||||
|
||||
if settings.DEBUG:
|
||||
|
|
Loading…
Reference in New Issue
Block a user