diff --git a/__snapshots__/action-pane.md b/__snapshots__/action-pane.md new file mode 100644 index 0000000000..232e04a63b --- /dev/null +++ b/__snapshots__/action-pane.md @@ -0,0 +1,51 @@ +# `action-pane` + +#### `looks like the latest snapshot` + +```html +
+

+ + + + + +

+
+ + +
+
+ +``` + +## `with icon property set` + +#### `looks like the latest snapshot` + +```html +
+

+ + + + edit + + + + +

+
+ + +
+
+ +``` + diff --git a/__snapshots__/bay-editor.md b/__snapshots__/bay-editor.md index fa16050c56..0847eba95c 100644 --- a/__snapshots__/bay-editor.md +++ b/__snapshots__/bay-editor.md @@ -3,45 +3,80 @@ #### `looks like the latest snapshot` ```html - + + + + + + + LNode + + + + + ConductingEquipment + + + +
@@ -54,7 +89,7 @@
-
+ ``` @@ -63,45 +98,80 @@ #### `looks like the latest snapshot` ```html - + + + + + + + LNode + + + + + ConductingEquipment + + + +
@@ -114,7 +184,7 @@
-
+ ``` diff --git a/__snapshots__/substation-editor.md b/__snapshots__/substation-editor.md index c276e18a90..e9fcc87300 100644 --- a/__snapshots__/substation-editor.md +++ b/__snapshots__/substation-editor.md @@ -3,47 +3,85 @@ #### `looks like the latest snapshot` ```html - + + + + + + + + LNode + + + + + VoltageLevel + + + + - + ``` @@ -52,47 +90,85 @@ #### `looks like the latest snapshot` ```html - + + + + + + + + LNode + + + + + VoltageLevel + + + + - + ``` diff --git a/__snapshots__/voltage-level-editor.md b/__snapshots__/voltage-level-editor.md index 1d1336d582..7db8c8314c 100644 --- a/__snapshots__/voltage-level-editor.md +++ b/__snapshots__/voltage-level-editor.md @@ -3,53 +3,88 @@ #### `looks like the latest snapshot` ```html - + + + + + + + LNode + + + + + Bay + + + +
-
+ ``` @@ -58,53 +93,88 @@ #### `looks like the latest snapshot` ```html - + + + + + + + LNode + + + + + Bay + + + +
-
+ ``` diff --git a/src/action-pane.ts b/src/action-pane.ts new file mode 100644 index 0000000000..0d43ffef2a --- /dev/null +++ b/src/action-pane.ts @@ -0,0 +1,174 @@ +import { + css, + customElement, + html, + LitElement, + property, + TemplateResult, +} from 'lit-element'; +import { classMap } from 'lit-html/directives/class-map'; + +import '@material/mwc-icon'; +import { nothing } from 'lit-html'; + +function closestTo(node: Node, selector: string): E | null { + const closest = + node.nodeType === Node.ELEMENT_NODE + ? (node).closest(selector) + : null; + + if (closest) return closest; + + const root = node.getRootNode(); + + if (root instanceof ShadowRoot) return closestTo(root.host, selector); + + return null; +} + +/** + * A responsive container rendering actions in a header. + * + * The "action" slot may contain up to eight icon buttons. + * The "icon" slot, if filled overrides the icon property. + * The default slot will be rendered into the pane body in a single column. + */ +@customElement('action-pane') +export class ActionPane extends LitElement { + /** caption text, displayed in the header */ + @property({ type: String }) + label?: string; + /** icon name, displayed unless the "icon" slot is filled */ + @property({ type: String }) + icon?: string; + /** color header with secondary theme color while focus is within */ + @property({ type: Boolean }) + secondary = false; + /** highlight pane with dotted outline */ + @property({ type: Boolean }) + highlighted = false; + /** nesting level, default (closest pane ancestor's level) + 1 */ + @property({ type: Number }) + level = 1; + + async firstUpdated(): Promise { + this.tabIndex = 0; + + const parentPane = closestTo(this.parentNode!, 'action-pane'); + if (parentPane) this.level = parentPane.level + 1; + + this.level = Math.floor(this.level); + } + + private renderHeader(): TemplateResult { + const content = html`${this.icon + ? html`${this.icon}` + : nothing} + ${this.label ?? nothing} + `; + + const headingLevel = Math.floor(Math.max(this.level, 1)); + switch (headingLevel) { + case 1: + return html`

${content}

`; + case 2: + return html`

