From 3bdff6b3f57f627c66d2c8c26d4e5c79047b9a50 Mon Sep 17 00:00:00 2001 From: skjnldsv Date: Wed, 6 Aug 2025 15:46:56 +0200 Subject: [PATCH] fix(files): filter non batch actions in header Signed-off-by: skjnldsv --- .../FilesListTableHeaderActions.vue | 10 +++- cypress/e2e/files/files-actions.cy.ts | 47 +++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/apps/files/src/components/FilesListTableHeaderActions.vue b/apps/files/src/components/FilesListTableHeaderActions.vue index 6a808355c58..a4fe1b79078 100644 --- a/apps/files/src/components/FilesListTableHeaderActions.vue +++ b/apps/files/src/components/FilesListTableHeaderActions.vue @@ -151,6 +151,10 @@ export default defineComponent({ .filter(action => !action.renderInline) // We don't handle actions that are not visible .filter(action => action.default !== DefaultType.HIDDEN) + // We allow top-level actions that have no execBatch method + // but children actions always need to have it + .filter(action => action.execBatch || !action.parent) + // We filter out actions that are not enabled for the current selection .filter(action => !action.enabled || action.enabled(this.nodes, this.currentView)) .sort((a, b) => (a.order || 0) - (b.order || 0)) }, @@ -190,7 +194,11 @@ export default defineComponent({ }) // Generate list of all top-level actions ids - const childrenActionsIds = actions.filter(action => action.parent).map(action => action.parent) as string[] + const childrenActionsIds = actions + .filter(action => action.parent) + // Filter out all actions that are not batch actions + .filter(action => action.execBatch) + .map(action => action.parent) as string[] const menuActions = actions .filter(action => { diff --git a/cypress/e2e/files/files-actions.cy.ts b/cypress/e2e/files/files-actions.cy.ts index dbcf810e2a2..1f5d9f07225 100644 --- a/cypress/e2e/files/files-actions.cy.ts +++ b/cypress/e2e/files/files-actions.cy.ts @@ -213,4 +213,51 @@ describe('Files: Actions', { testIsolation: true }, () => { getSelectionActionEntry('nested-child-1').should('not.exist') getSelectionActionEntry('nested-child-2').should('not.exist') }) + + it('Do not show parent if nested action has no batch support', () => { + const parent = new FileAction({ + id: 'nested-action', + displayName: () => 'Nested Action', + exec: cy.spy(), + iconSvgInline: () => '', + }) + + const child1 = new FileAction({ + id: 'nested-child-1', + displayName: () => 'Nested Child 1', + exec: cy.spy(), + iconSvgInline: () => '', + parent: 'nested-action', + }) + + const child2 = new FileAction({ + id: 'nested-child-2', + displayName: () => 'Nested Child 2', + exec: cy.spy(), + iconSvgInline: () => '', + parent: 'nested-action', + }) + + cy.visit('/apps/files', { + // Cannot use registerFileAction here + onBeforeLoad: (win) => { + if (!win._nc_fileactions) win._nc_fileactions = [] + // Cannot use registerFileAction here + win._nc_fileactions.push(parent) + win._nc_fileactions.push(child1) + win._nc_fileactions.push(child2) + }, + }) + + selectRowForFile('image.jpg') + + // Open the menu + getSelectionActionButton().click({ force: true }) + + // Check we have the parent action but not the children + getSelectionActionEntry('nested-action').should('not.exist') + getSelectionActionEntry('menu-back').should('not.exist') + getSelectionActionEntry('nested-child-1').should('not.exist') + getSelectionActionEntry('nested-child-2').should('not.exist') + }) })