app.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  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('.emptyfilelist.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('.emptyfilelist.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('.emptyfilelist.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('.emptyfilelist.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('.emptyfilelist.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. fileActions: this._createFileActions(),
  158. config: OCA.Files.App.getFilesConfig(),
  159. isOverview: true,
  160. // The file list is created when a "show" event is handled, so
  161. // it should be marked as "shown" like it would have been done
  162. // if handling the event with the file list already created.
  163. shown: true,
  164. }
  165. )
  166. this._extendFileList(this._overviewFileList)
  167. this._overviewFileList.appName = t('files_sharing', 'Shares')
  168. this._overviewFileList.$el.find('.emptyfilelist.emptycontent').html('<div class="icon-share"></div>'
  169. + '<h2>' + t('files_sharing', 'No shares') + '</h2>'
  170. + '<p>' + t('files_sharing', 'Shares will show up here') + '</p>')
  171. return this._overviewFileList
  172. },
  173. removeSharingIn() {
  174. if (this._inFileList) {
  175. this._inFileList.$fileList.empty()
  176. }
  177. },
  178. removeSharingOut() {
  179. if (this._outFileList) {
  180. this._outFileList.$fileList.empty()
  181. }
  182. },
  183. removeSharingLinks() {
  184. if (this._linkFileList) {
  185. this._linkFileList.$fileList.empty()
  186. }
  187. },
  188. removeSharingDeleted() {
  189. if (this._deletedFileList) {
  190. this._deletedFileList.$fileList.empty()
  191. }
  192. },
  193. removeSharingPending() {
  194. if (this._pendingFileList) {
  195. this._pendingFileList.$fileList.empty()
  196. }
  197. },
  198. removeSharingOverview() {
  199. if (this._overviewFileList) {
  200. this._overviewFileList.$fileList.empty()
  201. }
  202. },
  203. /**
  204. * Destroy the app
  205. */
  206. destroy() {
  207. OCA.Files.fileActions.off('setDefault.app-sharing', this._onActionsUpdated)
  208. OCA.Files.fileActions.off('registerAction.app-sharing', this._onActionsUpdated)
  209. this.removeSharingIn()
  210. this.removeSharingOut()
  211. this.removeSharingLinks()
  212. this._inFileList = null
  213. this._outFileList = null
  214. this._linkFileList = null
  215. this._overviewFileList = null
  216. delete this._globalActionsInitialized
  217. },
  218. _createFileActions() {
  219. // inherit file actions from the files app
  220. const fileActions = new OCA.Files.FileActions()
  221. // note: not merging the legacy actions because legacy apps are not
  222. // compatible with the sharing overview and need to be adapted first
  223. fileActions.registerDefaultActions()
  224. fileActions.merge(OCA.Files.fileActions)
  225. if (!this._globalActionsInitialized) {
  226. // in case actions are registered later
  227. this._onActionsUpdated = _.bind(this._onActionsUpdated, this)
  228. OCA.Files.fileActions.on('setDefault.app-sharing', this._onActionsUpdated)
  229. OCA.Files.fileActions.on('registerAction.app-sharing', this._onActionsUpdated)
  230. this._globalActionsInitialized = true
  231. }
  232. // when the user clicks on a folder, redirect to the corresponding
  233. // folder in the files app instead of opening it directly
  234. fileActions.register('dir', 'Open', OC.PERMISSION_READ, '', function(filename, context) {
  235. OCA.Files.App.setActiveView('files', { silent: true })
  236. OCA.Files.App.fileList.changeDirectory(OC.joinPaths(context.$file.attr('data-path'), filename), true, true)
  237. })
  238. fileActions.setDefault('dir', 'Open')
  239. return fileActions
  240. },
  241. _restoreShareAction() {
  242. const fileActions = new OCA.Files.FileActions()
  243. fileActions.registerAction({
  244. name: 'Restore',
  245. displayName: t('files_sharing', 'Restore'),
  246. altText: t('files_sharing', 'Restore share'),
  247. mime: 'all',
  248. permissions: OC.PERMISSION_ALL,
  249. iconClass: 'icon-history',
  250. type: OCA.Files.FileActions.TYPE_INLINE,
  251. actionHandler(fileName, context) {
  252. const shareId = context.$file.data('shareId')
  253. $.post(OC.linkToOCS('apps/files_sharing/api/v1/deletedshares', 2) + shareId)
  254. .success(function(result) {
  255. context.fileList.remove(context.fileInfoModel.attributes.name)
  256. }).fail(function() {
  257. OC.Notification.showTemporary(t('files_sharing', 'Something happened. Unable to restore the share.'))
  258. })
  259. },
  260. })
  261. return fileActions
  262. },
  263. _acceptShareAction() {
  264. const fileActions = new OCA.Files.FileActions()
  265. fileActions.registerAction({
  266. name: 'Accept share',
  267. displayName: t('files_sharing', 'Accept share'),
  268. mime: 'all',
  269. permissions: OC.PERMISSION_ALL,
  270. iconClass: 'icon-checkmark',
  271. type: OCA.Files.FileActions.TYPE_INLINE,
  272. actionHandler(fileName, context) {
  273. const shareId = context.$file.data('shareId')
  274. let shareBase = 'shares/pending'
  275. if (context.$file.attr('data-remote-id')) {
  276. shareBase = 'remote_shares/pending'
  277. }
  278. $.post(OC.linkToOCS('apps/files_sharing/api/v1/' + shareBase, 2) + shareId)
  279. .success(function(result) {
  280. context.fileList.remove(context.fileInfoModel.attributes.name)
  281. }).fail(function() {
  282. OC.Notification.showTemporary(t('files_sharing', 'Something happened. Unable to accept the share.'))
  283. })
  284. },
  285. })
  286. fileActions.registerAction({
  287. name: 'Reject share',
  288. displayName: t('files_sharing', 'Reject share'),
  289. mime: 'all',
  290. permissions: OC.PERMISSION_ALL,
  291. iconClass: 'icon-close',
  292. type: OCA.Files.FileActions.TYPE_INLINE,
  293. shouldRender(context) {
  294. // disable rejecting group shares from the pending list because they anyway
  295. // land back into that same list
  296. if (context.$file.attr('data-remote-id') && parseInt(context.$file.attr('data-share-type'), 10) === OC.Share.SHARE_TYPE_REMOTE_GROUP) {
  297. return false
  298. }
  299. return true
  300. },
  301. actionHandler(fileName, context) {
  302. const shareId = context.$file.data('shareId')
  303. let shareBase = 'shares'
  304. if (context.$file.attr('data-remote-id')) {
  305. shareBase = 'remote_shares'
  306. }
  307. $.ajax({
  308. url: OC.linkToOCS('apps/files_sharing/api/v1/' + shareBase, 2) + shareId,
  309. type: 'DELETE',
  310. }).success(function(result) {
  311. context.fileList.remove(context.fileInfoModel.attributes.name)
  312. }).fail(function() {
  313. OC.Notification.showTemporary(t('files_sharing', 'Something happened. Unable to reject the share.'))
  314. })
  315. },
  316. })
  317. return fileActions
  318. },
  319. _onActionsUpdated(ev) {
  320. _.each([this._inFileList, this._outFileList, this._linkFileList], function(list) {
  321. if (!list) {
  322. return
  323. }
  324. if (ev.action) {
  325. list.fileActions.registerAction(ev.action)
  326. } else if (ev.defaultAction) {
  327. list.fileActions.setDefault(
  328. ev.defaultAction.mime,
  329. ev.defaultAction.name
  330. )
  331. }
  332. })
  333. },
  334. _extendFileList(fileList) {
  335. // remove size column from summary
  336. fileList.fileSummary.$el.find('.filesize').remove()
  337. },
  338. }
  339. window.addEventListener('DOMContentLoaded', function() {
  340. $('#app-content-sharingin').on('show', function(e) {
  341. OCA.Sharing.App.initSharingIn($(e.target))
  342. })
  343. $('#app-content-sharingin').on('hide', function() {
  344. OCA.Sharing.App.removeSharingIn()
  345. })
  346. $('#app-content-sharingout').on('show', function(e) {
  347. OCA.Sharing.App.initSharingOut($(e.target))
  348. })
  349. $('#app-content-sharingout').on('hide', function() {
  350. OCA.Sharing.App.removeSharingOut()
  351. })
  352. $('#app-content-sharinglinks').on('show', function(e) {
  353. OCA.Sharing.App.initSharingLinks($(e.target))
  354. })
  355. $('#app-content-sharinglinks').on('hide', function() {
  356. OCA.Sharing.App.removeSharingLinks()
  357. })
  358. $('#app-content-deletedshares').on('show', function(e) {
  359. OCA.Sharing.App.initSharingDeleted($(e.target))
  360. })
  361. $('#app-content-deletedshares').on('hide', function() {
  362. OCA.Sharing.App.removeSharingDeleted()
  363. })
  364. $('#app-content-pendingshares').on('show', function(e) {
  365. OCA.Sharing.App.initSharingPening($(e.target))
  366. })
  367. $('#app-content-pendingshares').on('hide', function() {
  368. OCA.Sharing.App.removeSharingPending()
  369. })
  370. $('#app-content-shareoverview').on('show', function(e) {
  371. OCA.Sharing.App.initShareingOverview($(e.target))
  372. })
  373. $('#app-content-shareoverview').on('hide', function() {
  374. OCA.Sharing.App.removeSharingOverview()
  375. })
  376. })