From 04479d5ce3ae0eb19f61349b276cc7081e2d68ee Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Thu, 10 Mar 2022 02:53:30 +0000 Subject: [PATCH] TableView, UITable: fill in the plumbing Int heory, we now have the basics of the UI down now. We just need to hook up the navigation and do some testing :D --- src/static/js/ui/TableView.mjs | 9 +++++- src/static/js/ui/UITable.mjs | 58 ++++++++++++++++++++++++++++++---- src/static/js/ui/peer_name.mjs | 23 ++++++++++++++ 3 files changed, 82 insertions(+), 8 deletions(-) create mode 100644 src/static/js/ui/peer_name.mjs diff --git a/src/static/js/ui/TableView.mjs b/src/static/js/ui/TableView.mjs index 50e7793..ab9e043 100644 --- a/src/static/js/ui/TableView.mjs +++ b/src/static/js/ui/TableView.mjs @@ -32,7 +32,14 @@ class TableView { el.classList.add("data-item"); el_dataitems.appendChild(el); - let item_manager = new UITable(el, def); + let item_manager = null; + switch(def.type) { + case "table": + item_manager = new UITable(el, def); + break; + default: + console.warn(`Unknown item definition type '${def.type}', ignoring. This is probably a bug.`); + } this.el_parts.set(def.name, item_manager); } diff --git a/src/static/js/ui/UITable.mjs b/src/static/js/ui/UITable.mjs index aa7f10c..207268c 100644 --- a/src/static/js/ui/UITable.mjs +++ b/src/static/js/ui/UITable.mjs @@ -1,9 +1,10 @@ "use strict"; import Emel from 'emel'; -import { NightInk } from 'nightink'; +import { NightInk as nightink } from 'nightink'; import AbstractUIItem from './AbstractUIItem.mjs'; +import peer_name from './peer_name.mjs'; class UITable extends AbstractUIItem { constructor(el, def) { @@ -11,25 +12,68 @@ class UITable extends AbstractUIItem { this.emel = new Emel().emel; - this.el.replaceChildren(this.emel(`table>(thead>tr>${Object.keys(def.content).map(header => `th{${header}}`).join("+")})+tbody`)); + this.el.replaceChildren(this.emel(`table>(thead>(tr>th{Peer}+${ + Object.keys(def.content).map(header => `th{${header}}`).join("+") + })+tbody`)); } clear() { super.clear(); - // TODO: Empty the table, but avoiding removing the header, structure etc + this.el.querySelector(`tbody`).replaceChildren(); } append(peer, table) { super.append(peer, table); + const el_tbody = this.el.querySelector("tbody"); + let new_row = document.createElement("tr"); - for(let [ _, template ] of Object.entries(this.def.content)) { + // TODO: Insert a for the name of the peer here + new_row.appendChild(peer_name(peer)); + + // Note here that the comma is *important*. This is a destructuring assignment where we ignore the first value. + for(let [ , template ] of Object.entries(this.def.content)) { let table_cell = document.createElement("td"); - table_cell.appendChild(document.createTextNode()) + table_cell.appendChild(document.createTextNode(nightink(template, table))); + new_row.appendChild(table_cell); } - // TODO Append the new table item in the right place - // Perhaps we could use .dataset & iterate until we find the right one to insert directly before? + new_row.dataset.peer_name = peer.name; + new_row.dataset.peer_id = peer.id; + + const comparer = new Intl.Collator(navigator.language); + + // If the peer id exactly matches, replace this row instead + for(let row of el_tbody.childNodes) { + if(peer.id === row.dataset.peer_id) { + row.before(new_row); + el_tbody.removeChild(row); + return; + } + } + + // Otherwise, insert it such that the list is sorted + // FUTURE: Use a fanceh thingy that sorts table data? + for(let row of el_tbody.childNodes) { + const comp_name = comparer.compare( + peer.name.toLowerCase(), + row.dataset.peer_name.toLowerCase() + ); + const comp_id = comparer.compare(peer.id, row.dataset.peer_id); + + let insert_before = false; + if(comp_name < 0) insert_before = true; + if(!insert_before && comp_name === 0 && comp_id < 0) insert_before = true; + + if(insert_before) { + row.before(new_row); + return; + } + } + + // In the unlikely event we failed to insert it somewhere, make sure it's inserted + // e.g. if this is the first row, or sorts after all existing rows + el_tbody.appendChild(new_row); } } diff --git a/src/static/js/ui/peer_name.mjs b/src/static/js/ui/peer_name.mjs new file mode 100644 index 0000000..601070f --- /dev/null +++ b/src/static/js/ui/peer_name.mjs @@ -0,0 +1,23 @@ +"use strict"; + +export default function peer_name(peer) { + const result = document.createElement("span"); + result.classList.append(`peer-name`); + result.dataset.peer_id = peer.id; + result.dataset.peer_name = peer.name; + + const peer_name = document.createElement("span"); + peer_name.appendChild(document.createTextNode(peer.name)); + + const peer_id = document.createElement("span"); + peer_id.appendChild(document.createTextNode(peer.id)); + + // TODO: When the id is clicked, copy it to the clipboard - we may need a fancy tooltip library for this + + // text-overflow: ellipsis; may be useful here + + result.replaceChildren(peer_name, peer_id); + + + return result; +}