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