Skip to content

Commit

Permalink
Revert "Move functionality to scl-lib and remove unused code and simp…
Browse files Browse the repository at this point in the history
…lify structure"

This reverts commit fbabe0a.
  • Loading branch information
danyill committed Dec 27, 2023
1 parent fbabe0a commit 7b512f3
Show file tree
Hide file tree
Showing 6 changed files with 927 additions and 349 deletions.
93 changes: 93 additions & 0 deletions foundation.ts
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;
}
}
`;
113 changes: 113 additions & 0 deletions foundation/foundation.ts
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));
}
2 changes: 1 addition & 1 deletion foundation/icons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const smvIcon = svg`<svg style="width:24px;height:24px" viewBox="0 0 24 2

export type iconType = 'smvIcon' | 'gooseIcon';

function getIconButton(type: iconType, state: boolean): TemplateResult {
export function getIconButton(type: iconType, state: boolean): TemplateResult {
return svg`<svg
slot="${state ? 'onIcon' : 'offIcon'}"
xmlns="http://www.w3.orgs/2000/svg"
Expand Down
Loading

0 comments on commit 7b512f3

Please sign in to comment.