From 038aabbb7e51209ce1bb945382216b514cd0eee2 Mon Sep 17 00:00:00 2001 From: Sanj Date: Mon, 4 Apr 2011 07:05:25 +0530 Subject: [PATCH] added boxes app --- itf/app/admin.py | 3 + itf/app/models.py | 57 ++--------- itf/boxes/__init__.py | 0 itf/boxes/models.py | 226 ++++++++++++++++++++++++++++++++++++++++++ itf/boxes/tests.py | 23 +++++ itf/boxes/views.py | 35 +++++++ itf/settings.py | 1 + 7 files changed, 294 insertions(+), 51 deletions(-) create mode 100644 itf/boxes/__init__.py create mode 100644 itf/boxes/models.py create mode 100644 itf/boxes/tests.py create mode 100644 itf/boxes/views.py diff --git a/itf/app/admin.py b/itf/app/admin.py index b40a577..38a2ba0 100644 --- a/itf/app/admin.py +++ b/itf/app/admin.py @@ -1,6 +1,8 @@ +''' from django.contrib import admin from models import ModelBox, ModelSort, ModelExtraButton + class ButtonsInline(admin.StackedInline): model = ModelExtraButton extra = 2 @@ -13,3 +15,4 @@ class ModelBoxAdmin(admin.ModelAdmin): admin.site.register(ModelBox, ModelBoxAdmin) admin.site.register(ModelSort) admin.site.register(ModelExtraButton) +''' diff --git a/itf/app/models.py b/itf/app/models.py index 2093ddc..0604ddf 100644 --- a/itf/app/models.py +++ b/itf/app/models.py @@ -4,7 +4,7 @@ from django.db.models import Q from ox.text import smartSplit from ox.django.fields import DictField from django.core.paginator import Paginator, InvalidPage, EmptyPage -from django.contrib.contenttypes.models import ContentType + def splitSearch(string): ret = [] @@ -16,9 +16,10 @@ def splitSearch(string): class ItfModel(models.Model): fts_fields = [] fk_filters = [] - related_models = [] +# related_models = [] sort_fields = [] hasComments = True + class Meta: abstract = True @@ -30,7 +31,7 @@ class ItfModel(models.Model): return self.get_dict() def get_dict(self): - return self.get(self._get_fields().keys() + self.related_models) + return self.get(self._get_fields().keys()) def get(self, props): typ = type(props) @@ -167,8 +168,9 @@ class ItfModel(models.Model): operator = '-' else: operator = '' - sort = operator + s['key'] + sort = operator + s['ey'] qset = qset.order_by(sort) + r0 = options['range'][0] r1 = options['range'][1] results = qset[r0:r1] @@ -185,53 +187,6 @@ def getField(fields, name): - -class ModelBox(models.Model): - model = models.ForeignKey(ContentType) - friendly_name = models.CharField(max_length=256) - friendly_name_singular = models.CharField(max_length=256, blank=True, null=True) - info = models.TextField(blank=True) - sort_options = models.ManyToManyField("ModelSort", blank=True, null=True) -# filter_fields = DictField(blank=True) - is_visible = models.BooleanField(default=True) - - @property - def module(self): - return self.model.app_label - - def __unicode__(self): - return self.friendly_name - - def get_dict(self): -# sort_options = map(lambda x: {'key': x.key, 'text': x.text}, self.sort_options.all()) - return { - 'module': self.module, - 'model': self.model.model, - 'info': self.info, - 'friendly_name': self.friendly_name, - 'friendly_name_singular': self.friendly_name_singular, - 'fk_filters': self.model.model_class().fk_filters, - 'fts_fields': self.model.model_class().fts_fields, - 'sort_options': map(lambda x: {'key': x.key, 'text': x.text}, self.sort_options.all()) - } - - -class ModelSort(models.Model): - key = models.CharField(max_length=64) - text = models.CharField(max_length=512) - - def __unicode__(self): - return "%s: %s" % (self.key, self.text,) - -class ModelExtraButton(models.Model): - icon = models.CharField(max_length=64) - mouseover = models.CharField(max_length=512, blank=True, null=True) - dialog_text = models.TextField() - model = models.ForeignKey(ModelBox) - - def __unicode__(self): - return self.mouseover - def site_config(): with open(settings.SITE_CONFIG) as f: site_config = json.load(f) diff --git a/itf/boxes/__init__.py b/itf/boxes/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/itf/boxes/models.py b/itf/boxes/models.py new file mode 100644 index 0000000..a956a5b --- /dev/null +++ b/itf/boxes/models.py @@ -0,0 +1,226 @@ +from django.db import models +from django.contrib.contenttypes.models import ContentType +from app.models import ItfModel +from django.contrib.contenttypes import generic + + +''' +Classes that need to link to a ContentType should link to ModelExtra instead. Maybe there's a better way to do this? +''' +class ModelExtra(models.Model): + model = models.OneToOneField(ContentType) + friendly_name = models.CharField(max_length=255, blank=True, null=True) + friendly_name_plural = models.CharField(max_length=255, blank=True, null=True) + sort_options = models.ManyToManyField("ModelSort", blank=True, null=True) + + def __unicode__(self): + return "%d: %s" % (self.id, self.friendly_name) + + def get_dict(self): + return { + 'module': self.model.model_class()._meta.app_label, + 'model': self.model.model, +# 'info': self.info, + 'friendly_name': self.friendly_name, + 'friendly_name_plural': self.friendly_name_plural, + 'fk_filters': self.model.model_class().fk_filters, + 'fts_fields': self.model.model_class().fts_fields, + 'sort_options': map(lambda x: {'key': x.key, 'text': x.text}, self.sort_options.all()) + } + + + +class ModelSort(models.Model): + key = models.CharField(max_length=64) + text = models.CharField(max_length=512) + + def __unicode__(self): + return "%s: %s" % (self.key, self.text,) + + + +""" +Base class for buttons - buttons can be an 'extra_button' for either a Box class or an instance of a model (defined in ModelExtra). +""" +class Button(ItfModel): + typ = '' + icon = models.CharField(max_length=255) #FIXME: read choices from list of icons + mouseover = models.CharField(max_length=255) + + class Meta: + abstract = True + + def __unicode__(self): + return "%d: %s" % (self.id, self.mouseover) + + def get_dict(self): + data = self.get_data() + data['type'] = self.typ, + data['icon'] = self.icon, + data['mouseover'] = self.mouseover + return data + + ''' + Subclasses need to implement get_data and return additional data-items as a dict. Keys cannot be one of 'type', 'icon', and 'mouseover' in the return value. + ''' + def get_data(self): + return {} + + +class BoxButton(Button): + class Meta: + abstract = True + +class ModelButton(Button): + class Meta: + abstract = True + + +class DialogButton(BoxButton): + typ = 'dialog' + dialogTitle = models.CharField(max_length=255) + dialogHTML = models.TextField() + + def get_data(self): + return { + 'title': self.dialogTitle, + 'html': self.dialogHTML + } + + +class StaticDownloadButton(BoxButton): + typ = 'staticDownload' + fil = models.FileField(upload_to='uploads/button_downloads/') + + def get_data(self): + return { + 'file': { + 'path': self.fil.url + } + } + + +class ModelDownloadButton(ModelButton): + typ = 'modelDownload' + file_field = models.CharField(max_length=100) #name of field which holds the file/s(?) to be downloaded + + def get_data(self): + return { + 'file': { + 'path': self.fil.url + } + } + + + +""" +Join model to enable m2m relations to generic foreign keys +""" +class ExtraButton(models.Model): + related_name = models.CharField(max_length=255, blank=True, null=True) + button_content_type = models.ForeignKey(ContentType) + button_id = models.PositiveIntegerField() + button = generic.GenericForeignKey('button_content_type', 'button_id') + + def __unicode__(self): + return "%d: %s" % (self.id, self.related_name) + + def get_dict(self): + return self.button.get_dict() + +""" +Join model +""" +class PanelBoxes(models.Model): + related_name = models.CharField(max_length=255, blank=True, null=True) + box_content_type = models.ForeignKey(ContentType) + box_id = models.PositiveIntegerField() + box = generic.GenericForeignKey("box_content_type", "box_id") + + def __unicode__(self): + return "%d: %s" % (self.id, self.related_name) + + def get_dict(self): + return self.box.get_dict() + + class Meta: + verbose_name = "Panel box" + verbose_name_plural = "Panel boxes" + + + +''' +Abstract base-class for boxes. +''' +class Box(ItfModel): + title = models.CharField(max_length=256) + extra_buttons = models.ManyToManyField("ExtraButton", blank=True, null=True) + + class Meta: + abstract = True + + def render(): + return '' + + def __unicode__(self): + return "%d: %s" % (self.id, self.title) + + def _get_buttons(self): + ret = [] + for b in self.extra_buttons.all(): + ret.append(b.button.get_dict()) + return ret + + def get_dict(self): + return {} + + +class StaticBox(Box): + html = models.TextField(blank=True, null=True) + + def get_dict(self): + return { + 'type': 'StaticBox', + 'title': self.title, + 'html': self.html, + 'extra_buttons': self._get_buttons() + } + + +class ModelsBox(Box): + default_model = models.ForeignKey(ModelExtra) + view_models = models.ManyToManyField(ModelExtra, related_name="box_views", blank=True, null=True) + info = models.TextField(blank=True) + + @property + def module(self): + return self.default_model.app_label + + def get_dict(self): + data = { + 'type': 'ModelsBox', + 'title': self.title, + 'info': self.info, + 'extra_buttons': self._get_buttons(), + 'default_model': self.default_model.get_dict(), + 'view_models': map(lambda x: x.get_dict(), self.view_models.all()) + } + return data + + + +class Panel(models.Model): + title = models.CharField(max_length=255) + boxes = models.ManyToManyField("PanelBoxes", blank=True, null=True) + enabled = models.BooleanField(default=False) + displayed = models.BooleanField(default=False) + + def __unicode__(self): + return self.title + + def get_dict(self): + return { + 'title': self.title, + 'boxes': map(lambda x: x.get_dict(), self.boxes.all()) + } + diff --git a/itf/boxes/tests.py b/itf/boxes/tests.py new file mode 100644 index 0000000..2247054 --- /dev/null +++ b/itf/boxes/tests.py @@ -0,0 +1,23 @@ +""" +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/itf/boxes/views.py b/itf/boxes/views.py new file mode 100644 index 0000000..1f0f52e --- /dev/null +++ b/itf/boxes/views.py @@ -0,0 +1,35 @@ +# Create your views here. +from api.actions import actions +import ox +from ox.django.decorators import login_required_json +from ox.django.shortcuts import render_to_json_response, get_object_or_404_json, json_response +from models import Panel + + + +def getPage(request): + ''' + returns displayed panels as displayed; hidden panels as hidden. + each panel is: + title + boxes: + type + title + default_model + etc + ''' + data = json.loads(request.POST['data']) + displayedPanels = Panel.objects.filter(enabled=True).filter(displayed=True) + hiddenPanels = Panel.objects.filter(enabled=True).filter(displayed=False) + panels = {} + panels['displayed'] = [] + for d in displayedPanels: + panels['displayed'].append(d.get_dict()) + panels['hidden'] = [] + for h in hiddenPanels: + panels['hidden'].append(h.get_dict()) + response = json_response({}) + response['data'] = panels + response['status'] = {'code': 200} + return render_to_json_response(response) +actions.register(getPage) diff --git a/itf/settings.py b/itf/settings.py index 3b47e53..160c512 100644 --- a/itf/settings.py +++ b/itf/settings.py @@ -141,6 +141,7 @@ INSTALLED_APPS = ( 'tagging', 'app', 'api', + 'boxes', # 'solango', 'multilingual', # 'multilingual.flatpages',