mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-08-12 17:44:14 +08:00
🎨 style(redis): 扁平化工作台并修正分隔与悬浮细节
- 将 V2 Redis 工作台改为连续网格布局并移除卡牌边框与阴影 - 让左右面板分隔线跨行对齐并同步网格宽度变量 - 扩大分隔线拖动热区且保持视觉线宽为 1px - 优化长 Key 省略布局和悬浮查看触发区域 Refs #727
This commit is contained in:
@@ -113,6 +113,8 @@ describe('RedisResizableDivider interaction cleanup', () => {
|
||||
});
|
||||
|
||||
it('removes the full-screen overlay and commits the width when the window blurs', () => {
|
||||
expect(renderer?.root.findByType('div').props.className).toBe('redis-resizable-divider');
|
||||
|
||||
startResize();
|
||||
expect(overlays).toHaveLength(1);
|
||||
|
||||
@@ -142,6 +144,33 @@ describe('RedisResizableDivider interaction cleanup', () => {
|
||||
expect(onResizeEnd).toHaveBeenCalledWith(420);
|
||||
});
|
||||
|
||||
it('updates a container grid width variable while dragging', () => {
|
||||
const setProperty = vi.fn();
|
||||
target.parentElement = { offsetWidth: 1200, style: { setProperty } } as any;
|
||||
act(() => {
|
||||
renderer?.unmount();
|
||||
renderer = create(
|
||||
<RedisResizableDivider
|
||||
targetRef={{ current: target } as React.RefObject<HTMLDivElement>}
|
||||
onResizeEnd={onResizeEnd}
|
||||
maxReservedWidth={361}
|
||||
containerWidthCssVariable="--redis-sidebar-width"
|
||||
title="resize"
|
||||
/>,
|
||||
);
|
||||
});
|
||||
|
||||
startResize();
|
||||
act(() => fakeDocument.dispatch('mousemove', {
|
||||
buttons: 1,
|
||||
clientX: 520,
|
||||
preventDefault: vi.fn(),
|
||||
}));
|
||||
|
||||
expect(setProperty).toHaveBeenCalledWith('--redis-sidebar-width', '540px');
|
||||
expect(target.style.width).toBe('');
|
||||
});
|
||||
|
||||
it('removes the overlay without updating state when unmounted mid-resize', () => {
|
||||
startResize();
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ type RedisResizableDividerProps = {
|
||||
onResizeEnd: (newWidth: number) => void;
|
||||
targetRef: React.RefObject<HTMLDivElement>;
|
||||
minWidth?: number;
|
||||
maxReservedWidth?: number;
|
||||
containerWidthCssVariable?: `--${string}`;
|
||||
title: string;
|
||||
};
|
||||
|
||||
@@ -12,6 +14,8 @@ const RedisResizableDivider: React.FC<RedisResizableDividerProps> = ({
|
||||
onResizeEnd,
|
||||
targetRef,
|
||||
minWidth = 300,
|
||||
maxReservedWidth = 350,
|
||||
containerWidthCssVariable,
|
||||
title,
|
||||
}) => {
|
||||
const abortInteractionRef = useRef<(() => void) | null>(null);
|
||||
@@ -31,8 +35,9 @@ const RedisResizableDivider: React.FC<RedisResizableDividerProps> = ({
|
||||
|
||||
const startX = event.clientX;
|
||||
const startWidth = target.offsetWidth;
|
||||
const containerWidth = target.parentElement?.offsetWidth || window.innerWidth;
|
||||
const maxWidth = containerWidth - 350;
|
||||
const container = target.parentElement;
|
||||
const containerWidth = container?.offsetWidth || window.innerWidth;
|
||||
const maxWidth = containerWidth - maxReservedWidth;
|
||||
const overlay = document.createElement('div');
|
||||
overlay.style.cssText = 'position:fixed;top:0;left:0;right:0;bottom:0;cursor:col-resize;z-index:9999;';
|
||||
document.body.appendChild(overlay);
|
||||
@@ -63,8 +68,12 @@ const RedisResizableDivider: React.FC<RedisResizableDividerProps> = ({
|
||||
moveEvent.preventDefault();
|
||||
const delta = moveEvent.clientX - startX;
|
||||
currentWidth = Math.max(minWidth, Math.min(maxWidth, startWidth + delta));
|
||||
target.style.width = `${currentWidth}px`;
|
||||
target.style.flexBasis = `${currentWidth}px`;
|
||||
if (containerWidthCssVariable && container) {
|
||||
container.style.setProperty(containerWidthCssVariable, `${currentWidth}px`);
|
||||
} else {
|
||||
target.style.width = `${currentWidth}px`;
|
||||
target.style.flexBasis = `${currentWidth}px`;
|
||||
}
|
||||
};
|
||||
|
||||
abortInteractionRef.current = abortInteraction;
|
||||
@@ -75,6 +84,7 @@ const RedisResizableDivider: React.FC<RedisResizableDividerProps> = ({
|
||||
|
||||
return (
|
||||
<div
|
||||
className="redis-resizable-divider"
|
||||
onMouseDown={handleMouseDown}
|
||||
style={{
|
||||
width: 5,
|
||||
|
||||
@@ -341,13 +341,18 @@ describe('RedisViewer tree interactions', () => {
|
||||
await flushEffects();
|
||||
|
||||
const header = renderer!.root.findByProps({ className: 'redis-key-detail-header' });
|
||||
const top = renderer!.root.findByProps({ className: 'redis-key-detail-top' });
|
||||
const viewMode = renderer!.root.findByProps({ className: 'redis-key-view-mode' });
|
||||
const summary = renderer!.root.findByProps({ className: 'redis-key-detail-summary' });
|
||||
const identity = renderer!.root.findByProps({ className: 'redis-key-detail-identity' });
|
||||
const metadata = renderer!.root.findByProps({ className: 'redis-key-detail-metadata' });
|
||||
const actions = renderer!.root.findByProps({ className: 'redis-key-detail-actions' });
|
||||
|
||||
expect(header.props.style).toMatchObject({ flexDirection: 'column' });
|
||||
expect(header.parent).toBe(top);
|
||||
expect(viewMode.parent).toBe(top);
|
||||
expect(summary.props.style).toMatchObject({ minWidth: 0, width: '100%' });
|
||||
expect(identity.props.style).toMatchObject({ minWidth: 0, width: '100%' });
|
||||
expect(identity.parent).toBe(summary);
|
||||
expect(metadata.parent).toBe(summary);
|
||||
expect(actions.parent).toBe(summary);
|
||||
@@ -358,6 +363,9 @@ describe('RedisViewer tree interactions', () => {
|
||||
flexWrap: 'wrap',
|
||||
maxWidth: '100%',
|
||||
});
|
||||
const activeKey = renderer!.root.findByProps({ 'data-redis-active-key': 'true' });
|
||||
expect(activeKey.props.style).toMatchObject({ flex: '0 1 auto', minWidth: 0, textOverflow: 'ellipsis' });
|
||||
expect(activeKey.props.style).not.toHaveProperty('maxWidth');
|
||||
expect(findButtonByText(renderer!, 'Set TTL')).toBeTruthy();
|
||||
expect(findButtonByText(renderer!, 'Refresh')).toBeTruthy();
|
||||
expect(findButtonByText(renderer!, 'Delete Key')).toBeTruthy();
|
||||
|
||||
@@ -2131,58 +2131,60 @@ const RedisViewer: React.FC<RedisViewerProps> = ({ connectionId, redisDB }) => {
|
||||
|
||||
return (
|
||||
<div className={isV2Ui ? 'gn-v2-redis-value-layout' : undefined} style={{ height: '100%', display: 'flex', flexDirection: 'column', gap: 12 }}>
|
||||
<div className={`redis-key-detail-header${isV2Ui ? ' gn-v2-redis-value-header' : ''}`} style={{ ...workbenchCardStyle, padding: 18, display: 'flex', flexDirection: 'column', gap: 16, flexShrink: 0 }}>
|
||||
<div className="redis-key-detail-summary" style={{ display: 'flex', flexDirection: 'column', gap: 10, minWidth: 0, width: '100%' }}>
|
||||
<span style={{ fontSize: 12, textTransform: 'uppercase', letterSpacing: '.08em', color: workbenchTheme.textMuted, fontWeight: 600 }}>
|
||||
{tr('redis_viewer.title.active_key')}
|
||||
</span>
|
||||
<div className="redis-key-detail-identity" style={{ display: 'flex', alignItems: 'center', gap: 8, minWidth: 0 }}>
|
||||
<Tooltip title={selectedKey}>
|
||||
<strong style={{ maxWidth: 340, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', fontSize: 26, color: workbenchTheme.textPrimary }}>
|
||||
{selectedKey}
|
||||
</strong>
|
||||
</Tooltip>
|
||||
<Tooltip title={tr('redis_viewer.tooltip.copy_key_name')}>
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
icon={<CopyOutlined />}
|
||||
style={{ padding: '0 4px', display: 'flex', alignItems: 'center', color: workbenchTheme.textMuted }}
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(selectedKey).then(() => {
|
||||
message.success(tr('redis_viewer.message.key_name_copied'));
|
||||
}).catch(() => {
|
||||
message.error(tr('redis_viewer.message.copy_failed'));
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div className="redis-key-detail-metadata" style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap', minWidth: 0 }}>
|
||||
<Tag color={getTypeColor(keyValue.type)} style={pillTagStyle}>{keyValue.type}</Tag>
|
||||
<Tag icon={<ClockCircleOutlined />} style={mutedPillTagStyle}>{formatTTL(keyValue.ttl)}</Tag>
|
||||
{keyValue.length > 0 && <Tag style={mutedPillTagStyle}>{tr('redis_viewer.label.length', { count: keyValue.length })}</Tag>}
|
||||
</div>
|
||||
<div className="redis-key-detail-actions" style={{ display: 'flex', gap: 4, alignItems: 'center', alignSelf: 'flex-start', flexWrap: 'wrap', maxWidth: '100%' }}>
|
||||
<Button size="small" style={actionButtonStyle} onClick={() => {
|
||||
ttlForm.setFieldsValue({ ttl: keyValue.ttl > 0 ? keyValue.ttl : -1 });
|
||||
setTtlModalOpen(true);
|
||||
}}>{tr('redis_viewer.action.set_ttl')}</Button>
|
||||
<Button size="small" style={actionButtonStyle} onClick={() => loadKeyValue(selectedKey)} icon={<ReloadOutlined />}>{tr('redis_viewer.action.refresh')}</Button>
|
||||
<Popconfirm title={tr('redis_viewer.confirm.delete_key', { key: selectedKey })} onConfirm={handleDeleteCurrentKey}>
|
||||
<Button size="small" style={dangerActionButtonStyle} icon={<DeleteOutlined />}>{tr('redis_viewer.action.delete_key')}</Button>
|
||||
</Popconfirm>
|
||||
<div className={`redis-key-detail-top${isV2Ui ? ' gn-v2-redis-value-top' : ''}`} style={{ display: 'flex', flexDirection: 'column', gap: 12, flexShrink: 0 }}>
|
||||
<div className={`redis-key-detail-header${isV2Ui ? ' gn-v2-redis-value-header' : ''}`} style={{ ...workbenchCardStyle, padding: 18, display: 'flex', flexDirection: 'column', gap: 16, flexShrink: 0 }}>
|
||||
<div className="redis-key-detail-summary" style={{ display: 'flex', flexDirection: 'column', gap: 10, minWidth: 0, width: '100%' }}>
|
||||
<span style={{ fontSize: 12, textTransform: 'uppercase', letterSpacing: '.08em', color: workbenchTheme.textMuted, fontWeight: 600 }}>
|
||||
{tr('redis_viewer.title.active_key')}
|
||||
</span>
|
||||
<div className="redis-key-detail-identity" style={{ display: 'flex', alignItems: 'center', gap: 8, minWidth: 0, width: '100%' }}>
|
||||
<Tooltip title={selectedKey}>
|
||||
<strong data-redis-active-key="true" style={{ flex: '0 1 auto', minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', fontSize: 26, color: workbenchTheme.textPrimary }}>
|
||||
{selectedKey}
|
||||
</strong>
|
||||
</Tooltip>
|
||||
<Tooltip title={tr('redis_viewer.tooltip.copy_key_name')}>
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
icon={<CopyOutlined />}
|
||||
style={{ padding: '0 4px', display: 'flex', alignItems: 'center', color: workbenchTheme.textMuted, flex: '0 0 auto' }}
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(selectedKey).then(() => {
|
||||
message.success(tr('redis_viewer.message.key_name_copied'));
|
||||
}).catch(() => {
|
||||
message.error(tr('redis_viewer.message.copy_failed'));
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div className="redis-key-detail-metadata" style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap', minWidth: 0 }}>
|
||||
<Tag color={getTypeColor(keyValue.type)} style={pillTagStyle}>{keyValue.type}</Tag>
|
||||
<Tag icon={<ClockCircleOutlined />} style={mutedPillTagStyle}>{formatTTL(keyValue.ttl)}</Tag>
|
||||
{keyValue.length > 0 && <Tag style={mutedPillTagStyle}>{tr('redis_viewer.label.length', { count: keyValue.length })}</Tag>}
|
||||
</div>
|
||||
<div className="redis-key-detail-actions" style={{ display: 'flex', gap: 4, alignItems: 'center', alignSelf: 'flex-start', flexWrap: 'wrap', maxWidth: '100%' }}>
|
||||
<Button size="small" style={actionButtonStyle} onClick={() => {
|
||||
ttlForm.setFieldsValue({ ttl: keyValue.ttl > 0 ? keyValue.ttl : -1 });
|
||||
setTtlModalOpen(true);
|
||||
}}>{tr('redis_viewer.action.set_ttl')}</Button>
|
||||
<Button size="small" style={actionButtonStyle} onClick={() => loadKeyValue(selectedKey)} icon={<ReloadOutlined />}>{tr('redis_viewer.action.refresh')}</Button>
|
||||
<Popconfirm title={tr('redis_viewer.confirm.delete_key', { key: selectedKey })} onConfirm={handleDeleteCurrentKey}>
|
||||
<Button size="small" style={dangerActionButtonStyle} icon={<DeleteOutlined />}>{tr('redis_viewer.action.delete_key')}</Button>
|
||||
</Popconfirm>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={isV2Ui ? 'gn-v2-redis-view-mode' : undefined} style={{ ...workbenchSubCardStyle, padding: 6, display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 12, flexShrink: 0 }}>
|
||||
<span style={{ paddingInline: 10, fontSize: 12, color: workbenchTheme.textMuted }}>{tr('redis_viewer.view.title')}</span>
|
||||
<Radio.Group size="small" value={viewMode} onChange={(e) => setViewMode(e.target.value)}>
|
||||
<Radio.Button value="auto">{tr('redis_viewer.view.auto')}</Radio.Button>
|
||||
<Radio.Button value="text">{tr('redis_viewer.view.text')}</Radio.Button>
|
||||
<Radio.Button value="utf8">UTF-8</Radio.Button>
|
||||
<Radio.Button value="hex">{tr('redis_viewer.view.hex')}</Radio.Button>
|
||||
</Radio.Group>
|
||||
<div className={`redis-key-view-mode${isV2Ui ? ' gn-v2-redis-view-mode' : ''}`} style={{ ...workbenchSubCardStyle, padding: 6, display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 12, flexShrink: 0 }}>
|
||||
<span style={{ paddingInline: 10, fontSize: 12, color: workbenchTheme.textMuted }}>{tr('redis_viewer.view.title')}</span>
|
||||
<Radio.Group size="small" value={viewMode} onChange={(e) => setViewMode(e.target.value)}>
|
||||
<Radio.Button value="auto">{tr('redis_viewer.view.auto')}</Radio.Button>
|
||||
<Radio.Button value="text">{tr('redis_viewer.view.text')}</Radio.Button>
|
||||
<Radio.Button value="utf8">UTF-8</Radio.Button>
|
||||
<Radio.Button value="hex">{tr('redis_viewer.view.hex')}</Radio.Button>
|
||||
</Radio.Group>
|
||||
</div>
|
||||
</div>
|
||||
<div className={isV2Ui ? 'gn-v2-redis-value-card' : undefined} style={{ ...workbenchCardStyle, padding: 14, flex: 1, minHeight: 0, overflow: 'hidden' }}>
|
||||
<div style={{ flex: 1, minHeight: 0, overflow: 'hidden', height: '100%' }}>
|
||||
@@ -2203,7 +2205,19 @@ const RedisViewer: React.FC<RedisViewerProps> = ({ connectionId, redisDB }) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`redis-viewer-workbench${isV2Ui ? ' gn-v2-redis-workbench' : ''}`} style={{ display: 'flex', height: '100%', gap: 12, padding: 12, background: workbenchTheme.appBg, backdropFilter: workbenchBackdropFilter, WebkitBackdropFilter: workbenchBackdropFilter }}>
|
||||
<div
|
||||
className={`redis-viewer-workbench${isV2Ui ? ' gn-v2-redis-workbench' : ''}`}
|
||||
style={{
|
||||
display: 'flex',
|
||||
height: '100%',
|
||||
gap: 12,
|
||||
padding: 12,
|
||||
background: workbenchTheme.appBg,
|
||||
backdropFilter: workbenchBackdropFilter,
|
||||
WebkitBackdropFilter: workbenchBackdropFilter,
|
||||
'--gn-redis-sidebar-width': typeof leftPanelWidth === 'number' ? `${leftPanelWidth}px` : leftPanelWidth,
|
||||
} as React.CSSProperties}
|
||||
>
|
||||
{/* Left: Key List */}
|
||||
<div ref={leftPanelRef} className={isV2Ui ? 'gn-v2-redis-sidebar' : undefined} style={{ width: leftPanelWidth, minWidth: 300, display: 'flex', flexDirection: 'column', flexShrink: 0, gap: 12 }}>
|
||||
<div className={isV2Ui ? 'gn-v2-redis-header' : undefined} style={{ ...workbenchCardStyle, padding: 12 }}>
|
||||
@@ -2332,12 +2346,18 @@ const RedisViewer: React.FC<RedisViewerProps> = ({ connectionId, redisDB }) => {
|
||||
</div>
|
||||
|
||||
{/* Resizable Divider */}
|
||||
<RedisResizableDivider targetRef={leftPanelRef} onResizeEnd={setLeftPanelWidth} title={tr('redis_viewer.tooltip.resize_panels')} />
|
||||
<RedisResizableDivider
|
||||
targetRef={leftPanelRef}
|
||||
onResizeEnd={setLeftPanelWidth}
|
||||
maxReservedWidth={isV2Ui ? 361 : undefined}
|
||||
containerWidthCssVariable={isV2Ui ? '--gn-redis-sidebar-width' : undefined}
|
||||
title={tr('redis_viewer.tooltip.resize_panels')}
|
||||
/>
|
||||
|
||||
{/* Right: Value Viewer */}
|
||||
<div className={isV2Ui ? 'gn-v2-redis-value-pane' : undefined} style={{ flex: 1, overflow: 'hidden', minWidth: 300 }}>
|
||||
{valueLoading ? (
|
||||
<div style={{ ...workbenchCardStyle, padding: 20, textAlign: 'center', color: workbenchTheme.textMuted }}>{tr('common.loading')}...</div>
|
||||
<div className={isV2Ui ? 'gn-v2-redis-empty-value' : undefined} style={{ ...workbenchCardStyle, padding: 20, textAlign: 'center', color: workbenchTheme.textMuted }}>{tr('common.loading')}...</div>
|
||||
) : (
|
||||
renderValueEditor()
|
||||
)}
|
||||
|
||||
@@ -740,14 +740,23 @@ body[data-ui-version="v2"] .gn-v2-table-designer .ant-table-container {
|
||||
|
||||
/* ─── V2 Redis workbench ─ */
|
||||
body[data-ui-version="v2"] .gn-v2-redis-workbench {
|
||||
gap: 10px !important;
|
||||
padding: 10px !important;
|
||||
background: var(--gn-bg-app) !important;
|
||||
display: grid !important;
|
||||
grid-template-columns: clamp(320px, var(--gn-redis-sidebar-width, 50%), calc(100% - 361px)) 1px minmax(360px, 1fr);
|
||||
grid-template-rows: max-content minmax(0, 1fr);
|
||||
gap: 0 !important;
|
||||
padding: 0 !important;
|
||||
background: var(--gn-bg-panel) !important;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-redis-sidebar {
|
||||
min-width: 320px !important;
|
||||
gap: 10px !important;
|
||||
display: grid !important;
|
||||
grid-column: 1;
|
||||
grid-row: 1 / 3;
|
||||
grid-template-rows: subgrid;
|
||||
width: 100% !important;
|
||||
min-width: 0 !important;
|
||||
gap: 0 !important;
|
||||
background: var(--gn-bg-panel) !important;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-redis-header,
|
||||
@@ -755,14 +764,18 @@ body[data-ui-version="v2"] .gn-v2-redis-tree-card,
|
||||
body[data-ui-version="v2"] .gn-v2-redis-value-header,
|
||||
body[data-ui-version="v2"] .gn-v2-redis-value-card,
|
||||
body[data-ui-version="v2"] .gn-v2-redis-empty-value {
|
||||
border-radius: 8px !important;
|
||||
border: 0.5px solid var(--gn-br-1) !important;
|
||||
border: 0 !important;
|
||||
border-radius: 0 !important;
|
||||
background: var(--gn-bg-panel) !important;
|
||||
box-shadow: var(--gn-shadow-card) !important;
|
||||
box-shadow: none !important;
|
||||
backdrop-filter: none !important;
|
||||
-webkit-backdrop-filter: none !important;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-redis-header {
|
||||
padding: 12px !important;
|
||||
grid-row: 1;
|
||||
padding: 14px !important;
|
||||
border-bottom: 1px solid var(--gn-br-1) !important;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-redis-toolbar {
|
||||
@@ -770,13 +783,17 @@ body[data-ui-version="v2"] .gn-v2-redis-toolbar {
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-redis-tree-card {
|
||||
padding: 8px !important;
|
||||
grid-row: 2;
|
||||
padding: 10px 12px 12px !important;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-redis-tree-shell {
|
||||
border-radius: 7px !important;
|
||||
border: 0.5px solid var(--gn-br-1) !important;
|
||||
background: var(--gn-bg-panel-2) !important;
|
||||
border: 0 !important;
|
||||
border-radius: 0 !important;
|
||||
background: transparent !important;
|
||||
box-shadow: none !important;
|
||||
backdrop-filter: none !important;
|
||||
-webkit-backdrop-filter: none !important;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-redis-workbench .ant-tree-checkbox {
|
||||
@@ -784,15 +801,31 @@ body[data-ui-version="v2"] .gn-v2-redis-workbench .ant-tree-checkbox {
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-redis-value-pane {
|
||||
display: contents !important;
|
||||
min-width: 360px !important;
|
||||
background: var(--gn-bg-panel) !important;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-redis-value-layout {
|
||||
gap: 10px !important;
|
||||
display: contents !important;
|
||||
gap: 0 !important;
|
||||
background: var(--gn-bg-panel) !important;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-redis-value-top {
|
||||
display: flex;
|
||||
grid-column: 3;
|
||||
grid-row: 1;
|
||||
height: 100%;
|
||||
min-height: 0;
|
||||
gap: 0 !important;
|
||||
background: var(--gn-bg-panel);
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-redis-value-header {
|
||||
padding: 14px !important;
|
||||
flex: 1 1 auto !important;
|
||||
padding: 14px 16px !important;
|
||||
border-bottom: 0 !important;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-redis-value-header strong {
|
||||
@@ -804,22 +837,51 @@ body[data-ui-version="v2"] .gn-v2-redis-value-actions,
|
||||
body[data-ui-version="v2"] .gn-v2-redis-view-mode,
|
||||
body[data-ui-version="v2"] .gn-v2-redis-value-subtoolbar,
|
||||
body[data-ui-version="v2"] .gn-v2-redis-value-actionbar {
|
||||
border-radius: 7px !important;
|
||||
border: 0.5px solid var(--gn-br-1) !important;
|
||||
background: var(--gn-bg-panel-2) !important;
|
||||
border: 0 !important;
|
||||
border-radius: 0 !important;
|
||||
background: var(--gn-bg-panel) !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-redis-value-subtoolbar {
|
||||
min-height: 30px;
|
||||
border-width: 0 0 0.5px !important;
|
||||
border-radius: 0 !important;
|
||||
border-bottom: 1px solid var(--gn-br-1) !important;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-redis-value-actionbar {
|
||||
padding: 8px !important;
|
||||
padding: 10px 12px !important;
|
||||
margin-bottom: 0 !important;
|
||||
border-bottom-left-radius: 0 !important;
|
||||
border-bottom-right-radius: 0 !important;
|
||||
border-bottom: 1px solid var(--gn-br-1) !important;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-redis-view-mode {
|
||||
padding: 8px 16px !important;
|
||||
border-bottom: 1px solid var(--gn-br-1) !important;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-redis-value-card {
|
||||
grid-column: 3;
|
||||
grid-row: 2;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-redis-empty-value {
|
||||
grid-column: 3;
|
||||
grid-row: 1 / 3;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-redis-workbench > .redis-resizable-divider {
|
||||
grid-column: 2;
|
||||
grid-row: 1 / 3;
|
||||
position: relative;
|
||||
width: 1px !important;
|
||||
background: var(--gn-br-1) !important;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-redis-workbench > .redis-resizable-divider::before {
|
||||
position: absolute;
|
||||
inset: 0 -5px;
|
||||
content: '';
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-redis-data-section .ant-table-wrapper {
|
||||
|
||||
Reference in New Issue
Block a user