X-Git-Url: https://git.mdrn.pl/redakcja.git/blobdiff_plain/b9166b62220208f49bfd3521e547d60d377ab7c1..309ec8b919d57858254b78cd7ba3b4d84d90da9a:/src/redakcja/static/js/wiki/wikiapi.js diff --git a/src/redakcja/static/js/wiki/wikiapi.js b/src/redakcja/static/js/wiki/wikiapi.js index 4e3cd2c6..73642ac0 100644 --- a/src/redakcja/static/js/wiki/wikiapi.js +++ b/src/redakcja/static/js/wiki/wikiapi.js @@ -1,437 +1,557 @@ (function($) { - $.wikiapi = {}; - var noop = function() { - }; - var noops = { - success: noop, - failure: noop - }; - /* - * Return absolute reverse path of given named view. (at least he have it - * hard-coded in one place) - * - * TODO: think of a way, not to hard-code it here ;) - * - */ - function reverse() { - var vname = arguments[0]; - var base_path = "/editor"; - - if (vname == "ajax_document_text") { - var path = "/text/" + arguments[1] + '/'; - - if (arguments[2] !== undefined) - path += arguments[2] + '/'; - - return base_path + path; - } + $.wikiapi = {}; + var noop = function() { + }; + var noops = { + success: noop, + failure: noop + }; + /* + * Return absolute reverse path of given named view. (at least he have it + * hard-coded in one place) + * + * TODO: think of a way, not to hard-code it here ;) + * + */ + function reverse() { + var vname = arguments[0]; + var base_path = "/editor"; + + if (vname == "ajax_document_text") { + var path = "/text/" + arguments[1] + '/'; + + if (arguments[2] !== undefined) + path += arguments[2] + '/'; + + return base_path + path; + } if (vname == "ajax_document_revert") { return base_path + "/revert/" + arguments[1] + '/'; } - if (vname == "ajax_document_history") { - - return base_path + "/history/" + arguments[1] + '/'; - } - - if (vname == "ajax_document_gallery") { + if (vname == "ajax_document_history") { + return base_path + "/history/" + arguments[1] + '/'; + } - return base_path + "/gallery/" + arguments[1] + '/'; - } + if (vname == "ajax_document_scans") { + return base_path + "/scans/" + arguments[1] + '/'; + } + if (vname == "ajax_document_gallery") { + return base_path + "/gallery/" + arguments[1] + '/'; + } - if (vname == "ajax_document_diff") - return base_path + "/diff/" + arguments[1] + '/'; + if (vname == "ajax_document_diff") + return base_path + "/diff/" + arguments[1] + '/'; if (vname == "ajax_document_rev") return base_path + "/rev/" + arguments[1] + '/'; - if (vname == "ajax_document_pubmark") - return base_path + "/pubmark/" + arguments[1] + '/'; - - if (vname == "ajax_cover_preview") - return "/cover/preview/"; - - console.log("Couldn't reverse match:", vname); - return "/404.html"; - }; - - /* - * Document Abstraction - */ - function WikiDocument(element_id) { - var meta = $('#' + element_id); - this.id = meta.attr('data-chunk-id'); - - this.revision = $("*[data-key='revision']", meta).text(); - this.readonly = !!$("*[data-key='readonly']", meta).text(); - - this.galleryLink = $("*[data-key='gallery']", meta).text(); - this.galleryStart = parseInt($("*[data-key='gallery-start']", meta).text()); - - var diff = $("*[data-key='diff']", meta).text(); - if (diff) { - diff = diff.split(','); - if (diff.length == 2 && diff[0] < diff[1]) - this.diff = diff; - else if (diff.length == 1) { - diff = parseInt(diff); - if (diff != NaN) - this.diff = [diff - 1, diff]; - } - } + if (vname == "ajax_document_pubmark") + return base_path + "/pubmark/" + arguments[1] + '/'; - this.galleryImages = []; - this.text = null; - this.has_local_changes = false; - this._lock = -1; - this._context_lock = -1; - this._lock_count = 0; - }; - - WikiDocument.prototype.triggerDocumentChanged = function() { - $(document).trigger('wlapi_document_changed', this); - }; - /* - * Fetch text of this document. - */ - WikiDocument.prototype.fetch = function(params) { - params = $.extend({}, noops, params); - var self = this; - $.ajax({ - method: "GET", - url: reverse("ajax_document_text", self.id), - data: {"revision": self.revision}, - dataType: 'json', - success: function(data) { - var changed = false; - - if (self.text === null || self.revision !== data.revision) { - self.text = data.text; - self.revision = data.revision; - self.gallery = data.gallery; - changed = true; - self.triggerDocumentChanged(); - }; - - self.has_local_changes = false; - params['success'](self, changed); - }, - error: function() { - params['failure'](self, "Nie udało się wczytać treści dokumentu."); - } - }); - }; - /* - * Fetch history of this document. - * - * from - First revision to fetch (default = 0) upto - Last revision to - * fetch (default = tip) - * - */ - WikiDocument.prototype.fetchHistory = function(params) { - /* this doesn't modify anything, so no locks */ - params = $.extend({}, noops, params); - var self = this; - $.ajax({ - method: "GET", - url: reverse("ajax_document_history", self.id), - dataType: 'json', - data: { - "from": params['from'], - "upto": params['upto'] - }, - success: function(data) { - params['success'](self, data); - }, - error: function() { - params['failure'](self, "Nie udało się wczytać historii dokumentu."); - } - }); - }; - WikiDocument.prototype.fetchDiff = function(params) { - /* this doesn't modify anything, so no locks */ - var self = this; - params = $.extend({ - 'from': self.revision, - 'to': self.revision - }, noops, params); - $.ajax({ - method: "GET", - url: reverse("ajax_document_diff", self.id), - dataType: 'html', - data: { - "from": params['from'], - "to": params['to'] - }, - success: function(data) { - params['success'](self, data); - }, - error: function() { - params['failure'](self, "Nie udało się wczytać porównania wersji."); - } - }); - }; - - WikiDocument.prototype.checkRevision = function(params) { - /* this doesn't modify anything, so no locks */ - var self = this; - $.ajax({ - method: "GET", - url: reverse("ajax_document_rev", self.id), - dataType: 'text', - success: function(data) { - if (data == '') { - if (params.error) - params.error(); - } - else if (data != self.revision) - params.outdated(); - } - }); + if (vname == "ajax_cover_preview") + return "/cover/preview/"; + + console.log("Couldn't reverse match:", vname); + return "/404.html"; }; + class Api { + static csrf = $('input[name="csrfmiddlewaretoken"]').val(); + + // TODO: Add waiting marker, error reporting. + static post(url, data) { + data['csrfmiddlewaretoken'] = this.csrf; + $.ajax({ + url: url, + type: "POST", + data: data + }); + } - /* - * Fetch gallery - */ - WikiDocument.prototype.refreshGallery = function(params) { - params = $.extend({}, noops, params); - var self = this; - if (!self.galleryLink) { - params['failure'](self, 'Brak galerii.'); - return; - } - $.ajax({ - method: "GET", - url: reverse("ajax_document_gallery", self.galleryLink), - dataType: 'json', - // data: {}, - success: function(data) { - self.galleryImages = data; - params['success'](self, data); - }, - error: function(xhr) { - switch (xhr.status) { - case 403: - var msg = 'Galerie dostępne tylko dla zalogowanych użytkowników.'; - break; - case 404: - var msg = "Nie znaleziono galerii o nazwie: '" + self.galleryLink + "'."; - default: - var msg = "Nie udało się wczytać galerii o nazwie: '" + self.galleryLink + "'."; - } - self.galleryImages = []; - params['failure'](self, msg); - } - }); - }; + static get(url, callback) { + $.ajax({ + url: url, + type: "GET", + success: function(data) { + callback(data); + }, + }); + } + + static setGallery(id, gallery) { + this.post( + '/editor/set-gallery/' + id + '/', + {gallery: gallery} + ) + } + static setGalleryStart(id, start) { + this.post( + '/editor/set-gallery-start/' + id + '/', + {start: start} + ) + } + + static openGalleryEdit(bookSlug) { + window.open( + '/documents/book/' + bookSlug + '/gallery/', + '_blank' + ).focus(); + } + + static withGalleryList(callback) { + this.get( + '/editor/galleries/', + callback + ); + } + } /* - * Set document's text + * Document Abstraction */ - WikiDocument.prototype.setText = function(text, setter) { - if (text == this.text) return; - - this.text = text; - this.has_local_changes = true; + class WikiDocument { + constructor(element_id) { + var meta = $('#' + element_id); + this.id = meta.attr('data-chunk-id'); + + this.revision = $("*[data-key='revision']", meta).text(); + this.readonly = !!$("*[data-key='readonly']", meta).text(); + + this.bookSlug = $("*[data-key='book-slug']", meta).text(); + this.scansLink = $("*[data-key='scans']", meta).text(); + this.galleryLink = $("*[data-key='gallery']", meta).text(); + this.galleryStart = parseInt($("*[data-key='gallery-start']", meta).text()); + this.fullUri = $("*[data-key='full-uri']", meta).text(); + + this.text = null; + this.saving = false; + this.has_local_changes = false; + this.active = new Date(); + this._lock = -1; + this._context_lock = -1; + this._lock_count = 0; + }; + + triggerDocumentChanged() { + $(document).trigger('wlapi_document_changed', this); + } - }; + /* + * Fetch text of this document. + */ + fetch(params) { + params = $.extend({}, noops, params); + var self = this; + $.ajax({ + method: "GET", + url: reverse("ajax_document_text", self.id), + data: {"revision": self.revision}, + dataType: 'json', + success: function(data) { + var changed = false; + + if (self.text === null || self.revision !== data.revision) { + self.text = data.text; + $.wiki.undo.push(data.text); + self.revision = data.revision; + self.gallery = data.gallery; + changed = true; + self.triggerDocumentChanged(); + }; + + self.has_local_changes = false; + params['success'](self, changed); + }, + error: function() { + params['failure'](self, "Nie udało się wczytać treści dokumentu."); + } + }); + } - - /* - * Save text back to the server - */ - WikiDocument.prototype.save = function(params) { - params = $.extend({}, noops, params); - var self = this; - - if (!self.has_local_changes) { - console.log("Abort: no changes."); - return params['success'](self, false, "Nie ma zmian do zapisania."); - }; - - // Serialize form to dictionary - var data = {}; - $.each(params['form'].serializeArray(), function() { - data[this.name] = this.value; - }); - - data['textsave-text'] = self.text; - - $.ajax({ - url: reverse("ajax_document_text", self.id), - type: "POST", - dataType: "json", - data: data, - success: function(data) { - var changed = false; - - $('#header').removeClass('saving'); - - if (data.text) { - self.text = data.text; - self.revision = data.revision; - self.gallery = data.gallery; - changed = true; - self.triggerDocumentChanged(); - }; - - params['success'](self, changed, ((changed && "Udało się zapisać :)") || "Twoja wersja i serwera jest identyczna")); - }, - error: function(xhr) { - if ($('#header').hasClass('saving')) { - $('#header').removeClass('saving'); - $.blockUI({ - message: "

