Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: add examples for extension types #10906

Merged
merged 1 commit into from
May 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 59 additions & 5 deletions docs/extension-system/extension-types/actions.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ This is what the ActionExtension interface looks like:

```typescript
interface ActionExtension {
id: string
type: 'action'
scopes?: ExtensionScope[]
action: Action // Please check the Action section below
id: string
type: 'action'
scopes?: ExtensionScope[]
action: Action // Please check the Action section below
}
```

Expand All @@ -32,12 +32,66 @@ For `id`, `type`, and `scopes`, please see [extension base section]({{< ref "../
#### Action

The most important configuration options are:

- `icon` - The icon to be displayed, can be picked from https://owncloud.design/#/Design%20Tokens/IconList
- `name` - The name of the action (not displayed in the UI)
- `label` - The text to be displayed
- `route` - The string/route to navigate to, if the nav item should be a `<router-link>`
- `handler` - The action to perform upon click, if the nav item should be a `<button>`
- `componentType` - Either `'button'` or `'router-link'`, depending on whether the action should be a link or button
- `isEnabled` - Determines whether the action is displayed to the user
- `isVisible` - Determines whether the action is displayed to the user

Please check the [`Action` type](https://github.com/owncloud/web/blob/236c185540fc6758dc7bd84985c8834fa4145530/packages/web-pkg/src/composables/actions/types.ts#L6) for a full list of configuration options.

### Example

The following example shows how an action extension for downloading files could look like. Note that the extension is wrapped inside a Vue composable so it can easily be reused. All helper types and composables are being provided via the [web-pkg](https://github.com/owncloud/web/tree/master/packages/web-pkg) package.

```typescript
export const useDownloadFilesExtension = () => {
const { $gettext } = useGettext()

const extension = computed<ActionExtension>(() => ({
id: 'com.github.owncloud.web.files.download-action',
scopes: ['resource'],
type: 'action',
action: {
name: 'download-files',
icon: 'download',
componentType: 'button',
class: 'oc-files-actions-download-files',
label: () => $gettext('Download'),
isVisible: ({ space, resources }) => {
if (resources.length === 0) {
return false
}

return true
},
handler: ({ space, resources }) => {
console.log('Triggering download...')
}
}
}))

return { extension }
}
```

The extension could then be registered in any app like so:

```typescript
export default defineWebApplication({
setup() {
const { extension } = useFileActionDownloadFiles()

return {
appInfo: {
name: $gettext('Download app'),
id: 'download-app'
},
extensions: computed(() => [unref(extension)])
}
}
})
```
54 changes: 49 additions & 5 deletions docs/extension-system/extension-types/folder-view.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,11 @@ This is what the FolderViewExtension interface looks like:

```typescript
interface FolderViewExtension {
id: string
scopes?: ExtensionScope[]
type: 'folderView'
folderView: FolderView // See FolderView section below
id: string
scopes?: ExtensionScope[]
type: 'folderView'
folderView: FolderView // See FolderView section below
}

```

For `id`, `type`, and `scopes`, please see [extension base section]({{< ref "../_index.md#extension-base-configuration" >}}) in top level docs.
Expand All @@ -38,3 +37,48 @@ For the folderView object, you have the following configuration options:
- `isScrollable` - Optional boolean, determines whether the user can scroll inside the component or it statically fills the viewport
- `component` - The Vue component to render the resources. It should expect a prop of type `Resource[]`
- `componentAttrs` - Optional additional configuration for the component mentioned above

### Example

The following example shows how an extension for a custom folder view could look like. Note that the extension is wrapped inside a Vue composable so it can easily be reused. All helper types and composables are being provided via the [web-pkg](https://github.com/owncloud/web/tree/master/packages/web-pkg) package.

```typescript
export const useCustomFolderViewExtension = () => {
const { $gettext } = useGettext()

const extension = computed<FolderViewExtension>(() => ({
id: 'com.github.owncloud.web.files.folder-view.custom',
type: 'folderView',
scopes: ['resource', 'space', 'favorite'],
folderView: {
name: 'custom-table',
label: $gettext('Switch to custom folder view'),
icon: {
name: 'menu-line',
fillType: 'none'
},
component: YourCustomFolderViewComponent
}
}))

return { extension }
}
```

The extension could then be registered in any app like so:

```typescript
export default defineWebApplication({
setup() {
const { extension } = useCustomFolderViewExtension()

return {
appInfo: {
name: $gettext('Custom folder view app'),
id: 'custom-folder-view-app'
},
extensions: computed(() => [unref(extension)])
}
}
})
```
58 changes: 56 additions & 2 deletions docs/extension-system/extension-types/left-sidebar-menu-item.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ geekdocCollapseSection: true

{{< toc >}}


## Left sidebar menu item extension type

One possible extension type is left sidebar menu items. Registered left sidebar menu items get rendered in the left sidebar, as long as there is more than one available.
Expand All @@ -32,13 +31,68 @@ interface SidebarNavExtension {

For `id`, `type`, and `scopes`, please see [extension base section]({{< ref "../_index.md#extension-base-configuration" >}}) in top level docs.


#### AppNavigationItem

The most important configuration options are:

- `icon` - The icon to be displayed, can be picked from https://owncloud.design/#/Design%20Tokens/IconList
- `name` - The text to be displayed
- `route` - The string/route to navigate to, if the nav item should be a `<router-link>` (Mutually exclusive with `handler`)
- `handler` - The action to perform upon click, if the nav item should be a `<button>` (Mutually exclusive with `route`)

Please check the [`AppNavigationItem` type](https://github.com/owncloud/web/blob/f069ce44919cde5d112c68a519d433e015a4a011/packages/web-pkg/src/apps/types.ts#L14) for a full list of configuration options.

### Example

The following example shows an extension that adds a left sidebar nav item inside the files app, linking to a custom page. Note that the extension is wrapped inside a Vue composable so it can easily be reused. All helper types and composables are being provided via the [web-pkg](https://github.com/owncloud/web/tree/master/packages/web-pkg) package.

```typescript
export const useCustomPageExtension = () => {
const { $gettext } = useGettext()

const extension = computed<SidebarNavExtension>(() => ({
id: 'com.github.owncloud.web.files.left-nav.custom-page',
scopes: ['app.files'],
type: 'sidebarNav',
action: {
name: $gettext('Custom page'),
icon: 'world',
priority: 100,
isActive: () => true,
isVisible: () => true,
route: {
path: '/files/custom-page'
},
activeFor: [{ path: '/files/custom-page' }]
}
}))

return { extension }
}
```

The extension could then be registered in any app like so:

```typescript
export default defineWebApplication({
setup() {
const { extension } = useCustomPageExtension()

return {
appInfo: {
name: $gettext('Custom page app'),
id: 'custom-page-app'
},
routes: {
path: '/files/custom-page',
name: 'files-custom-page',
component: CustomPageComponent,
meta: {
title: $gettext('Custom Page')
}
},
extensions: computed(() => [unref(extension)])
}
}
})
```
67 changes: 59 additions & 8 deletions docs/extension-system/extension-types/right-sidebar-panels.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ geekdocCollapseSection: true
The right sidebar is supposed to show information and make context specific actions available for single or multiple selected items.

It is structured in a hierarchical way:

- Panels which are defined as `root` panels get rendered as immediate members of the right sidebar.
- Panels which are defined as non-`root` panels receive a navigation item below the `root` panels so that users can navigate into the respective
sub panel.
sub panel.

### Configuration

Expand All @@ -26,9 +27,9 @@ It can be found below:

```typescript
interface SidebarPanelExtension<R extends Item, P extends Item, T extends Item> {
id: string,
type: 'sidebarPanel',
scopes?: ExtensionScope[],
id: string
type: 'sidebarPanel'
scopes?: ExtensionScope[]
panel: SideBarPanel<R, P, T> // Please check the SideBarPanel section below
}
```
Expand All @@ -49,11 +50,11 @@ interface SideBarPanelContext<R extends Item, P extends Item, T extends Item> {
```

- `items` - The most important member of the panel context, which denotes all selected items. That can mean all selected files in a files listing,
all selected users in a user listing, the individual current file in a file editor.
all selected users in a user listing, the individual current file in a file editor.
- `parent` - The immediate parent of the selected items. For example, if the user selects a file in a file listing, the parent is the parent folder,
or if being in a root of a space, the space itself. Can be `null` for non-hierarchical contexts, e.g. a user listing.
or if being in a root of a space, the space itself. Can be `null` for non-hierarchical contexts, e.g. a user listing.
- `root` - The uppermost parent of the selected items. For example, if the user selects a file in a file listing, the root is always the space in which
the selected files reside. Can be `null` for non-hierarchical contexts, e.g. a user listing.
the selected files reside. Can be `null` for non-hierarchical contexts, e.g. a user listing.

#### SideBarPanel

Expand All @@ -80,6 +81,56 @@ interface SideBarPanel<R extends Item, P extends Item, T extends Item> {
## Extension Point FileSideBar

In the context of files (e.g. file listing, text editor for a single file, etc.) we have a dedicated component `FileSideBar` which can be
toggled (shown/hidden) with a button in the top bar. The component queries all extensions of the type `sideBarPanel` from the extension
toggled (shown/hidden) with a button in the top bar. The component queries all extensions of the type `sideBarPanel` from the extension
registry that also fulfill the scope `resource`. By registering an custom extension of type `sideBarPanel` and scope `resource`, your extension
will automatically become available in all environments that display the `FileSideBar` (i.e. any file viewer, file editor, file listing).

## Example

The following example shows how a sidebar panel for displaying exif data for a resource could look like. Note that the extension is wrapped inside a Vue composable so it can easily be reused. All helper types and composables are being provided via the [web-pkg](https://github.com/owncloud/web/tree/master/packages/web-pkg) and the [web-client](https://github.com/owncloud/web/tree/master/packages/web-client) packages.

```typescript
export const useExifDataPanelExtension = () => {
const { $gettext } = useGettext()

const extension = computed<SidebarPanelExtension<SpaceResource, Resource, Resource>>(() => ({
id: 'com.github.owncloud.web.files.sidebar-panel.exif-data',
type: 'sidebarPanel',
scopes: ['resource'],
panel: {
name: 'exif-data',
icon: 'image',
title: () => $gettext('EXIF data'),
component: ExifDataPanelComponent,
isRoot: () => true,
isVisible: ({ items }) => {
if (items?.length !== 1) {
return false
}

return true
}
}
}))

return { extension }
}
```

The extension can then be registered in any app like so:

```typescript
export default defineWebApplication({
setup() {
const { extension } = useExifDataPanelExtension()

return {
appInfo: {
name: $gettext('Exif panel app'),
id: 'exif-panel-app'
},
extensions: computed(() => [unref(extension)])
}
}
})
```
Loading