Skip to content

Commit 22555b6

Browse files
author
Dennis Labordus
authored
feat(editors/Substation): Add PowerTransformer Components to Substation Editor
1 parent af246dd commit 22555b6

27 files changed

+731
-103
lines changed

src/editors/singlelinediagram/wizards/powertransformer.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,12 @@ import {
2020
function render(
2121
name: string | null,
2222
desc: string | null,
23+
type: string | null,
2324
xCoordinate: string | null,
2425
yCoordinate: string | null,
2526
reservedNames: string[]
2627
): TemplateResult[] {
27-
return renderPowerTransformerWizard(name, desc, reservedNames)
28+
return renderPowerTransformerWizard(name, desc, type, reservedNames)
2829
.concat(renderXYCoordinateFields(xCoordinate, yCoordinate));
2930
}
3031

@@ -41,6 +42,7 @@ export function editPowerTransformerWizard(element: Element): Wizard {
4142
content: render(
4243
getNameAttribute(element),
4344
getDescAttribute(element),
45+
element.getAttribute('type'),
4446
getXCoordinateAttribute(element),
4547
getYCoordinateAttribute(element),
4648
reservedNamesPowerTransformer(element)

src/foundation.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2307,7 +2307,10 @@ export const tags: Record<
23072307
identity: namingIdentity,
23082308
selector: namingSelector,
23092309
parents: ['SCL'],
2310-
children: [...tEquipmentContainerSequence, 'VoltageLevel', 'Function'],
2310+
children: [...tEquipmentContainerSequence,
2311+
'VoltageLevel',
2312+
'Function',
2313+
],
23112314
},
23122315
SupSubscription: {
23132316
identity: singletonIdentity,
@@ -2384,7 +2387,11 @@ export const tags: Record<
23842387
identity: namingIdentity,
23852388
selector: namingSelector,
23862389
parents: ['Substation'],
2387-
children: [...tEquipmentContainerSequence, 'Voltage', 'Bay', 'Function'],
2390+
children: [...tEquipmentContainerSequence,
2391+
'Voltage',
2392+
'Bay',
2393+
'Function',
2394+
],
23882395
},
23892396
};
23902397

src/translations/de.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,9 @@ export const de: Translations = {
217217
wizard: {
218218
nameHelper: '`Name des Leistungstransformators',
219219
descHelper: 'Beschreibung des Leistungstransformators',
220+
typeHelper: 'Type des Leistungstransformators',
220221
title: {
222+
add: 'Leistungstransformator hinzufügen',
221223
edit: 'Leistungstransformator bearbeiten',
222224
},
223225
},

src/translations/en.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,9 @@ export const en = {
213213
wizard: {
214214
nameHelper: 'Power transformer name',
215215
descHelper: 'Power transformer description',
216+
typeHelper: 'Power transformer type',
216217
title: {
218+
add: 'Add power transformer',
217219
edit: 'Edit power transformer',
218220
},
219221
},

src/wizards/powertransformer.ts

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,44 @@ import { html, TemplateResult } from 'lit-element';
22
import { get, translate } from 'lit-translate';
33

44
import {
5+
createElement,
6+
EditorAction,
7+
getValue,
58
isPublic,
69
Wizard,
10+
WizardActor,
11+
WizardInput,
712
} from '../foundation.js';
813

914
import { updateNamingAction } from "./foundation/actions.js";
1015

16+
const defaultPowerTransformerType = 'PTR';
17+
18+
export function createAction(parent: Element): WizardActor {
19+
return (inputs: WizardInput[]): EditorAction[] => {
20+
const name = getValue(inputs.find(i => i.label === 'name')!);
21+
const desc = getValue(inputs.find(i => i.label === 'desc')!);
22+
const element = createElement(parent.ownerDocument, 'PowerTransformer', {
23+
name,
24+
desc,
25+
type: defaultPowerTransformerType
26+
});
27+
28+
const action = {
29+
new: {
30+
parent,
31+
element,
32+
},
33+
};
34+
35+
return [action];
36+
};
37+
}
38+
1139
export function renderPowerTransformerWizard(
1240
name: string | null,
1341
desc: string | null,
42+
type: string | null,
1443
reservedNames: string[]
1544
): TemplateResult[] {
1645
return [
@@ -29,19 +58,44 @@ export function renderPowerTransformerWizard(
2958
nullable
3059
helper="${translate('powertransformer.wizard.descHelper')}"
3160
></wizard-textfield>`,
61+
html`<wizard-textfield
62+
label="type"
63+
.maybeValue=${type}
64+
disabled
65+
helper="${translate('powertransformer.wizard.typeHelper')}"
66+
></wizard-textfield>`,
3267
];
3368
}
3469

35-
export function reservedNamesPowerTransformer(currentElement: Element): string[] {
36-
return Array.from(
37-
currentElement.parentNode!.querySelectorAll('PowerTransformer')
38-
)
70+
export function reservedNamesPowerTransformer(parent: Element, currentName?: string | null): string[] {
71+
return Array.from(parent.querySelectorAll('PowerTransformer'))
3972
.filter(isPublic)
40-
.map(cNode => cNode.getAttribute('name') ?? '')
41-
.filter(name => name !== currentElement.getAttribute('name'));
73+
.map(pwt => pwt.getAttribute('name') ?? '')
74+
.filter(name => currentName && name !== currentName);
75+
}
76+
77+
export function createPowerTransformerWizard(parent: Element): Wizard {
78+
const reservedNames = reservedNamesPowerTransformer(parent);
79+
80+
return [
81+
{
82+
title: get('powertransformer.wizard.title.add'),
83+
element: undefined,
84+
primary: {
85+
icon: '',
86+
label: get('add'),
87+
action: createAction(parent),
88+
},
89+
content: renderPowerTransformerWizard('', null, defaultPowerTransformerType, reservedNames),
90+
},
91+
];
4292
}
4393

4494
export function editPowerTransformerWizard(element: Element): Wizard {
95+
const reservedNames = reservedNamesPowerTransformer(
96+
<Element>element.parentNode!,
97+
element.getAttribute('name'));
98+
4599
return [
46100
{
47101
title: get('powertransformer.wizard.title.edit'),
@@ -54,7 +108,8 @@ export function editPowerTransformerWizard(element: Element): Wizard {
54108
content: renderPowerTransformerWizard(
55109
element.getAttribute('name'),
56110
element.getAttribute('desc'),
57-
reservedNamesPowerTransformer(element)
111+
element.getAttribute('type'),
112+
reservedNames
58113
),
59114
},
60115
];

src/wizards/wizard-library.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
voltageLevelCreateWizard,
1616
voltageLevelEditWizard,
1717
} from './voltagelevel.js';
18-
import { editPowerTransformerWizard } from './powertransformer.js';
18+
import { createPowerTransformerWizard, editPowerTransformerWizard } from './powertransformer.js';
1919
import { editSubNetworkWizard } from './subnetwork.js';
2020
import { editIEDWizard } from './ied.js';
2121
import { editTrgOpsWizard } from './trgops.js';
@@ -347,7 +347,7 @@ export const wizards: Record<
347347
},
348348
PowerTransformer: {
349349
edit: editPowerTransformerWizard,
350-
create: emptyWizard,
350+
create: createPowerTransformerWizard,
351351
},
352352
Private: {
353353
edit: emptyWizard,

src/zeroline/bay-editor.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { ListItem } from '@material/mwc-list/mwc-list-item';
1717
import '../action-pane.js';
1818
import './ied-editor.js';
1919
import './conducting-equipment-editor.js';
20+
import './powertransformer-editor.js';
2021
import { VoltageLevelEditor } from './voltage-level-editor.js';
2122
import {
2223
getChildElementsByTagName,
@@ -26,6 +27,11 @@ import {
2627
tags,
2728
} from '../foundation.js';
2829
import { emptyWizard, wizards } from '../wizards/wizard-library.js';
30+
import {
31+
cloneSubstationElement,
32+
startMove,
33+
styles,
34+
} from './foundation.js';
2935

3036
function childTags(element: Element | null | undefined): SCLTag[] {
3137
if (!element) return [];
@@ -34,7 +40,6 @@ function childTags(element: Element | null | undefined): SCLTag[] {
3440
child => wizards[child].create !== emptyWizard
3541
);
3642
}
37-
import { startMove, styles, cloneSubstationElement } from './foundation.js';
3843

3944
/** [[`SubstationEditor`]] subeditor for a `Bay` element. */
4045
@customElement('bay-editor')
@@ -135,7 +140,7 @@ export class BayEditor extends LitElement {
135140
<abbr slot="action" title="${translate('move')}">
136141
<mwc-icon-button
137142
icon="forward"
138-
@click=${() => startMove(this, BayEditor, VoltageLevelEditor)}
143+
@click=${() => startMove(this, BayEditor, [VoltageLevelEditor])}
139144
></mwc-icon-button>
140145
</abbr>
141146
<abbr slot="action" title="${translate('remove')}">
@@ -165,6 +170,12 @@ export class BayEditor extends LitElement {
165170
</abbr>
166171
${this.renderIedContainer()}
167172
<div id="ceContainer">
173+
${Array.from(
174+
getChildElementsByTagName(this.element, 'PowerTransformer')
175+
).map(
176+
pwt =>
177+
html`<powertransformer-editor .element=${pwt}></powertransformer-editor>`
178+
)}
168179
${Array.from(
169180
getChildElementsByTagName(this.element, 'ConductingEquipment')
170181
).map(

src/zeroline/conducting-equipment-editor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ export class ConductingEquipmentEditor extends LitElement {
6868
<mwc-fab
6969
slot="action"
7070
mini
71-
@click="${() => startMove(this, ConductingEquipmentEditor, BayEditor)}"
71+
@click="${() => startMove(this, ConductingEquipmentEditor, [BayEditor])}"
7272
icon="forward"
7373
></mwc-fab>
7474
<mwc-fab

src/zeroline/foundation.ts

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,6 @@ export function getAttachedIeds(
100100
};
101101
}
102102

103-
export type ElementEditor = Element & {
104-
element: Element;
105-
};
106-
107103
export function cloneSubstationElement(
108104
editor: BayEditor | VoltageLevelEditor | SubstationEditor
109105
): void {
@@ -144,6 +140,11 @@ export function cloneSubstationElement(
144140
);
145141
}
146142

143+
export type ElementEditor = Element & {
144+
element: Element;
145+
};
146+
export type ElementEditorClass<T extends ElementEditor> = new () => T;
147+
147148
/**
148149
* Moves the element edited by `editor` to the place before the next `Child`
149150
* editor selected or to the end of the next `Parent` editor selected by mouse
@@ -152,10 +153,14 @@ export function cloneSubstationElement(
152153
* The move action can be aborted by clicking on something other than a `Child`
153154
* or `Parent` editor or by hitting the escape key on the keyboard.
154155
*/
155-
export function startMove<E extends ElementEditor, P extends ElementEditor>(
156+
export function startMove<
157+
E extends ElementEditor,
158+
C extends ElementEditorClass<ElementEditor>,
159+
P extends ElementEditorClass<ElementEditor>>
160+
(
156161
editor: E,
157-
Child: new () => E,
158-
Parent: new () => P
162+
childClass: C,
163+
parentClasses: P[]
159164
): void {
160165
if (!editor.element) return;
161166

@@ -179,19 +184,17 @@ export function startMove<E extends ElementEditor, P extends ElementEditor>(
179184

180185
if (e instanceof KeyboardEvent && e.key === 'Escape') return;
181186

182-
const targetEditor = e
183-
.composedPath()
184-
.find(e => e instanceof Child || e instanceof Parent);
185-
187+
const targetEditor = e.composedPath()
188+
.find(et => et instanceof childClass || checkInstanceOfParentClass(et, parentClasses));
186189
if (targetEditor === undefined || targetEditor === editor) return;
187190

188191
const destination =
189-
targetEditor instanceof Child
192+
targetEditor instanceof childClass
190193
? {
191194
parent: targetEditor.element.parentElement!,
192195
reference: targetEditor.element,
193196
}
194-
: { parent: (<P>targetEditor).element, reference: null };
197+
: { parent: (<E>targetEditor).element, reference: null };
195198

196199
if (!destination.parent) return;
197200

@@ -215,6 +218,20 @@ export function startMove<E extends ElementEditor, P extends ElementEditor>(
215218
window.addEventListener('keydown', moveToTarget, true);
216219
}
217220

221+
/**
222+
* Check if the eventTarget that triggered the event is one of the classes that
223+
* we accepted as target to use to move an element to.
224+
*
225+
* @param et - The Event Target.
226+
* @param classes - The list of Classes which are acceptable.
227+
*/
228+
function checkInstanceOfParentClass<E extends ElementEditor>(
229+
et: EventTarget,
230+
classes: ElementEditorClass<E>[]): boolean {
231+
const targetEditor = classes.find(clazz => et instanceof clazz);
232+
return targetEditor !== undefined;
233+
}
234+
218235
/**
219236
* Get the correct icon for a specific Conducting Equipment.
220237
* @param condEq - The Conducting Equipment to search the icon for.
@@ -261,6 +278,14 @@ export const styles = css`
261278
border-bottom: none;
262279
}
263280
281+
#powertransformercontainer {
282+
display: grid;
283+
grid-gap: 12px;
284+
padding: 8px 12px 16px;
285+
box-sizing: border-box;
286+
grid-template-columns: repeat(auto-fit, minmax(64px, auto));
287+
}
288+
264289
#iedcontainer {
265290
display: grid;
266291
grid-gap: 12px;

0 commit comments

Comments
 (0)