@concord-consortium/cloud-file-manager 2.0.0-pre.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (486) hide show
  1. package/dist/autolaunch/autolaunch.css +220 -0
  2. package/dist/autolaunch/autolaunch.html +133 -0
  3. package/dist/autolaunch/autolaunch.js +3 -0
  4. package/dist/autolaunch/autolaunch.js.LICENSE.txt +16 -0
  5. package/dist/autolaunch/autolaunch.js.map +1 -0
  6. package/dist/cjs/app-options.d.ts +118 -0
  7. package/dist/cjs/app-options.js +6 -0
  8. package/dist/cjs/app-options.js.map +1 -0
  9. package/dist/cjs/client.d.ts +165 -0
  10. package/dist/cjs/client.js +1391 -0
  11. package/dist/cjs/client.js.map +1 -0
  12. package/dist/cjs/cloud-file-manager.d.ts +16 -0
  13. package/dist/cjs/cloud-file-manager.js +79 -0
  14. package/dist/cjs/cloud-file-manager.js.map +1 -0
  15. package/dist/cjs/create-react-factory.d.ts +3 -0
  16. package/dist/cjs/create-react-factory.js +14 -0
  17. package/dist/cjs/create-react-factory.js.map +1 -0
  18. package/dist/cjs/index.d.ts +4 -0
  19. package/dist/cjs/index.js +21 -0
  20. package/dist/cjs/index.js.map +1 -0
  21. package/dist/cjs/lib/file-saver.d.ts +2 -0
  22. package/dist/cjs/lib/file-saver.js +164 -0
  23. package/dist/cjs/lib/file-saver.js.map +1 -0
  24. package/dist/cjs/providers/document-store-provider.d.ts +48 -0
  25. package/dist/cjs/providers/document-store-provider.js +541 -0
  26. package/dist/cjs/providers/document-store-provider.js.map +1 -0
  27. package/dist/cjs/providers/document-store-share-provider.d.ts +17 -0
  28. package/dist/cjs/providers/document-store-share-provider.js +126 -0
  29. package/dist/cjs/providers/document-store-share-provider.js.map +1 -0
  30. package/dist/cjs/providers/document-store-url.d.ts +32 -0
  31. package/dist/cjs/providers/document-store-url.js +75 -0
  32. package/dist/cjs/providers/document-store-url.js.map +1 -0
  33. package/dist/cjs/providers/google-drive-provider.d.ts +75 -0
  34. package/dist/cjs/providers/google-drive-provider.js +684 -0
  35. package/dist/cjs/providers/google-drive-provider.js.map +1 -0
  36. package/dist/cjs/providers/interactive-api-provider.d.ts +55 -0
  37. package/dist/cjs/providers/interactive-api-provider.js +382 -0
  38. package/dist/cjs/providers/interactive-api-provider.js.map +1 -0
  39. package/dist/cjs/providers/lara-provider.d.ts +47 -0
  40. package/dist/cjs/providers/lara-provider.js +547 -0
  41. package/dist/cjs/providers/lara-provider.js.map +1 -0
  42. package/dist/cjs/providers/legacy-google-drive-provider.d.ts +74 -0
  43. package/dist/cjs/providers/legacy-google-drive-provider.js +600 -0
  44. package/dist/cjs/providers/legacy-google-drive-provider.js.map +1 -0
  45. package/dist/cjs/providers/local-file-provider.d.ts +16 -0
  46. package/dist/cjs/providers/local-file-provider.js +65 -0
  47. package/dist/cjs/providers/local-file-provider.js.map +1 -0
  48. package/dist/cjs/providers/localstorage-provider.d.ts +20 -0
  49. package/dist/cjs/providers/localstorage-provider.js +122 -0
  50. package/dist/cjs/providers/localstorage-provider.js.map +1 -0
  51. package/dist/cjs/providers/patchable-content.d.ts +16 -0
  52. package/dist/cjs/providers/patchable-content.js +65 -0
  53. package/dist/cjs/providers/patchable-content.js.map +1 -0
  54. package/dist/cjs/providers/post-message-provider.d.ts +12 -0
  55. package/dist/cjs/providers/post-message-provider.js +39 -0
  56. package/dist/cjs/providers/post-message-provider.js.map +1 -0
  57. package/dist/cjs/providers/provider-interface.d.ts +168 -0
  58. package/dist/cjs/providers/provider-interface.js +399 -0
  59. package/dist/cjs/providers/provider-interface.js.map +1 -0
  60. package/dist/cjs/providers/readonly-provider.d.ts +22 -0
  61. package/dist/cjs/providers/readonly-provider.js +303 -0
  62. package/dist/cjs/providers/readonly-provider.js.map +1 -0
  63. package/dist/cjs/providers/s3-provider.d.ts +14 -0
  64. package/dist/cjs/providers/s3-provider.js +109 -0
  65. package/dist/cjs/providers/s3-provider.js.map +1 -0
  66. package/dist/cjs/providers/s3-share-provider.d.ts +18 -0
  67. package/dist/cjs/providers/s3-share-provider.js +124 -0
  68. package/dist/cjs/providers/s3-share-provider.js.map +1 -0
  69. package/dist/cjs/providers/share-provider-interface.d.ts +15 -0
  70. package/dist/cjs/providers/share-provider-interface.js +3 -0
  71. package/dist/cjs/providers/share-provider-interface.js.map +1 -0
  72. package/dist/cjs/providers/test-provider.d.ts +26 -0
  73. package/dist/cjs/providers/test-provider.js +73 -0
  74. package/dist/cjs/providers/test-provider.js.map +1 -0
  75. package/dist/cjs/providers/url-provider.d.ts +13 -0
  76. package/dist/cjs/providers/url-provider.js +58 -0
  77. package/dist/cjs/providers/url-provider.js.map +1 -0
  78. package/dist/cjs/ui.d.ts +51 -0
  79. package/dist/cjs/ui.js +216 -0
  80. package/dist/cjs/ui.js.map +1 -0
  81. package/dist/cjs/utils/config.d.ts +6 -0
  82. package/dist/cjs/utils/config.js +10 -0
  83. package/dist/cjs/utils/config.js.map +1 -0
  84. package/dist/cjs/utils/get-hash-param.d.ts +1 -0
  85. package/dist/cjs/utils/get-hash-param.js +24 -0
  86. package/dist/cjs/utils/get-hash-param.js.map +1 -0
  87. package/dist/cjs/utils/get-query-param.d.ts +1 -0
  88. package/dist/cjs/utils/get-query-param.js +23 -0
  89. package/dist/cjs/utils/get-query-param.js.map +1 -0
  90. package/dist/cjs/utils/is-array.d.ts +2 -0
  91. package/dist/cjs/utils/is-array.js +4 -0
  92. package/dist/cjs/utils/is-array.js.map +1 -0
  93. package/dist/cjs/utils/is-empty-object.d.ts +1 -0
  94. package/dist/cjs/utils/is-empty-object.js +7 -0
  95. package/dist/cjs/utils/is-empty-object.js.map +1 -0
  96. package/dist/cjs/utils/is-string.d.ts +2 -0
  97. package/dist/cjs/utils/is-string.js +4 -0
  98. package/dist/cjs/utils/is-string.js.map +1 -0
  99. package/dist/cjs/utils/lang/de.json +156 -0
  100. package/dist/cjs/utils/lang/el.json +156 -0
  101. package/dist/cjs/utils/lang/en-US.json +156 -0
  102. package/dist/cjs/utils/lang/es.json +156 -0
  103. package/dist/cjs/utils/lang/fa.json +156 -0
  104. package/dist/cjs/utils/lang/he.json +156 -0
  105. package/dist/cjs/utils/lang/ja.json +156 -0
  106. package/dist/cjs/utils/lang/ko.json +156 -0
  107. package/dist/cjs/utils/lang/nb.json +156 -0
  108. package/dist/cjs/utils/lang/nn.json +156 -0
  109. package/dist/cjs/utils/lang/pl.json +156 -0
  110. package/dist/cjs/utils/lang/pt-BR.json +156 -0
  111. package/dist/cjs/utils/lang/th.json +156 -0
  112. package/dist/cjs/utils/lang/tr.json +156 -0
  113. package/dist/cjs/utils/lang/zh-Hans.json +156 -0
  114. package/dist/cjs/utils/lang/zh-TW.json +156 -0
  115. package/dist/cjs/utils/report-error.d.ts +1 -0
  116. package/dist/cjs/utils/report-error.js +10 -0
  117. package/dist/cjs/utils/report-error.js.map +1 -0
  118. package/dist/cjs/utils/s3-share-provider-token-service-helper.d.ts +21 -0
  119. package/dist/cjs/utils/s3-share-provider-token-service-helper.js +97 -0
  120. package/dist/cjs/utils/s3-share-provider-token-service-helper.js.map +1 -0
  121. package/dist/cjs/utils/translate.d.ts +3 -0
  122. package/dist/cjs/utils/translate.js +108 -0
  123. package/dist/cjs/utils/translate.js.map +1 -0
  124. package/dist/cjs/utils/url-params.d.ts +2 -0
  125. package/dist/cjs/utils/url-params.js +16 -0
  126. package/dist/cjs/utils/url-params.js.map +1 -0
  127. package/dist/cjs/views/alert-dialog-view.d.ts +3 -0
  128. package/dist/cjs/views/alert-dialog-view.js +32 -0
  129. package/dist/cjs/views/alert-dialog-view.js.map +1 -0
  130. package/dist/cjs/views/app-view.d.ts +49 -0
  131. package/dist/cjs/views/app-view.js +272 -0
  132. package/dist/cjs/views/app-view.js.map +1 -0
  133. package/dist/cjs/views/authorize-mixin.d.ts +10 -0
  134. package/dist/cjs/views/authorize-mixin.js +69 -0
  135. package/dist/cjs/views/authorize-mixin.js.map +1 -0
  136. package/dist/cjs/views/blocking-modal-view.d.ts +3 -0
  137. package/dist/cjs/views/blocking-modal-view.js +32 -0
  138. package/dist/cjs/views/blocking-modal-view.js.map +1 -0
  139. package/dist/cjs/views/confirm-dialog-view.d.ts +3 -0
  140. package/dist/cjs/views/confirm-dialog-view.js +40 -0
  141. package/dist/cjs/views/confirm-dialog-view.js.map +1 -0
  142. package/dist/cjs/views/download-dialog-view.d.ts +3 -0
  143. package/dist/cjs/views/download-dialog-view.js +79 -0
  144. package/dist/cjs/views/download-dialog-view.js.map +1 -0
  145. package/dist/cjs/views/dropdown-anchors.d.ts +4 -0
  146. package/dist/cjs/views/dropdown-anchors.js +17 -0
  147. package/dist/cjs/views/dropdown-anchors.js.map +1 -0
  148. package/dist/cjs/views/dropdown-view.d.ts +3 -0
  149. package/dist/cjs/views/dropdown-view.js +152 -0
  150. package/dist/cjs/views/dropdown-view.js.map +1 -0
  151. package/dist/cjs/views/file-dialog-tab-view.d.ts +3 -0
  152. package/dist/cjs/views/file-dialog-tab-view.js +405 -0
  153. package/dist/cjs/views/file-dialog-tab-view.js.map +1 -0
  154. package/dist/cjs/views/icons/spin.d.ts +5 -0
  155. package/dist/cjs/views/icons/spin.js +46 -0
  156. package/dist/cjs/views/icons/spin.js.map +1 -0
  157. package/dist/cjs/views/import-tabbed-dialog-view.d.ts +3 -0
  158. package/dist/cjs/views/import-tabbed-dialog-view.js +78 -0
  159. package/dist/cjs/views/import-tabbed-dialog-view.js.map +1 -0
  160. package/dist/cjs/views/local-file-tab-list-view.d.ts +3 -0
  161. package/dist/cjs/views/local-file-tab-list-view.js +84 -0
  162. package/dist/cjs/views/local-file-tab-list-view.js.map +1 -0
  163. package/dist/cjs/views/local-file-tab-save-view.d.ts +3 -0
  164. package/dist/cjs/views/local-file-tab-save-view.js +157 -0
  165. package/dist/cjs/views/local-file-tab-save-view.js.map +1 -0
  166. package/dist/cjs/views/menu-bar-view.d.ts +3 -0
  167. package/dist/cjs/views/menu-bar-view.js +201 -0
  168. package/dist/cjs/views/menu-bar-view.js.map +1 -0
  169. package/dist/cjs/views/modal-dialog-view.d.ts +8 -0
  170. package/dist/cjs/views/modal-dialog-view.js +18 -0
  171. package/dist/cjs/views/modal-dialog-view.js.map +1 -0
  172. package/dist/cjs/views/modal-tabbed-dialog-view.d.ts +3 -0
  173. package/dist/cjs/views/modal-tabbed-dialog-view.js +25 -0
  174. package/dist/cjs/views/modal-tabbed-dialog-view.js.map +1 -0
  175. package/dist/cjs/views/modal-view.d.ts +36 -0
  176. package/dist/cjs/views/modal-view.js +70 -0
  177. package/dist/cjs/views/modal-view.js.map +1 -0
  178. package/dist/cjs/views/provider-tabbed-dialog-view.d.ts +3 -0
  179. package/dist/cjs/views/provider-tabbed-dialog-view.js +67 -0
  180. package/dist/cjs/views/provider-tabbed-dialog-view.js.map +1 -0
  181. package/dist/cjs/views/rename-dialog-view.d.ts +3 -0
  182. package/dist/cjs/views/rename-dialog-view.js +60 -0
  183. package/dist/cjs/views/rename-dialog-view.js.map +1 -0
  184. package/dist/cjs/views/select-interactive-state-dialog-view.d.ts +22 -0
  185. package/dist/cjs/views/select-interactive-state-dialog-view.js +93 -0
  186. package/dist/cjs/views/select-interactive-state-dialog-view.js.map +1 -0
  187. package/dist/cjs/views/select-provider-dialog-tab-view.d.ts +2 -0
  188. package/dist/cjs/views/select-provider-dialog-tab-view.js +16 -0
  189. package/dist/cjs/views/select-provider-dialog-tab-view.js.map +1 -0
  190. package/dist/cjs/views/share-dialog-status-view.d.ts +9 -0
  191. package/dist/cjs/views/share-dialog-status-view.js +24 -0
  192. package/dist/cjs/views/share-dialog-status-view.js.map +1 -0
  193. package/dist/cjs/views/share-dialog-tabs-view.d.ts +45 -0
  194. package/dist/cjs/views/share-dialog-tabs-view.js +93 -0
  195. package/dist/cjs/views/share-dialog-tabs-view.js.map +1 -0
  196. package/dist/cjs/views/share-dialog-view.d.ts +50 -0
  197. package/dist/cjs/views/share-dialog-view.js +220 -0
  198. package/dist/cjs/views/share-dialog-view.js.map +1 -0
  199. package/dist/cjs/views/share-loading-view.d.ts +2 -0
  200. package/dist/cjs/views/share-loading-view.js +16 -0
  201. package/dist/cjs/views/share-loading-view.js.map +1 -0
  202. package/dist/cjs/views/tabbed-panel-view.d.ts +3 -0
  203. package/dist/cjs/views/tabbed-panel-view.js +79 -0
  204. package/dist/cjs/views/tabbed-panel-view.js.map +1 -0
  205. package/dist/cjs/views/url-tab-view.d.ts +3 -0
  206. package/dist/cjs/views/url-tab-view.js +67 -0
  207. package/dist/cjs/views/url-tab-view.js.map +1 -0
  208. package/dist/css/app.css +6 -0
  209. package/dist/css/app.css.map +1 -0
  210. package/dist/esm/app-options.d.ts +118 -0
  211. package/dist/esm/app-options.js +2 -0
  212. package/dist/esm/app-options.js.map +1 -0
  213. package/dist/esm/client.d.ts +165 -0
  214. package/dist/esm/client.js +1384 -0
  215. package/dist/esm/client.js.map +1 -0
  216. package/dist/esm/cloud-file-manager.d.ts +16 -0
  217. package/dist/esm/cloud-file-manager.js +72 -0
  218. package/dist/esm/cloud-file-manager.js.map +1 -0
  219. package/dist/esm/create-react-factory.d.ts +3 -0
  220. package/dist/esm/create-react-factory.js +6 -0
  221. package/dist/esm/create-react-factory.js.map +1 -0
  222. package/dist/esm/index.d.ts +4 -0
  223. package/dist/esm/index.js +5 -0
  224. package/dist/esm/index.js.map +1 -0
  225. package/dist/esm/lib/file-saver.d.ts +2 -0
  226. package/dist/esm/lib/file-saver.js +164 -0
  227. package/dist/esm/lib/file-saver.js.map +1 -0
  228. package/dist/esm/providers/document-store-provider.d.ts +48 -0
  229. package/dist/esm/providers/document-store-provider.js +536 -0
  230. package/dist/esm/providers/document-store-provider.js.map +1 -0
  231. package/dist/esm/providers/document-store-share-provider.d.ts +17 -0
  232. package/dist/esm/providers/document-store-share-provider.js +121 -0
  233. package/dist/esm/providers/document-store-share-provider.js.map +1 -0
  234. package/dist/esm/providers/document-store-url.d.ts +32 -0
  235. package/dist/esm/providers/document-store-url.js +73 -0
  236. package/dist/esm/providers/document-store-url.js.map +1 -0
  237. package/dist/esm/providers/google-drive-provider.d.ts +75 -0
  238. package/dist/esm/providers/google-drive-provider.js +656 -0
  239. package/dist/esm/providers/google-drive-provider.js.map +1 -0
  240. package/dist/esm/providers/interactive-api-provider.d.ts +55 -0
  241. package/dist/esm/providers/interactive-api-provider.js +374 -0
  242. package/dist/esm/providers/interactive-api-provider.js.map +1 -0
  243. package/dist/esm/providers/lara-provider.d.ts +47 -0
  244. package/dist/esm/providers/lara-provider.js +542 -0
  245. package/dist/esm/providers/lara-provider.js.map +1 -0
  246. package/dist/esm/providers/legacy-google-drive-provider.d.ts +74 -0
  247. package/dist/esm/providers/legacy-google-drive-provider.js +595 -0
  248. package/dist/esm/providers/legacy-google-drive-provider.js.map +1 -0
  249. package/dist/esm/providers/local-file-provider.d.ts +16 -0
  250. package/dist/esm/providers/local-file-provider.js +60 -0
  251. package/dist/esm/providers/local-file-provider.js.map +1 -0
  252. package/dist/esm/providers/localstorage-provider.d.ts +20 -0
  253. package/dist/esm/providers/localstorage-provider.js +117 -0
  254. package/dist/esm/providers/localstorage-provider.js.map +1 -0
  255. package/dist/esm/providers/patchable-content.d.ts +16 -0
  256. package/dist/esm/providers/patchable-content.js +60 -0
  257. package/dist/esm/providers/patchable-content.js.map +1 -0
  258. package/dist/esm/providers/post-message-provider.d.ts +12 -0
  259. package/dist/esm/providers/post-message-provider.js +34 -0
  260. package/dist/esm/providers/post-message-provider.js.map +1 -0
  261. package/dist/esm/providers/provider-interface.d.ts +168 -0
  262. package/dist/esm/providers/provider-interface.js +389 -0
  263. package/dist/esm/providers/provider-interface.js.map +1 -0
  264. package/dist/esm/providers/readonly-provider.d.ts +22 -0
  265. package/dist/esm/providers/readonly-provider.js +298 -0
  266. package/dist/esm/providers/readonly-provider.js.map +1 -0
  267. package/dist/esm/providers/s3-provider.d.ts +14 -0
  268. package/dist/esm/providers/s3-provider.js +104 -0
  269. package/dist/esm/providers/s3-provider.js.map +1 -0
  270. package/dist/esm/providers/s3-share-provider.d.ts +18 -0
  271. package/dist/esm/providers/s3-share-provider.js +122 -0
  272. package/dist/esm/providers/s3-share-provider.js.map +1 -0
  273. package/dist/esm/providers/share-provider-interface.d.ts +15 -0
  274. package/dist/esm/providers/share-provider-interface.js +2 -0
  275. package/dist/esm/providers/share-provider-interface.js.map +1 -0
  276. package/dist/esm/providers/test-provider.d.ts +26 -0
  277. package/dist/esm/providers/test-provider.js +71 -0
  278. package/dist/esm/providers/test-provider.js.map +1 -0
  279. package/dist/esm/providers/url-provider.d.ts +13 -0
  280. package/dist/esm/providers/url-provider.js +53 -0
  281. package/dist/esm/providers/url-provider.js.map +1 -0
  282. package/dist/esm/ui.d.ts +51 -0
  283. package/dist/esm/ui.js +208 -0
  284. package/dist/esm/ui.js.map +1 -0
  285. package/dist/esm/utils/config.d.ts +6 -0
  286. package/dist/esm/utils/config.js +6 -0
  287. package/dist/esm/utils/config.js.map +1 -0
  288. package/dist/esm/utils/get-hash-param.d.ts +1 -0
  289. package/dist/esm/utils/get-hash-param.js +21 -0
  290. package/dist/esm/utils/get-hash-param.js.map +1 -0
  291. package/dist/esm/utils/get-query-param.d.ts +1 -0
  292. package/dist/esm/utils/get-query-param.js +20 -0
  293. package/dist/esm/utils/get-query-param.js.map +1 -0
  294. package/dist/esm/utils/is-array.d.ts +2 -0
  295. package/dist/esm/utils/is-array.js +2 -0
  296. package/dist/esm/utils/is-array.js.map +1 -0
  297. package/dist/esm/utils/is-empty-object.d.ts +1 -0
  298. package/dist/esm/utils/is-empty-object.js +3 -0
  299. package/dist/esm/utils/is-empty-object.js.map +1 -0
  300. package/dist/esm/utils/is-string.d.ts +2 -0
  301. package/dist/esm/utils/is-string.js +2 -0
  302. package/dist/esm/utils/is-string.js.map +1 -0
  303. package/dist/esm/utils/lang/de.json +156 -0
  304. package/dist/esm/utils/lang/el.json +156 -0
  305. package/dist/esm/utils/lang/en-US.json +156 -0
  306. package/dist/esm/utils/lang/es.json +156 -0
  307. package/dist/esm/utils/lang/fa.json +156 -0
  308. package/dist/esm/utils/lang/he.json +156 -0
  309. package/dist/esm/utils/lang/ja.json +156 -0
  310. package/dist/esm/utils/lang/ko.json +156 -0
  311. package/dist/esm/utils/lang/nb.json +156 -0
  312. package/dist/esm/utils/lang/nn.json +156 -0
  313. package/dist/esm/utils/lang/pl.json +156 -0
  314. package/dist/esm/utils/lang/pt-BR.json +156 -0
  315. package/dist/esm/utils/lang/th.json +156 -0
  316. package/dist/esm/utils/lang/tr.json +156 -0
  317. package/dist/esm/utils/lang/zh-Hans.json +156 -0
  318. package/dist/esm/utils/lang/zh-TW.json +156 -0
  319. package/dist/esm/utils/report-error.d.ts +1 -0
  320. package/dist/esm/utils/report-error.js +6 -0
  321. package/dist/esm/utils/report-error.js.map +1 -0
  322. package/dist/esm/utils/s3-share-provider-token-service-helper.d.ts +21 -0
  323. package/dist/esm/utils/s3-share-provider-token-service-helper.js +87 -0
  324. package/dist/esm/utils/s3-share-provider-token-service-helper.js.map +1 -0
  325. package/dist/esm/utils/translate.d.ts +3 -0
  326. package/dist/esm/utils/translate.js +101 -0
  327. package/dist/esm/utils/translate.js.map +1 -0
  328. package/dist/esm/utils/url-params.d.ts +2 -0
  329. package/dist/esm/utils/url-params.js +14 -0
  330. package/dist/esm/utils/url-params.js.map +1 -0
  331. package/dist/esm/views/alert-dialog-view.d.ts +3 -0
  332. package/dist/esm/views/alert-dialog-view.js +27 -0
  333. package/dist/esm/views/alert-dialog-view.js.map +1 -0
  334. package/dist/esm/views/app-view.d.ts +49 -0
  335. package/dist/esm/views/app-view.js +267 -0
  336. package/dist/esm/views/app-view.js.map +1 -0
  337. package/dist/esm/views/authorize-mixin.d.ts +10 -0
  338. package/dist/esm/views/authorize-mixin.js +67 -0
  339. package/dist/esm/views/authorize-mixin.js.map +1 -0
  340. package/dist/esm/views/blocking-modal-view.d.ts +3 -0
  341. package/dist/esm/views/blocking-modal-view.js +27 -0
  342. package/dist/esm/views/blocking-modal-view.js.map +1 -0
  343. package/dist/esm/views/confirm-dialog-view.d.ts +3 -0
  344. package/dist/esm/views/confirm-dialog-view.js +35 -0
  345. package/dist/esm/views/confirm-dialog-view.js.map +1 -0
  346. package/dist/esm/views/download-dialog-view.d.ts +3 -0
  347. package/dist/esm/views/download-dialog-view.js +74 -0
  348. package/dist/esm/views/download-dialog-view.js.map +1 -0
  349. package/dist/esm/views/dropdown-anchors.d.ts +4 -0
  350. package/dist/esm/views/dropdown-anchors.js +10 -0
  351. package/dist/esm/views/dropdown-anchors.js.map +1 -0
  352. package/dist/esm/views/dropdown-view.d.ts +3 -0
  353. package/dist/esm/views/dropdown-view.js +147 -0
  354. package/dist/esm/views/dropdown-view.js.map +1 -0
  355. package/dist/esm/views/file-dialog-tab-view.d.ts +3 -0
  356. package/dist/esm/views/file-dialog-tab-view.js +400 -0
  357. package/dist/esm/views/file-dialog-tab-view.js.map +1 -0
  358. package/dist/esm/views/icons/spin.d.ts +5 -0
  359. package/dist/esm/views/icons/spin.js +39 -0
  360. package/dist/esm/views/icons/spin.js.map +1 -0
  361. package/dist/esm/views/import-tabbed-dialog-view.d.ts +3 -0
  362. package/dist/esm/views/import-tabbed-dialog-view.js +73 -0
  363. package/dist/esm/views/import-tabbed-dialog-view.js.map +1 -0
  364. package/dist/esm/views/local-file-tab-list-view.d.ts +3 -0
  365. package/dist/esm/views/local-file-tab-list-view.js +79 -0
  366. package/dist/esm/views/local-file-tab-list-view.js.map +1 -0
  367. package/dist/esm/views/local-file-tab-save-view.d.ts +3 -0
  368. package/dist/esm/views/local-file-tab-save-view.js +152 -0
  369. package/dist/esm/views/local-file-tab-save-view.js.map +1 -0
  370. package/dist/esm/views/menu-bar-view.d.ts +3 -0
  371. package/dist/esm/views/menu-bar-view.js +196 -0
  372. package/dist/esm/views/menu-bar-view.js.map +1 -0
  373. package/dist/esm/views/modal-dialog-view.d.ts +8 -0
  374. package/dist/esm/views/modal-dialog-view.js +13 -0
  375. package/dist/esm/views/modal-dialog-view.js.map +1 -0
  376. package/dist/esm/views/modal-tabbed-dialog-view.d.ts +3 -0
  377. package/dist/esm/views/modal-tabbed-dialog-view.js +20 -0
  378. package/dist/esm/views/modal-tabbed-dialog-view.js.map +1 -0
  379. package/dist/esm/views/modal-view.d.ts +36 -0
  380. package/dist/esm/views/modal-view.js +64 -0
  381. package/dist/esm/views/modal-view.js.map +1 -0
  382. package/dist/esm/views/provider-tabbed-dialog-view.d.ts +3 -0
  383. package/dist/esm/views/provider-tabbed-dialog-view.js +62 -0
  384. package/dist/esm/views/provider-tabbed-dialog-view.js.map +1 -0
  385. package/dist/esm/views/rename-dialog-view.d.ts +3 -0
  386. package/dist/esm/views/rename-dialog-view.js +55 -0
  387. package/dist/esm/views/rename-dialog-view.js.map +1 -0
  388. package/dist/esm/views/select-interactive-state-dialog-view.d.ts +22 -0
  389. package/dist/esm/views/select-interactive-state-dialog-view.js +87 -0
  390. package/dist/esm/views/select-interactive-state-dialog-view.js.map +1 -0
  391. package/dist/esm/views/select-provider-dialog-tab-view.d.ts +2 -0
  392. package/dist/esm/views/select-provider-dialog-tab-view.js +11 -0
  393. package/dist/esm/views/select-provider-dialog-tab-view.js.map +1 -0
  394. package/dist/esm/views/share-dialog-status-view.d.ts +9 -0
  395. package/dist/esm/views/share-dialog-status-view.js +17 -0
  396. package/dist/esm/views/share-dialog-status-view.js.map +1 -0
  397. package/dist/esm/views/share-dialog-tabs-view.d.ts +45 -0
  398. package/dist/esm/views/share-dialog-tabs-view.js +83 -0
  399. package/dist/esm/views/share-dialog-tabs-view.js.map +1 -0
  400. package/dist/esm/views/share-dialog-view.d.ts +50 -0
  401. package/dist/esm/views/share-dialog-view.js +214 -0
  402. package/dist/esm/views/share-dialog-view.js.map +1 -0
  403. package/dist/esm/views/share-loading-view.d.ts +2 -0
  404. package/dist/esm/views/share-loading-view.js +9 -0
  405. package/dist/esm/views/share-loading-view.js.map +1 -0
  406. package/dist/esm/views/tabbed-panel-view.d.ts +3 -0
  407. package/dist/esm/views/tabbed-panel-view.js +74 -0
  408. package/dist/esm/views/tabbed-panel-view.js.map +1 -0
  409. package/dist/esm/views/url-tab-view.d.ts +3 -0
  410. package/dist/esm/views/url-tab-view.js +62 -0
  411. package/dist/esm/views/url-tab-view.js.map +1 -0
  412. package/dist/examples/all-providers-react-18.html +74 -0
  413. package/dist/examples/all-providers.html +61 -0
  414. package/dist/examples/auto-saving.html +50 -0
  415. package/dist/examples/client-logging-provider.html +107 -0
  416. package/dist/examples/close-file.html +63 -0
  417. package/dist/examples/deprecate-phase-one.html +60 -0
  418. package/dist/examples/deprecate-phase-three.html +60 -0
  419. package/dist/examples/deprecate-phase-two.html +60 -0
  420. package/dist/examples/enable-demo-extension.html +52 -0
  421. package/dist/examples/enable-lara-sharing.html +51 -0
  422. package/dist/examples/example-app/index.html +133 -0
  423. package/dist/examples/hide-hamburger-2.html +55 -0
  424. package/dist/examples/hide-hamburger.html +34 -0
  425. package/dist/examples/index.html +40 -0
  426. package/dist/examples/interactive-api-provider.html +27 -0
  427. package/dist/examples/language-menu.html +86 -0
  428. package/dist/examples/lara-provider.html +52 -0
  429. package/dist/examples/load-url-query-param.html +54 -0
  430. package/dist/examples/menu-madness.html +67 -0
  431. package/dist/examples/new-does-not-use-new-tab.html +47 -0
  432. package/dist/examples/no-flag-language-menu.html +86 -0
  433. package/dist/examples/no-frame.html +130 -0
  434. package/dist/examples/no-shared-google-drives.html +47 -0
  435. package/dist/examples/read-only-with-folders.html +120 -0
  436. package/dist/examples/show-close-confirm.html +47 -0
  437. package/dist/examples/splash-screen.html +70 -0
  438. package/dist/examples/view-no-frame-nowrap.html +167 -0
  439. package/dist/examples/view-no-frame.html +129 -0
  440. package/dist/favicon.ico +0 -0
  441. package/dist/fonts/CodapIvy.eot +0 -0
  442. package/dist/fonts/CodapIvy.svg +61 -0
  443. package/dist/fonts/CodapIvy.ttf +0 -0
  444. package/dist/fonts/CodapIvy.woff +0 -0
  445. package/dist/fonts/Montserrat-Bold.otf +0 -0
  446. package/dist/fonts/Montserrat-Regular.otf +0 -0
  447. package/dist/fonts/MuseoSans_500.otf +0 -0
  448. package/dist/fonts/MuseoSans_500_Italic.otf +0 -0
  449. package/dist/fonts/icon-menu.eot +0 -0
  450. package/dist/fonts/icon-menu.svg +24 -0
  451. package/dist/fonts/icon-menu.ttf +0 -0
  452. package/dist/fonts/icon-menu.woff +0 -0
  453. package/dist/img/bb-chrome/arrow-collapse.svg +8 -0
  454. package/dist/img/bb-chrome/arrow-expand.svg +8 -0
  455. package/dist/img/bb-chrome/bg-horiz.png +0 -0
  456. package/dist/img/bb-chrome/btn-nodeLink.svg +298 -0
  457. package/dist/img/bb-chrome/chevron-down.png +0 -0
  458. package/dist/img/bb-chrome/chevron-left.png +0 -0
  459. package/dist/img/bb-chrome/chevron-right.png +0 -0
  460. package/dist/img/bb-chrome/chevron-up.png +0 -0
  461. package/dist/img/bb-chrome/global-nav-bg.png +0 -0
  462. package/dist/img/bb-chrome/icon-checkmark.svg +10 -0
  463. package/dist/img/bb-chrome/slider.svg +286 -0
  464. package/dist/img/bb-chrome/spin.svg +54 -0
  465. package/dist/img/concord-logo.png +0 -0
  466. package/dist/img/debug/grid.jpg +0 -0
  467. package/dist/img/document-store-16.png +0 -0
  468. package/dist/img/earth.svg +48 -0
  469. package/dist/img/flags.png +0 -0
  470. package/dist/img/fullscreen-dark.svg +22 -0
  471. package/dist/img/fullscreen-exit-dark.svg +22 -0
  472. package/dist/img/fullscreen-exit.svg +22 -0
  473. package/dist/img/fullscreen.svg +22 -0
  474. package/dist/img/google-drive-16.png +0 -0
  475. package/dist/img/google-drive-logo.png +0 -0
  476. package/dist/img/loading.gif +0 -0
  477. package/dist/index.html +21 -0
  478. package/dist/js/app.js +3 -0
  479. package/dist/js/app.js.LICENSE.txt +287 -0
  480. package/dist/js/app.js.map +1 -0
  481. package/dist/js/globals.js +3 -0
  482. package/dist/js/globals.js.LICENSE.txt +52 -0
  483. package/dist/js/globals.js.map +1 -0
  484. package/license.md +21 -0
  485. package/package.json +127 -0
  486. package/readme.md +275 -0
