diff --git a/aircox_cms/models.py b/aircox_cms/models.py
index 94b4390..3b6d92b 100755
--- a/aircox_cms/models.py
+++ b/aircox_cms/models.py
@@ -444,10 +444,10 @@ class ProgramPage(Publication):
class Track(aircox.models.Track,Orderable):
- sort_order_field = 'position'
-
diffusion = ParentalKey('DiffusionPage',
related_name='tracks')
+
+ sort_order_field = 'position'
panels = [
FieldPanel('artist'),
FieldPanel('title'),
diff --git a/aircox_cms/sections.py b/aircox_cms/sections.py
index 64cec6c..1e79bfe 100755
--- a/aircox_cms/sections.py
+++ b/aircox_cms/sections.py
@@ -470,6 +470,74 @@ class DatedListBase(models.Model):
}
+class TemplateMixinMeta(models.base.ModelBase):
+ """
+ Metaclass for SectionItem, assigning needed values such as `template`.
+
+ It needs to load the item's template if the section uses the default
+ one, and throw error if there is an error in the template.
+ """
+ def __new__(cls, name, bases, attrs):
+ from django.template.loader import get_template
+ from django.template import TemplateDoesNotExist
+
+ cl = super().__new__(cls, name, bases, attrs)
+ if not hasattr(cl, '_meta'):
+ return cl
+
+ if not 'template' in attrs:
+ cl.snake_name = camelcase_to_underscore(name)
+ cl.template = '{}/sections/{}.html'.format(
+ cl._meta.app_label,
+ cl.snake_name,
+ )
+ if name != 'SectionItem':
+ try:
+ get_template(cl.template)
+ except TemplateDoesNotExist:
+ cl.template = 'aircox_cms/sections/section_item.html'
+ return cl
+
+
+class TemplateMixin(metaclass=TemplateMixinMeta):
+ def get_context(self, request, page):
+ """
+ Default context attributes:
+ * self: section being rendered
+ * page: current page being rendered
+ * request: request used to render the current page
+
+ Other context attributes usable in the default template:
+ * content: **safe string** set as content of the section
+ * hide: DO NOT render the section, render only an empty string
+ """
+ return {
+ 'self': self,
+ 'page': page,
+ 'request': request,
+ }
+
+ def render(self, request, page, context, *args, **kwargs):
+ """
+ Render the section. Page is the current publication being rendered.
+
+ Rendering is similar to pages, using 'template' attribute set
+ by default to the app_label/sections/model_name_snake_case.html
+
+ If the default template is not found, use SectionItem's one,
+ that can have a context attribute 'content' that is used to render
+ content.
+ """
+ context_ = self.get_context(request, *args, page=page, **kwargs)
+ if context:
+ context_.update(context)
+
+ if context.get('hide'):
+ return ''
+ return render_to_string(self.template, context_)
+
+
+
#
# Sections
#
@@ -564,33 +632,8 @@ class Section(ClusterableModel):
return '{}: {}'.format(self.__class__.__name__, self.name or self.pk)
-class SectionItemMeta(models.base.ModelBase):
- """
- Metaclass for SectionItem, assigning needed values such as `template`.
-
- It needs to load the item's template if the section uses the default
- one, and throw error if there is an error in the template.
- """
- def __new__(cls, name, bases, attrs):
- from django.template.loader import get_template
- from django.template import TemplateDoesNotExist
-
- cl = super().__new__(cls, name, bases, attrs)
- if not 'template' in attrs:
- cl.snake_name = camelcase_to_underscore(name)
- cl.template = '{}/sections/{}.html'.format(
- cl._meta.app_label,
- cl.snake_name,
- )
- if name != 'SectionItem':
- try:
- get_template(cl.template)
- except TemplateDoesNotExist:
- cl.template = 'aircox_cms/sections/section_item.html'
- return cl
-
@register_snippet
-class SectionItem(models.Model,metaclass=SectionItemMeta):
+class SectionItem(models.Model,TemplateMixin):
"""
Base class for a section item.
"""
@@ -645,42 +688,6 @@ class SectionItem(models.Model,metaclass=SectionItemMeta):
self.real_type = type(self).__name__.lower()
return super().save(*args, **kwargs)
- def get_context(self, request, page):
- """
- Default context attributes:
- * self: section being rendered
- * page: current page being rendered
- * request: request used to render the current page
-
- Other context attributes usable in the default template:
- * content: **safe string** set as content of the section
- * hide: DO NOT render the section, render only an empty string
- """
- return {
- 'self': self,
- 'page': page,
- 'request': request,
- }
-
- def render(self, request, page, context, *args, **kwargs):
- """
- Render the section. Page is the current publication being rendered.
-
- Rendering is similar to pages, using 'template' attribute set
- by default to the app_label/sections/model_name_snake_case.html
-
- If the default template is not found, use SectionItem's one,
- that can have a context attribute 'content' that is used to render
- content.
- """
- context_ = self.get_context(request, *args, page=page, **kwargs)
- if context:
- context_.update(context)
-
- if context.get('hide'):
- return ''
- return render_to_string(self.template, context_)
-
def __str__(self):
return '{}: {}'.format(
(self.real_type or 'section item').replace('section','section '),
@@ -808,12 +815,14 @@ class SectionLinkList(ClusterableModel, SectionItem):
InlinePanel('links', label=_('Links')),
]
+
@register_snippet
-class SectionLink(RelatedLinkBase):
+class SectionLink(RelatedLinkBase,TemplateMixin):
"""
Render a link to a page or a given url.
Can either be used standalone or in a SectionLinkList
"""
+ template = 'aircox_cms/snippets/link.html'
parent = ParentalKey(
'SectionLinkList', related_name = 'links',
null = True
diff --git a/aircox_cms/static/aircox_cms/css/layout.css b/aircox_cms/static/aircox_cms/css/layout.css
index 69815ea..b6fabb8 100755
--- a/aircox_cms/static/aircox_cms/css/layout.css
+++ b/aircox_cms/static/aircox_cms/css/layout.css
@@ -62,30 +62,65 @@ ul {
/** content: menus **/
-nav.menu {
+.menu {
padding: 0.4em;
}
-.menu.top {
- padding: 0.2em;
- height: 2.5em;
- margin-bottom: 1em;
- background-color: white;
- box-shadow: 0em 0em 0.2em black;
-}
- .menu.top * {
- vertical-align: bottom;
+ body > .top *,
+ body > .header * {
+ vertical-align: middle;
}
- .menu.top > section {
+ body > .top section,
+ body > .header section {
display: inline-block;
}
- .menu.top a {
+ body > .top a,
+ body > .header a {
display: inline-block;
margin: 0.2em 1em;
}
+
+body > .top {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: calc(100% - 0.8em);
+ height: 2.5em;
+ background-color: white;
+ box-shadow: 0em 0em 0.2em black;
+ transition: opacity 1.5s;
+}
+
+ body[scrollY] > .top {
+ opacity: 0.1;
+ transition: opacity 1.5s 1s;
+ }
+
+ body > .top:hover {
+ opacity: 1.0;
+ transition: opacity 1.5s;
+ }
+
+
+body > .header {
+ overflow: hidden;
+ margin-top: 3.3em;
+ margin-bottom: 1em;
+}
+
+ body > .header > div {
+ width: 15000%;
+ }
+
+ body > .header > div > section {
+ margin: 0;
+ margin-right: -0.4em;
+ }
+
+
.page_left, .page_right {
max-width: 16em;
}
diff --git a/aircox_cms/static/aircox_cms/css/theme.css b/aircox_cms/static/aircox_cms/css/theme.css
index 11d9467..01d2ef3 100755
--- a/aircox_cms/static/aircox_cms/css/theme.css
+++ b/aircox_cms/static/aircox_cms/css/theme.css
@@ -108,10 +108,8 @@ main.detail {
}
main.detail > header h1.title {
- position: relative;
width: calc(70% - 0.8em);
margin: 0em;
- margin-bottom: -2em;
padding: 0.4em;
background-color: rgba(255,255,255,0.8);
}
@@ -125,7 +123,6 @@ main.detail {
main.detail header .summary {
display: inline-block;
padding: 1em;
- width: calc(20% - 2em);
vertical-align: middle;
font-size: 1.2em;
font-weight: bold;
diff --git a/aircox_cms/templates/aircox_cms/base_site.html b/aircox_cms/templates/aircox_cms/base_site.html
index 5a5f8f6..c06b27e 100755
--- a/aircox_cms/templates/aircox_cms/base_site.html
+++ b/aircox_cms/templates/aircox_cms/base_site.html
@@ -25,6 +25,7 @@
{% block css_extras %}{% endblock %}
{% endblock %}
+
@@ -36,7 +37,9 @@