commit 60441a7f9b6a176d2fab50d540840966d9031488
Author: Kostas Papadimitriou <kpap@grnet.gr>
Date:   Tue Jul 10 10:46:24 2012 +0300

    Cloudcms Service model

diff --git a/cloudcms/admin.py b/cloudcms/admin.py
index 943a974..a45317c 100644
--- a/cloudcms/admin.py
+++ b/cloudcms/admin.py
@@ -33,6 +33,8 @@
 
 
 from django.contrib import admin
+from feincms.translations import admin_translationinline, short_language_code
+
 from cloudcms import models
 
 
@@ -45,10 +47,19 @@ class ClientVersionSourceAdminInline(admin.StackedInline):
     raw_id_fields = ('logo',)
     extra = 1
 
+
 class ClientAdmin(admin.ModelAdmin):
     inlines = [ClientVersionSourceAdminInline]
 
 
+ServiceTranslationInline = admin_translationinline(models.ServiceTranslation,
+        prepopulated_fields={'slug': ('title',)})
+
+class ServiceAdmin(admin.ModelAdmin):
+    inlines = [ServiceTranslationInline]
+
+
 admin.site.register(models.Application, ApplicationAdmin)
 admin.site.register(models.Client, ClientAdmin)
+admin.site.register(models.Service, ServiceAdmin)
 
diff --git a/cloudcms/cms.py b/cloudcms/cms.py
index 023b323..4308958 100644
--- a/cloudcms/cms.py
+++ b/cloudcms/cms.py
@@ -158,7 +158,7 @@ Page.create_content_type(ApplicationContent, APPLICATIONS=(
 Page.create_content_type(LoginForm)
 Page.create_content_type(AboutBlock)
 Page.create_content_type(ResourcesList)
-Page.create_content_type(BlockColor) 
+Page.create_content_type(BlockColor)
 
 
 
@@ -174,6 +174,10 @@ if 'cloudcmsfaq' in settings.INSTALLED_APPS:
     from cloudcmsfaq.models import Question
     EXTRA_CONTENT_MODELS.append(Question)
 
+if 'cloudcmsguide' in settings.INSTALLED_APPS:
+    from cloudcmsguide.models import Section
+    EXTRA_CONTENT_MODELS.append(Section)
+
 for model in EXTRA_CONTENT_MODELS:
     # Feincms specific registrations for our blog entry model
     model.register_regions(
diff --git a/cloudcms/migrations/0009_auto__add_service__add_servicetranslation.py b/cloudcms/migrations/0009_auto__add_service__add_servicetranslation.py
new file mode 100644
index 0000000..fbab377
--- /dev/null
+++ b/cloudcms/migrations/0009_auto__add_service__add_servicetranslation.py
@@ -0,0 +1,146 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Adding model 'Service'
+        db.create_table('cloudcms_service', (
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('ordering', self.gf('django.db.models.fields.SmallIntegerField')(default=0)),
+        ))
+        db.send_create_signal('cloudcms', ['Service'])
+
+        # Adding model 'ServiceTranslation'
+        db.create_table('cloudcms_servicetranslation', (
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('parent', self.gf('django.db.models.fields.related.ForeignKey')(related_name='translations', to=orm['cloudcms.Service'])),
+            ('language_code', self.gf('django.db.models.fields.CharField')(default='en', max_length=10)),
+            ('title', self.gf('django.db.models.fields.CharField')(max_length=100)),
+            ('slug', self.gf('django.db.models.fields.SlugField')(unique=True, max_length=50)),
+            ('description', self.gf('django.db.models.fields.CharField')(max_length=250, blank=True)),
+            ('cms_page', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['page.Page'], null=True, blank=True)),
+        ))
+        db.send_create_signal('cloudcms', ['ServiceTranslation'])
+
+
+    def backwards(self, orm):
+        # Deleting model 'Service'
+        db.delete_table('cloudcms_service')
+
+        # Deleting model 'ServiceTranslation'
+        db.delete_table('cloudcms_servicetranslation')
+
+
+    models = {
+        'cloudcms.application': {
+            'Meta': {'object_name': 'Application'},
+            'app_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
+            'code': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'extra_styles': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
+            'facebook_username': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'favicon': ('feincms.module.medialibrary.fields.MediaFileForeignKey', [], {'blank': 'True', 'related_name': "'as_favicon'", 'null': 'True', 'to': "orm['medialibrary.MediaFile']"}),
+            'footer_bottom': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
+            'footer_top': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'index_url': ('django.db.models.fields.CharField', [], {'default': "'/'", 'max_length': '255'}),
+            'linked_in_username': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'logo': ('feincms.module.medialibrary.fields.MediaFileForeignKey', [], {'to': "orm['medialibrary.MediaFile']", 'null': 'True', 'blank': 'True'}),
+            'show_twitter_feed_on_top': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'site': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sites.Site']"}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'twitter_username': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'})
+        },
+        'cloudcms.client': {
+            'Meta': {'object_name': 'Client'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'uid': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'cloudcms.clientversionsource': {
+            'Meta': {'object_name': 'ClientVersionSource'},
+            'architecture': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'client': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['cloudcms.Client']"}),
+            'file_regex': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'link': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'logo': ('feincms.module.medialibrary.fields.MediaFileForeignKey', [], {'to': "orm['medialibrary.MediaFile']", 'null': 'True', 'blank': 'True'}),
+            'os': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'source_type': ('django.db.models.fields.CharField', [], {'max_length': '60'}),
+            'version_regex': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
+        },
+        'cloudcms.service': {
+            'Meta': {'ordering': "['-ordering']", 'object_name': 'Service'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ordering': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'})
+        },
+        'cloudcms.servicetranslation': {
+            'Meta': {'ordering': "['title']", 'object_name': 'ServiceTranslation'},
+            'cms_page': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['page.Page']", 'null': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '250', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'language_code': ('django.db.models.fields.CharField', [], {'default': "'en'", 'max_length': '10'}),
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'translations'", 'to': "orm['cloudcms.Service']"}),
+            'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'medialibrary.category': {
+            'Meta': {'ordering': "['parent__title', 'title']", 'object_name': 'Category'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['medialibrary.Category']"}),
+            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '150'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '200'})
+        },
+        'medialibrary.mediafile': {
+            'Meta': {'object_name': 'MediaFile'},
+            'categories': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['medialibrary.Category']", 'null': 'True', 'blank': 'True'}),
+            'copyright': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
+            'created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'file': ('django.db.models.fields.files.FileField', [], {'max_length': '255'}),
+            'file_size': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'})
+        },
+        'page.page': {
+            'Meta': {'ordering': "['tree_id', 'lft']", 'object_name': 'Page'},
+            '_cached_url': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '300', 'db_index': 'True', 'blank': 'True'}),
+            '_content_title': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            '_page_title': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
+            'active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'creation_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'in_navigation': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'language': ('django.db.models.fields.CharField', [], {'default': "'en'", 'max_length': '10'}),
+            'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+            'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+            'meta_description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'meta_keywords': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'modification_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
+            'navigation_extension': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
+            'override_url': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}),
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['page.Page']"}),
+            'publication_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 7, 10, 0, 0)'}),
+            'publication_end_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+            'redirect_to': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}),
+            'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+            'site': ('django.db.models.fields.related.ForeignKey', [], {'default': '1', 'to': "orm['sites.Site']"}),
+            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '150'}),
+            'symlinked_page': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'page_page_symlinks'", 'null': 'True', 'to': "orm['page.Page']"}),
+            'template_key': ('django.db.models.fields.CharField', [], {'default': "'twocolwide'", 'max_length': '255'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
+            'translation_of': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'translations'", 'null': 'True', 'to': "orm['page.Page']"}),
+            'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'})
+        },
+        'sites.site': {
+            'Meta': {'ordering': "('domain',)", 'object_name': 'Site', 'db_table': "'django_site'"},
+            'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        }
+    }
+
+    complete_apps = ['cloudcms']
\ No newline at end of file
diff --git a/cloudcms/models.py b/cloudcms/models.py
index 696b268..a4248b5 100644
--- a/cloudcms/models.py
+++ b/cloudcms/models.py
@@ -36,9 +36,11 @@ import datetime
 from django.db import models
 from django.conf import settings
 from django.contrib.sites import models as sites_models
