* Readonly document view.
authorŁukasz Rekucki <lrekucki@gmail.com>
Sun, 18 Apr 2010 19:25:27 +0000 (21:25 +0200)
committerŁukasz Rekucki <lrekucki@gmail.com>
Sun, 18 Apr 2010 19:25:27 +0000 (21:25 +0200)
* Refactored buttons to loop by continuations.
* UI state saved in HTML5 localStorage.

32 files changed:
apps/toolbar/templates/toolbar/toolbar.html
apps/wiki/models.py
apps/wiki/templates/wiki/document_details.html
apps/wiki/templates/wiki/document_details_base.html [new file with mode: 0644]
apps/wiki/templates/wiki/document_details_readonly.html [new file with mode: 0644]
apps/wiki/templates/wiki/history_view.html [deleted file]
apps/wiki/templates/wiki/summary_view.html [deleted file]
apps/wiki/templates/wiki/tabs/gallery_view.html [new file with mode: 0644]
apps/wiki/templates/wiki/tabs/history_view.html [new file with mode: 0644]
apps/wiki/templates/wiki/tabs/history_view_item.html [new file with mode: 0644]
apps/wiki/templates/wiki/tabs/source_editor.html [new file with mode: 0644]
apps/wiki/templates/wiki/tabs/source_editor_item.html [new file with mode: 0644]
apps/wiki/templates/wiki/tabs/summary_view.html [new file with mode: 0644]
apps/wiki/templates/wiki/tabs/summary_view_item.html [new file with mode: 0644]
apps/wiki/templates/wiki/tabs/wysiwyg_editor.html [new file with mode: 0644]
apps/wiki/templates/wiki/tabs/wysiwyg_editor_item.html [new file with mode: 0644]
apps/wiki/urls.py
apps/wiki/views.py
lib/vstorage.py
platforma/compress_settings.py
platforma/context_processors.py
platforma/static/css/master.css
platforma/static/js/button_scripts.js
platforma/static/js/lib/codemirror/codemirror.js
platforma/static/js/wiki/base.js
platforma/static/js/wiki/loader.js
platforma/static/js/wiki/loader_readonly.js [new file with mode: 0644]
platforma/static/js/wiki/view_editor_source.js
platforma/static/js/wiki/view_editor_wysiwyg.js
platforma/static/js/wiki/view_gallery.js
platforma/static/js/wiki/view_history.js
platforma/static/js/wiki/wikiapi.js

index f7a5d7e..fd8be78 100644 (file)
@@ -1,5 +1,5 @@
 {% load toolbar_tags %}
-<div class="toolbar" xmlns:ui="http://nowoczesnapolska.org.pl/platforma/ui">
+<div class="toolbar">
     <select name="button_group" id="toolbar-button-group-select" size="1">
         {% for group in toolbar_groups %}
         <option value="{{ group.slug }}" {% if forloop.first %}selected="selected"{% endif %}>{{ group.name }}</option>
index f35c307..f800481 100644 (file)
@@ -62,9 +62,6 @@ class DocumentStorage(object):
     def history(self, title):
         return list(self.vstorage.page_history(title))
 
-    def _info(self, name):
-        return self.vstorage.page_meta(name)
-
 
 class Document(object):
     META_REGEX = re.compile(r'\s*<!--\s(.*?)-->', re.DOTALL | re.MULTILINE)
@@ -108,10 +105,7 @@ class Document(object):
         return result
 
     def info(self):
-        return dict(zip(
-            ('revision', 'last_update', 'last_comitter', 'commit_message'),
-            self.storage._info(self.name),
-        ))
+        return self.storage.vstorage.page_meta(self.name, self.revision)
 
 
 def getstorage():
index 22e07e1..81d76dd 100644 (file)
-{% extends "base.html" %}
-{% load toolbar_tags %}
-{% block title %}{{ document.name }} - {{ block.super }}{% endblock %}
-{% block extrahead %}
-{% load compressed %}
-{% compressed_css 'detail' %}
-{% endblock %}
+{% extends "wiki/document_details_base.html" %}
 
 {% block extrabody %}
