mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-22 12:36:07 +00:00
fix(frontend): stabilize speed tags on inbound and client pages (#5930)
* fix(frontend): add shared stable speed-tag style Give live up/down rate tags a fixed width, centered layout, nowrap, and tabular numerals so digit/unit changes cannot reflow the Speed column. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix(frontend): stabilize InboundSpeedTag and ClientSpeedTag layout Apply the shared speed-tag class/style to both live rate tags and lock the behavior with a focused component test for small and large rates. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix(frontend): align speed columns with stable tag width Widen inbound/client Speed columns to match the fixed tag and apply the same stable style to idle dash cells so active/idle swaps do not jitter. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix(frontend): scope stable speed tags to table cells and fit content --------- Co-authored-by: x06579 <x06579@ai-dashboard> Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -67,6 +67,7 @@ import AppSidebar from '@/layouts/AppSidebar';
|
||||
import { IntlUtil, SizeFormatter } from '@/utils';
|
||||
import { setMessageInstance } from '@/utils/messageBus';
|
||||
import { LazyMount } from '@/components/utility';
|
||||
import { SPEED_COLUMN_WIDTH, SPEED_TAG_CLASS_NAME, SPEED_TAG_STYLE } from '@/components/utility/speedTagStyle';
|
||||
const ClientFormModal = lazy(() => import('./ClientFormModal'));
|
||||
const ClientInfoModal = lazy(() => import('./ClientInfoModal'));
|
||||
const ClientQrModal = lazy(() => import('./ClientQrModal'));
|
||||
@@ -908,12 +909,14 @@ export default function ClientsPage() {
|
||||
{
|
||||
title: t('pages.clients.speed'),
|
||||
key: 'speed',
|
||||
width: 110,
|
||||
width: SPEED_COLUMN_WIDTH,
|
||||
align: 'center',
|
||||
render: (_v, record) => {
|
||||
const speed = clientSpeed[record.email];
|
||||
if (!isActiveSpeed(speed)) return <Tag color="default">—</Tag>;
|
||||
return <ClientSpeedTag speed={speed} />;
|
||||
if (!isActiveSpeed(speed)) {
|
||||
return <Tag color="default" className={SPEED_TAG_CLASS_NAME} style={SPEED_TAG_STYLE}>—</Tag>;
|
||||
}
|
||||
return <ClientSpeedTag speed={speed} tableCell />;
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Tag, Tooltip } from 'antd';
|
||||
|
||||
import { SizeFormatter } from '@/utils';
|
||||
import { SPEED_TAG_CLASS_NAME, SPEED_TAG_STYLE } from '@/components/utility/speedTagStyle';
|
||||
|
||||
import type { InboundSpeedEntry } from './types';
|
||||
|
||||
@@ -12,12 +13,17 @@ export function isActiveSpeed(speed?: InboundSpeedEntry): speed is InboundSpeedE
|
||||
interface InboundSpeedTagProps {
|
||||
speed: InboundSpeedEntry;
|
||||
withTooltip?: boolean;
|
||||
tableCell?: boolean;
|
||||
}
|
||||
|
||||
// Blue "↑ up / ↓ down" rate tag, optionally with a stacked breakdown tooltip.
|
||||
export function InboundSpeedTag({ speed, withTooltip = false }: InboundSpeedTagProps) {
|
||||
export function InboundSpeedTag({ speed, withTooltip = false, tableCell = false }: InboundSpeedTagProps) {
|
||||
const tag = (
|
||||
<Tag color="blue">
|
||||
<Tag
|
||||
color="blue"
|
||||
className={tableCell ? SPEED_TAG_CLASS_NAME : undefined}
|
||||
style={tableCell ? SPEED_TAG_STYLE : undefined}
|
||||
>
|
||||
↑ {SizeFormatter.speedFormat(speed.up)}
|
||||
{' / '}
|
||||
↓ {SizeFormatter.speedFormat(speed.down)}
|
||||
|
||||
@@ -10,6 +10,7 @@ import type { NodeRecord } from '@/api/queries/useNodesQuery';
|
||||
import { coerceInboundJsonField } from '@/models/dbinbound';
|
||||
|
||||
import { RowActionsCell } from './RowActions';
|
||||
import { SPEED_COLUMN_WIDTH, SPEED_TAG_CLASS_NAME, SPEED_TAG_STYLE } from '@/components/utility/speedTagStyle';
|
||||
import { InboundSpeedTag, isActiveSpeed } from './InboundSpeedTag';
|
||||
import {
|
||||
readStreamHints,
|
||||
@@ -324,14 +325,14 @@ export function useInboundColumns({
|
||||
title: t('pages.inbounds.speed'),
|
||||
key: 'speed',
|
||||
align: 'center',
|
||||
width: 110,
|
||||
width: SPEED_COLUMN_WIDTH,
|
||||
sorter: (a, b) => speedTotal(a) - speedTotal(b),
|
||||
render: (_, record) => {
|
||||
const speed = inboundSpeed[record.id];
|
||||
if (!isActiveSpeed(speed)) {
|
||||
return <Tag color='default'>—</Tag>;
|
||||
return <Tag color="default" className={SPEED_TAG_CLASS_NAME} style={SPEED_TAG_STYLE}>—</Tag>;
|
||||
}
|
||||
return <InboundSpeedTag speed={speed} withTooltip />;
|
||||
return <InboundSpeedTag speed={speed} withTooltip tableCell />;
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user