"""
Form for saving document's text:
- * name - document's storage identifier.
* parent_revision - revision which the modified text originated from.
* comment - user's verbose comment; will be used in commit.
* stage_completed - mark this change as end of given stage.
"""
- id = forms.CharField(widget=forms.HiddenInput)
parent_revision = forms.IntegerField(widget=forms.HiddenInput)
text = forms.CharField(widget=forms.HiddenInput)
label=_(u"Completed"),
help_text=_(u"If you completed a life cycle stage, select it."),
)
+
+
+class DocumentTextRevertForm(forms.Form):
+ """
+ Form for reverting document's text:
+
+ * revision - revision to revert to.
+ * comment - user's verbose comment; will be used in commit.
+
+ """
+
+ revision = forms.IntegerField(widget=forms.HiddenInput)
+
+ author_name = forms.CharField(
+ required=False,
+ label=_(u"Author"),
+ help_text=_(u"Your name"),
+ )
+
+ author_email = forms.EmailField(
+ required=False,
+ label=_(u"Author's email"),
+ help_text=_(u"Your email address, so we can show a gravatar :)"),
+ )
+
+ comment = forms.CharField(
+ required=True,
+ widget=forms.Textarea,
+ label=_(u"Your comments"),
+ help_text=_(u"Describe the reason for reverting."),
+ )
text, rev = self.vstorage.page_text_by_tag(name, tag)
return Document(self, name=name, text=text, revision=rev)
- def revert(self, name, revision):
- text, rev = self.vstorage.revert(name, revision)
- return Document(self, name=name, text=text, revision=rev)
+ def revert(self, name, revision, **commit_args):
+ self.vstorage.revert(name, revision, **commit_args)
def get_or_404(self, *args, **kwargs):
try:
{% block tabs-menu %}
{% include "wiki/tabs/summary_view_item.html" %}
{% include "wiki/tabs/wysiwyg_editor_item.html" %}
- {% include "wiki/tabs/source_editor_item.html" %}
+ {% include "wiki/tabs/source_editor_item.html" %}
{% include "wiki/tabs/history_view_item.html" %}
{% endblock %}
{% block tabs-content %}
{% include "wiki/tabs/summary_view.html" %}
{% include "wiki/tabs/wysiwyg_editor.html" %}
- {% include "wiki/tabs/source_editor.html" %}
+ {% include "wiki/tabs/source_editor.html" %}
{% include "wiki/tabs/history_view.html" %}
{% endblock %}
{% endblock %}
{% block dialogs %}
- {% include "wiki/save_dialog.html" %}
- {% include "wiki/tag_dialog.html" %}
+ {% include "wiki/save_dialog.html" %}
+ {% include "wiki/revert_dialog.html" %}
+ {% include "wiki/tag_dialog.html" %}
{% endblock %}
--- /dev/null
+{% load i18n %}
+<div id="revert_dialog" class="dialog" data-ui-jsclass="RevertDialog">
+ <form method="POST" action="">
+ <p>{{ forms.text_revert.comment.label }}</p>
+ <p class="help_text">
+ {{ forms.text_revert.comment.help_text}}
+ <span data-ui-error-for="{{ forms.text_revert.comment.name }}"> </span>
+ </p>
+ {{forms.text_revert.comment }}
+
+
+
+ {% if request.user.is_anonymous %}
+ <table style='margin:0 4%;'>
+ <tr>
+ <td>{{ forms.text_revert.author_name.label }}:</td>
+ <td>{{ forms.text_revert.author_name }}
+ <span class="help_text">{{ forms.text_revert.author_name.help_text }}</span>
+ <span data-ui-error-for="{{ forms.text_revert.author_name.name }}"> </span></td>
+ </tr>
+ <tr>
+ <td>{{ forms.text_revert.author_email.label }}:</td>
+ <td>{{ forms.text_revert.author_email }}
+ <span class="help_text">{{ forms.text_revert.author_email.help_text }}</span>
+ <span data-ui-error-for="{{ forms.text_revert.author_email.name }}"> </span></td>
+ </tr>
+ </table>
+ {% endif %}
+
+
+ {% for f in forms.text_revert.hidden_fields %}
+ {{ f }}
+ {% endfor %}
+
+ <p data-ui-error-for="__all__"> </p>
+
+ <p class="action_area">
+ <button type="submit" class"ok" data-ui-action="revert">{% trans "Revert" %}</button>
+ <button type="button" class="cancel" data-ui-action="cancel">{% trans "Cancel" %}</button>
+ </p>
+ </form>
+</div>
url(r'^(?P<name>[^/]+)/text$',
'text', name="wiki_text"),
+ url(r'^(?P<name>[^/]+)/revert$',
+ 'revert', name='wiki_revert'),
+
url(r'^(?P<name>[^/]+)/publish$', 'publish', name="wiki_publish"),
url(r'^(?P<name>[^/]+)/publish/(?P<version>\d+)$', 'publish', name="wiki_publish"),
from django import http
from wiki.models import getstorage, DocumentNotFound, normalize_name, split_name, join_name, Theme
-from wiki.forms import DocumentTextSaveForm, DocumentTagForm, DocumentCreateForm, DocumentsUploadForm
+from wiki.forms import DocumentTextSaveForm, DocumentTextRevertForm, DocumentTagForm, DocumentCreateForm, DocumentsUploadForm
from datetime import datetime
from django.utils.encoding import smart_unicode
from django.utils.translation import ugettext_lazy as _
'document_meta': document.meta,
'forms': {
"text_save": DocumentTextSaveForm(prefix="textsave"),
+ "text_revert": DocumentTextRevertForm(prefix="textrevert"),
"add_tag": DocumentTagForm(prefix="addtag"),
},
'REDMINE_URL': settings.REDMINE_URL,
@require_POST
def revert(request, name):
storage = getstorage()
- revision = request.POST['target_revision']
+ form = DocumentTextRevertForm(request.POST, prefix="textrevert")
+ if form.is_valid():
+ print 'valid'
+ revision = form.cleaned_data['revision']
+
+ comment = form.cleaned_data['comment']
+ comment += "\n#revert to %s" % revision
+
+ if request.user.is_authenticated():
+ author_name = request.user
+ author_email = request.user.email
+ else:
+ author_name = form.cleaned_data['author_name']
+ author_email = form.cleaned_data['author_email']
+ author = "%s <%s>" % (author_name, author_email)
+
+ before = storage.get(name).revision
+ logger.info("Reverting %s to %s", name, revision)
+ storage.revert(name, revision, comment=comment, author=author)
+ logger.info("Fetching %s", name)
+ document = storage.get(name)
- try:
- document = storage.revert(name, revision)
return JSONResponse({
- 'text': document.plain_text if revision != document.revision else None,
+ 'text': document.plain_text if before != document.revision else None,
'meta': document.meta(),
'revision': document.revision,
})
- except DocumentNotFound:
- raise http.Http404
+ else:
+ print 'invalid'
+ return JSONFormInvalid(form)
+
@never_cache
def gallery(request, directory):
# dialogs
'js/wiki/dialog_save.js',
+ 'js/wiki/dialog_revert.js',
'js/wiki/dialog_addtag.js',
# views
font-weight: bold;
}
-#save_dialog textarea {
+#save_dialog textarea, #revert_dialog textarea {
width: 90%;
margin: 0.2em 4%;
}
\ No newline at end of file
--- /dev/null
+/*
+ * Dialog for reverting document on the server
+ *
+ */
+(function($) {
+
+ function RevertDialog(element, options) {
+ this.ctx = $.wiki.exitContext();
+ this.clearForm();
+
+ /* fill out hidden fields */
+ this.$form = $('form', element);
+
+ $("input[name='textrevert-revision']", this.$form).val(options.revision);
+
+ $.wiki.cls.GenericDialog.call(this, element);
+ };
+
+ RevertDialog.prototype = new $.wiki.cls.GenericDialog();
+
+ RevertDialog.prototype.cancelAction = function() {
+ $.wiki.enterContext(this.ctx);
+ this.hide();
+ };
+
+ RevertDialog.prototype.revertAction = function() {
+ var self = this;
+
+ self.$elem.block({
+ message: "Przywracanie...",
+ fadeIn: 0,
+ });
+ $.wiki.blocking = self.$elem;
+
+ try {
+
+ CurrentDocument.revertToVersion({
+ form: self.$form,
+ success: function(e, msg) {
+ self.$elem.block({
+ message: msg,
+ timeout: 2000,
+ fadeOut: 0,
+ onUnblock: function() {
+ self.hide();
+ $.wiki.enterContext(self.ctx);
+ }
+ });
+ },
+ 'failure': function(e, info) {
+ console.log("Failure", info);
+ self.reportErrors(info);
+ self.$elem.unblock();
+ }
+ });
+
+ } catch(e) {
+ console.log('Exception:', e)
+ self.$elem.unblock();
+ }
+ }; /* end of revert dialog */
+
+ /* make it global */
+ $.wiki.cls.RevertDialog = RevertDialog;
+})(jQuery);
/* fill out hidden fields */
this.$form = $('form', element);
- $("input[name='textsave-id']", this.$form).val(CurrentDocument.id);
$("input[name='textsave-parent_revision']", this.$form).val(CurrentDocument.revision);
$.wiki.cls.GenericDialog.call(this, element);
});
$('#doc-revert-button').click(function() {
- self.revertDocumentToVersion();
+ self.revertDialog();
});
$('#open-preview-button').click(function(event) {
});
};
- HistoryPerspective.prototype.revertDocumentToVersion = function(){
+ HistoryPerspective.prototype.revertDialog = function(){
+ var self = this;
var selected = $('#changes-list .entry.selected');
if (selected.length != 1) {
}
var version = parseInt($("*[data-stub-value='version']", selected[0]).text());
- this.doc.revertToVersion({'revision': version});
+ $.wiki.showDialog('#revert_dialog', {revision: version});
};
$.wiki.HistoryPerspective = HistoryPerspective;
return base_path + path;
}
+ if (vname == "ajax_document_revert") {
+ return base_path + "/" + arguments[1] + "/revert";
+ }
+
+
if (vname == "ajax_document_history") {
return base_path + "/" + arguments[1] + "/history";
});
}; /* end of save() */
+ WikiDocument.prototype.revertToVersion = function(params) {
+ var self = this;
+ params = $.extend({}, noops, params);
+
+ if (params.revision >= this.revision) {
+ params.failure(self, 'Proszę wybrać rewizję starszą niż aktualna.');
+ return;
+ }
+
+ // Serialize form to dictionary
+ var data = {};
+ $.each(params['form'].serializeArray(), function() {
+ data[this.name] = this.value;
+ });
+
+ $.ajax({
+ url: reverse("ajax_document_revert", self.id),
+ type: "POST",
+ dataType: "json",
+ data: data,
+ success: function(data) {
+ if (data.text) {
+ self.text = data.text;
+ self.revision = data.revision;
+ self.gallery = data.gallery;
+ self.triggerDocumentChanged();
+
+ params.success(self, "Udało się przywrócić wersję :)");
+ }
+ else {
+ params.failure(self, "Przywracana wersja identyczna z aktualną. Anulowano przywracanie.");
+ }
+ },
+ error: function(xhr) {
+ params.failure(self, "Nie udało się przywrócić wersji - błąd serwera.");
+ }
+ });
+ };
+
WikiDocument.prototype.publish = function(params) {
params = $.extend({}, noops, params);
var self = this;