Improve infrastructure source column readability

This commit is contained in:
rcourtman 2026-04-23 23:23:34 +01:00
parent 5e620d84d3
commit 517010308d
7 changed files with 70 additions and 25 deletions

View file

@ -81,8 +81,8 @@ export const UnifiedResourcePBSTableSection: Component<UnifiedResourcePBSTableSe
</TableHead>
<TableHead
classList={{ hidden: !table.isServiceVisible('secondary') }}
class={table.sourceColumn().className}
width={table.sourceColumn().width}
class={table.serviceSourceColumn().className}
width={table.serviceSourceColumn().width}
>
{table.headerLabels().source}
</TableHead>

View file

@ -95,8 +95,8 @@ export const UnifiedResourcePMGTableSection: Component<UnifiedResourcePMGTableSe
</TableHead>
<TableHead
classList={{ hidden: !table.isServiceVisible('secondary') }}
class={table.sourceColumn().className}
width={table.sourceColumn().width}
class={table.serviceSourceColumn().className}
width={table.serviceSourceColumn().width}
>
{table.headerLabels().source}
</TableHead>

View file

@ -13,6 +13,9 @@ interface UnifiedResourceSourceBadgeCellProps {
const getVisibleSourceBadgeLimit = (layoutMode: UnifiedResourceTableLayoutMode): number =>
layoutMode === 'wide' ? 3 : 2;
const compactSourceBadgeLabel = (label: string): string =>
label === 'Containers' ? 'Cont' : label;
export const UnifiedResourceSourceBadgeCell: Component<UnifiedResourceSourceBadgeCellProps> = (
props,
) => {
@ -35,29 +38,62 @@ export const UnifiedResourceSourceBadgeCell: Component<UnifiedResourceSourceBadg
.map((badge) => badge.title ?? badge.label)
.join(', '),
);
const summaryBadge = createMemo(() => {
const allBadges = badges();
if (props.layoutMode === 'wide' || allBadges.length === 0) return null;
const badge = allBadges[0];
if (!badge) return null;
const visibleLabels = allBadges
.slice(0, 2)
.map((badge) => compactSourceBadgeLabel(badge.label));
const hiddenCount = allBadges.length - visibleLabels.length;
return {
badge,
label: `${visibleLabels.join('+')}${hiddenCount > 0 ? `+${hiddenCount}` : ''}`,
};
});
return (
<div class="flex min-w-0 max-w-full items-center justify-center gap-1 overflow-hidden">
<For each={visibleBadges()}>
{(badge) => (
<Show
when={summaryBadge()}
fallback={
<>
<For each={visibleBadges()}>
{(badge) => (
<span
class={`${badge.classes} min-w-0 max-w-full overflow-hidden px-1`}
title={badge.title}
>
<span class="min-w-0 truncate">{badge.label}</span>
</span>
)}
</For>
<Show when={hiddenBadgeCount() > 0}>
<span
class="inline-flex min-w-0 max-w-full items-center overflow-hidden rounded bg-surface-alt px-1 py-0.5 text-[10px] font-medium text-muted"
aria-label={`Additional sources: ${hiddenBadges()
.map((badge) => badge.title ?? badge.label)
.join(', ')}`}
title={title()}
>
<span class="min-w-0 truncate">{hiddenBadgeLabel()}</span>
</span>
</Show>
</>
}
>
{(summary) => (
<span
class={`${badge.classes} min-w-0 max-w-full overflow-hidden px-1`}
title={badge.title}
class={`${summary().badge.classes} w-full min-w-0 max-w-full justify-center overflow-hidden px-1.5`}
aria-label={`Sources: ${title()}`}
title={title()}
>
<span class="min-w-0 truncate">{badge.label}</span>
<span class="min-w-0 truncate">{summary().label}</span>
</span>
)}
</For>
<Show when={hiddenBadgeCount() > 0}>
<span
class="inline-flex min-w-0 max-w-full items-center overflow-hidden rounded bg-surface-alt px-1 py-0.5 text-[10px] font-medium text-muted"
aria-label={`Additional sources: ${hiddenBadges()
.map((badge) => badge.title ?? badge.label)
.join(', ')}`}
title={title()}
>
<span class="min-w-0 truncate">{hiddenBadgeLabel()}</span>
</span>
</Show>
</div>
);

View file

@ -270,8 +270,7 @@ describe('UnifiedResourceTable performance contract', () => {
expect(getByText('Src').closest('th')).not.toHaveClass('hidden');
expect(getByText('Up').closest('th')).toHaveClass('hidden');
});
expect(getByText('PBS')).toBeInTheDocument();
expect(getByText('Agent')).toBeInTheDocument();
expect(getByText('PBS+Agent')).toBeInTheDocument();
expect(queryByText('+1')).toBeNull();
emitResizeObserverWidth(660);

View file

@ -130,19 +130,23 @@ describe('unifiedResourceTableStateModel', () => {
expect(mobileColumns.resourceColumn.width).toBe('40%');
expect(mobileColumns.metricColumn.width).toBe('20%');
expect(mobileColumns.serviceResourceColumn.width).toBe('28%');
expect(mobileColumns.serviceSourceColumn.width).toBe('10%');
expect(mobileColumns.serviceCountColumn.width).toBe('11%');
expect(mobileColumns.serviceHealthColumn.width).toBe('13%');
expect(mobileColumns.serviceActionColumn.width).toBe('14%');
expect(tabletColumns.resourceColumn.width).toBe('26%');
expect(tabletColumns.serviceResourceColumn.width).toBe('24%');
expect(tabletColumns.ioColumn.width).toBe('18%');
expect(tabletColumns.sourceColumn.width).toBe('8%');
expect(tabletColumns.sourceColumn.width).toBe('17%');
expect(tabletColumns.serviceSourceColumn.width).toBe('8%');
expect(compactColumns.resourceColumn.width).toBe('18%');
expect(compactColumns.serviceResourceColumn.width).toBe('18%');
expect(compactColumns.metricColumn.width).toBe('10.5%');
expect(compactColumns.serviceSourceColumn.width).toBe('9.5%');
expect(compactColumns.tempColumn.width).toBe('7%');
expect(wideColumns.resourceColumn.width).toBe('18%');
expect(wideColumns.serviceResourceColumn.width).toBe('18%');
expect(wideColumns.serviceSourceColumn.width).toBe('10%');
expect(wideColumns.ioColumn.width).toBe('12.5%');
expect(wideColumns.serviceActionColumn.width).toBe('16%');
expect(getUnifiedResourceTableHeaderLabels('wide').memory).toBe('Memory');

View file

@ -230,6 +230,7 @@ export type UnifiedResourceTableColumnPresentations = {
metricColumn: UnifiedResourceTableColumnPresentation;
ioColumn: UnifiedResourceTableColumnPresentation;
sourceColumn: UnifiedResourceTableColumnPresentation;
serviceSourceColumn: UnifiedResourceTableColumnPresentation;
uptimeColumn: UnifiedResourceTableColumnPresentation;
tempColumn: UnifiedResourceTableColumnPresentation;
serviceCountColumn: UnifiedResourceTableColumnPresentation;
@ -350,7 +351,8 @@ export const getUnifiedResourceTableColumnPresentations = (
serviceResourceColumn: buildUnifiedResourceTableColumnPresentation('', '28%'),
metricColumn: buildUnifiedResourceTableColumnPresentation('', '20%'),
ioColumn: buildUnifiedResourceTableColumnPresentation('', '20%'),
sourceColumn: buildUnifiedResourceTableColumnPresentation('', '10%'),
sourceColumn: buildUnifiedResourceTableColumnPresentation('', '20%'),
serviceSourceColumn: buildUnifiedResourceTableColumnPresentation('', '10%'),
uptimeColumn: buildUnifiedResourceTableColumnPresentation('', '8%'),
tempColumn: buildUnifiedResourceTableColumnPresentation('', '15%'),
serviceCountColumn: buildUnifiedResourceTableColumnPresentation('', '11%'),
@ -366,7 +368,8 @@ export const getUnifiedResourceTableColumnPresentations = (
serviceResourceColumn: buildUnifiedResourceTableColumnPresentation('', '24%'),
metricColumn: buildUnifiedResourceTableColumnPresentation('', '13%'),
ioColumn: buildUnifiedResourceTableColumnPresentation('', '18%'),
sourceColumn: buildUnifiedResourceTableColumnPresentation('', '8%'),
sourceColumn: buildUnifiedResourceTableColumnPresentation('', '17%'),
serviceSourceColumn: buildUnifiedResourceTableColumnPresentation('', '8%'),
uptimeColumn: buildUnifiedResourceTableColumnPresentation('', '7%'),
tempColumn: buildUnifiedResourceTableColumnPresentation('', '6%'),
serviceCountColumn: buildUnifiedResourceTableColumnPresentation('', '8%'),
@ -383,6 +386,7 @@ export const getUnifiedResourceTableColumnPresentations = (
metricColumn: buildUnifiedResourceTableColumnPresentation('', '10.5%'),
ioColumn: buildUnifiedResourceTableColumnPresentation('', '13%'),
sourceColumn: buildUnifiedResourceTableColumnPresentation('', '9.5%'),
serviceSourceColumn: buildUnifiedResourceTableColumnPresentation('', '9.5%'),
uptimeColumn: buildUnifiedResourceTableColumnPresentation('', '8%'),
tempColumn: buildUnifiedResourceTableColumnPresentation('', '7%'),
serviceCountColumn: buildUnifiedResourceTableColumnPresentation('', '9.5%'),
@ -398,6 +402,7 @@ export const getUnifiedResourceTableColumnPresentations = (
metricColumn: buildUnifiedResourceTableColumnPresentation('', '10.5%'),
ioColumn: buildUnifiedResourceTableColumnPresentation('', '12.5%'),
sourceColumn: buildUnifiedResourceTableColumnPresentation('', '10%'),
serviceSourceColumn: buildUnifiedResourceTableColumnPresentation('', '10%'),
uptimeColumn: buildUnifiedResourceTableColumnPresentation('', '8%'),
tempColumn: buildUnifiedResourceTableColumnPresentation('', '7.5%'),
serviceCountColumn: buildUnifiedResourceTableColumnPresentation('', '8.5%'),

View file

@ -233,6 +233,7 @@ export function useUnifiedResourceTableState(props: UnifiedResourceTableProps) {
metricColumn: () => columnPresentations().metricColumn,
ioColumn: () => columnPresentations().ioColumn,
sourceColumn: () => columnPresentations().sourceColumn,
serviceSourceColumn: () => columnPresentations().serviceSourceColumn,
uptimeColumn: () => columnPresentations().uptimeColumn,
tempColumn: () => columnPresentations().tempColumn,
showHostTable,