Nie udało się zapisać zmian.

" - }) - } - else { - try { - params['failure'](self, $.parseJSON(xhr.responseText)); + /* + * Fetch history of this document. + */ + fetchHistory(params) { + /* this doesn't modify anything, so no locks */ + params = $.extend({}, noops, params); + var self = this; + $.ajax({ + method: "GET", + url: reverse("ajax_document_history", self.id) + "?before=" + params.before, + dataType: 'json', + success: function(data) { + params['success'](self, data); + }, + error: function() { + params['failure'](self, "Nie udało się wczytać historii dokumentu."); + } + }); + } + + fetchDiff(params) { + /* this doesn't modify anything, so no locks */ + var self = this; + params = $.extend({ + 'from': self.revision, + 'to': self.revision + }, noops, params); + $.ajax({ + method: "GET", + url: reverse("ajax_document_diff", self.id), + dataType: 'html', + data: { + "from": params['from'], + "to": params['to'] + }, + success: function(data) { + params['success'](self, data); + }, + error: function() { + params['failure'](self, "Nie udało się wczytać porównania wersji."); + } + }); + } + + checkRevision(params) { + /* this doesn't modify anything, so no locks */ + var self = this; + let active = new Date() - self.active < 30 * 1000; + let saving = self.saving; + $.ajax({ + method: "GET", + url: reverse("ajax_document_rev", self.id), + data: { + 'a': active, + 'new': 1, + }, + dataType: 'json', + success: function(data) { + if (data == '') { + if (params.error) + params.error(); } - catch (e) { - params['failure'](self, { - "__message": "

