move xml check to celery,
[redakcja.git] / redakcja / static / js / wiki / wikiapi.js
1 (function($) {
2         $.wikiapi = {};
3         var noop = function() {
4         };
5         var noops = {
6                 success: noop,
7                 failure: noop
8         };
9         /*
10          * Return absolute reverse path of given named view. (at least he have it
11          * hard-coded in one place)
12          *
13          * TODO: think of a way, not to hard-code it here ;)
14          *
15          */
16         function reverse() {
17                 var vname = arguments[0];
18                 var base_path = "/editor";
19
20                 if (vname == "ajax_document_text") {
21                         var path = "/text/" + arguments[1] + '/';
22
23                 if (arguments[2] !== undefined)
24                                 path += arguments[2] + '/';
25
26                         return base_path + path;
27                 }
28
29         if (vname == "ajax_document_revert") {
30             return base_path + "/revert/" + arguments[1] + '/';
31         }
32
33
34                 if (vname == "ajax_document_history") {
35
36                         return base_path + "/history/" + arguments[1] + '/';
37                 }
38
39                 if (vname == "ajax_document_gallery") {
40
41                         return base_path + "/gallery/" + arguments[1] + '/';
42                 }
43
44                 if (vname == "ajax_document_diff")
45                         return base_path + "/diff/" + arguments[1] + '/';
46
47         if (vname == "ajax_document_rev")
48             return base_path + "/rev/" + arguments[1] + '/';
49
50                 if (vname == "ajax_document_pubmark")
51                         return base_path + "/pubmark/" + arguments[1] + '/';
52
53                 console.log("Couldn't reverse match:", vname);
54                 return "/404.html";
55         };
56
57         /*
58          * Document Abstraction
59          */
60         function WikiDocument(element_id) {
61                 var meta = $('#' + element_id);
62                 this.id = meta.attr('data-chunk-id');
63
64                 this.revision = $("*[data-key='revision']", meta).text();
65                 this.readonly = !!$("*[data-key='readonly']", meta).text();
66
67                 this.galleryLink = $("*[data-key='gallery']", meta).text();
68         this.galleryStart = parseInt($("*[data-key='gallery-start']", meta).text());
69
70         var diff = $("*[data-key='diff']", meta).text();
71         if (diff) {
72             diff = diff.split(',');
73             if (diff.length == 2 && diff[0] < diff[1])
74                 this.diff = diff;
75             else if (diff.length == 1) {
76                 diff = parseInt(diff);
77                 if (diff != NaN)
78                     this.diff = [diff - 1, diff];
79             }
80         }
81
82                 this.galleryImages = [];
83                 this.text = null;
84                 this.has_local_changes = false;
85                 this._lock = -1;
86                 this._context_lock = -1;
87                 this._lock_count = 0;
88         };
89
90         WikiDocument.prototype.triggerDocumentChanged = function() {
91                 $(document).trigger('wlapi_document_changed', this);
92         };
93         /*
94          * Fetch text of this document.
95          */
96         WikiDocument.prototype.fetch = function(params) {
97                 params = $.extend({}, noops, params);
98                 var self = this;
99                 $.ajax({
100                         method: "GET",
101                         url: reverse("ajax_document_text", self.id),
102                         data: {"revision": self.revision},
103                         dataType: 'json',
104                         success: function(data) {
105                                 var changed = false;
106
107                                 if (self.text === null || self.revision !== data.revision) {
108                                         self.text = data.text;
109                                         self.revision = data.revision;
110                                         self.gallery = data.gallery;
111                                         changed = true;
112                                         self.triggerDocumentChanged();
113                                 };
114
115                                 self.has_local_changes = false;
116                                 params['success'](self, changed);
117                         },
118                         error: function() {
119                                 params['failure'](self, "Nie udało się wczytać treści dokumentu.");
120                         }
121                 });
122         };
123         /*
124          * Fetch history of this document.
125          *
126          * from - First revision to fetch (default = 0) upto - Last revision to
127          * fetch (default = tip)
128          *
129          */
130         WikiDocument.prototype.fetchHistory = function(params) {
131                 /* this doesn't modify anything, so no locks */
132                 params = $.extend({}, noops, params);
133                 var self = this;
134                 $.ajax({
135                         method: "GET",
136                         url: reverse("ajax_document_history", self.id),
137                         dataType: 'json',
138                         data: {
139                                 "from": params['from'],
140                                 "upto": params['upto']
141                         },
142                         success: function(data) {
143                                 params['success'](self, data);
144                         },
145                         error: function() {
146                                 params['failure'](self, "Nie udało się wczytać historii dokumentu.");
147                         }
148                 });
149         };
150         WikiDocument.prototype.fetchDiff = function(params) {
151                 /* this doesn't modify anything, so no locks */
152                 var self = this;
153                 params = $.extend({
154                         'from': self.revision,
155                         'to': self.revision
156                 }, noops, params);
157                 $.ajax({
158                         method: "GET",
159                         url: reverse("ajax_document_diff", self.id),
160                         dataType: 'html',
161                         data: {
162                                 "from": params['from'],
163                                 "to": params['to']
164                         },
165                         success: function(data) {
166                                 params['success'](self, data);
167                         },
168                         error: function() {
169                                 params['failure'](self, "Nie udało się wczytać porównania wersji.");
170                         }
171                 });
172         };
173
174     WikiDocument.prototype.checkRevision = function(params) {
175         /* this doesn't modify anything, so no locks */
176         var self = this;
177         $.ajax({
178             method: "GET",
179             url: reverse("ajax_document_rev", self.id),
180             dataType: 'text',
181             success: function(data) {
182                 if (data == '') {
183                     if (params.error)
184                         params.error();
185                 }
186                 else if (data != self.revision)
187                     params.outdated();
188             }
189         });
190     };
191
192         /*
193          * Fetch gallery
194          */
195         WikiDocument.prototype.refreshGallery = function(params) {
196                 params = $.extend({}, noops, params);
197                 var self = this;
198                 $.ajax({
199                         method: "GET",
200                         url: reverse("ajax_document_gallery", self.galleryLink),
201                         dataType: 'json',
202                         // data: {},
203                         success: function(data) {
204                                 self.galleryImages = data;
205                                 params['success'](self, data);
206                         },
207                         error: function() {
208                                 self.galleryImages = [];
209                                 params['failure'](self, "<p>Nie udało się wczytać galerii pod nazwą: '" + self.galleryLink + "'.</p>");
210                         }
211                 });
212         };
213
214         /*
215          * Set document's text
216          */
217         WikiDocument.prototype.setText = function(text) {
218                 this.text = text;
219                 this.has_local_changes = true;
220         };
221
222         /*
223          * Set document's gallery link
224          */
225         WikiDocument.prototype.setGalleryLink = function(gallery) {
226                 this.galleryLink = gallery;
227                 this.has_local_changes = true;
228         };
229
230         /*
231          * Save text back to the server
232          */
233         WikiDocument.prototype.save = function(params) {
234                 params = $.extend({}, noops, params);
235                 var self = this;
236
237                 if (!self.has_local_changes) {
238                         console.log("Abort: no changes.");
239                         return params['success'](self, false, "Nie ma zmian do zapisania.");
240                 };
241
242                 // Serialize form to dictionary
243                 var data = {};
244                 $.each(params['form'].serializeArray(), function() {
245                         data[this.name] = this.value;
246                 });
247
248                 data['textsave-text'] = self.text;
249
250                 $.ajax({
251                         url: reverse("ajax_document_text", self.id),
252                         type: "POST",
253                         dataType: "json",
254                         data: data,
255                         success: function(data) {
256                                 var changed = false;
257
258                 $('#header').removeClass('saving');
259
260                                 if (data.text) {
261                                         self.text = data.text;
262                                         self.revision = data.revision;
263                                         self.gallery = data.gallery;
264                                         changed = true;
265                                         self.triggerDocumentChanged();
266                                 };
267
268                                 params['success'](self, changed, ((changed && "Udało się zapisać :)") || "Twoja wersja i serwera jest identyczna"));
269                         },
270                         error: function(xhr) {
271                 if ($('#header').hasClass('saving')) {
272                     $('#header').removeClass('saving');
273                     $.blockUI({
274                         message: "<p>Nie udało się zapisać zmian. <br/><button onclick='$.unblockUI()'>OK</button></p>"
275                     })
276                 }
277                 else {
278                     try {
279                         params['failure'](self, $.parseJSON(xhr.responseText));
280                     }
281                     catch (e) {
282                         params['failure'](self, {
283                             "__message": "<p>Nie udało się zapisać - błąd serwera.</p>"
284                         });
285                     };
286                 }
287
288                         }
289                 });
290
291         $('#save-hide').click(function(){
292             $('#header').addClass('saving');
293             $.unblockUI();
294             $.wiki.blocking.unblock();
295         });
296         }; /* end of save() */
297
298     WikiDocument.prototype.revertToVersion = function(params) {
299         var self = this;
300         params = $.extend({}, noops, params);
301
302         if (params.revision >= this.revision) {
303             params.failure(self, 'Proszę wybrać rewizję starszą niż aktualna.');
304             return;
305         }
306
307         // Serialize form to dictionary
308         var data = {};
309         $.each(params['form'].serializeArray(), function() {
310             data[this.name] = this.value;
311         });
312
313         $.ajax({
314             url: reverse("ajax_document_revert", self.id),
315             type: "POST",
316             dataType: "json",
317             data: data,
318             success: function(data) {
319                 if (data.text) {
320                     self.text = data.text;
321                     self.revision = data.revision;
322                     self.gallery = data.gallery;
323                     self.triggerDocumentChanged();
324
325                     params.success(self, "Udało się przywrócić wersję :)");
326                 }
327                 else {
328                     params.failure(self, "Przywracana wersja identyczna z aktualną. Anulowano przywracanie.");
329                 }
330             },
331             error: function(xhr) {
332                 params.failure(self, "Nie udało się przywrócić wersji - błąd serwera.");
333             }
334         });
335     };
336
337         WikiDocument.prototype.publish = function(params) {
338                 params = $.extend({}, noops, params);
339                 var self = this;
340                 $.ajax({
341                         url: reverse("ajax_publish", self.id),
342                         type: "POST",
343                         dataType: "json",
344                         success: function(data) {
345                                 params.success(self, data);
346                         },
347                         error: function(xhr) {
348                                 if (xhr.status == 403 || xhr.status == 401) {
349                                         params.failure(self, "Nie masz uprawnień lub nie jesteś zalogowany.");
350                                 }
351                                 else {
352                                         try {
353                                                 params.failure(self, xhr.responseText);
354                                         }
355                                         catch (e) {
356                                                 params.failure(self, "Nie udało się - błąd serwera.");
357                                         };
358                                 };
359
360                         }
361                 });
362         };
363
364         WikiDocument.prototype.pubmark = function(params) {
365                 params = $.extend({}, noops, params);
366                 var self = this;
367                 var data = {
368                         "pubmark-id": self.id,
369                 };
370
371                 /* unpack form */
372                 $.each(params.form.serializeArray(), function() {
373                         data[this.name] = this.value;
374                 });
375
376                 $.ajax({
377                         url: reverse("ajax_document_pubmark", self.id),
378                         type: "POST",
379                         dataType: "json",
380                         data: data,
381                         success: function(data) {
382                                 params.success(self, data.message);
383                         },
384                         error: function(xhr) {
385                                 if (xhr.status == 403 || xhr.status == 401) {
386                                         params.failure(self, {
387                                                 "__all__": ["Nie masz uprawnień lub nie jesteś zalogowany."]
388                                         });
389                                 }
390                                 else {
391                                         try {
392                                                 params.failure(self, $.parseJSON(xhr.responseText));
393                                         }
394                                         catch (e) {
395                                                 params.failure(self, {
396                                                         "__all__": ["Nie udało się - błąd serwera."]
397                                                 });
398                                         };
399                                 };
400                         }
401                 });
402         };
403
404     WikiDocument.prototype.getLength = function(params) {
405         var xml = this.text.replace(/\/(\s+)/g, '<br />$1');
406         var parser = new DOMParser();
407         var doc = parser.parseFromString(xml, 'text/xml');
408         var error = $('parsererror', doc);
409
410         if (error.length > 0) {
411             throw "Not an XML document.";
412         }
413         $.xmlns["rdf"] = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"; 
414         $('rdf|RDF, motyw, pa, pe, pr, pt', doc).remove();
415         var text = $(doc).text();
416         text = $.trim(text.replace(/\s{2,}/g, ' '));
417         return text.length;
418     }
419
420
421         $.wikiapi.WikiDocument = WikiDocument;
422 })(jQuery);