You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

app.js 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. /**
  2. * Copyright (c) 2014 Vincent Petry <pvince81@owncloud.com>
  3. *
  4. * This file is licensed under the Affero General Public License version 3
  5. * or later.
  6. *
  7. * See the COPYING-README file.
  8. *
  9. */
  10. if (!OCA.Sharing) {
  11. /**
  12. * @namespace OCA.Sharing
  13. */
  14. OCA.Sharing = {}
  15. }
  16. /**
  17. * @namespace
  18. */
  19. OCA.Sharing.App = {
  20. _inFileList: null,
  21. _outFileList: null,
  22. _overviewFileList: null,
  23. _pendingFileList: null,
  24. initSharingIn($el) {
  25. if (this._inFileList) {
  26. return this._inFileList
  27. }
  28. this._inFileList = new OCA.Sharing.FileList(
  29. $el,
  30. {
  31. id: 'shares.self',
  32. sharedWithUser: true,
  33. fileActions: this._createFileActions(),
  34. config: OCA.Files.App.getFilesConfig(),
  35. // The file list is created when a "show" event is handled, so
  36. // it should be marked as "shown" like it would have been done
  37. // if handling the event with the file list already created.
  38. shown: true,
  39. }
  40. )
  41. this._extendFileList(this._inFileList)
  42. this._inFileList.appName = t('files_sharing', 'Shared with you')
  43. this._inFileList.$el.find('#emptycontent').html('<div class="icon-shared"></div>'
  44. + '<h2>' + t('files_sharing', 'Nothing shared with you yet') + '</h2>'
  45. + '<p>' + t('files_sharing', 'Files and folders others share with you will show up here') + '</p>')
  46. return this._inFileList
  47. },
  48. initSharingOut($el) {
  49. if (this._outFileList) {
  50. return this._outFileList
  51. }
  52. this._outFileList = new OCA.Sharing.FileList(
  53. $el,
  54. {
  55. id: 'shares.others',
  56. sharedWithUser: false,
  57. fileActions: this._createFileActions(),
  58. config: OCA.Files.App.getFilesConfig(),
  59. // The file list is created when a "show" event is handled, so
  60. // it should be marked as "shown" like it would have been done
  61. // if handling the event with the file list already created.
  62. shown: true,
  63. }
  64. )
  65. this._extendFileList(this._outFileList)
  66. this._outFileList.appName = t('files_sharing', 'Shared with others')
  67. this._outFileList.$el.find('#emptycontent').html('<div class="icon-shared"></div>'
  68. + '<h2>' + t('files_sharing', 'Nothing shared yet') + '</h2>'
  69. + '<p>' + t('files_sharing', 'Files and folders you share will show up here') + '</p>')
  70. return this._outFileList
  71. },
  72. initSharingLinks($el) {
  73. if (this._linkFileList) {
  74. return this._linkFileList
  75. }
  76. this._linkFileList = new OCA.Sharing.FileList(
  77. $el,
  78. {
  79. id: 'shares.link',
  80. linksOnly: true,
  81. fileActions: this._createFileActions(),
  82. config: OCA.Files.App.getFilesConfig(),
  83. // The file list is created when a "show" event is handled, so
  84. // it should be marked as "shown" like it would have been done
  85. // if handling the event with the file list already created.
  86. shown: true,
  87. }
  88. )
  89. this._extendFileList(this._linkFileList)
  90. this._linkFileList.appName = t('files_sharing', 'Shared by link')
  91. this._linkFileList.$el.find('#emptycontent').html('<div class="icon-public"></div>'
  92. + '<h2>' + t('files_sharing', 'No shared links') + '</h2>'
  93. + '<p>' + t('files_sharing', 'Files and folders you share by link will show up here') + '</p>')
  94. return this._linkFileList
  95. },
  96. initSharingDeleted($el) {
  97. if (this._deletedFileList) {
  98. return this._deletedFileList
  99. }
  100. this._deletedFileList = new OCA.Sharing.FileList(
  101. $el,
  102. {
  103. id: 'shares.deleted',
  104. defaultFileActionsDisabled: true,
  105. showDeleted: true,
  106. sharedWithUser: true,
  107. fileActions: this._restoreShareAction(),
  108. config: OCA.Files.App.getFilesConfig(),
  109. // The file list is created when a "show" event is handled, so
  110. // it should be marked as "shown" like it would have been done
  111. // if handling the event with the file list already created.
  112. shown: true,
  113. }
  114. )
  115. this._extendFileList(this._deletedFileList)
  116. this._deletedFileList.appName = t('files_sharing', 'Deleted shares')
  117. this._deletedFileList.$el.find('#emptycontent').html('<div class="icon-share"></div>'
  118. + '<h2>' + t('files_sharing', 'No deleted shares') + '</h2>'
  119. + '<p>' + t('files_sharing', 'Shares you deleted will show up here') + '</p>')
  120. return this._deletedFileList
  121. },
  122. initSharingPening($el) {
  123. if (this._pendingFileList) {
  124. return this._pendingFileList
  125. }
  126. this._pendingFileList = new OCA.Sharing.FileList(
  127. $el,
  128. {
  129. id: 'shares.pending',
  130. showPending: true,
  131. detailsViewEnabled: false,
  132. defaultFileActionsDisabled: true,
  133. sharedWithUser: true,
  134. fileActions: this._acceptShareAction(),
  135. config: OCA.Files.App.getFilesConfig(),
  136. // The file list is created when a "show" event is handled, so
  137. // it should be marked as "shown" like it would have been done
  138. // if handling the event with the file list already created.
  139. shown: true,
  140. }
  141. )
  142. this._extendFileList(this._pendingFileList)
  143. this._pendingFileList.appName = t('files_sharing', 'Pending shares')
  144. this._pendingFileList.$el.find('#emptycontent').html('<div class="icon-share"></div>'
  145. + '<h2>' + t('files_sharing', 'No pending shares') + '</h2>'
  146. + '<p>' + t('files_sharing', 'Shares you have received but not confirmed will show up here') + '</p>')
  147. return this._pendingFileList
  148. },
  149. initShareingOverview($el) {
  150. if (this._overviewFileList) {
  151. return this._overviewFileList
  152. }
  153. this._overviewFileList = new OCA.Sharing.FileList(
  154. $el,
  155. {
  156. id: 'shares.overview',
  157. config: OCA.Files.App.getFilesConfig(),
  158. isOverview: true,
  159. // The file list is created when a "show" event is handled, so
  160. // it should be marked as "shown" like it would have been done
  161. // if handling the event with the file list already created.
  162. shown: true,
  163. }
  164. )
  165. this._extendFileList(this._overviewFileList)
  166. this._overviewFileList.appName = t('files_sharing', 'Shares')
  167. this._overviewFileList.$el.find('#emptycontent').html('<div class="icon-share"></div>'
  168. + '<h2>' + t('files_sharing', 'No shares') + '</h2>'
  169. + '<p>' + t('files_sharing', 'Shares will show up here') + '</p>')
  170. return this._overviewFileList
  171. },
  172. removeSharingIn() {
  173. if (this._inFileList) {
  174. this._inFileList.$fileList.empty()
  175. }
  176. },
  177. removeSharingOut() {
  178. if (this._outFileList) {
  179. this._outFileList.$fileList.empty()
  180. }
  181. },
  182. removeSharingLinks() {
  183. if (this._linkFileList) {
  184. this._linkFileList.$fileList.empty()
  185. }
  186. },
  187. removeSharingDeleted() {
  188. if (this._deletedFileList) {
  189. this._deletedFileList.$fileList.empty()
  190. }
  191. },
  192. removeSharingPending() {
  193. if (this._pendingFileList) {
  194. this._pendingFileList.$fileList.empty()
  195. }
  196. },
  197. removeSharingOverview() {
  198. if (this._overviewFileList) {
  199. this._overviewFileList.$fileList.empty()
  200. }
  201. },
  202. /**
  203. * Destroy the app
  204. */
  205. destroy() {
  206. OCA.Files.fileActions.off('setDefault.app-sharing', this._onActionsUpdated)
  207. OCA.Files.fileActions.off('registerAction.app-sharing', this._onActionsUpdated)
  208. this.removeSharingIn()
  209. this.removeSharingOut()
  210. this.removeSharingLinks()
  211. this._inFileList = null
  212. this._outFileList = null
  213. this._linkFileList = null
  214. this._overviewFileList = null
  215. delete this._globalActionsInitialized
  216. },
  217. _createFileActions() {
  218. // inherit file actions from the files app
  219. const fileActions = new OCA.Files.FileActions()
  220. // note: not merging the legacy actions because legacy apps are not
  221. // compatible with the sharing overview and need to be adapted first
  222. fileActions.registerDefaultActions()
  223. fileActions.merge(OCA.Files.fileActions)
  224. if (!this._globalActionsInitialized) {
  225. // in case actions are registered later
  226. this._onActionsUpdated = _.bind(this._onActionsUpdated, this)
  227. OCA.Files.fileActions.on('setDefault.app-sharing', this._onActionsUpdated)
  228. OCA.Files.fileActions.on('registerAction.app-sharing', this._onActionsUpdated)
  229. this._globalActionsInitialized = true
  230. }
  231. // when the user clicks on a folder, redirect to the corresponding
  232. // folder in the files app instead of opening it directly
  233. fileActions.register('dir', 'Open', OC.PERMISSION_READ, '', function(filename, context) {
  234. OCA.Files.App.setActiveView('files', { silent: true })
  235. OCA.Files.App.fileList.changeDirectory(OC.joinPaths(context.$file.attr('data-path'), filename), true, true)
  236. })
  237. fileActions.setDefault('dir', 'Open')
  238. return fileActions
  239. },
  240. _restoreShareAction() {
  241. const fileActions = new OCA.Files.FileActions()
  242. fileActions.registerAction({
  243. name: 'Restore',
  244. displayName: t('files_sharing', 'Restore'),
  245. altText: t('files_sharing', 'Restore share'),
  246. mime: 'all',
  247. permissions: OC.PERMISSION_ALL,
  248. iconClass: 'icon-history',
  249. type: OCA.Files.FileActions.TYPE_INLINE,
  250. actionHandler(fileName, context) {
  251. const shareId = context.$file.data('shareId')
  252. $.post(OC.linkToOCS('apps/files_sharing/api/v1/deletedshares', 2) + shareId)
  253. .success(function(result) {
  254. context.fileList.remove(context.fileInfoModel.attributes.name)
  255. }).fail(function() {
  256. OC.Notification.showTemporary(t('files_sharing', 'Something happened. Unable to restore the share.'))
  257. })
  258. },
  259. })
  260. return fileActions
  261. },
  262. _acceptShareAction() {
  263. const fileActions = new OCA.Files.FileActions()
  264. fileActions.registerAction({
  265. name: 'Accept share',
  266. displayName: t('files_sharing', 'Accept share'),
  267. mime: 'all',
  268. permissions: OC.PERMISSION_ALL,
  269. iconClass: 'icon-checkmark',
  270. type: OCA.Files.FileActions.TYPE_INLINE,
  271. actionHandler(fileName, context) {
  272. const shareId = context.$file.data('shareId')
  273. let shareBase = 'shares/pending'
  274. if (context.$file.attr('data-remote-id')) {
  275. shareBase = 'remote_shares/pending'
  276. }
  277. $.post(OC.linkToOCS('apps/files_sharing/api/v1/shares/pending', 2) + shareId)
  278. .success(function(result) {
  279. context.fileList.remove(context.fileInfoModel.attributes.name)
  280. }).fail(function() {
  281. OC.Notification.showTemporary(t('files_sharing', 'Something happened. Unable to accept the share.'))
  282. })
  283. },
  284. })
  285. fileActions.registerAction({
  286. name: 'Reject share',
  287. displayName: t('files_sharing', 'Reject share'),
  288. mime: 'all',
  289. permissions: OC.PERMISSION_ALL,
  290. iconClass: 'icon-close',
  291. type: OCA.Files.FileActions.TYPE_INLINE,
  292. shouldRender(context) {
  293. // disable rejecting group shares from the pending list because they anyway
  294. // land back into that same list
  295. if (context.$file.attr('data-remote-id') && parseInt(context.$file.attr('data-share-type'), 10) === OC.Share.SHARE_TYPE_REMOTE_GROUP) {
  296. return false
  297. }
  298. return true
  299. },
  300. actionHandler(fileName, context) {
  301. const shareId = context.$file.data('shareId')
  302. let shareBase = 'shares'
  303. if (context.$file.attr('data-remote-id')) {
  304. shareBase = 'remote_shares/pending'
  305. }
  306. $.ajax({
  307. url: OC.linkToOCS('apps/files_sharing/api/v1/shares', 2) + shareId,
  308. type: 'DELETE',
  309. }).success(function(result) {
  310. context.fileList.remove(context.fileInfoModel.attributes.name)
  311. }).fail(function() {
  312. OC.Notification.showTemporary(t('files_sharing', 'Something happened. Unable to reject the share.'))
  313. })
  314. },
  315. })
  316. return fileActions
  317. },
  318. _onActionsUpdated(ev) {
  319. _.each([this._inFileList, this._outFileList, this._linkFileList], function(list) {
  320. if (!list) {
  321. return
  322. }
  323. if (ev.action) {
  324. list.fileActions.registerAction(ev.action)
  325. } else if (ev.defaultAction) {
  326. list.fileActions.setDefault(
  327. ev.defaultAction.mime,
  328. ev.defaultAction.name
  329. )
  330. }
  331. })
  332. },
  333. _extendFileList(fileList) {
  334. // remove size column from summary
  335. fileList.fileSummary.$el.find('.filesize').remove()
  336. },
  337. }
  338. window.addEventListener('DOMContentLoaded', function() {
  339. $('#app-content-sharingin').on('show', function(e) {
  340. OCA.Sharing.App.initSharingIn($(e.target))
  341. })
  342. $('#app-content-sharingin').on('hide', function() {
  343. OCA.Sharing.App.removeSharingIn()
  344. })
  345. $('#app-content-sharingout').on('show', function(e) {
  346. OCA.Sharing.App.initSharingOut($(e.target))
  347. })
  348. $('#app-content-sharingout').on('hide', function() {
  349. OCA.Sharing.App.removeSharingOut()
  350. })
  351. $('#app-content-sharinglinks').on('show', function(e) {
  352. OCA.Sharing.App.initSharingLinks($(e.target))
  353. })
  354. $('#app-content-sharinglinks').on('hide', function() {
  355. OCA.Sharing.App.removeSharingLinks()
  356. })
  357. $('#app-content-deletedshares').on('show', function(e) {
  358. OCA.Sharing.App.initSharingDeleted($(e.target))
  359. })
  360. $('#app-content-deletedshares').on('hide', function() {
  361. OCA.Sharing.App.removeSharingDeleted()
  362. })
  363. $('#app-content-pendingshares').on('show', function(e) {
  364. OCA.Sharing.App.initSharingPening($(e.target))
  365. })
  366. $('#app-content-pendingshares').on('hide', function() {
  367. OCA.Sharing.App.removeSharingPending()
  368. })
  369. $('#app-content-shareoverview').on('show', function(e) {
  370. OCA.Sharing.App.initShareingOverview($(e.target))
  371. })
  372. $('#app-content-shareoverview').on('hide', function() {
  373. OCA.Sharing.App.removeSharingOverview()
  374. })
  375. })