Nie udało się zapisać - błąd serwera.

" + else { + let people = $('
'); + data.people.forEach((p) => { + let item = $(''); + item.attr('src', p.gravatar), + item.attr( + 'title', + p.name + ' (' + + (p.active ? 'akt.' : 'nieakt.') + + ' od ' + p.since + ')') + if (p.active) { + item.addClass('active'); + } + people.append(item); }); - }; + $("#people").html(people); + + if (!saving && (data.rev != self.revision)) { + params.outdated(); + } + } } + }); + } + + refreshImageGallery(params) { + if (this.galleryLink) { + params = $.extend({}, params, { + url: reverse("ajax_document_gallery", this.galleryLink) + }); + } + this.refreshGallery(params); + } - } - }); + refreshScansGallery(params) { + if (this.scansLink) { + params = $.extend({}, params, { + url: reverse("ajax_document_scans", this.scansLink) + }); + this.refreshGallery(params); + } else { + // Fallback to image gallery. + this.refreshImageGallery(params) + } + } + + /* + * Fetch gallery + */ + refreshGallery(params) { + params = $.extend({}, noops, params); + var self = this; + if (!params.url) { + params.failure('Brak galerii.'); + return; + } + $.ajax({ + method: "GET", + url: params.url, + dataType: 'json', + success: function(data) { + params.success(data); + }, + error: function(xhr) { + switch (xhr.status) { + case 403: + var msg = 'Galerie dostępne tylko dla zalogowanych użytkowników.'; + break; + case 404: + var msg = "Nie znaleziono galerii."; + default: + var msg = "Nie udało się wczytać galerii."; + } + params.failure(msg); + } + }); + } - $('#save-hide').click(function(){ - $('#header').addClass('saving'); - $.unblockUI(); - $.wiki.blocking.unblock(); - }); - }; /* end of save() */ + setGallery(gallery) { + this.galleryLink = gallery; + Api.setGallery(this.id, gallery); + } - WikiDocument.prototype.revertToVersion = function(params) { - var self = this; - params = $.extend({}, noops, params); + setGalleryStart(start) { + this.galleryStart = start; + Api.setGalleryStart(this.id, start); + } - if (params.revision >= this.revision) { - params.failure(self, 'Proszę wybrać rewizję starszą niż aktualna.'); - return; + openGalleryEdit(start) { + Api.openGalleryEdit(this.bookSlug); } - // 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."); + withGalleryList(callback) { + Api.withGalleryList(callback); + } + + /* + * Set document's text + */ + setText(text, silent=false) { + if (text == this.text) return; + if (!silent) { + $.wiki.undo.push(text); } - }); - }; + this.text = text; + this.has_local_changes = true; + } - WikiDocument.prototype.pubmark = function(params) { - params = $.extend({}, noops, params); - var self = this; - var data = { - "pubmark-id": self.id, - }; - - /* unpack form */ - $.each(params.form.serializeArray(), function() { - data[this.name] = this.value; - }); - - $.ajax({ - url: reverse("ajax_document_pubmark", self.id), - type: "POST", - dataType: "json", - data: data, - success: function(data) { - params.success(self, data.message); - }, - error: function(xhr) { - if (xhr.status == 403 || xhr.status == 401) { - params.failure(self, { - "__all__": ["Nie masz uprawnień lub nie jesteś zalogowany."] - }); - } - else { - try { - params.failure(self, $.parseJSON(xhr.responseText)); - } - catch (e) { - params.failure(self, { - "__all__": ["Nie udało się - błąd serwera."] - }); - }; - }; - } - }); - }; - - WikiDocument.prototype.refreshCover = function(params) { - var self = this; - var data = { - xml: self.text // TODO: send just DC - }; - $.ajax({ - url: reverse("ajax_cover_preview"), - type: "POST", - data: data, - success: function(data) { - params.success(data); - }, - error: function(xhr) { - // params.failure("Nie udało się odświeżyć okładki - błąd serwera."); + undo() { + let ctx = $.wiki.exitContext(); + this.setText( + $.wiki.undo.undo(), + true + ); + $.wiki.enterContext(ctx); + } + redo() { + let ctx = $.wiki.exitContext(); + this.setText( + $.wiki.undo.redo(), + true + ); + $.wiki.enterContext(ctx); + } + + /* + * Save text back to the server + */ + save(params) { + params = $.extend({}, noops, params); + var self = this; + + if (!self.has_local_changes) { + console.log("Abort: no changes."); + return params['success'](self, false, "Nie ma zmian do zapisania."); + }; + + // Serialize form to dictionary + var data = {}; + $.each(params['form'].serializeArray(), function() { + data[this.name] = this.value; + }); + + data['textsave-text'] = self.text; + + self.saving = true; + $.ajax({ + url: reverse("ajax_document_text", self.id), + type: "POST", + dataType: "json", + data: data, + success: function(data) { + var changed = false; + + $('#header').removeClass('saving'); + + if (data.text) { + self.text = data.text; + self.revision = data.revision; + self.gallery = data.gallery; + changed = true; + self.triggerDocumentChanged(); + }; + self.saving = false; + + params['success'](self, changed, ((changed && "Udało się zapisać :)") || "Twoja wersja i serwera jest identyczna")); + }, + error: function(xhr) { + self.saving = false; + if ($('#header').hasClass('saving')) { + $('#header').removeClass('saving'); + $.blockUI({ + message: "

