Skip to content
Merged
16 changes: 16 additions & 0 deletions src/shared/schema/us/actions/entries/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ import type {
GetRevisionsResponse,
GetSharedEntryBindingsArgs,
GetSharedEntryBindingsResponse,
GetSharedEntryWorkbookRelationsArgs,
GetSharedEntryWorkbookRelationsResponse,
MoveEntryArgs,
MoveEntryResponse,
RenameEntryArgs,
Expand Down Expand Up @@ -303,4 +305,18 @@ export const entriesActions = {
headers,
}),
}),
getSharedEntryWorkbookRelations: createAction<
GetSharedEntryWorkbookRelationsResponse,
GetSharedEntryWorkbookRelationsArgs
>({
method: 'GET',
path: ({entryId}) => `${PATH_PREFIX}/shared-entries/${entryId}/workbook-relations`,
params: ({scope, workbookId}, headers) => ({
query: {
workbookId,
scope,
},
headers,
}),
}),
};
11 changes: 11 additions & 0 deletions src/shared/schema/us/types/entries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import type {
EntryNavigationFields,
EntryRelationFields,
SharedEntryPermissions,
SharedEntryRelationFields,
} from './fields';

export interface GetEntryResponse extends EntryFields {
Expand Down Expand Up @@ -313,3 +314,13 @@ export type SharedEntryBindingsItem = {
export type GetSharedEntryBindingsResponse = {
items: SharedEntryBindingsItem[];
};

export type GetSharedEntryWorkbookRelationsArgs = {
entryId: string;
workbookId: string;
scope?: `${EntryScope}`;
};

export type GetSharedEntryWorkbookRelationsResponse = {
relations: SharedEntryRelationFields[];
};
5 changes: 5 additions & 0 deletions src/shared/schema/us/types/fields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@ export interface EntryRelationFields {
isLocked: boolean;
}

export type SharedEntryRelationFields = Omit<EntryRelationFields, 'isLocked'> & {
collectionId: string;
createdAt: string;
};

export interface TenantSettings {
defaultColorPaletteId?: string;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@
}

&__footer {
margin-left: -32px;
margin-right: -32px;
border-top: 1px solid var(--g-color-line-generic);
&_empty-list {
border: none;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,11 @@ export const DialogSharedEntryBindings: React.FC<DialogSharedEntryBindingsProps>
onDirectionChange,
currentDirection,
fetchEntityBindings,
isLoadingDelete,
onDelete,
} = useSharedEntryBindings({
entry,
onDeleteSuccess,
});
const showDirectionControl = entry.scope === 'dataset';

Expand All @@ -71,11 +74,12 @@ export const DialogSharedEntryBindings: React.FC<DialogSharedEntryBindingsProps>
title={getSharedEntryMockText('label-current-entry')}
className={b('current-row')}
/>
{isLoading && !isSearchLoading ? (
{(isLoading || isLoadingDelete) && !isSearchLoading ? (
<SmartLoader showAfter={0} />
) : (
<>
<DeleteAlert
isSearchActive={searchValue !== ''}
isDeleteDialog={isDeleteDialog}
entry={entry}
entities={entities}
Expand Down Expand Up @@ -105,17 +109,16 @@ export const DialogSharedEntryBindings: React.FC<DialogSharedEntryBindingsProps>
/>
</>
)}
{isDeleteDialog && (
<SharedBindingsFooter
onClose={onClose}
entry={entry}
onRefresh={() => fetchEntityBindings(searchValue)}
isLoading={isLoading || isSearchLoading}
emptyList={entities.length === 0}
onDeleteSuccess={onDeleteSuccess}
/>
)}
</Dialog.Body>
{isDeleteDialog && (
<SharedBindingsFooter
onClose={onClose}
onRefresh={() => fetchEntityBindings(searchValue)}
isLoading={isLoading || isSearchLoading || isLoadingDelete}
emptyList={entities.length === 0}
onDelete={onDelete}
/>
)}
</Dialog>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,19 @@ type DeleteAlertProps = {
entities: SharedEntryBindingsItem[];
isDeleteDialog: boolean;
isError: boolean;
isSearchActive: boolean;
};

const b = block(DialogClassName);

export const DeleteAlert = ({entities, entry, isDeleteDialog, isError}: DeleteAlertProps) => {
if (!isDeleteDialog || isError) {
export const DeleteAlert = ({
entities,
entry,
isDeleteDialog,
isError,
isSearchActive,
}: DeleteAlertProps) => {
if (!isDeleteDialog || isError || (isSearchActive && entities.length === 0)) {
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ export const Relations = ({
);
}

if (isDeleteDialog && entities.length === 0) {
if (isDeleteDialog && entities.length === 0 && searchValue === '') {
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,9 @@ import React from 'react';

import {Button, Dialog, Icon} from '@gravity-ui/uikit';
import block from 'bem-cn-lite';
import {useDispatch} from 'react-redux';
import {getSdk} from 'ui/libs/schematic-sdk';
import type {AppDispatch} from 'ui/store';
import {showToast} from 'ui/store/actions/toaster';
import {getSharedEntryMockText} from 'ui/units/collections/components/helpers';

import {DialogClassName} from '../constants';
import type {SharedEntry} from '../types';

import ArrowsRotateRightIcon from '@gravity-ui/icons/svgs/arrows-rotate-right.svg';

Expand All @@ -18,43 +13,18 @@ type SharedBindingsFooterProps = {
onRefresh: () => void;
onClose: () => void;
emptyList: boolean;
entry: SharedEntry;
onDeleteSuccess?: () => void;
onDelete: () => void;
};

const b = block(DialogClassName);

export const SharedBindingsFooter = ({
entry,
isLoading,
onRefresh,
emptyList,
onClose,
onDeleteSuccess,
onDelete,
}: SharedBindingsFooterProps) => {
const dispatch: AppDispatch = useDispatch();
const [isLoadingDelete, setIsLoadingDelete] = React.useState(false);

const onDelete = React.useCallback(async () => {
setIsLoadingDelete(true);
try {
await getSdk().sdk.mix.deleteEntry({
entryId: entry.entryId,
scope: entry.scope,
});
setIsLoadingDelete(false);
onDeleteSuccess?.();
} catch (error) {
setIsLoadingDelete(false);
dispatch(
showToast({
title: error.message,
error,
}),
);
}
}, [onDeleteSuccess, entry, dispatch]);

return (
<Dialog.Footer
textButtonApply={getSharedEntryMockText('apply-bindings-dialog-delete')}
Expand All @@ -65,17 +35,12 @@ export const SharedBindingsFooter = ({
view: 'flat',
}}
className={b('footer', {'empty-list': emptyList})}
loading={isLoading || isLoadingDelete}
loading={isLoading}
textButtonCancel={getSharedEntryMockText('cancel-bindings-dialog-delete')}
onClickButtonApply={onDelete}
onClickButtonCancel={onClose}
>
<Button
loading={isLoading || isLoadingDelete}
view="outlined"
size="l"
onClick={onRefresh}
>
<Button loading={isLoading} view="outlined" size="l" onClick={onRefresh}>
<Icon data={ArrowsRotateRightIcon} />
{getSharedEntryMockText('bindings-dialog-delete-refresh-btn')}
</Button>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
import React from 'react';

import debounce from 'lodash/debounce';
import {useDispatch} from 'react-redux';
import type {SharedEntryBindingsItem} from 'shared/schema';
import {getSdk} from 'ui/libs/schematic-sdk';
import type {AppDispatch} from 'ui/store';
import {showToast} from 'ui/store/actions/toaster';

import type {AttachmentValue} from '../constants';
import {Attachment, SEARCH_DELAY} from '../constants';
import type {SharedEntry} from '../types';
import {sortEntities} from '../utils';

type UseSharedEntryBindingsProps = {
entry: SharedEntry;
onDeleteSuccess?: () => void;
};

const CONCURRENT_ID = 'shared-entry-bindings';
const cancelConcurrentRequest = () => getSdk().cancelRequest(CONCURRENT_ID);

export const useSharedEntryBindings = ({entry}: UseSharedEntryBindingsProps) => {
export const useSharedEntryBindings = ({entry, onDeleteSuccess}: UseSharedEntryBindingsProps) => {
const dispatch: AppDispatch = useDispatch();
const [entities, setEntities] = React.useState<SharedEntryBindingsItem[]>([]);

const [currentDirection, setCurrentDirection] = React.useState<AttachmentValue>(
Expand All @@ -25,6 +31,27 @@ export const useSharedEntryBindings = ({entry}: UseSharedEntryBindingsProps) =>
const [isLoading, setIsLoading] = React.useState(true);
const [isSearchLoading, setIsSearchLoading] = React.useState(false);
const [isError, setIsError] = React.useState(false);
const [isLoadingDelete, setIsLoadingDelete] = React.useState(false);

const onDelete = React.useCallback(async () => {
setIsLoadingDelete(true);
try {
await getSdk().sdk.mix.deleteEntry({
entryId: entry.entryId,
scope: entry.scope,
});
setIsLoadingDelete(false);
onDeleteSuccess?.();
} catch (error) {
setIsLoadingDelete(false);
dispatch(
showToast({
title: error.message,
error,
}),
);
}
}, [onDeleteSuccess, entry, dispatch]);

const fetchEntityBindings = React.useCallback(
(filter = '') => {
Expand Down Expand Up @@ -91,6 +118,8 @@ export const useSharedEntryBindings = ({entry}: UseSharedEntryBindingsProps) =>
return {
isError,
isLoading,
isLoadingDelete,
onDelete,
isSearchLoading,
onSearch,
searchValue: searchFilter,
Expand Down
2 changes: 2 additions & 0 deletions src/ui/store/actions/openDialogTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import type {OpenDialogColumnSettingsArgs} from '../../units/wizard/components/D
import type {OpenDialogFieldEditorArgs} from '../../components/DialogFieldEditor/DialogFieldEditor';
import type {OpenDialogRenameEntryInNewWorkbookArgs} from '../../units/workbooks/components/RenameEntryDialog/RenameEntryDialog';
import type {OpenDialogDeleteEntryInNewWorkbookArgs} from '../../units/workbooks/components/DeleteEntryDialog/DeleteEntryDialog';
import type {OpenDialogDeleteSharedEntryInWorkbookArgs} from '../../units/workbooks/components/DeleteSharedEntryDialog/DeleteSharedEntryDialog';
import type {OpenDialogDuplicateEntryInWorkbookArgs} from '../../units/workbooks/components/DuplicateEntryDialog/DuplicateEntryDialog';
import type {OpenDialogConnS3Sources} from '../../units/connections/components/dialogs';
import type {OpenDialogConnWithInputArgs} from '../../units/connections/components/custom-forms/components/DialogWithInput';
Expand Down Expand Up @@ -129,4 +130,5 @@ export type OpenDialogArgs<T = unknown> =
| OpenDialogSharedEntryUnbindArgs
| OpenDialogSharedEntryPermissionsArgs
| OpenDialogSelectSharedEntryArgs
| OpenDialogDeleteSharedEntryInWorkbookArgs
| OpenDialogEntryDescriptionArgs;
7 changes: 7 additions & 0 deletions src/ui/units/collections/components/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,20 @@ export const mockSharedEntriesTexts = {
'apply-bindings-dialog-delete': 'Удалить',
'alert-title-info-bindings-dialog-delete': '{{entry}} нигде не используется',
'alert-message-info-bindings-dialog-delete': 'Удаление ничего не сломает',
'alert-message-info-workbook-dialog-delete':
'Удаление не повлияет на Wizard-чарты, но может повлиять на Editor-чарты если используется в них',
'alert-title-warning-bindings-dialog-delete': '{{entry}} используется в некоторых {{relation}}',
'alert-message-warning-bindings-dialog-delete':
'Перед удалением убедитесь, что ничего не сломается',
'alert-message-warning-workbook-dialog-delete':
'Перед удалением убедитесь, что ничего не сломается. Если у вас есть Editor-чарты, их придется проверить вручную',
'cancel-bindings-dialog-delete': 'Отмена',
'relations-bindings-dialog-delete': 'воркбуках и датасетах',
'relations-workbook-dialog-delete': 'зависимостях',
'relation-workbook-bindings-dialog-delete': 'воркбуках',
'relation-dataset-bindings-dialog-delete': 'датасетах',
'relation-chart-workbook-dialog-delete': 'чартах',
'relation-dash-workbook-dialog-delete': 'дашбордах',
'bindings-dialog-delete-refresh-btn': 'Обновить',
'entries-list-title-workbook': 'Воркбуки',
'entries-list-title-connection': 'Подключения',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
.dl-shared-entry-workbook-delete-dialog {
max-height: 85vh;

&__body {
display: flex;
flex-direction: column;
height: 100%;
}

&__list {
margin-top: var(--g-spacing-4);
width: 100%;
display: flex;
flex-direction: column;
gap: var(--g-spacing-4);
overflow-y: auto;
}

&__current-row {
margin-bottom: var(--g-spacing-4);
}

&__error-state {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
}

&__button-retry {
margin-top: var(--g-spacing-5);
}

&__info {
margin-bottom: var(--g-spacing-4);
}
}
Loading
Loading