From 6f54f72bb40113662a9b906bebcf37393b45e9fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Molakvo=C3=A6?= Date: Thu, 6 Jul 2023 08:58:11 +0200 Subject: [PATCH] feat(sharing): add sharing overview view MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: John Molakvoæ --- apps/files_sharing/js/app.js | 24 +-- .../files_sharing/lib/AppInfo/Application.php | 14 +- .../lib/Controller/ShareAPIController.php | 14 +- .../src/actions/acceptShareAction.ts | 66 +++++++ .../src/actions/rejectShareAction.ts | 78 ++++++++ .../src/actions/restoreShareAction.ts | 65 +++++++ apps/files_sharing/src/{index.js => main.ts} | 8 +- .../src/services/SharingService.ts | 183 ++++++++++++++++++ apps/files_sharing/src/services/logger.ts | 27 +++ apps/files_sharing/src/views/shares.ts | 123 ++++++++++++ package-lock.json | 18 +- package.json | 2 +- webpack.modules.js | 2 +- 13 files changed, 592 insertions(+), 32 deletions(-) create mode 100644 apps/files_sharing/src/actions/acceptShareAction.ts create mode 100644 apps/files_sharing/src/actions/rejectShareAction.ts create mode 100644 apps/files_sharing/src/actions/restoreShareAction.ts rename apps/files_sharing/src/{index.js => main.ts} (84%) create mode 100644 apps/files_sharing/src/services/SharingService.ts create mode 100644 apps/files_sharing/src/services/logger.ts create mode 100644 apps/files_sharing/src/views/shares.ts diff --git a/apps/files_sharing/js/app.js b/apps/files_sharing/js/app.js index b9a60c73dab..9435ceb80c3 100644 --- a/apps/files_sharing/js/app.js +++ b/apps/files_sharing/js/app.js @@ -370,40 +370,40 @@ OCA.Sharing.App = { } window.addEventListener('DOMContentLoaded', function() { - $('#app-content-sharingin').on('show', function(e) { + $('#app-content-sharinginOld').on('show', function(e) { OCA.Sharing.App.initSharingIn($(e.target)) }) - $('#app-content-sharingin').on('hide', function() { + $('#app-content-sharinginOld').on('hide', function() { OCA.Sharing.App.removeSharingIn() }) - $('#app-content-sharingout').on('show', function(e) { + $('#app-content-sharingoutOld').on('show', function(e) { OCA.Sharing.App.initSharingOut($(e.target)) }) - $('#app-content-sharingout').on('hide', function() { + $('#app-content-sharingoutOld').on('hide', function() { OCA.Sharing.App.removeSharingOut() }) - $('#app-content-sharinglinks').on('show', function(e) { + $('#app-content-sharinglinksOld').on('show', function(e) { OCA.Sharing.App.initSharingLinks($(e.target)) }) - $('#app-content-sharinglinks').on('hide', function() { + $('#app-content-sharinglinksOld').on('hide', function() { OCA.Sharing.App.removeSharingLinks() }) - $('#app-content-deletedshares').on('show', function(e) { + $('#app-content-deletedsharesOld').on('show', function(e) { OCA.Sharing.App.initSharingDeleted($(e.target)) }) - $('#app-content-deletedshares').on('hide', function() { + $('#app-content-deletedsharesOld').on('hide', function() { OCA.Sharing.App.removeSharingDeleted() }) - $('#app-content-pendingshares').on('show', function(e) { + $('#app-content-pendingsharesOld').on('show', function(e) { OCA.Sharing.App.initSharingPening($(e.target)) }) - $('#app-content-pendingshares').on('hide', function() { + $('#app-content-pendingsharesOld').on('hide', function() { OCA.Sharing.App.removeSharingPending() }) - $('#app-content-shareoverview').on('show', function(e) { + $('#app-content-shareoverviewOld').on('show', function(e) { OCA.Sharing.App.initShareingOverview($(e.target)) }) - $('#app-content-shareoverview').on('hide', function() { + $('#app-content-shareoverviewOld').on('hide', function() { OCA.Sharing.App.removeSharingOverview() }) }) diff --git a/apps/files_sharing/lib/AppInfo/Application.php b/apps/files_sharing/lib/AppInfo/Application.php index eff4a3ac5b7..9051d123f1e 100644 --- a/apps/files_sharing/lib/AppInfo/Application.php +++ b/apps/files_sharing/lib/AppInfo/Application.php @@ -231,7 +231,7 @@ class Application extends App implements IBootstrap { if ($shareManager->sharingDisabledForUser($userId) === false) { $sharingSublistArray[] = [ - 'id' => 'sharingout', + 'id' => 'sharingoutOld', 'appname' => 'files_sharing', 'script' => 'list.php', 'order' => 16, @@ -240,7 +240,7 @@ class Application extends App implements IBootstrap { } $sharingSublistArray[] = [ - 'id' => 'sharingin', + 'id' => 'sharinginOld', 'appname' => 'files_sharing', 'script' => 'list.php', 'order' => 15, @@ -251,7 +251,7 @@ class Application extends App implements IBootstrap { // Check if sharing by link is enabled if ($shareManager->shareApiAllowLinks()) { $sharingSublistArray[] = [ - 'id' => 'sharinglinks', + 'id' => 'sharinglinksOld', 'appname' => 'files_sharing', 'script' => 'list.php', 'order' => 17, @@ -261,7 +261,7 @@ class Application extends App implements IBootstrap { } $sharingSublistArray[] = [ - 'id' => 'deletedshares', + 'id' => 'deletedsharesOld', 'appname' => 'files_sharing', 'script' => 'list.php', 'order' => 19, @@ -269,7 +269,7 @@ class Application extends App implements IBootstrap { ]; $sharingSublistArray[] = [ - 'id' => 'pendingshares', + 'id' => 'pendingsharesOld', 'appname' => 'files_sharing', 'script' => 'list.php', 'order' => 19, @@ -277,11 +277,11 @@ class Application extends App implements IBootstrap { ]; return [ - 'id' => 'shareoverview', + 'id' => 'shareoverviewOld', 'appname' => 'files_sharing', 'script' => 'list.php', 'order' => 18, - 'name' => $l->t('Shares'), + 'name' => $l->t('Shares (old)'), 'classes' => 'collapsible', 'sublist' => $sharingSublistArray, ]; diff --git a/apps/files_sharing/lib/Controller/ShareAPIController.php b/apps/files_sharing/lib/Controller/ShareAPIController.php index e2fb950dceb..e80412f18b4 100644 --- a/apps/files_sharing/lib/Controller/ShareAPIController.php +++ b/apps/files_sharing/lib/Controller/ShareAPIController.php @@ -182,6 +182,11 @@ class ShareAPIController extends OCSController { $sharedBy = $this->userManager->get($share->getSharedBy()); $shareOwner = $this->userManager->get($share->getShareOwner()); + $isOwnShare = false; + if ($shareOwner !== null) { + $isOwnShare = $shareOwner->getUID() === $this->currentUser; + } + $result = [ 'id' => $share->getId(), 'share_type' => $share->getShareType(), @@ -225,6 +230,11 @@ class ShareAPIController extends OCSController { $result['item_type'] = 'file'; } + // Get the original node permission if the share owner is the current user + if ($isOwnShare) { + $result['permissions'] = $node->getPermissions(); + } + $result['mimetype'] = $node->getMimetype(); $result['has_preview'] = $this->previewManager->isAvailable($node); $result['storage_id'] = $node->getStorage()->getId(); @@ -233,6 +243,8 @@ class ShareAPIController extends OCSController { $result['file_source'] = $node->getId(); $result['file_parent'] = $node->getParent()->getId(); $result['file_target'] = $share->getTarget(); + $result['size'] = $node->getSize(); + $result['mtime'] = $node->getMTime(); $expiration = $share->getExpirationDate(); if ($expiration !== null) { @@ -1423,7 +1435,7 @@ class ShareAPIController extends OCSController { try { $formattedShare = $this->formatShare($share, $node); $formattedShare['status'] = $share->getStatus(); - $formattedShare['path'] = $share->getNode()->getName(); + $formattedShare['path'] = '/' . $share->getNode()->getName(); $formattedShare['permissions'] = 0; return $formattedShare; } catch (NotFoundException $e) { diff --git a/apps/files_sharing/src/actions/acceptShareAction.ts b/apps/files_sharing/src/actions/acceptShareAction.ts new file mode 100644 index 00000000000..8cdc138ca81 --- /dev/null +++ b/apps/files_sharing/src/actions/acceptShareAction.ts @@ -0,0 +1,66 @@ +/** + * @copyright Copyright (c) 2023 John Molakvoæ + * + * @author John Molakvoæ + * + * @license AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +import type { Node } from '@nextcloud/files' +import type { Navigation } from '../../../files/src/services/Navigation' + +import { generateOcsUrl } from '@nextcloud/router' +import { registerFileAction, FileAction } from '@nextcloud/files' +import { translatePlural as n } from '@nextcloud/l10n' +import axios from '@nextcloud/axios' +import CheckSvg from '@mdi/svg/svg/check.svg?raw' + +import { pendingSharesViewId } from '../views/shares' +import { emit } from '@nextcloud/event-bus' + +export const action = new FileAction({ + id: 'accept-share', + displayName: (nodes: Node[]) => n('files_sharing', 'Accept share', 'Accept shares', nodes.length), + iconSvgInline: () => CheckSvg, + + enabled: (files, view) => view.id === pendingSharesViewId, + + async exec(node: Node) { + try { + const isRemote = !!node.attributes.remote + const url = generateOcsUrl('apps/files_sharing/api/v1/{shareBase}/pending/{id}', { + shareBase: isRemote ? 'remote_shares' : 'shares', + id: node.attributes.id, + }) + await axios.post(url) + + // Remove from current view + emit('files:node:deleted', node) + + return true + } catch (error) { + return false + } + }, + async execBatch(nodes: Node[], view: Navigation, dir: string) { + return Promise.all(nodes.map(node => this.exec(node, view, dir))) + }, + + order: 1, + inline: () => true, +}) + +registerFileAction(action) diff --git a/apps/files_sharing/src/actions/rejectShareAction.ts b/apps/files_sharing/src/actions/rejectShareAction.ts new file mode 100644 index 00000000000..3d14896738a --- /dev/null +++ b/apps/files_sharing/src/actions/rejectShareAction.ts @@ -0,0 +1,78 @@ +/** + * @copyright Copyright (c) 2023 John Molakvoæ + * + * @author John Molakvoæ + * + * @license AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +import type { Node } from '@nextcloud/files' +import type { Navigation } from '../../../files/src/services/Navigation' + +import { emit } from '@nextcloud/event-bus' +import { generateOcsUrl } from '@nextcloud/router' +import { registerFileAction, FileAction } from '@nextcloud/files' +import { translatePlural as n } from '@nextcloud/l10n' +import axios from '@nextcloud/axios' +import CloseSvg from '@mdi/svg/svg/close.svg?raw' + +import { pendingSharesViewId } from '../views/shares' + +export const action = new FileAction({ + id: 'reject-share', + displayName: (nodes: Node[]) => n('files_sharing', 'Reject share', 'Reject shares', nodes.length), + iconSvgInline: () => CloseSvg, + + enabled: (nodes, view) => { + if (view.id !== pendingSharesViewId) { + return false + } + + // disable rejecting group shares from the pending list because they anyway + // land back into that same list after rejecting them + if (nodes.some(node => node.attributes.remote_id + && node.attributes.share_type === window.OC.Share.SHARE_TYPE_REMOTE_GROUP)) { + return false + } + return true + }, + + async exec(node: Node) { + try { + const isRemote = !!node.attributes.remote + const url = generateOcsUrl('apps/files_sharing/api/v1/{shareBase}/{id}', { + shareBase: isRemote ? 'remote_shares' : 'shares', + id: node.attributes.id, + }) + await axios.delete(url) + + // Remove from current view + emit('files:node:deleted', node) + + return true + } catch (error) { + return false + } + }, + async execBatch(nodes: Node[], view: Navigation, dir: string) { + return Promise.all(nodes.map(node => this.exec(node, view, dir))) + }, + + order: 2, + inline: () => true, +}) + +registerFileAction(action) diff --git a/apps/files_sharing/src/actions/restoreShareAction.ts b/apps/files_sharing/src/actions/restoreShareAction.ts new file mode 100644 index 00000000000..8e5a49a12b6 --- /dev/null +++ b/apps/files_sharing/src/actions/restoreShareAction.ts @@ -0,0 +1,65 @@ +/** + * @copyright Copyright (c) 2023 John Molakvoæ + * + * @author John Molakvoæ + * + * @license AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +import type { Node } from '@nextcloud/files' +import type { Navigation } from '../../../files/src/services/Navigation' + +import { generateOcsUrl } from '@nextcloud/router' +import { registerFileAction, FileAction } from '@nextcloud/files' +import { translatePlural as n } from '@nextcloud/l10n' +import axios from '@nextcloud/axios' +import ArrowULeftTopSvg from '@mdi/svg/svg/arrow-u-left-top.svg?raw' + +import { deletedSharesViewId } from '../views/shares' +import { emit } from '@nextcloud/event-bus' + +export const action = new FileAction({ + id: 'restore-share', + displayName: (nodes: Node[]) => n('files_sharing', 'Restore share', 'Restore shares', nodes.length), + + iconSvgInline: () => ArrowULeftTopSvg, + + enabled: (nodes, view) => view.id === deletedSharesViewId, + + async exec(node: Node) { + try { + const url = generateOcsUrl('apps/files_sharing/api/v1/deletedshares/{id}', { + id: node.attributes.id, + }) + await axios.post(url) + + // Remove from current view + emit('files:node:deleted', node) + + return true + } catch (error) { + return false + } + }, + async execBatch(nodes: Node[], view: Navigation, dir: string) { + return Promise.all(nodes.map(node => this.exec(node, view, dir))) + }, + + order: 1, + inline: () => true, +}) + +registerFileAction(action) diff --git a/apps/files_sharing/src/index.js b/apps/files_sharing/src/main.ts similarity index 84% rename from apps/files_sharing/src/index.js rename to apps/files_sharing/src/main.ts index 95ed017bbf9..c1d91bb470d 100644 --- a/apps/files_sharing/src/index.js +++ b/apps/files_sharing/src/main.ts @@ -20,9 +20,13 @@ * along with this program. If not, see . * */ +import './actions/acceptShareAction' +import './actions/rejectShareAction' +import './actions/restoreShareAction' +import registerSharingViews from './views/shares' // register default shares types -Object.assign(OC, { +Object.assign(window.OC, { Share: { SHARE_TYPE_USER: 0, SHARE_TYPE_GROUP: 1, @@ -37,3 +41,5 @@ Object.assign(OC, { SHARE_TYPE_SCIENCEMESH: 15, }, }) + +registerSharingViews() diff --git a/apps/files_sharing/src/services/SharingService.ts b/apps/files_sharing/src/services/SharingService.ts new file mode 100644 index 00000000000..036eae07bce --- /dev/null +++ b/apps/files_sharing/src/services/SharingService.ts @@ -0,0 +1,183 @@ +/** + * @copyright Copyright (c) 2023 John Molakvoæ + * + * @author John Molakvoæ + * + * @license AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +/* eslint-disable camelcase, n/no-extraneous-import */ +import type { AxiosPromise } from 'axios' +import type { ContentsWithRoot } from '../../../files/src/services/Navigation' + +import { Folder, File } from '@nextcloud/files' +import { generateOcsUrl, generateRemoteUrl, generateUrl } from '@nextcloud/router' +import { getCurrentUser } from '@nextcloud/auth' +import { rootPath } from '../../../files/src/services/WebdavClient' +import axios from '@nextcloud/axios' +import logger from './logger' + +type OCSResponse = { + ocs: { + meta: { + status: string + statuscode: number + message: string + }, + data: [] + } +} + +const headers = { + 'Content-Type': 'application/json', +} + +const ocsEntryToNode = function(ocsEntry: any): Folder | File | null { + try { + const Node = ocsEntry?.item_type === 'folder' ? Folder : File + + // Sometimes it's an int, sometimes it contains the identifier like "ocinternal:123" + const fileid = ocsEntry.file_source + const previewUrl = generateUrl('/core/preview?fileId={fileid}&x=32&y=32&forceIcon=0', { fileid }) + + // Generate path and strip double slashes + const path = ocsEntry?.path || ocsEntry.file_target + const source = generateRemoteUrl(`dav/${rootPath}/${path}`.replace(/\/\//, '/')) + + // Prefer share time if more recent than mtime + let mtime = ocsEntry?.mtime ? new Date((ocsEntry.mtime) * 1000) : undefined + if (ocsEntry?.stime > (ocsEntry?.mtime || 0)) { + mtime = new Date((ocsEntry.stime) * 1000) + } + + return new Node({ + id: fileid, + source, + owner: ocsEntry?.uid_owner, + mime: ocsEntry?.mimetype, + mtime, + size: ocsEntry?.size || undefined, + permissions: ocsEntry?.permissions, + root: rootPath, + attributes: { + ...ocsEntry, + previewUrl, + favorite: ocsEntry?.tags?.includes(window.OC.TAG_FAVORITE) ? 1 : 0, + }, + }) + } catch (error) { + logger.error('Error while parsing OCS entry', error) + return null + } +} + +const getShares = function(shared_with_me = false): AxiosPromise { + const url = generateOcsUrl('apps/files_sharing/api/v1/shares') + return axios({ + url, + headers, + params: { + shared_with_me, + include_tags: true, + }, + }) +} + +const getSharedWithYou = function(): AxiosPromise { + return getShares(true) +} + +const getSharedWithOthers = function(): AxiosPromise { + return getShares(false) +} + +const getRemoteShares = function(): AxiosPromise { + const url = generateOcsUrl('apps/files_sharing/api/v1/remote_shares') + return axios({ + url, + headers, + params: { + include_tags: true, + }, + }) +} + +const getPendingShares = function(): AxiosPromise { + const url = generateOcsUrl('apps/files_sharing/api/v1/shares/pending') + return axios({ + url, + headers, + params: { + include_tags: true, + }, + }) +} + +const getRemotePendingShares = function(): AxiosPromise { + const url = generateOcsUrl('apps/files_sharing/api/v1/remote_shares/pending') + return axios({ + url, + headers, + params: { + include_tags: true, + }, + }) +} + +const getDeletedShares = function(): AxiosPromise { + const url = generateOcsUrl('apps/files_sharing/api/v1/deletedshares') + return axios({ + url, + headers, + params: { + include_tags: true, + }, + }) +} + +export const getContents = async (sharedWithYou = true, sharedWithOthers = true, pendingShares = false, deletedshares = false, filterTypes: number[] = []): Promise => { + const promises = [] as AxiosPromise[] + + if (sharedWithYou) { + promises.push(getSharedWithYou(), getRemoteShares()) + } + if (sharedWithOthers) { + promises.push(getSharedWithOthers()) + } + if (pendingShares) { + promises.push(getPendingShares(), getRemotePendingShares()) + } + if (deletedshares) { + promises.push(getDeletedShares()) + } + + const responses = await Promise.all(promises) + const data = responses.map((response) => response.data.ocs.data).flat() + let contents = data.map(ocsEntryToNode).filter((node) => node !== null) as (Folder | File)[] + + if (filterTypes.length > 0) { + contents = contents.filter((node) => filterTypes.includes(node.attributes?.share_type)) + } + + return { + folder: new Folder({ + id: 0, + source: generateRemoteUrl('dav' + rootPath), + owner: getCurrentUser()?.uid || '', + }), + contents, + } +} diff --git a/apps/files_sharing/src/services/logger.ts b/apps/files_sharing/src/services/logger.ts new file mode 100644 index 00000000000..19be888bf1f --- /dev/null +++ b/apps/files_sharing/src/services/logger.ts @@ -0,0 +1,27 @@ +/** + * @copyright Copyright (c) 2022 John Molakvoæ + * + * @author John Molakvoæ + * + * @license AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +import { getLoggerBuilder } from '@nextcloud/logger' + +export default getLoggerBuilder() + .setApp('files_sharing') + .detectUser() + .build() diff --git a/apps/files_sharing/src/views/shares.ts b/apps/files_sharing/src/views/shares.ts new file mode 100644 index 00000000000..4afc9c07ef5 --- /dev/null +++ b/apps/files_sharing/src/views/shares.ts @@ -0,0 +1,123 @@ +/** + * @copyright Copyright (c) 2023 John Molakvoæ + * + * @author John Molakvoæ + * + * @license AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +import type NavigationService from '../../../files/src/services/Navigation' +import type { Navigation } from '../../../files/src/services/Navigation' + +import { translate as t } from '@nextcloud/l10n' +import AccountClockSvg from '@mdi/svg/svg/account-clock.svg?raw' +import AccountGroupSvg from '@mdi/svg/svg/account-group.svg?raw' +import AccountSvg from '@mdi/svg/svg/account.svg?raw' +import DeleteSvg from '@mdi/svg/svg/delete.svg?raw' +import LinkSvg from '@mdi/svg/svg/link.svg?raw' +import ShareVariantSvg from '@mdi/svg/svg/share-variant.svg?raw' + +import { getContents } from '../services/SharingService' + +export const sharesViewId = 'shareoverview' +export const pendingSharesViewId = 'pendingshares' +export const deletedSharesViewId = 'deletedshares' + +export default () => { + const Navigation = window.OCP.Files.Navigation as NavigationService + Navigation.register({ + id: sharesViewId, + name: t('files_sharing', 'Shares'), + caption: t('files_sharing', 'Overview of shared files.'), + + icon: ShareVariantSvg, + order: 20, + + columns: [], + + getContents: () => getContents(), + } as Navigation) + + Navigation.register({ + id: 'sharingin', + name: t('files_sharing', 'Shared with you'), + caption: t('files_sharing', 'List of files that are shared with you.'), + + icon: AccountSvg, + order: 20, + parent: sharesViewId, + + columns: [], + + getContents: () => getContents(true, false, false, false), + } as Navigation) + + Navigation.register({ + id: 'sharingout', + name: t('files_sharing', 'Shared with others'), + caption: t('files_sharing', 'List of files that you shared with others.'), + + icon: AccountGroupSvg, + order: 20, + parent: sharesViewId, + + columns: [], + + getContents: () => getContents(false, true, false, false), + } as Navigation) + + Navigation.register({ + id: 'sharinglinks', + name: t('files_sharing', 'Shared by link'), + caption: t('files_sharing', 'List of files that you shared with a share link.'), + + icon: LinkSvg, + order: 20, + parent: sharesViewId, + + columns: [], + + getContents: () => getContents(false, true, false, false, [window.OC.Share.SHARE_TYPE_LINK]), + } as Navigation) + + Navigation.register({ + id: deletedSharesViewId, + name: t('files_sharing', 'Deleted shares'), + caption: t('files_sharing', 'List of shares that you removed yourself from.'), + + icon: DeleteSvg, + order: 20, + parent: sharesViewId, + + columns: [], + + getContents: () => getContents(false, false, false, true), + } as Navigation) + + Navigation.register({ + id: 'pendingshares', + name: t('files_sharing', 'Pending shares'), + caption: t('files_sharing', 'List of unapproved shares.'), + + icon: AccountClockSvg, + order: 20, + parent: sharesViewId, + + columns: [], + + getContents: () => getContents(false, false, true, false), + } as Navigation) +} diff --git a/package-lock.json b/package-lock.json index 8dcb27537bd..1a41edc78ae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,7 @@ "@nextcloud/capabilities": "^1.0.4", "@nextcloud/dialogs": "^4.1.0", "@nextcloud/event-bus": "^3.1.0", - "@nextcloud/files": "^3.0.0-beta.10", + "@nextcloud/files": "^3.0.0-beta.11", "@nextcloud/initial-state": "^2.0.0", "@nextcloud/l10n": "^2.1.0", "@nextcloud/logger": "^2.5.0", @@ -3711,17 +3711,17 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/@nextcloud/files": { - "version": "3.0.0-beta.10", - "resolved": "https://registry.npmjs.org/@nextcloud/files/-/files-3.0.0-beta.10.tgz", - "integrity": "sha512-cAh2HWkFgktub/GW07qx/kYz9nR2E/D+Zk/qXF8JW7BL/+gNy4/wOJ7mfDisUZy0gCZKZTV0v5wtEkIHwNdTyA==", + "version": "3.0.0-beta.11", + "resolved": "https://registry.npmjs.org/@nextcloud/files/-/files-3.0.0-beta.11.tgz", + "integrity": "sha512-eYPtUo+pBAvY8H0pSDyBJrpUKWILIadOmPVoHKpwOFwljNN3xh+AeT1ofT3oJI6ALfrKD/lDTe18BKU8uhLADA==", "dependencies": { "@nextcloud/auth": "^2.0.0", "@nextcloud/l10n": "^2.1.0", "@nextcloud/logger": "^2.5.0" }, "engines": { - "node": "^16.0.0", - "npm": "^7.0.0 || ^8.0.0" + "node": "^20.0.0", + "npm": "^9.0.0" } }, "node_modules/@nextcloud/initial-state": { @@ -29869,9 +29869,9 @@ } }, "@nextcloud/files": { - "version": "3.0.0-beta.10", - "resolved": "https://registry.npmjs.org/@nextcloud/files/-/files-3.0.0-beta.10.tgz", - "integrity": "sha512-cAh2HWkFgktub/GW07qx/kYz9nR2E/D+Zk/qXF8JW7BL/+gNy4/wOJ7mfDisUZy0gCZKZTV0v5wtEkIHwNdTyA==", + "version": "3.0.0-beta.11", + "resolved": "https://registry.npmjs.org/@nextcloud/files/-/files-3.0.0-beta.11.tgz", + "integrity": "sha512-eYPtUo+pBAvY8H0pSDyBJrpUKWILIadOmPVoHKpwOFwljNN3xh+AeT1ofT3oJI6ALfrKD/lDTe18BKU8uhLADA==", "requires": { "@nextcloud/auth": "^2.0.0", "@nextcloud/l10n": "^2.1.0", diff --git a/package.json b/package.json index 05bd3d78044..d2f789a0f03 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "@nextcloud/capabilities": "^1.0.4", "@nextcloud/dialogs": "^4.1.0", "@nextcloud/event-bus": "^3.1.0", - "@nextcloud/files": "^3.0.0-beta.10", + "@nextcloud/files": "^3.0.0-beta.11", "@nextcloud/initial-state": "^2.0.0", "@nextcloud/l10n": "^2.1.0", "@nextcloud/logger": "^2.5.0", diff --git a/webpack.modules.js b/webpack.modules.js index 4bc14dbead8..fe24a391984 100644 --- a/webpack.modules.js +++ b/webpack.modules.js @@ -59,7 +59,7 @@ module.exports = { collaboration: path.join(__dirname, 'apps/files_sharing/src', 'collaborationresourceshandler.js'), files_sharing_tab: path.join(__dirname, 'apps/files_sharing/src', 'files_sharing_tab.js'), files_sharing: path.join(__dirname, 'apps/files_sharing/src', 'files_sharing.js'), - main: path.join(__dirname, 'apps/files_sharing/src', 'index.js'), + main: path.join(__dirname, 'apps/files_sharing/src', 'main.ts'), 'personal-settings': path.join(__dirname, 'apps/files_sharing/src', 'personal-settings.js'), }, files_trashbin: {