Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(editors/ied): add DO elements to IED editor #454

Merged
merged 7 commits into from
Jan 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion public/js/plugins.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const officialPlugins = [
name: 'IED',
src: '/src/editors/IED.js',
icon: 'edit',
default: true,
default: false,
kind: 'editor',
},
{
Expand Down
3 changes: 1 addition & 2 deletions src/editors/IED.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import '../zeroline-pane.js';
import './ied/ied-container.js'

import { translate } from 'lit-translate';
import { IEDSelector } from './ied/foundation.js';
import { Select } from '@material/mwc-select';
import { SingleSelectedEvent } from '@material/mwc-list/mwc-list-foundation';
import { compareNames, getDescriptionAttribute, getNameAttribute } from '../foundation.js';
Expand All @@ -21,7 +20,7 @@ export default class IedPlugin extends LitElement {

/** Query holding the current selected IEDs. */
@state()
currentSelectedIEDs: string = IEDSelector.IED;
currentSelectedIEDs = ':root > IED';

@query('#iedSelect') iedSelector?: Select;

Expand Down
3 changes: 1 addition & 2 deletions src/editors/ied/access-point-container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {

import '../../action-pane.js';
import './server-container.js'
import { IEDSelector } from './foundation.js';
import { nothing } from 'lit-html';
import { getDescriptionAttribute, getNameAttribute } from '../../foundation.js';

Expand All @@ -28,7 +27,7 @@ export class AccessPointContainer extends LitElement {

render(): TemplateResult {
return html`<action-pane .label="${this.header()}">
${Array.from(this.element.querySelectorAll(IEDSelector.Server)).map(
${Array.from(this.element.querySelectorAll(':scope > Server')).map(
Flurb marked this conversation as resolved.
Show resolved Hide resolved
server => html`<server-container
.element=${server}
></server-container>`)}
Expand Down
76 changes: 76 additions & 0 deletions src/editors/ied/do-container.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import {
css,
customElement,
html,
LitElement,
property,
TemplateResult,
} from 'lit-element';
import { nothing } from 'lit-html';

import '../../action-pane.js';
import { getDescriptionAttribute, getNameAttribute } from '../../foundation.js';

/** [[`IED`]] plugin subeditor for editing `DO` element. */
@customElement('do-container')
export class DOContainer extends LitElement {
/**
* The DO itself.
*/
@property({ attribute: false })
element!: Element;

/**
* The optional DOI of this DO.
*/
@property({ attribute: false })
instanceElement!: Element;

private header(): TemplateResult {
const name = getNameAttribute(this.element);
const desc = getDescriptionAttribute(this.element);

if (this.instanceElement != null) {
return html`<b>${name}${desc ? html` &mdash; ${desc}` : nothing}</b>`;
} else {
return html`${name}${desc ? html` &mdash; ${desc}` : nothing}`;
}
}

/**
* Get the nested SDO element(s).
* @returns The nested SDO element(s) of this DO container.
*/
private getDOElements(): Element[] {
const type = this.element.getAttribute('type') ?? undefined;
const doType = this.element.closest('SCL')!.querySelector(`:root > DataTypeTemplates > DOType[id="${type}"]`);
if (doType != null) {
return Array.from(doType!.querySelectorAll(':scope > SDO'))
}
return [];
}

/**
* Get the instance element (SDI) of a SDO element (if available)
* @param sdo - The SDO object to search with.
* @returns The optional SDI element.
*/
private getInstanceElement(sdo: Element): Element | null {
const sdoName = getNameAttribute(sdo);
if (this.instanceElement) {
return this.instanceElement.querySelector(`:scope > SDI[name="${sdoName}"]`)
}
return null;
}

render(): TemplateResult {
return html`<action-pane .label="${this.header()}" icon="${this.instanceElement != null ? 'done' : ''}">
${this.getDOElements().map(dO =>
html`<do-container
.element=${dO}
.instanceElement=${this.getInstanceElement(dO)}>
</do-container>`)}
</action-pane>
`;
}
}
10 changes: 0 additions & 10 deletions src/editors/ied/foundation.ts

This file was deleted.

3 changes: 1 addition & 2 deletions src/editors/ied/ied-container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { nothing } from 'lit-html';
import '../../action-pane.js';
import { getDescriptionAttribute, getNameAttribute } from '../../foundation.js';
import './access-point-container.js';
import { IEDSelector } from './foundation.js';

/** [[`IED`]] plugin subeditor for editing `IED` element. */
@customElement('ied-container')
Expand All @@ -29,7 +28,7 @@ export class IedContainer extends LitElement {

render(): TemplateResult {
return html`<action-pane .label="${this.header()}">
${Array.from(this.element.querySelectorAll(IEDSelector.AccessPoint)).map(
${Array.from(this.element.querySelectorAll(':scope > AccessPoint')).map(
ap => html`<access-point-container
.element=${ap}
></access-point-container>`)}
Expand Down
9 changes: 4 additions & 5 deletions src/editors/ied/ldevice-container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {

import '../../action-pane.js';
import './ln-container.js'
import { IEDSelector } from './foundation.js';
import { nothing } from 'lit-html';
import { getDescriptionAttribute, getInstanceAttribute, getNameAttribute } from '../../foundation.js';

Expand All @@ -28,8 +27,8 @@ export class LDeviceContainer extends LitElement {

render(): TemplateResult {
return html`<action-pane .label="${this.header()}">
<div id="bayContainer">
${Array.from(this.element.querySelectorAll(IEDSelector.AnyLN)).map(
<div id="lnContainer">
${Array.from(this.element.querySelectorAll(':scope > LN,LN0')).map(
server => html`<ln-container
.element=${server}
></ln-container>`)}
Expand All @@ -38,15 +37,15 @@ export class LDeviceContainer extends LitElement {
}

static styles = css`
#bayContainer {
#lnContainer {
display: grid;
grid-gap: 12px;
box-sizing: border-box;
grid-template-columns: repeat(auto-fit, minmax(316px, auto));
}

@media (max-width: 387px) {
#bayContainer {
#lnContainer {
grid-template-columns: repeat(auto-fit, minmax(196px, auto));
}
}`;
Expand Down
31 changes: 30 additions & 1 deletion src/editors/ied/ln-container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import {
import { nothing } from 'lit-html';

import '../../action-pane.js';
import { getInstanceAttribute } from '../../foundation.js';
import './do-container.js';
import { getInstanceAttribute, getNameAttribute } from '../../foundation.js';

/** [[`IED`]] plugin subeditor for editing `LN` and `LN0` element. */
@customElement('ln-container')
Expand All @@ -27,8 +28,36 @@ export class LNContainer extends LitElement {
${inst ? html` &mdash; ${inst}` : nothing}`;
}

/**
* Get the DO child elements of this LN(0) section.
* @returns The DO child elements, or an empty array if none are found.
*/
private getDOElements(): Element[] {
const lnType = this.element.getAttribute('lnType') ?? undefined;
const lNodeType = this.element.closest('SCL')!.querySelector(`:root > DataTypeTemplates > LNodeType[id="${lnType}"]`);
if (lNodeType != null) {
return Array.from(lNodeType.querySelectorAll(':scope > DO'));
}
return [];
}

/**
* Get the instance element (DOI) of a DO element (if available)
* @param dO - The DOI object to use.
* @returns The optional DOI object.
*/
private getInstanceElement(dO: Element): Element | null {
const doName = getNameAttribute(dO);
return this.element.querySelector(`:scope > DOI[name="${doName}"]`)
}

render(): TemplateResult {
return html`<action-pane .label="${this.header()}">
${this.getDOElements().map(dO => html`<do-container
.element=${dO}
.instanceElement=${this.getInstanceElement(dO)}>
</do-container>
`)}
</action-pane>`;
}

Expand Down
3 changes: 1 addition & 2 deletions src/editors/ied/server-container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {

import '../../action-pane.js';
import './ldevice-container.js';
import { IEDSelector } from './foundation.js';

/** [[`IED`]] plugin subeditor for editing `Server` element. */
@customElement('server-container')
Expand All @@ -23,7 +22,7 @@ export class ServerContainer extends LitElement {

render(): TemplateResult {
return html`<action-pane label="${this.header()}">
${Array.from(this.element.querySelectorAll(IEDSelector.LDevice)).map(
${Array.from(this.element.querySelectorAll(':scope > LDevice')).map(
server => html`<ldevice-container
.element=${server}
></ldevice-container>`)}
Expand Down
1 change: 0 additions & 1 deletion test/integration/__snapshots__/open-scd.test.snap.js
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,6 @@ snapshots["open-scd looks like its snapshot"] =
hasmeta=""
left=""
mwc-list-item=""
selected=""
tabindex="-1"
value="/src/editors/IED.js"
>
Expand Down
11 changes: 0 additions & 11 deletions test/integration/editors/ied/__snapshots__/IED.test.snap.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,6 @@
/* @web/test-runner snapshot v1 */
export const snapshots = {};

snapshots["IED Editor Plugin without a doc loaded looks like the latest snapshot"] =
`<h1>
<span style="color: var(--base1)">
[iededitor.missing]
</span>
</h1>
<wizard-dialog>
</wizard-dialog>
`;
/* end snapshot IED Editor Plugin without a doc loaded looks like the latest snapshot */

snapshots["IED Plugin without a doc loaded looks like the latest snapshot"] =
`<h1>
<span style="color: var(--base1)">
Expand Down
4 changes: 2 additions & 2 deletions test/integration/editors/triggered/ImportIedsPlugin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,12 @@ describe('ImportIedsPlugin', () => {
expect(
element.doc?.querySelectorAll(':root > DataTypeTemplates > DOType')
.length
).to.equal(14);
).to.equal(16);
element.prepareImport(importDoc, doc);
expect(
element.doc?.querySelectorAll(':root > DataTypeTemplates > DOType')
.length
).to.equal(24);
).to.equal(26);
});

it('loads unique datypes to the project', () => {
Expand Down
23 changes: 23 additions & 0 deletions test/testfiles/valid2007B4.scd
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@
</GSEControl>
</LN0>
<LN lnClass="LPHD" inst="1" lnType="Dummy.LPHD1"/>
<LN lnClass="THARDE" inst="1" lnType="Dummy.THARDE"/>
<LN lnClass="XCBR" inst="1" lnType="Dummy.XCBR1">
<DOI name="Pos">
<DAI name="ctlModel">
Expand Down Expand Up @@ -393,6 +394,7 @@
<DataTypeTemplates>
<LNodeType lnClass="LLN0" id="Dummy.LLN0">
<DO name="Mod" type="Dummy.LLN0.Mod" />
<DO name="ExtendedMod" type="Dummy.LLN0.ExtendedMod" />
<DO name="Beh" type="Dummy.LLN0.Beh" />
<DO name="Health" type="Dummy.LLN0.Health" />
<DO name="NamPlt" type="Dummy.LLN0.NamPlt" />
Expand Down Expand Up @@ -486,6 +488,27 @@
<DA fc="CO" name="Oper" bType="Struct" type="Dummy.LLN0.Mod.SBOw" />
<DA fc="CO" name="Cancel" bType="Struct" type="Dummy.LLN0.Mod.Cancel" />
</DOType>
<DOType cdc="ENC" id="Dummy.LLN0.ExtendedMod">
<SDO fc="ST" name="someSdo" type="someSdoType"/>
<DA fc="ST" name="stVal" bType="Enum" type="Dummy_Beh" />
<DA fc="ST" name="q" bType="Quality" />
<DA fc="ST" name="t" bType="Timestamp" />
<DA fc="ST" name="stSeld" bType="BOOLEAN" />
<DA fc="OR" name="opRcvd" bType="BOOLEAN" />
<DA fc="OR" name="opOk" bType="BOOLEAN" />
<DA fc="OR" name="tOpOk" bType="Timestamp" />
<DA fc="CF" name="ctlModel" bType="Enum" type="Dummy_ctlModel" />
<DA fc="CF" name="sboTimeout" bType="INT32U" />
<DA fc="CF" name="operTimeout" bType="INT32U" />
<DA fc="CO" name="SBO" bType="ObjRef" />
<DA fc="CO" name="SBOw" bType="Struct" type="Dummy.LLN0.Mod.SBOw" />
<DA fc="CO" name="Oper" bType="Struct" type="Dummy.LLN0.Mod.SBOw" />
<DA fc="CO" name="Cancel" bType="Struct" type="Dummy.LLN0.Mod.Cancel" />
</DOType>
<DOType cdc="CMV" id="someSdoType">
<DA fc="MX" qchg="true" name="q" bType="Quality"/>
<DA fc="MX" name="t" bType="Timestamp"/>
</DOType>
<DOType cdc="ENS" id="Dummy.LLN0.Beh">
<DA fc="ST" name="stVal" bType="Enum" type="Dummy_Beh" />
<DA fc="ST" name="q" bType="Quality" />
Expand Down
Loading