-<script type="text/javascript" charset="utf-8">
-    var STATIC_URL = '{{STATIC_URL}}';
-</script>
+{{ block.super }}
 <script src="{{STATIC_URL}}js/lib/codemirror/codemirror.js" type="text/javascript" charset="utf-8">
 </script>
-{% compressed_js 'detail' %}
+<script src="{{STATIC_URL}}js/wiki/loader.js" type="text/javascript" charset="utf-8"> </script>
 {% endblock %}
-{% block maincontent %}
-<div id="loading-overlay">
-    <div id="loading-message">
-        <img src="{{STATIC_URL}}img/spinner.gif" />
-        <p>
-            Ładowanie
-        </p>
-    </div>
-</div>
-
-<div id="document-meta"
-       data-document-name="{{ document.name }}" style="display:none">
-
-       {% for k, v in document_meta.items %}
-               <span data-key="{{ k }}">{{ v }}</span>
-       {% endfor %}
-</div>
 
-<div id="header">
-    <h1><a href="{% url wiki.views.document_list %}">Platforma</a></h1>
-    <div id="tools">
-        <a href="{{ REDMINE_URL }}projects/wl-publikacje/wiki/Pomoc" target="_blank">Pomoc</a>
-        | {% include "registration/head_login.html" %}
-        | Wersja: <span id="document-revision">unknown</span>
-        |
-        <button style="margin-left: 6px" id="save-button">
-            Zapisz
-        </button>
-    </div>
-    <ol id="tabs">
-               <li id="SummaryPerspective"
-                       data-ui-related="summary-view-editor"
-                       data-ui-jsclass="SummaryPerspective">
-            <span>{{ document_meta.title }}</span>
-        </li>
-
-        <li id="VisualPerspective"
-                       data-ui-related="simple-editor"
-                       data-ui-jsclass="VisualPerspective">
-            <span>Edytor</span>
-        </li>
+{% block tabs-menu %}
+    {% include "wiki/tabs/summary_view_item.html" %}
+    {% include "wiki/tabs/wysiwyg_editor_item.html" %}
+       {% include "wiki/tabs/history_view_item.html" %}
+       {% include "wiki/tabs/source_editor_item.html" %}
+{% endblock %}
 
-               <li id="HistoryPerspective"
-                       data-ui-related="history-view-editor"
-                       data-ui-jsclass="HistoryPerspective">
-            <span>Historia</span>
-        </li>
+{% block tabs-content %}
+    {% include "wiki/tabs/summary_view.html" %}
+    {% include "wiki/tabs/wysiwyg_editor.html" %}
+       {% include "wiki/tabs/history_view.html" %}
+       {% include "wiki/tabs/source_editor.html" %}
+{% endblock %}
 
-               <li id="CodeMirrorPerspective"
-                       data-ui-related="source-editor"
-                       data-ui-jsclass="CodeMirrorPerspective">
-            <span>Kod źródłowy</span>
-        </li>
-    </ol>
-</div>
-<div id="splitter">
-    <div id="editor">
-        <div id="source-editor" class="editor">
-            {% toolbar %}
-            <textarea id="codemirror_placeholder">&lt;br/&gt;</textarea>
-            <input type="hidden" name="name" value="{{ document.name }}" /><input type="hidden" name="author" value="annonymous" /><input type="hidden" name="comment" value="no comment" /><input type="hidden" name="revision" value="{{ document_info.revision }}" />
-        </div>
-        <div id="simple-editor" class="editor" style="display: none">
-            <div id="html-view" class="htmlview">
-            </div>
-            <div class="toolbar">
-                <button id="insert-theme-button">
-                    Wstaw motyw
-                </button>
-                <button id="insert-annotation-button">
-                    Wstaw przypis
-                </button>
-                <div class="toolbar-end">
-                </div>
-            </div>
-        </div>
-               {% include "wiki/history_view.html" %}
-               {% include "wiki/summary_view.html" %}
-    </div>
-    <div class="vsplitbar" title="Klinknij aby (ro)zwinąć galerię."> </div>
+{% block splitter-extra %}
+    {% include "wiki/tabs/gallery_view.html" %}
+{% endblock %}
 
