mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-20 18:55:40 +00:00
Fit TrueNAS detail tables
This commit is contained in:
+12
@@ -16,6 +16,8 @@ import proxmoxPageSurfaceSource from '@/features/proxmox/ProxmoxPageSurface.tsx?
|
||||
import proxmoxReplicationTableSource from '@/features/proxmox/ProxmoxReplicationTable.tsx?raw';
|
||||
import sharedPlatformPageSource from '@/features/platformPage/sharedPlatformPage.tsx?raw';
|
||||
import truenasAlertsTableSource from '@/features/truenas/TrueNASAlertsTable.tsx?raw';
|
||||
import truenasAppsTableSource from '@/features/truenas/TrueNASAppsTable.tsx?raw';
|
||||
import truenasNetworkSharesTableSource from '@/features/truenas/TrueNASNetworkSharesTable.tsx?raw';
|
||||
import truenasPageSurfaceSource from '@/features/truenas/TrueNASPageSurface.tsx?raw';
|
||||
import truenasProtectionTableSource from '@/features/truenas/TrueNASProtectionTable.tsx?raw';
|
||||
import truenasStorageTopologyTableSource from '@/features/truenas/TrueNASStorageTopologyTable.tsx?raw';
|
||||
@@ -32,6 +34,8 @@ const platformTableSources = [
|
||||
kubernetesNodesTableSource,
|
||||
kubernetesDeploymentsTableSource,
|
||||
truenasAlertsTableSource,
|
||||
truenasAppsTableSource,
|
||||
truenasNetworkSharesTableSource,
|
||||
truenasProtectionTableSource,
|
||||
truenasStorageTopologyTableSource,
|
||||
truenasSystemsTableSource,
|
||||
@@ -175,8 +179,16 @@ describe('platform overview layout guardrails', () => {
|
||||
expect(truenasPageSurfaceSource).not.toContain('<StorageSurface');
|
||||
expect(truenasPageSurfaceSource).not.toContain('<WorkloadsSurface');
|
||||
expect(truenasPageSurfaceSource).not.toContain('<TrueNASDisksTable');
|
||||
expect(truenasAppsTableSource).toContain('md:min-w-[960px]');
|
||||
expect(truenasAppsTableSource).not.toContain('Volumes');
|
||||
expect(truenasNetworkSharesTableSource).toContain('md:min-w-[960px]');
|
||||
expect(truenasNetworkSharesTableSource).not.toMatch(
|
||||
/getPlatformTableHeadClassForKind\('text'\)[\s\S]{0,200}?Dataset/,
|
||||
);
|
||||
expect(truenasProtectionTableSource).not.toContain('Signal');
|
||||
expect(truenasProtectionTableSource).toContain('md:min-w-[960px]');
|
||||
expect(truenasStorageTopologyTableSource).toContain('md:min-w-[960px]');
|
||||
expect(truenasVirtualMachinesTableSource).toContain('md:min-w-[960px]');
|
||||
expect(vmwarePageSurfaceSource).toContain('<VsphereHostsTable');
|
||||
expect(vmwarePageSurfaceSource).toContain('<WorkloadsSurface');
|
||||
expect(vmwarePageSurfaceSource).toContain('<StorageSurface');
|
||||
|
||||
@@ -33,12 +33,7 @@ import {
|
||||
createPlatformResourceLabelResolver,
|
||||
getPlatformResourceDetailRowClass,
|
||||
} from '@/features/platformPage/PlatformResourceDetailTableRow';
|
||||
import type {
|
||||
Resource,
|
||||
ResourceTrueNASAppMeta,
|
||||
ResourceTrueNASAppPort,
|
||||
ResourceTrueNASAppVolume,
|
||||
} from '@/types/resource';
|
||||
import type { Resource, ResourceTrueNASAppMeta, ResourceTrueNASAppPort } from '@/types/resource';
|
||||
import { filterTrueNASApps, type TrueNASAppStatusFilter } from './truenasPageModel';
|
||||
|
||||
const TRUENAS_APP_STATUS_OPTIONS: PlatformTableFilterOption<TrueNASAppStatusFilter>[] = [
|
||||
@@ -80,9 +75,6 @@ const appContainerCount = (app: ResourceTrueNASAppMeta | undefined): number => {
|
||||
return app?.containers?.length ?? 0;
|
||||
};
|
||||
|
||||
const plural = (count: number, singular: string): string =>
|
||||
`${count} ${count === 1 ? singular : `${singular}s`}`;
|
||||
|
||||
const formatHostPort = (port: ResourceTrueNASAppPort): string => {
|
||||
const protocol = (asTrimmedString(port.protocol) ?? '').toLowerCase() || 'tcp';
|
||||
const target = typeof port.containerPort === 'number' ? String(port.containerPort) : '';
|
||||
@@ -121,24 +113,6 @@ const formatImages = (
|
||||
return { label: `${visible.join(', ')}${suffix}`, title: images.join(', ') };
|
||||
};
|
||||
|
||||
const volumeLabel = (volume: ResourceTrueNASAppVolume): string => {
|
||||
const source = asTrimmedString(volume.source);
|
||||
const destination = asTrimmedString(volume.destination);
|
||||
if (source && destination) return `${source}->${destination}`;
|
||||
return source || destination || '';
|
||||
};
|
||||
|
||||
const formatVolumes = (
|
||||
app: ResourceTrueNASAppMeta | undefined,
|
||||
): { label: string; title: string } => {
|
||||
const volumes = app?.volumes ?? [];
|
||||
if (volumes.length === 0) return { label: '-', title: '' };
|
||||
return {
|
||||
label: plural(volumes.length, 'volume'),
|
||||
title: volumes.map(volumeLabel).filter(Boolean).join(', '),
|
||||
};
|
||||
};
|
||||
|
||||
const UpdatePills: Component<{ app: ResourceTrueNASAppMeta | undefined }> = (props) => {
|
||||
const hasAppUpdate = () => props.app?.upgradeAvailable === true;
|
||||
const hasImageUpdate = () => props.app?.imageUpdatesAvailable === true;
|
||||
@@ -221,10 +195,10 @@ export const TrueNASAppsTable: Component<{
|
||||
>
|
||||
<TableCard class={PLATFORM_TABLE_CARD_CLASS}>
|
||||
<TableCardHeader title="Apps" />
|
||||
<Table class="min-w-full table-fixed text-xs md:min-w-[1280px]">
|
||||
<Table class="min-w-full table-fixed text-xs md:min-w-[960px]">
|
||||
<TableHeader>
|
||||
<TableRow class={PLATFORM_TABLE_HEADER_ROW_CLASS}>
|
||||
<TableHead class={`${getPlatformTableHeadClassForKind('name')} md:w-[16%]`}>
|
||||
<TableHead class={`${getPlatformTableHeadClassForKind('name')} md:w-[17%]`}>
|
||||
App
|
||||
</TableHead>
|
||||
<TableHead
|
||||
@@ -232,33 +206,28 @@ export const TrueNASAppsTable: Component<{
|
||||
>
|
||||
Version
|
||||
</TableHead>
|
||||
<TableHead class={`${getPlatformTableHeadClassForKind('metric-bar')} md:w-[10%]`}>
|
||||
<TableHead class={`${getPlatformTableHeadClassForKind('metric-bar')} md:w-[9%]`}>
|
||||
CPU
|
||||
</TableHead>
|
||||
<TableHead class={`${getPlatformTableHeadClassForKind('metric-bar')} md:w-[12%]`}>
|
||||
Memory
|
||||
</TableHead>
|
||||
<TableHead
|
||||
class={`${getPlatformTableHeadClassForKind('numeric-value')} hidden sm:table-cell md:w-[9%]`}
|
||||
class={`${getPlatformTableHeadClassForKind('numeric-value')} hidden sm:table-cell md:w-[12%]`}
|
||||
>
|
||||
Containers
|
||||
</TableHead>
|
||||
<TableHead
|
||||
class={`${getPlatformTableHeadClassForKind('text')} hidden md:table-cell md:w-[16%]`}
|
||||
class={`${getPlatformTableHeadClassForKind('text')} hidden md:table-cell md:w-[18%]`}
|
||||
>
|
||||
Ports
|
||||
</TableHead>
|
||||
<TableHead
|
||||
class={`${getPlatformTableHeadClassForKind('text')} hidden lg:table-cell md:w-[13%]`}
|
||||
class={`${getPlatformTableHeadClassForKind('text')} hidden lg:table-cell md:w-[12%]`}
|
||||
>
|
||||
Images
|
||||
</TableHead>
|
||||
<TableHead
|
||||
class={`${getPlatformTableHeadClassForKind('numeric-value')} hidden xl:table-cell md:w-[7%]`}
|
||||
>
|
||||
Volumes
|
||||
</TableHead>
|
||||
<TableHead class={`${getPlatformTableHeadClassForKind('badge')} md:w-[7%]`}>
|
||||
<TableHead class={`${getPlatformTableHeadClassForKind('badge')} md:w-[10%]`}>
|
||||
Updates
|
||||
</TableHead>
|
||||
</TableRow>
|
||||
@@ -284,7 +253,6 @@ export const TrueNASAppsTable: Component<{
|
||||
const canRenderMetrics = () => indicator().variant !== 'muted';
|
||||
const ports = createMemo(() => formatPorts(app()));
|
||||
const images = createMemo(() => formatImages(app()));
|
||||
const volumes = createMemo(() => formatVolumes(app()));
|
||||
const detailRowId = () => drawer.detailRowId(resource);
|
||||
const isExpanded = () => drawer.isExpanded(resource);
|
||||
return (
|
||||
@@ -365,13 +333,6 @@ export const TrueNASAppsTable: Component<{
|
||||
{images().label}
|
||||
</span>
|
||||
</TableCell>
|
||||
<TableCell
|
||||
class={`${getPlatformTableCellClassForKind('numeric-value')} hidden xl:table-cell`}
|
||||
>
|
||||
<span class="block truncate" title={volumes().title}>
|
||||
{volumes().label}
|
||||
</span>
|
||||
</TableCell>
|
||||
<TableCell class={getPlatformTableCellClassForKind('badge')}>
|
||||
<UpdatePills app={app()} />
|
||||
</TableCell>
|
||||
@@ -380,7 +341,7 @@ export const TrueNASAppsTable: Component<{
|
||||
resource={resource}
|
||||
open={isExpanded()}
|
||||
detailRowId={detailRowId()}
|
||||
colSpan={9}
|
||||
colSpan={8}
|
||||
resolveResourceLabel={resolveResourceLabel}
|
||||
onClose={() => drawer.close(resource)}
|
||||
/>
|
||||
|
||||
@@ -169,34 +169,29 @@ export const TrueNASNetworkSharesTable: Component<{
|
||||
>
|
||||
<TableCard class={PLATFORM_TABLE_CARD_CLASS}>
|
||||
<TableCardHeader title="Network Shares" />
|
||||
<Table class="min-w-full table-fixed text-xs md:min-w-[1180px]">
|
||||
<Table class="min-w-full table-fixed text-xs md:min-w-[960px]">
|
||||
<TableHeader>
|
||||
<TableRow class={PLATFORM_TABLE_HEADER_ROW_CLASS}>
|
||||
<TableHead class={`${getPlatformTableHeadClassForKind('name')} md:w-[20%]`}>
|
||||
<TableHead class={`${getPlatformTableHeadClassForKind('name')} md:w-[23%]`}>
|
||||
Share
|
||||
</TableHead>
|
||||
<TableHead class={`${getPlatformTableHeadClassForKind('text')} md:w-[8%]`}>
|
||||
<TableHead class={`${getPlatformTableHeadClassForKind('text')} md:w-[11%]`}>
|
||||
Protocol
|
||||
</TableHead>
|
||||
<TableHead
|
||||
class={`${getPlatformTableHeadClassForKind('text')} hidden sm:table-cell md:w-[15%]`}
|
||||
>
|
||||
Dataset
|
||||
</TableHead>
|
||||
<TableHead
|
||||
class={`${getPlatformTableHeadClassForKind('text')} hidden md:table-cell md:w-[23%]`}
|
||||
class={`${getPlatformTableHeadClassForKind('text')} hidden md:table-cell md:w-[27%]`}
|
||||
>
|
||||
Path
|
||||
</TableHead>
|
||||
<TableHead class={`${getPlatformTableHeadClassForKind('text')} md:w-[16%]`}>
|
||||
<TableHead class={`${getPlatformTableHeadClassForKind('text')} md:w-[19%]`}>
|
||||
Access
|
||||
</TableHead>
|
||||
<TableHead
|
||||
class={`${getPlatformTableHeadClassForKind('text')} hidden lg:table-cell md:w-[12%]`}
|
||||
class={`${getPlatformTableHeadClassForKind('text')} hidden lg:table-cell md:w-[13%]`}
|
||||
>
|
||||
Clients
|
||||
</TableHead>
|
||||
<TableHead class={`${getPlatformTableHeadClassForKind('badge')} md:w-[6%]`}>
|
||||
<TableHead class={`${getPlatformTableHeadClassForKind('badge')} md:w-[7%]`}>
|
||||
State
|
||||
</TableHead>
|
||||
</TableRow>
|
||||
@@ -249,13 +244,6 @@ export const TrueNASNetworkSharesTable: Component<{
|
||||
{formatProtocol(share())}
|
||||
</span>
|
||||
</TableCell>
|
||||
<TableCell
|
||||
class={`${getPlatformTableCellClassForKind('text')} hidden text-base-content sm:table-cell`}
|
||||
>
|
||||
<span class="block truncate" title={share()?.dataset}>
|
||||
{share()?.dataset || '-'}
|
||||
</span>
|
||||
</TableCell>
|
||||
<TableCell
|
||||
class={`${getPlatformTableCellClassForKind('text')} hidden text-base-content md:table-cell`}
|
||||
>
|
||||
@@ -293,7 +281,7 @@ export const TrueNASNetworkSharesTable: Component<{
|
||||
resource={resource}
|
||||
open={isExpanded()}
|
||||
detailRowId={detailRowId()}
|
||||
colSpan={7}
|
||||
colSpan={6}
|
||||
resolveResourceLabel={resolveResourceLabel}
|
||||
onClose={() => drawer.close(resource)}
|
||||
/>
|
||||
|
||||
@@ -259,21 +259,21 @@ export const TrueNASStorageTopologyTable: Component<{
|
||||
>
|
||||
<TableCard class={PLATFORM_TABLE_CARD_CLASS}>
|
||||
<TableCardHeader title="Storage Topology" />
|
||||
<Table class="min-w-full table-fixed text-xs md:min-w-[1180px]">
|
||||
<Table class="min-w-full table-fixed text-xs md:min-w-[960px]">
|
||||
<TableHeader>
|
||||
<TableRow class={PLATFORM_TABLE_HEADER_ROW_CLASS}>
|
||||
<TableHead class={`${getPlatformTableHeadClassForKind('name')} md:w-[28%]`}>
|
||||
<TableHead class={`${getPlatformTableHeadClassForKind('name')} md:w-[27%]`}>
|
||||
Resource
|
||||
</TableHead>
|
||||
<TableHead class={`${getPlatformTableHeadClassForKind('text')} md:w-[10%]`}>
|
||||
<TableHead class={`${getPlatformTableHeadClassForKind('text')} md:w-[9%]`}>
|
||||
Kind
|
||||
</TableHead>
|
||||
<TableHead
|
||||
class={`${getPlatformTableHeadClassForKind('text')} hidden sm:table-cell md:w-[11%]`}
|
||||
class={`${getPlatformTableHeadClassForKind('text')} hidden sm:table-cell md:w-[10%]`}
|
||||
>
|
||||
State
|
||||
</TableHead>
|
||||
<TableHead class={`${getPlatformTableHeadClassForKind('metric-bar')} md:w-[21%]`}>
|
||||
<TableHead class={`${getPlatformTableHeadClassForKind('metric-bar')} md:w-[22%]`}>
|
||||
Usage / Size
|
||||
</TableHead>
|
||||
<TableHead
|
||||
@@ -287,11 +287,11 @@ export const TrueNASStorageTopologyTable: Component<{
|
||||
Disks
|
||||
</TableHead>
|
||||
<TableHead
|
||||
class={`${getPlatformTableHeadClassForKind('numeric-value')} hidden lg:table-cell md:w-[7%]`}
|
||||
class={`${getPlatformTableHeadClassForKind('numeric-value')} hidden lg:table-cell md:w-[6%]`}
|
||||
>
|
||||
Temp
|
||||
</TableHead>
|
||||
<TableHead class={`${getPlatformTableHeadClassForKind('badge')} md:w-[7%]`}>
|
||||
<TableHead class={`${getPlatformTableHeadClassForKind('badge')} md:w-[10%]`}>
|
||||
Health
|
||||
</TableHead>
|
||||
</TableRow>
|
||||
|
||||
@@ -163,7 +163,7 @@ export const TrueNASVirtualMachinesTable: Component<{
|
||||
>
|
||||
<TableCard class={PLATFORM_TABLE_CARD_CLASS}>
|
||||
<TableCardHeader title="Virtual Machines" />
|
||||
<Table class="min-w-full table-fixed text-xs md:min-w-[1100px]">
|
||||
<Table class="min-w-full table-fixed text-xs md:min-w-[960px]">
|
||||
<TableHeader>
|
||||
<TableRow class={PLATFORM_TABLE_HEADER_ROW_CLASS}>
|
||||
<TableHead class={`${getPlatformTableHeadClassForKind('name')} md:w-[22%]`}>
|
||||
@@ -235,7 +235,10 @@ export const TrueNASVirtualMachinesTable: Component<{
|
||||
{name()}
|
||||
</div>
|
||||
<div class="truncate text-[10px] text-muted">
|
||||
{vm()?.description || vm()?.uuid || resource.parentName || 'TrueNAS'}
|
||||
{vm()?.description ||
|
||||
vm()?.uuid ||
|
||||
resource.parentName ||
|
||||
'TrueNAS'}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user