Skip to content

Commit eb22280

Browse files
author
Dennis Labordus
authored
fix(editor/104): Small improvements and fix. (openscd#874)
* Small improvements and one fix. * Split function to make it more readable. * Small improvements and one fix.
1 parent d100042 commit eb22280

File tree

2 files changed

+81
-60
lines changed

2 files changed

+81
-60
lines changed

src/editors/protocol104/foundation/foundation.ts

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ export function getCdcValueFromDOIElement(doiElement: Element): string | null {
6666
const doName = doiElement.getAttribute('name');
6767

6868
const doElement = doiElement.ownerDocument.querySelector(
69-
`LNodeType[id="${lnType}"] > DO[name="${doName}"]`
69+
`:root > DataTypeTemplates > LNodeType[id="${lnType}"] > DO[name="${doName}"]`
7070
);
7171
if (doElement) {
7272
return getCdcValueFromDOElement(doElement);
@@ -78,7 +78,7 @@ export function getCdcValueFromDOIElement(doiElement: Element): string | null {
7878
export function getCdcValueFromDOElement(doElement: Element): string | null {
7979
const doType = getTypeAttribute(doElement);
8080
const doTypeElement = doElement.ownerDocument.querySelector(
81-
`DOType[id="${doType}"]`
81+
`:root > DataTypeTemplates > DOType[id="${doType}"]`
8282
);
8383
return doTypeElement ? doTypeElement.getAttribute('cdc') : null;
8484
}
@@ -145,7 +145,7 @@ export function getDaElement(doElement: Element, name: string): Element | null {
145145
const doType = getTypeAttribute(doElement);
146146
if (doType) {
147147
return doElement.ownerDocument.querySelector(
148-
`DOType[id="${doType}"] > DA[name="${name}"]`
148+
`:root > DataTypeTemplates > DOType[id="${doType}"] > DA[name="${name}"]`
149149
);
150150
}
151151
return null;
@@ -199,7 +199,7 @@ export function getDoiElement(
199199
lnElement: Element,
200200
doName: string
201201
): Element | null {
202-
return lnElement.querySelector(`DOI[name="${doName}"]`);
202+
return lnElement.querySelector(`:scope > DOI[name="${doName}"]`);
203203
}
204204

205205
export function getDoElement(
@@ -209,7 +209,7 @@ export function getDoElement(
209209
const lnType = lnElement.getAttribute('lnType');
210210
if (lnType) {
211211
return lnElement.ownerDocument.querySelector(
212-
`LNodeType[id="${lnType}"] > DO[name="${doName}"]`
212+
`:root > DataTypeTemplates > LNodeType[id="${lnType}"] > DO[name="${doName}"]`
213213
);
214214
}
215215
return null;
@@ -219,7 +219,9 @@ export function getDoElements(lnElement: Element): Element[] {
219219
const lnType = lnElement.getAttribute('lnType');
220220
if (lnType) {
221221
return Array.from(
222-
lnElement.ownerDocument.querySelectorAll(`LNodeType[id="${lnType}"] > DO`)
222+
lnElement.ownerDocument.querySelectorAll(
223+
`:root > DataTypeTemplates > LNodeType[id="${lnType}"] > DO`
224+
)
223225
);
224226
}
225227
return [];
@@ -286,7 +288,9 @@ function buildTemplateChainFromInstanceElements(
286288
// The LN Element will only be used as starting point to find the LNodeType.
287289
const lnElement = element.closest('LN, LN0')!;
288290
const typeId = lnElement.getAttribute('lnType') ?? '';
289-
typeElement = doc.querySelector(`LNodeType[id="${typeId}"]`);
291+
typeElement = doc.querySelector(
292+
`:root > DataTypeTemplates > LNodeType[id="${typeId}"]`
293+
);
290294

291295
if (typeElement) {
292296
// Next search for the DO Element below the LNodeType Element.
@@ -299,7 +303,9 @@ function buildTemplateChainFromInstanceElements(
299303

300304
// For the next element search the DOType that is linked to the DO Element.
301305
const typeId = getTypeAttribute(doElement) ?? '';
302-
typeElement = doc.querySelector(`DOType[id="${typeId}"]`);
306+
typeElement = doc.querySelector(
307+
`:root > DataTypeTemplates > DOType[id="${typeId}"]`
308+
);
303309
} else {
304310
typeElement = null;
305311
}
@@ -317,7 +323,9 @@ function buildTemplateChainFromInstanceElements(
317323
if (daElement.getAttribute('bType') === 'Struct') {
318324
// Only if the bType is a struct we need to search for the DAType for the next element.
319325
const typeId = getTypeAttribute(element) ?? '';
320-
typeElement = doc.querySelector(`DAType[id="${typeId}"]`);
326+
typeElement = doc.querySelector(
327+
`:root > DataTypeTemplates > DAType[id="${typeId}"]`
328+
);
321329
} else {
322330
typeElement = null;
323331
}
@@ -385,7 +393,7 @@ export function getEnumVal(daiElement: Element, ord: string): string | null {
385393
if (isEnumType(daElement)) {
386394
const enumType = getTypeAttribute(daElement!);
387395
const enumVal = daiElement.ownerDocument.querySelector(
388-
`EnumType[id="${enumType}"] > EnumVal[ord="${ord}"]`
396+
`:root > DataTypeTemplates > EnumType[id="${enumType}"] > EnumVal[ord="${ord}"]`
389397
);
390398
if (enumVal) {
391399
return enumVal.textContent;
@@ -405,7 +413,7 @@ export function getEnumOrds(daiElement: Element): string[] {
405413
if (isEnumType(daElement)) {
406414
const enumType = getTypeAttribute(daElement!);
407415
const enumVals = daiElement.ownerDocument.querySelectorAll(
408-
`EnumType[id="${enumType}"] > EnumVal`
416+
`:root > DataTypeTemplates > EnumType[id="${enumType}"] > EnumVal`
409417
);
410418
Array.from(enumVals)
411419
.filter(valElement => valElement.getAttribute('ord'))

src/editors/protocol104/wizards/selectDo.ts

Lines changed: 62 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -21,56 +21,63 @@ import {
2121
import { createAddressesWizard } from './createAddresses.js';
2222
import { SupportedCdcType, supportedCdcTypes } from '../foundation/cdc.js';
2323
import { PROTOCOL_104_PRIVATE } from '../foundation/private.js';
24-
import { getDoElements, getTypeAttribute } from '../foundation/foundation.js';
24+
import {
25+
getCdcValueFromDOElement,
26+
getDoElements,
27+
} from '../foundation/foundation.js';
2528

2629
/**
27-
* Check if there are DO Elements that aren't initiated and are supported by the 104 protocol available.
30+
* Check if the passed DO Element is supported by the 104 protocol and isn't initiated.
2831
*
29-
* @param parent - The parent element of the child, mainly needed to link the LN Element to the DO Elements.
30-
* @param child - The child to check if it should still be displayed in the finder list.
32+
* @param lnElement - The LN Element used to search for Address Element below DOI, if available.
33+
* @param doElement - The DO Element to check.
3134
*/
32-
function filterAvailableDOElements(parent: Element, child: Element): boolean {
33-
if (child.tagName === 'DO') {
34-
// First check if this DO Element is supported by the 104 Protocol.
35-
const doType = getTypeAttribute(child) ?? '';
36-
const doTypeElement = child.ownerDocument.querySelector(
37-
`DOType[id="${doType}"]`
38-
);
39-
const cdc = doTypeElement?.getAttribute('cdc') ?? '';
40-
if (!supportedCdcTypes.includes(<SupportedCdcType>cdc)) {
41-
return false;
42-
}
35+
function filterAvailableDOElements(
36+
lnElement: Element,
37+
doElement: Element
38+
): boolean {
39+
// First check if this DO Element is supported by the 104 Protocol.
40+
const cdc = getCdcValueFromDOElement(doElement) ?? '';
41+
if (!supportedCdcTypes.includes(<SupportedCdcType>cdc)) {
42+
return false;
43+
}
4344

44-
// Use the parent (LN) to find the DOI that's linked to the DO Element
45-
const doName = getNameAttribute(child);
46-
return (
47-
Array.from(
48-
parent.querySelectorAll(
49-
`:scope > DOI[name="${doName}"] DAI > Private[type="${PROTOCOL_104_PRIVATE}"] > Address`
50-
)
51-
).length <= 0
52-
);
53-
} else {
54-
// For other elements create a list of LN Elements for processing the DO Element from the LN Elements.
55-
let lnElements: Element[];
56-
if (['LN0', 'LN'].includes(child.tagName)) {
57-
lnElements = [child];
58-
} else {
59-
// For the other Elements we will just retrieve all the DOI Elements.
60-
lnElements = Array.from(child.querySelectorAll('LN0, LN'));
61-
}
45+
// Use the parent (LN) to find the DOI that's linked to the DO Element
46+
// And check if there is DOI if it doesn't already contain Address Elements for the 104 Protocol.
47+
const doName = getNameAttribute(doElement);
48+
return (
49+
lnElement.querySelectorAll(
50+
`:scope > DOI[name="${doName}"] DAI > Private[type="${PROTOCOL_104_PRIVATE}"] > Address`
51+
).length <= 0
52+
);
53+
}
6254

63-
// If after filtering there are still LN/DO Element(s) to be displayed, this element will be included.
64-
return (
65-
lnElements.filter(
66-
lnElement =>
67-
// Check if there are available DO Elements that aren't initiated and supported by 104 protocol
68-
getDoElements(lnElement).filter(doElement =>
69-
filterAvailableDOElements(lnElement, doElement)
70-
).length > 0
71-
).length > 0
72-
);
55+
/**
56+
* Check if there are DO Elements that aren't initiated and are supported by the 104 protocol. If this is the
57+
* case the Element can be shown in the Finder.
58+
*
59+
* @param child - The child to check if it should still be displayed in the finder list.
60+
*/
61+
function filterAvailableElements(child: Element): boolean {
62+
// For other elements create a list of LN Elements for processing the DO Element from the LN Elements.
63+
let lnElements: Element[];
64+
if (['LN0', 'LN'].includes(child.tagName)) {
65+
lnElements = [child];
66+
} else {
67+
// For the other Elements we will just retrieve all the DOI Elements.
68+
lnElements = Array.from(child.querySelectorAll('LN0, LN'));
7369
}
70+
71+
// If after filtering there are still LN/DO Element(s) to be displayed, this element will be included.
72+
return (
73+
lnElements.filter(
74+
lnElement =>
75+
// Check if there are available DO Elements that aren't initiated and supported by 104 protocol
76+
getDoElements(lnElement).filter(doElement =>
77+
filterAvailableDOElements(lnElement, doElement)
78+
).length > 0
79+
).length > 0
80+
);
7481
}
7582

7683
/**
@@ -85,23 +92,29 @@ export function getDataChildren(parent: Element): Element[] {
8592
// For LN Element we will not search for the children, but the DO Element linked to LN from the Template Section.
8693
const lnType = parent.getAttribute('lnType') ?? '';
8794
children = Array.from(
88-
parent.ownerDocument.querySelectorAll(`LNodeType[id="${lnType}"] > DO`)
89-
).sort((a, b) => compareNames(`${identity(a)}`, `${identity(b)}`));
95+
parent.ownerDocument.querySelectorAll(
96+
`:root > DataTypeTemplates > LNodeType[id="${lnType}"] > DO`
97+
)
98+
)
99+
.filter(child => filterAvailableDOElements(parent, child))
100+
.sort((a, b) => compareNames(`${identity(a)}`, `${identity(b)}`));
90101
} else if (parent.tagName === 'AccessPoint') {
91102
// From the Access Point we will skip directly to the LDevice Element and skip the Server element.
92-
children = Array.from(parent.querySelectorAll('LDevice')).sort((a, b) =>
93-
compareNames(`${identity(a)}`, `${identity(b)}`)
94-
);
103+
// Or retrieve the LN Elements directly below the AccessPoint.
104+
children = Array.from(parent.querySelectorAll('LDevice, :scope > LN'))
105+
.filter(child => filterAvailableElements(child))
106+
.sort((a, b) => compareNames(`${identity(a)}`, `${identity(b)}`));
95107
} else {
96108
// The other element, just retrieve the children and if the tagName is one we need return that child.
97109
children = Array.from(parent.children)
98110
.filter(child =>
99111
['IED', 'AccessPoint', 'LN0', 'LN'].includes(child.tagName)
100112
)
113+
.filter(child => filterAvailableElements(child))
101114
.sort((a, b) => compareNames(`${identity(a)}`, `${identity(b)}`));
102115
}
103116

104-
return children.filter(child => filterAvailableDOElements(parent, child));
117+
return children;
105118
}
106119

107120
/**

0 commit comments

Comments
 (0)