diff --git a/changelog/unreleased/enhancement-custom-component-extension b/changelog/unreleased/enhancement-custom-component-extension new file mode 100644 index 00000000000..02a6ffa8df2 --- /dev/null +++ b/changelog/unreleased/enhancement-custom-component-extension @@ -0,0 +1,7 @@ +Enhancement: Custom component extension type + +We've introduced a new extension type `customComponent`. This allows to register a custom component via an extension which +can then be rendered in a custom component render target. For the mapping to the render target, an extension point needs to be +registered and a CustomComponentTarget for this extension point needs to be in place in a vue template. + +https://github.com/owncloud/web/pull/10443 diff --git a/changelog/unreleased/enhancement-extension-points b/changelog/unreleased/enhancement-extension-points new file mode 100644 index 00000000000..b552f468823 --- /dev/null +++ b/changelog/unreleased/enhancement-extension-points @@ -0,0 +1,16 @@ +Enhancement: Add extensionPoint concept + +The extension system now allows developers to register extension points. An extension point defines the metadata for the +integration of a certain extension type in a certain context. Examples for extension points are render targets for +custom components, targets for file actions (e.g. the right click context menu, the batch actions, the whitespace context +menu), etc. + +Extensions can now specify that they are only valid for a certain or multiple extension points. This way a file action extension +can e.g. specify to be rendered only in the context menu, but not in the batch actions. Consequently, the extension points +concept is the next iteration of the `scopes` concept. The `scopes` concept will most likely be removed in a future release. + +Extension points can define if users should be able to choose preferences for the extension point. E.g. for the global progress +bar extension point, users can choose which of the available progress bar extensions should be used, since the extension point +only allows one extension to be active. At the moment we persist the user choice in the local storage of the browser. + +https://github.com/owncloud/web/pull/10443 diff --git a/docs/extension-system/_index.md b/docs/extension-system/_index.md index 97eafb34249..0ff800ecd7f 100644 --- a/docs/extension-system/_index.md +++ b/docs/extension-system/_index.md @@ -112,6 +112,8 @@ For details, please refer to the [sidebar nav docs]({{< ref "extension-types/lef 4. `SidebarPanelExtension`, (type `sidebarPanel`) - An extension that can register panels to the right sidebar. For details, please refer to the [sidebar panel docs]({{< ref "extension-types/right-sidebar-panels.md" >}}) 5. `FolderViewExtension` (type `folderView`) - An extension that can register additional ways of displaying the content of a folder (resources, so spaces, folders or files) to the user. For details, please refer to the [folder view docs]({{< ref "extension-types/folder-view.md" >}}) +6. `CustomComponentExtension` (type `customComponent`) - An extension that can register a custom component for a render target. For details, please refer to the +[custom component docs]({{< ref "extension-types/custom-components.md" >}}) You're free to introduce your own extension types within your application code and use the extension registry to query the available ones. However, if you have the impression that an important extension type is missing and would be beneficial for the platform, please reach out to us by opening a [GitHub issue](https://github.com/owncloud/web/issues/new/choose). @@ -125,22 +127,14 @@ Instead, we chose to use dot-formatted namespaces like e.g. `com.github.owncloud For the `type` you can choose from the ones listed above or define a custom one. -In addition, you can also pass optional `scopes` to further limit the usage of an extension. The extension system predefines some scopes which are then used in the default extension -points (see section below). Those include: -- `resource` - For extensions which are meant to work with a `file`, `folder` or `space` as data context. -- `user` - For extensions which are meant to work with a `user` as data context. -- `group` - For extensions which are meant to work with a `group` as data context. - -Similar to the extension types, you are always free to define and handle custom scopes within your own application. If you have the impression -that an important scope is missing and would be beneficial for the platform, please reach out to us by opening a [GitHub issue](https://github.com/owncloud/web/issues/new/choose). - -{{< hint info >}} -Scopes are meant to be defined in singular form, e.g. `resource` instead of `resources`, even when the data context holds multiple items. -{{< /hint >}} +In addition, you can also pass optional `extensionPointIds` to further limit the usage of an extension. With the right click context menu and the batch actions being +two different extension points, this could mean that a file action extension is only allowed in the context menu, but not in the batch actions. +You can find predefined extension point ids in the extension points section below. #### Extension Points -There are standardized components and places where extensions are being used automatically. These are the ones that are currently provided: +There are standardized components and places where extensions are being used automatically. The following are the ones that are currently provided +by the ownCloud Web runtime or the `files` app. 1. Left Sidebar for Navigation 2. Right Sidebar in any file(s) context @@ -150,3 +144,10 @@ There are standardized components and places where extensions are being used aut 6. Upload menu in the files app 7. Quick actions in the files list of the files app 8. Search results in the search app +9. Global progress bar for the global loading state. Extension point id `app.runtime.global-progress-bar`. Allows to render a single custom component. + +#### User Preferences for Extensions + +To allow users to configure extensions, extension points can define user preferences. User preferences are defined as an object on the extension point configuration. +Whenever an extension point declares to accept user preferences, it will get listed with a dropdown on the Preferences page (reachable via top right user menu). +The user can then select one out of all the extensions which have been registered for this extension point. diff --git a/docs/extension-system/extension-types/custom-components.md b/docs/extension-system/extension-types/custom-components.md new file mode 100644 index 00000000000..b9f5a528991 --- /dev/null +++ b/docs/extension-system/extension-types/custom-components.md @@ -0,0 +1,53 @@ +--- +title: 'Custom component extensions' +date: 2024-02-14T00:00:00+00:00 +weight: 60 +geekdocRepo: https://github.com/owncloud/web +geekdocEditPath: edit/master/docs/extension-system/extension-types +geekdocFilePath: custom-components.md +geekdocCollapseSection: true +--- + +{{< toc >}} + +## Extension Type CustomComponent + +CustomComponent extensions need to define one or multiple `extensionPointId`s as render target. A `CustomComponentTarget` component for this very +extension point needs to be mounted in the current view. + +### Configuration + +To define a custom component extension, you implement the `CustomComponentExtension` interface. +Here's what it looks like: + +```typescript +interface CustomComponentExtension { + id: string, + type: 'customComponent', + extensionPointIds: string[], + content: Slot | Component +} +``` + +For `id`, `type`, and `extensionPointIds`, please see [extension base section]({{< ref "../_index.md#extension-base-configuration" >}}) in the top level docs. + +The `content` property specifies a render function or a Component for the target extension point. + +### Example + +A simple example for a custom component extension could be a `NyanCat` progress bar component, being +targeted at the `global-progress-bar` extension point as render target. + +```typescript +const extension = { + id: 'com.github.owncloud.web.app.progress-bars.nyan-cat', + type: 'customComponent', + extensionPointIds: ['app.runtime.global-progress-bar'], + content: (slots) => [h(NyanCat, slots)], + userPreference: { + optionLabel: $gettext('Nyan Cat progress bar') + } +} +``` + +The `content` property in this example can also be defined as `content: NyanCat`. diff --git a/docs/extension-system/extension-types/right-sidebar-panels.md b/docs/extension-system/extension-types/right-sidebar-panels.md index 18d3e677b3e..4b0cfcc197c 100644 --- a/docs/extension-system/extension-types/right-sidebar-panels.md +++ b/docs/extension-system/extension-types/right-sidebar-panels.md @@ -21,7 +21,8 @@ sub panel. ### Configuration -An example of a right sidebar panel extension configuration can be found below: +To define a right sidebar panel extension, you implement the `SidebarPanelExtension` interface. +It can be found below: ```typescript interface SidebarPanelExtension { @@ -32,7 +33,7 @@ interface SidebarPanelExtension } ``` -For `id`, `type`, and `scopes`, please see [extension base section]({{< ref "../_index.md#extension-base-configuration" >}}) in top level docs. +For `id`, `type`, and `scopes`, please see [extension base section]({{< ref "../_index.md#extension-base-configuration" >}}) in the top level docs. The `panel` object configures the actual sidebar panel. It consists of different properties and functions, where all the functions get called with a `SideBarPanelContext` entity from the integrating extension points. diff --git a/package.json b/package.json index 3f0efd1fbc1..0830b728f2c 100644 --- a/package.json +++ b/package.json @@ -99,7 +99,7 @@ "typescript": "5.3.3", "url-search-params-polyfill": "8.1.1", "vite": "5.0.12", - "vitest": "1.2.1", + "vitest": "1.4.0", "vitest-mock-extended": "1.3.1", "@vitest/coverage-v8": "1.2.1", "vite-plugin-environment": "^1.1.3", diff --git a/packages/design-system/src/components/OcSelect/OcSelect.vue b/packages/design-system/src/components/OcSelect/OcSelect.vue index 3d8ff182928..44d0bf75aa7 100644 --- a/packages/design-system/src/components/OcSelect/OcSelect.vue +++ b/packages/design-system/src/components/OcSelect/OcSelect.vue @@ -1,6 +1,6 @@