-       <div id="side-gallery">
-               <!-- gallery toolbar -->
-        <div class="toolbar">
-            <button class="previous-page">
-                <img src="{{STATIC_URL}}icons/go-previous.png" alt="Poprzednia" title="Poprzednia"/>
-            </button><input type="text" size="3" maxlength="3" value="1" class="page-number" />
-            <button class="next-page">
-                <img src="{{STATIC_URL}}icons/go-next.png" alt="Następna" title="Następna"/>
-            </button>
-            <button class="zoom-in">
-                Powiększ
-            </button>
-            <button class="zoom-out">
-                Pomniejsz
-            </button>
-            <div class="toolbar-end">
-            </div>
-        </div>
-               <div class="error_message"> </div>
-               <div class="gallery-image">
-                       <img src="{{MEDIA_URL}}/images/empty.png" />
-               </div>
-    </div>
-</div>
-{% 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 (file)
index 0000000..576ee1e
--- /dev/null
@@ -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 %}
+<script type="text/javascript" charset="utf-8">
+    var STATIC_URL = '{{STATIC_URL}}';
+</script>
+{% compressed_js 'detail' %}
+{% endblock %}
+
+{% block maincontent %}
+<div id="loading-overlay">
+    <div id="loading-message">
+        <img src="{{STATIC_URL}}img/spinner.gif" />
+        <p>Ładowanie</p>
+    </div>
+</div>
+
+<div id="document-meta"
+       data-document-name="{{ document.name }}" style="display:none">
+
+       {% for k, v in document_meta.items %}
+               <span data-key="{{ k }}">{{ v }}</span>
+       {% endfor %}
+
+       {% for k, v in document_info.items %}
+               <span data-key="{{ k }}">{{ v }}</span>
+       {% endfor %}
+
+       {% block meta-extra %} {% endblock %}
+</div>
+
+<div id="header">
+    <h1><a href="{% url wiki.views.document_list %}">Platforma</a></h1>
+    <div id="tools">
+        <a href="{{ REDMINE_URL }}projects/wl-publikacje/wiki/Pomoc" target="_blank">Pomoc</a>
+        | {% include "registration/head_login.html" %}
+        | Wersja: <span id="document-revision">unknown</span>
+               {% if not readonly %}
+            | <button style="margin-left: 6px" id="save-button">Zapisz</button>
+               {% endif %}
+    </div>
+    <ol id="tabs">
+       {% block tabs-menu %} {% endblock %}
+    </ol>
+</div>
+<div id="splitter">
+    <div id="editor" class="{% block editor-class %} {% endblock %}">
+       {% block tabs-content %} {% endblock %}
+    </div>
+       {% block splitter-extra %} {% endblock %}
+</div>
+
+{% 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 (file)
index 0000000..c0ed66f
--- /dev/null
@@ -0,0 +1,26 @@
+{% extends "wiki/document_details_base.html" %}
+
+{% block editor-class %}readonly{% endblock %}
+
+{% block extrabody %}
+{{ block.super }}
+<script src="{{STATIC_URL}}js/lib/codemirror/codemirror.js" type="text/javascript" charset="utf-8">
+</script>
+<script src="{{STATIC_URL}}js/wiki/loader_readonly.js" type="text/javascript" charset="utf-8"> </script>
+{% 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/history_view.html b/apps/wiki/templates/wiki/history_view.html
deleted file mode 100644 (file)
index 58b5415..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-<div id="history-view-editor" class="editor" style="display: none">
-    <div class="toolbar">
-       <button type="button" id="make-diff-button">Porównaj</button>
-               <button type="button" id="tag-changeset-button">Oznacz wersje</button>
-       </div>
-    <div id="history-view">
-        <p class="message-box" style="display:none;"></p>
-
-               <table id="changes-list-container">
-        <tbody id="changes-list">
-        </tbody>
-               <tbody style="display: none;">
-                       <tr class="entry row-stub">
-                       <td data-stub-value="version"></td>
-                       <td>
-                               <span data-stub-value="description"></span>
-                               <br />
-               <span data-stub-value="author"></span>, <span data-stub-value="date"></span>
-                       </td>
-                       <td data-stub-value="tag">
-                       </td>
-               </tr>
-               </tbody>
-               </table>
-    </div>
-</div>
diff --git a/apps/wiki/templates/wiki/summary_view.html b/apps/wiki/templates/wiki/summary_view.html
deleted file mode 100644 (file)
index f6dd3de..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-<div id="summary-view-editor" class="editor" style="display: none">
-    <!-- <div class="toolbar">
-    </div> -->
-    <div id="summary-view">
-               <img class="book-cover" src="{{STATIC_URL}}img/sample_cover.png">
-
-               <h2>
-                       <label for="title">Tytuł:</label>
-                       <span data-ui-editable="true" data-edit-target="meta.displayTitle"
-                       >{{ document_meta.title }}</span>
-               </h2>
-               <p>
-                       <label>ID dokumentu:</label>
-                       <span>{{ document.name|urlencode }}</span>
-               </p>
-               <p>
-                       <label>Aktulana wersja:</label>
-                       {{ document_info.revision }} ({{document_info.last_update}})
-               <p>
-                       <label>Ostatnio edytowane przez:</label>
-                       {{document_info.last_comitter}}
-               </p>
-               <p>
-                       <label for="gallery">Link do galerii:</label>
-                       <span data-ui-editable="true" data-edit-target="meta.galleryLink"
-                       >{{ document_meta.gallery}}</span>
-               </p>
-
-               <p><button type="button" id="publish_button">Publikuj na wolnelektury.pl</button></p>
-       </div>
-</div>
\ 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 (file)
index 0000000..ec5f6e4
--- /dev/null
@@ -0,0 +1,26 @@
+<div class="vsplitbar" title="Klinknij aby (ro)zwinąć galerię.">
+</div>
+<div id="side-gallery">
+    <!-- gallery toolbar -->
+    <div class="toolbar">
+        <button class="previous-page">
+            <img src="{{STATIC_URL}}icons/go-previous.png" alt="Poprzednia" title="Poprzednia"/>
+        </button><input type="text" size="3" maxlength="3" value="1" class="page-number" />
+        <button class="next-page">
+            <img src="{{STATIC_URL}}icons/go-next.png" alt="Następna" title="Następna"/>
+        </button>
+        <button class="zoom-in">
+            Powiększ
+        </button>
+        <button class="zoom-out">
+            Pomniejsz
+        </button>
+        <div class="toolbar-end">
+        </div>
+    </div>
+    <div class="error_message">
+    </div>
+    <div class="gallery-image">
+        <img src="{{MEDIA_URL}}/images/empty.png" />
+    </div>
+</div>
\ No newline at end of file
diff --git a/apps/wiki/templates/wiki/tabs/history_view.html b/apps/wiki/templates/wiki/tabs/history_view.html
new file mode 100644 (file)
index 0000000..6d82785
--- /dev/null
@@ -0,0 +1,28 @@
+<div id="history-view-editor" class="editor" style="display: none">
+    <div class="toolbar">
+       <button type="button" id="make-diff-button">Porównaj</button>
+               <button type="button" id="tag-changeset-button">Oznacz wersje</button>
+               <button id="open-preview-button"
+                       data-basehref="{% url wiki_details_readonly document_name %}">Podejrzyj wersje</button>
+       </div>
+    <div id="history-view">
+        <p class="message-box" style="display:none;"></p>
+
+               <table id="changes-list-container">
+        <tbody id="changes-list">
+        </tbody>
+               <tbody style="display: none;">
+                       <tr class="entry row-stub">
+                       <td data-stub-value="version"></td>
+                       <td>
+                               <span data-stub-value="description"></span>
+                               <br />
+               <span data-stub-value="author"></span>, <span data-stub-value="date"></span>
+                       </td>
+                       <td data-stub-value="tag">
+                       </td>
+               </tr>
+               </tbody>
+               </table>
+    </div>
+</div>
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 (file)
index 0000000..3a90ea8
--- /dev/null
@@ -0,0 +1,3 @@
+<li id="HistoryPerspective" data-ui-related="history-view-editor" data-ui-jsclass="HistoryPerspective">
+    <span>Historia</span>
+</li>
diff --git a/apps/wiki/templates/wiki/tabs/source_editor.html b/apps/wiki/templates/wiki/tabs/source_editor.html
new file mode 100644 (file)
index 0000000..10ca334
--- /dev/null
@@ -0,0 +1,10 @@
+{% load toolbar_tags %}
+<div id="source-editor" class="editor">
+    {% if not document_info.readonly %}{% toolbar %}{% endif %}
+    <textarea id="codemirror_placeholder">&lt;br/&gt;</textarea>
+    <!-- <input type="hidden" name="name" value="{{ document.name }}" />
+       <input type="hidden" name="author" value="annonymous" />
+       <input type="hidden" name="comment" value="no comment" />
+       <input type="hidden" name="revision" value="{{ document_info.revision }}" />
+       -->
+</div>
\ 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 (file)
index 0000000..0382982
--- /dev/null
@@ -0,0 +1,5 @@
+<li id="CodeMirrorPerspective"
+       data-ui-related="source-editor"
+       data-ui-jsclass="CodeMirrorPerspective">
+    <span>Kod źródłowy</span>
+</li>
\ No newline at end of file
diff --git a/apps/wiki/templates/wiki/tabs/summary_view.html b/apps/wiki/templates/wiki/tabs/summary_view.html
new file mode 100644 (file)
index 0000000..f6dd3de
--- /dev/null
@@ -0,0 +1,31 @@
+<div id="summary-view-editor" class="editor" style="display: none">
+    <!-- <div class="toolbar">
+    </div> -->
+    <div id="summary-view">
+               <img class="book-cover" src="{{STATIC_URL}}img/sample_cover.png">
+
+               <h2>
+                       <label for="title">Tytuł:</label>
+                       <span data-ui-editable="true" data-edit-target="meta.displayTitle"
+                       >{{ document_meta.title }}</span>
+               </h2>
+               <p>
+                       <label>ID dokumentu:</label>
+                       <span>{{ document.name|urlencode }}</span>
+               </p>
+               <p>
+                       <label>Aktulana wersja:</label>
+                       {{ document_info.revision }} ({{document_info.last_update}})
+               <p>
+                       <label>Ostatnio edytowane przez:</label>
+                       {{document_info.last_comitter}}
+               </p>
+               <p>
+                       <label for="gallery">Link do galerii:</label>
+                       <span data-ui-editable="true" data-edit-target="meta.galleryLink"
+                       >{{ document_meta.gallery}}</span>
+               </p>
+
+               <p><button type="button" id="publish_button">Publikuj na wolnelektury.pl</button></p>
+       </div>
+</div>
\ No newline at end of file
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 (file)
index 0000000..d973d4d
--- /dev/null
@@ -0,0 +1,3 @@
+<li id="SummaryPerspective" data-ui-related="summary-view-editor" data-ui-jsclass="SummaryPerspective">
+    <span>{{ document_meta.title }}</span>
+</li>
diff --git a/apps/wiki/templates/wiki/tabs/wysiwyg_editor.html b/apps/wiki/templates/wiki/tabs/wysiwyg_editor.html
new file mode 100644 (file)
index 0000000..dbf1b6a
--- /dev/null
@@ -0,0 +1,17 @@
+<div id="simple-editor" class="editor" style="display: none">
+    <div id="html-view" class="htmlview">
+    </div>
+
+       <div class="toolbar">
+       {% if not document_info.readonly %}
+        <button id="insert-theme-button">
+            Wstaw motyw
+        </button>
+        <button id="insert-annotation-button">
+            Wstaw przypis
+        </button>
+               {% endif %}
+        <div class="toolbar-end">
+        </div>
+    </div>
+</div>
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 (file)
index 0000000..bd4dc62
--- /dev/null
@@ -0,0 +1,3 @@
+<li id="VisualPerspective" data-ui-related="simple-editor" data-ui-jsclass="VisualPerspective">
+    <span>Edytor</span>
+</li>
index dd0a0df..c5c08a1 100644 (file)
@@ -19,6 +19,10 @@ urlpatterns = patterns('wiki.views',
     url(r'^(?P<name>[^/]+)/tags$',
         'document_add_tag', name="wiki_add_tag"),
     url(r'^(?P<name>[^/]+)/publish$', 'document_publish'),
+
+    url(r'^(?P<name>[^/]+)/readonly$',
+        'document_detail_readonly', name="wiki_details_readonly"),
+
     url(r'^(?P<name>[^/]+)$',
         'document_detail', name="wiki_details"),
 )
index 9b7d807..46f0665 100644 (file)
@@ -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()
 
index 24d5ec9..82151da 100644 (file)
@@ -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()
index ab72329..fa416c4 100644 (file)
@@ -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',
      },
index 4492af7..813d8f3 100644 (file)
@@ -1,5 +1,6 @@
 # -*- coding: utf-8
 
+
 def settings(request):
     from django.conf import settings
     return {
index 517d863..ae74266 100644 (file)
@@ -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%;
index a208ca1..0d38b00 100644 (file)
 
 })();
 
