From cc6b01d9380c288cb0e861e7f87e543034441301 Mon Sep 17 00:00:00 2001 From: sanj Date: Tue, 27 Jul 2010 06:02:02 +0530 Subject: [PATCH] too many changes to enumerate, sorry. working state. now to break it again.. --- edgware/editor/models.py | 27 +++++++++------ edgware/editor/views.py | 39 ++++++++++++++++++--- edgware/files/admin.py | 1 + edgware/files/convert.py | 6 +++- edgware/files/models.py | 57 +++++++++++++++++++++++++++---- edgware/settings.py | 8 +++-- edgware/static/ckeditor/config.js | 7 ++-- edgware/static/css/editor.css | 2 +- edgware/static/css/fonts.css | 37 ++++++++++++++++---- edgware/static/js/editor.js | 20 ++++++++--- edgware/templates/editor.html | 11 ++++-- 11 files changed, 173 insertions(+), 42 deletions(-) diff --git a/edgware/editor/models.py b/edgware/editor/models.py index 774d9e0..49afe20 100644 --- a/edgware/editor/models.py +++ b/edgware/editor/models.py @@ -5,6 +5,7 @@ from django.contrib.comments.signals import comment_was_posted import simplejson from django.core.mail import send_mail import os +from os.path import join from PIL import Image from django.template import Template, Context from django.template.loader import get_template @@ -64,7 +65,7 @@ class Link(models.Model): class ProductType(models.Model): name = models.CharField(max_length=255) aspect_ratio = models.FloatField(default=0.707, help_text="Default 0.707 as per http://en.wikipedia.org/wiki/Paper_size") - print_width = models.IntegerField(help_text="Unit: mm") + print_width = models.IntegerField(default=210, help_text="Default: A4 (210mm) Unit: mm") def __unicode__(self): return self.name @@ -148,6 +149,7 @@ For image_resize, prop = 'image_resize' class Revision(models.Model): article = models.ForeignKey("Article") page = models.ForeignKey("Page") + user = models.ForeignKey(User) box_type = models.CharField(max_length=100) box_id = models.IntegerField() prop = models.CharField(max_length=100) @@ -158,7 +160,7 @@ class Revision(models.Model): def saveRevision(r): page = Page.objects.get(pk=r['page_id']) article = page.article - rev = Revision(article=article, page=page, box_type=r['box_type'], box_id=r['box_id'], prop=r['prop'], old_val=r['old_val'], new_val=r['new_val'], uuid=r['uuid']) + rev = Revision(article=article, page=page, user=r.user, box_type=r['box_type'], box_id=r['box_id'], prop=r['prop'], old_val=r['old_val'], new_val=r['new_val'], uuid=r['uuid']) rev.save() return rev.id @@ -389,7 +391,7 @@ class TextBox(models.Model): background_color = models.CharField(max_length=16) border_style = models.CharField(max_length=16) border_width = models.IntegerField() -# direction = models.CharField(max_length=8) + direction = models.CharField(max_length=8) # line_height = models.IntegerField(blank=True, null=True) # letter_spacing = models.IntegerField(blank=True, null=True) # word_spacing = models.IntegerField(blank=True, null=True) @@ -423,7 +425,7 @@ class TextBox(models.Model): 'left': addPx(self.left), 'z-index': self.z_index, 'opacity': self.opacity, -# 'direction': self.direction, + 'direction': self.direction, 'border-style': self.border_style, 'border-width': addPx(self.border_width), 'border-color': self.border_color, @@ -538,16 +540,18 @@ class ImageBox(models.Model): This function returns the filename of the highest res original dimensions file, converted to jpeg """ def original_print(self): + ''' basePath = "media/images/original/" filename = os.path.basename(str(self.file.file)) if extFileName(filename) != 'jpg': f = baseFileName(filename) + ".jpg" else: f = filename - return basePath + f + ''' + return str(self.file.file) def crop(self, x1, y1, x2, y2, width, height): - original_image = Image.open(MEDIA_ROOT + "/" + self.actual_unresized()) + original_image = Image.open(join(MEDIA_ROOT, self.actual_unresized())) original_width = original_image.size[0] original_height = original_image.size[1] current_width = self.width @@ -577,16 +581,17 @@ class ImageBox(models.Model): return self def cropped_fname(self): - filename = baseFileName(os.path.basename(self.original_print())) - cropped_fname = "%s_%d_%d_%d_%d.jpg" % (filename, self.crop_x1, self.crop_y1, self.crop_x2, self.crop_y2) + filename = os.path.splitext(os.path.basename(self.original_print()))[0] + cropped_fname = "%s_%d_%d_%d_%d.%s" % (filename, self.crop_x1, self.crop_y1, self.crop_x2, self.crop_y2, self.file.ext) return cropped_fname def cropped_path(self): - return MEDIA_ROOT + "/media/images/cropped/" + self.cropped_fname() + return os.path.dirname(str(self.file.file)) +# return MEDIA_ROOT + "/media/images/cropped/" + self.cropped_fname() def actual_unresized(self): if self.is_cropped: - return "media/images/cropped/" + self.cropped_fname() + return join(self.cropped_path(), self.cropped_fname()) else: return self.original_print() @@ -653,7 +658,7 @@ def comments_notify(sender, **kwargs): img_id = comment.content_object.id url = "http://edgwareroad.org/slider/%d" % (img_id) message = "Page: %s \n Name: %s \n Email: %s \n Comment: %s" % (url, name, email, content) - send_mail("New comment on edgwareroad.org", message, "do_not_reply@edgwareroad.org", ["hello@edgwareroad.org"]) + send_mail("New comment on edgwareroad.org", message, "do_not_reply@edgwareroad.org", ["hello@edgwareroad.org", "sanjaybhangar@gmail.com"]) # f = open("/home/sanj/tmp/edgeTest.txt", "w") # f.write(message) return True diff --git a/edgware/editor/views.py b/edgware/editor/views.py index 38bf0ba..0b73d23 100644 --- a/edgware/editor/views.py +++ b/edgware/editor/views.py @@ -17,6 +17,7 @@ from settings import MEDIA_ROOT from PIL import Image import os from print_pdf import print_url_list +from settings import SITE_BASE @login_required def editor(request): @@ -127,6 +128,7 @@ def imagebox_crop(request): old_value = json.dumps({'path': thisBox.get_path(), 'height': thisBox.height, 'width': thisBox.width}) thisBox.crop(int(o['x1']), int(o['y1']), int(o['x2']), int(o['y2']), o['width'], o['height']) revision_id = saveRevision({ + 'user': request.user, 'box_id': thisBox.id, 'box_type': 'image', 'prop': 'image_crop', @@ -161,6 +163,7 @@ def textbox_new(request): box.set_css(prop, val) box.save() revision_id = saveRevision({ + 'user': request.user, 'box_id': box.id, 'box_type': 'text', 'prop': 'new_box', @@ -189,6 +192,7 @@ def textbox_update_css(request): old_value = box.get_css(prop) box.set_css(prop, val) revision_id = saveRevision({ + 'user': request.user, 'box_id': box.id, 'box_type': 'text', 'prop': prop, @@ -218,6 +222,7 @@ def textbox_set_html(request): box.html = html box.save() revision_id = saveRevision({ + 'user': request.user, 'box_id': box.id, 'box_type': 'text', 'prop': 'html', @@ -239,6 +244,7 @@ def textbox_delete(request): box.is_displayed = False box.save() rev_id = saveRevision({ + 'user': request.user, 'box_id': box.id, 'box_type': 'text', 'prop': 'delete_box', @@ -263,6 +269,7 @@ def imagebox_new(request): box.set_css(prop, val) box.save() revision_id = saveRevision({ + 'user': request.user, 'box_id': box.id, 'box_type': 'image', 'prop': 'new_box', @@ -289,6 +296,7 @@ def imagebox_update_css(request): old_value = box.get_css(prop) box.set_css(prop, val) revision_id = saveRevision({ + 'user': request.user, 'box_id': box.id, 'box_type': 'image', 'prop': prop, @@ -322,6 +330,7 @@ def imagebox_resize(request): box.save() resizedPath = box.get_path() revision_id = saveRevision({ + 'user': request.user, 'box_id': box.id, 'box_type': 'image', 'prop': 'image_resize', @@ -349,6 +358,7 @@ def imagebox_delete(request): box.is_displayed = False box.save() rev_id = saveRevision({ + 'user': request.user, 'box_id': box.id, 'box_type': 'image', 'prop': 'delete_box', @@ -421,7 +431,7 @@ def category_json(request): 'media_id': media_id } rList.append(d) - j = json.dumps(rList) + j = json.dumps({'resources': rList}) return HttpResponse(j, mimetype="application/json") else: return False @@ -527,7 +537,7 @@ def page_pdf(request): print_width_mm = article.product.typ.print_width print_height_mm = int(print_width_mm // article.product.typ.aspect_ratio) output_path = MEDIA_ROOT + "/pdf/tmpPDF" + article_id + page_id + ".pdf" - cmd = "wkhtmltopdf --page-width %d --page-height %d 'http://edgwareroad.org/edit/view_article/%s/?m=%f&p=%s' '%s'" % (print_width_mm, print_height_mm, article_id, m, page_id,output_path,) + cmd = "wkhtmltopdf --page-width %d --page-height %d '%s/edit/view_article/%s/?m=%f&p=%s' '%s'" % (print_width_mm, print_height_mm, SITE_BASE, article_id, m, page_id,output_path,) os.system(cmd) return HttpResponseRedirect(output_path.replace(MEDIA_ROOT, "/static")) @@ -555,10 +565,26 @@ def product_pdf(request): m = product.get_print_multiplier(dpi) url_list = [] for p in pages: - url = "http://edgwareroad.org/edit/view_article/%d/?m=%f&p=%d'" % (p.article.id, m, p.id) + url = SITE_BASE + "/edit/view_article/%d/?m=%f&p=%d'" % (p.article.id, m, p.id) url_list.append(url) - output_path = MEDIA_ROOT + "/pdf/" + self.title + ".pdf" - pdf_path = print_url_list(url_list, width, height, output_path) + output_path = MEDIA_ROOT + "/pdf/" + product.title + ".pdf" + pdf_path = print_url_list(url_list, width_mm, height_mm, output_path) + return HttpResponseRedirect(pdf_path.replace(MEDIA_ROOT, "/static")) + +def article_pdf(request): + a_id = request.GET['id'] + article = get_object_or_404_json(Article, pk=a_id) + dpi = request.GET.get('dpi', 150) + width_mm = request.GET.get('width', article.product.typ.print_width) + height_mm = int(width_mm // product.typ.aspect_ratio) + pages = Page.objects.filter(article=article) + m = article.get_print_multiplier(dpi) + url_list = [] + for p in pages: + url = SITE_BASE + "/edit/view_article/%d/?m=%f&p=%d'" % (p.article.id, m, p.id) + url_list.append(url) + output_path = MEDIA_ROOT + "/pdf/" + article.name + "_" + str(article.current_revision()) + ".pdf" + pdf_path = print_url_list(url_list, width_mm, height_mm, output_path) return HttpResponseRedirect(pdf_path.replace(MEDIA_ROOT, "/static")) def article_json(request): @@ -580,6 +606,7 @@ def new_page(request): p.page_no = last_page_no + 1 p.save() rev_id = saveRevision({ + 'user': request.user, 'box_id': 0, 'box_type': 'page', 'prop': 'new_page', @@ -597,7 +624,9 @@ def new_page(request): @login_required_json def delete_page(request): page = get_object_or_404_json(Page, id=request.GET['id']) + page.delete() rev_id = saveRevision({ + 'user': request.user, 'box_id': 0, 'box_type': 'page', 'prop': 'delete_page', diff --git a/edgware/files/admin.py b/edgware/files/admin.py index 65c83b3..d29a46e 100755 --- a/edgware/files/admin.py +++ b/edgware/files/admin.py @@ -8,6 +8,7 @@ class filesForm(forms.ModelForm): file = forms.FileField(label='Upload File', required=False, widget=FirefoggInput({'passthrough': True})) + exclude = ('info',) class Meta: model = File diff --git a/edgware/files/convert.py b/edgware/files/convert.py index 2b5126c..f447f8b 100644 --- a/edgware/files/convert.py +++ b/edgware/files/convert.py @@ -16,6 +16,8 @@ def toJpg(f): return def toOgg(f): + if f.ext == 'ogg': + return output_path = "%s/media/audio/%s" % (MEDIA_ROOT, e.models.baseFileName(os.path.basename(f.file.path)) + ".ogg",) cmd = "ffmpeg2theora -o '%s' --no-skeleton --novideo '%s'" % (output_path, f.file.path,) os.system(cmd) @@ -28,6 +30,8 @@ def toTxt(f): # print f.file def toOgv(f): + if f.ext == 'ogv': + return output_path = "%s/media/video/%s" % (MEDIA_ROOT, e.models.baseFileName(os.path.basename(f.file.path)) + ".ogv",) if e.models.extFileName(str(f.file)).lower() == 'ogv' or e.models.extFileName(str(f.file)).lower() == 'ogg': cmd = "cp %s %s" % (f.file.path, output_path) @@ -44,7 +48,7 @@ def ignoreFile(f): #This function is called from the post_save signal, receives kwargs['instance'] as a File instance def convertFile(**kwargs): fn = { - 'jpg': toJpg, + 'jpg': ignoreFile, 'mp3': toOgg, 'txt': ignoreFile, 'ogv': toOgv, diff --git a/edgware/files/models.py b/edgware/files/models.py index 3a927f9..48e4dd5 100755 --- a/edgware/files/models.py +++ b/edgware/files/models.py @@ -4,9 +4,13 @@ from oxdjango.fields import DictField from tagging.models import Tag from django.contrib.auth.models import User, Group, Permission import os +from os.path import join from convert import convertFile from django.db.models.signals import post_save +from settings import UPLOAD_ROOT, MEDIA_ROOT +from utils.add_file import hashFile, fileInfo +#FIXME: The following two functions are ridiculous. please remove and clean up all references to them. def baseFileName(filename): r = filename.rindex('.') return filename[0:r] @@ -19,7 +23,8 @@ def extFileName(filename): MIME_TYPES = ( ('jpg', 'Image'), ('ogv', 'Video'), - ('mp3', 'Audio'), + ('mp3', 'Audio (mp3)'), + ('ogg', 'Audio (Ogg)'), ('txt', 'Text'), ('oth', 'Other'), ('hid', 'Hidden'), @@ -32,7 +37,7 @@ class Folder(models.Model): category = models.ForeignKey("Category") def get_full_path(self): - return join(UPLOAD_ROOT, category.folder_name, parent. + return join(UPLOAD_ROOT, self.category.folder_name, self.relative_path) def get_children(self): return Folder.objects.filter(parent=self) @@ -57,7 +62,8 @@ class Folder(models.Model): class File(models.Model): - file = models.FileField('File', upload_to='files') + file = models.FileField('File', upload_to=UPLOAD_ROOT) + full_path = models.CharField(max_length=2048, blank=True, db_index=True) #makes it more efficient to retrieve a file by path instead of using self.file.path title = models.CharField(max_length=255) description = models.TextField(blank=True) tags = TagField("Tags", help_text="Enter as many tags as you like, separated by commas") @@ -66,25 +72,62 @@ class File(models.Model): added = models.DateField("Date Added", auto_now_add=True) categories = models.ManyToManyField('Category', verbose_name='Studies') type = models.ForeignKey('Type', verbose_name='File Type') - folder = models.ForeignKey("Folder") - info = DictField(blank=True, null=True) + ext = models.CharField(max_length=100, blank=True) + oshash = models.CharField(max_length=128, blank=True, db_index=True) +# folder = models.ForeignKey("Folder") + info = DictField(blank=True) + @classmethod + def add_from_path(cls, category, user, path, **kwargs): + if cls.objects.filter(full_path=path).count() > 0: + #Do update checking here. For now, we move on if it already exists in db + return False + info = fileInfo(path) + oshash = hashFile(path) + dirname = os.path.dirname(path) + filename = os.path.basename(path) + title = kwargs.get("title", filename) + description = kwargs.get("description", "") + ext = os.path.splitext(filename)[1][1:] + django_file_path = UPLOAD_ROOT.replace(MEDIA_ROOT, "")[1:] + f = cls(file=django_file_path, full_path=path, title=title, description=description, ext=ext, oshash=oshash, info=info) + f.userID = user + f.save() + f.categories.append(category) + f.save_m2m() + return f + + @classmethod + def addFiles(cls, category, user, folder_name): + path = join(UPLOAD_ROOT, folder_name) + # spider(path, addFile, category=category) + for dirpath, dirnames, filenames in os.walk(path): + if filenames: + # prefix = dirpath[len(path)+1:] + for filename in filenames: + if not filename.startswith('._') and not filename in ('.DS_Store', ): + cls.add_from_path(category, user, join(dirpath, filename)) + # print dirpath + " + " + filename + def __unicode__(self): return self.title def original_print(self): + ''' basePath = "media/images/original/" filename = os.path.basename(str(self.file.url)) if extFileName(filename).lower() != 'jpg': f = baseFileName(filename) + ".jpg" else: f = filename - return basePath + f + ''' + return str(self.file) + class Category(models.Model): name = models.CharField(max_length=255) groups = models.ManyToManyField(Group, null=True) - folder_name = models.CharField(max_length=512) +# folder_name = models.CharField(max_length=512) def __unicode__(self): return self.name diff --git a/edgware/settings.py b/edgware/settings.py index e97fe19..ccf595a 100644 --- a/edgware/settings.py +++ b/edgware/settings.py @@ -13,6 +13,7 @@ LOGGING_OUTPUT_ENABLED = True INTERNAL_IPS = ('127.0.0.1',) PROJECT_PATH = os.path.dirname(__file__) +SITE_BASE = "http://localhost:8000" ADMINS = ( # ('Your Name', 'your_email@domain.com'), @@ -49,7 +50,7 @@ USE_I18N = True # Example: "/home/media/media.lawrence.com/" MEDIA_ROOT = join(PROJECT_PATH, 'static') UPLOAD_ROOT = join(MEDIA_ROOT, 'media', 'studies') - +UPLOAD_ROOT_RELATIVE = UPLOAD_ROOT.replace(MEDIA_ROOT, "")[1:] # URL that handles the media served from MEDIA_ROOT. Make sure to use a # trailing slash if there is a path component (optional in other cases). # Examples: "http://media.lawrence.com", "http://example.com/media/" @@ -72,6 +73,8 @@ TEMPLATE_LOADERS = ( MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.middleware.csrf.CsrfResponseMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware', @@ -99,9 +102,10 @@ INSTALLED_APPS = ( 'django_extensions', 'django.contrib.flatpages', 'debug_toolbar', - 'south', + # 'south', 'django.contrib.comments', 'sorl.thumbnail', + # 'utils', # 'django_firefogg', ) diff --git a/edgware/static/ckeditor/config.js b/edgware/static/ckeditor/config.js index adb45ce..a790128 100755 --- a/edgware/static/ckeditor/config.js +++ b/edgware/static/ckeditor/config.js @@ -8,13 +8,16 @@ CKEDITOR.editorConfig = function( config ) config.toolbar_Basic = [ - ['Bold', 'Italic', '-', 'FontSize', 'TextColor', 'JustifyLeft','JustifyCenter','JustifyRight'] + ['Bold', 'Italic', '-', 'FontSize', 'Font', 'TextColor', 'JustifyLeft','JustifyCenter','JustifyRight'] ]; config.toolbar_Min = [ ]; - + + config.contentsCss = '/static/css/fonts.css'; + config.font_names = "Berlin Safari;SG Grotesque;Tallys;GraublauWeb;Fontin;Tagesschrift;"; + // Define changes to default configuration here. For example: // config.language = 'fr'; diff --git a/edgware/static/css/editor.css b/edgware/static/css/editor.css index a386b74..75c84ae 100644 --- a/edgware/static/css/editor.css +++ b/edgware/static/css/editor.css @@ -231,7 +231,7 @@ p { left: 4px; } -#searchSelect { +.binSelect { width: 208px; font-size: 12px; margin-left: 7px; diff --git a/edgware/static/css/fonts.css b/edgware/static/css/fonts.css index c8a0d43..5f6a3ea 100644 --- a/edgware/static/css/fonts.css +++ b/edgware/static/css/fonts.css @@ -1,25 +1,48 @@ + @font-face { - font-family: GraublauWeb; + font-family: GraublauWeb; src: url(/static/fonts/GraublauWeb.otf) format("opentype"); } @font-face { - font-family: Tallys; + font-family: Tallys; src: url(/static/fonts/Tallys_15.otf) format("opentype"); } @font-face { - font-family: Fontin; - src: url(/static/fonts/Fontin-Regular.otf) format("opentype"); + font-family: Fontin; + src: url(/static/fonts/Fontin-Regular.otf) format("opentype"); } @font-face { - font-family: Tagesschrift; + font-family: Tagesschrift; src: url(/static/fonts/YanoneTagesschrift.ttf) format("truetype"); } + +@font-face { + font-family: "Berlin Safari"; + src: url(/static/fonts/berlinsafari.ttf) format("truetype"); +} + +@font-face { + font-family: "SG Grotesque"; + src: url('/static/fonts/SG Grotesque.otf' format("opentype"); +} + +@font-face { + font-family: "SG Grotesque"; + src: url('/static/fonts/SG Grotesque Bold.otf' format("opentype"); + font-weight: bold; +} + +@font-face { + font-family: "SG Grotesque"; + src: url('/static/fonts/SG Grotesque Italic.otf' format("opentype"); + font-weight: italic; +} + body { font-size: 14px; - } - +} diff --git a/edgware/static/js/editor.js b/edgware/static/js/editor.js index 48073ea..9e9b73e 100644 --- a/edgware/static/js/editor.js +++ b/edgware/static/js/editor.js @@ -15,7 +15,8 @@ var loadArticle = function(id) { startPoller(); }); } - + +//is used by the poller to call itself 1 second in the future. not sure why im doing this. FIXME: function name at least? function delayedRecursion(time) { // console.log("delayed recursion called" + time); POLLER = setTimeout(startPoller, time); @@ -103,6 +104,7 @@ function handleRevision(json) { var val = toPx(json.new_val); } d[json.prop] = val; + //dont try and animate properties like 'transparent', it will fail. if (d[json.prop] == 'transparent' || json.old_val == 'transparent') { box.jq.css(d); } else { @@ -145,9 +147,11 @@ $(document).ready(function() { $('.prevPage').click(function() { edgeBin.prevPage(); }); + $('.nextPage').click(function() { edgeBin.nextPage(); }); + $('.searchBin').keyup(function() { edgeBin.searchString($(this).val()); }); @@ -340,6 +344,7 @@ Canvas.prototype.toObj = function() { // console.log(json); } +//this function is not used. FIXME: remove Canvas.prototype.save = function() { var that = this; var url = "/editor/canvas/save/"; @@ -798,7 +803,7 @@ Bin.prototype.loadCategory = function(catid) { this.jq.find('.resource').remove(); this.resources = []; $.getJSON("/edit/category/json/", {'id': catid}, function(json) { - var resources = json; + var resources = json.resources; for (r in resources) { if (resources.hasOwnProperty(r)) { thisResource = new Resource(resources[r], r); @@ -810,6 +815,13 @@ Bin.prototype.loadCategory = function(catid) { }); }; +Bin.prototype.loadResources = function(url, params) { + var that = this; + this.jq.find('.resource').remove(); + this.resources = []; + +} + Bin.prototype.searchString = function(str) { var that = this; @@ -1158,7 +1170,7 @@ function replaceDiv( div ) { // }) - console.log(div); +// console.log(div); // alert($(div).attr('classname')); height = parseInt($(div).css('height')) - 6; height = toPx(height); @@ -1230,7 +1242,7 @@ $(".box").live("click", function(e){ var box = $(this).find('*').getBox().jq; var boxObj = $(this).find('*').getBox(); if ($(".properties").length == 0) { - console.log($(this).attr('class')) +// console.log($(this).attr('class')) if ($(this).hasClass("textBox")) { $('body').append(tmpl('tmpl_textbox_properties', {})); } diff --git a/edgware/templates/editor.html b/edgware/templates/editor.html index 9e083c1..8043fad 100644 --- a/edgware/templates/editor.html +++ b/edgware/templates/editor.html @@ -205,12 +205,19 @@
- {% for c in categories %} {% endfor %} - +
+