Skip to content

Commit 50537e9

Browse files
author
Rob Tjalma
authored
Merge pull request #148 from com-pas/update-compas-name
Added feature to update SCL Name in CoMPAS Private element.
2 parents 32d06db + 607351b commit 50537e9

File tree

16 files changed

+679
-266
lines changed

16 files changed

+679
-266
lines changed

src/compas-editors/CompasVersions.ts

Lines changed: 45 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import {css, html, LitElement, property, TemplateResult} from 'lit-element';
2-
import {get, translate} from 'lit-translate';
1+
import { css, html, LitElement, property, TemplateResult } from 'lit-element';
2+
import { get, translate } from 'lit-translate';
33

44
import '@material/mwc-fab';
55
import '@material/mwc-icon';
@@ -8,23 +8,30 @@ import '@material/mwc-list';
88
import '@material/mwc-list/mwc-list-item';
99
import '@material/mwc-list/mwc-check-list-item';
1010

11-
import {newLogEvent, newWizardEvent, Wizard} from "../foundation.js";
12-
import {MultiSelectedEvent} from "@material/mwc-list/mwc-list-foundation";
11+
import { newLogEvent, newWizardEvent, Wizard } from "../foundation.js";
12+
import { MultiSelectedEvent } from "@material/mwc-list/mwc-list-foundation";
1313

14-
import {CompasSclDataService, SDS_NAMESPACE} from "../compas-services/CompasSclDataService.js";
15-
import {createLogEvent} from "../compas-services/foundation.js";
14+
import { CompasSclDataService, SDS_NAMESPACE } from "../compas-services/CompasSclDataService.js";
15+
import { createLogEvent } from "../compas-services/foundation.js";
1616
import {
1717
dispatchEventOnOpenScd,
1818
getOpenScdElement,
1919
getTypeFromDocName,
2020
updateDocumentInOpenSCD
2121
} from "../compas/foundation.js";
22-
import {addVersionToCompasWizard} from "../compas/CompasUploadVersion.js";
23-
import {compareWizard} from "../compas/CompasCompareDialog.js";
24-
import {getElementByName, styles} from './foundation.js';
22+
import { addVersionToCompasWizard } from "../compas/CompasUploadVersion.js";
23+
import { compareWizard } from "../compas/CompasCompareDialog.js";
24+
import { getElementByName, styles } from './foundation.js';
25+
import { wizards } from "../wizards/wizard-library.js";
2526

2627
// Save the selection for the current document.
2728
let selectedVersionsOnCompasVersionsEditor: Set<number> = new Set();
29+
// We will also add an Event Listener when a new document is opened. We then want to reset the selection.
30+
function resetSelection(): void {
31+
// When a new document is loaded the selection will be reset.
32+
selectedVersionsOnCompasVersionsEditor = new Set();
33+
}
34+
addEventListener('open-doc', resetSelection);
2835

