From 50abca9dfeb56c701d875c71d70ef865779d8cb2 Mon Sep 17 00:00:00 2001 From: Flurb Date: Wed, 19 Jan 2022 14:04:07 +0100 Subject: [PATCH 01/42] Implemented adding document to localStorage --- src/Divider.ts | 22 +++++ src/NsdItem.ts | 33 +++++++ src/Setting.ts | 83 ++++++++++++++++++ src/translations/de.ts | 2 + src/translations/en.ts | 2 + .../__snapshots__/open-scd.test.snap.js | 86 +++++++++++++++++++ 6 files changed, 228 insertions(+) create mode 100644 src/Divider.ts create mode 100644 src/NsdItem.ts diff --git a/src/Divider.ts b/src/Divider.ts new file mode 100644 index 000000000..babe96356 --- /dev/null +++ b/src/Divider.ts @@ -0,0 +1,22 @@ +import {css, customElement, html, LitElement, TemplateResult} from "lit-element"; + +@customElement('openscd-divider') +export class DividerElement extends LitElement { + render(): TemplateResult { + return html ` +
+ ` + } + + static styles = css` + div { + height: 0px; + margin: 10px 0px 10px 0px; + border-top: none; + border-right: none; + border-left: none; + border-image: initial; + border-bottom: 1px solid rgba(0, 0, 0, 0.12); + } + ` +} diff --git a/src/NsdItem.ts b/src/NsdItem.ts new file mode 100644 index 000000000..cf73f648d --- /dev/null +++ b/src/NsdItem.ts @@ -0,0 +1,33 @@ +import { + css, + customElement, + html, + LitElement, + property, + TemplateResult, +} from 'lit-element'; + +@customElement('nsd-item') +export class AccessPointContainer extends LitElement { + @property({ attribute: false }) + nsdDocument!: Document; + + @property() + nsdId!: string; + + private onDeleteClick(): void { + console.log('check'); + } + + render(): TemplateResult { + return html` + ${this.nsdId} + ${this.nsdDocument ? html`done` : + html`close`} + ${this.nsdDocument ? html` this.onDeleteClick()}>delete` : + html``} + `; + } + + static styles = css``; +} diff --git a/src/Setting.ts b/src/Setting.ts index f587816c2..fb2fb37b6 100644 --- a/src/Setting.ts +++ b/src/Setting.ts @@ -15,17 +15,28 @@ import { ifImplemented, LitElementConstructor, Mixin } from './foundation.js'; import { Language, languages, loader } from './translations/loader.js'; import { WizardDialog } from './wizard-dialog.js'; +import './Divider.js'; +import './NsdItem.js'; + export type Settings = { language: Language; theme: 'light' | 'dark'; mode: 'safe' | 'pro'; showieds: 'on' | 'off'; + 'IEC 61850-7-2': Document | undefined; + 'IEC 61850-7-3': Document | undefined; + 'IEC 61850-7-4': Document | undefined; + 'IEC 61850-8-1': Document | undefined; }; export const defaults: Settings = { language: 'en', theme: 'light', mode: 'safe', showieds: 'off', + 'IEC 61850-7-2': undefined, + 'IEC 61850-7-3': undefined, + 'IEC 61850-7-4': undefined, + 'IEC 61850-8-1': undefined, }; /** Mixin that saves [[`Settings`]] to `localStorage`, reflecting them in the @@ -42,6 +53,10 @@ export function Setting(Base: TBase) { theme: this.getSetting('theme'), mode: this.getSetting('mode'), showieds: this.getSetting('showieds'), + 'IEC 61850-7-2': this.getSetting('IEC 61850-7-2'), + 'IEC 61850-7-3': this.getSetting('IEC 61850-7-3'), + 'IEC 61850-7-4': this.getSetting('IEC 61850-7-4'), + 'IEC 61850-8-1': this.getSetting('IEC 61850-8-1') }; } @@ -61,6 +76,7 @@ export function Setting(Base: TBase) { localStorage.getItem(setting) ?? defaults[setting] ); } + /** Update the `value` of `setting`, storing to `localStorage`. */ setSetting(setting: T, value: Settings[T]): void { localStorage.setItem(setting, (value)); @@ -90,6 +106,50 @@ export function Setting(Base: TBase) { if (changedProperties.has('settings')) use(this.settings.language); } + private renderFileSelect(): TemplateResult { + return html ` + this.updateNsdSettings(evt)}> + { + const input = this.shadowRoot!.querySelector("#nsd-file"); + console.log(input) + input?.click(); + }}> + + `; + } + + private async updateNsdSettings(evt: Event): Promise { + const file = (evt.target)?.files?.item(0) ?? false; + if (!file) return; + + const text = await file.text(); + const doc = new DOMParser().parseFromString(text, 'application/xml'); + const id = doc.querySelector('NSDoc')?.getAttribute('id'); + if (!id) return; + + switch (id) { + case 'IEC 61850-7-2': { + this.setSetting('IEC 61850-7-2', doc); + break; + } + case 'IEC 61850-7-3': { + this.setSetting('IEC 61850-7-3', doc); + break; + } + case 'IEC 61850-7-4': { + this.setSetting('IEC 61850-7-4', doc); + break; + } + case 'IEC 61850-8-1': { + this.setSetting('IEC 61850-8-1', doc); + break; + } + } + this.requestUpdate(); + } + constructor(...params: any[]) { super(...params); @@ -140,6 +200,29 @@ export function Setting(Base: TBase) { > + +
+

${translate('settings.loadNsdTranslations')}

+ ${this.renderFileSelect()} +
+ + + + + + ${translate('cancel')} diff --git a/src/translations/de.ts b/src/translations/de.ts index 3d4a5c596..8d9109da7 100644 --- a/src/translations/de.ts +++ b/src/translations/de.ts @@ -42,6 +42,8 @@ export const de: Translations = { dark: 'Dunkles Design', mode: 'Profimodus', showieds: 'Zeige IEDs im Substation-Editor', + selectFileButton: '???', + loadNsdTranslations: '???' }, menu: { new: 'Neues projekt', diff --git a/src/translations/en.ts b/src/translations/en.ts index 0f2698340..fb822717d 100644 --- a/src/translations/en.ts +++ b/src/translations/en.ts @@ -40,6 +40,8 @@ export const en = { dark: 'Dark theme', mode: 'Pro mode', showieds: 'Show IEDs in substation editor', + selectFileButton: 'Select file', + loadNsdTranslations: 'Load .nsdoc' }, menu: { new: 'New project', diff --git a/test/integration/__snapshots__/open-scd.test.snap.js b/test/integration/__snapshots__/open-scd.test.snap.js index 4f1d294bd..e28f27167 100644 --- a/test/integration/__snapshots__/open-scd.test.snap.js +++ b/test/integration/__snapshots__/open-scd.test.snap.js @@ -1077,6 +1077,92 @@ snapshots["open-scd looks like its snapshot"] = + + +
+

+ Load .nsdoc +

+ + + +
+ + + + 61850-7-2 + + + close + + + + + 61850-7-3 + + + close + + + + + 61850-7-4 + + + close + + + delete + + + + + 61850-8-1 + + + close + + + Date: Wed, 19 Jan 2022 23:35:22 +0100 Subject: [PATCH 02/42] Refactor --- src/NsdItem.ts | 33 ---- src/Setting.ts | 163 +++++++++--------- src/themes.ts | 8 +- src/zeroline-pane.ts | 4 +- .../__snapshots__/open-scd.test.snap.js | 24 +-- 5 files changed, 103 insertions(+), 129 deletions(-) delete mode 100644 src/NsdItem.ts diff --git a/src/NsdItem.ts b/src/NsdItem.ts deleted file mode 100644 index cf73f648d..000000000 --- a/src/NsdItem.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { - css, - customElement, - html, - LitElement, - property, - TemplateResult, -} from 'lit-element'; - -@customElement('nsd-item') -export class AccessPointContainer extends LitElement { - @property({ attribute: false }) - nsdDocument!: Document; - - @property() - nsdId!: string; - - private onDeleteClick(): void { - console.log('check'); - } - - render(): TemplateResult { - return html` - ${this.nsdId} - ${this.nsdDocument ? html`done` : - html`close`} - ${this.nsdDocument ? html` this.onDeleteClick()}>delete` : - html``} - `; - } - - static styles = css``; -} diff --git a/src/Setting.ts b/src/Setting.ts index fb2fb37b6..30f5e4117 100644 --- a/src/Setting.ts +++ b/src/Setting.ts @@ -16,9 +16,8 @@ import { Language, languages, loader } from './translations/loader.js'; import { WizardDialog } from './wizard-dialog.js'; import './Divider.js'; -import './NsdItem.js'; -export type Settings = { +export type SettingsRecord = { language: Language; theme: 'light' | 'dark'; mode: 'safe' | 'pro'; @@ -28,26 +27,11 @@ export type Settings = { 'IEC 61850-7-4': Document | undefined; 'IEC 61850-8-1': Document | undefined; }; -export const defaults: Settings = { - language: 'en', - theme: 'light', - mode: 'safe', - showieds: 'off', - 'IEC 61850-7-2': undefined, - 'IEC 61850-7-3': undefined, - 'IEC 61850-7-4': undefined, - 'IEC 61850-8-1': undefined, -}; - -/** Mixin that saves [[`Settings`]] to `localStorage`, reflecting them in the - * `settings` property, setting them through `setSetting(setting, value)`. */ -export type SettingElement = Mixin; -export function Setting(Base: TBase) { - class SettingElement extends Base { - /** Current [[`Settings`]] in `localStorage`, default to [[`defaults`]]. */ - @property() - get settings(): Settings { +export function Settings() { + return { + /** Current [[`CompasSettings`]] in `localStorage`, default to [[`defaults`]]. */ + get settings(): SettingsRecord { return { language: this.getSetting('language'), theme: this.getSetting('theme'), @@ -58,6 +42,49 @@ export function Setting(Base: TBase) { 'IEC 61850-7-4': this.getSetting('IEC 61850-7-4'), 'IEC 61850-8-1': this.getSetting('IEC 61850-8-1') }; + }, + + get defaultSettings(): SettingsRecord { + return { + language: 'en', + theme: 'light', + mode: 'safe', + showieds: 'off', + 'IEC 61850-7-2': undefined, + 'IEC 61850-7-3': undefined, + 'IEC 61850-7-4': undefined, + 'IEC 61850-8-1': undefined + } + }, + + /** Update the `value` of `setting`, storing to `localStorage`. */ + setSetting(setting: T, value: SettingsRecord[T]): void { + localStorage.setItem(setting, (value)); + }, + + /** Update the `value` of `setting`, storing to `localStorage`. */ + removeSetting(setting: T): void { + localStorage.removeItem(setting); + }, + + getSetting(setting: T): SettingsRecord[T] { + return ( + localStorage.getItem(setting) ?? this.defaultSettings[setting] + ); + } + } +} + +/** Mixin that saves [[`Settings`]] to `localStorage`, reflecting them in the + * `settings` property, setting them through `setSetting(setting, value)`. */ +export type SettingElement = Mixin; + +export function Setting(Base: TBase) { + class SettingElement extends Base { + /** Current [[`Settings`]] in `localStorage`, default to [[`defaults`]]. */ + @property() + get settings(): SettingsRecord { + return Settings().settings; } @query('#settings') @@ -71,20 +98,8 @@ export function Setting(Base: TBase) { @query('#showieds') showiedsUI!: Switch; - private getSetting(setting: T): Settings[T] { - return ( - localStorage.getItem(setting) ?? defaults[setting] - ); - } - - /** Update the `value` of `setting`, storing to `localStorage`. */ - setSetting(setting: T, value: Settings[T]): void { - localStorage.setItem(setting, (value)); - this.shadowRoot - ?.querySelector('wizard-dialog') - ?.requestUpdate(); - this.requestUpdate(); - } + @query('#nsdoc-file') + private nsdocFileUI!: HTMLInputElement; private onClosing(ae: CustomEvent<{ action: string } | null>): void { if (ae.detail?.action === 'reset') { @@ -93,10 +108,10 @@ export function Setting(Base: TBase) { ); this.requestUpdate('settings'); } else if (ae.detail?.action === 'save') { - this.setSetting('language', this.languageUI.value); - this.setSetting('theme', this.darkThemeUI.checked ? 'dark' : 'light'); - this.setSetting('mode', this.modeUI.checked ? 'pro' : 'safe'); - this.setSetting('showieds', this.showiedsUI.checked ? 'on' : 'off'); + Settings().setSetting('language', this.languageUI.value); + Settings().setSetting('theme', this.darkThemeUI.checked ? 'dark' : 'light'); + Settings().setSetting('mode', this.modeUI.checked ? 'pro' : 'safe'); + Settings().setSetting('showieds', this.showiedsUI.checked ? 'on' : 'off'); this.requestUpdate('settings'); } } @@ -108,19 +123,18 @@ export function Setting(Base: TBase) { private renderFileSelect(): TemplateResult { return html ` - this.updateNsdSettings(evt)}> + this.loadNsdocFile(evt)}> { - const input = this.shadowRoot!.querySelector("#nsd-file"); - console.log(input) + const input = this.shadowRoot!.querySelector("#nsdoc-file"); input?.click(); }}> `; } - private async updateNsdSettings(evt: Event): Promise { + private async loadNsdocFile(evt: Event): Promise { const file = (evt.target)?.files?.item(0) ?? false; if (!file) return; @@ -129,27 +143,32 @@ export function Setting(Base: TBase) { const id = doc.querySelector('NSDoc')?.getAttribute('id'); if (!id) return; - switch (id) { - case 'IEC 61850-7-2': { - this.setSetting('IEC 61850-7-2', doc); - break; - } - case 'IEC 61850-7-3': { - this.setSetting('IEC 61850-7-3', doc); - break; - } - case 'IEC 61850-7-4': { - this.setSetting('IEC 61850-7-4', doc); - break; - } - case 'IEC 61850-8-1': { - this.setSetting('IEC 61850-8-1', doc); - break; - } - } + Settings().setSetting(id as keyof SettingsRecord, doc); + + this.nsdocFileUI.onchange = null; this.requestUpdate(); } + /** + * Render one .nsdoc item in the Settings wizard + * @param key - The key of the nsdoc file in the settings. + * @returns a .nsdoc item for the Settings wizard + */ + private renderNsdocItem(key: T): TemplateResult { + const nsd = this.settings[key]; + + return html` + ${key} + ${nsd ? html`done` : + html`close`} + ${nsd ? html` { + Settings().removeSetting(key); + this.requestUpdate(); + }}>delete` : + html``} + `; + } + constructor(...params: any[]) { super(...params); @@ -206,22 +225,10 @@ export function Setting(Base: TBase) { ${this.renderFileSelect()} - - - - + ${this.renderNsdocItem('IEC 61850-7-2')} + ${this.renderNsdocItem('IEC 61850-7-3')} + ${this.renderNsdocItem('IEC 61850-7-4')} + ${this.renderNsdocItem('IEC 61850-8-1')} ${translate('cancel')} diff --git a/src/themes.ts b/src/themes.ts index 74b812711..ce214bbea 100644 --- a/src/themes.ts +++ b/src/themes.ts @@ -1,7 +1,7 @@ import { html, TemplateResult } from 'lit-element'; -import { Settings } from './Setting.js'; +import { SettingsRecord } from './Setting.js'; -export function getTheme(theme: Settings['theme']): TemplateResult { +export function getTheme(theme: SettingsRecord['theme']): TemplateResult { document.body.style.cssText = bodyStyles[theme]; return html` ${themes[theme]} @@ -61,12 +61,12 @@ export function getTheme(theme: Settings['theme']): TemplateResult { `; } -const bodyStyles: Record = { +const bodyStyles: Record = { dark: 'background: #073642', light: 'background: #eee8d5', }; -const themes: Record = { +const themes: Record = { light: html`