Skip to content

Commit

Permalink
feat: support ldname attribute
Browse files Browse the repository at this point in the history
Signed-off-by: Stef3st <[email protected]>
  • Loading branch information
Stef3st committed Dec 21, 2023
1 parent a3f2f5c commit 5c6f2dd
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 4 deletions.
23 changes: 22 additions & 1 deletion packages/open-scd/src/editors/ied/ldevice-container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@ import {
getDescriptionAttribute,
getInstanceAttribute,
getNameAttribute,
getLdNameAttribute,
newWizardEvent,
} from '../../foundation.js';
import { logicalDeviceIcon } from '../../icons/ied-icons.js';

import '../../action-pane.js';
import './ln-container.js';

import { wizards } from '../../wizards/wizard-library.js';
import { Container } from './foundation.js';

/** [[`IED`]] plugin subeditor for editing `LDevice` element. */
Expand All @@ -34,12 +37,20 @@ export class LDeviceContainer extends Container {
@query('#toggleButton')
toggleButton!: IconButtonToggle | undefined;

private openEditWizard(): void {
const wizard = wizards['LDevice'].edit(this.element);
if (wizard) this.dispatchEvent(newWizardEvent(wizard));
}

private header(): TemplateResult {
const nameOrInst =
getNameAttribute(this.element) ?? getInstanceAttribute(this.element);
const desc = getDescriptionAttribute(this.element);
const ldName = getLdNameAttribute(this.element);

return html`${nameOrInst}${desc ? html` &mdash; ${desc}` : nothing}`;
return html`${nameOrInst}${desc ? html` &mdash; ${desc}` : nothing}${ldName
? html` &mdash; ${ldName}`
: nothing}`;
}

protected firstUpdated(): void {
Expand Down Expand Up @@ -70,6 +81,12 @@ export class LDeviceContainer extends Container {

return html`<action-pane .label="${this.header()}">
<mwc-icon slot="icon">${logicalDeviceIcon}</mwc-icon>
<abbr slot="action" title="${translate('edit')}">
<mwc-icon-button
icon="edit"
@click=${() => this.openEditWizard()}
></mwc-icon-button>
</abbr>
${lnElements.length > 0
? html`<abbr
slot="action"
Expand Down Expand Up @@ -108,6 +125,10 @@ export class LDeviceContainer extends Container {
grid-template-columns: repeat(auto-fit, minmax(316px, auto));
}
abbr {
text-decoration: none;
}
@media (max-width: 387px) {
#lnContainer {
grid-template-columns: repeat(auto-fit, minmax(196px, auto));
Expand Down
17 changes: 15 additions & 2 deletions packages/open-scd/src/foundation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,10 @@ export type WizardInputElement =
| TextField
| (AceEditor & {
checkValidity: () => boolean;
validityTransform: (newValue: string, nativeValidity: ValidityState) => ValidityState;
validityTransform: (
newValue: string,
nativeValidity: ValidityState
) => ValidityState;
validationMessage: string;
validity: ValidityState;
label: string;
Expand Down Expand Up @@ -514,6 +517,16 @@ export function getNameAttribute(element: Element): string | undefined {
return name ? name : undefined;
}

/**
* Extract the 'ldName' attribute from the given XML element.
* @param element - The element to extract ldName from.
* @returns the ldName, or undefined if there is no ldName.
*/
export function getLdNameAttribute(element: Element): string | undefined {
const name = element.getAttribute('ldName');
return name ? name : undefined;
}

/**
* Extract the 'desc' attribute from the given XML element.
* @param element - The element to extract description from.
Expand Down Expand Up @@ -1559,7 +1572,7 @@ const sCLTags = [
'SecPerSamples',
] as const;

export type SCLTag = typeof sCLTags[number];
export type SCLTag = (typeof sCLTags)[number];

const tagSet = new Set<string>(sCLTags);

Expand Down
9 changes: 9 additions & 0 deletions packages/open-scd/src/translations/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,15 @@ export const de: Translations = {
deleteied: 'IED "{{name}}" entfernt',
},
},
ldevice: {
wizard: {
nameHelper: 'Name des Logisches Gerät',
descHelper: 'Beschreibung des Logisches Gerät',
title: {
edit: 'Logisches Gerät bearbeiten',
},
},
},
powertransformer: {
wizard: {
nameHelper: '`Name des Leistungstransformators',
Expand Down
9 changes: 9 additions & 0 deletions packages/open-scd/src/translations/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,15 @@ export const en = {
deleteied: 'Removed IED "{{name}}"',
},
},
ldevice: {
wizard: {
nameHelper: 'Logical device name',
descHelper: 'Logical device description',
title: {
edit: 'Edit logical device',
},
},
},
powertransformer: {
wizard: {
nameHelper: 'Power transformer name',
Expand Down
114 changes: 114 additions & 0 deletions packages/open-scd/src/wizards/ldevice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { html, TemplateResult } from 'lit-element';
import { get, translate } from 'lit-translate';

import '@material/mwc-list';
import '@material/mwc-list/mwc-list-item';

import '../wizard-textfield.js';
import {
cloneElement,
getValue,
SimpleAction,
Wizard,
WizardActor,
WizardInputElement,
} from '../foundation.js';

import { patterns } from './foundation/limits.js';

const lDeviceNamePattern =
'[A-Za-z][0-9A-Za-z_]{0,2}|' +
'[A-Za-z][0-9A-Za-z_]{4,63}|' +
'[A-MO-Za-z][0-9A-Za-z_]{3}|' +
'N[0-9A-Za-np-z_][0-9A-Za-z_]{2}|' +
'No[0-9A-Za-mo-z_][0-9A-Za-z_]|' +
'Non[0-9A-Za-df-z_]';

export function renderLdeviceWizard(
ldName: string | null,
readOnly: boolean,
desc: string | null,
ldInst: string | null
): TemplateResult[] {
return [
readOnly
? html`<wizard-textfield
label="ldName"
.maybeValue=${ldName}
readOnly
disabled
></wizard-textfield>`
: html`<wizard-textfield
label="ldName"
.maybeValue=${ldName}
helper="${translate('ldevice.wizard.nameHelper')}"
required
validationMessage="${translate('textfield.required')}"
dialogInitialFocus
pattern="${lDeviceNamePattern}"
></wizard-textfield>`,
html`<wizard-textfield
label="desc"
.maybeValue=${desc}
nullable
helper="${translate('ldevice.wizard.descHelper')}"
pattern="${patterns.normalizedString}"
></wizard-textfield>`,
html`<wizard-textfield
label="ldInst"
.maybeValue=${ldInst}
readOnly
disabled
></wizard-textfield>`,
];
}

function ldNameIsAllowed(element: Element): boolean {
const ConfLdName = element
.closest('IED')
?.querySelector('Services > ConfLdName');
if (ConfLdName) return true;

return false;
}

function updateAction(element: Element): WizardActor {
return (inputs: WizardInputElement[]): SimpleAction[] => {
const ldAttrs: Record<string, string | null> = {};
const ldKeys = ['ldName', 'desc', 'ldInst'];
ldKeys.forEach(key => {
ldAttrs[key] = getValue(inputs.find(i => i.label === key)!);
});

if (ldKeys.some(key => ldAttrs[key] !== element.getAttribute(key))) {
const newElement = cloneElement(element, ldAttrs);
return [
{
old: { element },
new: { element: newElement },
},
];
}
return [];
};
}

export function editLDeviceWizard(element: Element): Wizard {
return [
{
title: get('ldevice.wizard.title.edit'),
element,
primary: {
icon: 'edit',
label: get('save'),
action: updateAction(element),
},
content: renderLdeviceWizard(
element.getAttribute('ldName'),
!ldNameIsAllowed(element),
element.getAttribute('desc'),
element.getAttribute('inst')
),
},
];
}
3 changes: 2 additions & 1 deletion packages/open-scd/src/wizards/wizard-library.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
} from './powertransformer.js';
import { editSubNetworkWizard } from './subnetwork.js';
import { editIEDWizard } from './ied.js';
import { editLDeviceWizard } from './ldevice.js';
import { editTrgOpsWizard } from './trgops.js';
import { createDaWizard } from './da.js';
import { editDAIWizard } from './dai.js';
Expand Down Expand Up @@ -317,7 +318,7 @@ export const wizards: Record<
create: emptyWizard,
},
LDevice: {
edit: emptyWizard,
edit: editLDeviceWizard,
create: emptyWizard,
},
LN: {
Expand Down

0 comments on commit 5c6f2dd

Please sign in to comment.