From: Kostas Papadimitriou Date: Thu, 12 Jul 2012 14:41:06 +0000 (+0300) Subject: Initial commit of userguide app X-Git-Tag: v0.7.0~21 X-Git-Url: https://code.grnet.gr/git/snf-cloudcms/commitdiff_plain/b5eefa35edc45fd2d32df02d5e38c0ee551d9da5 Initial commit of userguide app --- diff --git a/cloudcmsguide/__init__.py b/cloudcmsguide/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/cloudcmsguide/admin.py b/cloudcmsguide/admin.py new file mode 100644 index 0000000..d0594f4 --- /dev/null +++ b/cloudcmsguide/admin.py @@ -0,0 +1,75 @@ +# Copyright 2012 GRNET S.A. All rights reserved. +# +# Redistribution and use in source and binary forms, with or +# without modification, are permitted provided that the following +# conditions are met: +# +# 1. Redistributions of source code must retain the above +# copyright notice, this list of conditions and the following +# disclaimer. +# +# 2. 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. +# +# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``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 GRNET S.A 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. +# +# The views and conclusions contained in the software and +# documentation are those of the authors and should not be +# interpreted as representing official policies, either expressed +# or implied, of GRNET S.A. + + +from django.contrib import admin +from django.utils.translation import ugettext_lazy as _ + +from feincms.translations import admin_translationinline, short_language_code +from feincms.admin import tree_editor, item_editor + +from cloudcmsguide.models import UserGuideEntry + + +class UserGuideEntryAdmin(item_editor.ItemEditor, tree_editor.TreeEditor): + + date_hierarchy = 'published_on' + list_display = ['title', 'is_active', 'published_on', 'service', 'author'] + list_editable = ['is_active'] + list_filter = ['is_active', 'is_featured', 'author'] + search_fields = ['title', 'slug'] + raw_id_fields = ['parent'] + + prepopulated_fields = { + 'slug': ('title',), + } + + fieldsets = [ + [None, { + 'fields': [ + ('is_active', 'published_on'), + ('title', 'slug'), + 'parent', + 'service', + 'author', + ] + }], + item_editor.FEINCMS_CONTENT_FIELDSET, + ] + + def import_from_sphinx(self, request): + return import_from_sphinx(request) + + +admin.site.register(UserGuideEntry, UserGuideEntryAdmin) + diff --git a/cloudcmsguide/models.py b/cloudcmsguide/models.py new file mode 100644 index 0000000..60be618 --- /dev/null +++ b/cloudcmsguide/models.py @@ -0,0 +1,148 @@ +# Copyright 2012 GRNET S.A. All rights reserved. +# +# Redistribution and use in source and binary forms, with or +# without modification, are permitted provided that the following +# conditions are met: +# +# 1. Redistributions of source code must retain the above +# copyright notice, this list of conditions and the following +# disclaimer. +# +# 2. 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. +# +# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``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 GRNET S.A 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. +# +# The views and conclusions contained in the software and +# documentation are those of the authors and should not be +# interpreted as representing official policies, either expressed +# or implied, of GRNET S.A. + + +from datetime import datetime + +from django.db import models +from django.conf import settings +from django.contrib.auth.models import User +from django.utils.translation import ugettext_lazy as _, ugettext, ungettext +from django.template.loader import render_to_string +from django.core import urlresolvers + +from feincms import translations +from feincms.models import Base +from feincms.module.page.models import Page +from feincms.content.application.models import reverse +from feincms.content.richtext.models import RichTextContent +from feincms.content.section.models import SectionContent +from feincms.module.medialibrary.fields import MediaFileForeignKey +from feincms.module.medialibrary.models import MediaFile +from feincms.module.page.extensions.navigation import NavigationExtension +from feincms.module.page.extensions.navigation import PagePretender +from feincms.content.application.models import ApplicationContent +from feincms.models import Base, create_base_model + +from cloudcms.cms_utils import get_app_page + +class UserGuideEntryManager(models.Manager): + + def active(self): + return self.filter(is_active=True) + + def latest(self, limit=3): + return self.filter()[:limit] + + +def get_guide_page(): + """ + Returns Page model that has been associated with userguide application + """ + return get_app_page(Page, "cloudcmsguide") + + +try: + # MPTT 0.4 + from mptt.models import MPTTModel + mptt_register = False + Base = create_base_model(MPTTModel) +except ImportError: + # MPTT 0.3 + mptt_register = True + +class UserGuideEntry(Base): + """ + User guide entry + """ + is_active = models.BooleanField(_('is active'), default=True) + is_featured = models.BooleanField(_('is featured'), default=False) + + title = models.CharField(_('title'), max_length=100) + slug = models.SlugField(_('slug'), max_length=100, unique_for_date='published_on') + author = models.ForeignKey(User, related_name='guide_pages', verbose_name=_('author')) + language = models.CharField(max_length=255, choices=settings.LANGUAGES) + + published_on = models.DateTimeField(_('published on'), blank=True, null=True, default=datetime.now, + help_text=_('Will be filled in automatically when entry gets published.')) + last_changed = models.DateTimeField(_('last change'), auto_now=True, editable=False) + + service = models.ForeignKey('cloudcms.Service', verbose_name=_('service'), + related_name='userguideentries', null=True, blank=False) + + parent = models.ForeignKey('self', verbose_name=_('Parent'), blank=True, null=True, related_name='children') + + objects = UserGuideEntryManager() + + class Meta: + get_latest_by = 'published_on' + ordering = ['service', '-published_on'] + verbose_name = _('User guide entry') + verbose_name_plural = _('User guide entries') + + def __unicode__(self): + return self.title + + def get_absolute_url(self): + try: + r = reverse('cloudcmsguide_entry_detail', 'cloudcmsguide.urls', (), + { + 'service': self.service.translation.slug, + 'slug': self.slug, + }) + except Exception, e: + print e + return "" + + # ugly hack to fix proper application reverse url + GUIDE_URL = "" + try: + GUIDE_URL = get_guide_page().get_navigation_url() + except Exception, e: + pass + + if r.startswith(GUIDE_URL): + return r + else: + return GUIDE_URL + r.lstrip('/') + + def back_url(self): + return get_guide_page().get_navigation_url() + +if mptt_register: # MPTT 0.3 legacy support + mptt.register(Page) + +UserGuideEntry.register_extensions( + 'changedate', + 'seo' +) diff --git a/cloudcmsguide/sitemap.py b/cloudcmsguide/sitemap.py new file mode 100644 index 0000000..45a2170 --- /dev/null +++ b/cloudcmsguide/sitemap.py @@ -0,0 +1,43 @@ +# Copyright 2012 GRNET S.A. All rights reserved. +# +# Redistribution and use in source and binary forms, with or +# without modification, are permitted provided that the following +# conditions are met: +# +# 1. Redistributions of source code must retain the above +# copyright notice, this list of conditions and the following +# disclaimer. +# +# 2. 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. +# +# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``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 GRNET S.A 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. +# +# The views and conclusions contained in the software and +# documentation are those of the authors and should not be +# interpreted as representing official policies, either expressed +# or implied, of GRNET S.A. + + +from django.db.models import Max +from django.contrib.sitemaps import Sitemap +from cloudcmsguide.models import UserGuideEntry + +class UserGuideSitemap(Sitemap): + + def items(self): + return UserGuideEntry.objects.filter(is_active=True) + diff --git a/cloudcmsguide/templates/cloudcmsguide/archive.html b/cloudcmsguide/templates/cloudcmsguide/archive.html new file mode 100644 index 0000000..9b51662 --- /dev/null +++ b/cloudcmsguide/templates/cloudcmsguide/archive.html @@ -0,0 +1,16 @@ +{% load applicationcontent_tags pagination_tags i18n %} + +
+ {% for service in services %} +
+

