Skip to content

Commit

Permalink
feat: settings usage in requests and modification... #1060
Browse files Browse the repository at this point in the history
  • Loading branch information
Anton Standrik committed Jul 26, 2024
1 parent f72690f commit 4af9fe8
Show file tree
Hide file tree
Showing 33 changed files with 671 additions and 155 deletions.
20 changes: 20 additions & 0 deletions src/components/Banner/Banner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import {Alert} from '@gravity-ui/uikit';

interface BannerProps {
message?: React.ReactNode;
title?: string;
className?: string;
onClose?: () => void;
}

export function Banner({message, title, className, onClose}: BannerProps) {
return (
<Alert
className={className}
theme="info"
title={title}
message={message}
onClose={onClose}
/>
);
}
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);
}
}
38 changes: 36 additions & 2 deletions src/components/QueryExecutionStatus/QueryExecutionStatus.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
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 getChangedQueryExecutionSettingsDescription from '../../containers/Tenant/Query/QueryEditorControls/utils/getChangedQueryExecutionSettingsDescription';
import i18n from '../../containers/Tenant/Query/i18n';
import {DEFAULT_QUERY_SETTINGS} from '../../lib';
import {cn} from '../../utils/cn';
import {useIsQuerySettingsBannerHidden} from '../../utils/hooks/useIsQuerySettingsBannerHidden';
import {useLastQueryExecutionSettings} from '../../utils/hooks/useLastQueryExecutionSettings';

import './QueryExecutionStatus.scss';

