diff --git a/src/editors/substation/line-editor.ts b/src/editors/substation/line-editor.ts new file mode 100644 index 0000000000..459c200e6e --- /dev/null +++ b/src/editors/substation/line-editor.ts @@ -0,0 +1,103 @@ +import { + customElement, + html, + LitElement, + TemplateResult, + property, + state, +} from 'lit-element'; + +import './conducting-equipment-editor.js'; +import './function-editor.js'; +import './general-equipment-editor.js'; +import './l-node-editor.js'; +import { getChildElementsByTagName } from '../../foundation.js'; + +@customElement('line-editor') +export class LineEditor extends LitElement { + /** The document being edited as provided to editor by [[`Zeroline`]]. */ + @property({ attribute: false }) + doc!: XMLDocument; + /** SCL element Line */ + @property({ attribute: false }) + element!: Element; + /** Whether `Function` and `LNode` are rendered */ + @property({ type: Boolean }) + showfunctions = false; + + @state() + get header(): string { + const name = this.element.getAttribute('name') ?? ''; + const desc = this.element.getAttribute('desc'); + + return `${name} ${desc ? `—${desc}` : ''}`; + } + + private renderConductingEquipments(): TemplateResult { + const ConductingEquipments = getChildElementsByTagName( + this.element, + 'ConductingEquipment' + ); + return html` ${ConductingEquipments.map( + ConductingEquipment => + html`` + )}`; + } + + private renderGeneralEquipments(): TemplateResult { + const GeneralEquipments = getChildElementsByTagName( + this.element, + 'GeneralEquipment' + ); + return html` ${GeneralEquipments.map( + GeneralEquipment => + html`` + )}`; + } + + private renderFunctions(): TemplateResult { + if (!this.showfunctions) return html``; + + const Functions = getChildElementsByTagName(this.element, 'Function'); + return html` ${Functions.map( + Function => + html`` + )}`; + } + + private renderLNodes(): TemplateResult { + if (!this.showfunctions) return html``; + + const lNodes = getChildElementsByTagName(this.element, 'LNode'); + return lNodes.length + ? html`
+ ${lNodes.map( + lNode => + html`` + )} +
` + : html``; + } + + render(): TemplateResult { + return html` ${this.renderConductingEquipments()}${this.renderGeneralEquipments()}${this.renderFunctions()}${this.renderLNodes()} + `; + } +} diff --git a/src/editors/substation/zeroline-pane.ts b/src/editors/substation/zeroline-pane.ts index 918f0077b9..146a860ea6 100644 --- a/src/editors/substation/zeroline-pane.ts +++ b/src/editors/substation/zeroline-pane.ts @@ -14,6 +14,7 @@ import '@material/mwc-icon-button-toggle'; import { IconButton } from '@material/mwc-icon-button'; import { IconButtonToggle } from '@material/mwc-icon-button-toggle'; +import './line-editor.js'; import './substation-editor.js'; import './ied-editor.js'; import { communicationMappingWizard } from '../../wizards/commmap-wizards.js'; @@ -113,11 +114,31 @@ export class ZerolinePane extends LitElement { return ieds.length ? html`
- ${ieds.map(ied => html``)} + ${ieds.map( + ied => + html`` + )}
` : html``; } + renderLines(): TemplateResult { + return this.doc?.querySelector(':root > Line') + ? html`
+ ${Array.from(this.doc.querySelectorAll('Line') ?? []) + .filter(isPublic) + .map( + line => + html`` + )} +
` + : html``; + } + render(): TemplateResult { return html`

`}`; + `}${this.renderLines()}`; } static styles = css` diff --git a/test/testfiles/editors/substation/Line.scd b/test/testfiles/editors/substation/Line.scd new file mode 100644 index 0000000000..3cbdb667bf --- /dev/null +++ b/test/testfiles/editors/substation/Line.scd @@ -0,0 +1,235 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + status-only + + + + + + + + + + + + + + + + + + sbo-with-enhanced-security + + + 30000 + + + 600 + + + + + + + + + + + + + + 1000 + + + direct-with-enhanced-security + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + sbo-with-enhanced-security + + + 30000 + + + 600 + + + + + + + + + + + + IEC 61850-8-1:2003 + + + + + + + + + IEC 61850-8-1:2003 + + + + + + + + + + + + + + IEC 61850-8-1:2003 + + + + + + + + + IEC 61850-8-1:2003 + + + + + + + + IEC 61850-8-1:2003 + + + + + + + + + IEC 61850-8-1:2003 + + + + + + + status-only + + + pulse + persistent + persistent-feedback + + + Ok + Warning + Alarm + + + status-only + direct-with-normal-security + sbo-with-normal-security + direct-with-enhanced-security + sbo-with-enhanced-security + + + on + blocked + test + test/blocked + off + + + not-supported + bay-control + station-control + remote-control + automatic-bay + automatic-station + automatic-remote + maintenance + process + + + + + + + + + 110.0 + + + + + + + + + + + + + + 380.0 + + + + + diff --git a/test/unit/editors/substation/__snapshots__/line-editor.test.snap.js b/test/unit/editors/substation/__snapshots__/line-editor.test.snap.js new file mode 100644 index 0000000000..ae6dbfe89d --- /dev/null +++ b/test/unit/editors/substation/__snapshots__/line-editor.test.snap.js @@ -0,0 +1,56 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["web component rendering Line element rendering LNode and Function children looks like the latest snapshot"] = +` + + + + +
+ + +
+
+`; +/* end snapshot web component rendering Line element rendering LNode and Function children looks like the latest snapshot */ + +snapshots["web component rendering Line element rendering ConductingEquipment looks like the latest snapshot"] = +` + + + + +
+ + +
+
+`; +/* end snapshot web component rendering Line element rendering ConductingEquipment looks like the latest snapshot */ + +snapshots["web component rendering Line element rendering GeneralEquipment looks like the latest snapshot"] = +` + + + + + + +
+ + +
+
+`; +/* end snapshot web component rendering Line element rendering GeneralEquipment looks like the latest snapshot */ + diff --git a/test/unit/editors/substation/line-editor.test.ts b/test/unit/editors/substation/line-editor.test.ts new file mode 100644 index 0000000000..31e6ef9e88 --- /dev/null +++ b/test/unit/editors/substation/line-editor.test.ts @@ -0,0 +1,68 @@ +import { fixture, html, expect } from '@open-wc/testing'; + +import '../../../../src/editors/substation/line-editor.js'; +import { LineEditor } from '../../../../src/editors/substation/line-editor.js'; + +describe('web component rendering Line element', () => { + let element: LineEditor; + let doc: XMLDocument; + + describe('rendering LNode and Function children', () => { + beforeEach(async () => { + doc = await fetch('/test/testfiles/editors/substation/Line.scd') + .then(response => response.text()) + .then(str => new DOMParser().parseFromString(str, 'application/xml')); + element = ( + await fixture( + html`` + ) + ); + element.showfunctions = true; + await element.updateComplete; + }); + it('looks like the latest snapshot', async () => { + await expect(element).shadowDom.to.equalSnapshot(); + }); + }); + + describe('rendering ConductingEquipment', () => { + beforeEach(async () => { + doc = await fetch('/test/testfiles/editors/substation/Line.scd') + .then(response => response.text()) + .then(str => new DOMParser().parseFromString(str, 'application/xml')); + element = ( + await fixture( + html`` + ) + ); + element.showfunctions = true; + await element.updateComplete; + }); + it('looks like the latest snapshot', async () => { + await expect(element).shadowDom.to.equalSnapshot(); + }); + }); + describe('rendering GeneralEquipment', () => { + beforeEach(async () => { + doc = await fetch('/test/testfiles/editors/substation/Line.scd') + .then(response => response.text()) + .then(str => new DOMParser().parseFromString(str, 'application/xml')); + element = ( + await fixture( + html`` + ) + ); + element.showfunctions = true; + await element.updateComplete; + }); + it('looks like the latest snapshot', async () => { + await expect(element).shadowDom.to.equalSnapshot(); + }); + }); +});