From 31c21c779723fb6efbe6aa89b2093091c5d3e187 Mon Sep 17 00:00:00 2001 From: provokateurin Date: Tue, 7 Jan 2025 17:02:43 +0100 Subject: feat(files_trashbin): Allow preventing trash to be deleted permanently Signed-off-by: provokateurin --- apps/files/src/actions/deleteAction.spec.ts | 25 +++++++++++++++++++++++++ apps/files/src/actions/deleteAction.ts | 8 ++++++++ apps/files/src/services/HotKeysService.spec.ts | 16 +++++++++++++++- 3 files changed, 48 insertions(+), 1 deletion(-) (limited to 'apps/files') diff --git a/apps/files/src/actions/deleteAction.spec.ts b/apps/files/src/actions/deleteAction.spec.ts index 224b196d364..4ed625b2412 100644 --- a/apps/files/src/actions/deleteAction.spec.ts +++ b/apps/files/src/actions/deleteAction.spec.ts @@ -127,6 +127,22 @@ describe('Delete action conditions tests', () => { }) describe('Delete action enabled tests', () => { + let initialState: HTMLInputElement + + afterEach(() => { + document.body.removeChild(initialState) + }) + + beforeEach(() => { + initialState = document.createElement('input') + initialState.setAttribute('type', 'hidden') + initialState.setAttribute('id', 'initial-state-files_trashbin-config') + initialState.setAttribute('value', btoa(JSON.stringify({ + allow_delete: true, + }))) + document.body.appendChild(initialState) + }) + test('Enabled with DELETE permissions', () => { const file = new File({ id: 1, @@ -177,6 +193,15 @@ describe('Delete action enabled tests', () => { expect(action.enabled!([folder2], view)).toBe(false) expect(action.enabled!([folder1, folder2], view)).toBe(false) }) + + test('Disabled if not allowed', () => { + initialState.setAttribute('value', btoa(JSON.stringify({ + allow_delete: false, + }))) + + expect(action.enabled).toBeDefined() + expect(action.enabled!([], view)).toBe(false) + }) }) describe('Delete action execute tests', () => { diff --git a/apps/files/src/actions/deleteAction.ts b/apps/files/src/actions/deleteAction.ts index 8d8aa4f9deb..8b3f45196e9 100644 --- a/apps/files/src/actions/deleteAction.ts +++ b/apps/files/src/actions/deleteAction.ts @@ -2,6 +2,9 @@ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later */ +import type { FilesTrashbinConfigState } from '../../../files_trashbin/src/fileListActions/emptyTrashAction.ts' + +import { loadState } from '@nextcloud/initial-state' import { Permission, Node, View, FileAction } from '@nextcloud/files' import { showInfo } from '@nextcloud/dialogs' import { translate as t } from '@nextcloud/l10n' @@ -34,6 +37,11 @@ export const action = new FileAction({ }, enabled(nodes: Node[]) { + const config = loadState('files_trashbin', 'config') + if (!config.allow_delete) { + return false + } + return nodes.length > 0 && nodes .map(node => node.permissions) .every(permission => (permission & Permission.DELETE) !== 0) diff --git a/apps/files/src/services/HotKeysService.spec.ts b/apps/files/src/services/HotKeysService.spec.ts index dfe9f66601b..3bfdac0bc32 100644 --- a/apps/files/src/services/HotKeysService.spec.ts +++ b/apps/files/src/services/HotKeysService.spec.ts @@ -2,7 +2,7 @@ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later */ -import { describe, it, vi, expect, beforeEach, beforeAll } from 'vitest' +import { describe, it, vi, expect, beforeEach, beforeAll, afterEach } from 'vitest' import { File, Permission, View } from '@nextcloud/files' import axios from '@nextcloud/axios' @@ -33,6 +33,12 @@ describe('HotKeysService testing', () => { const goToRouteMock = vi.fn() + let initialState: HTMLInputElement + + afterEach(() => { + document.body.removeChild(initialState) + }) + beforeAll(() => { registerHotkeys() }) @@ -57,6 +63,14 @@ describe('HotKeysService testing', () => { window.OCA = { Files: { Sidebar: { open: () => {}, setActiveTab: () => {} } } } // @ts-expect-error We only mock what needed, we do not need Files.Router.goTo or Files.Navigation window.OCP = { Files: { Router: { goToRoute: goToRouteMock, params: {}, query: {} } } } + + initialState = document.createElement('input') + initialState.setAttribute('type', 'hidden') + initialState.setAttribute('id', 'initial-state-files_trashbin-config') + initialState.setAttribute('value', btoa(JSON.stringify({ + allow_delete: true, + }))) + document.body.appendChild(initialState) }) it('Pressing d should open the sidebar once', () => { -- cgit v1.2.3