${content}

`; + case 3: + return html`

${content}

`; + case 4: + return html`

${content}

`; + case 5: + return html`
${content}
`; + default: + return html`
${content}
`; + } + } + + render(): TemplateResult { + return html`
+ ${this.renderHeader()} +
+
`; + } + + static styles = css` + :host { + outline: none; + } + + :host(:focus-within) section { + box-shadow: 0 8px 10px 1px rgba(0, 0, 0, 0.14), + 0 3px 14px 2px rgba(0, 0, 0, 0.12), 0 5px 5px -3px rgba(0, 0, 0, 0.2); + outline-width: 4px; + transition: all 250ms linear; + } + + section { + background-color: var(--mdc-theme-surface); + transition: all 200ms linear; + outline-style: solid; + margin: 0px; + outline-width: 0px; + outline-color: var(--mdc-theme-primary); + } + + section.secondary { + outline-color: var(--mdc-theme-secondary); + } + + section > div { + display: flex; + flex-direction: column; + gap: 12px; + padding: 8px 12px 16px; + clear: right; + } + + .highlighted { + outline-style: dotted; + outline-width: 2px; + } + + .contrasted { + background-color: var(--mdc-theme-on-primary); + } + + h1, + h2, + h3, + h4, + h5, + h6 { + color: var(--mdc-theme-on-surface); + font-family: 'Roboto', sans-serif; + font-weight: 300; + overflow: visible; + white-space: nowrap; + text-overflow: ellipsis; + margin: 0px; + line-height: 52px; + padding-left: 0.3em; + } + + nav { + float: right; + } + + mwc-icon { + vertical-align: middle; + position: relative; + top: -0.1em; + --mdc-icon-size: 1em; + } + `; +} diff --git a/src/editor-container.ts b/src/editor-container.ts deleted file mode 100644 index 5d3633c3a0..0000000000 --- a/src/editor-container.ts +++ /dev/null @@ -1,315 +0,0 @@ -import { - css, - customElement, - html, - internalProperty, - LitElement, - property, - query, - TemplateResult, -} from 'lit-element'; -import { classMap } from 'lit-html/directives/class-map'; - -import { newWizardEvent, SCLTag, tags } from './foundation.js'; - -import { emptyWizard, wizards } from './wizards/wizard-library.js'; - -import { Menu } from '@material/mwc-menu'; -import { IconButton } from '@material/mwc-icon-button'; -import { ListItem } from '@material/mwc-list/mwc-list-item'; - -function childTags(element: Element | null | undefined): SCLTag[] { - if (!element) return []; - - return tags[element.tagName].children.filter( - child => wizards[child].create !== emptyWizard - ); -} - -/** - * A responsive container for nested elements with header and - * create new child functionality. - */ -@customElement('editor-container') -export class EditorContainer extends LitElement { - /** The visualized `Element`. */ - @property() - element: Element | null = null; - /**Overwrites default header text*/ - @property({ type: String }) - header = ''; - /** Sets the header type h1, h2, h3, h4, h5 or h6 */ - @property({ type: Number }) - level: 1 | 2 | 3 | 4 | 5 | 6 = 1; - /** Sets the focused header color */ - @property({ type: Boolean }) - secondary = false; - /** Whether different background color shall be used */ - @property({ type: Boolean }) - contrasted = false; - /** Wether outline shall be permanent */ - @property({ type: Boolean }) - highlighted = false; - /** Whether the container does not have margins*/ - @property({ type: Boolean }) - nomargin = false; - - @internalProperty() - get defaultHeader(): string { - const name = this.element?.getAttribute('name') ?? ''; - const desc = this.element?.getAttribute('desc'); - - return `${name}${desc ? ` - ${desc}` : ''}`; - } - - @query('mwc-icon-button[icon="playlist_add"]') addIcon?: IconButton; - @query('#menu') addMenu!: Menu; - @query('#header') headerContainer!: HTMLElement; - @query('#morevert > mwc-icon-button') moreVert?: IconButton; - @query('.container') container!: HTMLElement; - - private openCreateWizard(tagName: string): void { - const wizard = wizards[tagName].create(this.element!); - - if (wizard) this.dispatchEvent(newWizardEvent(wizard)); - } - - async firstUpdated(): Promise { - await super.updateComplete; - - this.tabIndex = 0; - - if (this.addMenu) this.addMenu.anchor = this.headerContainer; - - const parentEditorContainer = - ( - (this.parentNode).host?.closest('editor-container') - ) ?? null; - - if (!parentEditorContainer) return; - - this.level = <1 | 2 | 3 | 4 | 5 | 6>( - Math.min(parentEditorContainer.level + 1, 6) - ); - - this.contrasted = !parentEditorContainer.contrasted; - } - - private renderAddButtons(): TemplateResult[] { - return childTags(this.element).map( - child => - html`${child}` - ); - } - - private styleFabButtonTransform(): string[] { - let transform = 0; - return Array.from(this.children).map((child, i) => { - if (child.tagName === 'MWC-FAB') - return `#morevert:focus-within > - ::slotted(mwc-fab:nth-child(${i + 1})) { transform: translate(0, - ${++transform * 48}px); }`; - return ``; - }); - } - - private renderHeaderBody(): TemplateResult { - return html`${this.header !== '' ? this.header : this.defaultHeader} - ${childTags(this.element).length - ? html` (this.addMenu.open = true)} - > - { - const tagName = ((e.target).selected).value; - this.openCreateWizard(tagName); - }} - >${this.renderAddButtons()} - ` - : html``} - ${Array.from(this.children).some(child => child.tagName === 'MWC-FAB') - ? html`
- - -
` - : html``} - `; - } - - private renderHeader(): TemplateResult { - let header = html``; - - switch (this.level) { - case 1: - header = html`

${this.renderHeaderBody()}

`; - break; - case 2: - header = html`

${this.renderHeaderBody()}

`; - break; - case 3: - header = html`

${this.renderHeaderBody()}

`; - break; - case 4: - header = html`

${this.renderHeaderBody()}

`; - break; - case 5: - header = html`
${this.renderHeaderBody()}
`; - break; - case 6: - header = html`
${this.renderHeaderBody()}
`; - } - - return html``; - } - - render(): TemplateResult { - return html`
- ${this.renderHeader()} - -
`; - } - - static styles = css` - :host(.moving) .container { - opacity: 0.3; - } - - .container { - background-color: var(--mdc-theme-surface); - transition: all 200ms linear; - outline-style: solid; - margin: 8px 12px 16px; - padding: 0.05px; - outline-width: 0px; - outline-color: var(--mdc-theme-primary); - opacity: 1; - } - - .container.secondary { - outline-color: var(--mdc-theme-secondary); - } - - .highlighted { - outline-width: 2px; - } - - .contrasted { - background-color: var(--mdc-theme-on-primary); - } - - .nomargin { - margin: 0px; - } - - :host { - outline: none; - } - - :host(:focus-within) .container { - box-shadow: 0 8px 10px 1px rgba(0, 0, 0, 0.14), - 0 3px 14px 2px rgba(0, 0, 0, 0.12), 0 5px 5px -3px rgba(0, 0, 0, 0.2); - outline-width: 2px; - transition: all 250ms linear; - } - - :host(:focus-within) h1, - :host(:focus-within) h2, - :host(:focus-within) h3 { - color: var(--mdc-theme-surface); - transition: background-color 200ms linear; - background-color: var(--mdc-theme-primary); - } - - :host(:focus-within) .container.secondary h1, - :host(:focus-within) .container.secondary h2, - :host(:focus-within) .container.secondary h3 { - background-color: var(--mdc-theme-secondary); - } - - h1, - h2, - h3 { - color: var(--mdc-theme-on-surface); - font-family: 'Roboto', sans-serif; - font-weight: 300; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - margin: 0px; - line-height: 48px; - padding-left: 0.3em; - transition: background-color 150ms linear; - } - - h1 > ::slotted(mwc-icon-button), - h2 > ::slotted(mwc-icon-button), - h3 > ::slotted(mwc-icon-button), - h1 > ::slotted(abbr), - h2 > ::slotted(abbr), - h3 > ::slotted(abbr) { - float: right; - } - - h1 > nav, - h2 > nav, - h3 > nav { - float: right; - } - - h1 > mwc-icon-button, - h2 > mwc-icon-button, - h3 > mwc-icon-button { - float: right; - } - - #morevert { - float: right; - } - - #header { - position: relative; - } - - abbr { - text-decoration: none; - border-bottom: none; - } - - ::slotted(mwc-fab) { - color: var(--mdc-theme-on-surface); - opacity: 0; - position: absolute; - pointer-events: none; - z-index: 1; - transition: transform 200ms cubic-bezier(0.4, 0, 0.2, 1), - opacity 200ms linear; - } - - #morevert:focus-within > ::slotted(mwc-fab) { - transition: transform 250ms cubic-bezier(0.4, 0, 0.2, 1), - opacity 250ms linear; - pointer-events: auto; - opacity: 1; - } - `; -} diff --git a/src/zeroline-pane.ts b/src/zeroline-pane.ts index 75abf52ded..1326c89982 100644 --- a/src/zeroline-pane.ts +++ b/src/zeroline-pane.ts @@ -141,8 +141,7 @@ export class ZerolinePane extends LitElement { } static styles = css` - h1, - h3 { + h1 { color: var(--mdc-theme-on-surface); font-family: 'Roboto', sans-serif; font-weight: 300; @@ -160,6 +159,10 @@ export class ZerolinePane extends LitElement { float: right; } + section { + padding: 8px 12px 16px; + } + abbr { text-decoration: none; border-bottom: none; diff --git a/src/zeroline/bay-editor.ts b/src/zeroline/bay-editor.ts index 62b1153837..d0a714982b 100644 --- a/src/zeroline/bay-editor.ts +++ b/src/zeroline/bay-editor.ts @@ -4,6 +4,7 @@ import { html, LitElement, property, + query, TemplateResult, } from 'lit-element'; import { translate } from 'lit-translate'; @@ -13,12 +14,26 @@ import { getChildElementsByTagName, newActionEvent, newWizardEvent, + SCLTag, + tags, } from '../foundation.js'; -import { wizards } from '../wizards/wizard-library.js'; +import { emptyWizard, wizards } from '../wizards/wizard-library.js'; import { VoltageLevelEditor } from './voltage-level-editor.js'; import './conducting-equipment-editor.js'; +import '../action-pane.js'; +import { Menu } from '@material/mwc-menu'; +import { IconButton } from '@material/mwc-icon-button'; +import { ListItem } from '@material/mwc-list/mwc-list-item'; + +function childTags(element: Element | null | undefined): SCLTag[] { + if (!element) return []; + + return tags[element.tagName].children.filter( + child => wizards[child].create !== emptyWizard + ); +} /** [[`SubstationEditor`]] subeditor for a `Bay` element. */ @customElement('bay-editor') @@ -28,11 +43,22 @@ export class BayEditor extends LitElement { @property({ type: Boolean }) readonly = false; + @property({ type: String }) + get header(): string { + const name = this.element.getAttribute('name') ?? ''; + const desc = this.element.getAttribute('desc'); + + return `${name} ${desc ? `- ${desc}` : ''}`; + } + @property({ attribute: false }) getAttachedIeds?: (element: Element) => Element[] = () => { return []; }; + @query('mwc-menu') addMenu!: Menu; + @query('mwc-icon-button[icon="playlist_add"]') addButton!: IconButton; + openEditWizard(): void { const wizard = wizards['Bay'].edit(this.element); if (wizard) this.dispatchEvent(newWizardEvent(wizard)); @@ -57,6 +83,16 @@ export class BayEditor extends LitElement { ); } + private openCreateWizard(tagName: string): void { + const wizard = wizards[tagName].create(this.element!); + + if (wizard) this.dispatchEvent(newWizardEvent(wizard)); + } + + firstUpdated(): void { + this.addMenu.anchor = this.addButton; + } + renderIedContainer(): TemplateResult { const ieds = this.getAttachedIeds?.(this.element) ?? []; return ieds?.length @@ -66,38 +102,66 @@ export class BayEditor extends LitElement { : html``; } + private renderAddButtons(): TemplateResult[] { + return childTags(this.element).map( + child => + html`${child}` + ); + } + render(): TemplateResult { - return html` - + return html` + - + cloneSubstationElement(this)} > - + this.openEditWizard()} > - + startMove(this, BayEditor, VoltageLevelEditor)} > - + this.remove()} > + + (this.addMenu.open = true)} + > { + const tagName = ((e.target).selected).value; + this.openCreateWizard(tagName); + }} + >${this.renderAddButtons()} + ${this.renderIedContainer()}
${Array.from( @@ -110,7 +174,7 @@ export class BayEditor extends LitElement { >` )}
- `; + `; } static styles = css` diff --git a/src/zeroline/foundation.ts b/src/zeroline/foundation.ts index be2c9578b0..488f6488f9 100644 --- a/src/zeroline/foundation.ts +++ b/src/zeroline/foundation.ts @@ -1,13 +1,6 @@ import { css } from 'lit-element'; -import { - newActionEvent, - isPublic, - SCLTag, - Wizard, - tags, -} from '../foundation.js'; -import { emptyWizard, wizards } from '../wizards/wizard-library.js'; +import { newActionEvent, isPublic } from '../foundation.js'; import { BayEditor } from './bay-editor.js'; import { SubstationEditor } from './substation-editor.js'; @@ -238,11 +231,19 @@ export const selectors = >( /** Common `CSS` styles used by substation subeditors */ export const styles = css` + :host { + transition: opacity 200ms linear; + } + abbr { text-decoration: none; border-bottom: none; } + .moving { + opacity: 0.3; + } + #iedcontainer { display: grid; grid-gap: 12px; diff --git a/src/zeroline/substation-editor.ts b/src/zeroline/substation-editor.ts index e31616bec0..cbc83d497f 100644 --- a/src/zeroline/substation-editor.ts +++ b/src/zeroline/substation-editor.ts @@ -4,11 +4,12 @@ import { html, LitElement, property, + query, TemplateResult, } from 'lit-element'; import { translate } from 'lit-translate'; -import { newActionEvent, newWizardEvent } from '../foundation.js'; +import { newActionEvent, newWizardEvent, SCLTag, tags } from '../foundation.js'; import { cloneSubstationElement, selectors, @@ -16,10 +17,21 @@ import { styles, } from './foundation.js'; -import { wizards } from '../wizards/wizard-library.js'; +import { emptyWizard, wizards } from '../wizards/wizard-library.js'; import './voltage-level-editor.js'; -import '../editor-container.js'; +import '../action-pane.js'; +import { Menu } from '@material/mwc-menu'; +import { IconButton } from '@material/mwc-icon-button'; +import { ListItem } from '@material/mwc-list/mwc-list-item'; + +function childTags(element: Element | null | undefined): SCLTag[] { + if (!element) return []; + + return tags[element.tagName].children.filter( + child => wizards[child].create !== emptyWizard + ); +} /** [[`Substation`]] plugin subeditor for editing `Substation` sections. */ @customElement('substation-editor') @@ -30,11 +42,22 @@ export class SubstationEditor extends LitElement { @property({ type: Boolean }) readonly = false; + @property({ type: String }) + get header(): string { + const name = this.element.getAttribute('name') ?? ''; + const desc = this.element.getAttribute('desc'); + + return `${name} ${desc ? `- ${desc}` : ''}`; + } + @property({ attribute: false }) getAttachedIeds?: (element: Element) => Element[] = () => { return []; }; + @query('mwc-menu') addMenu!: Menu; + @query('mwc-icon-button[icon="playlist_add"]') addButton!: IconButton; + /** Opens a [[`WizardDialog`]] for editing [[`element`]]. */ openEditWizard(): void { const wizard = wizards['Substation'].edit(this.element); @@ -60,6 +83,16 @@ export class SubstationEditor extends LitElement { ); } + private openCreateWizard(tagName: string): void { + const wizard = wizards[tagName].create(this.element!); + + if (wizard) this.dispatchEvent(newWizardEvent(wizard)); + } + + firstUpdated(): void { + this.addMenu.anchor = this.addButton; + } + renderIedContainer(): TemplateResult { const ieds = this.getAttachedIeds?.(this.element) ?? []; return ieds?.length @@ -69,38 +102,66 @@ export class SubstationEditor extends LitElement { : html``; } + private renderAddButtons(): TemplateResult[] { + return childTags(this.element).map( + child => + html`${child}` + ); + } + render(): TemplateResult { - return html` - + return html` + this.openLNodeWizard()} > - + cloneSubstationElement(this)} > - + this.openEditWizard()} > - + startMove(this, SubstationEditor, SubstationEditor)} > - + this.remove()} > + + (this.addMenu.open = true)} + > { + const tagName = ((e.target).selected).value; + this.openCreateWizard(tagName); + }} + >${this.renderAddButtons()} + ${this.renderIedContainer()} ${Array.from(this.element.querySelectorAll(selectors.VoltageLevel)).map( voltageLevel => @@ -109,7 +170,7 @@ export class SubstationEditor extends LitElement { .getAttachedIeds=${this.getAttachedIeds} ?readonly=${this.readonly} >` - )}`; } diff --git a/src/zeroline/voltage-level-editor.ts b/src/zeroline/voltage-level-editor.ts index 091bf73e51..f77854dfad 100644 --- a/src/zeroline/voltage-level-editor.ts +++ b/src/zeroline/voltage-level-editor.ts @@ -5,6 +5,7 @@ import { html, property, css, + query, } from 'lit-element'; import { translate } from 'lit-translate'; @@ -14,17 +15,29 @@ import { cloneSubstationElement, styles, } from './foundation.js'; -import { newActionEvent, newWizardEvent } from '../foundation.js'; +import { newActionEvent, newWizardEvent, SCLTag, tags } from '../foundation.js'; import { SubstationEditor } from './substation-editor.js'; -import { wizards } from '../wizards/wizard-library.js'; +import { emptyWizard, wizards } from '../wizards/wizard-library.js'; import './bay-editor.js'; +import '../action-pane.js'; +import { Menu } from '@material/mwc-menu'; +import { IconButton } from '@material/mwc-icon-button'; +import { ListItem } from '@material/mwc-list/mwc-list-item'; + +function childTags(element: Element | null | undefined): SCLTag[] { + if (!element) return []; + + return tags[element.tagName].children.filter( + child => wizards[child].create !== emptyWizard + ); +} /** [[`Substation`]] subeditor for a `VoltageLevel` element. */ @customElement('voltage-level-editor') export class VoltageLevelEditor extends LitElement { - @property() + @property({ attribute: false }) element!: Element; @property({ type: Boolean }) readonly = false; @@ -43,7 +56,7 @@ export class VoltageLevelEditor extends LitElement { const name = this.element.getAttribute('name') ?? ''; const desc = this.element.getAttribute('desc'); - return `${name} ${desc === null ? '' : '-'} ${desc} + return `${name} ${desc ? `- ${desc}` : ''} ${this.voltage === null ? '' : `(${this.voltage})`}`; } @@ -52,6 +65,9 @@ export class VoltageLevelEditor extends LitElement { return []; }; + @query('mwc-menu') addMenu!: Menu; + @query('mwc-icon-button[icon="playlist_add"]') addButton!: IconButton; + openEditWizard(): void { const wizard = wizards['VoltageLevel'].edit(this.element); if (wizard) this.dispatchEvent(newWizardEvent(wizard)); @@ -76,6 +92,16 @@ export class VoltageLevelEditor extends LitElement { ); } + private openCreateWizard(tagName: string): void { + const wizard = wizards[tagName].create(this.element!); + + if (wizard) this.dispatchEvent(newWizardEvent(wizard)); + } + + firstUpdated(): void { + this.addMenu.anchor = this.addButton; + } + renderIedContainer(): TemplateResult { const ieds = this.getAttachedIeds?.(this.element) ?? []; return ieds?.length @@ -85,41 +111,66 @@ export class VoltageLevelEditor extends LitElement { : html``; } + private renderAddButtons(): TemplateResult[] { + return childTags(this.element).map( + child => + html`${child}` + ); + } + render(): TemplateResult { - return html` - + return html` + this.openLNodeWizard()} > - + cloneSubstationElement(this)} > - + this.openEditWizard()} > - + startMove(this, VoltageLevelEditor, SubstationEditor)} > - + this.remove()} > + + (this.addMenu.open = true)} + > { + const tagName = ((e.target).selected).value; + this.openCreateWizard(tagName); + }} + >${this.renderAddButtons()} + ${this.renderIedContainer()}
${Array.from(this.element?.querySelectorAll(selectors.Bay) ?? []).map( @@ -130,7 +181,7 @@ export class VoltageLevelEditor extends LitElement { >` )}
- `; + `; } static styles = css` @@ -139,7 +190,6 @@ export class VoltageLevelEditor extends LitElement { #bayContainer { display: grid; grid-gap: 12px; - padding: 8px 12px 16px; box-sizing: border-box; grid-template-columns: repeat(auto-fit, minmax(316px, auto)); } diff --git a/test/integration/zeroline/bay-editor-wizarding-editing.test.ts b/test/integration/zeroline/bay-editor-wizarding-editing.test.ts index aabc943a76..15dd06e436 100644 --- a/test/integration/zeroline/bay-editor-wizarding-editing.test.ts +++ b/test/integration/zeroline/bay-editor-wizarding-editing.test.ts @@ -90,6 +90,7 @@ describe('bay-editor wizarding editing integration', () => { expect(doc.querySelector('Bay')?.getAttribute('desc')).to.be.null; }); }); + describe('open add conducting equipment wizard', () => { let doc: XMLDocument; let parent: WizardingElement & EditingElement; @@ -114,11 +115,9 @@ describe('bay-editor wizarding editing integration', () => { element = parent.querySelector('bay-editor'); (( - element?.shadowRoot - ?.querySelector('editor-container') - ?.shadowRoot?.querySelector( - 'mwc-list-item[value="ConductingEquipment"]' - ) + element?.shadowRoot?.querySelector( + 'mwc-list-item[value="ConductingEquipment"]' + ) )).click(); await parent.updateComplete; diff --git a/test/integration/zeroline/substation-editor-wizarding-editing.test.ts b/test/integration/zeroline/substation-editor-wizarding-editing.test.ts index 74e570a15c..23f97ab81a 100644 --- a/test/integration/zeroline/substation-editor-wizarding-editing.test.ts +++ b/test/integration/zeroline/substation-editor-wizarding-editing.test.ts @@ -108,9 +108,9 @@ describe('substation-editor wizarding editing integration', () => { element = parent.querySelector('substation-editor'); (( - element?.shadowRoot - ?.querySelector('editor-container') - ?.shadowRoot?.querySelector('mwc-list-item[value="VoltageLevel"]') + element?.shadowRoot?.querySelector( + 'mwc-list-item[value="VoltageLevel"]' + ) )).click(); await parent.updateComplete; diff --git a/test/integration/zeroline/voltage-level-editor-wizarding-editing.test.ts b/test/integration/zeroline/voltage-level-editor-wizarding-editing.test.ts index c458be24d1..bb09ceff18 100644 --- a/test/integration/zeroline/voltage-level-editor-wizarding-editing.test.ts +++ b/test/integration/zeroline/voltage-level-editor-wizarding-editing.test.ts @@ -195,9 +195,7 @@ describe('voltage-level-editor wizarding editing integration', () => { element = parent.querySelector('voltage-level-editor'); (( - element?.shadowRoot - ?.querySelector('editor-container') - ?.shadowRoot?.querySelector('mwc-list-item[value="Bay"]') + element?.shadowRoot?.querySelector('mwc-list-item[value="Bay"]') )).click(); await parent.updateComplete; diff --git a/test/unit/editor-container.test.ts b/test/unit/action-pane.test.ts similarity index 50% rename from test/unit/editor-container.test.ts rename to test/unit/action-pane.test.ts index 5d878c37bb..4145c1ac1d 100644 --- a/test/unit/editor-container.test.ts +++ b/test/unit/action-pane.test.ts @@ -1,35 +1,21 @@ import { expect, fixture, html } from '@open-wc/testing'; -import sinon, { SinonSpy } from 'sinon'; - -import '../../src/editor-container.js'; -import { EditorContainer } from '../../src/editor-container.js'; -import { BayEditor } from '../../src/zeroline/bay-editor.js'; - -describe('editor-container', () => { - let element: EditorContainer; - const substation = ( - new DOMParser().parseFromString( - ``, - 'application/xml' - ).documentElement - ); + +import '../../src/action-pane.js'; +import '../../src/zeroline/bay-editor.js'; +import { ActionPane } from '../../src/action-pane.js'; + +describe('action-pane', () => { + let element: ActionPane; + beforeEach(async () => { element = await fixture( - html`` + html`` ); await element.updateComplete; }); - it('does not render more vert option with missing mwc-fab children', () => { - expect(element.moreVert).to.not.exist; - }); - - it('renders more vert option with existing mwc-fab children', async () => { - const fabChild = element.ownerDocument.createElement('mwc-fab'); - fabChild.setAttribute('slot', 'morevert'); - element.appendChild(fabChild); - await element.requestUpdate(); - expect(element.moreVert).to.exist; + it('looks like the latest snapshot', () => { + expect(element).shadowDom.to.equalSnapshot(); }); it('renders the header as

per default', () => { @@ -107,75 +93,63 @@ describe('editor-container', () => { expect(element.shadowRoot?.querySelector('h5')).to.not.exist; }); - it('does not render header text with missing element and header text', () => { - expect(element.defaultHeader).to.equal(''); + it('renders the header as

for levels > 6', async () => { + element.level = 7; + await element.updateComplete; + expect(element.shadowRoot?.querySelector('h6')).to.exist; + expect(element.shadowRoot?.querySelector('h1')).to.not.exist; + expect(element.shadowRoot?.querySelector('h2')).to.not.exist; + expect(element.shadowRoot?.querySelector('h3')).to.not.exist; + expect(element.shadowRoot?.querySelector('h4')).to.not.exist; + expect(element.shadowRoot?.querySelector('h5')).to.not.exist; }); - it('header property overwrites default header text', async () => { - element.element = substation; - element.requestUpdate(); - expect( - element.headerContainer.querySelector('h1')?.innerText.trim() - ).to.equal('test header'); + it('renders the header as

for levels < 1', async () => { + element.level = -1; + await element.updateComplete; + expect(element.shadowRoot?.querySelector('h1')).to.exist; + expect(element.shadowRoot?.querySelector('h2')).to.not.exist; + expect(element.shadowRoot?.querySelector('h3')).to.not.exist; + expect(element.shadowRoot?.querySelector('h4')).to.not.exist; + expect(element.shadowRoot?.querySelector('h5')).to.not.exist; + expect(element.shadowRoot?.querySelector('h6')).to.not.exist; }); - it('renders default header text with missing header property', async () => { - element.header = ''; - element.element = substation; - await element.requestUpdate(); + it('does not set contrasted class property with odd level', async () => { + element.level = 3; + await element.updateComplete; + expect( - element.headerContainer.querySelector('h1')?.innerText.trim() - ).to.equal('name - desc'); + element.shadowRoot + ?.querySelector('section') + ?.classList.contains('contrasted') + ).to.be.false; }); - it('does not render add icon and add menu with missing element', () => { - expect(element.addMenu).to.not.exist; - expect(element.addIcon).to.not.exist; - }); + it('sets contrasted class property with even levels', async () => { + element.level = 4; + await element.updateComplete; - describe('with existing element definition', () => { - const substation = ( - new DOMParser().parseFromString( - ``, - 'application/xml' - ).documentElement - ); + expect( + element.shadowRoot + ?.querySelector('section') + ?.classList.contains('contrasted') + ).to.be.true; + }); - let wizardEvent: SinonSpy; + describe('with icon property set', () => { beforeEach(async () => { - element.element = substation; + element.icon = 'edit'; await element.updateComplete; - - wizardEvent = sinon.spy(); - window.addEventListener('wizard', wizardEvent); - }); - - it('render add icon and add menu', async () => { - expect(element.addMenu).to.exist; - expect(element.addIcon).to.exist; - }); - - it('opens menu on add icon click', async () => { - expect(element.addMenu.open).to.be.false; - element.addIcon?.click(); - await element.requestUpdate(); - expect(element.addMenu.open).to.be.true; - }); - - it('renders only children with existing create wizard', () => { - expect(element.addMenu.querySelectorAll('mwc-list-item').length).to.equal( - 2 - ); }); - it('does trigger wizard action with valid existing wizard', async () => { - element.addMenu.querySelector('mwc-list-item')?.click(); - expect(wizardEvent).to.have.been.called; + it('looks like the latest snapshot', () => { + expect(element).shadowDom.to.equalSnapshot(); }); }); - describe('with existing parent editor-container', () => { - let parent: EditorContainer; + describe('with existing parent action-pane', () => { + let parent: ActionPane; const bay = ( new DOMParser().parseFromString( ``, @@ -184,26 +158,17 @@ describe('editor-container', () => { ); beforeEach(async () => { parent = await fixture( - `` + html`` ); element = parent .querySelector('bay-editor')! - .shadowRoot!.querySelector('editor-container')!; + .shadowRoot!.querySelector('action-pane')!; await element.updateComplete; }); - it('negated the default contrasted property of the parent', () => { - expect(element.contrasted).to.be.true; - }); - - it('only negates on first update', async () => { - parent.contrasted = true; - await parent.requestUpdate(); - - expect(element.contrasted).to.be.true; - }); - it('increments the default level property of the parent', () => { expect(element.level).to.equal(2); }); @@ -214,31 +179,5 @@ describe('editor-container', () => { expect(element.level).to.equal(2); }); - - it('negated the set contrasted property of the parent', async () => { - parent = await fixture( - `` - ); - - element = parent - .querySelector('bay-editor')! - .shadowRoot!.querySelector('editor-container')!; - await element.updateComplete; - - expect(element.contrasted).to.be.false; - }); - - it('makes sure maximum level is 6', async () => { - parent = await fixture( - `` - ); - - element = parent - .querySelector('bay-editor')! - .shadowRoot!.querySelector('editor-container')!; - await element.updateComplete; - - expect(element.level).to.equal(6); - }); }); });