Skip to content

Commit

Permalink
fix(menu/importIEDs): Allow importing multiple IEDs from multiple SCD…
Browse files Browse the repository at this point in the history
… files (#1222)

* Initial refactoring to functions

* Allow consistent import of IEDs (closes #1106)

* Tidy up

* Tidying

* More tidying

* Remove nullish coalescing where not required
  • Loading branch information
danyill committed Jul 13, 2023
1 parent 1df6842 commit 8bdd990
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 99 deletions.
91 changes: 51 additions & 40 deletions src/menu/ImportIEDs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import {
isPublic,
newActionEvent,
newLogEvent,
newPendingStateEvent,
selector,
SimpleAction,
} from '../foundation.js';
Expand Down Expand Up @@ -368,25 +367,20 @@ function isIedNameUnique(ied: Element, doc: Document): boolean {
return true;
}

function resetSelection(dialog: Dialog): void {
(
(dialog.querySelector('filtered-list') as List).selected as ListItemBase[]
).forEach(item => (item.selected = false));
}

export default class ImportingIedPlugin extends LitElement {
@property({ attribute: false })
doc!: XMLDocument;
@property({ type: Number })
editCount = -1;

@state()
importDoc?: XMLDocument;
iedSelection: TemplateResult[] = [];

@query('#importied-plugin-input') pluginFileUI!: HTMLInputElement;
@query('mwc-dialog') dialog!: Dialog;

async run(): Promise<void> {
this.iedSelection = [];
this.pluginFileUI.click();
}

Expand Down Expand Up @@ -423,6 +417,7 @@ export default class ImportingIedPlugin extends LitElement {
// This doesn't provide redo/undo capability as it is not using the Editing
// action API. To use it would require us to cache the full SCL file in
// OpenSCD as it is now which could use significant memory.

// TODO: In open-scd core update this to allow including in undo/redo.
updateNamespaces(
this.doc.documentElement,
Expand All @@ -447,28 +442,34 @@ export default class ImportingIedPlugin extends LitElement {
);
}

private async importIEDs(): Promise<void> {
private async importIEDs(
importDoc: XMLDocument,
fileName: string
): Promise<void> {
const documentDialog: Dialog = this.shadowRoot!.querySelector(
`mwc-dialog[data-file="${fileName}"]`
)!;

const selectedItems = <ListItemBase[]>(
(<List>this.dialog.querySelector('filtered-list')).selected
(<List>documentDialog.querySelector('filtered-list')).selected
);

const ieds = selectedItems
.map(item => {
return this.importDoc!.querySelector(selector('IED', item.value));
return importDoc!.querySelector(selector('IED', item.value));
})
.filter(ied => ied) as Element[];

resetSelection(this.dialog);
this.dialog.close();
documentDialog.close();

for (const ied of ieds) {
this.importIED(ied);
await this.docUpdate();
}
}

public prepareImport(): void {
if (!this.importDoc) {
async prepareImport(importDoc: XMLDocument, fileName: string): Promise<void> {
if (!importDoc) {
this.dispatchEvent(
newLogEvent({
kind: 'error',
Expand All @@ -478,7 +479,7 @@ export default class ImportingIedPlugin extends LitElement {
return;
}

if (this.importDoc.querySelector('parsererror')) {
if (importDoc.querySelector('parsererror')) {
this.dispatchEvent(
newLogEvent({
kind: 'error',
Expand All @@ -488,7 +489,7 @@ export default class ImportingIedPlugin extends LitElement {
return;
}

const ieds = Array.from(this.importDoc.querySelectorAll(':root > IED'));
const ieds = Array.from(importDoc.querySelectorAll(':root > IED'));
if (ieds.length === 0) {
this.dispatchEvent(
newLogEvent({
Expand All @@ -501,10 +502,23 @@ export default class ImportingIedPlugin extends LitElement {

if (ieds.length === 1) {
this.importIED(ieds[0]);
return;
return await this.docUpdate();
}

this.dialog.show();
this.buildIedSelection(importDoc, fileName);
await this.requestUpdate();
const dialog = <Dialog>(
this.shadowRoot!.querySelector(`mwc-dialog[data-file="${fileName}"]`)
);
dialog.show();

// await closing of dialog
await new Promise<void>(resolve => {
dialog.addEventListener('closed', function onClosed(evt) {
evt.target?.removeEventListener('closed', onClosed);
resolve();
});
});
}

/** Loads the file `event.target.files[0]` into [[`src`]] as a `blob:...`. */
Expand All @@ -513,23 +527,20 @@ export default class ImportingIedPlugin extends LitElement {
(<HTMLInputElement | null>event.target)?.files ?? []
);

const promises = files.map(async file => {
this.importDoc = new DOMParser().parseFromString(
await file.text(),
'application/xml'
);

return this.prepareImport();
const promises = files.map(file => {
return {
text: file
.text()
.then(text =>
new DOMParser().parseFromString(text, 'application/xml')
),
name: file.name,
};
});

const mergedPromise = new Promise<void>((resolve, reject) =>
Promise.allSettled(promises).then(
() => resolve(),
() => reject()
)
);

this.dispatchEvent(newPendingStateEvent(mergedPromise));
for await (const file of promises) {
await this.prepareImport(await file.text, file.name);
}
}

protected renderInput(): TemplateResult {
Expand All @@ -539,10 +550,10 @@ export default class ImportingIedPlugin extends LitElement {
}} id="importied-plugin-input" accept=".sed,.scd,.ssd,.iid,.cid,.icd" type="file"></input>`;
}

protected renderIedSelection(): TemplateResult {
return html`<mwc-dialog>
protected buildIedSelection(importDoc: XMLDocument, fileName: string): void {
this.iedSelection.push(html`<mwc-dialog data-file="${fileName}">
<filtered-list hasSlot multi>
${Array.from(this.importDoc?.querySelectorAll(':root > IED') ?? []).map(
${Array.from(importDoc?.querySelectorAll(':root > IED') ?? []).map(
ied =>
html`<mwc-check-list-item value="${identity(ied)}"
>${ied.getAttribute('name')}</mwc-check-list-item
Expand All @@ -560,13 +571,13 @@ export default class ImportingIedPlugin extends LitElement {
label="IEDs"
slot="primaryAction"
icon="add"
@click=${this.importIEDs}
@click=${() => this.importIEDs(importDoc, fileName)}
></mwc-button>
</mwc-dialog>`;
</mwc-dialog>`);
}

render(): TemplateResult {
return html`${this.renderIedSelection()}${this.renderInput()}`;
return html`${this.iedSelection}${this.renderInput()}`;
}

static styles = css`
Expand Down
Loading

0 comments on commit 8bdd990

Please sign in to comment.