carousel, display logs

This commit is contained in:
bkfox 2023-11-28 01:23:56 +01:00
parent cb5a6a3ee8
commit ed9affbef6
6 changed files with 58 additions and 31 deletions

View File

@ -2,10 +2,13 @@
!*** css ./node_modules/css-loader/dist/cjs.js??clonedRuleSet-12.use[1]!./node_modules/vue-loader/dist/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-12.use[2]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/ACarousel.vue?vue&type=style&index=0&id=b79f173e&scoped=true&lang=css ***!
\*************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
.a-carousel[data-v-b79f173e] {
width: 100%;
position: relative;
}
.a-carousel-viewport[data-v-b79f173e] {
width: 100%;
overflow: hidden;
position: relative;
}
.a-carousel-container[data-v-b79f173e] {
display: flex;
@ -8542,6 +8545,7 @@ nav li a, nav li .button {
}
.preview-wide .headings {
width: var(--preview-cover-size);
min-width: var(--preview-cover-size);
flex-grow: 0;
margin-right: 1.2rem;
}
@ -8607,6 +8611,10 @@ preview-header:not(.no-cover) .preview-card-headings .heading {
gap: 1.2rem;
}
.a-carousel {
padding-bottom: 1.4rem;
}
.a-carousel-container {
width: 100%;
gap: 1.2rem;

View File

@ -35,7 +35,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _mod
\*******************************************************************************************************************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm-bundler.js\");\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n setup() {\n return {\n viewport: (0,vue__WEBPACK_IMPORTED_MODULE_0__.ref)(null),\n container: (0,vue__WEBPACK_IMPORTED_MODULE_0__.ref)(null)\n };\n },\n data() {\n return {\n cards: [],\n index: 0,\n refresh_: 0\n };\n },\n props: {\n cardSelector: {\n type: String,\n default: ''\n },\n containerClass: {\n type: String,\n default: ''\n },\n buttonClass: {\n type: String,\n default: 'button'\n },\n leftButtonIcon: {\n type: String,\n default: \"fas fa-chevron-left\"\n },\n rightButtonIcon: {\n type: String,\n default: \"fas fa-chevron-right\"\n }\n },\n computed: {\n card() {\n return this.cards()[this.index];\n },\n showPrevButton() {\n return this.index > 0;\n },\n showNextButton() {\n if (!this.cards || this.cards.length <= 1) return false;\n let {\n count\n } = this.visibility;\n return this.index + count < this.cards.length;\n },\n visibility() {\n // force refresh on index\n [this.index, this.refresh_];\n if (!this.cards) return {\n min: -1,\n max: -1,\n count: 0\n };\n const vOff = this.offset(this.$refs.viewport);\n var [min, max] = [-1, -1];\n for (let at = 0; at < this.cards.length; at++) {\n const card = this.cards[at];\n const cOff = this.offset(card);\n const visible = vOff.min <= cOff.min && vOff.max >= cOff.max;\n if (visible) {\n if (min === -1) min = parseInt(at);\n max = parseInt(at);\n }\n }\n if (max !== -1) max++;\n return {\n min,\n max,\n count: min !== -1 ? max - min : 0\n };\n }\n },\n methods: {\n offset(el, parent = null) {\n const rect = el.getBoundingClientRect();\n const off = {\n min: rect.left,\n max: rect.right\n };\n if (parent === null) return off;\n const pOff = this.offset(parent);\n return {\n min: off.min - pOff.min,\n max: off.max - pOff.max\n };\n },\n getCards() {\n if (!this.cardSelector) return this.$refs.container.children;\n return this.$refs.container.querySelectorAll(this.cardSelector);\n },\n selectIndex(index, relative = false) {\n if (relative) index = this.index + index;\n index = Math.min(this.cards.length, index);\n const el = this.cards[index];\n const elOff = this.offset(el, this.$refs.container);\n this.$refs.container.style.marginLeft = `-${elOff.min}px`;\n this.index = index;\n return el;\n },\n next() {\n if (!this.visibility.count) return;\n let {\n count\n } = this.visibility;\n let at = Math.min(count === 1 ? this.index + count : this.index + count - 1, this.cards.length - count);\n this.selectIndex(at);\n },\n prev() {\n if (!this.visibility.count) return;\n const {\n min,\n count\n } = this.visibility;\n let at = Math.max(0, min - count);\n if (min < 0 || count <= 0) return;\n this.selectIndex(at);\n },\n refresh() {\n this.cards = this.getCards();\n this.selectIndex(this.index);\n this.refresh_++;\n }\n },\n mounted() {\n this.observer = [new MutationObserver(() => this.refresh()), new ResizeObserver(() => this.refresh())];\n this.observer[0].observe(this.$refs.container, {\n \"childList\": true\n });\n this.observer[1].observe(this.$refs.container);\n this.refresh();\n },\n unmounted() {\n for (var observer of this.observers) observer.disconnect();\n }\n});\n\n//# sourceURL=webpack://aircox-assets/./src/components/ACarousel.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D");
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm-bundler.js\");\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n setup() {\n return {\n viewport: (0,vue__WEBPACK_IMPORTED_MODULE_0__.ref)(null),\n container: (0,vue__WEBPACK_IMPORTED_MODULE_0__.ref)(null)\n };\n },\n data() {\n return {\n cards: [],\n index: 0,\n refresh_: 0\n };\n },\n props: {\n cardSelector: {\n type: String,\n default: ''\n },\n containerClass: {\n type: String,\n default: ''\n },\n buttonClass: {\n type: String,\n default: 'button'\n },\n leftButtonIcon: {\n type: String,\n default: \"fas fa-chevron-left\"\n },\n rightButtonIcon: {\n type: String,\n default: \"fas fa-chevron-right\"\n }\n },\n computed: {\n card() {\n return this.cards()[this.index];\n },\n showPrevButton() {\n return this.index > 0;\n },\n showNextButton() {\n if (!this.cards || this.cards.length <= 1) return false;\n let {\n count\n } = this.visibility;\n return this.index + count < this.cards.length;\n },\n visibility() {\n // force refresh on index\n [this.index, this.refresh_];\n if (!this.cards) return {\n min: -1,\n max: -1,\n count: 0\n };\n const vOff = this.offset(this.$refs.viewport);\n var [min, max] = [-1, -1];\n for (let at = 0; at < this.cards.length; at++) {\n const card = this.cards[at];\n const cOff = this.offset(card);\n const visible = vOff.min <= cOff.min && vOff.max >= cOff.max;\n if (visible) {\n if (min === -1) min = parseInt(at);\n max = parseInt(at);\n }\n }\n if (max !== -1) max++;\n return {\n min,\n max,\n count: min !== -1 ? max - min : 0\n };\n }\n },\n methods: {\n offset(el, parent = null) {\n const rect = el.getBoundingClientRect();\n const off = {\n min: rect.left,\n max: rect.right\n };\n if (parent === null) return off;\n const pOff = this.offset(parent);\n return {\n min: off.min - pOff.min,\n max: off.max - pOff.max\n };\n },\n getCards() {\n if (!this.$refs.container) return [];\n if (!this.cardSelector) return this.$refs.container.children;\n return this.$refs.container.querySelectorAll(this.cardSelector);\n },\n selectIndex(index, relative = false) {\n if (relative) index = this.index + index;\n index = Math.min(this.cards.length, index);\n const el = this.cards[index];\n if (!el) return null;\n const elOff = this.offset(el, this.$refs.container);\n this.$refs.container.style.marginLeft = `-${elOff.min}px`;\n this.index = index;\n return el;\n },\n next() {\n this.refresh_++;\n if (!this.visibility.count) return;\n let {\n count\n } = this.visibility;\n let at = Math.min(count === 1 ? this.index + count : this.index + count - 1, this.cards.length - count);\n this.selectIndex(at);\n },\n prev() {\n this.refresh_++;\n if (!this.visibility.count) return;\n const {\n min,\n count\n } = this.visibility;\n let at = Math.max(0, min - count);\n if (min < 0 || count <= 0) return;\n this.selectIndex(at);\n },\n refresh() {\n this.cards = this.getCards();\n this.selectIndex(this.index);\n this.refresh_++;\n }\n },\n mounted() {\n this.observers = [new MutationObserver(() => this.refresh()), new ResizeObserver(() => this.refresh())];\n this.observers[0].observe(this.$refs.container, {\n \"childList\": true\n });\n this.observers[1].observe(this.$refs.container);\n this.refresh();\n },\n unmounted() {\n for (var observer of this.observers) observer.disconnect();\n }\n});\n\n//# sourceURL=webpack://aircox-assets/./src/components/ACarousel.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D");
/***/ }),
@ -195,7 +195,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
\***********************************************************************************************************************************************************************************************************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* binding */ render; }\n/* harmony export */ });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm-bundler.js\");\n\nconst _withScopeId = n => ((0,vue__WEBPACK_IMPORTED_MODULE_0__.pushScopeId)(\"data-v-b79f173e\"), n = n(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.popScopeId)(), n);\nconst _hoisted_1 = {\n key: 0,\n class: \"a-carousel-button-container\"\n};\nconst _hoisted_2 = {\n class: \"icon\"\n};\nconst _hoisted_3 = {\n key: 1,\n class: \"a-carousel-button-container\"\n};\nconst _hoisted_4 = {\n class: \"icon\"\n};\nconst _hoisted_5 = {\n ref: \"viewport\",\n class: \"a-carousel-viewport\"\n};\nfunction render(_ctx, _cache, $props, $setup, $data, $options) {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, [$options.showPrevButton ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_1, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([$props.buttonClass, 'prev']),\n \"aria-label\": \"Go left\",\n onClick: _cache[0] || (_cache[0] = (...args) => $options.prev && $options.prev(...args))\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"i\", {\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)($props.leftButtonIcon)\n }, null, 2 /* CLASS */)])], 2 /* CLASS */)])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), $options.showNextButton ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_3, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([$props.buttonClass, 'next']),\n \"aria-label\": \"Go left\",\n onClick: _cache[1] || (_cache[1] = (...args) => $options.next && $options.next(...args))\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", _hoisted_4, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"i\", {\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)($props.rightButtonIcon)\n }, null, 2 /* CLASS */)])], 2 /* CLASS */)])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_5, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"section\", {\n ref: \"container\",\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(['a-carousel-container', $props.containerClass])\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, \"default\", {}, undefined, true)], 2 /* CLASS */)], 512 /* NEED_PATCH */)], 64 /* STABLE_FRAGMENT */);\n}\n\n//# sourceURL=webpack://aircox-assets/./src/components/ACarousel.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/templateLoader.js??ruleSet%5B1%5D.rules%5B3%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D");
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* binding */ render; }\n/* harmony export */ });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm-bundler.js\");\n\nconst _withScopeId = n => ((0,vue__WEBPACK_IMPORTED_MODULE_0__.pushScopeId)(\"data-v-b79f173e\"), n = n(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.popScopeId)(), n);\nconst _hoisted_1 = {\n class: \"a-carousel\"\n};\nconst _hoisted_2 = {\n key: 0,\n class: \"a-carousel-button-container\"\n};\nconst _hoisted_3 = {\n class: \"icon\"\n};\nconst _hoisted_4 = {\n key: 1,\n class: \"a-carousel-button-container\"\n};\nconst _hoisted_5 = {\n class: \"icon\"\n};\nconst _hoisted_6 = {\n ref: \"viewport\",\n class: \"a-carousel-viewport\"\n};\nfunction render(_ctx, _cache, $props, $setup, $data, $options) {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"section\", _hoisted_1, [$options.showPrevButton ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"nav\", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([$props.buttonClass, 'prev']),\n \"aria-label\": \"Go left\",\n onClick: _cache[0] || (_cache[0] = (...args) => $options.prev && $options.prev(...args))\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", _hoisted_3, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"i\", {\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)($props.leftButtonIcon)\n }, null, 2 /* CLASS */)])], 2 /* CLASS */)])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), $options.showNextButton ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_4, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([$props.buttonClass, 'next']),\n \"aria-label\": \"Go left\",\n onClick: _cache[1] || (_cache[1] = (...args) => $options.next && $options.next(...args))\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", _hoisted_5, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"i\", {\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)($props.rightButtonIcon)\n }, null, 2 /* CLASS */)])], 2 /* CLASS */)])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"nav\", _hoisted_6, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"section\", {\n ref: \"container\",\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(['a-carousel-container', $props.containerClass])\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, \"default\", {}, undefined, true)], 2 /* CLASS */)], 512 /* NEED_PATCH */)]);\n}\n\n//# sourceURL=webpack://aircox-assets/./src/components/ACarousel.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/templateLoader.js??ruleSet%5B1%5D.rules%5B3%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D");
/***/ }),

