Skip to content

Commit

Permalink
Add default actions extension point (#11515)
Browse files Browse the repository at this point in the history
* feat: introduce default actions extension point
  • Loading branch information
kulmann authored Sep 4, 2024
1 parent d7a3f45 commit 6dd15ac
Show file tree
Hide file tree
Showing 13 changed files with 125 additions and 147 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Enhancement: Add default actions extension point

We've added a new extension point `global.files.default-action` for allowing action extensions to register themselves for the left click default action.

https://github.com/owncloud/web/pull/11515
9 changes: 5 additions & 4 deletions docs/extension-system/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,11 @@ your extension will be used automatically.
2. Folder views for regular folders. ExtensionPointId `app.files.folder-views.folder`. Mounts extensions of type `folderView`.
3. Folder views for the project spaces overview. ExtensionPointId `app.files.folder-views.project-spaces`. Mounts extensions of type `folderView`.
4. Folder views for the favorites page. ExtensionPointId `app.files.folder-views.favorites`. Mounts extensions of type `folderView`.
5. Right click context menu. ExtensionPointId `app.files.context-actions`. Mounts extensions of type `action`.
6. Batch actions in the app bar above file lists. ExtensionPointId `app.files.batch-actions`. Mounts extensions of type `action`.
7. Upload menu. ExtensionPointId `app.files.upload-menu`. Mounts extensions of type `action`.
8. Quick actions. ExtensionPointId `app.files.quick-actions`. Mounts extensions of type `action`.
5. Right click context menu. ExtensionPointId `global.files.context-actions`. Mounts extensions of type `action`.
6. Batch actions in the app bar above file lists. ExtensionPointId `global.files.batch-actions`. Mounts extensions of type `action`.
7. Default actions (left click) on a file. ExtensionPointId `global.files.default-actions`. Mounts extensions of type `action`.
8. Upload menu. ExtensionPointId `app.files.upload-menu`. Mounts extensions of type `action`.
9. Quick actions. ExtensionPointId `app.files.quick-actions`. Mounts extensions of type `action`.
4. Global search providers. ExtensionPointId `app.search.providers`. Utilizes extensions of type `search` as search engines for the search input in the global top bar.

#### User Preferences for Extensions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { Resource, SpaceResource } from '@ownclouders/web-client'
import FileActions from '../SideBar/Actions/FileActions.vue'
import FileDetails from '../SideBar/Details/FileDetails.vue'
import { useFileActions, FileInfo } from '@ownclouders/web-pkg'
import { FileInfo, useOpenWithDefaultApp } from '@ownclouders/web-pkg'
import { useRouteQuery } from '@ownclouders/web-pkg'
export default defineComponent({
Expand All @@ -25,6 +25,7 @@ export default defineComponent({
},
provide() {
return {
// provide resource and space for sub-components
resource: computed(() => this.singleResource),
space: computed(() => this.space)
}
Expand All @@ -42,20 +43,13 @@ export default defineComponent({
}
},
setup(props) {
const { getDefaultEditorAction } = useFileActions()
const { openWithDefaultApp } = useOpenWithDefaultApp()
const openWithDefaultAppQuery = useRouteQuery('openWithDefaultApp')
const fileActionsOptions = {
resources: [props.singleResource],
space: props.space
}
const defaultEditorAction = getDefaultEditorAction(fileActionsOptions)
if (unref(openWithDefaultAppQuery) === 'true' && defaultEditorAction) {
defaultEditorAction.handler({ ...fileActionsOptions })
}
return {
defaultEditorAction
if (unref(openWithDefaultAppQuery) === 'true') {
openWithDefaultApp({
space: props.space,
resource: props.singleResource
})
}
}
})
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import {
ActionExtension,
useFileActionsCopyQuickLink,
useFileActionsOpenShortcut,
useFileActionsShowShares
} from '@ownclouders/web-pkg'
import {
contextActionsExtensionPoint,
defaultActionsExtensionPoint,
quickActionsExtensionPoint
} from '../../extensionPoints'
import { unref } from 'vue'

export const useFileActions = (): ActionExtension[] => {
const { actions: openShortcutActions } = useFileActionsOpenShortcut()
const { actions: showSharesActions } = useFileActionsShowShares()
const { actions: quickLinkActions } = useFileActionsCopyQuickLink()

return [
{
id: 'com.github.owncloud.web.files.context-action.open-shortcut',
extensionPointIds: [contextActionsExtensionPoint.id, defaultActionsExtensionPoint.id],
type: 'action',
action: unref(openShortcutActions)[0]
},
{
id: 'com.github.owncloud.web.files.quick-action.collaborator',
extensionPointIds: [quickActionsExtensionPoint.id],
type: 'action',
action: unref(showSharesActions)[0]
},
{
id: 'com.github.owncloud.web.files.quick-action.quicklink',
extensionPointIds: [quickActionsExtensionPoint.id],
type: 'action',
action: unref(quickLinkActions)[0]
}
]
}
6 changes: 6 additions & 0 deletions packages/web-app-files/src/extensionPoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ export const contextActionsExtensionPoint: ExtensionPoint<ActionExtension> = {
extensionType: 'action',
multiple: true
}
export const defaultActionsExtensionPoint: ExtensionPoint<ActionExtension> = {
id: 'global.files.default-actions',
extensionType: 'action',
multiple: true
}
export const fileSideBarExtensionPoint: ExtensionPoint<SidebarPanelExtension<any, any, any>> = {
id: 'global.files.sidebar',
extensionType: 'sidebarPanel',
Expand All @@ -51,6 +56,7 @@ export const extensionPoints = () => {
quickActionsExtensionPoint,
batchActionsExtensionPoint,
contextActionsExtensionPoint,
defaultActionsExtensionPoint,
fileSideBarExtensionPoint,
folderViewsFolderExtensionPoint,
folderViewsFavoritesExtensionPoint,
Expand Down
23 changes: 4 additions & 19 deletions packages/web-app-files/src/extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,15 @@ import {
Extension,
useCapabilityStore,
useConfigStore,
useFileActionsCopyQuickLink,
useFileActionsShowShares,
useRouter,
useSearch,
useUserStore
} from '@ownclouders/web-pkg'
import { computed, unref } from 'vue'
import { computed } from 'vue'
import { SDKSearch } from './search'
import { useSideBarPanels } from './composables/extensions/useFileSideBars'
import { useFolderViews } from './composables/extensions/useFolderViews'
import { quickActionsExtensionPoint } from './extensionPoints'
import { useFileActions } from './composables/extensions/useFileActions'
import { urlJoin } from '@ownclouders/web-client'

export const extensions = (appInfo: ApplicationInformation) => {
Expand All @@ -23,13 +21,12 @@ export const extensions = (appInfo: ApplicationInformation) => {
const router = useRouter()
const { search: searchFunction } = useSearch()

const { actions: showSharesActions } = useFileActionsShowShares()
const { actions: quickLinkActions } = useFileActionsCopyQuickLink()

const fileActionExtensions = useFileActions()
const folderViewExtensions = useFolderViews()
const sideBarPanelExtensions = useSideBarPanels()

return computed<Extension[]>(() => [
...fileActionExtensions,
...folderViewExtensions,
...sideBarPanelExtensions,
{
Expand All @@ -38,18 +35,6 @@ export const extensions = (appInfo: ApplicationInformation) => {
type: 'search',
searchProvider: new SDKSearch(capabilityStore, router, searchFunction, configStore)
},
{
id: 'com.github.owncloud.web.files.quick-action.collaborator',
extensionPointIds: [quickActionsExtensionPoint.id],
type: 'action',
action: unref(showSharesActions)[0]
},
{
id: 'com.github.owncloud.web.files.quick-action.quicklink',
extensionPointIds: [quickActionsExtensionPoint.id],
type: 'action',
action: unref(quickLinkActions)[0]
},
...((userStore.user && [
{
id: `app.${appInfo.id}.menuItem`,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,50 +1,49 @@
import { defaultComponentMocks, defaultPlugins, mount, RouteLocation } from 'web-test-helpers'
import {
defaultComponentMocks,
defaultPlugins,
RouteLocation,
shallowMount
} from 'web-test-helpers'
import ResourceDetails from '../../../../src/components/FilesList/ResourceDetails.vue'
import { mock } from 'vitest-mock-extended'
import { useFileActions } from '@ownclouders/web-pkg'
import { Resource, SpaceResource } from '@ownclouders/web-client'
import { useRouteQuery } from '@ownclouders/web-pkg'
import { useOpenWithDefaultApp, useRouteQuery } from '@ownclouders/web-pkg'
import { ref } from 'vue'

vi.mock('@ownclouders/web-pkg', async (importOriginal) => ({
...(await importOriginal<any>()),
getIndicators: vi.fn(() => []),
useRouteQuery: vi.fn(),
useFileActions: vi.fn()
useOpenWithDefaultApp: vi.fn()
}))

describe('ResourceDetails component', () => {
vi.mocked(useFileActions).mockImplementation(() =>
mock<ReturnType<typeof useFileActions>>({
getDefaultEditorAction: () => ({ handler: vi.fn() }) as any
})
)

it('renders resource details correctly', () => {
const { wrapper } = getWrapper(true)
expect(wrapper.html()).toMatchSnapshot()
})

describe('open with default actions', () => {
it("doesn't open default action if query param 'openWithDefaultApp' isn't set true", () => {
const { wrapper } = getWrapper()
expect(wrapper.vm.defaultEditorAction.handler).not.toHaveBeenCalled()
const { mocks } = getWrapper()
expect(mocks.openWithDefaultAppMock).not.toHaveBeenCalled()
})
it("opens default action if query param 'openWithDefaultApp' is set true", () => {
vi.mocked(useRouteQuery).mockImplementationOnce(() => ref('true'))
const { wrapper } = getWrapper()
expect(wrapper.vm.defaultEditorAction.handler).toHaveBeenCalled()
const { mocks } = getWrapper()
expect(mocks.openWithDefaultAppMock).toHaveBeenCalled()
})
})

function getWrapper(isFolder = false) {
const openWithDefaultAppMock = vi.fn()
vi.mocked(useOpenWithDefaultApp).mockReturnValue({
openWithDefaultApp: openWithDefaultAppMock
})

const mocks = {
...defaultComponentMocks({
currentRoute: mock<RouteLocation>({
name: 'files-public-link',
query: { openWithDefaultAppQuery: 'true' }
})
})
}),
openWithDefaultAppMock
}

const file = {
Expand All @@ -64,7 +63,7 @@ describe('ResourceDetails component', () => {

return {
mocks,
wrapper: mount(ResourceDetails, {
wrapper: shallowMount(ResourceDetails, {
props: {
space,
singleResource: file
Expand Down

This file was deleted.

3 changes: 0 additions & 3 deletions packages/web-pkg/src/components/FilesList/ContextActions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
ActionExtension,
FileActionOptions,
useExtensionRegistry,
useFileActionsOpenShortcut,
useFileActionsToggleHideShare,
useFileActionsCopyQuickLink,
useFileActionsPaste,
Expand Down Expand Up @@ -64,7 +63,6 @@ export default defineComponent({
const { actions: showDetailsActions } = useFileActionsShowDetails()
const { actions: createSpaceFromResourceActions } = useFileActionsCreateSpaceFromResource()
const { actions: showSharesActions } = useFileActionsShowShares()
const { actions: openShortcutActions } = useFileActionsOpenShortcut()
const extensionRegistry = useExtensionRegistry()
const extensionsContextActions = computed(() => {
Expand Down Expand Up @@ -112,7 +110,6 @@ export default defineComponent({
const menuItemsContext = computed(() => {
return [
...unref(openShortcutActions),
...unref(editorActions),
...unref(extensionsContextActions).filter((a) => a.category === 'context')
]
Expand Down
Loading

0 comments on commit 6dd15ac

Please sign in to comment.