1/** 2 * Copyright (c) 2006-2017, JGraph Ltd 3 * Copyright (c) 2006-2017, Gaudenz Alder 4 */ 5OneDriveFile = function(ui, data, meta) 6{ 7 DrawioFile.call(this, ui, data); 8 9 this.meta = meta; 10}; 11 12//Extends mxEventSource 13mxUtils.extend(OneDriveFile, DrawioFile); 14 15/** 16 * Shorter autosave delay for optimistic sync. 17 */ 18OneDriveFile.prototype.autosaveDelay = 300; 19 20/** 21 * Translates this point by the given vector. 22 * 23 * @param {number} dx X-coordinate of the translation. 24 * @param {number} dy Y-coordinate of the translation. 25 */ 26OneDriveFile.prototype.share = function() 27{ 28 var url = this.meta.webUrl; 29 url = url.substring(0, url.lastIndexOf('/')); 30 31 if (this.meta.parentReference != null) 32 { 33 try 34 { 35 // Best effort guessing of the web interface URL for the file 36 if (this.meta.parentReference.driveType == 'personal') 37 { 38 url = 'https://onedrive.live.com/?cid=' + encodeURIComponent(this.meta.parentReference.driveId) + 39 '&id=' + encodeURIComponent(this.meta.id); 40 } 41 else if (this.meta.parentReference.driveType == 'documentLibrary') 42 { 43 var path = this.meta.parentReference.path; 44 path = path.substring(path.indexOf('/root:') + 6); 45 46 var id = this.meta.webUrl; 47 var url = id.substring(0, id.length - path.length - this.meta.name.length - ((path.length > 0) ? 1 : 0)); 48 id = id.substring(id.indexOf('/', 8)); 49 50 url = url + '/Forms/AllItems.aspx?id=' + id + '&parent=' + id.substring(0, id.lastIndexOf('/')); 51 } 52 else if (this.meta.parentReference.driveType == 'business') 53 { 54 var url = this.meta['@microsoft.graph.downloadUrl']; 55 var idx = url.indexOf('/_layouts/15/download.aspx?'); 56 57 // Strips protocol 58 var id = this.meta.webUrl; 59 var parent = id; 60 61 id = id.substring(8); 62 63 // Gets path and parent path 64 id = id.substring(id.indexOf('/')); 65 parent = parent.substring(0, parent.lastIndexOf('/')); 66 parent = parent.substring(parent.indexOf('/', 8)) 67 68 url = url.substring(0, idx) + '/_layouts/15/onedrive.aspx?id=' + id + '&parent=' + parent; 69 } 70 } 71 catch (e) 72 { 73 // ignore 74 } 75 } 76 77 this.ui.editor.graph.openLink(url); 78}; 79 80/** 81 * Translates this point by the given vector. 82 * 83 * @param {number} dx X-coordinate of the translation. 84 * @param {number} dy Y-coordinate of the translation. 85 */ 86OneDriveFile.prototype.getId = function() 87{ 88 return this.getIdOf(this.meta); 89}; 90 91/** 92 * Translates this point by the given vector. 93 * 94 * @param {number} dx X-coordinate of the translation. 95 * @param {number} dy Y-coordinate of the translation. 96 */ 97OneDriveFile.prototype.getParentId = function() 98{ 99 return this.getIdOf(this.meta, true); 100}; 101 102/** 103 * Translates this point by the given vector. 104 * 105 * @param {number} dx X-coordinate of the translation. 106 * @param {number} dy Y-coordinate of the translation. 107 */ 108OneDriveFile.prototype.getIdOf = function(itemObj, parent) 109{ 110 //TODO driveId is most probably always there. No need to check if it exists. Also, after some time, the code that check the old id format won't be needed 111 return ((itemObj.parentReference != null && itemObj.parentReference.driveId != null) ? itemObj.parentReference.driveId + '/' : '') + 112 ((parent != null) ? itemObj.parentReference.id : itemObj.id); 113}; 114 115/** 116 * Gets the channel ID for sync messages. 117 */ 118OneDriveFile.prototype.getChannelId = function() 119{ 120 return 'W-' + DrawioFile.prototype.getChannelId.apply(this, arguments); 121}; 122 123/** 124 * Translates this point by the given vector. 125 * 126 * @param {number} dx X-coordinate of the translation. 127 * @param {number} dy Y-coordinate of the translation. 128 */ 129OneDriveFile.prototype.getHash = function() 130{ 131 return 'W' + encodeURIComponent(this.getId()); 132}; 133 134/** 135 * Translates this point by the given vector. 136 * 137 * @param {number} dx X-coordinate of the translation. 138 * @param {number} dy Y-coordinate of the translation. 139 */ 140OneDriveFile.prototype.getMode = function() 141{ 142 return App.MODE_ONEDRIVE; 143}; 144 145/** 146 * Overridden to enable the autosave option in the document properties dialog. 147 */ 148OneDriveFile.prototype.isAutosaveOptional = function() 149{ 150 return true; 151}; 152 153/** 154 * Translates this point by the given vector. 155 * 156 * @param {number} dx X-coordinate of the translation. 157 * @param {number} dy Y-coordinate of the translation. 158 */ 159OneDriveFile.prototype.getTitle = function() 160{ 161 return this.meta.name; 162}; 163 164/** 165 * Translates this point by the given vector. 166 * 167 * @param {number} dx X-coordinate of the translation. 168 * @param {number} dy Y-coordinate of the translation. 169 */ 170OneDriveFile.prototype.isRenamable = function() 171{ 172 return true; 173}; 174 175/** 176 * Returns true if the notification to update should be sent 177 * together with the save request. 178 */ 179OneDriveFile.prototype.isOptimisticSync = function() 180{ 181 return true; 182}; 183 184/** 185 * Hook for subclassers. 186 */ 187OneDriveFile.prototype.isSyncSupported = function() 188{ 189 return true; 190}; 191 192/** 193 * Specifies if notify events should be ignored. 194 */ 195OneDriveFile.prototype.getSize = function() 196{ 197 return this.meta.size; 198}; 199 200/** 201 * Adds the listener for automatically saving the diagram for local changes. 202 */ 203OneDriveFile.prototype.isConflict = function(req) 204{ 205 return req != null && (req.getStatus() == 412 || req.getStatus() == 409); 206}; 207 208/** 209 * Returns the current etag. 210 */ 211OneDriveFile.prototype.getCurrentUser = function() 212{ 213 return (this.ui.oneDrive != null) ? this.ui.oneDrive.user : null; 214}; 215 216/** 217 * Adds the listener for automatically saving the diagram for local changes. 218 */ 219OneDriveFile.prototype.loadDescriptor = function(success, error) 220{ 221 this.ui.oneDrive.executeRequest(this.ui.oneDrive.getItemURL(this.getId()), mxUtils.bind(this, function(req) 222 { 223 if (req.getStatus() >= 200 && req.getStatus() <= 299) 224 { 225 success(JSON.parse(req.getText())); 226 } 227 else if (error != null) 228 { 229 error(); 230 } 231 }), error); 232}; 233 234/** 235 * Adds the listener for automatically saving the diagram for local changes. 236 */ 237OneDriveFile.prototype.getLatestVersion = function(success, error) 238{ 239 this.ui.oneDrive.getFile(this.getId(), success, error); 240}; 241 242/** 243 * Hook for subclassers to update the descriptor from given file 244 */ 245OneDriveFile.prototype.getDescriptor = function() 246{ 247 return this.meta; 248}; 249 250/** 251 * Hook for subclassers to update the descriptor from given file 252 */ 253OneDriveFile.prototype.setDescriptor = function(desc) 254{ 255 this.meta = desc; 256}; 257 258/** 259 * Adds all listeners. 260 */ 261OneDriveFile.prototype.getDescriptorEtag = function(desc) 262{ 263 return desc.eTag; 264}; 265 266/** 267 * Adds the listener for automatically saving the diagram for local changes. 268 */ 269OneDriveFile.prototype.setDescriptorEtag = function(desc, etag) 270{ 271 desc.eTag = etag; 272}; 273 274/** 275 * Adds the listener for automatically saving the diagram for local changes. 276 */ 277OneDriveFile.prototype.loadPatchDescriptor = function(success, error) 278{ 279 var url = this.ui.oneDrive.getItemURL(this.getId()); 280 281 this.ui.oneDrive.executeRequest(url + '?select=etag,file' , mxUtils.bind(this, function(req) 282 { 283 if (req.getStatus() >= 200 && req.getStatus() <= 299) 284 { 285 success(JSON.parse(req.getText())); 286 } 287 else 288 { 289 error(this.ui.oneDrive.parseRequestText(req)); 290 } 291 }), error) 292}; 293 294/** 295 * Using MD5 of create timestamp and user ID as crypto key. 296 */ 297OneDriveFile.prototype.getChannelKey = function() 298{ 299 if (typeof CryptoJS !== 'undefined') 300 { 301 return CryptoJS.MD5(this.meta.createdDateTime + 302 ((this.meta.createdBy != null && 303 this.meta.createdBy.user != null) ? 304 this.meta.createdBy.user.id : '')).toString(); 305 } 306 307 return null; 308}; 309 310/** 311 * Adds all listeners. 312 */ 313OneDriveFile.prototype.getLastModifiedDate = function() 314{ 315 return new Date(this.meta.lastModifiedDateTime); 316}; 317 318/** 319 * Translates this point by the given vector. 320 * 321 * @param {number} dx X-coordinate of the translation. 322 * @param {number} dy Y-coordinate of the translation. 323 */ 324OneDriveFile.prototype.save = function(revision, success, error, unloading, overwrite) 325{ 326 this.doSave(this.getTitle(), revision, success, error, unloading, overwrite); 327}; 328 329/** 330 * Translates this point by the given vector. 331 * 332 * @param {number} dx X-coordinate of the translation. 333 * @param {number} dy Y-coordinate of the translation. 334 */ 335OneDriveFile.prototype.saveAs = function(title, success, error) 336{ 337 this.doSave(title, false, success, error); 338}; 339 340/** 341 * Translates this point by the given vector. 342 * 343 * @param {number} dx X-coordinate of the translation. 344 * @param {number} dy Y-coordinate of the translation. 345 */ 346OneDriveFile.prototype.doSave = function(title, revision, success, error, unloading, overwrite) 347{ 348 // Forces update of data for new extensions 349 var prev = this.meta.name; 350 this.meta.name = title; 351 352 DrawioFile.prototype.save.apply(this, [null, mxUtils.bind(this, function() 353 { 354 this.meta.name = prev; 355 this.saveFile(title, revision, success, error, unloading, overwrite); 356 }), error, unloading, overwrite]); 357}; 358 359/** 360 * Translates this point by the given vector. 361 * 362 * @param {number} dx X-coordinate of the translation. 363 * @param {number} dy Y-coordinate of the translation. 364 */ 365OneDriveFile.prototype.saveFile = function(title, revision, success, error, unloading, overwrite) 366{ 367 if (!this.isEditable()) 368 { 369 if (success != null) 370 { 371 success(); 372 } 373 } 374 else if (!this.savingFile) 375 { 376 if (this.getTitle() == title) 377 { 378 var doSave = mxUtils.bind(this, function() 379 { 380 try 381 { 382 // Sets shadow modified state during save 383 this.savingFileTime = new Date(); 384 this.setShadowModified(false); 385 this.savingFile = true; 386 387 var etag = (!overwrite && this.constructor == OneDriveFile && 388 (DrawioFile.SYNC == 'manual' || DrawioFile.SYNC == 'auto')) ? 389 this.getCurrentEtag() : null; 390 var lastDesc = this.meta; 391 this.fileSaving(); 392 393 this.ui.oneDrive.saveFile(this, mxUtils.bind(this, function(meta, savedData) 394 { 395 // Checks for changes during save 396 this.setModified(this.getShadowModified()); 397 this.savingFile = false; 398 this.meta = meta; 399 400 this.fileSaved(savedData, lastDesc, mxUtils.bind(this, function() 401 { 402 this.contentChanged(); 403 404 if (success != null) 405 { 406 success(); 407 } 408 }), error); 409 }), mxUtils.bind(this, function(err, req) 410 { 411 try 412 { 413 this.savingFile = false; 414 415 if (this.isConflict(req)) 416 { 417 this.inConflictState = true; 418 419 if (this.sync != null) 420 { 421 this.savingFile = true; 422 423 this.sync.fileConflict(null, mxUtils.bind(this, function() 424 { 425 // Adds random cool-off 426 window.setTimeout(mxUtils.bind(this, function() 427 { 428 this.updateFileData(); 429 doSave(); 430 }), 100 + Math.random() * 500); 431 }), mxUtils.bind(this, function() 432 { 433 this.savingFile = false; 434 435 if (error != null) 436 { 437 error(); 438 } 439 })); 440 } 441 else if (error != null) 442 { 443 error(); 444 } 445 } 446 else if (error != null) 447 { 448 error(err); 449 } 450 } 451 catch (e) 452 { 453 this.savingFile = false; 454 455 if (error != null) 456 { 457 error(e); 458 } 459 else 460 { 461 throw e; 462 } 463 } 464 }), etag); 465 } 466 catch (e) 467 { 468 this.savingFile = false; 469 470 if (error != null) 471 { 472 error(e); 473 } 474 else 475 { 476 throw e; 477 } 478 } 479 }); 480 481 doSave(); 482 } 483 else 484 { 485 // Sets shadow modified state during save 486 this.savingFileTime = new Date(); 487 this.setShadowModified(false); 488 this.savingFile = true; 489 490 this.ui.oneDrive.insertFile(title, this.getData(), mxUtils.bind(this, function(file) 491 { 492 // Checks for changes during save 493 this.setModified(this.getShadowModified()); 494 this.savingFile = false; 495 496 if (success != null) 497 { 498 success(); 499 } 500 501 this.ui.fileLoaded(file); 502 }), mxUtils.bind(this, function() 503 { 504 this.savingFile = false; 505 506 if (error != null) 507 { 508 error(); 509 } 510 })); 511 } 512 } 513}; 514 515/** 516 * Translates this point by the given vector. 517 * 518 * @param {number} dx X-coordinate of the translation. 519 * @param {number} dy Y-coordinate of the translation. 520 */ 521OneDriveFile.prototype.rename = function(title, success, error) 522{ 523 var etag = this.getCurrentEtag(); 524 525 this.ui.oneDrive.renameFile(this, title, mxUtils.bind(this, function(meta) 526 { 527 if (!this.hasSameExtension(title, this.getTitle())) 528 { 529 this.meta = meta; 530 531 if (this.sync != null) 532 { 533 this.sync.descriptorChanged(etag); 534 } 535 536 this.save(true, success, error); 537 } 538 else 539 { 540 this.meta = meta; 541 this.descriptorChanged(); 542 543 if (this.sync != null) 544 { 545 this.sync.descriptorChanged(etag); 546 } 547 548 if (success != null) 549 { 550 success(meta); 551 } 552 } 553 }), error); 554}; 555 556/** 557 * Translates this point by the given vector. 558 * 559 * @param {number} dx X-coordinate of the translation. 560 * @param {number} dy Y-coordinate of the translation. 561 */ 562OneDriveFile.prototype.move = function(folderId, success, error) 563{ 564 this.ui.oneDrive.moveFile(this.getId(), folderId, mxUtils.bind(this, function(meta) 565 { 566 this.meta = meta; 567 this.descriptorChanged(); 568 569 if (success != null) 570 { 571 success(meta); 572 } 573 }), error); 574}; 575