+from prawokultury.helpers import AppSettings
+
+
+class Settings(AppSettings):
+ BOX_LENGTH = 3
+
+
+app_settings = Settings('EVENTS')
# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
#
from django import template
+from events import app_settings
from events.models import Event
register = template.Library()
@register.inclusion_tag('events/snippets/events_box.html', takes_context=True)
-def events_box(context, limit=5):
+def events_box(context, limit=app_settings.BOX_LENGTH):
objects = Event.objects.filter(date__gte=datetime.now())[:limit]
return {'objects': objects}
Migdal (מִגְדָּל) is a multilingual blog Django app.
Author: Radek Czajka <radoslaw.czajka@nowoczesnapolska.org.pl>
-"""
\ No newline at end of file
+"""
+from django.conf import settings
+from prawokultury.helpers import AppSettings
+from django.utils.translation import ugettext_lazy as _
+from migdal.helpers import EntryType
+
+
+class Settings(AppSettings):
+ # Types of entries:
+ # (slug, commentable, on main)
+ TYPES = (
+ EntryType('news', _('news'), commentable=True, on_main=True),
+ EntryType('publications', _('publications'), commentable=False, on_main=False),
+ EntryType('info', _('info'), commentable=False, on_main=False),
+ )
+ TYPE_SUBMIT = 'news'
+ TAXONOMIES = (
+ ('topics', _('topics')),
+ ('types', _('types')),
+ )
+ LAST_COMMENTS = 10
+
+ TYPES_DICT = None
+ def _more_TYPES_DICT(self, value):
+ return dict((t.db, t) for t in self.TYPES)
+
+ TYPES_ON_MAIN = None
+ def _more_TYPES_ON_MAIN(self, value):
+ return tuple(t.db for t in self.TYPES if t.on_main)
+
+ OBLIGATORY_LANGUAGES = None
+ def _more_OBLIGATORY_LANGUAGES(self, value):
+ return value or tuple(lang for lang in settings.LANGUAGES
+ if lang[0] == settings.LANGUAGE_CODE)
+
+ OPTIONAL_LANGUAGES = None
+ def _more_OPTIONAL_LANGUAGES(self, value):
+ return tuple(lang for lang in settings.LANGUAGES
+ if lang not in self.OBLIGATORY_LANGUAGES)
+
+app_settings = Settings('MIGDAL')
+
+
+
from django.utils.translation import get_language, ugettext_lazy as _, ugettext
from markupfield.fields import MarkupField
from migdal.helpers import add_translatable
-from migdal import settings
+from migdal import app_settings
class Category(models.Model):
taxonomy = models.CharField(_('taxonomy'), max_length=32,
- choices=settings.TAXONOMIES)
+ choices=app_settings.TAXONOMIES)
class Meta:
verbose_name = _('category')
class Entry(models.Model):
type = models.CharField(max_length=16,
- choices=((t.db, t.slug) for t in settings.TYPES),
+ choices=((t.db, t.slug) for t in app_settings.TYPES),
db_index=True)
date = models.DateTimeField(auto_now_add=True, db_index=True)
author = models.CharField(_('author'), max_length=128)
def save(self, *args, **kwargs):
# convert blank to null for slug uniqueness check to work
- for lc, ln in settings.OPTIONAL_LANGUAGES:
+ for lc, ln in app_settings.OPTIONAL_LANGUAGES:
slug_name = "slug_%s" % lc
if hasattr(self, slug_name) == u'':
setattr(self, slug_name, None)
return ('migdal_entry_%s' % self.type, [self.slug])
def get_type(self):
- return dict(settings.TYPES_DICT)[self.type]
+ return dict(app_settings.TYPES_DICT)[self.type]
-add_translatable(Entry, languages=settings.OPTIONAL_LANGUAGES, fields={
+add_translatable(Entry, languages=app_settings.OPTIONAL_LANGUAGES, fields={
'needed': models.CharField(_('needed'), max_length=1, db_index=True, choices=(
('n', _('Unneeded')), ('w', _('Needed')), ('y', _('Done'))),
default='n'),
+++ /dev/null
-# -*- coding: utf-8 -*-
-# This file is part of PrawoKultury, licensed under GNU Affero GPLv3 or later.
-# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
-#
-from django.conf import settings
-from django.utils.translation import ugettext_lazy as _
-from migdal.helpers import EntryType
-
-
-def app_setting(global_name, default):
- try:
- return getattr(settings, global_name)
- except AttributeError:
- return default
-
-# Types of entries:
-# (slug, commentable, on main)
-TYPES = app_setting('MIGDAL_TYPES', (
- EntryType('news', _('news'), commentable=True, on_main=True),
- EntryType('publications', _('publications'), commentable=False, on_main=False),
- EntryType('info', _('info'), commentable=False, on_main=False),
- ))
-TYPES_DICT = dict((t.db, t) for t in TYPES)
-TYPES_ON_MAIN = tuple(t.db for t in TYPES if t.on_main)
-TYPE_SUBMIT = 'news'
-
-
-LANGUAGES = app_setting('MIGDAL_LANGUAGES', settings.LANGUAGES)
-LANGUAGE_CODE = app_setting('MIGDAL_LANGUAGE_CODE', settings.LANGUAGE_CODE)
-OBLIGATORY_LANGUAGES = app_setting('MIGDAL_OBLIGATORY', tuple(
- lang for lang in LANGUAGES if lang[0]==LANGUAGE_CODE))
-OPTIONAL_LANGUAGES = tuple(lang for lang in LANGUAGES if lang not in OBLIGATORY_LANGUAGES)
-
-
-TAXONOMIES = (
- ('topics', _('topics')),
- ('types', _('types')),
-)
{% load i18n %}
{% load gravatar thumbnail %}
-<img class="avatar" src="{% gravatar_for_email object.author_email 48 %}"/>
-<h2><a href="{{ object.get_absolute_url }}">{{ object.title }}</a></h2>
+<img class="avatar" src="{% gravatar_for_email object.author_email 64 %}"/>
+{% if detail %}
+ <h1>{{ object.title }}</h1>
+{% else %}
+ <h2><a href="{{ object.get_absolute_url }}">{{ object.title }}</a></h2>
+{% endif %}
<div class="entry-data">
<div class="date">{{ object.date }}</div>
<div class="categories">
{% for category in object.categories.all %}
+ {% if forloop.counter != 1 %}/{% endif %}
<a href="{{ category.get_absolute_url }}">{{ category }}</a>
{% endfor %}
</div>
{% block "body" %}
-<div class="entry entry-short entry-{{ entry.type }}">
+<div class="entry entry-detail entry-{{ entry.type }}">
<div class="entry-wrapped">
-{% entry_begin entry %}
+{% entry_begin entry 1 %}
<div class="body">
{{ entry.body }}
</div>
{% block "body" %}
{% if category %}
- {% trans "Category" %}: {{ category }}
- <h1><a href="{% url 'migdal_category_feed' category.slug %}">RSS</a></h1>
+ <h1>{% trans "Category" %}: {{ category }}
+ <!--a href="{% url 'migdal_category_feed' category.slug %}">RSS</a-->
+ </h1>
{% elif entry_type %}
- {{ entry_type|capfirst }}
- <h1><a href="{% url 'migdal_entry_list_'|add:entry_type.db|add:'_feed' %}">RSS</a></h1>
+ <h1>{{ entry_type|capfirst }}
+ <!--a href="{% url 'migdal_entry_list_'|add:entry_type.db|add:'_feed' %}">RSS</a-->
+ </h1>
{% endif %}
{% if object_list.promobox and request.page == 1 %}
{% load i18n %}
-<h2><a href="{{ object.get_absolute_url }}">{{ object.title }}</a></h2>
+
+{% if detail %}
+ <h1>{{ object.title }}</h1>
+{% else %}
+ <h2><a href="{{ object.get_absolute_url }}">{{ object.title }}</a></h2>
+{% endif %}
+
<div class="entry-data">
{% if request.LANGUAGE_CODE == 'pl' %}
{% if object.image %}
<img class="entry-picture" src="{{ object.image.url }}" />
{% endif %}
+<div class="lead">
{{ object.lead }}
+</div>
{% for comment in object_list %}
<li>
<a href="{{ comment.get_absolute_url }}">
- <div>
- <img src="{% gravatar_for_email comment.email 16 %}"/>
- {{ comment.name }}, {{ comment.submit_date }}</div>
- {{ comment.comment|textile_restricted_pl|striptags|truncatechars:32 }}
+ <div class="title">{{ comment.content_object.title }}</div>
+ <div class="author">{{ comment.name }}</div>
+ <div class="body">{{ comment.comment|textile_restricted_pl|striptags|truncatechars:32 }}</div>
</a>
</li>
{% endfor %}
from django.contrib import comments
from django.core.urlresolvers import reverse
from django import template
+from migdal import app_settings
from migdal.models import Category, Entry
-from migdal import settings
from django.utils.translation import ugettext_lazy as _
register = template.Library()
@register.simple_tag(takes_context=True)
-def entry_begin(context, entry):
+def entry_begin(context, entry, detail=False):
t = template.loader.select_template((
'migdal/entry/%s/entry_begin.html' % entry.type,
'migdal/entry/entry_begin.html',
context = {
'request': context['request'],
'object': entry,
+ 'detail': detail,
}
return t.render(template.Context(context))
@register.inclusion_tag('migdal/last_comments.html')
-def last_comments(limit=10):
+def last_comments(limit=app_settings.LAST_COMMENTS):
return {'object_list':
XtdComment.objects.filter(is_public=True, is_removed=False).order_by('-submit_date')[:limit]}
from django.conf.urls import patterns, include, url
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import string_concat
-from migdal import feeds, settings
+from migdal import feeds, app_settings
from migdal.helpers import i18n_patterns
pats = []
-for t in settings.TYPES:
+for t in app_settings.TYPES:
pats += [
# entry list
url(string_concat(r'^', t.slug, r'/$'),
from migdal import api
from migdal.forms import get_submit_form
from migdal.models import Category, Entry
-from migdal.settings import TYPES_DICT, TYPES_ON_MAIN, TYPE_SUBMIT
+from migdal import app_settings
def entry_list(request, type_db=None, category_slug=None):
templates = ["migdal/entry/entry_list.html"]
if type_db:
- if TYPES_ON_MAIN == (type_db,):
+ if app_settings.TYPES_ON_MAIN == (type_db,):
return redirect('migdal_main')
- entry_type = TYPES_DICT[type_db]
+ entry_type = app_settings.TYPES_DICT[type_db]
templates = ["migdal/entry/%s/entry_list.html" % type_db] + templates
- submit = type_db == TYPE_SUBMIT
+ submit = type_db == app_settings.TYPE_SUBMIT
else:
- submit = TYPES_ON_MAIN == (TYPE_SUBMIT,)
+ submit = app_settings.TYPES_ON_MAIN == (app_settings.TYPE_SUBMIT,)
entry_type = None
if category_slug:
# This file is part of PrawoKultury, licensed under GNU Affero GPLv3 or later.
# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
#
+from django.conf import settings
from textile import Textile
text, rel='nofollow')
-
class LazyUGettextLazy():
"""You can use it to internationalize strings in settings.
LazyUGettextLazy._ = staticmethod(ugettext_lazy)
LazyUGettextLazy.real = True
return unicode(self._(self.text))
+
+
+class AppSettings(object):
+ """Allows specyfying custom settings for an app, with default values.
+
+ Just subclass, set some properties and instantiate with a prefix.
+ Getting a SETTING from an instance will check for prefix_SETTING
+ in project settings if set, else take the default. The value will be
+ then filtered through _more_SETTING method, if there is one.
+
+ """
+ def __init__(self, prefix):
+ self._prefix = prefix
+
+ def __getattribute__(self, name):
+ if name.startswith('_'):
+ return object.__getattribute__(self, name)
+ value = getattr(settings,
+ "%s_%s" % (self._prefix, name),
+ object.__getattribute__(self, name))
+ more = "_more_%s" % name
+ if hasattr(self, more):
+ value = getattr(self, more)(value)
+ return value
#COMMENTS_XTD_LIST_PAGINATE_BY = 10
THUMBNAIL_QUALITY = 95
+
+GRAVATAR_DEFAULT_IMAGE = 'http://localhost:8000/static/img/avatar.png'
body {
font-family: 'Lato', sans-serif;
font-size: .625em;
- background: #edece7;
+ background-color: #edece7;
background-image: url("/static/img/bg.png");
background-repeat: no-repeat;
+ color: #363a3b;
margin-top: 0;
background-position: 50% 0; }
a:hover {
text-decoration: underline; }
+
+h1 {
+ margin: 0;
+ color: #01519a;
+ font-size: 2em; }
body {
font-family: 'Lato', sans-serif;
font-size: .625em;
- background: #edece7;
+ background-color: #edece7;
background-image: url('/static/img/bg.png');
background-repeat: no-repeat;
+ color: #363a3b;
margin-top: 0;
background-position: 50% 0;
}
a:hover {
text-decoration: underline;
}
+
+
+h1 {
+ margin: 0;
+ color: #01519a;
+ font-size: 2em;
+}
.avatar {
float: left;
- margin-left: -7.5em;
- margin-top: .8em; }
+ margin-left: -8em;
+ margin-top: 0em; }
.entry-short {
border-top: 1px solid #8b8b87; }
+ .entry-short .entry-wrapped {
+ padding-top: .7em; }
.entry-wrapped {
- margin-left: 8em;
- padding-top: .7em; }
- .entry-wrapped h2 {
+ margin-left: 8em; }
+ .entry-wrapped h1, .entry-wrapped h2 {
margin: 0;
- font-size: 1.2em;
- color: #01519a; }
+ color: #01519a;
+ font-size: 1.2em; }
+ .entry-wrapped h1 a, .entry-wrapped h2 a {
+ color: #01519a; }
.entry-wrapped .entry-data {
font-size: 1.1em;
margin-top: 1.4em;
content: url("/static/img/read-more.png");
margin-left: .7em; }
+.entry-info .entry-wrapped {
+ margin-left: 0; }
+ .entry-info .entry-wrapped h1 {
+ font-size: 2em; }
+
.entry-picture {
float: left;
margin-right: 1.5em; }
.avatar {
float: left;
- margin-left: -7.5em;
- margin-top: .8em;
+ margin-left: -8em;
+ margin-top: 0em;
}
.entry-short {
border-top: 1px solid #8b8b87;
+
+ .entry-wrapped {
+ padding-top: .7em;
+ }
}
.entry-wrapped {
margin-left: 8em;
- padding-top: .7em;
- h2 {
+ h1, h2 {
margin: 0;
- font-size: 1.2em;
color: #01519a;
+ font-size: 1.2em;
+
+ a {
+ color: #01519a;
+ }
}
.entry-data {
}
}
+.entry-info .entry-wrapped {
+ margin-left: 0;
+ h1 {
+ font-size: 2em;
+ }
+}
.entry-picture {
float: left;
padding-bottom: .9em;
clear: both; }
.sidebar-box h3 {
- font-size: 1.3em;
+ font-size: 1.4em;
font-weight: normal;
margin-top: 0;
- margin-bottom: 1.2em; }
+ margin-bottom: 1.1em; }
.sidebar-box .more {
text-align: right; }
.sidebar-box .event-list {
color: #31ada3; }
#sidebar-box-categories .category-taxonomy-types a {
color: #ff6100; }
+
+#latest-comments {
+ list-style: none;
+ padding: 0;
+ margin: 0; }
+ #latest-comments a {
+ display: block;
+ color: #363a3b; }
+ #latest-comments li {
+ margin-bottom: 1.5em; }
+ #latest-comments li:after {
+ content: url("/static/img/dot.png");
+ display: block;
+ margin: 1.5em 1.5em 0 0;
+ text-align: center; }
+ #latest-comments li:last-child {
+ margin-bottom: 0; }
+ #latest-comments li:last-child:after {
+ display: none; }
+ #latest-comments .title {
+ font-size: 1.1em;
+ font-weight: bold; }
+ #latest-comments .author {
+ color: #acacac;
+ font-size: 1.1em; }
+ #latest-comments .body {
+ margin-top: 1.3em;
+ font-size: 1.1em; }
clear: both;
h3 {
- font-size: 1.3em;
+ font-size: 1.4em;
font-weight: normal;
margin-top: 0;
- margin-bottom: 1.2em;
+ margin-bottom: 1.1em;
}
.more {
color: #ff6100;
}
}
+
+
+#latest-comments {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+
+ a {
+ display: block;
+ color: #363a3b;
+ }
+
+ li {
+ margin-bottom: 1.5em;
+ }
+ li:after {
+ content: url("/static/img/dot.png");
+ display: block;
+ margin: 1.5em 1.5em 0 0;
+ text-align:center;
+ }
+
+ li:last-child {
+ margin-bottom: 0;
+ }
+ li:last-child:after {
+ display: none;
+ }
+
+ .title {
+ font-size: 1.1em;
+ font-weight: bold;
+ }
+ .author {
+ color: #acacac;
+ font-size: 1.1em;
+ }
+ .body {
+ margin-top: 1.3em;
+ font-size: 1.1em;
+ }
+}
\ No newline at end of file
};
-$switchers.each(function(i, e) {
- $(e).click(function(e) {
- e.preventDefault();
- change_slide(i);
- });
-});
-
-
var timeout = null;
var cycle_slide = function() {
var current = $slides.filter('.active').index();
change_slide((current + 1) % $slides.length);
}
+
+
var reset_timeout = function() {
clearTimeout(timeout);
timeout = setTimeout(cycle_slide, 5000);
};
-timeout = setTimeout(cycle_slide, 3000);
+
+
+if ($slides.length > 1) {
+ $switchers.each(function(i, e) {
+ $(e).click(function(e) {
+ e.preventDefault();
+ change_slide(i);
+ });
+ });
+
+ timeout = setTimeout(cycle_slide, 3000);
+}
});
\ No newline at end of file