View File

@ -23,7 +23,7 @@
</div>
<a-carousel section-class="card-grid">
{% for obj in next_diffs|slice:"1:4" %}
{% for obj in next_diffs|slice:"1:" %}
{% if object != diffusion %}
{% page_widget "card" obj.episode diffusion=obj timetable=True %}
{% endif %}

View File

@ -13,7 +13,7 @@ class HomeView(AttachedToMixin, BaseView, ListView):
attach_to_value = StaticPage.ATTACH_TO_HOME
model = Diffusion
queryset = Diffusion.objects.on_air().select_related("episode").order_by("-start")
logs_count = 5
diffusion_count = 7
publications_count = 7
def get_queryset(self):
@ -23,12 +23,12 @@ class HomeView(AttachedToMixin, BaseView, ListView):
today = date.today()
# diffs = Diffusion.objects.on_air().date(today)
object_list = self.object_list
diffs = list(object_list[: self.logs_count])
diffs = list(object_list[: self.diffusion_count])
logs = Log.objects.on_air().date(today).filter(track__isnull=False)
if diffs:
min_date = diffs[-1].start - timedelta(hours=1)
logs = logs.after(min_date)
return Log.merge_diffusions(logs, object_list, diff_count=self.logs_count)
return Log.merge_diffusions(logs, object_list, diff_count=self.diffusion_count)
def get_next_diffs(self):
now = tz.now()
@ -38,7 +38,7 @@ class HomeView(AttachedToMixin, BaseView, ListView):
if current_diff:
diffs = [current_diff] + list(next_diffs.exclude(pk=current_diff.pk)[:9])
else:
diffs = next_diffs[:10]
diffs = next_diffs[: self.diffusion_count]
return diffs
def get_last_publications(self):

