Skip to content

Commit

Permalink
Universal editor doc (#75)
Browse files Browse the repository at this point in the history
* SITES-20344: Documentation for Universal Editor Extensibility in UIX Docs

* fix: Added documentation about Properties Rails

- jira: SITES-21286

* fix: address CR comments

- jira: SITES-21286

* fix: address CR comments

- jira: SITES-21286

* fix: address CR comments

- jira: SITES-21286

* fix: address CR comments

- jira: SITES-21286

---------

Co-authored-by: Valerii Naida <vnayda@adobe.com>
  • Loading branch information
irenelagno and naydav committed Apr 26, 2024
1 parent 5a08af3 commit c92f041
Show file tree
Hide file tree
Showing 18 changed files with 953 additions and 1 deletion.
40 changes: 39 additions & 1 deletion gatsby-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ module.exports = {
title: "AEM Content Fragments Editor",
path: "/services/aem-cf-editor/"
},
{
title: "Universal Editor",
path: "/services/aem-universal-editor/"
},
{
title: "Adobe Commerce Admin",
path: "https://developer.adobe.com/commerce/extensibility/admin-ui-sdk/"
Expand Down Expand Up @@ -214,7 +218,41 @@ module.exports = {
path: "/extension-manager/extension-developed-by-adobe/content-fragments-workflows"
}
]
}
},
{
title: "Extension Points",
path: "/services/aem-universal-editor/api/",
pages: [
{
title: "Common Concepts",
path: "/services/aem-universal-editor/api/commons/"
},
{
title: "Header Menu",
path: "/services/aem-universal-editor/api/header-menu/"
},
{
title: "Modal Dialogs",
path: "/services/aem-universal-editor/api/modal/"
},
{
title: "Custom panels in Properties Rail",
path: "/services/aem-universal-editor/api/properties-rails/"
},
{
title: "Overriding Default Rendering of Item Types",
path: "/services/aem-universal-editor/api/item-types-renderers/"
},
{
title: "Working with events",
path: "/services/aem-universal-editor/api/events/"
},
{
title: "Retrieving Data from the Universal Editor",
path: "/services/aem-universal-editor/api/data/"
}
]
},
]
},
plugins: [
Expand Down
6 changes: 6 additions & 0 deletions src/pages/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,12 @@ Start building extensions for AEM Content Fragments editor

<DiscoverBlock slots="link, text"/>

[Universal Editor](services/aem-universal-editor/)

Start building extensions for the Universal Editor

<DiscoverBlock slots="link, text"/>

[Adobe Commerce Admin](https://developer.adobe.com/commerce/extensibility/admin-ui-sdk/)

Start building extensions for Adobe Commerce Admin
Expand Down
100 changes: 100 additions & 0 deletions src/pages/services/aem-universal-editor/api/commons/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
---
title: Universal Editor Extensibility
description: Learn how to customize Universal Editor
contributors:
- https://github.com/AdobeDocs/uix
---

# Common Concepts in Creating Extensions

Understand the fundamentals required to develop an extension for the Universal Editor.

## Extension Point

Universal editor has an `universal-editor/ui/1` [extension point](https://developer.adobe.com/app-builder/docs/guides/extensions/) that allows you to extend its functionality.
To declare it to be used by your extension, you need to add the following configuration to your `app.config.yaml` at the
root of your extension:

```yaml
extensions:
universal-editor/ui/1:
$include: src/universal-editor-ui-1/ext.config.yaml
```
Here is an example of `ext.config.yaml` file:

```yaml
operations:
view:
- type: web
impl: index.html
actions: actions
web: web-src
```

## Extension Registration

Interaction between UI Extension and Universal Editor starts with the initialization process that includes extension's
capabilities registration so Universal Editor knows when to invoke the extension. Registration is done by `register`
method provided by `@adobe/uix-guest` library. This asynchronous method takes single object that describes extension
and returns object representing connection to the Universal Editor.

Method `register` should be invoked after extension initialization page is loaded.

Extension registration data must include:

- `id` - string with random extension identifier. This identifier useful for debugging of interaction between Universal
Editor and extension and needed if extension provides custom UI.
- `methods` - objects with extension code exposed to the Universal Editor console. All methods are grouped into
namespaces that represents extension points provided by the Universal Editor.
Currently, the following **namespaces** are available:
- _headerMenu_, that allows to add buttons to the header of the Universal Editor;
- _rightPanel_, that allows to add custom content under the rails to the right panel of the Universal Editor;
- _canvas_, that allows to add custom renderer for data types

```js
import { register } from "@adobe/uix-guest";
// ...
const guestConnection = await register({
id: "extension-id",
methods: {
headerMenu: {
getButtons() {
// ..
}
},
rightPanel: {
getPanels() {
// ..
}
},
canvas: {
getRenderers() {
// ..
}
}
}
});
// ...
```
## Building Extension UI


In cases where a UI Extension manages data or sends data to a remote service, the register method is the only one expected to be called. If the UI Extension includes its own interface, it should be presented on a separate page. If this interface needs data from the Universal Editor or needs to trigger any logic, it should establish a connection using the attach method.

```js
import { attach } from "@adobe/uix-guest";
const guestConnection = await attach({ id: "extension-id" });
const state = await connection.host.editorState.get();
const token = await connection.sharedContext.get("token");
const model = await connection.host.field.getModel();
```

## Set up communication with Universal Editor

Both `register` and `attach` function of `@adobe/uix-guest` returns same connection object that has `host` property and
expose API of Universal Editor exposed for UI Extensions. Through this api you can access data from the universal editor as well as send data to it.

Check [this section](../data) to learn about common concepts on how to achive this
85 changes: 85 additions & 0 deletions src/pages/services/aem-universal-editor/api/data/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
---
title: Data exchange - Universal Editor Extensibility
description: Learn how to exchange data between Universal Editor and your extension
contributors:
- https://github.com/AdobeDocs/uix
---

# Learn how to exchange data between Universal Editor and your extension

As we develop extensions for the Universal Editor, it's essential to facilitate data exchange between the editor and the extension. There are two main categories of data involved:
- User-specific information, like IMS organization.
- Editor-specific information, such as the current editor location.

Below you can find the details on how to access these data categories.

### Shared Context

The shared context is a dataset that Universal Editor shares with UI Extensions. It's used to understand the context of
the user who is running Universal Editor. You can access the shared context through the `sharedContext` property of the
connection object.

```js
import { attach } from "@adobe/uix-guest";

useEffect(() => {
(async () => {
const guestConnection = await attach({ id: extensionId });

setGuestConnection(guestConnection);
})();
}, []);

...

const context = guestConnection.sharedContext;
const hostAppLocale = context.get("locale");
```

Available data in the shared context:

| Key | Type | Description |
|--------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| locale | `string` | Locale string for globalization of current user |
| theme | `string` | Available [options](https://experienceleague.adobe.com/en/docs/experience-manager-cloud-service/content/overview/aem-cloud-service-on-unified-shell#changing-to-dark-theme): "light" or "dark". The theme selected by current user |
| orgId | `string` | IMS org ID |
| token | `string` | User token |
| authScheme | `string` | Auth schema that should be used during communication with host application |


### Editor State

The editor state is a dataset that Universal Editor shares with UI Extensions. It's used to understand the current state
of the editor. You can access the editor state through the `editorState` property of the host object.

Below is an example of how you can access editor state properties, e.g., connections.

```js
import { attach } from "@adobe/uix-guest";

...

useEffect(() => {
(async () => {
const guestConnection = await attach({ id: extensionId });

setGuestConnection(guestConnection);
})();
}, []);
...

const editorState = await guestConnection.host.editorState.get();
const {connections} = editorState;

...

```
Available data in the editor state:

| Key | Type | Sample | Description |
|-----|---------------------------|-----------------------------------------------------------------------|-------------|
| connections | `obj` | { "aemconnection": "aem:%auth_instance_url%" } | [Connections](https://experienceleague.adobe.com/en/docs/experience-manager-cloud-service/content/implementing/developing/universal-editor/getting-started#connections) which are used in the app are stored as `<meta>` tags in the page’s `<head>`. |
| selected | `obj<string, boolean>` | {fcb38012-c4c7-51a8-896c-79e76kjk: true} | Element that is currently edited. |
| editables | `[objects]` | Array[{id: '33661..", type: 'reference', resource: "urn:..., ..}, {}] | List of elements that might be edited. The editable element object includes [proper metadata](https://experienceleague.adobe.com/en/docs/experience-manager-cloud-service/content/implementing/developing/universal-editor/attributes-types). |
| location | `string` | "%locationString%" | The current page location |
| customTokens | `obj<string, string>` | {"aemconnection":""} | Custom tokens available for connections |
43 changes: 43 additions & 0 deletions src/pages/services/aem-universal-editor/api/events/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
title: Working with the events - Universal Editor Extensibility
description: Leveraging universal editor events within your application
contributors:
- https://github.com/AdobeDocs/uix
---

# Working with Events

The Universal Editor sends defined events to remote applications. In case the remote application has no custom event listener for the sent event, a fallback event listener provided by the universal-editor-cors package is executed.

### Working with Events

The Universal Editor offers a list of events that extensions can subscribe to in order to respond to changes in content or the user interface.
Refer to this [document](https://experienceleague.adobe.com/en/docs/experience-manager-cloud-service/content/implementing/developing/universal-editor/events) for the available event list.

For instance, here's an example of how to subscribe to the `aue:ui-select` event:

```js

useEffect(() => {
(async () => {
const guestConnection = await attach({id: extensionId});
...
await guestConnection.host.remoteApp.addEventListener('aue:ui-select', console.log('event recieved!'));
...
})();
}, []);
```

If your business logic requires sending an event to the Universal Editor, you can use the `dispatchEvent` method.
Here's an example of how to dispatch the `aue:ui-select` event:

```js
useEffect(() => {
(async () => {
const guestConnection = await attach({id: extensionId});
...
await guestConnection.host.remoteApp.dispatchEvent('aue:ui-select', {data: 'some data'});
...
})();
}, []);
```
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit c92f041

Please sign in to comment.