From 36f6233fd79390ad5af8a1532eac60a0ae57c825 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=C5=81ukasz=20Rekucki?= Date: Sun, 18 Apr 2010 21:25:27 +0200 Subject: [PATCH] * Readonly document view. * Refactored buttons to loop by continuations. * UI state saved in HTML5 localStorage. --- apps/toolbar/templates/toolbar/toolbar.html | 2 +- apps/wiki/models.py | 8 +- .../wiki/templates/wiki/document_details.html | 135 +++--------------- .../templates/wiki/document_details_base.html | 61 ++++++++ .../wiki/document_details_readonly.html | 26 ++++ .../templates/wiki/tabs/gallery_view.html | 26 ++++ .../wiki/{ => tabs}/history_view.html | 2 + .../wiki/tabs/history_view_item.html | 3 + .../templates/wiki/tabs/source_editor.html | 10 ++ .../wiki/tabs/source_editor_item.html | 5 + .../wiki/{ => tabs}/summary_view.html | 0 .../wiki/tabs/summary_view_item.html | 3 + .../templates/wiki/tabs/wysiwyg_editor.html | 17 +++ .../wiki/tabs/wysiwyg_editor_item.html | 3 + apps/wiki/urls.py | 4 + apps/wiki/views.py | 29 +++- lib/vstorage.py | 25 ++-- platforma/compress_settings.py | 3 - platforma/context_processors.py | 1 + platforma/static/css/master.css | 7 +- platforma/static/js/button_scripts.js | 117 +++++++++++---- .../static/js/lib/codemirror/codemirror.js | 6 +- platforma/static/js/wiki/base.js | 55 ++++++- platforma/static/js/wiki/loader.js | 21 ++- platforma/static/js/wiki/loader_readonly.js | 92 ++++++++++++ .../static/js/wiki/view_editor_source.js | 35 +++-- .../static/js/wiki/view_editor_wysiwyg.js | 95 ++++++------ platforma/static/js/wiki/view_gallery.js | 13 +- platforma/static/js/wiki/view_history.js | 16 ++- platforma/static/js/wiki/wikiapi.js | 18 ++- 30 files changed, 590 insertions(+), 248 deletions(-) create mode 100644 apps/wiki/templates/wiki/document_details_base.html create mode 100644 apps/wiki/templates/wiki/document_details_readonly.html create mode 100644 apps/wiki/templates/wiki/tabs/gallery_view.html rename apps/wiki/templates/wiki/{ => tabs}/history_view.html (86%) create mode 100644 apps/wiki/templates/wiki/tabs/history_view_item.html create mode 100644 apps/wiki/templates/wiki/tabs/source_editor.html create mode 100644 apps/wiki/templates/wiki/tabs/source_editor_item.html rename apps/wiki/templates/wiki/{ => tabs}/summary_view.html (100%) create mode 100644 apps/wiki/templates/wiki/tabs/summary_view_item.html create mode 100644 apps/wiki/templates/wiki/tabs/wysiwyg_editor.html create mode 100644 apps/wiki/templates/wiki/tabs/wysiwyg_editor_item.html create mode 100644 platforma/static/js/wiki/loader_readonly.js diff --git a/apps/toolbar/templates/toolbar/toolbar.html b/apps/toolbar/templates/toolbar/toolbar.html index f7a5d7e2..fd8be783 100644 --- a/apps/toolbar/templates/toolbar/toolbar.html +++ b/apps/toolbar/templates/toolbar/toolbar.html @@ -1,5 +1,5 @@ {% load toolbar_tags %} -
+
- -
- - {% include "wiki/history_view.html" %} - {% include "wiki/summary_view.html" %} -
-
+{% block splitter-extra %} + {% include "wiki/tabs/gallery_view.html" %} +{% endblock %} - - -{% include "wiki/save_dialog.html" %} -{% include "wiki/tag_dialog.html" %} +{% block dialogs %} + {% include "wiki/save_dialog.html" %} + {% include "wiki/tag_dialog.html" %} {% endblock %} \ No newline at end of file diff --git a/apps/wiki/templates/wiki/document_details_base.html b/apps/wiki/templates/wiki/document_details_base.html new file mode 100644 index 00000000..576ee1e5 --- /dev/null +++ b/apps/wiki/templates/wiki/document_details_base.html @@ -0,0 +1,61 @@ +{% extends "base.html" %} +{% load toolbar_tags %} +{% block title %}{{ document.name }} - {{ block.super }}{% endblock %} +{% block extrahead %} +{% load compressed %} +{% compressed_css 'detail' %} +{% endblock %} + +{% block extrabody %} + +{% compressed_js 'detail' %} +{% endblock %} + +{% block maincontent %} +
+
+ +

Ładowanie