View File

@ -665,6 +665,7 @@ nav li {
& .headings {
width: var(--preview-cover-size);
min-width: var(--preview-cover-size);
flex-grow: 0;
margin-right: $mp-4;
}
@ -751,6 +752,10 @@ nav li {
gap: $mp-4;
}
.a-carousel {
padding-bottom: $text-size-medium;
}
.a-carousel-container {
width: 100%;
gap: $mp-4;

View File

@ -1,29 +1,35 @@
<template>
<div class="a-carousel-button-container" v-if="showPrevButton">
<button :class="[buttonClass, 'prev']" aria-label="Go left" @click="prev">
<span class="icon">
<i :class="leftButtonIcon"></i>
</span>
</button>
</div>
<div class="a-carousel-button-container" v-if="showNextButton">
<button :class="[buttonClass, 'next']" aria-label="Go left" @click="next">
<span class="icon">
<i :class="rightButtonIcon"></i>
</span>
</button>
</div>
<div ref="viewport" class="a-carousel-viewport">
<section ref="container" :class="['a-carousel-container', containerClass]">
<slot name="default"></slot>
</section>
</div>
<section class="a-carousel">
<nav class="a-carousel-button-container" v-if="showPrevButton">
<button :class="[buttonClass, 'prev']" aria-label="Go left" @click="prev">
<span class="icon">
<i :class="leftButtonIcon"></i>
</span>
</button>
</nav>
<div class="a-carousel-button-container" v-if="showNextButton">
<button :class="[buttonClass, 'next']" aria-label="Go left" @click="next">
<span class="icon">
<i :class="rightButtonIcon"></i>
</span>
</button>
</div>
<nav ref="viewport" class="a-carousel-viewport">
<section ref="container" :class="['a-carousel-container', containerClass]">
<slot name="default"></slot>
</section>
</nav>
</section>
</template>
<style scoped>
.a-carousel {
width: 100%;
position: relative;
}
.a-carousel-viewport {
width: 100%;
overflow: hidden;
position: relative;
}
.a-carousel-container {
@ -120,6 +126,8 @@ export default {
},
getCards() {
if(!this.$refs.container)
return []
if(!this.cardSelector)
return this.$refs.container.children
return this.$refs.container.querySelectorAll(this.cardSelector)
@ -131,6 +139,8 @@ export default {
index = Math.min(this.cards.length, index)
const el = this.cards[index]
if(!el)
return null;
const elOff = this.offset(el, this.$refs.container)
this.$refs.container.style.marginLeft = `-${elOff.min}px`
this.index = index;
@ -138,6 +148,8 @@ export default {
},
next() {
this.refresh_++
if(!this.visibility.count)
return
let {count} = this.visibility
@ -149,6 +161,8 @@ export default {
},
prev() {
this.refresh_++
if(!this.visibility.count)
return
const {min, count} = this.visibility
@ -167,12 +181,12 @@ export default {
mounted() {
this.observer = [
this.observers = [
new MutationObserver(() => this.refresh()),
new ResizeObserver(() => this.refresh())
]
this.observer[0].observe(this.$refs.container, {"childList": true})
this.observer[1].observe(this.$refs.container)
this.observers[0].observe(this.$refs.container, {"childList": true})
this.observers[1].observe(this.$refs.container)
this.refresh()
},