# interpreted as representing official policies, either expressed
# or implied, of GRNET S.A.
+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
class Application(models.Model):
+ """
+ Application object refers to the application each cms is deployed for.
+
+ Each cms deployment should contain at least one application object linked
+ to the site object the cms is deployed for.
+
+ Enabling cloudcms.context_processors.application in CONTEXT_PROCESSROS setting
+ let you can access the application object throughout the html templates.
+ """
code = models.CharField('Identifier', max_length=100, null=False, blank=False,
help_text="Just a codename of the application, to be used in "\
"several places where no free text is allowed"\
help_text="The title of the application")
logo = MediaFileForeignKey(MediaFile, blank=True, null=True)
+ favicon = MediaFileForeignKey(MediaFile, blank=True, null=True,
+ related_name="as_favicon")
site = models.ForeignKey(sites_models.Site)
app_url = models.URLField(help_text="The url of the application UI (not "\
"the cms", verify_exists=False, blank=True, null=True)
-
+ index_url = models.CharField(max_length=255, default="/", blank=False,
+ null=False)
linked_in_username = models.CharField(max_length=255, blank=True)
twitter_username = models.CharField(max_length=255, blank=True)
facebook_username = models.CharField(max_length=255, blank=True)
show_twitter_feed_on_top = models.BooleanField(default=False)
+ extra_styles = models.TextField(default="", blank=True)
+
+ footer_top = models.TextField(default="", blank=True)
+ footer_bottom = models.TextField(default="", blank=True)
@classmethod
def current(cls):
def __unicode__(self):
return self.title
+
+# http://stackoverflow.com/a/2680060/114435
+dthandler = lambda obj: obj.isoformat() if isinstance(obj, datetime.datetime) else None
+
+class Client(models.Model):
+ """
+ Model which refers to a service/application client. Client model contains
+ multiple ClientVersionSource to identify it's version downloads.
+ """
+ uid = models.CharField(max_length=255)
+ name = models.CharField(max_length=255)
+
+ def get_sources(self):
+ sources = {}
+ from cloudcms.clients import ClientVersions
+ for s in self.clientversionsource_set.all():
+ sources[s.os] = {'type': s.source_type,
+ 'args': [s.link]}
+
+ return ClientVersions(sources, cache_backend=cache)
+
+ def to_json(self):
+ return simplejson.dumps(list(self.get_sources().get_latest_versions()),
+ default=dthandler)
+
+ def get_default_os(self):
+ try:
+ return self.clientversionsource_set.filter(default=True)[0].os
+ except IndexError:
+ return self.clientversionsource_set.filter()[0].os
+
+ def __unicode__(self):
+ return self.name
+
+
+class ClientVersionSource(models.Model):
+ """
+ Client version source. source_type choices should map to
+ cloudcms.clients.SOURCE_TYPES.
+ """
+
+ default = models.BooleanField(default=True)
+ source_type = models.CharField(max_length=60,
+ choices=(('link','Link'),
+ ('direct','Direct'),
+ ('redmine_files','Redmine files')))
+ os = models.CharField(max_length=255)
+ link = models.CharField(max_length=255)
+ logo = MediaFileForeignKey(MediaFile, blank=True, null=True)
+ architecture = models.CharField(max_length=255, null=True, blank=True,
+ help_text="""Depending the source type this can be left empty and
+ let source type identify the architecture""")
+ client = models.ForeignKey(Client)
+ version_regex = models.CharField(max_length=255, help_text="""Regular expression to
+ match the version of the file based on retrieved source filenames
+ (used in redmine source types)""", null=True, blank=True)
+ file_regex = models.CharField(max_length=255, help_text="""Return only files that
+ match this expression""", null=True, blank=True)
+
+ def __unicode__(self):
+ return "[%s] %s" % (self.get_source_type_display(), self.os)
+
+
# 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)
+ image_faq = MediaFileForeignKey(MediaFile, blank=True, null=True, related_name='image_faq')
+ image_userguide = MediaFileForeignKey(MediaFile, blank=True, null=True,related_name='image_userguide')
+ class_name = models.CharField(_('class name'), max_length=100, blank=True)
+
+
+ class Meta:
+ verbose_name = _('service')
+ verbose_name_plural = _('services')
+ ordering = ['-ordering',]
+
+ objects = translations.TranslatedObjectManager()
+
+ def get_first_question(self):
+ try:
+ return self.faqs.filter(is_active=True)[0]
+ except:
+ return None
+
+ def get_first_entry(self):
+ try:
+ return self.userguideentries.filter(is_active=True)[0]
+ except:
+ return None
+
+ 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)
+ title_faq = models.CharField(_('service title (faq section)'), max_length=100, blank=True)
+ title_userguide = models.CharField(_('service title (userguide section)'), max_length=100, 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)
+