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(response)
93 if (this.get('state') != 'loading') {
94 alert('erroneous state:', this.get('state'));
97 var message = parseXHRError(response);
99 this.set('error', '<h2>Błąd przy ładowaniu XML</h2><p>'+message+'</p>');
100 this.set('state', 'error');
101 messageCenter.addMessage('error', 'xmlload', 'Nie udało mi się wczytać XML. Spróbuj ponownie :-(');
104 save: function(message) {
105 if (this.get('state') == 'dirty') {
106 this.set('state', 'updating');
107 messageCenter.addMessage('info', 'xmlsave', 'Zapisuję XML...');
110 contents: this.get('data'),
111 revision: this.get('revision'),
112 user: this.document.get('user')
115 payload.message = message;
123 success: this.saveSucceeded.bind(this),
124 error: this.saveFailed.bind(this)
131 saveSucceeded: function(data) {
132 if (this.get('state') != 'updating') {
133 alert('erroneous state:', this.get('state'));
135 this.set('revision', data.revision);
136 this.set('state', 'updated');
137 messageCenter.addMessage('success', 'xmlsave', 'Zapisałem XML :-)');
140 saveFailed: function() {
141 if (this.get('state') != 'updating') {
142 alert('erroneous state:', this.get('state'));
144 messageCenter.addMessage('error', 'xmlsave', 'Nie udało mi się zapisać XML. Spróbuj ponownie :-(');
145 this.set('state', 'dirty');
149 set: function(property, value) {
150 if (property == 'state') {
151 console.log(this.description(), ':', property, '=', value);
153 return this._super(property, value);
156 dataChanged: function(property, value) {
157 if (this.get('state') == 'synced') {
158 this.set('state', 'dirty');
162 dispose: function() {
163 this.removeObserver(this);
169 Editor.HTMLModel = Editor.Model.extend({
170 _className: 'Editor.HTMLModel',
178 init: function(document, dataURL, htmlURL) {
180 this.set('state', 'empty');
181 this.set('revision', document.get('revision'));
183 this.document = document;
184 this.htmlURL = htmlURL;
185 this.dataURL = dataURL;
186 this.renderURL = documentInfo.renderURL;
190 load: function(force) {
191 if (force || this.get('state') == 'empty') {
192 this.set('state', 'loading');
194 // load the transformed data
195 // messageCenter.addMessage('info', 'Wczytuję HTML...');
201 revision: this.get('revision'),
202 user: this.document.get('user')
204 success: this.loadingSucceeded.bind(this),
205 error: this.loadingFailed.bind(this)
210 loadingSucceeded: function(data) {
211 if (this.get('state') != 'loading') {
212 alert('erroneous state:', this.get('state'));
214 this.set('data', data);
215 this.set('state', 'synced');
218 loadingFailed: function(response) {
219 if (this.get('state') != 'loading') {
220 alert('erroneous state:', this.get('state'));
223 var err = parseXHRError(response);
225 this.set('error', '<p>Nie udało się wczytać widoku HTML: </p>' + err.error_message);
226 this.set('state', 'error');
229 getXMLPart: function(elem, callback)
231 var path = elem.attr('x-pointer');
232 if(!this.xmlParts[path])
233 this.loadXMLPart(elem, callback);
235 callback(path, this.xmlParts[path]);
238 loadXMLPart: function(elem, callback)
240 var path = elem.attr('x-pointer');
247 revision: this.get('revision'),
248 user: this.document.get('user'),
252 success: function(data) {
253 self.xmlParts[path] = data;
255 callback(path, data);
257 // TODO: error handling
258 error: function(data) {
259 console.log('Failed to load fragment');
260 callback(undefined, undefined);
265 putXMLPart: function(elem, data, callback) {
268 var path = elem.attr('x-pointer');
269 this.xmlParts[path] = data;
271 this.set('state', 'dirty');
273 /* re-render the changed fragment */
277 dataType: 'text; charset=utf-8',
283 success: function(htmldata) {
284 callback(elem, htmldata);
285 self.set('state', 'dirty');
290 save: function(message) {
291 if (this.get('state') == 'dirty') {
292 this.set('state', 'updating');
295 chunks: $.toJSON(this.xmlParts),
296 revision: this.get('revision'),
297 user: this.document.get('user')
301 payload.message = message;
311 success: this.saveSucceeded.bind(this),
312 error: this.saveFailed.bind(this)
320 saveSucceeded: function(data) {
321 if (this.get('state') != 'updating') {
322 alert('erroneous state:', this.get('state'));
328 this.set('revision', data.revision);
329 this.set('state', 'updated');
332 saveFailed: function() {
333 if (this.get('state') != 'updating') {
334 alert('erroneous state:', this.get('state'));
336 this.set('state', 'dirty');
340 set: function(property, value) {
341 if (property == 'state') {
342 console.log(this.description(), ':', property, '=', value);
344 return this._super(property, value);
349 Editor.ImageGalleryModel = Editor.Model.extend({
350 _className: 'Editor.ImageGalleryModel',
355 init: function(document, serverURL) {
357 this.set('state', 'empty');
358 this.serverURL = serverURL;
363 load: function(force) {
364 if (force || this.get('state') == 'empty') {
365 console.log("setting state");
366 this.set('state', 'loading');
367 console.log("going ajax");
371 success: this.loadingSucceeded.bind(this),
372 error: this.loadingFailed.bind(this)
377 loadingSucceeded: function(data)
379 console.log("success");
381 if (this.get('state') != 'loading') {
382 alert('erroneous state:', this.get('state'));
385 console.log('galleries:', data);
387 if (data.length === 0) {
388 this.set('data', []);
390 this.set('data', data[0].pages);
393 this.set('state', 'synced');
396 loadingFailed: function(data) {
397 console.log("failed");
399 if (this.get('state') != 'loading') {
400 alert('erroneous state:', this.get('state'));
403 this.set('state', 'error');
406 set: function(property, value) {
407 if (property == 'state') {
408 console.log(this.description(), ':', property, '=', value);
410 return this._super(property, value);
415 Editor.DocumentModel = Editor.Model.extend({
416 _className: 'Editor.DocumentModel',
417 data: null, // name, text_url, revision, latest_shared_rev, parts_url, dc_url, size, merge_url
426 this.set('state', 'empty');
430 if (this.get('state') == 'empty') {
431 this.set('state', 'loading');
432 messageCenter.addMessage('info', 'docload', 'Ładuję dane dokumentu...');
435 url: documentInfo.docURL,
437 success: this.successfulLoad.bind(this),
438 error: this.failedLoad.bind(this)
443 successfulLoad: function(data) {
444 this.set('data', data);
445 this.set('state', 'synced');
447 this.set('revision', data.revision);
448 this.set('user', data.user);
450 this.contentModels = {
451 'xml': new Editor.XMLModel(this, data.text_url),
452 'html': new Editor.HTMLModel(this, data.text_url, data.html_url),
453 'gallery': new Editor.ImageGalleryModel(this, data.gallery_url)
456 for (var key in this.contentModels) {
457 this.contentModels[key].addObserver(this, 'state', this.contentModelStateChanged.bind(this));
462 messageCenter.addMessage('success', 'docload', 'Dokument załadowany poprawnie :-)');
465 failedLoad: function(response) {
466 if (this.get('state') != 'loading') {
467 alert('erroneous state:', this.get('state'));
470 var err = parseXHRError(response);
471 this.set('error', '<h2>Nie udało się wczytać dokumentu</h2><p>'+err.error_message+"</p>");
472 this.set('state', 'error');
475 contentModelStateChanged: function(property, value, contentModel) {
476 if (value == 'dirty') {
477 this.set('state', 'dirty');
478 for (var key in this.contentModels) {
479 if (this.contentModels[key].guid() != contentModel.guid()) {
480 this.contentModels[key].set('state', 'unsynced');
483 } else if (value == 'updated') {
484 this.set('state', 'synced');
485 for (key in this.contentModels) {
486 if (this.contentModels[key].guid() == contentModel.guid()) {
487 this.contentModels[key].set('state', 'synced');
488 this.revision = this.contentModels[key].get('revision');
492 for (key in this.contentModels) {
493 if (this.contentModels[key].guid() != contentModel.guid()) {
494 this.contentModels[key].set('revision', this.revision);
495 this.contentModels[key].set('state', 'empty');
501 saveDirtyContentModel: function(message) {
502 for (var key in this.contentModels) {
503 if (this.contentModels[key].get('state') == 'dirty') {
504 this.contentModels[key].save(message);
511 this.set('state', 'loading');
513 messageCenter.addMessage('info', 'doc_update',
514 'Uaktualniam dokument...');
517 url: this.data.merge_url,
522 revision: this.get('revision'),
523 user: this.get('user')
525 complete: this.updateCompleted.bind(this),
529 updateCompleted: function(xhr, textStatus)
531 console.log(xhr.status, xhr.responseText);
532 var response = parseXHRResponse(xhr);
535 if( (response.data.result == 'no-op')
536 || (response.data.timestamp == response.data.parent_timestamp))
538 if( (response.data.revision) && (response.data.revision != this.get('revision')) )
541 this.set('state', 'unsynced');
545 messageCenter.addMessage('info', 'doc_update',
546 'Już posiadasz najbardziej aktualną wersję.');
547 this.set('state', 'synced');
552 this.set('revision', response.data.revision);
553 this.set('user', response.data.user);
555 messageCenter.addMessage('info', 'doc_update',
556 'Uaktualnienie dokumentu do wersji ' + response.data.revision);
558 for (var key in this.contentModels) {
559 this.contentModels[key].set('revision', this.get('revision') );
560 this.contentModels[key].set('state', 'empty');
563 this.set('state', 'synced');
567 // no success means trouble
568 messageCenter.addMessage(response.error_level, 'doc_update',
569 response.error_message);
571 this.set('state', 'unsynced');
574 merge: function(message) {
575 this.set('state', 'loading');
576 messageCenter.addMessage('info', 'doc_merge',
577 'Scalam dokument z głównym repozytorium...');
580 url: this.data.merge_url,
585 revision: this.get('revision'),
586 user: this.get('user'),
589 complete: this.mergeCompleted.bind(this),
590 success: function(data) {
591 this.set('mergeData', data);
596 mergeCompleted: function(xhr, textStatus) {
597 console.log(xhr.status, xhr.responseText);
598 var response = parseXHRResponse(xhr);
600 if(response.success) {
602 if( (response.data.result == 'no-op') ||
603 ( response.data.shared_parent_timestamp
604 && response.data.shared_timestamp
605 && (response.data.shared_timestamp == response.data.shared_parent_timestamp)) )
607 if( (response.data.revision) && (response.data.revision != this.get('revision')) )
610 this.set('state', 'unsynced');
614 messageCenter.addMessage('info', 'doc_merge',
615 'Twoja aktualna wersja nie różni się od ostatnio zatwierdzonej.');
616 this.set('state', 'synced');
620 if( response.data.result == 'accepted')
622 messageCenter.addMessage('info', 'doc_merge',
623 'Prośba o zatwierdzenie została przyjęta i oczekuję na przyjęcie.');
624 this.set('state', 'synced');
629 this.set('revision', response.data.revision);
630 this.set('user', response.data.user);
632 messageCenter.addMessage('info', 'doc_merge',
633 'Twoja wersja dokumentu została zatwierdzona.');
635 this.set('state', 'synced');
639 // no success means trouble
640 messageCenter.addMessage(response.error_level, 'doc_merge',
641 response.error_message);
643 this.set('state', 'unsynced');
647 set: function(property, value) {
648 if (property == 'state') {
649 console.log(this.description(), ':', property, '=', value);
651 return this._super(property, value);
656 var leftPanelView, rightPanelContainer, doc;
660 var flashView = new FlashView('#flashview', messageCenter);
662 doc = new Editor.DocumentModel();
664 EditorView = new EditorView('#body-wrap', doc);
665 EditorView.freeze("<h1>Wczytuję dokument...</h1>");
667 leftPanelView = new PanelContainerView('#left-panel-container', doc);
668 rightPanelContainer = new PanelContainerView('#right-panel-container', doc);