Skip to content

Commit da8324e

Browse files
authored
feat: move gse smv between connectedAPs (openscd#1680)
* feat: add wizard to move gse or smv * add unit tests * fix failing tests * add smv unit tests * feat: implement GSE/SMV move dialog and related functionality in editors * add styles for selected ap * rename helpers.ts. to foundation.ts * implement review comments
1 parent 26f6900 commit da8324e

File tree

16 files changed

+1181
-38
lines changed

16 files changed

+1181
-38
lines changed

packages/openscd/src/translations/de.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ export const de: Translations = {
9393
select: '{{tagName}} auswählen',
9494
edit: '{{tagName}} bearbeiten',
9595
add: '{{tagName}} hinzufügen',
96+
selectAp: 'ConnectedAP auswählen'
9697
},
9798
},
9899
openSCD: {

packages/openscd/src/translations/en.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ export const en = {
9191
select: 'Select {{tagName}}',
9292
edit: 'Edit {{tagName}}',
9393
add: 'Add {{tagName}}',
94+
selectAp: 'Select New ConnectedAP'
9495
},
9596
},
9697
openSCD: {
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/**
2+
* Returns the first element of type ConnectedAP in the provided element's hierarchy.
3+
* @param element - The reference element to search from
4+
* @returns An element of type ConnectedAP or null
5+
*/
6+
export function getCurrentConnectedAP(element: Element): Element | null {
7+
return element.closest('ConnectedAP');
8+
}
9+
10+
/**
11+
* Retrieves all ConnectedAP elements within the same IED as the provided element.
12+
*
13+
* @param element - The reference element to find the current ConnectedAP and its IED.
14+
* @param doc - The XML document containing the SubNetwork and ConnectedAP elements.
15+
* @returns An array of ConnectedAP elements belonging to the same IED as the provided element.
16+
*/
17+
export function getAllConnectedAPsOfSameIED(
18+
element: Element,
19+
doc: XMLDocument
20+
): Element[] {
21+
if (!element || !doc) {
22+
return [];
23+
}
24+
25+
const currentConnectedAP = getCurrentConnectedAP(element);
26+
if (!currentConnectedAP) {
27+
return [];
28+
}
29+
30+
const iedName = currentConnectedAP.getAttribute('iedName');
31+
32+
return Array.from(
33+
doc.querySelectorAll(`SubNetwork > ConnectedAP[iedName=${iedName}`)
34+
);
35+
}

packages/plugins/src/editors/communication/gse-editor.ts

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
customElement,
66
property,
77
state,
8+
css,
89
} from 'lit-element';
910

1011
import '@material/mwc-icon';
@@ -14,6 +15,7 @@ import { newWizardEvent } from '@openscd/open-scd/src/foundation.js';
1415
import { newActionEvent } from '@openscd/core/foundation/deprecated/editor.js';
1516
import { sizableGooseIcon } from '@openscd/open-scd/src/icons/icons.js';
1617
import { editGseWizard } from '../../wizards/gse.js';
18+
import { getAllConnectedAPsOfSameIED } from './foundation.js';
1719

