diff --git a/apps/files/src/components/FileEntry.vue b/apps/files/src/components/FileEntry.vue index 87c36356210..7ff6186a6e3 100644 --- a/apps/files/src/components/FileEntry.vue +++ b/apps/files/src/components/FileEntry.vue @@ -86,44 +86,14 @@ - - - - - - - - - {{ actionDisplayName(action) }} - - - + :files-list-width="filesListWidth" + :loading.sync="loading" + :opened.sync="openedMenu" + :source="source" + :visible="visible" /> 0) { - const action = this.enabledDefaultActions[0] + const enabledDefaultActions = this.$refs?.actions?.enabledDefaultActions + if (enabledDefaultActions?.length > 0) { + const action = enabledDefaultActions[0] const displayName = action.displayName([this.source], this.currentView) return { title: displayName, @@ -395,66 +363,6 @@ export default Vue.extend({ return this.selectedFiles.includes(this.fileid) }, - // Sorted actions that are enabled for this node - enabledActions() { - if (this.source.attributes.failed) { - return [] - } - - return actions - .filter(action => !action.enabled || action.enabled([this.source], this.currentView)) - .sort((a, b) => (a.order || 0) - (b.order || 0)) - }, - - // Enabled action that are displayed inline - enabledInlineActions() { - if (this.filesListWidth < 768) { - return [] - } - return this.enabledActions.filter(action => action?.inline?.(this.source, this.currentView)) - }, - - // Enabled action that are displayed inline with a custom render function - enabledRenderActions() { - if (!this.visible) { - return [] - } - return this.enabledActions.filter(action => typeof action.renderInline === 'function') - }, - - // Default actions - enabledDefaultActions() { - return this.enabledActions.filter(action => !!action?.default) - }, - - // Actions shown in the menu - enabledMenuActions() { - return [ - // Showing inline first for the NcActions inline prop - ...this.enabledInlineActions, - // Then the rest - ...this.enabledActions.filter(action => action.default !== DefaultType.HIDDEN && typeof action.renderInline !== 'function'), - ].filter((value, index, self) => { - // Then we filter duplicates to prevent inline actions to be shown twice - return index === self.findIndex(action => action.id === value.id) - }) - }, - openedMenu: { - get() { - return this.actionsMenuStore.opened === this.uniqueId - }, - set(opened) { - this.actionsMenuStore.opened = opened ? this.uniqueId : null - }, - }, - - uniqueId() { - return hashCode(this.source.source) - }, - isLoading() { - return this.source.status === NodeStatus.LOADING - }, - renameLabel() { const matchLabel: Record = { [FileType.File]: t('files', 'File name'), @@ -507,6 +415,15 @@ export default Vue.extend({ return (this.source.permissions & Permission.CREATE) !== 0 }, + + openedMenu: { + get() { + return this.actionsMenuStore.opened === this.uniqueId + }, + set(opened) { + this.actionsMenuStore.opened = opened ? this.uniqueId : null + }, + }, }, watch: { @@ -545,67 +462,6 @@ export default Vue.extend({ this.openedMenu = false }, - async onActionClick(action) { - const displayName = action.displayName([this.source], this.currentView) - try { - // Set the loading marker - this.loading = action.id - Vue.set(this.source, 'status', NodeStatus.LOADING) - - const success = await action.exec(this.source, this.currentView, this.currentDir) - - // If the action returns null, we stay silent - if (success === null) { - return - } - - if (success) { - showSuccess(t('files', '"{displayName}" action executed successfully', { displayName })) - return - } - showError(t('files', '"{displayName}" action failed', { displayName })) - } catch (e) { - logger.error('Error while executing action', { action, e }) - showError(t('files', '"{displayName}" action failed', { displayName })) - } finally { - // Reset the loading marker - this.loading = '' - Vue.set(this.source, 'status', undefined) - } - }, - execDefaultAction(event) { - if (this.enabledDefaultActions.length > 0) { - event.preventDefault() - event.stopPropagation() - // Execute the first default action if any - this.enabledDefaultActions[0].exec(this.source, this.currentView, this.currentDir) - } - }, - - openDetailsIfAvailable(event) { - event.preventDefault() - event.stopPropagation() - if (sidebarAction?.enabled?.([this.source], this.currentView)) { - sidebarAction.exec(this.source, this.currentView, this.currentDir) - } - }, - - // Open the actions menu on right click - onRightClick(event) { - // If already opened, fallback to default browser - if (this.openedMenu) { - return - } - - // If the clicked row is in the selection, open global menu - const isMoreThanOneSelected = this.selectedFiles.length > 1 - this.actionsMenuStore.opened = this.isSelected && isMoreThanOneSelected ? 'global' : this.uniqueId - - // Prevent any browser defaults - event.preventDefault() - event.stopPropagation() - }, - /** * Check if the file name is valid and update the * input validity using browser's native validation. @@ -749,23 +605,32 @@ export default Vue.extend({ } }, - /** - * Making this a function in case the files-list - * reference changes in the future. That way we're - * sure there is one at the time we call it. - */ - getBoundariesElement() { - return document.querySelector('.app-content > .files-list') + // Open the actions menu on right click + onRightClick(event) { + // If already opened, fallback to default browser + if (this.openedMenu) { + return + } + + // If the clicked row is in the selection, open global menu + const isMoreThanOneSelected = this.selectedFiles.length > 1 + this.actionsMenuStore.opened = this.isSelected && isMoreThanOneSelected ? 'global' : this.uniqueId + + // Prevent any browser defaults + event.preventDefault() + event.stopPropagation() }, - actionDisplayName(action: FileAction) { - if (this.filesListWidth < 768 && action.inline && typeof action.title === 'function') { - // if an inline action is rendered in the menu for - // lack of space we use the title first if defined - const title = action.title([this.source], this.currentView) - if (title) return title + execDefaultAction() { + this.$refs.actions.execDefaultAction() + }, + + openDetailsIfAvailable(event) { + event.preventDefault() + event.stopPropagation() + if (sidebarAction?.enabled?.([this.source], this.currentView)) { + sidebarAction.exec(this.source, this.currentView, this.currentDir) } - return action.displayName([this.source], this.currentView) }, onDragOver(event: DragEvent) { diff --git a/apps/files/src/components/FileEntry/FileEntryActions.vue b/apps/files/src/components/FileEntry/FileEntryActions.vue new file mode 100644 index 00000000000..84d8f4a40f9 --- /dev/null +++ b/apps/files/src/components/FileEntry/FileEntryActions.vue @@ -0,0 +1,238 @@ + + + +