Skip to content
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
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ Prefer widgets for product screens. Use modules and components when you need a c

### Widget imports

All six widgets support both root and individual imports:
Widgets support both root and individual imports:

```tsx
import {SavedQueries} from '@gravity-ui/querieskit';
Expand All @@ -73,7 +73,7 @@ import type {SavedQueriesProps} from '@gravity-ui/querieskit/widgets/SavedQuerie
```

Individual entrypoints are available for `QueriesHistory`, `SavedQueries`,
`TutorialsHistory`, `QueriesNavigation`, `QueryResults`, and `DashboardCharts`.
`TutorialsHistory`, `QueriesNavigation`, `QueryExecutionPanel`, and `DashboardCharts`.
They expose each widget's existing public exports, including its props and helpers.
Shared data types remain available from the package root.

Expand All @@ -85,6 +85,16 @@ Some bundlers, including esbuild, retain CSS from unused root re-exports even wh
their JavaScript is removed. Individual widget imports avoid introducing those
unrelated styles.

### QueryExecutionPanel

A query execution panel with ordered, typed tabs, custom content, automatic tab
selection until manual navigation, message severity titles, and application-owned
expand/close actions. See [the API and integration guide](src/widgets/QueryExecutionPanel/README.md)
and the QueryExecutionPanel Storybook examples.

`QueryResults` is a module, available from the package root or through
`@gravity-ui/querieskit/modules/QueryResults`.

### QueriesHistory

