-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(wizards/reportcontrol): added new IED wizard to update name/desc…
…ription (#494) * Added first version of IED Wizard. * Added function to update reference to IED Name. * Updated values referring to the IED Name. * Updated values referring to the IED Name. * Processed review comments. * Fixed and improved tests.
- Loading branch information
Dennis Labordus
authored
Jan 19, 2022
1 parent
4eabdb3
commit 110c83d
Showing
14 changed files
with
1,122 additions
and
4 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
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
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
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 {isPublic, SimpleAction} from "../../foundation.js"; | ||
|
||
const referenceInfoTags = ['IED'] as const; | ||
type ReferencesInfoTag = typeof referenceInfoTags[number]; | ||
|
||
/* | ||
* For every supported tag a list of information about which elements to search for and which attribute value | ||
* to replace with the new value typed in the screen by the user. This is used to update references to a name | ||
* of an element by other elements. | ||
* If the attribute is null the text content of the found element will be replaced. | ||
*/ | ||
const referenceInfos: Record< | ||
ReferencesInfoTag, | ||
{ | ||
elementQuery: string; | ||
attribute: string | null; | ||
}[] | ||
> = { | ||
IED: | ||
[{ | ||
elementQuery: `Association`, | ||
attribute: 'iedName' | ||
}, { | ||
elementQuery: `ClientLN`, | ||
attribute: 'iedName' | ||
}, { | ||
elementQuery: `ConnectedAP`, | ||
attribute: 'iedName' | ||
}, { | ||
elementQuery: `ExtRef`, | ||
attribute: 'iedName' | ||
}, { | ||
elementQuery: `KDC`, | ||
attribute: 'iedName' | ||
}, { | ||
elementQuery: `LNode`, | ||
attribute: 'iedName' | ||
}, { | ||
elementQuery: `GSEControl > IEDName`, | ||
attribute: null | ||
}, { | ||
elementQuery: `SampledValueControl > IEDName`, | ||
attribute: null | ||
}] | ||
} | ||
|
||
function cloneElement(element: Element, attributeName: string, value: string | null): Element { | ||
const newElement = <Element>element.cloneNode(false); | ||
if (value === null) { | ||
newElement.removeAttribute(attributeName); | ||
} else { | ||
newElement.setAttribute(attributeName, value); | ||
} | ||
return newElement; | ||
} | ||
|
||
function cloneElementAndTextContent(element: Element, value: string | null): Element { | ||
const newElement = <Element>element.cloneNode(false); | ||
newElement.textContent = value; | ||
return newElement; | ||
} | ||
|
||
export function updateReferences(element: Element, oldValue: string | null, newValue: string): SimpleAction[] { | ||
if (oldValue === newValue) { | ||
return []; | ||
} | ||
|
||
const referenceInfo = referenceInfos[<ReferencesInfoTag>element.tagName]; | ||
if (referenceInfo === undefined) { | ||
return []; | ||
} | ||
|
||
const actions: SimpleAction[] = []; | ||
referenceInfo.forEach(info => { | ||
if (info.attribute !== null) { | ||
Array.from(element.ownerDocument.querySelectorAll(`${info.elementQuery}[${info.attribute}="${oldValue}"]`)) | ||
.filter(isPublic) | ||
.forEach(element => { | ||
const newElement = cloneElement(element, info.attribute!, newValue); | ||
actions.push({old: {element}, new: {element: newElement}}); | ||
}) | ||
} else { | ||
Array.from(element.ownerDocument.querySelectorAll(`${info.elementQuery}`)) | ||
.filter(element => element.textContent === oldValue) | ||
.filter(isPublic) | ||
.forEach(element => { | ||
const newElement = cloneElementAndTextContent(element, newValue); | ||
actions.push({old: {element}, new: {element: newElement}}); | ||
}) | ||
} | ||
}) | ||
return actions; | ||
} |
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,99 @@ | ||
import {html, TemplateResult} from 'lit-element'; | ||
import {get, translate} from 'lit-translate'; | ||
|
||
import { | ||
cloneElement, | ||
ComplexAction, | ||
EditorAction, | ||
getValue, | ||
isPublic, | ||
Wizard, | ||
WizardActor, | ||
WizardInput, | ||
} from '../foundation.js'; | ||
import {patterns} from "./foundation/limits.js"; | ||
import {updateReferences} from "./foundation/references.js"; | ||
|
||
const iedNamePattern = "[A-Za-z][0-9A-Za-z_]{0,2}|" + | ||
"[A-Za-z][0-9A-Za-z_]{4,63}|" + | ||
"[A-MO-Za-z][0-9A-Za-z_]{3}|" + | ||
"N[0-9A-Za-np-z_][0-9A-Za-z_]{2}|" + | ||
"No[0-9A-Za-mo-z_][0-9A-Za-z_]|" + | ||
"Non[0-9A-Za-df-z_]"; | ||
|
||
export function updateIED(element: Element): WizardActor { | ||
return (inputs: WizardInput[]): EditorAction[] => { | ||
const name = getValue(inputs.find(i => i.label === 'name')!)!; | ||
const oldName = element.getAttribute('name'); | ||
const desc = getValue(inputs.find(i => i.label === 'desc')!); | ||
|
||
if ( name === oldName && | ||
desc === element.getAttribute('desc')) { | ||
return []; | ||
} | ||
|
||
const complexAction: ComplexAction = { | ||
actions: [], | ||
title: get('ied.action.updateied', {iedName: name}), | ||
}; | ||
|
||
const newElement = cloneElement(element, { name, desc }); | ||
complexAction.actions.push({ old: { element }, new: { element: newElement } }); | ||
complexAction.actions.push(...updateReferences(element, oldName, name)); | ||
return complexAction.actions.length ? [complexAction] : []; | ||
}; | ||
} | ||
|
||
export function renderIEDWizard( | ||
name: string | null, | ||
desc: string | null, | ||
reservedNames: string[] | ||
): TemplateResult[] { | ||
return [ | ||
html`<wizard-textfield | ||
label="name" | ||
.maybeValue=${name} | ||
helper="${translate('ied.wizard.nameHelper')}" | ||
required | ||
validationMessage="${translate('textfield.required')}" | ||
dialogInitialFocus | ||
.reservedValues=${reservedNames} | ||
pattern="${iedNamePattern}" | ||
></wizard-textfield>`, | ||
html`<wizard-textfield | ||
label="desc" | ||
.maybeValue=${desc} | ||
nullable | ||
helper="${translate('ied.wizard.descHelper')}" | ||
pattern="${patterns.normalizedString}" | ||
></wizard-textfield>`, | ||
]; | ||
} | ||
|
||
export function reservedNamesIED(currentElement: Element): string[] { | ||
return Array.from( | ||
currentElement.parentNode!.querySelectorAll('IED') | ||
) | ||
.filter(isPublic) | ||
.map(ied => ied.getAttribute('name') ?? '') | ||
.filter(name => name !== currentElement.getAttribute('name')); | ||
} | ||
|
||
export function editIEDWizard(element: Element): Wizard { | ||
return [ | ||
{ | ||
title: get('ied.wizard.title.edit'), | ||
element, | ||
primary: { | ||
icon: 'edit', | ||
label: get('save'), | ||
action: updateIED(element), | ||
}, | ||
content: renderIEDWizard( | ||
element.getAttribute('name'), | ||
element.getAttribute('desc'), | ||
reservedNamesIED(element) | ||
), | ||
}, | ||
]; | ||
} |
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
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.