Nie udało się zapisać zmian.

" + }) + } + else { + try { + params['failure'](self, $.parseJSON(xhr.responseText)); + } + catch (e) { + params['failure'](self, { + "__message": "

Nie udało się zapisać - błąd serwera.

" + }); + }; + } + } + }); + + $('#save-hide').click(function(){ + $('#header').addClass('saving'); + $.unblockUI(); + $.wiki.blocking.unblock(); + }); + } /* end of save() */ + + revertToVersion(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.getLength = function(params) { - params = $.extend({}, noops, params); - var xml = this.text.replace(/\/(\s+)/g, '
$1'); - var parser = new DOMParser(); - var doc = parser.parseFromString(xml, 'text/xml'); - var error = $('parsererror', doc); + pubmark(params) { + params = $.extend({}, noops, params); + var self = this; + var data = { + "pubmark-id": self.id, + }; + + /* unpack form */ + $.each(params.form.serializeArray(), function() { + data[this.name] = this.value; + }); + + $.ajax({ + url: reverse("ajax_document_pubmark", self.id), + type: "POST", + dataType: "json", + data: data, + success: function(data) { + params.success(self, data.message); + }, + error: function(xhr) { + if (xhr.status == 403 || xhr.status == 401) { + params.failure(self, { + "__all__": ["Nie masz uprawnień lub nie jesteś zalogowany."] + }); + } + else { + try { + params.failure(self, $.parseJSON(xhr.responseText)); + } + catch (e) { + params.failure(self, { + "__all__": ["Nie udało się - błąd serwera."] + }); + }; + }; + } + }); + } - if (error.length > 0) { - throw "Not an XML document."; + refreshCover(params) { + var self = this; + var data = { + xml: self.text // TODO: send just DC + }; + $.ajax({ + url: reverse("ajax_cover_preview"), + type: "POST", + data: data, + success: function(data) { + params.success(data); + }, + error: function(xhr) { + // params.failure("Nie udało się odświeżyć okładki - błąd serwera."); + } + }); } - $.xmlns["rdf"] = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"; - $('rdf|RDF', doc).remove(); - if (params.noFootnotes) { - $('pa, pe, pr, pt', doc).remove(); + + getLength(params) { + params = $.extend({}, noops, params); + var xml = this.text.replace(/\/(\s+)/g, '
$1'); + var parser = new DOMParser(); + var doc = parser.parseFromString(xml, 'text/xml'); + var error = $('parsererror', doc); + + if (error.length > 0) { + throw "Not an XML document."; + } + $.xmlns["rdf"] = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"; + $('rdf|RDF', doc).remove(); + if (params.noFootnotes) { + $('pa, pe, pr, pt', doc).remove(); + } + if (params.noThemes) { + $('motyw', doc).remove(); + } + var text = $(doc).text(); + text = $.trim(text.replace(/\s{2,}/g, ' ')); + return text.length; } - if (params.noThemes) { - $('motyw', doc).remove(); + + /* Temporary workaround for relative images. */ + getBase() { + return '/media/dynamic/images/' + this.galleryLink + '/'; } - var text = $(doc).text(); - text = $.trim(text.replace(/\s{2,}/g, ' ')); - return text.length; } - /* Temporary workaround for relative images. */ - WikiDocument.prototype.getBase = function() { - return '/media/dynamic/images/' + this.galleryLink + '/'; - }; - - $.wikiapi.WikiDocument = WikiDocument; + $.wikiapi.WikiDocument = WikiDocument; })(jQuery);