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

feat: Support edit api v2 #1581

Merged
merged 36 commits into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
ccdfa48
WIP: Add edit api v2 support
clepski Oct 4, 2024
44255c3
feat: WIP Convert v1 to v2 events
clepski Oct 10, 2024
e2060cc
feat: Dispatch edit completed
clepski Oct 11, 2024
1cae3d5
feat: WIP Handle undo and redo events
clepski Oct 14, 2024
a2f6552
feat: Add log text and remove old code
clepski Oct 17, 2024
5b8b62c
feat: Cleanup and fix complex event
clepski Oct 17, 2024
4f93c8e
feat: Clean up code
clepski Oct 18, 2024
0ef22da
feat: Add history state
clepski Oct 21, 2024
782ba0e
feat: Remove editing mixin
clepski Oct 22, 2024
65fcef4
feat: Move edit event converter to openscd package
clepski Oct 22, 2024
64a0505
feat: Remove editing mixin
clepski Oct 22, 2024
18a2061
test: Add tests
clepski Oct 23, 2024
e606c8b
chore: Remove outdated export
clepski Oct 23, 2024
d54b30b
test: Fix tests
clepski Oct 24, 2024
20b16c9
test: Fix history tests
clepski Oct 25, 2024
50f26fc
test: Remove editing tests
clepski Oct 25, 2024
c8b0652
test: Disable broken test
clepski Oct 25, 2024
78b922f
Revert "test: Disable broken test"
clepski Oct 25, 2024
146de19
Merge branch 'main' into feat/edit-api-v2
clepski Oct 25, 2024
faa1511
feat: Fix convert move ref
clepski Oct 25, 2024
a36755c
feat: Adjust converter to edit api v1 behavior
clepski Oct 25, 2024
5393f00
test: Fix test
clepski Oct 25, 2024
9359d83
Merge branch 'main' into feat/edit-api-v2
clepski Oct 28, 2024
e370f96
test: Adjust mock wizard editor
clepski Oct 28, 2024
41cf660
test: Fix tests
clepski Oct 28, 2024
70ddafb
feat: Fix self reference bug
clepski Oct 28, 2024
2772a04
test: Fix tests
clepski Oct 30, 2024
7ee2e37
test: Skip broken tests
clepski Oct 30, 2024
f50c71c
test: Add Editor tests
clepski Oct 30, 2024
6b2ceb9
test: Add Editor tests
clepski Oct 31, 2024
c4b774d
doc: Add edit api doc
clepski Nov 4, 2024
83e68a6
doc: Add editor action API doc
clepski Nov 4, 2024
305109b
doc: Add link to edit event doc
clepski Nov 4, 2024
c23c849
feat: Trigger validate after edit
clepski Nov 13, 2024
26a01eb
fix: Add review suggestions
clepski Nov 13, 2024
f455522
Merge branch 'main' into feat/edit-api-v2
clepski Nov 13, 2024
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,4 @@ How the documentation is organized.
A high-level overview of how it’s organized will help you know where to look for certain things:

- [⚖️ Decisions](docs/decisions/README.md) documents the decisions we made and why we made them.
- [✏️ Edit event API](docs/core-api/edit-api.md) documents the edit event API.
251 changes: 251 additions & 0 deletions docs/core-api/edit-api.md
clepski marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
# Edit Event API

Open SCD offers an API for editing the scd document which can be used with [Html Custom Events](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent). The main Open SCD components listens to events of the type `oscd-edit`, applies the changes to the `doc` and updates the `editCount` property.

The edits to the `doc` will be done in place, e.g. the `doc` changes but will keep the same reference. If your plugin needs to react to changes in the doc, you should listen to changes in the `editCount` property.

### Event factory
clepski marked this conversation as resolved.
Show resolved Hide resolved

Open SCD core exports a factory function for edit events, so you do not have to build them manually.

```ts
function newEditEvent<E extends Edit>(
edit: E,
initiator: Initiator = 'user'
): EditEvent

type Edit = Insert | Update | Remove | Edit[];

type Initiator = 'user' | 'system' | 'undo' | 'redo' | string;

```

Example for remove.

```ts
import { newEditEvent, Remove } from '@openscd/core';

const remove: Remove = { node: someNode };
const removeEvent = newEditEvent(remove);

someComponent.dispatchEvent(removeEvent);

```


### Insert

Insert events can be used to add new nodes or move existing nodes in the document. Since a node can only have one parent, using an insert on an existing node will replace it's previous parent with the new parent, essentially moving the node to a different position in the xml tree.

If the reference is not `null`, the node will be inserted before the reference node. The reference has to be a child node of the parent. And if the reference is `null` the node will be added as the last child of the parent.

```ts
interface Insert {
parent: Node;
node: Node;
reference: Node | null;
}
```


### Remove

This event will remove the node from the document.

```ts
interface Remove {
node: Node;
}
```


### Update

Update can add, remove or change attributes on an existing node. Existing attributes will only be removed, if `null` is passed as value in the event's `attributes` property.


