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(wizards/smvopts): add edit wizard #547

Merged
merged 6 commits into from
Feb 24, 2022
Merged
Show file tree
Hide file tree
Changes from 3 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
9 changes: 8 additions & 1 deletion src/translations/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ export const de: Translations = {
smpMod: 'Abtast-Art',
smpRate: 'Abtastrate',
nofASDU: 'Abtastpunkte pro Datenpacket',
SmvOpts: 'Optionale Informationen',
refreshTime: 'Zeitstempel des Abtastwertes zu Telegram hinzufügen',
sampleRate: 'Abtastrate zu Telegram hinzufügen',
dataSet: 'Datensatznamen zu Telegram hinzufügen',
security: 'Potentiel in Zukunft für z.B. digitale Signature',
synchSourceId: 'Identität der Zeitquelle zu Telegram hinzufügen',
},
settings: {
title: 'Einstellungen',
Expand All @@ -50,7 +56,8 @@ export const de: Translations = {
showieds: 'Zeige IEDs im Substation-Editor',
selectFileButton: 'Datei auswählen',
loadNsdTranslations: 'NSDoc-Dateien hochladen',
invalidFileNoIdFound: 'Ungültiges NSDoc; kein \'id\'-Attribut in der Datei gefunden'
invalidFileNoIdFound:
"Ungültiges NSDoc; kein 'id'-Attribut in der Datei gefunden",
},
menu: {
new: 'Neues projekt',
Expand Down
8 changes: 7 additions & 1 deletion src/translations/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ export const en = {
smpMod: 'Sample mode',
smpRate: 'Sample rate',
nofASDU: 'Samples per paket',
JakobVogelsang marked this conversation as resolved.
Show resolved Hide resolved
SmvOpts: 'Optional Information',
refreshTime: 'Add time stamp to SMV telegram',
sampleRate: 'Add sampled rete time to SMV telegram',
dataSet: 'Add DataSet name to SMV telegram',
security: 'Potential future use. E.g. dig signature',
synchSourceId: 'Add identity of sync source to SMV telegram',
JakobVogelsang marked this conversation as resolved.
Show resolved Hide resolved
},
settings: {
title: 'Settings',
Expand All @@ -48,7 +54,7 @@ export const en = {
showieds: 'Show IEDs in substation editor',
selectFileButton: 'Select file',
loadNsdTranslations: 'Uploading NSDoc files',
invalidFileNoIdFound: 'Invalid NSDoc; no \'id\' attribute found in file'
invalidFileNoIdFound: "Invalid NSDoc; no 'id' attribute found in file",
},
menu: {
new: 'New project',
Expand Down
12 changes: 12 additions & 0 deletions src/wizards/sampledvaluecontrol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
import { securityEnableEnum, smpModEnum } from './foundation/enums.js';
import { maxLength, patterns } from './foundation/limits.js';
import { editSMvWizard } from './smv.js';
import { editSmvOptsWizard } from './smvopts.js';

function getSMV(element: Element): Element | null {
const cbName = element.getAttribute('name');
Expand Down Expand Up @@ -224,6 +225,7 @@ export function editSampledValueControlWizard(element: Element): Wizard {
const securityEnable = element.getAttribute('securityEnabled');

const sMV = getSMV(element);
const smvOpts = element.querySelector('SmvOpts')!;

return [
{
Expand Down Expand Up @@ -257,6 +259,16 @@ export function editSampledValueControlWizard(element: Element): Wizard {
}}}"
></mwc-button>`
: html``,
html`<mwc-button
id="editsmvopts"
label=${translate('scl.SmvOpts')}
icon="edit"
@click="${(e: MouseEvent) => {
e.target?.dispatchEvent(
newSubWizardEvent(() => editSmvOptsWizard(smvOpts))
);
}}}"
></mwc-button>`,
html`<mwc-button
label="${translate('remove')}"
icon="delete"
Expand Down
86 changes: 86 additions & 0 deletions src/wizards/smvopts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { html, TemplateResult } from 'lit-element';
import { get, translate } from 'lit-translate';

import {
cloneElement,
getValue,
Wizard,
WizardAction,
WizardActor,
WizardInput,
} from '../foundation.js';

interface ContentOptions {
refreshTime: string | null;
sampleRate: string | null;
dataSet: string | null;
security: string | null;
synchSourceId: string | null;
}

function contentSmvOptsWizard(option: ContentOptions): TemplateResult[] {
return Object.entries(option).map(
([key, value]) =>
html`<wizard-checkbox
label="${key}"
.maybeValue=${value}
nullable
helper="${translate(`scl.${key}`)}"
></wizard-checkbox>`
);
}

function updateSmvOptsAction(element: Element): WizardActor {
return (inputs: WizardInput[]): WizardAction[] => {
const attributes: Record<string, string | null> = {};
const attributeKeys = [
'refreshTime',
'sampleRate',
'dataSet',
'security',
'synchSourceId',
];
attributeKeys.forEach(key => {
attributes[key] = getValue(inputs.find(i => i.label === key)!);
});

if (
!attributeKeys.some(key => attributes[key] !== element.getAttribute(key))
)
return [];

const newElement = cloneElement(element, attributes);
return [{ old: { element }, new: { element: newElement } }];
};
}

export function editSmvOptsWizard(element: Element): Wizard {
const [refreshTime, sampleRate, dataSet, security, synchSourceId] = [
'refreshTime',
'sampleRate',
'dataSet',
'security',
'synchSourceId',
].map(smvopt => element.getAttribute(smvopt));

return [
{
title: get('wizard.title.edit', { tagName: element.tagName }),
element,
primary: {
icon: 'save',
label: get('save'),
action: updateSmvOptsAction(element),
},
content: [
...contentSmvOptsWizard({
refreshTime,
sampleRate,
dataSet,
security,
synchSourceId,
}),
],
},
];
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { ListItemBase } from '@material/mwc-list/mwc-list-item-base';
import { FilteredList } from '../../../src/filtered-list.js';
import { WizardTextField } from '../../../src/wizard-textfield.js';
import { selectSampledValueControlWizard } from '../../../src/wizards/sampledvaluecontrol.js';
import { WizardCheckbox } from '../../../src/wizard-checkbox.js';

describe('Wizards for SCL element SampledValueControl', () => {
let doc: XMLDocument;
Expand Down Expand Up @@ -239,6 +240,28 @@ describe('Wizards for SCL element SampledValueControl', () => {
);
});

it('opens a edit wizard for SMV on edit SMV button click', async () => {
const editSmvOptsButton = <Button>(
element.wizardUI.dialog!.querySelector(
'mwc-button[id="editsmvopts"]'
)!
);
expect(editSmvOptsButton).to.exist;

await editSmvOptsButton.updateComplete;
editSmvOptsButton.click();
await new Promise(resolve => setTimeout(resolve, 100)); // await animation
JakobVogelsang marked this conversation as resolved.
Show resolved Hide resolved

const macField = <WizardCheckbox>(
element.wizardUI.dialog?.querySelector(
'wizard-checkbox[label="refreshTime"]'
)
);
await macField.updateComplete;

expect(macField).to.exist;
});

it('removes the SampledValueControl element and its referenced elements on remove button click', async () => {
expect(
doc.querySelector(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,12 @@ snapshots["Wizards for SCL element SampledValueControl define an edit wizard tha
SignatureAndEncryption
</mwc-list-item>
</wizard-select>
<mwc-button
icon="edit"
id="editsmvopts"
label="[scl.SmvOpts]"
>
</mwc-button>
<mwc-button
icon="delete"
label="[remove]"
Expand Down
60 changes: 60 additions & 0 deletions test/unit/wizards/__snapshots__/smvopts.test.snap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/* @web/test-runner snapshot v1 */
export const snapshots = {};

snapshots["Wizards for SCL SmvOpts element define an edit wizard that looks like the latest snapshot"] =
`<mwc-dialog
defaultaction="close"
heading="[wizard.title.edit]"
open=""
>
<div id="wizard-content">
<wizard-checkbox
helper="[scl.refreshTime]"
label="refreshTime"
nullable=""
>
</wizard-checkbox>
<wizard-checkbox
helper="[scl.sampleRate]"
label="sampleRate"
nullable=""
>
</wizard-checkbox>
<wizard-checkbox
helper="[scl.dataSet]"
label="dataSet"
nullable=""
>
</wizard-checkbox>
<wizard-checkbox
helper="[scl.security]"
label="security"
nullable=""
>
</wizard-checkbox>
<wizard-checkbox
helper="[scl.synchSourceId]"
label="synchSourceId"
nullable=""
>
</wizard-checkbox>
</div>
<mwc-button
dialogaction="close"
label="[cancel]"
slot="secondaryAction"
style="--mdc-theme-primary: var(--mdc-theme-error)"
>
</mwc-button>
<mwc-button
dialoginitialfocus=""
icon="save"
label="[save]"
slot="primaryAction"
trailingicon=""
>
</mwc-button>
</mwc-dialog>
`;
/* end snapshot Wizards for SCL SmvOpts element define an edit wizard that looks like the latest snapshot */

Loading