diff --git a/src/foundation.ts b/src/foundation.ts
index ed639b97a4..e2de6e75bc 100644
--- a/src/foundation.ts
+++ b/src/foundation.ts
@@ -235,6 +235,12 @@ export function newWizardEvent(
});
}
+export function newSubWizardEvent(
+ wizardOrFactory?: Wizard | WizardFactory
+): WizardEvent {
+ return newWizardEvent(wizardOrFactory, { detail: { subwizard: true } });
+}
+
type InfoEntryKind = 'info' | 'warning' | 'error';
export type LogEntryType =
diff --git a/src/wizards/reportcontrol.ts b/src/wizards/reportcontrol.ts
index 1d9f330ce2..651c1fa8b0 100644
--- a/src/wizards/reportcontrol.ts
+++ b/src/wizards/reportcontrol.ts
@@ -3,6 +3,9 @@ import { get, translate } from 'lit-translate';
import '@material/mwc-button';
import '@material/mwc-list/mwc-list-item';
+import { List } from '@material/mwc-list';
+import { ListItemBase } from '@material/mwc-list/mwc-list-item-base';
+import { SingleSelectedEvent } from '@material/mwc-list/mwc-list-foundation';
import '../wizard-textfield.js';
import '../wizard-select.js';
@@ -15,6 +18,8 @@ import {
getValue,
identity,
isPublic,
+ newSubWizardEvent,
+ selector,
SimpleAction,
Wizard,
WizardActor,
@@ -230,6 +235,17 @@ export function selectReportControlWizard(element: Element): Wizard {
title: get('wizard.title.select', { tagName: 'ReportControl' }),
content: [
html` {
+ const identity = ((e.target).selected).value;
+ const reportControl = element.querySelector(
+ selector('ReportControl', identity)
+ );
+ if (!reportControl) return;
+
+ e.target?.dispatchEvent(
+ newSubWizardEvent(() => editReportControlWizard(reportControl))
+ );
+ }}
>${reportControls.map(
reportControl =>
html`
+ selectReportControlWizard(this.doc.documentElement)
+ )
+ );
}
openGseControlSelection(): void {
diff --git a/src/zeroline/ied-editor.ts b/src/zeroline/ied-editor.ts
index a358519fea..40e7589521 100644
--- a/src/zeroline/ied-editor.ts
+++ b/src/zeroline/ied-editor.ts
@@ -14,7 +14,7 @@ import { Fab } from '@material/mwc-fab';
import '../action-icon.js';
import { createClientLnWizard } from '../wizards/clientln.js';
import { gooseIcon, smvIcon, reportIcon } from '../icons.js';
-import { newWizardEvent } from '../foundation.js';
+import { newSubWizardEvent, newWizardEvent } from '../foundation.js';
import { selectGseControlWizard } from '../wizards/gsecontrol.js';
import { selectSampledValueControlWizard } from '../wizards/sampledvaluecontrol.js';
import { selectReportControlWizard } from '../wizards/reportcontrol.js';
@@ -34,8 +34,9 @@ export class IedEditor extends LitElement {
@query('.connectreport') connectReport!: Fab;
private openReportControlSelection(): void {
- const wizard = selectReportControlWizard(this.element);
- if (wizard) this.dispatchEvent(newWizardEvent(wizard));
+ this.dispatchEvent(
+ newSubWizardEvent(() => selectReportControlWizard(this.element))
+ );
}
private openGseControlSelection(): void {
diff --git a/test/integration/wizards/reportcontrol-wizarding-editing.test.ts b/test/integration/wizards/reportcontrol-wizarding-editing.test.ts
new file mode 100644
index 0000000000..32dd3a8faf
--- /dev/null
+++ b/test/integration/wizards/reportcontrol-wizarding-editing.test.ts
@@ -0,0 +1,164 @@
+import { expect, fixture, html } from '@open-wc/testing';
+
+import '../../mock-wizard-editor.js';
+import { MockWizardEditor } from '../../mock-wizard-editor.js';
+
+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 { selectReportControlWizard } from '../../../src/wizards/reportcontrol.js';
+
+describe('Wizards for SCL element ReportControl', () => {
+ let doc: XMLDocument;
+ let element: MockWizardEditor;
+
+ beforeEach(async () => {
+ element = await fixture(html``);
+ doc = await fetch('/test/testfiles/wizards/reportcontrol.scd')
+ .then(response => response.text())
+ .then(str => new DOMParser().parseFromString(str, 'application/xml'));
+ });
+
+ describe('define a select wizards that ', () => {
+ let reportControlList: FilteredList;
+
+ beforeEach(async () => {
+ const wizard = selectReportControlWizard(doc.documentElement);
+ element.workflow.push(() => wizard);
+ await element.requestUpdate();
+
+ reportControlList = (
+ element.wizardUI.dialog?.querySelector('filtered-list')
+ );
+ await reportControlList.updateComplete;
+ });
+
+ it('shows all ReportControl elements within a project', () =>
+ expect(reportControlList.items.length).to.equal(
+ doc.querySelectorAll('ReportControl').length
+ ));
+
+ it('allows to filter ReportControl elements per IED', async () => {
+ const wizard = selectReportControlWizard(doc.querySelector('IED')!);
+ element.workflow.pop();
+ element.workflow.push(() => wizard);
+ await element.requestUpdate();
+
+ reportControlList = (
+ element.wizardUI.dialog?.querySelector('filtered-list')
+ );
+ await reportControlList.updateComplete;
+
+ expect(reportControlList.items.length).to.equal(
+ doc.querySelector('IED')!.querySelectorAll('ReportControl').length
+ );
+ });
+
+ it('opens edit wizard for selected ReportControl element on click', async () => {
+ const reportItem = reportControlList.items[1];
+ reportItem.click();
+ await new Promise(resolve => setTimeout(resolve, 20)); // await animation
+
+ const nameField = (
+ element.wizardUI.dialog?.querySelector('wizard-textfield[label="name"]')
+ );
+ await nameField.requestUpdate();
+
+ expect(nameField.value).to.equal(
+ doc.querySelectorAll('ReportControl')[1].getAttribute('name')
+ );
+ });
+ });
+
+ describe('defines an edit wizard that', () => {
+ let nameField: WizardTextField;
+ let secondaryAction: HTMLElement;
+ let primaryAction: HTMLElement;
+ let parentIED: Element;
+
+ beforeEach(async () => {
+ parentIED = doc.querySelector('IED')!;
+ element.workflow.push(() => selectReportControlWizard(parentIED));
+ await element.requestUpdate();
+ await new Promise(resolve => setTimeout(resolve, 20)); // await animation
+
+ const report = (
+ (element.wizardUI.dialog?.querySelector('filtered-list'))
+ .items[0]
+ );
+ report.click();
+ await new Promise(resolve => setTimeout(resolve, 20)); // await animation
+
+ nameField = element.wizardUI.dialog!.querySelector(
+ 'wizard-textfield[label="name"]'
+ )!;
+ primaryAction = (
+ element.wizardUI.dialog?.querySelector(
+ 'mwc-button[slot="primaryAction"]'
+ )
+ );
+ secondaryAction = (
+ element.wizardUI.dialog?.querySelector(
+ 'mwc-button[slot="secondaryAction"]'
+ )
+ );
+ await nameField.updateComplete;
+ });
+
+ it('rejects name attribute starting with decimals', async () => {
+ expect(
+ parentIED.querySelector('ReportControl')?.getAttribute('name')
+ ).to.not.equal('4adsasd');
+
+ nameField.value = '4adsasd';
+ await element.requestUpdate();
+ primaryAction.click();
+
+ expect(
+ parentIED.querySelector('ReportControl')?.getAttribute('name')
+ ).to.not.equal('4adsasd');
+ });
+
+ it('edits name attribute on primary action', async () => {
+ expect(
+ parentIED.querySelector('ReportControl')?.getAttribute('name')
+ ).to.not.equal('myNewName');
+
+ nameField.value = 'myNewName';
+ await element.requestUpdate();
+ primaryAction.click();
+
+ expect(
+ parentIED.querySelector('ReportControl')?.getAttribute('name')
+ ).to.equal('myNewName');
+ });
+
+ it('dynamically updates wizards after attribute change', async () => {
+ nameField.value = 'myNewName';
+ primaryAction.click();
+
+ await new Promise(resolve => setTimeout(resolve, 100)); // await animation
+
+ const report = (
+ (element.wizardUI.dialog?.querySelector('filtered-list'))
+ .items[0]
+ );
+
+ expect(report.innerHTML).to.contain('myNewName');
+ });
+
+ it('returns back to its starting wizard on secondary action', async () => {
+ secondaryAction.click();
+
+ await new Promise(resolve => setTimeout(resolve, 100)); // await animation
+
+ const report = (
+ (element.wizardUI.dialog?.querySelector('filtered-list'))
+ .items[0]
+ );
+
+ expect(report.innerHTML).to.contain('ReportCb');
+ });
+ });
+});
diff --git a/test/testfiles/wizards/reportcontrol.scd b/test/testfiles/wizards/reportcontrol.scd
index f34ab84548..1d2874926e 100644
--- a/test/testfiles/wizards/reportcontrol.scd
+++ b/test/testfiles/wizards/reportcontrol.scd
@@ -126,4 +126,88 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ status-only
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ status-only
+
+
+
+
+
+
+
+
+
+
+ status-only
+
+
+
+
+
+
+
+
diff --git a/test/unit/wizards/__snapshots__/reportcontrol.test.snap.js b/test/unit/wizards/__snapshots__/reportcontrol.test.snap.js
index c8eb4f4e33..6c29bd7141 100644
--- a/test/unit/wizards/__snapshots__/reportcontrol.test.snap.js
+++ b/test/unit/wizards/__snapshots__/reportcontrol.test.snap.js
@@ -180,6 +180,34 @@ snapshots["Wizards for SCL ReportControl element define a select wizard that loo
IED2>>CBSW> XSWI 2>ReportCb3
+
+
+ ReportCb
+
+
+ IED3>>CBSW>ReportCb
+
+
+
+
+ ReportCb2
+
+
+ IED3>>CBSW> XSWI 1>ReportCb2
+
+