Skip to content

Commit c866ab8

Browse files
committed
wip: add rendering of single elements
1 parent ca3909a commit c866ab8

File tree

2 files changed

+162
-23
lines changed

2 files changed

+162
-23
lines changed

demo/index.html

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,16 @@
33
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@300&family=Roboto:wght@300;400;500&display=swap">
44
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Symbols+Outlined">
55

6-
<oscd-diff></oscd-diff>
7-
8-
<hr>
9-
10-
<label for="scl1">SCL file 1</label>
6+
<label for="scl1">SCL files</label>
117
<input type="file" id="scl1" name="scl1" accept="application/xml" multiple />
128

139
<hr>
1410

1511
<div id="result">
1612
</div>
1713

14+
<oscd-diff></oscd-diff>
15+
1816
<script type="module">
1917
import OpenSCDDiffElement from "../dist/oscd-diff.js"
2018
customElements.define('oscd-diff', OpenSCDDiffElement);

diff-tree.ts

Lines changed: 159 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
1-
import { LitElement, html, nothing } from "lit";
1+
import { LitElement, html, css, nothing } from "lit";
22
import { customElement, property, query } from "lit/decorators.js";
33
import { identity, find } from "@openenergytools/scl-lib";
44

55
import "@material/web/all.js";
66

77
import type { newHasher } from "./hash.js";
88

9+
function filterObject(
10+
obj: object,
11+
predicate: (entry: [string, any]) => boolean,
12+
) {
13+
return Object.fromEntries(Object.entries(obj).filter(predicate));
14+
}
15+
916
type Description = Record<string, string | string[]> & {
1017
eNS?: Record<string, Record<string, string>>;
1118
};
@@ -107,7 +114,7 @@ export class DiffTree extends LitElement {
107114
}
108115

109116
get diff(): Record<string, { ours?: any; theirs?: any }> {
110-
return getDiff(this.ourDescription!, this.theirDescription!);
117+
return getDiff(this.ourDescription ?? {}, this.theirDescription ?? {});
111118
}
112119

