Skip to content

Commit 2da3d19

Browse files
authored
feat: Update the UI for the config list page (#189)
* Move the config list to pages * Add the inheritable utility class for global styling, update the components * Update the config list page * Update the links to config list page * Update the links to config list page * Update the side nav style * Format the code * Update the nav active color
1 parent a2299db commit 2da3d19

File tree

11 files changed

+311
-132
lines changed

11 files changed

+311
-132
lines changed

web/static/config/edit.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@
145145
// Set cookie named 'message' with the value 'Data saved successfully'
146146
document.cookie = 'message=The layer "' + layer + '" saved successfully.; path=/;';
147147

148-
window.location.href = '/config/';
148+
window.location.href = '/pages/config/list/';
149149
})
150150
.catch(error => {
151151
alert('Error saving data:', error);

web/static/config/index.html

Lines changed: 0 additions & 122 deletions
This file was deleted.
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
import { html, css } from 'https://cdn.jsdelivr.net/gh/lit/dist@3/all/lit-all.min.js';
2+
import 'https://cdn.jsdelivr.net/npm/[email protected]/dist/axios.min.js';
3+
import { StyledLitElement } from '/ux/StyledLitElement.mjs';
4+
import './list-tile.mjs';
5+
6+
class ConfigList extends StyledLitElement {
7+
constructor() {
8+
super();
9+
this.layers = [];
10+
this.topo = [];
11+
this.loadData();
12+
this.message = this.readCookie('message');
13+
this.eraseCookie('message');
14+
this.addName = '';
15+
}
16+
17+
async loadData() {
18+
Promise.all([
19+
axios.get('/api/config/layers'),
20+
axios.get('/api/config/topo'),
21+
axios.get('/api/config/default')
22+
])
23+
.then(responses => {
24+
this.layers = responses[0]?.data;
25+
this.layers.unshift('default');
26+
this.topo = responses[1]?.data;
27+
this.requestUpdate();
28+
})
29+
.catch(error => {
30+
console.error('Error fetching data:', error);
31+
});
32+
}
33+
34+
readCookie(name) {
35+
const cookies = document.cookie.split(';');
36+
for (let i = 0; i < cookies.length; i++) {
37+
const cookie = cookies[i].trim();
38+
if (cookie.startsWith(name + '=')) {
39+
return cookie.substring(name.length + 1);
40+
}
41+
}
42+
return '';
43+
}
44+
45+
eraseCookie(name) {
46+
document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
47+
}
48+
49+
updateName(e) {
50+
this.addName = e.target.value;
51+
}
52+
53+
addLayer() {
54+
// get a name
55+
const v = this.addName;
56+
if (v === '') {
57+
alert('Error: Layer name cannot be empty');
58+
return;
59+
}
60+
61+
axios.post('/api/config/addlayer', { name: v })
62+
.then(response => {
63+
window.location.href = '/config/edit.html?layer=' + v;
64+
})
65+
.catch(error => {
66+
alert('Error adding layer:', error);
67+
});
68+
}
69+
70+
render() {
71+
return html`
72+
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
73+
74+
${this.message ? html`<div class="alert">${this.message}</div>` : ''}
75+
76+
<ul class="pt-3">
77+
${this.layers.map((layer, index) => html`
78+
<list-tile id=${index}
79+
.layerName=${layer}
80+
.layerNodes=${this.topo.filter(topo => topo.LayersCSV.split(",").includes(layer))}></list-tile>
81+
`)}
82+
</ul>
83+
<div class="add-layer">
84+
<input autofocus type="text" id="layername" placeholder="Layer Name" @change=${this.updateName}>
85+
<button class="btn" @click=${this.addLayer}>Add Layer</button>
86+
</div>
87+
88+
<hr>
89+
<span>
90+
To delete a layer, use ysqlsh to issue the following command:<br>
91+
<code lang=sql>DELETE FROM curio.harmony_config WHERE title = 'my_layer_name';</code>
92+
</span>
93+
`
94+
}
95+
}
96+
97+
ConfigList.styles = css`
98+
.alert {
99+
font-size: 24px;
100+
display: inline-block;
101+
color: green;
102+
}
103+
104+
.add-layer {
105+
display: grid;
106+
grid-template-columns: 1fr max-content;
107+
grid-column-gap: 0.75rem;
108+
margin-bottom: 1rem;
109+
}
110+
111+
.btn {
112+
padding: 0.4rem 1rem;
113+
border: none;
114+
border-radius: 0;
115+
background-color: var(--color-form-default);
116+
color: var(--color-text-primary);
117+
118+
&:hover, &:focus, &:focus-visible {
119+
background-color: var(--color-form-default-pressed);
120+
color: var(--color-text-secondary);
121+
}
122+
}
123+
`;
124+
125+
customElements.define('config-list', ConfigList)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<title>Configurations</title>
5+
<script type="module" src="/ux/curio-ux.mjs"></script>
6+
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.21.1/axios.min.js"></script>
7+
<script type="module" src="config-list.mjs"></script>
8+
<link rel="stylesheet" href="/ux/main.css">
9+
</head>
10+
<body style="visibility:hidden; background:rgb(11, 22, 34)" data-bs-theme="dark">
11+
<curio-ux>
12+
<div class="row">
13+
<div class="col-md-3"></div>
14+
<div class="col-md-3 pt-4" style="width: 70%">
15+
<h2 style="text-wrap: nowrap">Configuration Editor</h2>
16+
<h4 style="text-wrap: nowrap">Click on a layer to edit its configuration</h4>
17+
<config-list></config-list>
18+
</div>
19+
<div class="col-md-3"></div>
20+
</div>
21+
</curio-ux>
22+
</body>
23+
</html>
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import {html, css} from 'https://cdn.jsdelivr.net/gh/lit/dist@3/all/lit-all.min.js';
2+
import {StyledLitElement} from "/ux/StyledLitElement.mjs";
3+
4+
class ListTile extends StyledLitElement {
5+
static get properties() {
6+
return {
7+
layerName: { type: String },
8+
layerNodes: { type: Array },
9+
};
10+
}
11+
12+
constructor() {
13+
super();
14+
this.layerName = '';
15+
this.layerNodes = [];
16+
}
17+
18+
render() {
19+
return html`
20+
<a class="anchor" href="/config/edit.html?layer=${this.layerName}">
21+
<li class="tile">
22+
<div>${this.layerName}</div>
23+
<div>Used by: ${this.layerNodes.length
24+
? html`<span><b>${this.layerNodes.length}</b>&nbsp;nodes</span>`
25+
: html`<span>&ndash;</span>`}
26+
</div>
27+
</li>
28+
</a>
29+
`
30+
}
31+
}
32+
33+
ListTile.styles = [
34+
css`
35+
.anchor {
36+
color: var(--color-text-primary);
37+
font-size: 1rem;
38+
}
39+
40+
.tile {
41+
display: grid;
42+
grid-template-columns: repeat(2, 1fr);
43+
grid-column-gap: 0.5rem;
44+
padding: 0.5rem 1.5rem;
45+
margin-bottom: 0.5rem;
46+
47+
background-color: rgba(255, 255, 255, 0.06);
48+
49+
&:hover, &:focus, &:focus-visible {
50+
background-color: #432E64;
51+
}
52+
}
53+
`
54+
]
55+
56+
customElements.define('list-tile', ListTile);

web/static/pages/node_info/index.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ <h1>Node Info</h1>
1414
</section>
1515
<section class="section">
1616
<div class="row">
17-
<div class="col-md-auto" style="max-width: 95%">
18-
<node-info></node-info>
19-
</div>
17+
<div class="col-md-auto" style="max-width: 95%">
18+
<node-info></node-info>
2019
</div>
2120
</div>
2221
</section>
2322
</curio-ux>
24-
</html>
23+
</body>
24+
</html>

web/static/ux/StyledLitElement.mjs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { LitElement } from 'https://cdn.jsdelivr.net/gh/lit/dist@3/all/lit-all.min.js';
2+
import cssReset from "./css-reset.js";
3+
import components from "./components.js";
4+
5+
// Base class including the default CSS styling
6+
export class StyledLitElement extends LitElement {
7+
static _styles = [];
8+
9+
static get styles() {
10+
const derivedStyles = this._styles || [];
11+
return [
12+
cssReset,
13+
components,
14+
...(Array.isArray(derivedStyles) ? derivedStyles : [derivedStyles]),
15+
]
16+
}
17+
18+
static set styles(styles) {
19+
this._styles = styles;
20+
}
21+
}

web/static/ux/components.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { css } from 'https://cdn.jsdelivr.net/gh/lit/dist@3/all/lit-all.min.js';
2+
3+
export default css `
4+
input {
5+
all: unset;
6+
box-sizing: border-box;
7+
8+
width: 100%;
9+
padding: 0.4rem 1rem;
10+
border: 1px solid #A1A1A1;
11+
background-color: rgba(255, 255, 255, 0.08);
12+
13+
font-size: 1rem;
14+
15+
&:hover, &:focus {
16+
box-shadow:0 0 0 1px #FFF inset;
17+
}
18+
}
19+
`;

0 commit comments

Comments
 (0)