1- import type { ColumnDef , StringOrTemplateHeader } from '@tanstack/table-core' ;
2- import { createRawSnippet } from 'svelte' ;
1+ import type { ColumnDef } from '@tanstack/table-core' ;
32import { SemVer } from 'semver' ;
4- import { renderComponent , renderSnippet } from '$lib/components/ui/data-table' ;
5- import { durationToString } from '$lib/utils/time' ;
6- import type { TwColor } from '$lib/types/Tailwind' ;
3+ import { renderComponent } from '$lib/components/ui/data-table' ;
74import DataTableActions from './data-table-actions.svelte' ;
8- import { getReadableUserAgentName } from '$lib/utils/userAgent' ;
9- import DataTableSortButton from '$lib/components/Table/SortButton.svelte' ;
5+ import {
6+ CreateSimpleCellSnippet ,
7+ CreateSortHeader ,
8+ FirmwareVersionRenderer ,
9+ NumberRenderer ,
10+ TimeSinceDurationRenderer ,
11+ UserAgentRenderer ,
12+ } from '$lib/components/Table/ColumnUtils' ;
1013
1114export type OnlineHubOwner = {
1215 id : string ;
@@ -26,13 +29,8 @@ export type OnlineHub = {
2629 rssi : number | null ;
2730} ;
2831
29- function CreateSortHeader < TData > ( name : string ) : StringOrTemplateHeader < TData , unknown > {
30- return ( { column } ) =>
31- renderComponent ( DataTableSortButton , {
32- name,
33- onclick : ( ) => column . toggleSorting ( column . getIsSorted ( ) === 'asc' ) ,
34- } ) ;
35- }
32+ const OwnerRenderer = ( owner : OnlineHubOwner ) =>
33+ `<div class="px-4 font-medium" title="${ owner . id } ">${ owner . name } </div>` ;
3634
3735export const columns : ColumnDef < OnlineHub > [ ] = [
3836 {
@@ -42,17 +40,7 @@ export const columns: ColumnDef<OnlineHub>[] = [
4240 {
4341 accessorKey : 'owner' ,
4442 header : CreateSortHeader ( 'Owner' ) ,
45- cell : ( { row } ) => {
46- const ownerCellSnippet = createRawSnippet < [ OnlineHubOwner ] > ( ( getOwner ) => {
47- const owner = getOwner ( ) ;
48- return {
49- render : ( ) =>
50- `<div class="text-left font-medium" title="${ owner . id } ">${ owner . name } </div>` ,
51- } ;
52- } ) ;
53-
54- return renderSnippet ( ownerCellSnippet , row . getValue < OnlineHubOwner > ( 'owner' ) ) ;
55- } ,
43+ cell : CreateSimpleCellSnippet ( 'owner' , OwnerRenderer ) ,
5644 sortingFn : ( row_a , row_b ) => {
5745 const a = row_a . getValue < OnlineHubOwner > ( 'owner' ) ;
5846 const b = row_b . getValue < OnlineHubOwner > ( 'owner' ) ;
@@ -63,26 +51,7 @@ export const columns: ColumnDef<OnlineHub>[] = [
6351 {
6452 accessorKey : 'firmware_version' ,
6553 header : CreateSortHeader ( 'Firmware Version' ) ,
66- cell : ( { row } ) => {
67- const firmwareVersionCellSnippet = createRawSnippet < [ string ] > ( ( getFirmwareVersion ) => {
68- let firmwareVersion = getFirmwareVersion ( ) . toString ( ) ;
69-
70- let color : `text-${TwColor } `;
71- if ( firmwareVersion . length <= 0 ) {
72- firmwareVersion = 'Invalid' ;
73- color = 'text-red-500' ;
74- } else if ( firmwareVersion === '0.0.0-local' ) {
75- color = 'text-orange-500' ;
76- }
77-
78- return {
79- render : ( ) =>
80- `<div class="text-left font-medium ${ color } " title="${ firmwareVersion } ">${ firmwareVersion } </div>` ,
81- } ;
82- } ) ;
83-
84- return renderSnippet ( firmwareVersionCellSnippet , row . getValue < string > ( 'firmware_version' ) ) ;
85- } ,
54+ cell : CreateSimpleCellSnippet ( 'firmware_version' , FirmwareVersionRenderer ) ,
8655 sortingFn : ( row_a , row_b ) => {
8756 const a = new SemVer ( row_a . getValue < string > ( 'firmware_version' ) ) ;
8857 const b = new SemVer ( row_b . getValue < string > ( 'firmware_version' ) ) ;
@@ -99,100 +68,27 @@ export const columns: ColumnDef<OnlineHub>[] = [
9968 {
10069 accessorKey : 'connected_at' ,
10170 header : CreateSortHeader ( 'Online for' ) ,
102- cell : ( { row } ) => {
103- const connectedAtCellSnippet = createRawSnippet < [ Date ] > ( ( getConnectedAt ) => {
104- const now = Date . now ( ) ;
105- const connectedAt = getConnectedAt ( ) ;
106- const formattedDuration = durationToString ( now - connectedAt . getTime ( ) ) ;
107- return {
108- render : ( ) =>
109- `<div class="text-left font-medium" title="${ connectedAt } ">${ formattedDuration } </div>` ,
110- } ;
111- } ) ;
112-
113- return renderSnippet ( connectedAtCellSnippet , row . getValue < Date > ( 'connected_at' ) ) ;
114- } ,
71+ cell : CreateSimpleCellSnippet ( 'connected_at' , TimeSinceDurationRenderer ) ,
11572 } ,
11673 {
11774 accessorKey : 'user_agent' ,
11875 header : 'User Agent' ,
119- cell : ( { row } ) => {
120- const userAgentCellSnippet = createRawSnippet < [ string | null ] > ( ( getUserAgent ) => {
121- const userAgent = getUserAgent ( ) ;
122- const readableName = userAgent ? getReadableUserAgentName ( userAgent ) : 'Unknown' ;
123-
124- let color : `` | `text-${TwColor } ` = '' ;
125- if ( ! userAgent ) {
126- color = 'text-red-500' ;
127- } else if ( ! readableName ) {
128- color = 'text-orange-500' ;
129- }
130-
131- return {
132- render : ( ) =>
133- `<div class="text-left font-medium ${ color } " title="${ userAgent } ">${ readableName ?? userAgent } </div>` ,
134- } ;
135- } ) ;
136-
137- return renderSnippet ( userAgentCellSnippet , row . getValue < string | null > ( 'user_agent' ) ) ;
138- } ,
76+ cell : CreateSimpleCellSnippet ( 'user_agent' , UserAgentRenderer ) ,
13977 } ,
14078 {
14179 accessorKey : 'booted_at' ,
14280 header : CreateSortHeader ( 'Uptime' ) ,
143- cell : ( { row } ) => {
144- const bootedAtCellSnippet = createRawSnippet < [ Date ] > ( ( getBootedAt ) => {
145- const bootedAt = getBootedAt ( ) ;
146- const now = Date . now ( ) ;
147- const formattedDuration = durationToString ( now - bootedAt . getTime ( ) ) ;
148- return {
149- render : ( ) =>
150- `<div class="text-left font-medium" title="${ bootedAt } ">${ formattedDuration } </div>` ,
151- } ;
152- } ) ;
153-
154- return renderSnippet ( bootedAtCellSnippet , row . getValue < Date > ( 'booted_at' ) ) ;
155- } ,
81+ cell : CreateSimpleCellSnippet ( 'booted_at' , TimeSinceDurationRenderer ) ,
15682 } ,
15783 {
15884 accessorKey : 'latency' ,
15985 header : CreateSortHeader ( 'Latency' ) ,
160- cell : ( { row } ) => {
161- const latencyCellSnippet = createRawSnippet < [ number | null ] > ( ( getLatency ) => {
162- const latency = getLatency ( ) ;
163- if ( ! latency ) {
164- return {
165- render : ( ) => `<div class="text-left font-medium" title="N/A">N/A</div>` ,
166- } ;
167- }
168-
169- return {
170- render : ( ) => `<div class="text-left font-medium" title="${ latency } ">${ latency } </div>` ,
171- } ;
172- } ) ;
173-
174- return renderSnippet ( latencyCellSnippet , row . getValue < number | null > ( 'latency' ) ) ;
175- } ,
86+ cell : CreateSimpleCellSnippet ( 'latency' , NumberRenderer ) ,
17687 } ,
17788 {
17889 accessorKey : 'rssi' ,
17990 header : CreateSortHeader ( 'RSSI' ) ,
180- cell : ( { row } ) => {
181- const rssiCellSnippet = createRawSnippet < [ number | null ] > ( ( getRssi ) => {
182- const rssi = getRssi ( ) ;
183- if ( ! rssi ) {
184- return {
185- render : ( ) => `<div class="text-left font-medium" title="N/A">N/A</div>` ,
186- } ;
187- }
188-
189- return {
190- render : ( ) => `<div class="text-left font-medium" title="${ rssi } ">${ rssi } </div>` ,
191- } ;
192- } ) ;
193-
194- return renderSnippet ( rssiCellSnippet , row . getValue < number | null > ( 'rssi' ) ) ;
195- } ,
91+ cell : CreateSimpleCellSnippet ( 'rssi' , NumberRenderer ) ,
19692 } ,
19793 {
19894 id : 'actions' ,
0 commit comments