+from django.utils.translation import ugettext_lazy as _, ugettext, ungettext
 from django.core.cache import cache
 from django.utils import simplejson
 
+from feincms import translations
 from feincms.module.medialibrary.fields import MediaFileForeignKey
 from feincms.module.medialibrary.models import MediaFile
 
@@ -143,3 +145,45 @@ class ClientVersionSource(models.Model):
 # hook for feincms configuration, is this appropriate place ??? who knows
 from cloudcms.cms import *
 
+class Service(models.Model, translations.TranslatedObjectMixin):
+    """
+    Service.
+    """
+
+    ordering = models.SmallIntegerField(_('ordering'), default=0)
+
+    class Meta:
+        verbose_name = _('service')
+        verbose_name_plural = _('services')
+        ordering = ['-ordering',]
+
+    objects = translations.TranslatedObjectManager()
+
+    def __unicode__(self):
+        trans = translations.TranslatedObjectMixin.__unicode__(self)
+        return trans or _('Unnamed category')
+
+
+class ServiceTranslation(translations.Translation(Service)):
+    """
+    Service translation
+    """
+    title = models.CharField(_('service title'), max_length=100)
+    slug = models.SlugField(_('slug'), unique=True)
+    description = models.CharField(_('description'), max_length=250, blank=True)
+    cms_page = models.ForeignKey(Page, null=True, blank=True)
+
+    class Meta:
+        verbose_name = _('service translation')
+        verbose_name_plural = _('service translations')
+        ordering = ['title']
+
+    def __unicode__(self):
+        return self.title
+
+    def save(self, *args, **kwargs):
+        if not self.slug:
+            self.slug = slugify(self.title)
+
+        super(ServiceTranslation, self).save(*args, **kwargs)
+
diff --git a/cloudcms/templatetags/__init__.py b/cloudcms/templatetags/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/cloudcms/templatetags/cloudcms_tags.py b/cloudcms/templatetags/cloudcms_tags.py
new file mode 100644
index 0000000..00f2bee
--- /dev/null
+++ b/cloudcms/templatetags/cloudcms_tags.py
@@ -0,0 +1,20 @@
+from django import template
+from cloudcmsfaq.models import Question
+
+register = template.Library()
+
+@register.filter('get_service_faqs')
+def get_service_faqs(service):
+    """
+    Retrun service faqs grouped by category
+    """
+    grouped = {}
+
+    for q in Question.objects.active().filter(service=service, is_active=True):
+        if q.category not in grouped:
+            grouped[q.category] = []
+
+        grouped[q.category].append(q)
+
+    print grouped
+    return grouped.iteritems()