Expand All @@ -17,6 +24,17 @@ export const QueryExecutionStatus = ({className, error}: QueryExecutionStatusPro
let icon: React.ReactNode;
let label: string;

const isQuerySettingsDialogHidden = useIsQuerySettingsBannerHidden();
const [querySettings] = useLastQueryExecutionSettings();
const changedQuerySettingsDescription = React.useMemo(() => {
return querySettings
? getChangedQueryExecutionSettingsDescription({
currentSettings: querySettings,
defaultSettings: DEFAULT_QUERY_SETTINGS,
})
: '';
}, [querySettings]);

if (isAxiosError(error) && error.code === 'ECONNABORTED') {
icon = <Icon data={CircleQuestionFill} />;
label = 'Connection aborted';
Expand All @@ -35,6 +53,22 @@ export const QueryExecutionStatus = ({className, error}: QueryExecutionStatusPro
<div className={b(null, className)}>
{icon}
{label}
{isQuerySettingsDialogHidden && changedQuerySettingsDescription ? (
<Tooltip
openDelay={0}
content={
<div
dangerouslySetInnerHTML={{
__html: i18n('banner.query-settings.message', {
message: changedQuerySettingsDescription,
}),
}}
/>
}
>
<Icon data={CircleInfo} className={b('query-settings-icon')} />
</Tooltip>
) : null}
</div>
);
};
5 changes: 2 additions & 3 deletions src/containers/Tenant/Query/ExecuteResult/ExecuteResult.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ 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 './ExecuteResult.scss';
Expand Down Expand Up @@ -57,7 +58,6 @@ 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();

Expand Down Expand Up @@ -203,7 +203,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 @@ -227,7 +226,7 @@ export function ExecuteResult({
/>
</div>
</div>

<QuerySettingsBanner />
{renderResultSection()}
</React.Fragment>
);
Expand Down
4 changes: 2 additions & 2 deletions src/containers/Tenant/Query/ExplainResult/ExplainResult.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ import {useTypedDispatch, useTypedSelector} from '../../../../utils/hooks';
import {LANGUAGE_S_EXPRESSION_ID} from '../../../../utils/monaco/s-expression/constants';
import {parseQueryErrorToString} from '../../../../utils/query';
import {PaneVisibilityToggleButtons} from '../../utils/paneVisibilityToggleHelpers';
import {QuerySettingsBanner} from '../QuerySettingsBanner/QuerySettingsBanner';

import {renderExplainNode} from './utils';

import './ExplainResult.scss';
import 'react-json-inspector/json-inspector.css';

const b = cn('ydb-query-explain-result');

const EDITOR_OPTIONS = {
Expand Down Expand Up @@ -77,7 +77,6 @@ function GraphRoot(props) {
export function ExplainResult(props) {
const dispatch = useTypedDispatch();
const [activeOption, setActiveOption] = React.useState(ExplainOptionIds.schema);

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

React.useEffect(() => {
Expand Down Expand Up @@ -258,6 +257,7 @@ export function ExplainResult(props) {
</React.Fragment>
)}
</div>
<QuerySettingsBanner />
<div className={b('result')}>{renderContent()}</div>
</React.Fragment>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
&__text-message {
padding: 15px 20px;
}

&__controls {
position: sticky;
z-index: 2;
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
60 changes: 44 additions & 16 deletions src/containers/Tenant/Query/QueryEditor/QueryEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,17 @@ import {setShowPreview} from '../../../../store/reducers/schema/schema';
import type {EPathType} from '../../../../types/api/schema';
import type {ValueOf} from '../../../../types/common';
import type {ExecuteQueryState} from '../../../../types/store/executeQuery';
import type {IQueryResult, QueryAction, QueryMode} from '../../../../types/store/query';
import type {IQueryResult, QueryAction, QuerySettings} from '../../../../types/store/query';
import {cn} from '../../../../utils/cn';
import {
DEFAULT_IS_QUERY_RESULT_COLLAPSED,
DEFAULT_SIZE_RESULT_PANE_KEY,
LAST_USED_QUERY_ACTION_KEY,
QUERY_USE_MULTI_SCHEMA_KEY,
} from '../../../../utils/constants';
import {useQueryModes, useSetting} from '../../../../utils/hooks';
import {useQueryExecutionSettings, useSetting} from '../../../../utils/hooks';
import {useLastQueryExecutionSettings} from '../../../../utils/hooks/useLastQueryExecutionSettings';
import {useQuerySettingsBannerLastClosed} from '../../../../utils/hooks/useQuerySettingsBannerLastClosed';
import {LANGUAGE_YQL_ID} from '../../../../utils/monaco/yql/constants';
import {QUERY_ACTIONS} from '../../../../utils/query';
import type {InitialPaneState} from '../../utils/paneVisibilityToggleHelpers';
Expand All @@ -41,6 +43,7 @@ import {ExecuteResult} from '../ExecuteResult/ExecuteResult';
import {ExplainResult} from '../ExplainResult/ExplainResult';
import {Preview} from '../Preview/Preview';
import {QueryEditorControls} from '../QueryEditorControls/QueryEditorControls';
import getChangedQueryExecutionSettings from '../QueryEditorControls/utils/getChangedQueryExecutionSettings';
import {QuerySettingsDialog} from '../QuerySettingsDialog/QuerySettingsDialog';
import {SaveQueryDialog} from '../SaveQuery/SaveQuery';
import i18n from '../i18n';
Expand Down Expand Up @@ -102,7 +105,11 @@ function QueryEditor(props: QueryEditorProps) {
const [resultType, setResultType] = React.useState(RESULT_TYPES.EXECUTE);

const [isResultLoaded, setIsResultLoaded] = React.useState(false);
const [queryMode, setQueryMode] = useQueryModes();
const [querySettings, setQuerySettings] = useQueryExecutionSettings();
const [lastQueryExecutionSettings, setLastQueryExecutionSettings] =
useLastQueryExecutionSettings();
const [_, setQuerySettingsBannerLastClosed] = useQuerySettingsBannerLastClosed();

const [useMultiSchema] = useSetting(QUERY_USE_MULTI_SCHEMA_KEY);
const [lastUsedQueryAction, setLastUsedQueryAction] = useSetting<QueryAction>(
LAST_USED_QUERY_ACTION_KEY,
Expand Down Expand Up @@ -182,22 +189,31 @@ function QueryEditor(props: QueryEditorProps) {
};
}, [executeQuery]);

const handleSendExecuteClick = (mode: QueryMode | undefined, text?: string) => {
if (!mode) {
return;
}
const handleSendExecuteClick = (settings: QuerySettings, text?: string) => {
const {input, history} = executeQuery;

const schema = useMultiSchema ? 'multi' : 'modern';

const query = text ?? input;

setLastUsedQueryAction(QUERY_ACTIONS.execute);

if (lastQueryExecutionSettings) {
const areSettingsChanged =
getChangedQueryExecutionSettings(querySettings, lastQueryExecutionSettings).length >
0;

if (areSettingsChanged) {
setQuerySettingsBannerLastClosed(undefined);
}
}
setLastQueryExecutionSettings(settings);

setResultType(RESULT_TYPES.EXECUTE);
sendExecuteQuery({
query,
database: tenantName,
mode,
querySettings: settings,
schema,
});
setIsResultLoaded(true);
Expand All @@ -207,7 +223,7 @@ function QueryEditor(props: QueryEditorProps) {
if (!text) {
const {queries, currentIndex} = history;
if (query !== queries[currentIndex]?.queryText) {
props.saveQueryToHistory(input, mode);
props.saveQueryToHistory(input, querySettings.queryMode);
}
}
dispatchResultVisibilityState(PaneVisibilityActionTypes.triggerExpand);
Expand All @@ -218,15 +234,27 @@ function QueryEditor(props: QueryEditorProps) {
props.setShowPreview(false);
};

const handleGetExplainQueryClick = (mode: QueryMode | undefined) => {
const handleGetExplainQueryClick = (settings: QuerySettings) => {
const {input} = executeQuery;

setLastUsedQueryAction(QUERY_ACTIONS.explain);

if (lastQueryExecutionSettings) {
const areSettingsChanged =
getChangedQueryExecutionSettings(querySettings, lastQueryExecutionSettings).length >
0;

if (areSettingsChanged) {
setQuerySettingsBannerLastClosed(undefined);
}
}
setLastQueryExecutionSettings(settings);

setResultType(RESULT_TYPES.EXPLAIN);
sendExplainQuery({
query: input,
database: tenantName,
mode: mode,
querySettings: settings,
});
setIsResultLoaded(true);
props.setShowPreview(false);
Expand All @@ -241,9 +269,9 @@ function QueryEditor(props: QueryEditorProps) {
switch (monacoHotKey) {
case MONACO_HOT_KEY_ACTIONS.sendQuery: {
if (lastUsedQueryAction === QUERY_ACTIONS.explain) {
handleGetExplainQueryClick(queryMode);
handleGetExplainQueryClick(querySettings);
} else {
handleSendExecuteClick(queryMode);
handleSendExecuteClick(querySettings);
}
break;
}
Expand All @@ -257,7 +285,7 @@ function QueryEditor(props: QueryEditorProps) {
endLineNumber: selection.getPosition().lineNumber,
endColumn: selection.getPosition().column,
});
handleSendExecuteClick(queryMode, text);
handleSendExecuteClick(querySettings, text);
}
break;
}
Expand Down Expand Up @@ -356,8 +384,8 @@ function QueryEditor(props: QueryEditorProps) {
onExplainButtonClick={handleGetExplainQueryClick}
explainIsLoading={explainQueryResult.isLoading}
disabled={!executeQuery.input}
onUpdateQueryMode={setQueryMode}
queryMode={queryMode}
onUpdateQueryMode={(queryMode) => setQuerySettings({...querySettings, queryMode})}
querySettings={querySettings}
highlightedAction={lastUsedQueryAction}
/>
);
Expand Down
Loading

0 comments on commit 4af9fe8

Please sign in to comment.