From b718b3f69d43ba7f32f4ad6a5c31429fa3dc2c4e Mon Sep 17 00:00:00 2001 From: Lukasz Rekucki Date: Tue, 10 Nov 2009 11:33:12 +0100 Subject: [PATCH] Dodanie wybierania motywow. --- apps/explorer/views.py | 3 +- platforma/settings.py | 1 + platforma/static/css/html.css | 66 ++++++++ platforma/static/css/jquery.modal.css | 1 + platforma/static/js/views/editor.js | 166 +++++++++++++----- platforma/static/js/views/html.js | 204 ++++++++++++++++------- platforma/static/xsl/html2wl_client.xsl | 2 +- platforma/static/xsl/wl2html_client.xsl | 2 +- platforma/templates/explorer/editor.html | 53 +++++- platforma/urls.py | 3 +- 10 files changed, 393 insertions(+), 108 deletions(-) mode change 100644 => 100755 platforma/settings.py mode change 100644 => 100755 platforma/static/js/views/editor.js diff --git a/apps/explorer/views.py b/apps/explorer/views.py index a67d27ca..76670f50 100755 --- a/apps/explorer/views.py +++ b/apps/explorer/views.py @@ -17,7 +17,7 @@ from django.contrib.auth.decorators import login_required from explorer import forms from api.models import PullRequest - +from bookthemes.models import Theme def ajax_login_required(view): """Similar ro @login_required, but instead of redirect, @@ -40,6 +40,7 @@ def display_editor(request, path): 'fileid': path, 'euser': user, 'gallery_from': gallery_form, + 'availble_themes': ({'first_letter': t.name[0].upper(), 'name': t.name} for t in Theme.objects.order_by('name')), }, context_instance=RequestContext(request)) # diff --git a/platforma/settings.py b/platforma/settings.py old mode 100644 new mode 100755 index 29974faa..cbfd70fa --- a/platforma/settings.py +++ b/platforma/settings.py @@ -122,6 +122,7 @@ INSTALLED_APPS = ( 'filebrowser', 'explorer', 'toolbar', + 'bookthemes', 'api', ) diff --git a/platforma/static/css/html.css b/platforma/static/css/html.css index 682e905e..c00b5f1d 100755 --- a/platforma/static/css/html.css +++ b/platforma/static/css/html.css @@ -473,4 +473,70 @@ z-index: 0; font-size: 10pt; background-color: ivory; +} + +/*/ +/* +/* Theme edit dialog +/* +/*/ +#theme-edit-dialog { + left: 5%; + right: 5%; + top: 5%; + bottom: 5%; + padding: 0em; +} + +#theme-edit-dialog *.data-area { + position: absolute; + + top: 0px; + left: 0px; + right: 0px; + bottom: 32px; + + padding: 0px; + background-color: #fafafa; + + overflow-y: scroll; +} + +#theme-edit-dialog *.action-area { + position: absolute; + height: 30px; + line-height: 20px; + + left: 5px; + right: 5px; + bottom: 0px; + + padding: 0px; + margin: 0px; + + border-top: 1px solid black; + background-color: #fafafa; +} + +#theme-edit-dialog *.action-area * { + vertical-align: baseline; +} + +#theme-edit-dialog .theme-multi-list { + padding: 0.5em 1em; +} + +#theme-edit-dialog .theme-multi-list .unknown-themes { + display: none; +} + +#theme-edit-dialog .theme-multi-list .letter-heading { + font-size: 150%; + text-align: left; + border-bottom: 1px solid black; + padding-top: 1em; +} + +#theme-edit-dialog .theme-mutli-list input:checked + label { + font-weight: bold; } \ No newline at end of file diff --git a/platforma/static/css/jquery.modal.css b/platforma/static/css/jquery.modal.css index 4717ad45..4dc8a258 100755 --- a/platforma/static/css/jquery.modal.css +++ b/platforma/static/css/jquery.modal.css @@ -23,6 +23,7 @@ color: #333; border: 1px solid black; padding: 1em; + z-index: 10000; } .jqmOverlay { background-color: #000; } diff --git a/platforma/static/js/views/editor.js b/platforma/static/js/views/editor.js old mode 100644 new mode 100755 index cfd18166..1d55af60 --- a/platforma/static/js/views/editor.js +++ b/platforma/static/js/views/editor.js @@ -19,37 +19,7 @@ var EditorView = View.extend({ this.splitView = new SplitView('#splitview', doc); // Inicjalizacja okien jQuery Modal - $('#commit-dialog', this.element). - jqm({ - modal: true, - onShow: this.loadRelatedIssues.bind(this) - }); - - $('#commit-dialog-cancel-button', this.element).click(function() { - $('#commit-dialog-error-empty-message').hide(); - $('#commit-dialog').jqmHide(); - }); - - $('#commit-dialog-save-button').click(function(event, data) - { - if ($('#commit-dialog-message').val().match(/^\s*$/)) { - $('#commit-dialog-error-empty-message').fadeIn(); - } else { - $('#commit-dialog-error-empty-message').hide(); - $('#commit-dialog').jqmHide(); - - var message = $('#commit-dialog-message').val(); - $('#commit-dialog-related-issues input:checked') - .each(function() { - message += ' refs #' + $(this).val(); - }); - - var ctx = $('#commit-dialog').data('context'); - console.log("COMMIT APROVED", ctx); - ctx.callback(message); - } - return false; - }); + this.commitDialog = new CommitDialog( $('#commit-dialog') ); // $('#split-dialog').jqm({ @@ -65,10 +35,10 @@ var EditorView = View.extend({ this.model.saveDirtyContentModel(); }, - commit: function(event) { - $('#commit-dialog', this.element).jqmShow({ - callback: this.doCommit.bind(this) - }); + commit: function(event) + { + this.commitDialog.show( this.doCommit.bind(this) ) + }, doCommit: function(message) { @@ -80,16 +50,14 @@ var EditorView = View.extend({ }, merge: function(event) { - $('#commit-dialog', this.element).jqmShow({ - callback: this.doMerge.bind(this) - }); + this.commitDialog.show( this.doMerge.bind(this) ) }, doMerge: function(message) { this.model.merge(message); }, - loadRelatedIssues: function(hash) { + /*loadRelatedIssues: function(hash) { var self = this; var c = $('#commit-dialog-related-issues'); @@ -113,7 +81,7 @@ var EditorView = View.extend({ }); hash.w.show(); - }, + }, */ modelStateChanged: function(property, value) { // Uaktualnia stan przycisków @@ -153,3 +121,121 @@ var EditorView = View.extend({ this._super(); } }); + + +var AbstractDialog = Class.extend({ + _className: 'AbstractDialog', + + init: function($element, modal, overlay) + { + this.$window = $element; + this.$window.jqm({ + modal: modal || true, + overlay: overlay || 80, + // toTop: true, + onShow: this.onShow.bind(this), + onHide: this.onHide.bind(this) + }); + + this.reset(); + + $('.cancel-button', this.$window).click(this.cancel.bind(this)); + $('.save-button', this.$window).click(this.accept.bind(this)); + }, + + onShow: function(hash) + { + hash.w.show(); + }, + + onHide: function(hash) + { + hash.w.hide(); + hash.o.remove(); + }, + + reset: function() { + this.acceptCallback = null; + this.cancelCallback = null; + this.errors = []; + + $('.error-messages-box', this.$window).html('').hide(); + + this.userData = {}; + }, + + show: function(acall, ccall) { + this.acceptCallback = acall; + this.cancelCallback = ccall; + + // do the show + this.$window.jqmShow(); + }, + + cancel: function() { + this.$window.jqmHide(); + if(this.cancelCallback) this.cancelCallback(this); + this.reset(); + }, + + accept: function() + { + this.errors = []; + + if(!this.validate()) { + this.displayErrors(); + return; + } + + this.$window.jqmHide(); + + if(this.acceptCallback) + this.acceptCallback(this); + + this.reset(); + }, + + validate: function() { + return true; + }, + + displayErrors: function() { + var errorDiv = $('.error-messages-box', this.$window); + if(errorDiv.length > 0) { + var html = ''; + $.each(this.errors, function() { + html += '
  • ' + this + '
  • '; + }); + errorDiv.html(''); + errorDiv.show(); + console.log('Validation errors:', html); + } + else + throw this.errors; + } + +}); + +var CommitDialog = AbstractDialog.extend({ + _className: 'CommitDialog', + + validate: function() + { + var message = $('textarea.commit-message', this.$window).val(); + + if( message.match(/^\s*$/) ) { + this.errors.push("Message can't be empty."); + return false; + } + + // append refs + $('.related-issues-fields input:checked', this.$window).each(function() { + message += ' refs #' + $(this).val(); + }); + + this.userData.message = message; + return this._super(); + } + }); + + \ No newline at end of file diff --git a/platforma/static/js/views/html.js b/platforma/static/js/views/html.js index cc42be24..d2677d42 100755 --- a/platforma/static/js/views/html.js +++ b/platforma/static/js/views/html.js @@ -8,7 +8,9 @@ var HTMLView = View.extend({ init: function(element, model, parent, template) { var submodel = model.contentModels['html']; this._super(element, submodel, template); - this.parent = parent; + this.parent = parent; + + this.themeEditor = new ThemeEditDialog( $('#theme-edit-dialog') ); this.model .addObserver(this, 'data', this.modelDataChanged.bind(this)) @@ -118,30 +120,6 @@ var HTMLView = View.extend({ console.log( this.model.serializer.serializeToString(this.model.get('data')) ); }, */ - renderPart: function($e, html) { - // exceptions aren't good, but I don't have a better idea right now - if($e.attr('x-annotation-box')) { - // replace the whole annotation - var $p = $e.parent(); - $p.html(html); - var $box = $('*[x-annotation-box]', $p); - $box.append( this.$menuTemplate.clone() ); - - if(this.currentFocused && $p[0] == this.currentFocused[0]) - { - this.currentFocused = $p; - $box.css({ - 'display': 'block' - }); - } - - return; - } - - $e.html(html); - $e.append( this.$menuTemplate.clone() ); - }, - reload: function() { this.model.load(true); }, @@ -185,26 +163,39 @@ var HTMLView = View.extend({ * - this greatly simplifies the whole click check */ - if( $e.hasClass('motyw') ) - { - console.log($e); + if( $e.hasClass('motyw')) + { this.selectTheme($e.attr('theme-class')); return false; } + + if( $e.hasClass('theme-text-list') ) + { + this.selectTheme($e.parent().attr('theme-class')); + return false; + } /* other buttons */ try { + var editable = this.editableFor($e); + if($e.hasClass('delete-button')) - this.deleteElement( this.editableFor($e) ); + this.deleteElement(editable); if($e.hasClass('edit-button')) - this.openForEdit( this.editableFor($e) ); + { + if( editable.hasClass('motyw') ) + this.editTheme(editable); + else + this.openForEdit(editable); + } if($e.hasClass('accept-button')) - this.closeWithSave( this.editableFor($e) ); + this.closeWithSave(editable); if($e.hasClass('reject-button')) - this.closeWithoutSave( this.editableFor($e) ); + this.closeWithoutSave(editable); + } catch(e) { messageCenter.addMessage('error', "wlsave", 'Błąd:' + e.toString()); } @@ -414,13 +405,28 @@ var HTMLView = View.extend({ return true; }, - addTheme: function() + + editTheme: function($element) + { + var themeTextSpan = $('.theme-text-list', $element); + this.themeEditor.setFromString( themeTextSpan.text() ); + + function _editThemeFinish(dialog) { + themeTextSpan.text( dialog.userData.themes.join(', ') ); + }; + + this.themeEditor.show(_editThemeFinish); + }, + + // + // Special stuff for themes + // + addTheme: function() { var selection = window.getSelection(); var n = selection.rangeCount; console.log("Range count:", n); - if(n == 0) { window.alert("Nie zaznaczono żadnego obszaru"); return false; @@ -432,26 +438,25 @@ var HTMLView = View.extend({ return false; } - // from this point, we will assume that the ranges are disjoint - for(var i=0; i < n; i++) - { - var range = selection.getRangeAt(i); - console.log(i, range.startContainer, range.endContainer); - - // verify if the start/end points make even sense - - // they must be inside a x-node (otherwise they will be discarded) - // and the x-node must be a main text - if(! this.verifyThemeInsertPoint(range.startContainer) ) { - window.alert("Motyw nie może się zaczynać w tym miejscu."); - return false; - } + // remember the selected range + var range = selection.getRangeAt(0); + console.log(range.startContainer, range.endContainer); - if(! this.verifyThemeInsertPoint(range.endContainer) ) { - window.alert("Motyw nie może się kończyć w tym miejscu."); - return false; - } + // verify if the start/end points make even sense - + // they must be inside a x-node (otherwise they will be discarded) + // and the x-node must be a main text + if(! this.verifyThemeInsertPoint(range.startContainer) ) { + window.alert("Motyw nie może się zaczynać w tym miejscu."); + return false; + } - + if(! this.verifyThemeInsertPoint(range.endContainer) ) { + window.alert("Motyw nie może się kończyć w tym miejscu."); + return false; + } + + function _addThemeFinish(dialog) + { var date = (new Date()).getTime(); var random = Math.floor(4000000000*Math.random()); var id = (''+date) + '-' + (''+random); @@ -463,11 +468,13 @@ var HTMLView = View.extend({ epoint.setStart(range.endContainer, range.endOffset); var mtag, btag, etag, errors; + var themesStr = dialog.userData.themes.join(', '); - // insert theme-ref + // insert theme-ref mtag = $(''); spoint.insertNode(mtag[0]); - errors = this.model.updateWithWLML(mtag, 'Nowy Motyw'); + errors = this.model.updateWithWLML(mtag, ''+themesStr+''); + if(errors) { messageCenter.addMessage('error', null, 'Błąd przy dodawaniu motywu :' + errors); return false; @@ -483,7 +490,6 @@ var HTMLView = View.extend({ return false; } - etag = $(''); epoint.insertNode(etag[0]); result = this.model.updateWithWLML(etag, ''); @@ -493,11 +499,16 @@ var HTMLView = View.extend({ messageCenter.addMessage('error', null, 'Błąd przy dodawaniu motywu :' + errors); return false; } - } - selection.removeAllRanges(); - }, + selection.removeAllRanges(); + return true; + }; + // show the modal + this.themeEditor.setFromString(''); + this.themeEditor.show(_addThemeFinish.bind(this)); + }, + selectTheme: function(themeId) { var selection = window.getSelection(); @@ -518,5 +529,82 @@ var HTMLView = View.extend({ } }); +var ThemeEditDialog = AbstractDialog.extend({ + + validate: function() + { + var active = $('input.theme-list-item:checked', this.$window); + + if(active.length < 1) { + this.errors.push("You must select at least one theme."); + return false; + } + + console.log("Active:", active); + this.userData.themes = $.makeArray(active.map(function() { return this.value; }) ); + console.log('After validate:', this.userData); + return this._super(); + }, + + setFromString: function(string) + { + var $unmatchedList = $('tbody.unknown-themes', this.$window); + + $("tr:not(.header)", $unmatchedList).remove(); + $unmatchedList.hide(); + + $('input.theme-list-item', this.$window).removeAttr('checked'); + + var unmatched = []; + + $.each(string.split(','), function() { + var name = $.trim(this); + if(!name) return; + + console.log('Selecting:', name); + var checkbox = $("input.theme-list-item[value='"+name+"']", this.$window); + + if(checkbox.length > 0) + checkbox.attr('checked', 'checked'); + else + unmatched.push(name); + }); + + if(unmatched.length > 0) + { + $.each(unmatched, function() { + $(''). + appendTo($unmatchedList); + }); + + $unmatchedList.show(); + } + }, + + displayErrors: function() { + var errorP = $('.error-messages-inline-box', this.$window); + if(errorP.length > 0) { + var html = ''; + $.each(this.errors, function() { + html += '' + this + ''; + }); + errorP.html(html); + errorP.show(); + console.log('Validation errors:', html); + } + else + this._super(); + }, + + reset: function() + { + this._super(); + $('.error-messages-inline-box', this.$window).html('').hide(); + } + + }); + // Register view panels['html'] = HTMLView; \ No newline at end of file diff --git a/platforma/static/xsl/html2wl_client.xsl b/platforma/static/xsl/html2wl_client.xsl index 3ee2f9ef..9e6a8be0 100755 --- a/platforma/static/xsl/html2wl_client.xsl +++ b/platforma/static/xsl/html2wl_client.xsl @@ -22,7 +22,7 @@ - + diff --git a/platforma/static/xsl/wl2html_client.xsl b/platforma/static/xsl/wl2html_client.xsl index 72ac7771..b544a313 100755 --- a/platforma/static/xsl/wl2html_client.xsl +++ b/platforma/static/xsl/wl2html_client.xsl @@ -680,7 +680,7 @@ - + diff --git a/platforma/templates/explorer/editor.html b/platforma/templates/explorer/editor.html index a3ee0450..08f7d41e 100755 --- a/platforma/templates/explorer/editor.html +++ b/platforma/templates/explorer/editor.html @@ -132,7 +132,7 @@ {% endif %} - +