1 /*globals Editor fileId SplitView PanelContainerView EditorView FlashView messageCenter*/
2 Editor.Model = Editor.Object.extend({
7 Editor.ToolbarButtonsModel = Editor.Model.extend({
8 className: 'Editor.ToolbarButtonsModel',
16 if (!this.get('buttons').length) {
18 url: documentInfo.toolbarURL,
20 success: this.loadSucceeded.bind(this)
25 loadSucceeded: function(data)
28 $.each(data, function() {
29 $.each(this.buttons, function() {
30 //do some lame escapes
31 this.tooltip = this.tooltip.replace(/"/g, """);
34 this.set('buttons', data);
41 // -> error -> loading
43 // empty -> loading -> synced -> unsynced -> loading
45 // -> dirty -> updating -> updated -> synced
47 Editor.XMLModel = Editor.Model.extend({
48 _className: 'Editor.XMLModel',
53 init: function(document, serverURL) {
55 this.set('state', 'empty');
56 this.set('revision', document.get('revision'));
57 this.document = document;
58 this.serverURL = serverURL;
59 this.toolbarButtonsModel = new Editor.ToolbarButtonsModel();
60 this.addObserver(this, 'data', this.dataChanged.bind(this));
63 load: function(force) {
64 if (force || this.get('state') == 'empty') {
65 this.set('state', 'loading');
66 messageCenter.addMessage('info', 'xmlload', 'Wczytuję XML...');
71 revision: this.get('revision'),
72 user: this.document.get('user')
74 success: this.loadingSucceeded.bind(this),
75 error: this.loadingFailed.bind(this)
82 loadingSucceeded: function(data) {
83 if (this.get('state') != 'loading') {
84 alert('erroneous state:', this.get('state'));
86 this.set('data', data);
87 this.set('state', 'synced');
88 messageCenter.addMessage('success', 'xmlload', 'Wczytałem XML :-)');
91 loadingFailed: function() {
92 if (this.get('state') != 'loading') {
93 alert('erroneous state:', this.get('state'));
95 var message = parseXHRError(response);
97 this.set('error', '<h2>Błąd przy ładowaniu XML</h2><p>'+message+'</p>');
98 this.set('state', 'error');
99 messageCenter.addMessage('error', 'xmlload', 'Nie udało mi się wczytać XML. Spróbuj ponownie :-(');
102 save: function(message) {
103 if (this.get('state') == 'dirty') {
104 this.set('state', 'updating');
105 messageCenter.addMessage('info', 'xmlsave', 'Zapisuję XML...');
108 contents: this.get('data'),
109 revision: this.get('revision'),
110 user: this.document.get('user')
113 payload.message = message;
121 success: this.saveSucceeded.bind(this),
122 error: this.saveFailed.bind(this)
129 saveSucceeded: function(data) {
130 if (this.get('state') != 'updating') {
131 alert('erroneous state:', this.get('state'));
133 this.set('revision', data.revision);
134 this.set('state', 'updated');
135 messageCenter.addMessage('success', 'xmlsave', 'Zapisałem XML :-)');
138 saveFailed: function() {
139 if (this.get('state') != 'updating') {
140 alert('erroneous state:', this.get('state'));
142 messageCenter.addMessage('error', 'xmlsave', 'Nie udało mi się zapisać XML. Spróbuj ponownie :-(');
143 this.set('state', 'dirty');
147 set: function(property, value) {
148 if (property == 'state') {
149 console.log(this.description(), ':', property, '=', value);
151 return this._super(property, value);
154 dataChanged: function(property, value) {
155 if (this.get('state') == 'synced') {
156 this.set('state', 'dirty');
160 dispose: function() {
161 this.removeObserver(this);
167 Editor.HTMLModel = Editor.Model.extend({
168 _className: 'Editor.HTMLModel',
176 init: function(document, dataURL, htmlURL) {
178 this.set('state', 'empty');
179 this.set('revision', document.get('revision'));
181 this.document = document;
182 this.htmlURL = htmlURL;
183 this.dataURL = dataURL;
184 this.renderURL = documentInfo.renderURL;
188 load: function(force) {
189 if (force || this.get('state') == 'empty') {
190 this.set('state', 'loading');
192 // load the transformed data
193 // messageCenter.addMessage('info', 'Wczytuję HTML...');
199 revision: this.get('revision'),
200 user: this.document.get('user')
202 success: this.loadingSucceeded.bind(this),
203 error: this.loadingFailed.bind(this)
208 loadingSucceeded: function(data) {
209 if (this.get('state') != 'loading') {
210 alert('erroneous state:', this.get('state'));
212 this.set('data', data);
213 this.set('state', 'synced');
216 loadingFailed: function(response) {
217 if (this.get('state') != 'loading') {
218 alert('erroneous state:', this.get('state'));
221 var message = parseXHRError(response);
223 this.set('error', '<p>Nie udało się wczytać widoku HTML: </p>' + message);
224 this.set('state', 'error');
227 getXMLPart: function(elem, callback)
229 var path = elem.attr('wl2o:path');
230 if(!this.xmlParts[path])
231 this.loadXMLPart(elem, callback);
233 callback(path, this.xmlParts[path]);
236 loadXMLPart: function(elem, callback)
238 var path = elem.attr('wl2o:path');
245 revision: this.get('revision'),
246 user: this.document.get('user'),
249 success: function(data) {
250 self.xmlParts[path] = data;
251 callback(path, data);
253 // TODO: error handling
254 error: function(data) {
255 console.log('Failed to load fragment');
256 callback(undefined, undefined);
261 putXMLPart: function(elem, data) {
264 var path = elem.attr('wl2o:path');
265 this.xmlParts[path] = data;
267 this.set('state', 'unsynced');
269 /* re-render the changed fragment */
273 dataType: 'text; charset=utf-8',
278 success: function(htmldata) {
279 elem.replaceWith(htmldata);
280 self.set('state', 'dirty');
285 save: function(message) {
286 if (this.get('state') == 'dirty') {
287 this.set('state', 'updating');
290 chunks: $.toJSON(this.xmlParts),
291 revision: this.get('revision'),
292 user: this.document.get('user')
296 payload.message = message;
306 success: this.saveSucceeded.bind(this),
307 error: this.saveFailed.bind(this)
315 saveSucceeded: function(data) {
316 if (this.get('state') != 'updating') {
317 alert('erroneous state:', this.get('state'));
323 this.set('revision', data.revision);
324 this.set('state', 'updated');
327 saveFailed: function() {
328 if (this.get('state') != 'updating') {
329 alert('erroneous state:', this.get('state'));
331 this.set('state', 'dirty');
335 set: function(property, value) {
336 if (property == 'state') {
337 console.log(this.description(), ':', property, '=', value);
339 return this._super(property, value);
344 Editor.ImageGalleryModel = Editor.Model.extend({
345 _className: 'Editor.ImageGalleryModel',
350 init: function(document, serverURL) {
352 this.set('state', 'empty');
353 this.serverURL = serverURL;
358 load: function(force) {
359 if (force || this.get('state') == 'empty') {
360 console.log("setting state");
361 this.set('state', 'loading');
362 console.log("going ajax");
366 success: this.loadingSucceeded.bind(this),
367 error: this.loadingFailed.bind(this)
372 loadingSucceeded: function(data)
374 console.log("success");
376 if (this.get('state') != 'loading') {
377 alert('erroneous state:', this.get('state'));
380 console.log('galleries:', data);
382 if (data.length === 0) {
383 this.set('data', []);
385 this.set('data', data[0].pages);
388 this.set('state', 'synced');
391 loadingFailed: function(data) {
392 console.log("failed");
394 if (this.get('state') != 'loading') {
395 alert('erroneous state:', this.get('state'));
398 this.set('state', 'error');
401 set: function(property, value) {
402 if (property == 'state') {
403 console.log(this.description(), ':', property, '=', value);
405 return this._super(property, value);
410 Editor.DocumentModel = Editor.Model.extend({
411 _className: 'Editor.DocumentModel',
412 data: null, // name, text_url, revision, latest_shared_rev, parts_url, dc_url, size, merge_url
421 this.set('state', 'empty');
425 if (this.get('state') == 'empty') {
426 this.set('state', 'loading');
427 messageCenter.addMessage('info', 'docload', 'Ładuję dane dokumentu...');
430 url: documentInfo.docURL,
432 success: this.successfulLoad.bind(this),
433 error: this.failedLoad.bind(this)
438 successfulLoad: function(data) {
439 this.set('data', data);
440 this.set('state', 'synced');
442 this.set('revision', data.revision);
443 this.set('user', data.user);
445 this.contentModels = {
446 'xml': new Editor.XMLModel(this, data.text_url),
447 'html': new Editor.HTMLModel(this, data.text_url, data.html_url),
448 'gallery': new Editor.ImageGalleryModel(this, data.gallery_url)
451 for (var key in this.contentModels) {
452 this.contentModels[key].addObserver(this, 'state', this.contentModelStateChanged.bind(this));
457 messageCenter.addMessage('success', 'docload', 'Dokument załadowany poprawnie :-)');
460 failedLoad: function(response) {
461 if (this.get('state') != 'loading') {
462 alert('erroneous state:', this.get('state'));
465 var message = parseXHRError(response);
466 this.set('error', '<h2>Nie udało się wczytać dokumentu</h2><p>'+message+"</p>");
467 this.set('state', 'error');
470 contentModelStateChanged: function(property, value, contentModel) {
471 if (value == 'dirty') {
472 this.set('state', 'dirty');
473 for (var key in this.contentModels) {
474 if (this.contentModels[key].guid() != contentModel.guid()) {
475 this.contentModels[key].set('state', 'unsynced');
478 } else if (value == 'updated') {
479 this.set('state', 'synced');
480 for (key in this.contentModels) {
481 if (this.contentModels[key].guid() == contentModel.guid()) {
482 this.contentModels[key].set('state', 'synced');
483 this.revision = this.contentModels[key].get('revision');
487 for (key in this.contentModels) {
488 if (this.contentModels[key].guid() != contentModel.guid()) {
489 this.contentModels[key].set('revision', this.revision);
490 this.contentModels[key].set('state', 'empty');
496 saveDirtyContentModel: function(message) {
497 for (var key in this.contentModels) {
498 if (this.contentModels[key].get('state') == 'dirty') {
499 this.contentModels[key].save(message);
506 this.set('state', 'loading');
508 messageCenter.addMessage('info', 'doc_update',
509 'Uaktualniam dokument...');
512 url: this.data.merge_url,
517 revision: this.get('revision'),
518 user: this.get('user')
520 complete: this.updateCompleted.bind(this),
521 success: function(data) {
522 this.set('updateData', data);
523 console.log("new data:", data)
528 updateCompleted: function(xhr, textStatus) {
529 console.log(xhr.status, textStatus);
531 if (xhr.status == 200)
533 var udata = this.get('updateData');
534 if(udata.timestamp == udata.parent_timestamp)
537 messageCenter.addMessage('info', 'doc_update',
538 'Nic się nie zmieniło od ostatniej aktualizacji. Po co mam uaktualniać?');
542 this.set('revision', udata.revision);
543 this.set('user', udata.user);
544 messageCenter.addMessage('info', 'doc_update',
545 'Uaktualnienie dokumentu do wersji ' + udata.revision);
547 for (var key in this.contentModels) {
548 this.contentModels[key].set('revision', this.get('revision') );
549 this.contentModels[key].set('state', 'empty');
552 } else if (xhr.status == 409) { // Konflikt podczas operacji
553 messageCenter.addMessage('error', 'doc_update',
554 'Wystąpił konflikt podczas aktualizacji. Pędź po programistów! :-(');
556 messageCenter.addMessage('critical', 'doc_update',
557 'Nieoczekiwany błąd. Pędź po programistów! :-(');
560 this.set('state', 'synced');
561 this.set('updateData', null);
564 merge: function(message) {
565 this.set('state', 'loading');
566 messageCenter.addMessage('info', null,
567 'Scalam dokument z głównym repozytorium...');
570 url: this.data.merge_url,
575 revision: this.get('revision'),
576 user: this.get('user'),
579 complete: this.mergeCompleted.bind(this),
580 success: function(data) {
581 this.set('mergeData', data);
586 mergeCompleted: function(xhr, textStatus) {
587 console.log(xhr.status, textStatus);
588 if (xhr.status == 200) { // Sukces
589 this.set('revision', this.get('updateData').revision);
590 this.set('user', this.get('updateData').user);
592 for (var key in this.contentModels) {
593 this.contentModels[key].set('revision', this.get('revision'));
594 this.contentModels[key].set('state', 'empty');
597 messageCenter.addMessage('success', null, 'Scaliłem dokument z głównym repozytorium :-)');
598 } else if (xhr.status == 202) { // Wygenerowano PullRequest
599 messageCenter.addMessage('success', null, 'Wysłałem prośbę o scalenie dokumentu z głównym repozytorium.');
600 } else if (xhr.status == 204) { // Nic nie zmieniono
601 messageCenter.addMessage('info', null, 'Nic się nie zmieniło od ostatniego scalenia. Po co mam scalać?');
602 } else if (xhr.status == 409) { // Konflikt podczas operacji
603 messageCenter.addMessage('error', null, 'Wystąpił konflikt podczas scalania. Pędź po programistów! :-(');
604 } else if (xhr.status == 500) {
605 messageCenter.addMessage('critical', null, 'Błąd serwera. Pędź po programistów! :-(');
607 this.set('state', 'synced');
608 this.set('mergeData', null);
612 set: function(property, value) {
613 if (property == 'state') {
614 console.log(this.description(), ':', property, '=', value);
616 return this._super(property, value);
621 var leftPanelView, rightPanelContainer, doc;
625 var flashView = new FlashView('#flashview', messageCenter);
627 doc = new Editor.DocumentModel();
629 EditorView = new EditorView('#body-wrap', doc);
630 EditorView.freeze("<h1>Wczytuję dokument...</h1>");
632 leftPanelView = new PanelContainerView('#left-panel-container', doc);
633 rightPanelContainer = new PanelContainerView('#right-panel-container', doc);