diff --git a/src/translations/de.ts b/src/translations/de.ts index 45d65a092a..3d4a5c596b 100644 --- a/src/translations/de.ts +++ b/src/translations/de.ts @@ -66,6 +66,7 @@ export const de: Translations = { iedsloading: 'IEDs werden geladen...', commmap: 'Kommunikationszuordnung', gsecontrol: 'GOOSEs anzeigen', + smvcontrol: 'Sampled Values anzeigen', }, editing: { created: '{{ name }} hinzugefügt', @@ -162,7 +163,7 @@ export const de: Translations = { searchHelper: 'IED auswählen', searchHelperDesc: '({{description}})', missing: 'Kein IED vorhanden', - toggleChildElements: "???" + toggleChildElements: '???', }, powertransformer: { wizard: { diff --git a/src/translations/en.ts b/src/translations/en.ts index 25055143d1..0f2698340d 100644 --- a/src/translations/en.ts +++ b/src/translations/en.ts @@ -64,6 +64,7 @@ export const en = { iedsloading: 'Loading IEDs...', commmap: 'Communication mapping', gsecontrol: 'Show all GOOSEs', + smvcontrol: 'Show all Sampled Values', }, editing: { created: 'Added {{ name }}', @@ -156,10 +157,10 @@ export const en = { }, }, iededitor: { - searchHelper: "Select IED", - searchHelperDesc: "({{description}})", + searchHelper: 'Select IED', + searchHelperDesc: '({{description}})', missing: 'No IED', - toggleChildElements: "Toggle child elements" + toggleChildElements: 'Toggle child elements', }, powertransformer: { wizard: { @@ -168,7 +169,7 @@ export const en = { title: { edit: 'Edit power transformer', }, - } + }, }, voltagelevel: { name: 'Voltage level', diff --git a/src/wizards/sampledvaluecontrol.ts b/src/wizards/sampledvaluecontrol.ts new file mode 100644 index 0000000000..54036fd0d0 --- /dev/null +++ b/src/wizards/sampledvaluecontrol.ts @@ -0,0 +1,29 @@ +import { html } from 'lit-element'; +import { get } from 'lit-translate'; + +import { identity, isPublic, Wizard } from '../foundation.js'; + +export function selectSampledValueControlWizard(element: Element): Wizard { + const smvControls = Array.from( + element.querySelectorAll('SampledValueControl') + ).filter(isPublic); + + return [ + { + title: get('wizard.title.select', { tagName: 'SampledValueControl' }), + content: [ + html`${smvControls.map( + smvControl => + html`${smvControl.getAttribute('name')}${identity(smvControl)}` + )}`, + ], + }, + ]; +} diff --git a/src/zeroline-pane.ts b/src/zeroline-pane.ts index ea858788fc..c4b6f623e5 100644 --- a/src/zeroline-pane.ts +++ b/src/zeroline-pane.ts @@ -18,11 +18,12 @@ import './zeroline/substation-editor.js'; import './zeroline/ied-editor.js'; import { Settings } from './Setting.js'; import { communicationMappingWizard } from './wizards/commmap-wizards.js'; -import { gooseIcon } from './icons.js'; +import { gooseIcon, smvIcon } from './icons.js'; import { isPublic, newWizardEvent } from './foundation.js'; import { selectGseControlWizard } from './wizards/gsecontrol.js'; import { wizards } from './wizards/wizard-library.js'; import { getAttachedIeds } from './zeroline/foundation.js'; +import { selectSampledValueControlWizard } from './wizards/sampledvaluecontrol.js'; function shouldShowIEDs(): boolean { return localStorage.getItem('showieds') === 'on'; @@ -47,6 +48,7 @@ export class ZerolinePane extends LitElement { @query('#commmap') commmap!: IconButton; @query('#showieds') showieds!: IconButtonToggle; @query('#gsecontrol') gsecontrol!: IconButton; + @query('#smvcontrol') smvcontrol!: IconButton; @query('#createsubstation') createsubstation!: IconButton; openCommunicationMapping(): void { @@ -65,6 +67,11 @@ export class ZerolinePane extends LitElement { if (wizard) this.dispatchEvent(newWizardEvent(wizard)); } + openSampledValueControlSelection(): void { + const wizard = selectSampledValueControlWizard(this.doc.documentElement); + if (wizard) this.dispatchEvent(newWizardEvent(wizard)); + } + toggleShowIEDs(): void { if (shouldShowIEDs()) setShowIEDs('off'); else setShowIEDs('on'); @@ -119,6 +126,13 @@ export class ZerolinePane extends LitElement { >${gooseIcon} + ${smvIcon} ${this.renderIedContainer()} diff --git a/src/zeroline/ied-editor.ts b/src/zeroline/ied-editor.ts index bdff48db51..28b57b33e3 100644 --- a/src/zeroline/ied-editor.ts +++ b/src/zeroline/ied-editor.ts @@ -13,9 +13,10 @@ import { Fab } from '@material/mwc-fab'; import '../action-icon.js'; import { createClientLnWizard } from '../wizards/clientln.js'; -import { gooseIcon } from '../icons.js'; +import { gooseIcon, smvIcon } from '../icons.js'; import { newWizardEvent } from '../foundation.js'; import { selectGseControlWizard } from '../wizards/gsecontrol.js'; +import { selectSampledValueControlWizard } from '../wizards/sampledvaluecontrol.js'; /** [[`SubstationEditor`]] subeditor for a child-less `IED` element. */ @customElement('ied-editor') @@ -44,6 +45,11 @@ export class IedEditor extends LitElement { if (wizard) this.dispatchEvent(newWizardEvent(wizard)); } + private openSmvControlSelection(): void { + const wizard = selectSampledValueControlWizard(this.element); + if (wizard) this.dispatchEvent(newWizardEvent(wizard)); + } + render(): TemplateResult { return html`${gooseIcon}${smvIcon} `; } diff --git a/test/integration/zeroline-pane.test.ts b/test/integration/zeroline-pane.test.ts index aa60104a52..65369d4c1e 100644 --- a/test/integration/zeroline-pane.test.ts +++ b/test/integration/zeroline-pane.test.ts @@ -44,6 +44,20 @@ describe('zeroline-pane wizarding editing integration', () => { ); }); + it('opens selectSampledValueControlWizard for the complete SCL file', async () => { + zeroline.smvcontrol.click(); + await parent.updateComplete; + + expect(parent.wizardUI.dialog).to.exist; + const smvControlList = ( + parent.wizardUI.dialog?.querySelector('filtered-list') + ); + await smvControlList.updateComplete; + expect(smvControlList.items.length).to.equal( + doc.querySelectorAll('SampledValueControl').length + ); + }); + it('add Substation element with createSubstationWizard', async () => { expect(doc.querySelector('Substation[name="newSubstation"]')).to.not.exist; zeroline.createsubstation.click(); diff --git a/test/testfiles/wizards/sampledvaluecontrol.scd b/test/testfiles/wizards/sampledvaluecontrol.scd new file mode 100644 index 0000000000..78f25eeaa8 --- /dev/null +++ b/test/testfiles/wizards/sampledvaluecontrol.scd @@ -0,0 +1,584 @@ + + +
+ TrainingIEC61850 + + + +
+ + + 100.0 + +
+

192.168.210.111

+

255.255.255.0

+

192.168.210.1

+

1,3,9999,23

+

23

+

00000001

+

0001

+

0001

+
+ +
+

01-0C-CD-01-00-10

+

005

+

4

+

0010

+
+ 10 + 10000 +
+ + 10 + 10000 + + +

RJ45

+
+
+
+ + +
+

192.168.0.112

+

255.255.255.0

+

192.168.210.1

+

1,3,9999,23

+

23

+

00000001

+

0001

+

0001

+
+
+ +
+

192.168.0.113

+

255.255.255.0

+

192.168.210.1

+

1,3,9999,23

+

23

+

00000001

+

0001

+

0001

+
+ +
+

01-0C-CD-04-00-20

+

007

+

4

+

4002

+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + status-only + + + + + + + + + + + + + + + status-only + + + + + + + + + direct-with-normal-security + + + + + + + sbo-with-normal-security + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + status-only + + + + + + + + + + + + + + + + + + status-only + + + + + + + + + + + + + + + + + + + + + + status-only + + + + + + + status-only + + + + + + + + + + + status-only + + + + + + + direct-with-enhanced-security + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + sbo-with-enhanced-security + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IEC 61850-8-1:2003 + + + + + + + + + + + + + + + + + + + + + + + + + status-only + direct-with-normal-security + sbo-with-normal-security + direct-with-enhanced-security + sbo-with-enhanced-security + + + on + blocked + test + test/blocked + off + + + Ok + Warning + Alarm + + + not-supported + bay-control + station-control + remote-control + automatic-bay + automatic-station + automatic-remote + maintenance + process + + + +
diff --git a/test/unit/__snapshots__/zeroline-pane.test.snap.js b/test/unit/__snapshots__/zeroline-pane.test.snap.js index 9d8721ab10..4084b943bc 100644 --- a/test/unit/__snapshots__/zeroline-pane.test.snap.js +++ b/test/unit/__snapshots__/zeroline-pane.test.snap.js @@ -32,6 +32,10 @@ snapshots["zeroline-pane per default looks like the latest snapshot"] = + + + +
@@ -75,6 +79,10 @@ snapshots["zeroline-pane showieds looks like the latest snapshot"] = + + + +
diff --git a/test/unit/wizards/__snapshots__/sampledvaluecontrol.test.snap.js b/test/unit/wizards/__snapshots__/sampledvaluecontrol.test.snap.js new file mode 100644 index 0000000000..4506ae2c61 --- /dev/null +++ b/test/unit/wizards/__snapshots__/sampledvaluecontrol.test.snap.js @@ -0,0 +1,52 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["Wizards for SCL element SampledValueControl define a select wizard that looks like the latest snapshot"] = +` +
+ + + + MSVCB01 + + + IED2>>CBSW>MSVCB01 + + + + + MSVCB01 + + + IED3>>MU01>MSVCB01 + + + +
+ + +
+`; +/* end snapshot Wizards for SCL element SampledValueControl define a select wizard that looks like the latest snapshot */ + diff --git a/test/unit/wizards/sampledvaluecontrol.test.ts b/test/unit/wizards/sampledvaluecontrol.test.ts new file mode 100644 index 0000000000..1e312d2e4f --- /dev/null +++ b/test/unit/wizards/sampledvaluecontrol.test.ts @@ -0,0 +1,38 @@ +import { expect, fixture, html } from '@open-wc/testing'; +import { SinonSpy, spy } from 'sinon'; + +import '../../mock-wizard.js'; +import { MockWizard } from '../../mock-wizard.js'; + +import { selectSampledValueControlWizard } from '../../../src/wizards/sampledvaluecontrol.js'; + +describe('Wizards for SCL element SampledValueControl', () => { + let doc: XMLDocument; + let element: MockWizard; + + let actionEvent: SinonSpy; + + beforeEach(async () => { + element = await fixture(html``); + doc = await fetch('test/testfiles/wizards/sampledvaluecontrol.scd') + .then(response => response.text()) + .then(str => new DOMParser().parseFromString(str, 'application/xml')); + + actionEvent = spy(); + window.addEventListener('editor-action', actionEvent); + }); + + describe('define a select wizard that', () => { + beforeEach(async () => { + const wizard = selectSampledValueControlWizard(doc.documentElement); + element.workflow.push(wizard); + await element.requestUpdate(); + + await element.wizardUI.requestUpdate(); // make sure wizard is rendered + }); + + it('looks like the latest snapshot', async () => { + await expect(element.wizardUI.dialog).dom.to.equalSnapshot(); + }).timeout(5000); + }); +}); diff --git a/test/unit/zeroline/__snapshots__/ied-editor.test.snap.js b/test/unit/zeroline/__snapshots__/ied-editor.test.snap.js index 16b24bc053..c2ed11ba51 100644 --- a/test/unit/zeroline/__snapshots__/ied-editor.test.snap.js +++ b/test/unit/zeroline/__snapshots__/ied-editor.test.snap.js @@ -22,6 +22,14 @@ snapshots["A component to visualize SCL element IED looks like the latest snapsh + + + + `; /* end snapshot A component to visualize SCL element IED looks like the latest snapshot */ diff --git a/test/unit/zeroline/ied-editor.test.ts b/test/unit/zeroline/ied-editor.test.ts index 5394545c32..3cc76d3d43 100644 --- a/test/unit/zeroline/ied-editor.test.ts +++ b/test/unit/zeroline/ied-editor.test.ts @@ -52,6 +52,17 @@ describe('A component to visualize SCL element IED', () => { ); }); + it('triggers select wizard for SampledValueControl element on action button click', async () => { + (( + element.shadowRoot?.querySelector('mwc-fab[class="selectsmv"]') + )).click(); + + await element.requestUpdate(); + + expect(wizardEvent).to.have.be.calledOnce; + expect(wizardEvent.args[0][0].detail.wizard[0].title).to.contain('select'); + }); + it('triggers create wizard for ClientLN element on action button click', async () => { (( element.shadowRoot?.querySelector('mwc-fab[class="connectreport"]')