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) {
27 this.set('buttons', data);
34 // -> error -> loading
36 // empty -> loading -> synced -> unsynced -> loading
38 // -> dirty -> updating -> updated -> synced
40 Editor.XMLModel = Editor.Model.extend({
41 _className: 'Editor.XMLModel',
46 init: function(serverURL, revision) {
48 this.set('state', 'empty');
49 this.set('revision', revision);
50 this.serverURL = serverURL;
51 this.toolbarButtonsModel = new Editor.ToolbarButtonsModel();
52 this.addObserver(this, 'data', this.dataChanged.bind(this));
55 load: function(force) {
56 if (force || this.get('state') == 'empty') {
57 this.set('state', 'loading');
58 messageCenter.addMessage('info', 'Wczytuję XML...');
63 revision: this.get('revision')
65 success: this.loadingSucceeded.bind(this),
66 error: this.loadingFailed.bind(this)
73 loadingSucceeded: function(data) {
74 if (this.get('state') != 'loading') {
75 alert('erroneous state:', this.get('state'));
77 this.set('data', data);
78 this.set('state', 'synced');
79 messageCenter.addMessage('success', 'Wczytałem XML :-)');
82 loadingFailed: function() {
83 if (this.get('state') != 'loading') {
84 alert('erroneous state:', this.get('state'));
86 this.set('error', 'Nie udało się załadować panelu');
87 this.set('state', 'error');
88 messageCenter.addMessage('error', 'Nie udało mi się wczytać XML. Spróbuj ponownie :-(');
91 update: function(message) {
92 if (this.get('state') == 'dirty') {
93 this.set('state', 'updating');
94 messageCenter.addMessage('info', 'Zapisuję XML...');
97 contents: this.get('data'),
98 revision: this.get('revision')
101 payload.message = message;
109 success: this.updatingSucceeded.bind(this),
110 error: this.updatingFailed.bind(this)
117 updatingSucceeded: function(data) {
118 if (this.get('state') != 'updating') {
119 alert('erroneous state:', this.get('state'));
121 this.set('revision', data.revision);
122 this.set('state', 'updated');
123 messageCenter.addMessage('success', 'Zapisałem XML :-)');
126 updatingFailed: function() {
127 if (this.get('state') != 'updating') {
128 alert('erroneous state:', this.get('state'));
130 messageCenter.addMessage('error', 'Nie udało mi się zapisać XML. Spróbuj ponownie :-(');
131 this.set('state', 'dirty');
135 set: function(property, value) {
136 if (property == 'state') {
137 console.log(this.description(), ':', property, '=', value);
139 return this._super(property, value);
142 dataChanged: function(property, value) {
143 if (this.get('state') == 'synced') {
144 this.set('state', 'dirty');
148 dispose: function() {
149 this.removeObserver(this);
155 Editor.HTMLModel = Editor.Model.extend({
156 _className: 'Editor.HTMLModel',
164 init: function(htmlURL, revision, dataURL) {
166 this.set('state', 'empty');
167 this.set('revision', revision);
168 this.htmlURL = htmlURL;
169 this.dataURL = dataURL;
170 this.renderURL = "http://localhost:8000/api/render";
174 load: function(force) {
175 if (force || this.get('state') == 'empty') {
176 this.set('state', 'loading');
178 // load the transformed data
179 // messageCenter.addMessage('info', 'Wczytuję HTML...');
185 revision: this.get('revision')
187 success: this.loadingSucceeded.bind(this),
188 error: this.loadingFailed.bind(this)
193 loadingSucceeded: function(data) {
194 if (this.get('state') != 'loading') {
195 alert('erroneous state:', this.get('state'));
197 this.set('data', data);
198 this.set('state', 'synced');
199 // messageCenter.addMessage('success', 'Wczytałem HTML :-)');
202 loadingFailed: function(response) {
203 if (this.get('state') != 'loading') {
204 alert('erroneous state:', this.get('state'));
207 var json_response = null;
211 json_response = $.evalJSON(response.responseText);
213 if(json_response.reason == 'xml-parse-error') {
215 message = json_response.message.replace(/(line\s+)(\d+)(\s+)/i,
216 "<a class='xml-editor-ref' href='#xml-$2-1'>$1$2$3</a>");
218 message = message.replace(/(line\s+)(\d+)(\,\s*column\s+)(\d+)/i,
219 "<a class='xml-editor-ref' href='#xml-$2-$4'>$1$2$3$4</a>");
224 message = json_response.message || json_response.reason || "nieznany błąd.";
228 message = response.statusText;
231 this.set('error', '<p>Nie udało się wczytać widoku HTML: </p>' + message);
233 this.set('state', 'error');
234 // messageCenter.addMessage('error', 'Nie udało mi się wczytać HTML. Spróbuj ponownie :-(');
237 getXMLPart: function(elem, callback)
239 var path = elem.attr('wl2o:path');
240 if(!this.xmlParts[path])
241 this.loadXMLPart(elem, callback);
243 callback(path, this.xmlParts[path]);
246 loadXMLPart: function(elem, callback)
248 var path = elem.attr('wl2o:path');
255 revision: this.get('revision'),
258 success: function(data) {
259 self.xmlParts[path] = data;
260 callback(path, data);
262 // TODO: error handling
263 error: function(data) {
264 console.log('Failed to load fragment');
265 callback(undefined, undefined);
270 putXMLPart: function(elem, data) {
273 var path = elem.attr('wl2o:path');
274 this.xmlParts[path] = data;
276 this.set('state', 'unsynced');
278 /* re-render the changed fragment */
282 dataType: 'text; charset=utf-8',
287 success: function(htmldata) {
288 elem.replaceWith(htmldata);
289 self.set('state', 'dirty');
294 update: function(message) {
295 if (this.get('state') == 'dirty') {
296 this.set('state', 'updating');
299 chunks: $.toJSON(this.xmlParts),
300 revision: this.get('revision')
304 payload.message = message;
314 success: this.updatingSucceeded.bind(this),
315 error: this.updatingFailed.bind(this)
323 updatingSucceeded: function(data) {
324 if (this.get('state') != 'updating') {
325 alert('erroneous state:', this.get('state'));
331 this.set('revision', data.revision);
332 this.set('state', 'updated');
335 updatingFailed: function() {
336 if (this.get('state') != 'updating') {
337 alert('erroneous state:', this.get('state'));
339 messageCenter.addMessage('error', 'Uaktualnienie nie powiodło się', 'Uaktualnienie nie powiodło się');
340 this.set('state', 'dirty');
344 set: function(property, value) {
345 if (property == 'state') {
346 console.log(this.description(), ':', property, '=', value);
348 return this._super(property, value);
353 Editor.ImageGalleryModel = Editor.Model.extend({
354 _className: 'Editor.ImageGalleryModel',
359 init: function(serverURL) {
361 this.set('state', 'empty');
362 this.serverURL = serverURL;
367 load: function(force) {
368 if (force || this.get('state') == 'empty') {
369 this.set('state', 'loading');
373 success: this.loadingSucceeded.bind(this)
378 loadingSucceeded: function(data) {
379 if (this.get('state') != 'loading') {
380 alert('erroneous state:', this.get('state'));
383 console.log('galleries:', data);
385 if (data.length === 0) {
386 this.set('data', []);
389 this.set('data', data[0].pages);
392 this.set('state', 'synced');
395 set: function(property, value) {
396 if (property == 'state') {
397 console.log(this.description(), ':', property, '=', value);
399 return this._super(property, value);
404 Editor.DocumentModel = Editor.Model.extend({
405 _className: 'Editor.DocumentModel',
406 data: null, // name, text_url, user_revision, latest_shared_rev, parts_url, dc_url, size, merge_url
412 this.set('state', 'empty');
417 if (this.get('state') == 'empty') {
418 this.set('state', 'loading');
419 messageCenter.addMessage('info', 'Ładuję dane dokumentu...');
422 url: documentsUrl + fileId,
424 success: this.successfulLoad.bind(this)
429 successfulLoad: function(data) {
430 this.set('data', data);
431 this.set('state', 'synced');
432 this.contentModels = {
433 'xml': new Editor.XMLModel(data.text_url, data.user_revision),
434 'html': new Editor.HTMLModel(data.html_url, data.user_revision, data.text_url),
435 'gallery': new Editor.ImageGalleryModel(data.gallery_url)
437 for (var key in this.contentModels) {
438 this.contentModels[key].addObserver(this, 'state', this.contentModelStateChanged.bind(this));
440 messageCenter.addMessage('success', 'Dane dokumentu zostały załadowane :-)');
443 contentModelStateChanged: function(property, value, contentModel) {
444 if (value == 'dirty') {
445 this.set('state', 'dirty');
446 for (var key in this.contentModels) {
447 if (this.contentModels[key].guid() != contentModel.guid()) {
448 this.contentModels[key].set('state', 'unsynced');
451 } else if (value == 'updated') {
452 this.set('state', 'synced');
453 for (key in this.contentModels) {
454 if (this.contentModels[key].guid() == contentModel.guid()) {
455 this.contentModels[key].set('state', 'synced');
456 this.data.user_revision = this.contentModels[key].get('revision');
459 for (key in this.contentModels) {
460 if (this.contentModels[key].guid() != contentModel.guid()) {
461 this.contentModels[key].set('revision', this.data.user_revision);
462 this.contentModels[key].set('state', 'empty');
468 saveDirtyContentModel: function(message) {
469 for (var key in this.contentModels) {
470 if (this.contentModels[key].get('state') == 'dirty') {
471 this.contentModels[key].update(message);
478 this.set('state', 'loading');
479 messageCenter.addMessage('info', 'Uaktualniam dokument...');
481 url: this.data.merge_url,
486 target_revision: this.data.user_revision
488 complete: this.updateCompleted.bind(this),
489 success: function(data) {
490 this.set('updateData', data);
495 updateCompleted: function(xhr, textStatus) {
496 console.log(xhr.status, textStatus);
497 if (xhr.status == 200) { // Sukces
498 this.data.user_revision = this.get('updateData').revision;
499 messageCenter.addMessage('info', 'Uaktualnienie dokumentu do wersji ' + this.get('updateData').revision,
500 'Uaktualnienie dokumentu do wersji ' + this.get('updateData').revision);
501 for (var key in this.contentModels) {
502 this.contentModels[key].set('revision', this.data.user_revision);
503 this.contentModels[key].set('state', 'empty');
505 messageCenter.addMessage('success', 'Uaktualniłem dokument do najnowszej wersji :-)');
506 } else if (xhr.status == 202) { // Wygenerowano PullRequest (tutaj?)
507 } else if (xhr.status == 204) { // Nic nie zmieniono
508 messageCenter.addMessage('info', 'Nic się nie zmieniło od ostatniej aktualizacji. Po co mam uaktualniać?');
509 } else if (xhr.status == 409) { // Konflikt podczas operacji
510 messageCenter.addMessage('error', 'Wystąpił konflikt podczas aktualizacji. Pędź po programistów! :-(');
511 } else if (xhr.status == 500) {
512 messageCenter.addMessage('critical', 'Błąd serwera. Pędź po programistów! :-(');
514 this.set('state', 'synced');
515 this.set('updateData', null);
518 merge: function(message) {
519 this.set('state', 'loading');
520 messageCenter.addMessage('info', 'Scalam dokument z głównym repozytorium...');
522 url: this.data.merge_url,
527 target_revision: this.data.user_revision,
530 complete: this.mergeCompleted.bind(this),
531 success: function(data) {
532 this.set('mergeData', data);
537 mergeCompleted: function(xhr, textStatus) {
538 console.log(xhr.status, textStatus);
539 if (xhr.status == 200) { // Sukces
540 this.data.user_revision = this.get('mergeData').revision;
541 for (var key in this.contentModels) {
542 this.contentModels[key].set('revision', this.data.user_revision);
543 this.contentModels[key].set('state', 'empty');
545 messageCenter.addMessage('success', 'Scaliłem dokument z głównym repozytorium :-)');
546 } else if (xhr.status == 202) { // Wygenerowano PullRequest
547 messageCenter.addMessage('success', 'Wysłałem prośbę o scalenie dokumentu z głównym repozytorium.');
548 } else if (xhr.status == 204) { // Nic nie zmieniono
549 messageCenter.addMessage('info', 'Nic się nie zmieniło od ostatniego scalenia. Po co mam scalać?');
550 } else if (xhr.status == 409) { // Konflikt podczas operacji
551 messageCenter.addMessage('error', 'Wystąpił konflikt podczas scalania. Pędź po programistów! :-(');
552 } else if (xhr.status == 500) {
553 messageCenter.addMessage('critical', 'Błąd serwera. Pędź po programistów! :-(');
555 this.set('state', 'synced');
556 this.set('mergeData', null);
560 set: function(property, value) {
561 if (property == 'state') {
562 console.log(this.description(), ':', property, '=', value);
564 return this._super(property, value);
569 var leftPanelView, rightPanelContainer, doc;
573 documentsUrl = $('#api-base-url').text() + '/';
574 toolbarUrl = $('#api-toolbar-url').text();
576 doc = new Editor.DocumentModel();
578 EditorView = new EditorView('#body-wrap', doc);
581 leftPanelView = new PanelContainerView('#left-panel-container', doc);
582 rightPanelContainer = new PanelContainerView('#right-panel-container', doc);
584 var flashView = new FlashView('#flashview', messageCenter);