mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2025-05-19 17:14:45 +00:00
Improve documentation extension (#2266)
* improve documentation step 1 * improve documentation step 2 * improve documentation step 3 * move in tutorials * tutotrials * fix * fix * fix * fix links * metadata extension configutation * tutorials links revamp
This commit is contained in:
parent
5212a40278
commit
ee27271776
docs
README.mdabn-tree.yml
configuration
extending
README.mdapplication-features.mdcustom-route.mddialog-actions.mdextensibility-features.mdtutorials.md
features
getting-started
images
toc.mdtutorials
@ -30,7 +30,9 @@ The documentation is divided into the following sections:
|
|||||||
|
|
||||||
- [Application features](/features/): Details of the user interface and app usage.
|
- [Application features](/features/): Details of the user interface and app usage.
|
||||||
- [Getting started](/getting-started/): Configuration of the development environment and the app.
|
- [Getting started](/getting-started/): Configuration of the development environment and the app.
|
||||||
- [Extending](/extending/): How to extend the features of the app with your own code.
|
- Customization:
|
||||||
|
- [Configuration](/configuration/): How to customize basic functionality of the app without touch the code.
|
||||||
|
- [Extending](/extending/): How to extend the features of the app with your own code.
|
||||||
- [Tutorials](/tutorials/): Exploration of development techniques in depth.
|
- [Tutorials](/tutorials/): Exploration of development techniques in depth.
|
||||||
- [Help](/help): Details of further help and support available.
|
- [Help](/help): Details of further help and support available.
|
||||||
|
|
||||||
|
@ -33,7 +33,6 @@
|
|||||||
- icons.md: Custom icons
|
- icons.md: Custom icons
|
||||||
- registration.md: Registration
|
- registration.md: Registration
|
||||||
- creating-custom-evaluators.md: Creating custom evaluators
|
- creating-custom-evaluators.md: Creating custom evaluators
|
||||||
- tutorials.md: Tutorials
|
|
||||||
- redistributable-libraries.md: Redistributable libraries
|
- redistributable-libraries.md: Redistributable libraries
|
||||||
- tutorials:
|
- tutorials:
|
||||||
title: Tutorials
|
title: Tutorials
|
||||||
@ -41,5 +40,8 @@
|
|||||||
- custom-route-with-parameters.md: Custom route with parameters
|
- custom-route-with-parameters.md: Custom route with parameters
|
||||||
- dialog-actions.md: Dialog actions
|
- dialog-actions.md: Dialog actions
|
||||||
- how-to-create-your-first-extension.md: How to create your first extension
|
- how-to-create-your-first-extension.md: How to create your first extension
|
||||||
- how-to-install-an-existing-extension.md: How to install an existing extension
|
- content-metadata.md: How to customize Content Metadata
|
||||||
|
- file-lists.md: How to customize File lists
|
||||||
|
- file-preview.md: How to customize File Preview
|
||||||
|
- search-form.md: How to customize The Search Form
|
||||||
- help.md: 'Get help'
|
- help.md: 'Get help'
|
||||||
|
@ -20,7 +20,7 @@ Learn how to extend the features of the Alfresco Content Application.
|
|||||||
- [Custom icons](/extending/icons)
|
- [Custom icons](/extending/icons)
|
||||||
- [Registration](/extending/registration)
|
- [Registration](/extending/registration)
|
||||||
- [Creating custom evaluators](/extending/creating-custom-evaluators)
|
- [Creating custom evaluators](/extending/creating-custom-evaluators)
|
||||||
- [Custom extension loaders](/extending/custom-extension-loaders.md)
|
- [Custom extension loaders](/extending/custom-extension-loaders)
|
||||||
- [Tutorials](/extending/tutorials)
|
|
||||||
- [Redistributable libraries](/extending/redistributable-libraries)
|
- [Redistributable libraries](/extending/redistributable-libraries)
|
||||||
- [Application Hook](/extending/application-hook)
|
- [Application Hook](/extending/application-hook)
|
||||||
|
- [Tutorials](/../tutorials/)
|
||||||
|
@ -15,6 +15,7 @@ The ACA supports the following set of extension points:
|
|||||||
- Viewer
|
- Viewer
|
||||||
- Sidebar (aka Info Drawer)
|
- Sidebar (aka Info Drawer)
|
||||||
- Content metadata presets (for `Properties` tab)
|
- Content metadata presets (for `Properties` tab)
|
||||||
|
- File list layout
|
||||||
- Search
|
- Search
|
||||||
|
|
||||||
All the customizations are stored in the `features` section of the configuration file:
|
All the customizations are stored in the `features` section of the configuration file:
|
||||||
|
124
docs/extending/custom-route.md
Normal file
124
docs/extending/custom-route.md
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
---
|
||||||
|
Title: Custom route with parameters
|
||||||
|
---
|
||||||
|
|
||||||
|
## Custom route with parameters
|
||||||
|
|
||||||
|
In this tutorial, we are going to implement the following features:
|
||||||
|
|
||||||
|
- Update the **Trashcan** component to receive and log route parameters.
|
||||||
|
- Create a new route that points to the **Trashcan** component and uses the main layout.
|
||||||
|
- Create an action reference that allows redirecting to the new route.
|
||||||
|
- Create a button in the **New** menu that invokes an action.
|
||||||
|
|
||||||
|
Update `src/app/components/trashcan/trashcan.component.ts` and append the following code to the `ngOnInit` body:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { ActivatedRoute, Params } from '@angular/router';
|
||||||
|
|
||||||
|
@Component({...})
|
||||||
|
export class TrashcanComponent {
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
// ...
|
||||||
|
private route: ActivatedRoute
|
||||||
|
) {}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
// ...
|
||||||
|
|
||||||
|
this.route.params.subscribe(({ nodeId }: Params) => {
|
||||||
|
console.log('node: ', nodeId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The code above logs the current route parameters to the browser console
|
||||||
|
and is proof the integration works as expected.
|
||||||
|
|
||||||
|
Next, add a new route definition as in the example below:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"$schema": "../../../extension.schema.json",
|
||||||
|
"$version": "1.0.0",
|
||||||
|
"$name": "plugin1",
|
||||||
|
|
||||||
|
"routes": [
|
||||||
|
{
|
||||||
|
"id": "custom.routes.trashcan",
|
||||||
|
"path": "ext/trashcan/:nodeId",
|
||||||
|
"component": "your.component.id",
|
||||||
|
"layout": "app.layout.main",
|
||||||
|
"auth": ["app.auth"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The template above creates a new route reference with the id `custom.routes.trashcan` that points to the `ext/trashcan/` route and accepts the `nodeId` parameter.
|
||||||
|
|
||||||
|
Also, we are going to use the default application layout (`app.layout.main`)
|
||||||
|
and authentication guards (`app.auth`).
|
||||||
|
|
||||||
|
Next, create an action reference for the `NAVIGATE_ROUTE` application action
|
||||||
|
and pass route parameters: `/ext/trashcan` for the path, and `10` for the `nodeId` value.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"$schema": "../../../extension.schema.json",
|
||||||
|
"$version": "1.0.0",
|
||||||
|
"$name": "plugin1",
|
||||||
|
|
||||||
|
"routes": [...],
|
||||||
|
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"id": "custom.actions.trashcan",
|
||||||
|
"type": "NAVIGATE_ROUTE",
|
||||||
|
"payload": "$(['/ext/trashcan', '10'])"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Finally, declare a new menu item for the `NEW` button and use the `custom.actions.trashcan` action created above.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"$schema": "../../../extension.schema.json",
|
||||||
|
"$version": "1.0.0",
|
||||||
|
"$name": "plugin1",
|
||||||
|
|
||||||
|
"routes": [...],
|
||||||
|
"actions": [...],
|
||||||
|
|
||||||
|
"features": {
|
||||||
|
"create": [
|
||||||
|
{
|
||||||
|
"id": "custom.create.trashcan",
|
||||||
|
"type": "default",
|
||||||
|
"icon": "build",
|
||||||
|
"title": "Custom trashcan route",
|
||||||
|
"actions": {
|
||||||
|
"click": "custom.actions.trashcan"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Now, if you run the application, you should see a new menu item called "Custom Trashcan Route" in the "NEW" dropdown.
|
||||||
|
Upon clicking this item you should navigate to the `/ext/trashcan/10` route containing a **Trashcan** component.
|
||||||
|
|
||||||
|
Check the browser console output and ensure you have the following output:
|
||||||
|
|
||||||
|
```text
|
||||||
|
node: 10
|
||||||
|
```
|
||||||
|
|
||||||
|
You have successfully created a new menu button that invokes your custom action
|
||||||
|
and redirects you to the extra application route.
|
124
docs/extending/dialog-actions.md
Normal file
124
docs/extending/dialog-actions.md
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
---
|
||||||
|
Title: Dialog actions
|
||||||
|
---
|
||||||
|
|
||||||
|
## Dialog actions
|
||||||
|
|
||||||
|
In this tutorial, we are going to create an action that invokes a custom material dialog.
|
||||||
|
|
||||||
|
Please read more details on Dialog components here: [Dialog Overview](https://material.angular.io/components/dialog/overview)
|
||||||
|
|
||||||
|
### Create a dialog
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ng g component dialogs/my-extension-dialog --module=app
|
||||||
|
```
|
||||||
|
|
||||||
|
Update `my-extension-dialog.component.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { MatDialogRef } from '@angular/material/dialog';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'aca-my-extension-dialog',
|
||||||
|
templateUrl: './my-extension-dialog.component.html',
|
||||||
|
styleUrls: ['./my-extension-dialog.component.scss']
|
||||||
|
})
|
||||||
|
export class MyExtensionDialogComponent {
|
||||||
|
constructor(public dialogRef: MatDialogRef<MyExtensionDialogComponent>) {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Update `my-extension-dialog.component.html`:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<h2 mat-dialog-title>Delete all</h2>
|
||||||
|
<mat-dialog-content>Are you sure?</mat-dialog-content>
|
||||||
|
<mat-dialog-actions>
|
||||||
|
<button mat-button mat-dialog-close>No</button>
|
||||||
|
<!-- The mat-dialog-close directive optionally accepts a value as a result for the dialog. -->
|
||||||
|
<button mat-button [mat-dialog-close]="true">Yes</button>
|
||||||
|
</mat-dialog-actions>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create an action
|
||||||
|
|
||||||
|
Append the following code to the `src/app/store/actions/app.actions.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export const SHOW_MY_DIALOG = 'SHOW_MY_DIALOG';
|
||||||
|
|
||||||
|
export class ShowMydDialogAction implements Action {
|
||||||
|
readonly type = SHOW_MY_DIALOG;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See also:
|
||||||
|
|
||||||
|
- [Comprehensive Introduction to @ngrx/store](https://gist.github.com/btroncone/a6e4347326749f938510)
|
||||||
|
|
||||||
|
### Create an effect
|
||||||
|
|
||||||
|
Update `src/app/store/effects/app.effects.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { ShowMydDialogAction, SHOW_MY_DIALOG } from '../actions/app.actions';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AppEffects {
|
||||||
|
@Effect({ dispatch: false })
|
||||||
|
showMyDialog$ = this.actions$.pipe(
|
||||||
|
ofType<ShowMydDialogAction>(SHOW_MY_DIALOG),
|
||||||
|
map(() => {})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See also:
|
||||||
|
|
||||||
|
- [Comprehensive Introduction to @ngrx/store](https://gist.github.com/btroncone/a6e4347326749f938510)
|
||||||
|
|
||||||
|
Update to raise a dialog
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
|
import { MyExtensionDialogComponent } from '../../dialogs/my-extension-dialog/my-extension-dialog.component';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AppEffects {
|
||||||
|
constructor(private dialog: MatDialog) {}
|
||||||
|
|
||||||
|
@Effect({ dispatch: false })
|
||||||
|
showMyDialog$ = this.actions$.pipe(
|
||||||
|
ofType<ShowMydDialogAction>(SHOW_MY_DIALOG),
|
||||||
|
map(() => {
|
||||||
|
this.dialog.open(MyExtensionDialogComponent)
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Register a toolbar action
|
||||||
|
|
||||||
|
Update the `src/assets/app.extensions.json` file, and insert a new entry to the `features.toolbar` section:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"features": {
|
||||||
|
"toolbar": [
|
||||||
|
{
|
||||||
|
"id": "my.custom.toolbar.button",
|
||||||
|
"order": 10,
|
||||||
|
"title": "Custom action",
|
||||||
|
"icon": "extension",
|
||||||
|
"actions": {
|
||||||
|
"click": "SHOW_MY_DIALOG"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Now, once you run the application, you should see an extra button that invokes your dialog on every click.
|
@ -27,6 +27,15 @@ You can create plugins that change, toggle, or extend the following areas:
|
|||||||
- Content metadata presets (used on `Properties` tab)
|
- Content metadata presets (used on `Properties` tab)
|
||||||
- Search
|
- Search
|
||||||
- Custom icons
|
- Custom icons
|
||||||
|
- File list column layout
|
||||||
|
- files
|
||||||
|
- libraries
|
||||||
|
- favoriteLibraries
|
||||||
|
- shared
|
||||||
|
- recent
|
||||||
|
- favorites
|
||||||
|
- trashcan
|
||||||
|
- searchLibraries
|
||||||
|
|
||||||
Extensions can also:
|
Extensions can also:
|
||||||
|
|
||||||
|
@ -1,311 +0,0 @@
|
|||||||
---
|
|
||||||
Title: Tutorials
|
|
||||||
---
|
|
||||||
|
|
||||||
# Tutorials
|
|
||||||
|
|
||||||
Below are some short tutorials that cover common tasks.
|
|
||||||
|
|
||||||
## Custom route with parameters
|
|
||||||
|
|
||||||
In this tutorial, we are going to implement the following features:
|
|
||||||
|
|
||||||
- Update the **Trashcan** component to receive and log route parameters.
|
|
||||||
- Create a new route that points to the **Trashcan** component and uses the main layout.
|
|
||||||
- Create an action reference that allows redirecting to the new route.
|
|
||||||
- Create a button in the **New** menu that invokes an action.
|
|
||||||
|
|
||||||
Update `src/app/components/trashcan/trashcan.component.ts` and append the following code to the `ngOnInit` body:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { ActivatedRoute, Params } from '@angular/router';
|
|
||||||
|
|
||||||
@Component({...})
|
|
||||||
export class TrashcanComponent {
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
// ...
|
|
||||||
private route: ActivatedRoute
|
|
||||||
) {}
|
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
// ...
|
|
||||||
|
|
||||||
this.route.params.subscribe(({ nodeId }: Params) => {
|
|
||||||
console.log('node: ', nodeId);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The code above logs the current route parameters to the browser console
|
|
||||||
and is proof the integration works as expected.
|
|
||||||
|
|
||||||
Next, add a new route definition as in the example below:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"$schema": "../../../extension.schema.json",
|
|
||||||
"$version": "1.0.0",
|
|
||||||
"$name": "plugin1",
|
|
||||||
|
|
||||||
"routes": [
|
|
||||||
{
|
|
||||||
"id": "custom.routes.trashcan",
|
|
||||||
"path": "ext/trashcan/:nodeId",
|
|
||||||
"component": "your.component.id",
|
|
||||||
"layout": "app.layout.main",
|
|
||||||
"auth": ["app.auth"]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The template above creates a new route reference with the id `custom.routes.trashcan` that points to the `ext/trashcan/` route and accepts the `nodeId` parameter.
|
|
||||||
|
|
||||||
Also, we are going to use the default application layout (`app.layout.main`)
|
|
||||||
and authentication guards (`app.auth`).
|
|
||||||
|
|
||||||
Next, create an action reference for the `NAVIGATE_ROUTE` application action
|
|
||||||
and pass route parameters: `/ext/trashcan` for the path, and `10` for the `nodeId` value.
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"$schema": "../../../extension.schema.json",
|
|
||||||
"$version": "1.0.0",
|
|
||||||
"$name": "plugin1",
|
|
||||||
|
|
||||||
"routes": [...],
|
|
||||||
|
|
||||||
"actions": [
|
|
||||||
{
|
|
||||||
"id": "custom.actions.trashcan",
|
|
||||||
"type": "NAVIGATE_ROUTE",
|
|
||||||
"payload": "$(['/ext/trashcan', '10'])"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Finally, declare a new menu item for the `NEW` button and use the `custom.actions.trashcan` action created above.
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"$schema": "../../../extension.schema.json",
|
|
||||||
"$version": "1.0.0",
|
|
||||||
"$name": "plugin1",
|
|
||||||
|
|
||||||
"routes": [...],
|
|
||||||
"actions": [...],
|
|
||||||
|
|
||||||
"features": {
|
|
||||||
"create": [
|
|
||||||
{
|
|
||||||
"id": "custom.create.trashcan",
|
|
||||||
"type": "default",
|
|
||||||
"icon": "build",
|
|
||||||
"title": "Custom trashcan route",
|
|
||||||
"actions": {
|
|
||||||
"click": "custom.actions.trashcan"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Now, if you run the application, you should see a new menu item called "Custom Trashcan Route" in the "NEW" dropdown.
|
|
||||||
Upon clicking this item you should navigate to the `/ext/trashcan/10` route containing a **Trashcan** component.
|
|
||||||
|
|
||||||
Check the browser console output and ensure you have the following output:
|
|
||||||
|
|
||||||
```text
|
|
||||||
node: 10
|
|
||||||
```
|
|
||||||
|
|
||||||
You have successfully created a new menu button that invokes your custom action
|
|
||||||
and redirects you to the extra application route.
|
|
||||||
|
|
||||||
## Dialog actions
|
|
||||||
|
|
||||||
In this tutorial, we are going to create an action that invokes a custom material dialog.
|
|
||||||
|
|
||||||
Please read more details on Dialog components here: [Dialog Overview](https://material.angular.io/components/dialog/overview)
|
|
||||||
|
|
||||||
### Create a dialog
|
|
||||||
|
|
||||||
```sh
|
|
||||||
ng g component dialogs/my-extension-dialog --module=app
|
|
||||||
```
|
|
||||||
|
|
||||||
Update `my-extension-dialog.component.ts`:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
import { Component } from '@angular/core';
|
|
||||||
import { MatDialogRef } from '@angular/material/dialog';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'aca-my-extension-dialog',
|
|
||||||
templateUrl: './my-extension-dialog.component.html',
|
|
||||||
styleUrls: ['./my-extension-dialog.component.scss']
|
|
||||||
})
|
|
||||||
export class MyExtensionDialogComponent {
|
|
||||||
constructor(public dialogRef: MatDialogRef<MyExtensionDialogComponent>) {}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Update `my-extension-dialog.component.html`:
|
|
||||||
|
|
||||||
```html
|
|
||||||
<h2 mat-dialog-title>Delete all</h2>
|
|
||||||
<mat-dialog-content>Are you sure?</mat-dialog-content>
|
|
||||||
<mat-dialog-actions>
|
|
||||||
<button mat-button mat-dialog-close>No</button>
|
|
||||||
<!-- The mat-dialog-close directive optionally accepts a value as a result for the dialog. -->
|
|
||||||
<button mat-button [mat-dialog-close]="true">Yes</button>
|
|
||||||
</mat-dialog-actions>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Create an action
|
|
||||||
|
|
||||||
Append the following code to the `src/app/store/actions/app.actions.ts`:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
export const SHOW_MY_DIALOG = 'SHOW_MY_DIALOG';
|
|
||||||
|
|
||||||
export class ShowMydDialogAction implements Action {
|
|
||||||
readonly type = SHOW_MY_DIALOG;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
See also:
|
|
||||||
|
|
||||||
- [Comprehensive Introduction to @ngrx/store](https://gist.github.com/btroncone/a6e4347326749f938510)
|
|
||||||
|
|
||||||
### Create an effect
|
|
||||||
|
|
||||||
Update `src/app/store/effects/app.effects.ts`:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
import { ShowMydDialogAction, SHOW_MY_DIALOG } from '../actions/app.actions';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class AppEffects {
|
|
||||||
@Effect({ dispatch: false })
|
|
||||||
showMyDialog$ = this.actions$.pipe(
|
|
||||||
ofType<ShowMydDialogAction>(SHOW_MY_DIALOG),
|
|
||||||
map(() => {})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
See also:
|
|
||||||
|
|
||||||
- [Comprehensive Introduction to @ngrx/store](https://gist.github.com/btroncone/a6e4347326749f938510)
|
|
||||||
|
|
||||||
Update to raise a dialog
|
|
||||||
|
|
||||||
```ts
|
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
|
||||||
import { MyExtensionDialogComponent } from '../../dialogs/my-extension-dialog/my-extension-dialog.component';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class AppEffects {
|
|
||||||
constructor(private dialog: MatDialog) {}
|
|
||||||
|
|
||||||
@Effect({ dispatch: false })
|
|
||||||
showMyDialog$ = this.actions$.pipe(
|
|
||||||
ofType<ShowMydDialogAction>(SHOW_MY_DIALOG),
|
|
||||||
map(() => {
|
|
||||||
this.dialog.open(MyExtensionDialogComponent)
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Register a toolbar action
|
|
||||||
|
|
||||||
Update the `src/assets/app.extensions.json` file, and insert a new entry to the `features.toolbar` section:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"features": {
|
|
||||||
"toolbar": [
|
|
||||||
{
|
|
||||||
"id": "my.custom.toolbar.button",
|
|
||||||
"order": 10,
|
|
||||||
"title": "Custom action",
|
|
||||||
"icon": "extension",
|
|
||||||
"actions": {
|
|
||||||
"click": "SHOW_MY_DIALOG"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Now, once you run the application, you should see an extra button that invokes your dialog on every click.
|
|
||||||
|
|
||||||
### File preview from a plugin with custom route
|
|
||||||
|
|
||||||
There might be scenarios where you build a plugin with a custom route, and from that route you might want to preview a file within an overlay.
|
|
||||||
When having a plugin's entry point in a custom route, using the `/view` root-level application routes for previewing a file might be contradictory, since hitting any of these urls results a navigation away from the original route implying a reload of the original route's entry component when closing the preview panel (navigating back).
|
|
||||||
|
|
||||||
#### Example
|
|
||||||
|
|
||||||
Let's say you have a custom plugin with which you can start a process with any of your files. The plugin registers a custom route (`start-process`) with its entry component, where the user can start a process.
|
|
||||||
In this component the user can fill in a form with different values for text fields and selectboxes and select a file. But for file selection, we would like to provide a preview functionality (with the `PreviewComponent` provided by the core application) to let the user be sure that the right file was selected. Obviously having a form filled in values (but not saved) means, that we don't want to loose our filled in data just because we are previewing a file. Because of this we would like the file preview to be opened in an overlay mode. The core application has one overlay region already defined for this reason, called `viewer`. This is the named router outlet we need to target without route change.
|
|
||||||
|
|
||||||
#### Solution
|
|
||||||
|
|
||||||
In our plugin we need to do the following steps:
|
|
||||||
|
|
||||||
##### Registering the custom route in the plugin.json
|
|
||||||
|
|
||||||
We need to add the custom route with our entry component and its child route for the preview:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"routes": [
|
|
||||||
{
|
|
||||||
"id": "start-process",
|
|
||||||
"path": "start-process",
|
|
||||||
"parentRoute": "",
|
|
||||||
"layout": "app.layout.main",
|
|
||||||
// The component we register to be our entry point for this particular route
|
|
||||||
"component": "myplugin.components.start-process",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"id": "start-process-preview",
|
|
||||||
// It can be accessed on the "/start-process(viewer:preview/nodeId)" route
|
|
||||||
"path": "preview/:nodeId",
|
|
||||||
"component": "app.components.preview",
|
|
||||||
"data": {
|
|
||||||
// Using history.back() when closing the preview
|
|
||||||
"navigateBackAsClose": true,
|
|
||||||
// Disabling complex action and buttons for the preview
|
|
||||||
"simplestMode": true
|
|
||||||
},
|
|
||||||
// We would like to target that named router outlet which is used for the viewer overlay
|
|
||||||
"outlet": "viewer"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
##### Dispatching the right action within our component to open the file preview
|
|
||||||
|
|
||||||
```ts
|
|
||||||
import { PluginPreviewAction } from '@alfresco/aca-shared/store';
|
|
||||||
|
|
||||||
@Component({...})
|
|
||||||
export class StartProcessComponent {
|
|
||||||
onFilePreview({ nodeId }) {
|
|
||||||
this.store.dispatch(new PluginPreviewAction('start-process-cloud', nodeId));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
@ -24,3 +24,4 @@ This application simplifies the complexity of Content Management and provides co
|
|||||||
- [Info Drawer](/features/info-drawer)
|
- [Info Drawer](/features/info-drawer)
|
||||||
- [Version Manager](/features/version-manager)
|
- [Version Manager](/features/version-manager)
|
||||||
- [Search results](/features/search-results)
|
- [Search results](/features/search-results)
|
||||||
|
- [Search forms](/features/search-forms)
|
||||||
|
31
docs/features/search-forms.md
Normal file
31
docs/features/search-forms.md
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
---
|
||||||
|
Title: Search Forms
|
||||||
|
---
|
||||||
|
|
||||||
|
# Search Forms
|
||||||
|
|
||||||
|
## Multiple search configuration
|
||||||
|
|
||||||
|
Since version 2.5.0 is now possible have multiple facet search configurations:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
In order to configure multiple search form you have to add your search configuration in `src/assets/plugins/app.search.json` in the property array `features.search`.
|
||||||
|
|
||||||
|
### Extension Properties
|
||||||
|
|
||||||
|
| Name | Type | Default value | Description |
|
||||||
|
| ---- | ---- | ------------- | ----------- |
|
||||||
|
| id | `string` | | Unique identifier of the search |
|
||||||
|
| name | `string` | "" | Display title of the form |
|
||||||
|
| order | `string` | | Visualization order in the dropdown |
|
||||||
|
| default | `boolean` | | if the search has to be used as default search |
|
||||||
|
| aca:fields| `string[]`| | list of aspects property to add in the query and search in the value for the given text. The property will be concatenated in AND|
|
||||||
|
|
||||||
|
### Search configuration properties
|
||||||
|
|
||||||
|
In order to learn more about :
|
||||||
|
-The search UI configuration possibilities refer to the [ADF Search configuration documentation](https://github.com/Alfresco/alfresco-ng2-components/blob/develop/docs/user-guide/search-configuration-guide.md)
|
||||||
|
-The search Query configuration possibilities refer to the [Full text search reference documentation](https://docs.alfresco.com/search-services/latest/using/)
|
||||||
|
|
||||||
|
|
@ -92,6 +92,3 @@ If you have entered an `=` symbol before the search term, then the search query
|
|||||||
| Disjunction | orange OR banana OR apple | Nodes that contain at least one of the terms **orange**, **banana** or **apple** |
|
| Disjunction | orange OR banana OR apple | Nodes that contain at least one of the terms **orange**, **banana** or **apple** |
|
||||||
| Exact term | =orange | Nodes that contain the exact term **orange** in any content |
|
| Exact term | =orange | Nodes that contain the exact term **orange** in any content |
|
||||||
|
|
||||||
## See also
|
|
||||||
|
|
||||||
<https://issues.alfresco.com/jira/browse/ACA-2219>
|
|
||||||
|
@ -14,6 +14,5 @@ Learn how to start developing with the Alfresco Content Application.
|
|||||||
- [Internationalization (i18n)](/getting-started/internationalization)
|
- [Internationalization (i18n)](/getting-started/internationalization)
|
||||||
- [CORS](/getting-started/cors)
|
- [CORS](/getting-started/cors)
|
||||||
- [Single Sign-On](/getting-started/sso)
|
- [Single Sign-On](/getting-started/sso)
|
||||||
- [Configuration](/getting-started/configuration)
|
|
||||||
- [Navigation](/getting-started/navigation)
|
- [Navigation](/getting-started/navigation)
|
||||||
- [Docker](/getting-started/docker)
|
- [Docker](/getting-started/docker)
|
||||||
|
BIN
docs/images/search-forms.png
Normal file
BIN
docs/images/search-forms.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 168 KiB |
@ -35,4 +35,10 @@
|
|||||||
- [Tutorials](/tutorials/)
|
- [Tutorials](/tutorials/)
|
||||||
- [Custom route with parameters](/tutorials/custom-route-with-parameters)
|
- [Custom route with parameters](/tutorials/custom-route-with-parameters)
|
||||||
- [Dialog actions](/tutorials/dialog-actions)
|
- [Dialog actions](/tutorials/dialog-actions)
|
||||||
|
- [Custom route with parameters](tutorials/custom-route-with-parameters)
|
||||||
|
- [How to create your first extension](/tutorials/how-to-create-your-first-extension)
|
||||||
|
- [How to extend Content Metadata](/tutorials/content-metadata)
|
||||||
|
- [How to extend File lists](/tutorials/file-lists)
|
||||||
|
- [How to extend File Preview](/tutorials/file-preview)
|
||||||
|
- [How to extend The Search Form](/tutorials/search-form)
|
||||||
- [Get help](/help)
|
- [Get help](/help)
|
||||||
|
@ -13,3 +13,9 @@ Learn more about developing with the Alfresco Content Application.
|
|||||||
- [Dialog actions](/tutorials/dialog-actions)
|
- [Dialog actions](/tutorials/dialog-actions)
|
||||||
- [How to create your first extension](/tutorials/how-to-create-your-first-extension)
|
- [How to create your first extension](/tutorials/how-to-create-your-first-extension)
|
||||||
- [How to install an existing extension](/tutorials/how-to-install-an-existing-extension)
|
- [How to install an existing extension](/tutorials/how-to-install-an-existing-extension)
|
||||||
|
- [Custom Route](/tutorials/custom-route)
|
||||||
|
- [Dialog Actions](/tutorials/dialog-actions)
|
||||||
|
- [File Preview](/tutorials/file-preview)
|
||||||
|
- [File Lists](/tutorials/file-lists)
|
||||||
|
- [Search Form](/tutorials/search-form)
|
||||||
|
- [Content Metadata](/tutorials/content-metadata)
|
||||||
|
187
docs/tutorials/content-metadata.md
Normal file
187
docs/tutorials/content-metadata.md
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
---
|
||||||
|
Title: Content Metadata
|
||||||
|
---
|
||||||
|
|
||||||
|
## Custom Content Metadata layout
|
||||||
|
|
||||||
|
In this tutorial, we are going to implement the following features:
|
||||||
|
|
||||||
|
- [MetadataLayout oriented config](#metadata-layout-oriented-config)
|
||||||
|
|
||||||
|
### Metadata Layout oriented config
|
||||||
|
|
||||||
|
Update `your-app.extensions.json` file, and insert a new entry to the `features.content-metadata-presets.custom`section:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"features": {
|
||||||
|
"content-metadata-presets": [
|
||||||
|
{
|
||||||
|
"custom": [
|
||||||
|
......
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If you need to configure the groups and properties in a more detailed way. With this type of configuration any property
|
||||||
|
of any aspect/type can be "cherry picked" and grouped into an accordion drawer, along with a translatable title defined
|
||||||
|
in the preset configuration.
|
||||||
|
|
||||||
|
In the example below we are going to display in a new group all the properties of the ```cm:versionable``` aspect
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"features": {
|
||||||
|
"content-metadata-presets": [
|
||||||
|
{
|
||||||
|
"custom": [
|
||||||
|
{
|
||||||
|
"id": "custom.features",
|
||||||
|
"title": "MY_CUSTOM_TITLE",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": "cm:versionable",
|
||||||
|
"aspect": "cm:versionable",
|
||||||
|
"properties": "*"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
In the example below we are going to display in a new group some of the ```cm:dublincore``` aspect:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"features": {
|
||||||
|
"content-metadata-presets": [
|
||||||
|
{
|
||||||
|
"custom": [
|
||||||
|
{
|
||||||
|
"id": "custom.features.two",
|
||||||
|
"title": "MY_CUSTOM_TITLE_TWO",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": "cm:dublincore",
|
||||||
|
"aspect": "cm:dublincore",
|
||||||
|
"properties": [
|
||||||
|
"cm:rights",
|
||||||
|
"cm:title"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
In the example below we are going to display in the same group a mix of ```cm:dublincore``` and ```cm:versionable```
|
||||||
|
aspect:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"features": {
|
||||||
|
"content-metadata-presets": [
|
||||||
|
{
|
||||||
|
"custom": [
|
||||||
|
{
|
||||||
|
"id": "custom.features.two",
|
||||||
|
"title": "MY_CUSTOM_TITLE_TWO",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": "cm:dublincore",
|
||||||
|
"aspect": "cm:dublincore",
|
||||||
|
"properties": [
|
||||||
|
"cm:rights",
|
||||||
|
"cm:title"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "cm:versionable",
|
||||||
|
"aspect": "cm:versionable",
|
||||||
|
"properties": "*"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
Note: empty aspect or aspect not associated to the node will not be displayed
|
||||||
|
|
||||||
|
# Exclude aspects or properties
|
||||||
|
|
||||||
|
|
||||||
|
You can also exclude specific aspects by adding the exclude property. It can be either a string if it's only one aspect or an array if you want to exclude multiple aspects at once:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"features": {
|
||||||
|
"content-metadata-presets": [
|
||||||
|
{
|
||||||
|
"custom": [
|
||||||
|
{
|
||||||
|
"id": "app.content.metadata.customSetting",
|
||||||
|
"includeAll": true,
|
||||||
|
"exclude": ["exif:exif", "owner:parameters"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
When using this configuration you can still whitelist aspects and properties as you desire. The example below shows this with an aspect-oriented config:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"features": {
|
||||||
|
"content-metadata-presets": [
|
||||||
|
{
|
||||||
|
"custom": [
|
||||||
|
{
|
||||||
|
"id": "app.content.metadata.customSetting",
|
||||||
|
"includeAll": true,
|
||||||
|
"exclude": ["cm:dublincore", "owner:parameters"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "custom.features.two",
|
||||||
|
"title": "MY_CUSTOM_TITLE_TWO",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": "cm:dublincore",
|
||||||
|
"aspect": "cm:dublincore",
|
||||||
|
"properties": [
|
||||||
|
"cm:rights",
|
||||||
|
"cm:title"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "cm:versionable",
|
||||||
|
"aspect": "cm:versionable",
|
||||||
|
"properties": "*"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
169
docs/tutorials/file-lists.md
Normal file
169
docs/tutorials/file-lists.md
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
---
|
||||||
|
Title: File Lists
|
||||||
|
---
|
||||||
|
|
||||||
|
## Custom File lists layout
|
||||||
|
|
||||||
|
In this tutorial, we are going to implement the following features:
|
||||||
|
|
||||||
|
- [Add a column in the Files list using a Node property](#add-a-column-in-the-files-list-using-a-node-property)
|
||||||
|
- [Replace a column in the Files list](#replace-a-column-in-the-files-list)
|
||||||
|
- [Add a Column in the Files list using a custom template](#add-a-column-in-the-files-list-using-a-node-property)
|
||||||
|
|
||||||
|
## File lists layout
|
||||||
|
|
||||||
|
The file list layout of:
|
||||||
|
- files
|
||||||
|
- libraries
|
||||||
|
- favoriteLibraries
|
||||||
|
- shared
|
||||||
|
- recent
|
||||||
|
- favorites
|
||||||
|
- trashcan
|
||||||
|
- searchLibraries
|
||||||
|
|
||||||
|
are all defined in the `/src/assets/app.extensions.json` of the content-app.
|
||||||
|
All the possible properties customizable in the column are:
|
||||||
|
|
||||||
|
### Properties
|
||||||
|
|
||||||
|
| Name | Type | Default value | Description |
|
||||||
|
| ---- | ---- | ------------- | ----------- |
|
||||||
|
| id | `string` | | Unique identifier of the column |
|
||||||
|
| key | `string` | | Data source key. Can be either a column/property key like `title` or a property path like `createdBy.name`. |
|
||||||
|
| title | `string` | "" | Display title of the column, typically used for column headers. You can use the i18n resource key to get it translated automatically. |
|
||||||
|
| type | `string` | "text" | Value type for the column. Possible settings are 'text', 'image', 'date', 'fileSize', 'location', and 'json'. |
|
||||||
|
| class | `string` | | Additional CSS class to be applied to column (header and cells). |
|
||||||
|
| sortable | `boolean` | true | Toggles ability to sort by this column, for example by clicking the column header. |
|
||||||
|
| template | `string` | optional |Custom layout template ID |
|
||||||
|
| desktopOnly | `string` | | Show the column only in bigger viewport |
|
||||||
|
| order | `string` | | Visualization order of the column |
|
||||||
|
|
||||||
|
|
||||||
|
#### Type
|
||||||
|
|
||||||
|
- **text** this will show the property as a plain text
|
||||||
|
- **fileSize** will convert the text into kb/mb/gb as needed.
|
||||||
|
- **json** Shows a JSON-formatted value
|
||||||
|
- **date** For the `date` column type, the Angular [DatePipe](https://angular.io/docs/ts/latest/api/common/DatePipe-class.html) formatting is used.
|
||||||
|
- **Location** this displays a clickable location link pointing to the parent path of the node.
|
||||||
|
|
||||||
|
### Add a column in the Files list using a Node property
|
||||||
|
|
||||||
|
Update the `your-app.extensions.json` file, and insert a new entry to the `features.documentList` section:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"features": {
|
||||||
|
"documentList": {
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"id": "app.files.type",
|
||||||
|
"key": "nodeType",
|
||||||
|
"title": "APP.DOCUMENT_LIST.COLUMNS.TYPE",
|
||||||
|
"type": "text",
|
||||||
|
"class": "adf-ellipsis-cell adf-expand-cell-5",
|
||||||
|
"sortable": true,
|
||||||
|
"desktopOnly": false,
|
||||||
|
"order": 102
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Now, once you run the application, you should see an extra column that contain the code of your custom component
|
||||||
|
|
||||||
|
### Replace a column in the Files list
|
||||||
|
|
||||||
|
In order to replace a column in the list you need to use the same `id` in your extension file. For example to replace the modifedOn column add the following JSON in `your-app.extensions.json`
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"features": {
|
||||||
|
"documentList": {
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"id": "app.files.modifiedOn",
|
||||||
|
"key": "modifiedByUser.displayName",
|
||||||
|
"title": "APP.DOCUMENT_LIST.COLUMNS.MODIFIED_FROM",
|
||||||
|
"type": "text",
|
||||||
|
"class": "adf-ellipsis-cell",
|
||||||
|
"sortable": true,
|
||||||
|
"desktopOnly": true,
|
||||||
|
"order": 40
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Add a Column in the Files list using a custom component template
|
||||||
|
|
||||||
|
As first step we can create our custom component in our extension:
|
||||||
|
```typescript
|
||||||
|
import { NameColumnComponent } from '@alfresco/adf-content-services';
|
||||||
|
import { Component, ChangeDetectionStrategy, ViewEncapsulation, ElementRef, OnInit, OnDestroy } from '@angular/core';
|
||||||
|
import { AlfrescoApiService } from '@alfresco/adf-core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'custom-template-column',
|
||||||
|
template: `<div *ngIf="isFile()">
|
||||||
|
This is a custom Template For File
|
||||||
|
</div>
|
||||||
|
<div *ngIf="!isFile()">
|
||||||
|
This is a custom Template For Folders
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
encapsulation: ViewEncapsulation.None,
|
||||||
|
host: { class: 'adf-datatable-content-cell adf-name-column' },
|
||||||
|
})
|
||||||
|
export class CustomTemplateComponent extends NameColumnComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
|
constructor(public elementRef: ElementRef, private apiService: AlfrescoApiService) {
|
||||||
|
super(elementRef, apiService);
|
||||||
|
}
|
||||||
|
|
||||||
|
isFile(){
|
||||||
|
return this.node.entry.isFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
In order to understand how to register a custom component refer to the [Registration](/extending/registration) documentation
|
||||||
|
Once your component is registered.
|
||||||
|
Register your new template component:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
extensions.setComponents({
|
||||||
|
'app.columns.custom': CustomTemplateComponent,
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
Add your new Column in `your-app.extensions.json` :
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"features": {
|
||||||
|
"documentList": {
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"id": "app.files.custom",
|
||||||
|
"key": "name",
|
||||||
|
"title": "APP.DOCUMENT_LIST.COLUMNS.CUSTOM",
|
||||||
|
"type": "text",
|
||||||
|
"class": "adf-ellipsis-cell adf-expand-cell-5",
|
||||||
|
"sortable": true,
|
||||||
|
"template": "app.columns.custom",
|
||||||
|
"desktopOnly": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
65
docs/tutorials/file-preview.md
Normal file
65
docs/tutorials/file-preview.md
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
---
|
||||||
|
Title: File preview
|
||||||
|
---
|
||||||
|
|
||||||
|
### File preview from a plugin with custom route
|
||||||
|
|
||||||
|
There might be scenarios where you build a plugin with a custom route, and from that route you might want to preview a file within an overlay.
|
||||||
|
When having a plugin's entry point in a custom route, using the `/view` root-level application routes for previewing a file might be contradictory, since hitting any of these urls results a navigation away from the original route implying a reload of the original route's entry component when closing the preview panel (navigating back).
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
Let's say you have a custom plugin with which you can start a process with any of your files. The plugin registers a custom route (`start-process`) with its entry component, where the user can start a process.
|
||||||
|
In this component the user can fill in a form with different values for text fields and selectboxes and select a file. But for file selection, we would like to provide a preview functionality (with the `PreviewComponent` provided by the core application) to let the user be sure that the right file was selected. Obviously having a form filled in values (but not saved) means, that we don't want to loose our filled in data just because we are previewing a file. Because of this we would like the file preview to be opened in an overlay mode. The core application has one overlay region already defined for this reason, called `viewer`. This is the named router outlet we need to target without route change.
|
||||||
|
|
||||||
|
#### Solution
|
||||||
|
|
||||||
|
In our plugin we need to do the following steps:
|
||||||
|
|
||||||
|
##### Registering the custom route in the plugin.json
|
||||||
|
|
||||||
|
We need to add the custom route with our entry component and its child route for the preview:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"routes": [
|
||||||
|
{
|
||||||
|
"id": "start-process",
|
||||||
|
"path": "start-process",
|
||||||
|
"parentRoute": "",
|
||||||
|
"layout": "app.layout.main",
|
||||||
|
// The component we register to be our entry point for this particular route
|
||||||
|
"component": "myplugin.components.start-process",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "start-process-preview",
|
||||||
|
// It can be accessed on the "/start-process(viewer:preview/nodeId)" route
|
||||||
|
"path": "preview/:nodeId",
|
||||||
|
"component": "app.components.preview",
|
||||||
|
"data": {
|
||||||
|
// Using history.back() when closing the preview
|
||||||
|
"navigateBackAsClose": true,
|
||||||
|
// Disabling complex action and buttons for the preview
|
||||||
|
"simplestMode": true
|
||||||
|
},
|
||||||
|
// We would like to target that named router outlet which is used for the viewer overlay
|
||||||
|
"outlet": "viewer"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Dispatching the right action within our component to open the file preview
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { PluginPreviewAction } from '@alfresco/aca-shared/store';
|
||||||
|
|
||||||
|
@Component({...})
|
||||||
|
export class StartProcessComponent {
|
||||||
|
onFilePreview({ nodeId }) {
|
||||||
|
this.store.dispatch(new PluginPreviewAction('start-process-cloud', nodeId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
82
docs/tutorials/search-form.md
Normal file
82
docs/tutorials/search-form.md
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
---
|
||||||
|
Title: Search Form
|
||||||
|
---
|
||||||
|
|
||||||
|
## Custom search form
|
||||||
|
|
||||||
|
From version 2.5.0 ACA search support multiple search configurations.
|
||||||
|
In this tutorial, we are going to implement the following features:
|
||||||
|
|
||||||
|
- [Add a new search form](#add-a-new-search-form)
|
||||||
|
- [Replace a search form](#replace-a-search-form)
|
||||||
|
- [Replace default search](#replace-default-search)
|
||||||
|
|
||||||
|
### Extension Properties
|
||||||
|
|
||||||
|
| Name | Type | Default value | Description |
|
||||||
|
| ---- | ---- | ------------- | ----------- |
|
||||||
|
| id | `string` | | Unique identifier of the search |
|
||||||
|
| name | `string` | "" | Display title of the form |
|
||||||
|
| order | `string` | | Visualization order in the dropdown |
|
||||||
|
| default | `boolean` | | if the search has to be used as default search |
|
||||||
|
| aca:fields| `string[]`| | list of aspects property to add in the query and search in the value for the given text. The property will be concatenated in AND|
|
||||||
|
|
||||||
|
### Search configuration properties
|
||||||
|
|
||||||
|
In order to learn more about :
|
||||||
|
-The search UI configuration possibilities refer to the [ADF Search configuration documentation](https://github.com/Alfresco/alfresco-ng2-components/blob/develop/docs/user-guide/search-configuration-guide.md)
|
||||||
|
-The search Query configuration possibilities refer to the [Full text search reference documentation](https://docs.alfresco.com/search-services/latest/using/)
|
||||||
|
|
||||||
|
### Add a new search form
|
||||||
|
|
||||||
|
Update `your-app.extensions.json` file, and insert a new entry to the `features.search` section:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"features": {
|
||||||
|
"search": [
|
||||||
|
{
|
||||||
|
"id": "app.search.custom_search",
|
||||||
|
"order": 200,
|
||||||
|
"name": "APP.SEARCH.MY_CUSTOM_SEARCH",
|
||||||
|
"default": false,
|
||||||
|
"aca:fields": [ "cm:name", "cm:title", "cm:description", "TEXT", "TAG"],
|
||||||
|
"filterQueries": [
|
||||||
|
{
|
||||||
|
"query": "+ASPECT: 'cm:person'"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Note that the entries of the filterQueries array are joined using the AND operator.
|
||||||
|
|
||||||
|
### Replace a search form
|
||||||
|
To replace an already present search form you need to add a new search configuration with the same `id` of an already present configuration
|
||||||
|
|
||||||
|
|
||||||
|
### Replace default search
|
||||||
|
To replace the default search with your configuration set to true the default field
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"features": {
|
||||||
|
"search": [
|
||||||
|
{
|
||||||
|
"id": "app.search.custom_search",
|
||||||
|
"order": 200,
|
||||||
|
"name": "APP.SEARCH.MY_CUSTOM_SEARCH",
|
||||||
|
"default": true,
|
||||||
|
"aca:fields": [ "cm:name", "cm:title", "cm:description", "TEXT", "TAG"],
|
||||||
|
"filterQueries": [
|
||||||
|
{
|
||||||
|
"query": "+ASPECT: 'cm:person'"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
Loading…
x
Reference in New Issue
Block a user