Skip to content

Commit 45b5440

Browse files
feat(editors/publisher): add read only data set element editor (openscd#911)
* feat(editors/publisher): add read only data set element editor * refactor(editors/publisher): resolve review comments
1 parent ed0e71d commit 45b5440

19 files changed

+1640
-494
lines changed

src/editors/Publisher.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ export default class PublisherPlugin extends LitElement {
8585
}
8686
8787
.publishertypeselector {
88-
margin: 4px 8px 16px;
88+
margin: 4px 8px 8px;
8989
background-color: var(--mdc-theme-surface);
9090
width: calc(100% - 16px);
9191
justify-content: space-around;

src/editors/publisher/data-set-editor.ts

Lines changed: 67 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,63 @@ import {
44
html,
55
LitElement,
66
property,
7+
query,
8+
state,
79
TemplateResult,
810
} from 'lit-element';
9-
import { compareNames, identity } from '../../foundation.js';
11+
import { translate } from 'lit-translate';
12+
13+
import '@material/mwc-button';
14+
import '@material/mwc-list/mwc-list-item';
15+
import { Button } from '@material/mwc-button';
16+
import { ListItem } from '@material/mwc-list/mwc-list-item';
17+
18+
import './data-set-element-editor.js';
19+
import '../../filtered-list.js';
20+
import { FilteredList } from '../../filtered-list.js';
21+
22+
import { compareNames, identity, selector } from '../../foundation.js';
23+
import { styles } from './foundation.js';
1024

1125
@customElement('data-set-editor')
1226
export class DataSetEditor extends LitElement {
1327
/** The document being edited as provided to plugins by [[`OpenSCD`]]. */
1428
@property({ attribute: false })
1529
doc!: XMLDocument;
1630

17-
renderList(): TemplateResult {
31+
@state()
32+
selectedDataSet?: Element;
33+
34+
@query('.selectionlist') selectionList!: FilteredList;
35+
@query('mwc-button') selectDataSetButton!: Button;
36+
37+
private selectDataSet(evt: Event): void {
38+
const id = ((evt.target as FilteredList).selected as ListItem).value;
39+
const dataSet = this.doc.querySelector(selector('DataSet', id));
40+
41+
if (dataSet) {
42+
this.selectedDataSet = dataSet;
43+
(evt.target as FilteredList).classList.add('hidden');
44+
this.selectDataSetButton.classList.remove('hidden');
45+
}
46+
}
47+
48+
private renderElementEditorContainer(): TemplateResult {
49+
if (this.selectedDataSet)
50+
return html`<div class="elementeditorcontainer">
51+
<data-set-element-editor
52+
.element=${this.selectedDataSet}
53+
></data-set-element-editor>
54+
</div>`;
55+
56+
return html``;
57+
}
58+
59+
private renderSelectionList(): TemplateResult {
1860
return html`<filtered-list
61+
activatable
62+
@action=${this.selectDataSet}
63+
class="selectionlist"
1964
>${Array.from(this.doc.querySelectorAll('IED'))
2065
.sort(compareNames)
2166
.flatMap(ied => {
@@ -36,10 +81,10 @@ export class DataSetEditor extends LitElement {
3681
<li divider role="separator"></li>`;
3782
3883
const dataSets = Array.from(ied.querySelectorAll('DataSet')).map(
39-
reportCb =>
40-
html`<mwc-list-item twoline value="${identity(reportCb)}"
41-
><span>${reportCb.getAttribute('name')}</span
42-
><span slot="secondary">${identity(reportCb)}</span>
84+
dataSet =>
85+
html`<mwc-list-item twoline value="${identity(dataSet)}"
86+
><span>${dataSet.getAttribute('name')}</span
87+
><span slot="secondary">${identity(dataSet)}</span>
4388
</mwc-list-item>`
4489
);
4590
@@ -48,22 +93,25 @@ export class DataSetEditor extends LitElement {
4893
>`;
4994
}
5095

96+
private renderToggleButton(): TemplateResult {
97+
return html`<mwc-button
98+
outlined
99+
label="${translate('publisher.selectbutton', { type: 'DataSet' })}"
100+
@click=${() => {
101+
this.selectionList.classList.remove('hidden');
102+
this.selectDataSetButton.classList.add('hidden');
103+
}}
104+
></mwc-button>`;
105+
}
106+
51107
render(): TemplateResult {
52-
return html`${this.renderList()}`;
108+
return html`${this.renderToggleButton()}
109+
<div class="content">
110+
${this.renderSelectionList()}${this.renderElementEditorContainer()}
111+
</div>`;
53112
}
54113

55114
static styles = css`
56-
filtered-list {
57-
margin: 4px 8px 16px;
58-
background-color: var(--mdc-theme-surface);
59-
}
60-
61-
.listitem.header {
62-
font-weight: 500;
63-
}
64-
65-
mwc-list-item.hidden[noninteractive] + li[divider] {
66-
display: none;
67-
}
115+
${styles}
68116
`;
69117
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
import {
2+
css,
3+
customElement,
4+
html,
5+
LitElement,
6+
property,
7+
state,
8+
TemplateResult,
9+
} from 'lit-element';
10+
import { translate } from 'lit-translate';
11+
12+
import '@material/mwc-list/mwc-list-item';
13+
14+
import '../../wizard-textfield.js';
15+
import '../../filtered-list.js';
16+
17+
import { identity } from '../../foundation.js';
18+
19+
@customElement('data-set-element-editor')
20+
export class DataSetElementEditor extends LitElement {
21+
@property({ attribute: false })
22+
element!: Element | null;
23+
24+
@state()
25+
private get name(): string | null {
26+
return this.element ? this.element.getAttribute('name') : 'UNDEFINED';
27+
}
28+
@state()
29+
private get desc(): string | null {
30+
return this.element ? this.element.getAttribute('desc') : 'UNDEFINED';
31+
}
32+
33+
render(): TemplateResult {
34+
if (this.element)
35+
return html`<div class="content">
36+
<h2>
37+
<div>DataSet</div>
38+
<div class="headersubtitle">${identity(this.element)}</div>
39+
</h2>
40+
<wizard-textfield
41+
label="name"
42+
.maybeValue=${this.name}
43+
helper="${translate('scl.name')}"
44+
required
45+
>
46+
</wizard-textfield>
47+
<wizard-textfield
48+
label="desc"
49+
.maybeValue=${this.desc}
50+
helper="${translate('scl.desc')}"
51+
nullable
52+
>
53+
</wizard-textfield>
54+
<filtered-list
55+
>${Array.from(this.element.querySelectorAll('FCDA')).map(fcda => {
56+
const [ldInst, prefix, lnClass, lnInst, doName, daName] = [
57+
'ldInst',
58+
'prefix',
59+
'lnClass',
60+
'lnInst',
61+
'doName',
62+
'daName',
63+
].map(attributeName => fcda.getAttribute(attributeName) ?? '');
64+
65+
return html`<mwc-list-item
66+
selected
67+
twoline
68+
value="${identity(fcda)}"
69+
><span>${doName + '.' + daName}</span
70+
><span slot="secondary"
71+
>${ldInst + '/' + prefix + lnClass + lnInst}</span
72+
>
73+
</mwc-list-item>`;
74+
})}</filtered-list
75+
>
76+
</div>`;
77+
78+
return html`<div class="content">
79+
<h2>${translate('publisher.nodataset')}</h2>
80+
</div>`;
81+
}
82+
83+
static styles = css`
84+
.content {
85+
display: flex;
86+
flex-direction: column;
87+
background-color: var(--mdc-theme-surface);
88+
}
89+
90+
.content > * {
91+
display: block;
92+
margin: 4px 8px 16px;
93+
}
94+
95+
h2 {
96+
color: var(--mdc-theme-on-surface);
97+
font-family: 'Roboto', sans-serif;
98+
font-weight: 300;
99+
100+
margin: 0px;
101+
padding-left: 0.3em;
102+
transition: background-color 150ms linear;
103+
}
104+
105+
.headersubtitle {
106+
font-size: 16px;
107+
font-weight: 200;
108+
overflow: hidden;
109+
white-space: nowrap;
110+
text-overflow: ellipsis;
111+
}
112+
113+
*[iconTrailing='search'] {
114+
--mdc-shape-small: 28px;
115+
}
116+
`;
117+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { css } from 'lit-element';
2+
3+
export const styles = css`
4+
.content {
5+
display: flex;
6+
height: calc(100vh - 184px);
7+
}
8+
9+
.selectionlist {
10+
flex: 35%;
11+
margin: 4px 4px 4px 8px;
12+
background-color: var(--mdc-theme-surface);
13+
overflow-y: scroll;
14+
}
15+
16+
.elementeditorcontainer {
17+
flex: 65%;
18+
margin: 4px 8px 4px 4px;
19+
background-color: var(--mdc-theme-surface);
20+
overflow-y: scroll;
21+
display: flex;
22+
}
23+
24+
data-set-element-editor {
25+
width: calc(100% - 6px);
26+
}
27+
28+
.listitem.header {
29+
font-weight: 500;
30+
}
31+
32+
mwc-list-item.hidden[noninteractive] + li[divider] {
33+
display: none;
34+
}
35+
36+
mwc-button {
37+
display: none;
38+
}
39+
40+
@media (max-width: 599px) {
41+
.content {
42+
height: 100%;
43+
}
44+
45+
.selectionlist {
46+
position: absolute;
47+
width: calc(100% - 32px);
48+
height: auto;
49+
top: 110px;
50+
left: 8px;
51+
background-color: var(--mdc-theme-surface);
52+
z-index: 1;
53+
box-shadow: 0 8px 10px 1px rgba(0, 0, 0, 0.14),
54+
0 3px 14px 2px rgba(0, 0, 0, 0.12), 0 5px 5px -3px rgba(0, 0, 0, 0.2);
55+
}
56+
57+
data-set-element-editor {
58+
width: calc(100% - 16px);
59+
}
60+
61+
.selectionlist.hidden {
62+
display: none;
63+
}
64+
65+
mwc-button {
66+
display: flex;
67+
margin: 4px 8px 8px;
68+
}
69+
}
70+
`;

0 commit comments

Comments
 (0)