mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-04-28 03:20:11 +00:00
feat(mobile): improve table layouts for remaining pages
- Add horizontal scrolling to Hosts table with 900px min-width - Add horizontal scrolling to Ceph tables with 700/650px min-widths - Tighten padding on Storage tables for compact mobile display - Add min-width to DiskList table for physical disks - Add min-width to Settings tables (PVE, PBS, PMG, Agents) - Add horizontal scroll container to Alerts patrol run table - Hide scrollbars across all scrollable tables for cleaner UI
This commit is contained in:
parent
be0d777158
commit
4f4fdcf81b
7 changed files with 61 additions and 58 deletions
|
|
@ -748,7 +748,7 @@ export const HostsOverview: Component = () => {
|
|||
|
||||
|
||||
|
||||
const thClass = "px-2 py-1 text-center text-[11px] sm:text-xs font-medium uppercase tracking-wider cursor-pointer hover:bg-gray-200 dark:hover:bg-gray-600 whitespace-nowrap";
|
||||
const thClass = "px-1.5 py-1 text-center text-[11px] sm:text-xs font-medium uppercase tracking-wider cursor-pointer hover:bg-gray-200 dark:hover:bg-gray-600 whitespace-nowrap";
|
||||
|
||||
return (
|
||||
<div class="space-y-4">
|
||||
|
|
@ -859,8 +859,9 @@ export const HostsOverview: Component = () => {
|
|||
}
|
||||
>
|
||||
<Card padding="none" tone="glass" class="overflow-hidden">
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full border-collapse whitespace-nowrap">
|
||||
<div class="overflow-x-auto" style="scrollbar-width: none; -ms-overflow-style: none;">
|
||||
<style>{`.overflow-x-auto::-webkit-scrollbar { display: none; }`}</style>
|
||||
<table class="w-full border-collapse whitespace-nowrap" style={{ "min-width": "900px" }}>
|
||||
<thead>
|
||||
<tr class="bg-gray-50 dark:bg-gray-700/50 text-gray-600 dark:text-gray-300 border-b border-gray-200 dark:border-gray-700">
|
||||
{/* Essential columns */}
|
||||
|
|
|
|||
|
|
@ -292,7 +292,7 @@ const findMatchingHostAgent = (
|
|||
export const PveNodesTable: Component<PveNodesTableProps> = (props) => {
|
||||
return (
|
||||
<Card padding="none" tone="glass" class="overflow-x-auto rounded-lg">
|
||||
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700 text-sm">
|
||||
<table class="min-w-[800px] divide-y divide-gray-200 dark:divide-gray-700 text-sm">
|
||||
<thead class="bg-gray-50 dark:bg-gray-800/70">
|
||||
<tr>
|
||||
<th scope="col" class="py-2 pl-4 pr-3 text-left text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400">
|
||||
|
|
@ -594,7 +594,7 @@ const resolvePbsStatusMeta = (
|
|||
export const PbsNodesTable: Component<PbsNodesTableProps> = (props) => {
|
||||
return (
|
||||
<Card padding="none" tone="glass" class="overflow-x-auto rounded-lg">
|
||||
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700 text-sm">
|
||||
<table class="min-w-[800px] divide-y divide-gray-200 dark:divide-gray-700 text-sm">
|
||||
<thead class="bg-gray-50 dark:bg-gray-800/70">
|
||||
<tr>
|
||||
<th scope="col" class="py-2 pl-4 pr-3 text-left text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400">
|
||||
|
|
@ -790,7 +790,7 @@ const resolvePmgStatusMeta = (
|
|||
export const PmgNodesTable: Component<PmgNodesTableProps> = (props) => {
|
||||
return (
|
||||
<Card padding="none" tone="glass" class="overflow-x-auto rounded-lg">
|
||||
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700 text-sm">
|
||||
<table class="min-w-[800px] divide-y divide-gray-200 dark:divide-gray-700 text-sm">
|
||||
<thead class="bg-gray-50 dark:bg-gray-800/70">
|
||||
<tr>
|
||||
<th scope="col" class="py-2 pl-4 pr-3 text-left text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400">
|
||||
|
|
|
|||
|
|
@ -900,8 +900,8 @@ export const UnifiedAgents: Component = () => {
|
|||
</div>
|
||||
</Show>
|
||||
|
||||
<Card padding="none" tone="glass" class="overflow-hidden rounded-lg">
|
||||
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
|
||||
<Card padding="none" tone="glass" class="overflow-x-auto rounded-lg">
|
||||
<table class="min-w-[800px] divide-y divide-gray-200 dark:divide-gray-700">
|
||||
<thead class="bg-gray-50 dark:bg-gray-800">
|
||||
<tr>
|
||||
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-400">Hostname</th>
|
||||
|
|
@ -1031,8 +1031,8 @@ export const UnifiedAgents: Component = () => {
|
|||
</p>
|
||||
</div>
|
||||
|
||||
<Card padding="none" tone="glass" class="overflow-hidden rounded-lg">
|
||||
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
|
||||
<Card padding="none" tone="glass" class="overflow-x-auto rounded-lg">
|
||||
<table class="min-w-[800px] divide-y divide-gray-200 dark:divide-gray-700">
|
||||
<thead class="bg-gray-50 dark:bg-gray-800">
|
||||
<tr>
|
||||
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-400">Cluster</th>
|
||||
|
|
@ -1094,8 +1094,8 @@ export const UnifiedAgents: Component = () => {
|
|||
</p>
|
||||
</div>
|
||||
|
||||
<Card padding="none" tone="glass" class="overflow-hidden rounded-lg">
|
||||
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
|
||||
<Card padding="none" tone="glass" class="overflow-x-auto rounded-lg">
|
||||
<table class="min-w-[800px] divide-y divide-gray-200 dark:divide-gray-700">
|
||||
<thead class="bg-gray-50 dark:bg-gray-800">
|
||||
<tr>
|
||||
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-400">Hostname</th>
|
||||
|
|
@ -1143,8 +1143,8 @@ export const UnifiedAgents: Component = () => {
|
|||
</p>
|
||||
</div>
|
||||
|
||||
<Card padding="none" tone="glass" class="overflow-hidden rounded-lg">
|
||||
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
|
||||
<Card padding="none" tone="glass" class="overflow-x-auto rounded-lg">
|
||||
<table class="min-w-[800px] divide-y divide-gray-200 dark:divide-gray-700">
|
||||
<thead class="bg-gray-50 dark:bg-gray-800">
|
||||
<tr>
|
||||
<th scope="col" class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-400">Cluster</th>
|
||||
|
|
|
|||
|
|
@ -151,37 +151,37 @@ export const DiskList: Component<DiskListProps> = (props) => {
|
|||
<Show when={filteredDisks().length > 0}>
|
||||
<Card padding="none" tone="glass" class="overflow-hidden">
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full">
|
||||
<table class="w-full" style={{ "min-width": "750px" }}>
|
||||
<thead>
|
||||
<tr class="bg-gray-50 dark:bg-gray-700/50 text-gray-600 dark:text-gray-300 border-b border-gray-200 dark:border-gray-600">
|
||||
<th class="px-2 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider w-[10%]">
|
||||
<th class="px-1 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider w-[10%]">
|
||||
Node
|
||||
</th>
|
||||
<th class="px-2 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider w-[10%]">
|
||||
<th class="px-1 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider w-[10%]">
|
||||
Device
|
||||
</th>
|
||||
<th class="hidden md:table-cell px-2 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider w-[20%]">
|
||||
<th class="px-1 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider w-[20%]">
|
||||
Model
|
||||
</th>
|
||||
<th class="hidden sm:table-cell px-2 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider w-[8%]">
|
||||
<th class="px-1 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider w-[8%]">
|
||||
Type
|
||||
</th>
|
||||
<th class="hidden lg:table-cell px-2 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider w-[8%]">
|
||||
<th class="px-1 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider w-[8%]">
|
||||
FS
|
||||
</th>
|
||||
<th class="px-2 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider w-[10%]">
|
||||
<th class="px-1 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider w-[10%]">
|
||||
Health
|
||||
</th>
|
||||
<th class="hidden md:table-cell px-2 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider w-[15%]">
|
||||
<th class="px-1 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider w-[15%]">
|
||||
SSD Life
|
||||
</th>
|
||||
<th class="px-2 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider hidden sm:table-cell w-[8%]">
|
||||
<th class="px-1 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider w-[8%]">
|
||||
Temp
|
||||
</th>
|
||||
<th class="px-2 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider w-[10%]">
|
||||
<th class="px-1 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider w-[10%]">
|
||||
Size
|
||||
</th>
|
||||
<th class="px-2 py-1.5 w-8"></th>
|
||||
<th class="px-1 py-1.5 w-8"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-200 dark:divide-gray-700">
|
||||
|
|
@ -192,29 +192,29 @@ export const DiskList: Component<DiskListProps> = (props) => {
|
|||
return (
|
||||
<>
|
||||
<tr class="hover:bg-gray-50 dark:hover:bg-gray-700/30 transition-colors">
|
||||
<td class="px-2 py-1.5 text-xs">
|
||||
<td class="px-1 py-1.5 text-xs">
|
||||
<span class="font-medium text-gray-900 dark:text-gray-100">
|
||||
{disk.node}
|
||||
</span>
|
||||
</td>
|
||||
<td class="px-2 py-1.5 text-xs">
|
||||
<td class="px-1 py-1.5 text-xs">
|
||||
<span class="font-mono text-gray-600 dark:text-gray-400">
|
||||
{disk.devPath}
|
||||
</span>
|
||||
</td>
|
||||
<td class="hidden md:table-cell px-2 py-1.5 text-xs">
|
||||
<td class="px-1 py-1.5 text-xs">
|
||||
<span class="text-gray-700 dark:text-gray-300">
|
||||
{disk.model || 'Unknown'}
|
||||
</span>
|
||||
</td>
|
||||
<td class="hidden sm:table-cell px-2 py-1.5 text-xs">
|
||||
<td class="px-1 py-1.5 text-xs">
|
||||
<span
|
||||
class={`inline-block px-1.5 py-0.5 text-[10px] font-medium rounded ${getDiskTypeBadge(disk.type)}`}
|
||||
>
|
||||
{disk.type.toUpperCase()}
|
||||
</span>
|
||||
</td>
|
||||
<td class="hidden lg:table-cell px-2 py-1.5 text-xs">
|
||||
<td class="px-1 py-1.5 text-xs">
|
||||
<Show
|
||||
when={disk.used && disk.used !== 'unknown'}
|
||||
fallback={<span class="text-gray-400">-</span>}
|
||||
|
|
@ -224,14 +224,14 @@ export const DiskList: Component<DiskListProps> = (props) => {
|
|||
</span>
|
||||
</Show>
|
||||
</td>
|
||||
<td class="px-2 py-1.5 text-xs">
|
||||
<td class="px-1 py-1.5 text-xs">
|
||||
<span
|
||||
class={`inline-block px-1.5 py-0.5 text-[10px] font-medium rounded ${health.bgColor} ${health.color}`}
|
||||
>
|
||||
{health.text}
|
||||
</span>
|
||||
</td>
|
||||
<td class="hidden md:table-cell px-2 py-1.5 text-xs">
|
||||
<td class="px-1 py-1.5 text-xs">
|
||||
<Show
|
||||
when={disk.wearout > 0}
|
||||
fallback={<span class="text-gray-400">-</span>}
|
||||
|
|
@ -254,7 +254,7 @@ export const DiskList: Component<DiskListProps> = (props) => {
|
|||
</div>
|
||||
</Show>
|
||||
</td>
|
||||
<td class="px-2 py-1.5 text-xs hidden sm:table-cell">
|
||||
<td class="px-1 py-1.5 text-xs">
|
||||
<Show
|
||||
when={typeof disk.temperature === 'number' && disk.temperature !== 0}
|
||||
fallback={<span class="font-medium text-gray-400">-</span>}
|
||||
|
|
@ -271,12 +271,12 @@ export const DiskList: Component<DiskListProps> = (props) => {
|
|||
</span>
|
||||
</Show>
|
||||
</td>
|
||||
<td class="px-2 py-1.5 text-xs">
|
||||
<td class="px-1 py-1.5 text-xs">
|
||||
<span class="text-gray-700 dark:text-gray-300">
|
||||
{formatBytes(disk.size)}
|
||||
</span>
|
||||
</td>
|
||||
<td class="px-2 py-1.5"></td>
|
||||
<td class="px-1 py-1.5"></td>
|
||||
</tr>
|
||||
</>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -788,36 +788,36 @@ const Storage: Component = () => {
|
|||
<style>{`
|
||||
.overflow-x-auto::-webkit-scrollbar { display: none; }
|
||||
`}</style>
|
||||
<table class="w-full" style={{ "min-width": "900px" }}>
|
||||
<table class="w-full" style={{ "min-width": "750px" }}>
|
||||
<thead>
|
||||
<tr class="bg-gray-50 dark:bg-gray-700/50 text-gray-600 dark:text-gray-300 border-b border-gray-200 dark:border-gray-600">
|
||||
<th class="px-2 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider w-auto">
|
||||
<th class="px-1.5 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider w-auto">
|
||||
Storage
|
||||
</th>
|
||||
<th class="px-2 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider w-[10%]">
|
||||
<th class="px-1.5 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider w-[10%]">
|
||||
Type
|
||||
</th>
|
||||
<th class="px-2 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider w-[15%]">
|
||||
<th class="px-1.5 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider w-[15%]">
|
||||
Content
|
||||
</th>
|
||||
<th class="px-2 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider w-[10%]">
|
||||
<th class="px-1.5 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider w-[10%]">
|
||||
Status
|
||||
</th>
|
||||
<Show when={viewMode() === 'node'}>
|
||||
<th class="px-2 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider w-[8%]">
|
||||
<th class="px-1.5 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider w-[6%]">
|
||||
Shared
|
||||
</th>
|
||||
</Show>
|
||||
<th class="px-2 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider w-[25%] min-w-[150px]">
|
||||
<th class="px-1.5 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider w-[25%] min-w-[120px]">
|
||||
Usage
|
||||
</th>
|
||||
<th class="px-2 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider w-[10%]">
|
||||
<th class="px-1.5 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider w-[10%]">
|
||||
Free
|
||||
</th>
|
||||
<th class="px-2 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider w-[10%]">
|
||||
<th class="px-1.5 py-1.5 text-left text-[11px] sm:text-xs font-medium uppercase tracking-wider w-[10%]">
|
||||
Total
|
||||
</th>
|
||||
<th class="px-2 py-1.5 w-8"></th>
|
||||
<th class="px-1.5 py-1.5 w-8"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-200 dark:divide-gray-700">
|
||||
|
|
@ -1064,12 +1064,12 @@ const Storage: Component = () => {
|
|||
const firstCellClass = createMemo(() => {
|
||||
if (viewMode() === 'node') {
|
||||
return firstCellHasIndicator()
|
||||
? 'p-0.5 pl-7 pr-1.5'
|
||||
: 'p-0.5 pl-8 pr-1.5';
|
||||
? 'p-0.5 pl-6 pr-1.5'
|
||||
: 'p-0.5 pl-7 pr-1.5';
|
||||
}
|
||||
return firstCellHasIndicator()
|
||||
? 'p-0.5 pl-3 pr-1.5'
|
||||
: 'p-0.5 pl-3 pr-1.5';
|
||||
? 'p-0.5 pl-2 pr-1.5'
|
||||
: 'p-0.5 pl-2 pr-1.5';
|
||||
});
|
||||
|
||||
const toggleDrawer = () => {
|
||||
|
|
@ -1088,9 +1088,9 @@ const Storage: Component = () => {
|
|||
aria-expanded={canExpand() && isExpanded() ? 'true' : 'false'}
|
||||
>
|
||||
<td class={`${firstCellClass()} align-middle`}>
|
||||
<div class="flex items-center gap-2 min-w-0">
|
||||
<div class="flex items-center gap-1.5 min-w-0">
|
||||
<span
|
||||
class={`text-sm font-medium text-gray-900 dark:text-gray-100 truncate ${canExpand() ? 'max-w-[180px]' : 'max-w-[200px]'
|
||||
class={`text-xs sm:text-sm font-medium text-gray-900 dark:text-gray-100 truncate ${canExpand() ? 'max-w-[140px] sm:max-w-[180px]' : 'max-w-[160px] sm:max-w-[200px]'
|
||||
}`}
|
||||
title={storage.name}
|
||||
>
|
||||
|
|
@ -1098,7 +1098,7 @@ const Storage: Component = () => {
|
|||
</span>
|
||||
{/* ZFS Health Map */}
|
||||
<Show when={zfsPool && zfsPool.devices && zfsPool.devices.length > 0}>
|
||||
<div class="mx-1.5">
|
||||
<div class="mx-1">
|
||||
<ZFSHealthMap pool={zfsPool!} />
|
||||
</div>
|
||||
</Show>
|
||||
|
|
|
|||
|
|
@ -3370,8 +3370,8 @@ function OverviewTab(props: {
|
|||
<p class="text-sm text-gray-500 dark:text-gray-400 italic py-4">No patrol runs in selected time range.</p>
|
||||
}
|
||||
>
|
||||
<div class="border border-gray-200 dark:border-gray-700 rounded overflow-hidden">
|
||||
<table class="w-full text-xs sm:text-sm">
|
||||
<div class="border border-gray-200 dark:border-gray-700 rounded overflow-x-auto">
|
||||
<table class="w-full min-w-[600px] text-xs sm:text-sm">
|
||||
<thead>
|
||||
<tr class="bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300 border-b border-gray-300 dark:border-gray-600">
|
||||
<th class="p-1.5 px-2 text-left text-[10px] sm:text-xs font-medium uppercase tracking-wider w-4"></th>
|
||||
|
|
|
|||
|
|
@ -488,8 +488,9 @@ const Ceph: Component = () => {
|
|||
Cluster Overview
|
||||
</h3>
|
||||
</div>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full border-collapse whitespace-nowrap">
|
||||
<div class="overflow-x-auto" style="scrollbar-width: none; -ms-overflow-style: none;">
|
||||
<style>{`.overflow-x-auto::-webkit-scrollbar { display: none; }`}</style>
|
||||
<table class="w-full border-collapse whitespace-nowrap" style={{ "min-width": "700px" }}>
|
||||
<thead>
|
||||
<tr class="bg-gray-50 dark:bg-gray-700/50 text-gray-600 dark:text-gray-300 border-b border-gray-200 dark:border-gray-700">
|
||||
<th class={`${thClass} pl-4`}>Cluster</th>
|
||||
|
|
@ -612,8 +613,9 @@ const Ceph: Component = () => {
|
|||
</div>
|
||||
}
|
||||
>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full border-collapse whitespace-nowrap">
|
||||
<div class="overflow-x-auto" style="scrollbar-width: none; -ms-overflow-style: none;">
|
||||
<style>{`.overflow-x-auto::-webkit-scrollbar { display: none; }`}</style>
|
||||
<table class="w-full border-collapse whitespace-nowrap" style={{ "min-width": "650px" }}>
|
||||
<thead>
|
||||
<tr class="bg-gray-50 dark:bg-gray-700/50 text-gray-600 dark:text-gray-300 border-b border-gray-200 dark:border-gray-700">
|
||||
<th class={`${thClass} pl-4`}>Pool</th>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue