diff --git a/core/client.js b/core/client.js
index 1d7b31e0..e23a7527 100644
--- a/core/client.js
+++ b/core/client.js
@@ -1,7 +1,6 @@
-import {LitElement, html, css} from '/static/lit/lit-all.min.js';
+import {LitElement, html, css, svg} from '/static/lit/lit-all.min.js';
let gSocket;
-let gPermissions;
let gCurrentFile;
let gFiles = {};
@@ -52,6 +51,7 @@ class TfNavigationElement extends LitElement {
permissions: {type: Object},
show_permissions: {type: Boolean},
status: {type: Object},
+ spark_lines: {type: Object},
};
}
@@ -60,6 +60,7 @@ class TfNavigationElement extends LitElement {
this.permissions = {};
this.show_permissions = false;
this.status = {};
+ this.spark_lines = {};
}
toggle_edit(event) {
@@ -75,6 +76,21 @@ class TfNavigationElement extends LitElement {
send({action: "resetPermission", permission: key});
}
+ get_spark_line(key, options) {
+ if (!this.spark_lines[key]) {
+ let spark_line = document.createElement('tf-sparkline');
+ spark_line.title = key;
+ if (options) {
+ if (options.max) {
+ spark_line.max = options.max;
+ }
+ }
+ this.spark_lines[key] = spark_line;
+ this.requestUpdate();
+ }
+ return this.spark_lines[key];
+ }
+
render_login() {
if (this?.credentials?.session?.name) {
return html`logout ${this.credentials.session.name}`;
@@ -106,22 +122,21 @@ class TfNavigationElement extends LitElement {
let self = this;
return html`
- 😎
- Tilde Friends
- apps
- edit
- self.show_permissions = !self.show_permissions}>🎛️
- ${this.status.message}
-
- ${this.render_permissions()}
-
- ${this.render_login()}
+
`;
}
}
@@ -193,6 +208,65 @@ class TfFilesElement extends LitElement {
}
customElements.define('tf-files', TfFilesElement);
+class TfSparkLineElement extends LitElement {
+ static get properties() {
+ return {
+ lines: {type: Array},
+ min: {type: Number},
+ max: {type: Number},
+ };
+ }
+
+ constructor() {
+ super();
+ this.min = 0;
+ this.max = 1.0;
+ this.lines = [];
+ }
+
+ append(key, value) {
+ let line = null;
+ for (let it of this.lines) {
+ if (it.name == key) {
+ line = it;
+ break;
+ }
+ }
+ if (!line) {
+ const k_colors = ['#0f0', '#88f', '#ff0', '#f0f', '#0ff', '#f00', '#888'];
+ line = {
+ name: key,
+ style: k_colors[this.lines.length % k_colors.length],
+ values: [],
+ };
+ this.lines.push(line);
+ }
+ line.values.push(value);
+ if (line.values.length > 100) {
+ line.values.shift();
+ }
+ this.requestUpdate();
+ }
+
+ render_line(line) {
+ if (line?.values?.length >= 2) {
+ let points = [].concat(...line.values.map((x, i) => [i * 100 / (line.values.length - 1), 10 - 10 * (x - this.min) / (this.max - this.min)]));
+ return svg`
+
+ `;
+ }
+ }
+
+ render() {
+ return html`
+
+ `;
+ }
+}
+customElements.define('tf-sparkline', TfSparkLineElement);
+
window.addEventListener("keydown", function(event) {
if (event.keyCode == 83 && (event.altKey || event.ctrlKey)) {
if (editing()) {
@@ -306,13 +380,11 @@ function trace() {
function stats() {
window.localStorage.setItem('stats', '1');
document.getElementById("statsPane").style.display = 'flex';
- send({action: 'enableStats', enabled: true});
}
function closeStats() {
window.localStorage.setItem('stats', '0');
document.getElementById("statsPane").style.display = 'none';
- send({action: 'enableStats', enabled: false});
}
function toggleStats() {
@@ -648,10 +720,7 @@ function _receive_websocket_message(message) {
if (window.location.hash) {
send({event: "hashChange", hash: window.location.hash});
}
- if (window.localStorage.getItem('stats') == '1') {
- /* Stats were opened before we connected. */
- send({action: 'enableStats', enabled: true});
- }
+ send({action: 'enableStats', enabled: true});
} else if (message && message.action == "ping") {
send({action: "pong"});
} else if (message && message.action == "stats") {
@@ -733,6 +802,10 @@ function _receive_websocket_message(message) {
}
}
timeseries.append(now, message.stats[key]);
+
+ if (graph_key == 'cpu' || graph_key == 'rpc' || graph_key == 'stored') {
+ document.getElementsByTagName('tf-navigation')[0].get_spark_line(graph_key, { max: 100 }).append(key, message.stats[key]);
+ }
}
} else if (message &&
message.message === 'tfrpc' &&