Skip to content

Commit 106688b

Browse files
authored
feat: edit and delete virtual IED elements (openscd#1715)
* feat: edit IED manufacturer * feat: edit and delete accesspoint+refs * feat: edit and delete LDevice * feat: edit LN(0) and delete LN * test: update snapshots and unit tests * fix: update inst duplication check * feat: add access point wizard tests
1 parent 0c1074b commit 106688b

24 files changed

+831
-124
lines changed

packages/openscd/src/translations/de.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,10 +284,23 @@ export const de: Translations = {
284284
noResults: 'Keine Logical Node Types gefunden',
285285
},
286286
},
287+
accesspoint: {
288+
wizard: {
289+
nameHelper: 'AccessPoint Name',
290+
descHelper: 'AccessPoint Beschreibung',
291+
title: {
292+
add: 'AccessPoint hinzufügen',
293+
edit: 'AccessPoint bearbeiten',
294+
delete: 'AccessPoint mit Abhängigkeiten entfernen',
295+
references: 'Gelöschte Abhängikeiten',
296+
},
297+
},
298+
},
287299
ied: {
288300
wizard: {
289301
nameHelper: 'Name des IED',
290302
descHelper: 'Beschreibung des IED',
303+
manufacturerHelper: 'Hersteller des IED',
291304
title: {
292305
edit: 'IED bearbeiten',
293306
delete: 'IED mit Abhängigkeiten entfernen',
@@ -304,6 +317,7 @@ export const de: Translations = {
304317
nameHelper: 'Name des Logisches Gerät',
305318
noNameSupportHelper: 'IED unterstützt keine funktionale Benennung',
306319
descHelper: 'Beschreibung des Logisches Gerät',
320+
instHelper: 'Instanz des Logisches Gerät',
307321
title: {
308322
edit: 'Logisches Gerät bearbeiten',
309323
},

packages/openscd/src/translations/en.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,10 +281,23 @@ export const en = {
281281
noResults: 'No Logical Node Types found',
282282
},
283283
},
284+
accesspoint: {
285+
wizard: {
286+
nameHelper: 'AccessPoint name',
287+
descHelper: 'AccessPoint description',
288+
title: {
289+
add: 'Add AccessPoint',
290+
edit: 'Edit AccessPoint',
291+
delete: 'Remove AccessPoint with references',
292+
references: 'References to be removed',
293+
},
294+
},
295+
},
284296
ied: {
285297
wizard: {
286298
nameHelper: 'IED name',
287299
descHelper: 'IED description',
300+
manufacturerHelper: 'IED manufacturer',
288301
title: {
289302
edit: 'Edit IED',
290303
delete: 'Remove IED with references',
@@ -301,6 +314,7 @@ export const en = {
301314
nameHelper: 'Logical device name',
302315
noNameSupportHelper: "IED doesn't support Functional Naming",
303316
descHelper: 'Logical device description',
317+
instHelper: 'Logical device inst',
304318
title: {
305319
edit: 'Edit logical device',
306320
},

packages/plugins/src/editors/ied/access-point-container.ts

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,18 @@ import {
88
TemplateResult,
99
} from 'lit-element';
1010
import { nothing } from 'lit-html';
11-
import { get } from 'lit-translate';
11+
import { get, translate } from 'lit-translate';
1212

1313
import {
1414
getDescriptionAttribute,
1515
getNameAttribute,
1616
newWizardEvent,
1717
} from '@openscd/open-scd/src/foundation.js';
1818
import { accessPointIcon } from '@openscd/open-scd/src/icons/ied-icons.js';
19+
import { newActionEvent } from '@openscd/core/foundation/deprecated/editor.js';
20+
import { wizards } from '../../wizards/wizard-library.js';
1921
import { editServicesWizard } from '../../wizards/services.js';
22+
import { removeAccessPointWizard } from '../../wizards/accesspoint.js';
2023

2124
import '@openscd/open-scd/src/action-pane.js';
2225
import './server-container.js';
@@ -29,6 +32,16 @@ export class AccessPointContainer extends Container {
2932
@property()
3033
selectedLNClasses: string[] = [];
3134

35+
@state()
36+
private get lnElements(): Element[] {
37+
return Array.from(this.element.querySelectorAll(':scope > LN')).filter(
38+
element => {
39+
const lnClass = element.getAttribute('lnClass') ?? '';
40+
return this.selectedLNClasses.includes(lnClass);
41+
}
42+
);
43+
}
44+
3245
protected updated(_changedProperties: PropertyValues): void {
3346
super.updated(_changedProperties);
3447

@@ -45,27 +58,22 @@ export class AccessPointContainer extends Container {
4558
return html``;
4659
}
4760

48-
return html` <abbr slot="action" title="${get('iededitor.settings')}">
49-
<mwc-icon-button
50-
icon="settings"
51-
@click=${() => this.openSettingsWizard(services)}
52-
></mwc-icon-button>
53-
</abbr>`;
61+
return html` <mwc-icon-button
62+
slot="action"
63+
icon="settings"
64+
title="${get('iededitor.settings')}"
65+
@click=${() => this.openSettingsWizard(services)}
66+
></mwc-icon-button>`;
5467
}
5568

56-
private openSettingsWizard(services: Element): void {
57-
const wizard = editServicesWizard(services);
69+
private openEditWizard(): void {
70+
const wizard = wizards['AccessPoint'].edit(this.element);
5871
if (wizard) this.dispatchEvent(newWizardEvent(wizard));
5972
}
6073

61-
@state()
62-
private get lnElements(): Element[] {
63-
return Array.from(this.element.querySelectorAll(':scope > LN')).filter(
64-
element => {
65-
const lnClass = element.getAttribute('lnClass') ?? '';
66-
return this.selectedLNClasses.includes(lnClass);
67-
}
68-
);
74+
private openSettingsWizard(services: Element): void {
75+
const wizard = editServicesWizard(services);
76+
if (wizard) this.dispatchEvent(newWizardEvent(wizard));
6977
}
7078

7179
private header(): TemplateResult {
@@ -75,11 +83,37 @@ export class AccessPointContainer extends Container {
7583
return html`${name}${desc ? html` &mdash; ${desc}` : nothing}`;
7684
}
7785

86+
private removeAccessPoint(): void {
87+
const wizard = removeAccessPointWizard(this.element);
88+
if (wizard) {
89+
this.dispatchEvent(newWizardEvent(() => wizard));
90+
} else {
91+
// If no Wizard is needed, just remove the element.
92+
this.dispatchEvent(
93+
newActionEvent({
94+
old: { parent: this.element.parentElement!, element: this.element },
95+
})
96+
);
97+
}
98+
}
99+
78100
render(): TemplateResult {
79101
const lnElements = this.lnElements;
80102

81103
return html`<action-pane .label="${this.header()}">
82104
<mwc-icon slot="icon">${accessPointIcon}</mwc-icon>
105+
<mwc-icon-button
106+
slot="action"
107+
icon="delete"
108+
title="${translate('remove')}"
109+
@click=${() => this.removeAccessPoint()}
110+
></mwc-icon-button>
111+
<mwc-icon-button
112+
slot="action"
113+
icon="edit"
114+
title="${translate('edit')}"
115+
@click=${() => this.openEditWizard()}
116+
></mwc-icon-button>
83117
${this.renderServicesIcon()}
84118
${Array.from(this.element.querySelectorAll(':scope > Server')).map(
85119
server =>

packages/plugins/src/editors/ied/ldevice-container.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
getLdNameAttribute,
2424
newWizardEvent,
2525
} from '@openscd/open-scd/src/foundation.js';
26+
import { newActionEvent } from '@openscd/core/foundation/deprecated/editor.js';
2627

2728
import { wizards } from '../../wizards/wizard-library.js';
2829
import { Container } from './foundation.js';
@@ -104,11 +105,25 @@ export class LDeviceContainer extends Container {
104105
this.dispatchEvent(newEditEventV2(inserts));
105106
}
106107

108+
private removeLDevice(): void {
109+
this.dispatchEvent(
110+
newActionEvent({
111+
old: { parent: this.element.parentElement!, element: this.element },
112+
})
113+
);
114+
}
115+
107116
render(): TemplateResult {
108117
const lnElements = this.lnElements;
109118

110119
return html`<action-pane .label="${this.header()}">
111120
<mwc-icon slot="icon">${logicalDeviceIcon}</mwc-icon>
121+
<mwc-icon-button
122+
slot="action"
123+
icon="delete"
124+
title="${translate('remove')}"
125+
@click=${() => this.removeLDevice()}
126+
></mwc-icon-button>
112127
<abbr slot="action" title="${get('edit')}">
113128
<mwc-icon-button
114129
icon="edit"

packages/plugins/src/editors/ied/ln-container.ts

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import { customElement, html, query, TemplateResult } from 'lit-element';
22
import { nothing } from 'lit-html';
33
import { until } from 'lit-html/directives/until';
4-
import { get } from 'lit-translate';
4+
import { get, translate } from 'lit-translate';
55

66
import {
77
getInstanceAttribute,
88
getNameAttribute,
99
newWizardEvent,
1010
} from '@openscd/open-scd/src/foundation.js';
11+
import { newActionEvent } from '@openscd/core/foundation/deprecated/editor.js';
1112
import { IconButtonToggle } from '@material/mwc-icon-button-toggle';
1213

1314
import '@openscd/open-scd/src/action-pane.js';
@@ -65,30 +66,44 @@ export class LNContainer extends Container {
6566
if (wizard) this.dispatchEvent(newWizardEvent(wizard));
6667
}
6768

69+
private removeElement(): void {
70+
if (this.element.tagName === 'LN') {
71+
this.dispatchEvent(
72+
newActionEvent({
73+
old: { parent: this.element.parentElement!, element: this.element },
74+
})
75+
);
76+
}
77+
}
78+
6879
render(): TemplateResult {
6980
const doElements = this.getDOElements();
7081

7182
return html`<action-pane .label="${until(this.header())}">
7283
${doElements.length > 0
73-
? html`<abbr slot="action">
74-
<mwc-icon-button
75-
slot="action"
76-
mini
77-
icon="edit"
78-
@click="${() => this.openEditWizard()}}"
79-
></mwc-icon-button>
80-
</abbr>
81-
<abbr
82-
slot="action"
83-
title="${get('iededitor.toggleChildElements')}"
84-
>
85-
<mwc-icon-button-toggle
86-
id="toggleButton"
87-
onIcon="keyboard_arrow_up"
88-
offIcon="keyboard_arrow_down"
89-
@click=${() => this.requestUpdate()}
90-
></mwc-icon-button-toggle>
91-
</abbr>`
84+
? html`${this.element.tagName === 'LN'
85+
? html`<mwc-icon-button
86+
slot="action"
87+
icon="delete"
88+
title="${translate('remove')}"
89+
@click=${() => this.removeElement()}
90+
></mwc-icon-button>`
91+
: nothing}<abbr slot="action">
92+
<mwc-icon-button
93+
slot="action"
94+
mini
95+
icon="edit"
96+
@click="${() => this.openEditWizard()}}"
97+
></mwc-icon-button>
98+
</abbr>
99+
<abbr slot="action" title="${get('iededitor.toggleChildElements')}">
100+
<mwc-icon-button-toggle
101+
id="toggleButton"
102+
onIcon="keyboard_arrow_up"
103+
offIcon="keyboard_arrow_down"
104+
@click=${() => this.requestUpdate()}
105+
></mwc-icon-button-toggle>
106+
</abbr>`
92107
: nothing}
93108
${this.toggleButton?.on
94109
? doElements.map(

packages/plugins/src/editors/ied/server-container.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ export class ServerContainer extends Container {
8181

8282
const ln0 = createElement(this.doc, 'LN0', {
8383
lnClass: 'LLN0',
84+
inst: '',
8485
lnType: lnTypeId,
8586
});
8687

0 commit comments

Comments
 (0)