clean-up css; related publications; pagination

This commit is contained in:
bkfox 2023-11-26 21:35:37 +01:00
parent d075fecbce
commit bc697bd4bd
15 changed files with 564 additions and 1672 deletions

File diff suppressed because it is too large Load Diff

View File

@ -285,7 +285,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
\************************************************************************************************************************************************************************************************************************************************************************/ \************************************************************************************************************************************************************************************************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /***/ (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 _hoisted_1 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", {\n class: \"icon mr-3\"\n}, [/*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"i\", {\n class: \"fa fa-play\"\n})], -1 /* HOISTED */);\nconst _hoisted_2 = {\n class: \"button-group actions\"\n};\nconst _hoisted_3 = [\"href\"];\nconst _hoisted_4 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", {\n class: \"icon is-small\"\n}, [/*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"i\", {\n class: \"fa fa-external-link\"\n})], -1 /* HOISTED */);\nconst _hoisted_5 = [_hoisted_4];\nconst _hoisted_6 = [\"href\"];\nconst _hoisted_7 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", {\n class: \"icon is-small\"\n}, [/*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", {\n class: \"fa fa-download\"\n})], -1 /* HOISTED */);\nconst _hoisted_8 = [_hoisted_7];\nconst _hoisted_9 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", {\n class: \"icon is-small\"\n}, [/*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", {\n class: \"fa fa-star\"\n})], -1 /* HOISTED */);\nconst _hoisted_10 = [_hoisted_9];\nfunction render(_ctx, _cache, $props, $setup, $data, $options) {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", {\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(['a-sound-item m-0 button-group', $options.playing && 'playing' || ''])\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, \"title\", {\n player: $props.player,\n item: $options.item,\n loaded: $options.loaded\n }, () => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", {\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(['title is-flex-grow-1', $options.playing && 'blink' || '']),\n onClick: _cache[0] || (_cache[0] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($event => _ctx.$emit('togglePlay'), [\"stop\"]))\n }, [_hoisted_1, (0,vue__WEBPACK_IMPORTED_MODULE_0__.createTextVNode)(\" \" + (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.name || $options.item.name), 1 /* TEXT */)], 2 /* CLASS */)]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_2, [$options.hasAction('page') ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"a\", {\n key: 0,\n class: \"button\",\n href: $options.item.data.page_url\n }, _hoisted_5, 8 /* PROPS */, _hoisted_3)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), $options.item.data.is_downloadable ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"a\", {\n key: 1,\n class: \"button\",\n href: $options.item.data.url,\n target: \"_blank\"\n }, _hoisted_8, 8 /* PROPS */, _hoisted_6)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), $props.player && $props.player.sets.pin != _ctx.$parent.set ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"button\", {\n key: 2,\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(['button', $options.pinned ? 'selected' : 'not-selected']),\n onClick: _cache[1] || (_cache[1] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($event => $props.player.togglePin($options.item), [\"stop\"]))\n }, _hoisted_10, 2 /* CLASS */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, \"actions\", {\n player: $props.player,\n item: $options.item,\n loaded: $options.loaded\n })]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, \"extra-right\", {\n player: $props.player,\n item: $options.item,\n loaded: $options.loaded\n })], 2 /* CLASS */);\n}\n\n//# sourceURL=webpack://aircox-assets/./src/components/ASoundItem.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 _hoisted_1 = {\n class: \"button-group actions\"\n};\nconst _hoisted_2 = [\"href\"];\nconst _hoisted_3 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", {\n class: \"icon is-small\"\n}, [/*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"i\", {\n class: \"fa fa-external-link\"\n})], -1 /* HOISTED */);\nconst _hoisted_4 = [_hoisted_3];\nconst _hoisted_5 = [\"href\"];\nconst _hoisted_6 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", {\n class: \"icon is-small\"\n}, [/*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", {\n class: \"fa fa-download\"\n})], -1 /* HOISTED */);\nconst _hoisted_7 = [_hoisted_6];\nconst _hoisted_8 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", {\n class: \"icon is-small\"\n}, [/*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", {\n class: \"fa fa-star\"\n})], -1 /* HOISTED */);\nconst _hoisted_9 = [_hoisted_8];\nfunction render(_ctx, _cache, $props, $setup, $data, $options) {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", {\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(['a-sound-item m-0 button-group', $options.playing && 'playing' || ''])\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, \"title\", {\n player: $props.player,\n item: $options.item,\n loaded: $options.loaded\n }, () => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", {\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(['title is-flex-grow-1 align-left', $options.playing && 'blink' || '']),\n onClick: _cache[0] || (_cache[0] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($event => _ctx.$emit('togglePlay'), [\"stop\"]))\n }, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.name || $options.item.name), 3 /* TEXT, CLASS */)]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_1, [$options.hasAction('page') ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"a\", {\n key: 0,\n class: \"button action\",\n href: $options.item.data.page_url\n }, _hoisted_4, 8 /* PROPS */, _hoisted_2)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), $options.item.data.is_downloadable ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"a\", {\n key: 1,\n class: \"button action\",\n href: $options.item.data.url,\n target: \"_blank\"\n }, _hoisted_7, 8 /* PROPS */, _hoisted_5)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), $props.player && $props.player.sets.pin != _ctx.$parent.set ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"button\", {\n key: 2,\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(['button action', $options.pinned ? 'selected' : 'not-selected']),\n onClick: _cache[1] || (_cache[1] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($event => $props.player.togglePin($options.item), [\"stop\"]))\n }, _hoisted_9, 2 /* CLASS */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, \"actions\", {\n player: $props.player,\n item: $options.item,\n loaded: $options.loaded\n })]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, \"extra-right\", {\n player: $props.player,\n item: $options.item,\n loaded: $options.loaded\n })], 2 /* CLASS */);\n}\n\n//# sourceURL=webpack://aircox-assets/./src/components/ASoundItem.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

@ -48,41 +48,30 @@
<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="{% translate "pagination" %}"> <nav class="nav-urls is-centered" role="pagination" aria-label="{% translate "pagination" %}">
{% block 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="left button">
{% else %}
<a class="pagination-previous" disabled>
{% endif %}
{% comment %}Translators: Bottom of the list, "previous page"{% endcomment %} {% comment %}Translators: Bottom of the list, "previous page"{% endcomment %}
{% translate "Previous" %}</a> {% translate "Previous" %}</a>
{% if page_obj.has_next %}
<a href="?{{ GET }}&page={{ page_obj.next_page_number }}" class="pagination-next">
{% else %}
<a class="pagination-next" disabled>
{% endif %} {% endif %}
{% comment %}Translators: Bottom of the list, "Nextpage"{% endcomment %}
{% translate "Next" %}</a>
<ul class="pagination-list"> <ul class="urls">
{% for i in paginator.page_range %} {% for i in paginator.page_range %}
<li> <li>
{% comment %} <a class="button {% if page_obj.number == i %}active{% endif %}"
<form action="?{{ GET }}">
{% for get in GET %}
<input type="hidden" name="{{ get.0 }}" value="{{ get.1 }}" />
{% endfor %}
<input type="number" name="page" value="{{ page_obj.number }}" />
</form>
{% endcomment %}
<a class="pagination-link {% if page_obj.number == i %}is-current{% endif %}"
href="?{{ GET }}&page={{ i }}">{{ i }}</a> href="?{{ GET }}&page={{ i }}">{{ i }}</a>
</li> </li>
{% endfor %} {% endfor %}
</ul> </ul>
{% endblock %} {% endblock %}
{% if page_obj.has_next %}
<a href="?{{ GET }}&page={{ page_obj.next_page_number }}" class="right button">
{% comment %}Translators: Bottom of the list, "Nextpage"{% endcomment %}
{% translate "Next" %}</a>
{% endif %}
</nav> </nav>
{% endwith %} {% endwith %}
{% endif %} {% endif %}

View File

@ -39,7 +39,7 @@
{% include "./widgets/log.html" with widget="item" %} {% include "./widgets/log.html" with widget="item" %}
{% endfor %} {% endfor %}
<nav class="list-urls"> <nav class="nav-urls">
<a href="{% url "diffusion-list" %}" <a href="{% url "diffusion-list" %}"
aria-label="{% translate "Show all program's for today" %}"> aria-label="{% translate "Show all program's for today" %}">
{% translate "Today" %} {% translate "Today" %}
@ -58,7 +58,7 @@
{% endfor %} {% endfor %}
</div> </div>
<nav class="list-urls"> <nav class="nav-urls">
<a href="{% url "page-list" %}" <a href="{% url "page-list" %}"
aria-label="{% translate "Show all publications" %}"> aria-label="{% translate "Show all publications" %}">
{% translate "All publications" %} {% translate "All publications" %}

View File

@ -6,6 +6,8 @@ Base template used to display a Page
Context: Context:
- page: page - page: page
- parent: parent page - parent: parent page
- related_objects: list of object to display as related publications
- related_url: url to the full list of related_objects
{% endcomment %} {% endcomment %}
{% block header_crumbs %} {% block header_crumbs %}
@ -31,6 +33,29 @@ Context:
{% block main %} {% block main %}
{{ block.super }} {{ block.super }}
{% block related %}
{% if related_objects %}
<section class="container">
{% with models=object|verbose_name:True %}
<h3 class="title is-3">{% blocktranslate %}Related {{models}}{% endblocktranslate %}</h3>
{% endwith %}
<section class="card-grid">
{% for object in related_objects %}
{% page_widget "card" object %}
{% endfor %}
</section>
{% if related_url %}
<nav class="nav-urls">
<a href="{{ related_url }}">
{% translate "See more" %}
</a>
</nav>
{% endif %}
{% endif %}
{% endblock %}
{% block comments %} {% block comments %}
{% if comments %} {% if comments %}
<section class="container"> <section class="container">
@ -46,8 +71,8 @@ Context:
{% if comment_form %} {% if comment_form %}
<section class="container"> <section class="container">
<form method="POST">
<h2 class="title">{% translate "Post a comment" %}</h2> <h2 class="title">{% translate "Post a comment" %}</h2>
<form method="POST">
{% csrf_token %} {% csrf_token %}
{% render_honeypot_field "website" %} {% render_honeypot_field "website" %}

View File

@ -5,7 +5,7 @@
{% block secondary-nav %} {% block secondary-nav %}
<form class="nav secondary"> <form class="nav secondary">
{% for id, title in view.categories.items %} {% for id, title in view.categories.items %}
<a class="nav-item{% if category_id == id %} active{% endif %}" <a class="nav-item{% if category_id == id or parent and parent.category_id == id %} active{% endif %}"
href="?category__id={{ id }}">{{ title }}</a> href="?category__id={{ id }}">{{ title }}</a>
{% endfor %} {% endfor %}
</form> </form>

View File

@ -16,9 +16,9 @@
{% endfor %} {% endfor %}
</section> </section>
<nav class="list-urls"> <nav class="nav-urls">
<a href="{% url "episode-list" parent_slug=program.slug %}"> <a href="{% url "episode-list" parent_slug=program.slug %}">
{% translate "All episodes" %} {% translate "See more" %}
</a> </a>
</nav> </nav>
</section> </section>
@ -35,10 +35,10 @@
{% endfor %} {% endfor %}
</section> </section>
<nav class="list-urls"> <nav class="nav-urls">
<a href="{% url "article-list" parent_slug=program.slug %}" <a href="{% url "article-list" parent_slug=program.slug %}"
aria-label="{% translate "Show all program's articles" %}"> aria-label="{% translate "Show all program's articles" %}">
{% translate "All articles" %} {% translate "See more" %}
</a> </a>
</nav> </nav>
</section> </section>

View File

@ -40,7 +40,7 @@ Context variables:
<div class="actions"> <div class="actions">
{% block actions %} {% block actions %}
<a class="button btn-hg float-right" href="{{ object.get_absolute_url|escape }}"> <a class="button float-right" href="{{ object.get_absolute_url|escape }}">
<span class="icon"> <span class="icon">
<i class="fas fa-external-link"></i> <i class="fas fa-external-link"></i>
</span> </span>

View File

@ -90,7 +90,10 @@ def do_nav_items(context, menu, **kwargs):
@register.simple_tag(name="update_query") @register.simple_tag(name="update_query")
def do_update_query(obj, **kwargs): def do_update_query(obj, **kwargs):
"""Replace provided querydict's values with **kwargs.""" """Replace provided querydict's values with **kwargs.
Values set to ``None`` will be dropped.
"""
for k, v in kwargs.items(): for k, v in kwargs.items():
if v is not None: if v is not None:
obj[k] = list(v) if hasattr(v, "__iter__") else [v] obj[k] = list(v) if hasattr(v, "__iter__") else [v]
@ -103,4 +106,6 @@ def do_update_query(obj, **kwargs):
def do_verbose_name(obj, plural=False): def do_verbose_name(obj, plural=False):
"""Return model's verbose name (singular or plural) or `obj` if it is a """Return model's verbose name (singular or plural) or `obj` if it is a
string (can act for default values).""" string (can act for default values)."""
return obj if isinstance(obj, str) else obj._meta.verbose_name_plural if plural else obj._meta.verbose_name if isinstance(obj, str):
return obj
return obj._meta.verbose_name_plural if plural else obj._meta.verbose_name

View File

@ -1,3 +1,5 @@
from django.shortcuts import reverse
from ..filters import EpisodeFilters from ..filters import EpisodeFilters
from ..models import Episode, Program, StaticPage from ..models import Episode, Program, StaticPage
from .page import PageListView from .page import PageListView
@ -17,6 +19,14 @@ class EpisodeDetailView(ProgramPageDetailView):
kwargs["tracks"] = self.object.track_set.order_by("position") kwargs["tracks"] = self.object.track_set.order_by("position")
return super().get_context_data(**kwargs) return super().get_context_data(**kwargs)
def get_related_queryset(self):
return (
self.get_queryset().parent(self.object.parent).exclude(pk=self.object.pk).published().order_by("-pub_date")
)
def get_related_url(self):
return reverse("episode-list", kwargs={"parent_slug": self.object.parent.slug})
class EpisodeListView(PageListView): class EpisodeListView(PageListView):
model = Episode model = Episode

View File

@ -119,7 +119,12 @@ class PageListView(FiltersMixin, BasePageListView):
if cat_id: if cat_id:
cat_id = int(cat_id) cat_id = int(cat_id)
kwargs["category_id"] = cat_id kwargs["category_id"] = cat_id
return super().get_context_data(**kwargs)
context = super().get_context_data(**kwargs)
if context.get("parent") and not cat_id:
kwargs["category_id"] = context["parent"].category_id
return context
class PageDetailView(BasePageDetailView): class PageDetailView(BasePageDetailView):
@ -128,6 +133,16 @@ class PageDetailView(BasePageDetailView):
template_name = None template_name = None
context_object_name = "page" context_object_name = "page"
related_count = 3
def get_related_queryset(self):
"""Return a queryset of related pages or None."""
return None
def get_related_url(self):
"""Return an url to the list of related pages."""
return None
def get_template_names(self): def get_template_names(self):
return super().get_template_names() + ["aircox/page_detail.html"] return super().get_template_names() + ["aircox/page_detail.html"]
@ -138,8 +153,16 @@ class PageDetailView(BasePageDetailView):
if self.object.allow_comments and "comment_form" not in kwargs: if self.object.allow_comments and "comment_form" not in kwargs:
kwargs["comment_form"] = CommentForm() kwargs["comment_form"] = CommentForm()
kwargs["comments"] = Comment.objects.filter(page=self.object).order_by("-date") kwargs["comments"] = Comment.objects.filter(page=self.object).order_by("-date")
if self.object.parent_subclass: if self.object.parent_subclass:
kwargs["parent"] = self.object.parent_subclass kwargs["parent"] = self.object.parent_subclass
if "related_objects" not in kwargs:
related = self.get_related_queryset()
if related:
related = related[: self.related_count]
kwargs["related_objects"] = related
kwargs["related_url"] = self.get_related_url()
return super().get_context_data(**kwargs) return super().get_context_data(**kwargs)
@classmethod @classmethod

View File

@ -1,3 +1,5 @@
import random
from django.urls import reverse from django.urls import reverse
from ..models import Article, Page, Program, StaticPage, Episode from ..models import Article, Page, Program, StaticPage, Episode
@ -23,6 +25,19 @@ class BaseProgramMixin:
class ProgramDetailView(BaseProgramMixin, PageDetailView): class ProgramDetailView(BaseProgramMixin, PageDetailView):
model = Program model = Program
def get_related_queryset(self):
queryset = (
self.get_queryset()
.filter(category_id=self.object.category_id)
.exclude(pk=self.object.pk)
.published()
.order_by("-pub_date")[:50]
)
return random.sample(list(queryset), self.related_count)
def get_related_url(self):
return reverse("program-list") + f"?category__id={self.object.category_id}"
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
episodes = Episode.objects.program(self.object).published().order_by("-pub_date") episodes = Episode.objects.program(self.object).published().order_by("-pub_date")
articles = Article.objects.parent(self.object).published().order_by("-pub_date") articles = Article.objects.parent(self.object).published().order_by("-pub_date")

View File

@ -5,21 +5,33 @@ $font-special-url: url("assets/Bagnard.otf");
$black: #000; $black: #000;
$white: #fff; $white: #fff;
$red: #e00;
$red-dark: #b00;
$green: #0e0;
$green-dark: #0b0;
$mp-1: 0.2em; $mp-1: 0.2rem;
$mp-2: 0.4em; $mp-1e: 0.2em;
$mp-3: 0.8em; $mp-2: 0.4rem;
$mp-4: 1.2em; $mp-2e: 0.4em;
$mp-5: 1.6em; $mp-3: 0.6rem;
$mp-6: 2em; $mp-3e: 0.6em;
$mp-7: 4em; $mp-4: 1.2rem;
$mp-4e: 1.2em;
$mp-5: 1.6rem;
$mp-5e: 1.6em;
$mp-6: 2rem;
$mp-6e: 2em;
$mp-7: 4rem;
$mp-7e: 4em;
$text-size-small: 0.6em; $text-size-small: 0.6rem;
$text-size-smaller: 0.8em; $text-size-smaller: 0.8rem;
$text-size: 1em; $text-size: 1rem;
$text-size-medium: 1.4em; $text-size-2: 1.2rem;
$text-size-bigger: 1.6em; $text-size-medium: 1.4rem;
$text-size-big: 2em; $text-size-bigger: 1.6rem;
$text-size-big: 2rem;
$h1-size: 40px; $h1-size: 40px;
$h2-size: 32px; $h2-size: 32px;
@ -152,10 +164,15 @@ a.navbar-item.is-active {
//-- general //-- general
:root { :root {
--text-color: black; --text-color: black;
--disabled-color: #aaa;
--disabled-bg: #eee;
--highlight-color: rgba(255, 255, 0, 1); --highlight-color: rgba(255, 255, 0, 1);
--highlight-color-alpha: rgba(255, 255, 0, 0.7); --highlight-color-alpha: rgba(255, 255, 0, 0.7);
--highlight-color-grey: rgba(230, 230, 60, 1);
--highlight-color-2: rgb(0, 0, 254); --highlight-color-2: rgb(0, 0, 254);
--highlight-color-2-alpha: rgb(0, 0, 254, 0.7); --highlight-color-2-alpha: rgb(0, 0, 254, 0.7);
--highlight-color-2-grey: rgba(50, 200, 200, 1);
--header-height: 30em; --header-height: 30em;
@ -165,10 +182,7 @@ a.navbar-item.is-active {
--heading-bg-highlight-color: var(--highlight-color-2); --heading-bg-highlight-color: var(--highlight-color-2);
--heading-font-family: default; --heading-font-family: default;
--preview-media-height: 10em; --preview-cover-size: 18em;
--preview-media-cover-size: 10em;
--preview-cover-size: 24em;
--preview-cover-small-size: 10em; --preview-cover-small-size: 10em;
--player-panel-bg: var(--highlight-color); --player-panel-bg: var(--highlight-color);
@ -182,6 +196,7 @@ a.navbar-item.is-active {
body { body {
font-size: 1.4em;
background-color: $body-background-color; background-color: $body-background-color;
} }
@ -192,13 +207,14 @@ section > .toolbar {
} }
// ---- main theme & layout
h1, h2, h3, h4, h5, h6, .heading, .title, .subtitle { h1, h2, h3, h4, h5, h6, .heading, .title, .subtitle {
font-family: var(--heading-font-family); font-family: var(--heading-font-family);
} }
// ---- main theme & layout
.page { .page {
padding-bottom: 5em; padding-bottom: 5rem;
a { a {
background-color: var(--highlight-color-alpha); background-color: var(--highlight-color-alpha);
@ -207,10 +223,6 @@ h1, h2, h3, h4, h5, h6, .heading, .title, .subtitle {
padding: $mp-2; padding: $mp-2;
} }
.content {
font-size: $text-size-big;
}
section.container { section.container {
padding-top: $mp-6; padding-top: $mp-6;
@ -229,6 +241,7 @@ h1, h2, h3, h4, h5, h6, .heading, .title, .subtitle {
// ---- helpers // ---- helpers
// -- layout
.d-inline { display: inline; } .d-inline { display: inline; }
.d-block { display: block; } .d-block { display: block; }
.d-inline-block { display: inline-block; } .d-inline-block { display: inline-block; }
@ -239,6 +252,7 @@ h1, h2, h3, h4, h5, h6, .heading, .title, .subtitle {
.p-sticky { position: sticky } .p-sticky { position: sticky }
.p-static { position: static } .p-static { position: static }
.align-left { text-align: left; justify-content: left; }
.align-right { text-align: right; justify-content: right; } .align-right { text-align: right; justify-content: right; }
.height-full { height: 100%; } .height-full { height: 100%; }
@ -247,34 +261,82 @@ h1, h2, h3, h4, h5, h6, .heading, .title, .subtitle {
.no-border { border: 0px !important; } .no-border { border: 0px !important; }
.is-clickable { cursor: pointer; } // -- colors
.is-success {
background-color: $green !important;
// ---- components border-color: $green-dark !important;
.btn-hg, .btn-outline-hg { }
border: 0.1em var(--highlight-color) solid; .is-danger {
background-color: var(--highlight-color-alpha) !important; background-color: $red !important;
border-radius: 0.2em; border-color: $red-dark !important;
}
// ---- components
.dropdown-item {
font-size: unset !important
}
.vc-weekday-1, .vc-weekday-7 {
color: var(--highlight-color-2) !important;
}
// -- buttons, forms
.button, a.button, button.button, .nav-urls a {
display: inline-block;
padding: $mp-3e;
border-radius: 4px;
border: 1px var(--highlight-color-2-alpha) solid;
justify-content: center;
text-align: center;
font-size: $text-size-medium;
background-color: var(--highlight-color);
.icon {
vertical-align: middle;
&:first-child { margin-right: $mp-3; }
&:last-child { margin-left: $mp-3 }
} }
.button {
border-radius: 0px;
border-color: var(--highlight-color-2-alpha);
&:hover { &:hover {
border-color: var(--highlight-color-2) !important; border-color: var(--highlight-color-2);
color: var(--highlight-color-2) !important; color: var(--highlight-color-2);
opacity: 1 !important; opacity: 1 !important;
} }
&.active {
border-color: var(--highlight-color-alpha);
background-color: var(--highlight-color-2);
color: var(--highlight-color);
&:hover {
border-color: var(--highlight-color);
background-color: var(--highlight-color-2-alpha);
opacity: 1 !important;
}
}
&:not([disabled]), &:not(.disabled) {
cursor: pointer;
}
&[disabled], &.disabled {
background-color: var(--highlight-color-grey);
color: var(--highlight-color-2);
border-color: var(--highlight-color-2-alpha);
}
.actions &, &.action { .actions &, &.action {
background-color: var(--highlight-color); background-color: var(--highlight-color);
justify-content: center; justify-content: center;
padding: $mp-2 !important; min-width: 2rem;
min-width: 2em;
.not-selected { opacity: 0.6; }
.icon { margin: 0em !important; } .icon { margin: 0em !important; }
.not-selected { opacity: 0.6; }
label { label {
margin-left: $mp-2; margin-left: $mp-2;
@ -298,9 +360,8 @@ h1, h2, h3, h4, h5, h6, .heading, .title, .subtitle {
border-bottom: 0px; border-bottom: 0px;
height: 100%; height: 100%;
&:last-child { &:not(:first-child) { border-left: 0px; }
border-right: 0px; &:last-child { border-right: 0px; }
}
} }
} }
@ -311,6 +372,7 @@ h1, h2, h3, h4, h5, h6, .heading, .title, .subtitle {
} }
// -- headings
.title { .title {
text-transform: uppercase; text-transform: uppercase;
@ -339,25 +401,6 @@ h1, h2, h3, h4, h5, h6, .heading, .title, .subtitle {
} }
} }
.dropdown-item {
font-size: unset !important
}
.list-urls {
margin-top: $mp-3;
text-align: right;
font-size: $text-size-medium;
a:not(:last-child) {
margin-right: $mp-3;
}
}
.vc-weekday-1, .vc-weekday-7 {
color: var(--highlight-color-2) !important;
}
// ---- main navigation // ---- main navigation
.nav { .nav {
display: flex; display: flex;
@ -385,7 +428,7 @@ h1, h2, h3, h4, h5, h6, .heading, .title, .subtitle {
padding: $mp-3; padding: $mp-3;
img { img {
width: 14em !important; width: 12rem !important;
} }
} }
@ -395,7 +438,7 @@ h1, h2, h3, h4, h5, h6, .heading, .title, .subtitle {
} }
.nav-item { .nav-item {
font-size: $text-size-medium; font-size: $text-size-2;
font-weight: $weight-bold; font-weight: $weight-bold;
} }
} }
@ -404,7 +447,7 @@ h1, h2, h3, h4, h5, h6, .heading, .title, .subtitle {
justify-content: right; justify-content: right;
.nav-item { .nav-item {
font-size: 1.2em; font-size: $text-size;
} }
} }
} }
@ -418,6 +461,46 @@ nav li {
} }
.nav-urls {
display: flex;
flex-direction: row;
margin-top: $mp-3;
text-align: right;
font-size: $text-size-medium;
> a:only-child {
margin-left: auto;
}
li {
list-style: none;
}
.urls {
flex-grow: 1;
display: flex;
flex-direction: row;
gap: $mp-3;
justify-content: center;
a:not(:last-child) {
margin-right: $mp-3;
}
}
.left {
flex-grow: 0;
text-align: left;
}
.right {
flex-grow: 0;
text-align: right;
}
}
// ---- ---- detail // ---- ---- detail
.page-content { .page-content {
margin-top: $mp-6; margin-top: $mp-6;
@ -641,8 +724,6 @@ nav li {
// -- program grid // -- program grid
.card-grid { .card-grid {
display: grid; display: grid;
grid-template-columns: 1fr 1fr 1fr; grid-template-columns: 1fr 1fr 1fr;
@ -729,7 +810,7 @@ nav li {
align-items: center; align-items: center;
flex-direction: row; flex-direction: row;
height: 3em; height: 3rem;
background-color: var(--highlight-color-alpha); background-color: var(--highlight-color-alpha);
&.playing, &.playing .title { &.playing, &.playing .title {
@ -738,21 +819,35 @@ nav li {
&:hover { &:hover {
background-color: var(--highlight-color); background-color: var(--highlight-color);
.title { .title {
color: var(--highlight-color-2) !important; color: var(--highlight-color-2) !important;
} }
} }
.title:hover::before, &.playing .title::before {
content: "\f04b";
font-family: "Font Awesome 6 Free";
margin-right: $mp-3e;
}
&.playing .title:hover::before {
content: '';
margin: 0;
}
.headings > * { .headings > * {
} }
.title { .title {
cursor: pointer;
.icon { .icon {
padding: 0em $mp-3; padding: 0em $mp-3;
} }
margin: 0em; margin: 0em;
padding: 0em; padding: $mp-3e;
font-size: $text-size-medium; font-size: $text-size-medium;
} }
.button { .button {
@ -826,20 +921,12 @@ nav li {
font-size: $text-size-bigger; font-size: $text-size-bigger;
height: 100%; height: 100%;
padding: auto 0.2em !important; padding: auto 0.2em !important;
min-width: 2.5em; min-width: 3em;
border-radius: 0px; border-radius: 0px;
transition: background-color 0.5s; transition: background-color 0.5s;
&:hover {
color: var(--highlight-color-2) !important;
}
&.active {
color: var(--highlight-color-2);
}
&.open { &.open {
background-color: var(--highlight-color-2); background-color: var(--highlight-color-2-alpha);
color: var(--highlight-color); color: var(--highlight-color);
} }
} }

View File

@ -12,14 +12,14 @@ $menu-item-active-background-color: #d2d2d2;
@import "~bulma/sass/components/media"; @import "~bulma/sass/components/media";
@import "~bulma/sass/components/message"; @import "~bulma/sass/components/message";
@import "~bulma/sass/components/modal"; @import "~bulma/sass/components/modal";
@import "~bulma/sass/components/pagination"; //@import "~bulma/sass/components/pagination";
@import "~bulma/sass/form/_all"; @import "~bulma/sass/form/_all";
@import "~bulma/sass/grid/_all"; @import "~bulma/sass/grid/_all";
@import "~bulma/sass/helpers/_all"; @import "~bulma/sass/helpers/_all";
@import "~bulma/sass/layout/_all"; @import "~bulma/sass/layout/_all";
@import "~bulma/sass/elements/box"; @import "~bulma/sass/elements/box";
@import "~bulma/sass/elements/button"; // @import "~bulma/sass/elements/button";
@import "~bulma/sass/elements/container"; @import "~bulma/sass/elements/container";
@import "~bulma/sass/elements/content"; @import "~bulma/sass/elements/content";
@import "~bulma/sass/elements/icon"; @import "~bulma/sass/elements/icon";

View File

@ -1,27 +1,24 @@
<template> <template>
<div :class="['a-sound-item m-0 button-group', playing && 'playing' || '']"> <div :class="['a-sound-item m-0 button-group', playing && 'playing' || '']">
<slot name="title" :player="player" :item="item" :loaded="loaded"> <slot name="title" :player="player" :item="item" :loaded="loaded">
<span :class="['title is-flex-grow-1', playing && 'blink' || '']" @click.stop="$emit('togglePlay')"> <span :class="['title is-flex-grow-1 align-left', playing && 'blink' || '']" @click.stop="$emit('togglePlay')">
<span class="icon mr-3">
<i class="fa fa-play"></i>
</span>
{{ name || item.name }} {{ name || item.name }}
</span> </span>
</slot> </slot>
<div class="button-group actions"> <div class="button-group actions">
<a class="button" v-if="hasAction('page')" <a class="button action" v-if="hasAction('page')"
:href="item.data.page_url"> :href="item.data.page_url">
<span class="icon is-small"> <span class="icon is-small">
<i class="fa fa-external-link"></i> <i class="fa fa-external-link"></i>
</span> </span>
</a> </a>
<a class="button" v-if="item.data.is_downloadable" <a class="button action" v-if="item.data.is_downloadable"
:href="item.data.url" target="_blank"> :href="item.data.url" target="_blank">
<span class="icon is-small"> <span class="icon is-small">
<span class="fa fa-download"></span> <span class="fa fa-download"></span>
</span> </span>
</a> </a>
<button :class="['button', pinned ? 'selected' : 'not-selected']" v-if="player && player.sets.pin != $parent.set" @click.stop="player.togglePin(item)"> <button :class="['button action', pinned ? 'selected' : 'not-selected']" v-if="player && player.sets.pin != $parent.set" @click.stop="player.togglePin(item)">
<span class="icon is-small"> <span class="icon is-small">
<span class="fa fa-star"></span> <span class="fa fa-star"></span>
</span> </span>