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() {
203 if (this.get('state') != 'loading') {
204 alert('erroneous state:', this.get('state'));
206 this.set('error', 'Nie udało się załadować panelu');
207 this.set('state', 'error');
208 messageCenter.addMessage('error', 'Nie udało mi się wczytać HTML. Spróbuj ponownie :-(');
211 getXMLPart: function(elem, callback)
213 var path = elem.attr('wl2o:path');
214 if(!this.xmlParts[path])
215 this.loadXMLPart(elem, callback);
217 callback(path, this.xmlParts[path]);
220 loadXMLPart: function(elem, callback)
222 var path = elem.attr('wl2o:path');
229 revision: this.get('revision'),
232 success: function(data) {
233 self.xmlParts[path] = data;
234 callback(path, data);
236 // TODO: error handling
237 error: function(data) {
238 console.log('Failed to load fragment');
239 callback(undefined, undefined);
244 putXMLPart: function(elem, data) {
247 var path = elem.attr('wl2o:path');
248 this.xmlParts[path] = data;
250 this.set('state', 'unsynced');
252 /* re-render the changed fragment */
256 dataType: 'text; charset=utf-8',
261 success: function(htmldata) {
262 elem.replaceWith(htmldata);
263 self.set('state', 'dirty');
268 update: function(message) {
269 if (this.get('state') == 'dirty') {
270 this.set('state', 'updating');
273 chunks: $.toJSON(this.xmlParts),
274 revision: this.get('revision')
278 payload.message = message;
288 success: this.updatingSucceeded.bind(this),
289 error: this.updatingFailed.bind(this)
297 updatingSucceeded: function(data) {
298 if (this.get('state') != 'updating') {
299 alert('erroneous state:', this.get('state'));
305 this.set('revision', data.revision);
306 this.set('state', 'updated');
309 updatingFailed: function() {
310 if (this.get('state') != 'updating') {
311 alert('erroneous state:', this.get('state'));
313 messageCenter.addMessage('error', 'Uaktualnienie nie powiodło się', 'Uaktualnienie nie powiodło się');
314 this.set('state', 'dirty');
318 set: function(property, value) {
319 if (property == 'state') {
320 console.log(this.description(), ':', property, '=', value);
322 return this._super(property, value);
327 Editor.ImageGalleryModel = Editor.Model.extend({
328 _className: 'Editor.ImageGalleryModel',
333 init: function(serverURL) {
335 this.set('state', 'empty');
336 this.serverURL = serverURL;
341 load: function(force) {
342 if (force || this.get('state') == 'empty') {
343 this.set('state', 'loading');
347 success: this.loadingSucceeded.bind(this)
352 loadingSucceeded: function(data) {
353 if (this.get('state') != 'loading') {
354 alert('erroneous state:', this.get('state'));
357 console.log('galleries:', data);
359 if (data.length === 0) {
360 this.set('data', []);
363 this.set('data', data[0].pages);
366 this.set('state', 'synced');
369 set: function(property, value) {
370 if (property == 'state') {
371 console.log(this.description(), ':', property, '=', value);
373 return this._super(property, value);
378 Editor.DocumentModel = Editor.Model.extend({
379 _className: 'Editor.DocumentModel',
380 data: null, // name, text_url, user_revision, latest_shared_rev, parts_url, dc_url, size, merge_url
386 this.set('state', 'empty');
391 if (this.get('state') == 'empty') {
392 this.set('state', 'loading');
393 messageCenter.addMessage('info', 'Ładuję dane dokumentu...');
396 url: documentsUrl + fileId,
398 success: this.successfulLoad.bind(this)
403 successfulLoad: function(data) {
404 this.set('data', data);
405 this.set('state', 'synced');
406 this.contentModels = {
407 'xml': new Editor.XMLModel(data.text_url, data.user_revision),
408 'html': new Editor.HTMLModel(data.html_url, data.user_revision, data.text_url),
409 'gallery': new Editor.ImageGalleryModel(data.gallery_url)
411 for (var key in this.contentModels) {
412 this.contentModels[key].addObserver(this, 'state', this.contentModelStateChanged.bind(this));
414 messageCenter.addMessage('success', 'Dane dokumentu zostały załadowane :-)');
417 contentModelStateChanged: function(property, value, contentModel) {
418 if (value == 'dirty') {
419 this.set('state', 'dirty');
420 for (var key in this.contentModels) {
421 if (this.contentModels[key].guid() != contentModel.guid()) {
422 this.contentModels[key].set('state', 'unsynced');
425 } else if (value == 'updated') {
426 this.set('state', 'synced');
427 for (key in this.contentModels) {
428 if (this.contentModels[key].guid() == contentModel.guid()) {
429 this.contentModels[key].set('state', 'synced');
430 this.data.user_revision = this.contentModels[key].get('revision');
433 for (key in this.contentModels) {
434 if (this.contentModels[key].guid() != contentModel.guid()) {
435 this.contentModels[key].set('revision', this.data.user_revision);
436 this.contentModels[key].set('state', 'empty');
442 saveDirtyContentModel: function(message) {
443 for (var key in this.contentModels) {
444 if (this.contentModels[key].get('state') == 'dirty') {
445 this.contentModels[key].update(message);
452 this.set('state', 'loading');
453 messageCenter.addMessage('info', 'Uaktualniam dokument...');
455 url: this.data.merge_url,
460 target_revision: this.data.user_revision
462 complete: this.updateCompleted.bind(this),
463 success: function(data) {
464 this.set('updateData', data);
469 updateCompleted: function(xhr, textStatus) {
470 console.log(xhr.status, textStatus);
471 if (xhr.status == 200) { // Sukces
472 this.data.user_revision = this.get('updateData').revision;
473 messageCenter.addMessage('info', 'Uaktualnienie dokumentu do wersji ' + this.get('updateData').revision,
474 'Uaktualnienie dokumentu do wersji ' + this.get('updateData').revision);
475 for (var key in this.contentModels) {
476 this.contentModels[key].set('revision', this.data.user_revision);
477 this.contentModels[key].set('state', 'empty');
479 messageCenter.addMessage('success', 'Uaktualniłem dokument do najnowszej wersji :-)');
480 } else if (xhr.status == 202) { // Wygenerowano PullRequest (tutaj?)
481 } else if (xhr.status == 204) { // Nic nie zmieniono
482 messageCenter.addMessage('info', 'Nic się nie zmieniło od ostatniej aktualizacji. Po co mam uaktualniać?');
483 } else if (xhr.status == 409) { // Konflikt podczas operacji
484 messageCenter.addMessage('error', 'Wystąpił konflikt podczas aktualizacji. Pędź po programistów! :-(');
485 } else if (xhr.status == 500) {
486 messageCenter.addMessage('critical', 'Błąd serwera. Pędź po programistów! :-(');
488 this.set('state', 'synced');
489 this.set('updateData', null);
492 merge: function(message) {
493 this.set('state', 'loading');
494 messageCenter.addMessage('info', 'Scalam dokument z głównym repozytorium...');
496 url: this.data.merge_url,
501 target_revision: this.data.user_revision,
504 complete: this.mergeCompleted.bind(this),
505 success: function(data) {
506 this.set('mergeData', data);
511 mergeCompleted: function(xhr, textStatus) {
512 console.log(xhr.status, textStatus);
513 if (xhr.status == 200) { // Sukces
514 this.data.user_revision = this.get('mergeData').revision;
515 for (var key in this.contentModels) {
516 this.contentModels[key].set('revision', this.data.user_revision);
517 this.contentModels[key].set('state', 'empty');
519 messageCenter.addMessage('success', 'Scaliłem dokument z głównym repozytorium :-)');
520 } else if (xhr.status == 202) { // Wygenerowano PullRequest
521 messageCenter.addMessage('success', 'Wysłałem prośbę o scalenie dokumentu z głównym repozytorium.');
522 } else if (xhr.status == 204) { // Nic nie zmieniono
523 messageCenter.addMessage('info', 'Nic się nie zmieniło od ostatniego scalenia. Po co mam scalać?');
524 } else if (xhr.status == 409) { // Konflikt podczas operacji
525 messageCenter.addMessage('error', 'Wystąpił konflikt podczas scalania. Pędź po programistów! :-(');
526 } else if (xhr.status == 500) {
527 messageCenter.addMessage('critical', 'Błąd serwera. Pędź po programistów! :-(');
529 this.set('state', 'synced');
530 this.set('mergeData', null);
534 set: function(property, value) {
535 if (property == 'state') {
536 console.log(this.description(), ':', property, '=', value);
538 return this._super(property, value);
543 var leftPanelView, rightPanelContainer, doc;
547 documentsUrl = $('#api-base-url').text() + '/';
548 toolbarUrl = $('#api-toolbar-url').text();
550 doc = new Editor.DocumentModel();
551 var editor = new EditorView('#body-wrap', doc);
554 var flashView = new FlashView('#flashview', messageCenter);
555 var splitView = new SplitView('#splitview', doc);
557 leftPanelView = new PanelContainerView('#left-panel-container', doc);
558 rightPanelContainer = new PanelContainerView('#right-panel-container', doc);