import { LitElement , TemplateResult , customElement , html , property , css , query , } from 'lit-element' ; import { translate } from 'lit-translate' ; import '@material/mwc-icon-button' ; import { Menu } from '@material/mwc-menu' ; import { IconButton } from '@material/mwc-icon-button' ; import { ListItem } from '@material/mwc-list/mwc-list-item' ; import '../action-pane.js' ; import './bay-editor.js' ; import './ied-editor.js' ; import { selectors , startMove , cloneSubstationElement , styles , } from './foundation.js' ; import { newActionEvent , newWizardEvent , SCLTag , tags } from '../foundation.js' ; import { SubstationEditor } from './substation-editor.js' ; import { emptyWizard , wizards } from '../wizards/wizard-library.js' ; function childTags ( element ) { if ( ! element ) return [ ] ; return tags [ < SCLTag > 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 ( { attribute : false } ) element ! : Element ; @ property ( { type : Boolean } ) readonly = false ; @ property ( ) get voltage ( ) : string | null { const V = this . element . querySelector ( selectors . VoltageLevel + ' > Voltage' ) ; if ( V === null ) return null ; const v = V . textContent ?? '' ; const m = V . getAttribute ( 'multiplier' ) ; const u = m === null ? 'V' : ' ' + m + 'V' ; return v ? v + u : null ; } @ property ( { type : String } ) get header ( ) : string { const name = this . element . getAttribute ( 'name' ) ?? '' ; const desc = this . element . getAttribute ( 'desc' ) ; return `${ name } ${ desc ? `- ${ desc }` : '' }
    ${ this . voltage === null ? '' : `(${ this . voltage })` }` ; } @ property ( { attribute : false } ) getAttachedIeds ? : ( element : Element ) => Element [ ] = ( ) => { return [ ] ; } ; @ query ( 'mwc-menu' ) addMenu ! : Menu ; @ query ( 'mwc-icon-button[icon="playlist_add"]' ) addButton ! : IconButton ; openEditWizard ( ) { const wizard = wizards [ 'VoltageLevel' ] . edit ( this . element ) ; if ( wizard ) this . dispatchEvent ( newWizardEvent ( wizard ) ) ; } /** Opens a [[`WizardDialog`]] for editing `LNode` connections. */ openLNodeWizard ( ) { const wizard = wizards [ 'LNode' ] . edit ( this . element ) ; if ( wizard ) this . dispatchEvent ( newWizardEvent ( wizard ) ) ; } remove ( ) { if ( this . element ) this . dispatchEvent ( newActionEvent ( { old : { parent : this . element . parentElement ! , element : this . element , reference : this . element . nextSibling , } , } ) ) ; } private openCreateWizard ( tagName ) { const wizard = wizards [ < SCLTag > tagName ] . create ( this . element ! ) ; if ( wizard ) this . dispatchEvent ( newWizardEvent ( wizard ) ) ; } firstUpdated ( ) { this . addMenu . anchor = < HTMLElement > this . addButton ; } renderIedContainer ( ) { const ieds = this . getAttachedIeds ?. ( this . element ) ?? [ ] ; return ieds ?. length ? html `<div id="iedcontainer">
          ${ ieds . map ( ied => html `<ied-editor .element=${ ied }></ied-editor>` ) }
        </div>` : html `` ; } private renderAddButtons ( ) { return childTags ( this . element ) . map ( child => html `<mwc-list-item value="${ child }"
          ><span>${ child }</span></mwc-list-item
        >` ) ; } render ( ) { return html `<action-pane label="${ this . header }">
      <abbr slot="action" title="${ translate ( 'lnode.tooltip' ) }">
        <mwc-icon-button
          icon="account_tree"
          @click=${ ( ) => this . openLNodeWizard ( ) }
        ></mwc-icon-button>
      </abbr>
      <abbr slot="action" title="${ translate ( 'duplicate' ) }">
        <mwc-icon-button
          icon="content_copy"
          @click=${ ( ) => cloneSubstationElement ( this ) }
        ></mwc-icon-button>
      </abbr>
      <abbr slot="action" title="${ translate ( 'edit' ) }">
        <mwc-icon-button
          icon="edit"
          @click=${ ( ) => this . openEditWizard ( ) }
        ></mwc-icon-button>
      </abbr>
      <abbr slot="action" title="${ translate ( 'move' ) }">
        <mwc-icon-button
          icon="forward"
          @click=${ ( ) => startMove ( this , VoltageLevelEditor , SubstationEditor ) }
        ></mwc-icon-button>
      </abbr>
      <abbr slot="action" title="${ translate ( 'remove' ) }">
        <mwc-icon-button
          icon="delete"
          @click=${ ( ) => this . remove ( ) }
        ></mwc-icon-button>
      </abbr>
      <abbr
        slot="action"
        style="position:relative;"
        title="${ translate ( 'add' ) }"
      >
        <mwc-icon-button
          icon="playlist_add"
          @click=${ ( ) => ( this . addMenu . open = true ) }
        ></mwc-icon-button
        ><mwc-menu
          corner="BOTTOM_RIGHT"
          menuCorner="END"
          @selected=${ ( e ) => { const tagName = ( < ListItem > ( < Menu > e . target ) . selected ) . value ; this . openCreateWizard ( tagName ) ; } }
          >${ this . renderAddButtons ( ) }</mwc-menu
        >
      </abbr>
      ${ this . renderIedContainer ( ) }
      <div id="bayContainer">
        ${ Array . from ( this . element ?. querySelectorAll ( selectors . Bay ) ?? [ ] ) . map ( bay => html `<bay-editor
            .element=${ bay }
            .getAttachedIeds=${ this . getAttachedIeds }
            ?readonly=${ this . readonly }
          ></bay-editor>` ) }
      </div>
    </action-pane>` ; } static styles = css `
    ${ styles }

    #bayContainer {
      display: grid;
      grid-gap: 12px;
      box-sizing: border-box;
      grid-template-columns: repeat(auto-fit, minmax(316px, auto));
    }

    @media (max-width: 387px) {
      #bayContainer {
        grid-template-columns: repeat(auto-fit, minmax(196px, auto));
      }
    }
  ` ; }