113120
renderChildDiffs() {
@@ -138,7 +145,6 @@ export class DiffTree extends LitElement {
138145
elementDiff[id] ??= {};
139146
elementDiff[id].theirs = element;
140147
});
141-
console.warn(elementDiff);
142148
return Object.entries(elementDiff).map(([id, { ours, theirs }]) => {
143149
return html`<diff-tree
144150
.ours=${ours}
@@ -150,35 +156,170 @@ export class DiffTree extends LitElement {
150156
</div>`;
151157
}
152158

159+
renderAttributeDiff() {
160+
const attrDiff = filterObject(
161+
this.diff,
162+
([key]) => !key.startsWith("@") && key !== "eNS",
163+
);
164+
const eNSDiff = this.diff.eNS;
165+
if (!Object.keys(attrDiff).length && !eNSDiff) return nothing;
166+
return html`<table>
167+
${Object.entries(attrDiff).map(
168+
([name, { ours, theirs }]) =>
169+
html`<tr>
170+
<td></td>
171+
<td>${name}</td>
172+
<td>${ours}</td>
173+
<td>${theirs}</td>
174+
</tr>`,
175+
)}
176+
${Object.entries(eNSDiff ?? {}).map(([ns, ks]) =>
177+
Object.entries(ks).map(
178+
([k, d]) =>
179+
html`<tr>
180+
<td>${ns}</td>
181+
<td>${k}</td>
182+
<td>${(d as { ours: string }).ours}</td>
183+
<td>${(d as { theirs: string }).theirs}</td>
184+
</tr>`,
185+
),
186+
)},
187+
</table>`;
188+
}
189+
153190
renderDiff() {
154-
return html`<pre>
155-
${JSON.stringify(this.diff, null, 2)}
156-
</pre>
157-
${this.renderChildDiffs()}`;
191+
return html`${this.renderAttributeDiff()}${this.renderChildDiffs()}`;
192+
}
193+
194+
renderElement() {
195+
const element = this.ours ?? this.theirs;
196+
if (!element) return nothing;
197+
const id = identity(element);
198+
const tag = element.tagName;
199+
const description = this.ourDescription ?? this.theirDescription;
200+
const hash = this.ourHash ?? this.theirHash;
201+
return html`<md-icon-button toggle @click=${() => this.requestUpdate()}>
202+
<md-icon>unfold_more</md-icon>
203+
<md-icon slot="selected">unfold_less</md-icon>
204+
</md-icon-button>
205+
<p>${this.ours ? "-" : "+"} ${id}</p>
206+
${this.expanded ? this.renderDiff() : ""} `;
158207
}
159208

160209
render() {
161-
if (!this.ours || !this.theirs)
162-
return html`<h2>missing ${this.ours ? "their" : "our"} element</h2>`;
210+
if (!this.ours && !this.theirs)
211+
return html`<p>missing ${this.ours ? "their" : "our"} element</p>`;
212+
if (!this.ours || !this.theirs) return this.renderElement();
163213
if (!this.ourHasher || !this.theirHasher)
164-
return html`<h2>missing ${this.ourHasher ? "their" : "our"} hasher</h2>`;
214+
return html`<p>missing ${this.ourHasher ? "their" : "our"} hasher</p>`;
165215
if (!this.ourDescription || !this.theirDescription)
166-
return html`<h2>
216+
return html`<p>
167217
missing ${this.ourDescription ? "their" : "our"} description
168-
</h2>`;
218+
</p>`;
169219
if (this.ourHash === this.theirHash) return nothing;
170220

171221
Object.keys(this.ourDescription ?? {}).forEach((key) => {});
172222

173-
return html`<h2>
174-
${identity(this.ours) || this.ours.tagName}
175-
<md-icon>arrow_forward</md-icon> ${identity(this.theirs) ||
176-
this.theirs.tagName}
177-
</h2>
178-
<md-icon-button toggle @click=${() => this.requestUpdate()}>
223+
return html`<md-icon-button toggle @click=${() => this.requestUpdate()}>
179224
<md-icon>unfold_more</md-icon>
180225
<md-icon slot="selected">unfold_less</md-icon>
181226
</md-icon-button>
227+
<p>
228+
${identity(this.ours) || this.ours.tagName}
229+
<md-icon style="--md-icon-size: 1em">arrow_forward</md-icon> ${identity(
230+
this.theirs,
231+
) || this.theirs.tagName}
232+
</p>
182233
${this.expanded ? this.renderDiff() : ""} `;
183234
}
235+
236+
static styles = css`
237+
md-icon-button {
238+
float: left;
239+
transform: scale(0.6);
240+
}
241+
div {
242+
margin-left: 1em;
243+
}
244+
pre {
245+
max-width: 100%;
246+
overflow-x: auto;
247+
}
248+
* {
249+
margin-top: 0px;
250+
}
251+
252+
i {
253+
color: #555a;
254+
}
255+
th {
256+
font-weight: 300;
257+
opacity: 0.8;
258+
width: 1%;
259+
white-space: nowrap;
260+
}
261+
th:first-child {
262+
text-align: right;
263+
color: var(--oscd-base1);
264+
padding-right: 0.5em;
265+
}
266+
td.arrow {
267+
width: 2em;
268+
text-align: center;
269+
color: var(--oscd-base1);
270+
}
271+
.odd > table > tr > th:first-child,
272+
td.arrow {
273+
color: var(--oscd-base0);
274+
}
275+
th:nth-child(2) {
276+
text-align: left;
277+
color: var(--oscd-base0);
278+
background: var(--oscd-base2);
279+
padding-right: 1em;
280+
}
281+
table td:nth-child(3) {
282+
text-align: right;
283+
}
284+
td:nth-child(5) {
285+
text-align: left;
286+
}
287+
tr:nth-child(2n) td,
288+
tr:nth-child(2n) th {
289+
background: var(--oscd-base2);
290+
}
291+
tr:nth-child(2n + 1) td,
292+
tr:nth-child(2n + 1) th {
293+
background: var(--oscd-base3);
294+
}
295+
table {
296+
border: 0.25em solid var(--oscd-base2);
297+
table-layout: auto;
298+
border-collapse: collapse;
299+
width: max-content;
300+
margin-left: 1.2em;
301+
margin-bottom: 0.3em;
302+
background: none;
303+
}
304+
* {
305+
cursor: default;
306+
--oscd-primary: var(--oscd-theme-primary, #2aa198);
307+
--oscd-secondary: var(--oscd-theme-secondary, #6c71c4);
308+
--oscd-error: var(--oscd-theme-error, #dc322f);
309+
--oscd-base03: var(--oscd-theme-base03, #002b36);
310+
--oscd-base02: var(--oscd-theme-base02, #073642);
311+
--oscd-base01: var(--oscd-theme-base01, #586e75);
312+
--oscd-base00: var(--oscd-theme-base00, #657b83);
313+
--oscd-base0: var(--oscd-theme-base0, #839496);
314+
--oscd-base1: var(--oscd-theme-base1, #93a1a1);
315+
--oscd-base2: var(--oscd-theme-base2, #eee8d5);
316+
--oscd-base3: var(--oscd-theme-base3, #fdf6e3);
317+
--oscd-text-font: var(--oscd-theme-text-font, "Roboto");
318+
}
319+
:host {
320+
font-family: var(--oscd-text-font);
321+
display: block;
322+
padding: 0.5rem;
323+
}
324+
`;
184325
}

0 commit comments

Comments
 (0)