From 1e896b3b098589c89e1cfcf13906d20e5463bdd1 Mon Sep 17 00:00:00 2001 From: Jakob Vogelsang Date: Mon, 21 Mar 2022 13:31:33 +0100 Subject: [PATCH] refactor(editors/template/dotype): dotype/sdo wizards use menu actions (#628) * refactor(editors/template/dotype): refactor sdo wizard remove button from content * refactor(editors/template/dotype): refactor dotype wizard remove button from content --- src/editors/templates/dotype-wizards.ts | 108 +++++++----------- .../dotype-wizarding.test.snap.js | 106 ++++++++++++----- .../templates/dotype-wizarding.test.ts | 36 ++++-- .../wizards/da-wizarding-editing.test.ts | 21 +++- 4 files changed, 162 insertions(+), 109 deletions(-) diff --git a/src/editors/templates/dotype-wizards.ts b/src/editors/templates/dotype-wizards.ts index ddc676132..3fe41df6b 100644 --- a/src/editors/templates/dotype-wizards.ts +++ b/src/editors/templates/dotype-wizards.ts @@ -19,14 +19,14 @@ import { getValue, identity, isPublic, - newActionEvent, newSubWizardEvent, - newWizardEvent, Replace, selector, Wizard, + WizardAction, WizardActor, WizardInput, + WizardMenuActor, } from '../../foundation.js'; import { createDaWizard, editDAWizard } from '../../wizards/da.js'; import { patterns } from '../../wizards/foundation/limits.js'; @@ -39,6 +39,12 @@ import { WizardOptions, } from './foundation.js'; +function remove(element: Element): WizardMenuActor { + return (): EditorAction[] => { + return [{ old: { parent: element.parentElement!, element } }]; + }; +} + function updateSDoAction(element: Element): WizardActor { return (inputs: WizardInput[]): EditorAction[] => { const name = getValue(inputs.find(i => i.label === 'name')!)!; @@ -96,29 +102,12 @@ function sDOWizard(options: WizardOptions): Wizard | undefined { ) ).find(isPublic) ?? null; - const [title, action, type, deleteButton, name, desc] = sdo + const [title, action, type, menuActions, name, desc] = sdo ? [ get('sdo.wizard.title.edit'), updateSDoAction(sdo), sdo.getAttribute('type'), - html` { - e.target!.dispatchEvent(newWizardEvent()); - e.target!.dispatchEvent( - newActionEvent({ - old: { - parent: sdo.parentElement!, - element: sdo, - reference: sdo.nextSibling, - }, - }) - ); - }} - fullwidth - > `, + [{ icon: 'delete', label: get('remove'), action: remove(sdo) }], sdo.getAttribute('name'), sdo.getAttribute('desc'), ] @@ -126,7 +115,7 @@ function sDOWizard(options: WizardOptions): Wizard | undefined { get('sdo.wizard.title.add'), createSDoAction((options).parent), null, - html``, + undefined, '', null, ]; @@ -140,8 +129,8 @@ function sDOWizard(options: WizardOptions): Wizard | undefined { title, element: sdo ?? undefined, primary: { icon: '', label: get('save'), action }, + menuActions, content: [ - deleteButton, html` { + return [() => sDOWizard({ parent })!]; + }; +} + +function openAddDa(parent: Element): WizardMenuActor { + return (): WizardAction[] => { + return [() => createDaWizard(parent)!]; + }; +} + function updateDOTypeAction(element: Element): WizardActor { return (inputs: WizardInput[]): EditorAction[] => { const id = getValue(inputs.find(i => i.label === 'id')!)!; @@ -358,25 +359,24 @@ export function dOTypeWizard( label: get('save'), action: updateDOTypeAction(dotype), }, + menuActions: [ + { + label: get('remove'), + icon: 'delete', + action: remove(dotype), + }, + { + label: get('scl.DO'), + icon: 'playlist_add', + action: openAddSdo(dotype), + }, + { + label: get('scl.DA'), + icon: 'playlist_add', + action: openAddDa(dotype), + }, + ], content: [ - html` { - e.target!.dispatchEvent(newWizardEvent()); - e.target!.dispatchEvent( - newActionEvent({ - old: { - parent: dotype.parentElement!, - element: dotype, - reference: dotype.nextSibling, - }, - }) - ); - }} - fullwidth - > `, html``, - html`
- { - const wizard = sDOWizard({ - parent: dotype, - }); - if (wizard) e.target!.dispatchEvent(newSubWizardEvent(wizard)); - }} - > - { - if (dotype) - e.target!.dispatchEvent( - newSubWizardEvent(createDaWizard(dotype)) - ); - }} - > -
`, html` -
- + + + - + + + [remove] + + + delete + + + + + [scl.DO] + + + playlist_add + + + + + [scl.DA] + + + playlist_add + + + + +
-
- - - - -
-
- + + + - + + + [remove] + + + delete + + + + +
{ if (customElements.get('templates-editor') === undefined) @@ -70,6 +71,7 @@ describe('DOType wizards', () => { it('looks like the latest snapshot', async () => { await expect(parent.wizardUI.dialog).to.equalSnapshot(); }); + it('allows to add empty DOTypes to the project', async () => { expect(doc.querySelector('DOType[id="myGeneralDOType"]')).to.not.exist; idField.maybeValue = 'myGeneralDOType'; @@ -79,6 +81,7 @@ describe('DOType wizards', () => { await parent.updateComplete; expect(doc.querySelector('DOType[id="myGeneralDOType"]')).to.exist; }); + it('allows to define CDC only for empty DOType creation', async () => { await cdcField.updateComplete; expect(cdcField.disabled).to.not.be.true; @@ -86,6 +89,7 @@ describe('DOType wizards', () => { await cdcField.requestUpdate(); expect(cdcField.disabled).to.be.true; }); + it('requires CDC definition for empty DOTypes', async () => { expect(doc.querySelector('DOType[id="myGeneralDOType"]')).to.not.exist; idField.maybeValue = 'myGeneralDOType'; @@ -95,6 +99,7 @@ describe('DOType wizards', () => { await parent.updateComplete; expect(doc.querySelector('DOType[id="myGeneralDOType"]')).to.not.exist; }); + it('respects the sequence defined in the standard', async () => { idField.maybeValue = 'myGeneralDOType'; cdcField.maybeValue = 'SPS'; @@ -105,6 +110,7 @@ describe('DOType wizards', () => { expect(element?.nextElementSibling?.tagName).to.equal('DOType'); expect(element?.previousElementSibling?.tagName).to.equal('LNodeType'); }); + it('recursively add missing! subsequent EnumType elements', async () => { expect(doc.querySelector('DOType[id="myENSHealth"]')).to.not.exist; expect(doc.querySelector('EnumType[id="HealthKind"]')).to.not.exist; @@ -119,6 +125,7 @@ describe('DOType wizards', () => { 1 ); }); + it('recursively add missing! subsequent DAType elements', async () => { expect(doc.querySelector('DAType[id="OpenSCD_AnalogueValue_INT32"]')).to .not.exist; @@ -155,14 +162,19 @@ describe('DOType wizards', () => { ) ); deleteButton = ( - parent.wizardUI.dialog?.querySelector('mwc-button[icon="delete"]') + Array.from( + parent.wizardUI.dialog!.querySelectorAll( + 'mwc-menu > mwc-list-item' + ) + ).find(item => item.innerHTML.includes(`[remove]`)) ); }); it('looks like the latest snapshot', async () => { await expect(parent.wizardUI.dialog).to.equalSnapshot(); }); - it('edits DAType attributes id', async () => { + + it('edits DOType attributes id', async () => { expect(doc.querySelector('DOType[id="Dummy.LLN0.Mod"]')).to.exist; idField.value = 'changedDOType'; await parent.requestUpdate(); @@ -171,7 +183,8 @@ describe('DOType wizards', () => { expect(doc.querySelector('DOType[id="Dummy.LLN0.Mod"]')).to.not.exist; expect(doc.querySelector('DOType[id="changedDOType"]')).to.exist; }); - it('deletes the DAType attribute on delete button click', async () => { + + it('deletes the DOType attribute on delete button click', async () => { expect(doc.querySelector('DOType[id="Dummy.LLN0.Mod"]')).to.exist; expect(doc.querySelectorAll('DOType').length).to.equal(15); deleteButton.click(); @@ -179,7 +192,8 @@ describe('DOType wizards', () => { expect(doc.querySelector('DAType[id="Dummy.LLN0.Mod"]')).to.not.exist; expect(doc.querySelectorAll('DOType').length).to.equal(14); }); - it('does not edit DAType element without changes', async () => { + + it('does not edit DOType element without changes', async () => { const originData = (( doc.querySelector('DOType[id="Dummy.LLN0.Mod"]') )).cloneNode(true); @@ -220,7 +234,7 @@ describe('DOType wizards', () => { ) ); deleteButton = ( - parent.wizardUI.dialog?.querySelector('mwc-button[icon="delete"]') + parent.wizardUI.dialog?.querySelector('mwc-menu > mwc-list-item') ); typeSelect =