+
+
+ + + + +
+
+ {% block tabs-content %} {% endblock %} +
+ {% block splitter-extra %} {% endblock %} +
+ +{% block dialogs %} {% endblock %} + +{% endblock %} \ No newline at end of file diff --git a/apps/wiki/templates/wiki/document_details_readonly.html b/apps/wiki/templates/wiki/document_details_readonly.html new file mode 100644 index 00000000..c0ed66ff --- /dev/null +++ b/apps/wiki/templates/wiki/document_details_readonly.html @@ -0,0 +1,26 @@ +{% extends "wiki/document_details_base.html" %} + +{% block editor-class %}readonly{% endblock %} + +{% block extrabody %} +{{ block.super }} + + +{% endblock %} + +{% block tabs-menu %} + {% include "wiki/tabs/wysiwyg_editor_item.html" %} + {% include "wiki/tabs/source_editor_item.html" %} +{% endblock %} + +{% block tabs-content %} + {% include "wiki/tabs/wysiwyg_editor.html" %} + {% include "wiki/tabs/source_editor.html" %} +{% endblock %} + +{% block splitter-extra %} +{% endblock %} + +{% block dialogs %} +{% endblock %} \ No newline at end of file diff --git a/apps/wiki/templates/wiki/tabs/gallery_view.html b/apps/wiki/templates/wiki/tabs/gallery_view.html new file mode 100644 index 00000000..ec5f6e4a --- /dev/null +++ b/apps/wiki/templates/wiki/tabs/gallery_view.html @@ -0,0 +1,26 @@ +
+
+ \ No newline at end of file diff --git a/apps/wiki/templates/wiki/history_view.html b/apps/wiki/templates/wiki/tabs/history_view.html similarity index 86% rename from apps/wiki/templates/wiki/history_view.html rename to apps/wiki/templates/wiki/tabs/history_view.html index 58b54156..6d82785b 100644 --- a/apps/wiki/templates/wiki/history_view.html +++ b/apps/wiki/templates/wiki/tabs/history_view.html @@ -2,6 +2,8 @@
+
diff --git a/apps/wiki/templates/wiki/tabs/history_view_item.html b/apps/wiki/templates/wiki/tabs/history_view_item.html new file mode 100644 index 00000000..3a90ea8e --- /dev/null +++ b/apps/wiki/templates/wiki/tabs/history_view_item.html @@ -0,0 +1,3 @@ +
  • + Historia +
  • diff --git a/apps/wiki/templates/wiki/tabs/source_editor.html b/apps/wiki/templates/wiki/tabs/source_editor.html new file mode 100644 index 00000000..10ca3348 --- /dev/null +++ b/apps/wiki/templates/wiki/tabs/source_editor.html @@ -0,0 +1,10 @@ +{% load toolbar_tags %} +
    + {% if not document_info.readonly %}{% toolbar %}{% endif %} + + +
    \ No newline at end of file diff --git a/apps/wiki/templates/wiki/tabs/source_editor_item.html b/apps/wiki/templates/wiki/tabs/source_editor_item.html new file mode 100644 index 00000000..0382982d --- /dev/null +++ b/apps/wiki/templates/wiki/tabs/source_editor_item.html @@ -0,0 +1,5 @@ +
  • + Kod źródłowy +
  • \ No newline at end of file diff --git a/apps/wiki/templates/wiki/summary_view.html b/apps/wiki/templates/wiki/tabs/summary_view.html similarity index 100% rename from apps/wiki/templates/wiki/summary_view.html rename to apps/wiki/templates/wiki/tabs/summary_view.html diff --git a/apps/wiki/templates/wiki/tabs/summary_view_item.html b/apps/wiki/templates/wiki/tabs/summary_view_item.html new file mode 100644 index 00000000..d973d4d1 --- /dev/null +++ b/apps/wiki/templates/wiki/tabs/summary_view_item.html @@ -0,0 +1,3 @@ +
  • + {{ document_meta.title }} +
  • diff --git a/apps/wiki/templates/wiki/tabs/wysiwyg_editor.html b/apps/wiki/templates/wiki/tabs/wysiwyg_editor.html new file mode 100644 index 00000000..dbf1b6a7 --- /dev/null +++ b/apps/wiki/templates/wiki/tabs/wysiwyg_editor.html @@ -0,0 +1,17 @@ + diff --git a/apps/wiki/templates/wiki/tabs/wysiwyg_editor_item.html b/apps/wiki/templates/wiki/tabs/wysiwyg_editor_item.html new file mode 100644 index 00000000..bd4dc621 --- /dev/null +++ b/apps/wiki/templates/wiki/tabs/wysiwyg_editor_item.html @@ -0,0 +1,3 @@ +
  • + Edytor +
  • diff --git a/apps/wiki/urls.py b/apps/wiki/urls.py index dd0a0df1..c5c08a13 100644 --- a/apps/wiki/urls.py +++ b/apps/wiki/urls.py @@ -19,6 +19,10 @@ urlpatterns = patterns('wiki.views', url(r'^(?P[^/]+)/tags$', 'document_add_tag', name="wiki_add_tag"), url(r'^(?P[^/]+)/publish$', 'document_publish'), + + url(r'^(?P[^/]+)/readonly$', + 'document_detail_readonly', name="wiki_details_readonly"), + url(r'^(?P[^/]+)$', 'document_detail', name="wiki_details"), ) diff --git a/apps/wiki/views.py b/apps/wiki/views.py index 9b7d8076..46f0665f 100644 --- a/apps/wiki/views.py +++ b/apps/wiki/views.py @@ -3,7 +3,7 @@ import os from django.conf import settings from django.views.generic.simple import direct_to_template -from django.views.decorators.http import require_POST +from django.views.decorators.http import require_POST, require_GET from django.core.urlresolvers import reverse from wiki.helpers import JSONResponse, JSONFormInvalid, JSONServerError, ajax_require_permission from django import http @@ -70,6 +70,33 @@ def document_detail(request, name, template_name='wiki/document_details.html'): }) +@require_GET +def document_detail_readonly(request, name, template_name='wiki/document_details_readonly.html'): + storage = getstorage() + + try: + revision = request.GET['revision'] + document = storage.get(name, revision) + except (KeyError, DocumentNotFound) as e: + raise http.Http404 + + access_time = datetime.now() + last_documents = request.session.get("wiki_last_docs", {}) + last_documents[name] = access_time + + if len(last_documents) > MAX_LAST_DOCS: + oldest_key = min(last_documents, key=last_documents.__getitem__) + del last_documents[oldest_key] + request.session['wiki_last_docs'] = last_documents + + return direct_to_template(request, template_name, extra_context={ + 'document': document, + 'document_name': document.name, + 'document_info': dict(document.info(), readonly=True), + 'document_meta': document.meta, + }) + + def document_create_missing(request, name): storage = getstorage() diff --git a/lib/vstorage.py b/lib/vstorage.py index 24d5ec9d..82151da7 100644 --- a/lib/vstorage.py +++ b/lib/vstorage.py @@ -269,10 +269,10 @@ class VersionedStorage(object): def page_text(self, title, revision=None): """Read unicode text of a page.""" ctx = self._find_filectx(title, revision) - + if ctx is None: raise DocumentNotFound(title) - + return ctx.data().decode(self.charset, 'replace'), ctx.filerev() def page_text_by_tag(self, title, tag): @@ -297,20 +297,19 @@ class VersionedStorage(object): return st_ino, st_size, st_mtime @with_working_copy_locked - def page_meta(self, title): + def page_meta(self, title, revision=None): """Get page's revision, date, last editor and his edit comment.""" - if not title in self: - raise DocumentNotFound(title) + fctx = self._find_filectx(title, revision) - filectx_tip = self._find_filectx(title) - if filectx_tip is None: + if fctx is None: raise DocumentNotFound(title) - rev = filectx_tip.filerev() - filectx = filectx_tip.filectx(rev) - date = datetime.datetime.fromtimestamp(filectx.date()[0]) - author = filectx.user().decode("utf-8", 'replace') - comment = filectx.description().decode("utf-8", 'replace') - return rev, date, author, comment + + return { + "revision": fctx.filerev(), + "date": datetime.datetime.fromtimestamp(fctx.date()[0]), + "author": fctx.user().decode("utf-8", 'replace'), + "comment": fctx.description().decode("utf-8", 'replace'), + } def repo_revision(self): return self.repo['tip'].rev() diff --git a/platforma/compress_settings.py b/platforma/compress_settings.py index ab72329f..fa416c41 100644 --- a/platforma/compress_settings.py +++ b/platforma/compress_settings.py @@ -50,9 +50,6 @@ COMPRESS_JS = { 'js/wiki/view_editor_wysiwyg.js', 'js/wiki/view_gallery.js', 'js/wiki/view_column_diff.js', - - # bootstrap - 'js/wiki/loader.js', ), 'output_filename': 'compressed/detail_scripts_?.js', }, diff --git a/platforma/context_processors.py b/platforma/context_processors.py index 4492af70..813d8f36 100644 --- a/platforma/context_processors.py +++ b/platforma/context_processors.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 + def settings(request): from django.conf import settings return { diff --git a/platforma/static/css/master.css b/platforma/static/css/master.css index 517d863e..ae742667 100644 --- a/platforma/static/css/master.css +++ b/platforma/static/css/master.css @@ -43,10 +43,14 @@ body { overflow: hidden; } +#editor.readonly .editor { + right: 0px; +} + #html-view { overflow: auto; position: absolute; - top: 30px; + top: 33px; bottom: 0; left: 0; right: 0; @@ -226,6 +230,7 @@ p { margin: 0;} height: 100%; width: 100%; } + #content { height: 100%; width: 100%; diff --git a/platforma/static/js/button_scripts.js b/platforma/static/js/button_scripts.js index a208ca1f..0d38b004 100644 --- a/platforma/static/js/button_scripts.js +++ b/platforma/static/js/button_scripts.js @@ -26,12 +26,29 @@ })(); +function nblck_each(array, body, after) { + $.each(array, function(i) { + body(this, i); + }); + + after(); +}; + +function nblck_map(array, func, after) { + var acc = []; + + nblck_each(array, function(elem, index) { + acc.push(func(elem, index)); + }, function(){ + after(acc); + }); +}; function ScriptletCenter() { this.scriptlets = {}; - this.scriptlets['insert_tag'] = function(context, params) + this.scriptlets['insert_tag'] = function(context, params, done) { var text = this.XMLEditorSelectedText(context); var start_tag = '<'+params.tag; @@ -86,9 +103,11 @@ function ScriptletCenter() } } catch(e) {} + done(); }.bind(this); - this.scriptlets['lineregexp'] = function(context, params) { + this.scriptlets['lineregexp'] = function(context, params, done) { + var self = this; var exprs = $.map(params.exprs, function(expr) { var opts = "g"; @@ -102,27 +121,34 @@ function ScriptletCenter() var partial = true; var text = this.XMLEditorSelectedText(context); - if(!text) return; + if(!text) return done(); var changed = 0; var lines = text.split('\n'); - lines = $.map(lines, function(line) { + + nblck_map(lines, function(line, index) { var old_line = line; $(exprs).each(function() { var expr = this; line = line.replace(expr.rx, expr.repl); }); + $progress.html(index); + if(old_line != line) changed += 1; return line; - }); + }, function(newlines) { + if(changed > 0) { + self.XMLEditorReplaceSelectedText(context, newlines.join('\n') ); + }; - if(changed > 0) { - this.XMLEditorReplaceSelectedText(context, lines.join('\n') ); - } + done(); + }); }.bind(this); - this.scriptlets['fulltextregexp'] = function(context, params) { + this.scriptlets['fulltextregexp'] = function(context, params, done) { + var self = this; + var exprs = $.map(params.exprs, function(expr) { var opts = "mg"; if(expr.length > 2) { @@ -135,27 +161,40 @@ function ScriptletCenter() }); var text = this.XMLEditorSelectedText(context); - if(!text) return; + if(!text) return done(); var original = text; - $(exprs).each(function() { - text = text.replace(this.rx, this.repl); - }); - if( original != text) { - this.XMLEditorReplaceSelectedText(context, text); - } + nblck_each(exprs, function(expr, index) { + $progress.html(600 + index); + text = text.replace(expr.rx, expr.repl); + }, function() { + if( original != text) { + self.XMLEditorReplaceSelectedText(context, text); + } + + done(); + }); }.bind(this); - this.scriptlets['macro'] = function(context, params) { + this.scriptlets['macro'] = function(context, params, done) { var self = this; - - $(params).each(function() { - $.log(this[0], this[1]); - self.scriptlets[this[0]](context, this[1]); - }); + var i = 0; + + function next() { + if (i < params.length) { + var e = params[i]; + i = i + 1; + self.scriptlets[e[0]](context, e[1], next); + } + else { + done(); + } + }; + + next(); }.bind(this); - this.scriptlets['lowercase'] = function(context, params) + this.scriptlets['lowercase'] = function(context, params, done) { var text = this.XMLEditorSelectedText(context); @@ -179,10 +218,12 @@ function ScriptletCenter() } if(repl != text) this.XMLEditorReplaceSelectedText(context, repl); + + done(); }.bind(this); - this.scriptlets["insert_stanza"] = function(context, params) { + this.scriptlets["insert_stanza"] = function(context, params, done) { var text = this.XMLEditorSelectedText(context); if(text) { @@ -209,19 +250,35 @@ function ScriptletCenter() this.XMLEditorMoveCursorForward(context, params.tag.length + 2); } + done(); }.bind(this); } -ScriptletCenter.prototype.XMLEditorSelectedText = function(panel) { - return panel.selection(); +ScriptletCenter.prototype.callInteractive = function(opts) { + $progress = $('Executing script'); + var self = this; + + $.blockUI({ + message: $progress, + + }); + + + self.scriptlets[opts.action](opts.context, opts.extra, function(){ + $.unblockUI(); // done + }); +} + +ScriptletCenter.prototype.XMLEditorSelectedText = function(editor) { + + return editor.selection(); }; -ScriptletCenter.prototype.XMLEditorReplaceSelectedText = function(panel, replacement) +ScriptletCenter.prototype.XMLEditorReplaceSelectedText = function(editor, replacement) { - panel.replaceSelection(replacement); - // Tell XML view that it's data has changed - // panel.contentView.editorDataChanged(); + $progress.html("Replacing text"); + editor.replaceSelection(replacement); }; ScriptletCenter.prototype.XMLEditorMoveCursorForward = function(panel, n) { diff --git a/platforma/static/js/lib/codemirror/codemirror.js b/platforma/static/js/lib/codemirror/codemirror.js index 10202174..8c62dab9 100644 --- a/platforma/static/js/lib/codemirror/codemirror.js +++ b/platforma/static/js/lib/codemirror/codemirror.js @@ -80,7 +80,7 @@ var CodeMirror = (function(){ nums = frame.nextSibling, scroller = nums.firstChild; var nextNum = 1; - + function update() { var diff = 20 + Math.max(doc.body.offsetHeight, frame.offsetHeight) - scroller.offsetHeight; for (var n = Math.ceil(diff / 10); n > 0; n--) { @@ -90,10 +90,10 @@ var CodeMirror = (function(){ } nums.scrollTop = doc.body.scrollTop || doc.documentElement.scrollTop || 0; } - + update(); win.addEventHandler(win, "scroll", update); - win.addEventHandler(win, "resize", update); + win.addEventHandler(win, "resize", update); } function CodeMirror(place, options) { diff --git a/platforma/static/js/wiki/base.js b/platforma/static/js/wiki/base.js index 40a29426..523ad96e 100644 --- a/platforma/static/js/wiki/base.js +++ b/platforma/static/js/wiki/base.js @@ -4,9 +4,48 @@ $.wiki = { perspectives: {}, - cls: {} + cls: {}, + state: { + "version": 1, + "perspectives": { + "ScanGalleryPerspective": { + "show": true, + "page": 1 + }, + "CodeMirrorPerspective": {} + /* + "VisualPerspective": {}, + "HistoryPerspective": {}, + "SummaryPerspective": {} + */ + } + } }; + $.wiki.loadConfig = function() { + if(!window.localStorage) + return; + + try { + var value = window.localStorage.getItem(CurrentDocument.id) || "{}"; + var config = JSON.parse(value); + + if (config.version == $.wiki.state.version) { + $.wiki.state.perspectives = $.extend($.wiki.state.perspectives, config.perspectives); + } + } catch(e) { + console.log("Failed to load config, using default."); + } + + console.log("Loaded:", $.wiki.state, $.wiki.state.version); + }; + + $(window).bind('unload', function() { + if(window.localStorage) + window.localStorage.setItem(CurrentDocument.id, JSON.stringify($.wiki.state)); + }) + + $.wiki.activePerspective = function() { return this.perspectives[$("#tabs li.active").attr('id')]; }; @@ -76,8 +115,8 @@ $old.each(function(){ $(this).removeClass('active'); - $('#' + $(this).attr('data-ui-related')).hide(); self.perspectives[$(this).attr('id')].onExit(); + $('#' + $(this).attr('data-ui-related')).hide(); }); /* show new */ @@ -108,6 +147,10 @@ options.callback.call(this); }; + $.wiki.Perspective.prototype.config = function() { + return $.wiki.state.perspectives[this.perspective_id]; + } + $.wiki.Perspective.prototype.toString = function() { return this.perspective_id; }; @@ -118,16 +161,16 @@ $.wiki.Perspective.prototype.onEnter = function () { // called when perspective in initialized - if (this.perspective_id) { + if (!this.noupdate_hash_onenter) { document.location.hash = '#' + this.perspective_id; } - - console.log(document.location.hash); }; $.wiki.Perspective.prototype.onExit = function () { // called when user switches to another perspective - document.location.hash = ''; + if (!this.noupdate_hash_onenter) { + document.location.hash = ''; + } }; $.wiki.Perspective.prototype.destroy = function() { diff --git a/platforma/static/js/wiki/loader.js b/platforma/static/js/wiki/loader.js index 34305d71..a4414027 100644 --- a/platforma/static/js/wiki/loader.js +++ b/platforma/static/js/wiki/loader.js @@ -22,7 +22,7 @@ $(function() function initialize() { gallery = new $.wiki.ScanGalleryPerspective({ - doc: CurrentDocument + doc: CurrentDocument, id: "ScanGalleryPerspective" }); $(document).keydown(function(event) { @@ -65,6 +65,7 @@ $(function() $('.vsplitbar').toggle( function() { + $.wiki.state.perspectives.ScanGalleryPerspective.show = true; $('#side-gallery').show(); $('.vsplitbar').css('right', 480).addClass('.active'); $('#editor .editor').css('right', 510); @@ -72,6 +73,7 @@ $(function() gallery.onEnter(); }, function() { + $.wiki.state.perspectives.ScanGalleryPerspective.show = false; $('#side-gallery').hide(); $('.vsplitbar').css('right', 0).removeClass('active'); $('#editor .editor').css('right', 30); @@ -80,6 +82,9 @@ $(function() } ); + if($.wiki.state.perspectives.ScanGalleryPerspective.show) + $('.vsplitbar').trigger('click'); + window.onbeforeunload = function(e) { if($.wiki.isDirty()) { e.returnValue = "Na stronie mogą być nie zapisane zmiany."; @@ -102,17 +107,24 @@ $(function() console.log("Fetch success"); $('#loading-overlay').fadeOut(); var active_tab = document.location.hash || DEFAULT_PERSPECTIVE; - var $active = $("#tabs " + active_tab); - $active.trigger("click"); + if(active_tab == "#ScanGalleryPerspective") + active_tab = DEFAULT_PERSPECTIVE; + + console.log("Initial tab is:", active_tab) + $.wiki.switchToTab(active_tab); }, failure: function() { $('#loading-overlay').fadeOut(); alert("FAILURE"); } - }); + }); }; /* end of initialize() */ + + /* Load configuration */ + $.wiki.loadConfig(); + var initAll = function(a, f) { if (a.length == 0) return f(); @@ -125,6 +137,7 @@ $(function() }); }; + /* * Initialize all perspectives */ diff --git a/platforma/static/js/wiki/loader_readonly.js b/platforma/static/js/wiki/loader_readonly.js new file mode 100644 index 00000000..c22e9d7a --- /dev/null +++ b/platforma/static/js/wiki/loader_readonly.js @@ -0,0 +1,92 @@ +if (!window.console) { + window.console = { + log: function(){ + } + } +} + + +DEFAULT_PERSPECTIVE = "#VisualPerspective"; + +$(function() +{ + var tabs = $('ol#tabs li'); + var gallery = null; + + CurrentDocument = new $.wikiapi.WikiDocument("document-meta"); + $.blockUI.defaults.baseZ = 10000; + + function initialize() + { + $('.editor').hide(); + + /* + * TABS + */ + $('#tabs li').live('click', function(event, callback) { + $.wiki.switchToTab(this); + }); + + $('#tabs li > .tabclose').live('click', function(event, callback) { + var $tab = $(this).parent(); + + if($tab.is('.active')) + $.wiki.switchToTab(DEFAULT_PERSPECTIVE); + + var p = $.wiki.perspectiveForTab($tab); + p.destroy(); + return false; + }); + + $(window).resize(function(){ + $('iframe').height($(window).height() - $('#tabs').outerHeight() - $('#source-editor .toolbar').outerHeight()); + }); + + $(document).bind('wlapi_document_changed', function(event, doc) { + try { + $('#document-revision').text(doc.revision); + } catch(e) { + console.log("Failed handler", e); + } + }); + + CurrentDocument.fetch({ + success: function(){ + console.log("Fetch success"); + $('#loading-overlay').fadeOut(); + var active_tab = document.location.hash || DEFAULT_PERSPECTIVE; + + $(window).resize(); + + console.log("Initial tab is:", active_tab) + $.wiki.switchToTab(active_tab); + }, + failure: function() { + $('#loading-overlay').fadeOut(); + alert("FAILURE"); + } + }); + }; /* end of initialize() */ + + /* Load configuration */ + $.wiki.loadConfig(); + + var initAll = function(a, f) { + if (a.length == 0) return f(); + + $.wiki.initTab({ + tab: a.pop(), + doc: CurrentDocument, + callback: function(){ + initAll(a, f); + } + }); + }; + + + /* + * Initialize all perspectives + */ + initAll( $.makeArray($('ol#tabs li')), initialize); + console.log(location.hash); +}); \ No newline at end of file diff --git a/platforma/static/js/wiki/view_editor_source.js b/platforma/static/js/wiki/view_editor_source.js index 0acd2cd9..a0a2e69a 100644 --- a/platforma/static/js/wiki/view_editor_source.js +++ b/platforma/static/js/wiki/view_editor_source.js @@ -20,6 +20,7 @@ width: "100%", tabMode: 'spaces', indentUnit: 0, + readOnly: CurrentDocument.readonly || false, initCallback: function(){ self.codemirror.grabKeys(function(event) { @@ -48,7 +49,11 @@ $('#source-editor .toolbar button').click(function(event){ event.preventDefault(); var params = eval("(" + $(this).attr('data-ui-action-params') + ")"); - scriptletCenter.scriptlets[$(this).attr('data-ui-action')](self.codemirror, params); + scriptletCenter.callInteractive({ + action: $(this).attr('data-ui-action'), + context: self.codemirror, + extra: params + }); }); $('.toolbar select').change(function(event){ @@ -62,10 +67,10 @@ $('.toolbar select').change(); console.log("Initialized CodeMirror"); - + // textarea is no longer needed $('codemirror_placeholder').remove(); - + old_callback.call(self); } }); @@ -78,33 +83,39 @@ CodeMirrorPerspective.prototype = new $.wiki.Perspective(); CodeMirrorPerspective.prototype.freezeState = function() { + this.config().position = this.codemirror.win.scrollY || 0; + }; + CodeMirrorPerspective.prototype.unfreezeState = function () { + this.codemirror.win.scroll(0, this.config().position || 0); }; - - CodeMirrorPerspective.prototype.onEnter = function(success, failure) { $.wiki.Perspective.prototype.onEnter.call(this); console.log('Entering', this.doc); this.codemirror.setCode(this.doc.text); - + /* fix line numbers bar */ var $nums = $('.CodeMirror-line-numbers'); var barWidth = $nums.width(); - - $(this.codemirror.frame).css('margin-left', barWidth); - $nums.css('left', -barWidth); - - $(this.codemirror.frame.contentWindow).trigger('resize'); + + $(this.codemirror.frame.contentDocument.body).css('padding-left', barWidth); + // $nums.css('left', -barWidth); + + $(window).resize(); + this.unfreezeState(this._uistate); + if(success) success(); } CodeMirrorPerspective.prototype.onExit = function(success, failure) { - $.wiki.Perspective.prototype.onExit.call(this); + this.freezeState(); + $.wiki.Perspective.prototype.onExit.call(this); console.log('Exiting', this.doc); this.doc.setText(this.codemirror.getCode()); + if(success) success(); } diff --git a/platforma/static/js/wiki/view_editor_wysiwyg.js b/platforma/static/js/wiki/view_editor_wysiwyg.js index 177c1133..2ae1a8dd 100644 --- a/platforma/static/js/wiki/view_editor_wysiwyg.js +++ b/platforma/static/js/wiki/view_editor_wysiwyg.js @@ -232,19 +232,19 @@ }); } - if ($origin.is('.motyw')) { - $('.delete-button', $overlay).click(function() { - if (window.confirm("Czy jesteś pewien, że chcesz usunąć ten motyw ?")) { - $('[theme-class=' + $origin.attr('theme-class') + ']').remove(); - $overlay.remove(); - $(document).unbind('click.blur-overlay'); - return false; - }; - }); - } - else { - $('.delete-button', $overlay).hide(); - } + if ($origin.is('.motyw')) { + $('.delete-button', $overlay).click(function(){ + if (window.confirm("Czy jesteś pewien, że chcesz usunąć ten motyw ?")) { + $('[theme-class=' + $origin.attr('theme-class') + ']').remove(); + $overlay.remove(); + $(document).unbind('click.blur-overlay'); + return false; + }; + }); + } + else { + $('.delete-button', $overlay).hide(); + } var serializer = new XMLSerializer(); @@ -304,49 +304,52 @@ var old_callback = options.callback; - options.callback = function() { + options.callback = function(){ var element = $("#html-view"); var button = $(''); - $('#html-view').bind('mousemove', function(event){ - var editable = $(event.target).closest('*[x-editable]'); - $('.active', element).not(editable).removeClass('active').children('.edit-button').remove(); + if (!CurrentDocument.readonly) { + $('#html-view').bind('mousemove', function(event){ + var editable = $(event.target).closest('*[x-editable]'); + $('.active', element).not(editable).removeClass('active').children('.edit-button').remove(); - if (!editable.hasClass('active')) { - editable.addClass('active').append(button); - } - if (editable.is('.annotation-inline-box')) { - $('*[x-annotation-box]', editable).css({ - position: 'absolute', - left: event.clientX - editable.offset().left + 5, - top: event.clientY - editable.offset().top + 5 - }).show(); - } - else { - $('*[x-annotation-box]').hide(); - } - }); + if (!editable.hasClass('active')) { + editable.addClass('active').append(button); + } + if (editable.is('.annotation-inline-box')) { + $('*[x-annotation-box]', editable).css({ + position: 'absolute', + left: event.clientX - editable.offset().left + 5, + top: event.clientY - editable.offset().top + 5 + }).show(); + } + else { + $('*[x-annotation-box]').hide(); + } + }); - $('.motyw').live('click', function(){ - selectTheme($(this).attr('theme-class')); - }); + $('#insert-annotation-button').click(function(){ + addAnnotation(); + return false; + }); - $('#insert-annotation-button').click(function(){ - addAnnotation(); - return false; - }); + $('#insert-theme-button').click(function(){ + addTheme(); + return false; + }); - $('#insert-theme-button').click(function(){ - addTheme(); - return false; - }); + $('.edit-button').live('click', function(event){ + event.preventDefault(); + openForEdit($(this).parent()); + }); + + } - $('.edit-button').live('click', function(event){ - event.preventDefault(); - openForEdit($(this).parent()); + $('.motyw').live('click', function(){ + selectTheme($(this).attr('theme-class')); }); - old_callback.call(this); + old_callback.call(this); }; $.wiki.Perspective.call(this, options); diff --git a/platforma/static/js/wiki/view_gallery.js b/platforma/static/js/wiki/view_gallery.js index 69761ca3..aa39e15f 100644 --- a/platforma/static/js/wiki/view_gallery.js +++ b/platforma/static/js/wiki/view_gallery.js @@ -44,6 +44,8 @@ function ScanGalleryPerspective(options){ var old_callback = options.callback || function() { }; + this.noupdate_hash_onenter = true; + options.callback = function(){ var self = this; @@ -92,6 +94,8 @@ self.imageMoveStart.apply(self, arguments); }); + + old_callback.call(this); }; @@ -136,6 +140,7 @@ ScanGalleryPerspective.prototype.setPage = function(newPage){ newPage = normalizeNumber(newPage, this.doc.galleryImages.length); this.$numberInput.val(newPage); + this.config().page = newPage; $('.gallery-image img', this.$element).attr('src', this.doc.galleryImages[newPage - 1]); }; @@ -222,7 +227,8 @@ this.doc.refreshGallery({ success: function(doc, data){ self.$image.show(); - self.setPage( self.$numberInput.val() ); + console.log("gconfig:", self.config().page ); + self.setPage( self.config().page ); $('.error_message', self.$element).hide(); if(success) success(); @@ -233,8 +239,13 @@ if(failure) failure(); } }); + }; + ScanGalleryPerspective.prototype.onExit = function(success, failure) { + + }; + $.wiki.ScanGalleryPerspective = ScanGalleryPerspective; })(jQuery); \ No newline at end of file diff --git a/platforma/static/js/wiki/view_history.js b/platforma/static/js/wiki/view_history.js index 5a3e8131..b4a9dd8a 100644 --- a/platforma/static/js/wiki/view_history.js +++ b/platforma/static/js/wiki/view_history.js @@ -15,6 +15,20 @@ self.showTagForm(); }); + $('#open-preview-button').click(function(event) { + var selected = $('#changes-list .entry.selected'); + + if (selected.length != 1) { + window.alert("Wybierz dokładnie *jedną* wersję."); + return; + } + + var version = parseInt($("*[data-stub-value='version']", selected[0]).text()); + window.open($(this).attr('data-basehref') + "?revision=" + version); + + event.preventDefault(); + }); + $('#changes-list .entry').live('click', function(){ var $this = $(this); if ($this.hasClass('selected')) @@ -99,7 +113,7 @@ var selected = $('#changes-list .entry.selected'); if (selected.length != 1) { - window.alert("Musisz dokładnie jedną wersję do oznaczenia."); + window.alert("Musisz zaznaczyć dokładnie jedną wersję."); return; } diff --git a/platforma/static/js/wiki/wikiapi.js b/platforma/static/js/wiki/wikiapi.js index d0ac5dce..27ab97e2 100644 --- a/platforma/static/js/wiki/wikiapi.js +++ b/platforma/static/js/wiki/wikiapi.js @@ -55,7 +55,10 @@ function WikiDocument(element_id) { var meta = $('#' + element_id); this.id = meta.attr('data-document-name'); + this.revision = $("*[data-key='revision']", meta).text(); + this.readonly = !!$("*[data-key='readonly']", meta).text(); + this.galleryLink = $("*[data-key='gallery']", meta).text(); this.galleryImages = []; this.text = null; @@ -77,6 +80,7 @@ $.ajax({ method: "GET", url: reverse("ajax_document_text", self.id), + data: {"revision": self.revision}, dataType: 'json', success: function(data) { var changed = false; @@ -147,6 +151,7 @@ } }); }; + /* * Fetch gallery */ @@ -168,6 +173,7 @@ } }); }; + /* * Set document's text */ @@ -175,6 +181,7 @@ this.text = text; this.has_local_changes = true; }; + /* * Set document's gallery link */ @@ -182,6 +189,7 @@ this.galleryLink = gallery; this.has_local_changes = true; }; + /* * Save text back to the server */ @@ -199,7 +207,7 @@ $.each(params['form'].serializeArray(), function() { data[this.name] = this.value; }); - + var metaComment = '\n' @@ -237,6 +245,7 @@ } }); }; /* end of save() */ + WikiDocument.prototype.publish = function(params) { params = $.extend({}, noops, params); var self = this; @@ -269,12 +278,12 @@ var data = { "addtag-id": self.id, }; - + /* unpack form */ $.each(params.form.serializeArray(), function() { data[this.name] = this.value; }); - + $.ajax({ url: reverse("ajax_document_addtag", self.id), type: "POST", @@ -298,11 +307,10 @@ "__all__": ["Nie udało się - błąd serwera."] }); }; - }; - } }); }; + $.wikiapi.WikiDocument = WikiDocument; })(jQuery); -- 2.20.1