+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 = $('<span>Executing script</span>');
+       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) {
index 1020217..8c62dab 100644 (file)
@@ -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) {
index 40a2942..523ad96 100644 (file)
@@ -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')];
        };
 
                $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 */
                        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;
        };
 
        $.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() {
index 34305d7..a441402 100644 (file)
@@ -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 (file)
index 0000000..c22e9d7
--- /dev/null
@@ -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
index 0acd2cd..a0a2e69 100644 (file)
@@ -20,6 +20,7 @@
                                width: "100%",
                                tabMode: 'spaces',
                                indentUnit: 0,
+                               readOnly: CurrentDocument.readonly || false,
                                initCallback: function(){
 
                                        self.codemirror.grabKeys(function(event) {
                                        $('#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){
                                        $('.toolbar select').change();
 
                                        console.log("Initialized CodeMirror");
-                                       
+
                                        // textarea is no longer needed
                                        $('codemirror_placeholder').remove();
-                                       
+
                                        old_callback.call(self);
                                }
                        });
        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();
        }
 
index 177c113..2ae1a8d 100644 (file)
             });
         }
 
-               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();
 
         var old_callback = options.callback;
 
-        options.callback = function() {
+        options.callback = function(){
             var element = $("#html-view");
             var button = $('<button class="edit-button">Edytuj</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);
index 69761ca..aa39e15 100644 (file)
@@ -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);
         };
 
     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]);
     };
 
         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();
                 if(failure) failure();
             }
         });
