forked from rc/aircox
		
	work on sections
This commit is contained in:
		@ -1,10 +1,41 @@
 | 
				
			|||||||
body { padding: 0; margin: 0; }
 | 
					body {
 | 
				
			||||||
 | 
					    padding: 0;
 | 
				
			||||||
nav.menu_top {
 | 
					    margin: 0;
 | 
				
			||||||
    width: 100%
 | 
					 | 
				
			||||||
    position: absolute;
 | 
					 | 
				
			||||||
    border-bottom: 1px grey solid;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.page {
 | 
				
			||||||
 | 
					    display: flex;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .page .menu {
 | 
				
			||||||
 | 
					        width: 15em;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .page .menu_left { margin-right: 0.5em; }
 | 
				
			||||||
 | 
					    .page .menu_right { margin-left: 0.5em; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .page main {
 | 
				
			||||||
 | 
					        flex-grow: 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					main .section {
 | 
				
			||||||
 | 
					    width: calc(50% - 1em);
 | 
				
			||||||
 | 
					    float: left;
 | 
				
			||||||
 | 
					    padding: 0.5em;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    main .section .section_content {
 | 
				
			||||||
 | 
					        font-size: 0.95em;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    main .section h1 {
 | 
				
			||||||
 | 
					        font-size: 1.2em;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    main .section * {
 | 
				
			||||||
 | 
					        max-width: 100%;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										9
									
								
								aircox_cms/templates/aircox_cms/base_section.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								aircox_cms/templates/aircox_cms/base_section.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					<{{ tag }} class="section {{ classes }}"
 | 
				
			||||||
 | 
					    {% for key, value in attrs.items %}{{ key }} = "{{ value|addslashes }}"
 | 
				
			||||||
 | 
					    {% endfor %} >
 | 
				
			||||||
 | 
					{% block content %}
 | 
				
			||||||
 | 
					{{ content|safe }}
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
 | 
					</{{ tag }}>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -8,22 +8,23 @@
 | 
				
			|||||||
        <meta name="description" content="{{ website.description }}">
 | 
					        <meta name="description" content="{{ website.description }}">
 | 
				
			||||||
        <meta name="keywords" content="{{ website.tags }}">
 | 
					        <meta name="keywords" content="{{ website.tags }}">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <link rel="stylesheet" href="{% static "aircox_aircox_cms/styles.css" %}" type="text/css">
 | 
					        <link rel="stylesheet" href="{% static "aircox_cms/styles.css" %}" type="text/css">
 | 
				
			||||||
 | 
					        {% if website.styles %}
 | 
				
			||||||
 | 
					        <link rel="stylesheet" href="{% static website.styles %}" type="text/css">
 | 
				
			||||||
 | 
					        {% endif %}
 | 
				
			||||||
        <title>{{ website.name }} {% if title %}- {{ title }} {% endif %}</title>
 | 
					        <title>{{ website.name }} {% if title %}- {{ title }} {% endif %}</title>
 | 
				
			||||||
    </head>
 | 
					    </head>
 | 
				
			||||||
    <body>
 | 
					    <body>
 | 
				
			||||||
 | 
					        {% block header %}
 | 
				
			||||||
 | 
					            {% if menus.header %}
 | 
				
			||||||
 | 
					            {{ menus.header|safe }}
 | 
				
			||||||
 | 
					            {% endif %}
 | 
				
			||||||
 | 
					        {% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        {% if menus.top %}
 | 
					        {% if menus.top %}
 | 
				
			||||||
            {{ menus.top|safe }}
 | 
					            {{ menus.top|safe }}
 | 
				
			||||||
        {% endif %}
 | 
					        {% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        {% block header %}
 | 
					 | 
				
			||||||
            {% if menus.header %}
 | 
					 | 
				
			||||||
            <header>
 | 
					 | 
				
			||||||
                {{ menus.header|safe }}
 | 
					 | 
				
			||||||
            </header>
 | 
					 | 
				
			||||||
            {% endif %}
 | 
					 | 
				
			||||||
        {% endblock %}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        <div class="page">
 | 
					        <div class="page">
 | 
				
			||||||
            {% if menus.left %}
 | 
					            {% if menus.left %}
 | 
				
			||||||
                {{ menus.left|safe }}
 | 
					                {{ menus.left|safe }}
 | 
				
			||||||
@ -50,11 +51,13 @@
 | 
				
			|||||||
            {% endif %}
 | 
					            {% endif %}
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        {% if menus.page_bottom %}
 | 
				
			||||||
 | 
					            {{ menus.page_bottom|safe }}
 | 
				
			||||||
 | 
					        {% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        {% block footer %}
 | 
					        {% block footer %}
 | 
				
			||||||
            {% if menus.footer %}
 | 
					            {% if menus.footer %}
 | 
				
			||||||
            <footer>
 | 
					 | 
				
			||||||
            {{ menus.footer|safe }}
 | 
					            {{ menus.footer|safe }}
 | 
				
			||||||
            </footer>
 | 
					 | 
				
			||||||
            {% endif %}
 | 
					            {% endif %}
 | 
				
			||||||
        {% endblock %}
 | 
					        {% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,10 +1,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
<nav class="menu menu_{{ position }} {{ classes }}" {% if name %}
 | 
					<{{ tag }} class="menu menu_{{ position }} {{ classes }}" {% if name %}
 | 
				
			||||||
        name="menu_{{ name }}"
 | 
					        name="{{ name }}"
 | 
				
			||||||
        id="menu_{{ name }}"
 | 
					        id="{{ name }}"
 | 
				
			||||||
    {% endif %}>
 | 
					    {% endif %}>
 | 
				
			||||||
    {% for section in sections %}
 | 
					    {% for section in sections %}
 | 
				
			||||||
    {{ section|safe }}
 | 
					    {{ section|safe }}
 | 
				
			||||||
    {% endfor %}
 | 
					    {% endfor %}
 | 
				
			||||||
</nav>
 | 
					</{{ tag }}>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,33 +1,34 @@
 | 
				
			|||||||
<div class="section {{ classes }}">
 | 
					{% extends "aircox_cms/base_section.html" %}
 | 
				
			||||||
    {% if title %}
 | 
					
 | 
				
			||||||
    <h1>
 | 
					{% block content %}
 | 
				
			||||||
 | 
					{% if title %}
 | 
				
			||||||
 | 
					<h1>
 | 
				
			||||||
    {% block section_title %}
 | 
					    {% block section_title %}
 | 
				
			||||||
    {{ title }}
 | 
					    {{ title }}
 | 
				
			||||||
    {% endblock %}
 | 
					    {% endblock %}
 | 
				
			||||||
    </h1>
 | 
					</h1>
 | 
				
			||||||
    {% endif %}
 | 
					{% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    {% if header %}
 | 
					{% if header %}
 | 
				
			||||||
    <header class="section_header">
 | 
					<header class="section_header">
 | 
				
			||||||
    {% block section_header %}
 | 
					    {% block section_header %}
 | 
				
			||||||
    {{ header }}
 | 
					    {{ header }}
 | 
				
			||||||
    {% endblock %}
 | 
					    {% endblock %}
 | 
				
			||||||
    </header>
 | 
					</header>
 | 
				
			||||||
    {% endif %}
 | 
					{% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <div class="section_content">
 | 
					<div class="section_content">
 | 
				
			||||||
    {% block section_content %}
 | 
					    {% block section_content %}
 | 
				
			||||||
    {{ content|safe }}
 | 
					    {{ content|safe }}
 | 
				
			||||||
    {% endblock %}
 | 
					    {% endblock %}
 | 
				
			||||||
    </div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    {% if bottom %}
 | 
					{% if bottom %}
 | 
				
			||||||
    <div class="section_bottom">
 | 
					<div class="section_bottom">
 | 
				
			||||||
    {% block section_bottom %}
 | 
					    {% block section_bottom %}
 | 
				
			||||||
    {{ bottom }}
 | 
					    {{ bottom }}
 | 
				
			||||||
    {% endblock %}
 | 
					    {% endblock %}
 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
    {% endif %}
 | 
					 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					{% endif %}
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,9 +1,14 @@
 | 
				
			|||||||
 | 
					import re
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from django.templatetags.static import static
 | 
				
			||||||
from django.shortcuts import render
 | 
					from django.shortcuts import render
 | 
				
			||||||
from django.template.loader import render_to_string
 | 
					from django.template.loader import render_to_string
 | 
				
			||||||
from django.views.generic import ListView, DetailView
 | 
					from django.views.generic import ListView, DetailView
 | 
				
			||||||
from django.views.generic.base import View, TemplateResponseMixin
 | 
					from django.views.generic.base import View, TemplateResponseMixin
 | 
				
			||||||
from django.core import serializers
 | 
					from django.core import serializers
 | 
				
			||||||
from django.utils.translation import ugettext as _, ugettext_lazy
 | 
					from django.utils.translation import ugettext as _, ugettext_lazy
 | 
				
			||||||
 | 
					from django.utils.html import escape
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import aircox_cms.routes as routes
 | 
					import aircox_cms.routes as routes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -29,12 +34,8 @@ class PostBaseView:
 | 
				
			|||||||
            context['menus'] = {
 | 
					            context['menus'] = {
 | 
				
			||||||
                k: v.get(self.request)
 | 
					                k: v.get(self.request)
 | 
				
			||||||
                for k, v in {
 | 
					                for k, v in {
 | 
				
			||||||
                    'top': self.website.get_menu('top'),
 | 
					                    k: self.website.get_menu(k)
 | 
				
			||||||
                    'left': self.website.get_menu('left'),
 | 
					                    for k in self.website.menu_layouts
 | 
				
			||||||
                    'bottom': self.website.get_menu('bottom'),
 | 
					 | 
				
			||||||
                    'right': self.website.get_menu('right'),
 | 
					 | 
				
			||||||
                    'header': self.website.get_menu('header'),
 | 
					 | 
				
			||||||
                    'footer': self.website.get_menu('footer'),
 | 
					 | 
				
			||||||
                }.items() if v
 | 
					                }.items() if v
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -162,46 +163,14 @@ class PostDetailView (DetailView, PostBaseView):
 | 
				
			|||||||
        return context
 | 
					        return context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ViewSet:
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    A ViewSet is a class helper that groups detail and list views that can be
 | 
					 | 
				
			||||||
    used to generate views and routes given a model and a name used for the
 | 
					 | 
				
			||||||
    routing.
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    model = None
 | 
					 | 
				
			||||||
    list_view = PostListView
 | 
					 | 
				
			||||||
    list_routes = []
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    detail_view = PostDetailView
 | 
					 | 
				
			||||||
    detail_sections = []
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __init__ (self, website = None):
 | 
					 | 
				
			||||||
        self.detail_sections = [
 | 
					 | 
				
			||||||
            section()
 | 
					 | 
				
			||||||
                for section in self.detail_sections
 | 
					 | 
				
			||||||
        ]
 | 
					 | 
				
			||||||
        self.detail_view = self.detail_view.as_view(
 | 
					 | 
				
			||||||
            model = self.model,
 | 
					 | 
				
			||||||
            sections = self.detail_sections,
 | 
					 | 
				
			||||||
            website = website,
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        self.list_view = self.list_view.as_view(
 | 
					 | 
				
			||||||
            model = self.model,
 | 
					 | 
				
			||||||
            website = website,
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        self.urls = [ route.as_url(self.model, self.list_view)
 | 
					 | 
				
			||||||
                            for route in self.list_routes ] + \
 | 
					 | 
				
			||||||
                      [ routes.DetailRoute.as_url(self.model, self.detail_view ) ]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class Menu (View):
 | 
					class Menu (View):
 | 
				
			||||||
    template_name = 'aircox_cms/menu.html'
 | 
					    template_name = 'aircox_cms/menu.html'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    name = ''
 | 
					    name = ''
 | 
				
			||||||
 | 
					    tag = 'nav'
 | 
				
			||||||
    enabled = True
 | 
					    enabled = True
 | 
				
			||||||
    classes = ''
 | 
					    classes = ''
 | 
				
			||||||
    position = ''   # top, left, bottom, right, header, footer
 | 
					    position = ''   # top, left, bottom, right, header, footer, page_top, page_bottom
 | 
				
			||||||
    sections = None
 | 
					    sections = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__ (self, *args, **kwargs):
 | 
					    def __init__ (self, *args, **kwargs):
 | 
				
			||||||
@ -211,6 +180,7 @@ class Menu (View):
 | 
				
			|||||||
    def get_context_data (self, **kwargs):
 | 
					    def get_context_data (self, **kwargs):
 | 
				
			||||||
        return {
 | 
					        return {
 | 
				
			||||||
            'name': self.name,
 | 
					            'name': self.name,
 | 
				
			||||||
 | 
					            'tag': self.tag,
 | 
				
			||||||
            'classes': self.classes,
 | 
					            'classes': self.classes,
 | 
				
			||||||
            'position': self.position,
 | 
					            'position': self.position,
 | 
				
			||||||
            'sections': [
 | 
					            'sections': [
 | 
				
			||||||
@ -225,39 +195,84 @@ class Menu (View):
 | 
				
			|||||||
        return render_to_string(self.template_name, context)
 | 
					        return render_to_string(self.template_name, context)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Section (View):
 | 
					
 | 
				
			||||||
 | 
					class BaseSection (View):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Base class for sections. Sections are view that can be used in detail view
 | 
					    Base class for sections. Sections are view that can be used in detail view
 | 
				
			||||||
    in order to have extra content about a post.
 | 
					    in order to have extra content about a post, or in menus.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    template_name = 'aircox_cms/section.html'
 | 
					    template_name = 'aircox_cms/base_section.html'
 | 
				
			||||||
    require_object = False
 | 
					    tag = 'div'        # container tags
 | 
				
			||||||
    object = None
 | 
					    classes = ''    # container classes
 | 
				
			||||||
    classes = ''
 | 
					    attrs = ''      # container extra attributes
 | 
				
			||||||
    title = ''
 | 
					    content = ''    # content
 | 
				
			||||||
    content = ''
 | 
					
 | 
				
			||||||
    header = ''
 | 
					 | 
				
			||||||
    bottom = ''
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_context_data (self, **kwargs):
 | 
					    def get_context_data (self, **kwargs):
 | 
				
			||||||
        context = {
 | 
					        return {
 | 
				
			||||||
            'title': self.title,
 | 
					            'tag': self.tag,
 | 
				
			||||||
            'header': self.header,
 | 
					 | 
				
			||||||
            'content': self.content,
 | 
					 | 
				
			||||||
            'bottom': self.bottom,
 | 
					 | 
				
			||||||
            'classes': self.classes,
 | 
					            'classes': self.classes,
 | 
				
			||||||
 | 
					            'attrs': self.attrs,
 | 
				
			||||||
 | 
					            'content': self.content,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return context
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get (self, request, **kwargs):
 | 
					    def get (self, request, **kwargs):
 | 
				
			||||||
        self.object = kwargs.get('object') or self.object
 | 
					 | 
				
			||||||
        self.request = request
 | 
					        self.request = request
 | 
				
			||||||
        context = self.get_context_data(**kwargs)
 | 
					        context = self.get_context_data(**kwargs)
 | 
				
			||||||
        return render_to_string(self.template_name, context)
 | 
					        return render_to_string(self.template_name, context)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Section (BaseSection):
 | 
				
			||||||
 | 
					    template_name = 'aircox_cms/section.html'
 | 
				
			||||||
 | 
					    require_object = False
 | 
				
			||||||
 | 
					    object = None
 | 
				
			||||||
 | 
					    title = ''
 | 
				
			||||||
 | 
					    header = ''
 | 
				
			||||||
 | 
					    bottom = ''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ListSection (Section):
 | 
					    def get_context_data (self, **kwargs):
 | 
				
			||||||
 | 
					        context = super().get_context_data(**kwargs)
 | 
				
			||||||
 | 
					        context.update({
 | 
				
			||||||
 | 
					            'title': self.title,
 | 
				
			||||||
 | 
					            'header': self.header,
 | 
				
			||||||
 | 
					            'bottom': self.bottom,
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        return context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get (self, request, **kwargs):
 | 
				
			||||||
 | 
					        self.object = kwargs.get('object') or self.object
 | 
				
			||||||
 | 
					        return super().get(request, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Sections:
 | 
				
			||||||
 | 
					    class Image (BaseSection):
 | 
				
			||||||
 | 
					        url = None # relative url to the image
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @property
 | 
				
			||||||
 | 
					        def content (self):
 | 
				
			||||||
 | 
					            return '<img src="{}">'.format(
 | 
				
			||||||
 | 
					                        static(self.url),
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class PostContent (Section):
 | 
				
			||||||
 | 
					        @property
 | 
				
			||||||
 | 
					        def content (self):
 | 
				
			||||||
 | 
					            content = escape(self.object.content)
 | 
				
			||||||
 | 
					            content = re.sub(r'(^|\n\n)((\n?[^\n])+)', r'<p>\2</p>', content)
 | 
				
			||||||
 | 
					            content = re.sub(r'\n', r'<br>', content)
 | 
				
			||||||
 | 
					            return content
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class PostImage (Section):
 | 
				
			||||||
 | 
					        @property
 | 
				
			||||||
 | 
					        def content (self):
 | 
				
			||||||
 | 
					            return '<img src="{}" class="post_image">'.format(
 | 
				
			||||||
 | 
					                        self.object.image.url
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class List (Section):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Section to render list. The context item 'object_list' is used as list of
 | 
					        Section to render list. The context item 'object_list' is used as list of
 | 
				
			||||||
        items to render.
 | 
					        items to render.
 | 
				
			||||||
@ -289,13 +304,13 @@ class ListSection (Section):
 | 
				
			|||||||
            return context
 | 
					            return context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class UrlListSection (ListSection):
 | 
					    class UrlList (List):
 | 
				
			||||||
        classes = 'section_urls'
 | 
					        classes = 'section_urls'
 | 
				
			||||||
        targets = None
 | 
					        targets = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def get_object_list (self, request, **kwargs):
 | 
					        def get_object_list (self, request, **kwargs):
 | 
				
			||||||
            return [
 | 
					            return [
 | 
				
			||||||
            ListSection.Item(
 | 
					                List.Item(
 | 
				
			||||||
                    target.image or None,
 | 
					                    target.image or None,
 | 
				
			||||||
                    '<a href="{}">{}</a>'.format(target.detail_url(), target.title)
 | 
					                    '<a href="{}">{}</a>'.format(target.detail_url(), target.title)
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
@ -303,7 +318,7 @@ class UrlListSection (ListSection):
 | 
				
			|||||||
            ]
 | 
					            ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PostListSection (PostListView):
 | 
					    class PostList (PostListView):
 | 
				
			||||||
        route = None
 | 
					        route = None
 | 
				
			||||||
        model = None
 | 
					        model = None
 | 
				
			||||||
        embed = True
 | 
					        embed = True
 | 
				
			||||||
@ -319,7 +334,41 @@ class PostListSection (PostListView):
 | 
				
			|||||||
            response = super().dispatch(request, *args, **kwargs)
 | 
					            response = super().dispatch(request, *args, **kwargs)
 | 
				
			||||||
            return str(response.content)
 | 
					            return str(response.content)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# TODO:
 | 
					
 | 
				
			||||||
# - get_title: pass object / queryset
 | 
					
 | 
				
			||||||
 | 
					class ViewSet:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    A ViewSet is a class helper that groups detail and list views that can be
 | 
				
			||||||
 | 
					    used to generate views and routes given a model and a name used for the
 | 
				
			||||||
 | 
					    routing.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    model = None
 | 
				
			||||||
 | 
					    list_view = PostListView
 | 
				
			||||||
 | 
					    list_routes = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    detail_view = PostDetailView
 | 
				
			||||||
 | 
					    detail_sections = [
 | 
				
			||||||
 | 
					        Sections.PostContent,
 | 
				
			||||||
 | 
					        Sections.PostImage,
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__ (self, website = None):
 | 
				
			||||||
 | 
					        self.detail_sections = [
 | 
				
			||||||
 | 
					            section()
 | 
				
			||||||
 | 
					                for section in self.detail_sections
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					        self.detail_view = self.detail_view.as_view(
 | 
				
			||||||
 | 
					            model = self.model,
 | 
				
			||||||
 | 
					            sections = self.detail_sections,
 | 
				
			||||||
 | 
					            website = website,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        self.list_view = self.list_view.as_view(
 | 
				
			||||||
 | 
					            model = self.model,
 | 
				
			||||||
 | 
					            website = website,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.urls = [ route.as_url(self.model, self.list_view)
 | 
				
			||||||
 | 
					                            for route in self.list_routes ] + \
 | 
				
			||||||
 | 
					                      [ routes.DetailRoute.as_url(self.model, self.detail_view ) ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -6,38 +6,46 @@ class Website:
 | 
				
			|||||||
    description = 'An aircox website'   # public description (used in meta info)
 | 
					    description = 'An aircox website'   # public description (used in meta info)
 | 
				
			||||||
    tags = 'aircox,radio,music'         # public keywords (used in meta info)
 | 
					    tags = 'aircox,radio,music'         # public keywords (used in meta info)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    logo = None
 | 
					    styles = ''                         # relative url to stylesheet file
 | 
				
			||||||
    menus = None
 | 
					    menus = None                        # list of menus
 | 
				
			||||||
 | 
					    menu_layouts = ['top', 'left',      # available positions
 | 
				
			||||||
 | 
					                    'right', 'bottom',
 | 
				
			||||||
 | 
					                    'header', 'footer']
 | 
				
			||||||
    router = None
 | 
					    router = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def urls (self):
 | 
				
			||||||
 | 
					        return self.router.get_urlpatterns()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__ (self, **kwargs):
 | 
					    def __init__ (self, **kwargs):
 | 
				
			||||||
        self.__dict__.update(kwargs)
 | 
					        self.__dict__.update(kwargs)
 | 
				
			||||||
        if not self.router:
 | 
					        if not self.router:
 | 
				
			||||||
            self.router = routes.Router()
 | 
					            self.router = routes.Router()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def register_set (self, view_set):
 | 
					    def register_set (self, view_set):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Register a ViewSet (or subclass) to the router,
 | 
				
			||||||
 | 
					        and connect it to self.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
        view_set = view_set(website = self)
 | 
					        view_set = view_set(website = self)
 | 
				
			||||||
        self.router.register_set(view_set)
 | 
					        self.router.register_set(view_set)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_menu (self, position):
 | 
					    def get_menu (self, position):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Get an enabled menu by its position
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
        for menu in self.menus:
 | 
					        for menu in self.menus:
 | 
				
			||||||
            if menu.enabled and menu.position == position:
 | 
					            if menu.enabled and menu.position == position:
 | 
				
			||||||
 | 
					                self.check_menu_tag(menu)
 | 
				
			||||||
                return menu
 | 
					                return menu
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_top_menu (self):
 | 
					    def check_menu_tag (self, menu):
 | 
				
			||||||
        return self.get_menu('top')
 | 
					        """
 | 
				
			||||||
 | 
					        Update menu tag if it is a footer or a header
 | 
				
			||||||
    def get_left_menu (self):
 | 
					        """
 | 
				
			||||||
        return self.get_menu('left')
 | 
					        if menu.position in ('footer','header'):
 | 
				
			||||||
 | 
					            menu.tag = menu.position
 | 
				
			||||||
    def get_bottom_menu (self):
 | 
					        if menu.position in ('left', 'right'):
 | 
				
			||||||
        return self.get_menu('bottom')
 | 
					            menu.tag = 'side'
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def get_right_menu (self):
 | 
					 | 
				
			||||||
        return self.get_menu('right')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @property
 | 
					 | 
				
			||||||
    def urls (self):
 | 
					 | 
				
			||||||
        return self.router.get_urlpatterns()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										
											BIN
										
									
								
								website/static/website/colony.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								website/static/website/colony.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 15 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								website/static/website/logo.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								website/static/website/logo.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 41 KiB  | 
							
								
								
									
										44
									
								
								website/static/website/styles.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								website/static/website/styles.css
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,44 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					body {
 | 
				
			||||||
 | 
					    background-color: #F2F2F2;
 | 
				
			||||||
 | 
					    font-family: "Myriad Pro",Calibri,Helvetica,Arial,sans-serif;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					h1, h2, h3 {
 | 
				
			||||||
 | 
					    font-family: "Myriad Pro",Calibri,Helvetica,Arial,sans-serif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nav.menu {
 | 
				
			||||||
 | 
					    padding: 0.5em;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nav.menu_top {
 | 
				
			||||||
 | 
					    background-color: #212121;
 | 
				
			||||||
 | 
					    color: #007EDF;
 | 
				
			||||||
 | 
					    font-size: 1.1em;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    header {
 | 
				
			||||||
 | 
					        height: 9em;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    header img {
 | 
				
			||||||
 | 
					        height: 100%;
 | 
				
			||||||
 | 
					        float: left;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    header .colony {
 | 
				
			||||||
 | 
					        position: fixed;
 | 
				
			||||||
 | 
					        top: 0em;
 | 
				
			||||||
 | 
					        right: 0;
 | 
				
			||||||
 | 
					        z-index: -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.page {
 | 
				
			||||||
 | 
					    width: 100%;
 | 
				
			||||||
 | 
					    background-color: rgba(255, 255, 255, 0.8);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -4,7 +4,7 @@ from website.models import *
 | 
				
			|||||||
from website.views import *
 | 
					from website.views import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from aircox_cms.models import Article
 | 
					from aircox_cms.models import Article
 | 
				
			||||||
from aircox_cms.views import ViewSet, Menu, Section
 | 
					from aircox_cms.views import Menu, Section, Sections, ViewSet
 | 
				
			||||||
from aircox_cms.routes import *
 | 
					from aircox_cms.routes import *
 | 
				
			||||||
from aircox_cms.website import Website
 | 
					from aircox_cms.website import Website
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -17,8 +17,8 @@ class ProgramSet (ViewSet):
 | 
				
			|||||||
        DateRoute,
 | 
					        DateRoute,
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    detail_sections = [
 | 
					    detail_sections = ViewSet.detail_sections + [
 | 
				
			||||||
        ScheduleSection
 | 
					        ScheduleSection,
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class EpisodeSet (ViewSet):
 | 
					class EpisodeSet (ViewSet):
 | 
				
			||||||
@ -42,17 +42,33 @@ class ArticleSet (ViewSet):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
website = Website(
 | 
					website = Website(
 | 
				
			||||||
    name = 'RadioCampus',
 | 
					    name = 'RadioCampus',
 | 
				
			||||||
 | 
					    styles = 'website/styles.css',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    menus = [
 | 
					    menus = [
 | 
				
			||||||
 | 
					        Menu(
 | 
				
			||||||
 | 
					            position = 'header',
 | 
				
			||||||
 | 
					            sections = [
 | 
				
			||||||
 | 
					                Sections.Image(url = 'website/logo.png'),
 | 
				
			||||||
 | 
					                Sections.Image(url = 'website/colony.png', classes='colony'),
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Menu(
 | 
					        Menu(
 | 
				
			||||||
            position = 'top',
 | 
					            position = 'top',
 | 
				
			||||||
            sections = [
 | 
					            sections = [
 | 
				
			||||||
                Section(content = "Radio Campus le SITE")
 | 
					                Section(content = "Radio Campus le SITE")
 | 
				
			||||||
            ]
 | 
					            ]
 | 
				
			||||||
        )
 | 
					        ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Menu(
 | 
				
			||||||
 | 
					            position = 'left',
 | 
				
			||||||
 | 
					            sections = [
 | 
				
			||||||
 | 
					                Section(content = 'loool<br>blob')
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
website.register_set(ProgramSet)
 | 
					website.register_set(ProgramSet)
 | 
				
			||||||
website.register_set(EpisodeSet)
 | 
					website.register_set(EpisodeSet)
 | 
				
			||||||
website.register_set(ArticleSet)
 | 
					website.register_set(ArticleSet)
 | 
				
			||||||
 | 
				
			|||||||
@ -6,21 +6,21 @@ from django.core import serializers
 | 
				
			|||||||
from django.utils.translation import ugettext as _, ugettext_lazy
 | 
					from django.utils.translation import ugettext as _, ugettext_lazy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import aircox_programs.models as programs
 | 
					import aircox_programs.models as programs
 | 
				
			||||||
from aircox_cms.views import ListSection
 | 
					from aircox_cms.views import Sections
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PlaylistSection (ListSection):
 | 
					class PlayListSection (Sections.List):
 | 
				
			||||||
    title = _('Playlist')
 | 
					    title = _('Playlist')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_object_list (self):
 | 
					    def get_object_list (self):
 | 
				
			||||||
        tracks = programs.Track.objects \
 | 
					        tracks = programs.Track.objects \
 | 
				
			||||||
                     .filter(episode = self.object) \
 | 
					                     .filter(episode = self.object) \
 | 
				
			||||||
                     .order_by('position')
 | 
					                     .order_by('position')
 | 
				
			||||||
        return [ ListSection.Item(None, track.title, track.artist)
 | 
					        return [ Sections.List.Item(None, track.title, track.artist)
 | 
				
			||||||
                    for track in tracks ]
 | 
					                    for track in tracks ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ScheduleSection (ListSection):
 | 
					class ScheduleSection (Sections.List):
 | 
				
			||||||
    title = _('Schedule')
 | 
					    title = _('Schedule')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_object_list (self):
 | 
					    def get_object_list (self):
 | 
				
			||||||
@ -28,7 +28,7 @@ class ScheduleSection (ListSection):
 | 
				
			|||||||
                    .filter(program = self.object.pk)
 | 
					                    .filter(program = self.object.pk)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return [
 | 
					        return [
 | 
				
			||||||
            ListSection.Item(None, sched.get_frequency_display(),
 | 
					            Sections.List.Item(None, sched.get_frequency_display(),
 | 
				
			||||||
                             _('rerun') if sched.rerun else None)
 | 
					                             _('rerun') if sched.rerun else None)
 | 
				
			||||||
            for sched in scheds
 | 
					            for sched in scheds
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user