84f0af8f11f925ab83423b92f55a8427146793b0
[fnpeditor.git] / src / editor / modules / data / data.js
1 define([
2     'libs/jquery',
3     './dialog',
4     'wlxml/wlxml',
5     'wlxml/extensions/list/list',
6     'fnpjs/logging/logging',
7 ], function($, Dialog, wlxml, listExtension, logging) {
8
9 'use strict';
10 /* global gettext, alert, window */
11
12 var logger = logging.getLogger('editor.modules.data'),
13     stubDocument = '<section><div>' + gettext('This is an empty document.') + '</div></section>';
14
15
16 return function(sandbox) {
17
18     var document_id = sandbox.getBootstrappedData().document_id;
19     var document_version = sandbox.getBootstrappedData().version;
20     var history = sandbox.getBootstrappedData().history;
21     var documentDirty = false;
22     var draftDirty = false;
23
24     var wlxmlDocument, text;
25
26     var loadDocument = function(text) {
27         logger.debug('loading document');
28         try {
29             wlxmlDocument = wlxml.WLXMLDocumentFromXML(text);
30         } catch(e) {
31             logger.exception(e);
32             alert(gettext('This document contains errors and can\'t be loaded. :(')); // TODO
33             wlxmlDocument = wlxml.WLXMLDocumentFromXML(stubDocument);
34         }
35
36         wlxmlDocument.registerExtension(listExtension);
37         sandbox.getPlugins().forEach(function(plugin) {
38             if(plugin.documentExtension) {
39                 wlxmlDocument.registerExtension(plugin.documentExtension);
40             }
41         });
42         
43         var modificationFlag = true;
44         wlxmlDocument.on('change', function() {
45             documentDirty = true;
46             draftDirty = true;
47             modificationFlag = true;
48         });
49         if(window.localStorage) {
50             window.setInterval(function() {
51                 if(modificationFlag) {
52                     modificationFlag = false;
53                     return;
54                 }
55                 if(wlxmlDocument && documentDirty && draftDirty) {
56                     logger.debug('Saving draft to local storage.');
57                     sandbox.publish('savingStarted', 'local');
58                     window.localStorage.setItem(getLocalStorageKey(), wlxmlDocument.toXML());
59                     sandbox.publish('savingEnded', 'success', 'local');
60                     draftDirty = false;
61                 }
62             }, sandbox.getConfig().autoSaveInterval || 2500);
63         }
64         sandbox.publish('ready');
65     };
66     
67     function readCookie(name) {
68         /* global escape, unescape, document */
69         var nameEQ = escape(name) + '=';
70         var ca = document.cookie.split(';');
71         for (var i = 0; i < ca.length; i++) {
72             var c = ca[i];
73             while (c.charAt(0) === ' ') {
74                 c = c.substring(1, c.length);
75             }
76             if (c.indexOf(nameEQ) === 0) {
77                 return unescape(c.substring(nameEQ.length, c.length));
78             }
79         }
80         return null;
81     }
82     
83     $.ajaxSetup({
84         crossDomain: false,
85         beforeSend: function(xhr, settings) {
86             if (!(/^(GET|HEAD|OPTIONS|TRACE)$/.test(settings.type))) {
87                 xhr.setRequestHeader('X-CSRFToken', readCookie('csrftoken'));
88             }
89         }
90     });
91     
92     var reloadHistory = function() {
93         $.ajax({
94             method: 'get',
95             url: sandbox.getConfig().documentHistoryUrl(document_id),
96             success: function(data) {
97                 history = data;
98                 sandbox.publish('historyItemAdded', data.slice(-1)[0]);
99             },
100         });
101     };
102
103     var getLocalStorageKey = function() {
104         return 'draft-id:' + document_id + '-ver:' + document_version;
105     };
106
107    
108     return {
109         start: function() {
110
111             if(window.localStorage) {
112                 text = window.localStorage.getItem(getLocalStorageKey());
113                 if(text) {
114                     logger.debug('Local draft exists');
115                     var dialog = Dialog.create({
116                         title: gettext('Local draft of a document exists'),
117                         text: gettext('Unsaved local draft of this version of the document exists in your browser. Do you want to load it instead?'),
118                         executeButtonText: gettext('Yes, restore local draft'),
119                         cancelButtonText: gettext('No, use version loaded from the server')
120                     });
121                     dialog.on('cancel', function() {
122                         logger.debug('Bootstrapped version chosen');
123                         text = sandbox.getBootstrappedData().document;
124                         
125                     });
126                     dialog.on('execute', function(event) {
127                         logger.debug('Local draft chosen');
128                         event.success();
129                     });
130                     dialog.show();
131                     dialog.on('close', function() {
132                         loadDocument(text);
133                     });
134                 } else {
135                     loadDocument(sandbox.getBootstrappedData().document);
136                 }
137             } else {
138                 loadDocument(sandbox.getBootstrappedData().document);
139             }
140         },
141         getDocument: function() {
142             return wlxmlDocument;
143         },
144         saveDocument: function() {
145             var documentSaveForm = $.extend({
146                         fields: [],
147                         content_field_name: 'text',
148                         version_field_name: 'version'
149                     },
150                     sandbox.getConfig().documentSaveForm
151                 ),
152                 dialog = Dialog.create({
153                     fields: documentSaveForm.fields,
154                     title: gettext('Save Document'),
155                     executeButtonText: gettext('Save')
156                 });
157             
158             dialog.on('execute', function(event) {
159                 sandbox.publish('savingStarted', 'remote');
160
161                 var formData = event.formData;
162                 formData[documentSaveForm.content_field_name] = wlxmlDocument.toXML();
163                 formData[documentSaveForm.version_field_name] = document_version;
164                 if(sandbox.getConfig().jsonifySentData) {
165                     formData = JSON.stringify(formData);
166                 }
167
168                 dialog.toggleButtons(false);
169                 $.ajax({
170                     method: 'post',
171                     url: sandbox.getConfig().documentSaveUrl(document_id),
172                     data: formData,
173                     success: function(data) {
174                         event.success();
175                         sandbox.publish('savingEnded', 'success', 'remote', data.version);
176                         document_version = data.version;
177                         reloadHistory();
178                     },
179                     error: function() {event.error(); sandbox.publish('savingEnded', 'error', 'remote');}
180                 });
181             });
182             dialog.on('cancel', function() {
183             });
184             dialog.show();
185             
186
187         },
188         getHistory: function() {
189             return history;
190         },
191         fetchDiff: function(ver1, ver2) {
192             $.ajax({
193                 method: 'get',
194                 url: sandbox.getConfig().documentDiffUrl(document_id),
195                 data: {from: ver1, to: ver2},
196                 success: function(data) {
197                     sandbox.publish('diffFetched', {table: data, ver1: ver1, ver2: ver2});
198                 },
199             });
200         },
201         restoreVersion: function(version) {
202             var documentRestoreForm = $.extend({
203                         fields: [],
204                         version_field_name: 'version'
205                     },
206                     sandbox.getConfig().documentRestoreForm
207                 ),
208                 dialog = Dialog.create({
209                     fields: documentRestoreForm.fields,
210                     title: gettext('Restore Version'),
211                     executeButtonText: gettext('Restore')
212                 });
213
214             dialog.on('execute', function(event) {
215                 var formData = event.formData;
216                 formData[documentRestoreForm.version_field_name] = version;
217                 sandbox.publish('restoringStarted', {version: version});
218                 if(sandbox.getConfig().jsonifySentData) {
219                     formData = JSON.stringify(formData);
220                 }
221                 $.ajax({
222                     method: 'post',
223                     dataType: 'json',
224                     url: sandbox.getConfig().documentRestoreUrl(document_id),
225                     data: formData,
226                     success: function(data) {
227                         document_version = data.version;
228                         reloadHistory();
229                         wlxmlDocument.loadXML(data.document);
230                         documentDirty = false;
231                         sandbox.publish('documentReverted', data.version);
232                         event.success();
233                     },
234                 });
235             });
236             dialog.show();
237         },
238         getDocumentId: function() {
239             return document_id;
240         },
241         getDocumentVersion: function() {
242             return document_version;
243         }
244     };
245 };
246
247 });