From 06fc1248478933aa68b0d3e5821f4b4a2460f938 Mon Sep 17 00:00:00 2001 From: Boris Yuzhakov Date: Fri, 28 Jun 2024 16:54:05 +0300 Subject: [PATCH 01/13] feat: add creating directory through context menu in navigation tree --- .../Tenant/Schema/SchemaTree/SchemaTree.scss | 14 +++ .../Tenant/Schema/SchemaTree/SchemaTree.tsx | 99 +++++++++++++++---- src/containers/Tenant/i18n/en.json | 8 +- src/containers/Tenant/utils/schemaActions.ts | 7 +- src/services/api.ts | 14 +++ src/store/reducers/schema/schema.ts | 10 ++ 6 files changed, 129 insertions(+), 23 deletions(-) create mode 100644 src/containers/Tenant/Schema/SchemaTree/SchemaTree.scss diff --git a/src/containers/Tenant/Schema/SchemaTree/SchemaTree.scss b/src/containers/Tenant/Schema/SchemaTree/SchemaTree.scss new file mode 100644 index 000000000..5d8c215ac --- /dev/null +++ b/src/containers/Tenant/Schema/SchemaTree/SchemaTree.scss @@ -0,0 +1,14 @@ +@import '../../../../styles/mixins.scss'; + +.ydb-schema-tree { + &__modal { + max-height: 100%; + @include flex-container(); + } + &__label { + margin-bottom: 10px; + } + &__description { + opacity: 0.6; + } +} diff --git a/src/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx b/src/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx index 66e51e301..985d526cc 100644 --- a/src/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx +++ b/src/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx @@ -1,14 +1,23 @@ +// todo: tableTree is very smart, so it is impossible to update it without re-render +// It is need change NavigationTree to dump component and pass props from parent component +// In this case we can store state of tree - uploaded entities, opened nodes, selected entity and so on import React from 'react'; +import {Dialog, TextInput} from '@gravity-ui/uikit'; import {NavigationTree} from 'ydb-ui-components'; import {schemaApi} from '../../../../store/reducers/schema/schema'; import type {EPathType} from '../../../../types/api/schema'; +import {cn} from '../../../../utils/cn'; import {useQueryModes, useTypedDispatch} from '../../../../utils/hooks'; +import i18n from '../../i18n'; import {isChildlessPathType, mapPathTypeToNavigationTreeType} from '../../utils/schema'; import {getActions} from '../../utils/schemaActions'; import {getControls} from '../../utils/schemaControls'; +import './SchemaTree.scss'; +const b = cn('ydb-schema-tree'); + interface SchemaTreeProps { rootPath: string; rootName: string; @@ -19,10 +28,14 @@ interface SchemaTreeProps { export function SchemaTree(props: SchemaTreeProps) { const {rootPath, rootName, rootType, currentPath, onActivePathUpdate} = props; - const dispatch = useTypedDispatch(); const [_, setQueryMode] = useQueryModes(); + const [open, setOpen] = React.useState(false); + const [parent, setParent] = React.useState(''); + const [child, setChild] = React.useState(''); + + const [createDirectory, {requestId}] = schemaApi.useCreateDirectoryMutation(); const fetchPath = async (path: string) => { const promise = dispatch( @@ -57,26 +70,70 @@ export function SchemaTree(props: SchemaTreeProps) { } }, [currentPath, onActivePathUpdate, rootPath]); + const handleCreateDirectoryClose = () => { + setChild(''); + setOpen(false); + }; + + const handleCreateDirectory = () => { + createDirectory({database: parent, path: `${parent}/${child}`}); + + onActivePathUpdate(`${parent}/${child}`); + + handleCreateDirectoryClose(); + }; + + const handleOpenCreateDirectoryDialog = (path: string) => { + setParent(path); + setOpen(true); + }; + return ( - + + + + +
+
+ {i18n('schema.tree.dialog.description')} +
+
{`${parent}/`}
+
+ +
+ +
+ +
); } diff --git a/src/containers/Tenant/i18n/en.json b/src/containers/Tenant/i18n/en.json index 8b358bb9a..f9e06a5de 100644 --- a/src/containers/Tenant/i18n/en.json +++ b/src/containers/Tenant/i18n/en.json @@ -40,5 +40,11 @@ "actions.selectQuery": "Select query...", "actions.upsertQuery": "Upsert query...", "actions.alterReplication": "Alter async replicaton...", - "actions.dropReplication": "Drop async replicaton..." + "actions.dropReplication": "Drop async replicaton...", + "actions.createDirectory": "Create directory...", + "schema.tree.dialog.placeholder": "Relative path", + "schema.tree.dialog.header": "Create directory", + "schema.tree.dialog.description": "Inside directory", + "schema.tree.dialog.buttonCancel": "Cancel", + "schema.tree.dialog.buttonApply": "Create" } diff --git a/src/containers/Tenant/utils/schemaActions.ts b/src/containers/Tenant/utils/schemaActions.ts index f3b34ecf1..24e5d4373 100644 --- a/src/containers/Tenant/utils/schemaActions.ts +++ b/src/containers/Tenant/utils/schemaActions.ts @@ -29,6 +29,7 @@ import { interface ActionsAdditionalEffects { setQueryMode: (mode: QueryMode) => void; setActivePath: (path: string) => void; + showCreateDirectoryDialog: (path: string) => void; } const bindActions = ( @@ -36,7 +37,7 @@ const bindActions = ( dispatch: React.Dispatch, additionalEffects: ActionsAdditionalEffects, ) => { - const {setActivePath, setQueryMode} = additionalEffects; + const {setActivePath, setQueryMode, showCreateDirectoryDialog} = additionalEffects; const inputQuery = (tmpl: (path: string) => string, mode?: QueryMode) => () => { if (mode) { @@ -50,6 +51,9 @@ const bindActions = ( }; return { + createDirectory: () => { + showCreateDirectoryDialog(path); + }, createTable: inputQuery(createTableTemplate, 'script'), createColumnTable: inputQuery(createColumnTableTemplate, 'script'), createAsyncReplication: inputQuery(createAsyncReplicationTemplate, 'script'), @@ -96,6 +100,7 @@ export const getActions = const DIR_SET: ActionsSet = [ [copyItem], [ + {text: i18n('actions.createDirectory'), action: actions.createDirectory}, {text: i18n('actions.createTable'), action: actions.createTable}, {text: i18n('actions.createColumnTable'), action: actions.createColumnTable}, { diff --git a/src/services/api.ts b/src/services/api.ts index fc1e138e4..72927b593 100644 --- a/src/services/api.ts +++ b/src/services/api.ts @@ -635,6 +635,20 @@ export class YdbEmbeddedAPI extends AxiosWrapper { requestConfig: {signal}, }); } + + createSchemaDirectory(database: string, path: string, {signal}: {signal?: AbortSignal} = {}) { + return this.post<{test: string}>( + this.getPath('/scheme/directory'), + {}, + { + database, + path, + }, + { + requestConfig: {signal}, + }, + ); + } } export class YdbWebVersionAPI extends YdbEmbeddedAPI { diff --git a/src/store/reducers/schema/schema.ts b/src/store/reducers/schema/schema.ts index ae760fbd8..a32c3937b 100644 --- a/src/store/reducers/schema/schema.ts +++ b/src/store/reducers/schema/schema.ts @@ -41,6 +41,16 @@ export default schema; export const schemaApi = api.injectEndpoints({ endpoints: (builder) => ({ + createDirectory: builder.mutation({ + queryFn: async ({database, path}, {signal}) => { + try { + const data = await window.api.createSchemaDirectory(database, path, {signal}); + return {data}; + } catch (error) { + return {error}; + } + }, + }), getSchema: builder.query({ queryFn: async ({path}, {signal}) => { try { From f53985993fff397e174c103c0ccfd4efed968a81 Mon Sep 17 00:00:00 2001 From: Boris Yuzhakov Date: Fri, 28 Jun 2024 17:08:51 +0300 Subject: [PATCH 02/13] fix: move 'Create directory' to a separate section in context menu --- src/containers/Tenant/i18n/en.json | 2 +- src/containers/Tenant/utils/schemaActions.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/containers/Tenant/i18n/en.json b/src/containers/Tenant/i18n/en.json index f9e06a5de..373e6fe02 100644 --- a/src/containers/Tenant/i18n/en.json +++ b/src/containers/Tenant/i18n/en.json @@ -41,7 +41,7 @@ "actions.upsertQuery": "Upsert query...", "actions.alterReplication": "Alter async replicaton...", "actions.dropReplication": "Drop async replicaton...", - "actions.createDirectory": "Create directory...", + "actions.createDirectory": "Create directory", "schema.tree.dialog.placeholder": "Relative path", "schema.tree.dialog.header": "Create directory", "schema.tree.dialog.description": "Inside directory", diff --git a/src/containers/Tenant/utils/schemaActions.ts b/src/containers/Tenant/utils/schemaActions.ts index 24e5d4373..9f44501a0 100644 --- a/src/containers/Tenant/utils/schemaActions.ts +++ b/src/containers/Tenant/utils/schemaActions.ts @@ -99,8 +99,8 @@ export const getActions = const DIR_SET: ActionsSet = [ [copyItem], + [{text: i18n('actions.createDirectory'), action: actions.createDirectory}], [ - {text: i18n('actions.createDirectory'), action: actions.createDirectory}, {text: i18n('actions.createTable'), action: actions.createTable}, {text: i18n('actions.createColumnTable'), action: actions.createColumnTable}, { From fe8fc7addf2043f22d3de010da5e2d4a5ccfa2dd Mon Sep 17 00:00:00 2001 From: Boris Yuzhakov Date: Mon, 1 Jul 2024 14:08:59 +0300 Subject: [PATCH 03/13] fix: after review create directory --- .../CreateDirectoryDialog.scss} | 2 +- .../CreateDirectoryDialog.tsx | 53 +++++++++++++++++++ .../Tenant/Schema/SchemaTree/SchemaTree.tsx | 47 +++++----------- src/containers/Tenant/i18n/en.json | 2 +- 4 files changed, 67 insertions(+), 37 deletions(-) rename src/containers/Tenant/Schema/{SchemaTree/SchemaTree.scss => CreateDirectoryDialog/CreateDirectoryDialog.scss} (85%) create mode 100644 src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx diff --git a/src/containers/Tenant/Schema/SchemaTree/SchemaTree.scss b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.scss similarity index 85% rename from src/containers/Tenant/Schema/SchemaTree/SchemaTree.scss rename to src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.scss index 5d8c215ac..05e2b6d2a 100644 --- a/src/containers/Tenant/Schema/SchemaTree/SchemaTree.scss +++ b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.scss @@ -1,6 +1,6 @@ @import '../../../../styles/mixins.scss'; -.ydb-schema-tree { +.ydb-schema-create-directory-dialog { &__modal { max-height: 100%; @include flex-container(); diff --git a/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx new file mode 100644 index 000000000..5675178b6 --- /dev/null +++ b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx @@ -0,0 +1,53 @@ +import React from 'react'; + +import {Dialog, TextInput} from '@gravity-ui/uikit'; + +import {cn} from '../../../../utils/cn'; +import i18n from '../../i18n'; + +import './CreateDirectoryDialog.scss'; +const b = cn('ydb-schema-tree'); + +interface SchemaTreeProps { + open: boolean; + parent: string; + onClose: () => void; + onSubmit: (value: string) => void; +} + +export function CreateDirectoryDialog(props: SchemaTreeProps) { + const {open, parent, onClose, onSubmit} = props; + const [child, setChild] = React.useState(''); + + const handleClose = () => { + setChild(''); + onClose(); + }; + const handleSubmit = () => { + setChild(''); + onSubmit(child); + }; + + return ( + + + +
+
{i18n('schema.tree.dialog.description')}
+
{`${parent}/`}
+
+ +
+ +
+ ); +} diff --git a/src/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx b/src/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx index 985d526cc..3c53e62a2 100644 --- a/src/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx +++ b/src/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx @@ -3,20 +3,15 @@ // In this case we can store state of tree - uploaded entities, opened nodes, selected entity and so on import React from 'react'; -import {Dialog, TextInput} from '@gravity-ui/uikit'; import {NavigationTree} from 'ydb-ui-components'; import {schemaApi} from '../../../../store/reducers/schema/schema'; import type {EPathType} from '../../../../types/api/schema'; -import {cn} from '../../../../utils/cn'; import {useQueryModes, useTypedDispatch} from '../../../../utils/hooks'; -import i18n from '../../i18n'; import {isChildlessPathType, mapPathTypeToNavigationTreeType} from '../../utils/schema'; import {getActions} from '../../utils/schemaActions'; import {getControls} from '../../utils/schemaControls'; - -import './SchemaTree.scss'; -const b = cn('ydb-schema-tree'); +import {CreateDirectoryDialog} from '../CreateDirectoryDialog/CreateDirectoryDialog'; interface SchemaTreeProps { rootPath: string; @@ -31,9 +26,8 @@ export function SchemaTree(props: SchemaTreeProps) { const dispatch = useTypedDispatch(); const [_, setQueryMode] = useQueryModes(); - const [open, setOpen] = React.useState(false); + const [createDirectoryOpen, setCreateDirectoryOpen] = React.useState(false); const [parent, setParent] = React.useState(''); - const [child, setChild] = React.useState(''); const [createDirectory, {requestId}] = schemaApi.useCreateDirectoryMutation(); @@ -71,47 +65,30 @@ export function SchemaTree(props: SchemaTreeProps) { }, [currentPath, onActivePathUpdate, rootPath]); const handleCreateDirectoryClose = () => { - setChild(''); - setOpen(false); + setCreateDirectoryOpen(false); }; - const handleCreateDirectory = () => { + const handleCreateDirectorySubmit = (child: string) => { createDirectory({database: parent, path: `${parent}/${child}`}); onActivePathUpdate(`${parent}/${child}`); - handleCreateDirectoryClose(); + setCreateDirectoryOpen(false); }; const handleOpenCreateDirectoryDialog = (path: string) => { setParent(path); - setOpen(true); + setCreateDirectoryOpen(true); }; return ( - - - -
-
- {i18n('schema.tree.dialog.description')} -
-
{`${parent}/`}
-
- -
- -
+ Date: Mon, 1 Jul 2024 14:10:18 +0300 Subject: [PATCH 04/13] fix: after review create directory - update previous --- .../CreateDirectoryDialog/CreateDirectoryDialog.scss | 2 +- .../CreateDirectoryDialog/CreateDirectoryDialog.tsx | 4 +++- .../Tenant/Schema/SchemaTree/SchemaTree.tsx | 11 +++++++++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.scss b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.scss index 05e2b6d2a..3770ffd52 100644 --- a/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.scss +++ b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.scss @@ -9,6 +9,6 @@ margin-bottom: 10px; } &__description { - opacity: 0.6; + color: var(--g-color-text-secondary); } } diff --git a/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx index 5675178b6..ae0729fa7 100644 --- a/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx +++ b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx @@ -6,7 +6,7 @@ import {cn} from '../../../../utils/cn'; import i18n from '../../i18n'; import './CreateDirectoryDialog.scss'; -const b = cn('ydb-schema-tree'); +const b = cn('ydb-schema-create-directory-dialog'); interface SchemaTreeProps { open: boolean; @@ -40,6 +40,8 @@ export function CreateDirectoryDialog(props: SchemaTreeProps) { placeholder={i18n('schema.tree.dialog.placeholder')} value={child} onUpdate={setChild} + autoFocus + hasClear /> (''); + const [navigationTreeKey, setNavigationTreeKey] = React.useState(''); - const [createDirectory, {requestId}] = schemaApi.useCreateDirectoryMutation(); + const [createDirectory, {isSuccess, requestId}] = schemaApi.useCreateDirectoryMutation(); const fetchPath = async (path: string) => { const promise = dispatch( @@ -57,6 +58,12 @@ export function SchemaTree(props: SchemaTreeProps) { return childItems; }; + React.useEffect(() => { + if (isSuccess) { + setNavigationTreeKey(requestId); + } + }, [isSuccess, requestId]); + React.useEffect(() => { // if the cached path is not in the current tree, show root if (!currentPath?.startsWith(rootPath)) { @@ -90,7 +97,7 @@ export function SchemaTree(props: SchemaTreeProps) { onSubmit={handleCreateDirectorySubmit} /> Date: Mon, 1 Jul 2024 14:45:09 +0300 Subject: [PATCH 05/13] fix: create directory by Enter --- .../Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx index ae0729fa7..598c71782 100644 --- a/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx +++ b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx @@ -29,7 +29,7 @@ export function CreateDirectoryDialog(props: SchemaTreeProps) { }; return ( - +
From 2e163d18a61041b38c202a8a70543e9ac7fce25a Mon Sep 17 00:00:00 2001 From: Boris Yuzhakov Date: Mon, 1 Jul 2024 17:34:03 +0300 Subject: [PATCH 06/13] fix: add validation for create directory modal --- .../CreateDirectoryDialog.scss | 11 ++--- .../CreateDirectoryDialog.tsx | 32 +++++++++++-- .../Tenant/Schema/SchemaTree/SchemaTree.tsx | 47 ++++++++++++------- 3 files changed, 64 insertions(+), 26 deletions(-) diff --git a/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.scss b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.scss index 3770ffd52..081eee895 100644 --- a/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.scss +++ b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.scss @@ -1,14 +1,13 @@ -@import '../../../../styles/mixins.scss'; - .ydb-schema-create-directory-dialog { - &__modal { - max-height: 100%; - @include flex-container(); - } &__label { margin-bottom: 10px; } &__description { color: var(--g-color-text-secondary); } + &__error { + margin-top: 10px; + + color: var(--g-color-private-red-450); + } } diff --git a/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx index 598c71782..b70a2b650 100644 --- a/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx +++ b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx @@ -11,23 +11,43 @@ const b = cn('ydb-schema-create-directory-dialog'); interface SchemaTreeProps { open: boolean; parent: string; + isLoading: boolean; onClose: () => void; onSubmit: (value: string) => void; + onUpdate: (value: string) => void; + error: string; } export function CreateDirectoryDialog(props: SchemaTreeProps) { - const {open, parent, onClose, onSubmit} = props; + const {open, parent, isLoading, onClose, onSubmit, onUpdate, error} = props; const [child, setChild] = React.useState(''); const handleClose = () => { - setChild(''); onClose(); }; + const handleSubmit = () => { - setChild(''); onSubmit(child); }; + const handleUpdate = (value: string) => { + setChild(value); + }; + + React.useEffect(() => { + if (!open) { + setChild(''); + } + }, [open]); + + React.useEffect(() => { + onUpdate(child); + }, [onUpdate, child]); + + const invalid = React.useMemo(() => { + return /\s/.test(child); + }, [child]); + return ( @@ -39,12 +59,16 @@ export function CreateDirectoryDialog(props: SchemaTreeProps) { + {error &&
{error}
} (''); + const [child, setChild] = React.useState(''); const [navigationTreeKey, setNavigationTreeKey] = React.useState(''); + const [error, setError] = React.useState(''); + const [createDirectory, createDirectoryResult] = schemaApi.useCreateDirectoryMutation(); - const [createDirectory, {isSuccess, requestId}] = schemaApi.useCreateDirectoryMutation(); - - const fetchPath = async (path: string) => { + const fetchPath = async (value: string) => { const promise = dispatch( - schemaApi.endpoints.getSchema.initiate({path}, {forceRefetch: true}), + schemaApi.endpoints.getSchema.initiate({path: value}, {forceRefetch: true}), ); const {data} = await promise; promise.unsubscribe(); if (!data) { - throw new Error(`no describe data about path ${path}`); + throw new Error(`no describe data about path ${value}`); } const {PathDescription: {Children = []} = {}} = data; @@ -59,10 +60,20 @@ export function SchemaTree(props: SchemaTreeProps) { }; React.useEffect(() => { - if (isSuccess) { - setNavigationTreeKey(requestId); + if (createDirectoryResult.isSuccess) { + setNavigationTreeKey(createDirectoryResult.requestId); + onActivePathUpdate(`${parent}/${child}`); + setCreateDirectoryOpen(false); + } + }, [createDirectoryResult, onActivePathUpdate, parent, child]); + + React.useEffect(() => { + if (createDirectoryResult.isError) { + const errorMessage = + (createDirectoryResult.error as {data: string})?.data || ' Unknown error'; + setError(errorMessage); } - }, [isSuccess, requestId]); + }, [createDirectoryResult]); React.useEffect(() => { // if the cached path is not in the current tree, show root @@ -75,19 +86,20 @@ export function SchemaTree(props: SchemaTreeProps) { setCreateDirectoryOpen(false); }; - const handleCreateDirectorySubmit = (child: string) => { - createDirectory({database: parent, path: `${parent}/${child}`}); - - onActivePathUpdate(`${parent}/${child}`); - - setCreateDirectoryOpen(false); + const handleCreateDirectorySubmit = (value: string) => { + setChild(value); + createDirectory({database: parent, path: `${parent}/${value}`}); }; - const handleOpenCreateDirectoryDialog = (path: string) => { - setParent(path); + const handleOpenCreateDirectoryDialog = (value: string) => { + setParent(value); setCreateDirectoryOpen(true); }; + const handleCreateDirectoryUpdate = React.useCallback(() => { + setError(''); + }, []); + return ( Date: Mon, 1 Jul 2024 18:35:12 +0300 Subject: [PATCH 07/13] fix: disable apply button whet invalid input --- .../CreateDirectoryDialog.tsx | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx index b70a2b650..e0ec29207 100644 --- a/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx +++ b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx @@ -22,12 +22,18 @@ export function CreateDirectoryDialog(props: SchemaTreeProps) { const {open, parent, isLoading, onClose, onSubmit, onUpdate, error} = props; const [child, setChild] = React.useState(''); + const disabled = React.useMemo(() => { + return Boolean(error) || /\s/.test(child); + }, [error, child]); + const handleClose = () => { onClose(); }; const handleSubmit = () => { - onSubmit(child); + if (!disabled) { + onSubmit(child); + } }; const handleUpdate = (value: string) => { @@ -44,10 +50,6 @@ export function CreateDirectoryDialog(props: SchemaTreeProps) { onUpdate(child); }, [onUpdate, child]); - const invalid = React.useMemo(() => { - return /\s/.test(child); - }, [child]); - return ( @@ -63,7 +65,7 @@ export function CreateDirectoryDialog(props: SchemaTreeProps) { autoFocus hasClear disabled={isLoading} - validationState={error || invalid ? 'invalid' : undefined} + validationState={disabled ? 'invalid' : undefined} /> {error &&
{error}
} @@ -73,6 +75,7 @@ export function CreateDirectoryDialog(props: SchemaTreeProps) { textButtonCancel={i18n('schema.tree.dialog.buttonCancel')} onClickButtonCancel={handleClose} onClickButtonApply={handleSubmit} + propsButtonApply={{disabled}} />
); From d17e6d048f9c28a12713a054da88a7643f2069d4 Mon Sep 17 00:00:00 2001 From: Boris Yuzhakov Date: Mon, 1 Jul 2024 23:40:23 +0300 Subject: [PATCH 08/13] fix: create directory with dump component --- .../CreateDirectoryDialog.scss | 10 ++++++++++ .../CreateDirectoryDialog/CreateDirectoryDialog.tsx | 13 ++++++++++--- src/containers/Tenant/i18n/en.json | 1 + 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.scss b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.scss index 081eee895..2bc922b17 100644 --- a/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.scss +++ b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.scss @@ -1,4 +1,9 @@ .ydb-schema-create-directory-dialog { + &__modal { + position: relative; + + padding-bottom: 20px; + } &__label { margin-bottom: 10px; } @@ -8,6 +13,11 @@ &__error { margin-top: 10px; + color: var(--g-color-private-red-450); + } + &__invalid { + position: absolute; + color: var(--g-color-private-red-450); } } diff --git a/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx index e0ec29207..051ce40b8 100644 --- a/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx +++ b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx @@ -22,9 +22,13 @@ export function CreateDirectoryDialog(props: SchemaTreeProps) { const {open, parent, isLoading, onClose, onSubmit, onUpdate, error} = props; const [child, setChild] = React.useState(''); + const invalid = React.useMemo(() => { + return /\s/.test(child); + }, [child]); + const disabled = React.useMemo(() => { - return Boolean(error) || /\s/.test(child); - }, [error, child]); + return Boolean(error) || invalid; + }, [error, invalid]); const handleClose = () => { onClose(); @@ -67,7 +71,10 @@ export function CreateDirectoryDialog(props: SchemaTreeProps) { disabled={isLoading} validationState={disabled ? 'invalid' : undefined} /> - {error &&
{error}
} + {Boolean(error) &&
{error}
} + {!error && invalid && ( +
{i18n('schema.tree.dialog.invalid')}
+ )} Date: Tue, 2 Jul 2024 01:05:50 +0300 Subject: [PATCH 09/13] fix: make createDirectoryDialog smarter --- .../CreateDirectoryDialog.tsx | 66 +++++++++++-------- .../Tenant/Schema/SchemaTree/SchemaTree.tsx | 53 ++++----------- 2 files changed, 48 insertions(+), 71 deletions(-) diff --git a/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx index 051ce40b8..c6409a9d6 100644 --- a/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx +++ b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx @@ -2,6 +2,8 @@ import React from 'react'; import {Dialog, TextInput} from '@gravity-ui/uikit'; +import {schemaApi} from '../../../../store/reducers/schema/schema'; +import type {IResponseError} from '../../../../types/api/error'; import {cn} from '../../../../utils/cn'; import i18n from '../../i18n'; @@ -10,65 +12,71 @@ const b = cn('ydb-schema-create-directory-dialog'); interface SchemaTreeProps { open: boolean; - parent: string; - isLoading: boolean; - onClose: () => void; + onOpen: (value: boolean) => void; + parentPath: string; onSubmit: (value: string) => void; - onUpdate: (value: string) => void; - error: string; } export function CreateDirectoryDialog(props: SchemaTreeProps) { - const {open, parent, isLoading, onClose, onSubmit, onUpdate, error} = props; - const [child, setChild] = React.useState(''); + const [error, setError] = React.useState(''); + const [relativePath, setRelativePath] = React.useState(''); + const [create, response] = schemaApi.useCreateDirectoryMutation(); const invalid = React.useMemo(() => { - return /\s/.test(child); - }, [child]); + return /\s/.test(relativePath); + }, [relativePath]); const disabled = React.useMemo(() => { return Boolean(error) || invalid; }, [error, invalid]); + React.useEffect(() => { + props.onOpen(props.open); + }, [props]); + const handleClose = () => { - onClose(); + props.onOpen(false); + setRelativePath(''); }; - const handleSubmit = () => { + const handleSubmit = async () => { if (!disabled) { - onSubmit(child); + const path = `${props.parentPath}/${relativePath}`; + try { + await create({ + database: props.parentPath, + path: `${props.parentPath}/${relativePath}`, + }).unwrap(); + props.onOpen(false); + props.onSubmit(path); + setRelativePath(''); + } catch (e) { + const errorMessage = (e as IResponseError)?.data || ' Unknown error'; + setError(errorMessage); + } } }; - const handleUpdate = (value: string) => { - setChild(value); + const handleUpdate = (updated: string) => { + setRelativePath(updated); + setError(''); }; - React.useEffect(() => { - if (!open) { - setChild(''); - } - }, [open]); - - React.useEffect(() => { - onUpdate(child); - }, [onUpdate, child]); - return ( - +
{i18n('schema.tree.dialog.description')}
-
{`${parent}/`}
+
{`${props.parentPath}/`}
{Boolean(error) &&
{error}
} @@ -77,7 +85,7 @@ export function CreateDirectoryDialog(props: SchemaTreeProps) { )}
(''); - const [child, setChild] = React.useState(''); - const [navigationTreeKey, setNavigationTreeKey] = React.useState(''); - const [error, setError] = React.useState(''); - const [createDirectory, createDirectoryResult] = schemaApi.useCreateDirectoryMutation(); + const [parentPath, setParentPath] = React.useState(''); + const [path, setPath] = React.useState(''); const fetchPath = async (value: string) => { const promise = dispatch( @@ -58,23 +55,6 @@ export function SchemaTree(props: SchemaTreeProps) { return childItems; }; - - React.useEffect(() => { - if (createDirectoryResult.isSuccess) { - setNavigationTreeKey(createDirectoryResult.requestId); - onActivePathUpdate(`${parent}/${child}`); - setCreateDirectoryOpen(false); - } - }, [createDirectoryResult, onActivePathUpdate, parent, child]); - - React.useEffect(() => { - if (createDirectoryResult.isError) { - const errorMessage = - (createDirectoryResult.error as {data: string})?.data || ' Unknown error'; - setError(errorMessage); - } - }, [createDirectoryResult]); - React.useEffect(() => { // if the cached path is not in the current tree, show root if (!currentPath?.startsWith(rootPath)) { @@ -82,37 +62,26 @@ export function SchemaTree(props: SchemaTreeProps) { } }, [currentPath, onActivePathUpdate, rootPath]); - const handleCreateDirectoryClose = () => { - setCreateDirectoryOpen(false); - }; - - const handleCreateDirectorySubmit = (value: string) => { - setChild(value); - createDirectory({database: parent, path: `${parent}/${value}`}); + const handleSubmit = (relativePath: string) => { + const newPath = `${parentPath}/${relativePath}`; + onActivePathUpdate(newPath); + setPath(newPath); }; const handleOpenCreateDirectoryDialog = (value: string) => { - setParent(value); + setParentPath(value); setCreateDirectoryOpen(true); }; - - const handleCreateDirectoryUpdate = React.useCallback(() => { - setError(''); - }, []); - return ( Date: Tue, 2 Jul 2024 10:14:26 +0300 Subject: [PATCH 10/13] fix: code-review --- .../CreateDirectoryDialog.scss | 16 +--- .../CreateDirectoryDialog.tsx | 87 +++++++++---------- .../Tenant/Schema/SchemaTree/SchemaTree.tsx | 16 ++-- src/containers/Tenant/i18n/en.json | 1 + 4 files changed, 56 insertions(+), 64 deletions(-) diff --git a/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.scss b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.scss index 2bc922b17..af6a162b9 100644 --- a/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.scss +++ b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.scss @@ -1,23 +1,11 @@ .ydb-schema-create-directory-dialog { - &__modal { - position: relative; - - padding-bottom: 20px; - } &__label { margin-bottom: 10px; } &__description { color: var(--g-color-text-secondary); } - &__error { - margin-top: 10px; - - color: var(--g-color-private-red-450); - } - &__invalid { - position: absolute; - - color: var(--g-color-private-red-450); + &__error-wrapper { + height: var(--g-text-body-1-line-height); } } diff --git a/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx index c6409a9d6..049ab5419 100644 --- a/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx +++ b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx @@ -2,73 +2,68 @@ import React from 'react'; import {Dialog, TextInput} from '@gravity-ui/uikit'; +import {ResponseError} from '../../../../components/Errors/ResponseError'; import {schemaApi} from '../../../../store/reducers/schema/schema'; -import type {IResponseError} from '../../../../types/api/error'; import {cn} from '../../../../utils/cn'; import i18n from '../../i18n'; import './CreateDirectoryDialog.scss'; + const b = cn('ydb-schema-create-directory-dialog'); interface SchemaTreeProps { open: boolean; - onOpen: (value: boolean) => void; + onClose: VoidFunction; parentPath: string; - onSubmit: (value: string) => void; + onSuccess: (value: string) => void; +} + +function validateRelativePath(value: string) { + if (value && /\s/.test(value)) { + return i18n('schema.tree.dialog.whitespace'); + } + return ''; } -export function CreateDirectoryDialog(props: SchemaTreeProps) { - const [error, setError] = React.useState(''); +export function CreateDirectoryDialog({open, onClose, parentPath, onSuccess}: SchemaTreeProps) { + const [error, setError] = React.useState(''); const [relativePath, setRelativePath] = React.useState(''); const [create, response] = schemaApi.useCreateDirectoryMutation(); - const invalid = React.useMemo(() => { - return /\s/.test(relativePath); - }, [relativePath]); - - const disabled = React.useMemo(() => { - return Boolean(error) || invalid; - }, [error, invalid]); - - React.useEffect(() => { - props.onOpen(props.open); - }, [props]); + const handleUpdate = (updated: string) => { + setRelativePath(updated); + setError(validateRelativePath(updated)); + }; const handleClose = () => { - props.onOpen(false); + onClose(); setRelativePath(''); + setError(''); }; const handleSubmit = async () => { - if (!disabled) { - const path = `${props.parentPath}/${relativePath}`; - try { - await create({ - database: props.parentPath, - path: `${props.parentPath}/${relativePath}`, - }).unwrap(); - props.onOpen(false); - props.onSubmit(path); - setRelativePath(''); - } catch (e) { - const errorMessage = (e as IResponseError)?.data || ' Unknown error'; - setError(errorMessage); - } + try { + const path = `${parentPath}/${relativePath}`; + await create({ + database: parentPath, + path, + }).unwrap(); + handleClose(); + onSuccess(relativePath); + } catch (e) { + setError(e); } }; - const handleUpdate = (updated: string) => { - setRelativePath(updated); - setError(''); - }; + const hasError = Boolean(error); return ( - + - +
{i18n('schema.tree.dialog.description')}
-
{`${props.parentPath}/`}
+
{`${parentPath}/`}
- {Boolean(error) &&
{error}
} - {!error && invalid && ( -
{i18n('schema.tree.dialog.invalid')}
- )} +
+ {hasError && ( + + )} +
); diff --git a/src/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx b/src/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx index 26cbdf339..64187eddb 100644 --- a/src/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx +++ b/src/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx @@ -30,14 +30,14 @@ export function SchemaTree(props: SchemaTreeProps) { const [parentPath, setParentPath] = React.useState(''); const [path, setPath] = React.useState(''); - const fetchPath = async (value: string) => { + const fetchPath = async (path: string) => { const promise = dispatch( - schemaApi.endpoints.getSchema.initiate({path: value}, {forceRefetch: true}), + schemaApi.endpoints.getSchema.initiate({path}, {forceRefetch: true}), ); const {data} = await promise; promise.unsubscribe(); if (!data) { - throw new Error(`no describe data about path ${value}`); + throw new Error(`no describe data about path ${path}`); } const {PathDescription: {Children = []} = {}} = data; @@ -62,12 +62,16 @@ export function SchemaTree(props: SchemaTreeProps) { } }, [currentPath, onActivePathUpdate, rootPath]); - const handleSubmit = (relativePath: string) => { + const handleSuccessSubmit = (relativePath: string) => { const newPath = `${parentPath}/${relativePath}`; onActivePathUpdate(newPath); setPath(newPath); }; + const handleCloseDialog = () => { + setCreateDirectoryOpen(false); + }; + const handleOpenCreateDirectoryDialog = (value: string) => { setParentPath(value); setCreateDirectoryOpen(true); @@ -75,10 +79,10 @@ export function SchemaTree(props: SchemaTreeProps) { return ( Date: Wed, 3 Jul 2024 09:27:37 +0300 Subject: [PATCH 11/13] fix: code-review --- .../Errors/ResponseError/ResponseError.tsx | 4 +- .../CreateDirectoryDialog.tsx | 76 ++++++++++++------- .../Tenant/Schema/SchemaTree/SchemaTree.tsx | 6 +- 3 files changed, 54 insertions(+), 32 deletions(-) diff --git a/src/components/Errors/ResponseError/ResponseError.tsx b/src/components/Errors/ResponseError/ResponseError.tsx index 56994d8fd..026311f08 100644 --- a/src/components/Errors/ResponseError/ResponseError.tsx +++ b/src/components/Errors/ResponseError/ResponseError.tsx @@ -17,7 +17,9 @@ export const ResponseError = ({ statusText = error; } if (error && typeof error === 'object') { - if ('statusText' in error && typeof error.statusText === 'string') { + if ('data' in error && typeof error.data === 'string') { + statusText = error.data; + } else if ('statusText' in error && typeof error.statusText === 'string') { statusText = error.statusText; } else if ('message' in error && typeof error.message === 'string') { statusText = error.message; diff --git a/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx index 049ab5419..8a990821a 100644 --- a/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx +++ b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx @@ -27,18 +27,24 @@ function validateRelativePath(value: string) { export function CreateDirectoryDialog({open, onClose, parentPath, onSuccess}: SchemaTreeProps) { const [error, setError] = React.useState(''); + const [validationError, setValidationError] = React.useState(''); const [relativePath, setRelativePath] = React.useState(''); const [create, response] = schemaApi.useCreateDirectoryMutation(); + const resetErrors = () => { + setValidationError(''); + setError(''); + }; + const handleUpdate = (updated: string) => { setRelativePath(updated); - setError(validateRelativePath(updated)); + resetErrors(); }; const handleClose = () => { onClose(); setRelativePath(''); - setError(''); + resetErrors(); }; const handleSubmit = async () => { @@ -56,41 +62,55 @@ export function CreateDirectoryDialog({open, onClose, parentPath, onSuccess}: Sc }; const hasError = Boolean(error); + const hasValidationError = Boolean(validationError); return ( - + - -
-
{i18n('schema.tree.dialog.description')}
-
{`${parentPath}/`}
-
- -
+
{ + e.preventDefault(); + const validationError = validateRelativePath(relativePath); + setValidationError(validationError); + if (!validationError) { + handleSubmit(); + } + }} + > + +
+
+ {i18n('schema.tree.dialog.description')} +
+
{`${parentPath}/`}
+
+ +
+ {hasValidationError && } +
{hasError && ( )} -
-
- + + +
); } diff --git a/src/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx b/src/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx index 64187eddb..9d25acad1 100644 --- a/src/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx +++ b/src/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx @@ -28,7 +28,7 @@ export function SchemaTree(props: SchemaTreeProps) { const [_, setQueryMode] = useQueryModes(); const [createDirectoryOpen, setCreateDirectoryOpen] = React.useState(false); const [parentPath, setParentPath] = React.useState(''); - const [path, setPath] = React.useState(''); + const [schemaTreeKey, setSchemaTreeKey] = React.useState(''); const fetchPath = async (path: string) => { const promise = dispatch( @@ -65,7 +65,7 @@ export function SchemaTree(props: SchemaTreeProps) { const handleSuccessSubmit = (relativePath: string) => { const newPath = `${parentPath}/${relativePath}`; onActivePathUpdate(newPath); - setPath(newPath); + setSchemaTreeKey(newPath); }; const handleCloseDialog = () => { @@ -85,7 +85,7 @@ export function SchemaTree(props: SchemaTreeProps) { onSuccess={handleSuccessSubmit} /> Date: Wed, 3 Jul 2024 18:57:07 +0300 Subject: [PATCH 12/13] fix: code-review --- .../CreateDirectoryDialog.scss | 7 ++- .../CreateDirectoryDialog.tsx | 51 ++++++++++--------- 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.scss b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.scss index af6a162b9..74f6d2f62 100644 --- a/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.scss +++ b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.scss @@ -1,11 +1,14 @@ .ydb-schema-create-directory-dialog { &__label { - margin-bottom: 10px; + display: flex; + flex-direction: column; + + margin-bottom: 8px; } &__description { color: var(--g-color-text-secondary); } &__error-wrapper { - height: var(--g-text-body-1-line-height); + min-height: var(--g-text-body-1-line-height); } } diff --git a/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx index 8a990821a..8024852c9 100644 --- a/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx +++ b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx @@ -11,6 +11,8 @@ import './CreateDirectoryDialog.scss'; const b = cn('ydb-schema-create-directory-dialog'); +const relativePathInputName = 'relativePath'; + interface SchemaTreeProps { open: boolean; onClose: VoidFunction; @@ -26,14 +28,14 @@ function validateRelativePath(value: string) { } export function CreateDirectoryDialog({open, onClose, parentPath, onSuccess}: SchemaTreeProps) { - const [error, setError] = React.useState(''); + const [showResponseError, setShowResponseError] = React.useState(false); const [validationError, setValidationError] = React.useState(''); const [relativePath, setRelativePath] = React.useState(''); const [create, response] = schemaApi.useCreateDirectoryMutation(); const resetErrors = () => { setValidationError(''); - setError(''); + setShowResponseError(false); }; const handleUpdate = (updated: string) => { @@ -47,21 +49,20 @@ export function CreateDirectoryDialog({open, onClose, parentPath, onSuccess}: Sc resetErrors(); }; - const handleSubmit = async () => { - try { - const path = `${parentPath}/${relativePath}`; - await create({ - database: parentPath, - path, - }).unwrap(); - handleClose(); - onSuccess(relativePath); - } catch (e) { - setError(e); - } + const handleSubmit = () => { + setShowResponseError(true); + const path = `${parentPath}/${relativePath}`; + create({ + database: parentPath, + path, + }) + .unwrap() + .then(() => { + handleClose(); + onSuccess(relativePath); + }); }; - const hasError = Boolean(error); const hasValidationError = Boolean(validationError); return ( @@ -78,27 +79,29 @@ export function CreateDirectoryDialog({open, onClose, parentPath, onSuccess}: Sc }} > -
-
+
-
{`${parentPath}/`}
-
+ + {`${parentPath}/`} +
{hasValidationError && }
- {hasError && ( + {showResponseError && response.isError && ( )} @@ -108,7 +111,7 @@ export function CreateDirectoryDialog({open, onClose, parentPath, onSuccess}: Sc textButtonApply={i18n('schema.tree.dialog.buttonApply')} textButtonCancel={i18n('schema.tree.dialog.buttonCancel')} onClickButtonCancel={handleClose} - propsButtonApply={{disabled: hasValidationError, type: 'submit'}} + propsButtonApply={{type: 'submit'}} />
From 064ac63ca3ad2b15ca5e9b438e9f6ff03f865d20 Mon Sep 17 00:00:00 2001 From: Elena Makarova Date: Thu, 4 Jul 2024 13:19:58 +0300 Subject: [PATCH 13/13] fix: code-review --- .../CreateDirectoryDialog.scss | 4 +- .../CreateDirectoryDialog.tsx | 38 +++++++++---------- 2 files changed, 19 insertions(+), 23 deletions(-) diff --git a/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.scss b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.scss index 74f6d2f62..fb39b3476 100644 --- a/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.scss +++ b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.scss @@ -8,7 +8,7 @@ &__description { color: var(--g-color-text-secondary); } - &__error-wrapper { - min-height: var(--g-text-body-1-line-height); + &__input-wrapper { + min-height: 48px; } } diff --git a/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx index 8024852c9..301c7955b 100644 --- a/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx +++ b/src/containers/Tenant/Schema/CreateDirectoryDialog/CreateDirectoryDialog.tsx @@ -11,7 +11,7 @@ import './CreateDirectoryDialog.scss'; const b = cn('ydb-schema-create-directory-dialog'); -const relativePathInputName = 'relativePath'; +const relativePathInputId = 'relativePath'; interface SchemaTreeProps { open: boolean; @@ -28,14 +28,13 @@ function validateRelativePath(value: string) { } export function CreateDirectoryDialog({open, onClose, parentPath, onSuccess}: SchemaTreeProps) { - const [showResponseError, setShowResponseError] = React.useState(false); const [validationError, setValidationError] = React.useState(''); const [relativePath, setRelativePath] = React.useState(''); const [create, response] = schemaApi.useCreateDirectoryMutation(); const resetErrors = () => { setValidationError(''); - setShowResponseError(false); + response.reset(); }; const handleUpdate = (updated: string) => { @@ -50,7 +49,6 @@ export function CreateDirectoryDialog({open, onClose, parentPath, onSuccess}: Sc }; const handleSubmit = () => { - setShowResponseError(true); const path = `${parentPath}/${relativePath}`; create({ database: parentPath, @@ -63,8 +61,6 @@ export function CreateDirectoryDialog({open, onClose, parentPath, onSuccess}: Sc }); }; - const hasValidationError = Boolean(validationError); - return ( @@ -79,27 +75,27 @@ export function CreateDirectoryDialog({open, onClose, parentPath, onSuccess}: Sc }} > -