Compare commits
5 Commits
c8a1a69862
...
026de5987b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
026de5987b | ||
|
|
59174d3c88 | ||
|
|
071c5fc08c | ||
|
|
3b0cb99334 | ||
|
|
bc602c7bd8 |
@@ -1,36 +1,34 @@
|
|||||||
import {isIsoDateWithMs, padIsoMilliseconds} from "./util.js";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @template R A type that the shape of a row should be. E.g.
|
* @template TRow A type that the shape of a row should be. E.g.
|
||||||
* ```
|
* ```
|
||||||
* type Heist = {
|
* type User = {
|
||||||
* id: number;
|
* id: number;
|
||||||
* name: string;
|
* name: string;
|
||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
* Then `Heist` would be passed as the generic.
|
* Then `User` would be passed as the generic.
|
||||||
*/
|
*/
|
||||||
export abstract class Table<R extends Object> {
|
export abstract class Table<TRow extends Object> {
|
||||||
|
|
||||||
table: HTMLTableElement;
|
table: HTMLTableElement;
|
||||||
tableBody: HTMLTableSectionElement;
|
tableBody: HTMLTableSectionElement;
|
||||||
headers: Header<R>[];
|
headers: Header<TRow>[];
|
||||||
|
|
||||||
messageEl: HTMLElement | null;
|
messageEl: HTMLElement | null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a list of Header objects to be used in a table for the header cell values and column types.
|
* Creates a list of Header objects to be used in a table for the header cell values and column types.
|
||||||
* @param exampleObject An instance of the type to be displaying. Can be an object with default values such as
|
* @param exampleObject An instance of the type to be displaying. Can be an object with default/zero values for that type
|
||||||
* `0`, `""`, `false` or `true`. E.g. for a heist ```{ id: 0; name: ""; }```
|
* such as `0`, `""`, `false` or `true`. E.g. for a user ```{ id: 0; name: ""; }``` would be passed
|
||||||
* @param displayNamesAndOrder A object with the same properties, but all string type for the header cell values.
|
* @param displayNamesAndOrder A object with the same properties, but all string type for the header cell values.
|
||||||
* Used by passing an object with the keys of R and the name preferred. E.g. for a heist:
|
* Used by passing an object with the keys of R and the name preferred. E.g. for a user:
|
||||||
* ```{ id: "ID", name: "Heist Name" }```, this makes the columns appear in the order of ID then Heist Name.
|
* ```{ id: "ID", name: "Name" }```, this makes the columns appear in the order of ID then Name.
|
||||||
* @param messageElement Used to display messaged related to data output. Optional.
|
* @param messageElement Used to display messaged related to data output. Optional.
|
||||||
* Omit (undefined) to use the class provided HTMLParagraphElement.
|
* Omit (undefined) to use the class provided HTMLParagraphElement.
|
||||||
* Pass an HTMLElement tp ise a custom element.
|
* Pass an HTMLElement to use a custom element.
|
||||||
* Pass null to disable automatic message output.
|
* Pass null to disable automatic message output.
|
||||||
*/
|
*/
|
||||||
constructor(exampleObject: R, displayNamesAndOrder?: Record<keyof R, string>, messageElement?: HTMLElement | null | undefined) {
|
constructor(exampleObject: TRow, displayNamesAndOrder?: Record<keyof TRow, string>, messageElement?: HTMLElement | null | undefined) {
|
||||||
|
|
||||||
this.table = document.createElement("table")
|
this.table = document.createElement("table")
|
||||||
this.tableBody = document.createElement("tbody");
|
this.tableBody = document.createElement("tbody");
|
||||||
@@ -46,17 +44,18 @@ export abstract class Table<R extends Object> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createHeadersFromType(
|
createHeadersFromType(
|
||||||
exampleObject: R, // Needed for runtime, since types don't exist in JS.
|
exampleObject: TRow, // Needed for runtime, since types don't exist in JS.
|
||||||
displayNamesAndOrder?: Record<keyof R, string>
|
displayNamesAndOrder?: Record<keyof TRow, string>
|
||||||
): Header<R>[] {
|
): Header<TRow>[] {
|
||||||
|
// Checks if display names and order was passed. If not, derives the keys to use for the header from the example object.
|
||||||
const keys = displayNamesAndOrder
|
const keys = displayNamesAndOrder
|
||||||
? (Object.keys(displayNamesAndOrder) as (keyof R)[])
|
? (Object.keys(displayNamesAndOrder) as (keyof TRow)[])
|
||||||
: (Object.keys(exampleObject) as (keyof R)[]);
|
: (Object.keys(exampleObject) as (keyof TRow)[]);
|
||||||
|
|
||||||
return keys.map(key => ({
|
return keys.map(key => ({
|
||||||
key,
|
key, // Raw property name from TRow
|
||||||
value: displayNamesAndOrder?.[key] ?? String(key),
|
value: displayNamesAndOrder?.[key] ?? String(key), // The value of the th html element, with a nullish coalescing operator for if its null
|
||||||
type: typeof exampleObject[key],
|
type: typeof exampleObject[key], // The type of the column
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,12 +95,12 @@ export abstract class Table<R extends Object> {
|
|||||||
* Appends one more row to the current rows.
|
* Appends one more row to the current rows.
|
||||||
* @param data Data to append as a row.
|
* @param data Data to append as a row.
|
||||||
*/
|
*/
|
||||||
appendRow(data: R): void {
|
appendRow(data: TRow): void {
|
||||||
const row = this.createPopulatedRow(data)
|
const row = this.createPopulatedRow(data)
|
||||||
this.tableBody.appendChild(row)
|
this.tableBody.appendChild(row)
|
||||||
}
|
}
|
||||||
|
|
||||||
appendRows(data: R[]): void {
|
appendRows(data: TRow[]): void {
|
||||||
if (data.length === 0) {
|
if (data.length === 0) {
|
||||||
this.setMessage("No data to append. Empty list provided.")
|
this.setMessage("No data to append. Empty list provided.")
|
||||||
return;
|
return;
|
||||||
@@ -116,7 +115,7 @@ export abstract class Table<R extends Object> {
|
|||||||
* @param data The data in the shape of `R`, with values populated.
|
* @param data The data in the shape of `R`, with values populated.
|
||||||
* @return A HTMLTableRowElement that can then be set on a table.
|
* @return A HTMLTableRowElement that can then be set on a table.
|
||||||
*/
|
*/
|
||||||
createPopulatedRow(data: R): HTMLTableRowElement {
|
createPopulatedRow(data: TRow): HTMLTableRowElement {
|
||||||
const row = document.createElement("tr");
|
const row = document.createElement("tr");
|
||||||
|
|
||||||
for (const header of this.headers) {
|
for (const header of this.headers) {
|
||||||
@@ -139,17 +138,7 @@ export abstract class Table<R extends Object> {
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
const strValue = String(value)
|
const strValue = String(value)
|
||||||
if (isIsoDateWithMs(strValue))
|
|
||||||
{
|
|
||||||
const strValueDateTime = padIsoMilliseconds(strValue);
|
|
||||||
cell.classList.add("table-cell-datetime")
|
|
||||||
const date = strValueDateTime.split("T")[0]
|
|
||||||
const time = strValueDateTime.split("T")[1]
|
|
||||||
cellValue = `${date} ${time}`;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
cellValue = value != null ? String(value) : "";
|
cellValue = value != null ? String(value) : "";
|
||||||
}
|
|
||||||
}
|
}
|
||||||
cell.textContent = cellValue;
|
cell.textContent = cellValue;
|
||||||
row.append(cell);
|
row.append(cell);
|
||||||
@@ -169,18 +158,18 @@ export abstract class Table<R extends Object> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes all current rows and sets a single row to the data in data param.
|
* Deletes all current rows and sets a single row to the data in data param.
|
||||||
* @param data The data to set the table to. Should be of shape {@link R}
|
* @param data The data to set the table to. Should be of shape {@link TRow}
|
||||||
*/
|
*/
|
||||||
setSingleRow(data: R): void {
|
setSingleRow(data: TRow): void {
|
||||||
this.clearRows()
|
this.clearRows()
|
||||||
this.appendRow(data)
|
this.appendRow(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes all current rows and sets the rows to the data in data param.
|
* Deletes all current rows and sets the rows to the data in data param.
|
||||||
* @param data The data to set the table to. Should be of shape {@link R}
|
* @param data The data to set the table to. Should be of shape {@link TRow}
|
||||||
*/
|
*/
|
||||||
setRows(data: R[]): void {
|
setRows(data: TRow[]): void {
|
||||||
this.clearRows()
|
this.clearRows()
|
||||||
if (data.length === 0) {
|
if (data.length === 0) {
|
||||||
this.setMessage("No data to show. Empty list provided.")
|
this.setMessage("No data to show. Empty list provided.")
|
||||||
|
|||||||
Reference in New Issue
Block a user