Skip to content

Commit

Permalink
feat: warn about unsaved changes in editor
Browse files Browse the repository at this point in the history
  • Loading branch information
Raubzeug committed Nov 14, 2024
1 parent 122f3c5 commit d1997fb
Show file tree
Hide file tree
Showing 23 changed files with 455 additions and 366 deletions.
11 changes: 11 additions & 0 deletions package-lock.json

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

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@
"devDependencies": {
"@commitlint/cli": "^19.3.0",
"@commitlint/config-conventional": "^19.2.2",
"@ebay/nice-modal-react": "^1.2.13",
"@gravity-ui/browserslist-config": "^4.3.0",
"@gravity-ui/eslint-config": "^3.2.0",
"@gravity-ui/prettier-config": "^1.1.0",
Expand Down
5 changes: 5 additions & 0 deletions src/components/ConfirmationDialog/ConfirmationDialog.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.confirmation-dialog {
&__message {
white-space: pre-wrap;
}
}
99 changes: 99 additions & 0 deletions src/components/ConfirmationDialog/ConfirmationDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import * as NiceModal from '@ebay/nice-modal-react';
import type {ButtonView} from '@gravity-ui/uikit';
import {Dialog} from '@gravity-ui/uikit';

import {cn} from '../../utils/cn';

import {confirmationDialogKeyset} from './i18n';

import './ConfirmationDialog.scss';

const block = cn('confirmation-dialog');

interface CommonDialogProps {
caption?: string;
message?: React.ReactNode;
body?: React.ReactNode;

progress?: boolean;
textButtonCancel?: string;
textButtonApply?: string;
buttonApplyView?: ButtonView;
className?: string;
onConfirm?: () => void;
}

interface ConfirmationDialogNiceModalProps extends CommonDialogProps {
onClose?: () => void;
}

interface ConfirmationDialogProps extends CommonDialogProps {
onClose: () => void;
open: boolean;
children?: React.ReactNode;
}

export const CONFIRMATION_DIALOG = 'confirmation-dialog';
function ConfirmationDialog({
caption = '',
children,
onConfirm,
onClose,
progress,
textButtonApply,
textButtonCancel,
buttonApplyView = 'normal',
className,
open,
}: ConfirmationDialogProps) {
return (
<Dialog
className={block(null, className)}
size="s"
onClose={onClose}
disableOutsideClick
open={open}
>
<Dialog.Header caption={caption} />
<Dialog.Body>{children}</Dialog.Body>
<Dialog.Footer
onClickButtonApply={onConfirm}
propsButtonApply={{view: buttonApplyView}}
textButtonApply={textButtonApply}
textButtonCancel={textButtonCancel ?? confirmationDialogKeyset('action_cancel')}
onClickButtonCancel={onClose}
loading={progress}
/>
</Dialog>
);
}

export const ConfirmationDialogNiceModal = NiceModal.create(
(props: ConfirmationDialogNiceModalProps) => {
const modal = NiceModal.useModal();

const handleClose = () => {
modal.hide();
modal.remove();
};

return (
<ConfirmationDialog
{...props}
onConfirm={async () => {
await props.onConfirm?.();
modal.resolve(true);
handleClose();
}}
onClose={() => {
props.onClose?.();
modal.resolve(false);
handleClose();
}}
open={modal.visible}
/>
);
},
);

NiceModal.register(CONFIRMATION_DIALOG, ConfirmationDialogNiceModal);
3 changes: 3 additions & 0 deletions src/components/ConfirmationDialog/i18n/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"action_cancel": "Cancel"
}
7 changes: 7 additions & 0 deletions src/components/ConfirmationDialog/i18n/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import {registerKeysets} from '../../../utils/i18n';

import en from './en.json';

const COMPONENT = 'ydb-confirmation-dialog';

export const confirmationDialogKeyset = registerKeysets(COMPONENT, {en});
9 changes: 6 additions & 3 deletions src/containers/App/Providers.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';

