@compas-oscd/scl-template-update 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +41 -0
- package/dist/assets/nsd-0a370a57.json +137748 -0
- package/dist/components/add-data-object-dialog.d.ts +42 -0
- package/dist/components/add-data-object-dialog.js +288 -0
- package/dist/components/add-data-object-dialog.js.map +1 -0
- package/dist/components/delete-lnodetype-dialog.d.ts +21 -0
- package/dist/components/delete-lnodetype-dialog.js +104 -0
- package/dist/components/delete-lnodetype-dialog.js.map +1 -0
- package/dist/components/lnodetype-sidebar.d.ts +28 -0
- package/dist/components/lnodetype-sidebar.js +196 -0
- package/dist/components/lnodetype-sidebar.js.map +1 -0
- package/dist/components/settings-dialog.d.ts +30 -0
- package/dist/components/settings-dialog.js +144 -0
- package/dist/components/settings-dialog.js.map +1 -0
- package/dist/foundation/constants.d.ts +2 -0
- package/dist/foundation/constants.js +37 -0
- package/dist/foundation/constants.js.map +1 -0
- package/dist/foundation/tree.d.ts +4 -0
- package/dist/foundation/tree.js +57 -0
- package/dist/foundation/tree.js.map +1 -0
- package/dist/foundation/utils.d.ts +48 -0
- package/dist/foundation/utils.js +249 -0
- package/dist/foundation/utils.js.map +1 -0
- package/dist/scl-template-update.d.ts +88 -0
- package/dist/scl-template-update.js +40780 -0
- package/dist/scl-template-update.js.map +1 -0
- package/dist/utils/debounce.d.ts +1 -0
- package/dist/utils/debounce.js +10 -0
- package/dist/utils/debounce.js.map +1 -0
- package/package.json +129 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
3
|
+
import { LitElement, html, css } from 'lit';
|
|
4
|
+
import { property, state } from 'lit/decorators.js';
|
|
5
|
+
import { ScopedElementsMixin } from '@open-wc/scoped-elements/lit-element.js';
|
|
6
|
+
import { OscdFilledButton } from '@omicronenergy/oscd-ui/button/OscdFilledButton.js';
|
|
7
|
+
import { OscdOutlinedTextField } from '@omicronenergy/oscd-ui/textfield/OscdOutlinedTextField.js';
|
|
8
|
+
import { OscdList } from '@omicronenergy/oscd-ui/list/OscdList.js';
|
|
9
|
+
import { OscdListItem } from '@omicronenergy/oscd-ui/list/OscdListItem.js';
|
|
10
|
+
export class LNodeTypeSidebar extends ScopedElementsMixin(LitElement) {
|
|
11
|
+
constructor() {
|
|
12
|
+
super(...arguments);
|
|
13
|
+
this.lNodeTypes = [];
|
|
14
|
+
this.filter = '';
|
|
15
|
+
this.sortedLNodeTypes = [];
|
|
16
|
+
}
|
|
17
|
+
static { this.scopedElements = {
|
|
18
|
+
'oscd-filled-button': OscdFilledButton,
|
|
19
|
+
'oscd-outlined-textfield': OscdOutlinedTextField,
|
|
20
|
+
'oscd-list': OscdList,
|
|
21
|
+
'oscd-list-item': OscdListItem,
|
|
22
|
+
}; }
|
|
23
|
+
static sortLNodeTypes(nodes) {
|
|
24
|
+
return [...nodes].sort((a, b) => {
|
|
25
|
+
const aId = a.getAttribute('id')?.toLowerCase() || '';
|
|
26
|
+
const bId = b.getAttribute('id')?.toLowerCase() || '';
|
|
27
|
+
return aId.localeCompare(bId);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
willUpdate(changedProperties) {
|
|
31
|
+
super.willUpdate(changedProperties);
|
|
32
|
+
if (changedProperties.has('lNodeTypes')) {
|
|
33
|
+
this.sortedLNodeTypes = LNodeTypeSidebar.sortLNodeTypes(this.lNodeTypes);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
handleInput(e) {
|
|
37
|
+
const { value } = e.target;
|
|
38
|
+
clearTimeout(this.debounceTimer);
|
|
39
|
+
this.debounceTimer = window.setTimeout(() => {
|
|
40
|
+
this.filter = value;
|
|
41
|
+
}, 300);
|
|
42
|
+
}
|
|
43
|
+
clearFilter() {
|
|
44
|
+
this.filter = '';
|
|
45
|
+
}
|
|
46
|
+
handleClick(id) {
|
|
47
|
+
this.dispatchEvent(new CustomEvent('lnodetype-select', {
|
|
48
|
+
detail: { id },
|
|
49
|
+
bubbles: true,
|
|
50
|
+
composed: true,
|
|
51
|
+
}));
|
|
52
|
+
}
|
|
53
|
+
get filteredLNodeTypes() {
|
|
54
|
+
const sortedLNTypes = this.sortedLNodeTypes;
|
|
55
|
+
if (!this.filter.trim())
|
|
56
|
+
return sortedLNTypes;
|
|
57
|
+
// If the filter includes words separated by &, treat as a single AND group (e.g. 'a & b', 'a&b', 'a &b', 'a& b').
|
|
58
|
+
// Otherwise, split on comma or space (unless adjacent to &), so 'a b' and 'a,b' are separate OR groups.
|
|
59
|
+
let groups = [];
|
|
60
|
+
const filter = this.filter.toLowerCase().trim();
|
|
61
|
+
if (/^\s*\w+\s*&\s*\w+\s*$/.test(filter)) {
|
|
62
|
+
groups = [
|
|
63
|
+
filter
|
|
64
|
+
.replace(/\s*&\s*/g, '&')
|
|
65
|
+
.split('&')
|
|
66
|
+
.filter(Boolean),
|
|
67
|
+
];
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
groups = filter
|
|
71
|
+
.split(/(?<!&)[ ,]+(?!&)/)
|
|
72
|
+
.map(group => group
|
|
73
|
+
.replace(/\s*&\s*/g, '&')
|
|
74
|
+
.split('&')
|
|
75
|
+
.filter(Boolean))
|
|
76
|
+
.filter(group => group.length > 0);
|
|
77
|
+
}
|
|
78
|
+
if (groups.length === 0)
|
|
79
|
+
return sortedLNTypes;
|
|
80
|
+
return sortedLNTypes.filter(ln => {
|
|
81
|
+
const id = ln.getAttribute('id')?.toLowerCase() || '';
|
|
82
|
+
const desc = ln.getAttribute('desc')?.toLowerCase() || '';
|
|
83
|
+
return groups.some(group => group.every(term => id.includes(term) || desc.includes(term)));
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
render() {
|
|
87
|
+
return html `<div class="sidebar">
|
|
88
|
+
<div class="actions">
|
|
89
|
+
<oscd-filled-button class="clear-all" @click=${this.clearFilter}>
|
|
90
|
+
Clear filter
|
|
91
|
+
</oscd-filled-button>
|
|
92
|
+
</div>
|
|
93
|
+
<div class="search-filter">
|
|
94
|
+
<div class="search-container">
|
|
95
|
+
<oscd-outlined-textfield
|
|
96
|
+
label="Filter Logical Node Types"
|
|
97
|
+
type="text"
|
|
98
|
+
placeholder="e.g.: TCTR, TVTR&protection"
|
|
99
|
+
.value=${this.filter}
|
|
100
|
+
@input=${this.handleInput}
|
|
101
|
+
aria-label="Filter Logical Node Types"
|
|
102
|
+
supporting-text="Search by ID or description. Use commas/spaces for OR, use & for AND."
|
|
103
|
+
></oscd-outlined-textfield>
|
|
104
|
+
</div>
|
|
105
|
+
</div>
|
|
106
|
+
<oscd-list>
|
|
107
|
+
${this.filteredLNodeTypes.map(ln => {
|
|
108
|
+
const id = ln.getAttribute('id') || '';
|
|
109
|
+
const desc = ln.getAttribute('desc') || '';
|
|
110
|
+
const isSelected = this.selectedId === id;
|
|
111
|
+
return html `
|
|
112
|
+
<oscd-list-item
|
|
113
|
+
type="button"
|
|
114
|
+
?selected=${isSelected}
|
|
115
|
+
@click=${() => this.handleClick(id)}
|
|
116
|
+
>
|
|
117
|
+
<span slot="headline" title=${id}>${id}</span>
|
|
118
|
+
<span slot="supporting-text">${desc}</span>
|
|
119
|
+
</oscd-list-item>
|
|
120
|
+
`;
|
|
121
|
+
})}
|
|
122
|
+
</oscd-list>
|
|
123
|
+
</div>`;
|
|
124
|
+
}
|
|
125
|
+
static { this.styles = css `
|
|
126
|
+
.sidebar {
|
|
127
|
+
display: flex;
|
|
128
|
+
flex-direction: column;
|
|
129
|
+
flex: 1 1 auto;
|
|
130
|
+
min-height: 0;
|
|
131
|
+
padding: 1rem;
|
|
132
|
+
overflow: hidden;
|
|
133
|
+
background-color: var(--oscd-base3);
|
|
134
|
+
}
|
|
135
|
+
oscd-list {
|
|
136
|
+
min-height: 0;
|
|
137
|
+
max-height: calc(100vh - var(--header-height) - 1rem - 134px);
|
|
138
|
+
overflow-y: auto;
|
|
139
|
+
scrollbar-width: thin;
|
|
140
|
+
padding: 0;
|
|
141
|
+
}
|
|
142
|
+
oscd-list::-webkit-scrollbar {
|
|
143
|
+
width: 8px;
|
|
144
|
+
}
|
|
145
|
+
oscd-list::-webkit-scrollbar-thumb {
|
|
146
|
+
border-radius: 4px;
|
|
147
|
+
}
|
|
148
|
+
oscd-list::-webkit-scrollbar-track {
|
|
149
|
+
background: transparent;
|
|
150
|
+
}
|
|
151
|
+
oscd-list-item {
|
|
152
|
+
box-sizing: border-box;
|
|
153
|
+
}
|
|
154
|
+
oscd-list-item[selected] {
|
|
155
|
+
background: var(--md-sys-color-primary);
|
|
156
|
+
}
|
|
157
|
+
oscd-list-item[selected] span[slot='headline'],
|
|
158
|
+
oscd-list-item[selected] span[slot='supporting-text'] {
|
|
159
|
+
color: var(--md-sys-color-on-primary, #ffffff);
|
|
160
|
+
}
|
|
161
|
+
oscd-outlined-textfield {
|
|
162
|
+
width: 100%;
|
|
163
|
+
}
|
|
164
|
+
.actions {
|
|
165
|
+
display: flex;
|
|
166
|
+
flex-direction: row-reverse;
|
|
167
|
+
margin-bottom: 0.5rem;
|
|
168
|
+
}
|
|
169
|
+
.search-filter {
|
|
170
|
+
display: flex;
|
|
171
|
+
align-items: center;
|
|
172
|
+
gap: 1rem;
|
|
173
|
+
margin-bottom: 1rem;
|
|
174
|
+
}
|
|
175
|
+
.search-container {
|
|
176
|
+
flex: 1;
|
|
177
|
+
position: relative;
|
|
178
|
+
}
|
|
179
|
+
.clear-all {
|
|
180
|
+
cursor: pointer;
|
|
181
|
+
color: var(--md-sys-color-primary, #0078d4);
|
|
182
|
+
text-decoration: underline;
|
|
183
|
+
font-size: 0.95em;
|
|
184
|
+
}
|
|
185
|
+
`; }
|
|
186
|
+
}
|
|
187
|
+
__decorate([
|
|
188
|
+
property({ type: Array })
|
|
189
|
+
], LNodeTypeSidebar.prototype, "lNodeTypes", void 0);
|
|
190
|
+
__decorate([
|
|
191
|
+
property({ type: String })
|
|
192
|
+
], LNodeTypeSidebar.prototype, "selectedId", void 0);
|
|
193
|
+
__decorate([
|
|
194
|
+
state()
|
|
195
|
+
], LNodeTypeSidebar.prototype, "filter", void 0);
|
|
196
|
+
//# sourceMappingURL=lnodetype-sidebar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lnodetype-sidebar.js","sourceRoot":"","sources":["../../components/lnodetype-sidebar.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-unused-vars */\nimport { LitElement, html, css, PropertyValues } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { ScopedElementsMixin } from '@open-wc/scoped-elements/lit-element.js';\n\nimport { OscdFilledButton } from '@omicronenergy/oscd-ui/button/OscdFilledButton.js';\nimport { OscdOutlinedTextField } from '@omicronenergy/oscd-ui/textfield/OscdOutlinedTextField.js';\nimport { OscdList } from '@omicronenergy/oscd-ui/list/OscdList.js';\nimport { OscdListItem } from '@omicronenergy/oscd-ui/list/OscdListItem.js';\n\nexport class LNodeTypeSidebar extends ScopedElementsMixin(LitElement) {\n static scopedElements = {\n 'oscd-filled-button': OscdFilledButton,\n 'oscd-outlined-textfield': OscdOutlinedTextField,\n 'oscd-list': OscdList,\n 'oscd-list-item': OscdListItem,\n };\n\n @property({ type: Array })\n lNodeTypes: Element[] = [];\n\n @property({ type: String })\n selectedId?: string;\n\n @state()\n filter: string = '';\n\n private sortedLNodeTypes: Element[] = [];\n\n private debounceTimer?: number;\n\n private static sortLNodeTypes(nodes: Element[]): Element[] {\n return [...nodes].sort((a, b) => {\n const aId = a.getAttribute('id')?.toLowerCase() || '';\n const bId = b.getAttribute('id')?.toLowerCase() || '';\n return aId.localeCompare(bId);\n });\n }\n\n protected willUpdate(changedProperties: PropertyValues<this>) {\n super.willUpdate(changedProperties);\n\n if (changedProperties.has('lNodeTypes')) {\n this.sortedLNodeTypes = LNodeTypeSidebar.sortLNodeTypes(this.lNodeTypes);\n }\n }\n\n private handleInput(e: Event) {\n const { value } = e.target as HTMLInputElement;\n clearTimeout(this.debounceTimer);\n this.debounceTimer = window.setTimeout(() => {\n this.filter = value;\n }, 300);\n }\n\n private clearFilter() {\n this.filter = '';\n }\n\n private handleClick(id: string) {\n this.dispatchEvent(\n new CustomEvent('lnodetype-select', {\n detail: { id },\n bubbles: true,\n composed: true,\n })\n );\n }\n\n get filteredLNodeTypes(): Element[] {\n const sortedLNTypes = this.sortedLNodeTypes;\n\n if (!this.filter.trim()) return sortedLNTypes;\n // If the filter includes words separated by &, treat as a single AND group (e.g. 'a & b', 'a&b', 'a &b', 'a& b').\n // Otherwise, split on comma or space (unless adjacent to &), so 'a b' and 'a,b' are separate OR groups.\n let groups: string[][] = [];\n const filter = this.filter.toLowerCase().trim();\n if (/^\\s*\\w+\\s*&\\s*\\w+\\s*$/.test(filter)) {\n groups = [\n filter\n .replace(/\\s*&\\s*/g, '&')\n .split('&')\n .filter(Boolean),\n ];\n } else {\n groups = filter\n .split(/(?<!&)[ ,]+(?!&)/)\n .map(group =>\n group\n .replace(/\\s*&\\s*/g, '&')\n .split('&')\n .filter(Boolean)\n )\n .filter(group => group.length > 0);\n }\n\n if (groups.length === 0) return sortedLNTypes;\n\n return sortedLNTypes.filter(ln => {\n const id = ln.getAttribute('id')?.toLowerCase() || '';\n const desc = ln.getAttribute('desc')?.toLowerCase() || '';\n return groups.some(group =>\n group.every(term => id.includes(term) || desc.includes(term))\n );\n });\n }\n\n render() {\n return html`<div class=\"sidebar\">\n <div class=\"actions\">\n <oscd-filled-button class=\"clear-all\" @click=${this.clearFilter}>\n Clear filter\n </oscd-filled-button>\n </div>\n <div class=\"search-filter\">\n <div class=\"search-container\">\n <oscd-outlined-textfield\n label=\"Filter Logical Node Types\"\n type=\"text\"\n placeholder=\"e.g.: TCTR, TVTR&protection\"\n .value=${this.filter}\n @input=${this.handleInput}\n aria-label=\"Filter Logical Node Types\"\n supporting-text=\"Search by ID or description. Use commas/spaces for OR, use & for AND.\"\n ></oscd-outlined-textfield>\n </div>\n </div>\n <oscd-list>\n ${this.filteredLNodeTypes.map(ln => {\n const id = ln.getAttribute('id') || '';\n const desc = ln.getAttribute('desc') || '';\n const isSelected = this.selectedId === id;\n return html`\n <oscd-list-item\n type=\"button\"\n ?selected=${isSelected}\n @click=${() => this.handleClick(id)}\n >\n <span slot=\"headline\" title=${id}>${id}</span>\n <span slot=\"supporting-text\">${desc}</span>\n </oscd-list-item>\n `;\n })}\n </oscd-list>\n </div>`;\n }\n\n static styles = css`\n .sidebar {\n display: flex;\n flex-direction: column;\n flex: 1 1 auto;\n min-height: 0;\n padding: 1rem;\n overflow: hidden;\n background-color: var(--oscd-base3);\n }\n oscd-list {\n min-height: 0;\n max-height: calc(100vh - var(--header-height) - 1rem - 134px);\n overflow-y: auto;\n scrollbar-width: thin;\n padding: 0;\n }\n oscd-list::-webkit-scrollbar {\n width: 8px;\n }\n oscd-list::-webkit-scrollbar-thumb {\n border-radius: 4px;\n }\n oscd-list::-webkit-scrollbar-track {\n background: transparent;\n }\n oscd-list-item {\n box-sizing: border-box;\n }\n oscd-list-item[selected] {\n background: var(--md-sys-color-primary);\n }\n oscd-list-item[selected] span[slot='headline'],\n oscd-list-item[selected] span[slot='supporting-text'] {\n color: var(--md-sys-color-on-primary, #ffffff);\n }\n oscd-outlined-textfield {\n width: 100%;\n }\n .actions {\n display: flex;\n flex-direction: row-reverse;\n margin-bottom: 0.5rem;\n }\n .search-filter {\n display: flex;\n align-items: center;\n gap: 1rem;\n margin-bottom: 1rem;\n }\n .search-container {\n flex: 1;\n position: relative;\n }\n .clear-all {\n cursor: pointer;\n color: var(--md-sys-color-primary, #0078d4);\n text-decoration: underline;\n font-size: 0.95em;\n }\n `;\n}\n"]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
import { OscdDialog } from '@omicronenergy/oscd-ui/dialog/OscdDialog.js';
|
|
3
|
+
import { OscdTextButton } from '@omicronenergy/oscd-ui/button/OscdTextButton.js';
|
|
4
|
+
import { OscdRadio } from '@omicronenergy/oscd-ui/radio/OscdRadio.js';
|
|
5
|
+
export declare enum UpdateSetting {
|
|
6
|
+
Swap = "swap",
|
|
7
|
+
Update = "update"
|
|
8
|
+
}
|
|
9
|
+
declare const SettingsDialog_base: typeof LitElement & import("@open-wc/scoped-elements/lit-element.js").ScopedElementsHostConstructor;
|
|
10
|
+
export declare class SettingsDialog extends SettingsDialog_base {
|
|
11
|
+
static scopedElements: {
|
|
12
|
+
'oscd-dialog': typeof OscdDialog;
|
|
13
|
+
'oscd-text-button': typeof OscdTextButton;
|
|
14
|
+
'oscd-radio': typeof OscdRadio;
|
|
15
|
+
};
|
|
16
|
+
dialog: OscdDialog;
|
|
17
|
+
private updateSetting;
|
|
18
|
+
connectedCallback(): void;
|
|
19
|
+
private loadSettings;
|
|
20
|
+
private saveSettings;
|
|
21
|
+
get open(): boolean;
|
|
22
|
+
show(): void;
|
|
23
|
+
close(): void;
|
|
24
|
+
private handleRadioChange;
|
|
25
|
+
private handleConfirm;
|
|
26
|
+
private handleCancel;
|
|
27
|
+
render(): import("lit").TemplateResult<1>;
|
|
28
|
+
static styles: import("lit").CSSResult;
|
|
29
|
+
}
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
3
|
+
import { ScopedElementsMixin } from '@open-wc/scoped-elements/lit-element.js';
|
|
4
|
+
import { LitElement, html, css } from 'lit';
|
|
5
|
+
import { query, state } from 'lit/decorators.js';
|
|
6
|
+
import { OscdDialog } from '@omicronenergy/oscd-ui/dialog/OscdDialog.js';
|
|
7
|
+
import { OscdTextButton } from '@omicronenergy/oscd-ui/button/OscdTextButton.js';
|
|
8
|
+
import { OscdRadio } from '@omicronenergy/oscd-ui/radio/OscdRadio.js';
|
|
9
|
+
import { TEMPLATE_UPDATE_SETTING_STORAGE_KEY } from '../foundation/constants.js';
|
|
10
|
+
// eslint-disable-next-line no-shadow
|
|
11
|
+
export var UpdateSetting;
|
|
12
|
+
(function (UpdateSetting) {
|
|
13
|
+
UpdateSetting["Swap"] = "swap";
|
|
14
|
+
UpdateSetting["Update"] = "update";
|
|
15
|
+
})(UpdateSetting || (UpdateSetting = {}));
|
|
16
|
+
export class SettingsDialog extends ScopedElementsMixin(LitElement) {
|
|
17
|
+
constructor() {
|
|
18
|
+
super(...arguments);
|
|
19
|
+
this.updateSetting = UpdateSetting.Update;
|
|
20
|
+
}
|
|
21
|
+
static { this.scopedElements = {
|
|
22
|
+
'oscd-dialog': OscdDialog,
|
|
23
|
+
'oscd-text-button': OscdTextButton,
|
|
24
|
+
'oscd-radio': OscdRadio,
|
|
25
|
+
}; }
|
|
26
|
+
connectedCallback() {
|
|
27
|
+
super.connectedCallback();
|
|
28
|
+
this.loadSettings();
|
|
29
|
+
}
|
|
30
|
+
loadSettings() {
|
|
31
|
+
const stored = localStorage.getItem(TEMPLATE_UPDATE_SETTING_STORAGE_KEY);
|
|
32
|
+
if (stored && Object.values(UpdateSetting).includes(stored)) {
|
|
33
|
+
this.updateSetting = stored;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
this.updateSetting = UpdateSetting.Update;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
saveSettings() {
|
|
40
|
+
localStorage.setItem(TEMPLATE_UPDATE_SETTING_STORAGE_KEY, this.updateSetting);
|
|
41
|
+
}
|
|
42
|
+
get open() {
|
|
43
|
+
return this.dialog?.open ?? false;
|
|
44
|
+
}
|
|
45
|
+
show() {
|
|
46
|
+
this.loadSettings();
|
|
47
|
+
this.dialog?.show();
|
|
48
|
+
}
|
|
49
|
+
close() {
|
|
50
|
+
this.dialog?.close();
|
|
51
|
+
}
|
|
52
|
+
handleRadioChange(event) {
|
|
53
|
+
const target = event.target;
|
|
54
|
+
if (target.checked) {
|
|
55
|
+
this.updateSetting = target.value;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
handleConfirm() {
|
|
59
|
+
this.saveSettings();
|
|
60
|
+
this.close();
|
|
61
|
+
}
|
|
62
|
+
handleCancel() {
|
|
63
|
+
this.loadSettings();
|
|
64
|
+
this.close();
|
|
65
|
+
}
|
|
66
|
+
render() {
|
|
67
|
+
return html `
|
|
68
|
+
<oscd-dialog @closed=${() => this.dialog?.close()}>
|
|
69
|
+
<div slot="headline">LNodeType update behaviour</div>
|
|
70
|
+
<div slot="content">
|
|
71
|
+
<div class="radio-group">
|
|
72
|
+
<label class="radio-item">
|
|
73
|
+
<oscd-radio
|
|
74
|
+
name="update-setting"
|
|
75
|
+
value=${UpdateSetting.Update}
|
|
76
|
+
.checked=${this.updateSetting === UpdateSetting.Update}
|
|
77
|
+
@change=${this.handleRadioChange}
|
|
78
|
+
></oscd-radio>
|
|
79
|
+
<span class="radio-label">Update logical node type </span>
|
|
80
|
+
</label>
|
|
81
|
+
<label class="radio-item">
|
|
82
|
+
<oscd-radio
|
|
83
|
+
name="update-setting"
|
|
84
|
+
value=${UpdateSetting.Swap}
|
|
85
|
+
.checked=${this.updateSetting === UpdateSetting.Swap}
|
|
86
|
+
@change=${this.handleRadioChange}
|
|
87
|
+
></oscd-radio>
|
|
88
|
+
<span class="radio-label">Swap logical node type </span>
|
|
89
|
+
</label>
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
<div slot="actions">
|
|
93
|
+
<oscd-text-button @click=${this.handleCancel} type="button">
|
|
94
|
+
Cancel
|
|
95
|
+
</oscd-text-button>
|
|
96
|
+
<oscd-text-button @click=${this.handleConfirm} type="button">
|
|
97
|
+
Save
|
|
98
|
+
</oscd-text-button>
|
|
99
|
+
</div>
|
|
100
|
+
</oscd-dialog>
|
|
101
|
+
`;
|
|
102
|
+
}
|
|
103
|
+
static { this.styles = css `
|
|
104
|
+
oscd-dialog {
|
|
105
|
+
--md-dialog-container-max-width: 400px;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.radio-group {
|
|
109
|
+
display: flex;
|
|
110
|
+
flex-direction: column;
|
|
111
|
+
gap: 12px;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.radio-item {
|
|
115
|
+
display: flex;
|
|
116
|
+
align-items: flex-start;
|
|
117
|
+
gap: 12px;
|
|
118
|
+
cursor: pointer;
|
|
119
|
+
padding: 8px;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.radio-item:hover {
|
|
123
|
+
background-color: rgba(0, 0, 0, 0.04);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.radio-label {
|
|
127
|
+
display: flex;
|
|
128
|
+
flex-direction: column;
|
|
129
|
+
gap: 4px;
|
|
130
|
+
flex: 1;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
oscd-text-button {
|
|
134
|
+
text-transform: uppercase;
|
|
135
|
+
}
|
|
136
|
+
`; }
|
|
137
|
+
}
|
|
138
|
+
__decorate([
|
|
139
|
+
query('oscd-dialog')
|
|
140
|
+
], SettingsDialog.prototype, "dialog", void 0);
|
|
141
|
+
__decorate([
|
|
142
|
+
state()
|
|
143
|
+
], SettingsDialog.prototype, "updateSetting", void 0);
|
|
144
|
+
//# sourceMappingURL=settings-dialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings-dialog.js","sourceRoot":"","sources":["../../components/settings-dialog.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-unused-vars */\nimport { ScopedElementsMixin } from '@open-wc/scoped-elements/lit-element.js';\nimport { LitElement, html, css } from 'lit';\nimport { query, state } from 'lit/decorators.js';\nimport { OscdDialog } from '@omicronenergy/oscd-ui/dialog/OscdDialog.js';\nimport { OscdTextButton } from '@omicronenergy/oscd-ui/button/OscdTextButton.js';\nimport { OscdRadio } from '@omicronenergy/oscd-ui/radio/OscdRadio.js';\nimport { TEMPLATE_UPDATE_SETTING_STORAGE_KEY } from '../foundation/constants.js';\n\n// eslint-disable-next-line no-shadow\nexport enum UpdateSetting {\n Swap = 'swap',\n Update = 'update',\n}\n\nexport class SettingsDialog extends ScopedElementsMixin(LitElement) {\n static scopedElements = {\n 'oscd-dialog': OscdDialog,\n 'oscd-text-button': OscdTextButton,\n 'oscd-radio': OscdRadio,\n };\n\n @query('oscd-dialog')\n dialog!: OscdDialog;\n\n @state()\n private updateSetting: UpdateSetting = UpdateSetting.Update;\n\n connectedCallback() {\n super.connectedCallback();\n this.loadSettings();\n }\n\n private loadSettings() {\n const stored = localStorage.getItem(\n TEMPLATE_UPDATE_SETTING_STORAGE_KEY\n ) as UpdateSetting;\n if (stored && Object.values(UpdateSetting).includes(stored)) {\n this.updateSetting = stored;\n } else {\n this.updateSetting = UpdateSetting.Update;\n }\n }\n\n private saveSettings() {\n localStorage.setItem(\n TEMPLATE_UPDATE_SETTING_STORAGE_KEY,\n this.updateSetting\n );\n }\n\n get open() {\n return this.dialog?.open ?? false;\n }\n\n show() {\n this.loadSettings();\n this.dialog?.show();\n }\n\n close() {\n this.dialog?.close();\n }\n\n private handleRadioChange(event: Event) {\n const target = event.target as OscdRadio;\n if (target.checked) {\n this.updateSetting = target.value as UpdateSetting;\n }\n }\n\n private handleConfirm() {\n this.saveSettings();\n this.close();\n }\n\n private handleCancel() {\n this.loadSettings();\n this.close();\n }\n\n render() {\n return html`\n <oscd-dialog @closed=${() => this.dialog?.close()}>\n <div slot=\"headline\">LNodeType update behaviour</div>\n <div slot=\"content\">\n <div class=\"radio-group\">\n <label class=\"radio-item\">\n <oscd-radio\n name=\"update-setting\"\n value=${UpdateSetting.Update}\n .checked=${this.updateSetting === UpdateSetting.Update}\n @change=${this.handleRadioChange}\n ></oscd-radio>\n <span class=\"radio-label\">Update logical node type </span>\n </label>\n <label class=\"radio-item\">\n <oscd-radio\n name=\"update-setting\"\n value=${UpdateSetting.Swap}\n .checked=${this.updateSetting === UpdateSetting.Swap}\n @change=${this.handleRadioChange}\n ></oscd-radio>\n <span class=\"radio-label\">Swap logical node type </span>\n </label>\n </div>\n </div>\n <div slot=\"actions\">\n <oscd-text-button @click=${this.handleCancel} type=\"button\">\n Cancel\n </oscd-text-button>\n <oscd-text-button @click=${this.handleConfirm} type=\"button\">\n Save\n </oscd-text-button>\n </div>\n </oscd-dialog>\n `;\n }\n\n static styles = css`\n oscd-dialog {\n --md-dialog-container-max-width: 400px;\n }\n\n .radio-group {\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n\n .radio-item {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n cursor: pointer;\n padding: 8px;\n }\n\n .radio-item:hover {\n background-color: rgba(0, 0, 0, 0.04);\n }\n\n .radio-label {\n display: flex;\n flex-direction: column;\n gap: 4px;\n flex: 1;\n }\n\n oscd-text-button {\n text-transform: uppercase;\n }\n `;\n}\n"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const cdClasses: readonly ["ACD", "ACT", "APC", "ASG", "BAC", "BCR", "BSC", "CMV", "DEL", "DPC", "DPL", "HDEL", "HMV", "HST", "HWYE", "INC", "INS", "ISC", "LPL", "MV", "ORG", "ORS", "SAV", "SEC", "SEQ", "SPC", "SPG", "SPS", "TCS", "TSG", "VSG", "VSS", "WYE"];
|
|
2
|
+
export declare const TEMPLATE_UPDATE_SETTING_STORAGE_KEY = "template-update-setting";
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export const cdClasses = [
|
|
2
|
+
'ACD',
|
|
3
|
+
'ACT',
|
|
4
|
+
'APC',
|
|
5
|
+
'ASG',
|
|
6
|
+
'BAC',
|
|
7
|
+
'BCR',
|
|
8
|
+
'BSC',
|
|
9
|
+
'CMV',
|
|
10
|
+
'DEL',
|
|
11
|
+
'DPC',
|
|
12
|
+
'DPL',
|
|
13
|
+
'HDEL',
|
|
14
|
+
'HMV',
|
|
15
|
+
'HST',
|
|
16
|
+
'HWYE',
|
|
17
|
+
'INC',
|
|
18
|
+
'INS',
|
|
19
|
+
'ISC',
|
|
20
|
+
'LPL',
|
|
21
|
+
'MV',
|
|
22
|
+
'ORG',
|
|
23
|
+
'ORS',
|
|
24
|
+
'SAV',
|
|
25
|
+
'SEC',
|
|
26
|
+
'SEQ',
|
|
27
|
+
'SPC',
|
|
28
|
+
'SPG',
|
|
29
|
+
'SPS',
|
|
30
|
+
'TCS',
|
|
31
|
+
'TSG',
|
|
32
|
+
'VSG',
|
|
33
|
+
'VSS',
|
|
34
|
+
'WYE',
|
|
35
|
+
];
|
|
36
|
+
export const TEMPLATE_UPDATE_SETTING_STORAGE_KEY = 'template-update-setting';
|
|
37
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../foundation/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,MAAM;IACN,KAAK;IACL,KAAK;IACL,MAAM;IACN,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,IAAI;IACJ,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;CACG,CAAC;AAEX,MAAM,CAAC,MAAM,mCAAmC,GAAG,yBAAyB,CAAC","sourcesContent":["export const cdClasses = [\n 'ACD',\n 'ACT',\n 'APC',\n 'ASG',\n 'BAC',\n 'BCR',\n 'BSC',\n 'CMV',\n 'DEL',\n 'DPC',\n 'DPL',\n 'HDEL',\n 'HMV',\n 'HST',\n 'HWYE',\n 'INC',\n 'INS',\n 'ISC',\n 'LPL',\n 'MV',\n 'ORG',\n 'ORS',\n 'SAV',\n 'SEC',\n 'SEQ',\n 'SPC',\n 'SPG',\n 'SPS',\n 'TCS',\n 'TSG',\n 'VSG',\n 'VSS',\n 'WYE',\n] as const;\n\nexport const TEMPLATE_UPDATE_SETTING_STORAGE_KEY = 'template-update-setting';\n"]}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { nsdToJson } from '@openscd/scl-lib';
|
|
2
|
+
import { cdClasses } from './constants.js';
|
|
3
|
+
function getCDCForDOType(doc, doType) {
|
|
4
|
+
const doTypeElement = doc.querySelector(`:root > DataTypeTemplates > DOType[id="${doType}"]`);
|
|
5
|
+
return doTypeElement?.getAttribute('cdc') ?? undefined;
|
|
6
|
+
}
|
|
7
|
+
function isSupportedCDC(cdc) {
|
|
8
|
+
return !!cdc && cdClasses.includes(cdc);
|
|
9
|
+
}
|
|
10
|
+
function buildDataObject(doName, cdc) {
|
|
11
|
+
const cdcChildren = nsdToJson(cdc);
|
|
12
|
+
return {
|
|
13
|
+
[doName]: {
|
|
14
|
+
tagName: 'DataObject',
|
|
15
|
+
type: cdc,
|
|
16
|
+
descID: '',
|
|
17
|
+
presCond: 'O',
|
|
18
|
+
children: cdcChildren,
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Merges user-defined Data Objects in the NSD tree. This ensures that
|
|
24
|
+
* any custom or extra DOs present in the user's SCL are preserved
|
|
25
|
+
* in the tree, even if they are not part of the NSD definition.
|
|
26
|
+
*/
|
|
27
|
+
function mergeUserDOsIntoTree(tree, lNodeType, doc) {
|
|
28
|
+
if (!lNodeType || !doc)
|
|
29
|
+
return { tree, unsupportedDOs: [] };
|
|
30
|
+
const result = { ...tree };
|
|
31
|
+
const doElements = Array.from(lNodeType.querySelectorAll(':scope > DO'));
|
|
32
|
+
const standardDONames = tree ? Object.keys(tree) : [];
|
|
33
|
+
const unsupportedDOs = [];
|
|
34
|
+
doElements.forEach(doEl => {
|
|
35
|
+
const doName = doEl.getAttribute('name');
|
|
36
|
+
const doType = doEl.getAttribute('type');
|
|
37
|
+
if (!doName || !doType)
|
|
38
|
+
return;
|
|
39
|
+
if (!standardDONames.includes(doName)) {
|
|
40
|
+
const cdc = getCDCForDOType(doc, doType);
|
|
41
|
+
if (isSupportedCDC(cdc)) {
|
|
42
|
+
Object.assign(result, buildDataObject(doName, cdc));
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
unsupportedDOs.push(doName);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
return { tree: result, unsupportedDOs };
|
|
50
|
+
}
|
|
51
|
+
export function buildLNodeTree(selectedLNodeTypeClass, lNodeType, doc) {
|
|
52
|
+
const tree = nsdToJson(selectedLNodeTypeClass);
|
|
53
|
+
if (!tree)
|
|
54
|
+
return { tree: undefined, unsupportedDOs: [] };
|
|
55
|
+
return mergeUserDOsIntoTree(tree, lNodeType, doc);
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=tree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tree.js","sourceRoot":"","sources":["../../foundation/tree.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAoB,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,SAAS,eAAe,CAAC,GAAgB,EAAE,MAAc;IACvD,MAAM,aAAa,GAAG,GAAG,CAAC,aAAa,CACrC,0CAA0C,MAAM,IAAI,CACrD,CAAC;IACF,OAAO,aAAa,EAAE,YAAY,CAAC,KAAK,CAAC,IAAI,SAAS,CAAC;AACzD,CAAC;AAED,SAAS,cAAc,CAAC,GAAuB;IAC7C,OAAO,CAAC,CAAC,GAAG,IAAK,SAAmC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AACrE,CAAC;AAED,SAAS,eAAe,CAAC,MAAc,EAAE,GAAW;IAClD,MAAM,WAAW,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IACnC,OAAO;QACL,CAAC,MAAM,CAAC,EAAE;YACR,OAAO,EAAE,YAAY;YACrB,IAAI,EAAE,GAAG;YACT,MAAM,EAAE,EAAE;YACV,QAAQ,EAAE,GAAG;YACb,QAAQ,EAAE,WAAW;SACtB;KACF,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,oBAAoB,CAC3B,IAAS,EACT,SAAkB,EAClB,GAAgB;IAEhB,IAAI,CAAC,SAAS,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC;IAC5D,MAAM,MAAM,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC;IAC3B,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC,CAAC;IACzE,MAAM,eAAe,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACtD,MAAM,cAAc,GAAa,EAAE,CAAC;IAEpC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;QACxB,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QACzC,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM;YAAE,OAAO;QAC/B,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACtC,MAAM,GAAG,GAAG,eAAe,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YACzC,IAAI,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC;gBACxB,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,MAAM,EAAE,GAAI,CAAC,CAAC,CAAC;YACvD,CAAC;iBAAM,CAAC;gBACN,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC9B,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;IACH,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,sBAA8B,EAC9B,SAAkB,EAClB,GAAgB;IAEhB,MAAM,IAAI,GAAG,SAAS,CAAC,sBAAsB,CAAQ,CAAC;IACtD,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC;IAC1D,OAAO,oBAAoB,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;AACpD,CAAC","sourcesContent":["import { nsdToJson, LNodeDescription } from '@openscd/scl-lib';\nimport { cdClasses } from './constants.js';\n\nfunction getCDCForDOType(doc: XMLDocument, doType: string): string | undefined {\n const doTypeElement = doc.querySelector(\n `:root > DataTypeTemplates > DOType[id=\"${doType}\"]`\n );\n return doTypeElement?.getAttribute('cdc') ?? undefined;\n}\n\nfunction isSupportedCDC(cdc: string | undefined): boolean {\n return !!cdc && (cdClasses as ReadonlyArray<string>).includes(cdc);\n}\n\nfunction buildDataObject(doName: string, cdc: string) {\n const cdcChildren = nsdToJson(cdc);\n return {\n [doName]: {\n tagName: 'DataObject',\n type: cdc,\n descID: '',\n presCond: 'O',\n children: cdcChildren,\n },\n };\n}\n\n/**\n * Merges user-defined Data Objects in the NSD tree. This ensures that\n * any custom or extra DOs present in the user's SCL are preserved\n * in the tree, even if they are not part of the NSD definition.\n */\nfunction mergeUserDOsIntoTree(\n tree: any,\n lNodeType: Element,\n doc: XMLDocument\n): { tree: LNodeDescription; unsupportedDOs: string[] } {\n if (!lNodeType || !doc) return { tree, unsupportedDOs: [] };\n const result = { ...tree };\n const doElements = Array.from(lNodeType.querySelectorAll(':scope > DO'));\n const standardDONames = tree ? Object.keys(tree) : [];\n const unsupportedDOs: string[] = [];\n\n doElements.forEach(doEl => {\n const doName = doEl.getAttribute('name');\n const doType = doEl.getAttribute('type');\n if (!doName || !doType) return;\n if (!standardDONames.includes(doName)) {\n const cdc = getCDCForDOType(doc, doType);\n if (isSupportedCDC(cdc)) {\n Object.assign(result, buildDataObject(doName, cdc!));\n } else {\n unsupportedDOs.push(doName);\n }\n }\n });\n return { tree: result, unsupportedDOs };\n}\n\nexport function buildLNodeTree(\n selectedLNodeTypeClass: string,\n lNodeType: Element,\n doc: XMLDocument\n): { tree: any; unsupportedDOs: string[] } {\n const tree = nsdToJson(selectedLNodeTypeClass) as any;\n if (!tree) return { tree: undefined, unsupportedDOs: [] };\n return mergeUserDOsIntoTree(tree, lNodeType, doc);\n}\n"]}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Tree, TreeSelection } from '@openenergytools/tree-grid';
|
|
2
|
+
import { EditV2 } from '@openscd/oscd-api';
|
|
3
|
+
export type MissingMandatoryField = {
|
|
4
|
+
path: string[];
|
|
5
|
+
kind: 'subfield';
|
|
6
|
+
};
|
|
7
|
+
export type EmptyReferencedElement = {
|
|
8
|
+
tagName: 'DOType' | 'DAType' | 'EnumType';
|
|
9
|
+
id: string;
|
|
10
|
+
referencePath: string;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Returns an array of the mandatory fields that are missing from the selection.
|
|
14
|
+
* @param tree The tree structure representing the data model
|
|
15
|
+
* @param selection The current selection in the tree
|
|
16
|
+
* @returns An array of MissingMandatoryField objects
|
|
17
|
+
*/
|
|
18
|
+
export declare function getMissingMandatoryFields(tree: Tree, selection: TreeSelection): MissingMandatoryField[];
|
|
19
|
+
/**
|
|
20
|
+
* Finds all referenced elements of an LNodeType that are empty (i.e., have no children).
|
|
21
|
+
* @param lNodeType The LNodeType element to analyse
|
|
22
|
+
* @param missingMandatoryFields An optional array of MissingMandatoryField objects to filter out empty elements that are part of mandatory fields
|
|
23
|
+
* @returns An array of EmptyReferencedElement objects representing the empty referenced elements
|
|
24
|
+
*/
|
|
25
|
+
export declare function getEmptyReferencedElements(lNodeType: Element, missingMandatoryFields?: MissingMandatoryField[]): EmptyReferencedElement[];
|
|
26
|
+
export declare function getLNodeTypes(doc: XMLDocument | undefined): Element[];
|
|
27
|
+
export declare function getSelectedLNodeType(doc: XMLDocument, selected: string): Element | undefined;
|
|
28
|
+
export declare function isLNodeTypeReferenced(doc: XMLDocument, selectedLNodeTypeID: string | null): boolean;
|
|
29
|
+
export declare function filterSelection(tree: Tree, selection: TreeSelection): TreeSelection;
|
|
30
|
+
/**
|
|
31
|
+
* Creates a clone of an LNodeType with only the DOs that are present in the selection.
|
|
32
|
+
* DOs not included in the selection are removed from the cloned element.
|
|
33
|
+
* @param lNodeType - The LNodeType element to filter
|
|
34
|
+
* @param selection - The tree selection containing the DO names to keep
|
|
35
|
+
* @returns A cloned LNodeType element containing only the selected DOs
|
|
36
|
+
*/
|
|
37
|
+
export declare function removeDOsNotInSelection(lNodeType: Element, selection: TreeSelection): Element;
|
|
38
|
+
/**
|
|
39
|
+
* Builds the Remove edits needed when an LNodeType is replaced.
|
|
40
|
+
* Clones the DataTypeTemplates once, adds the incoming new nodes, removes
|
|
41
|
+
* the old LNodeType, then cascades to find which pre-existing sub-types are
|
|
42
|
+
* now unreferenced. Returns the old LNodeType remove plus all orphan removes.
|
|
43
|
+
* @param dataTypeTemplates The live DataTypeTemplates element to base the remove calculations on
|
|
44
|
+
* @param oldLNodeTypeId The ID of the LNodeType being replaced
|
|
45
|
+
* @param newNodes The new nodes being added (cloned before passing in)
|
|
46
|
+
* @returns An array of EditV2 objects representing the nodes to remove
|
|
47
|
+
*/
|
|
48
|
+
export declare function computeOrphanedRemoves(dataTypeTemplates: Element, oldLNodeTypeId: string, newNodes: Element[]): EditV2[];
|