@@ -0,0 +1,1391 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.CloudFileManagerClient = exports.CloudFileManagerClientEvent = void 0;
7
+ // TODO: This file was created by bulk-decaffeinate.
8
+ // Sanity-check the conversion and remove this comment.
9
+ /*
10
+ * decaffeinate suggestions:
11
+ * DS102: Remove unnecessary code created because of implicit returns
12
+ * DS207: Consider shorter variations of null checks
13
+ * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
14
+ */
15
+ const jquery_1 = __importDefault(require("jquery"));
16
+ const lodash_1 = __importDefault(require("lodash"));
17
+ const mime_1 = __importDefault(require("mime"));
18
+ const translate_1 = __importDefault(require("./utils/translate"));
19
+ const is_string_1 = __importDefault(require("./utils/is-string"));
20
+ const base64_js_1 = __importDefault(require("base64-js")); // https://github.com/beatgammit/base64-js
21
+ const get_query_param_1 = __importDefault(require("./utils/get-query-param"));
22
+ const app_options_1 = require("./app-options");
23
+ const ui_1 = require("./ui");
24
+ const localstorage_provider_1 = __importDefault(require("./providers/localstorage-provider"));
25
+ const readonly_provider_1 = __importDefault(require("./providers/readonly-provider"));
26
+ const google_drive_provider_1 = __importDefault(require("./providers/google-drive-provider"));
27
+ const interactive_api_provider_1 = __importDefault(require("./providers/interactive-api-provider"));
28
+ const lara_provider_1 = __importDefault(require("./providers/lara-provider"));
29
+ const document_store_provider_1 = __importDefault(require("./providers/document-store-provider"));
30
+ const s3_share_provider_1 = __importDefault(require("./providers/s3-share-provider"));
31
+ const s3_provider_1 = __importDefault(require("./providers/s3-provider"));
32
+ const local_file_provider_1 = __importDefault(require("./providers/local-file-provider"));
33
+ const post_message_provider_1 = __importDefault(require("./providers/post-message-provider"));
34
+ const url_provider_1 = __importDefault(require("./providers/url-provider"));
35
+ const test_provider_1 = __importDefault(require("./providers/test-provider"));
36
+ const provider_interface_1 = require("./providers/provider-interface");
37
+ const report_error_1 = require("./utils/report-error");
38
+ const lara_interactive_api_1 = require("@concord-consortium/lara-interactive-api");
39
+ let CLOUDFILEMANAGER_EVENT_ID = 0;
40
+ const CLOUDFILEMANAGER_EVENTS = {};
41
+ class CloudFileManagerClientEvent {
42
+ constructor(type, data, callback = null, state) {
43
+ this.type = type;
44
+ if (data == null) {
45
+ data = {};
46
+ }
47
+ this.data = data;
48
+ this.callback = callback;
49
+ if (state == null) {
50
+ state = {};
51
+ }
52
+ this.state = state;
53
+ CLOUDFILEMANAGER_EVENT_ID++;
54
+ this.id = CLOUDFILEMANAGER_EVENT_ID;
55
+ }
56
+ postMessage(iframe) {
57
+ if (this.callback) {
58
+ CLOUDFILEMANAGER_EVENTS[this.id] = this;
59
+ }
60
+ // remove client from data to avoid structured clone error in postMessage
61
+ const eventData = lodash_1.default.clone(this.data);
62
+ delete eventData.client;
63
+ const message = { type: "cfm::event", eventId: this.id, eventType: this.type, eventData };
64
+ return iframe.postMessage(message, "*");
65
+ }
66
+ }
67
+ exports.CloudFileManagerClientEvent = CloudFileManagerClientEvent;
68
+ class CloudFileManagerClient {
69
+ constructor(options) {
70
+ this.shouldAutoSave = this.shouldAutoSave.bind(this);
71
+ this.state = { availableProviders: [] };
72
+ this._listeners = [];
73
+ this._resetState();
74
+ this._ui = new ui_1.CloudFileManagerUI(this);
75
+ this.providers = {};
76
+ this.urlProvider = new url_provider_1.default();
77
+ this.onUnload = this.onUnload.bind(this);
78
+ (0, lara_interactive_api_1.setOnUnload)(this.onUnload);
79
+ this.connectedPromise = new Promise((resolve, reject) => {
80
+ this.connectedPromiseResolver = {
81
+ resolve: () => {
82
+ resolve();
83
+ this.connectedPromiseResolver = null;
84
+ },
85
+ reject: () => {
86
+ reject();
87
+ this.connectedPromiseResolver = null;
88
+ }
89
+ };
90
+ });
91
+ }
92
+ setAppOptions(appOptions) {
93
+ var _a, _b, _c, _d;
94
+ let providerName;
95
+ let Provider;
96
+ if (appOptions == null) {
97
+ appOptions = {};
98
+ }
99
+ this.appOptions = appOptions;
100
+ if (this.appOptions.wrapFileContent == null) {
101
+ this.appOptions.wrapFileContent = true;
102
+ }
103
+ provider_interface_1.CloudContent.wrapFileContent = this.appOptions.wrapFileContent;
104
+ if (this.appOptions.isClientContent)
105
+ provider_interface_1.cloudContentFactory.isClientContent = this.appOptions.isClientContent;
106
+ const allProviders = {};
107
+ // Determine the available providers. Note that order in the list can
108
+ // be significant in provider searches (e.g. @autoProvider).
109
+ const providerList = [
110
+ localstorage_provider_1.default,
111
+ readonly_provider_1.default,
112
+ google_drive_provider_1.default,
113
+ lara_provider_1.default,
114
+ interactive_api_provider_1.default,
115
+ document_store_provider_1.default,
116
+ local_file_provider_1.default,
117
+ post_message_provider_1.default,
118
+ s3_provider_1.default,
119
+ test_provider_1.default
120
+ ];
121
+ for (Provider of providerList) {
122
+ if (Provider.Available()) {
123
+ allProviders[Provider.Name] = Provider;
124
+ }
125
+ }
126
+ // default to all providers if none specified
127
+ if (!this.appOptions.providers) {
128
+ this.appOptions.providers = [];
129
+ for (providerName of Object.keys(allProviders || {})) {
130
+ appOptions.providers.push(providerName);
131
+ }
132
+ }
133
+ // preset the extension if Available
134
+ provider_interface_1.CloudMetadata.Extension = this.appOptions.extension;
135
+ provider_interface_1.CloudMetadata.ReadableExtensions = this.appOptions.readableExtensions || [];
136
+ if (provider_interface_1.CloudMetadata.Extension) {
137
+ provider_interface_1.CloudMetadata.ReadableExtensions.push(provider_interface_1.CloudMetadata.Extension);
138
+ }
139
+ const readableMimetypes = this.appOptions.readableMimeTypes || [];
140
+ readableMimetypes.push(this.appOptions.mimeType);
141
+ // check the providers
142
+ const requestedProviders = this.appOptions.providers.slice();
143
+ if ((0, get_query_param_1.default)("saveSecondaryFileViaPostMessage")) {
144
+ requestedProviders.push('postMessage');
145
+ }
146
+ const isInteractiveApiRequested = requestedProviders.includes('interactiveApi');
147
+ const availableProviders = [];
148
+ let shareProvider = null;
149
+ for (let providerSpec of requestedProviders) {
150
+ const [providerName, providerOptions] = (0, is_string_1.default)(providerSpec)
151
+ ? [providerSpec, {}]
152
+ : [providerSpec.name, providerSpec];
153
+ // merge in other options as needed
154
+ if (providerOptions.mimeType == null) {
155
+ providerOptions.mimeType = this.appOptions.mimeType;
156
+ }
157
+ providerOptions.readableMimetypes = readableMimetypes;
158
+ if (!providerName) {
159
+ this.alert("Invalid provider spec - must either be string or object with name property");
160
+ }
161
+ else {
162
+ if ((0, app_options_1.isCustomClientProvider)(providerOptions)) {
163
+ allProviders[providerName] = providerOptions.createProvider(provider_interface_1.ProviderInterface);
164
+ }
165
+ if (allProviders[providerName]) {
166
+ Provider = allProviders[providerName];
167
+ // don't add providers that require configuration if no (or invalid) configuration provided
168
+ if (!Provider.hasValidOptions || Provider.hasValidOptions(providerOptions)) {
169
+ const provider = new Provider(providerOptions, this);
170
+ this.providers[providerName] = provider;
171
+ shareProvider = this._getShareProvider();
172
+ // also add to here in providers list so we can look it up when parsing url hash
173
+ if (provider.urlDisplayName) {
174
+ this.providers[provider.urlDisplayName] = provider;
175
+ }
176
+ availableProviders.push(provider);
177
+ // InteractiveApiProvider is a newer form of Lara provider
178
+ if (!isInteractiveApiRequested && (providerName === "lara")) {
179
+ const interactiveApiProvider = new interactive_api_provider_1.default(providerOptions, this);
180
+ this.providers.interactiveApi = interactiveApiProvider;
181
+ availableProviders.push(interactiveApiProvider);
182
+ }
183
+ }
184
+ }
185
+ else {
186
+ this.alert(`Unknown provider: ${providerName}`);
187
+ }
188
+ }
189
+ }
190
+ this._setState({
191
+ availableProviders,
192
+ shareProvider
193
+ });
194
+ if (!this.appOptions.ui) {
195
+ this.appOptions.ui = {};
196
+ }
197
+ if (!this.appOptions.ui.windowTitleSuffix) {
198
+ this.appOptions.ui.windowTitleSuffix = document.title;
199
+ }
200
+ if (!this.appOptions.ui.windowTitleSeparator) {
201
+ this.appOptions.ui.windowTitleSeparator = ' - ';
202
+ }
203
+ this._setWindowTitle();
204
+ this._ui.init(this.appOptions.ui);
205
+ // check for autosave
206
+ if (this.appOptions.autoSaveInterval) {
207
+ this.autoSave(this.appOptions.autoSaveInterval);
208
+ }
209
+ // initialize the cloudContentFactory with all data we want in the envelope
210
+ provider_interface_1.cloudContentFactory.setEnvelopeMetadata({
211
+ cfmVersion: '__PACKAGE_VERSION__', // replaced by version number at build time
212
+ appName: this.appOptions.appName || "",
213
+ appVersion: this.appOptions.appVersion || "",
214
+ appBuildNum: this.appOptions.appBuildNum || ""
215
+ });
216
+ this.newFileOpensInNewTab = (_b = (_a = this.appOptions.ui) === null || _a === void 0 ? void 0 : _a.newFileOpensInNewTab) !== null && _b !== void 0 ? _b : true;
217
+ this.newFileAddsNewToQuery = (_c = this.appOptions.ui) === null || _c === void 0 ? void 0 : _c.newFileAddsNewToQuery;
218
+ if ((_d = this.appOptions.ui) === null || _d === void 0 ? void 0 : _d.confirmCloseIfDirty) {
219
+ this._setupConfirmOnClose();
220
+ }
221
+ return this._startPostMessageListener();
222
+ }
223
+ _getShareProvider() {
224
+ return new s3_share_provider_1.default(this, new s3_provider_1.default(this));
225
+ }
226
+ setProviderOptions(name, newOptions) {
227
+ for (let provider of this.state.availableProviders) {
228
+ if (provider.name === name) {
229
+ provider.options = { ...provider.options, newOptions };
230
+ break;
231
+ }
232
+ }
233
+ }
234
+ connect() {
235
+ var _a;
236
+ (_a = this.connectedPromiseResolver) === null || _a === void 0 ? void 0 : _a.resolve();
237
+ return this._event('connected', { client: this });
238
+ }
239
+ //
240
+ // Called from CloudFileManager.clientConnect to process the URL parameters
241
+ // and initiate opening any document specified by URL parameters. The CFM
242
+ // hash params are processed here after which providers are given a chance
243
+ // to process any provider-specific URL parameters. Calls ready() if no
244
+ // initial document opening occurs.
245
+ //
246
+ processUrlParams() {
247
+ // process the hash params
248
+ let providerName;
249
+ const { hashParams } = this.appOptions;
250
+ if (hashParams.sharedContentId) {
251
+ return this.openSharedContent(hashParams.sharedContentId);
252
+ }
253
+ else if (hashParams.fileParams) {
254
+ if (hashParams.fileParams.indexOf("http") === 0) {
255
+ return this.openUrlFile(hashParams.fileParams);
256
+ }
257
+ else {
258
+ let providerParams;
259
+ [providerName, providerParams] = hashParams.fileParams.split(':');
260
+ return this.openProviderFile(providerName, providerParams);
261
+ }
262
+ }
263
+ else if (hashParams.copyParams) {
264
+ return this.openCopiedFile(hashParams.copyParams);
265
+ }
266
+ else if (hashParams.newInFolderParams) {
267
+ let folder;
268
+ [providerName, folder] = hashParams.newInFolderParams.split(':');
269
+ return this.createNewInFolder(providerName, folder);
270
+ }
271
+ else if (this.haveTempFile()) {
272
+ return this.openAndClearTempFile();
273
+ }
274
+ else {
275
+ // give providers a chance to process url params
276
+ for (let provider of this.state.availableProviders) {
277
+ if (provider.handleUrlParams()) {
278
+ return;
279
+ }
280
+ }
281
+ // if no providers handled it, then just signal ready()
282
+ return this.ready();
283
+ }
284
+ }
285
+ ready() {
286
+ return this._event('ready');
287
+ }
288
+ rendered() {
289
+ return this._event('rendered', { client: this });
290
+ }
291
+ listen(listener) {
292
+ if (listener) {
293
+ return this._listeners.push(listener);
294
+ }
295
+ }
296
+ log(event, eventData) {
297
+ this._event('log', { logEvent: event, logEventData: eventData });
298
+ if (this.appOptions.log) {
299
+ return this.appOptions.log(event, eventData);
300
+ }
301
+ }
302
+ autoProvider(capability) {
303
+ for (let provider of this.state.availableProviders) {
304
+ if (provider.canAuto(capability)) {
305
+ return provider;
306
+ }
307
+ }
308
+ }
309
+ appendMenuItem(item) {
310
+ this._ui.appendMenuItem(item);
311
+ return this;
312
+ }
313
+ prependMenuItem(item) {
314
+ this._ui.prependMenuItem(item);
315
+ return this;
316
+ }
317
+ replaceMenuItem(key, item) {
318
+ this._ui.replaceMenuItem(key, item);
319
+ return this;
320
+ }
321
+ insertMenuItemBefore(key, item) {
322
+ this._ui.insertMenuItemBefore(key, item);
323
+ return this;
324
+ }
325
+ insertMenuItemAfter(key, item) {
326
+ this._ui.insertMenuItemAfter(key, item);
327
+ return this;
328
+ }
329
+ setMenuBarInfo(info) {
330
+ return this._ui.setMenuBarInfo(info);
331
+ }
332
+ newFile(callback = null) {
333
+ this._closeCurrentFile();
334
+ this._resetState();
335
+ window.location.hash = "";
336
+ return this._event('newedFile', { content: "" }, callback);
337
+ }
338
+ newFileDialog(callback = null) {
339
+ if (this.newFileOpensInNewTab) {
340
+ return window.open(this.getCurrentUrl(this.newFileAddsNewToQuery ? "#new" : null), '_blank');
341
+ }
342
+ else if (this.state.dirty) {
343
+ if (this._autoSaveInterval && this.state.metadata) {
344
+ this.save();
345
+ return this.newFile(callback);
346
+ }
347
+ else {
348
+ return this.confirm((0, translate_1.default)('~CONFIRM.NEW_FILE'), () => this.newFile(callback));
349
+ }
350
+ }
351
+ else {
352
+ return this.newFile(callback);
353
+ }
354
+ }
355
+ openFile(metadata, callback = null) {
356
+ var _a;
357
+ if ((_a = metadata === null || metadata === void 0 ? void 0 : metadata.provider) === null || _a === void 0 ? void 0 : _a.can(provider_interface_1.ECapabilities.load, metadata)) {
358
+ this._event('willOpenFile', { op: "openFile" });
359
+ return metadata.provider.load(metadata, (err, content) => {
360
+ if (err) {
361
+ return this.alert(err, () => this.ready());
362
+ }
363
+ // should wait to close current file until client signals open is complete
364
+ this._closeCurrentFile();
365
+ content = this._filterLoadedContent(content);
366
+ this._fileOpened(content, metadata, { openedContent: content.clone() }, this._getHashParams(metadata));
367
+ if (typeof callback === 'function') {
368
+ callback(content, metadata);
369
+ }
370
+ return metadata.provider.fileOpened(content, metadata);
371
+ });
372
+ }
373
+ else {
374
+ return this.openFileDialog(callback);
375
+ }
376
+ }
377
+ openFileDialog(callback = null) {
378
+ const showDialog = () => {
379
+ return this._ui.openFileDialog((metadata) => {
380
+ return this.openFile(metadata, callback);
381
+ });
382
+ };
383
+ if (!this.state.dirty) {
384
+ return showDialog();
385
+ }
386
+ else {
387
+ return this.confirm((0, translate_1.default)('~CONFIRM.OPEN_FILE'), showDialog);
388
+ }
389
+ }
390
+ closeFile(callback = null) {
391
+ this._closeCurrentFile();
392
+ this._resetState();
393
+ window.location.hash = "";
394
+ this._event('closedFile', { content: "" });
395
+ return (typeof callback === 'function' ? callback() : undefined);
396
+ }
397
+ closeFileDialog(callback = null) {
398
+ if (!this.state.dirty) {
399
+ return this.closeFile(callback);
400
+ }
401
+ else {
402
+ return this.confirm((0, translate_1.default)('~CONFIRM.CLOSE_FILE'), () => this.closeFile(callback));
403
+ }
404
+ }
405
+ importData(data, callback = null) {
406
+ this._event('importedData', data);
407
+ return (typeof callback === 'function' ? callback(data) : undefined);
408
+ }
409
+ importDataDialog(callback = null) {
410
+ return this._ui.importDataDialog((data) => {
411
+ return this.importData(data, callback);
412
+ });
413
+ }
414
+ readLocalFile(file, callback = null) {
415
+ const reader = new FileReader();
416
+ reader.onload = loaded => typeof callback === 'function' ? callback({ name: file.name, content: loaded.target.result }) : undefined;
417
+ return reader.readAsText(file);
418
+ }
419
+ openLocalFile(file, callback = null) {
420
+ this._event('willOpenFile', { op: "openLocalFile" });
421
+ return this.readLocalFile(file, (data) => {
422
+ let content = provider_interface_1.cloudContentFactory.createEnvelopedCloudContent(data.content);
423
+ content = this._filterLoadedContent(content);
424
+ const metadata = new provider_interface_1.CloudMetadata({
425
+ name: data.name,
426
+ type: provider_interface_1.CloudMetadata.File
427
+ });
428
+ this._fileOpened(content, metadata, { openedContent: content.clone() });
429
+ return (typeof callback === 'function' ? callback(content, metadata) : undefined);
430
+ });
431
+ }
432
+ importLocalFile(file, callback = null) {
433
+ return this.readLocalFile(file, (data) => {
434
+ return this.importData(data, callback);
435
+ });
436
+ }
437
+ openSharedContent(id) {
438
+ const { shareProvider } = this.state;
439
+ this._event('willOpenFile', { op: "openSharedContent" });
440
+ if (shareProvider.loadSharedContent) {
441
+ shareProvider.loadSharedContent(id, (err, content, metadata) => {
442
+ if (err) {
443
+ this.alert(err, () => this.ready());
444
+ }
445
+ else {
446
+ content = this._filterLoadedContent(content);
447
+ this._fileOpened(content, metadata, { overwritable: false, openedContent: content.clone() });
448
+ }
449
+ });
450
+ }
451
+ }
452
+ // must be called as a result of user action (e.g. click) to avoid popup blockers
453
+ parseUrlAuthorizeAndOpen() {
454
+ var _a;
455
+ if (((_a = this.appOptions.hashParams) === null || _a === void 0 ? void 0 : _a.fileParams) != null) {
456
+ const [providerName, providerParams] = this.appOptions.hashParams.fileParams.split(':');
457
+ const provider = this.providers[providerName];
458
+ if (provider) {
459
+ return provider.authorize(() => {
460
+ return this.openProviderFile(providerName, providerParams);
461
+ });
462
+ }
463
+ }
464
+ }
465
+ /**
466
+ * Disassociates the current document from its provider.
467
+ *
468
+ * This is important specifically for autosaving providers. When authenticated
469
+ * state is lost we must not continue to autosave.
470
+ */
471
+ disconnectCurrentFile() {
472
+ console.warn('Closing file (rejected reauth)');
473
+ if (this.state.metadata) {
474
+ this.state.metadata.provider = null;
475
+ }
476
+ this._setState({ saving: null, saved: null });
477
+ window.location.hash = "";
478
+ this._event('ready');
479
+ }
480
+ confirmAuthorizeAndOpen(provider, providerParams) {
481
+ const rejectCallback = () => this.disconnectCurrentFile();
482
+ // trigger authorize() from confirmation dialog to avoid popup blockers
483
+ return this.confirm((0, translate_1.default)("~CONFIRM.AUTHORIZE_OPEN"), () => {
484
+ return provider.authorize(() => {
485
+ this._event('willOpenFile', { op: "confirmAuthorizeAndOpen" });
486
+ return provider.openSaved(providerParams, (err, content, metadata) => {
487
+ if (err) {
488
+ return this.alert(err);
489
+ }
490
+ content = this._filterLoadedContent(content);
491
+ this._fileOpened(content, metadata, { openedContent: content.clone() }, this._getHashParams(metadata));
492
+ return provider.fileOpened(content, metadata);
493
+ });
494
+ });
495
+ }, rejectCallback);
496
+ }
497
+ openProviderFileWhenConnected(providerName, providerParams) {
498
+ this.connectedPromise.then(() => this.openProviderFile(providerName, providerParams));
499
+ }
500
+ openProviderFile(providerName, providerParams) {
501
+ const provider = this.providers[providerName];
502
+ if (provider) {
503
+ return provider.authorized((isAuthorized) => {
504
+ // we can open the document without authorization in some cases
505
+ if (isAuthorized || !provider.isAuthorizationRequired()) {
506
+ this._event('willOpenFile', { op: "openProviderFile" });
507
+ return provider.openSaved(providerParams, (err, content, metadata) => {
508
+ if (err) {
509
+ return this.alert(err, () => this.ready());
510
+ }
511
+ // if we just opened the file, it doesn't need to be saved until the contents are changed unless
512
+ // it requires conversion from an older version
513
+ content = this._filterLoadedContent(content);
514
+ const additionalState = { openedContent: content.clone(), dirty: content.requiresConversion() };
515
+ this._fileOpened(content, metadata, additionalState, this._getHashParams(metadata));
516
+ return provider.fileOpened(content, metadata);
517
+ });
518
+ }
519
+ else {
520
+ return this.confirmAuthorizeAndOpen(provider, providerParams);
521
+ }
522
+ }, { forceAuthorization: true }); // force authorization for Google Drive
523
+ }
524
+ else {
525
+ return this.alert((0, translate_1.default)("~ALERT.NO_PROVIDER"), () => this.ready());
526
+ }
527
+ }
528
+ openUrlFile(url) {
529
+ return this.urlProvider.openFileFromUrl(url, (err, content, metadata) => {
530
+ this._event('willOpenFile', { op: "openUrlFile" });
531
+ if (err) {
532
+ return this.alert(err, () => this.ready());
533
+ }
534
+ content = this._filterLoadedContent(content);
535
+ return this._fileOpened(content, metadata, { openedContent: content.clone() }, this._getHashParams(metadata));
536
+ });
537
+ }
538
+ createNewInFolder(providerName, folder) {
539
+ const provider = this.providers[providerName];
540
+ if (provider && provider.can(provider_interface_1.ECapabilities.setFolder, this.state.metadata)) {
541
+ if ((this.state.metadata == null)) {
542
+ this.state.metadata = new provider_interface_1.CloudMetadata({
543
+ type: provider_interface_1.CloudMetadata.File,
544
+ provider
545
+ });
546
+ }
547
+ this.state.metadata.parent = new provider_interface_1.CloudMetadata({
548
+ type: provider_interface_1.CloudMetadata.Folder,
549
+ providerData: {
550
+ id: folder
551
+ }
552
+ });
553
+ this._ui.editInitialFilename();
554
+ }
555
+ return this._event('newedFile', { content: "" });
556
+ }
557
+ setInitialFilename(filename) {
558
+ this.state.metadata.rename(filename);
559
+ return this.save();
560
+ }
561
+ isSaveInProgress() {
562
+ return (this.state.saving != null);
563
+ }
564
+ confirmAuthorizeAndSave(stringContent, callback) {
565
+ let rejectCallback = () => { this.disconnectCurrentFile(); };
566
+ // trigger authorize() from confirmation dialog to avoid popup blockers
567
+ return this.confirm((0, translate_1.default)("~CONFIRM.AUTHORIZE_SAVE"), () => {
568
+ return this.state.metadata.provider.authorize(() => {
569
+ return this.saveFile(stringContent, this.state.metadata, callback);
570
+ });
571
+ }, rejectCallback);
572
+ }
573
+ save(callback = null) {
574
+ return this._event('getContent', { shared: this._sharedMetadata() }, (stringContent) => {
575
+ return this.saveContent(stringContent, callback);
576
+ });
577
+ }
578
+ saveContent(stringContent, callback = null) {
579
+ var _a;
580
+ const provider = ((_a = this.state.metadata) === null || _a === void 0 ? void 0 : _a.provider) || this.autoProvider(provider_interface_1.ECapabilities.save);
581
+ if (provider != null) {
582
+ return provider.authorized((isAuthorized) => {
583
+ // we can save the document without authorization in some cases
584
+ if (isAuthorized || !provider.isAuthorizationRequired()) {
585
+ return this.saveFile(stringContent, this.state.metadata, callback);
586
+ }
587
+ else {
588
+ return this.confirmAuthorizeAndSave(stringContent, callback);
589
+ }
590
+ });
591
+ }
592
+ else {
593
+ return this.saveFileDialog(stringContent, callback);
594
+ }
595
+ }
596
+ saveFile(stringContent, metadata, callback = null) {
597
+ var _a;
598
+ const readonly = metadata && !metadata.overwritable; // only check if metadata exists
599
+ const resaveable = (_a = metadata === null || metadata === void 0 ? void 0 : metadata.provider) === null || _a === void 0 ? void 0 : _a.can(provider_interface_1.ECapabilities.resave, metadata);
600
+ // must be able to 'resave' to save silently, i.e. without save dialog
601
+ if (!readonly && resaveable) {
602
+ return this.saveFileNoDialog(stringContent, metadata, callback);
603
+ }
604
+ else {
605
+ return this.saveFileDialog(stringContent, callback);
606
+ }
607
+ }
608
+ saveFileNoDialog(stringContent, metadata, callback = null) {
609
+ var _a, _b;
610
+ this._setState({
611
+ saving: metadata
612
+ });
613
+ let currentContent = this._createOrUpdateCurrentContent(stringContent, metadata);
614
+ currentContent = ((_b = (_a = this.appOptions).contentSaveFilter) === null || _b === void 0 ? void 0 : _b.call(_a, currentContent)) || currentContent;
615
+ return metadata.provider.save(currentContent, metadata, (err, statusCode, savedContent) => {
616
+ let failures;
617
+ if (err) {
618
+ if (statusCode === 401 || statusCode === 403 || statusCode === 404) {
619
+ // disable autosave while the confirmation dialog is showing
620
+ metadata.autoSaveDisabled = true;
621
+ this._setState({ metadata, saving: null });
622
+ return this.confirmAuthorizeAndSave(stringContent, callback);
623
+ }
624
+ else {
625
+ this._setState({ saving: null });
626
+ failures = this.state.failures;
627
+ if (!failures) {
628
+ failures = 1;
629
+ }
630
+ else {
631
+ failures++;
632
+ }
633
+ if (failures === 1) {
634
+ this._setState({ failures, showingSaveAlert: true });
635
+ let error = err.toString();
636
+ if (this.isAutoSaving()) {
637
+ error = `${error}<br><br>${(0, translate_1.default)("~FILE_STATUS.CONTINUE_SAVE")}`;
638
+ }
639
+ return this.alert(error, () => {
640
+ this._setState({ showingSaveAlert: false });
641
+ });
642
+ }
643
+ else {
644
+ this._setState({ failures });
645
+ }
646
+ }
647
+ }
648
+ else {
649
+ if (this.state.showingSaveAlert) {
650
+ this.hideAlert();
651
+ }
652
+ this._setState({ failures: 0, showingSaveAlert: false });
653
+ if (this.state.metadata !== metadata) {
654
+ this._closeCurrentFile();
655
+ }
656
+ // reenable autosave on save success if this isn't a local file save
657
+ if (metadata.autoSaveDisabled != null) {
658
+ delete metadata.autoSaveDisabled;
659
+ }
660
+ this._fileChanged('savedFile', currentContent, metadata, { saved: true }, this._getHashParams(metadata));
661
+ return (typeof callback === 'function' ? callback(currentContent, metadata, savedContent) : undefined);
662
+ }
663
+ });
664
+ }
665
+ saveFileDialog(stringContent = null, callback = null) {
666
+ return this._ui.saveFileDialog((metadata) => {
667
+ return this._dialogSave(stringContent, metadata, callback);
668
+ });
669
+ }
670
+ saveFileAsDialog(stringContent = null, callback = null) {
671
+ return this._ui.saveFileAsDialog((metadata) => {
672
+ return this._dialogSave(stringContent, metadata, callback);
673
+ });
674
+ }
675
+ createCopy(stringContent = null, callback = null) {
676
+ const saveAndOpenCopy = (stringContent) => {
677
+ var _a;
678
+ return this.saveCopiedFile(stringContent, (_a = this.state.metadata) === null || _a === void 0 ? void 0 : _a.name, (err, copyParams) => {
679
+ if (err) {
680
+ return (typeof callback === 'function' ? callback(err) : undefined);
681
+ }
682
+ window.open(this.getCurrentUrl(`#copy=${copyParams}`));
683
+ return (typeof callback === 'function' ? callback(copyParams) : undefined);
684
+ });
685
+ };
686
+ if (stringContent == null) {
687
+ return this._event('getContent', {}, (stringContent) => saveAndOpenCopy(stringContent));
688
+ }
689
+ else {
690
+ return saveAndOpenCopy(stringContent);
691
+ }
692
+ }
693
+ saveCopiedFile(stringContent, name, callback) {
694
+ try {
695
+ const prefix = 'cfm-copy::';
696
+ let maxCopyNumber = 0;
697
+ for (let key of Object.keys(window.localStorage || {})) {
698
+ if (key.substr(0, prefix.length) === prefix) {
699
+ const copyNumber = parseInt(key.substr(prefix.length), 10);
700
+ maxCopyNumber = Math.max(maxCopyNumber, copyNumber);
701
+ }
702
+ }
703
+ maxCopyNumber++;
704
+ const value = JSON.stringify({
705
+ name: (name === null || name === void 0 ? void 0 : name.length) ? `Copy of ${name}` : "Copy of Untitled Document",
706
+ stringContent
707
+ });
708
+ window.localStorage.setItem(`${prefix}${maxCopyNumber}`, value);
709
+ return (typeof callback === 'function' ? callback(null, maxCopyNumber) : undefined);
710
+ }
711
+ catch (e) {
712
+ // CODAP style overrides
713
+ const divStyle = "text-align: left";
714
+ const paragraphStyle = "margin: 10px 0;";
715
+ const listStyle = "margin: 10px 10px 10px 30px; padding: 0;";
716
+ const message = `
717
+ <div style="${divStyle}">
718
+ <p style="${paragraphStyle}">The document is either too large to copy within the app, or your browser does not allow local storage.</p>
719
+
720
+ <p style="${paragraphStyle}">To copy this file you must duplicate it outside the app using these steps:</p>
721
+
722
+ <ol style="${listStyle}">
723
+ <li>Save the document.</li>
724
+ <li>Duplicate it using Google Drive or your local file system.</li>
725
+ <li>Open or import the newly duplicated document.</li>
726
+ </ol>
727
+ </div>
728
+ `;
729
+ return this.alert(message, "Copy Error");
730
+ }
731
+ }
732
+ openCopiedFile(copyParams) {
733
+ this._event('willOpenFile', { op: "openCopiedFile" });
734
+ try {
735
+ const key = `cfm-copy::${copyParams}`;
736
+ const copied = JSON.parse(window.localStorage.getItem(key));
737
+ let content = provider_interface_1.cloudContentFactory.createEnvelopedCloudContent(copied.stringContent);
738
+ content = this._filterLoadedContent(content);
739
+ const metadata = new provider_interface_1.CloudMetadata({
740
+ name: copied.name,
741
+ type: provider_interface_1.CloudMetadata.File
742
+ });
743
+ window.location.hash = "";
744
+ this._fileOpened(content, metadata, { dirty: true, openedContent: content.clone() });
745
+ return window.localStorage.removeItem(key);
746
+ }
747
+ catch (e) {
748
+ (0, report_error_1.reportError)("Unable to load copied file");
749
+ }
750
+ }
751
+ haveTempFile() {
752
+ try {
753
+ const key = "cfm-tempfile";
754
+ return !!(JSON.parse(window.localStorage.getItem(key)));
755
+ }
756
+ catch (e) {
757
+ return false;
758
+ }
759
+ }
760
+ saveTempFile(callback) {
761
+ return this._event('getContent', { shared: this._sharedMetadata() }, (stringContent) => {
762
+ var _a;
763
+ const currentContent = this._createOrUpdateCurrentContent(stringContent);
764
+ try {
765
+ const key = "cfm-tempfile";
766
+ const name = (_a = this.state.metadata) === null || _a === void 0 ? void 0 : _a.name;
767
+ const value = JSON.stringify({ name, stringContent });
768
+ window.localStorage.setItem(key, value);
769
+ const metadata = new provider_interface_1.CloudMetadata({
770
+ name,
771
+ type: provider_interface_1.CloudMetadata.File
772
+ });
773
+ this._fileChanged('savedFile', currentContent, metadata, { saved: true }, "");
774
+ return callback === null || callback === void 0 ? void 0 : callback(null);
775
+ }
776
+ catch (e) {
777
+ return callback === null || callback === void 0 ? void 0 : callback("Unable to temporarily save copied file");
778
+ }
779
+ });
780
+ }
781
+ openAndClearTempFile() {
782
+ this._event('willOpenFile', { op: "openAndClearTempFile" });
783
+ try {
784
+ const key = "cfm-tempfile";
785
+ const { name, stringContent } = JSON.parse(window.localStorage.getItem(key));
786
+ let content = provider_interface_1.cloudContentFactory.createEnvelopedCloudContent(stringContent);
787
+ content = this._filterLoadedContent(content);
788
+ const metadata = new provider_interface_1.CloudMetadata({
789
+ name,
790
+ type: provider_interface_1.CloudMetadata.File
791
+ });
792
+ this._fileOpened(content, metadata, { dirty: true, openedContent: content.clone() });
793
+ return window.localStorage.removeItem(key);
794
+ }
795
+ catch (e) {
796
+ (0, report_error_1.reportError)("Unable to load temp file");
797
+ }
798
+ }
799
+ _sharedMetadata() {
800
+ var _a;
801
+ return ((_a = this.state.currentContent) === null || _a === void 0 ? void 0 : _a.getSharedMetadata()) || {};
802
+ }
803
+ shareGetLink() {
804
+ return this._ui.shareDialog(this);
805
+ }
806
+ shareUpdate() {
807
+ return this.share(() => this.alert(((0, translate_1.default)("~SHARE_UPDATE.MESSAGE")), ((0, translate_1.default)("~SHARE_UPDATE.TITLE"))));
808
+ }
809
+ toggleShare(callback) {
810
+ if (this.isShared()) {
811
+ return this.unshare(callback);
812
+ }
813
+ else {
814
+ return this.share(callback);
815
+ }
816
+ }
817
+ isShared() {
818
+ var _a;
819
+ const currentContent = (_a = this.state) === null || _a === void 0 ? void 0 : _a.currentContent;
820
+ if (currentContent) {
821
+ const unshared = currentContent.get("isUnshared");
822
+ if (!unshared) {
823
+ const sharedDocumentId = currentContent.get("sharedDocumentId");
824
+ const sharedDocumentUrl = currentContent.get("sharedDocumentUrl");
825
+ return (sharedDocumentId || sharedDocumentUrl);
826
+ }
827
+ }
828
+ return false;
829
+ }
830
+ canEditShared() {
831
+ const accessKeys = (this.state.currentContent != null ? this.state.currentContent.get("accessKeys") : undefined) || {};
832
+ const shareEditKey = this.state.currentContent != null ? this.state.currentContent.get("shareEditKey") : undefined;
833
+ return (shareEditKey || accessKeys.readWrite) && !(this.state.currentContent != null ? this.state.currentContent.get("isUnshared") : undefined);
834
+ }
835
+ setShareState(shared, callback) {
836
+ if (this.state.shareProvider) {
837
+ const sharingMetadata = this.state.shareProvider.getSharingMetadata(shared);
838
+ return this._event('getContent', { shared: sharingMetadata }, (stringContent) => {
839
+ this._setState({ sharing: shared });
840
+ const sharedContent = provider_interface_1.cloudContentFactory.createEnvelopedCloudContent(stringContent);
841
+ sharedContent.addMetadata(sharingMetadata);
842
+ const currentContent = this._createOrUpdateCurrentContent(stringContent, this.state.metadata);
843
+ sharedContent.set('docName', currentContent.get('docName'));
844
+ // save the current name at the top level so it is displayed when the shared file is loaded
845
+ if (this.state.metadata) {
846
+ sharedContent.getClientContent().name = this.state.metadata.name;
847
+ }
848
+ if (shared) {
849
+ currentContent.remove('isUnshared');
850
+ }
851
+ else {
852
+ currentContent.set('isUnshared', true);
853
+ }
854
+ return this.state.shareProvider.share(shared, currentContent, sharedContent, this.state.metadata, (err, sharedContentId) => {
855
+ if (err) {
856
+ return this.alert(err);
857
+ }
858
+ return callback === null || callback === void 0 ? void 0 : callback(null, sharedContentId, currentContent);
859
+ });
860
+ });
861
+ }
862
+ }
863
+ share(callback) {
864
+ if (!this.state.metadata) {
865
+ // PJ, 07/10/2020: Without these lines the sharing process will fail (it looks for filename and later tries to
866
+ // update metadata object). Apparently, there's an assumption that metadata already exists. It can initialized
867
+ // in a few random places, but a new document that has never been renamed won't have this object available.
868
+ this.state.metadata = new provider_interface_1.CloudMetadata({
869
+ name: (0, translate_1.default)("~MENUBAR.UNTITLED_DOCUMENT"),
870
+ type: provider_interface_1.CloudMetadata.File
871
+ });
872
+ }
873
+ return this.setShareState(true, (err, sharedContentId, currentContent) => {
874
+ this._fileChanged('sharedFile', currentContent, this.state.metadata);
875
+ return callback === null || callback === void 0 ? void 0 : callback(null, sharedContentId);
876
+ });
877
+ }
878
+ unshare(callback) {
879
+ return this.setShareState(false, (err, sharedContentId, currentContent) => {
880
+ this._fileChanged('unsharedFile', currentContent, this.state.metadata);
881
+ return callback === null || callback === void 0 ? void 0 : callback(null);
882
+ });
883
+ }
884
+ revertToShared(callback = null) {
885
+ var _a, _b, _c;
886
+ // Look for sharedDocumentUrl or Url first:
887
+ const id = ((_a = this.state.currentContent) === null || _a === void 0 ? void 0 : _a.get("sharedDocumentUrl"))
888
+ || ((_b = this.state.currentContent) === null || _b === void 0 ? void 0 : _b.get("url"))
889
+ || ((_c = this.state.currentContent) === null || _c === void 0 ? void 0 : _c.get("sharedDocumentId"));
890
+ if (id && (this.state.shareProvider != null)) {
891
+ return this.state.shareProvider.loadSharedContent(id, (err, content, metadata) => {
892
+ let docName;
893
+ if (err) {
894
+ return this.alert(err);
895
+ }
896
+ content = this._filterLoadedContent(content);
897
+ this.state.currentContent.copyMetadataTo(content);
898
+ if (!metadata.name && (docName = content.get('docName'))) {
899
+ metadata.name = docName;
900
+ }
901
+ this._fileOpened(content, metadata, { dirty: true, openedContent: content.clone() });
902
+ return callback === null || callback === void 0 ? void 0 : callback(null);
903
+ });
904
+ }
905
+ }
906
+ revertToSharedDialog(callback = null) {
907
+ if ((this.state.currentContent != null ? this.state.currentContent.get("sharedDocumentId") : undefined) && (this.state.shareProvider != null)) {
908
+ return this.confirm((0, translate_1.default)("~CONFIRM.REVERT_TO_SHARED_VIEW"), () => this.revertToShared(callback));
909
+ }
910
+ }
911
+ downloadDialog(callback = null) {
912
+ // should share metadata be included in downloaded local files?
913
+ return this._event('getContent', { shared: this._sharedMetadata() }, (content) => {
914
+ var _a;
915
+ const envelopedContent = provider_interface_1.cloudContentFactory.createEnvelopedCloudContent(content);
916
+ if (this.state.currentContent != null) {
917
+ this.state.currentContent.copyMetadataTo(envelopedContent);
918
+ }
919
+ return this._ui.downloadDialog((_a = this.state.metadata) === null || _a === void 0 ? void 0 : _a.name, envelopedContent, callback);
920
+ });
921
+ }
922
+ getDownloadBlob(content, includeShareInfo, mimeType) {
923
+ var _a;
924
+ let contentToSave;
925
+ if (mimeType == null) {
926
+ mimeType = 'text/plain';
927
+ }
928
+ if (typeof content === "string") {
929
+ if (mimeType.indexOf("image") >= 0) {
930
+ contentToSave = base64_js_1.default.toByteArray(content);
931
+ }
932
+ else {
933
+ contentToSave = content;
934
+ }
935
+ }
936
+ else if (includeShareInfo) {
937
+ contentToSave = JSON.stringify(content.getContent());
938
+ }
939
+ else { // not includeShareInfo
940
+ // clone the document so we can delete the share info and not affect the original
941
+ const json = content.clone().getContent();
942
+ delete json.sharedDocumentId;
943
+ delete json.sharedDocumentUrl;
944
+ delete json.shareEditKey;
945
+ delete json.isUnshared;
946
+ delete json.accessKeys;
947
+ // CODAP moves the keys into its own namespace
948
+ if (((_a = json.metadata) === null || _a === void 0 ? void 0 : _a.shared) != null) {
949
+ delete json.metadata.shared;
950
+ }
951
+ contentToSave = JSON.stringify(json);
952
+ }
953
+ return new Blob([contentToSave], { type: mimeType });
954
+ }
955
+ getDownloadUrl(content, includeShareInfo, mimeType) {
956
+ if (mimeType == null) {
957
+ mimeType = 'text/plain';
958
+ }
959
+ const wURL = window.URL || window.webkitURL;
960
+ if (wURL) {
961
+ return wURL.createObjectURL(this.getDownloadBlob(content, includeShareInfo, mimeType));
962
+ }
963
+ }
964
+ rename(metadata, newName, callback) {
965
+ var _a;
966
+ const { dirty } = this.state;
967
+ const _rename = (metadata) => {
968
+ var _a;
969
+ if (this.state.currentContent != null) {
970
+ this.state.currentContent.addMetadata({ docName: metadata.name });
971
+ }
972
+ this._fileChanged('renamedFile', this.state.currentContent, metadata, { dirty }, this._getHashParams(metadata));
973
+ const done = () => typeof callback === 'function' ? callback(newName) : undefined;
974
+ const readOnlyProvider = ((_a = metadata === null || metadata === void 0 ? void 0 : metadata.provider) === null || _a === void 0 ? void 0 : _a.name) === readonly_provider_1.default.Name;
975
+ if (!readOnlyProvider && ((metadata === null || metadata === void 0 ? void 0 : metadata.provider) || this.autoProvider(provider_interface_1.ECapabilities.save))) {
976
+ // autosave renamed file if it has already been saved or can be autosaved
977
+ this.save(done);
978
+ }
979
+ else {
980
+ done();
981
+ }
982
+ };
983
+ if (newName !== (this.state.metadata != null ? this.state.metadata.name : undefined)) {
984
+ if ((_a = metadata === null || metadata === void 0 ? void 0 : metadata.provider) === null || _a === void 0 ? void 0 : _a.can(provider_interface_1.ECapabilities.rename, metadata)) {
985
+ return this.state.metadata.provider.rename(this.state.metadata, newName, (err, metadata) => {
986
+ if (err) {
987
+ return this.alert(err);
988
+ }
989
+ return _rename(metadata);
990
+ });
991
+ }
992
+ else {
993
+ if (metadata) {
994
+ metadata.rename(newName);
995
+ }
996
+ else {
997
+ metadata = new provider_interface_1.CloudMetadata({
998
+ name: newName,
999
+ type: provider_interface_1.CloudMetadata.File
1000
+ });
1001
+ }
1002
+ return _rename(metadata);
1003
+ }
1004
+ }
1005
+ }
1006
+ renameDialog(callback = null) {
1007
+ return this._ui.renameDialog(this.state.metadata != null ? this.state.metadata.name : undefined, (newName) => {
1008
+ return this.rename(this.state.metadata, newName, callback);
1009
+ });
1010
+ }
1011
+ revertToLastOpened(callback = null) {
1012
+ this._event('willOpenFile', { op: "revertToLastOpened" });
1013
+ if ((this.state.openedContent != null) && this.state.metadata) {
1014
+ return this._fileOpened(this.state.openedContent, this.state.metadata, { openedContent: this.state.openedContent.clone() });
1015
+ }
1016
+ }
1017
+ revertToLastOpenedDialog(callback = null) {
1018
+ if ((this.state.openedContent != null) && this.state.metadata) {
1019
+ return this.confirm((0, translate_1.default)('~CONFIRM.REVERT_TO_LAST_OPENED'), () => this.revertToLastOpened(callback));
1020
+ }
1021
+ else {
1022
+ return (typeof callback === 'function' ? callback('No initial opened version was found for the currently active file') : undefined);
1023
+ }
1024
+ }
1025
+ saveSecondaryFileAsDialog(stringContent, extension, mimeType, callback) {
1026
+ // set the mimeType if not given with the extension
1027
+ const extensionMimeType = mime_1.default.getType(extension);
1028
+ if (extension && !mimeType && extensionMimeType) {
1029
+ mimeType = extensionMimeType;
1030
+ }
1031
+ const provider = this.autoProvider(provider_interface_1.ECapabilities['export']);
1032
+ if (provider) {
1033
+ const metadata = { provider, extension, mimeType };
1034
+ return this.saveSecondaryFile(stringContent, metadata, callback);
1035
+ }
1036
+ else {
1037
+ const data = { content: stringContent, extension, mimeType };
1038
+ return this._ui.saveSecondaryFileAsDialog(data, (metadata) => {
1039
+ // replace defaults
1040
+ if (extension) {
1041
+ metadata.filename = provider_interface_1.CloudMetadata.newExtension(metadata.filename, extension);
1042
+ }
1043
+ if (mimeType) {
1044
+ metadata.mimeType = mimeType;
1045
+ }
1046
+ return this.saveSecondaryFile(stringContent, metadata, callback);
1047
+ });
1048
+ }
1049
+ }
1050
+ // Saves a file to backend, but does not update current metadata.
1051
+ // Used e.g. when exporting .csv files from CODAP
1052
+ saveSecondaryFile(stringContent, metadata, callback = null) {
1053
+ var _a;
1054
+ if ((_a = metadata === null || metadata === void 0 ? void 0 : metadata.provider) === null || _a === void 0 ? void 0 : _a.can(provider_interface_1.ECapabilities["export"], metadata)) {
1055
+ return metadata.provider.saveAsExport(stringContent, metadata, (err, statusCode) => {
1056
+ return err ? this.alert(err) : callback === null || callback === void 0 ? void 0 : callback(stringContent, metadata);
1057
+ });
1058
+ }
1059
+ }
1060
+ dirty(isDirty = true) {
1061
+ this._setState({
1062
+ dirty: isDirty,
1063
+ saved: this.state.saved && !isDirty
1064
+ });
1065
+ if (window.self !== window.top) {
1066
+ // post to parent and not top window (not a bug even though we test for self inst top above)
1067
+ return window.parent.postMessage({ type: "cfm::setDirty", isDirty }, "*");
1068
+ }
1069
+ }
1070
+ shouldAutoSave() {
1071
+ var _a;
1072
+ const { metadata } = this.state;
1073
+ return (this.state.dirty
1074
+ && !(metadata === null || metadata === void 0 ? void 0 : metadata.autoSaveDisabled)
1075
+ && !this.isSaveInProgress()
1076
+ && ((_a = metadata === null || metadata === void 0 ? void 0 : metadata.provider) === null || _a === void 0 ? void 0 : _a.can(provider_interface_1.ECapabilities.resave, metadata)));
1077
+ }
1078
+ autoSave(interval) {
1079
+ if (this._autoSaveInterval) {
1080
+ clearInterval(this._autoSaveInterval);
1081
+ }
1082
+ // in case the caller uses milliseconds
1083
+ if (interval > 1000) {
1084
+ interval = Math.round(interval / 1000);
1085
+ }
1086
+ if (interval > 0) {
1087
+ return this._autoSaveInterval = window.setInterval(() => { if (this.shouldAutoSave()) {
1088
+ return this.save();
1089
+ } }, interval * 1000);
1090
+ }
1091
+ }
1092
+ isAutoSaving() {
1093
+ return (this._autoSaveInterval != null);
1094
+ }
1095
+ changeLanguage(newLangCode, callback) {
1096
+ var _a, _b;
1097
+ if (callback) {
1098
+ const postSave = (err) => {
1099
+ if (err) {
1100
+ this.alert(err);
1101
+ return this.confirm((0, translate_1.default)('~CONFIRM.CHANGE_LANGUAGE'), () => callback(newLangCode));
1102
+ }
1103
+ else {
1104
+ return callback(newLangCode);
1105
+ }
1106
+ };
1107
+ if ((_b = (_a = this.state.metadata) === null || _a === void 0 ? void 0 : _a.provider) === null || _b === void 0 ? void 0 : _b.can(provider_interface_1.ECapabilities.save)) {
1108
+ return this.save((err) => postSave(err));
1109
+ }
1110
+ else {
1111
+ return this.saveTempFile(postSave);
1112
+ }
1113
+ }
1114
+ }
1115
+ showBlockingModal(modalProps) {
1116
+ return this._ui.showBlockingModal(modalProps);
1117
+ }
1118
+ hideBlockingModal() {
1119
+ return this._ui.hideBlockingModal();
1120
+ }
1121
+ getCurrentUrl(hashString) {
1122
+ return `${window.location.origin}${window.location.pathname}${window.location.search}${hashString || ""}`;
1123
+ }
1124
+ // Takes an array of strings representing url parameters to be removed from the URL.
1125
+ // Removes the specified parameters from the URL and then uses the history API's
1126
+ // pushState() method to update the URL without reloading the page.
1127
+ // Adapted from http://stackoverflow.com/a/11654436.
1128
+ removeQueryParams(params) {
1129
+ let url = window.location.href;
1130
+ const hash = url.split('#');
1131
+ for (let key of params) {
1132
+ const re = new RegExp(`([?&])${key}=.*?(&|#|$)(.*)`, "g");
1133
+ if (re.test(url)) {
1134
+ hash[0] = hash[0].replace(re, '$1$3').replace(/(&|\?)$/, '');
1135
+ }
1136
+ }
1137
+ url = hash[0] + ((hash[1] != null) ? `#${hash[1]}` : '');
1138
+ if (url !== window.location.href) {
1139
+ return history.pushState({ originalUrl: window.location.href }, '', url);
1140
+ }
1141
+ }
1142
+ confirm(message, callback, rejectCallback) {
1143
+ return this.confirmDialog({ message, callback, rejectCallback });
1144
+ }
1145
+ confirmDialog(params) {
1146
+ return this._ui.confirmDialog(params);
1147
+ }
1148
+ alert(message, titleOrCallback, callback) {
1149
+ if (lodash_1.default.isFunction(titleOrCallback)) {
1150
+ callback = titleOrCallback;
1151
+ titleOrCallback = null;
1152
+ }
1153
+ return this._ui.alertDialog(message, (titleOrCallback || (0, translate_1.default)("~CLIENT_ERROR.TITLE")), callback);
1154
+ }
1155
+ hideAlert() {
1156
+ this._ui.hideAlertDialog();
1157
+ }
1158
+ selectInteractiveStateDialog(props, callback) {
1159
+ this._event("requiresUserInteraction");
1160
+ this._ui.selectInteractiveStateDialog({ ...props, onSelect: callback });
1161
+ }
1162
+ async onUnload(options) {
1163
+ if (options.unloading) {
1164
+ return new Promise(resolve => {
1165
+ var _a;
1166
+ // only save if the provider is set - when using linked interactives the provider is not set when
1167
+ // the linked interactive changed and the version choice dialog is showing
1168
+ if ((_a = this.state.metadata) === null || _a === void 0 ? void 0 : _a.provider) {
1169
+ this.save((content, metadata, savedContent) => {
1170
+ // providers can save a different format for the content
1171
+ // for example the interactiveApi provider can save attachments in which case the savedContent
1172
+ // will be an object pointing at the attachment
1173
+ resolve(savedContent || content);
1174
+ });
1175
+ }
1176
+ else {
1177
+ // signal that nothing needs to be saved
1178
+ resolve(undefined);
1179
+ }
1180
+ });
1181
+ }
1182
+ return Promise.resolve(undefined);
1183
+ }
1184
+ _dialogSave(stringContent, metadata, callback) {
1185
+ if (stringContent != null) {
1186
+ return this.saveFileNoDialog(stringContent, metadata, callback);
1187
+ }
1188
+ else {
1189
+ return this._event('getContent', { shared: this._sharedMetadata() }, (stringContent) => {
1190
+ return this.saveFileNoDialog(stringContent, metadata, callback);
1191
+ });
1192
+ }
1193
+ }
1194
+ // The purpose of this seems to be to definitely set whether or not the content
1195
+ // can be overwritten? Will mutate metadata:
1196
+ _updateMetaDataOverwritable(metadata) {
1197
+ if (metadata != null) {
1198
+ metadata.overwritable = (metadata.overwritable != null)
1199
+ ? metadata.overwritable
1200
+ : true;
1201
+ }
1202
+ }
1203
+ _fileChanged(type, content, metadata, additionalState, hashParams = null) {
1204
+ if (additionalState == null) {
1205
+ additionalState = {};
1206
+ }
1207
+ this._updateMetaDataOverwritable(metadata);
1208
+ this._updateState(content, metadata, additionalState, hashParams);
1209
+ return this._event(type, { content: (content != null ? content.getClientContent() : undefined), shared: this._sharedMetadata() });
1210
+ }
1211
+ _fileOpened(content, metadata, additionalState, hashParams = null) {
1212
+ var _a, _b;
1213
+ if (additionalState == null) {
1214
+ additionalState = {};
1215
+ }
1216
+ const eventData = { content: (_b = (_a = content === null || content === void 0 ? void 0 : content.getClientContent) === null || _a === void 0 ? void 0 : _a.call(content)) !== null && _b !== void 0 ? _b : content };
1217
+ // update state before sending 'openedFile' events so that 'openedFile' listeners that
1218
+ // reference state have the updated state values
1219
+ this._updateState(content, metadata, additionalState, hashParams);
1220
+ // add metadata contentType to event for CODAP to load via postMessage API (for SageModeler standalone)
1221
+ const contentType = metadata.mimeType || metadata.contentType;
1222
+ eventData.metadata = { contentType, url: metadata.url, filename: metadata.filename };
1223
+ return this._event('openedFile', eventData, (iError, iSharedMetadata) => {
1224
+ if (iError) {
1225
+ return this.alert(iError, () => this.ready());
1226
+ }
1227
+ this._updateMetaDataOverwritable(metadata);
1228
+ if (!this.appOptions.wrapFileContent) {
1229
+ content.addMetadata(iSharedMetadata);
1230
+ }
1231
+ // and then update state again for the metadata and content changes
1232
+ this._updateState(content, metadata, additionalState, hashParams);
1233
+ return this.ready();
1234
+ });
1235
+ }
1236
+ _updateState(content, metadata, additionalState = {}, hashParams = null) {
1237
+ const state = {
1238
+ currentContent: content,
1239
+ metadata,
1240
+ saving: null,
1241
+ saved: false,
1242
+ dirty: !additionalState.saved && (content === null || content === void 0 ? void 0 : content.requiresConversion()),
1243
+ ...additionalState
1244
+ };
1245
+ this._setWindowTitle(metadata === null || metadata === void 0 ? void 0 : metadata.name);
1246
+ if (hashParams !== null) {
1247
+ window.location.hash = hashParams;
1248
+ }
1249
+ return this._setState(state);
1250
+ }
1251
+ _event(type, data, eventCallback = null) {
1252
+ var _a;
1253
+ if (data == null) {
1254
+ data = {};
1255
+ }
1256
+ const event = new CloudFileManagerClientEvent(type, data, eventCallback, this.state);
1257
+ for (let listener of this._listeners) {
1258
+ listener(event);
1259
+ }
1260
+ // Workaround to fix https://www.pivotaltracker.com/story/show/162392580
1261
+ // CODAP will fail on the renamedFile message because we don't send the state with
1262
+ // the postMessage events and CODAP examines the state to get the new name.
1263
+ // I tried sending the state but that causes CODAP to replace its state which breaks other things.
1264
+ // A permanent fix for this would be to send the new filename outside of the state metadata.
1265
+ const skipPostMessage = type === "renamedFile";
1266
+ if (((_a = this.appOptions) === null || _a === void 0 ? void 0 : _a.sendPostMessageClientEvents) && this.iframe && !skipPostMessage) {
1267
+ return event.postMessage(this.iframe.contentWindow);
1268
+ }
1269
+ }
1270
+ _setState(newState) {
1271
+ this.state = { ...this.state, ...newState };
1272
+ return this._event('stateChanged');
1273
+ }
1274
+ _resetState() {
1275
+ return this._setState({
1276
+ openedContent: null,
1277
+ currentContent: null,
1278
+ metadata: null,
1279
+ dirty: false,
1280
+ saving: null,
1281
+ saved: false,
1282
+ failures: 0
1283
+ });
1284
+ }
1285
+ _closeCurrentFile() {
1286
+ var _a;
1287
+ const { metadata } = this.state;
1288
+ if ((_a = metadata === null || metadata === void 0 ? void 0 : metadata.provider) === null || _a === void 0 ? void 0 : _a.can(provider_interface_1.ECapabilities.close, metadata)) {
1289
+ return metadata.provider.close(metadata);
1290
+ }
1291
+ }
1292
+ _createOrUpdateCurrentContent(stringContent, metadata = null) {
1293
+ let currentContent;
1294
+ if (this.state.currentContent != null) {
1295
+ ({ currentContent } = this.state);
1296
+ currentContent.setText(stringContent);
1297
+ }
1298
+ else {
1299
+ currentContent = provider_interface_1.cloudContentFactory.createEnvelopedCloudContent(stringContent);
1300
+ }
1301
+ if (metadata != null) {
1302
+ currentContent.addMetadata({ docName: metadata.name });
1303
+ }
1304
+ return currentContent;
1305
+ }
1306
+ _setWindowTitle(name) {
1307
+ var _a;
1308
+ if ((_a = this.appOptions) === null || _a === void 0 ? void 0 : _a.appSetsWindowTitle) {
1309
+ return;
1310
+ }
1311
+ const { ui } = this.appOptions;
1312
+ if (ui) {
1313
+ const { windowTitleSeparator, windowTitleSuffix } = ui;
1314
+ if (windowTitleSuffix) {
1315
+ const displayName = (name || "").length > 0
1316
+ ? name
1317
+ : (0, translate_1.default)("~MENUBAR.UNTITLED_DOCUMENT");
1318
+ document.title = `${displayName}${windowTitleSeparator}${windowTitleSuffix}`;
1319
+ }
1320
+ }
1321
+ }
1322
+ _getHashParams(metadata) {
1323
+ var _a, _b;
1324
+ const canOpenSaved = ((_a = metadata === null || metadata === void 0 ? void 0 : metadata.provider) === null || _a === void 0 ? void 0 : _a.canOpenSaved()) || false;
1325
+ let openSavedParams = canOpenSaved ? (_b = metadata === null || metadata === void 0 ? void 0 : metadata.provider) === null || _b === void 0 ? void 0 : _b.getOpenSavedParams(metadata) : null;
1326
+ if (canOpenSaved && (openSavedParams != null) && (typeof openSavedParams === "string")) {
1327
+ return `#file=${metadata.provider.urlDisplayName || metadata.provider.name}:${encodeURIComponent(openSavedParams)}`;
1328
+ }
1329
+ else if ((metadata === null || metadata === void 0 ? void 0 : metadata.provider) instanceof url_provider_1.default && (window.location.hash.indexOf("#file=http") === 0)) {
1330
+ return window.location.hash; // leave it alone
1331
+ }
1332
+ else {
1333
+ return "";
1334
+ }
1335
+ }
1336
+ _startPostMessageListener() {
1337
+ return (0, jquery_1.default)(window).on('message', e => {
1338
+ var _a, _b;
1339
+ const oe = e.originalEvent;
1340
+ const data = oe.data || {};
1341
+ const reply = function (type, params) {
1342
+ if (params == null) {
1343
+ params = {};
1344
+ }
1345
+ const message = lodash_1.default.merge({}, params, { type });
1346
+ return oe.source.postMessage(message, oe.origin);
1347
+ };
1348
+ switch (data === null || data === void 0 ? void 0 : data.type) {
1349
+ case 'cfm::getCommands':
1350
+ return reply('cfm::commands', { commands: ['cfm::autosave', 'cfm::event', 'cfm::event:reply', 'cfm::setDirty', 'cfm::iframedClientConnected'] });
1351
+ case 'cfm::autosave':
1352
+ if (this.shouldAutoSave()) {
1353
+ return this.save(() => reply('cfm::autosaved', { saved: true }));
1354
+ }
1355
+ else {
1356
+ return reply('cfm::autosaved', { saved: false });
1357
+ }
1358
+ case 'cfm::event':
1359
+ return this._event(data.eventType, data.eventData, function () {
1360
+ const callbackArgs = JSON.stringify(Array.prototype.slice.call(arguments));
1361
+ return reply('cfm::event:reply', { eventId: data.eventId, callbackArgs });
1362
+ });
1363
+ case 'cfm::event:reply': {
1364
+ const event = CLOUDFILEMANAGER_EVENTS[data.eventId];
1365
+ const callbackData = JSON.parse((data === null || data === void 0 ? void 0 : data.callbackArgs) || null);
1366
+ return (_a = event === null || event === void 0 ? void 0 : event.callback) === null || _a === void 0 ? void 0 : _a.apply(this, callbackData);
1367
+ }
1368
+ case 'cfm::setDirty':
1369
+ return this.dirty(data.isDirty);
1370
+ case 'cfm::iframedClientConnected':
1371
+ (_b = this.connectedPromiseResolver) === null || _b === void 0 ? void 0 : _b.resolve();
1372
+ return this.processUrlParams();
1373
+ }
1374
+ });
1375
+ }
1376
+ _setupConfirmOnClose() {
1377
+ return (0, jquery_1.default)(window).on('beforeunload', e => {
1378
+ if (this.state.dirty) {
1379
+ // different browsers trigger the confirm in different ways
1380
+ e.preventDefault();
1381
+ return e.returnValue = true;
1382
+ }
1383
+ });
1384
+ }
1385
+ _filterLoadedContent(content) {
1386
+ var _a, _b;
1387
+ return ((_b = (_a = this.appOptions).contentLoadFilter) === null || _b === void 0 ? void 0 : _b.call(_a, content)) || content;
1388
+ }
1389
+ }
1390
+ exports.CloudFileManagerClient = CloudFileManagerClient;
1391
+ //# sourceMappingURL=client.js.map