GitHubFile.js 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  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.share = function()
  20. {
  21. this.ui.editor.graph.openLink('https://github.com/' +
  22. encodeURIComponent(this.meta.org) + '/' +
  23. encodeURIComponent(this.meta.repo) +'/settings/access');
  24. };
  25. /**
  26. * Translates this point by the given vector.
  27. *
  28. * @param {number} dx X-coordinate of the translation.
  29. * @param {number} dy Y-coordinate of the translation.
  30. */
  31. GitHubFile.prototype.getId = function()
  32. {
  33. return encodeURIComponent(this.meta.org) + '/' +
  34. ((this.meta.repo != null) ? encodeURIComponent(this.meta.repo) + '/' +
  35. ((this.meta.ref != null) ? this.meta.ref +
  36. ((this.meta.path != null) ? '/' + this.meta.path : '') : '') : '');
  37. };
  38. /**
  39. * Translates this point by the given vector.
  40. *
  41. * @param {number} dx X-coordinate of the translation.
  42. * @param {number} dy Y-coordinate of the translation.
  43. */
  44. GitHubFile.prototype.getHash = function()
  45. {
  46. return encodeURIComponent('H' + this.getId());
  47. };
  48. /**
  49. * Returns true if copy, export and print are not allowed for this file.
  50. */
  51. GitHubFile.prototype.getFileUrl = function()
  52. {
  53. return 'https://github.com/' + encodeURIComponent(this.meta.org) + '/' +
  54. encodeURIComponent(this.meta.repo) + '/blob/' +
  55. this.meta.ref + '/' + this.meta.path;
  56. };
  57. /**
  58. * Returns true if copy, export and print are not allowed for this file.
  59. */
  60. GitHubFile.prototype.getFolderUrl = function()
  61. {
  62. return 'https://github.com/' + encodeURIComponent(this.meta.org) + '/' +
  63. encodeURIComponent(this.meta.repo) + '/tree/' + this.meta.ref + '/' +
  64. this.meta.path.split('/').slice(0, -1).join('/');
  65. };
  66. /**
  67. * Returns true if copy, export and print are not allowed for this file.
  68. */
  69. GitHubFile.prototype.getPublicUrl = function(fn)
  70. {
  71. if (this.meta.download_url != null)
  72. {
  73. try
  74. {
  75. // Checks for short-term token in URL which means private repo
  76. var url = new URL(this.meta.download_url);
  77. if (url.search != '')
  78. {
  79. fn(null);
  80. }
  81. else
  82. {
  83. mxUtils.get(this.meta.download_url, mxUtils.bind(this, function(req)
  84. {
  85. fn((req.getStatus() >= 200 && req.getStatus() <= 299) ? this.meta.download_url : null);
  86. }), mxUtils.bind(this, function()
  87. {
  88. fn(null);
  89. }));
  90. }
  91. }
  92. catch (e)
  93. {
  94. fn(null);
  95. }
  96. }
  97. else
  98. {
  99. fn(null);
  100. }
  101. };
  102. /**
  103. * Adds the listener for automatically saving the diagram for local changes.
  104. */
  105. GitHubFile.prototype.isConflict = function(err)
  106. {
  107. return err != null && err.status == 409;
  108. };
  109. /**
  110. * Translates this point by the given vector.
  111. *
  112. * @param {number} dx X-coordinate of the translation.
  113. * @param {number} dy Y-coordinate of the translation.
  114. */
  115. GitHubFile.prototype.getMode = function()
  116. {
  117. return App.MODE_GITHUB;
  118. };
  119. /**
  120. * Overridden to enable the autosave option in the document properties dialog.
  121. */
  122. GitHubFile.prototype.isAutosave = function()
  123. {
  124. return false;
  125. };
  126. /**
  127. * Translates this point by the given vector.
  128. *
  129. * @param {number} dx X-coordinate of the translation.
  130. * @param {number} dy Y-coordinate of the translation.
  131. */
  132. GitHubFile.prototype.getTitle = function()
  133. {
  134. return this.meta.name;
  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.isRenamable = function()
  143. {
  144. return false;
  145. };
  146. /**
  147. * Adds the listener for automatically saving the diagram for local changes.
  148. */
  149. GitHubFile.prototype.getLatestVersion = function(success, error)
  150. {
  151. this.peer.getFile(this.getId(), success, error);
  152. };
  153. /**
  154. * Hook for subclassers to update the descriptor from given file
  155. */
  156. GitHubFile.prototype.getDescriptor = function()
  157. {
  158. return this.meta;
  159. };
  160. /**
  161. * Hook for subclassers to update the descriptor from given file
  162. */
  163. GitHubFile.prototype.setDescriptor = function(desc)
  164. {
  165. this.meta = desc;
  166. };
  167. /**
  168. * Adds all listeners.
  169. */
  170. GitHubFile.prototype.getDescriptorEtag = function(desc)
  171. {
  172. return desc.sha;
  173. };
  174. /**
  175. * Adds the listener for automatically saving the diagram for local changes.
  176. */
  177. GitHubFile.prototype.setDescriptorEtag = function(desc, etag)
  178. {
  179. desc.sha = etag;
  180. };
  181. /**
  182. * Translates this point by the given vector.
  183. *
  184. * @param {number} dx X-coordinate of the translation.
  185. * @param {number} dy Y-coordinate of the translation.
  186. */
  187. GitHubFile.prototype.save = function(revision, success, error, unloading, overwrite, message)
  188. {
  189. this.doSave(this.getTitle(), success, error, unloading, overwrite, message);
  190. };
  191. /**
  192. * Translates this point by the given vector.
  193. *
  194. * @param {number} dx X-coordinate of the translation.
  195. * @param {number} dy Y-coordinate of the translation.
  196. */
  197. GitHubFile.prototype.saveAs = function(title, success, error)
  198. {
  199. this.doSave(title, success, error);
  200. };
  201. /**
  202. * Translates this point by the given vector.
  203. *
  204. * @param {number} dx X-coordinate of the translation.
  205. * @param {number} dy Y-coordinate of the translation.
  206. */
  207. GitHubFile.prototype.doSave = function(title, success, error, unloading, overwrite, message)
  208. {
  209. // Forces update of data for new extensions
  210. var prev = this.meta.name;
  211. this.meta.name = title;
  212. DrawioFile.prototype.save.apply(this, [null, mxUtils.bind(this, function()
  213. {
  214. this.meta.name = prev;
  215. this.saveFile(title, false, success, error, unloading, overwrite, message);
  216. }), error, unloading, overwrite]);
  217. };
  218. /**
  219. * Translates this point by the given vector.
  220. *
  221. * @param {number} dx X-coordinate of the translation.
  222. * @param {number} dy Y-coordinate of the translation.
  223. */
  224. GitHubFile.prototype.saveFile = function(title, revision, success, error, unloading, overwrite, message)
  225. {
  226. if (!this.isEditable())
  227. {
  228. if (success != null)
  229. {
  230. success();
  231. }
  232. }
  233. else if (!this.savingFile)
  234. {
  235. var doSave = mxUtils.bind(this, function(message)
  236. {
  237. if (this.getTitle() == title)
  238. {
  239. try
  240. {
  241. // Sets shadow modified state during save
  242. this.savingFileTime = new Date();
  243. this.setShadowModified(false);
  244. this.savingFile = true;
  245. var savedEtag = this.getCurrentEtag();
  246. var savedData = this.data;
  247. this.peer.saveFile(this, mxUtils.bind(this, function(etag)
  248. {
  249. // Checks for changes during save
  250. this.setModified(this.getShadowModified());
  251. this.savingFile = false;
  252. this.setDescriptorEtag(this.meta, etag);
  253. this.fileSaved(savedData, savedEtag, mxUtils.bind(this, function()
  254. {
  255. this.contentChanged();
  256. if (success != null)
  257. {
  258. success();
  259. }
  260. }), error);
  261. }),
  262. mxUtils.bind(this, function(err)
  263. {
  264. this.savingFile = false;
  265. if (this.isConflict(err))
  266. {
  267. this.inConflictState = true;
  268. if (error != null)
  269. {
  270. // Adds commit message to save after
  271. // conflict has been resolved
  272. err.commitMessage = message;
  273. error(err);
  274. }
  275. }
  276. else if (error != null)
  277. {
  278. error(err);
  279. }
  280. }), overwrite, message);
  281. }
  282. catch (e)
  283. {
  284. this.savingFile = false;
  285. if (error != null)
  286. {
  287. error(e);
  288. }
  289. else
  290. {
  291. throw e;
  292. }
  293. }
  294. }
  295. else
  296. {
  297. // Sets shadow modified state during save
  298. this.savingFileTime = new Date();
  299. this.setShadowModified(false);
  300. this.savingFile = true;
  301. this.ui.pickFolder(this.getMode(), mxUtils.bind(this, function(folderId)
  302. {
  303. this.peer.insertFile(title, this.getData(), mxUtils.bind(this, function(file)
  304. {
  305. // Checks for changes during save
  306. this.setModified(this.getShadowModified());
  307. this.savingFile = false;
  308. if (success != null)
  309. {
  310. success();
  311. }
  312. this.ui.fileLoaded(file);
  313. }), mxUtils.bind(this, function()
  314. {
  315. this.savingFile = false;
  316. if (error != null)
  317. {
  318. error();
  319. }
  320. }), false, folderId, message);
  321. }));
  322. }
  323. });
  324. if (message != null)
  325. {
  326. doSave(message);
  327. }
  328. else
  329. {
  330. this.peer.showCommitDialog(this.meta.name,
  331. this.getDescriptorEtag(this.meta) == null ||
  332. this.meta.isNew, mxUtils.bind(this, function(message)
  333. {
  334. doSave(message);
  335. }), error);
  336. }
  337. }
  338. else if (error != null)
  339. {
  340. error({code: App.ERROR_BUSY});
  341. }
  342. };