diff --git a/aircox/models/__pycache__/__init__.cpython-37.pyc b/aircox/models/__pycache__/__init__.cpython-37.pyc
index cfebf45..4631e36 100644
Binary files a/aircox/models/__pycache__/__init__.cpython-37.pyc and b/aircox/models/__pycache__/__init__.cpython-37.pyc differ
diff --git a/aircox/models/__pycache__/episode.cpython-37.pyc b/aircox/models/__pycache__/episode.cpython-37.pyc
index 6059e25..e24c66e 100644
Binary files a/aircox/models/__pycache__/episode.cpython-37.pyc and b/aircox/models/__pycache__/episode.cpython-37.pyc differ
diff --git a/aircox/models/__pycache__/log.cpython-37.pyc b/aircox/models/__pycache__/log.cpython-37.pyc
index 0271250..1d2a826 100644
Binary files a/aircox/models/__pycache__/log.cpython-37.pyc and b/aircox/models/__pycache__/log.cpython-37.pyc differ
diff --git a/aircox/models/__pycache__/page.cpython-37.pyc b/aircox/models/__pycache__/page.cpython-37.pyc
index 1e1b877..e4ceab9 100644
Binary files a/aircox/models/__pycache__/page.cpython-37.pyc and b/aircox/models/__pycache__/page.cpython-37.pyc differ
diff --git a/aircox/models/__pycache__/program.cpython-37.pyc b/aircox/models/__pycache__/program.cpython-37.pyc
index 07c00dd..ae0e9b6 100644
Binary files a/aircox/models/__pycache__/program.cpython-37.pyc and b/aircox/models/__pycache__/program.cpython-37.pyc differ
diff --git a/aircox/models/__pycache__/sound.cpython-37.pyc b/aircox/models/__pycache__/sound.cpython-37.pyc
index db47a40..bb3264a 100644
Binary files a/aircox/models/__pycache__/sound.cpython-37.pyc and b/aircox/models/__pycache__/sound.cpython-37.pyc differ
diff --git a/aircox/models/__pycache__/station.cpython-37.pyc b/aircox/models/__pycache__/station.cpython-37.pyc
index fbb7e58..3b8c0b8 100644
Binary files a/aircox/models/__pycache__/station.cpython-37.pyc and b/aircox/models/__pycache__/station.cpython-37.pyc differ
diff --git a/aircox/models/episode.py b/aircox/models/episode.py
index 0412763..dd3c6a4 100644
--- a/aircox/models/episode.py
+++ b/aircox/models/episode.py
@@ -19,7 +19,7 @@ __all__ = ['Episode', 'Diffusion', 'DiffusionQuerySet']
class Episode(Page):
objects = ProgramChildQuerySet.as_manager()
detail_url_name = 'episode-detail'
- item_template_name = 'aircox/episode_item.html'
+ item_template_name = 'aircox/widgets/episode_item.html'
@property
def program(self):
@@ -75,7 +75,9 @@ class DiffusionQuerySet(BaseRerunQuerySet):
def today(self, today=None, order=True):
""" Diffusions occuring today. """
today = today or datetime.date.today()
- qs = self.filter(Q(start__date=today) | Q(end__date=today))
+ start = tz.datetime.combine(today, datetime.time())
+ end = tz.datetime.combine(today, datetime.time(23, 59, 59, 999))
+ qs = self.filter(start__range = (start, end))
return qs.order_by('start') if order else qs
def at(self, date, order=True):
@@ -90,9 +92,9 @@ class DiffusionQuerySet(BaseRerunQuerySet):
"""
date = utils.date_or_default(date)
if isinstance(date, tz.datetime):
- qs = self.filter(start__gte=date)
+ qs = self.filter(Q(start__gte=date) | Q(end__gte=date))
else:
- qs = self.filter(start__date__gte=date)
+ qs = self.filter(Q(start__date__gte=date) | Q(end__date__gte=date))
return qs.order_by('start')
def before(self, date=None):
@@ -157,7 +159,7 @@ class Diffusion(BaseRerun):
# help_text = _('use this input port'),
# )
- item_template_name = 'aircox/diffusion_item.html'
+ item_template_name = 'aircox/widgets/diffusion_item.html'
class Meta:
verbose_name = _('Diffusion')
@@ -181,12 +183,10 @@ class Diffusion(BaseRerun):
# self.check_conflicts()
def save_rerun(self):
- print('rerun save', self)
self.episode = self.initial.episode
self.program = self.episode.program
def save_initial(self):
- print('initial save', self)
self.program = self.episode.program
if self.episode != self._initial['episode']:
self.rerun_set.update(episode=self.episode, program=self.program)
@@ -221,6 +221,13 @@ class Diffusion(BaseRerun):
return tz.localtime(self.end, tz.get_current_timezone())
+ @property
+ def is_now(self):
+ """ True if diffusion is currently running """
+ now = tz.now()
+ return self.type == self.TYPE_ON_AIR and \
+ self.start <= now and self.end >= now
+
# TODO: property?
def is_live(self):
""" True if Diffusion is live (False if there are sounds files). """
diff --git a/aircox/models/log.py b/aircox/models/log.py
index 390d3f1..ac7765a 100644
--- a/aircox/models/log.py
+++ b/aircox/models/log.py
@@ -271,21 +271,22 @@ class Log(models.Model):
object_list += logs[:index]
logs = logs[index:]
- # - last log while diff is running
- if logs[0].date > diff.start:
- object_list.append(logs[0])
+ if len(logs):
+ # FIXME
+ # - last log while diff is running
+ #if logs[0].date > diff.start:
+ # object_list.append(logs[0])
- # - skips logs while diff is running
- index = next((i for i, v in enumerate(logs)
- if v.date < diff.start), len(logs))
- if index is not None and index > 0:
- logs = logs[index:]
+ # - skips logs while diff is running
+ index = next((i for i, v in enumerate(logs)
+ if v.date < diff.start), len(logs))
+ if index is not None and index > 0:
+ logs = logs[index:]
# - add diff
object_list.append(diff)
- return object_list
-
+ return object_list if count is None else object_list[:count]
def print(self):
r = []
diff --git a/aircox/models/page.py b/aircox/models/page.py
index 6ccb5c8..b2dfc43 100644
--- a/aircox/models/page.py
+++ b/aircox/models/page.py
@@ -92,7 +92,7 @@ class Page(models.Model):
objects = PageQuerySet.as_manager()
detail_url_name = None
- item_template_name = 'aircox/page_item.html'
+ item_template_name = 'aircox/widgets/page_item.html'
def __str__(self):
return '{}'.format(self.title or self.pk)
diff --git a/aircox/static/aircox/admin.css b/aircox/static/aircox/admin.css
index fa1696a..515d1ee 100644
--- a/aircox/static/aircox/admin.css
+++ b/aircox/static/aircox/admin.css
@@ -1,6 +1,3 @@
-.navbar {
- box-shadow: 0em 0em 0.6em rgba(0, 0, 0, 0.4); }
-
.navbar .navbar-brand {
padding-right: 1em; }
@@ -7211,6 +7208,28 @@ a.navbar-item.is-active {
margin: 0em;
padding: 0em; }
+.card .title {
+ padding: 0.2em;
+ font-size: 1.25rem;
+ font-weight: 500; }
+ .card .title a {
+ color: #363636; }
+
+.card.is-primary {
+ box-shadow: 0em 0em 0.5em #0a0a0a; }
+
+.card-super-title {
+ position: absolute;
+ z-index: 1000;
+ font-size: 1.2em;
+ font-weight: 700;
+ padding: 0.2em;
+ top: 1em;
+ background-color: white; }
+ .card-super-title .fas {
+ padding: 0.1em;
+ font-size: 0.8em; }
+
.filters {
margin: 1em 0em;
background-color: transparent;
@@ -7223,16 +7242,6 @@ a.navbar-item.is-active {
color: #7a7a7a;
font-weight: 300; }
-/*
-.navbar-brand img {
- min-height: 6em;
-}
-
-.navbar-menu .navbar-item:not(:last-child) {
- border-right: 1px $grey solid;
-}
-*/
-/** page **/
.page > .cover {
float: right;
max-width: 45%; }
@@ -7247,26 +7256,23 @@ a.navbar-item.is-active {
.page p {
padding: 0.4em 0em; }
-section > .toolbar {
- background-color: rgba(0, 0, 0, 0.05);
- padding: 1em;
- margin-bottom: 1.5em; }
-
-main .cover {
- margin: 1em 0em;
- border: 0.2em black solid; }
-
-main .small-cover {
- width: 10em; }
-
-aside .small-cover {
- width: 4em; }
-
-aside .media .subtitle {
- font-size: 1em; }
-
-aside .media .content {
- display: none; }
+.media.item .headline {
+ line-height: 1.2em;
+ max-height: calc(1.2em * 3);
+ overflow: hidden; }
+ .media.item .headline + .headline-overflow {
+ position: relative;
+ width: 100%;
+ height: 2em;
+ margin-top: -2em; }
+ .media.item .headline + .headline-overflow:before {
+ content: '';
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ background: linear-gradient(transparent 1em, whitesmoke); }
.player {
box-shadow: 0em 1.5em 2.5em rgba(0, 0, 0, 0.6); }
@@ -7287,3 +7293,37 @@ aside .media .content {
.player .title {
margin: 0em; }
+.media .subtitle {
+ margin-bottom: 0.4em; }
+
+.media .media-content .headline {
+ font-size: 1em;
+ font-weight: 400; }
+
+body {
+ background-color: whitesmoke; }
+
+section > .toolbar {
+ background-color: rgba(0, 0, 0, 0.05);
+ padding: 1em;
+ margin-bottom: 1.5em; }
+
+main .cover {
+ margin: 1em 0em;
+ border: 0.2em black solid; }
+
+main .small-cover {
+ width: 10em; }
+
+aside > section {
+ margin-bottom: 2em; }
+
+aside .cover {
+ margin-bottom: 2em; }
+
+aside .small-cover {
+ width: 4em; }
+
+aside .media .subtitle {
+ font-size: 1em; }
+
diff --git a/aircox/static/aircox/admin.js b/aircox/static/aircox/admin.js
index 81267d7..fbaf339 100644
--- a/aircox/static/aircox/admin.js
+++ b/aircox/static/aircox/admin.js
@@ -305,7 +305,7 @@ eval("// extracted by mini-css-extract-plugin\n\n//# sourceURL=webpack:///./asse
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
-eval("__webpack_require__.r(__webpack_exports__);\n//\n//\n//\n//\n//\n//\n\n\nconst splitReg = new RegExp(`,\\s*`, 'g');\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n data() {\n return {\n counts: {},\n }\n },\n\n methods: {\n update() {\n const items = this.$el.querySelectorAll('input[name=\"data\"]:checked')\n const counts = {};\n\n console.log(items)\n for(var item of items)\n if(item.value)\n for(var tag of item.value.split(splitReg))\n counts[tag.trim()] = (counts[tag.trim()] || 0) + 1;\n this.counts = counts;\n }\n },\n\n mounted() {\n this.$refs.form.addEventListener('change', () => this.update())\n this.update()\n }\n});\n\n\n//# sourceURL=webpack:///./assets/admin/statistics.vue?./node_modules/vue-loader/lib??vue-loader-options");
+eval("__webpack_require__.r(__webpack_exports__);\n//\n//\n//\n//\n//\n//\n\n\nconst splitReg = new RegExp(`,\\s*`, 'g');\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n data() {\n return {\n counts: {},\n }\n },\n\n methods: {\n update() {\n const items = this.$el.querySelectorAll('input[name=\"data\"]:checked')\n const counts = {};\n\n console.log(items)\n for(var item of items)\n if(item.value)\n for(var tag of item.value.split(splitReg))\n counts[tag.trim()] = (counts[tag.trim()] || 0) + 1;\n this.counts = counts;\n },\n\n onclick(event) {\n // TODO: row click => check checkbox\n }\n },\n\n mounted() {\n this.$refs.form.addEventListener('change', () => this.update())\n this.update()\n }\n});\n\n\n//# sourceURL=webpack:///./assets/admin/statistics.vue?./node_modules/vue-loader/lib??vue-loader-options");
/***/ }),
@@ -317,7 +317,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n//\n//\n//\n//\n//\n//\n\n\nc
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
-eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"State\", function() { return State; });\n/* harmony import */ var _liveInfo__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./liveInfo */ \"./assets/public/liveInfo.js\");\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n\n\n\nconst State = {\n paused: 0,\n playing: 1,\n loading: 2,\n}\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n data() {\n return {\n state: State.paused,\n liveInfo: new _liveInfo__WEBPACK_IMPORTED_MODULE_0__[\"default\"](this.liveInfoUrl, this.liveInfoTimeout),\n }\n },\n\n props: {\n buttonTitle: String,\n liveInfoUrl: String,\n liveInfoTimeout: { type: Number, default: 5},\n src: String,\n },\n\n computed: {\n paused() { return this.state == State.paused; },\n playing() { return this.state == State.playing; },\n loading() { return this.state == State.loading; },\n\n onAir() {\n return this.liveInfo.items && this.liveInfo.items[0];\n },\n\n buttonStyle() {\n if(!this.onAir)\n return;\n return { backgroundImage: `url(${this.onAir.cover})` }\n }\n },\n\n methods: {\n load(src) {\n const audio = this.$refs.audio;\n audio.src = src;\n audio.load()\n },\n\n play(src) {\n if(src)\n this.load(src);\n this.$refs.audio.play().catch(e => console.error(e))\n },\n\n pause() {\n this.$refs.audio.pause()\n },\n\n toggle() {\n if(this.paused)\n this.play()\n else\n this.pause()\n },\n\n onChange(event) {\n const audio = this.$refs.audio;\n this.state = audio.paused ? State.paused : State.playing;\n },\n },\n\n mounted() {\n this.liveInfo.refresh()\n },\n\n destroyed() {\n this.liveInfo.drop()\n },\n});\n\n\n\n//# sourceURL=webpack:///./assets/public/player.vue?./node_modules/vue-loader/lib??vue-loader-options");
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"State\", function() { return State; });\n/* harmony import */ var _liveInfo__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./liveInfo */ \"./assets/public/liveInfo.js\");\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n\n\n\nconst State = {\n paused: 0,\n playing: 1,\n loading: 2,\n}\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n data() {\n return {\n state: State.paused,\n liveInfo: new _liveInfo__WEBPACK_IMPORTED_MODULE_0__[\"default\"](this.liveInfoUrl, this.liveInfoTimeout),\n }\n },\n\n props: {\n buttonTitle: String,\n liveInfoUrl: String,\n liveInfoTimeout: { type: Number, default: 5},\n src: String,\n },\n\n computed: {\n paused() { return this.state == State.paused; },\n playing() { return this.state == State.playing; },\n loading() { return this.state == State.loading; },\n\n onAir() {\n return this.liveInfo.items && this.liveInfo.items[0];\n },\n\n buttonStyle() {\n if(!this.onAir)\n return;\n return { backgroundImage: `url(${this.onAir.cover})` }\n }\n },\n\n methods: {\n load(src) {\n const audio = this.$refs.audio;\n audio.src = src;\n audio.load()\n },\n\n play(src) {\n if(src)\n this.load(src);\n this.$refs.audio.play().catch(e => console.error(e))\n },\n\n pause() {\n this.$refs.audio.pause()\n },\n\n toggle() {\n console.log('tooogle', this.paused, '-', this.$refs.audio.src)\n if(this.paused)\n this.play()\n else\n this.pause()\n },\n\n onChange(event) {\n const audio = this.$refs.audio;\n this.state = audio.paused ? State.paused : State.playing;\n },\n },\n\n mounted() {\n this.liveInfo.refresh()\n },\n\n destroyed() {\n this.liveInfo.drop()\n },\n});\n\n\n\n//# sourceURL=webpack:///./assets/public/player.vue?./node_modules/vue-loader/lib??vue-loader-options");
/***/ }),
diff --git a/aircox/static/aircox/main.css b/aircox/static/aircox/main.css
index 5368918..6e70140 100644
--- a/aircox/static/aircox/main.css
+++ b/aircox/static/aircox/main.css
@@ -7190,6 +7190,28 @@ a.navbar-item.is-active {
margin: 0em;
padding: 0em; }
+.card .title {
+ padding: 0.2em;
+ font-size: 1.25rem;
+ font-weight: 500; }
+ .card .title a {
+ color: #363636; }
+
+.card.is-primary {
+ box-shadow: 0em 0em 0.5em #0a0a0a; }
+
+.card-super-title {
+ position: absolute;
+ z-index: 1000;
+ font-size: 1.2em;
+ font-weight: 700;
+ padding: 0.2em;
+ top: 1em;
+ background-color: white; }
+ .card-super-title .fas {
+ padding: 0.1em;
+ font-size: 0.8em; }
+
.filters {
margin: 1em 0em;
background-color: transparent;
@@ -7202,16 +7224,6 @@ a.navbar-item.is-active {
color: #7a7a7a;
font-weight: 300; }
-/*
-.navbar-brand img {
- min-height: 6em;
-}
-
-.navbar-menu .navbar-item:not(:last-child) {
- border-right: 1px $grey solid;
-}
-*/
-/** page **/
.page > .cover {
float: right;
max-width: 45%; }
@@ -7226,26 +7238,23 @@ a.navbar-item.is-active {
.page p {
padding: 0.4em 0em; }
-section > .toolbar {
- background-color: rgba(0, 0, 0, 0.05);
- padding: 1em;
- margin-bottom: 1.5em; }
-
-main .cover {
- margin: 1em 0em;
- border: 0.2em black solid; }
-
-main .small-cover {
- width: 10em; }
-
-aside .small-cover {
- width: 4em; }
-
-aside .media .subtitle {
- font-size: 1em; }
-
-aside .media .content {
- display: none; }
+.media.item .headline {
+ line-height: 1.2em;
+ max-height: calc(1.2em * 3);
+ overflow: hidden; }
+ .media.item .headline + .headline-overflow {
+ position: relative;
+ width: 100%;
+ height: 2em;
+ margin-top: -2em; }
+ .media.item .headline + .headline-overflow:before {
+ content: '';
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ background: linear-gradient(transparent 1em, whitesmoke); }
.player {
box-shadow: 0em 1.5em 2.5em rgba(0, 0, 0, 0.6); }
@@ -7266,3 +7275,37 @@ aside .media .content {
.player .title {
margin: 0em; }
+.media .subtitle {
+ margin-bottom: 0.4em; }
+
+.media .media-content .headline {
+ font-size: 1em;
+ font-weight: 400; }
+
+body {
+ background-color: whitesmoke; }
+
+section > .toolbar {
+ background-color: rgba(0, 0, 0, 0.05);
+ padding: 1em;
+ margin-bottom: 1.5em; }
+
+main .cover {
+ margin: 1em 0em;
+ border: 0.2em black solid; }
+
+main .small-cover {
+ width: 10em; }
+
+aside > section {
+ margin-bottom: 2em; }
+
+aside .cover {
+ margin-bottom: 2em; }
+
+aside .small-cover {
+ width: 4em; }
+
+aside .media .subtitle {
+ font-size: 1em; }
+
diff --git a/aircox/static/aircox/main.js b/aircox/static/aircox/main.js
index b514119..5af8f05 100644
--- a/aircox/static/aircox/main.js
+++ b/aircox/static/aircox/main.js
@@ -246,7 +246,7 @@ eval("// extracted by mini-css-extract-plugin\n\n//# sourceURL=webpack:///./asse
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
-eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"State\", function() { return State; });\n/* harmony import */ var _liveInfo__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./liveInfo */ \"./assets/public/liveInfo.js\");\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n\n\n\nconst State = {\n paused: 0,\n playing: 1,\n loading: 2,\n}\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n data() {\n return {\n state: State.paused,\n liveInfo: new _liveInfo__WEBPACK_IMPORTED_MODULE_0__[\"default\"](this.liveInfoUrl, this.liveInfoTimeout),\n }\n },\n\n props: {\n buttonTitle: String,\n liveInfoUrl: String,\n liveInfoTimeout: { type: Number, default: 5},\n src: String,\n },\n\n computed: {\n paused() { return this.state == State.paused; },\n playing() { return this.state == State.playing; },\n loading() { return this.state == State.loading; },\n\n onAir() {\n return this.liveInfo.items && this.liveInfo.items[0];\n },\n\n buttonStyle() {\n if(!this.onAir)\n return;\n return { backgroundImage: `url(${this.onAir.cover})` }\n }\n },\n\n methods: {\n load(src) {\n const audio = this.$refs.audio;\n audio.src = src;\n audio.load()\n },\n\n play(src) {\n if(src)\n this.load(src);\n this.$refs.audio.play().catch(e => console.error(e))\n },\n\n pause() {\n this.$refs.audio.pause()\n },\n\n toggle() {\n if(this.paused)\n this.play()\n else\n this.pause()\n },\n\n onChange(event) {\n const audio = this.$refs.audio;\n this.state = audio.paused ? State.paused : State.playing;\n },\n },\n\n mounted() {\n this.liveInfo.refresh()\n },\n\n destroyed() {\n this.liveInfo.drop()\n },\n});\n\n\n\n//# sourceURL=webpack:///./assets/public/player.vue?./node_modules/vue-loader/lib??vue-loader-options");
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"State\", function() { return State; });\n/* harmony import */ var _liveInfo__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./liveInfo */ \"./assets/public/liveInfo.js\");\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n\n\n\nconst State = {\n paused: 0,\n playing: 1,\n loading: 2,\n}\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n data() {\n return {\n state: State.paused,\n liveInfo: new _liveInfo__WEBPACK_IMPORTED_MODULE_0__[\"default\"](this.liveInfoUrl, this.liveInfoTimeout),\n }\n },\n\n props: {\n buttonTitle: String,\n liveInfoUrl: String,\n liveInfoTimeout: { type: Number, default: 5},\n src: String,\n },\n\n computed: {\n paused() { return this.state == State.paused; },\n playing() { return this.state == State.playing; },\n loading() { return this.state == State.loading; },\n\n onAir() {\n return this.liveInfo.items && this.liveInfo.items[0];\n },\n\n buttonStyle() {\n if(!this.onAir)\n return;\n return { backgroundImage: `url(${this.onAir.cover})` }\n }\n },\n\n methods: {\n load(src) {\n const audio = this.$refs.audio;\n audio.src = src;\n audio.load()\n },\n\n play(src) {\n if(src)\n this.load(src);\n this.$refs.audio.play().catch(e => console.error(e))\n },\n\n pause() {\n this.$refs.audio.pause()\n },\n\n toggle() {\n console.log('tooogle', this.paused, '-', this.$refs.audio.src)\n if(this.paused)\n this.play()\n else\n this.pause()\n },\n\n onChange(event) {\n const audio = this.$refs.audio;\n this.state = audio.paused ? State.paused : State.playing;\n },\n },\n\n mounted() {\n this.liveInfo.refresh()\n },\n\n destroyed() {\n this.liveInfo.drop()\n },\n});\n\n\n\n//# sourceURL=webpack:///./assets/public/player.vue?./node_modules/vue-loader/lib??vue-loader-options");
/***/ }),
diff --git a/aircox/templates/admin/aircox/statistics.html b/aircox/templates/admin/aircox/statistics.html
index 6dfa9b2..5f0156e 100644
--- a/aircox/templates/admin/aircox/statistics.html
+++ b/aircox/templates/admin/aircox/statistics.html
@@ -3,8 +3,14 @@
{% block content %}{{ block.super }}
+
+
{# TODO: date subtitle #}
-
+
@@ -23,13 +29,12 @@
{% for track in tracks %}
{% if forloop.first %}
- {{ object.start|time:"H:i" }} |
+ {{ object.start|time:"H:i" }} {% if object|is_diffusion %} - {{ object.end|time:"H:i" }}{% endif %} |
{{ object.episode|default:"" }} |
{% endif %}
- {% if not object|is_diffusion %}
{% with track as object %}
- {% include "aircox/track_item.html" %} |
+ {% include "aircox/widgets/track_item.html" %} |
{% endwith %}
{% with track.tags.all|join:', ' as tags %}
@@ -41,10 +46,17 @@
{% endif %}
|
{% endwith %}
- {% else %}
+
+ {% empty %}
+ {% if object|is_diffusion %}
+
+ {{ object.start|time:"H:i" }} - {{ object.end|time:"H:i" }} |
+ {{ object.episode|default:"" }} |
+ |
+ |
+
{% endif %}
{% endfor %}
-
{% endwith %}
{% endfor %}
@@ -65,14 +77,6 @@
-
-
-
-
{% endblock %}
diff --git a/aircox/templates/admin/base.html b/aircox/templates/admin/base.html
index e66b147..3eb3808 100644
--- a/aircox/templates/admin/base.html
+++ b/aircox/templates/admin/base.html
@@ -29,11 +29,10 @@
data-admin-utc-offset="{% now "Z" %}">
-
-
+
{% if not is_popup %}
-
-
+
{% endblock %}
diff --git a/aircox/templates/aircox/article_detail.html b/aircox/templates/aircox/article_detail.html
index dce7ec4..ee86496 100644
--- a/aircox/templates/aircox/article_detail.html
+++ b/aircox/templates/aircox/article_detail.html
@@ -4,12 +4,12 @@
{% block sidebar %}
{{ block.super }}
-{% if sidebar_items %}
+{% if sidebar_object_list %}
{% trans "Latest news" %}
- {% for object in sidebar_items %}
- {% include "aircox/page_item.html" %}
+ {% for object in sidebar_object_list %}
+ {% include "aircox/widgets/page_item.html" %}
{% endfor %}
diff --git a/aircox/templates/aircox/base.html b/aircox/templates/aircox/base.html
index e06477f..c427aa5 100644
--- a/aircox/templates/aircox/base.html
+++ b/aircox/templates/aircox/base.html
@@ -1,10 +1,29 @@
-{% load static i18n thumbnail aircox %}
{% comment %}
Context:
- cover: image cover
- site: current website
- has_filters: display filter bar (using block "filters")
+- sidebar_object_list: item to display in sidebar
+- sidebar_url_name: url name sidebar item complete list
+- sidebar_url_parent: parent page for sidebar items complete list
+
+Blocks:
+- assets
+- head_title
+- head_extra
+- top_nav
+- header:
+ - title
+ - subtitle
+ - header_meta
+- main:
+ - filters
+- cover
+- sidebar:
+ - sidebar_title
{% endcomment %}
+{% load static i18n thumbnail aircox %}
+
@@ -72,14 +91,14 @@ Context:
{% endblock %}
- {% if has_filters %}
-
- {% block filters %}{% endblock %}
-
- {% endif %}
-
- {% block main %}{% endblock main %}
+ {% block main %}
+ {% if has_filters %}
+
+ {% block filters %}{% endblock %}
+
+ {% endif %}
+ {% endblock main %}
{% if has_sidebar %}
@@ -92,28 +111,18 @@ Context:
{% endblock %}
{% block sidebar %}
- {% if sidebar_items %}
+ {% if sidebar_object_list %}
+ {% with object_list=sidebar_object_list %}
+ {% with list_url=sidebar_list_url %}
+ {% with has_headline=False %}
{% block sidebar_title %}{% trans "Recently" %}{% endblock %}
-
- {% for object in sidebar_items %}
- {% include "aircox/episode_item.html" %}
- {% endfor %}
-
-
-
+ {% include "aircox/widgets/page_list.html" %}
+ {% endwith %}
+ {% endwith %}
+ {% endwith %}
{% endif %}
{% endblock %}
diff --git a/aircox/templates/aircox/diffusion_list.html b/aircox/templates/aircox/diffusion_list.html
index 78d60b4..47ebc29 100644
--- a/aircox/templates/aircox/diffusion_list.html
+++ b/aircox/templates/aircox/diffusion_list.html
@@ -16,7 +16,7 @@
{% endblock %}
{% block main %}{{ block.super }}
-{% with True as hide_schedule %}
+{% with hide_schedule=True %}
{% for diffusion in object_list %}
@@ -24,12 +24,12 @@
{% with diffusion.episode as object %}
- {% include "aircox/episode_item.html" %}
+ {% include "aircox/widgets/episode_item.html" %}
{% endwith %}
diff --git a/aircox/templates/aircox/episode_detail.html b/aircox/templates/aircox/episode_detail.html
index 2d31754..43075f4 100644
--- a/aircox/templates/aircox/episode_detail.html
+++ b/aircox/templates/aircox/episode_detail.html
@@ -50,7 +50,7 @@
{% trans "Podcasts" %}
{% for object in podcasts %}
- {% include "aircox/podcast_item.html" %}
+ {% include "aircox/widgets/podcast_item.html" %}
{% endfor %}
{% endif %}
diff --git a/aircox/templates/aircox/home.html b/aircox/templates/aircox/home.html
new file mode 100644
index 0000000..3c76f5c
--- /dev/null
+++ b/aircox/templates/aircox/home.html
@@ -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 %}
+
+ {% with render_card=True %}
+ {% for object in top_diffs %}
+ {% with is_primary=object.is_now %}
+
+
+ {% if is_primary %}
+
+ {% trans "Currently" %}
+ {% else %}{{ object.start|date:"H:i" }}{% endif %}
+
+ {% include object.item_template_name %}
+
+ {% endwith %}
+ {% endfor %}
+ {% endwith %}
+
+
+
+
{% trans "Last publications" %}
+{{ block.super }}
+{% endblock %}
+
+
+{% block pagination %}
+
+{% endblock %}
+
+
+{% block sidebar %}
+
+ {% trans "Previously on air" %}
+ {% with logs as object_list %}
+ {% include "aircox/widgets/log_list.html" %}
+ {% endwith %}
+
+
+
+ {% trans "Today" %}
+ {% with hide_schedule=True %}
+ {% with has_headline=False %}
+
+ {% for object in sidebar_object_list %}
+
+ {{ object.start|date:"H:i" }} |
+ {% include "aircox/widgets/diffusion_item.html" %} |
+
+ {% endfor %}
+
+ {% endwith %}
+ {% endwith %}
+
+{% endblock %}
+
+
diff --git a/aircox/templates/aircox/log_list.html b/aircox/templates/aircox/log_list.html
index be03e6a..13d1772 100644
--- a/aircox/templates/aircox/log_list.html
+++ b/aircox/templates/aircox/log_list.html
@@ -16,29 +16,10 @@
{% endwith %}
{% endblock %}
-{% block main %}
+{% block main %}{{ block.super }}
{# {{ date }}
#}
- {% with True as hide_schedule %}
-
- {% for object in object_list %}
-
-
- {% if object|is_diffusion %}
-
- {% else %}
-
- {% endif %}
- |
- {% include "aircox/log_item.html" %} |
-
- {% endfor %}
-
- {% endwith %}
+ {% include "aircox/widgets/log_list.html" %}
{% endblock %}
diff --git a/aircox/templates/aircox/page_list.html b/aircox/templates/aircox/page_list.html
index 539a98c..ee5b01d 100644
--- a/aircox/templates/aircox/page_list.html
+++ b/aircox/templates/aircox/page_list.html
@@ -56,21 +56,23 @@
{% endblock %}
-{% block main %}
+{% block main %}{{ block.super }}
+{% with has_headline=True %}
{% for object in object_list %}
{% block list_object %}
{% include object.item_template_name|default:item_template_name %}
{% endblock %}
{% endfor %}
+{% endwith %}
{% if is_paginated %}
-
{% update_query request.GET.copy page=None as GET %}
{% with GET.urlencode as GET %}
{% endwith %}
{% endif %}
diff --git a/aircox/templates/aircox/program_base.html b/aircox/templates/aircox/program_base.html
index a3f5db2..d7a8e3e 100644
--- a/aircox/templates/aircox/program_base.html
+++ b/aircox/templates/aircox/program_base.html
@@ -3,13 +3,7 @@
{% block sidebar_title %}
{% with program.title as program %}
-{% blocktrans %} Recently on {{ program }}{% endblocktrans %}
-{% endwith %}
-{% endblock %}
-
-{% block sidebar %}
-{% with program as parent %}
-{{ block.super }}
+{% blocktrans %}Recently on {{ program }}{% endblocktrans %}
{% endwith %}
{% endblock %}
diff --git a/aircox/templates/aircox/program_detail.html b/aircox/templates/aircox/program_detail.html
index 9692562..e91a330 100644
--- a/aircox/templates/aircox/program_detail.html
+++ b/aircox/templates/aircox/program_detail.html
@@ -10,15 +10,14 @@
{% block content %}{{ block.super }}
-
-{% with show_headline=False %}
+{% with has_headline=False %}
{% if articles %}
{% trans "Articles" %}
{% for object in articles %}
- {% include "aircox/page_item.html" %}
+ {% include "aircox/widgets/page_item.html" %}
{% endfor %}
diff --git a/aircox/templates/aircox/diffusion_item.html b/aircox/templates/aircox/widgets/diffusion_item.html
similarity index 81%
rename from aircox/templates/aircox/diffusion_item.html
rename to aircox/templates/aircox/widgets/diffusion_item.html
index 8b5d651..2971908 100644
--- a/aircox/templates/aircox/diffusion_item.html
+++ b/aircox/templates/aircox/widgets/diffusion_item.html
@@ -5,7 +5,7 @@ Context:
{% endcomment %}
{% with object as diffusion %}
{% with object.episode as object %}
-{% include "aircox/episode_item.html" %}
+{% include "aircox/widgets/episode_item.html" %}
{% endwith %}
{% endwith %}
diff --git a/aircox/templates/aircox/episode_item.html b/aircox/templates/aircox/widgets/episode_item.html
similarity index 95%
rename from aircox/templates/aircox/episode_item.html
rename to aircox/templates/aircox/widgets/episode_item.html
index a5d6911..d9c6a73 100644
--- a/aircox/templates/aircox/episode_item.html
+++ b/aircox/templates/aircox/widgets/episode_item.html
@@ -1,4 +1,4 @@
-{% extends "aircox/page_item.html" %}
+{% extends "aircox/widgets/page_item.html" %}
{% load i18n easy_thumbnails_tags aircox %}
{% comment %}
diff --git a/aircox/templates/aircox/log_item.html b/aircox/templates/aircox/widgets/log_item.html
similarity index 79%
rename from aircox/templates/aircox/log_item.html
rename to aircox/templates/aircox/widgets/log_item.html
index 9cbae9b..355f81c 100644
--- a/aircox/templates/aircox/log_item.html
+++ b/aircox/templates/aircox/widgets/log_item.html
@@ -11,11 +11,11 @@ for design review.
{% if object|is_diffusion %}
{% with object as diffusion %}
- {% include "aircox/diffusion_item.html" %}
+ {% include "aircox/widgets/diffusion_item.html" %}
{% endwith %}
{% else %}
{% with object.track as object %}
- {% include "aircox/track_item.html" %}
+ {% include "aircox/widgets/track_item.html" %}
{% endwith %}
{% endif %}
diff --git a/aircox/templates/aircox/widgets/log_list.html b/aircox/templates/aircox/widgets/log_list.html
new file mode 100644
index 0000000..0b1cae3
--- /dev/null
+++ b/aircox/templates/aircox/widgets/log_list.html
@@ -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 %}
+
+ {% for object in object_list %}
+
+
+ {% if object|is_diffusion %}
+
+ {% else %}
+
+ {% endif %}
+ |
+ {% include "aircox/widgets/log_item.html" %} |
+
+ {% endfor %}
+
+{% endwith %}
+
diff --git a/aircox/templates/aircox/page_item.html b/aircox/templates/aircox/widgets/page_item.html
similarity index 52%
rename from aircox/templates/aircox/page_item.html
rename to aircox/templates/aircox/widgets/page_item.html
index 0d47cf8..67f422e 100644
--- a/aircox/templates/aircox/page_item.html
+++ b/aircox/templates/aircox/widgets/page_item.html
@@ -1,15 +1,36 @@
{% load i18n easy_thumbnails_tags aircox %}
{% comment %}
Context variables:
-- object: the actual diffusion
-- show_headline: if True, display headline
+- object: the object to render
+- render_card: render as card
+- is-primary: render as primary
+- has_headline (=False): if True, display headline
+- has_cover (=True): hide page cover
{% endcomment %}
-
+{% if render_card %}
+
+
+
+
+
+
+
+
+
+
+{% else %}
+
+ {% if has_cover|default_if_none:True %}
+ {% endif %}
{% block title %}
@@ -26,8 +47,8 @@ Context variables:
{% endblock %}
- {% if show_headline %}
-
+ {% if has_headline|default_if_none:True %}
+
{% block headline %}
{{ object.headline|safe }}
{% endblock %}
@@ -35,4 +56,5 @@ Context variables:
{% endif %}
+{% endif %}
diff --git a/aircox/templates/aircox/widgets/page_list.html b/aircox/templates/aircox/widgets/page_list.html
new file mode 100644
index 0000000..46a798b
--- /dev/null
+++ b/aircox/templates/aircox/widgets/page_list.html
@@ -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 %}
+
+
+{% endif %}
+
+
diff --git a/aircox/templates/aircox/podcast_item.html b/aircox/templates/aircox/widgets/podcast_item.html
similarity index 100%
rename from aircox/templates/aircox/podcast_item.html
rename to aircox/templates/aircox/widgets/podcast_item.html
diff --git a/aircox/templates/aircox/track_item.html b/aircox/templates/aircox/widgets/track_item.html
similarity index 100%
rename from aircox/templates/aircox/track_item.html
rename to aircox/templates/aircox/widgets/track_item.html
diff --git a/aircox/urls.py b/aircox/urls.py
index 6fbcf82..cb7c74e 100755
--- a/aircox/urls.py
+++ b/aircox/urls.py
@@ -24,8 +24,7 @@ api = [
urls = [
- path(_(''),
- views.DiffusionListView.as_view(), name='home'),
+ path('', views.HomeView.as_view(), name='home'),
path('api/', include(api)),
# path('', views.PageDetailView.as_view(model=models.Article),
@@ -51,9 +50,9 @@ urls = [
# path('
', views.route_page, name='page'),
path(_('publications/'),
- views.ProgramPageListView.as_view(), name='page-list'),
+ views.PageListView.as_view(model=models.Page), name='page-list'),
- path(_('programs/'), views.PageListView.as_view(model=models.Program),
+ path(_('programs/'), views.ProgramListView.as_view(model=models.Program),
name='program-list'),
path(_('programs//'),
views.ProgramDetailView.as_view(), name='program-detail'),
@@ -62,7 +61,7 @@ urls = [
path(_('programs//articles/'),
views.ArticleListView.as_view(), name='article-list'),
path(_('programs//publications/'),
- views.ProgramPageListView.as_view(), name='page-list'),
+ views.ProgramPageListView.as_view(), name='program-page-list'),
]
diff --git a/aircox/views/__init__.py b/aircox/views/__init__.py
index ed44b56..e031491 100644
--- a/aircox/views/__init__.py
+++ b/aircox/views/__init__.py
@@ -1,9 +1,12 @@
from . import api, admin
-from .article import ArticleDetailView, ArticleListView
from .base import BaseView
+from .home import HomeView
+
+from .article import ArticleDetailView, ArticleListView
from .episode import EpisodeDetailView, EpisodeListView, DiffusionListView
from .log import LogListView
from .page import PageDetailView, PageListView
-from .program import ProgramDetailView, ProgramPageListView
+from .program import ProgramDetailView, ProgramListView, \
+ ProgramPageDetailView, ProgramPageListView
diff --git a/aircox/views/admin.py b/aircox/views/admin.py
index 49ec58a..441d379 100644
--- a/aircox/views/admin.py
+++ b/aircox/views/admin.py
@@ -44,8 +44,7 @@ class AdminSite(admin.AdminSite):
def get_urls(self):
from django.urls import path, include
- urls = super().get_urls()
- urls += [
+ urls = super().get_urls() + [
path('tools/statistics/',
self.admin_view(StatisticsView.as_view()),
name='tools-stats'),
diff --git a/aircox/views/api.py b/aircox/views/api.py
index e00e2eb..9060d52 100644
--- a/aircox/views/api.py
+++ b/aircox/views/api.py
@@ -4,7 +4,6 @@ from django.utils import timezone as tz
from rest_framework.generics import ListAPIView
-from ..utils import str_to_date
from ..models import Log
from ..serializers import LogInfo, LogInfoSerializer
from .log import LogListMixin
diff --git a/aircox/views/article.py b/aircox/views/article.py
index e81cc1a..02dabbc 100644
--- a/aircox/views/article.py
+++ b/aircox/views/article.py
@@ -25,7 +25,7 @@ class ArticleDetailView(PageDetailView):
class ArticleListView(ParentMixin, PageListView):
model = Article
template_name = 'aircox/article_list.html'
- show_headline = True
+ has_headline = True
is_static = False
parent_model = Program
diff --git a/aircox/views/base.py b/aircox/views/base.py
index eb4c0f0..c3a807c 100644
--- a/aircox/views/base.py
+++ b/aircox/views/base.py
@@ -2,6 +2,7 @@
from django.http import Http404
from django.views.generic import DetailView, ListView
from django.views.generic.base import TemplateResponseMixin, ContextMixin
+from django.urls import reverse
from ..models import Page
from ..utils import Redirect
@@ -35,21 +36,25 @@ class BaseView(TemplateResponseMixin, ContextMixin):
return Page.objects.select_subclasses().published() \
.order_by('-pub_date')
- def get_context_data(self, sidebar_items=None, **kwargs):
+ def get_sidebar_url(self):
+ return reverse('page-list')
+
+ def get_context_data(self, **kwargs):
kwargs.setdefault('station', self.station)
kwargs.setdefault('cover', self.cover)
kwargs.setdefault('has_filters', self.has_filters)
has_sidebar = kwargs.setdefault('has_sidebar', self.has_sidebar)
- if has_sidebar and sidebar_items is None:
- sidebar_items = self.get_sidebar_queryset()
- sidebar_items = None if sidebar_items is None else \
- sidebar_items[:self.list_count]
+ if has_sidebar and 'sidebar_object_list' not in kwargs:
+ sidebar_object_list = self.get_sidebar_queryset()
+ if sidebar_object_list is not None:
+ kwargs['sidebar_object_list'] = sidebar_object_list[:self.list_count]
+ kwargs['sidebar_list_url'] = self.get_sidebar_url()
if not 'audio_streams' in kwargs:
streams = self.station.audio_streams
streams = streams and streams.split('\n')
kwargs['audio_streams'] = streams
- return super().get_context_data(sidebar_items=sidebar_items, **kwargs)
+ return super().get_context_data(**kwargs)
diff --git a/aircox/views/episode.py b/aircox/views/episode.py
index 8e1aa1a..36eb0fa 100644
--- a/aircox/views/episode.py
+++ b/aircox/views/episode.py
@@ -21,9 +21,6 @@ class EpisodeDetailView(ProgramPageDetailView):
return Sound.objects.diffusion(diffusion).podcasts()
def get_context_data(self, **kwargs):
- self.program = kwargs.setdefault('program', self.object.program)
-
- kwargs.setdefault('parent', self.program)
if not 'tracks' in kwargs:
kwargs['tracks'] = self.object.track_set.order_by('position')
if not 'podcasts' in kwargs:
@@ -33,8 +30,8 @@ class EpisodeDetailView(ProgramPageDetailView):
class EpisodeListView(ParentMixin, PageListView):
model = Episode
- item_template_name = 'aircox/episode_item.html'
- show_headline = True
+ item_template_name = 'aircox/widgets/episode_item.html'
+ has_headline = True
parent_model = Program
diff --git a/aircox/views/home.py b/aircox/views/home.py
new file mode 100644
index 0000000..71c8a4a
--- /dev/null
+++ b/aircox/views/home.py
@@ -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)
+
+
+
diff --git a/aircox/views/log.py b/aircox/views/log.py
index f61670e..6f3de61 100644
--- a/aircox/views/log.py
+++ b/aircox/views/log.py
@@ -2,6 +2,7 @@ from collections import deque
import datetime
from django.views.generic import ListView
+from django.utils import timezone as tz
from ..models import Diffusion, Log
from .base import BaseView
@@ -23,12 +24,14 @@ class LogListMixin(GetDateMixin):
def get_queryset(self):
# only get logs for tracks: log for diffusion will be retrieved
# by the diffusions' queryset.
- qs = super().get_queryset().on_air().filter(track__isnull=False)
+ qs = super().get_queryset().on_air().filter(track__isnull=False) \
+ .filter(date__lte=tz.now())
return qs.today(self.date) if self.date is not None else \
qs.after(self.min_date) if self.min_date is not None else qs
def get_diffusions_queryset(self):
- qs = Diffusion.objects.station(self.station).on_air()
+ qs = Diffusion.objects.station(self.station).on_air() \
+ .filter(start__lte=tz.now())
return qs.today(self.date) if self.date is not None else \
qs.after(self.min_date) if self.min_date is not None else qs
diff --git a/aircox/views/mixins.py b/aircox/views/mixins.py
index 6b56260..28d3dc9 100644
--- a/aircox/views/mixins.py
+++ b/aircox/views/mixins.py
@@ -63,9 +63,9 @@ class ParentMixin:
return super().get_queryset()
def get_context_data(self, **kwargs):
- parent = kwargs.setdefault('parent', self.parent)
- if parent is not None:
- kwargs.setdefault('cover', parent.cover)
+ self.parent = kwargs.setdefault('parent', self.parent)
+ if self.parent is not None:
+ kwargs.setdefault('cover', self.parent.cover)
return super().get_context_data(**kwargs)
diff --git a/aircox/views/page.py b/aircox/views/page.py
index 1dcaa7f..9ba3f13 100644
--- a/aircox/views/page.py
+++ b/aircox/views/page.py
@@ -6,7 +6,7 @@ from django.views.generic import DetailView, ListView
from honeypot.decorators import check_honeypot
from ..forms import CommentForm
-from ..models import Category, Comment
+from ..models import Category, Comment, Page
from ..utils import Redirect
from .base import BaseView
@@ -17,12 +17,12 @@ __all__ = ['PageDetailView', 'PageListView']
# TODO: pagination: in template, only a limited number of pages displayed
class PageListView(BaseView, ListView):
template_name = 'aircox/page_list.html'
- item_template_name = 'aircox/page_item.html'
+ item_template_name = 'aircox/widgets/page_item.html'
has_sidebar = True
has_filters = True
paginate_by = 20
- show_headline = True
+ has_headline = True
categories = None
def get(self, *args, **kwargs):
@@ -30,7 +30,7 @@ class PageListView(BaseView, ListView):
return super().get(*args, **kwargs)
def get_queryset(self):
- qs = super().get_queryset().published() \
+ qs = super().get_queryset().select_subclasses().published() \
.select_related('cover', 'category')
# category can be filtered based on request.GET['categories']
@@ -50,7 +50,7 @@ class PageListView(BaseView, ListView):
kwargs.setdefault('item_template_name', self.item_template_name)
kwargs.setdefault('filter_categories', self.get_categories_queryset())
kwargs.setdefault('categories', self.categories)
- kwargs.setdefault('show_headline', self.show_headline)
+ kwargs.setdefault('has_headline', self.has_headline)
return super().get_context_data(**kwargs)
diff --git a/aircox/views/program.py b/aircox/views/program.py
index e9698fc..4388148 100644
--- a/aircox/views/program.py
+++ b/aircox/views/program.py
@@ -1,6 +1,7 @@
from django.db.models import Q
from django.core.exceptions import ObjectDoesNotExist
from django.shortcuts import get_object_or_404
+from django.urls import reverse
from ..models import Episode, Program, Page
from .mixins import ParentMixin
@@ -10,30 +11,54 @@ from .page import PageDetailView, PageListView
__all__ = ['ProgramPageDetailView', 'ProgramDetailView', 'ProgramPageListView']
-class ProgramPageDetailView(PageDetailView):
+class BaseProgramMixin:
+ def get_program(self):
+ return self.object
+
+ def get_sidebar_url(self):
+ return reverse('program-page-list',
+ kwargs={"parent_slug": self.program.slug})
+
+ def get_context_data(self, **kwargs):
+ self.program = self.get_program()
+ kwargs['program'] = self.program
+ return super().get_context_data(**kwargs)
+
+
+class ProgramDetailView(BaseProgramMixin, PageDetailView):
+ model = Program
+
+ def get_sidebar_queryset(self):
+ return super().get_sidebar_queryset().filter(parent=self.program)
+
+
+class ProgramListView(PageListView):
+ model = Program
+
+
+class ProgramPageDetailView(BaseProgramMixin, ParentMixin, PageDetailView):
"""
Base view class for a page that is displayed as a program's child page.
"""
- program = None
- has_sidebar = True
- list_count = 5
+ parent_model = Program
+
+ def get_program(self):
+ self.parent = self.object.program
+ return self.object.program
def get_sidebar_queryset(self):
- return super().get_sidebar_queryset().filter(parent=self.object)
+ return super().get_sidebar_queryset().filter(parent=self.program)
-class ProgramPageListView(ParentMixin, PageListView):
+class ProgramPageListView(BaseProgramMixin, ParentMixin, PageListView):
model = Page
parent_model = Program
queryset = Page.objects.select_subclasses()
-
-class ProgramDetailView(ProgramPageDetailView):
- model = Program
+ def get_program(self):
+ return self.parent
def get_context_data(self, **kwargs):
- self.program = kwargs.setdefault('program', self.object)
+ kwargs.setdefault('sidebar_url_parent', None)
return super().get_context_data(**kwargs)
-
-
diff --git a/assets/admin/admin.scss b/assets/admin/admin.scss
index 8b299d3..0cc5b67 100644
--- a/assets/admin/admin.scss
+++ b/assets/admin/admin.scss
@@ -1,10 +1,4 @@
-// @import './bulmacolors';
-
-.navbar {
- box-shadow: 0em 0em 0.6em rgba(0, 0, 0, 0.4);
-}
-
.navbar .navbar-brand {
padding-right: 1em;
}
diff --git a/assets/admin/statistics.vue b/assets/admin/statistics.vue
index bebbc65..518c1fe 100644
--- a/assets/admin/statistics.vue
+++ b/assets/admin/statistics.vue
@@ -26,6 +26,10 @@ export default {
for(var tag of item.value.split(splitReg))
counts[tag.trim()] = (counts[tag.trim()] || 0) + 1;
this.counts = counts;
+ },
+
+ onclick(event) {
+ // TODO: row click => check checkbox
}
},
diff --git a/assets/public/player.vue b/assets/public/player.vue
index 62dba06..5fcacdb 100644
--- a/assets/public/player.vue
+++ b/assets/public/player.vue
@@ -83,6 +83,7 @@ export default {
},
toggle() {
+ console.log('tooogle', this.paused, '-', this.$refs.audio.src)
if(this.paused)
this.play()
else
diff --git a/assets/public/styles.scss b/assets/public/styles.scss
index 1c4c987..e4e927c 100644
--- a/assets/public/styles.scss
+++ b/assets/public/styles.scss
@@ -3,7 +3,7 @@
$body-background-color: $light;
-@import "~bulma/bulma";
+@import "~bulma";
//-- helpers/modifiers
.is-fullwidth { width: 100%; }
@@ -58,6 +58,38 @@ a.navbar-item.is-active {
}
}
+//-- cards
+.card {
+ .title {
+ a {
+ color: $dark;
+ }
+
+ padding: 0.2em;
+ font-size: $size-5;
+ font-weight: $weight-medium;
+ }
+
+ &.is-primary {
+ box-shadow: 0em 0em 0.5em $black
+ }
+}
+
+.card-super-title {
+ position: absolute;
+ z-index: 1000;
+ font-size: 1.2em;
+ font-weight: $weight-bold;
+ padding: 0.2em;
+ top: 1em;
+ background-color: $white;
+
+ .fas {
+ padding: 0.1em;
+ font-size: 0.8em;
+ }
+}
+
//-- filters
.filters {
@@ -77,18 +109,7 @@ a.navbar-item.is-active {
}
-/*
-.navbar-brand img {
- min-height: 6em;
-}
-
-.navbar-menu .navbar-item:not(:last-child) {
- border-right: 1px $grey solid;
-}
-*/
-
-
-/** page **/
+//-- page
.page {
& > .cover {
float: right;
@@ -109,39 +130,33 @@ a.navbar-item.is-active {
}
}
-section > .toolbar {
- background-color: rgba(0,0,0,0.05);
- padding: 1em;
- margin-bottom: 1.5em;
-}
+.media.item .headline {
+ line-height: 1.2em;
+ max-height: calc(1.2em * 3);
+ overflow: hidden;
-main {
- .cover {
- margin: 1em 0em;
- border: 0.2em black solid;
+ & + .headline-overflow {
+ position: relative;
+ width: 100%;
+ height: 2em;
+ margin-top: -2em;
}
- .small-cover {
- width: 10em;
- }
-}
-
-aside {
- .small-cover {
- width: 4em;
- }
-
- .media .subtitle {
- font-size: 1em;
- }
-
- .media .content {
- display: none;
+ & + .headline-overflow:before {
+ content:'';
+ width:100%;
+ height:100%;
+ position:absolute;
+ left:0;
+ bottom:0;
+ background:linear-gradient(transparent 1em, $body-background-color);
}
}
+
+//-- player
.player {
box-shadow: 0em 1.5em 2.5em rgba(0, 0, 0, 0.6);
@@ -175,4 +190,57 @@ aside {
}
+//-- media
+.media {
+ .subtitle {
+ margin-bottom: 0.4em;
+ }
+ .media-content .headline {
+ font-size: 1em;
+ font-weight: 400;
+ }
+}
+
+//-- general
+body {
+ background-color: $body-background-color;
+}
+
+section > .toolbar {
+ background-color: rgba(0,0,0,0.05);
+ padding: 1em;
+ margin-bottom: 1.5em;
+}
+
+
+main {
+ .cover {
+ margin: 1em 0em;
+ border: 0.2em black solid;
+ }
+
+ .small-cover {
+ width: 10em;
+ }
+}
+
+aside {
+ & > section {
+ margin-bottom: 2em;
+ }
+
+ .cover {
+ margin-bottom: 2em;
+ }
+
+ .small-cover {
+ width: 4em;
+ }
+
+ .media .subtitle {
+ font-size: 1em;
+ }
+}
+
+
diff --git a/instance/urls.py b/instance/urls.py
index 38ae87f..2046b53 100755
--- a/instance/urls.py
+++ b/instance/urls.py
@@ -22,9 +22,8 @@ import aircox.urls
try:
- urlpatterns = [
+ urlpatterns = aircox.urls.urls + [
path('admin/', admin.site.urls),
- path('aircox/', include(aircox.urls.urls)),
]
if settings.DEBUG: