From 0249ff0d913dfaef2a6f5e8518e5736545a23c28 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=C5=81ukasz=20Rekucki?= Date: Wed, 26 Aug 2009 13:42:42 +0200 Subject: [PATCH 1/1] Server-side refactor. Brute-force refresh of HTMLEditor. --- apps/explorer/forms.py | 6 +-- apps/explorer/views.py | 47 ++++++++++------- lib/hg.py | 18 +++++++ project/static/js/editor.js | 50 ++++++++++++++++--- .../explorer/{file_xml.html => editor.html} | 0 project/templates/explorer/file_list.html | 2 +- .../templates/explorer/panels/xmleditor.html | 13 ++++- project/urls.py | 19 ++++--- 8 files changed, 115 insertions(+), 40 deletions(-) rename project/templates/explorer/{file_xml.html => editor.html} (100%) diff --git a/apps/explorer/forms.py b/apps/explorer/forms.py index e648aa5f..f7fcf07e 100644 --- a/apps/explorer/forms.py +++ b/apps/explorer/forms.py @@ -5,11 +5,9 @@ from librarian import dcparser from explorer import models - class BookForm(forms.Form): - text = forms.CharField(widget=forms.Textarea) - commit_message = forms.CharField() - user = forms.CharField() + content = forms.CharField(widget=forms.Textarea) + message = forms.CharField(required=False) class ImageFoldersForm(forms.Form): folders = forms.ChoiceField(required=False) diff --git a/apps/explorer/views.py b/apps/explorer/views.py index ffe5973d..197e6f51 100644 --- a/apps/explorer/views.py +++ b/apps/explorer/views.py @@ -1,5 +1,5 @@ from librarian import html -import hg, urllib2 +import hg, urllib2, time from django.utils import simplejson as json from django.views.generic.simple import direct_to_template @@ -17,54 +17,62 @@ def file_list(request): 'objects': repo.all_files(), }) + +# +# Edit the file +# def file_xml(request, path): if request.method == 'POST': form = forms.BookForm(request.POST) if form.is_valid(): - # save the changes to a local branch -# repo.write_lock() - print request.user -# repo.switch_to_branch(request.user.name) -# repo.add_file(path, form.cleaned_data['text']) - - # add references to comment - issues = _get_issues_for_file(path) - commit_message = _add_references(form.cleaned_data['commit_message'], issues) - print 'Commiting with: ' + commit_message - -# repo.commit(message=commit_message, user=form.cleaned_data['user']) - return HttpResponse( json.dumps({'message': commit_message}) ) + print 'Saving whole text.', request.user.username + def save_action(): + repo.add_file(path, form.cleaned_data['content']) + repo.commit(message='Local save at %s' % time.ctime(), user=request.user.username) + + repo.in_branch('local_'+request.user.username, save_action); + return HttpResponse( json.dumps({'result': 'ok', 'errors': []}) ); else: form = forms.BookForm() - form.fields['text'].initial = repo.get_file(path).data() - - return direct_to_template(request, 'explorer/file_xml.html', extra_context={ - 'hash': path, + form.fields['content'].initial = repo.get_file(path).data() + + return direct_to_template(request, 'explorer/edit_text.html', extra_context={ 'form': form, - 'image_folders_form': forms.ImageFoldersForm(), }) +def file_dc(request, path): + return HttpResponse("N/A") + +# Display the main editor view +def display_editor(request, path): + return direct_to_template(request, 'explorer/editor.html', extra_context={ + 'hash': path, + }) # =============== # = Panel views = # =============== + def xmleditor_panel(request, path): form = forms.BookForm() text = repo.get_file(path).data() return direct_to_template(request, 'explorer/panels/xmleditor.html', extra_context={ + 'fpath': path, 'text': text, }) def gallery_panel(request, path): return direct_to_template(request, 'explorer/panels/gallery.html', extra_context={ + 'fpath': path, 'form': forms.ImageFoldersForm(), }) def htmleditor_panel(request, path): return direct_to_template(request, 'explorer/panels/htmleditor.html', extra_context={ + 'fpath': path, 'html': html.transform(repo.get_file(path).data(), is_file=False), }) @@ -80,6 +88,7 @@ def dceditor_panel(request, path): form = forms.DublinCoreForm(text=text) return direct_to_template(request, 'explorer/panels/dceditor.html', extra_context={ + 'fpath': path, 'form': form, }) diff --git a/lib/hg.py b/lib/hg.py index e785b375..2b885b3c 100644 --- a/lib/hg.py +++ b/lib/hg.py @@ -108,4 +108,22 @@ class Repository(object): # reread keys # self._keys = self.get_persisted_objects_keys() # return node.hex(rev) + + def in_branch(self, branch_name, action): + wlock = self.repo.wlock() + try: + current_branch = self.repo[None].branch() + self.repo.dirstate.setbranch(branch_name) + try: + # do some stuff + action() + finally: + self.repo.dirstate.setbranch(current_branch) + finally: + wlock.release() + + def write_lock(self): + """Returns w write lock to the repository.""" + return self.repo.wlock() + diff --git a/project/static/js/editor.js b/project/static/js/editor.js index 234a436c..4e867b7b 100644 --- a/project/static/js/editor.js +++ b/project/static/js/editor.js @@ -13,7 +13,7 @@ function Panel(panelWrap) { if(self != data) self.otherPanelChanged(event.target); else - self.changed(); + self.markChanged(); return false; }); @@ -24,7 +24,7 @@ Panel.prototype.callHook = function(hookName) { { // arguments.shift(); $.log('calling hook: ', hookName, 'with args: ', arguments); - this.hooks[hookName].apply(this, arguments); + return this.hooks[hookName].apply(this, arguments); } } @@ -32,6 +32,7 @@ Panel.prototype.load = function (url) { $.log('preparing xhr load: ', this.wrap); $(document).trigger('panel:unload', this); var self = this; + self.current_url = url; $.ajax({ url: url, @@ -61,14 +62,30 @@ Panel.prototype.unload = function(event, data) { }; } +Panel.prototype.refresh = function(event, data) { + $('.change-notification', this.wrap).fadeOut(); + $.log('refreshing view for panel ', this.current_url); + this.load(this.current_url); +// if( this.callHook('refresh') ) +} + Panel.prototype.otherPanelChanged = function(other) { $.log('panel ', other, ' changed.'); $('.change-notification', this.wrap).fadeIn(); this.callHook('dirty'); } +Panel.prototype.markChanged = function () { + if(!this.wrap.hasClass('changed') ) // TODO: is this needed ? + this.wrap.addClass('changed'); +} + Panel.prototype.changed = function () { - this.wrap.addClass('changed'); + return this.wrap.hasClass('changed'); +} + +Panel.prototype.unmarkChanged = function () { + this.wrap.removeClass('changed'); } Panel.prototype.saveInfo = function() { @@ -87,6 +104,7 @@ Editor.prototype.setupUI = function() { // set up the UI visually and attach callbacks var self = this; var panelRoot = $('#panels'); + self.rootDiv = panelRoot; panelRoot.makeHorizPanel({}); // TODO: this probably doesn't belong into jQuery panelRoot.css('top', ($('#header').outerHeight() ) + 'px'); @@ -112,6 +130,7 @@ Editor.prototype.loadConfig = function() { Editor.prototype.saveToBranch = function() { var changed_panel = $('.panel-wrap.changed'); + var self = this; $.log('Saving to local branch - panel:', changed_panel); if( changed_panel.length == 0) { @@ -127,19 +146,36 @@ Editor.prototype.saveToBranch = function() { saveInfo = changed_panel.data('ctrl').saveInfo(); $.ajax({ - url: location.href + (saveInfo.part || ''), - dataType: (saveInfo.dataType || 'text'), + url: saveInfo.url, + dataType: 'json', success: function(data, textStatus) { - $.log('Success:', data); + if (data.result != 'ok') + $.log('save errors: ', data.errors) + else + self.refreshPanels(changed_panel); }, error: function(rq, tstat, err) { $.log('save error', rq, tstat, err); }, type: 'POST', - data: (saveInfo.content || '') + data: saveInfo.postData }); }; +Editor.prototype.refreshPanels = function(goodPanel) { + var self = this; + var panels = $('#' + self.rootDiv.attr('id') +' > *.panel-wrap', self.rootDiv.parent()); + + panels.each(function() { + var panel = $(this).data('ctrl'); + $.log(this, panel); + if ( panel.changed() ) + panel.unmarkChanged(); + else + panel.refresh(); + }); +}; + $(function() { editor = new Editor(); diff --git a/project/templates/explorer/file_xml.html b/project/templates/explorer/editor.html similarity index 100% rename from project/templates/explorer/file_xml.html rename to project/templates/explorer/editor.html diff --git a/project/templates/explorer/file_list.html b/project/templates/explorer/file_list.html index 7063d293..bfbafe13 100644 --- a/project/templates/explorer/file_list.html +++ b/project/templates/explorer/file_list.html @@ -3,7 +3,7 @@ {% block maincontent %} {% endblock maincontent %} diff --git a/project/templates/explorer/panels/xmleditor.html b/project/templates/explorer/panels/xmleditor.html index 9186f04a..fe1870ed 100644 --- a/project/templates/explorer/panels/xmleditor.html +++ b/project/templates/explorer/panels/xmleditor.html @@ -81,8 +81,19 @@ panel_hooks = { this.texteditor = null; }, + + refresh: function(hn) { + // TODO + return true; + }, + saveInfo: function(hn, saveInfo) { - var myInfo = {content: this.texteditor.getCode(), dataType: 'xml'}; + var myInfo = { + url: "{% url file_xml fpath %}", + postData: { + content: this.texteditor.getCode() + } + }; $.extend(saveInfo, myInfo); } }; diff --git a/project/urls.py b/project/urls.py index 05fe1b4c..4e672f3e 100644 --- a/project/urls.py +++ b/project/urls.py @@ -2,23 +2,26 @@ from django.conf.urls.defaults import * from django.contrib import admin from django.conf import settings - admin.autodiscover() - +PATH_END = r"(?P[^/]+)$" urlpatterns = patterns('', # Explorer: url(r'^$', 'explorer.views.file_list', name='file_list'), - url(r'^file/(?P[^/]+)/$', 'explorer.views.file_xml', name='file_xml'), + + url(r'^file/text/'+PATH_END, 'explorer.views.file_xml', name='file_xml'), + url(r'^file/dc/'+PATH_END, 'explorer.views.file_dc', name='file_dc'), + url(r'^images/(?P[^/]+)/$', 'explorer.views.folder_images', name='folder_image'), url(r'^images/$', 'explorer.views.folder_images', {'folder': '.'}, name='folder_image_ajax'), # Editor panels - url(r'^editor/(?P[^/]+)/panels/xmleditor/$', 'explorer.views.xmleditor_panel', name='xmleditor_panel'), - url(r'^editor/(?P[^/]+)/panels/gallery/$', 'explorer.views.gallery_panel', name='gallery_panel'), - url(r'^editor/(?P[^/]+)/panels/htmleditor/$', 'explorer.views.htmleditor_panel', name='htmleditor_panel'), - url(r'^editor/(?P[^/]+)/panels/dceditor/$', 'explorer.views.dceditor_panel', name='dceditor_panel'), - + url(r'^editor/panel/xmleditor/'+PATH_END, 'explorer.views.xmleditor_panel', name='xmleditor_panel'), + url(r'^editor/panel/gallery/'+PATH_END, 'explorer.views.gallery_panel', name='gallery_panel'), + url(r'^editor/panel/htmleditor/'+PATH_END, 'explorer.views.htmleditor_panel', name='htmleditor_panel'), + url(r'^editor/panel/dceditor/'+PATH_END, 'explorer.views.dceditor_panel', name='dceditor_panel'), + url(r'^editor/'+PATH_END, 'explorer.views.display_editor', name='editor_view'), + # Admin panel url(r'^admin/doc/', include('django.contrib.admindocs.urls')), url(r'^admin/(.*)', admin.site.root), -- 2.20.1