forked from rc/aircox
work on home page, fix views & templates issues
This commit is contained in:
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:
|
||||||
|
Reference in New Issue
Block a user