Skip to content

Commit 2b11ae8

Browse files
feat(wizard-checkbox): web component for xs:boolean XML attributes (openscd#537)
* feat(wizard-checkbox): web component for xs:boolean attributes * feat(foundation): add wizard-checkbox to WizardInputs * refactor(wizard/gsecontrol): use wizard-checkbox * refactor(wizard-checkbox): improvements triggered by review * refactor(wizard/optfields): use wizard-checkbox * refactor(wizard/trgops): use wizard-checkbox * refactor(wizard/reportcontrol): use wizard-checkbox * refactor(wizard/sampledvaluecontrol): use wizard-checkbox * refactor(wizard/da,bda): use wizard-checkbox * refactor(editors/template/lnodetype): use wizard-checkbox * refactor(wizards/abstractda): use wizard-checkbox * refactor(wizards/foundation): remove unused function
1 parent 02b8d97 commit 2b11ae8

31 files changed

+397
-801
lines changed

src/editors/templates/foundation.ts

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -105,19 +105,6 @@ export function addReferencedDataTypes(
105105
return actions;
106106
}
107107

108-
export function buildListFromStringArray(
109-
list: (string | null)[],
110-
selected: string | null
111-
): TemplateResult[] {
112-
return list.map(
113-
item => html`<mwc-list-item
114-
value=${ifDefined(item === null ? undefined : item)}
115-
?selected=${item === selected}
116-
>${item}</mwc-list-item
117-
>`
118-
);
119-
}
120-
121108
/** Common `CSS` styles used by DataTypeTemplate subeditors */
122109
export const styles = css`
123110
:host(.moving) section {

src/editors/templates/lnodetype-wizard.ts

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { ListItem } from '@material/mwc-list/mwc-list-item';
1010
import { Select } from '@material/mwc-select';
1111
import { SingleSelectedEvent } from '@material/mwc-list/mwc-list-foundation';
1212

13+
import '../../wizard-checkbox.js';
1314
import '../../wizard-textfield.js';
1415
import '../../wizard-select.js';
1516
import {
@@ -33,7 +34,6 @@ import { WizardSelect } from '../../wizard-select.js';
3334
import {
3435
addReferencedDataTypes,
3536
allDataTypeSelector,
36-
buildListFromStringArray,
3737
CreateOptions,
3838
unifyCreateActionArray,
3939
UpdateOptions,
@@ -127,7 +127,7 @@ function dOWizard(options: WizardOptions): Wizard | undefined {
127127
name,
128128
desc,
129129
accessControl,
130-
transientList,
130+
transient,
131131
] = DO
132132
? [
133133
get('do.wizard.title.edit'),
@@ -154,10 +154,7 @@ function dOWizard(options: WizardOptions): Wizard | undefined {
154154
DO.getAttribute('name'),
155155
DO.getAttribute('desc'),
156156
DO.getAttribute('accessControl'),
157-
buildListFromStringArray(
158-
[null, 'true', 'false'],
159-
DO.getAttribute('transient')
160-
),
157+
DO.getAttribute('transient'),
161158
]
162159
: [
163160
get('do.wizard.title.add'),
@@ -167,7 +164,7 @@ function dOWizard(options: WizardOptions): Wizard | undefined {
167164
'',
168165
null,
169166
null,
170-
buildListFromStringArray([null, 'true', 'false'], null),
167+
null,
171168
];
172169

173170
const types = Array.from(doc.querySelectorAll('DOType'))
@@ -219,12 +216,12 @@ function dOWizard(options: WizardOptions): Wizard | undefined {
219216
nullable
220217
pattern="${patterns.normalizedString}"
221218
></wizard-textfield>`,
222-
html`<mwc-select
223-
fixedMenuPosition
219+
html`<wizard-checkbox
224220
label="transient"
221+
.maybeValue="${transient}"
225222
helper="${translate('scl.transient')}"
226-
>${transientList}</mwc-select
227-
>`,
223+
nullable
224+
></wizard-checkbox>`,
228225
],
229226
},
230227
];
@@ -335,7 +332,7 @@ function createLNodeTypeHelperWizard(
335332
.maybeValue=${null}
336333
>${validDOTypes.map(
337334
doType =>
338-
html`<mwc-list-item value="${doType.getAttribute('id')}"
335+
html`<mwc-list-item value="${doType.getAttribute('id')!}"
339336
>${doType.getAttribute('id')}</mwc-list-item
340337
>`
341338
)}</wizard-select

src/foundation.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import AceEditor from 'ace-custom-element';
88

99
import { WizardTextField } from './wizard-textfield.js';
1010
import { WizardSelect } from './wizard-select.js';
11+
import { WizardCheckbox } from './wizard-checkbox.js';
1112

1213
export type SimpleAction = Create | Update | Delete | Move;
1314
export type ComplexAction = {
@@ -133,7 +134,7 @@ export function newActionEvent<T extends EditorAction>(
133134
}
134135

135136
export const wizardInputSelector =
136-
'wizard-textfield, mwc-textfield, ace-editor, mwc-select,wizard-select';
137+
'wizard-textfield, mwc-textfield, ace-editor, mwc-select,wizard-select, wizard-checkbox';
137138
export type WizardInput =
138139
| WizardTextField
139140
| TextField
@@ -173,7 +174,11 @@ export function reportValidity(input: WizardInput): boolean {
173174

174175
/** @returns the `value` or `maybeValue` of `input` depending on type. */
175176
export function getValue(input: WizardInput): string | null {
176-
if (input instanceof WizardTextField || input instanceof WizardSelect)
177+
if (
178+
input instanceof WizardTextField ||
179+
input instanceof WizardSelect ||
180+
input instanceof WizardCheckbox
181+
)
177182
return input.maybeValue;
178183
else return input.value ?? null;
179184
}

src/wizard-checkbox.ts

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
import {
2+
customElement,
3+
html,
4+
LitElement,
5+
property,
6+
query,
7+
state,
8+
TemplateResult,
9+
} from 'lit-element';
10+
11+
import '@material/mwc-formfield';
12+
import '@material/mwc-switch';
13+
import '@material/mwc-checkbox';
14+
import { Checkbox } from '@material/mwc-checkbox';
15+
import { Switch } from '@material/mwc-switch';
16+
17+
/** A potentially `nullable` labelled checkbox. */
18+
@customElement('wizard-checkbox')
19+
export class WizardCheckbox extends LitElement {
20+
@property({ type: String })
21+
label = '';
22+
/** Parenthetical information rendered after the label: `label (helper)` */
23+
@property({ type: String })
24+
helper = '';
25+
/** Whether [[`maybeValue`]] may be `null` */
26+
@property({ type: Boolean })
27+
nullable = false;
28+
/** The default `checked` state while [[`maybeValue`]] is `null`. */
29+
@property({ type: Boolean })
30+
defaultChecked = false;
31+
/** Is `"true"` when checked, `"false"` un-checked, `null` if [[`nullable`]]. */
32+
@property({ type: String })
33+
get maybeValue(): string | null {
34+
return this.null ? null : this.checked ? 'true' : 'false';
35+
}
36+
set maybeValue(check: string | null) {
37+
if (check === null) this.null = true;
38+
else {
39+
this.null = false;
40+
this.checked = check === 'true' ? true : false;
41+
}
42+
}
43+
44+
private isNull = false;
45+
46+
@state()
47+
private get null(): boolean {
48+
return this.nullable && this.isNull;
49+
}
50+
private set null(value: boolean) {
51+
if (!this.nullable || value === this.isNull) return;
52+
this.isNull = value;
53+
if (this.null) this.disable();
54+
else this.enable();
55+
}
56+
57+
private initChecked = false;
58+
59+
@state()
60+
get checked(): boolean {
61+
return this.checkbox?.checked ?? this.initChecked;
62+
}
63+
set checked(value: boolean) {
64+
if (this.checkbox) this.checkbox.checked = value;
65+
else this.initChecked = value;
66+
}
67+
68+
@state()
69+
disabled = false;
70+
@state()
71+
get formfieldLabel(): string {
72+
return this.helper ? `${this.label} (${this.helper})` : this.label;
73+
}
74+
75+
@query('mwc-switch') nullSwitch?: Switch;
76+
@query('mwc-checkbox') checkbox?: Checkbox;
77+
78+
private nulled: boolean | null = null;
79+
80+
private enable(): void {
81+
if (this.nulled === null) return;
82+
this.checked = this.nulled;
83+
this.nulled = null;
84+
this.disabled = false;
85+
}
86+
87+
private disable(): void {
88+
if (this.nulled !== null) return;
89+
this.nulled = this.checked;
90+
this.checked = this.defaultChecked;
91+
this.disabled = true;
92+
}
93+
94+
firstUpdated(): void {
95+
this.requestUpdate();
96+
}
97+
98+
renderSwitch(): TemplateResult {
99+
if (this.nullable) {
100+
return html`<mwc-switch
101+
style="margin-left: 12px;"
102+
?checked=${!this.null}
103+
@change=${() => {
104+
this.null = !this.nullSwitch!.checked;
105+
}}
106+
></mwc-switch>`;
107+
}
108+
return html``;
109+
}
110+
111+
render(): TemplateResult {
112+
return html`
113+
<div style="display: flex; flex-direction: row;">
114+
<div style="flex: auto;">
115+
<mwc-formfield
116+
label="${this.formfieldLabel}"
117+
style="${this.disabled
118+
? `--mdc-theme-text-primary-on-background:rgba(0, 0, 0, 0.38)`
119+
: ``}"
120+
><mwc-checkbox
121+
?checked=${this.initChecked}
122+
?disabled=${this.disabled}
123+
></mwc-checkbox
124+
></mwc-formfield>
125+
</div>
126+
<div style="display: flex; align-items: center;">
127+
${this.renderSwitch()}
128+
</div>
129+
</div>
130+
`;
131+
}
132+
}

src/wizards/abstractda.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { ListItem } from '@material/mwc-list/mwc-list-item';
66
import { SelectedEvent } from '@material/mwc-list/mwc-list-foundation';
77
import { Select } from '@material/mwc-select';
88

9+
import '../wizard-checkbox.js';
910
import '../wizard-select.js';
1011
import '../wizard-textfield.js';
1112
import { createElement, EditorAction } from '../foundation.js';
@@ -173,20 +174,13 @@ export function wizardContent(
173174
>`
174175
)}</wizard-select
175176
>`,
176-
html`<wizard-select
177+
html`<wizard-checkbox
177178
label="valImport"
178179
.maybeValue=${valImport}
179180
helper="${translate('scl.valImport')}"
180181
nullable
181182
required
182-
fixedMenuPosition
183-
>${['true', 'false'].map(
184-
valImportOption =>
185-
html`<mwc-list-item value="${valImportOption}"
186-
>${valImportOption}</mwc-list-item
187-
>`
188-
)}</wizard-select
189-
>`,
183+
></wizard-checkbox>`,
190184
html`<wizard-select
191185
label="Val"
192186
.maybeValue=${Val}

