Fehler bei Vergabe von Bonuspunkte korrigiert.
Kommentare für Bonuspunkte werden jetzt als Kommentar beim Spieler hinterlassen, nicht als Kommentar in der Hanchan. FIXED: 3_in_a_row counter wurde nicht zurückgesetzt wenn Bonuspunkte vergeben wurden. FIXED: Durchschnittliche Platzierung während eines Events wurde nur als Ganzzahl berechnet. Wird nun als Fießkomma berechnet und gesichert.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -10,6 +10,7 @@ __pycache__/
|
||||
.Python
|
||||
env/
|
||||
build/
|
||||
upload/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
from django.contrib import admin
|
||||
|
||||
from models import Feed, FeedItem
|
||||
|
||||
|
||||
admin.site.register(
|
||||
Feed,
|
||||
list_display=["title", "public_url", "last_update", 'is_functional'],
|
||||
list_filter=["is_functional"],
|
||||
ordering=["title"],
|
||||
search_fields=["title", "public_url"],
|
||||
list_per_page=500,
|
||||
)
|
||||
|
||||
admin.site.register(
|
||||
FeedItem,
|
||||
list_display=['title', 'feed', 'date_modified'],
|
||||
list_filter=['feed'],
|
||||
search_fields=['feed__title', 'feed__public_url', 'title'],
|
||||
date_heirarchy=['date_modified'],
|
||||
)
|
||||
@@ -1,25 +0,0 @@
|
||||
import django.contrib.syndication.views
|
||||
|
||||
from .models import FeedItem
|
||||
|
||||
|
||||
# noinspection PyMethodMayBeStatic
|
||||
class LatestFeedItems(django.contrib.syndication.views.Feed):
|
||||
link = "http://aol.animanga.at/"
|
||||
description = "Aktuelle Nachrichten aus der Austrian Otaku League"
|
||||
title = "AOL - Newsfeed"
|
||||
|
||||
def items(self):
|
||||
return FeedItem.objects.get_recent_items()
|
||||
|
||||
def item_title(self, item):
|
||||
return "%s: %s" % (item.feed.title, item.title)
|
||||
|
||||
def item_description(self, item):
|
||||
return item.summary
|
||||
|
||||
def item_author_name(self, item):
|
||||
return item.feed.title
|
||||
|
||||
def item_pubdate(self, item):
|
||||
return item.date_modified
|
||||
@@ -1 +0,0 @@
|
||||
# -
|
||||
@@ -1 +0,0 @@
|
||||
#
|
||||
@@ -1,21 +0,0 @@
|
||||
"""
|
||||
Update feeds for Django community page. Requires Mark Pilgrim's excellent
|
||||
Universal Feed Parser (http://feedparser.org)
|
||||
"""
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from aggregator.models import Feed
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Updates all RSS Feeds"
|
||||
|
||||
def handle(self, *args, **options):
|
||||
verbose = int(options['verbosity']) > 0
|
||||
for feed in Feed.objects.filter(is_functional=True):
|
||||
if verbose:
|
||||
print
|
||||
print "%s - URL: %s" % (feed.title, feed.feed_url)
|
||||
print '=' * 80
|
||||
feed.parse()
|
||||
@@ -1,45 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
import utils.html5.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('sites', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Feed',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('title', utils.html5.models.CharField(max_length=500)),
|
||||
('feed_url', utils.html5.models.URLField(unique=True, max_length=255)),
|
||||
('public_url', utils.html5.models.URLField(max_length=255)),
|
||||
('last_update', utils.html5.models.DateTimeField(null=True, blank=True)),
|
||||
('is_functional', utils.html5.models.BooleanField(default=True)),
|
||||
('site', utils.html5.models.ForeignKey(to='sites.Site')),
|
||||
],
|
||||
options={
|
||||
'ordering': ('title',),
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='FeedItem',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('title', utils.html5.models.CharField(max_length=500)),
|
||||
('link', utils.html5.models.URLField(max_length=500)),
|
||||
('guid', utils.html5.models.CharField(unique=True, max_length=255, db_index=True)),
|
||||
('summary', utils.html5.models.TextField(blank=True)),
|
||||
('date_modified', utils.html5.models.DateTimeField()),
|
||||
('feed', utils.html5.models.ForeignKey(related_name='feed_items', to='aggregator.Feed')),
|
||||
],
|
||||
options={
|
||||
'ordering': ('-date_modified',),
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -1,114 +0,0 @@
|
||||
"""
|
||||
Created on 05.02.2011
|
||||
|
||||
@author: christian
|
||||
"""
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
import HTMLParser
|
||||
import urllib2
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.sites.models import Site
|
||||
from django.utils import timezone
|
||||
import django.db.models
|
||||
import feedparser
|
||||
|
||||
from utils.html5 import models
|
||||
|
||||
|
||||
class FeedManager(django.db.models.Manager):
|
||||
def active(self):
|
||||
site = settings.SITE_ID
|
||||
feeds = self.filter(is_functional=True, site=site)
|
||||
for feed in feeds:
|
||||
if feed.last_update:
|
||||
feed_age = timezone.now() - feed.last_update
|
||||
if feed_age > timedelta(hours=12):
|
||||
feed.parse()
|
||||
else:
|
||||
feed.parse()
|
||||
return feeds
|
||||
|
||||
|
||||
class FeedItemManager(django.db.models.Manager):
|
||||
def recent_items(self, max_items=10, site=None):
|
||||
site = site or settings.SITE_ID
|
||||
return self.select_related().filter(feed__site=site)[:max_items]
|
||||
|
||||
|
||||
class Feed(django.db.models.Model):
|
||||
title = models.CharField(max_length=500)
|
||||
site = models.ForeignKey(Site)
|
||||
feed_url = models.URLField(unique=True, max_length=255)
|
||||
public_url = models.URLField(max_length=255)
|
||||
last_update = models.DateTimeField(blank=True, null=True)
|
||||
is_functional = models.BooleanField(default=True)
|
||||
objects = FeedManager()
|
||||
|
||||
def __unicode__(self):
|
||||
return self.title
|
||||
|
||||
def parse(self):
|
||||
parsed_feed = feedparser.parse(self.feed_url)
|
||||
html_parser = HTMLParser.HTMLParser()
|
||||
|
||||
if parsed_feed.bozo and type(
|
||||
parsed_feed.bozo_exception) == urllib2.URLError:
|
||||
self.is_functional = False
|
||||
return self.save()
|
||||
|
||||
for feed_entry in parsed_feed.entries:
|
||||
title = html_parser.unescape(feed_entry.title)
|
||||
if not title:
|
||||
continue
|
||||
|
||||
link = feed_entry.link
|
||||
guid = feed_entry.get("id", link)
|
||||
summary = html_parser.unescape(
|
||||
feed_entry.get("summary", feed_entry.get(
|
||||
"description",
|
||||
feed_entry.get("content", u"")
|
||||
))
|
||||
)
|
||||
date_modified = feed_entry.get(
|
||||
"published_parsed",
|
||||
parsed_feed.get("published_parsed",
|
||||
timezone.now))
|
||||
date_modified = timezone.make_aware(
|
||||
datetime(*date_modified[:6]),
|
||||
timezone.get_current_timezone())
|
||||
|
||||
feed_item, updated = self.feed_items.get_or_create(
|
||||
guid=guid,
|
||||
defaults={
|
||||
'title': title,
|
||||
'link': link,
|
||||
'summary': summary,
|
||||
'date_modified': date_modified
|
||||
})
|
||||
feed_item.save()
|
||||
self.last_update = timezone.now()
|
||||
return self.save()
|
||||
|
||||
class Meta:
|
||||
ordering = ("title",)
|
||||
|
||||
|
||||
class FeedItem(django.db.models.Model):
|
||||
feed = models.ForeignKey(Feed, related_name='feed_items')
|
||||
title = models.CharField(max_length=500)
|
||||
link = models.URLField(max_length=500)
|
||||
guid = models.CharField(max_length=255, unique=True, db_index=True)
|
||||
summary = models.TextField(blank=True)
|
||||
date_modified = models.DateTimeField()
|
||||
objects = FeedItemManager()
|
||||
|
||||
class Meta:
|
||||
ordering = ("-date_modified",)
|
||||
|
||||
def __unicode__(self):
|
||||
return self.title
|
||||
|
||||
def get_absolute_url(self):
|
||||
return self.link
|
||||
@@ -1,16 +0,0 @@
|
||||
from django.contrib.sitemaps import Sitemap
|
||||
|
||||
from models import FeedItem
|
||||
|
||||
|
||||
|
||||
# noinspection PyMethodMayBeStatic
|
||||
class FeedItemSitemap(Sitemap):
|
||||
changefreq = "never"
|
||||
priority = 0.5
|
||||
|
||||
def items(self):
|
||||
return FeedItem.objects.get_recent_items()
|
||||
|
||||
def lastmod(self, obj):
|
||||
return obj.date_modified
|
||||
@@ -1,31 +0,0 @@
|
||||
from django import template
|
||||
|
||||
from models import Feed
|
||||
|
||||
|
||||
class FeedListNode(template.Node):
|
||||
def __init__(self, varname):
|
||||
self.varname = varname
|
||||
|
||||
def render(self, context):
|
||||
context[self.varname] = Feed.objects.filter(is_defunct=False)
|
||||
return ''
|
||||
|
||||
|
||||
# noinspection PyUnusedLocal
|
||||
def do_get_feed_list(parser, token):
|
||||
"""
|
||||
{% get_feed_list as feed_list %}
|
||||
"""
|
||||
bits = token.contents.split()
|
||||
if len(bits) != 3:
|
||||
raise template.TemplateSyntaxError, \
|
||||
"'%s' tag takes two arguments" % bits[0]
|
||||
if bits[1] != "as":
|
||||
raise template.TemplateSyntaxError, \
|
||||
"First argument to '%s' tag must be 'as'" % bits[0]
|
||||
return FeedListNode(bits[2])
|
||||
|
||||
|
||||
register = template.Library()
|
||||
register.tag('get_feed_list', do_get_feed_list)
|
||||
@@ -15,12 +15,12 @@ def content_menus(request):
|
||||
current_path = request.path_info[1:request.path_info.rfind('.')]
|
||||
|
||||
# erzeuge das Top-Level Menü
|
||||
top_menu_items = []
|
||||
top_level_pages = cache.get('top_level_pages')
|
||||
if top_level_pages is None:
|
||||
top_level_pages = models.Page.objects.filter(parent=None)
|
||||
top_level_pages = top_level_pages.exclude(slug='index')
|
||||
top_level_pages = top_level_pages.order_by('position')
|
||||
top_level_pages = top_level_pages.prefetch_related('subpages')
|
||||
cache.set('top_level_pages', top_level_pages, 360)
|
||||
for item in top_level_pages:
|
||||
if current_path.startswith(item.path):
|
||||
@@ -28,7 +28,6 @@ def content_menus(request):
|
||||
current_top_page = item
|
||||
else:
|
||||
item.active = False
|
||||
top_menu_items.append(item)
|
||||
|
||||
# Entdecke die aktuell geöffnete Seite
|
||||
all_pages = cache.get('all_pages')
|
||||
@@ -43,7 +42,7 @@ def content_menus(request):
|
||||
break
|
||||
current_path = current_path[0:current_path.rfind('.')]
|
||||
|
||||
return {'top_menu_items': top_menu_items,
|
||||
return {'top_menu_items': top_level_pages,
|
||||
'current_top_page': current_top_page,
|
||||
'current_path': current_path,
|
||||
'current_page': current_page
|
||||
|
||||
@@ -9,8 +9,6 @@ from django.utils.feedgenerator import Rss201rev2Feed
|
||||
from models import Article
|
||||
|
||||
|
||||
|
||||
# noinspection PyMethodMayBeStatic
|
||||
class LatestNews(Feed):
|
||||
link = "http://www.kasu.at/"
|
||||
description = _("Current news from Kasu")
|
||||
|
||||
@@ -12,12 +12,11 @@ import json
|
||||
class Command(BaseCommand):
|
||||
help = "Synchornisiert den Facenbook Feed für die Anzeige auf der Homepage"
|
||||
|
||||
|
||||
def handle(self, *args, **options):
|
||||
#graph_api = facebook.GraphAPI(settings.FACEBOOK_ACCESS_TOKEN)
|
||||
#facebook_page = graph_api.get_object(settings.FACEBOOK_APP_ID+'/feed/')
|
||||
#print facebook_page
|
||||
#print graph_api.get_connections(facebook_page['id'], )
|
||||
# print facebook_page
|
||||
# print graph_api.get_connections(facebook_page['id'], )
|
||||
self.login()
|
||||
|
||||
def login(self):
|
||||
|
||||
@@ -7,7 +7,6 @@ from django.conf import settings
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
@@ -16,17 +15,36 @@ class Migration(migrations.Migration):
|
||||
migrations.CreateModel(
|
||||
name='Article',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('headline_de', models.CharField(max_length=255, verbose_name='Schlagzeile')),
|
||||
('headline_en', models.CharField(max_length=255, verbose_name=b'Headline', blank=True)),
|
||||
('id', models.AutoField(
|
||||
verbose_name='ID',
|
||||
serialize=False, auto_created=True,
|
||||
primary_key=True)),
|
||||
('headline_de', models.CharField(
|
||||
max_length=255, verbose_name='Schlagzeile')),
|
||||
('headline_en', models.CharField(
|
||||
max_length=255, verbose_name=b'Headline', blank=True)),
|
||||
('content_de', models.TextField(verbose_name='Inhalt')),
|
||||
('content_en', models.TextField(verbose_name=b'Content', blank=True)),
|
||||
('image', models.ImageField(upload_to=b'news/', null=True, verbose_name='Bild', blank=True)),
|
||||
('slug', models.SlugField(unique_for_month=b'date_created', verbose_name='Slug')),
|
||||
('status', models.SmallIntegerField(default=1, verbose_name='Status', choices=[(-1, 'Zur\xfcckgewiesen'), (0, 'Wartend...'), (1, 'Ver\xf6ffentlicht')])),
|
||||
('date_created', models.DateTimeField(verbose_name='Erstellt', blank=True)),
|
||||
('date_modified', models.DateTimeField(auto_now=True, verbose_name='Bearbeitet')),
|
||||
('author', models.ForeignKey(verbose_name='Autor', to=settings.AUTH_USER_MODEL)),
|
||||
('content_en', models.TextField(
|
||||
verbose_name=b'Content', blank=True)),
|
||||
('image', models.ImageField(
|
||||
upload_to=b'news/',
|
||||
null=True, verbose_name='Bild',
|
||||
blank=True)),
|
||||
('slug', models.SlugField(
|
||||
unique_for_month=b'date_created', verbose_name='Slug')),
|
||||
('status',
|
||||
models.SmallIntegerField(
|
||||
default=1, verbose_name='Status',
|
||||
choices=[
|
||||
(-1, 'Zur\xfcckgewiesen'),
|
||||
(0, 'Wartend...'),
|
||||
(1, 'Ver\xf6ffentlicht')])),
|
||||
('date_created', models.DateTimeField(
|
||||
verbose_name='Erstellt', blank=True)),
|
||||
('date_modified', models.DateTimeField(
|
||||
auto_now=True, verbose_name='Bearbeitet')),
|
||||
('author', models.ForeignKey(
|
||||
verbose_name='Autor', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'ordering': ('-date_created',),
|
||||
@@ -37,12 +55,22 @@ class Migration(migrations.Migration):
|
||||
migrations.CreateModel(
|
||||
name='Category',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('name_de', models.CharField(max_length=80, verbose_name='Name')),
|
||||
('name_en', models.CharField(max_length=80, verbose_name='Name', blank=True)),
|
||||
('description_de', models.TextField(verbose_name='Beschreibung')),
|
||||
('description_en', models.TextField(verbose_name='Beschreibung', blank=True)),
|
||||
('image', models.ImageField(upload_to=b'news/categories/', null=True, verbose_name='Bild', blank=True)),
|
||||
('id', models.AutoField(
|
||||
verbose_name='ID',
|
||||
serialize=False, auto_created=True,
|
||||
primary_key=True)),
|
||||
('name_de',
|
||||
models.CharField(max_length=80, verbose_name='Name')),
|
||||
('name_en', models.CharField(
|
||||
max_length=80, verbose_name='Name', blank=True)),
|
||||
('description_de',
|
||||
models.TextField(verbose_name='Beschreibung')),
|
||||
('description_en', models.TextField(
|
||||
verbose_name='Beschreibung', blank=True)),
|
||||
('image', models.ImageField(
|
||||
upload_to=b'news/categories/',
|
||||
null=True, verbose_name='Bild',
|
||||
blank=True)),
|
||||
('slug', models.SlugField(unique=True, verbose_name='Slug')),
|
||||
],
|
||||
options={
|
||||
@@ -54,23 +82,57 @@ class Migration(migrations.Migration):
|
||||
migrations.CreateModel(
|
||||
name='Page',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('menu_name_de', models.CharField(help_text='Ein kurzer Name f\xfcr den Men\xfceintrag', max_length=255, verbose_name=b'Men\xc3\xbc Name')),
|
||||
('menu_name_en', models.CharField(help_text='Ein kurzer Name f\xfcr den Men\xfceintrag', max_length=255, verbose_name=b'Menu Name', blank=True)),
|
||||
('title_de', models.CharField(help_text='Der Titel erscheint im HTML Header', max_length=255, verbose_name=b'Titel')),
|
||||
('title_en', models.CharField(help_text='Der Titel erscheint im HTML Header', max_length=255, verbose_name=b'Title', blank=True)),
|
||||
('id', models.AutoField(
|
||||
verbose_name='ID',
|
||||
serialize=False, auto_created=True,
|
||||
primary_key=True)),
|
||||
('menu_name_de', models.CharField(
|
||||
help_text='Ein kurzer Name f\xfcr den Men\xfceintrag',
|
||||
max_length=255, verbose_name=b'Men\xc3\xbc Name')),
|
||||
('menu_name_en', models.CharField(
|
||||
help_text='Ein kurzer Name f\xfcr den Men\xfceintrag',
|
||||
max_length=255, verbose_name=b'Menu Name', blank=True)),
|
||||
('title_de', models.CharField(
|
||||
help_text='Der Titel erscheint im HTML Header',
|
||||
max_length=255, verbose_name=b'Titel')),
|
||||
('title_en', models.CharField(
|
||||
help_text='Der Titel erscheint im HTML Header',
|
||||
max_length=255, verbose_name=b'Title', blank=True)),
|
||||
('slug', models.SlugField(verbose_name='Slug')),
|
||||
('path', models.CharField(verbose_name='Pfad', unique=True, max_length=100, editable=False, db_index=True)),
|
||||
('position', models.PositiveSmallIntegerField(null=True, verbose_name='Position', blank=True)),
|
||||
('status', models.SmallIntegerField(default=0, verbose_name='Status', choices=[(-1, 'Zur\xfcckgewiesen'), (0, 'Wartend...'), (1, 'Ver\xf6ffentlicht')])),
|
||||
('content_type', models.IntegerField(choices=[(0, 'Django View'), (1, 'HTML'), (2, 'PDF')])),
|
||||
('content_de', models.TextField(verbose_name=b'Inhalt', blank=True)),
|
||||
('content_en', models.TextField(verbose_name=b'Content', blank=True)),
|
||||
('enable_comments', models.BooleanField(default=True, verbose_name='Kommentare m\xf6glich')),
|
||||
('template', models.CharField(default=b'content/page.html', max_length=100, verbose_name='Vorlage')),
|
||||
('pdf_de', models.FileField(null=True, upload_to=b'pdf/de/', blank=True)),
|
||||
('pdf_en', models.FileField(null=True, upload_to=b'pdf/en/', blank=True)),
|
||||
('parent', models.ForeignKey(related_name='subpages', on_delete=django.db.models.deletion.SET_NULL, blank=True, to='content.Page', null=True)),
|
||||
('path', models.CharField(
|
||||
verbose_name='Pfad', unique=True,
|
||||
max_length=100, editable=False,
|
||||
db_index=True)),
|
||||
('position', models.PositiveSmallIntegerField(
|
||||
null=True, verbose_name='Position', blank=True)),
|
||||
('status',
|
||||
models.SmallIntegerField(
|
||||
default=0, verbose_name='Status',
|
||||
choices=[
|
||||
(-1, 'Zur\xfcckgewiesen'),
|
||||
(0, 'Wartend...'),
|
||||
(1, 'Ver\xf6ffentlicht')])),
|
||||
('content_type', models.IntegerField(choices=[
|
||||
(0, 'Django View'), (1, 'HTML'), (2, 'PDF')])),
|
||||
('content_de',
|
||||
models.TextField(verbose_name=b'Inhalt', blank=True)),
|
||||
('content_en', models.TextField(
|
||||
verbose_name=b'Content', blank=True)),
|
||||
('enable_comments', models.BooleanField(
|
||||
default=True, verbose_name='Kommentare m\xf6glich')),
|
||||
('template', models.CharField(
|
||||
default=b'content/page.html',
|
||||
max_length=100,
|
||||
verbose_name='Vorlage')),
|
||||
('pdf_de', models.FileField(
|
||||
null=True, upload_to=b'pdf/de/', blank=True)),
|
||||
('pdf_en', models.FileField(
|
||||
null=True, upload_to=b'pdf/en/', blank=True)),
|
||||
('parent', models.ForeignKey(
|
||||
related_name='subpages',
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
blank=True, to='content.Page',
|
||||
null=True)),
|
||||
],
|
||||
options={
|
||||
'ordering': ['parent__id', 'position'],
|
||||
@@ -81,7 +143,8 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='article',
|
||||
name='category',
|
||||
field=models.ForeignKey(verbose_name='Kategorie', to='content.Category'),
|
||||
field=models.ForeignKey(
|
||||
verbose_name='Kategorie', to='content.Category'),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='page',
|
||||
|
||||
38
src/content/migrations/0002_auto_20150823_2232.py
Normal file
38
src/content/migrations/0002_auto_20150823_2232.py
Normal file
@@ -0,0 +1,38 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
import ckeditor.fields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('content', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='article',
|
||||
name='content_de',
|
||||
field=ckeditor.fields.RichTextField(verbose_name='Inhalt'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='article',
|
||||
name='content_en',
|
||||
field=ckeditor.fields.RichTextField(
|
||||
verbose_name=b'Content', blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='page',
|
||||
name='content_de',
|
||||
field=ckeditor.fields.RichTextField(
|
||||
verbose_name=b'Inhalt', blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='page',
|
||||
name='content_en',
|
||||
field=ckeditor.fields.RichTextField(
|
||||
verbose_name=b'Content', blank=True),
|
||||
),
|
||||
]
|
||||
@@ -11,9 +11,6 @@ from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import get_language, ugettext as _
|
||||
from django.core.exceptions import ValidationError
|
||||
from ckeditor.fields import RichTextField
|
||||
|
||||
|
||||
from kasu.image_models import ImageModel
|
||||
from utils import STATUS_CHOICES, STATUS_WAITING, STATUS_PUBLISHED, \
|
||||
cleaner
|
||||
|
||||
@@ -42,11 +39,15 @@ def get_upload_path(instance, filename):
|
||||
|
||||
|
||||
class ArticleManager(models.Manager):
|
||||
|
||||
def get_queryset(self):
|
||||
return super(ArticleManager, self).get_queryset().select_related('author', 'category')
|
||||
|
||||
def published(self):
|
||||
return self.filter(status=STATUS_PUBLISHED, date_created__lte=now())
|
||||
|
||||
|
||||
class Article(ImageModel):
|
||||
class Article(models.Model):
|
||||
headline_de = models.CharField(_('Headline'), max_length=255)
|
||||
headline_en = models.CharField('Headline', max_length=255, blank=True)
|
||||
content_de = RichTextField(_('Content'))
|
||||
@@ -80,11 +81,11 @@ class Article(ImageModel):
|
||||
return self.headline
|
||||
|
||||
@property
|
||||
def posting_image(self):
|
||||
def get_image(self):
|
||||
if self.image:
|
||||
return self.article
|
||||
return self.image
|
||||
else:
|
||||
return self.category.article
|
||||
return self.category.image
|
||||
|
||||
def get_absolute_url(self):
|
||||
kwargs = {
|
||||
@@ -219,7 +220,7 @@ class Page(models.Model):
|
||||
verbose_name_plural = _('Pages')
|
||||
|
||||
|
||||
class Category(ImageModel):
|
||||
class Category(models.Model):
|
||||
name_de = models.CharField(_('Name'), max_length=80)
|
||||
name_en = models.CharField(_('Name'), max_length=80, blank=True)
|
||||
description_de = models.TextField(_('Description'))
|
||||
|
||||
@@ -1,32 +1,33 @@
|
||||
{% extends "base.html" %}
|
||||
{% load i18n comments %}
|
||||
{% load i18n comments thumbnail %}
|
||||
|
||||
{% block title %}
|
||||
{% trans 'Article Archive' %}
|
||||
{% if active_category %} - {{active_category.name}}{% endif %}
|
||||
{% if month %}{{ month|date:'F Y' }}</h2>{% elif year %}{{year}}{% endif %}
|
||||
{% if month %}{{ month|date:'F Y' }}{% elif year %}{{year}}{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block meta_title %}
|
||||
{% trans 'Article Archive' %}
|
||||
{% if active_category %} - {{active_category.name}}{% endif %}
|
||||
{% if month %}{{ month|date:'F Y' }}</h2>{% elif year %}{{year}}{% endif %}
|
||||
{% endblock %}
|
||||
{% block jumbotron_background %}{% spaceless %}
|
||||
{% if active_category %}
|
||||
{{ active_category.image.url }}
|
||||
{% else %}
|
||||
{{STATIC_URL}}img/teaser/{{current_top_page.slug}}.jpg
|
||||
{% endif %}
|
||||
{% endspaceless %}{% endblock %}
|
||||
|
||||
{% block jumbotron_background %}{% if active_category %}{{ active_category.image.url }}{% else %}{{STATIC_URL}}img/teaser/{{current_top_page.slug}}.jpg{% endif %}{% endblock %}
|
||||
|
||||
{% block teaser %}<h1>
|
||||
{% block teaser %}
|
||||
<h1>
|
||||
{% trans 'Article Archive' %}
|
||||
{% if active_category %} - {{active_category.name}}{% endif %}
|
||||
{% if month %}{{ month|date:'F Y' }}{% elif year %}{{year}}{% endif %}
|
||||
</h1>
|
||||
<div id="teaser_text">
|
||||
</h1>
|
||||
<div id="teaser_text">
|
||||
{% if active_category %}
|
||||
<p>{{ active_category.description }}</p>
|
||||
{% else %}
|
||||
{{current_page.content|safe}}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block redbox %}
|
||||
@@ -67,7 +68,7 @@
|
||||
<li><span class="fa fa-user" title="{% trans 'by' %}"></span> {{ article.author }}</li>
|
||||
<li><span class="fa fa-comments" title="{% trans 'comments' %}"></span> <a href="{{article.get_absolute_url}}#comments" >{{comment_count}} {% trans "comments" %}</a></li>
|
||||
</ul>
|
||||
<a href="{{article.get_absolute_url}}"><img src="{{article.posting_image.url}}" alt="{{article.category}}:" class="posting_image" width="200" height="120"/></a>
|
||||
<a href="{{article.get_absolute_url}}"><img src="{{article.get_image|thumbnail_url:'article'}}" alt="{{article.category}}:" class="posting_image" width="200" height="120"/></a>
|
||||
{{article.content|truncatewords_html:50}}
|
||||
<p class="more_link"><a href="{{article.get_absolute_url}}" class="button">{% trans "Read More"%} <span class="fa fa-arrow-right"></span></a></p>
|
||||
</article>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "base.html" %}
|
||||
{% load i18n comments %}
|
||||
{% load i18n comments thumbnail %}
|
||||
|
||||
{% block title %}{{ article.headline }}{% endblock %}
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="og:title" content="{{ article.headline|force_escape }}" />
|
||||
<meta property="og:url" content="http://www.kasu.at{{ article.get_absolute_url }}" />
|
||||
<meta property="og:image" content="http://www.kasu.at{{article.posting_image.url}}" />
|
||||
<meta property="og:image" content="http://www.kasu.at{{article.get_image|thumbnail_url:'article'}}" />
|
||||
<meta property="og:description" content="{{article.content|striptags|truncatewords:25|force_escape}}" />
|
||||
<link rel="image_src" type="image/jpeg" href="{{article.posting_image.url}}" />
|
||||
<link rel="image_src" type="image/jpeg" href="{{article.get_image|thumbnail_url:'article'}}" />
|
||||
{% endblock %}
|
||||
|
||||
{% block itemscope %}itemscope itemtype="http://schema.org/Article"{% endblock %}
|
||||
@@ -21,7 +21,7 @@
|
||||
<div id="teaser_text">
|
||||
<ul class="info">
|
||||
<li><span class="fa fa-user"></span> <strong>{% trans 'Author' %}:</strong> <a href="{% url 'membership-details' article.author %}" itemprop="author">{{article.author}}</a></li>
|
||||
<li><span class="fa fa-calendar-o"></span> <strong>{% trans 'Created on' %}: </strong><time datetime="{{article.date_created|date:'Y-m-d H:i'}}">{{ article.date_created|date }}</time></li>
|
||||
<li><span class="fa fa-calendar-o"></span> <strong>{% trans 'Created on' %}: </strong><time datetime="{{article.date_created|date:'Y-m-d H:i'}}">{{ article.date_created|date:'DATE_FORMAT' }}</time></li>
|
||||
<li><span class="fa fa-tag"></span> <strong>{% trans "Category"%}: </strong><a href="{{ article.category.get_absolute_url }}" itemprop="articleSection">{{article.category.name}}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
{% block maincontent %}
|
||||
<div itemprop="articleBody" class="grid_12">
|
||||
<img alt="{{article.category.name}}" src="{{article.posting_image.url}}" class="posting_image" itemprop="image"/>
|
||||
<img alt="{{article.category.name}}" src="{{article.get_image|thumbnail_url:'article'}}" class="posting_image" itemprop="image"/>
|
||||
{{ article.content }}
|
||||
</div>
|
||||
<p class="right">
|
||||
|
||||
@@ -13,6 +13,7 @@ register = template.Library()
|
||||
|
||||
|
||||
class FieldSetNode(template.Node):
|
||||
|
||||
def __init__(self, form_variable, variable_name, fields):
|
||||
self.fields = fields
|
||||
self.variable_name = variable_name
|
||||
|
||||
@@ -9,6 +9,7 @@ from django.test import TestCase
|
||||
|
||||
|
||||
class SimpleTest(TestCase):
|
||||
|
||||
def test_basic_addition(self):
|
||||
"""
|
||||
Tests that 1 + 1 always equals 2.
|
||||
|
||||
@@ -8,15 +8,16 @@ from django.utils.translation import ugettext as _
|
||||
from django.views import generic
|
||||
|
||||
from . import models, forms
|
||||
from aggregator.models import Feed
|
||||
from events.models import Photo
|
||||
from utils.mixins import PermissionRequiredMixin
|
||||
|
||||
|
||||
class ArticleArchiveMixin(object):
|
||||
|
||||
def get_category(self, queryset):
|
||||
try:
|
||||
self.category = models.Category.objects.get(slug=self.kwargs['category'])
|
||||
self.category = models.Category.objects.get(
|
||||
slug=self.kwargs['category'])
|
||||
return queryset.filter(category=self.category)
|
||||
except models.Category.DoesNotExist:
|
||||
raise Http404(_("This Category does not exist."))
|
||||
@@ -28,7 +29,6 @@ class ArticleArchiveMixin(object):
|
||||
context = super(ArticleArchiveMixin, self).get_context_data(**kwargs)
|
||||
context['categories'] = models.Category.objects.all()
|
||||
context['active_category'] = self.category
|
||||
context['feeds'] = Feed.objects.active()
|
||||
return context
|
||||
|
||||
|
||||
@@ -99,6 +99,7 @@ class ArticleForm(PermissionRequiredMixin, generic.UpdateView):
|
||||
|
||||
class ImageList(generic.View):
|
||||
# noinspection PyMethodMayBeStatic
|
||||
|
||||
def get(self, kwargs):
|
||||
image_list = []
|
||||
response = HttpResponse(content_type='text/javascript')
|
||||
@@ -146,6 +147,7 @@ class PageEditForm(PermissionRequiredMixin, generic.UpdateView):
|
||||
|
||||
|
||||
class PageHtml(generic.DetailView):
|
||||
|
||||
def get_object(self, queryset=None):
|
||||
try:
|
||||
return models.Page.objects.get(path=self.kwargs['path'],
|
||||
@@ -160,6 +162,7 @@ class PageHtml(generic.DetailView):
|
||||
|
||||
|
||||
class PagePdf(generic.DeleteView):
|
||||
|
||||
def get_object(self, queryset=None):
|
||||
try:
|
||||
return models.Page.objects.get(path=self.kwargs['path'],
|
||||
@@ -183,6 +186,7 @@ class PagePdf(generic.DeleteView):
|
||||
|
||||
class PageList(generic.View):
|
||||
# noinspection PyMethodMayBeStatic
|
||||
|
||||
def get(self, kwargs):
|
||||
response = HttpResponse(content_type='text/javascript')
|
||||
response.write('var tinyMCELinkList = new Array(')
|
||||
@@ -212,7 +216,7 @@ class StartPage(generic.TemplateView):
|
||||
context = {
|
||||
'title': page.title,
|
||||
'content': page.content,
|
||||
'random_photo': random_photo.callout,
|
||||
'random_photo': random_photo,
|
||||
'recent_article_list': models.Article.objects.published()[:3],
|
||||
'recent_comment_list': recent_comment_list,
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ Created on 19.09.2011
|
||||
"""
|
||||
# import stuff we need from django
|
||||
from django.contrib import admin
|
||||
from imagekit.admin import AdminThumbnail
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from events.models import Event, Photo, Location
|
||||
@@ -19,7 +18,7 @@ class EventInline(admin.TabularInline):
|
||||
|
||||
class EventAdmin(admin.ModelAdmin):
|
||||
list_display = ('name', 'start', 'end', 'location',)
|
||||
list_editable = ('start', 'end', 'location',)
|
||||
list_editable = ('start', 'end', 'location')
|
||||
readonly_fields = ('event_series',)
|
||||
date_hierarchy = 'start'
|
||||
search_fields = ('name', 'description')
|
||||
@@ -32,12 +31,11 @@ class LocationAdmin(admin.ModelAdmin):
|
||||
|
||||
|
||||
class PhotoAdmin(admin.ModelAdmin):
|
||||
admin_thumbnail = AdminThumbnail(image_field='thumbnail')
|
||||
# admin_thumbnail = AdminThumbnail(image_field='thumbnail')
|
||||
fields = ('image', 'event', 'name', 'description',
|
||||
('anchor_horizontal', 'anchor_vertical'),
|
||||
('photographer', 'created_date'))
|
||||
list_filter = ('event', 'on_startpage',)
|
||||
list_display = ('admin_thumbnail', 'image', 'name', 'event',
|
||||
list_display = ('image', 'image', 'name', 'event',
|
||||
'photographer', 'on_startpage')
|
||||
list_display_links = ('image',)
|
||||
list_editable = ('on_startpage', 'name', 'event', 'photographer')
|
||||
|
||||
@@ -4,12 +4,30 @@ Created on 30.09.2011
|
||||
|
||||
@author: christian
|
||||
"""
|
||||
from . import models
|
||||
from django.core.cache import cache
|
||||
from .models import Event
|
||||
|
||||
|
||||
def upcoming_events(request):
|
||||
current_event = cache.get('current_event', False)
|
||||
next_event = cache.get('next_event', False)
|
||||
upcoming_events = cache.get('upcoming_events', False)
|
||||
|
||||
if current_event == False:
|
||||
current_event = Event.objects.current_event()
|
||||
cache.set('current_event', current_event, 360)
|
||||
if next_event == False:
|
||||
next_event = Event.objects.next_event()
|
||||
cache.set('next_event', next_event, 360)
|
||||
|
||||
if not upcoming_events and current_event:
|
||||
upcoming_events = Event.objects.upcoming(limit=3)
|
||||
cache.set('upcoming_events', upcoming_events, 360)
|
||||
elif not upcoming_events:
|
||||
upcoming_events = Event.objects.upcoming()[1:4]
|
||||
cache.set('upcoming_events', upcoming_events, 360)
|
||||
return {
|
||||
'current_event': models.Event.objects.current_event(),
|
||||
'next_event': models.Event.objects.next_event(),
|
||||
'upcoming_events': models.Event.objects.upcoming(),
|
||||
'current_event': current_event,
|
||||
'next_event': next_event,
|
||||
'upcoming_events': upcoming_events
|
||||
}
|
||||
|
||||
@@ -38,7 +38,6 @@ class EditPhotoForm(forms.ModelForm):
|
||||
class Meta(object):
|
||||
model = models.Photo
|
||||
fields = ('event', 'name', 'description', 'photographer',
|
||||
'anchor_horizontal', 'anchor_vertical',
|
||||
'created_date', 'on_startpage')
|
||||
|
||||
|
||||
@@ -59,4 +58,5 @@ class EventForm(forms.ModelForm):
|
||||
model = models.Event
|
||||
exclude = ('event_count', 'event_series', )
|
||||
|
||||
EventSeriesFormset = forms.inlineformset_factory(models.Event, models.Event, fields=('start', 'end'), form=EventForm)
|
||||
EventSeriesFormset = forms.inlineformset_factory(
|
||||
models.Event, models.Event, fields=('start', 'end'), form=EventForm)
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -18,11 +18,13 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='event',
|
||||
name='mahjong_season',
|
||||
field=models.PositiveSmallIntegerField(null=True, verbose_name='Mahjong Season', blank=True),
|
||||
field=models.PositiveSmallIntegerField(
|
||||
null=True, verbose_name='Mahjong Season', blank=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='event',
|
||||
name='mahjong_tournament',
|
||||
field=models.BooleanField(default=False, help_text='Diese Veranstaltung ist ein Turnier, es gelten andere Regeln f\xfcr das Kyu Ranking.', verbose_name='Mahjong Tournament'),
|
||||
field=models.BooleanField(
|
||||
default=False, help_text='Diese Veranstaltung ist ein Turnier, es gelten andere Regeln f\xfcr das Kyu Ranking.', verbose_name='Mahjong Tournament'),
|
||||
),
|
||||
]
|
||||
|
||||
20
src/events/migrations/0003_auto_20150823_2232.py
Normal file
20
src/events/migrations/0003_auto_20150823_2232.py
Normal file
@@ -0,0 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('events', '0002_auto_20150818_2139'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='event',
|
||||
name='mahjong_tournament',
|
||||
field=models.BooleanField(
|
||||
default=False, help_text='Diese Veranstaltung ist ein Turnier, es gelten andere Regeln f\xfcr das Kyu Ranking.', verbose_name='Mahjong Turnier'),
|
||||
),
|
||||
]
|
||||
91
src/events/migrations/0004_auto_20150901_2204.py
Normal file
91
src/events/migrations/0004_auto_20150901_2204.py
Normal file
@@ -0,0 +1,91 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
import ckeditor.fields
|
||||
import events.models
|
||||
import easy_thumbnails.fields
|
||||
import django.db.models.deletion
|
||||
import utils
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('events', '0003_auto_20150823_2232'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Photo',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID',
|
||||
serialize=False, auto_created=True, primary_key=True)),
|
||||
('name', models.CharField(max_length=100,
|
||||
verbose_name='Name', blank=True)),
|
||||
('image', easy_thumbnails.fields.ThumbnailerImageField(
|
||||
upload_to=events.models.get_upload_path, storage=utils.OverwriteStorage(), verbose_name='Bild')),
|
||||
('description', models.TextField(max_length=300,
|
||||
verbose_name='Beschreibung', blank=True)),
|
||||
('on_startpage', models.BooleanField(default=False,
|
||||
help_text='Display this Photo on the Startpage Teaser', verbose_name='Startpage')),
|
||||
('created_date', models.DateTimeField(verbose_name='Published on')),
|
||||
('views', models.PositiveIntegerField(default=0,
|
||||
verbose_name='Number of views', editable=False)),
|
||||
],
|
||||
options={
|
||||
'ordering': ['created_date'],
|
||||
'db_table': 'events_photo',
|
||||
'verbose_name': 'Veranstaltungsbild',
|
||||
'verbose_name_plural': 'Event Images',
|
||||
'get_latest_by': 'created_date',
|
||||
},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='event',
|
||||
options={'ordering': (
|
||||
'start', 'end'), 'verbose_name': 'Termin', 'verbose_name_plural': 'Termine'},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='event',
|
||||
name='description',
|
||||
field=ckeditor.fields.RichTextField(
|
||||
verbose_name='Beschreibung', blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='event',
|
||||
name='event_series',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, blank=True, to='events.Event',
|
||||
help_text='Wenn dieser Termin zu einer Veranstaltungsreihe geh\xf6rt werden Ort, Beschreibung, Bild und Homepage von dem hier angegebenen Event \xfcbernommen.', null=True, verbose_name='Veranstaltungsreihen'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='event',
|
||||
name='image',
|
||||
field=easy_thumbnails.fields.ThumbnailerImageField(storage=utils.OverwriteStorage(
|
||||
), upload_to=events.models.get_upload_path, null=True, verbose_name='Bild', blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='location',
|
||||
name='description',
|
||||
field=ckeditor.fields.RichTextField(
|
||||
verbose_name='Beschreibung', blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='location',
|
||||
name='image',
|
||||
field=easy_thumbnails.fields.ThumbnailerImageField(storage=utils.OverwriteStorage(
|
||||
), upload_to=events.models.get_upload_path, null=True, verbose_name='Bild', blank=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='photo',
|
||||
name='event',
|
||||
field=models.ForeignKey(to='events.Event'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='photo',
|
||||
name='photographer',
|
||||
field=models.ForeignKey(to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
||||
20
src/events/migrations/0005_auto_20150907_2021.py
Normal file
20
src/events/migrations/0005_auto_20150907_2021.py
Normal file
@@ -0,0 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('events', '0004_auto_20150901_2204'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='photo',
|
||||
name='on_startpage',
|
||||
field=models.BooleanField(
|
||||
default=False, help_text='Display this Photo on the Startpage Teaser', db_index=True, verbose_name='Startpage'),
|
||||
),
|
||||
]
|
||||
@@ -1,14 +1,17 @@
|
||||
# -'- Encoding: utf-8 -*-
|
||||
|
||||
import os
|
||||
from django.conf import settings
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.db import models
|
||||
from django.db.models import Q
|
||||
from django.template.defaultfilters import slugify
|
||||
from django.utils.timezone import now
|
||||
from django.utils.translation import ugettext as _
|
||||
from ckeditor.fields import RichTextField
|
||||
from easy_thumbnails.fields import ThumbnailerImageField
|
||||
|
||||
from utils import COUNTRIES, OverwriteStorage
|
||||
from gallery.models import Photo
|
||||
from kasu import image_models
|
||||
|
||||
|
||||
def get_upload_path(instance, filename):
|
||||
@@ -22,63 +25,87 @@ def get_upload_path(instance, filename):
|
||||
@param filename: The filename of the uploaded image.
|
||||
@type filename: String
|
||||
"""
|
||||
extension = filename[filename.rfind('.') + 1:]
|
||||
filename, extension = os.path.splitext(filename.lower())
|
||||
if isinstance(instance, Event):
|
||||
if instance.id:
|
||||
return "events/%s.%s" % (instance.id, extension)
|
||||
else:
|
||||
return "events/%s.%s" % (slugify(instance.name), extension)
|
||||
return "events/{date:%Y-%m-%d}/{name}{ext}".format(
|
||||
date=instance.start,
|
||||
name=slugify(instance.name),
|
||||
ext=extension
|
||||
)
|
||||
elif isinstance(instance, Location):
|
||||
if instance.id:
|
||||
return "events/location/%s.%s" % (instance.id, extension)
|
||||
else:
|
||||
return "events/location/%s.%s" % (instance.id, extension)
|
||||
return "events/locations/{name}{ext}".format(
|
||||
name=slugify(instance.name),
|
||||
ext=extension
|
||||
)
|
||||
elif isinstance(instance, Photo):
|
||||
return "events/%s/%s" % (instance.event.id, filename)
|
||||
return "events/{date:%Y-%m-%d}/{name}{ext}".format(
|
||||
date=instance.event.start,
|
||||
name=filename,
|
||||
ext=extension
|
||||
)
|
||||
|
||||
|
||||
class EventManager(models.Manager):
|
||||
|
||||
def get_queryset(self):
|
||||
return super(EventManager, self).get_queryset().select_related('location')
|
||||
|
||||
def current_event(self):
|
||||
try:
|
||||
current = self.filter(start__lte=now())
|
||||
current = current.filter(end__gte=now())
|
||||
return current.order_by('start', 'end')[0]
|
||||
except:
|
||||
except IndexError:
|
||||
return None
|
||||
|
||||
def next_event(self):
|
||||
try:
|
||||
return self.filter(start__gt=now()).order_by('start', 'end')[0]
|
||||
except:
|
||||
except IndexError:
|
||||
return None
|
||||
|
||||
def archive(self):
|
||||
return self.filter(start__lt=now())
|
||||
|
||||
def upcoming(self, limit=3):
|
||||
def latest_events(self, num=3):
|
||||
return self.filter(start__lt=now()).order_by('-start', '-end')[:num]
|
||||
|
||||
def upcoming(self, limit=None):
|
||||
result = self.filter(start__gt=now()).order_by('start', 'end')
|
||||
if limit:
|
||||
return result[1:(limit + 1)]
|
||||
return result[0:limit]
|
||||
else:
|
||||
return result
|
||||
|
||||
|
||||
class Event(image_models.ImageModel):
|
||||
class Event(models.Model):
|
||||
name = models.CharField(_('Name'), max_length=255)
|
||||
description = models.TextField(_("Description"), blank=True)
|
||||
description = RichTextField(_("Description"), blank=True)
|
||||
location = models.ForeignKey('Location')
|
||||
start = models.DateTimeField(_('Start'))
|
||||
end = models.DateTimeField(_('End'), blank=True, null=True)
|
||||
url = models.URLField(_('Homepage'), blank=True)
|
||||
image = models.ImageField(_("Image"), upload_to=get_upload_path,
|
||||
storage=OverwriteStorage(), blank=True, null=True)
|
||||
mahjong_tournament = models.BooleanField(_('Mahjong Tournament'), default=False,
|
||||
image = ThumbnailerImageField(
|
||||
_("Image"),
|
||||
upload_to=get_upload_path,
|
||||
storage=OverwriteStorage(),
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
mahjong_tournament = models.BooleanField(
|
||||
_('Mahjong Tournament'),
|
||||
default=False,
|
||||
help_text=_(u'This event is a tournament, different rules apply for \
|
||||
the kyu ranking.'))
|
||||
mahjong_season = models.PositiveSmallIntegerField(_('Mahjong Season'), blank=True, null=True)
|
||||
the kyu ranking.')
|
||||
)
|
||||
mahjong_season = models.PositiveSmallIntegerField(
|
||||
_('Mahjong Season'),
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
photo_count = models.PositiveIntegerField(default=0, editable=False)
|
||||
event_series = models.ForeignKey('Event', blank=True, null=True,
|
||||
on_delete=models.SET_NULL, editable=False,
|
||||
on_delete=models.SET_NULL, editable=True,
|
||||
verbose_name=_('Event Series'),
|
||||
help_text=_(u'Wenn dieser Event zu einer Veranstaltungsreihe gehört \
|
||||
werden Ort, Beschreibung, Bild und Homepage von dem hier angegebenen \
|
||||
@@ -89,7 +116,7 @@ class Event(image_models.ImageModel):
|
||||
class Meta(object):
|
||||
verbose_name = _('Event')
|
||||
verbose_name_plural = _('Events')
|
||||
ordering = ('-start', '-end',)
|
||||
ordering = ('start', 'end',)
|
||||
|
||||
def __unicode__(self):
|
||||
try:
|
||||
@@ -122,23 +149,13 @@ class Event(image_models.ImageModel):
|
||||
}
|
||||
return reverse('event-form', kwargs=kwargs)
|
||||
|
||||
def get_callout(self):
|
||||
def get_image(self):
|
||||
if self.image:
|
||||
return self.callout
|
||||
elif self.photo_set.count():
|
||||
return self.photo_set.all().order_by('?')[0].callout
|
||||
return self.image
|
||||
elif self.photo_count:
|
||||
return self.photo_set.all().order_by('?')[0].image
|
||||
elif self.location.image:
|
||||
return self.location.callout
|
||||
else:
|
||||
return None
|
||||
|
||||
def get_thumbnail(self):
|
||||
if self.image:
|
||||
return self.thumbnail
|
||||
elif self.photo_set.count():
|
||||
return self.photo_set.all().order_by('?')[0].thumbnail
|
||||
elif self.location.image:
|
||||
return self.location.thumbnail
|
||||
return self.location.image
|
||||
else:
|
||||
return None
|
||||
|
||||
@@ -159,11 +176,16 @@ class Event(image_models.ImageModel):
|
||||
hanchan.save()
|
||||
|
||||
|
||||
class Location(image_models.ImageModel):
|
||||
class Location(models.Model):
|
||||
name = models.CharField(_("Name"), max_length=200)
|
||||
description = models.TextField(_("Description"), blank=True)
|
||||
image = models.ImageField(_("Image"), upload_to=get_upload_path,
|
||||
storage=OverwriteStorage(), blank=True, null=True)
|
||||
description = RichTextField(_("Description"), blank=True)
|
||||
image = ThumbnailerImageField(
|
||||
_("Image"),
|
||||
upload_to=get_upload_path,
|
||||
storage=OverwriteStorage(),
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
url = models.URLField(_('Homepage'), blank=True)
|
||||
postal_code = models.CharField(_('Postal Code'), max_length=6)
|
||||
street_address = models.CharField(_('Street Address'), max_length=127)
|
||||
@@ -183,7 +205,111 @@ class Location(image_models.ImageModel):
|
||||
return ','.join(address)
|
||||
|
||||
|
||||
models.signals.post_save.connect(image_models.regenerate_image_cache,
|
||||
sender=Event)
|
||||
models.signals.post_save.connect(image_models.regenerate_image_cache,
|
||||
sender=Location)
|
||||
class PhotoManager(models.Manager):
|
||||
|
||||
def get_random(self, startpage=True):
|
||||
if startpage:
|
||||
queryset = self.filter(on_startpage=True)
|
||||
else:
|
||||
queryset = self.all().order_by('?')[0]
|
||||
try:
|
||||
return queryset.order_by('?')[0]
|
||||
except IndexError:
|
||||
return Photo()
|
||||
|
||||
|
||||
class Photo(models.Model):
|
||||
name = models.CharField(_("Name"), max_length=100, blank=True)
|
||||
image = ThumbnailerImageField(_("Image"), upload_to=get_upload_path,
|
||||
storage=OverwriteStorage())
|
||||
event = models.ForeignKey('events.Event')
|
||||
description = models.TextField(
|
||||
_("Description"),
|
||||
max_length=300,
|
||||
blank=True
|
||||
)
|
||||
photographer = models.ForeignKey(settings.AUTH_USER_MODEL)
|
||||
on_startpage = models.BooleanField(
|
||||
_("Startpage"),
|
||||
default=False,
|
||||
db_index=True,
|
||||
help_text=_('Display this Photo on the Startpage Teaser')
|
||||
)
|
||||
created_date = models.DateTimeField(_("Published on"))
|
||||
views = models.PositiveIntegerField(
|
||||
_("Number of views"),
|
||||
editable=False,
|
||||
default=0
|
||||
)
|
||||
objects = PhotoManager()
|
||||
metadata = None
|
||||
orientation = 1
|
||||
|
||||
class Meta:
|
||||
get_latest_by = "created_date"
|
||||
ordering = ["created_date"]
|
||||
db_table = 'events_photo'
|
||||
verbose_name = _('Event Image')
|
||||
verbose_name_plural = _('Event Images')
|
||||
|
||||
def __unicode__(self):
|
||||
return os.path.basename(self.image.name)
|
||||
|
||||
def rotate(self, rotate):
|
||||
# TODO: Eine vernüftigte Methode ohne viele Abhängigkeiten finden um
|
||||
# die Bilder bei Bedarf zu drehen.
|
||||
if rotate == 'clockwise':
|
||||
pass
|
||||
elif rotate == 'counter-clockwise':
|
||||
pass
|
||||
self.save()
|
||||
|
||||
def save(self, **kwargs):
|
||||
super(Photo, self).save(**kwargs)
|
||||
self.event.save()
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse(
|
||||
'event-photo',
|
||||
kwargs={'event': self.event.id, 'pk': self.id}
|
||||
)
|
||||
|
||||
@property
|
||||
def next_photo(self):
|
||||
queryset = Photo.objects.filter(created_date__gt=self.created_date)
|
||||
queryset = queryset.order_by('created_date')
|
||||
try:
|
||||
if self.event.event_series:
|
||||
return queryset.filter(
|
||||
Q(event=self.event) |
|
||||
Q(event=self.event.event_series) |
|
||||
Q(event__event_series=self.event.event_series)
|
||||
)[0]
|
||||
else:
|
||||
return queryset.filter(
|
||||
Q(event=self.event) |
|
||||
Q(event__event_series=self.event)
|
||||
)[0]
|
||||
except IndexError:
|
||||
return None
|
||||
return self.get_next_by_created_date(event=self.event)
|
||||
|
||||
@property
|
||||
def previous_photo(self):
|
||||
queryset = Photo.objects.filter(created_date__lt=self.created_date)
|
||||
queryset = queryset.order_by('-created_date')
|
||||
try:
|
||||
if self.event.event_series:
|
||||
return queryset.filter(
|
||||
Q(event=self.event) |
|
||||
Q(event=self.event.event_series) |
|
||||
Q(event__event_series=self.event.event_series)
|
||||
)[0]
|
||||
else:
|
||||
return queryset.filter(
|
||||
Q(event=self.event) |
|
||||
Q(event__event_series=self.event)
|
||||
)[0]
|
||||
except IndexError:
|
||||
return None
|
||||
return self.get_previous_by_created_date(event=self.event)
|
||||
|
||||
11
src/events/static/js/mousetrap.js
Normal file
11
src/events/static/js/mousetrap.js
Normal file
@@ -0,0 +1,11 @@
|
||||
/* mousetrap v1.5.3 craig.is/killing/mice */
|
||||
(function(C,r,g){function t(a,b,h){a.addEventListener?a.addEventListener(b,h,!1):a.attachEvent("on"+b,h)}function x(a){if("keypress"==a.type){var b=String.fromCharCode(a.which);a.shiftKey||(b=b.toLowerCase());return b}return l[a.which]?l[a.which]:p[a.which]?p[a.which]:String.fromCharCode(a.which).toLowerCase()}function D(a){var b=[];a.shiftKey&&b.push("shift");a.altKey&&b.push("alt");a.ctrlKey&&b.push("ctrl");a.metaKey&&b.push("meta");return b}function u(a){return"shift"==a||"ctrl"==a||"alt"==a||
|
||||
"meta"==a}function y(a,b){var h,c,e,g=[];h=a;"+"===h?h=["+"]:(h=h.replace(/\+{2}/g,"+plus"),h=h.split("+"));for(e=0;e<h.length;++e)c=h[e],z[c]&&(c=z[c]),b&&"keypress"!=b&&A[c]&&(c=A[c],g.push("shift")),u(c)&&g.push(c);h=c;e=b;if(!e){if(!k){k={};for(var m in l)95<m&&112>m||l.hasOwnProperty(m)&&(k[l[m]]=m)}e=k[h]?"keydown":"keypress"}"keypress"==e&&g.length&&(e="keydown");return{key:c,modifiers:g,action:e}}function B(a,b){return null===a||a===r?!1:a===b?!0:B(a.parentNode,b)}function c(a){function b(a){a=
|
||||
a||{};var b=!1,n;for(n in q)a[n]?b=!0:q[n]=0;b||(v=!1)}function h(a,b,n,f,c,h){var g,e,l=[],m=n.type;if(!d._callbacks[a])return[];"keyup"==m&&u(a)&&(b=[a]);for(g=0;g<d._callbacks[a].length;++g)if(e=d._callbacks[a][g],(f||!e.seq||q[e.seq]==e.level)&&m==e.action){var k;(k="keypress"==m&&!n.metaKey&&!n.ctrlKey)||(k=e.modifiers,k=b.sort().join(",")===k.sort().join(","));k&&(k=f&&e.seq==f&&e.level==h,(!f&&e.combo==c||k)&&d._callbacks[a].splice(g,1),l.push(e))}return l}function g(a,b,n,f){d.stopCallback(b,
|
||||
b.target||b.srcElement,n,f)||!1!==a(b,n)||(b.preventDefault?b.preventDefault():b.returnValue=!1,b.stopPropagation?b.stopPropagation():b.cancelBubble=!0)}function e(a){"number"!==typeof a.which&&(a.which=a.keyCode);var b=x(a);b&&("keyup"==a.type&&w===b?w=!1:d.handleKey(b,D(a),a))}function l(a,c,n,f){function e(c){return function(){v=c;++q[a];clearTimeout(k);k=setTimeout(b,1E3)}}function h(c){g(n,c,a);"keyup"!==f&&(w=x(c));setTimeout(b,10)}for(var d=q[a]=0;d<c.length;++d){var p=d+1===c.length?h:e(f||
|
||||
y(c[d+1]).action);m(c[d],p,f,a,d)}}function m(a,b,c,f,e){d._directMap[a+":"+c]=b;a=a.replace(/\s+/g," ");var g=a.split(" ");1<g.length?l(a,g,b,c):(c=y(a,c),d._callbacks[c.key]=d._callbacks[c.key]||[],h(c.key,c.modifiers,{type:c.action},f,a,e),d._callbacks[c.key][f?"unshift":"push"]({callback:b,modifiers:c.modifiers,action:c.action,seq:f,level:e,combo:a}))}var d=this;a=a||r;if(!(d instanceof c))return new c(a);d.target=a;d._callbacks={};d._directMap={};var q={},k,w=!1,p=!1,v=!1;d._handleKey=function(a,
|
||||
c,e){var f=h(a,c,e),d;c={};var k=0,l=!1;for(d=0;d<f.length;++d)f[d].seq&&(k=Math.max(k,f[d].level));for(d=0;d<f.length;++d)f[d].seq?f[d].level==k&&(l=!0,c[f[d].seq]=1,g(f[d].callback,e,f[d].combo,f[d].seq)):l||g(f[d].callback,e,f[d].combo);f="keypress"==e.type&&p;e.type!=v||u(a)||f||b(c);p=l&&"keydown"==e.type};d._bindMultiple=function(a,b,c){for(var d=0;d<a.length;++d)m(a[d],b,c)};t(a,"keypress",e);t(a,"keydown",e);t(a,"keyup",e)}var l={8:"backspace",9:"tab",13:"enter",16:"shift",17:"ctrl",18:"alt",
|
||||
20:"capslock",27:"esc",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",45:"ins",46:"del",91:"meta",93:"meta",224:"meta"},p={106:"*",107:"+",109:"-",110:".",111:"/",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"},A={"~":"`","!":"1","@":"2","#":"3",$:"4","%":"5","^":"6","&":"7","*":"8","(":"9",")":"0",_:"-","+":"=",":":";",'"':"'","<":",",">":".","?":"/","|":"\\"},z={option:"alt",command:"meta","return":"enter",
|
||||
escape:"esc",plus:"+",mod:/Mac|iPod|iPhone|iPad/.test(navigator.platform)?"meta":"ctrl"},k;for(g=1;20>g;++g)l[111+g]="f"+g;for(g=0;9>=g;++g)l[g+96]=g;c.prototype.bind=function(a,b,c){a=a instanceof Array?a:[a];this._bindMultiple.call(this,a,b,c);return this};c.prototype.unbind=function(a,b){return this.bind.call(this,a,function(){},b)};c.prototype.trigger=function(a,b){if(this._directMap[a+":"+b])this._directMap[a+":"+b]({},a);return this};c.prototype.reset=function(){this._callbacks={};this._directMap=
|
||||
{};return this};c.prototype.stopCallback=function(a,b){return-1<(" "+b.className+" ").indexOf(" mousetrap ")||B(b,this.target)?!1:"INPUT"==b.tagName||"SELECT"==b.tagName||"TEXTAREA"==b.tagName||b.isContentEditable};c.prototype.handleKey=function(){return this._handleKey.apply(this,arguments)};c.init=function(){var a=c(r),b;for(b in a)"_"!==b.charAt(0)&&(c[b]=function(b){return function(){return a[b].apply(a,arguments)}}(b))};c.init();C.Mousetrap=c;"undefined"!==typeof module&&module.exports&&(module.exports=
|
||||
c);"function"===typeof define&&define.amd&&define(function(){return c})})(window,document);
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "events/page.html" %}
|
||||
{% load i18n comments%}
|
||||
{% load i18n comments thumbnail %}
|
||||
|
||||
{% block title %}
|
||||
{% trans 'Event Archive' %} {% if month %}{{ month|date:'F Y' }} {% else %}{% if year %}{{year}}{% endif %}{% endif %}
|
||||
@@ -32,14 +32,19 @@
|
||||
<h3 class="grid_12">{{ month.grouper }}</h3>
|
||||
{% for event in month.list %}
|
||||
{% get_comment_count for event as comment_count %}
|
||||
<a href="{{ event.get_absolute_url }}" class="grid_2"><img src="{{ event.get_thumbnail.url }}"
|
||||
alt="{% trans 'Event Image' %}"
|
||||
class="thumbnail"/></a>
|
||||
<div class="grid_4">
|
||||
<h4><a href="{{ event.get_absolute_url }}">{{ event.name }}</a></h4>
|
||||
|
||||
<p><span class="fa fa-calendar-o" title="{% trans 'Start' %}"></span>
|
||||
{{ event.start|date }}
|
||||
<div class="grid_6">
|
||||
<a href="{{ event.get_absolute_url }}" class="thumbnail"><img src="{{ event.get_image|thumbnail_url:'thumbnail' }}"
|
||||
alt="{% trans 'Event Image' %}" width="140" height="140"/></a>
|
||||
|
||||
<h4><a href="{{ event.get_absolute_url }}">{{ event.name }}</a></h4>
|
||||
<p>
|
||||
<span class="fa fa-calendar-o" title="{% trans 'Date' %}" aria-label="{% trans 'Date' %}"></span>
|
||||
<time datetime="{{event.start|date:'c'}}">
|
||||
{{ event.start|date:'D' }}
|
||||
{{ event.start|date:'SHORT_DATE_FORMAT' }} {{hanchan.start|time:'H:i'}}
|
||||
</time>
|
||||
<span class="fa fa-clock-o" title="{% trans 'Time' %}" aria-label="{% trans 'Time' %}"></span>
|
||||
{% if event.end %}
|
||||
{% trans "from" %} {{ event.start|time:'H:i' }} {% trans "to" %} {{ event.end|time:'H:i' }}
|
||||
{% else %}
|
||||
@@ -59,7 +64,6 @@
|
||||
<p class="right"><a href="{{ event.get_edit_url }}" class="button"><span class="fa fa-pencil"></span></a></p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if forloop.counter|divisibleby:2 %}<br class="clear"/>{% endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "events/page.html" %}
|
||||
{% load i18n django_markdown comments %}
|
||||
{% load i18n comments thumbnail %}
|
||||
|
||||
{% block title %}{{ event.name }}{% endblock %}
|
||||
|
||||
@@ -8,19 +8,19 @@
|
||||
<meta property="og:title" content="{{event.name}}" />
|
||||
<meta property="og:url" content="http://www.kasu.at{{event.get_absolute_url}}" />
|
||||
<meta property="og:image" content="http://www.kasu.at{{ event.get_thumbnail.url }}" />
|
||||
{% if event.description %}<meta property="og:description" content="{{event.description}}" />{% endif %}
|
||||
{% if event.description %}<meta property="og:description" content="{{event.description|striptags}}" />{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_head %}
|
||||
<script type="text/javascript" src="https://maps.google.com/maps/api/js?sensor=false"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block jumbotron_background %} {{ event.get_callout.url }} {% endblock %}
|
||||
{% block jumbotron_background %} {{ event.get_image|thumbnail_url:'callout' }} {% endblock %}
|
||||
|
||||
{% block teaser %}
|
||||
<h1>{{event.name}}</h1>
|
||||
{% if event.description %}
|
||||
<div id="teaser_text">{{event.description|markdown|truncatewords_html:75}}</div>
|
||||
<div id="teaser_text">{{event.description|truncatewords_html:75|safe}}</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -48,10 +48,8 @@
|
||||
<li><a href="{% url 'event-photo-list' event.pk %}"><span class="fa fa-camera-retro"></span> {{ event.photo_count }} {% trans 'Photos' %}</a></li>
|
||||
<li><a href="{% url 'event-hanchan-list' event.pk %}" ><span class="fa fa-table"></span> {{ event.hanchan_set.count }} {% trans "Hanchans" %}</a></li>
|
||||
<li><a href="{% url 'maistar-game-list' event.pk %}" ><span class="fa fa-glass"></span> {{ event.maistargame_set.count }} {% trans "Mai-Star Games" %}</a></li>
|
||||
|
||||
{% if event.mahjong_tournament %}
|
||||
<li><a href="{% url 'event-ranking' event.id %}"><span class="fa fa-trophy"></span> {% trans "Tournament Ranking" %}</a></li>
|
||||
{% endif %}
|
||||
<li><a href="{% url 'event-ranking' event.id %}"><span
|
||||
class="fa fa-trophy"></span> {% trans "Event Ranking" %}</a></li>
|
||||
</ul>
|
||||
{% endblock %}
|
||||
|
||||
@@ -81,16 +79,30 @@
|
||||
|
||||
<div class="grid_12">
|
||||
{% if event.description %}
|
||||
{{event.description|markdown}}
|
||||
{{event.description|safe}}
|
||||
{% else %}
|
||||
{{event.location.description|markdown}}
|
||||
{{event.location.description|safe}}
|
||||
{% endif %}
|
||||
<p class="more_link">
|
||||
<a href="https://plus.google.com/share?url=http%3A%2F%2Fwww.kasu.at{{event.get_absolute_url|urlencode}}" onclick="javascript:window.open(this.href,
|
||||
'', 'menubar=no,toolbar=no,resizable=yes,scrollbars=yes,height=600,width=600');return false;"><img src="{{STATIC_URL}}img/google_plus.png" alt="Google+" title="{% trans 'Share on Google+'%}" width="39" height="39"/></a>
|
||||
<a href="https://twitter.com/share?url=http%3A%2F%2Fwww.kasu.at{{event.get_absolute_url|urlencode}}" target='_blank'><img src="{{STATIC_URL}}img/twitter.png" alt="Twitter" title=" {% trans 'Share on Twitter' %}" width="39" height="39"/></a>
|
||||
<a href="http://facebook.com/sharer.php?u=http%3A%2F%2Fwww.kasu.at{{event.get_absolute_url|urlencode}}" target="_blank"><img src="{{STATIC_URL}}img/facebook.png" alt="Facebook" title="{% trans 'Share on Facebook'%}" width="39" height="39"/></a>
|
||||
<a href="http://maps.google.com/maps?q={{event.location.address|urlencode}}&z=16" target="gmaps"><img src="{{ STATIC_URL }}img/google_maps.png" alt="Google Maps" title="{% trans 'Show on Google Maps' %}" width="39" height="39"/></a>
|
||||
|
||||
<a class="button" href="http://facebook.com/sharer.php?u=http%3A%2F%2Fwww.kasu.at{{event.get_absolute_url|urlencode}}" target="_blank">
|
||||
<span class="fa fa-facebook"></span>
|
||||
{% trans 'Share on Facebook'%}
|
||||
</a>
|
||||
|
||||
<a class="button" href="https://plus.google.com/share?url=http%3A%2F%2Fwww.kasu.at{{event.get_absolute_url|urlencode}}" onclick="javascript:window.open(this.href,
|
||||
'', 'menubar=no,toolbar=no,resizable=yes,scrollbars=yes,height=600,width=600');return false;">
|
||||
<span class="fa fa-google-plus"></span>
|
||||
{% trans 'Share on Google+'%}
|
||||
</a>
|
||||
<a class="button" href="https://twitter.com/share?url=http%3A%2F%2Fwww.kasu.at{{event.get_absolute_url|urlencode}}" target='_blank'>
|
||||
<span class="fa fa-twitter"></span>
|
||||
{% trans 'Share on Twitter' %}
|
||||
</a>
|
||||
<a class="button" href="http://maps.google.com/maps?q={{event.location.address|urlencode}}&z=16" target="gmaps">
|
||||
<span class="fa fa-map"></span>
|
||||
{% trans 'Show on Google Maps' %}
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
<br class="clear" />
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "events/page.html" %}
|
||||
{% load i18n comments%}
|
||||
{% load i18n comments thumbnail %}
|
||||
|
||||
{% block title %}{% trans "Upcoming Events" %}{% endblock %}
|
||||
{% block teaser%}<h2>{% trans "Upcoming Events" %}</h2>{% endblock %}
|
||||
@@ -10,22 +10,33 @@
|
||||
<h3 class="grid_12">{{ month.grouper }}</h3>
|
||||
{% for event in month.list %}
|
||||
{% get_comment_count for event as comment_count %}
|
||||
<a href="{{ event.get_absolute_url }}" class="grid_2"><img
|
||||
src="{{ event.get_thumbnail.url }}" alt=" {% trans 'Event Image' %}" class="thumbnail"/></a>
|
||||
<div class="grid_4">
|
||||
<div class="grid_6">
|
||||
{% if perms.events.change_event %}
|
||||
<a href="{{ event.get_edit_url }}" class="button" style="float:right"><span class="fa fa-pencil"></span></a>
|
||||
{% endif %}
|
||||
{% if perms.events.add_photo %}
|
||||
<a href="{% url 'event-photo-list' event.pk %}" class="button" style="float:right"><span class="fa fa-camera-retro"></span></a>
|
||||
{% endif %}
|
||||
<a href="{{ event.get_absolute_url }}" class="thumbnail"><img
|
||||
src="{{ event.get_image|thumbnail_url:'thumbnail' }}" alt="{% trans 'Event Image' %}" width="140" height="140"/>
|
||||
</a>
|
||||
<h4><a href="{{ event.get_absolute_url }}">{{ event.name }}</a></h4>
|
||||
<ul class="info">
|
||||
<li><span class="fa fa-calendar-o" title="{% trans 'Date' %}"></span> <time datetime="{{event.start|date:'c'}}">{{ event.start|date:'SHORT_DATE_FORMAT' }}</time></li>
|
||||
<li><span class="fa fa-map-marker" title="{% trans 'Location' %}"></span> {{ event.location }}</li>
|
||||
<li><span class="fa fa-comments" title="{% trans 'Comments' %}"></span> <a href="{{event.get_absolute_url}}#comments">{{ comment_count }}</a></li>
|
||||
<li><span class="fa fa-calendar-o" title="{% trans 'Date' %}" aria-label="{% trans 'Date' %}"></span>
|
||||
<time datetime="{{event.start|date:'c'}}">
|
||||
{{ event.start|date:'D' }}
|
||||
{{ event.start|date:'SHORT_DATE_FORMAT' }}
|
||||
</time>
|
||||
</li>
|
||||
<li><span class="fa fa-clock-o" title="{% trans 'Start' %}" aria-label="{% trans 'Start' %}"></span>
|
||||
{{ event.start|time:'H:i' }}
|
||||
</li>
|
||||
|
||||
<li><span class="fa fa-map-marker" title="{% trans 'Location' %}" aria-label="{% trans 'Location' %}"></span>
|
||||
{{ event.location }}
|
||||
</li>
|
||||
<li><span class="fa fa-comments" title="{% trans 'Comments' %}" aria-label="{% trans 'Comments' %}"></span>
|
||||
<a href="{{event.get_absolute_url}}#comments">{{ comment_count }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
<p>{{event.description|truncatewords_html:20}}</p>
|
||||
<p>{{event.description|truncatewords_html:25|safe}}</p>
|
||||
</div>
|
||||
{% if forloop.counter|divisibleby:2 %}<br class="clear">{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "base.html" %}
|
||||
{% load i18n django_markdown%}
|
||||
{% load i18n %}
|
||||
|
||||
{% block title %}{{ event.name }}{% endblock %}
|
||||
|
||||
@@ -11,12 +11,12 @@
|
||||
{% if event.description %}<meta property="og:description" content="{{event.description}}" />{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block jumbotron_background %}{{ event.get_callout.url }}')}{% endblock %}
|
||||
{% block jumbotron_background %} {{ event.get_image|thumbnail_url:'callout' }} {% endblock %}
|
||||
|
||||
{% block teaser %}
|
||||
<h1>{{event.name}}</h1>
|
||||
<div id="teaser_text">
|
||||
{% if event.description %}{{event.description|markdown}}{% else %}{{event.location.description|markdown}}{% endif %}
|
||||
{% if event.description %}{{event.description}}{% else %}{{event.location.description}}{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@@ -1,15 +1,8 @@
|
||||
{% extends "events/event_detail.html" %}
|
||||
{% load i18n django_markdown comments %}
|
||||
{% load i18n comments %}
|
||||
|
||||
{% block title %}{{ event.name }}{% endblock %}
|
||||
|
||||
{% block teaser %}
|
||||
<h1>{{event.name}}</h1>
|
||||
{% if event.description %}
|
||||
<div id="teaser_text">{{event.description|markdown|truncatewords_html:75}}</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block event_content %}
|
||||
<h3>Hier kommt eine Tabelle rein!</h3>
|
||||
<form class="grid_12" method="post">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "events/event_detail.html" %}
|
||||
{% load i18n comments %}
|
||||
{% load i18n comments thumbnail %}
|
||||
|
||||
{% block maincontent %}
|
||||
<form action="" method="post" class="grid_12">
|
||||
@@ -8,13 +8,16 @@
|
||||
<h1 class="grid_12">Dieses Photo wirklich löschen?</h1>
|
||||
</header>
|
||||
<p>Sind Sie sicher, dass Sie das Bild “{{photo.name}}” löschen wollen?</p>
|
||||
<img src="{{photo.display.url}}" alt="{{photo.name}}" title="{{photo.name}}" class="grid_10 push_1"/>
|
||||
<img src="{{photo.image|thumbnail_url:'display'}}" alt="{{photo.name}}" title="{{photo.name}}" class="grid_10 push_1"/>
|
||||
<br class="clear"/>
|
||||
<p> </p>
|
||||
<p class="buttonbar">
|
||||
<a href="{% url 'event-photo-list' photo.event.id %}" class="button" style="float: left;"><img
|
||||
src="{{STATIC_URL}}icons/cancel.png" alt="{% trans 'Cancel' %}"/> {% trans 'Cancel' %}</a>
|
||||
<button type="submit"><img src="{{STATIC_URL}}icons/delete.png" alt="{% trans 'Delete' %}"/>
|
||||
<a class="button" href="{% url 'event-photo-list' photo.event.id %}" style="float: left;">
|
||||
<span class="fa fa-ban"></span>
|
||||
{% trans 'Cancel' %}
|
||||
</a>
|
||||
<button type="submit">
|
||||
<span class="fa fa-trash"></span>
|
||||
{% trans 'Delete' %}
|
||||
</button>
|
||||
</p>
|
||||
85
src/events/templates/events/photo_detail.html
Normal file
85
src/events/templates/events/photo_detail.html
Normal file
@@ -0,0 +1,85 @@
|
||||
{% extends "events/event_detail.html" %}
|
||||
{% load i18n comments thumbnail %}
|
||||
|
||||
{% block title %} {{ photo.name }} - {{ photo.event.name }} {% endblock %}
|
||||
|
||||
{% block extra_head %}
|
||||
<script type="text/javascript" src="{{ STATIC_URL }}/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="{{ STATIC_URL }}/js/mousetrap.js"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block javascript %}
|
||||
if ($('a.previous').attr('href')) {
|
||||
Mousetrap.bind('left', function() { window.location = $('a.previous').attr('href'); });
|
||||
}
|
||||
if ($('a.next').attr('href')) {
|
||||
Mousetrap.bind('right', function() { window.location = $('a.next').attr('href'); });
|
||||
}
|
||||
{% endblock %}
|
||||
|
||||
{% block teaser %}
|
||||
<h1 class="grid_12">{{event.name}} - {{ photo.name }}</h1>
|
||||
{% if event.description %}
|
||||
<div id="teaser_text">{{event.description|truncatewords_html:75}}</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block opengraph %}
|
||||
<meta property="og:type" content="photo" />
|
||||
<meta property="og:title" content="{{photo.name}} - Foto" />
|
||||
<meta property="og:url" content="http://www.kasu.at{{photo.get_absolute_url}}" />
|
||||
<meta property="og:image" content="http://www.kasu.at{{photo.thumbnail.url}}" />
|
||||
{% if photo.description %}<meta property="og:description" content="{{photo.description}}" />{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block maincontent %}
|
||||
<div id="display" class="grid_12">
|
||||
<img src="{{photo.image|thumbnail_url:'display'}}" alt="{{photo.name}}" title="{{photo.name}}"/>
|
||||
{% if photo.previous_photo %}
|
||||
<a href="{% url 'event-photo' photo.previous_photo.event.id photo.previous_photo.id %}#display" class="previous" id="previous">{% trans 'previous' %}</a>
|
||||
{% endif %}
|
||||
{% if photo.next_photo %}
|
||||
<a href="{% url 'event-photo' photo.next_photo.event.id photo.next_photo.id %}#display" class="next" id="next">Next</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="grid_12">
|
||||
<ul class="info">
|
||||
<li><span class="fa fa-user"></span> <strong>{% trans 'Photographer' %}: </strong>{{ photo.photographer }}</li>
|
||||
<li><span class="fa fa-calendar-o"></span> <strong>{% trans 'Date' %}</strong> {{ photo.created_date }}</li>
|
||||
</ul>
|
||||
<p>{{ photo.description }}</p>
|
||||
</div>
|
||||
<p class="right">
|
||||
<strong>{% trans 'share on' %}:</strong>
|
||||
<a class="button" href="http://facebook.com/sharer.php?u=http%3A%2F%2Fwww.kasu.at{{photo.get_absolute_url|urlencode}}" target="_blank" rel="nofollow">
|
||||
<span class="fa fa-twitter"></span>Facebook
|
||||
</a>
|
||||
<a class="button" href="https://m.google.com/app/plus/x/?v=compose&content={{photo.headline|urlencode}}+-+http%3A%2F%2Fwww.kasu.at/{{photo.get_absolute_url|urlencode}}" target="_blank" rel="nofollow">
|
||||
<span class="fa fa-google-plus"></span> Google+
|
||||
</a>
|
||||
<a class="button" href="https://twitter.com/share?url=http%3A%2F%2Fwww.kasu.at/{{photo.get_absolute_url|urlencode}}" target='_blank' rel="nofollow">
|
||||
<span class="fa fa-twitter"></span> Twitter
|
||||
</a>
|
||||
</p>
|
||||
{% endblock %}
|
||||
|
||||
{% block comment %}
|
||||
{% render_comment_list for photo %}
|
||||
{% render_comment_form for photo %}
|
||||
{% endblock %}
|
||||
|
||||
{% block buttonbar %}
|
||||
{% if perms.events.change_photo %}
|
||||
<form method="post" enctype="multipart/form-data" class="grid_12">
|
||||
{% csrf_token %}
|
||||
<p class="buttonbar">
|
||||
<a href="{{ photo.image.url }}" class="button" type="application/octet-stream"><span class="fa fa-download"></span> {% trans 'download' %}</a>
|
||||
<button type="submit" name="rotate" value="counter-clockwise"><span class="fa fa-undo"></span> {% trans 'Rotate counter clockwise' %}</button>
|
||||
<button type="submit" name="rotate" value="clockwise"><span class="fa fa-repeat"></span> {% trans 'Rotate clockwise' %}</button>
|
||||
<button type="submit"><span class="fa fa-check"></span> {% trans 'Save' %}</button>
|
||||
</p>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{% extends "base.html" %}
|
||||
{% load i18n %}
|
||||
{% load i18n thumbnail %}
|
||||
|
||||
{% block maincontent %}
|
||||
{% for event in event_list %}
|
||||
<div class="gallery grid_4">
|
||||
<h3><a href="{% url 'event-photo-list' event.id %}">{{event.name}}</a></h3>
|
||||
<a href="{% url 'event-photo-list' event.id %}"><img src="{{event.get_thumbnail.url}}" class="thumbnail" alt="{{ event.name }}"/></a>
|
||||
<a href="{% url 'event-photo-list' event.id %}"><img src="{{event.get_image|thumbnail_url:'thumbnail' }}" class="thumbnail" alt="{{ event.name }}"/></a>
|
||||
</div>
|
||||
{% empty %}
|
||||
<p>Sorry da kommt erst was hin!</p>
|
||||
45
src/events/templates/events/photo_list.html
Normal file
45
src/events/templates/events/photo_list.html
Normal file
@@ -0,0 +1,45 @@
|
||||
{% extends "events/event_detail.html" %}
|
||||
{% load i18n thumbnail %}
|
||||
|
||||
{% block title %}{{event.name}}{% endblock %}
|
||||
|
||||
{% block opengraph %}
|
||||
<meta property="og:type" content="album" />
|
||||
<meta property="og:title" content="{{event.name}}" />
|
||||
<meta property="og:url" content="http://www.kasu.at{% url 'event-photo-list' event.pk %}" />
|
||||
<meta property="og:image" content="http://www.kasu.at{{ event.get_thumbnail.url }}" />
|
||||
{% if event.description %}<meta property="og:description" content="{{event.description}}" />{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block maincontent %}
|
||||
|
||||
{% for photo in photo_list %}
|
||||
<div class="thumbnail">
|
||||
<a href="{% url 'event-photo' event.id photo.id %}"><img src="{{photo.image|thumbnail_url:'thumbnail'}}" alt=""/></a>
|
||||
{% if perms.events.delete_photo %}
|
||||
<a href="{% url 'delete-event-photo' photo.pk %}" class="button delete_image">
|
||||
<span class="fa fa-trash" aria-label="{% trans 'Delete' %}" title="{% trans 'Delete' %}"></span>
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
|
||||
{% if perms.events.add_photo %}
|
||||
<form action="{% url 'event-photo-upload' event.id %}" method="post" enctype="multipart/form-data" class="grid_12">
|
||||
{% csrf_token %}
|
||||
<fieldset>
|
||||
<legend>Photos hochladen</legend>
|
||||
{% include "form.html"%}
|
||||
<p class="buttonbar">
|
||||
<button type="reset"><span class="fa fa-undo"></span> {% trans 'reset' %}</button>
|
||||
<button type="submit"><span class="fa fa-cloud-upload"></span> {% trans 'Upload' %}</button>
|
||||
</p>
|
||||
</fieldset>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block buttonbar %}{% endblock %}
|
||||
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
{% extends "base.html" %}
|
||||
{% load i18n comments %}
|
||||
{% load i18n comments thumbnail %}
|
||||
|
||||
{% block maincontent %}
|
||||
{% for event in event_list %}
|
||||
{% get_comment_count for event as comment_count %}
|
||||
{% ifchanged %}<h3 class="grid_12">{{ event.start|date:'F Y' }}</h3>{% endifchanged %}
|
||||
<div style="float:left">
|
||||
<a href="{% url 'event-photo-list' event.pk %}"><img src="{{ event.get_thumbnail.url }}" alt="" class="thumbnail"/></a>
|
||||
<a href="{% url 'event-photo-list' event.pk %}"><img src="{{ event.get_image|thumbnail_url:'thumbnail' }}" alt="" class="thumbnail"/></a>
|
||||
<div class="grid_4" />
|
||||
<h4><a href="{% url 'event-photo-list' event.pk %}">{{ event.name }}</a></h4>
|
||||
<div class="info">
|
||||
<img src="{{ STATIC_URL }}/icons/date.png" alt="{% trans 'Start' %}" title="{% trans 'Start' %}">
|
||||
<span class="fa fa-calendar-o" title="{% trans 'Start' %}"></span>
|
||||
{{ event.start|date }}
|
||||
{% if event.end %}
|
||||
{% trans "from" %} {{ event.start|time:'H:i' }} {% trans "to" %} {{ event.end|time:'H:i' }}
|
||||
@@ -20,16 +20,19 @@
|
||||
</div>
|
||||
{% if event.description %}<p>{{event.description}}</p>{% endif %}
|
||||
<div class="info">
|
||||
<img src="{{ STATIC_URL }}/icons/map.png" alt="{% trans 'Location' %}" title="{% trans 'Location' %}">
|
||||
<span class="fa fa-map-marker" title="{% trans 'Location' %}"></span>
|
||||
{{ event.location }}
|
||||
<img src="{{ STATIC_URL }}/icons/comments.png" alt="{% trans 'Comments' %}" title="{% trans 'Comments' %}">
|
||||
<span class="fa fa-comments" title="{% trans 'Comments' %}"></span>
|
||||
<a href="{{event.get_absolute_url}}#comments">{{ comment_count }} {% trans 'Comments' %}</a>
|
||||
<img src="{{ STATIC_URL }}/icons/images.png" alt="{% trans 'Photos' %}" title="{% trans 'Photos' %}">
|
||||
|
||||
<span class="fa fa-camera-retro" title="{% trans 'Photos' %}"></span>
|
||||
<a href="{% url 'event-photo-list' event.pk %}">{{ event.photo_count }} {% trans 'Photos' %}</a>
|
||||
</div>
|
||||
<p style="text-align:right">
|
||||
{% if perms.events.add_photo %}
|
||||
<a href="{% url 'event-photo-list' event.pk %}" class="button"><img src="{{ STATIC_URL }}icons/image_add.png" alt="{%trans "Upload" %}"></a>
|
||||
<a href="{% url 'event-photo-list' event.pk %}" class="button">
|
||||
<span class="fa fa-cloud-upload"></span>
|
||||
{%trans "Upload" %}</a>
|
||||
{% endif %}
|
||||
</p>
|
||||
</div></div>
|
||||
@@ -42,8 +45,8 @@
|
||||
{% include "form.html" %}
|
||||
<p class="buttonbar">
|
||||
<button type="submit">
|
||||
<img src="{{ STATIC_URL }}icons/drive_go.png" alt="" />
|
||||
{% trans "upload" %}
|
||||
<span class="fa fa-cloud-upload"></span>
|
||||
{% trans "Upload" %}
|
||||
</button>
|
||||
</p>
|
||||
</fieldset>
|
||||
@@ -9,6 +9,7 @@ from django.test import TestCase
|
||||
|
||||
|
||||
class SimpleTest(TestCase):
|
||||
|
||||
def test_basic_addition(self):
|
||||
"""
|
||||
Tests that 1 + 1 always equals 2.
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
from django.conf.urls import patterns, url
|
||||
|
||||
from django.views.generic import RedirectView
|
||||
from .views import *
|
||||
|
||||
urlpatterns = patterns(
|
||||
'',
|
||||
url(r'^$', UpcomingEvents.as_view(), name='upcoming-events'),
|
||||
url(r'^$', RedirectView.as_view(url='/events/upcoming/', permanent=True)),
|
||||
url(r'^(?P<year>[\d]{4})/$', EventArchiveYear.as_view(),
|
||||
name='event-archive'),
|
||||
url(r'^(?P<year>[\d]{4})/(?P<month>[\d]+)/$', EventArchiveMonth.as_view(),
|
||||
@@ -18,4 +18,5 @@ urlpatterns = patterns(
|
||||
EventForm.as_view(), name='event-form'),
|
||||
url(r'^add/$', EventForm.as_view(), name='event-form'),
|
||||
url(r'^archive/$', EventArchiveIndex.as_view(), name='event-archive'),
|
||||
url(r'^upcoming/$', UpcomingEvents.as_view(), name='upcoming-events'),
|
||||
)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
# Create your views here.
|
||||
from datetime import timedelta
|
||||
|
||||
from django.db.models import Q
|
||||
from django.contrib.auth.decorators import permission_required
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core.urlresolvers import reverse
|
||||
@@ -13,22 +14,23 @@ from django.utils.decorators import method_decorator
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.views import generic
|
||||
from icalendar import Calendar, Event
|
||||
import pyexiv2
|
||||
|
||||
from utils.mixins import PermissionRequiredMixin
|
||||
|
||||
from . import models, forms
|
||||
|
||||
|
||||
class DeleteEventPhoto(generic.DeleteView):
|
||||
model = models.Photo
|
||||
"""
|
||||
def get_object(self, queryset=None):
|
||||
return models.Photo.objects.get(pk=self.kwargs['pk'])
|
||||
"""
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse('event-photo-list', args=[self.object.event.id])
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(DeleteEventPhoto, self).get_context_data()
|
||||
context['event'] = self.object.event
|
||||
return context
|
||||
|
||||
@method_decorator(permission_required('events.delete_photo'))
|
||||
def dispatch(self, *args, **kwargs):
|
||||
return super(DeleteEventPhoto, self).dispatch(*args, **kwargs)
|
||||
@@ -39,10 +41,9 @@ class EventArchiveIndex(generic.ArchiveIndexView):
|
||||
context_object_name = 'event_list'
|
||||
date_field = 'start'
|
||||
model = models.Event
|
||||
queryset = model.objects.all()
|
||||
ordering = ('-start', '-end')
|
||||
paginate_by = 15
|
||||
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = generic.ArchiveIndexView.get_context_data(self, **kwargs)
|
||||
context['is_archive'] = True
|
||||
@@ -53,6 +54,7 @@ class EventArchiveMonth(generic.MonthArchiveView):
|
||||
date_field = 'start'
|
||||
make_object_list = True
|
||||
model = models.Event
|
||||
ordering = ('start', 'end')
|
||||
month_format = '%m'
|
||||
paginate_by = 15
|
||||
template_name = 'events/event_archive.html'
|
||||
@@ -64,9 +66,10 @@ class EventArchiveMonth(generic.MonthArchiveView):
|
||||
|
||||
|
||||
class EventArchiveYear(generic.YearArchiveView):
|
||||
model = models.Event
|
||||
date_field = 'start'
|
||||
make_object_list = True
|
||||
model = models.Event
|
||||
ordering = ('start', 'end')
|
||||
paginate_by = 15
|
||||
template_name = 'events/event_archive.html'
|
||||
year_format = '%Y'
|
||||
@@ -117,27 +120,13 @@ class EventForm(PermissionRequiredMixin, generic.UpdateView):
|
||||
return models.Event()
|
||||
|
||||
|
||||
class EventSeriesForm(EventDetailMixin, PermissionRequiredMixin, InlineFormSetView):
|
||||
model = models.Event
|
||||
inline_model = models.Event
|
||||
fk_name = 'event_series'
|
||||
fields = ('start', 'end')
|
||||
form_class = forms.EventForm
|
||||
extra = 3
|
||||
permission_required = 'events.add_event'
|
||||
template_name = 'events/eventseries_form.html'
|
||||
|
||||
def get_object(self, queryset=None):
|
||||
self.event = models.Event.objects.get(pk=self.kwargs['pk'])
|
||||
if self.event.event_series:
|
||||
self.event = self.event.event_series
|
||||
return self.event
|
||||
|
||||
|
||||
class EventGallery(generic.ListView):
|
||||
template_name = 'events/photo_gallery.html'
|
||||
queryset = models.Event.objects.filter(start__lt=timezone.now(),
|
||||
photo_count__gt=0)
|
||||
queryset = models.Event.objects.filter(
|
||||
start__lt=timezone.now(),
|
||||
event_series__isnull=True,
|
||||
photo_count__gt=0
|
||||
)
|
||||
paginate_by = 12
|
||||
|
||||
|
||||
@@ -180,7 +169,10 @@ class EventPhoto(generic.UpdateView):
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(EventPhoto, self).get_context_data()
|
||||
try:
|
||||
event = models.Event.objects.get(id=self.kwargs['event'])
|
||||
except models.Event.DoesNotExist:
|
||||
event = self.object.event
|
||||
context['event'] = event
|
||||
return context
|
||||
|
||||
@@ -209,7 +201,10 @@ class EventPhotoList(generic.ListView):
|
||||
def get_queryset(self):
|
||||
try:
|
||||
self.event = models.Event.objects.get(id=self.kwargs['event'])
|
||||
return models.Photo.objects.filter(event=self.event)
|
||||
return models.Photo.objects.filter(
|
||||
Q(event=self.event) |
|
||||
Q(event__event_series=self.event)
|
||||
)
|
||||
except models.Event.DoesNotExist:
|
||||
raise Http404(_('Event does not exist'))
|
||||
|
||||
@@ -261,20 +256,28 @@ class EventPhotoUpload(generic.FormView):
|
||||
return redirect('event-photo-list', event=self.event.id)
|
||||
|
||||
def read_exif(self, photo):
|
||||
exif_data = pyexiv2.ImageMetadata.from_buffer(photo.read())
|
||||
exif_data.read()
|
||||
|
||||
try:
|
||||
created_date = exif_data['Exif.Image.DateTime'].value
|
||||
except:
|
||||
created_date = self.event.start + timedelta(minutes=self.counter)
|
||||
try:
|
||||
description = exif_data['Exif.Image.ImageDescription'].value
|
||||
except:
|
||||
description = ''
|
||||
return created_date, description
|
||||
|
||||
|
||||
class EventSeriesForm(EventDetailMixin, PermissionRequiredMixin, InlineFormSetView):
|
||||
model = models.Event
|
||||
inline_model = models.Event
|
||||
fk_name = 'event_series'
|
||||
fields = ('start', 'end')
|
||||
form_class = forms.EventForm
|
||||
extra = 3
|
||||
permission_required = 'events.add_event'
|
||||
template_name = 'events/eventseries_form.html'
|
||||
|
||||
def get_object(self, queryset=None):
|
||||
self.event = models.Event.objects.get(pk=self.kwargs['pk'])
|
||||
if self.event.event_series:
|
||||
self.event = self.event.event_series
|
||||
return self.event
|
||||
|
||||
|
||||
class UpcomingEvents(generic.ListView):
|
||||
queryset = models.Event.objects.upcoming(limit=None)
|
||||
paginate_by = 16
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
__author__ = 'christian'
|
||||
@@ -1,42 +0,0 @@
|
||||
"""
|
||||
Created on 03.10.2011
|
||||
|
||||
@author: christian
|
||||
"""
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.contrib.auth import get_user_model
|
||||
|
||||
from . import models
|
||||
from events.models import Event
|
||||
|
||||
|
||||
user_query = get_user_model().objects.all()
|
||||
|
||||
|
||||
class PhotoUploadForm(forms.Form):
|
||||
error_css_class = 'error'
|
||||
required_css_class = 'required'
|
||||
photographer = forms.ModelChoiceField(user_query, required=True, )
|
||||
event = forms.ModelChoiceField(Event.objects.all(), required=True, )
|
||||
upload = forms.FileField(
|
||||
label=_('Images'),
|
||||
required=True,
|
||||
widget=forms.widgets.ClearableFileInput(
|
||||
attrs={
|
||||
'multiple': 'multiple',
|
||||
'accept': "image/gif,image/png,image/jpeg"
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class EditPhotoForm(forms.ModelForm):
|
||||
error_css_class = 'error'
|
||||
required_css_class = 'required'
|
||||
|
||||
class Meta(object):
|
||||
model = models.Photo
|
||||
fields = ('event', 'name', 'description', 'photographer',
|
||||
'anchor_horizontal', 'anchor_vertical',
|
||||
'created_date', 'on_startpage')
|
||||
@@ -1,154 +0,0 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-08-22 23:28+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: forms.py:23
|
||||
msgid "Images"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:44
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:45
|
||||
msgid "Image"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:48
|
||||
msgid "horizontal Anchorpoint"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:55
|
||||
msgid "vertical Anchorpoint"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:64
|
||||
msgid "Description"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:70
|
||||
msgid "Startpage"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:72
|
||||
msgid "Display this Photo on the Startpage Teaser"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:74
|
||||
msgid "Published on"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:76
|
||||
msgid "Number of views"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:88
|
||||
msgid "Event Image"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:89
|
||||
msgid "Event Images"
|
||||
msgstr ""
|
||||
|
||||
#: templates/gallery/photo_confirm_delete.html:16
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#: templates/gallery/photo_confirm_delete.html:17
|
||||
#: templates/gallery/photo_confirm_delete.html:18
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
|
||||
#: templates/gallery/photo_detail.html:19
|
||||
msgid "previous"
|
||||
msgstr ""
|
||||
|
||||
#: templates/gallery/photo_detail.html:27
|
||||
msgid "Share on Google+"
|
||||
msgstr ""
|
||||
|
||||
#: templates/gallery/photo_detail.html:28
|
||||
msgid "Share on Twitter"
|
||||
msgstr ""
|
||||
|
||||
#: templates/gallery/photo_detail.html:29
|
||||
msgid "Share on Facebook"
|
||||
msgstr ""
|
||||
|
||||
#: templates/gallery/photo_detail.html:33
|
||||
msgid "Photographer"
|
||||
msgstr ""
|
||||
|
||||
#: templates/gallery/photo_detail.html:34
|
||||
msgid "on"
|
||||
msgstr ""
|
||||
|
||||
#: templates/gallery/photo_detail.html:48
|
||||
msgid "download"
|
||||
msgstr ""
|
||||
|
||||
#: templates/gallery/photo_detail.html:51
|
||||
msgid "save"
|
||||
msgstr ""
|
||||
|
||||
#: templates/gallery/photo_list.html:20
|
||||
msgid "delete"
|
||||
msgstr ""
|
||||
|
||||
#: templates/gallery/photo_list.html:37
|
||||
msgid "reset"
|
||||
msgstr ""
|
||||
|
||||
#: templates/gallery/photo_list.html:38 templates/gallery/photo_upload.html:46
|
||||
msgid "upload"
|
||||
msgstr ""
|
||||
|
||||
#: templates/gallery/photo_upload.html:13
|
||||
msgid "Start"
|
||||
msgstr ""
|
||||
|
||||
#: templates/gallery/photo_upload.html:16
|
||||
msgid "from"
|
||||
msgstr ""
|
||||
|
||||
#: templates/gallery/photo_upload.html:16
|
||||
msgid "to"
|
||||
msgstr ""
|
||||
|
||||
#: templates/gallery/photo_upload.html:23
|
||||
msgid "Location"
|
||||
msgstr ""
|
||||
|
||||
#: templates/gallery/photo_upload.html:25
|
||||
#: templates/gallery/photo_upload.html:26
|
||||
msgid "Comments"
|
||||
msgstr ""
|
||||
|
||||
#: templates/gallery/photo_upload.html:27
|
||||
#: templates/gallery/photo_upload.html:28
|
||||
msgid "Photos"
|
||||
msgstr ""
|
||||
|
||||
#: templates/gallery/photo_upload.html:32
|
||||
msgid "Upload"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:80
|
||||
msgid "Event does not exist"
|
||||
msgstr ""
|
||||
@@ -1,41 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
import gallery.models
|
||||
import utils
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('events', '0001_initial'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Photo',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('name', models.CharField(max_length=100, verbose_name='Name', blank=True)),
|
||||
('image', models.ImageField(upload_to=gallery.models.get_upload_path, storage=utils.OverwriteStorage(), verbose_name='Bild')),
|
||||
('anchor_horizontal', models.FloatField(blank=True, help_text=b'Der Ankerpunkt ist der interessante Teil des Bildes, welcher nie abgeschnitten werden darf', null=True, verbose_name='horizontal Anchorpoint', choices=[(1e-08, 'Links'), (0.5, 'Mitte'), (1, 'Rechts')])),
|
||||
('anchor_vertical', models.FloatField(blank=True, help_text=b'Wenn kein Ankerpunkt von Hand (horizontal und vertikal) festgelegt wird, versucht die Software diesen selbst zu erraten.', null=True, verbose_name='vertical Anchorpoint', choices=[(1e-08, 'Oben'), (0.5, 'Mitte'), (1, 'Unten')])),
|
||||
('description', models.TextField(max_length=300, verbose_name='Beschreibung', blank=True)),
|
||||
('on_startpage', models.BooleanField(default=False, help_text='Display this Photo on the Startpage Teaser', verbose_name='Startpage')),
|
||||
('created_date', models.DateTimeField(verbose_name='Published on')),
|
||||
('views', models.PositiveIntegerField(default=0, verbose_name='Number of views', editable=False)),
|
||||
('event', models.ForeignKey(to='events.Event')),
|
||||
('photographer', models.ForeignKey(to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'ordering': ['created_date'],
|
||||
'db_table': 'events_photo',
|
||||
'verbose_name': 'Veranstaltungsbild',
|
||||
'verbose_name_plural': 'Event Images',
|
||||
'get_latest_by': 'created_date',
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -1,171 +0,0 @@
|
||||
# -'- Encoding: utf-8 -*-
|
||||
|
||||
import os
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext as _
|
||||
import pyexiv2
|
||||
|
||||
from utils import OverwriteStorage
|
||||
from kasu import image_models
|
||||
|
||||
|
||||
def get_upload_path(instance, filename):
|
||||
"""
|
||||
Generates the desired file path and filename for an uploaded Image.
|
||||
With this function Django can save the uploaded images to subfolders that
|
||||
also have a meaning for humans.
|
||||
|
||||
@param instance: an Django Object for which the Image has been uploaded.
|
||||
@type instance: a instace of an models.Model sub-class.
|
||||
@param filename: The filename of the uploaded image.
|
||||
@type filename: String
|
||||
"""
|
||||
extension = filename[filename.rfind('.') + 1:]
|
||||
if isinstance(instance, Photo):
|
||||
return "events/%s/%s" % (instance.event.id, filename)
|
||||
|
||||
|
||||
class PhotoManager(models.Manager):
|
||||
def get_random(self, startpage=True):
|
||||
if startpage:
|
||||
queryset = self.filter(on_startpage=True)
|
||||
else:
|
||||
queryset = self.all().order_by('?')[0]
|
||||
try:
|
||||
return queryset.order_by('?')[0]
|
||||
except IndexError:
|
||||
return Photo()
|
||||
|
||||
|
||||
class Photo(image_models.ImageModel):
|
||||
name = models.CharField(_("Name"), max_length=100, blank=True)
|
||||
image = models.ImageField(_("Image"), upload_to=get_upload_path,
|
||||
storage=OverwriteStorage())
|
||||
anchor_horizontal = models.FloatField(
|
||||
_('horizontal Anchorpoint'),
|
||||
choices=image_models.CHOICES_HORIZONTAL,
|
||||
blank=True, null=True,
|
||||
help_text='Der Ankerpunkt ist der interessante Teil des Bildes,\
|
||||
welcher nie abgeschnitten werden darf'
|
||||
)
|
||||
anchor_vertical = models.FloatField(
|
||||
_('vertical Anchorpoint'),
|
||||
choices=image_models.CHOICES_VERTICAL,
|
||||
blank=True, null=True,
|
||||
help_text='Wenn kein Ankerpunkt von Hand (horizontal und vertikal)\
|
||||
festgelegt wird, versucht die Software diesen selbst zu erraten.'
|
||||
)
|
||||
|
||||
event = models.ForeignKey('events.Event')
|
||||
description = models.TextField(
|
||||
_("Description"),
|
||||
max_length=300,
|
||||
blank=True
|
||||
)
|
||||
photographer = models.ForeignKey(settings.AUTH_USER_MODEL)
|
||||
on_startpage = models.BooleanField(
|
||||
_("Startpage"),
|
||||
default=False,
|
||||
help_text=_('Display this Photo on the Startpage Teaser')
|
||||
)
|
||||
created_date = models.DateTimeField(_("Published on"))
|
||||
views = models.PositiveIntegerField(
|
||||
_("Number of views"),
|
||||
editable=False,
|
||||
default=0
|
||||
)
|
||||
objects = PhotoManager()
|
||||
metadata = None
|
||||
orientation = 1
|
||||
|
||||
class Meta:
|
||||
get_latest_by = "created_date"
|
||||
ordering = ["created_date"]
|
||||
db_table = 'events_photo'
|
||||
verbose_name = _('Event Image')
|
||||
verbose_name_plural = _('Event Images')
|
||||
|
||||
|
||||
def __unicode__(self):
|
||||
return os.path.basename(self.image.name)
|
||||
|
||||
def read_metadata(self):
|
||||
image_path = os.path.join(settings.MEDIA_ROOT, self.image.name)
|
||||
self.metadata = pyexiv2.ImageMetadata(image_path)
|
||||
self.metadata.read()
|
||||
try:
|
||||
self.orientation = self.metadata['Exif.Image.Orientation'].value
|
||||
except:
|
||||
self.orientation = 1
|
||||
|
||||
def save_metadata(self):
|
||||
if not self.metadata:
|
||||
self.read_metadata()
|
||||
self.metadata['Exif.Image.DateTime'] = self.created_date
|
||||
self.metadata['Exif.Image.ImageDescription'] = self.description
|
||||
self.metadata['Exif.Image.Artist'] = self.photographer.username
|
||||
self.metadata['Exif.Image.Orientation'] = self.orientation or 1
|
||||
self.metadata.write()
|
||||
|
||||
def rotate(self, rotate):
|
||||
"""
|
||||
Sets an the Exif tag in an image to set the right direction.
|
||||
This provides lossless image rotation.
|
||||
@param rotate: 'clockwise' or 'counter-clockwise' the direction in
|
||||
which we should rotate the image in 90° steps.
|
||||
"""
|
||||
if not self.metadata:
|
||||
self.read_metadata()
|
||||
if rotate == 'clockwise':
|
||||
if self.orientation == 1:
|
||||
self.orientation = 6
|
||||
elif self.orientation == 6:
|
||||
self.orientation = 3
|
||||
elif self.orientation == 3:
|
||||
self.orientation = 8
|
||||
else:
|
||||
self.orientation = 1
|
||||
elif rotate == 'counter-clockwise':
|
||||
if self.orientation == 1:
|
||||
self.orientation = 8
|
||||
elif self.orientation == 8:
|
||||
self.orientation = 3
|
||||
elif self.orientation == 3:
|
||||
self.orientation = 6
|
||||
else:
|
||||
self.orientation = 1
|
||||
self.save()
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse(
|
||||
'event-photo',
|
||||
kwargs={'event': self.event.id, 'pk': self.id}
|
||||
)
|
||||
|
||||
@property
|
||||
def next_photo(self):
|
||||
return self.get_next_by_created_date(event=self.event)
|
||||
|
||||
@property
|
||||
def previous_photo(self):
|
||||
return self.get_previous_by_created_date(event=self.event)
|
||||
|
||||
def save(self, **kwargs):
|
||||
"""
|
||||
Triggers to save related Event to save. This should force an update for
|
||||
the denormalized Photo count.
|
||||
"""
|
||||
super(Photo, self).save()
|
||||
self.save_metadata()
|
||||
|
||||
|
||||
def update_event(sender, instance=None, created=False, raw=False, **kwargs):
|
||||
image_models.regenerate_image_cache(sender, instance=instance)
|
||||
instance.event.save()
|
||||
|
||||
|
||||
models.signals.post_save.connect(update_event, sender=Photo)
|
||||
models.signals.post_delete.connect(update_event, sender=Photo)
|
||||
@@ -1,57 +0,0 @@
|
||||
{% extends "gallery/photo_list.html" %}
|
||||
{% load i18n comments %}
|
||||
|
||||
{% block title %} {{ photo.name }} - {{ photo.event.name }} {% endblock %}
|
||||
|
||||
{% block opengraph %}
|
||||
<meta property="og:type" content="photo" />
|
||||
<meta property="og:title" content="{{photo.name}} - Foto" />
|
||||
<meta property="og:url" content="http://www.kasu.at{{photo.get_absolute_url}}" />
|
||||
<meta property="og:image" content="http://www.kasu.at{{photo.thumbnail.url}}" />
|
||||
{% if photo.description %}<meta property="og:description" content="{{photo.description}}" />{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block maincontent %}
|
||||
<h2 class="grid_12"><a href="{% url 'event-photo-list' photo.event.id %}">{{photo.event.name}}</a> » {{ photo.name }}</h2>
|
||||
<div id="display" class="grid_12 clearfix">
|
||||
<img src="{{photo.display.url}}" alt="{{photo.name}}" title="{{photo.name}}"/>
|
||||
{% if photo.previous_photo %}
|
||||
<a href="{{ photo.previous_photo.get_absolute_url }}" class="previous">{% trans 'previous' %}</a>
|
||||
{% endif %}
|
||||
{% if photo.next_photo %}
|
||||
<a href="{{ photo.next_photo.get_absolute_url }}" class="next">Next</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
<p class="grid_10 push_1">{{ photo.description }}</p>
|
||||
<div class="grid_12 more_link">
|
||||
<a href="https://m.google.com/app/plus/x/?v=compose&content={{photo.headline|urlencode}}+-+http%3A%2F%2Fwww.kasu.at/{{photo.get_absolute_url|urlencode}}" target="_blank"><img src="{{STATIC_URL}}img/google_plus.png" alt="Google+" title="{% trans 'Share on Google+'%}" /></a>
|
||||
<a href="https://twitter.com/share?url=http%3A%2F%2Fwww.kasu.at/{{photo.get_absolute_url|urlencode}}" target='_blank'><img src="{{STATIC_URL}}img/twitter.png" alt="Twitter" title="{% trans 'Share on Twitter' %}" /></a>
|
||||
<a href="http://facebook.com/sharer.php?u=http%3A%2F%2Fwww.kasu.at{{photo.get_absolute_url|urlencode}}" target="_blank"><img src="{{STATIC_URL}}img/facebook.png" alt="Facebook" title="{% trans 'Share on Facebook'%}" /></a>
|
||||
</div>
|
||||
|
||||
<ul class="info grid_12">
|
||||
<li class="user"><strong>{% trans 'Photographer' %}: </strong>{{ photo.photographer }}</li>
|
||||
<li class="date"><strong>{% trans 'on' %}</strong> {{ photo.created_date }}</li>
|
||||
</ul>
|
||||
{% endblock %}
|
||||
|
||||
{% block comment %}
|
||||
{% render_comment_list for photo %}
|
||||
{% render_comment_form for photo %}
|
||||
{% endblock %}
|
||||
|
||||
{% block buttonbar %}
|
||||
{% if perms.events.change_photo %}
|
||||
<form method="post" enctype="multipart/form-data" class="grid_12">
|
||||
{% csrf_token %}
|
||||
<p class="buttonbar">
|
||||
<a href="{{ photo.image.url }}" class="button" type="application/octet-stream"><img src="{{ STATIC_URL}}icons/drive_go.png" alt="{% trans 'download' %}" title="{% trans 'download' %}" /></a>
|
||||
<button type="submit" name="rotate" value="counter-clockwise"><img src="{{STATIC_URL}}icons/shape_rotate_anticlockwise.png" title="Gegen den Uhrzeiger drehen"></button>
|
||||
<button type="submit" name="rotate" value="clockwise"><img src="{{STATIC_URL}}icons/shape_rotate_clockwise.png" title="Im Uhrzeiger drehen"></button>
|
||||
<button type="submit"><img src="{{STATIC_URL}}icons/disk.png" alt=""> {% trans "save" %}</button>
|
||||
</p>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
{% extends "events/event_detail.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block title %}{{event.name}}{% endblock %}
|
||||
|
||||
{% block opengraph %}
|
||||
<meta property="og:type" content="album" />
|
||||
<meta property="og:title" content="{{event.name}}" />
|
||||
<meta property="og:url" content="http://www.kasu.at{% url 'event-photo-list' event.pk %}" />
|
||||
<meta property="og:image" content="http://www.kasu.at{{ event.get_thumbnail.url }}" />
|
||||
{% if event.description %}<meta property="og:description" content="{{event.description}}" />{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block maincontent %}
|
||||
{% if perms.events.delete_photo %}
|
||||
{% for photo in photo_list %}
|
||||
<div class="thumbnail">
|
||||
<a href="{{photo.get_absolute_url}}"><img src="{{photo.thumbnail.url}}" alt=""/></a>
|
||||
<a href="{% url 'delete-event-photo' photo.pk %}" class="delete_image"><img src="{{STATIC_URL}}icons/delete.png" title="{% trans 'delete' %}"/></a>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{% for photo in photo_list %}
|
||||
<a href="{{photo.get_absolute_url}}" class="thumbnail"><img src="{{photo.thumbnail.url}}" alt=""/></a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% if perms.events.add_photo %}
|
||||
<br class="clear" />
|
||||
<form action="{% url 'event-photo-upload' event.id %}" method="post" enctype="multipart/form-data" class="grid_12">
|
||||
{% csrf_token %}
|
||||
<fieldset>
|
||||
<legend>Photos hochladen</legend>
|
||||
{% include "form.html"%}
|
||||
<p class="buttonbar">
|
||||
<button type="reset"><img src="{{STATIC_URL}}icons/arrow_undo.png" alt="{% trans 'reset' %}" /> {% trans 'reset' %}</button>
|
||||
<button type="submit"><img src="{{STATIC_URL}}icons/image_add.png" alt="{% trans 'upload' %}" /> {% trans 'upload' %}</button>
|
||||
</p>
|
||||
</fieldset>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block buttonbar %}{% endblock %}
|
||||
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
# Create your views here.
|
||||
from datetime import timedelta
|
||||
|
||||
from django.contrib.auth.decorators import permission_required
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.http import Http404
|
||||
from django.shortcuts import redirect
|
||||
from django.utils import timezone
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.views import generic
|
||||
import pyexiv2
|
||||
|
||||
from events.models import Event
|
||||
from .models import Photo
|
||||
from . import forms
|
||||
|
||||
|
||||
class DeleteEventPhoto(generic.DeleteView):
|
||||
model = Photo
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse('event-photo-list', args=[self.object.event.id])
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(DeleteEventPhoto, self).get_context_data()
|
||||
context['event'] = self.object.event
|
||||
return context
|
||||
|
||||
@method_decorator(permission_required('events.delete_photo'))
|
||||
def dispatch(self, *args, **kwargs):
|
||||
return super(DeleteEventPhoto, self).dispatch(*args, **kwargs)
|
||||
|
||||
|
||||
class EventGallery(generic.ListView):
|
||||
template_name = 'gallery/photo_gallery.html'
|
||||
queryset = Event.objects.filter(start__lt=timezone.now(), photo_count__gt=0)
|
||||
paginate_by = 12
|
||||
|
||||
|
||||
class EventPhoto(generic.UpdateView):
|
||||
form_class = forms.EditPhotoForm
|
||||
model = Photo
|
||||
template_name = 'gallery/photo_detail.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(EventPhoto, self).get_context_data()
|
||||
context['event'] = self.object.event
|
||||
return context
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
if request.POST.get('rotate') and request.user.has_perm(
|
||||
'events.change_photo'):
|
||||
photo = Photo.objects.get(pk=kwargs['pk'])
|
||||
photo.rotate(request.POST['rotate'])
|
||||
# return redirect(photo.get_absolute_url())
|
||||
return self.get(request)
|
||||
else:
|
||||
return generic.UpdateView.post(self, request, *args, **kwargs)
|
||||
|
||||
|
||||
class EventPhotoList(generic.ListView):
|
||||
context_object_name = 'photo_list'
|
||||
paginate_by = 36
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = generic.ListView.get_context_data(self, **kwargs)
|
||||
context['event'] = self.event
|
||||
context['form'] = forms.PhotoUploadForm(
|
||||
initial={'event': self.event, 'photographer': self.request.user})
|
||||
return context
|
||||
|
||||
def get_queryset(self):
|
||||
try:
|
||||
self.event = Event.objects.get(id=self.kwargs['event'])
|
||||
return Photo.objects.filter(event=self.event)
|
||||
except Event.DoesNotExist:
|
||||
raise Http404(_('Event does not exist'))
|
||||
|
||||
|
||||
class EventPhotoUpload(generic.FormView):
|
||||
form_class = forms.PhotoUploadForm
|
||||
template_name = 'gallery/photo_upload.html'
|
||||
|
||||
@method_decorator(permission_required('events.add_photo'))
|
||||
def dispatch(self, *args, **kwargs):
|
||||
return super(EventPhotoUpload, self).dispatch(*args, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = generic.FormView.get_context_data(self, **kwargs)
|
||||
context['event_list'] = Event.objects.archive()[:12]
|
||||
return context
|
||||
|
||||
def get_initial(self):
|
||||
"""
|
||||
Set the current logged in user a default value for the photographer.
|
||||
"""
|
||||
return {
|
||||
'photographer': self.request.user,
|
||||
}
|
||||
|
||||
def post(self, *args, **kwargs):
|
||||
"""
|
||||
|
||||
"""
|
||||
self.event = Event.objects.get(
|
||||
id=self.request.REQUEST.get('event'))
|
||||
photographer = self.request.POST.get('photographer',
|
||||
self.request.user.id)
|
||||
photographer = get_user_model().objects.get(id=photographer)
|
||||
self.counter = 1
|
||||
for upload in self.request.FILES.getlist('upload'):
|
||||
name = upload.name
|
||||
created_date, description = self.read_exif(upload)
|
||||
photo = Photo(
|
||||
event=self.event,
|
||||
photographer=photographer,
|
||||
image=upload,
|
||||
name=name,
|
||||
created_date=created_date,
|
||||
description=description
|
||||
)
|
||||
photo.save()
|
||||
self.counter += 1
|
||||
return redirect('event-photo-list', event=self.event.id)
|
||||
|
||||
def read_exif(self, photo):
|
||||
exif_data = pyexiv2.ImageMetadata.from_buffer(photo.read())
|
||||
exif_data.read()
|
||||
|
||||
try:
|
||||
created_date = exif_data['Exif.Image.DateTime'].value
|
||||
except:
|
||||
created_date = self.event.start + timedelta(minutes=self.counter)
|
||||
try:
|
||||
description = exif_data['Exif.Image.ImageDescription'].value
|
||||
except:
|
||||
description = ''
|
||||
return created_date, description
|
||||
|
||||
@@ -10,19 +10,6 @@ from imagekit.models import ImageSpecField
|
||||
import imagekit
|
||||
|
||||
|
||||
CHOICES_HORIZONTAL = (
|
||||
(0.00000001, _('left')),
|
||||
(0.5, _('center')),
|
||||
(1, _('right'))
|
||||
)
|
||||
|
||||
CHOICES_VERTICAL = (
|
||||
(0.00000001, _('top')),
|
||||
(0.5, _('middle')),
|
||||
(1, _('bottom'))
|
||||
)
|
||||
|
||||
|
||||
class ArticleImage(imagekit.ImageSpec):
|
||||
format = 'JPEG'
|
||||
width = 200
|
||||
@@ -96,11 +83,10 @@ def regenerate_image_cache(sender, instance=None, created=False, raw=False,
|
||||
Reganerate the images.
|
||||
"""
|
||||
if instance.image:
|
||||
print instance.image
|
||||
print instance.display
|
||||
print instance.callout
|
||||
for cached_image in (instance.article, instance.callout, instance.display, instance.thumbnail):
|
||||
try:
|
||||
os.remove(cached_image.path)
|
||||
except IOError:
|
||||
pass
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
|
Before Width: | Height: | Size: 663 B |
Binary file not shown.
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 10 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.8 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1021 B |
@@ -12,55 +12,6 @@
|
||||
src: url('../fonts/amerikasans.woff') format('woff'), url('../fonts/amerikasans.ttf') format('truetype');
|
||||
}
|
||||
|
||||
.clear {
|
||||
clear: both;
|
||||
display: block;
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
width: 0;
|
||||
}
|
||||
#display {position:relative;top:0px; text-align: center;}
|
||||
.clearfix {
|
||||
clear: both;
|
||||
}
|
||||
.grid_1,.grid_2,.grid_3,.grid_4,.grid_5,.grid_6,.grid_7,.grid_8,.grid_9,.grid_10,.grid_11,.grid_12
|
||||
{
|
||||
display: inline;
|
||||
float: left;
|
||||
margin: 0px 10px;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.grid_1 {
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
.grid_2 {
|
||||
width: 140px;
|
||||
}
|
||||
|
||||
.grid_3 {
|
||||
width: 220px;
|
||||
}
|
||||
|
||||
.grid_4 {
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.grid_5 {
|
||||
width: 380px;
|
||||
}
|
||||
|
||||
.more_link {
|
||||
text-align: right;
|
||||
clear: left;
|
||||
}
|
||||
.error, ul.errorlist li {
|
||||
color: #a40000;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #a40000;
|
||||
text-decoration: underline;
|
||||
@@ -71,11 +22,13 @@ a:link {
|
||||
font-weight: 700;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #5c3566;
|
||||
a:visited {color: #5c3566;}
|
||||
article, aside, details, figcaption, figure, footer, header, hgroup, main, menu, nav, section {display: block;}
|
||||
body {
|
||||
font: 12pt Philosopher, Georgia, serif;
|
||||
line-height: 1;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
button, a.button, #redbox a.button:link, #redbox a.button:visited {
|
||||
display: inline-block;
|
||||
padding: 0.25em;
|
||||
@@ -90,17 +43,79 @@ button, a.button, #redbox a.button:link, #redbox a.button:visited {
|
||||
text-decoration: none;
|
||||
text-shadow: 1px 1px 1px #ffffff;
|
||||
}
|
||||
div.tab_container {
|
||||
background-color:#fff;
|
||||
padding-top: 1em;
|
||||
|
||||
article, aside, details, figcaption, figure, footer, header, hgroup, main, menu, nav, section {
|
||||
display: block;
|
||||
}
|
||||
|
||||
h1 a:link, h2 a:link, h3 a:link, h4 a:link, h5 a:link, h6 a:link, h1 a:visited, h2 a:visited, h3 a:visited, h4 a:visited, h5 a:visited, h6 a:visited {
|
||||
color: #bc0a19;
|
||||
fieldset {
|
||||
border: none;
|
||||
color: #2e3436;
|
||||
border-radius: 10px;
|
||||
padding: 0 10px 0 160px;
|
||||
background-color: #f2f5f6;
|
||||
background: linear-gradient(135deg, #f2f5f6 0%, #e3eaed 37%, #c8d7dc 100%);
|
||||
vertical-align: top;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
fieldset div {margin: 5px 0px;}
|
||||
fieldset legend {
|
||||
margin-top: -.1em;
|
||||
margin-left: -150px;
|
||||
color: #a40000;
|
||||
font-family: 'Amerika Sans', sans-serif;
|
||||
font-variant: small-caps;
|
||||
font-weight: 400;
|
||||
text-decoration: none;
|
||||
font-size: 16pt;
|
||||
text-shadow: 2px 2px 2px #888;
|
||||
}
|
||||
fieldset .required {font-weight: bold;}
|
||||
fieldset .buttonbar {
|
||||
border-radius: 0px 0px 10px 10px;
|
||||
margin: 0 -10px 0 -160px;
|
||||
}
|
||||
fieldset .help_text {font-size: small;}
|
||||
fieldset .field_name {
|
||||
text-align: right;
|
||||
width: 140px;
|
||||
margin: 0 20px 0 -160px;
|
||||
padding-top: 3px;
|
||||
display: inline-block;
|
||||
clear: left;
|
||||
vertical-align: top;
|
||||
}
|
||||
fieldset input,
|
||||
fieldset textarea {
|
||||
border: 1px solid #999999;
|
||||
border-radius: 5px;
|
||||
padding: 2px;
|
||||
margin: 0;
|
||||
}
|
||||
fieldset input[maxlength="255"],
|
||||
fieldset textarea {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
max-width: 760px;
|
||||
}
|
||||
fieldset ul {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
}
|
||||
fieldset ul li {
|
||||
list-style: none;
|
||||
display: inline;
|
||||
}
|
||||
fieldset table {
|
||||
display: inline-table;
|
||||
max-width: 760px;
|
||||
}
|
||||
fieldset.comment {
|
||||
padding: 0;
|
||||
|
||||
legend {margin-left: 15px}
|
||||
|
||||
.buttonbar {margin: 0; width: 100%}
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6, .player {
|
||||
color: #bc0a19;
|
||||
font-family: 'Amerika Sans', sans-serif;
|
||||
@@ -110,66 +125,57 @@ h1, h2, h3, h4, h5, h6, .player {
|
||||
margin: 1em 0 0.5em 0;
|
||||
text-shadow: 1px 1px 1px #888;
|
||||
vertical-align: baseline;
|
||||
|
||||
a:link, a:visited {
|
||||
color: #bc0a19;
|
||||
font-weight: 400;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
.player {
|
||||
margin:0
|
||||
ol {
|
||||
list-style: cjk-ideographic;
|
||||
padding-left: 2em;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
width: 100%;
|
||||
margin: 0 auto 1em auto;
|
||||
|
||||
html, div, span, applet, object, iframe, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video {
|
||||
border: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
vertical-align: baseline;
|
||||
td {
|
||||
border-bottom: 1px solid #d3d7cf;
|
||||
border-top: 1px solid #d3d7cf;
|
||||
padding: 2px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
th {
|
||||
background: #a40000;
|
||||
color: #fff;
|
||||
padding: 2px;
|
||||
vertical-align: middle;
|
||||
|
||||
a:link, a:visited {color: #FFF;}
|
||||
}
|
||||
|
||||
tr:nth-child(2n+1) {background-color: #eeeeec;}
|
||||
tr:hover {background-color: #eedcdc;}
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 0.5em
|
||||
ul {
|
||||
list-style: circle outside;
|
||||
padding-left: 2em;
|
||||
margin:0.5em 0 0.5em 0
|
||||
}
|
||||
ul.info {
|
||||
list-style: none;
|
||||
margin: 0 0 0.5em 0;
|
||||
padding-left: 0;
|
||||
|
||||
img.partner, img.posting_image {
|
||||
border: 1px solid #babdb6;
|
||||
display:block;
|
||||
float: left;
|
||||
height: 120px;
|
||||
margin: 0 20px 0 0;
|
||||
padding: 4px;
|
||||
width: 200px;
|
||||
li {
|
||||
display: inline-block;
|
||||
margin-right: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
img.partner:nth-of-type(odd) {
|
||||
float: right;
|
||||
}
|
||||
|
||||
input {font: normal 12pt Philosopher, sans-serif;}
|
||||
|
||||
input[type=number] {text-align: right;}
|
||||
input[maxlength="255"] {width: 100%}
|
||||
input[readonly="readonly"], input[readonly] {
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: #2e3436;
|
||||
}
|
||||
|
||||
.cke_chrome {border:0 !important}
|
||||
.cke_wysiwyg_div {padding: 1em 0 !important}
|
||||
|
||||
li {
|
||||
margin-bottom: .2em;
|
||||
}
|
||||
|
||||
.thumbnail {
|
||||
display: block;
|
||||
position: relative;
|
||||
float: left;
|
||||
height: 140px;
|
||||
width: 140px;
|
||||
padding: 5px;
|
||||
border: 0;
|
||||
margin: 5px;
|
||||
background: transparent url('../img/thumbnail-bg.png') top left no-repeat;
|
||||
}
|
||||
|
||||
ul.tabs {
|
||||
width: 100%;
|
||||
list-style: none;
|
||||
@@ -205,102 +211,9 @@ ul.tabs {
|
||||
}
|
||||
}
|
||||
}
|
||||
div.tab_container {
|
||||
background-color:#fff;
|
||||
padding-top: 1em;
|
||||
|
||||
}
|
||||
ol {
|
||||
list-style: cjk-ideographic;
|
||||
padding-left: 2em;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
width: 100%;
|
||||
margin: 0 auto 1em auto;
|
||||
}
|
||||
|
||||
table td {
|
||||
border-bottom: 1px solid #d3d7cf;
|
||||
border-top: 1px solid #d3d7cf;
|
||||
padding: 2px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
table th {
|
||||
background: #a40000;
|
||||
color: #fff;
|
||||
padding: 2px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
table th a:link, table th a:visited {
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
table tr:nth-child(2n+1) {
|
||||
background-color: #eeeeec;
|
||||
}
|
||||
|
||||
table tr:hover {
|
||||
background-color: #eedcdc;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: circle outside;
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
ul.info {
|
||||
list-style: none;
|
||||
margin-bottom: 0.5em;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
ul.info li {
|
||||
display: inline-block;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.buttonbar {
|
||||
text-align: right;
|
||||
border-radius: 10px;
|
||||
background-color: #000000;
|
||||
background: linear-gradient(to bottom, #45484d 0%,#000000 100%);
|
||||
}
|
||||
|
||||
/** PAGINATOR **/
|
||||
.pagination {
|
||||
text-align:center
|
||||
}
|
||||
|
||||
.pagination a, .pagination .current, .pagination .next, .pagination .previous {
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
padding: 0 0.5em 0 0.5em;
|
||||
}
|
||||
|
||||
.pagination .next {
|
||||
float: right;
|
||||
background: none;
|
||||
}
|
||||
|
||||
|
||||
.pagination .previous {
|
||||
float: left;
|
||||
background: none;
|
||||
}
|
||||
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
.right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
#bottom_buttonbar {border-radius: 0 0 10px 10px;}
|
||||
#display {position:relative; text-align: center;}
|
||||
#redbox {
|
||||
color: white;
|
||||
background-color: #a90329;
|
||||
@@ -312,25 +225,106 @@ ul.info li {
|
||||
h2:first-of-type {margin: -20px 0 0 10px; color: black; text-shadow: 1px 1px 1px #ffffff;}
|
||||
}
|
||||
|
||||
.avatar {
|
||||
display: block;
|
||||
position: relative;
|
||||
float: left;
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
padding: 0;
|
||||
margin: 0 1em 1em 0;
|
||||
box-shadow: 2px 2px 5px #888;
|
||||
|
||||
img {
|
||||
height: 70px;
|
||||
width: 70px;
|
||||
}
|
||||
}
|
||||
.buttonbar {
|
||||
text-align: right;
|
||||
border-radius: 10px;
|
||||
background-color: #000000;
|
||||
background: linear-gradient(to bottom, #45484d 0%,#000000 100%);
|
||||
}
|
||||
.center {text-align: center;}
|
||||
.clear, .clearfix {clear: both;}
|
||||
.cke_chrome {border:0 !important}
|
||||
.cke_wysiwyg_div {padding: 1em 0 !important}
|
||||
.disabled {color: #ccc}
|
||||
.comment {
|
||||
display:table;
|
||||
margin-bottom: 1em;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
}
|
||||
.error, ul.errorlist li {color: #a40000;}
|
||||
.game h2 {margin: 0.5em 0;}
|
||||
.grid_1,.grid_2,.grid_3,.grid_4,.grid_5,.grid_6,.grid_7,.grid_8,.grid_9,.grid_10,.grid_11,.grid_12
|
||||
{
|
||||
display: inline;
|
||||
float: left;
|
||||
margin: 0px 10px;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.grid_1 { width: 60px;}
|
||||
.grid_2 {width: 140px;}
|
||||
.grid_3 {width: 220px;}
|
||||
.grid_4 {width: 300px;}
|
||||
.grid_5 {width: 380px;}
|
||||
.grid_6 {width: 460px;}
|
||||
.grid_7 {width: 540px;}
|
||||
.grid_8 {width: 620px;}
|
||||
.grid_9 {width: 700px;}
|
||||
.grid_10 {width: 780px;}
|
||||
.grid_11 {width: 860px;}
|
||||
.grid_12 {width: 940px;}
|
||||
|
||||
fieldset.comment {
|
||||
.more_link {text-align: right; clear: left;}
|
||||
|
||||
.pagination {
|
||||
clear: both;
|
||||
margin-bottom: 1em;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
z-index: 30;
|
||||
|
||||
legend {margin-left: 15px}
|
||||
.buttonbar {margin: 0; width: 100%}
|
||||
.buttonbar {margin: 0; width: 100%}
|
||||
a {
|
||||
background-color: #000000;
|
||||
background: linear-gradient(to bottom, #45484d 0%,#000000 100%);
|
||||
border-radius: 5px;
|
||||
display: inline-block;
|
||||
font-weight: bold;
|
||||
padding: 0.5em 1em;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:link, a:visited {color: #fff;}
|
||||
a:hover, a.active {color: #bc0a19;}
|
||||
a.disabled, a.disabled:hover {color: #666}
|
||||
|
||||
a.previous {
|
||||
float:left;
|
||||
border-radius: 10px 5px 5px 10px;
|
||||
}
|
||||
a.next {
|
||||
float: right;
|
||||
border-radius: 5px 10px 10px 5px;
|
||||
}
|
||||
}
|
||||
|
||||
#bottom_buttonbar {
|
||||
position: absolute;
|
||||
border-radius: 0 0 10px 10px;
|
||||
bottom: 0px;
|
||||
margin: 0;
|
||||
width: 100%
|
||||
.player {margin:0 auto; float:none}
|
||||
|
||||
.right {text-align: right;}
|
||||
.thumbnail {
|
||||
display: block;
|
||||
position: relative;
|
||||
float: left;
|
||||
height: 140px;
|
||||
width: 140px;
|
||||
padding: 5px;
|
||||
border: 0;
|
||||
margin: 5px;
|
||||
background: transparent url('../img/thumbnail-bg.png') top left no-repeat;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,30 @@
|
||||
@media screen and (min-width: @min-desktop-width) {
|
||||
|
||||
#content {
|
||||
body {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
min-width: 960px;
|
||||
height: 100%;
|
||||
}
|
||||
#body {
|
||||
background-color: #ffffff;
|
||||
background-image: url('../img/kranich.png'), url('../img/header_bg.jpg');
|
||||
background-repeat: no-repeat, no-repeat;
|
||||
background-position: center bottom, center top;
|
||||
background-attachment: scroll, fixed;
|
||||
}
|
||||
#bottom_buttonbar {
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
margin: 0;
|
||||
width: 100%
|
||||
}
|
||||
#content {
|
||||
width: 940px;
|
||||
margin: 0px 10px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#display .next, #display .previous {
|
||||
}
|
||||
#display .next,
|
||||
#display .previous {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
@@ -17,120 +35,43 @@
|
||||
text-indent: 9999px;
|
||||
overflow: hidden;
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
#display .next:hover, #display .previous:hover {
|
||||
}
|
||||
#display .next:hover,
|
||||
#display .previous:hover {
|
||||
opacity: 1;
|
||||
transition: all 0.2s ease-out;
|
||||
}
|
||||
|
||||
#display .next {
|
||||
}
|
||||
#display .next {
|
||||
background: transparent url(../img/right-arrow.png) no-repeat center center;
|
||||
right: 10px;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
#display .previous {
|
||||
}
|
||||
#display .previous {
|
||||
background: transparent url(../img/left-arrow.png) no-repeat center center;
|
||||
left: 10px;
|
||||
z-index: 2
|
||||
}
|
||||
|
||||
#display img {
|
||||
box-shadow: 1px 1px 5px 1px #444;
|
||||
}
|
||||
|
||||
#footer {
|
||||
}
|
||||
#display img {box-shadow: 1px 1px 5px 1px #444;}
|
||||
#footer {
|
||||
width: 920px;
|
||||
min-height:50px;
|
||||
min-height: 50px;
|
||||
margin: 20px auto 0 auto;
|
||||
z-index: 30;
|
||||
}
|
||||
|
||||
#footer p {text-align: center;}
|
||||
|
||||
#footer_kranich {
|
||||
display: block;
|
||||
position: relative;
|
||||
max-width:1250px;
|
||||
width:100%;
|
||||
margin:0 auto;
|
||||
top: -320px;
|
||||
text-align: right;
|
||||
z-index: -2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#maincontent {
|
||||
margin: 0 auto;
|
||||
height: auto !important;
|
||||
width: 960px;
|
||||
min-height: 800px;
|
||||
padding: 10px 0 2em 0;
|
||||
position: relative;
|
||||
z-index: 19;
|
||||
border-radius: 10px;
|
||||
background:rgba(255, 255, 255, 0.5);
|
||||
box-shadow: 0px 0px 20px 1px rgba(0,0,0,0.75);
|
||||
}
|
||||
|
||||
#messages {
|
||||
clear: both;
|
||||
margin: 0 auto;
|
||||
padding: 8px 0 0 30px;
|
||||
width: 920px;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
#messages li.success {
|
||||
color: #253324;
|
||||
background: #89bd84;
|
||||
border: 1px solid #253324;
|
||||
border-radius:10px;
|
||||
margin: 10px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
#navigation, .pagination {
|
||||
clear: both;
|
||||
position: relative;
|
||||
background: url(../img/navigation-bg.png) no-repeat left top;
|
||||
height: 56px;
|
||||
list-style: none;
|
||||
margin: 0 auto;
|
||||
padding: 8px 35px 0px 25px;
|
||||
width: 900px;
|
||||
z-index: 30;
|
||||
|
||||
|
||||
a {
|
||||
background: url(../img/navigation-separator.png) no-repeat right center;
|
||||
color: #FFF;
|
||||
display: block;
|
||||
float: left;
|
||||
font-weight: bold;
|
||||
height: 33px;
|
||||
padding: 17px 15px 0;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover, #navigation a.active {
|
||||
background: url(../img/navigation-hover.png) repeat-x left top;
|
||||
color: #3B3B3B;
|
||||
}
|
||||
|
||||
li {
|
||||
display: inline;
|
||||
margin: 0;
|
||||
}
|
||||
p {text-align: center;}
|
||||
}
|
||||
#google_maps {
|
||||
position: relative;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
height: 280px;
|
||||
padding: 10px;
|
||||
border-radius: 0px 10px 10px 0px;
|
||||
}
|
||||
|
||||
|
||||
#jumbotron {
|
||||
clear: both;
|
||||
position: relative;
|
||||
padding: 0 1px 0 0;
|
||||
padding: 0;
|
||||
width: 940px;
|
||||
margin: 0 10px 1em 10px;
|
||||
z-index: 5;
|
||||
@@ -140,7 +81,6 @@
|
||||
background-repeat: no-repeat;
|
||||
background-color: #333;
|
||||
background-position: center left;
|
||||
|
||||
> h2, > h1 {
|
||||
color: #eff0ef;
|
||||
text-shadow: 1px 1px 1px #000;
|
||||
@@ -150,7 +90,6 @@
|
||||
max-width: 600px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#teaser_text {
|
||||
display: block;
|
||||
position: absolute;
|
||||
@@ -158,12 +97,69 @@
|
||||
bottom: 0px;
|
||||
width: 620px;
|
||||
color: #FFF;
|
||||
background: rgba(0, 0, 0, 0.5);;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
padding: 1em;
|
||||
border-radius: 0px 0px 0px 10px;
|
||||
|
||||
a:link, a:active, a:visited {color: #fff; text-decoration:underline;}
|
||||
}
|
||||
}
|
||||
#maincontent {
|
||||
margin: 0 auto;
|
||||
height: auto !important;
|
||||
width: 960px;
|
||||
min-height: 800px;
|
||||
padding: 10px 0 2em 0;
|
||||
position: relative;
|
||||
z-index: 19;
|
||||
border-radius: 10px;
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
box-shadow: 0px 0px 20px 1px rgba(0, 0, 0, 0.75);
|
||||
}
|
||||
#messages {
|
||||
clear: both;
|
||||
margin: 0 auto;
|
||||
padding: 8px 0 0 30px;
|
||||
width: 920px;
|
||||
list-style: none;
|
||||
|
||||
li.success {
|
||||
color: #253324;
|
||||
background: #89bd84;
|
||||
border: 1px solid #253324;
|
||||
border-radius: 10px;
|
||||
margin: 10px;
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
||||
#navigation {
|
||||
clear: both;
|
||||
background: url(../img/navigation-bg.png) no-repeat left top;
|
||||
height: 56px;
|
||||
margin: 0 auto;
|
||||
padding: 8px 35px 0px 25px;
|
||||
position: relative;
|
||||
width: 900px;
|
||||
z-index: 30;
|
||||
|
||||
a {
|
||||
background: url(../img/navigation-separator.png) no-repeat right center;
|
||||
color: #FFF;
|
||||
display: inline-block;
|
||||
font-weight: bold;
|
||||
height: 33px;
|
||||
padding: 17px 15px 0;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover, a.active {
|
||||
background: url(../img/navigation-hover.png) repeat-x left top;
|
||||
color: #3B3B3B;
|
||||
}
|
||||
|
||||
li {display: inline;}
|
||||
}
|
||||
#recaptcha_widget_div {margin-top: -20px;}
|
||||
#redbox {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
@@ -171,41 +167,45 @@
|
||||
height: 280px;
|
||||
width: 280px;
|
||||
border-radius: 0px 10px 10px 0px;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
|
||||
#usernav {
|
||||
#usernav {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
text-align: right;
|
||||
background: black;
|
||||
background: linear-gradient(to bottom, #45484d 0%,#000000 100%);
|
||||
background: linear-gradient(to bottom, #45484d 0%, #000000 100%);
|
||||
border-radius: 0 0 0 10px;
|
||||
font-size: 14pt;
|
||||
color: #FFF;
|
||||
padding: 10px 10px;
|
||||
z-index: 50;
|
||||
box-shadow: -1px -1px 5px 1px rgba(0,0,0,0.75);
|
||||
box-shadow: -1px -1px 5px 1px rgba(0, 0, 0, 0.75);
|
||||
|
||||
a {color: #FFF;}
|
||||
}
|
||||
|
||||
a {
|
||||
color: #FFF;
|
||||
}
|
||||
}
|
||||
#usernav img {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.clearfix {
|
||||
zoom: 1px;
|
||||
}
|
||||
|
||||
.clearfix:after {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.gallery {
|
||||
.comment_picture {
|
||||
display: table-cell;
|
||||
padding: 0px 10px;
|
||||
width: 60px;
|
||||
vertical-align: top;
|
||||
}
|
||||
.comment_header {
|
||||
display: table-cell;
|
||||
padding: 0px 10px;
|
||||
width: 140px;
|
||||
vertical-align: top;
|
||||
}
|
||||
.comment_header h3 {margin: 0}
|
||||
.comment_text {
|
||||
display: table-cell;
|
||||
padding: 0px 10px;
|
||||
width: auto;
|
||||
max-width: 700px;
|
||||
}
|
||||
.gallery {
|
||||
display: inline;
|
||||
float: left;
|
||||
height: 200px;
|
||||
@@ -213,222 +213,57 @@
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.gallery .thumbnail {
|
||||
}
|
||||
.gallery .thumbnail {
|
||||
display: block;
|
||||
float: none;
|
||||
margin: 5px auto;
|
||||
}
|
||||
|
||||
.game img {
|
||||
float:right;
|
||||
margin: 0.5em 0 0.5em 1em;
|
||||
width: 300px;
|
||||
height: auto;
|
||||
box-shadow: 1px 1px 5px 1px #444;
|
||||
}
|
||||
|
||||
.game:nth-child(2n+1) img {
|
||||
float:left;
|
||||
margin-right:1em;
|
||||
margin: 0.5em 2em 0.5em 0;
|
||||
}
|
||||
|
||||
div.thumbnail a.delete_image {
|
||||
.officer {
|
||||
float:left;
|
||||
width: 140px;
|
||||
margin:5px;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
|
||||
img {
|
||||
border: 0;
|
||||
border-radius: 50%;
|
||||
box-shadow: 1px 1px 5px 1px #444;
|
||||
width:130px;
|
||||
height:130px;
|
||||
}
|
||||
|
||||
.function {font-size:small;margin-top: 0.25em}
|
||||
}
|
||||
|
||||
img.posting_image, img.partner {
|
||||
float: left;
|
||||
width: 200px;
|
||||
height: 120px;
|
||||
padding: 2px;
|
||||
margin: 0 1em 1em 0;
|
||||
border: 1px solid #babdb6;
|
||||
}
|
||||
|
||||
|
||||
.thumbnail a.delete_image {
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
bottom: 0px;
|
||||
}
|
||||
|
||||
#body {
|
||||
background-color: #ffffff;
|
||||
background-image: url('../img/kranich.png'), url('../img/header_bg.jpg');
|
||||
background-repeat: no-repeat, no-repeat;
|
||||
background-position: center bottom, center top;
|
||||
background-attachment: scroll, fixed;
|
||||
}
|
||||
body {
|
||||
font: 12pt Philosopher, Georgia, serif;
|
||||
line-height: 1;
|
||||
position: relative;
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
min-width: 960px;
|
||||
padding: 0;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
border: none;
|
||||
color: #2e3436;
|
||||
border-radius: 10px;
|
||||
margin: 10px 0 0 0;
|
||||
padding: 0 10px 0 160px;
|
||||
background-color: #f2f5f6;
|
||||
background: linear-gradient(135deg, #f2f5f6 0%, #e3eaed 37%, #c8d7dc 100%);
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
fieldset legend {
|
||||
margin-top: -.1em;
|
||||
margin-left: -150px;
|
||||
color: #a40000;
|
||||
font-family: 'Amerika Sans', sans-serif;
|
||||
font-variant: small-caps;
|
||||
font-weight: 400;
|
||||
font-size: 16pt;
|
||||
text-shadow: 2px 2px 2px #888;
|
||||
}
|
||||
|
||||
fieldset div {
|
||||
margin: 5px 0px;
|
||||
}
|
||||
|
||||
fieldset .required {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
fieldset .buttonbar {
|
||||
border-radius: 0px 0px 10px 10px;
|
||||
margin: 0 -10px 0 -160px;
|
||||
}
|
||||
|
||||
fieldset .help_text {
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
fieldset .field_name {
|
||||
text-align: right;
|
||||
width: 140px;
|
||||
margin: 0 20px 0 -160px;
|
||||
padding-top: 3px;
|
||||
display: inline-block;
|
||||
clear: left;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
fieldset input, fieldset textarea {
|
||||
border: 1px solid #999999;
|
||||
border-radius: 5px;
|
||||
padding: 2px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
fieldset input[maxlength="255"], fieldset textarea {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
max-width: 760px;
|
||||
}
|
||||
|
||||
fieldset ul {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
fieldset ul li {
|
||||
list-style: none;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
fieldset table {
|
||||
display: inline-table;
|
||||
max-width: 760px;
|
||||
}
|
||||
|
||||
img.partner, img.partner_right, img.posting_image {
|
||||
border: 1px solid #babdb6;
|
||||
float: left;
|
||||
height: 120px;
|
||||
margin: 0 20px 0 0;
|
||||
padding: 4px;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
img.partner:nth-of-type(odd) {
|
||||
float: right;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.pagination a, .pagination .current, .pagination .next, .pagination .previous {
|
||||
display: inline-block;
|
||||
padding: 2px;
|
||||
color: #FFF;
|
||||
font-weight: bold;
|
||||
height: 33px;
|
||||
text-decoration: none;
|
||||
padding: 17px 0.5em 0 0.5em;
|
||||
}
|
||||
|
||||
.pagination .current {
|
||||
color: #a40000;
|
||||
}
|
||||
|
||||
.pagination .disabled {
|
||||
color: #ccc
|
||||
}
|
||||
|
||||
img.avatar {
|
||||
border: none;
|
||||
box-shadow: 2px 2px 2px #888;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
.comment_picture {
|
||||
display: table-cell;
|
||||
padding: 0px 10px;
|
||||
width: 60px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.comment_header {
|
||||
display: table-cell;
|
||||
padding: 0px 10px;
|
||||
width: 140px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.comment_header h3 {
|
||||
margin: 0
|
||||
}
|
||||
|
||||
.comment_text {
|
||||
display: table-cell;
|
||||
padding: 0px 10px;
|
||||
width: auto;
|
||||
max-width: 700px;
|
||||
}
|
||||
|
||||
.userinfo {
|
||||
width: 140px;
|
||||
}
|
||||
|
||||
.grid_6 {
|
||||
width: 460px;
|
||||
}
|
||||
|
||||
.grid_7 {
|
||||
width: 540px;
|
||||
}
|
||||
|
||||
.grid_8 {
|
||||
width: 620px;
|
||||
}
|
||||
|
||||
.grid_9 {
|
||||
width: 700px;
|
||||
}
|
||||
|
||||
.grid_10 {
|
||||
width: 780px;
|
||||
}
|
||||
|
||||
.grid_11 {
|
||||
width: 860px;
|
||||
}
|
||||
|
||||
.grid_12 {
|
||||
width: 940px;
|
||||
}
|
||||
|
||||
#recaptcha_widget_div {
|
||||
margin-top: -20px;
|
||||
}
|
||||
|
||||
#google_maps {
|
||||
position: relative;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
height: 280px;
|
||||
padding: 10px;
|
||||
border-radius: 0px 10px 10px 0px;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
@media screen and (min-width: @min-desktop-width) {
|
||||
#siteheader {
|
||||
min-height: 100px;
|
||||
min-height: 110px;
|
||||
width: 960px;
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
@@ -33,17 +33,17 @@
|
||||
#mainnav {
|
||||
left: 233px;
|
||||
position: absolute;
|
||||
top: 65px;
|
||||
bottom: 0px;
|
||||
|
||||
#toggle, .toggle {display: none;}
|
||||
|
||||
> ul.main_menu {
|
||||
padding: 0px;
|
||||
position:relativ;
|
||||
ul.main_menu {
|
||||
list-style:none;
|
||||
margin:0;
|
||||
padding: 0;
|
||||
|
||||
> li {
|
||||
display: block;
|
||||
float: left;
|
||||
display: inline-block;
|
||||
min-width: 50px;
|
||||
padding: 8px;
|
||||
font: normal small-caps 18px 'Amerika Sans', sans-serif;
|
||||
@@ -70,17 +70,16 @@
|
||||
display: none;
|
||||
background:rgba(255, 255, 255, 0.8);
|
||||
border-radius: 10px;
|
||||
padding: 10px 0;
|
||||
padding: 0.25em;
|
||||
min-width: 10em;
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
margin-left: -10px;
|
||||
top: 100%;
|
||||
margin: 0 0 0 -15px;
|
||||
box-shadow: -1px 1px 5px 0px rgba(0,0,0,0.75);
|
||||
transition: all 0.25s linear;
|
||||
|
||||
li {
|
||||
display:block;
|
||||
padding:2px;
|
||||
float: none;
|
||||
font: normal small-caps 14pt 'Amerika Sans', sans-serif;
|
||||
text-align: left;
|
||||
@@ -89,14 +88,14 @@
|
||||
li a {
|
||||
display:block;
|
||||
color: black;
|
||||
padding: 0.5em 0.25em;
|
||||
padding: 5px;
|
||||
transition: all 0.25s linear;
|
||||
border-radius: 0.5em;
|
||||
}
|
||||
li a:hover {
|
||||
color: white;
|
||||
background: #bc0a19;
|
||||
background: linear-gradient(135deg, #6d0019 0%, #8f0222 44%, #a90329 100%);
|
||||
background: linear-gradient(135deg, #a90329 0%,#8f0222 44%,#6d0019 100%);
|
||||
transition: all 0.25s linear;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,31 @@
|
||||
@min-desktop-width: 700px;
|
||||
@max-mobile-with: 699px;
|
||||
|
||||
@import "font-awesome/path.less";
|
||||
@import "font-awesome/variables.less";
|
||||
|
||||
@import "common";
|
||||
@import "desktop";
|
||||
@import "mobile";
|
||||
|
||||
@import "header_nav";
|
||||
@import "print";
|
||||
@import "font-aweseome/font-awesome";
|
||||
|
||||
@media screen and (max-width: @max-mobile-with) {
|
||||
@import "mobile";
|
||||
}
|
||||
|
||||
@media screen and (min-width: @min-desktop-width) {
|
||||
@import "desktop";
|
||||
}
|
||||
|
||||
@page {
|
||||
margin: 1cm 1cm 1cm 2cm;
|
||||
size: A4 portrait;
|
||||
}
|
||||
|
||||
@media print {
|
||||
@import "print";
|
||||
}
|
||||
@import "font-awesome/core.less";
|
||||
@import "font-awesome/larger.less";
|
||||
@import "font-awesome/fixed-width.less";
|
||||
@import "font-awesome/list.less";
|
||||
@import "font-awesome/icons.less";
|
||||
@@ -1,20 +1,45 @@
|
||||
@media screen and (max-width: @max-mobile-with) {
|
||||
|
||||
body {
|
||||
body {
|
||||
margin: 5px 10px;
|
||||
background: url('../img/background_mobile.png') no-repeat top center;
|
||||
background-attachment: fixed;
|
||||
font: 12pt "Philosopher", Georgia, serif;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
img.thumbnail {
|
||||
display: block;
|
||||
float: left;
|
||||
height: 70px;
|
||||
width: 70px;
|
||||
margin: 5px;
|
||||
box-shadow: 2px 2px 5px #888;
|
||||
}
|
||||
img.posting_image, img.partner {
|
||||
float: left;
|
||||
width: 99px;
|
||||
height: 59px;
|
||||
padding: 2px;
|
||||
margin: 1em 0.5em 0 0;
|
||||
border: 1px solid #babdb6;
|
||||
}
|
||||
ul.main_dropdown {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
li {padding: 0;}
|
||||
|
||||
#display .grid_10 {
|
||||
a {padding-left: 2em; font-size: 12pt;}
|
||||
}
|
||||
|
||||
#display .grid_10 {
|
||||
margin: 0;
|
||||
position: relative;
|
||||
z-index: 1
|
||||
}
|
||||
|
||||
#display .next, #display .previous {
|
||||
}
|
||||
#display .next, #display .previous {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
@@ -25,64 +50,48 @@
|
||||
text-indent: 9999px;
|
||||
overflow: hidden;
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
#display .next:hover, #display .previous:hover {
|
||||
}
|
||||
#display .next:hover, #display .previous:hover {
|
||||
opacity: .9;
|
||||
transition: all 0.2s ease-out;
|
||||
}
|
||||
|
||||
#display .next {
|
||||
}
|
||||
#display .next {
|
||||
background: transparent url(../img/right-arrow.png) no-repeat center center;
|
||||
right: 0px;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
#display .previous {
|
||||
}
|
||||
#display .previous {
|
||||
background: transparent url(../img/left-arrow.png) no-repeat center center;
|
||||
left: 0px;
|
||||
z-index: 2
|
||||
}
|
||||
|
||||
#footer {
|
||||
}
|
||||
#footer {
|
||||
border-top: 1px solid black;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
img.posting_image, img.partner {
|
||||
float: left;
|
||||
width: 99px;
|
||||
height: 59px;
|
||||
padding: 2px;
|
||||
margin: 1em 0.5em 0 0;
|
||||
border: 1px solid #babdb6;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
#topnav a {
|
||||
display: inline-block;
|
||||
color: #000;
|
||||
font: 400 small-caps 24pt 'Amerika Sans', sans-serif;
|
||||
min-width: 80px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
text-shadow: 2px 2px 2px #2e3436;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
#topnav a.active {
|
||||
color: #bc0a19;
|
||||
}
|
||||
|
||||
#topnav a:hover {
|
||||
}
|
||||
#jumbotron {background: none !important;}
|
||||
#maincontent {width: 100%;}
|
||||
#mainnav {display: block; float: right}
|
||||
#navigation {
|
||||
margin: 10px 0;
|
||||
padding: 0;
|
||||
background: #45484d url("../img/navigation-mobile.png") top left repeat-x;
|
||||
background-size: contain;
|
||||
}
|
||||
#navigation a {
|
||||
font: bold 12px Arial;
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
#sitelogo {
|
||||
text-decoration: none;
|
||||
}
|
||||
#navigation li {
|
||||
display: inline-block;
|
||||
padding: 0.5em 0.3em 0.5em 0.5em;
|
||||
text-align: center;
|
||||
border-left: 1px solid #ffffff;
|
||||
margin: 0;
|
||||
}
|
||||
#navigation li:first-of-type {border: none;}
|
||||
#sitelogo {
|
||||
background: url('../img/logo_mobile.png') no-repeat;
|
||||
width: 114px;
|
||||
height: 54px;
|
||||
@@ -93,107 +102,115 @@
|
||||
top: 5px;
|
||||
z-index: 20;
|
||||
float: left;
|
||||
}
|
||||
|
||||
#teaser {
|
||||
background: none;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
#teaser_text {
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
#navigation {
|
||||
margin: 10px 0;
|
||||
padding: 0;
|
||||
background: #45484d url("../img/navigation-mobile.png") top left repeat-x;
|
||||
background-size: contain;
|
||||
}
|
||||
|
||||
#navigation li {
|
||||
display: inline-block;
|
||||
padding: 0.5em 0.3em 0.5em 0.5em;
|
||||
text-align: center;
|
||||
border-left: 1px solid #ffffff;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#navigation li:first-of-type {
|
||||
border: none;
|
||||
}
|
||||
|
||||
#navigation a {
|
||||
font: bold 12px Arial;
|
||||
color: #FFF;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#sitelogo a {
|
||||
}
|
||||
#sitelogo a {
|
||||
display: block;
|
||||
width: 114px;
|
||||
height: 54px;
|
||||
}
|
||||
|
||||
#siteheader:after {
|
||||
content: ".";
|
||||
}
|
||||
#siteheader:after {
|
||||
content: "";
|
||||
clear: both;
|
||||
display: block;
|
||||
visibility: hidden;
|
||||
height: 0px;
|
||||
}
|
||||
|
||||
#maincontent {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Dynamische Menü */
|
||||
#mainnav {
|
||||
}
|
||||
#redbox {
|
||||
margin-top: 1em;
|
||||
display: block;
|
||||
float: right
|
||||
}
|
||||
|
||||
#toggle, .toggle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#toggle:checked ~ .main_menu {
|
||||
#teaser {
|
||||
background: none;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
#teaser_text {background: rgba(255, 255, 255, 0.5);}
|
||||
#topnav a {
|
||||
display: inline-block;
|
||||
color: #000;
|
||||
font: 400 small-caps 24pt 'Amerika Sans', sans-serif;
|
||||
min-width: 80px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
text-shadow: 2px 2px 2px #2e3436;
|
||||
padding: 5px;
|
||||
}
|
||||
#topnav a.active {color: #bc0a19;}
|
||||
#topnav a:hover {color: #FFF;}
|
||||
#toggle, .toggle {display: none;}
|
||||
#toggle:checked ~ .main_menu {
|
||||
display: block;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
#toggle:checked ~ .toggle, .toggle:hover {background: #45ABD6}
|
||||
|
||||
#toggle:checked ~ .toggle, .toggle:hover {
|
||||
background: #45ABD6;
|
||||
}
|
||||
|
||||
.comment_picture {
|
||||
.comment_picture {
|
||||
display: table-cell;
|
||||
padding: 0px 10px;
|
||||
width: 60px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.comment_header {
|
||||
}
|
||||
.comment_header {
|
||||
display: table-cell;
|
||||
padding: 0px 10px;
|
||||
width: 140px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.comment_header h3 {
|
||||
margin: 0
|
||||
}
|
||||
|
||||
.toggle {
|
||||
z-index: 2;
|
||||
}
|
||||
.comment_header h3 {margin: 0}
|
||||
.comment {display: block}
|
||||
.comment_picture {
|
||||
display: block;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
float: left;
|
||||
vertical-align: top;
|
||||
width: 60px;
|
||||
}
|
||||
.comment_header {
|
||||
display: block;
|
||||
float: left;
|
||||
padding: 0px 10px;
|
||||
vertical-align: top;
|
||||
width: 140px;
|
||||
}
|
||||
.comment_header h3 {margin: 0}
|
||||
.comment_text {
|
||||
border-top: 1px solid #45484d;
|
||||
display: block;
|
||||
margin: 0px 10px;
|
||||
padding-top: 0.5em;
|
||||
clear: both;
|
||||
}
|
||||
.gallery {
|
||||
float: left;
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.gallery h3 {font-size: 12pt;}
|
||||
.game img {
|
||||
float:right;
|
||||
margin: 0.5em 0 0.5em 1em;
|
||||
width: 140px;
|
||||
height: auto;
|
||||
box-shadow: 1px 1px 5px 1px #444;
|
||||
}
|
||||
.game:nth-child(2n+1) img {
|
||||
float:left;
|
||||
margin-right:1em;
|
||||
margin: 0.5em 2em 0.5em 0;
|
||||
}
|
||||
.grid_2 {
|
||||
min-width: 140px;
|
||||
width:31%;
|
||||
margin: 1% 0 1% 0;
|
||||
}
|
||||
.grid_3 {
|
||||
width:48%;
|
||||
margin: 1% 0 1% 0;
|
||||
}
|
||||
.grid_4, .grid_5, .grid_6, .grid_7, .grid_8, .grid_9, .grid_10, .grid_11, .grid_12 {
|
||||
clear: both;
|
||||
margin:0;
|
||||
width: 100%;
|
||||
}
|
||||
.main_menu {
|
||||
position: absolute;
|
||||
display: none;
|
||||
@@ -231,59 +248,37 @@
|
||||
border-left: 3px solid #a40000;
|
||||
}
|
||||
}
|
||||
ul.main_dropdown {
|
||||
list-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
li {padding: 0;}
|
||||
|
||||
a {padding-left: 2em; font-size: 12pt;}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#jumbotron {
|
||||
background: none !important;
|
||||
}
|
||||
|
||||
#redbox {
|
||||
margin-top: 1em;
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
.grid_6, .grid_7, .grid_8, .grid_9, .grid_10, .grid_11, .grid_12 {
|
||||
width: 100%;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.player {
|
||||
display: inline;
|
||||
float: left;
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
position: relative;
|
||||
.officer {
|
||||
float:left;
|
||||
width: 25%;
|
||||
padding:5px;
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
min-width: 60px;
|
||||
text-align: center;
|
||||
|
||||
img {
|
||||
border: 0;
|
||||
border-radius: 50%;
|
||||
box-shadow: 1px 1px 5px 1px #444;
|
||||
width:100%;
|
||||
height:100%;
|
||||
}
|
||||
|
||||
.toggle {
|
||||
.function {font-size:small;margin-top: 0.25em}
|
||||
}
|
||||
.toggle {
|
||||
background: #a40000;
|
||||
border-radius: 5px;
|
||||
color: #FFFFFF;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
width: 150px;
|
||||
margin: 8px 0;
|
||||
padding: 10px;
|
||||
background: #a40000;
|
||||
text-align: center;
|
||||
color: #FFFFFF;
|
||||
content: 'Main Menu';
|
||||
border-radius: 2px;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
transition: all 0.5s linear;
|
||||
}
|
||||
|
||||
.thumbnail {
|
||||
/*user-select: none;*/
|
||||
z-index: 2;
|
||||
}
|
||||
.thumbnail {
|
||||
display: block;
|
||||
position: relative;
|
||||
float: left;
|
||||
@@ -292,152 +287,9 @@ ul.main_dropdown {
|
||||
width: 70px;
|
||||
margin: 5px;
|
||||
box-shadow: 2px 2px 5px #888;
|
||||
}
|
||||
|
||||
.thumbnail img {
|
||||
img {
|
||||
height: 70px;
|
||||
width: 70px;
|
||||
}
|
||||
|
||||
.thumbnail a.delete_image {
|
||||
display: none
|
||||
}
|
||||
|
||||
img.thumbnail {
|
||||
display: block;
|
||||
float: left;
|
||||
height: 70px;
|
||||
width: 70px;
|
||||
margin: 5px;
|
||||
box-shadow: 2px 2px 5px #888;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
border: none;
|
||||
color: #2e3436;
|
||||
border-radius: 10px;
|
||||
margin: 10px 0 0 0;
|
||||
padding: 0 10px 0 160px;
|
||||
background: #f2f5f6; /* Old browsers */
|
||||
background: linear-gradient(135deg, #f2f5f6 0%, #e3eaed 37%, #c8d7dc 100%);
|
||||
background: -moz-linear-gradient(-45deg, #f2f5f6 0%, #e3eaed 37%, #c8d7dc 100%);
|
||||
background: -webkit-gradient(linear, left top, right bottom, color-stop(0%, #f2f5f6),
|
||||
color-stop(37%, #e3eaed), color-stop(100%, #c8d7dc));
|
||||
background: -webkit-linear-gradient(-45deg, #f2f5f6 0%, #e3eaed 37%, #c8d7dc 100%);
|
||||
background: -o-linear-gradient(-45deg, #f2f5f6 0%, #e3eaed 37%, #c8d7dc 100%);
|
||||
background: -ms-linear-gradient(-45deg, #f2f5f6 0%, #e3eaed 37%, #c8d7dc 100%);
|
||||
|
||||
}
|
||||
|
||||
fieldset legend {
|
||||
margin-top: -.1em;
|
||||
margin-left: -150px;
|
||||
color: #a40000;
|
||||
font-family: 'Amerika Sans', sans-serif;
|
||||
font-variant: small-caps;
|
||||
font-weight: 400;
|
||||
font-size: 16pt;
|
||||
text-shadow: 2px 2px 2px #888;
|
||||
}
|
||||
|
||||
fieldset .required {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
fieldset .error {
|
||||
color: #a40000
|
||||
}
|
||||
|
||||
fieldset .buttonbar {
|
||||
border-radius: 0px 0px 10px 10px;
|
||||
margin: 0 -10px 0 -160px;
|
||||
}
|
||||
|
||||
fieldset .help_text {
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
fieldset .field_name {
|
||||
text-align: right;
|
||||
width: 140px;
|
||||
margin: 0 20px 0 -160px;
|
||||
padding-top: 3px;
|
||||
display: inline-block;
|
||||
clear: left;
|
||||
}
|
||||
|
||||
fieldset input, fieldset textarea {
|
||||
border: 1px solid #999999;
|
||||
border-radius: 5px;
|
||||
padding: 2px;
|
||||
margin: 0;
|
||||
font-size: 12pt;
|
||||
}
|
||||
|
||||
fieldset input[maxlength="255"], fieldset textarea {
|
||||
width: 99%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
fieldset ul {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
fieldset ul li {
|
||||
list-style: none;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.pagination {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.pagination a, .pagination .current, .pagination .next, .pagination .previous {
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
padding: 0 0.5em 0 0.5em;
|
||||
}
|
||||
|
||||
.gallery {
|
||||
float: left;
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.gallery h3 {
|
||||
font-size: 12pt;
|
||||
}
|
||||
|
||||
.comment {
|
||||
display: block
|
||||
}
|
||||
|
||||
.comment_picture {
|
||||
display: block;
|
||||
float: left;
|
||||
vertical-align: top;
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
.comment_header {
|
||||
display: block;
|
||||
float: left;
|
||||
padding: 0px 10px;
|
||||
vertical-align: top;
|
||||
width: 140px;
|
||||
}
|
||||
|
||||
.comment_header h3 {
|
||||
margin: 0
|
||||
}
|
||||
|
||||
.comment_text {
|
||||
border-top: 1px solid #45484d;
|
||||
display: block;
|
||||
margin-left: 0px 10px;
|
||||
padding-top: 0.5em;
|
||||
clear: both;
|
||||
}
|
||||
}
|
||||
@@ -1,34 +1,32 @@
|
||||
@media print {
|
||||
|
||||
@page {
|
||||
size: portrait;
|
||||
margin: 0.5cm 0.5cm 0.5cm 1cm;
|
||||
orphans: 3;
|
||||
widows: 3;
|
||||
}
|
||||
|
||||
nav, aside, #comment_form, #navigation, #mainnav, #usernav, #bottom_buttonbar, #footer > form {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
#footer {
|
||||
a:link, a:visited {color: black; font-weight: bold;}
|
||||
body, article {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: #000;
|
||||
background: #fff;
|
||||
}
|
||||
h1 {font-size: 32pt;}
|
||||
h2, h3, h4, h5, h6 {
|
||||
text-shadow: none;
|
||||
page-break-after: avoid;
|
||||
}
|
||||
img {
|
||||
max-width: 100% !important;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
nav, aside {display: none;}
|
||||
ul {page-break-inside: avoid;}
|
||||
#footer {
|
||||
width: 100%;
|
||||
padding-top: 0.5em;
|
||||
border-top: 1px solid black;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
* {
|
||||
-webkit-print-color-adjust: exact;
|
||||
print-color-adjust: exact;
|
||||
}
|
||||
|
||||
a:link, a:visited {
|
||||
color: black;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#sitelogo {
|
||||
}
|
||||
#jumbotron {background: none !important;}
|
||||
#maincontent nav {display: none}
|
||||
#maincontent aside {display: none}
|
||||
#sitelogo {
|
||||
background: url(../img/logo.png) top right no-repeat;
|
||||
background-size: contain;
|
||||
left: 0;
|
||||
@@ -39,53 +37,9 @@
|
||||
font-size: 8pt;
|
||||
top: 5px;
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
#jumbotron {
|
||||
background: none !important;
|
||||
}
|
||||
|
||||
body, article {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: #000;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 32pt;
|
||||
}
|
||||
h2, h3, h4, h5, h6 {
|
||||
text-shadow: none;
|
||||
page-break-after: avoid;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100% !important;
|
||||
}
|
||||
|
||||
ul, img {
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
|
||||
#comment_form, #comments, #footer, #navigation, #mainnav, #usernav, #bottom_buttonbar, #footer > form {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.more_link {
|
||||
display: none
|
||||
}
|
||||
|
||||
#maincontent nav {
|
||||
display: none
|
||||
}
|
||||
|
||||
#maincontent aside {
|
||||
display: none
|
||||
}
|
||||
|
||||
.grid_6, grid_7, .grid_8, grid_9, .grid_10, .grid_11, .grid_12 {
|
||||
width: 100%
|
||||
}
|
||||
}
|
||||
#comment_form, #comments, #footer, #navigation, #mainnav,
|
||||
#usernav, #bottom_buttonbar, #footer > form {display: none;}
|
||||
|
||||
.grid_6, grid_7, .grid_8, grid_9, .grid_10, .grid_11, .grid_12 {width: 100%}
|
||||
.more_link {display: none}
|
||||
|
||||
@@ -15,15 +15,28 @@
|
||||
document.createElement('aside');
|
||||
document.createElement('footer');
|
||||
document.createElement('hgroup');
|
||||
|
||||
</script>
|
||||
<![endif]-->
|
||||
<link rel="stylesheet" href="{{STATIC_URL}}css/kasu.css">
|
||||
<link rel="alternate" type="application/rss+xml" title="{% trans 'Current News' %}"
|
||||
href="{% url 'feed-latest-news' %}"/>
|
||||
<link rel="alternate" type="application/rss+xml" title="{% trans 'Recent Comments' %}"
|
||||
href="{% url 'feed-latest-comments' %}"/>
|
||||
<link rel="shortcut icon" href="{{STATIC_URL}}img/favicon.ico">
|
||||
<link rel="stylesheet" href="{{STATIC_URL}}css/kasu.css">
|
||||
<link rel="apple-touch-icon" sizes="57x57" href="{{STATIC_URL}}img/apple-touch-icon-57x57.png">
|
||||
<link rel="apple-touch-icon" sizes="60x60" href="{{STATIC_URL}}img/apple-touch-icon-60x60.png">
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="{{STATIC_URL}}img/apple-touch-icon-72x72.png">
|
||||
<link rel="apple-touch-icon" sizes="76x76" href="{{STATIC_URL}}img/apple-touch-icon-76x76.png">
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="{{STATIC_URL}}img/apple-touch-icon-114x114.png">
|
||||
<link rel="apple-touch-icon" sizes="120x120" href="{{STATIC_URL}}img/apple-touch-icon-120x120.png">
|
||||
<link rel="apple-touch-icon" sizes="144x144" href="{{STATIC_URL}}img/apple-touch-icon-144x144.png">
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="{{STATIC_URL}}img/apple-touch-icon-152x152.png">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="{{STATIC_URL}}img/apple-touch-icon-180x180.png">
|
||||
<link rel="icon" type="image/png" href="{{STATIC_URL}}img/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="{{STATIC_URL}}img/android-chrome-192x192.png" sizes="192x192">
|
||||
<link rel="icon" type="image/png" href="{{STATIC_URL}}img/favicon-96x96.png" sizes="96x96">
|
||||
<link rel="icon" type="image/png" href="{{STATIC_URL}}img/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="mask-icon" href="{{STATIC_URL}}img/safari-pinned-tab.svg" color="#5bbad5">
|
||||
{% block opengraph %}
|
||||
<meta property="og:type" content="website"/>
|
||||
<meta property="og:title" content="Kasu - Verein Japanische Spielekultur"/>
|
||||
@@ -37,7 +50,7 @@
|
||||
<div id="sitelogo"><a href="/index.html">Kasu - traditionelle asiatische Spielkultur</a></div>
|
||||
<nav id="mainnav">
|
||||
<input type="checkbox" id="toggle" aria-hidden="true" />
|
||||
<label for="toggle" class="toggle" onclick aria-hidden="true">{% trans "Menu" %}</label>
|
||||
<label for="toggle" class="toggle" onclick aria-hidden="true"><span class="fa fa-bars"></span> {% trans "Menu" %}</label>
|
||||
<ul class="main_menu">
|
||||
{% for item in top_menu_items %}
|
||||
<li><a href="{{item.get_absolute_url}}" title="{{ item.title }}"
|
||||
@@ -55,14 +68,10 @@
|
||||
<main id="maincontent">
|
||||
<header id="jumbotron"
|
||||
style="background-image: url('{% block jumbotron_background %}{{STATIC_URL}}img/teaser/{{current_top_page.slug|default:'jumbotron'}}.jpg{% endblock %}')">
|
||||
{% block teaser %}
|
||||
<h1>{% if title %}{{title}}{% elif current_page %}{{ current_page.title }}{% elif current_top_page %}{{current_top_page.title }}{% endif %}</h1>
|
||||
{% endblock %}
|
||||
<aside id="redbox">
|
||||
{% block redbox %}
|
||||
{% if current_event %}
|
||||
<h2>{% trans "Current Event" %}</h2>
|
||||
|
||||
<h3>{{ current_event.name}}</h3>
|
||||
<ul class="fa-ul">
|
||||
<li><span class="fa-li fa fa-clock-o"></span><strong>{% trans "Since" %}:</strong> {{current_event.start|timesince}}</li>
|
||||
@@ -75,9 +84,7 @@
|
||||
{% trans "More Details" %} <span class="fa fa-arrow-right"></span></a></div>
|
||||
{% else %}
|
||||
<h2>{% trans "Next Event" %}</h2>
|
||||
|
||||
<h3>{{ next_event.name}}</h3>
|
||||
|
||||
<ul class="fa-ul">
|
||||
<li><span class="fa-li fa fa-clock-o"></span><strong>{% trans "in" %}:</strong> {{next_event.start|timeuntil}}</li>
|
||||
<li><span class="fa-li fa fa-calendar"></span><strong>{% trans "Start" %}:</strong>
|
||||
@@ -93,12 +100,18 @@
|
||||
</h3>
|
||||
<ul class="fa-ul">
|
||||
{% for event in upcoming_events %}
|
||||
<li><span class="fa-li fa fa-calendar-o"></span> {{event.start|date:'d. M:'}} <a href="{{ event.get_absolute_url}}">{{event.name}}</a></li>
|
||||
<li><span class="fa-li fa fa-calendar-o"></span>
|
||||
<a href="{{ event.get_absolute_url}}">
|
||||
<time datetime="{{event.start|date:'c'}}">{{event.start|date:'D d. M:'}}</time>
|
||||
{{event.name}}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endblock %}
|
||||
</aside>
|
||||
</header>
|
||||
{% block teaser %}
|
||||
<h1>{% if title %}{{title}}{% elif current_page %}{{ current_page.title }}{% elif current_top_page %}{{current_top_page.title }}{% endif %}</h1>
|
||||
{% endblock %}
|
||||
</header>
|
||||
{% block navigation %}{% if current_top_page.subpages.count %}
|
||||
<ul id="navigation">
|
||||
<li><a href="{{current_top_page.get_absolute_url}}"
|
||||
@@ -145,7 +158,7 @@
|
||||
</main>
|
||||
<footer id="footer">
|
||||
<p><strong>Herausgeber:</strong> Verein Kasu - traditionelle asiatische Spielkultur (<a
|
||||
href="/verein/impressum.html">{% trans "Imprint" %}</a> – <a
|
||||
href="/about.html#impressum">{% trans "Imprint" %}</a> – <a
|
||||
href='mailto:ve%72e%69n@%6B%61su.a%74'>{% trans "contact" %}</a>)
|
||||
</p>
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{% load comments i18n %}
|
||||
{% load comments i18n thumbnail %}
|
||||
<form action="{% comment_form_target %}" method="post" id='comment_form' class="grid_12">
|
||||
{% csrf_token %}
|
||||
<fieldset class="comment">
|
||||
@@ -10,10 +10,10 @@
|
||||
<input type="hidden" name="next" value="{{ next|default:request.path_info }}"/>
|
||||
</p>
|
||||
<div class="comment">
|
||||
|
||||
<div class="comment_picture"><img class="avatar"
|
||||
src="{% if user.thumbnail %}{{user.thumbnail.url}}{% else %}{{STATIC_URL}}img/unknown_thumbnail.png{% endif %}"
|
||||
width="60" height="60"
|
||||
alt=""/></div>
|
||||
src="{% thumbnail user.avatar|default:'unknown_profile.jpg' 'avatar' %}"
|
||||
width="70" height="70" alt=""/></div>
|
||||
<header class="comment_header">
|
||||
<h3><a href="{{ user.get_profile.get_absolute_url }}" class="user">{{user}}</a></h3>
|
||||
|
||||
@@ -28,9 +28,8 @@
|
||||
{% else %}
|
||||
<div class="comment">
|
||||
<div class="comment_picture"><img class="avatar"
|
||||
src="{{STATIC_URL}}img/unknown_thumbnail.png"
|
||||
width="60" height="60"
|
||||
alt=""/></div>
|
||||
src="{% thumbnail user.avatar|default:'unknown_profile.jpg' 'avatar' %}"
|
||||
width="70" height="70" alt=""/></div>
|
||||
<header class="comment_header">
|
||||
<h3>{% trans "not logged in" %}</h3>
|
||||
</header>
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
{% load i18n django_markdown %}
|
||||
{% load i18n thumbnail %}
|
||||
<h2 class="grid_12" id="comments">{% trans 'Comments' %}</h2>
|
||||
{% for comment in comment_list %}
|
||||
<article id="c{{ comment.id }}" class="comment">
|
||||
<div class="comment_picture">
|
||||
<img class="avatar" src="{% if comment.user.get_profile.thumbnail %}
|
||||
{{comment.user.get_profile.thumbnail.url}}
|
||||
{% else %}
|
||||
{{STATIC_URL}}img/unknown_thumbnail.png
|
||||
{% endif %}" alt=""/>
|
||||
<img class="avatar" src="{% thumbnail comment.user.avatar|default:'unknown_profile.jpg' 'avatar' %}" alt=""/>
|
||||
</div>
|
||||
<header class="comment_header">
|
||||
<h3><a href="{{ comment.user.get_profile.get_absolute_url }}" class="user">{{comment.user}}</a></h3>
|
||||
<time datetime="{{comment.submit_date|date:'Y-m-d'}}" class="submit_date">{{comment.submit_date|timesince}}</time>
|
||||
</header>
|
||||
<div class="comment_text">{{comment.comment|markdown_safe}}</div>
|
||||
<div class="comment_text">{{comment.comment}}</div>
|
||||
</article>
|
||||
{% endfor %}
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "base.html" %}
|
||||
{% load i18n django_markdown %}
|
||||
{% load i18n thumbnail %}
|
||||
|
||||
{% block title %}{% trans "Preview your comment" %}{% endblock %}
|
||||
|
||||
@@ -11,17 +11,14 @@
|
||||
{% else %}
|
||||
<article id="c{{ comment.id }}" class="comment">
|
||||
<div class="comment_picture">
|
||||
<img class="avatar" src="{% if user.get_profile.thumbnail %}
|
||||
{{user.get_profile.thumbnail.url}}
|
||||
{% else %}
|
||||
{{STATIC_URL}}img/unknown_thumbnail.png
|
||||
{% endif %}" alt=""/>
|
||||
<img class="avatar" src="{% thumbnail user.avatar|default:'unknown_profile.jpg' 'avatar' %}"
|
||||
width="70" height="70" alt="{{ comment.user }}"/>
|
||||
</div>
|
||||
<header class="comment_header">
|
||||
<a href="{{ user.get_profile.get_absolute_url }}" class="user">{{comment.user}}</a>
|
||||
<div class="submit_date"><time time="{% now 'c' %}">{% now 'DATETIME_FORMAT' %}</time></div>
|
||||
</header>
|
||||
<div class="comment_text">{{comment|markdown_safe}}</div>
|
||||
<div class="comment_text">{{comment}}</div>
|
||||
</article>
|
||||
|
||||
{% endif %}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
{{ form.media }}
|
||||
{% for hidden in form.hidden_fields %}{{ hidden }}{% endfor %}
|
||||
{% for field in form.visible_fields %}
|
||||
<div>
|
||||
<label for="{% if field.html_name == 'recaptcha' %}recaptcha_response_field{% else %}id_{{ field.html_name}}{% endif %}" class="field_name {{ field.css_classes }}">{{ field.label }}</label>
|
||||
<div>
|
||||
<label {% if field.html_name != 'recaptcha' %}for="id_{{ field.html_name}}"{% endif %} class="field_name {{ field.css_classes }}">{{ field.label }}</label>
|
||||
{{ field }}
|
||||
{%if field.help_text %}<p class="help_text">{{field.help_text}}</p>{% endif %}
|
||||
{%if field.errors %}{{ field.errors }}{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% for hidden in form.hidden_fields %}{{ hidden }}{% endfor %}
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "base.html" %}
|
||||
{% load i18n comments%}
|
||||
{% load i18n comments thumbnail %}
|
||||
|
||||
{% block title %}{% trans 'traditional Asian game culture' %}{% endblock %}
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
|
||||
{% block maincontent %}
|
||||
<div class="grid_8">
|
||||
{% for article in recent_article_list %}{% get_comment_count for article as comment_count %}
|
||||
{% for article in recent_article_list %}
|
||||
{% get_comment_count for article as comment_count %}
|
||||
<article class="article">
|
||||
<header>
|
||||
<h2><a href="{{article.get_absolute_url}}">{{article.headline}}</a></h2>
|
||||
@@ -24,7 +25,9 @@
|
||||
{% trans "Comments" %}</a></li>
|
||||
</ul>
|
||||
</header>
|
||||
<a href="{{article.get_absolute_url}}"><img src="{{article.posting_image.url}}" alt="{{article.category}}:"
|
||||
<a href="{{article.get_absolute_url}}">
|
||||
|
||||
<img src="{{article.get_image|thumbnail_url:'article'}}" alt="{{article.category}}:"
|
||||
class="posting_image" width="200" height="120"/></a>
|
||||
{{article.content|truncatewords_html:50}}
|
||||
<footer class="more_link"><a href="{{article.get_absolute_url}}" class="button">{% trans "Read More"%} <span class="fa fa-arrow-right"></span></a></footer>
|
||||
@@ -56,12 +59,10 @@
|
||||
<h2>{% trans 'Kasu in the social network' %}</h2>
|
||||
|
||||
<p style="text-align: center">
|
||||
<a href="https://www.facebook.com/Kasu.at"><img src="{{STATIC_URL}}img/facebook.png" alt="Facebook"
|
||||
title="{% trans 'Visit us on' %} Facebook" width="78" height="78"></a>
|
||||
<a href="https://twitter.com/KasuAustria"><img src="{{STATIC_URL}}img/twitter.png" alt="Twitter"
|
||||
title="{% trans 'Visit us on' %} Twitter" width="78" height="78"></a>
|
||||
<a href="https://plus.google.com/u/0/114092233962732014973/"><img src="{{STATIC_URL}}img/google_plus.png"
|
||||
alt="Google+" title="{% trans 'Visit us on' %} Google+" width="78" height="78"></a>
|
||||
<a href="https://www.facebook.com/Kasu.at"><span class="fa fa-facebook fa-5x" title="{% trans 'Visit us on' %} Facebook"></span></a>
|
||||
<a href="https://twitter.com/KasuAustria"><span
|
||||
class="fa fa-twitter fa-5x"
|
||||
title="{% trans 'Visit us on' %} Twitter"></span></a>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
|
||||
@@ -1,22 +1,15 @@
|
||||
{% load i18n %}
|
||||
<nav class="pagination">
|
||||
{% if page_obj.has_previous %}
|
||||
<a class="previous" href="?page={{ page_obj.previous_page_number }}"><span aria-hidden="true">←</span> {% trans "Previous" %}</a></li>
|
||||
{% else %}
|
||||
<div class="previous disabled"><span aria-hidden="true">←</span> {% trans "Prev" %}</div>
|
||||
{% endif %}
|
||||
<nav class="grid_12 pagination">
|
||||
<a {% if page_obj.has_previous %}class="previous" href="?page={{ page_obj.previous_page_number }}"{% else %}class="previous disabled" {% endif %}>
|
||||
<span class="fa fa-arrow-left"></span>{% trans "Previous" %}
|
||||
</a>
|
||||
|
||||
{% for page in paginator.page_range %}
|
||||
{% ifequal page_obj.number page %}
|
||||
<div class="current">{{page}}</div>
|
||||
{% else %}
|
||||
<a href="?page={{page}}">{{page}}</a>
|
||||
{% endifequal %}
|
||||
<a {% ifequal page_obj.number page %}class="active"{% else %}href="?page={{page}}"{% endifequal %}>{{page}}</a>
|
||||
{% endfor %}
|
||||
{% if page_obj.has_next %}
|
||||
<a class="next" href="?page={{ page_obj.next_page_number }}">{% trans "Next" %} <span aria-hidden="true">→</span></a></li>
|
||||
{% else %}
|
||||
<div class="next disabled">{% trans "Next" %} <span aria-hidden="true">→</span></div>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
<a {% if page_obj.has_next %}class="next" href="?page={{ page_obj.next_page_number }}"{% else %}class="next disabled"{% endif %}>
|
||||
{% trans "Next" %} <span class="fa fa-arrow-right"></span>
|
||||
</a>
|
||||
</nav>
|
||||
|
||||
|
||||
@@ -17,39 +17,43 @@ urlpatterns = patterns(
|
||||
url(r'^404/$', TemplateView.as_view(template_name='404.html')),
|
||||
url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
|
||||
url(r'^admin/', include(admin.site.urls)),
|
||||
url(r'^ckeditor/', include('ckeditor.urls')),
|
||||
url(r'^ckeditor/', include('ckeditor_uploader.urls')),
|
||||
url(r'^comments/', include('django_comments.urls')),
|
||||
url(r'^content/', include('content.urls')),
|
||||
url(r'^events/', include('events.urls')),
|
||||
url(r'^events.ics$', EventListIcal.as_view(), name='events-ical'),
|
||||
url(r'^feeds/latest/$', LatestNews(), name='feed-latest-news'),
|
||||
url(r'^feeds/comments/$', LatestComments(), name='feed-latest-comments'),
|
||||
url(r'^gallery/', include('gallery.urls')),
|
||||
url(r'^google25dabc1a49a9ef03.html$', TemplateView.as_view(template_name='google25dabc1a49a9ef03.html')),
|
||||
url(r'^gallery/', include('events.gallery_urls')),
|
||||
url(r'^google25dabc1a49a9ef03.html$', TemplateView.as_view(
|
||||
template_name='google25dabc1a49a9ef03.html')),
|
||||
url(r'^grappelli/', include('grappelli.urls')),
|
||||
url(r'^i18n/', include('django.conf.urls.i18n'), name='start-page'),
|
||||
url(r'^index.html$', StartPage.as_view()),
|
||||
url(r'^markdown/', include('django_markdown.urls')),
|
||||
url(r'^membership/', include('membership.urls')),
|
||||
url(r'^news/', include('content.news_urls')),
|
||||
url(r'^ranking/', include('mahjong_ranking.urls')),
|
||||
url(r'^ranking/', include('maistar_ranking.urls')),
|
||||
url(r'^robots.txt$', TemplateView.as_view(template_name='robots.txt')),
|
||||
url(r'^users/$', MembershipDetail.as_view(), name='membership-details'),
|
||||
url(r'^users/(?P<username>[\-\.\d\w]+)/$', MembershipDetail.as_view(), name='membership-details'),
|
||||
url(r'^users/(?P<username>[\-\.\d\w]+)/$',
|
||||
MembershipDetail.as_view(), name='membership-details'),
|
||||
)
|
||||
|
||||
if settings.DEBUG:
|
||||
urlpatterns += patterns('',
|
||||
url(r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}),
|
||||
url(r'^media/(?P<path>.*)$', 'django.views.static.serve',
|
||||
{'document_root': settings.MEDIA_ROOT}),
|
||||
)
|
||||
|
||||
if 'rosetta' in settings.INSTALLED_APPS:
|
||||
urlpatterns += patterns('', url(r'^rosetta/', include('rosetta.urls')),)
|
||||
urlpatterns += patterns('', url(r'^rosetta/',
|
||||
include('rosetta.urls')),)
|
||||
|
||||
if 'debug_toolbar' in settings.INSTALLED_APPS:
|
||||
import debug_toolbar
|
||||
urlpatterns += patterns('', url(r'^__debug__/', include(debug_toolbar.urls)),)
|
||||
urlpatterns += patterns('', url(r'^__debug__/',
|
||||
include(debug_toolbar.urls)),)
|
||||
|
||||
urlpatterns += patterns('',
|
||||
url(r'^add_page/(?P<path>[\+\.\-\d\w\/]+)/$',
|
||||
@@ -58,5 +62,6 @@ urlpatterns += patterns('',
|
||||
PageEditForm.as_view(), name='edit-page'),
|
||||
url(r'^(?P<path>[\-\d\w\/]+)\.html$',
|
||||
PageHtml.as_view(), name='view-page'),
|
||||
url(r'^(?P<path>[\-\d\w\/]+)\.pdf$', PagePdf.as_view()),
|
||||
)
|
||||
url(r'^(?P<path>[\-\d\w\/]+)\.pdf$',
|
||||
PagePdf.as_view()),
|
||||
)
|
||||
|
||||
@@ -273,13 +273,16 @@ STATUS_CHOICES = (
|
||||
)
|
||||
USER_MODEL = get_user_model()
|
||||
|
||||
|
||||
class OverwriteStorage(FileSystemStorage):
|
||||
|
||||
def get_available_name(self, name):
|
||||
"""
|
||||
Returns a filename that's free on the target storage system, and
|
||||
available for new content to be written to.
|
||||
"""
|
||||
# If the filename already exists, remove it as if it was a true file system
|
||||
# If the filename already exists, remove it as if it was a true file
|
||||
# system
|
||||
if self.exists(name):
|
||||
os.remove(os.path.join(settings.MEDIA_ROOT, name))
|
||||
return name
|
||||
|
||||
@@ -14,5 +14,3 @@ os.environ['DJANGO_SETTINGS_MODULE'] = 'kasu.settings.production'
|
||||
import django.core.handlers.wsgi
|
||||
|
||||
application = django.core.handlers.wsgi.WSGIHandler()
|
||||
|
||||
|
||||
|
||||
@@ -24,7 +24,8 @@ def recalculate(modeladmin, request, queryset):
|
||||
set_dirty(user=kyu_dan_ranking.user_id)
|
||||
elif isinstance(modeladmin, SeasonRankingAdmin):
|
||||
for ladder_ranking in queryset:
|
||||
set_dirty(user=ladder_ranking.user_id, season=ladder_ranking.season)
|
||||
set_dirty(user=ladder_ranking.user_id,
|
||||
season=ladder_ranking.season)
|
||||
recalculate.short_description = _("Recalculate")
|
||||
|
||||
|
||||
@@ -41,6 +42,7 @@ def unconfirm(modeladmin, request, queryset):
|
||||
hanchan.save()
|
||||
unconfirm.short_description = _('Set unconfirmed')
|
||||
|
||||
|
||||
class EventRankingAdmin(admin.ModelAdmin):
|
||||
list_filter = ['event']
|
||||
list_display = ('placement', 'user', 'event', 'avg_placement', 'avg_score',
|
||||
@@ -84,7 +86,7 @@ class KyuDanAdmin(admin.ModelAdmin):
|
||||
'classes': ('grp-collapse grp-open',),
|
||||
}),
|
||||
('Frühere Aufzeichnungen', {
|
||||
'fields': ('legacy_date', ('legacy_kyu_points', 'legacy_dan_points')),
|
||||
'fields': ('legacy_date', 'legacy_hanchan_count', ('legacy_kyu_points', 'legacy_dan_points')),
|
||||
'classes': ('grp-collapse grp-closed',),
|
||||
}),
|
||||
)
|
||||
|
||||
@@ -23,11 +23,11 @@ class HanchanForm(forms.ModelForm):
|
||||
|
||||
class Meta(object):
|
||||
model = models.Hanchan
|
||||
fields = ( 'start',
|
||||
'player1', 'player1_input_score',
|
||||
'player2', 'player2_input_score',
|
||||
'player3', 'player3_input_score',
|
||||
'player4', 'player4_input_score',
|
||||
fields = ('start',
|
||||
'player1', 'player1_input_score', # 'player1_comment',
|
||||
'player2', 'player2_input_score', # 'player2_comment',
|
||||
'player3', 'player3_input_score', # 'player3_comment',
|
||||
'player4', 'player4_input_score', # 'player4_comment',
|
||||
'comment')
|
||||
widgets = {'event': forms.HiddenInput(),
|
||||
'comment': forms.widgets.Textarea(attrs={'rows': 4, 'cols': 40})
|
||||
@@ -37,31 +37,19 @@ class HanchanForm(forms.ModelForm):
|
||||
super(HanchanForm, self).__init__(*args, **kwargs)
|
||||
# self.fields['event'].widget.attrs['disabled'] = True
|
||||
for i in xrange(1, 4):
|
||||
self.fields['player%d_input_score' % i].widget.attrs['size'] = 6
|
||||
self.fields['player%d_input_score' % i].widget.attrs['type'] = 'number'
|
||||
player_input_score = 'player%d_input_score' % i
|
||||
self.fields[player_input_score].widget.attrs['size'] = 6
|
||||
self.fields[player_input_score].widget.attrs['type'] = 'number'
|
||||
|
||||
|
||||
'''
|
||||
def clean_start(self):
|
||||
u"""Das Datum darf nicht in der Zukunft liegen und es muss innerhalb
|
||||
der Dauer des Events liegen."""
|
||||
start = self.cleaned_data['start']
|
||||
event = self.cleaned_data['event']
|
||||
if start > timezone.now():
|
||||
raise django.forms.ValidationError(
|
||||
_("It's not allowed to enter future games."))
|
||||
if not event.start <= start <= event.end:
|
||||
raise django.forms.ValidationError(
|
||||
_("Only games running during this event are allowed."))
|
||||
return start
|
||||
'''
|
||||
|
||||
class HanchanAdminForm(HanchanForm):
|
||||
|
||||
class Meta(object):
|
||||
model = models.Hanchan
|
||||
fields = HanchanForm.Meta.fields + ('confirmed',)
|
||||
|
||||
|
||||
|
||||
class SeasonSelectForm(django.forms.Form):
|
||||
season = django.forms.ChoiceField(label='', choices=('a', 'b', 'c'))
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ msgstr ""
|
||||
"Project-Id-Version: kasu.mahjong_ranking\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-08-22 23:28+0200\n"
|
||||
"PO-Revision-Date: 2015-08-22 15:09+0100\n"
|
||||
"Last-Translator: Christian Berg <xeniac@posteo.at>\n"
|
||||
"PO-Revision-Date: 2015-09-06 00:13+0200\n"
|
||||
"Last-Translator: Christian Berg <xeniac.at@gmail.com>\n"
|
||||
"Language-Team: Kasu <verein@kasu.at>\n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -375,7 +375,7 @@ msgstr "%s wurde erfolgreich aktualisiert."
|
||||
#: views.py:96
|
||||
#, python-format
|
||||
msgid "%s has been added successfully. You can now add a new one."
|
||||
msgstr "%s wurde erfolgreich hinzugefügt. Du kannst eine neue anlagen."
|
||||
msgstr "%s wurde erfolgreich hinzugefügt. Du kannst eine neue eintragen."
|
||||
|
||||
#: views.py:113 views.py:129
|
||||
msgid "Event does not exist"
|
||||
|
||||
41
src/mahjong_ranking/management/commands/export-ranking.py
Normal file
41
src/mahjong_ranking/management/commands/export-ranking.py
Normal file
@@ -0,0 +1,41 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Export Mahjong Rankings...
|
||||
"""
|
||||
|
||||
from operator import itemgetter
|
||||
from django.core.management.base import BaseCommand
|
||||
from mahjong_ranking.models import SeasonRanking
|
||||
from openpyxl import Workbook
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Exports the SeasonRankings"
|
||||
|
||||
def geneate_seasonexcel(self, json_data):
|
||||
|
||||
wb = Workbook()
|
||||
worksheet = wb.active
|
||||
|
||||
worksheet.append([
|
||||
'Rang', 'Spitzname',
|
||||
'⌀ Platz', '⌀ Punkte',
|
||||
'Hanchans', 'Gut', 'Gewonnen'
|
||||
])
|
||||
|
||||
json_data = json_data.values()
|
||||
json_data = sorted(json_data, key=itemgetter('placement'))
|
||||
for row in json_data:
|
||||
print row
|
||||
worksheet.append([
|
||||
row['placement'], row['username'],
|
||||
row['avg_placement'], row['avg_score'],
|
||||
row['hanchan_count'],
|
||||
row['good_hanchans'], row['won_hanchans']
|
||||
])
|
||||
wb.save("sample.xlsx")
|
||||
|
||||
def handle(self, *args, **options):
|
||||
season_json = SeasonRanking.objects.json_data()
|
||||
self.geneate_seasonexcel(season_json)
|
||||
@@ -85,7 +85,6 @@ class Command(BaseCommand):
|
||||
self.add_players(hanchan)
|
||||
hanchan.save()
|
||||
|
||||
|
||||
def handle(self, *args, **options):
|
||||
num_hanchans = int(options.get('hanchans', 4))
|
||||
self.user_list = list(auth.get_user_model().objects.all())
|
||||
@@ -93,5 +92,3 @@ class Command(BaseCommand):
|
||||
for event in Event.objects.all():
|
||||
for i in range(random.randrange(2, 8)):
|
||||
self.create_hanchan(event)
|
||||
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
__author__ = 'christian'
|
||||
|
||||
from datetime import date
|
||||
|
||||
from django.db import models
|
||||
|
||||
|
||||
class HanchanManager(models.Manager):
|
||||
|
||||
use_for_related_fields = True
|
||||
|
||||
def confirmed_hanchans(self, user=None, **kwargs):
|
||||
@@ -77,3 +77,25 @@ class SeasonRankingManager(models.Manager):
|
||||
def season_list(self):
|
||||
values_list = self.model.objects.values_list('season', flat=True)
|
||||
return values_list.order_by('season').distinct()
|
||||
|
||||
def json_data(self, season=None):
|
||||
season = season or date.today().year
|
||||
json_data = {}
|
||||
values = self.filter(season=season, placement__isnull=False)
|
||||
values = values.values('placement', 'user_id', 'user__username',
|
||||
'user__first_name', 'user__last_name', 'avg_placement', 'avg_score',
|
||||
'hanchan_count', 'good_hanchans', 'won_hanchans')
|
||||
for user in values:
|
||||
json_data[user['user_id']] = {
|
||||
'placement': user['placement'],
|
||||
'user_id': user['user_id'],
|
||||
'username': user['user__username'],
|
||||
'first_name': user['user__first_name'],
|
||||
'last_name': user['user__last_name'],
|
||||
'avg_placement': user['avg_placement'],
|
||||
'avg_score': user['avg_score'],
|
||||
'hanchan_count': user['hanchan_count'],
|
||||
'good_hanchans': user['good_hanchans'],
|
||||
'won_hanchans': user['won_hanchans']
|
||||
}
|
||||
return json_data
|
||||
|
||||
@@ -36,38 +36,41 @@ class DenormalizationUpdateMiddleware(object):
|
||||
cache.set('ladder_ranking_queue', set(), 360)
|
||||
|
||||
for event_id in self.event_queue:
|
||||
self.update_event_placement()
|
||||
self.update_event_placements()
|
||||
for season in self.season_queue:
|
||||
self.update_season_placements()
|
||||
|
||||
|
||||
|
||||
return response
|
||||
|
||||
def recalculate_event_rankings(self, queue):
|
||||
# recalculate tournament (event) rankings:
|
||||
for event_id, user_id in queue:
|
||||
logger.info("recalculate %d tournament Ranking in %s", user_id, event_id)
|
||||
ranking = models.EventRanking.objects.get_or_create(event_id=event_id, user_id=user_id)[0]
|
||||
logger.info("recalculate %d tournament Ranking in %s",
|
||||
user_id, event_id)
|
||||
ranking = models.EventRanking.objects.get_or_create(
|
||||
event_id=event_id, user_id=user_id)[0]
|
||||
ranking.recalculate()
|
||||
self.event_queue.add(event_id)
|
||||
return queue
|
||||
|
||||
def recalulate_kyu_dan_ranking(self, queue):
|
||||
for user_id in queue:
|
||||
ranking = models.KyuDanRanking.objects.get_or_create(user_id=user_id)[0]
|
||||
ranking = models.KyuDanRanking.objects.get_or_create(user_id=user_id)[
|
||||
0]
|
||||
ranking.recalculate()
|
||||
return queue
|
||||
|
||||
def recalculate_ladder_ranking(self, queue):
|
||||
for season, user_id in queue:
|
||||
ladder = models.SeasonRanking.objects.get_or_create(user_id=user_id, season=season)[0]
|
||||
ladder = models.SeasonRanking.objects.get_or_create(
|
||||
user_id=user_id, season=season)[0]
|
||||
ladder.recalculate()
|
||||
self.season_queue.add(season)
|
||||
|
||||
def update_event_placements(self):
|
||||
for event_id in self.event_queue:
|
||||
eventranking_set = models.EventRanking.objects.filter(event_id=event_id).order_by('avg_placement', '-avg_score')
|
||||
eventranking_set = models.EventRanking.objects.filter(
|
||||
event_id=event_id).order_by('avg_placement', '-avg_score')
|
||||
placement = 1
|
||||
for ranking in eventranking_set:
|
||||
ranking.placement = placement
|
||||
|
||||
157
src/mahjong_ranking/migrations/0001_initial.py
Normal file
157
src/mahjong_ranking/migrations/0001_initial.py
Normal file
@@ -0,0 +1,157 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('events', '0005_auto_20150907_2021'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='EventRanking',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID',
|
||||
serialize=False, auto_created=True, primary_key=True)),
|
||||
('placement', models.PositiveIntegerField(null=True, blank=True)),
|
||||
('avg_placement', models.FloatField(default=4)),
|
||||
('avg_score', models.FloatField(default=0)),
|
||||
('hanchan_count', models.PositiveIntegerField(default=0)),
|
||||
('good_hanchans', models.PositiveIntegerField(default=0)),
|
||||
('won_hanchans', models.PositiveIntegerField(default=0)),
|
||||
('event', models.ForeignKey(to='events.Event')),
|
||||
('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'ordering': ('placement', 'avg_placement', '-avg_score'),
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Hanchan',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID',
|
||||
serialize=False, auto_created=True, primary_key=True)),
|
||||
('start', models.DateTimeField(
|
||||
help_text='Wichtig damit die richtigen Hanchans in die Wertung kommen.', verbose_name='Beginn')),
|
||||
('player1_input_score', models.IntegerField(verbose_name='Punkte')),
|
||||
('player1_game_score', models.PositiveIntegerField(
|
||||
default=0, verbose_name='Punkte', editable=False)),
|
||||
('player1_placement', models.PositiveSmallIntegerField(
|
||||
default=0, editable=False)),
|
||||
('player1_kyu_points', models.SmallIntegerField(
|
||||
null=True, editable=False, blank=True)),
|
||||
('player1_dan_points', models.SmallIntegerField(
|
||||
null=True, editable=False, blank=True)),
|
||||
('player1_bonus_points', models.SmallIntegerField(
|
||||
null=True, editable=False, blank=True)),
|
||||
('player1_comment', models.CharField(verbose_name='Anmerkung',
|
||||
max_length=255, editable=False, blank=True)),
|
||||
('player2_input_score', models.IntegerField(verbose_name='Punkte')),
|
||||
('player2_game_score', models.PositiveIntegerField(
|
||||
default=0, verbose_name='Punkte', editable=False)),
|
||||
('player2_placement', models.PositiveSmallIntegerField(
|
||||
default=0, editable=False)),
|
||||
('player2_kyu_points', models.SmallIntegerField(
|
||||
null=True, editable=False, blank=True)),
|
||||
('player2_dan_points', models.SmallIntegerField(
|
||||
null=True, editable=False, blank=True)),
|
||||
('player2_bonus_points', models.SmallIntegerField(
|
||||
null=True, editable=False, blank=True)),
|
||||
('player2_comment', models.CharField(verbose_name='Anmerkung',
|
||||
max_length=255, editable=False, blank=True)),
|
||||
('player3_input_score', models.IntegerField(verbose_name='Punkte')),
|
||||
('player3_game_score', models.PositiveIntegerField(
|
||||
default=0, verbose_name='Punkte', editable=False)),
|
||||
('player3_placement', models.PositiveSmallIntegerField(
|
||||
default=0, editable=False)),
|
||||
('player3_kyu_points', models.SmallIntegerField(
|
||||
null=True, editable=False, blank=True)),
|
||||
('player3_dan_points', models.SmallIntegerField(
|
||||
null=True, editable=False, blank=True)),
|
||||
('player3_bonus_points', models.SmallIntegerField(
|
||||
null=True, editable=False, blank=True)),
|
||||
('player3_comment', models.CharField(verbose_name='Anmerkung',
|
||||
max_length=255, editable=False, blank=True)),
|
||||
('player4_input_score', models.IntegerField(verbose_name='Punkte')),
|
||||
('player4_game_score', models.PositiveIntegerField(
|
||||
default=0, verbose_name='Punkte', editable=False)),
|
||||
('player4_placement', models.PositiveSmallIntegerField(
|
||||
default=0, editable=False)),
|
||||
('player4_kyu_points', models.SmallIntegerField(
|
||||
null=True, editable=False, blank=True)),
|
||||
('player4_dan_points', models.SmallIntegerField(
|
||||
null=True, editable=False, blank=True)),
|
||||
('player4_bonus_points', models.SmallIntegerField(
|
||||
null=True, editable=False, blank=True)),
|
||||
('player4_comment', models.CharField(verbose_name='Anmerkung',
|
||||
max_length=255, editable=False, blank=True)),
|
||||
('comment', models.TextField(verbose_name='Anmerkung', blank=True)),
|
||||
('confirmed', models.BooleanField(
|
||||
default=True, help_text='Nur g\xfcltige und best\xe4tigte Hanchans kommen in die Wertung.', verbose_name='Wurde best\xe4tigt')),
|
||||
('player_names', models.CharField(max_length=255, editable=False)),
|
||||
('season', models.PositiveSmallIntegerField(
|
||||
verbose_name='Saison', editable=False, db_index=True)),
|
||||
('event', models.ForeignKey(to='events.Event')),
|
||||
('player1', models.ForeignKey(related_name='user_hanchan+',
|
||||
verbose_name='Spieler 1', to=settings.AUTH_USER_MODEL)),
|
||||
('player2', models.ForeignKey(related_name='user_hanchan+',
|
||||
verbose_name='Spieler 2', to=settings.AUTH_USER_MODEL)),
|
||||
('player3', models.ForeignKey(related_name='user_hanchan+',
|
||||
verbose_name='Spieler 3', to=settings.AUTH_USER_MODEL)),
|
||||
('player4', models.ForeignKey(related_name='user_hanchan+',
|
||||
verbose_name='Spieler 4', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'ordering': ('-start',),
|
||||
'verbose_name': 'Hanchan',
|
||||
'verbose_name_plural': 'Hanchans',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='KyuDanRanking',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID',
|
||||
serialize=False, auto_created=True, primary_key=True)),
|
||||
('dan', models.PositiveSmallIntegerField(null=True, blank=True)),
|
||||
('dan_points', models.PositiveIntegerField(default=0)),
|
||||
('kyu', models.PositiveSmallIntegerField(
|
||||
default=10, null=True, blank=True)),
|
||||
('kyu_points', models.PositiveIntegerField(default=0)),
|
||||
('won_hanchans', models.PositiveIntegerField(default=0)),
|
||||
('good_hanchans', models.PositiveIntegerField(default=0)),
|
||||
('hanchan_count', models.PositiveIntegerField(default=0)),
|
||||
('legacy_date', models.DateField(null=True, blank=True)),
|
||||
('legacy_dan_points', models.PositiveIntegerField(default=0)),
|
||||
('legacy_kyu_points', models.PositiveIntegerField(default=0)),
|
||||
('user', models.OneToOneField(to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'ordering': ('-dan', '-dan_points', '-kyu_points'),
|
||||
'verbose_name': 'Ky\u016b/Dan Wertung',
|
||||
'verbose_name_plural': 'Ky\u016b/Dan Wertungen',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SeasonRanking',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID',
|
||||
serialize=False, auto_created=True, primary_key=True)),
|
||||
('season', models.PositiveSmallIntegerField(verbose_name='Saison')),
|
||||
('placement', models.PositiveIntegerField(null=True, blank=True)),
|
||||
('avg_placement', models.FloatField(null=True, blank=True)),
|
||||
('avg_score', models.FloatField(null=True, blank=True)),
|
||||
('hanchan_count', models.PositiveIntegerField(default=0)),
|
||||
('good_hanchans', models.PositiveIntegerField(default=0)),
|
||||
('won_hanchans', models.PositiveIntegerField(default=0)),
|
||||
('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'ordering': ('placement', 'avg_placement', '-avg_score'),
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,19 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('mahjong_ranking', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='kyudanranking',
|
||||
name='legacy_hanchan_count',
|
||||
field=models.PositiveIntegerField(default=0),
|
||||
),
|
||||
]
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user