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')
+ })
})