src/wizards/da.ts

Lines changed: 10 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { get, translate } from 'lit-translate';
44
import '@material/mwc-button';
55
import '@material/mwc-list/mwc-list-item';
66

7+
import '../wizard-checkbox.js';
78
import '../wizard-select.js';
89
import {
910
cloneElement,
@@ -38,42 +39,24 @@ export function renderDa(
3839
html`<mwc-list-item value="${fcOption}">${fcOption}</mwc-list-item>`
3940
)}</wizard-select
4041
>`,
41-
html`<wizard-select
42+
html`<wizard-checkbox
4243
label="dchg"
4344
.maybeValue=${dchg}
44-
helper="${translate('scl.valImport')}"
45+
helper="${translate('scl.dchg')}"
4546
nullable
46-
required
47-
fixedMenuPosition
48-
>${['true', 'false'].map(
49-
option =>
50-
html`<mwc-list-item value="${option}">${option}</mwc-list-item>`
51-
)}</wizard-select
52-
>`,
53-
html`<wizard-select
47+
></wizard-checkbox>`,
48+
html`<wizard-checkbox
5449
label="qchg"
5550
.maybeValue=${qchg}
56-
helper="${translate('scl.valImport')}"
51+
helper="${translate('scl.qchg')}"
5752
nullable
58-
required
59-
fixedMenuPosition
60-
>${['true', 'false'].map(
61-
option =>
62-
html`<mwc-list-item value="${option}">${option}</mwc-list-item>`
63-
)}</wizard-select
64-
>`,
65-
html`<wizard-select
53+
></wizard-checkbox>`,
54+
html`<wizard-checkbox
6655
label="dupd"
6756
.maybeValue=${dupd}
68-
helper="${translate('scl.valImport')}"
57+
helper="${translate('scl.dupd')}"
6958
nullable
70-
required
71-
fixedMenuPosition
72-
>${['true', 'false'].map(
73-
option =>
74-
html`<mwc-list-item value="${option}">${option}</mwc-list-item>`
75-
)}</wizard-select
76-
>`,
59+
></wizard-checkbox>`,
7760
];
7861
}
7962

src/wizards/gsecontrol.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { ListItem } from '@material/mwc-list/mwc-list-item';
88
import { SingleSelectedEvent } from '@material/mwc-list/mwc-list-foundation';
99

1010
import '../filtered-list.js';
11+
import '../wizard-checkbox.js';
1112
import '../wizard-select.js';
1213
import '../wizard-textfield.js';
1314
import {
@@ -86,16 +87,12 @@ export function renderGseAttributes(
8687
required
8788
validationMessage="${translate('textfield.nonempty')}"
8889
></wizard-textfield>`,
89-
html`<wizard-select
90+
html`<wizard-checkbox
9091
label="fixedOffs"
9192
.maybeValue=${fixedOffs}
9293
nullable
93-
required
9494
helper="${translate('scl.fixedOffs')}"
95-
>${['true', 'false'].map(
96-
type => html`<mwc-list-item value="${type}">${type}</mwc-list-item>`
97-
)}</wizard-select
98-
>`,
95+
></wizard-checkbox>`,
9996
html`<wizard-select
10097
label="securityEnabled"
10198
.maybeValue=${securityEnabled}

src/wizards/optfields.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { get } from 'lit-translate';
33

44
import '@material/mwc-list/mwc-list-item';
55

6+
import '../wizard-checkbox.js';
67
import '../wizard-select.js';
78
import {
89
cloneElement,
@@ -73,16 +74,12 @@ export function editOptFieldsWizard(element: Element): Wizard {
7374
},
7475
content: optFields.map(
7576
optField =>
76-
html`<wizard-select
77+
html`<wizard-checkbox
7778
label="${optField}"
7879
.maybeValue=${element.getAttribute(optField)}
7980
nullable
8081
required
81-
>${['true', 'false'].map(
82-
option =>
83-
html`<mwc-list-item value="${option}">${option}</mwc-list-item>`
84-
)}</wizard-select
85-
>`
82+
></wizard-checkbox>`
8683
),
8784
},
8885
];

0 commit comments

Comments
 (0)