{{ service.translation.title|upper }}

+
    + {% for e in service.userguideentries.active %} +
  • + {{ e.title }} +
  • + {% endfor %} +
+
+ {% endfor %} +
diff --git a/cloudcmsguide/templates/cloudcmsguide/detail.html b/cloudcmsguide/templates/cloudcmsguide/detail.html new file mode 100644 index 0000000..c420732 --- /dev/null +++ b/cloudcmsguide/templates/cloudcmsguide/detail.html @@ -0,0 +1,19 @@ +{% load applicationcontent_tags i18n %} + +{% fragment request "sidecol" %} +{% include "cloudcmsguide/archive.html" %} +{% endfragment %} + +{% fragment request "maincol" %} +
+

{{ entry.title|upper }}

+
+ {% for content in entry.content.main %} + {{ content.render }} + {% endfor %} +
+ +
+{% endfragment %} diff --git a/cloudcmsguide/tests.py b/cloudcmsguide/tests.py new file mode 100644 index 0000000..ba67af7 --- /dev/null +++ b/cloudcmsguide/tests.py @@ -0,0 +1,57 @@ +# Copyright 2012 GRNET S.A. All rights reserved. +# +# Redistribution and use in source and binary forms, with or +# without modification, are permitted provided that the following +# conditions are met: +# +# 1. Redistributions of source code must retain the above +# copyright notice, this list of conditions and the following +# disclaimer. +# +# 2. 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. +# +# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``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 GRNET S.A 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. +# +# The views and conclusions contained in the software and +# documentation are those of the authors and should not be +# interpreted as representing official policies, either expressed +# or implied, of GRNET S.A. + + +""" +This file demonstrates two different styles of tests (one doctest and one +unittest). These will both pass when you run "manage.py test". + +Replace these with more appropriate tests for your application. +""" + +from django.test import TestCase + +class SimpleTest(TestCase): + def test_basic_addition(self): + """ + Tests that 1 + 1 always equals 2. + """ + self.failUnlessEqual(1 + 1, 2) + +__test__ = {"doctest": """ +Another way to test that 1 + 1 is equal to 2. + +>>> 1 + 1 == 2 +True +"""} + diff --git a/cloudcmsguide/urls.py b/cloudcmsguide/urls.py new file mode 100644 index 0000000..9e3d07e --- /dev/null +++ b/cloudcmsguide/urls.py @@ -0,0 +1,46 @@ +# Copyright 2012 GRNET S.A. All rights reserved. +# +# Redistribution and use in source and binary forms, with or +# without modification, are permitted provided that the following +# conditions are met: +# +# 1. Redistributions of source code must retain the above +# copyright notice, this list of conditions and the following +# disclaimer. +# +# 2. 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. +# +# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``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 GRNET S.A 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. +# +# The views and conclusions contained in the software and +# documentation are those of the authors and should not be +# interpreted as representing official policies, either expressed +# or implied, of GRNET S.A. + + +from django.conf.urls.defaults import patterns, include, url +from django.conf import settings +from django.contrib import admin + +admin.autodiscover() + +urlpatterns = patterns('cloudcmsguide.views', + url(r'^$', 'index', name='cloudcmsguide_entries_archive'), + url(r'^(?P[\w]+)-(?P[-\w]+)/$', + 'detail', name='cloudcmsguide_entry_detail'), +) + diff --git a/cloudcmsguide/views.py b/cloudcmsguide/views.py new file mode 100644 index 0000000..ea50662 --- /dev/null +++ b/cloudcmsguide/views.py @@ -0,0 +1,64 @@ +# Copyright 2012 GRNET S.A. All rights reserved. +# +# Redistribution and use in source and binary forms, with or +# without modification, are permitted provided that the following +# conditions are met: +# +# 1. Redistributions of source code must retain the above +# copyright notice, this list of conditions and the following +# disclaimer. +# +# 2. 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. +# +# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``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 GRNET S.A 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. +# +# The views and conclusions contained in the software and +# documentation are those of the authors and should not be +# interpreted as representing official policies, either expressed +# or implied, of GRNET S.A. + + +from django.conf import settings +from django.views.generic.simple import direct_to_template +from django.http import HttpResponseRedirect, Http404 + +from cloudcms.models import Service +from cloudcmsguide.models import UserGuideEntry + +def index(request): + return archive(request) + +def archive(request): + """ + Display entries list + """ + services = Service.objects.all() + + return direct_to_template(request, + "cloudcmsguide/archive.html", {'services': services}) + +def detail(request, service, slug): + """ + Display detailed entry. + """ + entry = UserGuideEntry.objects.get(slug=slug) + services = Service.objects.all() + + return direct_to_template(request, + "cloudcmsguide/detail.html", {'entry': entry, + 'services': services}) +