Skip to content

Commit

Permalink
feat: settings usage in requests and modification... #1060 (#1068)
Browse files Browse the repository at this point in the history
  • Loading branch information
astandrik committed Jul 31, 2024
1 parent 73c53dd commit c767175
Show file tree
Hide file tree
Showing 37 changed files with 899 additions and 305 deletions.
12 changes: 11 additions & 1 deletion src/components/LabelWithPopover/LabelWithPopover.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,31 @@
import {HelpPopover} from '@gravity-ui/components';
import type {ButtonProps} from '@gravity-ui/uikit';

interface LabelWithPopoverProps {
text: React.ReactNode;
popoverContent: React.ReactNode;
popoverClassName?: string;
className?: string;
contentClassName?: string;
buttonProps?: ButtonProps;
}

export const LabelWithPopover = ({
text,
popoverContent,
popoverClassName,
className,
contentClassName,
buttonProps,
}: LabelWithPopoverProps) => (
<div className={className}>
{text}
{'\u00a0'}
<HelpPopover content={popoverContent} contentClassName={contentClassName} />
<HelpPopover
className={popoverClassName}
buttonProps={buttonProps}
content={popoverContent}
contentClassName={contentClassName}
/>
</div>
);
4 changes: 4 additions & 0 deletions src/components/QueryExecutionStatus/QueryExecutionStatus.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,8 @@
color: var(--g-color-text-danger);
}
}

&__query-settings-icon {
color: var(--g-color-text-hint);
}
}
34 changes: 32 additions & 2 deletions src/components/QueryExecutionStatus/QueryExecutionStatus.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import {CircleCheck, CircleQuestionFill, CircleXmark} from '@gravity-ui/icons';
import {Icon} from '@gravity-ui/uikit';
import React from 'react';

import {CircleCheck, CircleInfo, CircleQuestionFill, CircleXmark} from '@gravity-ui/icons';
import {Icon, Tooltip} from '@gravity-ui/uikit';
import {isAxiosError} from 'axios';

import i18n from '../../containers/Tenant/Query/i18n';
import {QUERY_SETTINGS, useSetting} from '../../lib';
import {cn} from '../../utils/cn';
import {useChangedQuerySettings} from '../../utils/hooks/useChangedQuerySettings';
import QuerySettingsDescription from '../QuerySettingsDescription/QuerySettingsDescription';

import './QueryExecutionStatus.scss';

Expand All @@ -13,6 +19,29 @@ interface QueryExecutionStatusProps {
error?: unknown;
}

const QuerySettingsIndicator = () => {
const [useQuerySettings] = useSetting<boolean>(QUERY_SETTINGS);
const {isIndicatorShown, changedLastExecutionSettingsDescriptions} = useChangedQuerySettings();

if (!isIndicatorShown || !useQuerySettings) {
return null;
}

return (
<Tooltip
openDelay={0}
content={
<QuerySettingsDescription
prefix={i18n('banner.query-settings.message')}
querySettings={changedLastExecutionSettingsDescriptions}
/>
}
>
<Icon data={CircleInfo} className={b('query-settings-icon')} />
</Tooltip>
);
};

