From b5a070a920eeadbe7b6d52f5d8ab8a70b6f3dbaa Mon Sep 17 00:00:00 2001 From: Rob Tjalma Date: Fri, 10 Dec 2021 11:55:32 +0100 Subject: [PATCH 01/46] Added IED Container --- public/js/plugins.js | 8 +++- src/editors/IEDEditor.ts | 39 +++++++++++++++++++ src/editors/iededitor/ied-container.ts | 33 ++++++++++++++++ src/translations/de.ts | 12 ++++++ src/translations/en.ts | 12 ++++++ .../__snapshots__/open-scd.test.snap.js | 16 ++++++++ test/unit/Plugging.test.ts | 10 ++--- 7 files changed, 124 insertions(+), 6 deletions(-) create mode 100644 src/editors/IEDEditor.ts create mode 100644 src/editors/iededitor/ied-container.ts diff --git a/public/js/plugins.js b/public/js/plugins.js index 27831ba12c..f3e141b3b3 100644 --- a/public/js/plugins.js +++ b/public/js/plugins.js @@ -6,6 +6,13 @@ export const officialPlugins = [ default: true, kind: 'editor', }, + { + name: 'IED Editor', + src: '/src/editors/IEDEditor.js', + icon: 'edit', + default: true, + kind: 'editor', + }, { name: 'Single Line Diagram', src: '/src/editors/SingleLineDiagram.js', @@ -19,7 +26,6 @@ export const officialPlugins = [ icon: 'settings_ethernet', default: true, kind: 'editor', - }, { name: 'Templates', diff --git a/src/editors/IEDEditor.ts b/src/editors/IEDEditor.ts new file mode 100644 index 0000000000..a2d5bc6d2c --- /dev/null +++ b/src/editors/IEDEditor.ts @@ -0,0 +1,39 @@ +import { css, html, LitElement, property, TemplateResult } from 'lit-element'; + +import '@material/mwc-fab'; + +import '../zeroline-pane.js'; +import './iededitor/ied-container.js' + +/** An editor [[`plugin`]] for editing the `IED Editor` section. */ +export default class IedEditorPlugin extends LitElement { + /** The document being edited as provided to plugins by [[`OpenSCD`]]. */ + @property() + doc!: XMLDocument; + /** Are the (sub)containers read-only? */ + @property({ type: Boolean }) + readonly = true; + + renderIeds(): TemplateResult { + const ieds = Array.from(this.doc.querySelectorAll('IED')) ?? []; + return ieds?.length + ? html`
+ ${ieds.map(ied => html` + + `)} +
` + : html``; + } + + render(): TemplateResult { + return html`${this.renderIeds()}`; + } + + static styles = css` + :host { + width: 100vw; + } + `; +} diff --git a/src/editors/iededitor/ied-container.ts b/src/editors/iededitor/ied-container.ts new file mode 100644 index 0000000000..a7a9ec46d9 --- /dev/null +++ b/src/editors/iededitor/ied-container.ts @@ -0,0 +1,33 @@ +import { + css, + customElement, + html, + LitElement, + property, + TemplateResult, +} from 'lit-element'; + +import '../../action-pane.js'; + +/** [[`IED Container`]] plugin subeditor for editing `IED` sections. */ +@customElement('ied-container') +export class IedContainer extends LitElement { + @property({ attribute: false }) + element!: Element; + @property({ type: Boolean }) + readonly = false; + + @property({ type: String }) + get header(): string { + const name = this.element.getAttribute('name') ?? ''; + const desc = this.element.getAttribute('desc') ?? ''; + + return `${name} ${desc ? `- ${desc}` : ''}`; + } + + render(): TemplateResult { + return html``; + } + + static styles = css``; +} diff --git a/src/translations/de.ts b/src/translations/de.ts index 7de1a1e3cc..c0ef6f756a 100644 --- a/src/translations/de.ts +++ b/src/translations/de.ts @@ -158,6 +158,18 @@ export const de: Translations = { addvoltagelevel: 'Spannungsebene hinzufügen', }, }, + iededitor: { + name: '???', + missing: '???', + wizard: { + nameHelper: '???', + descHelper: '???', + title: { + add: '???', + edit: '???', + }, + } + }, voltagelevel: { name: 'Spannungsebene', wizard: { diff --git a/src/translations/en.ts b/src/translations/en.ts index 3a1c9fa638..17e88909fc 100644 --- a/src/translations/en.ts +++ b/src/translations/en.ts @@ -155,6 +155,18 @@ export const en = { addvoltagelevel: 'Add voltage level', }, }, + iededitor: { + name: 'IED', + missing: 'No IED', + wizard: { + nameHelper: 'IED name', + descHelper: 'IED description', + title: { + add: 'Add IED', + edit: 'Edit IED', + }, + } + }, voltagelevel: { name: 'Voltage level', wizard: { diff --git a/test/integration/__snapshots__/open-scd.test.snap.js b/test/integration/__snapshots__/open-scd.test.snap.js index cd086c5636..f15f56819b 100644 --- a/test/integration/__snapshots__/open-scd.test.snap.js +++ b/test/integration/__snapshots__/open-scd.test.snap.js @@ -574,6 +574,22 @@ snapshots["open-scd looks like its snapshot"] = Substation + + + edit + + IED Editor + { }); it('stores default plugins on load', () => - expect(element).property('editors').to.have.lengthOf(3)); + expect(element).property('editors').to.have.lengthOf(4)); describe('plugin manager dialog', () => { let firstEditorPlugin: HTMLElement; @@ -49,7 +49,7 @@ describe('PluggingElement', () => { it('disables deselected plugins', async () => { firstEditorPlugin.click(); await element.updateComplete; - expect(element).property('editors').to.have.lengthOf(2); + expect(element).property('editors').to.have.lengthOf(3); }); it('enables selected plugins', async () => { @@ -57,7 +57,7 @@ describe('PluggingElement', () => { await element.updateComplete; (element.pluginList.firstElementChild).click(); await element.updateComplete; - expect(element).property('editors').to.have.lengthOf(3); + expect(element).property('editors').to.have.lengthOf(4); }); it('resets plugins to default on reset button click', async () => { @@ -65,7 +65,7 @@ describe('PluggingElement', () => { await element.updateComplete; resetAction.click(); await element.updateComplete; - expect(element).property('editors').to.have.lengthOf(3); + expect(element).property('editors').to.have.lengthOf(4); }); it('opens the custom plugin dialog on add button click', async () => { @@ -139,7 +139,7 @@ describe('PluggingElement', () => { await name.updateComplete; primaryAction.click(); await element.updateComplete; - expect(element.editors).to.have.lengthOf(4); + expect(element.editors).to.have.lengthOf(5); }); it('adds a new menu kind plugin on add button click', async () => { const lengthMenuKindPlugins = element.menuEntries.length; From 70dc504a61612cd5bf7a784a7386f46b4520017e Mon Sep 17 00:00:00 2001 From: Rob Tjalma Date: Fri, 10 Dec 2021 14:52:35 +0100 Subject: [PATCH 02/46] Added tests --- src/editors/IEDEditor.ts | 18 ++------ .../editors/iededitor/IEDEditor.test.ts | 42 +++++++++++++++++++ .../__snapshots__/IEDEditor.test.snap.js | 9 ++++ 3 files changed, 55 insertions(+), 14 deletions(-) create mode 100644 test/integration/editors/iededitor/IEDEditor.test.ts create mode 100644 test/integration/editors/iededitor/__snapshots__/IEDEditor.test.snap.js diff --git a/src/editors/IEDEditor.ts b/src/editors/IEDEditor.ts index a2d5bc6d2c..dece52e93e 100644 --- a/src/editors/IEDEditor.ts +++ b/src/editors/IEDEditor.ts @@ -14,21 +14,11 @@ export default class IedEditorPlugin extends LitElement { @property({ type: Boolean }) readonly = true; - renderIeds(): TemplateResult { - const ieds = Array.from(this.doc.querySelectorAll('IED')) ?? []; - return ieds?.length - ? html`
- ${ieds.map(ied => html` - - `)} -
` - : html``; - } - render(): TemplateResult { - return html`${this.renderIeds()}`; + return html` + ${Array.from(this.doc?.querySelectorAll('IED') ?? []).map( + ied => html`` + )}`; } static styles = css` diff --git a/test/integration/editors/iededitor/IEDEditor.test.ts b/test/integration/editors/iededitor/IEDEditor.test.ts new file mode 100644 index 0000000000..4b9dbc0b2d --- /dev/null +++ b/test/integration/editors/iededitor/IEDEditor.test.ts @@ -0,0 +1,42 @@ +import { html, fixture, expect } from '@open-wc/testing'; + +import '../../../mock-wizard.js'; + +import IEDEditor from '../../../../src/editors/IEDEditor.js'; +import { Editing } from '../../../../src/Editing.js'; +import { Wizarding } from '../../../../src/Wizarding.js'; + +describe('IED Editor Plugin', () => { + customElements.define( + 'iededitor-plugin', + Wizarding(Editing(IEDEditor)) + ); + let element: IEDEditor; + beforeEach(async () => { + element = await fixture( + html`` + ); + }); + + describe('without a doc loaded', () => { + it('looks like the latest snapshot', async () => { + await expect(element).shadowDom.to.equalSnapshot(); + }); + }); + + describe('with a doc loaded including IED sections', () => { + let doc: XMLDocument; + let element: IEDEditor; + beforeEach(async () => { + doc = await fetch('/test/testfiles/valid2007B4.scd') + .then(response => response.text()) + .then(str => new DOMParser().parseFromString(str, 'application/xml')); + element = await fixture( + html`` + ); + }); + it('contains multiple IED containers rendering the IED section', () => { + expect(element.shadowRoot?.querySelectorAll('ied-container').length).to.eql(3); + }); + }); +}); diff --git a/test/integration/editors/iededitor/__snapshots__/IEDEditor.test.snap.js b/test/integration/editors/iededitor/__snapshots__/IEDEditor.test.snap.js new file mode 100644 index 0000000000..1dce47f751 --- /dev/null +++ b/test/integration/editors/iededitor/__snapshots__/IEDEditor.test.snap.js @@ -0,0 +1,9 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["IED Editor Plugin without a doc loaded looks like the latest snapshot"] = +` + +`; +/* end snapshot IED Editor Plugin without a doc loaded looks like the latest snapshot */ + From 807e9b525fe0d611b7e2a8b6b0ec680285d871e2 Mon Sep 17 00:00:00 2001 From: Rob Tjalma Date: Fri, 10 Dec 2021 15:58:44 +0100 Subject: [PATCH 03/46] Added Access Point container --- src/editors/IEDEditor.ts | 7 ++-- .../iededitor/accesspoint-container.ts | 31 ++++++++++++++ src/editors/iededitor/ied-container.ts | 10 +++-- .../__snapshots__/zeroline-pane.test.snap.js | 42 ------------------- .../iededitor/access-point-container.test.ts | 21 ++++++++++ .../editors/iededitor/ied-container.test.ts | 22 ++++++++++ 6 files changed, 84 insertions(+), 49 deletions(-) create mode 100644 src/editors/iededitor/accesspoint-container.ts create mode 100644 test/unit/editors/iededitor/access-point-container.test.ts create mode 100644 test/unit/editors/iededitor/ied-container.test.ts diff --git a/src/editors/IEDEditor.ts b/src/editors/IEDEditor.ts index dece52e93e..a69a6c3116 100644 --- a/src/editors/IEDEditor.ts +++ b/src/editors/IEDEditor.ts @@ -10,14 +10,13 @@ export default class IedEditorPlugin extends LitElement { /** The document being edited as provided to plugins by [[`OpenSCD`]]. */ @property() doc!: XMLDocument; - /** Are the (sub)containers read-only? */ - @property({ type: Boolean }) - readonly = true; render(): TemplateResult { return html` ${Array.from(this.doc?.querySelectorAll('IED') ?? []).map( - ied => html`` + ied => html`` )}`; } diff --git a/src/editors/iededitor/accesspoint-container.ts b/src/editors/iededitor/accesspoint-container.ts new file mode 100644 index 0000000000..7bcbf514e9 --- /dev/null +++ b/src/editors/iededitor/accesspoint-container.ts @@ -0,0 +1,31 @@ +import { + css, + customElement, + html, + LitElement, + property, + TemplateResult, +} from 'lit-element'; + +import '../../action-pane.js'; + +/** [[`AccessPoint Container`]] plugin subeditor for editing `AccessPoint` sections. */ +@customElement('access-point-container') +export class AccessPointContainer extends LitElement { + @property({ attribute: false }) + element!: Element; + + @property({ type: String }) + get header(): string { + const name = this.element.getAttribute('name') ?? ''; + const desc = this.element.getAttribute('desc') ?? ''; + + return `${name} ${desc ? `- ${desc}` : ''}`; + } + + render(): TemplateResult { + return html``; + } + + static styles = css``; +} diff --git a/src/editors/iededitor/ied-container.ts b/src/editors/iededitor/ied-container.ts index a7a9ec46d9..0193014ff2 100644 --- a/src/editors/iededitor/ied-container.ts +++ b/src/editors/iededitor/ied-container.ts @@ -8,14 +8,13 @@ import { } from 'lit-element'; import '../../action-pane.js'; +import './accesspoint-container.js'; /** [[`IED Container`]] plugin subeditor for editing `IED` sections. */ @customElement('ied-container') export class IedContainer extends LitElement { @property({ attribute: false }) element!: Element; - @property({ type: Boolean }) - readonly = false; @property({ type: String }) get header(): string { @@ -26,7 +25,12 @@ export class IedContainer extends LitElement { } render(): TemplateResult { - return html``; + return html` + ${Array.from(this.element.querySelectorAll('AccessPoint')).map( + ap => html``)} + `; } static styles = css``; diff --git a/test/unit/__snapshots__/zeroline-pane.test.snap.js b/test/unit/__snapshots__/zeroline-pane.test.snap.js index cfd01e8703..9d8721ab10 100644 --- a/test/unit/__snapshots__/zeroline-pane.test.snap.js +++ b/test/unit/__snapshots__/zeroline-pane.test.snap.js @@ -43,48 +43,6 @@ snapshots["zeroline-pane per default looks like the latest snapshot"] = `; /* end snapshot zeroline-pane per default looks like the latest snapshot */ -snapshots["zeroline-pane readonly looks like the latest snapshot"] = -`

- - -

-
- - - - -
-`; -/* end snapshot zeroline-pane readonly looks like the latest snapshot */ - snapshots["zeroline-pane showieds looks like the latest snapshot"] = `