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(serverURL) {
352 this.set('state', 'empty');
353 this.serverURL = serverURL;
358 load: function(force) {
359 if (force || this.get('state') == 'empty') {
360 this.set('state', 'loading');
364 success: this.loadingSucceeded.bind(this)
369 loadingSucceeded: function(data) {
370 if (this.get('state') != 'loading') {
371 alert('erroneous state:', this.get('state'));
374 console.log('galleries:', data);
376 if (data.length === 0) {
377 this.set('data', []);
379 this.set('data', data[0].pages);
382 this.set('state', 'synced');
385 set: function(property, value) {
386 if (property == 'state') {
387 console.log(this.description(), ':', property, '=', value);
389 return this._super(property, value);
394 Editor.DocumentModel = Editor.Model.extend({
395 _className: 'Editor.DocumentModel',
396 data: null, // name, text_url, revision, latest_shared_rev, parts_url, dc_url, size, merge_url
405 this.set('state', 'empty');
409 if (this.get('state') == 'empty') {
410 this.set('state', 'loading');
411 messageCenter.addMessage('info', 'docload', 'Ładuję dane dokumentu...');
414 url: documentInfo.docURL,
416 success: this.successfulLoad.bind(this),
417 error: this.failedLoad.bind(this)
422 successfulLoad: function(data) {
423 this.set('data', data);
424 this.set('state', 'synced');
426 this.set('revision', data.revision);
427 this.set('user', data.user);
429 this.contentModels = {
430 'xml': new Editor.XMLModel(this, data.text_url),
431 'html': new Editor.HTMLModel(this, data.text_url, data.html_url),
432 'gallery': new Editor.ImageGalleryModel(this, data.gallery_url)
435 for (var key in this.contentModels) {
436 this.contentModels[key].addObserver(this, 'state', this.contentModelStateChanged.bind(this));
441 messageCenter.addMessage('success', 'docload', 'Dokument załadowany poprawnie :-)');
444 failedLoad: function(response) {
445 if (this.get('state') != 'loading') {
446 alert('erroneous state:', this.get('state'));
449 var message = parseXHRError(response);
450 this.set('error', '<h2>Nie udało się wczytać dokumentu</h2><p>'+message+"</p>");
451 this.set('state', 'error');
454 contentModelStateChanged: function(property, value, contentModel) {
455 if (value == 'dirty') {
456 this.set('state', 'dirty');
457 for (var key in this.contentModels) {
458 if (this.contentModels[key].guid() != contentModel.guid()) {
459 this.contentModels[key].set('state', 'unsynced');
462 } else if (value == 'updated') {
463 this.set('state', 'synced');
464 for (key in this.contentModels) {
465 if (this.contentModels[key].guid() == contentModel.guid()) {
466 this.contentModels[key].set('state', 'synced');
467 this.revision = this.contentModels[key].get('revision');
471 for (key in this.contentModels) {
472 if (this.contentModels[key].guid() != contentModel.guid()) {
473 this.contentModels[key].set('revision', this.revision);
474 this.contentModels[key].set('state', 'empty');
480 saveDirtyContentModel: function(message) {
481 for (var key in this.contentModels) {
482 if (this.contentModels[key].get('state') == 'dirty') {
483 this.contentModels[key].save(message);
490 this.set('state', 'loading');
492 messageCenter.addMessage('info', 'doc_update',
493 'Uaktualniam dokument...');
496 url: this.data.merge_url,
501 revision: this.get('revision'),
502 user: this.get('user')
504 complete: this.updateCompleted.bind(this),
505 success: function(data) {
506 this.set('updateData', data);
507 console.log("new data:", data)
512 updateCompleted: function(xhr, textStatus) {
513 console.log(xhr.status, textStatus);
515 if (xhr.status == 200)
517 var udata = this.get('updateData');
518 if(udata.timestamp == udata.parent_timestamp)
521 messageCenter.addMessage('info', 'doc_update',
522 'Nic się nie zmieniło od ostatniej aktualizacji. Po co mam uaktualniać?');
526 this.set('revision', udata.revision);
527 this.set('user', udata.user);
528 messageCenter.addMessage('info', 'doc_update',
529 'Uaktualnienie dokumentu do wersji ' + udata.revision);
531 for (var key in this.contentModels) {
532 this.contentModels[key].set('revision', this.get('revision') );
533 this.contentModels[key].set('state', 'empty');
536 } else if (xhr.status == 409) { // Konflikt podczas operacji
537 messageCenter.addMessage('error', 'doc_update',
538 'Wystąpił konflikt podczas aktualizacji. Pędź po programistów! :-(');
540 messageCenter.addMessage('critical', 'doc_update',
541 'Nieoczekiwany błąd. Pędź po programistów! :-(');
544 this.set('state', 'synced');
545 this.set('updateData', null);
548 merge: function(message) {
549 this.set('state', 'loading');
550 messageCenter.addMessage('info', null,
551 'Scalam dokument z głównym repozytorium...');
554 url: this.data.merge_url,
559 revision: this.get('revision'),
560 user: this.get('user'),
563 complete: this.mergeCompleted.bind(this),
564 success: function(data) {
565 this.set('mergeData', data);
570 mergeCompleted: function(xhr, textStatus) {
571 console.log(xhr.status, textStatus);
572 if (xhr.status == 200) { // Sukces
573 this.set('revision', this.get('updateData').revision);
574 this.set('user', this.get('updateData').user);
576 for (var key in this.contentModels) {
577 this.contentModels[key].set('revision', this.get('revision'));
578 this.contentModels[key].set('state', 'empty');
581 messageCenter.addMessage('success', null, 'Scaliłem dokument z głównym repozytorium :-)');
582 } else if (xhr.status == 202) { // Wygenerowano PullRequest
583 messageCenter.addMessage('success', null, 'Wysłałem prośbę o scalenie dokumentu z głównym repozytorium.');
584 } else if (xhr.status == 204) { // Nic nie zmieniono
585 messageCenter.addMessage('info', null, 'Nic się nie zmieniło od ostatniego scalenia. Po co mam scalać?');
586 } else if (xhr.status == 409) { // Konflikt podczas operacji
587 messageCenter.addMessage('error', null, 'Wystąpił konflikt podczas scalania. Pędź po programistów! :-(');
588 } else if (xhr.status == 500) {
589 messageCenter.addMessage('critical', null, 'Błąd serwera. Pędź po programistów! :-(');
591 this.set('state', 'synced');
592 this.set('mergeData', null);
596 set: function(property, value) {
597 if (property == 'state') {
598 console.log(this.description(), ':', property, '=', value);
600 return this._super(property, value);
605 var leftPanelView, rightPanelContainer, doc;
609 var flashView = new FlashView('#flashview', messageCenter);
611 doc = new Editor.DocumentModel();
613 EditorView = new EditorView('#body-wrap', doc);
614 EditorView.freeze("<h1>Wczytuję dokument...</h1>");
616 leftPanelView = new PanelContainerView('#left-panel-container', doc);
617 rightPanelContainer = new PanelContainerView('#right-panel-container', doc);