+
     };
 
+       ScanGalleryPerspective.prototype.onExit = function(success, failure) {
+
+       };
+
     $.wiki.ScanGalleryPerspective = ScanGalleryPerspective;
 
 })(jQuery);
\ No newline at end of file
index 5a3e813..b4a9dd8 100644 (file)
                                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'))
                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;
         }
 
index d0ac5dc..27ab97e 100644 (file)
        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;
                        }
                });
        };
+
        /*
         * Fetch gallery
         */
                        }
                });
        };
+
        /*
         * Set document's text
         */
                this.text = text;
                this.has_local_changes = true;
        };
+
        /*
         * Set document's gallery link
         */
                this.galleryLink = gallery;
                this.has_local_changes = true;
        };
+
        /*
         * Save text back to the server
         */
                $.each(params['form'].serializeArray(), function() {
                        data[this.name] = this.value;
                });
-               
+
                var metaComment = '<!--';
                metaComment += '\n\tgallery:' + self.galleryLink;
                metaComment += '\n-->\n'
                        }
                });
        }; /* end of save() */
+
        WikiDocument.prototype.publish = function(params) {
                params = $.extend({}, noops, params);
                var self = this;
                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",
                                                        "__all__": ["Nie udało się - błąd serwera."]
                                                });
                                        };
-
                                };
-
                        }
                });
        };
+
        $.wikiapi.WikiDocument = WikiDocument;
 })(jQuery);