1 /*globals Editor fileId SplitView PanelContainerView EditorView FlashView messageCenter*/
2 Editor.Model = Editor.Object.extend({
8 Editor.ToolbarButtonsModel = Editor.Model.extend({
9 className: 'Editor.ToolbarButtonsModel',
17 if (!this.get('buttons').length) {
21 success: this.loadSucceeded.bind(this)
26 loadSucceeded: function(data)
29 $.each(data, function() {
30 $.each(this.buttons, function() {
31 //do some lame escapes
32 this.tooltip = this.tooltip.replace(/"/g, """);
35 this.set('buttons', data);
42 // -> error -> loading
44 // empty -> loading -> synced -> unsynced -> loading
46 // -> dirty -> updating -> updated -> synced
48 Editor.XMLModel = Editor.Model.extend({
49 _className: 'Editor.XMLModel',
54 init: function(serverURL, revision) {
56 this.set('state', 'empty');
57 this.set('revision', revision);
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', 'Wczytuję XML...');
71 revision: this.get('revision')
73 success: this.loadingSucceeded.bind(this),
74 error: this.loadingFailed.bind(this)
81 loadingSucceeded: function(data) {
82 if (this.get('state') != 'loading') {
83 alert('erroneous state:', this.get('state'));
85 this.set('data', data);
86 this.set('state', 'synced');
87 messageCenter.addMessage('success', 'Wczytałem XML :-)');
90 loadingFailed: function() {
91 if (this.get('state') != 'loading') {
92 alert('erroneous state:', this.get('state'));
94 this.set('error', 'Nie udało się załadować panelu');
95 this.set('state', 'error');
96 messageCenter.addMessage('error', 'Nie udało mi się wczytać XML. Spróbuj ponownie :-(');
99 update: function(message) {
100 if (this.get('state') == 'dirty') {
101 this.set('state', 'updating');
102 messageCenter.addMessage('info', 'Zapisuję XML...');
105 contents: this.get('data'),
106 revision: this.get('revision')
109 payload.message = message;
117 success: this.updatingSucceeded.bind(this),
118 error: this.updatingFailed.bind(this)
125 updatingSucceeded: function(data) {
126 if (this.get('state') != 'updating') {
127 alert('erroneous state:', this.get('state'));
129 this.set('revision', data.revision);
130 this.set('state', 'updated');
131 messageCenter.addMessage('success', 'Zapisałem XML :-)');
134 updatingFailed: function() {
135 if (this.get('state') != 'updating') {
136 alert('erroneous state:', this.get('state'));
138 messageCenter.addMessage('error', 'Nie udało mi się zapisać XML. Spróbuj ponownie :-(');
139 this.set('state', 'dirty');
143 set: function(property, value) {
144 if (property == 'state') {
145 console.log(this.description(), ':', property, '=', value);
147 return this._super(property, value);
150 dataChanged: function(property, value) {
151 if (this.get('state') == 'synced') {
152 this.set('state', 'dirty');
156 dispose: function() {
157 this.removeObserver(this);
163 Editor.HTMLModel = Editor.Model.extend({
164 _className: 'Editor.HTMLModel',
172 init: function(htmlURL, revision, dataURL) {
174 this.set('state', 'empty');
175 this.set('revision', revision);
176 this.htmlURL = htmlURL;
177 this.dataURL = dataURL;
178 this.renderURL = "http://localhost:8000/api/render";
182 load: function(force) {
183 if (force || this.get('state') == 'empty') {
184 this.set('state', 'loading');
186 // load the transformed data
187 // messageCenter.addMessage('info', 'Wczytuję HTML...');
193 revision: this.get('revision')
195 success: this.loadingSucceeded.bind(this),
196 error: this.loadingFailed.bind(this)
201 loadingSucceeded: function(data) {
202 if (this.get('state') != 'loading') {
203 alert('erroneous state:', this.get('state'));
205 this.set('data', data);
206 this.set('state', 'synced');
207 // messageCenter.addMessage('success', 'Wczytałem HTML :-)');
210 loadingFailed: function(response) {
211 if (this.get('state') != 'loading') {
212 alert('erroneous state:', this.get('state'));
215 var json_response = null;
219 json_response = $.evalJSON(response.responseText);
221 if(json_response.reason == 'xml-parse-error') {
223 message = json_response.message.replace(/(line\s+)(\d+)(\s+)/i,
224 "<a class='xml-editor-ref' href='#xml-$2-1'>$1$2$3</a>");
226 message = message.replace(/(line\s+)(\d+)(\,\s*column\s+)(\d+)/i,
227 "<a class='xml-editor-ref' href='#xml-$2-$4'>$1$2$3$4</a>");
232 message = json_response.message || json_response.reason || "nieznany błąd.";
236 message = response.statusText;
239 this.set('error', '<p>Nie udało się wczytać widoku HTML: </p>' + message);
241 this.set('state', 'error');
242 // messageCenter.addMessage('error', 'Nie udało mi się wczytać HTML. Spróbuj ponownie :-(');
245 getXMLPart: function(elem, callback)
247 var path = elem.attr('wl2o:path');
248 if(!this.xmlParts[path])
249 this.loadXMLPart(elem, callback);
251 callback(path, this.xmlParts[path]);
254 loadXMLPart: function(elem, callback)
256 var path = elem.attr('wl2o:path');
263 revision: this.get('revision'),
266 success: function(data) {
267 self.xmlParts[path] = data;
268 callback(path, data);
270 // TODO: error handling
271 error: function(data) {
272 console.log('Failed to load fragment');
273 callback(undefined, undefined);
278 putXMLPart: function(elem, data) {
281 var path = elem.attr('wl2o:path');
282 this.xmlParts[path] = data;
284 this.set('state', 'unsynced');
286 /* re-render the changed fragment */
290 dataType: 'text; charset=utf-8',
295 success: function(htmldata) {
296 elem.replaceWith(htmldata);
297 self.set('state', 'dirty');
302 update: function(message) {
303 if (this.get('state') == 'dirty') {
304 this.set('state', 'updating');
307 chunks: $.toJSON(this.xmlParts),
308 revision: this.get('revision')
312 payload.message = message;
322 success: this.updatingSucceeded.bind(this),
323 error: this.updatingFailed.bind(this)
331 updatingSucceeded: function(data) {
332 if (this.get('state') != 'updating') {
333 alert('erroneous state:', this.get('state'));
339 this.set('revision', data.revision);
340 this.set('state', 'updated');
343 updatingFailed: function() {
344 if (this.get('state') != 'updating') {
345 alert('erroneous state:', this.get('state'));
347 messageCenter.addMessage('error', 'Uaktualnienie nie powiodło się', 'Uaktualnienie nie powiodło się');
348 this.set('state', 'dirty');
352 set: function(property, value) {
353 if (property == 'state') {
354 console.log(this.description(), ':', property, '=', value);
356 return this._super(property, value);
361 Editor.ImageGalleryModel = Editor.Model.extend({
362 _className: 'Editor.ImageGalleryModel',
367 init: function(serverURL) {
369 this.set('state', 'empty');
370 this.serverURL = serverURL;
375 load: function(force) {
376 if (force || this.get('state') == 'empty') {
377 this.set('state', 'loading');
381 success: this.loadingSucceeded.bind(this)
386 loadingSucceeded: function(data) {
387 if (this.get('state') != 'loading') {
388 alert('erroneous state:', this.get('state'));
391 console.log('galleries:', data);
393 if (data.length === 0) {
394 this.set('data', []);
397 this.set('data', data[0].pages);
400 this.set('state', 'synced');
403 set: function(property, value) {
404 if (property == 'state') {
405 console.log(this.description(), ':', property, '=', value);
407 return this._super(property, value);
412 Editor.DocumentModel = Editor.Model.extend({
413 _className: 'Editor.DocumentModel',
414 data: null, // name, text_url, user_revision, latest_shared_rev, parts_url, dc_url, size, merge_url
420 this.set('state', 'empty');
425 if (this.get('state') == 'empty') {
426 this.set('state', 'loading');
427 messageCenter.addMessage('info', 'Ładuję dane dokumentu...');
430 url: documentsUrl + fileId,
432 success: this.successfulLoad.bind(this)
437 successfulLoad: function(data) {
438 this.set('data', data);
439 this.set('state', 'synced');
440 this.contentModels = {
441 'xml': new Editor.XMLModel(data.text_url, data.user_revision),
442 'html': new Editor.HTMLModel(data.html_url, data.user_revision, data.text_url),
443 'gallery': new Editor.ImageGalleryModel(data.gallery_url)
445 for (var key in this.contentModels) {
446 this.contentModels[key].addObserver(this, 'state', this.contentModelStateChanged.bind(this));
448 messageCenter.addMessage('success', 'Dane dokumentu zostały załadowane :-)');
451 contentModelStateChanged: function(property, value, contentModel) {
452 if (value == 'dirty') {
453 this.set('state', 'dirty');
454 for (var key in this.contentModels) {
455 if (this.contentModels[key].guid() != contentModel.guid()) {
456 this.contentModels[key].set('state', 'unsynced');
459 } else if (value == 'updated') {
460 this.set('state', 'synced');
461 for (key in this.contentModels) {
462 if (this.contentModels[key].guid() == contentModel.guid()) {
463 this.contentModels[key].set('state', 'synced');
464 this.data.user_revision = this.contentModels[key].get('revision');
467 for (key in this.contentModels) {
468 if (this.contentModels[key].guid() != contentModel.guid()) {
469 this.contentModels[key].set('revision', this.data.user_revision);
470 this.contentModels[key].set('state', 'empty');
476 saveDirtyContentModel: function(message) {
477 for (var key in this.contentModels) {
478 if (this.contentModels[key].get('state') == 'dirty') {
479 this.contentModels[key].update(message);
486 this.set('state', 'loading');
487 messageCenter.addMessage('info', 'Uaktualniam dokument...');
489 url: this.data.merge_url,
494 target_revision: this.data.user_revision
496 complete: this.updateCompleted.bind(this),
497 success: function(data) {
498 this.set('updateData', data);
503 updateCompleted: function(xhr, textStatus) {
504 console.log(xhr.status, textStatus);
505 if (xhr.status == 200) { // Sukces
506 this.data.user_revision = this.get('updateData').revision;
507 messageCenter.addMessage('info', 'Uaktualnienie dokumentu do wersji ' + this.get('updateData').revision,
508 'Uaktualnienie dokumentu do wersji ' + this.get('updateData').revision);
509 for (var key in this.contentModels) {
510 this.contentModels[key].set('revision', this.data.user_revision);
511 this.contentModels[key].set('state', 'empty');
513 messageCenter.addMessage('success', 'Uaktualniłem dokument do najnowszej wersji :-)');
514 } else if (xhr.status == 202) { // Wygenerowano PullRequest (tutaj?)
515 } else if (xhr.status == 204) { // Nic nie zmieniono
516 messageCenter.addMessage('info', 'Nic się nie zmieniło od ostatniej aktualizacji. Po co mam uaktualniać?');
517 } else if (xhr.status == 409) { // Konflikt podczas operacji
518 messageCenter.addMessage('error', 'Wystąpił konflikt podczas aktualizacji. Pędź po programistów! :-(');
519 } else if (xhr.status == 500) {
520 messageCenter.addMessage('critical', 'Błąd serwera. Pędź po programistów! :-(');
522 this.set('state', 'synced');
523 this.set('updateData', null);
526 merge: function(message) {
527 this.set('state', 'loading');
528 messageCenter.addMessage('info', 'Scalam dokument z głównym repozytorium...');
530 url: this.data.merge_url,
535 target_revision: this.data.user_revision,
538 complete: this.mergeCompleted.bind(this),
539 success: function(data) {
540 this.set('mergeData', data);
545 mergeCompleted: function(xhr, textStatus) {
546 console.log(xhr.status, textStatus);
547 if (xhr.status == 200) { // Sukces
548 this.data.user_revision = this.get('mergeData').revision;
549 for (var key in this.contentModels) {
550 this.contentModels[key].set('revision', this.data.user_revision);
551 this.contentModels[key].set('state', 'empty');
553 messageCenter.addMessage('success', 'Scaliłem dokument z głównym repozytorium :-)');
554 } else if (xhr.status == 202) { // Wygenerowano PullRequest
555 messageCenter.addMessage('success', 'Wysłałem prośbę o scalenie dokumentu z głównym repozytorium.');
556 } else if (xhr.status == 204) { // Nic nie zmieniono
557 messageCenter.addMessage('info', 'Nic się nie zmieniło od ostatniego scalenia. Po co mam scalać?');
558 } else if (xhr.status == 409) { // Konflikt podczas operacji
559 messageCenter.addMessage('error', 'Wystąpił konflikt podczas scalania. Pędź po programistów! :-(');
560 } else if (xhr.status == 500) {
561 messageCenter.addMessage('critical', 'Błąd serwera. Pędź po programistów! :-(');
563 this.set('state', 'synced');
564 this.set('mergeData', null);
568 set: function(property, value) {
569 if (property == 'state') {
570 console.log(this.description(), ':', property, '=', value);
572 return this._super(property, value);
577 var leftPanelView, rightPanelContainer, doc;
581 documentsUrl = $('#api-base-url').text() + '/';
582 toolbarUrl = $('#api-toolbar-url').text();
584 doc = new Editor.DocumentModel();
586 EditorView = new EditorView('#body-wrap', doc);
589 leftPanelView = new PanelContainerView('#left-panel-container', doc);
590 rightPanelContainer = new PanelContainerView('#right-panel-container', doc);
592 var flashView = new FlashView('#flashview', messageCenter);