Skip to content

Commit 78e8f0f

Browse files
authored
fix(editing): reactively update after changes to doc (openscd#814)
* fix(editing): reactively update after changes to doc * test(ValidateTemplates): move integration tests to integration test file * fix(hosting): prevent error with no editors loaded This prevents an error that shows up in integration tests which don't load any editor type plugins.
1 parent a7af8b2 commit 78e8f0f

File tree

17 files changed

+278
-265
lines changed

17 files changed

+278
-265
lines changed

public/js/plugins.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ export const officialPlugins = [
7676
position: 'top'
7777
},
7878
{
79-
name: 'Validate project',
79+
name: 'Validate Schema',
8080
src: '/src/validators/ValidateSchema.js',
8181
icon: 'rule_folder',
8282
default: true,

src/Editing.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -423,8 +423,17 @@ export function Editing<TBase extends LitElementConstructor>(Base: TBase) {
423423

424424
this.dispatchEvent(newValidateEvent());
425425

426-
for (const element of event.composedPath())
427-
if (element instanceof LitElement) element.requestUpdate();
426+
if (!this.doc) return;
427+
428+
const newDoc = document.implementation.createDocument(
429+
this.doc.lookupNamespaceURI(''),
430+
this.doc.documentElement.tagName,
431+
this.doc.doctype
432+
);
433+
434+
// change the document object reference to enable reactive updates
435+
newDoc.documentElement.replaceWith(this.doc.documentElement);
436+
this.doc = newDoc;
428437
}
429438

430439
private async onOpenDoc(event: OpenDocEvent) {

src/Hosting.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ export function Hosting<
308308
</mwc-top-app-bar-fixed>
309309
</mwc-drawer>
310310
311-
${this.doc
311+
${this.doc && this.editors[this.activeTab]?.content
312312
? this.editors[this.activeTab].content
313313
: html`<div class="landing">
314314
${(<MenuItem[]>this.menu.filter(mi => mi !== 'divider')).map(

src/Plugging.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ export function Plugging<TBase extends new (...args: any[]) => EditingElement>(
226226
private get storedPlugins(): Plugin[] {
227227
return <Plugin[]>(
228228
JSON.parse(localStorage.getItem('plugins') ?? '[]', (key, value) =>
229-
value.src ? this.addContent(value) : value
229+
value.src && value.installed ? this.addContent(value) : value
230230
)
231231
);
232232
}

src/validators/ValidateTemplates.ts

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,6 @@ import { validateChildren } from './templates/foundation.js';
1010

1111
type ValidationResult = LogDetailBase | LogDetail;
1212

13-
export function dispatch(detail: ValidationResult, validatorId: string): void {
14-
const kind = (<LogDetail>detail).kind;
15-
const title = (<LogDetailBase>detail).title;
16-
const message = (<LogDetailBase>detail).message;
17-
18-
if (kind)
19-
document
20-
.querySelector('open-scd')
21-
?.dispatchEvent(newLogEvent(<LogDetail>detail));
22-
else
23-
document.querySelector('open-scd')?.dispatchEvent(
24-
newIssueEvent({
25-
validatorId,
26-
title,
27-
message,
28-
})
29-
);
30-
}
31-
3213
export default class ValidateTemplates extends LitElement {
3314
@property({ attribute: false })
3415
doc!: XMLDocument;
@@ -61,12 +42,19 @@ export default class ValidateTemplates extends LitElement {
6142
const data = this.doc.querySelector('DataTypeTemplates');
6243
if (!data) return;
6344

64-
const issuesTemaplte = await validateChildren(data);
65-
if (issuesTemaplte.length === 0)
66-
issuesTemaplte.push({
45+
const templateIssues = await validateChildren(data);
46+
if (templateIssues.length === 0)
47+
templateIssues.push({
6748
title: get('diag.zeroissues'),
6849
});
6950

70-
issuesTemaplte.forEach(error => dispatch(error, this.pluginId));
51+
templateIssues.forEach(error =>
52+
this.dispatchEvent(
53+
newIssueEvent({
54+
...error,
55+
validatorId: this.pluginId,
56+
})
57+
)
58+
);
7159
}
7260
}

src/validators/templates/foundation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ export async function validateChildren(
9494
const children = Array.from(element.children);
9595

9696
for (const child of children) {
97-
const validator = await tagValidator[child.tagName];
97+
const validator = tagValidator[child.tagName];
9898
if (!validator) continue;
9999

100100
const childIssues = await validator(child);

test/integration/__snapshots__/open-scd.test.snap.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ snapshots["open-scd looks like its snapshot"] =
121121
rule_folder
122122
</mwc-icon>
123123
<span>
124-
Validate project
124+
Validate Schema
125125
</span>
126126
<oscd-plugin3aa68346726da1cd>
127127
</oscd-plugin3aa68346726da1cd>
@@ -774,7 +774,7 @@ snapshots["open-scd looks like its snapshot"] =
774774
<mwc-icon slot="meta">
775775
rule_folder
776776
</mwc-icon>
777-
Validate project
777+
Validate Schema
778778
</mwc-check-list-item>
779779
<mwc-check-list-item
780780
aria-disabled="false"

test/integration/editors/cleanup/control-blocks-container.test.ts

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,10 @@ describe('cleanup-editor integration: unreferenced control blocks', () => {
5757
await element.cleanButton.click();
5858

5959
// the correct number of LogControls should remain
60-
expect(doc.querySelectorAll('LogControl')).to.have.length(1);
61-
expect(doc.querySelectorAll('LogControl[name="LogNP"]')).to.have.length(
62-
0
63-
);
60+
expect(element.doc.querySelectorAll('LogControl')).to.have.length(1);
61+
expect(
62+
element.doc.querySelectorAll('LogControl[name="LogNP"]')
63+
).to.have.length(0);
6464
});
6565

6666
it('correctly removes all GSEControl entries and Address entries from the SCL', async () => {
@@ -77,15 +77,17 @@ describe('cleanup-editor integration: unreferenced control blocks', () => {
7777
await element.cleanButton.click();
7878

7979
// the correct number of GSEControl should remain
80-
expect(doc.querySelectorAll('GSEControl')).to.have.lengthOf(2);
80+
expect(element.doc.querySelectorAll('GSEControl')).to.have.lengthOf(2);
8181
expect(
82-
doc.querySelectorAll(
82+
element.doc.querySelectorAll(
8383
'GSEControl[name="GCB_NP"], GSEControl[name="GCB2_NP"]'
8484
)
8585
).to.have.lengthOf(0);
8686
// Addresses removed
87-
expect(doc.querySelectorAll('GSE[cbName="GCB_NP"]')).to.have.lengthOf(0);
88-
expect(doc.querySelectorAll('GSE')).to.have.lengthOf(1);
87+
expect(
88+
element.doc.querySelectorAll('GSE[cbName="GCB_NP"]')
89+
).to.have.lengthOf(0);
90+
expect(element.doc.querySelectorAll('GSE')).to.have.lengthOf(1);
8991
});
9092

9193
it('correctly removes all SampledValueControl and Address entries from the SCL', async () => {
@@ -102,15 +104,17 @@ describe('cleanup-editor integration: unreferenced control blocks', () => {
102104
await element.cleanButton.click();
103105

104106
// the correct number of SampledValueControls should remain
105-
expect(doc.querySelectorAll('SampledValueControl')).to.have.lengthOf(1);
106107
expect(
107-
doc.querySelectorAll('SampledValueControl[name="MSVCB01_A"]')
108+
element.doc.querySelectorAll('SampledValueControl')
109+
).to.have.lengthOf(1);
110+
expect(
111+
element.doc.querySelectorAll('SampledValueControl[name="MSVCB01_A"]')
108112
).to.have.lengthOf(0);
109113
// Addresses removed
110-
expect(doc.querySelectorAll('SMV[cbName="MSVCB01_A"]')).to.have.lengthOf(
111-
0
112-
);
113-
expect(doc.querySelectorAll('SMV')).to.have.lengthOf(1);
114+
expect(
115+
element.doc.querySelectorAll('SMV[cbName="MSVCB01_A"]')
116+
).to.have.lengthOf(0);
117+
expect(element.doc.querySelectorAll('SMV')).to.have.lengthOf(1);
114118
});
115119

116120
describe('if the Address checkbox is unchecked', () => {
@@ -132,15 +136,17 @@ describe('cleanup-editor integration: unreferenced control blocks', () => {
132136
await element.cleanButton.click();
133137

134138
// the correct number of SampledValueControls should remain
135-
expect(doc.querySelectorAll('SampledValueControl')).to.have.lengthOf(1);
136139
expect(
137-
doc.querySelectorAll('SampledValueControl[name="MSVCB01_A"]')
140+
element.doc.querySelectorAll('SampledValueControl')
141+
).to.have.lengthOf(1);
142+
expect(
143+
element.doc.querySelectorAll('SampledValueControl[name="MSVCB01_A"]')
138144
).to.have.lengthOf(0);
139145
// Addresses unchanged
140146
expect(
141-
doc.querySelectorAll('SMV[cbName="MSVCB01_A"]')
147+
element.doc.querySelectorAll('SMV[cbName="MSVCB01_A"]')
142148
).to.have.lengthOf(1);
143-
expect(doc.querySelectorAll('SMV')).to.have.lengthOf(2);
149+
expect(element.doc.querySelectorAll('SMV')).to.have.lengthOf(2);
144150
});
145151

146152
it('correctly removes all GSEControl entries but not Address entries from the SCL', async () => {
@@ -160,17 +166,17 @@ describe('cleanup-editor integration: unreferenced control blocks', () => {
160166
await element.cleanButton.click();
161167

162168
// the correct number of GSEControl should remain
163-
expect(doc.querySelectorAll('GSEControl')).to.have.lengthOf(2);
169+
expect(element.doc.querySelectorAll('GSEControl')).to.have.lengthOf(2);
164170
expect(
165171
doc.querySelectorAll(
166172
'GSEControl[name="GCB_NP"], GSEControl[name="GCB2_NP"]'
167173
)
168174
).to.have.lengthOf(0);
169175
// Addresses unchanged
170-
expect(doc.querySelectorAll('GSE[cbName="GCB_NP"]')).to.have.lengthOf(
171-
1
172-
);
173-
expect(doc.querySelectorAll('GSE')).to.have.lengthOf(2);
176+
expect(
177+
element.doc.querySelectorAll('GSE[cbName="GCB_NP"]')
178+
).to.have.lengthOf(1);
179+
expect(element.doc.querySelectorAll('GSE')).to.have.lengthOf(2);
174180
});
175181
});
176182

test/integration/editors/cleanup/datasets-container.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,12 @@ describe('cleanup-editor integration: dataset removal', () => {
7070
await element.cleanupButton!.click();
7171
// the correct number of DataSets should remain
7272
const remainingDataSetCountCheck =
73-
doc.querySelectorAll(
73+
element.doc.querySelectorAll(
7474
':root > IED > AccessPoint > Server > LDevice > LN0 > DataSet, :root > IED > AccessPoint > Server > LDevice > LN > DataSet'
7575
).length === 6;
7676
// those DataSets selected had best be gone
7777
const datasetsCorrectlyRemoved =
78-
doc.querySelectorAll(
78+
element.doc.querySelectorAll(
7979
'DataSet[name="GooseDataSet2"], DataSet[name="PhsMeas2"]'
8080
).length === 0;
8181
expect(remainingDataSetCountCheck && datasetsCorrectlyRemoved).to.equal(

0 commit comments

Comments
 (0)