Ready-made query history sidebar: search, filters, editable titles, row actions, and optional compare mode.
Expand Down
30 changes: 20 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,6 @@
"default": "./build/cjs/widgets/QueriesNavigation/index.js"
}
},
"./widgets/QueryResults": {
"import": {
"types": "./build/esm/widgets/QueryResults/index.d.ts",
"default": "./build/esm/widgets/QueryResults/index.js"
},
"require": {
"types": "./build/cjs/widgets/QueryResults/index.d.ts",
"default": "./build/cjs/widgets/QueryResults/index.js"
}
},
"./widgets/DashboardCharts": {
"import": {
"types": "./build/esm/widgets/DashboardCharts/index.d.ts",
Expand All @@ -85,6 +75,26 @@
"types": "./build/cjs/widgets/DashboardCharts/index.d.ts",
"default": "./build/cjs/widgets/DashboardCharts/index.js"
}
},
"./modules/QueryResults": {
"import": {
"types": "./build/esm/modules/QueryResults/index.d.ts",
"default": "./build/esm/modules/QueryResults/index.js"
},
"require": {
"types": "./build/cjs/modules/QueryResults/index.d.ts",
"default": "./build/cjs/modules/QueryResults/index.js"
}
},
"./widgets/QueryExecutionPanel": {
"import": {
"types": "./build/esm/widgets/QueryExecutionPanel/index.d.ts",
"default": "./build/esm/widgets/QueryExecutionPanel/index.js"
},
"require": {
"types": "./build/cjs/widgets/QueryExecutionPanel/index.d.ts",
"default": "./build/cjs/widgets/QueryExecutionPanel/index.js"
}
}
},
"files": [
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ export * from './types/queryStatistics';
export * from './types/queryResults';
export * from './types/queryGraph';
export * from './types/queryTimeline';
export * from './types/queryExecutionPanel';
10 changes: 8 additions & 2 deletions src/modules/QueryProgress/QueryProgress.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const statusIcons = {
} satisfies Record<QueryGraphNodeStatus, typeof Circle>;

export function QueryProgress({
active = true,
graphProps,
timelineProps,
view: controlledView,
Expand Down Expand Up @@ -112,7 +113,10 @@ export function QueryProgress({
hidden={view !== 'graph'}
>
<Suspense fallback={<Loader size="m" />}>
<QueryGraph {...graphProps} active={view === 'graph'} />
<QueryGraph
{...graphProps}
active={active && view === 'graph' && graphProps.active !== false}
/>
</Suspense>
</div>
)}
Expand All @@ -125,7 +129,9 @@ export function QueryProgress({
<QueryTimeline
items={EMPTY_TIMELINE_ITEMS}
{...timelineProps}
active={view === 'timeline'}
active={
active && view === 'timeline' && timelineProps?.active !== false
}
/>
</Suspense>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ const rows: Row[] = [
];

const meta: Meta<typeof QueryResults> = {
title: 'Widgets/QueryResults',
title: 'Modules/QueryResults',
component: QueryResults,
tags: ['autodocs'],
parameters: {layout: 'padded'},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,15 @@ import React, {useCallback, useState} from 'react';
import {Flex, SegmentedRadioGroup, Text} from '@gravity-ui/uikit';
import cn from 'bem-cn-lite';
import {QueryResultsTable} from '../../components/QueryResultsTable';
import type {
QueryResultColumn,
QueryResultFormatterSettings,
QueryResultsSchemaRenderContext,
QueryResultsView,
} from '../../types/queryResults';
import type {QueryResultsProps, QueryResultsView} from '../../types/queryResults';
import {QueryResultsSchema} from './internal/QueryResultsSchema';
import i18n from './i18n';

import './QueryResults.scss';

const block = cn('qp-query-results');

export type QueryResultsProps<TRow extends Record<string, unknown>> = {
columns: Array<QueryResultColumn<TRow>>;
/** Values use the YQL wire representation consumed by @gravity-ui/unipika. */
rows: TRow[];
totalRows?: number;
loading?: boolean;
errorContent?: React.ReactNode;
rowKey?: (row: TRow, index: number) => string | number;
formatterSettings?: QueryResultFormatterSettings;
maxVisibleLines?: number;
title?: React.ReactNode;
toolbarContent?: React.ReactNode;
actions?: React.ReactNode;
view?: QueryResultsView;
defaultView?: QueryResultsView;
onViewChange?: (view: QueryResultsView) => void;
renderSchema?: (context: QueryResultsSchemaRenderContext<TRow>) => React.ReactNode;
className?: string;
};
export type {QueryResultsProps} from '../../types/queryResults';

export function QueryResults<TRow extends Record<string, unknown>>({
columns,
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, {useMemo} from 'react';
import BaseDataTable, {type Column} from '@gravity-ui/react-data-table';
import {DataTable} from '../../../components';
import {DataTable} from '../../../components/DataTable';
import type {
QueryStatisticsColumn,
QueryStatisticsExtraColumn,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {ChevronsDown, ChevronsUp} from '@gravity-ui/icons';
import {Button, Icon} from '@gravity-ui/uikit';
import cn from 'bem-cn-lite';

import {SearchWithButtons} from '../../../components';
import {SearchWithButtons} from '../../../components/SearchWithButtons';
import i18n from '../i18n';

import './QueryStatisticsToolbar.scss';
Expand Down
2 changes: 2 additions & 0 deletions src/modules/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,5 @@ export type {NavigationMetaProps, NavigationMetaViewConfig} from './NavigationMe
export {NavigationView, buildViewColumns} from './NavigationView';
export type {NavigationViewProps, NavigationViewViewConfig} from './NavigationView';
export {QueryTimeline} from './QueryTimeline';
export {QueryResults} from './QueryResults';
export type {QueryResultsProps} from './QueryResults';
59 changes: 59 additions & 0 deletions src/types/queryExecutionPanel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import type {ReactNode} from 'react';
import type {NavigationMetaProps} from '../modules/NavigationMeta';
import type {ErrorTreeProps} from './errorTree';
import type {NavigationMetaItem} from './navigation';
import type {QueryProgressProps} from './queryGraph';
import type {QueryResultsProps} from './queryResults';
import type {QueryStatisticsProps} from './queryStatistics';

export type QueryExecutionTabBase = {
/** Unique, non-empty and stable within one execution. */
id: string;
disabled?: boolean;
};

export type QueryExecutionTabRenderContext = {active: boolean};

export type QueryExecutionTab<
TRow extends Record<string, unknown> = Record<string, unknown>,
TMetaItem extends NavigationMetaItem = NavigationMetaItem,
> = QueryExecutionTabBase &
(
| {type: 'result'; title?: ReactNode; props: QueryResultsProps<TRow>}
| {type: 'progress'; title?: ReactNode; props: QueryProgressProps}
| {type: 'info'; props?: ErrorTreeProps}
| {type: 'statistics'; title?: ReactNode; props: QueryStatisticsProps}
| {type: 'meta'; title?: ReactNode; props: NavigationMetaProps<TMetaItem>}
| {
type: 'charts';
title?: ReactNode;
renderContent: (context: QueryExecutionTabRenderContext) => ReactNode;
}
| {
type: 'custom';
title: ReactNode;
renderContent: (context: QueryExecutionTabRenderContext) => ReactNode;
}
);

export type QueryExecutionPanelProps<
TRow extends Record<string, unknown> = Record<string, unknown>,
TMetaItem extends NavigationMetaItem = NavigationMetaItem,
> = {
/** Array order is display order. Keep each tab's id and type stable. */
tabs: QueryExecutionTab<TRow, TMetaItem>[];
/** Do not switch between controlled and uncontrolled modes after mounting. */
activeTab?: string;
defaultActiveTab?: string;
/** Followed until the first manual selection in uncontrolled mode. */
preferredActiveTab?: string;
/** Called on changes after initialization; never called with an empty selection. */
onActiveTabChange?: (id: string) => void;
/** Values are formatted by the application, including its timezone. */
execution?: {startedAt?: ReactNode; author?: ReactNode};
expanded?: boolean;
onExpandedChange?: (expanded: boolean) => void;
onClose?: () => void;
emptyContent?: ReactNode;
className?: string;
};
2 changes: 2 additions & 0 deletions src/types/queryGraph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ export type QueryGraphProps = {

export type QueryProgressView = 'graph' | 'timeline';
export type QueryProgressProps = {
/** Pauses both views while preserving their state. */
active?: boolean;
graphProps: QueryGraphProps;
timelineProps?: QueryTimelineProps;
view?: QueryProgressView;
Expand Down
20 changes: 20 additions & 0 deletions src/types/queryResults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,23 @@ export type QueryResultsView = 'result' | 'schema';
export type QueryResultsSchemaRenderContext<TRow extends Record<string, unknown>> = {
columns: Array<QueryResultColumn<TRow>>;
};

export type QueryResultsProps<TRow extends Record<string, unknown>> = {
columns: Array<QueryResultColumn<TRow>>;
/** Values use the YQL wire representation consumed by @gravity-ui/unipika. */
rows: TRow[];
totalRows?: number;
loading?: boolean;
errorContent?: ReactNode;
rowKey?: (row: TRow, index: number) => string | number;
formatterSettings?: QueryResultFormatterSettings;
maxVisibleLines?: number;
title?: ReactNode;
toolbarContent?: ReactNode;
actions?: ReactNode;
view?: QueryResultsView;
defaultView?: QueryResultsView;
onViewChange?: (view: QueryResultsView) => void;
renderSchema?: (context: QueryResultsSchemaRenderContext<TRow>) => ReactNode;
className?: string;
};
41 changes: 41 additions & 0 deletions src/widgets/QueryExecutionPanel/QueryExecutionPanel.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
.qp-query-execution-panel {
min-width: 0;
min-height: 0;
height: 100%;

&__header {
flex-shrink: 0;
border-bottom: 1px solid var(--g-color-line-generic);
}

&__tabs {
flex: 1 1 20rem;
flex-wrap: nowrap;
overflow-x: auto;
min-width: 0;
--g-tabs-border-width: 0;
}

&__details {
margin-left: auto;
min-width: 0;
overflow-wrap: anywhere;
}

&__actions {
flex-shrink: 0;
}

&__content {
flex: 1;
min-height: 0;
min-width: 0;
overflow: auto;
padding: var(--g-spacing-3);
}

&__panel {
min-width: 0;
height: 100%;
}
}
Loading
Loading