Skip to content

Commit a238cc9

Browse files
authored
feat(openscd):Add multiple Val element into DAI distinguished by sGroup (openscd#1221)
* feat:add multiple Val elements in createDAIWizard * test: fixing dai-field-type snapshot * test:update DAI unit tests with settingGroups file * test: integration test for multiple Val wizard * fix: remove unnecessary type * fix: update typing in checkForMultipleSettings fn * refactor: helper fn emptyIfNull reduces complexity
1 parent f113180 commit a238cc9

File tree

6 files changed

+583
-89
lines changed

6 files changed

+583
-89
lines changed

src/wizards/dai.ts

Lines changed: 79 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,41 @@ export function createValue(
4141
parent: Element,
4242
element: Element,
4343
newElement: Element,
44-
instanceElement: Element
44+
instanceElement: Element,
45+
numberOfmultipleSettings?: number
4546
): WizardActor {
4647
return (inputs: WizardInputElement[]): EditorAction[] => {
4748
const bType = element.getAttribute('bType')!;
48-
const newValue = getCustomField()[<DaiFieldTypes>bType].value(inputs);
49-
50-
let valElement = instanceElement.querySelector('Val');
51-
if (!valElement) {
52-
valElement = parent.ownerDocument.createElementNS(SCL_NAMESPACE, 'Val');
53-
instanceElement.append(valElement);
49+
if (numberOfmultipleSettings) {
50+
//Should we remove all Val elements before adding new ones?
51+
Array.from(instanceElement.querySelectorAll('Val')).forEach(item =>
52+
item.remove()
53+
);
54+
// Adds a new Val element for each sGroup value from the wizard
55+
[...Array(numberOfmultipleSettings)].forEach((item, i) => {
56+
const newValue = getCustomField()[<DaiFieldTypes>bType].value(
57+
inputs,
58+
i + 1
59+
);
60+
61+
const valElement = parent.ownerDocument.createElementNS(
62+
SCL_NAMESPACE,
63+
'Val'
64+
);
65+
valElement.textContent = newValue;
66+
valElement.setAttribute('sGroup', `${i + 1}`);
67+
instanceElement.append(valElement);
68+
});
69+
} else {
70+
const newValue = getCustomField()[<DaiFieldTypes>bType].value(inputs);
71+
72+
let valElement = instanceElement.querySelector('Val');
73+
if (!valElement) {
74+
valElement = parent.ownerDocument.createElementNS(SCL_NAMESPACE, 'Val');
75+
instanceElement.append(valElement);
76+
}
77+
valElement.textContent = newValue;
5478
}
55-
valElement.textContent = newValue;
5679

5780
const name = instanceElement.getAttribute('name');
5881
const complexAction: ComplexAction = {
@@ -65,15 +88,17 @@ export function createValue(
6588

6689
export function renderDAIWizard(
6790
element: Element,
68-
instanceElement?: Element
91+
instanceElement?: Element,
92+
numberOfmultipleSettings: number | null = null
6993
): TemplateResult[] {
7094
const bType = element.getAttribute('bType')!;
7195
const daValue = element.querySelector('Val')?.textContent?.trim() ?? '';
7296

7397
return [
7498
html` ${getCustomField()[<DaiFieldTypes>bType].render(
7599
element,
76-
instanceElement
100+
instanceElement,
101+
numberOfmultipleSettings
77102
)}
78103
${daValue
79104
? html`<wizard-textfield
@@ -88,12 +113,44 @@ export function renderDAIWizard(
88113
];
89114
}
90115

116+
/**
117+
* Checks if the DAI corresponds to a multiple setting group
118+
*
119+
* @param parent The parent element of the DAI
120+
* @param element The BDA/DA element
121+
* @returns The number of setting groups if the DAI is a multiple setting group, null otherwise
122+
*/
123+
function checkForMultipleSettings(
124+
parent: Element,
125+
element: Element
126+
): number | undefined {
127+
// Look for the DA element to validate that the DAI has the functional constraint SG or SE
128+
let da = element;
129+
if (element.tagName === 'BDA')
130+
da = (<Element>element.getRootNode()).querySelector(
131+
`DOType>DA[type="${element.parentElement!.id}"]`
132+
)!;
133+
const fc = da.getAttribute('fc') ?? '';
134+
// Check if the closest IED to the parent element has a SettingControl element with a numOfSGs attribute
135+
const ied = parent.closest('IED');
136+
const settingControl = ied?.querySelector('SettingControl');
137+
const numOfSGsAttribute = settingControl?.getAttribute('numOfSGs') ?? '';
138+
const numberOfmultipleSettings = parseInt(numOfSGsAttribute);
139+
// If the DA has the functional constraint SG or SE and the IED has a SettingControl element with a numOfSGs attribute, then the DAI is a multiple setting group
140+
return (fc === 'SG' || fc === 'SE') &&
141+
numOfSGsAttribute !== '' &&
142+
!isNaN(numberOfmultipleSettings)
143+
? numberOfmultipleSettings
144+
: undefined;
145+
}
146+
91147
export function createDAIWizard(
92148
parent: Element,
93149
newElement: Element,
94150
element: Element
95151
): Wizard {
96152
// Retrieve the created DAI, can be the new element or one of the child elements below.
153+
const numberOfmultipleSettings = checkForMultipleSettings(parent, element);
97154
const instanceElement =
98155
newElement.tagName === 'DAI'
99156
? newElement
@@ -108,9 +165,19 @@ export function createDAIWizard(
108165
primary: {
109166
icon: 'edit',
110167
label: get('save'),
111-
action: createValue(parent, element, newElement, instanceElement),
168+
action: createValue(
169+
parent,
170+
element,
171+
newElement,
172+
instanceElement,
173+
numberOfmultipleSettings
174+
),
112175
},
113-
content: renderDAIWizard(element, instanceElement),
176+
content: renderDAIWizard(
177+
element,
178+
instanceElement,
179+
numberOfmultipleSettings
180+
),
114181
},
115182
];
116183
}

0 commit comments

Comments
 (0)