import React from 'react';
import NiceModal from '@ebay/nice-modal-react';
import type {ButtonButtonProps} from '@gravity-ui/uikit';
import {Button, Dialog, DropdownMenu, TextInput} from '@gravity-ui/uikit';
import {
selectActiveTab,
selectActiveTabSavedQueryName,
selectUserInput,
setIsDirty,
syncSavedQueryTab,
} from '../../../../store/reducers/query/query';
import {setQueryAction} from '../../../../store/reducers/queryActions/queryActions';
import type {SavedQuery} from '../../../../types/store/query';
import {cn} from '../../../../utils/cn';
import {BRAND_BUTTON_CLASS} from '../../../../utils/constants';
import {useTypedDispatch, useTypedSelector} from '../../../../utils/hooks';
import {getTabTitleForSave} from '../utils/queryTabTitles';
import {hasSavedQueryName} from '../utils/savedQueries';
import {useSavedQueries} from '../utils/useSavedQueries';
import {useEditExistingSavedQuery} from '../utils/useUpdateSavedQueryFromTab';
import i18n from './i18n';
import './SaveQuery.scss';
const b = cn('ydb-save-query');
export const SAVE_QUERY_DIALOG = 'save-query-dialog';
interface SaveQueryProps {
buttonProps?: ButtonButtonProps;
}
export function useSaveQueryWithTabSync() {
const dispatch = useTypedDispatch();
const {saveQuery} = useSavedQueries();
const activeTab = useTypedSelector(selectActiveTab);
return React.useCallback(
(tabId?: string) => {
const targetTabId = tabId ?? activeTab?.id;
return (queryName: string | null, queryBody: string) => {
saveQuery(queryName, queryBody);
if (targetTabId && queryName) {
dispatch(
syncSavedQueryTab({
tabId: targetTabId,
title: queryName,
savedQueryName: queryName,
}),
);
}
};
},
[activeTab, dispatch, saveQuery],
);
}
function useSaveQueryHandler(dialogProps: SaveQueryDialogCommonProps) {
const {savedQueries} = useSavedQueries();
const activeTab = useTypedSelector(selectActiveTab);
const createSaveQueryHandler = useSaveQueryWithTabSync();
const onSaveQueryClick = React.useCallback(() => {
const computedDefaultQueryName = getTabTitleForSave(activeTab);
const handleSaveQuery = createSaveQueryHandler(activeTab?.id);
NiceModal.show(SAVE_QUERY_DIALOG, {
...dialogProps,
defaultQueryName: dialogProps.defaultQueryName ?? computedDefaultQueryName,
savedQueries,
onSaveQuery: handleSaveQuery,
});
}, [activeTab, createSaveQueryHandler, dialogProps, savedQueries]);
return onSaveQueryClick;
}
interface SaveQueryButtonProps extends ButtonButtonProps {
dialogProps: SaveQueryDialogCommonProps;
}
export function SaveQueryButton({dialogProps, children, ...buttonProps}: SaveQueryButtonProps) {
const onSaveQueryClick = useSaveQueryHandler(dialogProps);
return (
);
}
export function SaveQuery({buttonProps = {}}: SaveQueryProps) {
const activeTab = useTypedSelector(selectActiveTab);
const activeTabSavedQueryName = useTypedSelector(selectActiveTabSavedQueryName);
const currentInput = useTypedSelector(selectUserInput);
const onSaveQueryClick = useSaveQueryHandler({queryBody: currentInput});
const currentSavedQueryName = activeTabSavedQueryName;
const editExistingSavedQuery = useEditExistingSavedQuery();
const onEditQueryClick = () => {
if (!activeTab || !currentSavedQueryName) {
return;
}
editExistingSavedQuery(activeTab, currentInput);
};
const renderSaveDropdownMenu = () => {
const items = [
{
action: onEditQueryClick,
text: i18n('action.edit-existing'),
},
{
action: onSaveQueryClick,
text: i18n('action.save-as-new'),
},
];
return (
(
)}
popupProps={{placement: 'top'}}
/>
);
};
return currentSavedQueryName ? (
renderSaveDropdownMenu()
) : (
);
}
interface SaveQueryDialogCommonProps {
onSuccess?: () => void;
onCancel?: () => void;
onClose?: () => void;
defaultQueryName?: string;
queryBody: string;
}
interface SaveQueryDialogProps extends SaveQueryDialogCommonProps {
open: boolean;
savedQueries?: SavedQuery[];
onSaveQuery: (name: string | null, body: string) => void;
}
function SaveQueryDialog({
onSuccess,
onCancel,
onClose,
defaultQueryName,
open,
savedQueries,
onSaveQuery,
queryBody,
}: SaveQueryDialogProps) {
const dispatch = useTypedDispatch();
const [queryName, setQueryName] = React.useState(defaultQueryName ?? '');
const [validationError, setValidationError] = React.useState();
const controlRef = React.useRef(null);
const validateQueryName = (value: string) => {
if (!value.trim()) {
return i18n('error.name-not-empty');
}
if (savedQueries && hasSavedQueryName(savedQueries, value)) {
return i18n('error.name-exists');
}
return undefined;
};
const onCloseDialog = () => {
dispatch(setQueryAction('idle'));
setQueryName('');
setValidationError(undefined);
onClose?.();
};
const onCloseWithoutSave = () => {
onCancel?.();
onCloseDialog();
};
const handleQueryNameChange = (value: string) => {
setQueryName(value);
setValidationError(undefined);
};
const onSaveClick = () => {
onSaveQuery(queryName.trim(), queryBody);
dispatch(setIsDirty(false));
onCloseDialog();
onSuccess?.();
};
return (
);
}
export const SaveQueryDialogNiceModal = NiceModal.create((props: SaveQueryDialogProps) => {
const modal = NiceModal.useModal();
const handleClose = () => {
modal.hide();
modal.remove();
};
return (
{
props.onClose?.();
handleClose();
}}
open={modal.visible}
/>
);
});
NiceModal.register(SAVE_QUERY_DIALOG, SaveQueryDialogNiceModal);