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...');
 
  62         data: {revision: this.get('revision')},
 
  63         success: this.loadingSucceeded.bind(this),
 
  64         error: this.loadingFailed.bind(this)
 
  71   loadingSucceeded: function(data) {
 
  72     if (this.get('state') != 'loading') {
 
  73       alert('erroneous state:', this.get('state'));
 
  75     this.set('data', data);
 
  76     this.set('state', 'synced');
 
  77     messageCenter.addMessage('success', 'Wczytałem XML :-)');
 
  80   loadingFailed: function() {
 
  81     if (this.get('state') != 'loading') {
 
  82       alert('erroneous state:', this.get('state'));
 
  84     this.set('error', 'Nie udało się załadować panelu');
 
  85     this.set('state', 'error');    
 
  86     messageCenter.addMessage('error', 'Nie udało mi się wczytać XML. Spróbuj ponownie :-(');
 
  89   update: function(message) {
 
  90     if (this.get('state') == 'dirty') {
 
  91       this.set('state', 'updating');
 
  92       messageCenter.addMessage('info', 'Zapisuję XML...');
 
  95         contents: this.get('data'),
 
  96         revision: this.get('revision')
 
  99         payload.message = message;
 
 107         success: this.updatingSucceeded.bind(this),
 
 108         error: this.updatingFailed.bind(this)
 
 115   updatingSucceeded: function(data) {
 
 116     if (this.get('state') != 'updating') {
 
 117       alert('erroneous state:', this.get('state'));
 
 119     this.set('revision', data.revision);
 
 120     this.set('state', 'updated');
 
 121     messageCenter.addMessage('success', 'Zapisałem XML :-)');
 
 124   updatingFailed: function() {
 
 125     if (this.get('state') != 'updating') {
 
 126       alert('erroneous state:', this.get('state'));
 
 128     messageCenter.addMessage('error', 'Nie udało mi się zapisać XML. Spróbuj ponownie :-(');
 
 129     this.set('state', 'dirty');
 
 133   set: function(property, value) {
 
 134     if (property == 'state') {
 
 135       console.log(this.description(), ':', property, '=', value);
 
 137     return this._super(property, value);
 
 140   dataChanged: function(property, value) {
 
 141     if (this.get('state') == 'synced') {
 
 142       this.set('state', 'dirty');
 
 146   dispose: function() {
 
 147     this.removeObserver(this);
 
 153 Editor.HTMLModel = Editor.Model.extend({
 
 154   _className: 'Editor.HTMLModel',
 
 159   init: function(serverURL, revision) {
 
 161     this.set('state', 'empty');
 
 162     this.set('revision', revision);
 
 163     this.serverURL = serverURL;
 
 166   load: function(force) {
 
 167     if (force || this.get('state') == 'empty') {
 
 168       this.set('state', 'loading');
 
 169       messageCenter.addMessage('info', 'Wczytuję HTML...');
 
 173         data: {revision: this.get('revision')},
 
 174         success: this.loadingSucceeded.bind(this),
 
 175         error: this.loadingFailed.bind(this)
 
 180   loadingSucceeded: function(data) {
 
 181     if (this.get('state') != 'loading') {
 
 182       alert('erroneous state:', this.get('state'));
 
 184     this.set('data', data);
 
 185     this.set('state', 'synced');
 
 186     messageCenter.addMessage('success', 'Wczytałem HTML :-)');
 
 189   loadingFailed: function() {
 
 190     if (this.get('state') != 'loading') {
 
 191       alert('erroneous state:', this.get('state'));
 
 193     this.set('error', 'Nie udało się załadować panelu');
 
 194     this.set('state', 'error');    
 
 195     messageCenter.addMessage('error', 'Nie udało mi się wczytać HTML. Spróbuj ponownie :-(');
 
 199   set: function(property, value) {
 
 200     if (property == 'state') {
 
 201       console.log(this.description(), ':', property, '=', value);
 
 203     return this._super(property, value);
 
 208 Editor.ImageGalleryModel = Editor.Model.extend({
 
 209   _className: 'Editor.ImageGalleryModel',
 
 214   init: function(serverURL) {
 
 216     this.set('state', 'empty');
 
 217     this.serverURL = serverURL;
 
 222   load: function(force) {
 
 223     if (force || this.get('state') == 'empty') {
 
 224       this.set('state', 'loading');
 
 228         success: this.loadingSucceeded.bind(this)
 
 233   loadingSucceeded: function(data) {
 
 234     if (this.get('state') != 'loading') {
 
 235       alert('erroneous state:', this.get('state'));
 
 238     console.log('galleries:', data);
 
 240     if (data.length === 0) {
 
 241         this.set('data', []);
 
 244         this.set('data', data[0].pages);
 
 247     this.set('state', 'synced');
 
 250   set: function(property, value) {
 
 251     if (property == 'state') {
 
 252       console.log(this.description(), ':', property, '=', value);
 
 254     return this._super(property, value);
 
 259 Editor.DocumentModel = Editor.Model.extend({
 
 260   _className: 'Editor.DocumentModel',
 
 261   data: null, // name, text_url, user_revision, latest_shared_rev, parts_url, dc_url, size, merge_url
 
 267     this.set('state', 'empty');
 
 272     if (this.get('state') == 'empty') {
 
 273       this.set('state', 'loading');
 
 274       messageCenter.addMessage('info', 'Ładuję dane dokumentu...');
 
 277         url: documentsUrl + fileId,
 
 279         success: this.successfulLoad.bind(this)
 
 284   successfulLoad: function(data) {
 
 285     this.set('data', data);
 
 286     this.set('state', 'synced');
 
 287     this.contentModels = {
 
 288       'xml': new Editor.XMLModel(data.text_url, data.user_revision),
 
 289       'html': new Editor.HTMLModel(data.html_url, data.user_revision),
 
 290       'gallery': new Editor.ImageGalleryModel(data.gallery_url)
 
 292     for (var key in this.contentModels) {
 
 293       this.contentModels[key].addObserver(this, 'state', this.contentModelStateChanged.bind(this));
 
 295     messageCenter.addMessage('success', 'Dane dokumentu zostały załadowane :-)');
 
 298   contentModelStateChanged: function(property, value, contentModel) {
 
 299     if (value == 'dirty') {
 
 300       this.set('state', 'dirty');
 
 301       for (var key in this.contentModels) {
 
 302         if (this.contentModels[key].guid() != contentModel.guid()) {
 
 303           this.contentModels[key].set('state', 'unsynced');
 
 306     } else if (value == 'updated') {
 
 307       this.set('state', 'synced');
 
 308       for (key in this.contentModels) {
 
 309         if (this.contentModels[key].guid() == contentModel.guid()) {
 
 310           this.contentModels[key].set('state', 'synced');
 
 311           this.data.user_revision = this.contentModels[key].get('revision');
 
 314       for (key in this.contentModels) {
 
 315         if (this.contentModels[key].guid() != contentModel.guid()) {
 
 316           this.contentModels[key].set('revision', this.data.user_revision);
 
 317           this.contentModels[key].set('state', 'empty');
 
 323   saveDirtyContentModel: function(message) {
 
 324     for (var key in this.contentModels) {
 
 325       if (this.contentModels[key].get('state') == 'dirty') {
 
 326         this.contentModels[key].update(message);
 
 333     this.set('state', 'loading');
 
 334     messageCenter.addMessage('info', 'Uaktualniam dokument...');
 
 336       url: this.data.merge_url,
 
 341         target_revision: this.data.user_revision
 
 343       complete: this.updateCompleted.bind(this),
 
 344       success: function(data) { this.set('updateData', data); }.bind(this)
 
 348   updateCompleted: function(xhr, textStatus) {
 
 349     console.log(xhr.status, textStatus);
 
 350     if (xhr.status == 200) { // Sukces
 
 351       this.data.user_revision = this.get('updateData').revision;
 
 352       messageCenter.addMessage('info', 'Uaktualnienie dokumentu do wersji ' + this.get('updateData').revision,
 
 353         'Uaktualnienie dokumentu do wersji ' + this.get('updateData').revision);
 
 354       for (var key in this.contentModels) {
 
 355         this.contentModels[key].set('revision', this.data.user_revision);
 
 356         this.contentModels[key].set('state', 'empty');
 
 358       messageCenter.addMessage('success', 'Uaktualniłem dokument do najnowszej wersji :-)');
 
 359     } else if (xhr.status == 202) { // Wygenerowano PullRequest (tutaj?)
 
 360     } else if (xhr.status == 204) { // Nic nie zmieniono
 
 361       messageCenter.addMessage('info', 'Nic się nie zmieniło od ostatniej aktualizacji. Po co mam uaktualniać?');
 
 362     } else if (xhr.status == 409) { // Konflikt podczas operacji
 
 363       messageCenter.addMessage('error', 'Wystąpił konflikt podczas aktualizacji. Pędź po programistów! :-(');
 
 364     } else if (xhr.status == 500) {
 
 365       messageCenter.addMessage('critical', 'Błąd serwera. Pędź po programistów! :-(');
 
 367     this.set('state', 'synced');
 
 368     this.set('updateData', null);
 
 371   merge: function(message) {
 
 372     this.set('state', 'loading');
 
 373     messageCenter.addMessage('info', 'Scalam dokument z głównym repozytorium...');
 
 375       url: this.data.merge_url,
 
 380         target_revision: this.data.user_revision,
 
 383       complete: this.mergeCompleted.bind(this),
 
 384       success: function(data) { this.set('mergeData', data); }.bind(this)
 
 388   mergeCompleted: function(xhr, textStatus) {
 
 389     console.log(xhr.status, textStatus);
 
 390     if (xhr.status == 200) { // Sukces
 
 391       this.data.user_revision = this.get('mergeData').revision;
 
 392       for (var key in this.contentModels) {
 
 393         this.contentModels[key].set('revision', this.data.user_revision);
 
 394         this.contentModels[key].set('state', 'empty');
 
 396       messageCenter.addMessage('success', 'Scaliłem dokument z głównym repozytorium :-)');
 
 397     } else if (xhr.status == 202) { // Wygenerowano PullRequest
 
 398       messageCenter.addMessage('success', 'Wysłałem prośbę o scalenie dokumentu z głównym repozytorium.');
 
 399     } else if (xhr.status == 204) { // Nic nie zmieniono
 
 400       messageCenter.addMessage('info', 'Nic się nie zmieniło od ostatniego scalenia. Po co mam scalać?');
 
 401     } else if (xhr.status == 409) { // Konflikt podczas operacji
 
 402       messageCenter.addMessage('error', 'Wystąpił konflikt podczas scalania. Pędź po programistów! :-(');
 
 403     } else if (xhr.status == 500) {
 
 404       messageCenter.addMessage('critical', 'Błąd serwera. Pędź po programistów! :-(');
 
 406     this.set('state', 'synced');
 
 407     this.set('mergeData', null);
 
 411   set: function(property, value) {
 
 412     if (property == 'state') {
 
 413       console.log(this.description(), ':', property, '=', value);
 
 415     return this._super(property, value);
 
 420 var leftPanelView, rightPanelContainer, doc;
 
 424   documentsUrl = $('#api-base-url').text() + '/';
 
 425   toolbarUrl = $('#api-toolbar-url').text();
 
 427   doc = new Editor.DocumentModel();
 
 428   var editor = new EditorView('#body-wrap', doc);  
 
 431   var flashView = new FlashView('#flashview', messageCenter);
 
 432   var splitView = new SplitView('#splitview', doc);
 
 434   leftPanelView = new PanelContainerView('#left-panel-container', doc);
 
 435   rightPanelContainer = new PanelContainerView('#right-panel-container', doc);