-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Revert "Move functionality to scl-lib and remove unused code and simp…
…lify structure" This reverts commit fbabe0a.
- Loading branch information
Showing
6 changed files
with
927 additions
and
349 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import { css } from 'lit'; | ||
import { identity, find } from '@openenergytools/scl-lib'; | ||
|
||
export function updateElementReference( | ||
newDoc: XMLDocument, | ||
oldElement: Element | ||
): Element | null { | ||
if (!oldElement || !oldElement.closest('SCL')) return null; | ||
|
||
const id = identity(oldElement); | ||
const newElement = find(newDoc, oldElement.tagName, id); | ||
|
||
return newElement; | ||
} | ||
|
||
export function isPublic(element: Element): boolean { | ||
return !element.closest('Private'); | ||
} | ||
|
||
export const styles = css` | ||
.content { | ||
display: flex; | ||
height: calc(100vh - 184px); | ||
} | ||
.selectionlist { | ||
flex: 35%; | ||
margin: 4px 4px 4px 8px; | ||
background-color: var(--mdc-theme-surface); | ||
overflow-y: scroll; | ||
} | ||
.elementeditorcontainer { | ||
flex: 65%; | ||
margin: 4px 8px 4px 4px; | ||
background-color: var(--mdc-theme-surface); | ||
overflow-y: scroll; | ||
display: flex; | ||
} | ||
.listitem.header { | ||
font-weight: 500; | ||
} | ||
mwc-list-item.hidden[noninteractive] + li[divider] { | ||
display: none; | ||
} | ||
mwc-button { | ||
display: none; | ||
} | ||
@media (max-width: 950px) { | ||
.elementeditorcontainer { | ||
display: block; | ||
} | ||
} | ||
@media (max-width: 599px) { | ||
.content { | ||
height: 100%; | ||
} | ||
.selectionlist { | ||
position: absolute; | ||
width: calc(100% - 32px); | ||
height: auto; | ||
top: 110px; | ||
left: 8px; | ||
background-color: var(--mdc-theme-surface); | ||
z-index: 1; | ||
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); | ||
} | ||
.elementeditorcontainer { | ||
display: block; | ||
} | ||
data-set-element-editor { | ||
width: calc(100% - 16px); | ||
} | ||
.selectionlist.hidden { | ||
display: none; | ||
} | ||
mwc-button { | ||
display: flex; | ||
margin: 4px 8px 8px; | ||
} | ||
} | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
import { findFCDAs, isSubscribed } from './subscription/subscription.js'; | ||
|
||
/** | ||
* Extract the 'name' attribute from the given XML element. | ||
* @param element - The element to extract name from. | ||
* @returns the name, or undefined if there is no name. | ||
*/ | ||
export function getNameAttribute(element: Element): string | undefined { | ||
const name = element.getAttribute('name'); | ||
return name || undefined; | ||
} | ||
|
||
/** | ||
* Extract the 'desc' attribute from the given XML element. | ||
* @param element - The element to extract description from. | ||
* @returns the name, or undefined if there is no description. | ||
*/ | ||
export function getDescriptionAttribute(element: Element): string | undefined { | ||
const name = element.getAttribute('desc'); | ||
return name || undefined; | ||
} | ||
|
||
/** Sorts selected `ListItem`s to the top and disabled ones to the bottom. */ | ||
export function compareNames(a: Element | string, b: Element | string): number { | ||
if (typeof a === 'string' && typeof b === 'string') return a.localeCompare(b); | ||
|
||
if (typeof a === 'object' && typeof b === 'string') | ||
return (a.getAttribute('name') ?? '').localeCompare(b); | ||
|
||
if (typeof a === 'string' && typeof b === 'object') | ||
return a.localeCompare(b.getAttribute('name')!); | ||
|
||
if (typeof a === 'object' && typeof b === 'object') | ||
return (a.getAttribute('name') ?? '').localeCompare( | ||
b.getAttribute('name') ?? '' | ||
); | ||
|
||
return 0; | ||
} | ||
|
||
const serviceTypeControlBlockTags: Partial<Record<string, string[]>> = { | ||
GOOSE: ['GSEControl'], | ||
SMV: ['SampledValueControl'], | ||
Report: ['ReportControl'], | ||
NONE: ['LogControl', 'GSEControl', 'SampledValueControl', 'ReportControl'], | ||
}; | ||
|
||
// NOTE: This function modified extensively from the core function to more efficiently handle the srcXXX attributes on ExtRefs | ||
export function findControlBlocks( | ||
extRef: Element, | ||
controlType: 'GOOSE' | 'SMV' | ||
): Element[] { | ||
if (!isSubscribed(extRef)) return []; | ||
|
||
const extRefValues = ['iedName', 'srcPrefix', 'srcCBName', 'srcLNInst']; | ||
const [srcIedName, srcPrefix, srcCBName, srcLNInst] = extRefValues.map( | ||
attr => extRef.getAttribute(attr) ?? '' | ||
); | ||
|
||
const srcLDInst = | ||
extRef.getAttribute('srcLDInst') ?? extRef.getAttribute('ldInst'); | ||
const srcLNClass = extRef.getAttribute('srcLNClass') ?? 'LLN0'; | ||
|
||
const controlBlockFromSrc = Array.from( | ||
extRef | ||
.closest('SCL')! | ||
.querySelectorAll( | ||
`IED[name="${srcIedName}"] LDevice[inst="${srcLDInst}"] > LN0[lnClass="${srcLNClass}"]${ | ||
srcPrefix !== '' ? `[prefix="${srcPrefix}"]` : '' | ||
}${srcLNInst !== '' ? `[inst="${srcLNInst}"]` : ''} > ${ | ||
serviceTypeControlBlockTags[controlType] | ||
}[name="${srcCBName}"]` | ||
) | ||
); | ||
|
||
if (controlBlockFromSrc) return controlBlockFromSrc; | ||
|
||
// Ed 1 this is more complicated as control blocks not explicitly identified... | ||
|
||
const fcdas = findFCDAs(extRef); | ||
const cbTags = | ||
serviceTypeControlBlockTags[extRef.getAttribute('serviceType') ?? 'NONE'] ?? | ||
[]; | ||
const controlBlocks = new Set( | ||
fcdas.flatMap(fcda => { | ||
const dataSet = fcda.parentElement!; | ||
const dsName = dataSet.getAttribute('name') ?? ''; | ||
const anyLN = dataSet.parentElement!; | ||
return cbTags | ||
.flatMap(tag => Array.from(anyLN.getElementsByTagName(tag))) | ||
.filter(cb => cb.getAttribute('datSet') === dsName); | ||
}) | ||
); | ||
return Array.from(controlBlocks); | ||
} | ||
|
||
/** maximum value for `lnInst` attribute */ | ||
const maxLnInst = 99; | ||
const lnInstRange = Array(maxLnInst) | ||
.fill(1) | ||
.map((_, i) => `${i + 1}`); | ||
|
||
/** | ||
* @param lnElements - The LN elements to be scanned for `inst` | ||
* values already in use. | ||
* @returns first available inst value for LN or undefined if no inst is available | ||
*/ | ||
export function minAvailableLogicalNodeInstance( | ||
lnElements: Element[] | ||
): string | undefined { | ||
const lnInsts = new Set(lnElements.map(ln => ln.getAttribute('inst') || '')); | ||
return lnInstRange.find(lnInst => !lnInsts.has(lnInst)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.