```ts
interface Update {
element: Element;
attributes: Partial<Record<string, AttributeValue>>;
}

// Attirubte value

type AttributeValue = string | null | NamespacedAttributeValue;

type NamespacedAttributeValue = {
value: string | null;
namespaceURI: string | null;
};
```

Example for adding and changing values.

```ts

const update: Update = {
element: elementToUpdate,
attributes: {
name: 'new name',
value: 'new value'
}
};

```

To remove an existing value pass `null` as value.

```ts

const update: Update = {
element: elementToUpdate,
attributes: {
attributeToRemove: null
}
};

```

Update also supports [Xml namespaces](https://developer.mozilla.org/en-US/docs/Related/IMSC/Namespaces#namespaced_attributes) for attributes. To change namespaced attributes you need to pass an `NamespacedAttributeValue` instead of a plain `string`.

```ts

const update: Update = {
element: elementToUpdate,
attributes: {
name: {
value: 'namespaced name',
namespaceURI: 'http://www.iec.ch/61850/2003/SCLcoordinates'
},
type: {
value: 'namespaced type',
namespaceURI: 'http://www.iec.ch/61850/2003/SCLcoordinates'
},
}
};

```

Adding, updating and removing attributes with and without namespaces can be combined in a single `Update`.

### Complex edits

Complex edits can be used to apply multiple edits as a single event. This will create a single entry in the history. You can create complex edit events by passing an array of edit events to the `newEditEvent` factory function.

```ts
import { newEditEvent } from '@openscd/core';

const complexEditEvent = newEditEvent([ insert, update, remove ]);

someComponent.dispatchEvent(complexEditEvent);

```



## History

All edit events with initiator `user` will create a history log entry and can be undone and redone through the history addon.


## Editor Action API (deprecated)

Before the edit event API the editor action API was used to edit the `doc`. It is also custom event based and listens to the events of the type `editor-action`.

For backwards compatibility the API is still supported, but it is recommended to use the edit event API instead. Internally editor actions are converted to edit events.

### Breaking changes due to migration

With open SCD version **v0.36.0** and higher some editor action features are no longer supported.

* The edtior action properties `derived` and `checkValidity` do not have any effect.
* All validation checks have been removed (i.e. check for unique `id` attribute on element before create).
* The `title` for `ComplexAction` does not have any effect.

### Event factory
clepski marked this conversation as resolved.
Show resolved Hide resolved

```ts

function newActionEvent<T extends EditorAction>(
action: T,
initiator: Initiator = 'user',
eventInitDict?: CustomEventInit<Partial<EditorActionDetail<T>>>
): EditorActionEvent<T>

type SimpleAction = Update | Create | Replace | Delete | Move;
type ComplexAction = {
actions: SimpleAction[];
title: string;
derived?: boolean;
};
type EditorAction = SimpleAction | ComplexAction;

```


### Create

`Create` actions are converted to `Insert` events.

```ts
interface Create {
new: { parent: Node; element: Node; reference?: Node | null };
derived?: boolean;
checkValidity?: () => boolean;
}
```

### Move

`Move` actions are converted to `Insert` events.

```ts
interface Move {
old: { parent: Element; element: Element; reference?: Node | null };
new: { parent: Element; reference?: Node | null };
derived?: boolean;
checkValidity?: () => boolean;
}
```


### Delete

`Delete` actions are converted to `Remove` events.

```ts
interface Delete {
old: { parent: Node; element: Node; reference?: Node | null };
derived?: boolean;
checkValidity?: () => boolean;
}
```


### Update

`Update` actions are converted to `Update` events.

```ts
interface Update {
element: Element;
oldAttributes: Record<string, string | null>;
newAttributes: Record<string, string | null>;
derived?: boolean;
checkValidity?: () => boolean;
}
```

### Replace

`Replace` actions are converted to a complex event with `Remove` and `Insert` events.

```ts
interface Replace {
old: { element: Element };
new: { element: Element };
derived?: boolean;
checkValidity?: () => boolean;
}
```
1 change: 0 additions & 1 deletion packages/core/foundation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ export type {

export { cyrb64 } from './foundation/cyrb64.js';

export { Editing } from './mixins/Editing.js';
export type { Plugin, PluginSet } from './foundation/plugin.js';

export { newEditCompletedEvent } from './foundation/edit-completed-event.js';
Expand Down
5 changes: 3 additions & 2 deletions packages/core/foundation/deprecated/history.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { EditorAction } from './editor';
import { Edit } from '../edit-event.js';

type InfoEntryKind = 'info' | 'warning' | 'error';

Expand All @@ -12,7 +12,8 @@ export interface LogDetailBase {
/** The [[`LogEntry`]] for a committed [[`EditorAction`]]. */
export interface CommitDetail extends LogDetailBase {
kind: 'action';
action: EditorAction;
redo: Edit;
undo: Edit;
}
/** A [[`LogEntry`]] for notifying the user. */
export interface InfoDetail extends LogDetailBase {
Expand Down
Loading
Loading