Skip to content

feat(Preview): add preview for topics #2292

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
May 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
"use-query-params": "^2.2.1",
"uuid": "^10.0.0",
"web-vitals": "^1.1.2",
"ydb-ui-components": "^4.6.0",
"ydb-ui-components": "^4.7.0",
"zod": "^3.24.1"
},
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion src/components/EntityStatus/EntityStatus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export function EntityStatus({
</InternalLink>
);
}
return name && <span className={b('name')}>{name}</span>;
return name && <span className={b('name')}>{renderName(name)}</span>;
};
return (
<div className={b(null, className)}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,11 @@
@use '../../../../../styles/mixins.scss';

.ydb-diagnostics-topic-data-columns {
&__ts-diff_danger {
color: var(--g-color-text-danger);
}
&__message_clickable {
cursor: pointer;

color: var(--g-color-text-info);
}
&__offset {
display: inline-flex;
align-items: center;
gap: var(--g-spacing-1);
.g-help-mark,
.g-help-mark__button {
display: flex;
}
}
&__offset {

width: 100%;
height: 100%;
}
Expand Down
115 changes: 72 additions & 43 deletions src/containers/Tenant/Diagnostics/TopicData/columns/columns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';

import {TriangleExclamation} from '@gravity-ui/icons';
import DataTable from '@gravity-ui/react-data-table';
import type {TextProps} from '@gravity-ui/uikit';
import {ActionTooltip, Icon, Popover, Text} from '@gravity-ui/uikit';
import {isNil} from 'lodash';
import {Link} from 'react-router-dom';
Expand Down Expand Up @@ -88,18 +89,8 @@ export const tsDiffColumn: Column<TopicMessageEnhanced> = {
name: TOPIC_DATA_COLUMNS_IDS.TS_DIFF,
header: TOPIC_DATA_COLUMNS_TITLES[TOPIC_DATA_COLUMNS_IDS.TS_DIFF],
align: DataTable.RIGHT,
render: ({row}) => {
if (isNil(row.TimestampDiff)) {
return EMPTY_DATA_PLACEHOLDER;
}
const numericValue = safeParseNumber(row.TimestampDiff);
return (
<span className={b('ts-diff', {danger: numericValue >= 100_000})}>
{formatToMs(numericValue)}
</span>
);
},
width: 90,
render: ({row: {TimestampDiff}}) => <TopicDataTsDiff value={TimestampDiff} />,
width: 110,
note: i18n('context_ts-diff'),
};

Expand All @@ -121,44 +112,17 @@ export const messageColumn: Column<TopicMessageEnhanced> = {
name: TOPIC_DATA_COLUMNS_IDS.MESSAGE,
header: TOPIC_DATA_COLUMNS_TITLES[TOPIC_DATA_COLUMNS_IDS.MESSAGE],
align: DataTable.LEFT,
render: ({row: {Message, OriginalSize}}) => {
if (isNil(Message)) {
return EMPTY_DATA_PLACEHOLDER;
}
let encryptedMessage;
let invalid = false;
try {
encryptedMessage = atob(Message);
} catch {
encryptedMessage = i18n('description_failed-decode');
invalid = true;
}

const truncated = safeParseNumber(OriginalSize) > TOPIC_MESSAGE_SIZE_LIMIT;
return (
<Text
variant="body-2"
color={invalid ? 'secondary' : 'primary'}
className={b('message', {invalid})}
>
{encryptedMessage}
{truncated && (
<Text color="secondary" className={b('truncated')}>
{' '}
{i18n('description_truncated')}
</Text>
)}
</Text>
);
},
render: ({row: {Message, OriginalSize}}) => (
<TopicDataMessage message={Message} size={OriginalSize} />
),
width: 500,
};

export const sizeColumn: Column<TopicMessageEnhanced> = {
name: TOPIC_DATA_COLUMNS_IDS.SIZE,
header: TOPIC_DATA_COLUMNS_TITLES[TOPIC_DATA_COLUMNS_IDS.SIZE],
align: DataTable.RIGHT,
render: ({row}) => formatBytes(row.StorageSize),
render: ({row: {StorageSize}}) => <TopicDataSize size={StorageSize} />,
width: 100,
};

Expand Down Expand Up @@ -316,3 +280,68 @@ function Offset({offset, removed, notLoaded}: PartitionIdProps) {
</Link>
);
}
interface TopicDataTsDiffProps {
value?: string;
baseColor?: TextProps['color'];
variant?: TextProps['variant'];
}

export function TopicDataTsDiff({
value,
baseColor = 'primary',
variant = 'body-2',
}: TopicDataTsDiffProps) {
if (isNil(value)) {
return EMPTY_DATA_PLACEHOLDER;
}
const numericValue = safeParseNumber(value);
return (
<Text variant={variant} color={numericValue >= 100_000 ? 'danger' : baseColor}>
{formatToMs(numericValue)}
</Text>
);
}

interface TopicDataMessageProps {
message?: string;
size?: number;
}

export function TopicDataMessage({message, size}: TopicDataMessageProps) {
if (isNil(message)) {
return EMPTY_DATA_PLACEHOLDER;
}
let encryptedMessage;
let invalid = false;
try {
encryptedMessage = atob(message);
} catch {
encryptedMessage = i18n('description_failed-decode');
invalid = true;
}

const truncated = safeParseNumber(size) > TOPIC_MESSAGE_SIZE_LIMIT;
return (
<Text
variant="body-2"
color={invalid ? 'secondary' : 'primary'}
className={b('message', {invalid})}
>
{encryptedMessage}
{truncated && (
<Text color="secondary" className={b('truncated')}>
{' '}
{i18n('description_truncated')}
</Text>
)}
</Text>
);
}

interface TopicDataSizeProps {
size?: number;
}

export function TopicDataSize({size}: TopicDataSizeProps) {
return formatBytes(size);
}
10 changes: 9 additions & 1 deletion src/containers/Tenant/ObjectGeneral/ObjectGeneral.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,15 @@ function ObjectGeneral(props: ObjectGeneralProps) {
props;
switch (tenantPage) {
case TENANT_PAGES_IDS.query: {
return <Query tenantName={tenantName} path={path} theme={theme} type={type} />;
return (
<Query
tenantName={tenantName}
path={path}
theme={theme}
type={type}
subType={subType}
/>
);
}
default: {
return (
Expand Down
22 changes: 17 additions & 5 deletions src/containers/Tenant/ObjectSummary/SchemaTree/SchemaTree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import React from 'react';
import {NavigationTree} from 'ydb-ui-components';

import {getConnectToDBDialog} from '../../../../components/ConnectToDB/ConnectToDBDialog';
import {useCreateDirectoryFeatureAvailable} from '../../../../store/reducers/capabilities/hooks';
import {
useCreateDirectoryFeatureAvailable,
useTopicDataAvailable,
} from '../../../../store/reducers/capabilities/hooks';
import {selectIsDirty, selectUserInput} from '../../../../store/reducers/query/query';
import {schemaApi} from '../../../../store/reducers/schema/schema';
import {tableSchemaDataApi} from '../../../../store/reducers/tableSchemaData';
Expand All @@ -21,6 +24,7 @@ import {
nodeTableTypeToPathType,
} from '../../utils/schema';
import {getActions} from '../../utils/schemaActions';
import type {DropdownItem, TreeNodeMeta} from '../../utils/types';
import {CreateDirectoryDialog} from '../CreateDirectoryDialog/CreateDirectoryDialog';
import {useDispatchTreeKey, useTreeKey} from '../UpdateTreeContext';
import {isDomain} from '../transformPath';
Expand All @@ -44,6 +48,8 @@ export function SchemaTree(props: SchemaTreeProps) {
{currentData: actionsSchemaData, isFetching: isActionsDataFetching},
] = tableSchemaDataApi.useLazyGetTableSchemaDataQuery();

const isTopicPreviewAvailable = useTopicDataAvailable();

const [createDirectoryOpen, setCreateDirectoryOpen] = React.useState(false);
const [parentPath, setParentPath] = React.useState('');
const setSchemaTreeKey = useDispatchTreeKey();
Expand Down Expand Up @@ -91,6 +97,7 @@ export function SchemaTree(props: SchemaTreeProps) {
// FIXME: should only be explicitly set to true for tables with indexes
// at the moment of writing there is no property to determine this, fix later
expandable: !isChildless,
meta: {subType: PathSubType},
};
});

Expand Down Expand Up @@ -153,7 +160,7 @@ export function SchemaTree(props: SchemaTreeProps) {
parentPath={parentPath}
onSuccess={handleSuccessSubmit}
/>
<NavigationTree
<NavigationTree<DropdownItem, TreeNodeMeta>
key={schemaTreeKey}
rootState={{
path: rootPath,
Expand All @@ -171,9 +178,14 @@ export function SchemaTree(props: SchemaTreeProps) {

return [];
}}
renderAdditionalNodeElements={getSchemaControls(dispatch, {
setActivePath: onActivePathUpdate,
})}
renderAdditionalNodeElements={getSchemaControls(
dispatch,
{
setActivePath: onActivePathUpdate,
},
undefined,
isTopicPreviewAvailable,
)}
activePath={currentPath}
onActivePathUpdate={onActivePathUpdate}
cache={false}
Expand Down
29 changes: 9 additions & 20 deletions src/containers/Tenant/Query/Preview/Preview.scss
Original file line number Diff line number Diff line change
@@ -1,30 +1,22 @@
@use '../../../../styles/mixins.scss';

.kv-preview {
.ydb-preview {
height: 100%;
@include mixins.flex-container();
@include mixins.query-data-table();
&__header {
position: sticky;
top: 0;

display: flex;
flex-shrink: 0;
justify-content: space-between;
align-items: center;

height: 53px;
padding: 0 20px;
padding: 0 var(--g-spacing-6);

border-bottom: 1px solid var(--g-color-line-generic);
background-color: var(--g-color-base-background);
}

&__title {
display: flex;
gap: var(--g-spacing-1);
}

&__table-name {
margin-left: var(--g-spacing-1);

Expand All @@ -36,21 +28,18 @@
gap: var(--g-spacing-1);
}
&__message-container {
padding: 15px 20px;
}

&__loader-container {
display: flex;
justify-content: center;
align-items: center;

height: 100%;
padding: var(--g-spacing-3) 0;
}

&__result {
overflow: auto;

width: 100%;
padding-left: 10px;
padding-left: var(--g-spacing-5);
}

&__partition-info {
height: 36px;
padding-left: var(--g-spacing-1);
}
}
Loading
Loading