import * as NiceModal from '@ebay/nice-modal-react';
import {ThemeProvider} from '@gravity-ui/uikit';
import type {Store} from '@reduxjs/toolkit';
import type {History} from 'history';
Expand Down Expand Up @@ -34,9 +35,11 @@ export function Providers({
<Router history={history}>
<QueryParamProvider adapter={ReactRouter5Adapter}>
<Theme>
<ComponentsProvider registry={componentsRegistry}>
{children}
</ComponentsProvider>
<NiceModal.Provider>
<ComponentsProvider registry={componentsRegistry}>
{children}
</ComponentsProvider>
</NiceModal.Provider>
</Theme>
</QueryParamProvider>
</Router>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
TENANT_QUERY_TABS_ID,
} from '../../../../../store/reducers/tenant/constants';
import {useAutoRefreshInterval, useTypedDispatch} from '../../../../../utils/hooks';
import {useChangeInputWithConfirmation} from '../../../../../utils/hooks/withConfirmation/useChangeInputWithConfirmation';
import {parseQueryErrorToString} from '../../../../../utils/query';
import {TenantTabsGroups, getTenantPath} from '../../../TenantPages';
import {
Expand Down Expand Up @@ -48,7 +49,7 @@ export function TopQueries({tenantName}: TopQueriesProps) {
const loading = isFetching && currentData === undefined;
const data = currentData?.resultSets?.[0]?.result || [];

const handleRowClick = React.useCallback(
const applyRowClick = React.useCallback(
(row: any) => {
const {QueryText: input} = row;

Expand All @@ -67,6 +68,8 @@ export function TopQueries({tenantName}: TopQueriesProps) {
[dispatch, history, location],
);

const handleRowClick = useChangeInputWithConfirmation(applyRowClick);

const title = getSectionTitle({
entity: i18n('queries'),
postfix: i18n('by-cpu-time', {executionPeriod: i18n('executed-last-hour')}),
Expand Down
5 changes: 4 additions & 1 deletion src/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
} from '../../../../store/reducers/tenant/constants';
import {cn} from '../../../../utils/cn';
import {useTypedDispatch, useTypedSelector} from '../../../../utils/hooks';
import {useChangeInputWithConfirmation} from '../../../../utils/hooks/withConfirmation/useChangeInputWithConfirmation';
import {TenantTabsGroups, getTenantPath} from '../../TenantPages';

import {RunningQueriesData} from './RunningQueriesData';
Expand Down Expand Up @@ -68,7 +69,7 @@ export const TopQueries = ({tenantName}: TopQueriesProps) => {

const filters = useTypedSelector((state) => state.executeTopQueries);

const onRowClick = React.useCallback(
const applyRowClick = React.useCallback(
(input: string) => {
dispatch(changeUserInput({input}));

Expand All @@ -85,6 +86,8 @@ export const TopQueries = ({tenantName}: TopQueriesProps) => {
[dispatch, history, location],
);

const onRowClick = useChangeInputWithConfirmation(applyRowClick);

const handleTextSearchUpdate = (text: string) => {
dispatch(setTopQueriesFilters({text}));
};
Expand Down
10 changes: 9 additions & 1 deletion src/containers/Tenant/ObjectSummary/SchemaTree/SchemaTree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,19 @@ import React from 'react';
import {NavigationTree} from 'ydb-ui-components';

import {useCreateDirectoryFeatureAvailable} from '../../../../store/reducers/capabilities/hooks';
import {selectIsQuerySaved} from '../../../../store/reducers/executeQuery';
import {schemaApi} from '../../../../store/reducers/schema/schema';
import {tableSchemaDataApi} from '../../../../store/reducers/tableSchemaData';
import type {GetTableSchemaDataParams} from '../../../../store/reducers/tableSchemaData';
import type {EPathType, TEvDescribeSchemeResult} from '../../../../types/api/schema';
import {wait} from '../../../../utils';
import {SECOND_IN_MS} from '../../../../utils/constants';
import {useQueryExecutionSettings, useTypedDispatch} from '../../../../utils/hooks';
import {
useQueryExecutionSettings,
useTypedDispatch,
useTypedSelector,
} from '../../../../utils/hooks';
import {getConfirmation} from '../../../../utils/hooks/withConfirmation/useChangeInputWithConfirmation';
import {getSchemaControls} from '../../utils/controls';
import {isChildlessPathType, mapPathTypeToNavigationTreeType} from '../../utils/schema';
import {getActions} from '../../utils/schemaActions';
Expand All @@ -33,6 +39,7 @@ export function SchemaTree(props: SchemaTreeProps) {
const createDirectoryFeatureAvailable = useCreateDirectoryFeatureAvailable();
const {rootPath, rootName, rootType, currentPath, onActivePathUpdate} = props;
const dispatch = useTypedDispatch();
const isQuerySaved = useTypedSelector(selectIsQuerySaved);
const [getTableSchemaDataMutation] = tableSchemaDataApi.useGetTableSchemaDataMutation();

const getTableSchemaDataPromise = React.useCallback(
Expand Down Expand Up @@ -144,6 +151,7 @@ export function SchemaTree(props: SchemaTreeProps) {
? handleOpenCreateDirectoryDialog
: undefined,
getTableSchemaDataPromise,
getConfirmation: isQuerySaved ? undefined : getConfirmation,
},
rootPath,
)}
Expand Down
16 changes: 15 additions & 1 deletion src/containers/Tenant/Query/NewSQL/NewSQL.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,28 @@
import React from 'react';

import {ChevronDown} from '@gravity-ui/icons';
import {Button, DropdownMenu} from '@gravity-ui/uikit';

import {changeUserInput} from '../../../../store/reducers/executeQuery';
import {useTypedDispatch} from '../../../../utils/hooks';
import {useChangeInputWithConfirmation} from '../../../../utils/hooks/withConfirmation/useChangeInputWithConfirmation';
import {bindActions} from '../../utils/newSQLQueryActions';

import i18n from './i18n';

export function NewSQL() {
const dispatch = useTypedDispatch();
const actions = bindActions(dispatch);

const insertTemplate = React.useCallback(
(input: string) => {
dispatch(changeUserInput({input}));
},
[dispatch],
);

const onTemplateClick = useChangeInputWithConfirmation(insertTemplate);

const actions = bindActions(onTemplateClick);

const items = [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import type {QueryInHistory} from '../../../../types/store/executeQuery';
import {cn} from '../../../../utils/cn';
import {formatDateTime} from '../../../../utils/dataFormatters/dataFormatters';
import {useTypedDispatch, useTypedSelector} from '../../../../utils/hooks';
import {useChangeInputWithConfirmation} from '../../../../utils/hooks/withConfirmation/useChangeInputWithConfirmation';
import {formatToMs, parseUsToMs} from '../../../../utils/timeParsers';
import {MAX_QUERY_HEIGHT, QUERY_TABLE_SETTINGS} from '../../utils/constants';
import i18n from '../i18n';
Expand All @@ -36,11 +37,13 @@ function QueriesHistory({changeUserInput}: QueriesHistoryProps) {
const filter = useTypedSelector(selectQueriesHistoryFilter);
const reversedHistory = [...queriesHistory].reverse();

const onQueryClick = (query: QueryInHistory) => {
const applyQueryClick = (query: QueryInHistory) => {
changeUserInput({input: query.queryText});
dispatch(setQueryTab(TENANT_QUERY_TABS_ID.newQuery));
};

const onQueryClick = useChangeInputWithConfirmation(applyQueryClick);

const onChangeFilter = (value: string) => {
dispatch(setQueryHistoryFilter(value));
};
Expand Down
Loading

0 comments on commit d1997fb

Please sign in to comment.