diff options
author | gnowgi <nagarjun@gnowledge.org> | 2012-03-15 16:19:20 +0530 |
---|---|---|
committer | gnowgi <nagarjun@gnowledge.org> | 2012-03-15 16:19:20 +0530 |
commit | 7a4f561e851fdc7246d804c3abb6748b8a4199a6 (patch) | |
tree | d2afc3463fd49625a9be482012f5c3bfcf7c42b9 /gstudio/templatetags | |
download | gnowsys-7a4f561e851fdc7246d804c3abb6748b8a4199a6.tar.gz |
master trunk of gnowsys-studio
Diffstat (limited to 'gstudio/templatetags')
-rw-r--r-- | gstudio/templatetags/__init__.py | 0 | ||||
-rw-r--r-- | gstudio/templatetags/gstudio_admin_tags.py | 59 | ||||
-rw-r--r-- | gstudio/templatetags/gstudio_tags.py | 352 | ||||
-rw-r--r-- | gstudio/templatetags/zbreadcrumbs.py | 167 | ||||
-rw-r--r-- | gstudio/templatetags/zcalendar.py | 128 |
5 files changed, 706 insertions, 0 deletions
diff --git a/gstudio/templatetags/__init__.py b/gstudio/templatetags/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/gstudio/templatetags/__init__.py diff --git a/gstudio/templatetags/gstudio_admin_tags.py b/gstudio/templatetags/gstudio_admin_tags.py new file mode 100644 index 0000000..a341b3f --- /dev/null +++ b/gstudio/templatetags/gstudio_admin_tags.py @@ -0,0 +1,59 @@ + +# Copyright (c) 2011, 2012 Free Software Foundation + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + + +"""Template tags and filters for Gstudio's admin""" +from django.template import Library +from django.contrib import comments +from django.contrib.contenttypes.models import ContentType + +from gstudio.models import Nodetype +from gstudio.models import Author +from gstudio.models import Metatype +from gstudio.managers import DRAFT +from gstudio.managers import tags_published + +register = Library() + + +@register.inclusion_tag('gstudio/tags/dummy.html') +def get_draft_nodetypes( + number=5, template='admin/gstudio/widgets/_draft_nodetypes.html'): + """Return the latest draft nodetypes""" + return {'template': template, + 'nodetypes': Nodetype.objects.filter(status=DRAFT)[:number]} + + +@register.inclusion_tag('gstudio/tags/dummy.html') +def get_content_stats( + template='admin/gstudio/widgets/_content_stats.html'): + """Return statistics of the contents""" + content_type = ContentType.objects.get_for_model(Nodetype) + + discussions = comments.get_model().objects.filter( + is_public=True, content_type=content_type) + + return {'template': template, + 'nodetypes': Nodetype.published.count(), + 'metatypes': Metatype.objects.count(), + 'tags': tags_published().count(), + 'authors': Author.published.count(), + 'comments': discussions.filter(flags=None).count(), + 'pingbacks': discussions.filter(flags__flag='pingback').count(), + 'trackbacks': discussions.filter(flags__flag='trackback').count(), + 'rejects': comments.get_model().objects.filter( + is_public=False, content_type=content_type).count(), + } diff --git a/gstudio/templatetags/gstudio_tags.py b/gstudio/templatetags/gstudio_tags.py new file mode 100644 index 0000000..574da8c --- /dev/null +++ b/gstudio/templatetags/gstudio_tags.py @@ -0,0 +1,352 @@ + +# Copyright (c) 2011, 2012 Free Software Foundation + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + + +"""Template tags and filters for Gstudio""" +from hashlib import md5 +from random import sample +from urllib import urlencode +from datetime import datetime + +from django.db.models import Q +from django.db import connection +from django.template import Node +from django.template import Library +from django.template import TemplateSyntaxError +from django.contrib.comments.models import CommentFlag +from django.contrib.contenttypes.models import ContentType +from django.utils.encoding import smart_unicode +from django.contrib.comments import get_model as get_comment_model + +from tagging.models import Tag +from tagging.utils import calculate_cloud + +from gstudio.models import Nodetype +from gstudio.models import Author +from gstudio.models import Metatype + +from gstudio.gnowql import get_node + +from gstudio.managers import tags_published +from gstudio.comparison import VectorBuilder +from gstudio.comparison import pearson_score +from gstudio.templatetags.zcalendar import GstudioCalendar +from gstudio.templatetags.zbreadcrumbs import retrieve_breadcrumbs + +register = Library() + +VECTORS = None +VECTORS_FACTORY = lambda: VectorBuilder(Nodetype.published.all(), + ['title', 'excerpt', 'content']) +CACHE_NODETYPES_RELATED = {} + + +@register.inclusion_tag('gstudio/tags/dummy.html') +def get_metatypes(template='gstudio/tags/metatypes.html'): + """Return the metatypes""" + return {'template': template, + 'metatypes': Metatype.tree.all()} + +#@register.inclusion_tag('gstudio/tags/dummy.html') +#def get_subtypes(template='gstudio/tags/nodetypes.html'): +# """Return the subtypes""" +# return {'template': template, +# 'subtypes': Nodetype.tree.all()} + + +@register.inclusion_tag('gstudio/tags/dummy.html') +def get_authors(template='gstudio/tags/authors.html'): + """Return the published authors""" + return {'template': template, + 'authors': Author.published.all()} + + +@register.inclusion_tag('gstudio/tags/dummy.html') +def get_recent_nodetypes(number=5, template='gstudio/tags/recent_nodetypes.html'): + """Return the most recent nodetypes""" + return {'template': template, + 'nodetypes': Nodetype.published.all()[:number]} + + +@register.inclusion_tag('gstudio/tags/dummy.html') +def get_featured_nodetypes(number=5, + template='gstudio/tags/featured_nodetypes.html'): + """Return the featured nodetypes""" + return {'template': template, + 'nodetypes': Nodetype.published.filter(featured=True)[:number]} + + +@register.inclusion_tag('gstudio/tags/dummy.html') +def get_random_nodetypes(number=5, template='gstudio/tags/random_nodetypes.html'): + """Return random nodetypes""" + nodetypes = Nodetype.published.all() + if number > len(nodetypes): + number = len(nodetypes) + return {'template': template, + 'nodetypes': sample(nodetypes, number)} + + +@register.inclusion_tag('gstudio/tags/dummy.html') +def get_popular_nodetypes(number=5, template='gstudio/tags/popular_nodetypes.html'): + """Return popular nodetypes""" + ctype = ContentType.objects.get_for_model(Nodetype) + query = """SELECT object_pk, COUNT(*) AS score + FROM %s + WHERE content_type_id = %%s + AND is_public = '1' + GROUP BY object_pk + ORDER BY score DESC""" % get_comment_model()._meta.db_table + + cursor = connection.cursor() + cursor.execute(query, [ctype.id]) + object_ids = [int(row[0]) for row in cursor.fetchall()] + + # Use ``in_bulk`` here instead of an ``id__in`` filter, because ``id__in`` + # would clobber the ordering. + object_dict = Nodetype.published.in_bulk(object_ids) + + return {'template': template, + 'nodetypes': [object_dict[object_id] + for object_id in object_ids + if object_id in object_dict][:number]} + + +@register.inclusion_tag('gstudio/tags/dummy.html', takes_context=True) +def get_similar_nodetypes(context, number=5, + template='gstudio/tags/similar_nodetypes.html', + flush=False): + """Return similar nodetypes""" + global VECTORS + global CACHE_NODETYPES_RELATED + + if VECTORS is None or flush: + VECTORS = VECTORS_FACTORY() + CACHE_NODETYPES_RELATED = {} + + def compute_related(object_id, dataset): + """Compute related nodetypes to a nodetype with a dataset""" + object_vector = None + for nodetype, e_vector in dataset.items(): + if nodetype.pk == object_id: + object_vector = e_vector + + if not object_vector: + return [] + + nodetype_related = {} + for nodetype, e_vector in dataset.items(): + if nodetype.pk != object_id: + score = pearson_score(object_vector, e_vector) + if score: + nodetype_related[nodetype] = score + + related = sorted(nodetype_related.items(), key=lambda(k, v): (v, k)) + return [rel[0] for rel in related] + + object_id = context['object'].pk + columns, dataset = VECTORS() + key = '%s-%s' % (object_id, VECTORS.key) + if not key in CACHE_NODETYPES_RELATED.keys(): + CACHE_NODETYPES_RELATED[key] = compute_related(object_id, dataset) + + nodetypes = CACHE_NODETYPES_RELATED[key][:number] + return {'template': template, + 'nodetypes': nodetypes} + + +@register.inclusion_tag('gstudio/tags/dummy.html') +def get_archives_nodetypes(template='gstudio/tags/archives_nodetypes.html'): + """Return archives nodetypes""" + return {'template': template, + 'archives': Nodetype.published.dates('creation_date', 'month', + order='DESC')} + + +@register.inclusion_tag('gstudio/tags/dummy.html') +def get_archives_nodetypes_tree( + template='gstudio/tags/archives_nodetypes_tree.html'): + """Return archives nodetypes as a Tree""" + return {'template': template, + 'archives': Nodetype.published.dates('creation_date', 'day', + order='ASC')} + + +@register.inclusion_tag('gstudio/tags/dummy.html', takes_context=True) +def get_calendar_nodetypes(context, year=None, month=None, + template='gstudio/tags/calendar.html'): + """Return an HTML calendar of nodetypes""" + if not year or not month: + date_month = context.get('month') or context.get('day') or \ + getattr(context.get('object'), 'creation_date', None) or \ + datetime.today() + year, month = date_month.timetuple()[:2] + + calendar = GstudioCalendar() + current_month = datetime(year, month, 1) + + dates = list(Nodetype.published.dates('creation_date', 'month')) + + if not current_month in dates: + dates.append(current_month) + dates.sort() + index = dates.index(current_month) + + previous_month = index > 0 and dates[index - 1] or None + next_month = index != len(dates) - 1 and dates[index + 1] or None + + return {'template': template, + 'next_month': next_month, + 'previous_month': previous_month, + 'calendar': calendar.formatmonth(year, month)} + + +@register.inclusion_tag('gstudio/tags/dummy.html') +def get_recent_comments(number=5, template='gstudio/tags/recent_comments.html'): + """Return the most recent comments""" + # Using map(smart_unicode... fix bug related to issue #8554 + nodetype_published_pks = map(smart_unicode, + Nodetype.published.values_list('id', flat=True)) + content_type = ContentType.objects.get_for_model(Nodetype) + + comments = get_comment_model().objects.filter( + Q(flags=None) | Q(flags__flag=CommentFlag.MODERATOR_APPROVAL), + content_type=content_type, object_pk__in=nodetype_published_pks, + is_public=True).order_by('-submit_date')[:number] + + return {'template': template, + 'comments': comments} + + +@register.inclusion_tag('gstudio/tags/dummy.html') +def get_recent_linkbacks(number=5, + template='gstudio/tags/recent_linkbacks.html'): + """Return the most recent linkbacks""" + nodetype_published_pks = map(smart_unicode, + Nodetype.published.values_list('id', flat=True)) + content_type = ContentType.objects.get_for_model(Nodetype) + + linkbacks = get_comment_model().objects.filter( + content_type=content_type, + object_pk__in=nodetype_published_pks, + flags__flag__in=['pingback', 'trackback'], + is_public=True).order_by( + '-submit_date')[:number] + + return {'template': template, + 'linkbacks': linkbacks} + + +@register.inclusion_tag('gstudio/tags/dummy.html', takes_context=True) +def gstudio_pagination(context, page, begin_pages=3, end_pages=3, + before_pages=2, after_pages=2, + template='gstudio/tags/pagination.html'): + """Return a Digg-like pagination, by splitting long list of page + into 3 blocks of pages""" + GET_string = '' + for key, value in context['request'].GET.items(): + if key != 'page': + GET_string += '&%s=%s' % (key, value) + + begin = page.paginator.page_range[:begin_pages] + end = page.paginator.page_range[-end_pages:] + middle = page.paginator.page_range[max(page.number - before_pages - 1, 0): + page.number + after_pages] + + if set(begin) & set(end): # [1, 2, 3], [...], [2, 3, 4] + begin = sorted(set(begin + end)) # [1, 2, 3, 4] + middle, end = [], [] + elif begin[-1] + 1 == end[0]: # [1, 2, 3], [...], [4, 5, 6] + begin += end # [1, 2, 3, 4, 5, 6] + middle, end = [], [] + elif set(begin) & set(middle): # [1, 2, 3], [2, 3, 4], [...] + begin = sorted(set(begin + middle)) # [1, 2, 3, 4] + middle = [] + elif begin[-1] + 1 == middle[0]: # [1, 2, 3], [4, 5, 6], [...] + begin += middle # [1, 2, 3, 4, 5, 6] + middle = [] + elif middle[-1] + 1 == end[0]: # [...], [15, 16, 17], [18, 19, 20] + end = middle + end # [15, 16, 17, 18, 19, 20] + middle = [] + elif set(middle) & set(end): # [...], [17, 18, 19], [18, 19, 20] + end = sorted(set(middle + end)) # [17, 18, 19, 20] + middle = [] + + return {'template': template, 'page': page, 'GET_string': GET_string, + 'begin': begin, 'middle': middle, 'end': end} + + +@register.inclusion_tag('gstudio/tags/dummy.html', takes_context=True) +def gstudio_breadcrumbs(context, separator='/', root_name='gstudio', + template='gstudio/tags/breadcrumbs.html',): + """Return a breadcrumb for the application""" + path = context['request'].path + page_object = context.get('object') or context.get('metatype') or \ + context.get('tag') or context.get('author') + breadcrumbs = retrieve_breadcrumbs(path, page_object, root_name) + + return {'template': template, + 'separator': separator, + 'breadcrumbs': breadcrumbs} + +@register.simple_tag +def get_gravatar(email, size=80, rating='g', default=None): + """Return url for a Gravatar""" + url = 'http://www.gravatar.com/avatar/%s.jpg' % \ + md5(email.strip().lower()).hexdigest() + options = {'s': size, 'r': rating} + if default: + options['d'] = default + + url = '%s?%s' % (url, urlencode(options)) + return url.replace('&', '&') + +@register.simple_tag +def get_type(name): + + """Return the type of node""" + return get_node(name) + + +class TagsNode(Node): + def __init__(self, context_var): + self.context_var = context_var + + def render(self, context): + context[self.context_var] = tags_published() + return '' + + +@register.tag +def get_tags(parser, token): + """{% get_tags as var %}""" + bits = token.split_contents() + + if len(bits) != 3: + raise TemplateSyntaxError( + 'get_tags tag takes exactly two arguments') + if bits[1] != 'as': + raise TemplateSyntaxError( + "first argument to get_tags tag must be 'as'") + return TagsNode(bits[2]) + + +@register.inclusion_tag('gstudio/tags/dummy.html') +def get_tag_cloud(steps=6, template='gstudio/tags/tag_cloud.html'): + """Return a cloud of published tags""" + tags = Tag.objects.usage_for_queryset( + Nodetype.published.all(), counts=True) + return {'template': template, + 'tags': calculate_cloud(tags, steps)} diff --git a/gstudio/templatetags/zbreadcrumbs.py b/gstudio/templatetags/zbreadcrumbs.py new file mode 100644 index 0000000..27f06c4 --- /dev/null +++ b/gstudio/templatetags/zbreadcrumbs.py @@ -0,0 +1,167 @@ + + +# Copyright (c) 2011, 2012 Free Software Foundation + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + + +# This project incorporates work covered by the following copyright and permission notice: + +# Copyright (c) 2009, Julien Fache +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: + +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of the author nor the names of other +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +# OF THE POSSIBILITY OF SUCH DAMAGE. + +# Copyright (c) 2011, 2012 Free Software Foundation + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + + + +"""Breadcrumb module for Gstudio templatetags""" +import re +from datetime import datetime + +from django.core.urlresolvers import reverse +from django.utils.translation import ugettext as _ + + +class Crumb(object): + """Part of the Breadcrumbs""" + def __init__(self, name, url=None): + self.name = name + self.url = url + + +def year_crumb(creation_date): + """Crumb for a year""" + year = creation_date.strftime('%Y') + return Crumb(year, reverse('gstudio_nodetype_archive_year', + args=[year])) + + +def month_crumb(creation_date): + """Crumb for a month""" + year = creation_date.strftime('%Y') + month = creation_date.strftime('%m') + month_text = creation_date.strftime('%b').capitalize() + return Crumb(month_text, reverse('gstudio_nodetype_archive_month', + args=[year, month])) + + +def day_crumb(creation_date): + """Crumb for a day""" + year = creation_date.strftime('%Y') + month = creation_date.strftime('%m') + day = creation_date.strftime('%d') + return Crumb(day, reverse('gstudio_nodetype_archive_day', + args=[year, month, day])) + + +GSTUDIO_ROOT_URL = lambda: reverse('gstudio_nodetype_archive_index') + +MODEL_BREADCRUMBS = {'Tag': lambda x: [Crumb(_('Tags'), + reverse('gstudio_tag_list')), + Crumb(x.name)], + 'Author': lambda x: [Crumb(_('Authors'), + reverse('gstudio_author_list')), + Crumb(x.username)], + 'Metatype': lambda x: [Crumb( + _('Metatypes'), reverse('gstudio_metatype_list'))] + \ + [Crumb(anc.title, anc.get_absolute_url()) + for anc in x.get_ancestors()] + [Crumb(x.title)], + 'Nodetype': lambda x: [year_crumb(x.creation_date), + month_crumb(x.creation_date), + day_crumb(x.creation_date), + Crumb(x.title)]} + +DATE_REGEXP = re.compile( + r'.*(?P<year>\d{4})/(?P<month>\d{2})?/(?P<day>\d{2})?.*') + + +def retrieve_breadcrumbs(path, model_instance, root_name='gstudio'): + """Build a semi-hardcoded breadcrumbs + based of the model's url handled by Gstudio""" + breadcrumbs = [] + + if root_name: + breadcrumbs.append(Crumb(root_name, GSTUDIO_ROOT_URL())) + + if model_instance is not None: + key = model_instance.__class__.__name__ + if key in MODEL_BREADCRUMBS: + breadcrumbs.extend(MODEL_BREADCRUMBS[key](model_instance)) + return breadcrumbs + + date_match = DATE_REGEXP.match(path) + if date_match: + date_dict = date_match.groupdict() + path_date = datetime( + int(date_dict['year']), + date_dict.get('month') is not None and \ + int(date_dict.get('month')) or 1, + date_dict.get('day') is not None and \ + int(date_dict.get('day')) or 1) + + date_breadcrumbs = [year_crumb(path_date)] + if date_dict['month']: + date_breadcrumbs.append(month_crumb(path_date)) + if date_dict['day']: + date_breadcrumbs.append(day_crumb(path_date)) + breadcrumbs.extend(date_breadcrumbs) + + return breadcrumbs + + url_components = [comp for comp in + path.replace(GSTUDIO_ROOT_URL(), '').split('/') if comp] + if len(url_components): + breadcrumbs.append(Crumb(_(url_components[-1].capitalize()))) + + return breadcrumbs diff --git a/gstudio/templatetags/zcalendar.py b/gstudio/templatetags/zcalendar.py new file mode 100644 index 0000000..8ff1b77 --- /dev/null +++ b/gstudio/templatetags/zcalendar.py @@ -0,0 +1,128 @@ +# Copyright (c) 2011, 2012 Free Software Foundation + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + + +# This project incorporates work covered by the following copyright and permission notice: + +# Copyright (c) 2009, Julien Fache +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: + +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of the author nor the names of other +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +# OF THE POSSIBILITY OF SUCH DAMAGE. + +# Copyright (c) 2011, 2012 Free Software Foundation + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + + + + +"""Calendar module for Gstudio templatetags""" +from datetime import date +from calendar import HTMLCalendar + +from django.utils.dates import MONTHS +from django.utils.dates import WEEKDAYS_ABBR +from django.utils.formats import get_format +from django.core.urlresolvers import reverse + +from gstudio.models import Nodetype + +AMERICAN_TO_EUROPEAN_WEEK_DAYS = [6, 0, 1, 2, 3, 4, 5] + + +class GstudioCalendar(HTMLCalendar): + """Override of HTMLCalendar""" + + def __init__(self): + """Retrieve and convert the localized first week day + at initialization""" + HTMLCalendar.__init__(self, AMERICAN_TO_EUROPEAN_WEEK_DAYS[ + get_format('FIRST_DAY_OF_WEEK')]) + + def formatday(self, day, weekday): + """Return a day as a table cell with a link + if nodetypes are published this day""" + if day and day in self.day_nodetypes: + day_date = date(self.current_year, self.current_month, day) + archive_day_url = reverse('gstudio_nodetype_archive_day', + args=[day_date.strftime('%Y'), + day_date.strftime('%m'), + day_date.strftime('%d')]) + return '<td class="%s nodetype"><a href="%s" '\ + 'rel="archives">%d</a></td>' % ( + self.cssclasses[weekday], archive_day_url, day) + + return super(GstudioCalendar, self).formatday(day, weekday) + + def formatmonth(self, theyear, themonth, withyear=True): + """Return a formatted month as a table with + new attributes computed for formatting a day""" + self.current_year = theyear + self.current_month = themonth + self.day_nodetypes = [nodetypes.creation_date.day for nodetypes in + Nodetype.published.filter( + creation_date__year=theyear, + creation_date__month=themonth)] + + return super(GstudioCalendar, self).formatmonth( + theyear, themonth, withyear) + + def formatweekday(self, day): + """Return a weekday name translated + as a table header.""" + return '<th class="%s">%s</th>' % (self.cssclasses[day], + WEEKDAYS_ABBR[day].title()) + + def formatmonthname(self, theyear, themonth, withyear=True): + """Return a month name translated + as a table row.""" + monthname = '%s %s' % (MONTHS[themonth].title(), theyear) + return '<tr><th colspan="7" class="month">%s</th></tr>' % monthname |