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.

newFolder.ts 3.0KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. /**
  2. * @copyright Copyright (c) 2023 John Molakvoæ <skjnldsv@protonmail.com>
  3. *
  4. * @author John Molakvoæ <skjnldsv@protonmail.com>
  5. *
  6. * @license AGPL-3.0-or-later
  7. *
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU Affero General Public License as
  10. * published by the Free Software Foundation, either version 3 of the
  11. * License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU Affero General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Affero General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. *
  21. */
  22. import type { Entry, Node } from '@nextcloud/files'
  23. import { basename } from 'path'
  24. import { emit } from '@nextcloud/event-bus'
  25. import { getCurrentUser } from '@nextcloud/auth'
  26. import { Permission, Folder } from '@nextcloud/files'
  27. import { showSuccess } from '@nextcloud/dialogs'
  28. import { translate as t } from '@nextcloud/l10n'
  29. import axios from '@nextcloud/axios'
  30. import FolderPlusSvg from '@mdi/svg/svg/folder-plus.svg?raw'
  31. import { newNodeName } from '../utils/newNodeDialog'
  32. import logger from '../logger'
  33. type createFolderResponse = {
  34. fileid: number
  35. source: string
  36. }
  37. const createNewFolder = async (root: Folder, name: string): Promise<createFolderResponse> => {
  38. const source = root.source + '/' + name
  39. const encodedSource = root.encodedSource + '/' + encodeURIComponent(name)
  40. const response = await axios({
  41. method: 'MKCOL',
  42. url: encodedSource,
  43. headers: {
  44. Overwrite: 'F',
  45. },
  46. })
  47. return {
  48. fileid: parseInt(response.headers['oc-fileid']),
  49. source,
  50. }
  51. }
  52. export const entry = {
  53. id: 'newFolder',
  54. displayName: t('files', 'New folder'),
  55. enabled: (context: Folder) => (context.permissions & Permission.CREATE) !== 0,
  56. iconSvgInline: FolderPlusSvg,
  57. order: 0,
  58. async handler(context: Folder, content: Node[]) {
  59. const name = await newNodeName(t('files', 'New folder'), content)
  60. if (name !== null) {
  61. const { fileid, source } = await createNewFolder(context, name)
  62. // Create the folder in the store
  63. const folder = new Folder({
  64. source,
  65. id: fileid,
  66. mtime: new Date(),
  67. owner: getCurrentUser()?.uid || null,
  68. permissions: Permission.ALL,
  69. root: context?.root || '/files/' + getCurrentUser()?.uid,
  70. // Include mount-type from parent folder as this is inherited
  71. attributes: {
  72. 'mount-type': context.attributes?.['mount-type'],
  73. 'owner-id': context.attributes?.['owner-id'],
  74. 'owner-display-name': context.attributes?.['owner-display-name'],
  75. },
  76. })
  77. showSuccess(t('files', 'Created new folder "{name}"', { name: basename(source) }))
  78. logger.debug('Created new folder', { folder, source })
  79. emit('files:node:created', folder)
  80. window.OCP.Files.Router.goToRoute(
  81. null, // use default route
  82. { view: 'files', fileid: folder.fileid },
  83. { dir: context.path },
  84. )
  85. }
  86. },
  87. } as Entry