1820
@customElement('gse-editor')
1921
export class GseEditor extends LitElement {
@@ -36,6 +38,16 @@ export class GseEditor extends LitElement {
3638
this.dispatchEvent(newWizardEvent(editGseWizard(this.element)));
3739
}
3840

41+
private openGseMoveDialog(): void {
42+
this.dispatchEvent(
43+
new CustomEvent('request-gse-move', {
44+
detail: { element: this.element },
45+
bubbles: true,
46+
composed: true,
47+
})
48+
);
49+
}
50+
3951
remove(): void {
4052
if (this.element)
4153
this.dispatchEvent(
@@ -50,6 +62,12 @@ export class GseEditor extends LitElement {
5062
}
5163

5264
render(): TemplateResult {
65+
const allConnectedAPsOfSameIED = getAllConnectedAPsOfSameIED(
66+
this.element,
67+
this.doc
68+
);
69+
const hasMoreThanOneConnectedAP = allConnectedAPsOfSameIED.length > 1;
70+
5371
return html`<action-icon label="${this.label}" .icon="${sizableGooseIcon}"
5472
><mwc-fab
5573
slot="action"
@@ -61,8 +79,26 @@ export class GseEditor extends LitElement {
6179
slot="action"
6280
mini
6381
icon="delete"
64-
@click="${() => this.remove()}}"
65-
></mwc-fab
66-
></action-icon>`;
82+
@click="${() => this.remove()}"
83+
></mwc-fab>
84+
<mwc-fab
85+
slot="action"
86+
mini
87+
icon="forward"
88+
class="gse-move-button"
89+
?disabled="${!hasMoreThanOneConnectedAP}"
90+
@click="${() => this.openGseMoveDialog()}"
91+
>
92+
</mwc-fab>
93+
</action-icon> `;
6794
}
95+
96+
static styles = css`
97+
:host(:focus-within) .gse-move-button[disabled] {
98+
color: var(--mdc-theme-text-disabled-on-light, #9e9e9e);
99+
pointer-events: none;
100+
cursor: not-allowed;
101+
opacity: 0.5;
102+
}
103+
`;
68104
}

packages/plugins/src/editors/communication/smv-editor.ts

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
customElement,
66
property,
77
state,
8+
css,
89
} from 'lit-element';
910

1011
import '@material/mwc-icon';
@@ -14,6 +15,7 @@ import { sizableSmvIcon } from '@openscd/open-scd/src/icons/icons.js';
1415
import { newWizardEvent } from '@openscd/open-scd/src/foundation.js';
1516
import { newActionEvent } from '@openscd/core/foundation/deprecated/editor.js';
1617
import { editSMvWizard } from '../../wizards/smv.js';
18+
import { getAllConnectedAPsOfSameIED } from './foundation.js';
1719

1820
@customElement('smv-editor')
1921
export class SmvEditor extends LitElement {
@@ -36,6 +38,16 @@ export class SmvEditor extends LitElement {
3638
this.dispatchEvent(newWizardEvent(editSMvWizard(this.element)));
3739
}
3840

41+
private openSmvMoveDialog(): void {
42+
this.dispatchEvent(
43+
new CustomEvent('request-smv-move', {
44+
detail: { element: this.element },
45+
bubbles: true,
46+
composed: true,
47+
})
48+
);
49+
}
50+
3951
remove(): void {
4052
if (this.element)
4153
this.dispatchEvent(
@@ -50,6 +62,12 @@ export class SmvEditor extends LitElement {
5062
}
5163

5264
render(): TemplateResult {
65+
const allConnectedAPsOfSameIED = getAllConnectedAPsOfSameIED(
66+
this.element,
67+
this.doc
68+
);
69+
const hasMoreThanOneConnectedAP = allConnectedAPsOfSameIED.length > 1;
70+
5371
return html`<action-icon label="${this.label}" .icon="${sizableSmvIcon}"
5472
><mwc-fab
5573
slot="action"
@@ -61,8 +79,26 @@ export class SmvEditor extends LitElement {
6179
slot="action"
6280
mini
6381
icon="delete"
64-
@click="${() => this.remove()}}"
65-
></mwc-fab
66-
></action-icon>`;
82+
@click="${() => this.remove()}"
83+
></mwc-fab>
84+
<mwc-fab
85+
slot="action"
86+
mini
87+
icon="forward"
88+
class="smv-move-button"
89+
?disabled=${!hasMoreThanOneConnectedAP}
90+
@click="${() => this.openSmvMoveDialog()}"
91+
>
92+
</mwc-fab>
93+
</action-icon>`;
6794
}
95+
96+
static styles = css`
97+
:host(:focus-within) .smv-move-button[disabled] {
98+
color: var(--mdc-theme-text-disabled-on-light, #9e9e9e);
99+
pointer-events: none;
100+
cursor: not-allowed;
101+
opacity: 0.5;
102+
}
103+
`;
68104
}

0 commit comments

Comments
 (0)