2936
/** An editor [[`plugin`]] for selecting the `Substation` section. */
3037
export default class CompasVersionsPlugin extends LitElement {
@@ -38,21 +45,6 @@ export default class CompasVersionsPlugin extends LitElement {
3845
@property()
3946
scls!: Element[];
4047

41-
constructor() {
42-
super();
43-
44-
// Add event to get a notification when a new document is opened.
45-
const openSCD = getOpenScdElement();
46-
if (openSCD !== null) {
47-
openSCD.addEventListener('open-doc', this.resetSelection);
48-
}
49-
}
50-
51-
resetSelection() {
52-
// When a new document is loaded the selection will be reset.
53-
selectedVersionsOnCompasVersionsEditor = new Set();
54-
}
55-
5648
firstUpdated(): void {
5749
if (!this.docId) {
5850
this.scls = [];
@@ -141,6 +133,21 @@ export default class CompasVersionsPlugin extends LitElement {
141133
});
142134
}
143135

136+
private openEditWizard(): void {
137+
const wizard = wizards['SCL'].edit(this.doc.documentElement);
138+
if (wizard) this.dispatchEvent(newWizardEvent(wizard));
139+
}
140+
141+
private getCurrentVersion(): string {
142+
const header = this.doc.querySelector('Header');
143+
return header!.getAttribute('version') ?? 'unknown';
144+
}
145+
146+
private getCurrentName(): string {
147+
const sclName = this.doc.querySelector('SCL > Private[type="compas_scl"] > SclName');
148+
return sclName!.textContent ?? 'unknown';
149+
}
150+
144151
render(): TemplateResult {
145152
if (!this.scls) {
146153
return html `
@@ -158,6 +165,10 @@ export default class CompasVersionsPlugin extends LitElement {
158165
}
159166
return html`
160167
<h1>
168+
${translate('compas.versions.sclInfo',
169+
{ name: this.getCurrentName(),
170+
version: this.getCurrentVersion()
171+
})}
161172
<nav>
162173
<abbr title="${translate('compas.versions.addVersionButton')}">
163174
<mwc-icon-button icon="playlist_add"
@@ -174,10 +185,18 @@ export default class CompasVersionsPlugin extends LitElement {
174185
}}></mwc-icon-button>
175186
</abbr>
176187
</nav>
188+
<nav>
189+
<abbr title="${translate('edit')}">
190+
<mwc-icon-button icon="edit"
191+
@click=${() => this.openEditWizard()}></mwc-icon-button>
192+
</abbr>
193+
</nav>
177194
</h1>
178195
<div id="containerCompasVersions">
179196
<section tabindex="0">
180-
<h1>${translate('compas.versions.title')}</h1>
197+
<h1>
198+
${translate('compas.versions.title')}
199+
</h1>
181200
<mwc-list multi
182201
@selected=${(evt: MultiSelectedEvent) => {
183202
selectedVersionsOnCompasVersionsEditor = evt.detail.index;
@@ -248,7 +267,7 @@ export default class CompasVersionsPlugin extends LitElement {
248267
}
249268
250269
#containerCompasVersions {
251-
padding: 8px 12px 16px;
270+
padding: 16px 12px 16px 12px;
252271
box-sizing: border-box;
253272
grid-template-columns: repeat(auto-fit, minmax(316px, auto));
254273
}

src/compas-wizards/scl.ts

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import { html, TemplateResult } from 'lit-element';
2+
import { get, translate } from 'lit-translate';
3+
4+
import {
5+
cloneElement,
6+
EditorAction,
7+
getValue,
8+
Wizard,
9+
WizardActor,
10+
WizardInputElement,
11+
} from '../foundation.js';
12+
import { COMPAS_SCL_PRIVATE_TYPE } from "../compas/private.js";
13+
import {
14+
createCompasSclName,
15+
createPrivate,
16+
getCompasSclName,
17+
getPrivate
18+
} from "../compas/private.js";
19+
20+
export function updateSCL(sclElement: Element): WizardActor {
21+
return (inputs: WizardInputElement[]): EditorAction[] => {
22+
const newValue = getValue(inputs.find(i => i.label === 'filename')!)!;
23+
const oldSclNameElement = getCompasSclName(sclElement);
24+
25+
if (oldSclNameElement) {
26+
// Update the value in the existing SclName Element by cloning.
27+
const oldValue = oldSclNameElement.textContent;
28+
if (newValue === oldValue) {
29+
return [];
30+
}
31+
32+
const newSclNameElement = cloneElement(oldSclNameElement, {});
33+
newSclNameElement.textContent = newValue;
34+
return [{ old: { element: oldSclNameElement }, new: { element: newSclNameElement } }];
35+
} else {
36+
let privateElement = getPrivate(sclElement, COMPAS_SCL_PRIVATE_TYPE);
37+
if (!privateElement) {
38+
// No Private Element under SCL, so create both Private and SclName Element to be added to the SCL Element.
39+
const newSclNameElement = createCompasSclName(sclElement, newValue);
40+
privateElement = createPrivate(sclElement, COMPAS_SCL_PRIVATE_TYPE);
41+
privateElement.prepend(newSclNameElement);
42+
return [{ new: { parent: sclElement, element: privateElement } }];
43+
}
44+
45+
// There is a Private Element, but no SclName Element, so only create a new SclName Element.
46+
const newSclNameElement = createCompasSclName(sclElement, newValue);
47+
return [{ new: { parent: privateElement, element: newSclNameElement } }];
48+
}
49+
};
50+
}
51+
52+
export function renderCompasSCL(
53+
sclElement: Element
54+
): TemplateResult[] {
55+
const privateFilenameElement = getCompasSclName(sclElement);
56+
const filename = privateFilenameElement ? privateFilenameElement.textContent : '';
57+
58+
return [
59+
html`<wizard-textfield
60+
label="filename"
61+
.maybeValue=${filename}
62+
helper="${translate('compas.scl.filenameHelper')}"
63+
required
64+
validationMessage="${translate('textfield.required')}"
65+
dialogInitialFocus>
66+
</wizard-textfield>`,
67+
];
68+
}
69+
70+
71+
export function editCompasSCLWizard(sclElement: Element): Wizard {
72+
return [
73+
{
74+
title: get('compas.scl.wizardTitle'),
75+
element: sclElement,
76+
primary: {
77+
icon: 'edit',
78+
label: get('save'),
79+
action: updateSCL(sclElement),
80+
},
81+
content: renderCompasSCL(sclElement),
82+
},
83+
];
84+
}

src/compas/private.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { SCL_NAMESPACE } from "../schemas.js";
2+
3+
export const COMPAS_NAMESPACE = 'https://www.lfenergy.org/compas/extension/v1';
4+
export const COMPAS_PREFIX = 'compas';
5+
export const COMPAS_SCL_PRIVATE_TYPE = 'compas_scl';
6+
7+
export function getPrivate(element: Element, type: string): Element | null {
8+
return element.querySelector(`Private[type="${type}"]`);
9+
}
10+
11+
export function createPrivate(parent: Element, type: string): Element {
12+
const privateElement = parent.ownerDocument.createElementNS(SCL_NAMESPACE, "Private");
13+
privateElement.setAttribute('type', type);
14+
return privateElement;
15+
}
16+
17+
export function getCompasSclName(element: Element): Element | null {
18+
const privateElement = getPrivate(element, COMPAS_SCL_PRIVATE_TYPE);
19+
return privateElement ? privateElement.querySelector(`SclName`) : null;
20+
}
21+
22+
export function createCompasSclName(parent: Element, value: string): Element {
23+
// Make sure the prefix is available.
24+
addPrefixAndNamespaceToDocument(parent, COMPAS_NAMESPACE, COMPAS_PREFIX);
25+
26+
const newSclNameElement = parent.ownerDocument.createElementNS(COMPAS_NAMESPACE, COMPAS_PREFIX + ":SclName");
27+
newSclNameElement.textContent = value;
28+
return newSclNameElement;
29+
}
30+
31+
export function addPrefixAndNamespaceToDocument(element: Element, namespace: string, prefix: string) : void {
32+
const rootElement = element.ownerDocument.firstElementChild!;
33+
if (!rootElement.hasAttribute('xmlns:' + prefix)) {
34+
rootElement.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:' + prefix, namespace);
35+
}
36+
}

src/translations/de.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,7 @@ export const de: Translations = {
621621
},
622622
versions: {
623623
title: '???',
624+
sclInfo: '???: {{name}}, ???: {{version}}',
624625
addVersionButton: '???',
625626
confirmRestoreTitle: "???",
626627
confirmRestore: "??? {{version}}?",
@@ -640,6 +641,10 @@ export const de: Translations = {
640641
selectOneVersionsTitle: "???",
641642
selectOneVersionsMessage: "???",
642643
},
644+
scl: {
645+
wizardTitle: '???',
646+
filenameHelper: '???',
647+
},
643648
compare: {
644649
title: '???',
645650
attributes: 'Attribute',

src/translations/en.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,7 @@ export const en = {
616616
},
617617
versions: {
618618
title: 'CoMPAS Versions',
619+
sclInfo: 'Current project - Name: {{name}}, Version: {{version}}',
619620
addVersionButton: 'Add version',
620621
confirmRestoreTitle: 'Restore version?',
621622
confirmRestore: 'Are you sure to restore version {{version}}?',
@@ -635,6 +636,10 @@ export const en = {
635636
selectOneVersionsTitle: 'Select one version?',
636637
selectOneVersionsMessage: 'Select maximum one version to compare the current project against. Currently selected: {{size}}.',
637638
},
639+
scl: {
640+
wizardTitle: 'Edit SCL',
641+
filenameHelper: 'Filename used by CoMPAS when saving to a filesystem',
642+
},
638643
compare: {
639644
title: 'Compare version {{oldVersion}} with version {{newVersion}}',
640645
attributes: 'Attributes from',

src/wizard-dialog.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -352,13 +352,15 @@ export class WizardDialog extends LitElement {
352352
style="--mdc-theme-primary: var(--mdc-theme-error)"
353353
></mwc-button>`}
354354
${this.code && page.element
355-
? html`<mwc-button
356-
slot="primaryAction"
357-
@click=${() => this.act(codeAction(page.element!))}
358-
icon="code"
359-
label="${translate('save')}"
360-
trailingIcon
361-
></mwc-button>`
355+
? (page.element.parentElement)
356+
? html`<mwc-button
357+
slot="primaryAction"
358+
@click=${() => this.act(codeAction(page.element!))}
359+
icon="code"
360+
label="${translate('save')}"
361+
trailingIcon
362+
></mwc-button>`
363+
: html ``
362364
: page.primary
363365
? html`<mwc-button
364366
slot="primaryAction"

src/wizards/wizard-library.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { createPowerTransformerWizard, editPowerTransformerWizard } from './powe
1919
import { editSubNetworkWizard } from './subnetwork.js';
2020
import { editIEDWizard } from './ied.js';
2121
import { editTrgOpsWizard } from './trgops.js';
22+
import { editCompasSCLWizard } from "../compas-wizards/scl.js";
2223

2324
type SclElementWizard = (element: Element) => Wizard | undefined;
2425

@@ -398,7 +399,7 @@ export const wizards: Record<
398399
create: emptyWizard,
399400
},
400401
SCL: {
401-
edit: emptyWizard,
402+
edit: editCompasSCLWizard,
402403
create: emptyWizard,
403404
},
404405
SDI: {

test/integration/compas-editors/CompasVersions.test.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,21 @@ describe('compas-versions-plugin', () => {
1919
'compas-versions-plugin',
2020
Wizarding(Editing(CompasVersionsPlugin))
2121
);
22+
let doc: Document;
2223
let element: CompasVersionsPlugin;
2324
let stub: SinonStub;
2425

26+
beforeEach(async () => {
27+
doc = await fetch('/test/testfiles/compas/test-scd.cid')
28+
.then(response => response.text())
29+
.then(str => new DOMParser().parseFromString(str, 'application/xml'));
30+
})
31+
2532
describe('no-compas-document', () => {
2633
beforeEach(async () => {
2734
element = fixtureSync(html`
28-
<compas-versions-plugin></compas-versions-plugin>`);
35+
<compas-versions-plugin .doc="${doc}">
36+
</compas-versions-plugin>`);
2937

3038
stub = stubFetchResponseFunction(element, FETCH_FUNCTION, undefined, VERSION_ENTRY_ELEMENT_NAME,
3139
() => {
@@ -49,8 +57,8 @@ describe('compas-versions-plugin', () => {
4957
describe('show-loading', () => {
5058
beforeEach(async () => {
5159
element = fixtureSync(html`
52-
<compas-versions-plugin></compas-versions-plugin>`);
53-
element.docId = docId;
60+
<compas-versions-plugin .doc="${doc}" .docId="${docId}">
61+
</compas-versions-plugin>`);
5462

5563
stub = stubFetchResponseFunction(element, FETCH_FUNCTION, undefined, VERSION_ENTRY_ELEMENT_NAME,
5664
() => {
@@ -72,8 +80,8 @@ describe('compas-versions-plugin', () => {
7280
describe('no-items-in-list', () => {
7381
beforeEach(async () => {
7482
element = fixtureSync(html`
75-
<compas-versions-plugin></compas-versions-plugin>`);
76-
element.docId = docId;
83+
<compas-versions-plugin .doc="${doc}" .docId="${docId}">
84+
</compas-versions-plugin>`);
7785

7886
stub = stubFetchResponseFunction(element, FETCH_FUNCTION, undefined, VERSION_ENTRY_ELEMENT_NAME,
7987
(result: Element[]) => {
@@ -97,8 +105,8 @@ describe('compas-versions-plugin', () => {
97105
describe('items-in-list', () => {
98106
beforeEach(async () => {
99107
element = fixtureSync(html`
100-
<compas-versions-plugin></compas-versions-plugin>`);
101-
element.docId = docId;
108+
<compas-versions-plugin .doc="${doc}" .docId="${docId}">
109+
</compas-versions-plugin>`);
102110

103111
stub = stubFetchResponseFunction(element, FETCH_FUNCTION, BASIC_VERSIONS_LIST_RESPONSE, VERSION_ENTRY_ELEMENT_NAME,
104112
(result: Element[]) => {

0 commit comments

Comments
 (0)