Skip to content

Commit 758da72

Browse files
authored
feat(editors/subscriber-later-binding): Add plugin with filterable FCDA list (openscd#945)
* refactor(smv-laterbinding-list): created a reusable clone called later-binding-list * feat: GooseSubscriberLaterBindingPlugin with filterable FCDA list * refactor: implemented suggested changes from @dlabordus and @JakobVogelsang and refactored translations obj structure * test: refactored svc test file and implemented missing GooseLaterBinding tests * chore: renaming controlBlockElement to controlElement and missing snapshot test file
1 parent 7989fb7 commit 758da72

File tree

15 files changed

+706
-100
lines changed

15 files changed

+706
-100
lines changed

public/js/plugins.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ export const officialPlugins = [
2727
default: true,
2828
kind: 'editor',
2929
},
30+
{
31+
name: 'Subscriber Later Binding (GOOSE)',
32+
src: '/src/editors/GooseSubscriberLaterBinding.js',
33+
icon: 'link',
34+
default: false,
35+
kind: 'editor',
36+
},
3037
{
3138
name: 'Subscriber (SMV)',
3239
src: '/src/editors/SampledValuesSubscription.js',
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { LitElement, property, html, TemplateResult, css } from 'lit-element';
2+
3+
import './subscription/later-binding/fcda-later-binding-list.js';
4+
5+
export default class GooseSubscribeLaterBindingPlugin extends LitElement {
6+
@property({ attribute: false })
7+
doc!: XMLDocument;
8+
9+
render(): TemplateResult {
10+
return html`<div>
11+
<div class="container">
12+
<fcda-later-binding-list .doc=${this.doc} controlTag="GSEControl">
13+
</fcda-later-binding-list>
14+
</div>
15+
</div>`;
16+
}
17+
18+
static styles = css`
19+
:host {
20+
width: 100vw;
21+
}
22+
23+
.container {
24+
padding: 8px 6px 16px;
25+
}
26+
`;
27+
}

src/editors/SMVSubscriberLaterBinding.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { css, html, LitElement, property, TemplateResult } from 'lit-element';
22

3-
import './subscription/smv-laterbinding/svc-laterbinding-list.js';
3+
import './subscription/later-binding/fcda-later-binding-list.js';
44
import './subscription/smv-laterbinding/ext-ref-laterbinding-list.js';
55

66
/** An editor [[`plugin`]] for Subscribe Later Binding (SMV). */
@@ -11,8 +11,12 @@ export default class SMVSubscribeLaterBindingPlugin extends LitElement {
1111
render(): TemplateResult {
1212
return html`<div>
1313
<div class="container">
14-
<svc-later-binding-list class="column" .doc=${this.doc}>
15-
</svc-later-binding-list>
14+
<fcda-later-binding-list
15+
class="column"
16+
.doc=${this.doc}
17+
controlTag="SampledValueControl"
18+
>
19+
</fcda-later-binding-list>
1620
<extref-later-binding-list class="column" .doc=${this.doc}>
1721
</extref-later-binding-list>
1822
</div>

src/editors/subscription/smv-laterbinding/svc-laterbinding-list.ts renamed to src/editors/subscription/later-binding/fcda-later-binding-list.ts

Lines changed: 48 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,26 @@ import { wizards } from '../../../wizards/wizard-library.js';
2727

2828
import { styles } from '../foundation.js';
2929

30-
import { getFcdaTitleValue, newFcdaSelectEvent } from './foundation.js';
30+
import {
31+
getFcdaTitleValue,
32+
newFcdaSelectEvent,
33+
} from '../smv-laterbinding/foundation.js';
3134

3235
/**
33-
* A sub element for showing all Sampled Value Controls.
34-
* A Sample Value Control can be edited using the standard wizard.
36+
* A sub element for showing all Goose/Sampled Value Controls.
37+
* A control can be edited using the standard wizard.
3538
* And when selecting a FCDA Element a custom event is fired, so other list can be updated.
3639
*/
37-
@customElement('svc-later-binding-list')
38-
export class SVCLaterBindingList extends LitElement {
40+
@customElement('fcda-later-binding-list')
41+
export class FCDALaterBindingList extends LitElement {
3942
@property({ attribute: false })
4043
doc!: XMLDocument;
44+
@property()
45+
controlTag!: 'SampledValueControl' | 'GSEControl';
4146

4247
// The selected Elements when a FCDA Line is clicked.
4348
@state()
44-
selectedSvcElement: Element | undefined;
49+
selectedControlElement: Element | undefined;
4550
@state()
4651
selectedFcdaElement: Element | undefined;
4752

@@ -52,41 +57,43 @@ export class SVCLaterBindingList extends LitElement {
5257
parent.addEventListener('open-doc', this.resetSelection);
5358
}
5459

55-
private getSvcElements(): Element[] {
60+
private getControlElements(): Element[] {
5661
if (this.doc) {
5762
return Array.from(
58-
this.doc.querySelectorAll('LN0 > SampledValueControl')
63+
this.doc.querySelectorAll(`LN0 > ${this.controlTag}`)
5964
).sort((a, b) => compareNames(`${identity(a)}`, `${identity(b)}`));
6065
}
6166
return [];
6267
}
6368

64-
private getFcdaElements(svcElement: Element): Element[] {
65-
const lnElement = svcElement.parentElement;
69+
private getFcdaElements(controlElement: Element): Element[] {
70+
const lnElement = controlElement.parentElement;
6671
if (lnElement) {
6772
return Array.from(
6873
lnElement.querySelectorAll(
69-
`:scope > DataSet[name=${svcElement.getAttribute('datSet')}] > FCDA`
74+
`:scope > DataSet[name=${controlElement.getAttribute(
75+
'datSet'
76+
)}] > FCDA`
7077
)
7178
).sort((a, b) => compareNames(`${identity(a)}`, `${identity(b)}`));
7279
}
7380
return [];
7481
}
7582

76-
private openEditWizard(svcElement: Element): void {
77-
const wizard = wizards['SampledValueControl'].edit(svcElement);
83+
private openEditWizard(controlElement: Element): void {
84+
const wizard = wizards[this.controlTag].edit(controlElement);
7885
if (wizard) this.dispatchEvent(newWizardEvent(wizard));
7986
}
8087

8188
private resetSelection(): void {
82-
this.selectedSvcElement = undefined;
89+
this.selectedControlElement = undefined;
8390
this.selectedFcdaElement = undefined;
8491
}
8592

86-
private onFcdaSelect(svcElement: Element, fcdaElement: Element) {
93+
private onFcdaSelect(controlElement: Element, fcdaElement: Element) {
8794
this.resetSelection();
8895

89-
this.selectedSvcElement = svcElement;
96+
this.selectedControlElement = controlElement;
9097
this.selectedFcdaElement = fcdaElement;
9198
}
9299

@@ -96,22 +103,25 @@ export class SVCLaterBindingList extends LitElement {
96103
// When the document is updated, we will fire the event again.
97104
if (
98105
_changedProperties.has('doc') ||
99-
_changedProperties.has('selectedSvcElement') ||
106+
_changedProperties.has('selectedControlElement') ||
100107
_changedProperties.has('selectedFcdaElement')
101108
) {
102109
this.dispatchEvent(
103-
newFcdaSelectEvent(this.selectedSvcElement, this.selectedFcdaElement)
110+
newFcdaSelectEvent(
111+
this.selectedControlElement,
112+
this.selectedFcdaElement
113+
)
104114
);
105115
}
106116
}
107117

108-
renderFCDA(svcElement: Element, fcdaElement: Element): TemplateResult {
118+
renderFCDA(controlElement: Element, fcdaElement: Element): TemplateResult {
109119
return html`<mwc-list-item
110120
graphic="large"
111121
twoline
112122
class="subitem"
113-
@click=${() => this.onFcdaSelect(svcElement, fcdaElement)}
114-
value="${identity(svcElement)} ${identity(fcdaElement)}"
123+
@click=${() => this.onFcdaSelect(controlElement, fcdaElement)}
124+
value="${identity(controlElement)} ${identity(fcdaElement)}"
115125
>
116126
<span>${getFcdaTitleValue(fcdaElement)}</span>
117127
<span slot="secondary">
@@ -128,49 +138,53 @@ export class SVCLaterBindingList extends LitElement {
128138
}
129139

130140
render(): TemplateResult {
131-
const svcElements = this.getSvcElements();
141+
const controlElements = this.getControlElements();
132142
return html` <section tabindex="0">
133-
${svcElements.length > 0
143+
${controlElements.length > 0
134144
? html`<h1>
135-
${translate('subscription.smvLaterBinding.svcList.title')}
145+
${translate(
146+
`subscription.laterBinding.${this.controlTag}.controlBlockList.title`
147+
)}
136148
</h1>
137149
<filtered-list>
138-
${svcElements.map(svcElement => {
139-
const fcdaElements = this.getFcdaElements(svcElement);
150+
${controlElements.map(controlElement => {
151+
const fcdaElements = this.getFcdaElements(controlElement);
140152
return html`
141153
<mwc-list-item
142154
noninteractive
143155
graphic="icon"
144156
twoline
145157
hasMeta
146-
value="${identity(svcElement)} ${fcdaElements
158+
value="${identity(controlElement)} ${fcdaElements
147159
.map(fcdaElement => identity(fcdaElement) as string)
148160
.join(' ')}"
149161
>
150162
<mwc-icon-button
151163
slot="meta"
152164
icon="edit"
153165
class="interactive"
154-
@click=${() => this.openEditWizard(svcElement)}
166+
@click=${() => this.openEditWizard(controlElement)}
155167
></mwc-icon-button>
156168
<span
157-
>${getNameAttribute(svcElement)}
158-
${getDescriptionAttribute(svcElement)
159-
? html`${getDescriptionAttribute(svcElement)}`
169+
>${getNameAttribute(controlElement)}
170+
${getDescriptionAttribute(controlElement)
171+
? html`${getDescriptionAttribute(controlElement)}`
160172
: nothing}</span
161173
>
162-
<span slot="secondary">${identity(svcElement)}</span>
174+
<span slot="secondary">${identity(controlElement)}</span>
163175
<mwc-icon slot="graphic">${smvIcon}</mwc-icon>
164176
</mwc-list-item>
165177
<li divider role="separator"></li>
166178
${fcdaElements.map(fcdaElement =>
167-
this.renderFCDA(svcElement, fcdaElement)
179+
this.renderFCDA(controlElement, fcdaElement)
168180
)}
169181
`;
170182
})}
171183
</filtered-list>`
172184
: html`<h1>
173-
${translate('subscription.smvLaterBinding.svcList.noSvcFound')}
185+
${translate(
186+
`subscription.laterBinding.${this.controlTag}.controlBlockList.noControlBlockFound`
187+
)}
174188
</h1>`}
175189
</section>`;
176190
}

src/editors/subscription/smv-laterbinding/ext-ref-laterbinding-list.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -213,10 +213,13 @@ export class ExtRefLaterBindingList extends LitElement {
213213
: undefined;
214214

215215
return html`<h1>
216-
${translate('subscription.smvLaterBinding.extRefList.title', {
217-
svcName: svcName ?? '-',
218-
fcdaName: fcdaName ?? '-',
219-
})}
216+
${translate(
217+
'subscription.laterBinding.extRefList.SampledValueControl.title',
218+
{
219+
svcName: svcName ?? '-',
220+
fcdaName: fcdaName ?? '-',
221+
}
222+
)}
220223
</h1>`;
221224
}
222225

@@ -261,7 +264,7 @@ export class ExtRefLaterBindingList extends LitElement {
261264
)}`
262265
: html`<mwc-list-item graphic="large" noninteractive>
263266
${translate(
264-
'subscription.smvLaterBinding.extRefList.noSubscribedExtRefs'
267+
'subscription.laterBinding.extRefList.noSubscribedExtRefs'
265268
)}
266269
</mwc-list-item>`}
267270
`;
@@ -312,7 +315,7 @@ export class ExtRefLaterBindingList extends LitElement {
312315
)}`
313316
: html`<mwc-list-item graphic="large" noninteractive>
314317
${translate(
315-
'subscription.smvLaterBinding.extRefList.noAvailableExtRefs'
318+
'subscription.laterBinding.extRefList.noAvailableExtRefs'
316319
)}
317320
</mwc-list-item>`}
318321
`;
@@ -329,9 +332,7 @@ export class ExtRefLaterBindingList extends LitElement {
329332
`
330333
: html`
331334
<h1>
332-
${translate(
333-
'subscription.smvLaterBinding.extRefList.noSelection'
334-
)}
335+
${translate('subscription.laterBinding.extRefList.noSelection')}
335336
</h1>
336337
`}
337338
</section>`;

src/translations/de.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -371,14 +371,24 @@ export const de: Translations = {
371371
'Zeigt verbundene Sampled Value(s) des ausgewählten IED',
372372
},
373373
},
374-
smvLaterBinding: {
375-
svcList: {
376-
title: 'Sampled Values and verknüpfte Datensätze im Projekt',
377-
noSvcFound: 'Kein Sampled-Value-Kontrolblock im Projekt',
374+
laterBinding: {
375+
SampledValueControl: {
376+
controlBlockList: {
377+
title: 'Sampled Values and verknüpfte Datensätze im Projekt',
378+
noControlBlockFound: 'Kein Sampled-Value-Kontrolblock im Projekt',
379+
},
380+
},
381+
GSEControl: {
382+
controlBlockList: {
383+
title: '???',
384+
noControlBlockFound: '???',
385+
},
378386
},
379387
extRefList: {
380-
title:
381-
'Ausgewählter Sampled Value Datenpunkt "{{ svcName }}" / "{{ fcdaName }}"',
388+
SampledValueControl: {
389+
title:
390+
'Ausgewählter Sampled Value Datenpunkt "{{ svcName }}" / "{{ fcdaName }}"',
391+
},
382392
noSelection: 'Kein Daten-Attribut ausgewählt',
383393
noSubscribedExtRefs: 'Keine verknüpften externen Referenzen',
384394
noAvailableExtRefs:

src/translations/en.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -368,14 +368,24 @@ export const en = {
368368
'Show subscribed Sampled Value(s) publisher for selected IED',
369369
},
370370
},
371-
smvLaterBinding: {
372-
svcList: {
373-
title: 'List of Sampled Values Controls with linked FCDAs',
374-
noSvcFound: 'No Sampled Value Controls found',
371+
laterBinding: {
372+
SampledValueControl: {
373+
controlBlockList: {
374+
title: 'List of Sampled Values Controls with linked FCDAs',
375+
noControlBlockFound: 'No Sampled Value Controls found',
376+
},
377+
},
378+
GSEControl: {
379+
controlBlockList: {
380+
title: 'List of Goose Controls with linked FCDAs',
381+
noControlBlockFound: 'No Goose Controls found',
382+
},
375383
},
376384
extRefList: {
377-
title:
378-
'Selected Sampled Value data "{{ svcName }}" / FCDA "{{ fcdaName }}"',
385+
SampledValueControl: {
386+
title:
387+
'Selected Sampled Value data "{{ svcName }}" / FCDA "{{ fcdaName }}"',
388+
},
379389
noSelection: 'No data attribute selected',
380390
noSubscribedExtRefs: 'No subscribed ExtRefs',
381391
noAvailableExtRefs: 'No available ExtRefs to subscribe',

test/integration/__snapshots__/open-scd.test.snap.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
/* @web/test-runner snapshot v1 */
22
export const snapshots = {};
33

4-
snapshots['open-scd looks like its snapshot'] = `<mwc-drawer
4+
snapshots["open-scd looks like its snapshot"] =
5+
`<mwc-drawer
56
class="mdc-theme--surface"
67
hasheader=""
78
id="menu"
@@ -635,6 +636,21 @@ snapshots['open-scd looks like its snapshot'] = `<mwc-drawer
635636
</mwc-icon>
636637
Subscriber (GOOSE)
637638
</mwc-check-list-item>
639+
<mwc-check-list-item
640+
aria-disabled="false"
641+
class="official"
642+
graphic="control"
643+
hasmeta=""
644+
left=""
645+
mwc-list-item=""
646+
tabindex="-1"
647+
value="/src/editors/GooseSubscriberLaterBinding.js"
648+
>
649+
<mwc-icon slot="meta">
650+
link
651+
</mwc-icon>
652+
Subscriber Later Binding (GOOSE)
653+
</mwc-check-list-item>
638654
<mwc-check-list-item
639655
aria-disabled="false"
640656
class="official"
@@ -1364,3 +1380,4 @@ snapshots['open-scd looks like its snapshot'] = `<mwc-drawer
13641380
</mwc-dialog>
13651381
`;
13661382
/* end snapshot open-scd looks like its snapshot */
1383+

0 commit comments

Comments
 (0)