export const QueryExecutionStatus = ({className, error}: QueryExecutionStatusProps) => {
let icon: React.ReactNode;
let label: string;
Expand All @@ -35,6 +64,7 @@ export const QueryExecutionStatus = ({className, error}: QueryExecutionStatusPro
<div className={b(null, className)}>
{icon}
{label}
<QuerySettingsIndicator />
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.ydb-query-settings-description {
&__message {
display: flex;
flex-wrap: wrap;

white-space: pre;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import {cn} from '../../utils/cn';

import './QuerySettingsDescription.scss';

const b = cn('ydb-query-settings-description');

interface QuerySettingsDescriptionProps {
prefix: string;
querySettings: Record<string, string>;
}

const QuerySettingsDescription = ({querySettings, prefix}: QuerySettingsDescriptionProps) => {
return (
<div className={b('message')}>
{prefix}
{Object.entries(querySettings).map(([key, value], index, arr) => (
<span key={index} className={b('description-item')}>
{`${key}: ${value}`}
{index < arr.length - 1 ? ', ' : null}
</span>
))}
</div>
);
};

export default QuerySettingsDescription;
1 change: 1 addition & 0 deletions src/components/QuerySettingsDescription/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './QuerySettingsDescription';
9 changes: 5 additions & 4 deletions src/containers/Tenant/Query/ExecuteResult/ExecuteResult.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,19 @@ import Fullscreen from '../../../../components/Fullscreen/Fullscreen';
import {YDBGraph} from '../../../../components/Graph/Graph';
import {QueryExecutionStatus} from '../../../../components/QueryExecutionStatus';
import {QueryResultTable} from '../../../../components/QueryResultTable/QueryResultTable';
import {QUERY_SETTINGS} from '../../../../lib';
import {disableFullscreen} from '../../../../store/reducers/fullscreen';
import type {ColumnType, KeyValueRow} from '../../../../types/api/query';
import type {ValueOf} from '../../../../types/common';
import type {IQueryResult} from '../../../../types/store/query';
import {getArray} from '../../../../utils';
import {cn} from '../../../../utils/cn';
import {useTypedDispatch, useTypedSelector} from '../../../../utils/hooks';
import {useSetting, useTypedDispatch, useTypedSelector} from '../../../../utils/hooks';
import {parseQueryError} from '../../../../utils/query';
import {PaneVisibilityToggleButtons} from '../../utils/paneVisibilityToggleHelpers';
import {ResultIssues} from '../Issues/Issues';
import {QueryDuration} from '../QueryDuration/QueryDuration';
import {QuerySettingsBanner} from '../QuerySettingsBanner/QuerySettingsBanner';
import {getPreparedResult} from '../utils/getPreparedResult';

import {getPlan} from './utils';
Expand Down Expand Up @@ -57,9 +59,9 @@ export function ExecuteResult({
}: ExecuteResultProps) {
const [selectedResultSet, setSelectedResultSet] = React.useState(0);
const [activeSection, setActiveSection] = React.useState<SectionID>(resultOptionsIds.result);

const isFullscreen = useTypedSelector((state) => state.fullscreen);
const dispatch = useTypedDispatch();
const [useQuerySettings] = useSetting<boolean>(QUERY_SETTINGS);

const stats = data?.stats;
const resultsSetsCount = data?.resultSets?.length;
Expand Down Expand Up @@ -238,7 +240,6 @@ export function ExecuteResult({
<div className={b('controls')}>
<div className={b('controls-right')}>
<QueryExecutionStatus error={error} />

{stats && !error && (
<React.Fragment>
<QueryDuration duration={stats?.DurationUs} />
Expand All @@ -262,7 +263,7 @@ export function ExecuteResult({
/>
</div>
</div>

{useQuerySettings && <QuerySettingsBanner />}
{renderResultSection()}
</React.Fragment>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
&__text-message {
padding: 15px 20px;
}

&__controls {
position: sticky;
z-index: 2;
Expand Down
7 changes: 6 additions & 1 deletion src/containers/Tenant/Query/ExplainResult/ExplainResult.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ import EnableFullscreenButton from '../../../../components/EnableFullscreenButto
import Fullscreen from '../../../../components/Fullscreen/Fullscreen';
import {LoaderWrapper} from '../../../../components/LoaderWrapper/LoaderWrapper';
import {QueryExecutionStatus} from '../../../../components/QueryExecutionStatus';
import {QUERY_SETTINGS} from '../../../../lib';
import type {PreparedExplainResponse} from '../../../../store/reducers/explainQuery/types';
import {disableFullscreen} from '../../../../store/reducers/fullscreen';
import type {ValueOf} from '../../../../types/common';
import {cn} from '../../../../utils/cn';
import {useTypedDispatch, useTypedSelector} from '../../../../utils/hooks';
import {useSetting, useTypedDispatch, useTypedSelector} from '../../../../utils/hooks';
import {parseQueryErrorToString} from '../../../../utils/query';
import {PaneVisibilityToggleButtons} from '../../utils/paneVisibilityToggleHelpers';
import {QuerySettingsBanner} from '../QuerySettingsBanner/QuerySettingsBanner';

import {Ast} from './components/Ast/Ast';
import {Graph} from './components/Graph/Graph';
Expand Down Expand Up @@ -82,6 +84,8 @@ export function ExplainResult({

const isFullscreen = useTypedSelector((state) => state.fullscreen);

const [useQuerySettings] = useSetting<boolean>(QUERY_SETTINGS);

React.useEffect(() => {
return () => {
dispatch(disableFullscreen());
Expand Down Expand Up @@ -165,6 +169,7 @@ export function ExplainResult({
</React.Fragment>
)}
</div>
{useQuerySettings && <QuerySettingsBanner />}
<LoaderWrapper loading={loading || isPending}>
{/* this is a hack: only one Graph component may be in DOM because of it's canvas id */}
{activeOption === EXPLAIN_OPTIONS_IDS.schema && isFullscreen ? null : (
Expand Down
16 changes: 10 additions & 6 deletions src/containers/Tenant/Query/QueriesHistory/QueriesHistory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ import {TENANT_QUERY_TABS_ID} from '../../../../store/reducers/tenant/constants'
import {setQueryTab} from '../../../../store/reducers/tenant/tenant';
import type {QueryInHistory} from '../../../../types/store/executeQuery';
import {cn} from '../../../../utils/cn';
import {useQueryModes, useTypedDispatch, useTypedSelector} from '../../../../utils/hooks';
import {
useQueryExecutionSettings,
useTypedDispatch,
useTypedSelector,
} from '../../../../utils/hooks';
import {QUERY_MODES, QUERY_SYNTAX} from '../../../../utils/query';
import {MAX_QUERY_HEIGHT, QUERY_TABLE_SETTINGS} from '../../utils/constants';
import i18n from '../i18n';
Expand All @@ -25,17 +29,17 @@ interface QueriesHistoryProps {
function QueriesHistory({changeUserInput}: QueriesHistoryProps) {
const dispatch = useTypedDispatch();

const [queryMode, setQueryMode] = useQueryModes();
const [settings, setQuerySettings] = useQueryExecutionSettings();

const queriesHistory = useTypedSelector(selectQueriesHistory);
const reversedHistory = [...queriesHistory].reverse();

const onQueryClick = (query: QueryInHistory) => {
if (query.syntax === QUERY_SYNTAX.pg && queryMode !== QUERY_MODES.pg) {
setQueryMode(QUERY_MODES.pg);
} else if (query.syntax !== QUERY_SYNTAX.pg && queryMode === QUERY_MODES.pg) {
if (query.syntax === QUERY_SYNTAX.pg && settings.queryMode !== QUERY_MODES.pg) {
setQuerySettings({...settings, queryMode: QUERY_MODES.pg});
} else if (query.syntax !== QUERY_SYNTAX.pg && settings.queryMode === QUERY_MODES.pg) {
// Set query mode for queries with yql syntax
setQueryMode(QUERY_MODES.script);
setQuerySettings({...settings, queryMode: QUERY_MODES.script});
}

changeUserInput({input: query.queryText});
Expand Down
11 changes: 11 additions & 0 deletions src/containers/Tenant/Query/QueryDuration/QueryDuration.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,21 @@
color: var(--g-color-text-complementary);

&__item-with-popover {
display: flex;

white-space: nowrap;
}

&__popover {
display: flex;
align-items: center;
}

&__popover-content {
max-width: 300px;
}

&__popover-button {
display: flex;
}
}
4 changes: 3 additions & 1 deletion src/containers/Tenant/Query/QueryDuration/QueryDuration.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ export const QueryDuration = ({duration}: QueryDurationProps) => {
<span className={b()}>
<LabelWithPopover
className={b('item-with-popover')}
contentClassName={b('popover')}
contentClassName={b('popover-content')}
text={parsedDuration}
popoverClassName={b('popover')}
popoverContent={i18n('query-duration.description')}
buttonProps={{className: b('popover-button')}}
/>
</span>
);
Expand Down
Loading

0 comments on commit c767175

Please sign in to comment.