GitHubFile.js 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. /**
  2. * Copyright (c) 2006-2017, JGraph Ltd
  3. * Copyright (c) 2006-2017, Gaudenz Alder
  4. */
  5. GitHubFile = function(ui, data, meta)
  6. {
  7. DrawioFile.call(this, ui, data);
  8. this.meta = meta;
  9. this.peer = this.ui.gitHub;
  10. };
  11. //Extends mxEventSource
  12. mxUtils.extend(GitHubFile, DrawioFile);
  13. /**
  14. * Translates this point by the given vector.
  15. *
  16. * @param {number} dx X-coordinate of the translation.
  17. * @param {number} dy Y-coordinate of the translation.
  18. */
  19. GitHubFile.prototype.getId = function()
  20. {
  21. return encodeURIComponent(this.meta.org) + '/' +
  22. ((this.meta.repo != null) ? encodeURIComponent(this.meta.repo) + '/' +
  23. ((this.meta.ref != null) ? this.meta.ref +
  24. ((this.meta.path != null) ? '/' + this.meta.path : '') : '') : '');
  25. };
  26. /**
  27. * Translates this point by the given vector.
  28. *
  29. * @param {number} dx X-coordinate of the translation.
  30. * @param {number} dy Y-coordinate of the translation.
  31. */
  32. GitHubFile.prototype.getHash = function()
  33. {
  34. return encodeURIComponent('H' + this.getId());
  35. };
  36. /**
  37. * Returns true if copy, export and print are not allowed for this file.
  38. */
  39. GitHubFile.prototype.getPublicUrl = function(fn)
  40. {
  41. // LATER: Check if download_url is always null for private repos
  42. if (this.meta.download_url != null)
  43. {
  44. mxUtils.get(this.meta.download_url, mxUtils.bind(this, function(req)
  45. {
  46. fn((req.getStatus() >= 200 && req.getStatus() <= 299) ? this.meta.download_url : null);
  47. }), mxUtils.bind(this, function()
  48. {
  49. fn(null);
  50. }));
  51. }
  52. else
  53. {
  54. fn(null);
  55. }
  56. };
  57. /**
  58. * Adds the listener for automatically saving the diagram for local changes.
  59. */
  60. GitHubFile.prototype.isConflict = function(err)
  61. {
  62. return err != null && err.status == 409;
  63. };
  64. /**
  65. * Translates this point by the given vector.
  66. *
  67. * @param {number} dx X-coordinate of the translation.
  68. * @param {number} dy Y-coordinate of the translation.
  69. */
  70. GitHubFile.prototype.getMode = function()
  71. {
  72. return App.MODE_GITHUB;
  73. };
  74. /**
  75. * Overridden to enable the autosave option in the document properties dialog.
  76. */
  77. GitHubFile.prototype.isAutosave = function()
  78. {
  79. return false;
  80. };
  81. /**
  82. * Translates this point by the given vector.
  83. *
  84. * @param {number} dx X-coordinate of the translation.
  85. * @param {number} dy Y-coordinate of the translation.
  86. */
  87. GitHubFile.prototype.getTitle = function()
  88. {
  89. return this.meta.name;
  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. */
  97. GitHubFile.prototype.isRenamable = function()
  98. {
  99. return false;
  100. };
  101. /**
  102. * Adds the listener for automatically saving the diagram for local changes.
  103. */
  104. GitHubFile.prototype.getLatestVersion = function(success, error)
  105. {
  106. this.peer.getFile(this.getId(), success, error);
  107. };
  108. /**
  109. * Hook for subclassers to update the descriptor from given file
  110. */
  111. GitHubFile.prototype.getDescriptor = function()
  112. {
  113. return this.meta;
  114. };
  115. /**
  116. * Hook for subclassers to update the descriptor from given file
  117. */
  118. GitHubFile.prototype.setDescriptor = function(desc)
  119. {
  120. this.meta = desc;
  121. };
  122. /**
  123. * Adds all listeners.
  124. */
  125. GitHubFile.prototype.getDescriptorEtag = function(desc)
  126. {
  127. return desc.sha;
  128. };
  129. /**
  130. * Adds the listener for automatically saving the diagram for local changes.
  131. */
  132. GitHubFile.prototype.setDescriptorEtag = function(desc, etag)
  133. {
  134. desc.sha = etag;
  135. };
  136. /**
  137. * Translates this point by the given vector.
  138. *
  139. * @param {number} dx X-coordinate of the translation.
  140. * @param {number} dy Y-coordinate of the translation.
  141. */
  142. GitHubFile.prototype.save = function(revision, success, error, unloading, overwrite, message)
  143. {
  144. this.doSave(this.getTitle(), success, error, unloading, overwrite, message);
  145. };
  146. /**
  147. * Translates this point by the given vector.
  148. *
  149. * @param {number} dx X-coordinate of the translation.
  150. * @param {number} dy Y-coordinate of the translation.
  151. */
  152. GitHubFile.prototype.saveAs = function(title, success, error)
  153. {
  154. this.doSave(title, success, error);
  155. };
  156. /**
  157. * Translates this point by the given vector.
  158. *
  159. * @param {number} dx X-coordinate of the translation.
  160. * @param {number} dy Y-coordinate of the translation.
  161. */
  162. GitHubFile.prototype.doSave = function(title, success, error, unloading, overwrite, message)
  163. {
  164. // Forces update of data for new extensions
  165. var prev = this.meta.name;
  166. this.meta.name = title;
  167. DrawioFile.prototype.save.apply(this, [null, mxUtils.bind(this, function()
  168. {
  169. this.meta.name = prev;
  170. this.saveFile(title, false, success, error, unloading, overwrite, message);
  171. }), error, unloading, overwrite]);
  172. };
  173. /**
  174. * Translates this point by the given vector.
  175. *
  176. * @param {number} dx X-coordinate of the translation.
  177. * @param {number} dy Y-coordinate of the translation.
  178. */
  179. GitHubFile.prototype.saveFile = function(title, revision, success, error, unloading, overwrite, message)
  180. {
  181. if (!this.isEditable())
  182. {
  183. if (success != null)
  184. {
  185. success();
  186. }
  187. }
  188. else if (!this.savingFile)
  189. {
  190. var doSave = mxUtils.bind(this, function(message)
  191. {
  192. if (this.getTitle() == title)
  193. {
  194. var prevModified = null;
  195. var modified = null;
  196. try
  197. {
  198. // Makes sure no changes get lost while the file is saved
  199. prevModified = this.isModified;
  200. modified = this.isModified();
  201. this.savingFile = true;
  202. this.savingFileTime = new Date();
  203. // Makes sure no changes get lost while the file is saved
  204. var prepare = mxUtils.bind(this, function()
  205. {
  206. this.setModified(false);
  207. this.isModified = function()
  208. {
  209. return modified;
  210. };
  211. });
  212. var savedEtag = this.getCurrentEtag();
  213. var savedData = this.data;
  214. prepare();
  215. this.peer.saveFile(this, mxUtils.bind(this, function(etag)
  216. {
  217. this.savingFile = false;
  218. this.isModified = prevModified;
  219. this.setDescriptorEtag(this.meta, etag);
  220. this.fileSaved(savedData, savedEtag, mxUtils.bind(this, function()
  221. {
  222. this.contentChanged();
  223. if (success != null)
  224. {
  225. success();
  226. }
  227. }), error);
  228. }),
  229. mxUtils.bind(this, function(err)
  230. {
  231. this.savingFile = false;
  232. this.isModified = prevModified;
  233. this.setModified(modified || this.isModified());
  234. if (this.isConflict(err))
  235. {
  236. this.inConflictState = true;
  237. if (error != null)
  238. {
  239. // Passes current commit message to avoid
  240. // multiple dialogs after synchronize
  241. error({commitMessage: message});
  242. }
  243. }
  244. else if (error != null)
  245. {
  246. // Handles modified state for retries
  247. if (err != null && err.retry != null)
  248. {
  249. var retry = err.retry;
  250. err.retry = function()
  251. {
  252. prepare();
  253. retry();
  254. };
  255. }
  256. error(err);
  257. }
  258. }), overwrite, message);
  259. }
  260. catch (e)
  261. {
  262. this.savingFile = false;
  263. if (prevModified != null)
  264. {
  265. this.isModified = prevModified;
  266. }
  267. if (modified != null)
  268. {
  269. this.setModified(modified || this.isModified());
  270. }
  271. if (error != null)
  272. {
  273. error(e);
  274. }
  275. else
  276. {
  277. throw e;
  278. }
  279. }
  280. }
  281. else
  282. {
  283. this.savingFile = true;
  284. this.savingFileTime = new Date();
  285. this.ui.pickFolder(this.getMode(), mxUtils.bind(this, function(folderId)
  286. {
  287. this.peer.insertFile(title, this.getData(), mxUtils.bind(this, function(file)
  288. {
  289. this.savingFile = false;
  290. if (success != null)
  291. {
  292. success();
  293. }
  294. this.ui.fileLoaded(file);
  295. }), mxUtils.bind(this, function()
  296. {
  297. this.savingFile = false;
  298. if (error != null)
  299. {
  300. error();
  301. }
  302. }), false, folderId, message);
  303. }));
  304. }
  305. });
  306. if (message != null)
  307. {
  308. doSave(message);
  309. }
  310. else
  311. {
  312. this.peer.showCommitDialog(this.meta.name,
  313. this.getDescriptorEtag(this.meta) == null ||
  314. this.meta.isNew, mxUtils.bind(this, function(message)
  315. {
  316. doSave(message);
  317. }), error);
  318. }
  319. }
  320. else if (error != null)
  321. {
  322. error({code: App.ERROR_BUSY});
  323. }
  324. };