OneDriveFile.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  1. /**
  2. * Copyright (c) 2006-2017, JGraph Ltd
  3. * Copyright (c) 2006-2017, Gaudenz Alder
  4. */
  5. OneDriveFile = function(ui, data, meta)
  6. {
  7. DrawioFile.call(this, ui, data);
  8. this.meta = meta;
  9. };
  10. //Extends mxEventSource
  11. mxUtils.extend(OneDriveFile, DrawioFile);
  12. /**
  13. * Translates this point by the given vector.
  14. *
  15. * @param {number} dx X-coordinate of the translation.
  16. * @param {number} dy Y-coordinate of the translation.
  17. */
  18. OneDriveFile.prototype.getId = function()
  19. {
  20. return this.getIdOf(this.meta);
  21. };
  22. /**
  23. * Translates this point by the given vector.
  24. *
  25. * @param {number} dx X-coordinate of the translation.
  26. * @param {number} dy Y-coordinate of the translation.
  27. */
  28. OneDriveFile.prototype.getParentId = function()
  29. {
  30. return this.getIdOf(this.meta, true);
  31. };
  32. /**
  33. * Translates this point by the given vector.
  34. *
  35. * @param {number} dx X-coordinate of the translation.
  36. * @param {number} dy Y-coordinate of the translation.
  37. */
  38. OneDriveFile.prototype.getIdOf = function(itemObj, parent)
  39. {
  40. //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
  41. return ((itemObj.parentReference != null && itemObj.parentReference.driveId != null) ? itemObj.parentReference.driveId + '/' : '') +
  42. ((parent != null) ? itemObj.parentReference.id : itemObj.id);
  43. };
  44. /**
  45. * Gets the channel ID for sync messages.
  46. */
  47. OneDriveFile.prototype.getChannelId = function()
  48. {
  49. return 'W-' + DrawioFile.prototype.getChannelId.apply(this, arguments);
  50. };
  51. /**
  52. * Translates this point by the given vector.
  53. *
  54. * @param {number} dx X-coordinate of the translation.
  55. * @param {number} dy Y-coordinate of the translation.
  56. */
  57. OneDriveFile.prototype.getHash = function()
  58. {
  59. return 'W' + encodeURIComponent(this.getId());
  60. };
  61. /**
  62. * Translates this point by the given vector.
  63. *
  64. * @param {number} dx X-coordinate of the translation.
  65. * @param {number} dy Y-coordinate of the translation.
  66. */
  67. OneDriveFile.prototype.getMode = function()
  68. {
  69. return App.MODE_ONEDRIVE;
  70. };
  71. /**
  72. * Overridden to enable the autosave option in the document properties dialog.
  73. */
  74. OneDriveFile.prototype.isAutosaveOptional = function()
  75. {
  76. return true;
  77. };
  78. /**
  79. * Translates this point by the given vector.
  80. *
  81. * @param {number} dx X-coordinate of the translation.
  82. * @param {number} dy Y-coordinate of the translation.
  83. */
  84. OneDriveFile.prototype.getTitle = function()
  85. {
  86. return this.meta.name;
  87. };
  88. /**
  89. * Translates this point by the given vector.
  90. *
  91. * @param {number} dx X-coordinate of the translation.
  92. * @param {number} dy Y-coordinate of the translation.
  93. */
  94. OneDriveFile.prototype.isRenamable = function()
  95. {
  96. return true;
  97. };
  98. /**
  99. * Hook for subclassers.
  100. */
  101. OneDriveFile.prototype.isSyncSupported = function()
  102. {
  103. return true;
  104. };
  105. /**
  106. * Specifies if notify events should be ignored.
  107. */
  108. OneDriveFile.prototype.getSize = function()
  109. {
  110. return this.meta.size;
  111. };
  112. /**
  113. * Adds the listener for automatically saving the diagram for local changes.
  114. */
  115. OneDriveFile.prototype.isConflict = function(req)
  116. {
  117. return req != null && (req.getStatus() == 412 || req.getStatus() == 409);
  118. };
  119. /**
  120. * Returns the current etag.
  121. */
  122. OneDriveFile.prototype.getCurrentUser = function()
  123. {
  124. return (this.ui.oneDrive != null) ? this.ui.oneDrive.user : null;
  125. };
  126. /**
  127. * Adds the listener for automatically saving the diagram for local changes.
  128. */
  129. OneDriveFile.prototype.loadDescriptor = function(success, error)
  130. {
  131. this.ui.oneDrive.executeRequest(this.ui.oneDrive.getItemURL(this.getId()), mxUtils.bind(this, function(req)
  132. {
  133. if (req.getStatus() >= 200 && req.getStatus() <= 299)
  134. {
  135. success(JSON.parse(req.getText()));
  136. }
  137. else if (error != null)
  138. {
  139. error();
  140. }
  141. }), error);
  142. };
  143. /**
  144. * Adds the listener for automatically saving the diagram for local changes.
  145. */
  146. OneDriveFile.prototype.getLatestVersion = function(success, error)
  147. {
  148. this.ui.oneDrive.getFile(this.getId(), success, error);
  149. };
  150. /**
  151. * Hook for subclassers to update the descriptor from given file
  152. */
  153. OneDriveFile.prototype.getDescriptor = function()
  154. {
  155. return this.meta;
  156. };
  157. /**
  158. * Hook for subclassers to update the descriptor from given file
  159. */
  160. OneDriveFile.prototype.setDescriptor = function(desc)
  161. {
  162. this.meta = desc;
  163. };
  164. /**
  165. * Using the quickXorHash of the content as the access password.
  166. */
  167. OneDriveFile.prototype.getDescriptorSecret = function(desc)
  168. {
  169. if (desc.file != null && desc.file.hashes != null &&
  170. desc.file.hashes.quickXorHash != null)
  171. {
  172. return desc.file.hashes.quickXorHash;
  173. }
  174. return null;
  175. };
  176. /**
  177. * Adds all listeners.
  178. */
  179. OneDriveFile.prototype.getDescriptorEtag = function(desc)
  180. {
  181. return desc.eTag;
  182. };
  183. /**
  184. * Adds the listener for automatically saving the diagram for local changes.
  185. */
  186. OneDriveFile.prototype.setDescriptorEtag = function(desc, etag)
  187. {
  188. desc.eTag = etag;
  189. };
  190. /**
  191. * Adds the listener for automatically saving the diagram for local changes.
  192. */
  193. OneDriveFile.prototype.loadPatchDescriptor = function(success, error)
  194. {
  195. var url = this.ui.oneDrive.getItemURL(this.getId());
  196. this.ui.oneDrive.executeRequest(url + '?select=etag,file' , mxUtils.bind(this, function(req)
  197. {
  198. if (req.getStatus() >= 200 && req.getStatus() <= 299)
  199. {
  200. success(JSON.parse(req.getText()));
  201. }
  202. else
  203. {
  204. error(this.ui.oneDrive.parseRequestText(req));
  205. }
  206. }), error)
  207. };
  208. /**
  209. * Using MD5 of create timestamp and user ID as crypto key.
  210. */
  211. OneDriveFile.prototype.getChannelKey = function()
  212. {
  213. if (typeof CryptoJS !== 'undefined')
  214. {
  215. return CryptoJS.MD5(this.meta.createdDateTime +
  216. ((this.meta.createdBy != null &&
  217. this.meta.createdBy.user != null) ?
  218. this.meta.createdBy.user.id : '')).toString();
  219. }
  220. return null;
  221. };
  222. /**
  223. * Adds all listeners.
  224. */
  225. OneDriveFile.prototype.getLastModifiedDate = function()
  226. {
  227. return new Date(this.meta.lastModifiedDateTime);
  228. };
  229. /**
  230. * Translates this point by the given vector.
  231. *
  232. * @param {number} dx X-coordinate of the translation.
  233. * @param {number} dy Y-coordinate of the translation.
  234. */
  235. OneDriveFile.prototype.save = function(revision, success, error, unloading, overwrite)
  236. {
  237. this.doSave(this.getTitle(), revision, success, error, unloading, overwrite);
  238. };
  239. /**
  240. * Translates this point by the given vector.
  241. *
  242. * @param {number} dx X-coordinate of the translation.
  243. * @param {number} dy Y-coordinate of the translation.
  244. */
  245. OneDriveFile.prototype.saveAs = function(title, success, error)
  246. {
  247. this.doSave(title, false, success, error);
  248. };
  249. /**
  250. * Translates this point by the given vector.
  251. *
  252. * @param {number} dx X-coordinate of the translation.
  253. * @param {number} dy Y-coordinate of the translation.
  254. */
  255. OneDriveFile.prototype.doSave = function(title, revision, success, error, unloading, overwrite)
  256. {
  257. // Forces update of data for new extensions
  258. var prev = this.meta.name;
  259. this.meta.name = title;
  260. DrawioFile.prototype.save.apply(this, [null, mxUtils.bind(this, function()
  261. {
  262. this.meta.name = prev;
  263. this.saveFile(title, revision, success, error, unloading, overwrite);
  264. }), error, unloading, overwrite]);
  265. };
  266. /**
  267. * Translates this point by the given vector.
  268. *
  269. * @param {number} dx X-coordinate of the translation.
  270. * @param {number} dy Y-coordinate of the translation.
  271. */
  272. OneDriveFile.prototype.saveFile = function(title, revision, success, error, unloading, overwrite)
  273. {
  274. if (!this.isEditable())
  275. {
  276. if (success != null)
  277. {
  278. success();
  279. }
  280. }
  281. else if (!this.savingFile)
  282. {
  283. if (this.getTitle() == title)
  284. {
  285. var doSave = mxUtils.bind(this, function()
  286. {
  287. var prevModified = null;
  288. var modified = null;
  289. try
  290. {
  291. // Makes sure no changes get lost while the file is saved
  292. prevModified = this.isModified;
  293. modified = this.isModified();
  294. this.savingFile = true;
  295. this.savingFileTime = new Date();
  296. var prepare = mxUtils.bind(this, function()
  297. {
  298. this.setModified(false);
  299. this.isModified = function()
  300. {
  301. return modified;
  302. };
  303. });
  304. var etag = (!overwrite && this.constructor == OneDriveFile &&
  305. (DrawioFile.SYNC == 'manual' || DrawioFile.SYNC == 'auto')) ?
  306. this.getCurrentEtag() : null;
  307. var lastDesc = this.meta;
  308. prepare();
  309. this.ui.oneDrive.saveFile(this, mxUtils.bind(this, function(meta, savedData)
  310. {
  311. this.isModified = prevModified;
  312. this.savingFile = false;
  313. this.meta = meta;
  314. this.fileSaved(savedData, lastDesc, mxUtils.bind(this, function()
  315. {
  316. this.contentChanged();
  317. if (success != null)
  318. {
  319. success();
  320. }
  321. }), error);
  322. }),
  323. mxUtils.bind(this, function(err, req)
  324. {
  325. this.savingFile = false;
  326. this.isModified = prevModified;
  327. this.setModified(modified || this.isModified());
  328. if (this.isConflict(req))
  329. {
  330. this.inConflictState = true;
  331. if (this.sync != null)
  332. {
  333. this.savingFile = true;
  334. this.savingFileTime = new Date();
  335. this.sync.fileConflict(null, mxUtils.bind(this, function()
  336. {
  337. // Adds random cool-off
  338. window.setTimeout(mxUtils.bind(this, function()
  339. {
  340. this.updateFileData();
  341. doSave();
  342. }), 100 + Math.random() * 500);
  343. }), mxUtils.bind(this, function()
  344. {
  345. this.savingFile = false;
  346. if (error != null)
  347. {
  348. error();
  349. }
  350. }));
  351. }
  352. else if (error != null)
  353. {
  354. error();
  355. }
  356. }
  357. else if (error != null)
  358. {
  359. // Handles modified state for retries
  360. if (err != null && err.retry != null)
  361. {
  362. var retry = err.retry;
  363. err.retry = function()
  364. {
  365. prepare();
  366. retry();
  367. };
  368. }
  369. error(err);
  370. }
  371. }), etag);
  372. }
  373. catch (e)
  374. {
  375. this.savingFile = false;
  376. if (prevModified != null)
  377. {
  378. this.isModified = prevModified;
  379. }
  380. if (modified != null)
  381. {
  382. this.setModified(modified || this.isModified());
  383. }
  384. if (error != null)
  385. {
  386. error(e);
  387. }
  388. else
  389. {
  390. throw e;
  391. }
  392. }
  393. });
  394. doSave();
  395. }
  396. else
  397. {
  398. this.savingFile = true;
  399. this.savingFileTime = new Date();
  400. this.ui.oneDrive.insertFile(title, this.getData(), mxUtils.bind(this, function(file)
  401. {
  402. this.savingFile = false;
  403. if (success != null)
  404. {
  405. success();
  406. }
  407. this.ui.fileLoaded(file);
  408. }), mxUtils.bind(this, function()
  409. {
  410. this.savingFile = false;
  411. if (error != null)
  412. {
  413. error();
  414. }
  415. }));
  416. }
  417. }
  418. };
  419. /**
  420. * Translates this point by the given vector.
  421. *
  422. * @param {number} dx X-coordinate of the translation.
  423. * @param {number} dy Y-coordinate of the translation.
  424. */
  425. OneDriveFile.prototype.rename = function(title, success, error)
  426. {
  427. var etag = this.getCurrentEtag();
  428. this.ui.oneDrive.renameFile(this, title, mxUtils.bind(this, function(meta)
  429. {
  430. if (!this.hasSameExtension(title, this.getTitle()))
  431. {
  432. this.meta = meta;
  433. if (this.sync != null)
  434. {
  435. this.sync.descriptorChanged(etag);
  436. }
  437. this.save(true, success, error);
  438. }
  439. else
  440. {
  441. this.meta = meta;
  442. this.descriptorChanged();
  443. if (this.sync != null)
  444. {
  445. this.sync.descriptorChanged(etag);
  446. }
  447. if (success != null)
  448. {
  449. success(meta);
  450. }
  451. }
  452. }), error);
  453. };
  454. /**
  455. * Translates this point by the given vector.
  456. *
  457. * @param {number} dx X-coordinate of the translation.
  458. * @param {number} dy Y-coordinate of the translation.
  459. */
  460. OneDriveFile.prototype.move = function(folderId, success, error)
  461. {
  462. this.ui.oneDrive.moveFile(this.getId(), folderId, mxUtils.bind(this, function(meta)
  463. {
  464. this.meta = meta;
  465. this.descriptorChanged();
  466. if (success != null)
  467. {
  468. success(meta);
  469. }
  470. }), error);
  471. };