Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filter on labels when opening a SCL File from CoMPAS #195

Merged
merged 3 commits into from
Oct 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/compas/CompasOpen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import '../WizardDivider.js';
import './CompasSclTypeList.js';
import './CompasSclList.js';

/* Event that will be used when a SCL Document is retrieved. */
/* Event that will be used when an SCL Document is retrieved. */
export interface DocRetrievedDetail {
localFile: boolean;
doc: Document;
Expand All @@ -33,7 +33,7 @@ export function newDocRetrievedEvent(
doc: Document,
docName?: string
): DocRetrievedEvent {
return new CustomEvent<DocRetrievedDetail>('docRetrieved', {
return new CustomEvent<DocRetrievedDetail>('doc-retrieved', {
bubbles: true,
composed: true,
detail: { localFile, doc, docName },
Expand Down Expand Up @@ -110,7 +110,7 @@ export default class CompasOpenElement extends LitElement {
type: this.selectedType ?? '',
})}</p>
<compas-scl-list .type=${this.selectedType}
@sclSelected=${(evt: SclSelectedEvent) =>
@scl-selected=${(evt: SclSelectedEvent) =>
this.dispatchEvent(
newPendingStateEvent(
this.getSclDocument(evt.detail.docId)
Expand Down
47 changes: 32 additions & 15 deletions src/compas/CompasSave.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
html,
LitElement,
property,
PropertyValues,
query,
TemplateResult,
} from 'lit-element';
Expand Down Expand Up @@ -42,6 +43,15 @@ import './CompasLabelsField.js';
import './CompasLoading.js';
import './CompasSclTypeSelect.js';

/* Event that will be used when an SCL Document is saved. */
export type DocSavedEvent = CustomEvent<void>;
export function newDocSavedEvent(): DocSavedEvent {
return new CustomEvent<void>('doc-saved', {
bubbles: true,
composed: true,
});
}

@customElement('compas-save')
export default class CompasSaveElement extends CompasExistsIn(LitElement) {
@property()
Expand All @@ -62,6 +72,17 @@ export default class CompasSaveElement extends CompasExistsIn(LitElement) {
@query('compas-labels-field')
private labelsField!: CompasLabelsFieldElement;

protected updated(_changedProperties: PropertyValues): void {
super.updated(_changedProperties);

// When the document is updated, we reset the selected IED.
if (_changedProperties.has('doc')) {
if (this.commentField) {
this.commentField.value = null;
}
}
}

valid(): boolean {
if (!this.existInCompas) {
return this.nameField.checkValidity() && this.sclTypeRadioGroup.valid();
Expand All @@ -79,16 +100,14 @@ export default class CompasSaveElement extends CompasExistsIn(LitElement) {
this.labelsField.updateLabelsInPrivateElement(privateElement!);
}

private async addSclToCompas(doc: XMLDocument): Promise<boolean> {
private async addSclToCompas(doc: XMLDocument): Promise<void> {
const name = stripExtensionFromName(this.nameField.value);
const comment = this.commentField.value;
const docType = this.sclTypeRadioGroup.getSelectedValue() ?? '';
let success = false;

await CompasSclDataService()
.addSclDocument(docType, { sclName: name, comment: comment, doc: doc })
.then(sclDocument => {
this.commentField.value = null;
updateDocumentInOpenSCD(this, sclDocument);

this.dispatchEvent(
Expand All @@ -97,22 +116,20 @@ export default class CompasSaveElement extends CompasExistsIn(LitElement) {
title: get('compas.save.addSuccess'),
})
);
success = true;

this.dispatchEvent(newDocSavedEvent());
})
.catch(reason => createLogEvent(this, reason));

return success;
}

private async updateSclInCompas(
docId: string,
docName: string,
doc: XMLDocument
): Promise<boolean> {
): Promise<void> {
const changeSet = this.changeSetRadiogroup.getSelectedValue();
const comment = this.commentField.value;
const docType = getTypeFromDocName(docName);
let success = false;

await CompasSclDataService()
.updateSclDocument(docType, docId, {
Expand All @@ -121,7 +138,6 @@ export default class CompasSaveElement extends CompasExistsIn(LitElement) {
doc: doc,
})
.then(sclDocument => {
this.commentField.value = null;
updateDocumentInOpenSCD(this, sclDocument);

this.dispatchEvent(
Expand All @@ -130,19 +146,18 @@ export default class CompasSaveElement extends CompasExistsIn(LitElement) {
title: get('compas.save.updateSuccess'),
})
);
success = true;

this.dispatchEvent(newDocSavedEvent());
})
.catch(reason => createLogEvent(this, reason));

return success;
}

async saveToCompas(): Promise<boolean> {
async saveToCompas(): Promise<void> {
this.updateLabels();
if (!this.docId || !this.existInCompas) {
return this.addSclToCompas(this.doc);
await this.addSclToCompas(this.doc);
} else {
return this.updateSclInCompas(this.docId, this.docName, this.doc);
await this.updateSclInCompas(this.docId, this.docName, this.doc);
}
}

Expand All @@ -153,6 +168,8 @@ export default class CompasSaveElement extends CompasExistsIn(LitElement) {
@click=${() => {
this.updateLabels();
saveDocumentToFile(this.doc, this.docName);

this.dispatchEvent(newDocSavedEvent());
}}
>
</mwc-button>
Expand Down
177 changes: 144 additions & 33 deletions src/compas/CompasSclList.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
import {
css,
customElement,
html,
LitElement,
property,
PropertyValues,
state,
TemplateResult,
} from 'lit-element';
import { translate } from 'lit-translate';

import '@material/mwc-icon';
import '@material/mwc-list';
import '@material/mwc-list/mwc-list-item';

import { SelectedItemsChangedEvent } from '../oscd-filter-button.js';

import '../filtered-list.js';
import '../oscd-filter-button.js';

import {
CompasSclDataService,
SDS_NAMESPACE,
Expand All @@ -21,7 +30,7 @@ export interface SclSelectedDetail {
}
export type SclSelectedEvent = CustomEvent<SclSelectedDetail>;
export function newSclSelectedEvent(docId: string): SclSelectedEvent {
return new CustomEvent<SclSelectedDetail>('sclSelected', {
return new CustomEvent<SclSelectedDetail>('scl-selected', {
bubbles: true,
composed: true,
detail: { docId },
Expand All @@ -30,54 +39,156 @@ export function newSclSelectedEvent(docId: string): SclSelectedEvent {

@customElement('compas-scl-list')
export class CompasSclList extends LitElement {
@property({ type: String })
type = '';

@property()
scls!: Element[];
type?: string;

@state()
private items?: Element[];

@state()
private labels: string[] = [];

@state()
private selectedLabels: string[] = [];

@state()
private get filteredItems(): Element[] | undefined {
// If items are still being retrieved, return undefined.
if (!this.items) {
return undefined;
}

// If all labels are selected, show all items, including the ones not having a Label.
if (this.labels.length === this.selectedLabels.length) {
return this.items;
}

return this.items.filter(item => {
const labels = Array.from(item.querySelectorAll('Label') ?? [])
.map(element => element.textContent)
.filter(value => !!value) as string[];
return (
labels.filter(label => this.selectedLabels.includes(label)).length > 0
);
});
}

firstUpdated(): void {
this.fetchData();
}

protected updated(_changedProperties: PropertyValues): void {
super.updated(_changedProperties);

// When the document is updated, we reset the selected IED.
if (_changedProperties.has('type')) {
this.items = undefined;
this.labels = [];
this.selectedLabels = [];
this.fetchData();
}
}

fetchData(): void {
CompasSclDataService()
.listScls(this.type)
.then(xmlResponse => {
this.scls = Array.from(xmlResponse.querySelectorAll('Item') ?? []);
});
if (this.type) {
CompasSclDataService()
.listScls(this.type)
.then(xmlResponse => {
this.items = Array.from(xmlResponse.querySelectorAll('Item') ?? []);
this.labels = Array.from(
new Set(
Array.from(xmlResponse.querySelectorAll('Label') ?? [])
.map(element => element.textContent)
.filter(label => !!label)
.sort((label1, label2) => label1!.localeCompare(label2!))
)
) as string[];
this.selectedLabels = this.labels;
});
}
}

render(): TemplateResult {
if (!this.scls) {
if (!this.items) {
return html` <compas-loading></compas-loading> `;
}
if (this.scls?.length <= 0) {
if (this.items?.length <= 0) {
return html` <mwc-list>
<mwc-list-item><i>${translate('compas.noScls')}</i></mwc-list-item>
</mwc-list>`;
}
return html` <mwc-list>
${this.scls.map(item => {
const id =
item.getElementsByTagNameNS(SDS_NAMESPACE, 'Id').item(0)!
.textContent ?? '';
let name =
item.getElementsByTagNameNS(SDS_NAMESPACE, 'Name').item(0)!
.textContent ?? '';
if (name === '') {
name = id;
}
const version =
item.getElementsByTagNameNS(SDS_NAMESPACE, 'Version').item(0)!
.textContent ?? '';
return html`<mwc-list-item
tabindex="0"
@click=${() => this.dispatchEvent(newSclSelectedEvent(id))}
const filteredItems = this.filteredItems;
return html`
<div class="filters">
<span>${translate('compas.sclFilter')}</span>
<oscd-filter-button
id="labelsFilter"
multi="true"
?disabled="${this.labels.length <= 0}"
.header=${translate('compas.label.selectLabels')}
@selected-items-changed="${(e: SelectedItemsChangedEvent) => {
this.selectedLabels = e.detail.selectedItems;
this.requestUpdate('items');
this.requestUpdate('filteredItems');
this.requestUpdate('selectedLabels');
}}"
>
${name} (${version})
</mwc-list-item>`;
})}
</mwc-list>`;
<span slot="icon">
<mwc-icon>
${this.labels.length != this.selectedLabels.length
? 'label'
: 'label_off'}
</mwc-icon>
</span>
${this.labels.map(label => {
return html` <mwc-check-list-item
value="${label}"
?selected="${this.selectedLabels.includes(label)}"
>
${label}
</mwc-check-list-item>`;
})}
</oscd-filter-button>
</div>
${filteredItems && filteredItems.length > 0
? html` <filtered-list>
${filteredItems.map(item => {
const id =
item.getElementsByTagNameNS(SDS_NAMESPACE, 'Id').item(0)!
.textContent ?? '';
let name =
item.getElementsByTagNameNS(SDS_NAMESPACE, 'Name').item(0)!
.textContent ?? '';
if (name === '') {
name = id;
}
const version =
item.getElementsByTagNameNS(SDS_NAMESPACE, 'Version').item(0)!
.textContent ?? '';
return html` <mwc-list-item
tabindex="0"
@click=${() => this.dispatchEvent(newSclSelectedEvent(id))}
>
${name} (${version})
</mwc-list-item>`;
})}
</filtered-list>`
: html` <mwc-list>
<mwc-list-item>
<i>${translate('compas.noFilteredScls')}</i>
</mwc-list-item>
</mwc-list>`}
`;
}

static styles = css`
.filters {
padding-left: var(--mdc-list-side-padding, 16px);
display: flex;
}

.filters > span {
line-height: 48px;
}
`;
}
2 changes: 1 addition & 1 deletion src/menu/CompasCompareIED.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export default class CompasCompareIEDPlugin extends CompareIEDPlugin {
*/
protected renderSelectTemplateFile(): TemplateResult {
return html`<compas-open
@docRetrieved=${(evt: DocRetrievedEvent) => {
@doc-retrieved=${(evt: DocRetrievedEvent) => {
this.templateDoc = evt.detail.doc;
}}
></compas-open>
Expand Down
Loading