@astral/ui 4.18.6 → 4.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/ConfigProvider/ConfigProvider.d.ts +9 -0
- package/components/DataGrid/Body/Body.js +3 -2
- package/components/DataGrid/Body/styles.d.ts +1 -0
- package/components/DataGrid/Body/styles.js +2 -4
- package/components/DataGrid/types.d.ts +5 -0
- package/components/fileUploading/FileUploader/FIleList/FileList.d.ts +6 -2
- package/components/fileUploading/FileUploader/FIleList/FileList.js +1 -1
- package/components/fileUploading/FileUploaderFile/Actions/Actions.js +3 -3
- package/components/fileUploading/FileUploaderFile/Actions/useLogic/useLogic.d.ts +6 -1
- package/components/fileUploading/FileUploaderFile/Actions/useLogic/useLogic.js +2 -1
- package/components/fileUploading/FileUploaderFile/FileUploaderFile.d.ts +4 -0
- package/components/fileUploading/PreviewFileUploader/FileList/FileList.d.ts +6 -2
- package/components/fileUploading/PreviewFileUploader/FileList/FileList.js +1 -1
- package/components/fileUploading/PreviewFileUploaderFile/FilePreview/FilePreview.d.ts +4 -0
- package/components/fileUploading/PreviewFileUploaderFile/FilePreview/FilePreview.js +2 -2
- package/components/fileUploading/PreviewFileUploaderFile/PreviewFileUploaderFile.d.ts +4 -0
- package/components/fileUploading/PreviewFileUploaderFile/PreviewFileUploaderFile.js +2 -2
- package/components/fileUploading/hooks/useFileUploader/useFileUploader.d.ts +2 -1
- package/components/fileUploading/hooks/useFileUploader/useFileUploader.js +17 -5
- package/components/fileUploading/hooks/usePreviewFileUploader/usePreviewFileUploader.d.ts +10 -2
- package/components/fileUploading/hooks/usePreviewFileUploader/usePreviewFileUploader.js +14 -4
- package/components/fileUploading/types.d.ts +7 -0
- package/node/components/ConfigProvider/ConfigProvider.d.ts +9 -0
- package/node/components/DataGrid/Body/Body.js +3 -2
- package/node/components/DataGrid/Body/styles.d.ts +1 -0
- package/node/components/DataGrid/Body/styles.js +2 -4
- package/node/components/DataGrid/types.d.ts +5 -0
- package/node/components/fileUploading/FileUploader/FIleList/FileList.d.ts +6 -2
- package/node/components/fileUploading/FileUploader/FIleList/FileList.js +1 -1
- package/node/components/fileUploading/FileUploaderFile/Actions/Actions.js +3 -3
- package/node/components/fileUploading/FileUploaderFile/Actions/useLogic/useLogic.d.ts +6 -1
- package/node/components/fileUploading/FileUploaderFile/Actions/useLogic/useLogic.js +2 -1
- package/node/components/fileUploading/FileUploaderFile/FileUploaderFile.d.ts +4 -0
- package/node/components/fileUploading/PreviewFileUploader/FileList/FileList.d.ts +6 -2
- package/node/components/fileUploading/PreviewFileUploader/FileList/FileList.js +1 -1
- package/node/components/fileUploading/PreviewFileUploaderFile/FilePreview/FilePreview.d.ts +4 -0
- package/node/components/fileUploading/PreviewFileUploaderFile/FilePreview/FilePreview.js +2 -2
- package/node/components/fileUploading/PreviewFileUploaderFile/PreviewFileUploaderFile.d.ts +4 -0
- package/node/components/fileUploading/PreviewFileUploaderFile/PreviewFileUploaderFile.js +2 -2
- package/node/components/fileUploading/hooks/useFileUploader/useFileUploader.d.ts +2 -1
- package/node/components/fileUploading/hooks/useFileUploader/useFileUploader.js +16 -4
- package/node/components/fileUploading/hooks/usePreviewFileUploader/usePreviewFileUploader.d.ts +10 -2
- package/node/components/fileUploading/hooks/usePreviewFileUploader/usePreviewFileUploader.js +13 -3
- package/node/components/fileUploading/types.d.ts +7 -0
- package/package.json +1 -1
- package/hook-form/FormFileUploader/faker.d.ts +0 -2
- package/hook-form/FormFileUploader/faker.js +0 -37
- package/hook-form/FormPreviewFileUploader/faker.d.ts +0 -2
- package/hook-form/FormPreviewFileUploader/faker.js +0 -37
- package/node/hook-form/FormFileUploader/faker.d.ts +0 -2
- package/node/hook-form/FormFileUploader/faker.js +0 -44
- package/node/hook-form/FormPreviewFileUploader/faker.d.ts +0 -2
- package/node/hook-form/FormPreviewFileUploader/faker.js +0 -44
|
@@ -117,6 +117,15 @@ export type ConfigContextProps = {
|
|
|
117
117
|
isSmoothLoading?: boolean;
|
|
118
118
|
};
|
|
119
119
|
};
|
|
120
|
+
dataGrid?: {
|
|
121
|
+
defaultProps?: {
|
|
122
|
+
/**
|
|
123
|
+
* Флаг отключения минимальной высоты таблицы.
|
|
124
|
+
* Необходимо включить флаг, чтобы избежать баг с скроллом таблицы: https://track.astral.ru/soft/browse/UIKIT-3008.
|
|
125
|
+
*/
|
|
126
|
+
disableMinHeight?: boolean;
|
|
127
|
+
};
|
|
128
|
+
};
|
|
120
129
|
};
|
|
121
130
|
};
|
|
122
131
|
export type ConfigProviderProps = Partial<ConfigContextProps> & {
|
|
@@ -10,8 +10,9 @@ import { Wrapper } from './styles';
|
|
|
10
10
|
import { useLogic } from './useLogic';
|
|
11
11
|
const INITIAL_LEVEL = 0;
|
|
12
12
|
export const Body = (props) => {
|
|
13
|
-
const { imagesMap } = useContext(ConfigContext);
|
|
13
|
+
const { imagesMap, components } = useContext(ConfigContext);
|
|
14
14
|
const { isNoData, contentStateProps } = useLogic(props);
|
|
15
|
+
const disableMinHeight = components?.dataGrid?.defaultProps?.disableMinHeight;
|
|
15
16
|
const { rows, selectedRows = [], isLoading, isError, errorMsg, minDisplayRows, keyId, noDataPlaceholder, onRetry, ...rowProps } = props;
|
|
16
17
|
const renderedRows = rows.map(({ children, options, ...row }) => {
|
|
17
18
|
const rowId = row[keyId];
|
|
@@ -20,7 +21,7 @@ export const Body = (props) => {
|
|
|
20
21
|
});
|
|
21
22
|
return (_jsx(Wrapper, { className: classNames(dataGridClassnames.body, {
|
|
22
23
|
[dataGridClassnames.bodyEmpty]: isNoData,
|
|
23
|
-
}), "$minDisplayRows": minDisplayRows, children: _jsx(ContentState, { ...contentStateProps, errorState: {
|
|
24
|
+
}), "$minDisplayRows": minDisplayRows, "$disableMinHeight": disableMinHeight, children: _jsx(ContentState, { ...contentStateProps, errorState: {
|
|
24
25
|
imgAlt: 'Что-то пошло не так',
|
|
25
26
|
errorList: [errorMsg || ''],
|
|
26
27
|
imgSrc: imagesMap.defaultErrorImgSrc,
|
|
@@ -4,4 +4,5 @@ export declare const Wrapper: import("../../styled").StyledComponent<{
|
|
|
4
4
|
as?: import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements> | undefined;
|
|
5
5
|
} & {
|
|
6
6
|
$minDisplayRows: number;
|
|
7
|
+
$disableMinHeight?: boolean | undefined;
|
|
7
8
|
}, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLUListElement>, HTMLUListElement>, {}>;
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import { styled } from '../../styled';
|
|
2
2
|
import { dataGridClassnames, MIN_ROW_HEIGHT } from '../constants';
|
|
3
|
-
export const Wrapper = styled
|
|
4
|
-
shouldForwardProp: (prop) => !['$minDisplayRows'].includes(prop),
|
|
5
|
-
}) `
|
|
3
|
+
export const Wrapper = styled.ul `
|
|
6
4
|
overflow-y: auto;
|
|
7
5
|
|
|
8
6
|
width: fit-content;
|
|
9
7
|
min-width: 100%;
|
|
10
8
|
height: 100%;
|
|
11
|
-
min-height: ${({ $minDisplayRows }) => `${MIN_ROW_HEIGHT * $minDisplayRows}px`};
|
|
9
|
+
min-height: ${({ $minDisplayRows, $disableMinHeight }) => ($disableMinHeight ? 'unset' : `${MIN_ROW_HEIGHT * $minDisplayRows}px`)};
|
|
12
10
|
margin: 0;
|
|
13
11
|
padding: 0;
|
|
14
12
|
|
|
@@ -131,6 +131,11 @@ export type DataGridProps<TData extends Record<string, CellValue> = DataGridRow,
|
|
|
131
131
|
/**
|
|
132
132
|
* Используется для отображения переданного кол-ва строк при отсутствии данных
|
|
133
133
|
* @default 10
|
|
134
|
+
* @deprecated Не поддерживается, параметр будет удален в следующей major версии пакета.
|
|
135
|
+
* Мотивация: задание минимальной высоты через параметр компонента мешает корректной работе таблицы
|
|
136
|
+
* в части верстки.
|
|
137
|
+
* Чтобы отключить минимальную высоту таблицы, задайте в ConfigProvider:
|
|
138
|
+
* `components.dataGrid.defaultProps.disableMinHeight: true`
|
|
134
139
|
*/
|
|
135
140
|
minDisplayRows?: number;
|
|
136
141
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type FileUploaderFileProps } from '../../FileUploaderFile';
|
|
2
|
-
import { type UploadFile } from '../../types';
|
|
2
|
+
import { type FileId, type UploadFile } from '../../types';
|
|
3
3
|
export type FileListProps = {
|
|
4
4
|
isMultiple?: boolean;
|
|
5
5
|
/**
|
|
@@ -7,5 +7,9 @@ export type FileListProps = {
|
|
|
7
7
|
*/
|
|
8
8
|
files?: UploadFile[];
|
|
9
9
|
className?: string;
|
|
10
|
+
/**
|
|
11
|
+
* Идентификатор файла, для которого выполняется удаление
|
|
12
|
+
*/
|
|
13
|
+
deletingFileId?: FileId | null;
|
|
10
14
|
} & Pick<FileUploaderFileProps, 'onDelete' | 'onRetry' | 'onView' | 'generateDownloadLink' | 'selfFiles' | 'setErrorStatusFile'>;
|
|
11
|
-
export declare const FileList: ({ isMultiple, files, className, ...restProps }: FileListProps) => import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
export declare const FileList: ({ isMultiple, files, className, deletingFileId, ...restProps }: FileListProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { FileUploaderFile, } from '../../FileUploaderFile';
|
|
3
3
|
import { Wrapper } from './styles';
|
|
4
|
-
export const FileList = ({ isMultiple, files, className, ...restProps }) => (_jsx(Wrapper, { "$isMultiple": isMultiple, className: className, children: files?.map((file) => (_jsx("li", { children: _jsx(FileUploaderFile, { ...file, ...restProps }) }, file.id))) }));
|
|
4
|
+
export const FileList = ({ isMultiple, files, className, deletingFileId, ...restProps }) => (_jsx(Wrapper, { "$isMultiple": isMultiple, className: className, children: files?.map((file) => (_jsx("li", { children: _jsx(FileUploaderFile, { ...file, ...restProps, isDeletingFile: deletingFileId === file.id }) }, file.id))) }));
|
|
@@ -9,13 +9,13 @@ import { Tooltip } from '../../../Tooltip';
|
|
|
9
9
|
import { Wrapper } from './styles';
|
|
10
10
|
import { useLogic } from './useLogic';
|
|
11
11
|
export const Actions = (props) => {
|
|
12
|
-
const { downloadButtonProps, viewButtonProps, isVisibleAbortButton, isVisibleRetryButton, handleAbort, handleDelete, handleRetry, isLoading, isError, fileName, } = useLogic(props);
|
|
12
|
+
const { downloadButtonProps, viewButtonProps, isVisibleAbortButton, isVisibleRetryButton, handleAbort, handleDelete, handleRetry, isLoading, isError, isDeletingFile, fileName, } = useLogic(props);
|
|
13
13
|
if (isLoading) {
|
|
14
14
|
return (_jsx(Wrapper, { children: isVisibleAbortButton && (_jsx(Tooltip, { title: "\u041E\u0442\u043C\u0435\u043D\u0438\u0442\u044C \u0437\u0430\u0433\u0440\u0443\u0437\u043A\u0443", children: _jsx(IconButton, { variant: "text", onClick: handleAbort, children: _jsx(CrossOutlineMd, {}) }) })) }));
|
|
15
15
|
}
|
|
16
16
|
if (isError) {
|
|
17
|
-
return (_jsxs(Wrapper, { children: [isVisibleRetryButton && (_jsx(Tooltip, { title: "\u041F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u044C \u0437\u0430\u0433\u0440\u0443\u0437\u043A\u0443", children: _jsx(IconButton, { variant: "text", onClick: handleRetry, children: _jsx(RetryOutlineMd, {}) }) })), _jsx(Tooltip, { title: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C", children: _jsx(IconButton, { variant: "text", onClick: handleDelete, children: _jsx(CrossOutlineMd, {}) }) })] }));
|
|
17
|
+
return (_jsxs(Wrapper, { children: [isVisibleRetryButton && (_jsx(Tooltip, { title: "\u041F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u044C \u0437\u0430\u0433\u0440\u0443\u0437\u043A\u0443", children: _jsx(IconButton, { variant: "text", onClick: handleRetry, children: _jsx(RetryOutlineMd, {}) }) })), _jsx(Tooltip, { title: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C", children: _jsx(IconButton, { variant: "text", onClick: handleDelete, loading: isDeletingFile, children: _jsx(CrossOutlineMd, {}) }) })] }));
|
|
18
18
|
}
|
|
19
19
|
const { isShowViewButton, ...restViewButtonProps } = viewButtonProps;
|
|
20
|
-
return (_jsxs(Wrapper, { children: [isShowViewButton && (_jsx(Tooltip, { title: "\u041F\u043E\u0441\u043C\u043E\u0442\u0440\u0435\u0442\u044C", children: _jsx(IconButton, { variant: "text", ...restViewButtonProps, children: _jsx(EyeOutlineMd, {}) }) })), _jsx(Tooltip, { title: "\u0421\u043A\u0430\u0447\u0430\u0442\u044C", children: _jsx(IconButton, { component: "a", variant: "text", download: fileName, ...downloadButtonProps, children: _jsx(DownloadOutlineMd, {}) }) }), _jsx(Tooltip, { title: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C", children: _jsx(IconButton, { variant: "text", onClick: handleDelete, children: _jsx(BinOutlineMd, {}) }) })] }));
|
|
20
|
+
return (_jsxs(Wrapper, { children: [isShowViewButton && (_jsx(Tooltip, { title: "\u041F\u043E\u0441\u043C\u043E\u0442\u0440\u0435\u0442\u044C", children: _jsx(IconButton, { variant: "text", ...restViewButtonProps, children: _jsx(EyeOutlineMd, {}) }) })), _jsx(Tooltip, { title: "\u0421\u043A\u0430\u0447\u0430\u0442\u044C", children: _jsx(IconButton, { component: "a", variant: "text", download: fileName, ...downloadButtonProps, children: _jsx(DownloadOutlineMd, {}) }) }), _jsx(Tooltip, { title: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C", children: _jsx(IconButton, { variant: "text", onClick: handleDelete, loading: isDeletingFile, children: _jsx(BinOutlineMd, {}) }) })] }));
|
|
21
21
|
};
|
|
@@ -45,9 +45,13 @@ export type UseLogicParams = {
|
|
|
45
45
|
* Функция, вызываемая при удалении файла
|
|
46
46
|
*/
|
|
47
47
|
onDelete: (fileId: FileId) => void;
|
|
48
|
+
/**
|
|
49
|
+
* Флаг загрузки при удалении файла
|
|
50
|
+
*/
|
|
51
|
+
isDeletingFile?: boolean;
|
|
48
52
|
abortController?: AbortController;
|
|
49
53
|
} & Pick<SelfFileApi, 'selfFiles' | 'setErrorStatusFile'>;
|
|
50
|
-
export declare const useLogic: ({ fileId, file, fileUrl, isUploadError, generateDownloadLink, onDelete, onRetry, onView, setErrorStatusFile, selfFiles, isLoading, isError, fileName, }: UseLogicParams) => {
|
|
54
|
+
export declare const useLogic: ({ fileId, file, fileUrl, isUploadError, generateDownloadLink, onDelete, onRetry, onView, setErrorStatusFile, selfFiles, isLoading, isError, isDeletingFile, fileName, }: UseLogicParams) => {
|
|
51
55
|
downloadButtonProps: {
|
|
52
56
|
href: string;
|
|
53
57
|
};
|
|
@@ -69,5 +73,6 @@ export declare const useLogic: ({ fileId, file, fileUrl, isUploadError, generate
|
|
|
69
73
|
handleRetry: () => void | undefined;
|
|
70
74
|
isLoading: boolean | undefined;
|
|
71
75
|
isError: boolean | undefined;
|
|
76
|
+
isDeletingFile: boolean | undefined;
|
|
72
77
|
fileName: string;
|
|
73
78
|
};
|
|
@@ -4,7 +4,7 @@ import { ConfigContext } from '../../../../ConfigProvider';
|
|
|
4
4
|
import { ABORT_ERROR_MESSAGE, EXTENSIONS_IN_NEW_TAB, VIEW_NEW_TAB_ERROR_MESSAGE, } from '../../../constants';
|
|
5
5
|
import { useGenerateLocalFileURL } from '../../../hooks/useGenerateLocalFileURL';
|
|
6
6
|
import { generateAttrLinkNewTab } from '../../../utils/generateAttrLinkNewTab';
|
|
7
|
-
export const useLogic = ({ fileId, file, fileUrl, isUploadError, generateDownloadLink, onDelete, onRetry, onView, setErrorStatusFile, selfFiles, isLoading, isError, fileName, }) => {
|
|
7
|
+
export const useLogic = ({ fileId, file, fileUrl, isUploadError, generateDownloadLink, onDelete, onRetry, onView, setErrorStatusFile, selfFiles, isLoading, isError, isDeletingFile, fileName, }) => {
|
|
8
8
|
const { captureException } = useContext(ConfigContext);
|
|
9
9
|
const { generateUrl } = useGenerateLocalFileURL();
|
|
10
10
|
const { controller } = selfFiles[fileId] || {};
|
|
@@ -71,6 +71,7 @@ export const useLogic = ({ fileId, file, fileUrl, isUploadError, generateDownloa
|
|
|
71
71
|
handleRetry,
|
|
72
72
|
isLoading,
|
|
73
73
|
isError,
|
|
74
|
+
isDeletingFile,
|
|
74
75
|
fileName,
|
|
75
76
|
};
|
|
76
77
|
};
|
|
@@ -17,5 +17,9 @@ export type FileUploaderFileProps = UploadFile & {
|
|
|
17
17
|
* Функция, вызываемая при удалении файла
|
|
18
18
|
*/
|
|
19
19
|
onDelete: (fileId: FileId) => void;
|
|
20
|
+
/**
|
|
21
|
+
* Флаг загрузки при удалении файла
|
|
22
|
+
*/
|
|
23
|
+
isDeletingFile?: boolean;
|
|
20
24
|
} & Pick<ActionsProps, 'selfFiles' | 'setErrorStatusFile'>;
|
|
21
25
|
export declare const FileUploaderFile: (props: FileUploaderFileProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { type PreviewFileUploaderFileProps } from '../../PreviewFileUploaderFile';
|
|
2
|
-
import {
|
|
2
|
+
import type { FileId, UploadFile } from '../../types';
|
|
3
3
|
export type FileListProps = {
|
|
4
4
|
files: UploadFile[];
|
|
5
|
+
/**
|
|
6
|
+
* Идентификатор файла, для которого выполняется удаление
|
|
7
|
+
*/
|
|
8
|
+
deletingFileId?: FileId | null;
|
|
5
9
|
} & Pick<PreviewFileUploaderFileProps, 'onDelete' | 'onRetry' | 'onView' | 'generateDownloadLink' | 'selfFiles' | 'setErrorStatusFile'>;
|
|
6
|
-
export declare const FileList: ({ files, ...restProps }: FileListProps) => import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export declare const FileList: ({ files, deletingFileId, ...restProps }: FileListProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { PreviewFileUploaderFile, } from '../../PreviewFileUploaderFile';
|
|
3
|
-
export const FileList = ({ files, ...restProps }) => (_jsx(_Fragment, { children: files?.map((file) => (_jsx(PreviewFileUploaderFile, { ...file, ...restProps }, file.id))) }));
|
|
3
|
+
export const FileList = ({ files, deletingFileId, ...restProps }) => (_jsx(_Fragment, { children: files?.map((file) => (_jsx(PreviewFileUploaderFile, { ...file, ...restProps, isDeletingFile: deletingFileId === file.id }, file.id))) }));
|
|
@@ -42,6 +42,10 @@ export type FilePreviewProps = {
|
|
|
42
42
|
* Скрытие персональных данных от инструментов мониторинга
|
|
43
43
|
*/
|
|
44
44
|
isHidePersonalData?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Флаг загрузки при удалении файла
|
|
47
|
+
*/
|
|
48
|
+
isDeletingFile?: boolean;
|
|
45
49
|
/**
|
|
46
50
|
* Компонент для отображения превью pdf-файлов
|
|
47
51
|
*/
|
|
@@ -13,7 +13,7 @@ import { Actions, Details, StyledFileInfo, Wrapper } from './styles';
|
|
|
13
13
|
import { useLogic } from './useLogic';
|
|
14
14
|
export const FilePreview = (props) => {
|
|
15
15
|
const { viewButtonProps, downloadButtonProps, deleteButtonProps, isImageFile, isPdfFile, isOtherFile, } = useLogic(props);
|
|
16
|
-
const { file, fileName, fileSize, fileUrl, generateDownloadLink, isHidePersonalData, PdfViewer, } = props;
|
|
16
|
+
const { file, fileName, fileSize, fileUrl, generateDownloadLink, isHidePersonalData, PdfViewer, isDeletingFile, } = props;
|
|
17
17
|
const { isMobile } = useViewportType();
|
|
18
|
-
return (_jsxs(Wrapper, { children: [_jsx(Preview, { isImageFile: isImageFile, isPdfFile: isPdfFile, file: file, fileUrl: fileUrl, generateDownloadLink: generateDownloadLink, isHidePersonalData: isHidePersonalData, PdfViewer: PdfViewer }), _jsxs(Details, { className: previewFileUploaderClassnames.details, "$isOtherFile": isOtherFile, children: [isOtherFile && _jsx(Typography, { variant: "h6", children: "\u0424\u0430\u0439\u043B \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043D" }), _jsx(StyledFileInfo, { "$isOtherFile": isOtherFile, fileName: fileName, fileSize: fileSize }), _jsx(Actions, { children: isMobile && isOtherFile ? (_jsx(Button, { variant: "light", color: "grey", ...deleteButtonProps, children: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C" })) : (_jsxs(_Fragment, { children: [!isOtherFile && (_jsx(Tooltip, { title: "\u041F\u043E\u0441\u043C\u043E\u0442\u0440\u0435\u0442\u044C", disableInteractive: true, children: _jsx(IconButton, { variant: "light", color: "grey", ...viewButtonProps, children: _jsx(EyeOutlineMd, {}) }) })), _jsx(Tooltip, { title: "\u0421\u043A\u0430\u0447\u0430\u0442\u044C", disableInteractive: true, children: _jsx(IconButton, { component: "a", variant: "light", color: "grey", download: fileName, ...downloadButtonProps, children: _jsx(DownloadOutlineMd, {}) }) }), _jsx(Tooltip, { title: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C", disableInteractive: true, children: _jsx(IconButton, { variant: "light", color: "grey", ...deleteButtonProps, children: _jsx(BinOutlineMd, {}) }) })] })) })] })] }));
|
|
18
|
+
return (_jsxs(Wrapper, { children: [_jsx(Preview, { isImageFile: isImageFile, isPdfFile: isPdfFile, file: file, fileUrl: fileUrl, generateDownloadLink: generateDownloadLink, isHidePersonalData: isHidePersonalData, PdfViewer: PdfViewer }), _jsxs(Details, { className: previewFileUploaderClassnames.details, "$isOtherFile": isOtherFile, children: [isOtherFile && _jsx(Typography, { variant: "h6", children: "\u0424\u0430\u0439\u043B \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043D" }), _jsx(StyledFileInfo, { "$isOtherFile": isOtherFile, fileName: fileName, fileSize: fileSize }), _jsx(Actions, { children: isMobile && isOtherFile ? (_jsx(Button, { variant: "light", color: "grey", loading: isDeletingFile, ...deleteButtonProps, children: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C" })) : (_jsxs(_Fragment, { children: [!isOtherFile && (_jsx(Tooltip, { title: "\u041F\u043E\u0441\u043C\u043E\u0442\u0440\u0435\u0442\u044C", disableInteractive: true, children: _jsx(IconButton, { variant: "light", color: "grey", ...viewButtonProps, children: _jsx(EyeOutlineMd, {}) }) })), _jsx(Tooltip, { title: "\u0421\u043A\u0430\u0447\u0430\u0442\u044C", disableInteractive: true, children: _jsx(IconButton, { component: "a", variant: "light", color: "grey", download: fileName, ...downloadButtonProps, children: _jsx(DownloadOutlineMd, {}) }) }), _jsx(Tooltip, { title: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C", disableInteractive: true, children: _jsx(IconButton, { variant: "light", color: "grey", loading: isDeletingFile, ...deleteButtonProps, children: _jsx(BinOutlineMd, {}) }) })] })) })] })] }));
|
|
19
19
|
};
|
|
@@ -23,6 +23,10 @@ export type PreviewFileUploaderFileProps = UploadFile & {
|
|
|
23
23
|
* Скрытие персональных данных от инструментов мониторинга
|
|
24
24
|
*/
|
|
25
25
|
isHidePersonalData?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Флаг загрузки при удалении файла
|
|
28
|
+
*/
|
|
29
|
+
isDeletingFile?: boolean;
|
|
26
30
|
/**
|
|
27
31
|
* Компонент для отображения превью pdf-файлов
|
|
28
32
|
*/
|
|
@@ -5,8 +5,8 @@ import { FileLoading } from './FileLoading';
|
|
|
5
5
|
import { FilePreview } from './FilePreview';
|
|
6
6
|
import { Wrapper } from './styles';
|
|
7
7
|
export const PreviewFileUploaderFile = (props) => {
|
|
8
|
-
const { id, name, type, file, url, size, status, generateDownloadLink, onRetry, onDelete, onView, selfFiles, setErrorStatusFile, isHidePersonalData, PdfViewer, } = props;
|
|
8
|
+
const { id, name, type, file, url, size, status, generateDownloadLink, onRetry, onDelete, onView, selfFiles, setErrorStatusFile, isHidePersonalData, PdfViewer, isDeletingFile, } = props;
|
|
9
9
|
const { isLoading, isUploadError, isRestrictionError, errorMsg, progress } = status || {};
|
|
10
10
|
const isError = isUploadError || isRestrictionError;
|
|
11
|
-
return (_jsx(Fade, { in: true, children: _jsxs(Wrapper, { "$isLoading": isLoading, "$isError": isError, children: [!isLoading && !isError && (_jsx(FilePreview, { fileId: id, fileName: name, fileType: type, file: file, fileUrl: url, fileSize: size, generateDownloadLink: generateDownloadLink, onView: onView, onDelete: onDelete, isHidePersonalData: isHidePersonalData, PdfViewer: PdfViewer })), isLoading && (_jsx(FileLoading, { selfFiles: selfFiles, setErrorStatusFile: setErrorStatusFile, fileId: id, fileName: name, fileSize: size, progress: progress })), isError && (_jsx(FileError, { fileId: id, fileName: name, file: file, fileSize: size, errorMsg: errorMsg, isUploadError: isUploadError, onRetry: onRetry, onDelete: onDelete }))] }) }));
|
|
11
|
+
return (_jsx(Fade, { in: true, children: _jsxs(Wrapper, { "$isLoading": isLoading, "$isError": isError, children: [!isLoading && !isError && (_jsx(FilePreview, { fileId: id, fileName: name, fileType: type, file: file, fileUrl: url, fileSize: size, generateDownloadLink: generateDownloadLink, onView: onView, onDelete: onDelete, isHidePersonalData: isHidePersonalData, PdfViewer: PdfViewer, isDeletingFile: isDeletingFile })), isLoading && (_jsx(FileLoading, { selfFiles: selfFiles, setErrorStatusFile: setErrorStatusFile, fileId: id, fileName: name, fileSize: size, progress: progress })), isError && (_jsx(FileError, { fileId: id, fileName: name, file: file, fileSize: size, errorMsg: errorMsg, isUploadError: isUploadError, onRetry: onRetry, onDelete: onDelete }))] }) }));
|
|
12
12
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type ChangeEvent } from 'react';
|
|
2
2
|
import type { FileId, FileUploaderProps, UploadFile } from '../../types';
|
|
3
3
|
export type UseFileUploaderParams = FileUploaderProps;
|
|
4
|
-
export declare const useFileUploader: ({ value, isDisabled, isMultiple, accept, restrictions, maxFileSize, maxFileCount, inputRef, notify, onChange, onUploadFile, name, isError, onView, generateDownloadLink, placeholder, helperText, label, className, getErrorMessage, }: UseFileUploaderParams) => {
|
|
4
|
+
export declare const useFileUploader: ({ value, isDisabled, isMultiple, accept, restrictions, maxFileSize, maxFileCount, inputRef, notify, onChange, onUploadFile, onDeleteFile, name, isError, onView, generateDownloadLink, placeholder, helperText, label, className, getErrorMessage, }: UseFileUploaderParams) => {
|
|
5
5
|
dropZoneProps: {
|
|
6
6
|
isLimitMaxFileCount: boolean;
|
|
7
7
|
maxFileCount: number;
|
|
@@ -53,5 +53,6 @@ export declare const useFileUploader: ({ value, isDisabled, isMultiple, accept,
|
|
|
53
53
|
selfFiles: Record<string, UploadFile & import("../../types").SpecificSelfFileParams>;
|
|
54
54
|
setErrorStatusFile: (fileId: string, errorMsg: string) => void;
|
|
55
55
|
getErrorMessage: ((fileId: string, error: Error) => string) | undefined;
|
|
56
|
+
deletingFileId: string | null;
|
|
56
57
|
};
|
|
57
58
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { declensionOfWords } from '@astral/utils/declension/declensionOfWords';
|
|
2
2
|
import { formatFileSizeToView } from '@astral/utils/file/formatFileSizeToView';
|
|
3
|
-
import { useMemo } from 'react';
|
|
3
|
+
import { useMemo, useState } from 'react';
|
|
4
4
|
import { useGenerateLocalId } from '../../../useGenerateLocalId';
|
|
5
5
|
import { useId } from '../../../useId';
|
|
6
6
|
import { DEFAULT_FILE_STATUS, fileUploaderClassnames } from '../../constants';
|
|
@@ -11,8 +11,9 @@ import { toArray } from '../../utils/toArray';
|
|
|
11
11
|
import { useDnD } from '../useDnD';
|
|
12
12
|
import { useUploadFiles } from '../useUploadFiles';
|
|
13
13
|
export const useFileUploader = ({ value, isDisabled, isMultiple, accept, restrictions = [], maxFileSize, maxFileCount = 1, // для случая, когда isMultiple=false
|
|
14
|
-
inputRef, notify, onChange, onUploadFile, name, isError, onView, generateDownloadLink, placeholder, helperText, label, className, getErrorMessage, }) => {
|
|
14
|
+
inputRef, notify, onChange, onUploadFile, onDeleteFile, name, isError, onView, generateDownloadLink, placeholder, helperText, label, className, getErrorMessage, }) => {
|
|
15
15
|
const inputId = useId();
|
|
16
|
+
const [deletingFileId, setDeletingFileId] = useState(null);
|
|
16
17
|
const { generateId } = useGenerateLocalId();
|
|
17
18
|
// Преобразуем value к массиву
|
|
18
19
|
const files = useMemo(() => toArray(value), [value]);
|
|
@@ -94,10 +95,20 @@ inputRef, notify, onChange, onUploadFile, name, isError, onView, generateDownloa
|
|
|
94
95
|
},
|
|
95
96
|
});
|
|
96
97
|
const handleDelete = (fileId) => {
|
|
97
|
-
|
|
98
|
-
|
|
98
|
+
const deleteFile = () => {
|
|
99
|
+
if (isMultiple) {
|
|
100
|
+
return onChange(files?.filter(({ id }) => id !== fileId));
|
|
101
|
+
}
|
|
102
|
+
return onChange(null);
|
|
103
|
+
};
|
|
104
|
+
if (!onDeleteFile) {
|
|
105
|
+
return deleteFile();
|
|
99
106
|
}
|
|
100
|
-
|
|
107
|
+
setDeletingFileId(fileId);
|
|
108
|
+
onDeleteFile(fileId)
|
|
109
|
+
.then(deleteFile)
|
|
110
|
+
.catch(() => notify.error('Ошибка удаления файла'))
|
|
111
|
+
.finally(() => setDeletingFileId(null));
|
|
101
112
|
};
|
|
102
113
|
const getHandlerOnRetry = () => {
|
|
103
114
|
if (onUploadFile) {
|
|
@@ -155,6 +166,7 @@ inputRef, notify, onChange, onUploadFile, name, isError, onView, generateDownloa
|
|
|
155
166
|
selfFiles,
|
|
156
167
|
setErrorStatusFile,
|
|
157
168
|
getErrorMessage,
|
|
169
|
+
deletingFileId,
|
|
158
170
|
},
|
|
159
171
|
};
|
|
160
172
|
};
|
|
@@ -117,6 +117,13 @@ export type UsePreviewFileUploaderParams = {
|
|
|
117
117
|
* - При обновлении информации о файле после успешной загрузки
|
|
118
118
|
*/
|
|
119
119
|
onChange: (value: UploadFile | null) => void;
|
|
120
|
+
/**
|
|
121
|
+
* Функция, вызываемая при удалении файла.
|
|
122
|
+
* Используется для сбора идентификаторов файлов, помеченных на удаление.
|
|
123
|
+
* Фактическое удаление файлов с сервера должно выполняться только при подтверждении формы,
|
|
124
|
+
* чтобы избежать потери данных при отмене действия или перезагрузке страницы.
|
|
125
|
+
*/
|
|
126
|
+
onDeleteFile?: (fileId: FileId) => Promise<void>;
|
|
120
127
|
/**
|
|
121
128
|
* Скрытие персональных данных от инструментов мониторинга
|
|
122
129
|
*/
|
|
@@ -126,7 +133,7 @@ export type UsePreviewFileUploaderParams = {
|
|
|
126
133
|
*/
|
|
127
134
|
PdfViewer?: ((props: PdfViewerProps) => ReactElement) | LazyExoticComponent<(props: PdfViewerProps) => ReactElement>;
|
|
128
135
|
};
|
|
129
|
-
export declare const usePreviewFileUploader: ({ value, isDisabled, accept, restrictions, maxFileSize, inputRef, notify, onChange, onUploadFile, label, isError, generateDownloadLink, onView, name, helperText, className, placeholder, placeholderImgSrc, isHidePersonalData, PdfViewer, }: UsePreviewFileUploaderParams) => {
|
|
136
|
+
export declare const usePreviewFileUploader: ({ value, isDisabled, accept, restrictions, maxFileSize, inputRef, notify, onChange, onUploadFile, onDeleteFile, label, isError, generateDownloadLink, onView, name, helperText, className, placeholder, placeholderImgSrc, isHidePersonalData, PdfViewer, }: UsePreviewFileUploaderParams) => {
|
|
130
137
|
dropZoneProps: {
|
|
131
138
|
isVisibleAddFile: boolean;
|
|
132
139
|
isVisibleFileList: boolean;
|
|
@@ -165,7 +172,7 @@ export declare const usePreviewFileUploader: ({ value, isDisabled, accept, restr
|
|
|
165
172
|
isError: boolean | undefined;
|
|
166
173
|
};
|
|
167
174
|
fileListProps: {
|
|
168
|
-
onDelete: () => void;
|
|
175
|
+
onDelete: (fileId: FileId) => void;
|
|
169
176
|
onRetry: ((fileId: FileId, file: File) => void) | undefined;
|
|
170
177
|
setErrorStatusFile: (fileId: string, errorMsg: string) => void;
|
|
171
178
|
selfFiles: Record<string, UploadFile & import("../../types").SpecificSelfFileParams>;
|
|
@@ -174,5 +181,6 @@ export declare const usePreviewFileUploader: ({ value, isDisabled, accept, restr
|
|
|
174
181
|
files: UploadFile[];
|
|
175
182
|
isHidePersonalData: boolean | undefined;
|
|
176
183
|
PdfViewer: LazyExoticComponent<(props: PdfViewerProps) => ReactElement> | ((props: PdfViewerProps) => ReactElement) | undefined;
|
|
184
|
+
deletingFileId: string | null;
|
|
177
185
|
};
|
|
178
186
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { declensionOfWords } from '@astral/utils/declension/declensionOfWords';
|
|
2
2
|
import { formatFileSizeToView } from '@astral/utils/file/formatFileSizeToView';
|
|
3
|
-
import { useMemo, } from 'react';
|
|
3
|
+
import { useMemo, useState, } from 'react';
|
|
4
4
|
import { useGenerateLocalId } from '../../../useGenerateLocalId';
|
|
5
5
|
import { useId } from '../../../useId';
|
|
6
6
|
import { DEFAULT_FILE_STATUS, previewFileUploaderClassnames, } from '../../constants';
|
|
@@ -10,8 +10,9 @@ import { rulePipe } from '../../utils/rulePipe';
|
|
|
10
10
|
import { toArray } from '../../utils/toArray';
|
|
11
11
|
import { useDnD } from '../useDnD';
|
|
12
12
|
import { useUploadFiles } from '../useUploadFiles';
|
|
13
|
-
export const usePreviewFileUploader = ({ value, isDisabled, accept, restrictions = [], maxFileSize, inputRef, notify, onChange, onUploadFile, label, isError, generateDownloadLink, onView, name, helperText, className, placeholder, placeholderImgSrc, isHidePersonalData, PdfViewer, }) => {
|
|
13
|
+
export const usePreviewFileUploader = ({ value, isDisabled, accept, restrictions = [], maxFileSize, inputRef, notify, onChange, onUploadFile, onDeleteFile, label, isError, generateDownloadLink, onView, name, helperText, className, placeholder, placeholderImgSrc, isHidePersonalData, PdfViewer, }) => {
|
|
14
14
|
const inputId = useId();
|
|
15
|
+
const [deletingFileId, setDeletingFileId] = useState(null);
|
|
15
16
|
const { generateId } = useGenerateLocalId();
|
|
16
17
|
// Преобразуем value к массиву
|
|
17
18
|
const files = useMemo(() => toArray(value), [value]);
|
|
@@ -80,8 +81,16 @@ export const usePreviewFileUploader = ({ value, isDisabled, accept, restrictions
|
|
|
80
81
|
});
|
|
81
82
|
},
|
|
82
83
|
});
|
|
83
|
-
const handleDelete = () => {
|
|
84
|
-
|
|
84
|
+
const handleDelete = (fileId) => {
|
|
85
|
+
const deleteFile = () => onChange(null);
|
|
86
|
+
if (!onDeleteFile) {
|
|
87
|
+
return deleteFile();
|
|
88
|
+
}
|
|
89
|
+
setDeletingFileId(fileId);
|
|
90
|
+
onDeleteFile(fileId)
|
|
91
|
+
.then(deleteFile)
|
|
92
|
+
.catch(() => notify.error('Ошибка удаления файла'))
|
|
93
|
+
.finally(() => setDeletingFileId(null));
|
|
85
94
|
};
|
|
86
95
|
const getHandlerOnRetry = () => {
|
|
87
96
|
if (onUploadFile) {
|
|
@@ -135,6 +144,7 @@ export const usePreviewFileUploader = ({ value, isDisabled, accept, restrictions
|
|
|
135
144
|
files,
|
|
136
145
|
isHidePersonalData,
|
|
137
146
|
PdfViewer,
|
|
147
|
+
deletingFileId,
|
|
138
148
|
},
|
|
139
149
|
};
|
|
140
150
|
};
|
|
@@ -188,6 +188,13 @@ type BaseFileUploaderProps = {
|
|
|
188
188
|
signal: AbortSignal;
|
|
189
189
|
setProgress: (progressFileId: FileId, progressEvent: ProgressEvent) => void;
|
|
190
190
|
}) => Promise<UploadedFileData>;
|
|
191
|
+
/**
|
|
192
|
+
* Функция, вызываемая при удалении файла.
|
|
193
|
+
* Используется для сбора идентификаторов файлов, помеченных на удаление.
|
|
194
|
+
* Фактическое удаление файлов с сервера должно выполняться только при подтверждении формы,
|
|
195
|
+
* чтобы избежать потери данных при отмене действия или перезагрузке страницы.
|
|
196
|
+
*/
|
|
197
|
+
onDeleteFile?: (fileId: FileId) => Promise<void>;
|
|
191
198
|
/**
|
|
192
199
|
* Обработчик просмотра файла
|
|
193
200
|
* @param fileId - Идентификатор файла
|
|
@@ -117,6 +117,15 @@ export type ConfigContextProps = {
|
|
|
117
117
|
isSmoothLoading?: boolean;
|
|
118
118
|
};
|
|
119
119
|
};
|
|
120
|
+
dataGrid?: {
|
|
121
|
+
defaultProps?: {
|
|
122
|
+
/**
|
|
123
|
+
* Флаг отключения минимальной высоты таблицы.
|
|
124
|
+
* Необходимо включить флаг, чтобы избежать баг с скроллом таблицы: https://track.astral.ru/soft/browse/UIKIT-3008.
|
|
125
|
+
*/
|
|
126
|
+
disableMinHeight?: boolean;
|
|
127
|
+
};
|
|
128
|
+
};
|
|
120
129
|
};
|
|
121
130
|
};
|
|
122
131
|
export type ConfigProviderProps = Partial<ConfigContextProps> & {
|
|
@@ -13,8 +13,9 @@ const styles_1 = require("./styles");
|
|
|
13
13
|
const useLogic_1 = require("./useLogic");
|
|
14
14
|
const INITIAL_LEVEL = 0;
|
|
15
15
|
const Body = (props) => {
|
|
16
|
-
const { imagesMap } = (0, react_1.useContext)(ConfigProvider_1.ConfigContext);
|
|
16
|
+
const { imagesMap, components } = (0, react_1.useContext)(ConfigProvider_1.ConfigContext);
|
|
17
17
|
const { isNoData, contentStateProps } = (0, useLogic_1.useLogic)(props);
|
|
18
|
+
const disableMinHeight = components?.dataGrid?.defaultProps?.disableMinHeight;
|
|
18
19
|
const { rows, selectedRows = [], isLoading, isError, errorMsg, minDisplayRows, keyId, noDataPlaceholder, onRetry, ...rowProps } = props;
|
|
19
20
|
const renderedRows = rows.map(({ children, options, ...row }) => {
|
|
20
21
|
const rowId = row[keyId];
|
|
@@ -23,7 +24,7 @@ const Body = (props) => {
|
|
|
23
24
|
});
|
|
24
25
|
return ((0, jsx_runtime_1.jsx)(styles_1.Wrapper, { className: (0, classNames_1.classNames)(constants_1.dataGridClassnames.body, {
|
|
25
26
|
[constants_1.dataGridClassnames.bodyEmpty]: isNoData,
|
|
26
|
-
}), "$minDisplayRows": minDisplayRows, children: (0, jsx_runtime_1.jsx)(ContentState_1.ContentState, { ...contentStateProps, errorState: {
|
|
27
|
+
}), "$minDisplayRows": minDisplayRows, "$disableMinHeight": disableMinHeight, children: (0, jsx_runtime_1.jsx)(ContentState_1.ContentState, { ...contentStateProps, errorState: {
|
|
27
28
|
imgAlt: 'Что-то пошло не так',
|
|
28
29
|
errorList: [errorMsg || ''],
|
|
29
30
|
imgSrc: imagesMap.defaultErrorImgSrc,
|
|
@@ -4,4 +4,5 @@ export declare const Wrapper: import("@emotion/styled/dist/declarations/src/type
|
|
|
4
4
|
as?: import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements> | undefined;
|
|
5
5
|
} & {
|
|
6
6
|
$minDisplayRows: number;
|
|
7
|
+
$disableMinHeight?: boolean | undefined;
|
|
7
8
|
}, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLUListElement>, HTMLUListElement>, {}>;
|
|
@@ -3,15 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Wrapper = void 0;
|
|
4
4
|
const styled_1 = require("../../styled");
|
|
5
5
|
const constants_1 = require("../constants");
|
|
6
|
-
exports.Wrapper =
|
|
7
|
-
shouldForwardProp: (prop) => !['$minDisplayRows'].includes(prop),
|
|
8
|
-
}) `
|
|
6
|
+
exports.Wrapper = styled_1.styled.ul `
|
|
9
7
|
overflow-y: auto;
|
|
10
8
|
|
|
11
9
|
width: fit-content;
|
|
12
10
|
min-width: 100%;
|
|
13
11
|
height: 100%;
|
|
14
|
-
min-height: ${({ $minDisplayRows }) => `${constants_1.MIN_ROW_HEIGHT * $minDisplayRows}px`};
|
|
12
|
+
min-height: ${({ $minDisplayRows, $disableMinHeight }) => ($disableMinHeight ? 'unset' : `${constants_1.MIN_ROW_HEIGHT * $minDisplayRows}px`)};
|
|
15
13
|
margin: 0;
|
|
16
14
|
padding: 0;
|
|
17
15
|
|
|
@@ -131,6 +131,11 @@ export type DataGridProps<TData extends Record<string, CellValue> = DataGridRow,
|
|
|
131
131
|
/**
|
|
132
132
|
* Используется для отображения переданного кол-ва строк при отсутствии данных
|
|
133
133
|
* @default 10
|
|
134
|
+
* @deprecated Не поддерживается, параметр будет удален в следующей major версии пакета.
|
|
135
|
+
* Мотивация: задание минимальной высоты через параметр компонента мешает корректной работе таблицы
|
|
136
|
+
* в части верстки.
|
|
137
|
+
* Чтобы отключить минимальную высоту таблицы, задайте в ConfigProvider:
|
|
138
|
+
* `components.dataGrid.defaultProps.disableMinHeight: true`
|
|
134
139
|
*/
|
|
135
140
|
minDisplayRows?: number;
|
|
136
141
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type FileUploaderFileProps } from '../../FileUploaderFile';
|
|
2
|
-
import { type UploadFile } from '../../types';
|
|
2
|
+
import { type FileId, type UploadFile } from '../../types';
|
|
3
3
|
export type FileListProps = {
|
|
4
4
|
isMultiple?: boolean;
|
|
5
5
|
/**
|
|
@@ -7,5 +7,9 @@ export type FileListProps = {
|
|
|
7
7
|
*/
|
|
8
8
|
files?: UploadFile[];
|
|
9
9
|
className?: string;
|
|
10
|
+
/**
|
|
11
|
+
* Идентификатор файла, для которого выполняется удаление
|
|
12
|
+
*/
|
|
13
|
+
deletingFileId?: FileId | null;
|
|
10
14
|
} & Pick<FileUploaderFileProps, 'onDelete' | 'onRetry' | 'onView' | 'generateDownloadLink' | 'selfFiles' | 'setErrorStatusFile'>;
|
|
11
|
-
export declare const FileList: ({ isMultiple, files, className, ...restProps }: FileListProps) => import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
export declare const FileList: ({ isMultiple, files, className, deletingFileId, ...restProps }: FileListProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -4,5 +4,5 @@ exports.FileList = void 0;
|
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const FileUploaderFile_1 = require("../../FileUploaderFile");
|
|
6
6
|
const styles_1 = require("./styles");
|
|
7
|
-
const FileList = ({ isMultiple, files, className, ...restProps }) => ((0, jsx_runtime_1.jsx)(styles_1.Wrapper, { "$isMultiple": isMultiple, className: className, children: files?.map((file) => ((0, jsx_runtime_1.jsx)("li", { children: (0, jsx_runtime_1.jsx)(FileUploaderFile_1.FileUploaderFile, { ...file, ...restProps }) }, file.id))) }));
|
|
7
|
+
const FileList = ({ isMultiple, files, className, deletingFileId, ...restProps }) => ((0, jsx_runtime_1.jsx)(styles_1.Wrapper, { "$isMultiple": isMultiple, className: className, children: files?.map((file) => ((0, jsx_runtime_1.jsx)("li", { children: (0, jsx_runtime_1.jsx)(FileUploaderFile_1.FileUploaderFile, { ...file, ...restProps, isDeletingFile: deletingFileId === file.id }) }, file.id))) }));
|
|
8
8
|
exports.FileList = FileList;
|
|
@@ -12,14 +12,14 @@ const Tooltip_1 = require("../../../Tooltip");
|
|
|
12
12
|
const styles_1 = require("./styles");
|
|
13
13
|
const useLogic_1 = require("./useLogic");
|
|
14
14
|
const Actions = (props) => {
|
|
15
|
-
const { downloadButtonProps, viewButtonProps, isVisibleAbortButton, isVisibleRetryButton, handleAbort, handleDelete, handleRetry, isLoading, isError, fileName, } = (0, useLogic_1.useLogic)(props);
|
|
15
|
+
const { downloadButtonProps, viewButtonProps, isVisibleAbortButton, isVisibleRetryButton, handleAbort, handleDelete, handleRetry, isLoading, isError, isDeletingFile, fileName, } = (0, useLogic_1.useLogic)(props);
|
|
16
16
|
if (isLoading) {
|
|
17
17
|
return ((0, jsx_runtime_1.jsx)(styles_1.Wrapper, { children: isVisibleAbortButton && ((0, jsx_runtime_1.jsx)(Tooltip_1.Tooltip, { title: "\u041E\u0442\u043C\u0435\u043D\u0438\u0442\u044C \u0437\u0430\u0433\u0440\u0443\u0437\u043A\u0443", children: (0, jsx_runtime_1.jsx)(IconButton_1.IconButton, { variant: "text", onClick: handleAbort, children: (0, jsx_runtime_1.jsx)(CrossOutlineMd_1.CrossOutlineMd, {}) }) })) }));
|
|
18
18
|
}
|
|
19
19
|
if (isError) {
|
|
20
|
-
return ((0, jsx_runtime_1.jsxs)(styles_1.Wrapper, { children: [isVisibleRetryButton && ((0, jsx_runtime_1.jsx)(Tooltip_1.Tooltip, { title: "\u041F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u044C \u0437\u0430\u0433\u0440\u0443\u0437\u043A\u0443", children: (0, jsx_runtime_1.jsx)(IconButton_1.IconButton, { variant: "text", onClick: handleRetry, children: (0, jsx_runtime_1.jsx)(RetryOutlineMd_1.RetryOutlineMd, {}) }) })), (0, jsx_runtime_1.jsx)(Tooltip_1.Tooltip, { title: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C", children: (0, jsx_runtime_1.jsx)(IconButton_1.IconButton, { variant: "text", onClick: handleDelete, children: (0, jsx_runtime_1.jsx)(CrossOutlineMd_1.CrossOutlineMd, {}) }) })] }));
|
|
20
|
+
return ((0, jsx_runtime_1.jsxs)(styles_1.Wrapper, { children: [isVisibleRetryButton && ((0, jsx_runtime_1.jsx)(Tooltip_1.Tooltip, { title: "\u041F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u044C \u0437\u0430\u0433\u0440\u0443\u0437\u043A\u0443", children: (0, jsx_runtime_1.jsx)(IconButton_1.IconButton, { variant: "text", onClick: handleRetry, children: (0, jsx_runtime_1.jsx)(RetryOutlineMd_1.RetryOutlineMd, {}) }) })), (0, jsx_runtime_1.jsx)(Tooltip_1.Tooltip, { title: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C", children: (0, jsx_runtime_1.jsx)(IconButton_1.IconButton, { variant: "text", onClick: handleDelete, loading: isDeletingFile, children: (0, jsx_runtime_1.jsx)(CrossOutlineMd_1.CrossOutlineMd, {}) }) })] }));
|
|
21
21
|
}
|
|
22
22
|
const { isShowViewButton, ...restViewButtonProps } = viewButtonProps;
|
|
23
|
-
return ((0, jsx_runtime_1.jsxs)(styles_1.Wrapper, { children: [isShowViewButton && ((0, jsx_runtime_1.jsx)(Tooltip_1.Tooltip, { title: "\u041F\u043E\u0441\u043C\u043E\u0442\u0440\u0435\u0442\u044C", children: (0, jsx_runtime_1.jsx)(IconButton_1.IconButton, { variant: "text", ...restViewButtonProps, children: (0, jsx_runtime_1.jsx)(EyeOutlineMd_1.EyeOutlineMd, {}) }) })), (0, jsx_runtime_1.jsx)(Tooltip_1.Tooltip, { title: "\u0421\u043A\u0430\u0447\u0430\u0442\u044C", children: (0, jsx_runtime_1.jsx)(IconButton_1.IconButton, { component: "a", variant: "text", download: fileName, ...downloadButtonProps, children: (0, jsx_runtime_1.jsx)(DownloadOutlineMd_1.DownloadOutlineMd, {}) }) }), (0, jsx_runtime_1.jsx)(Tooltip_1.Tooltip, { title: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C", children: (0, jsx_runtime_1.jsx)(IconButton_1.IconButton, { variant: "text", onClick: handleDelete, children: (0, jsx_runtime_1.jsx)(BinOutlineMd_1.BinOutlineMd, {}) }) })] }));
|
|
23
|
+
return ((0, jsx_runtime_1.jsxs)(styles_1.Wrapper, { children: [isShowViewButton && ((0, jsx_runtime_1.jsx)(Tooltip_1.Tooltip, { title: "\u041F\u043E\u0441\u043C\u043E\u0442\u0440\u0435\u0442\u044C", children: (0, jsx_runtime_1.jsx)(IconButton_1.IconButton, { variant: "text", ...restViewButtonProps, children: (0, jsx_runtime_1.jsx)(EyeOutlineMd_1.EyeOutlineMd, {}) }) })), (0, jsx_runtime_1.jsx)(Tooltip_1.Tooltip, { title: "\u0421\u043A\u0430\u0447\u0430\u0442\u044C", children: (0, jsx_runtime_1.jsx)(IconButton_1.IconButton, { component: "a", variant: "text", download: fileName, ...downloadButtonProps, children: (0, jsx_runtime_1.jsx)(DownloadOutlineMd_1.DownloadOutlineMd, {}) }) }), (0, jsx_runtime_1.jsx)(Tooltip_1.Tooltip, { title: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C", children: (0, jsx_runtime_1.jsx)(IconButton_1.IconButton, { variant: "text", onClick: handleDelete, loading: isDeletingFile, children: (0, jsx_runtime_1.jsx)(BinOutlineMd_1.BinOutlineMd, {}) }) })] }));
|
|
24
24
|
};
|
|
25
25
|
exports.Actions = Actions;
|
|
@@ -45,9 +45,13 @@ export type UseLogicParams = {
|
|
|
45
45
|
* Функция, вызываемая при удалении файла
|
|
46
46
|
*/
|
|
47
47
|
onDelete: (fileId: FileId) => void;
|
|
48
|
+
/**
|
|
49
|
+
* Флаг загрузки при удалении файла
|
|
50
|
+
*/
|
|
51
|
+
isDeletingFile?: boolean;
|
|
48
52
|
abortController?: AbortController;
|
|
49
53
|
} & Pick<SelfFileApi, 'selfFiles' | 'setErrorStatusFile'>;
|
|
50
|
-
export declare const useLogic: ({ fileId, file, fileUrl, isUploadError, generateDownloadLink, onDelete, onRetry, onView, setErrorStatusFile, selfFiles, isLoading, isError, fileName, }: UseLogicParams) => {
|
|
54
|
+
export declare const useLogic: ({ fileId, file, fileUrl, isUploadError, generateDownloadLink, onDelete, onRetry, onView, setErrorStatusFile, selfFiles, isLoading, isError, isDeletingFile, fileName, }: UseLogicParams) => {
|
|
51
55
|
downloadButtonProps: {
|
|
52
56
|
href: string;
|
|
53
57
|
};
|
|
@@ -69,5 +73,6 @@ export declare const useLogic: ({ fileId, file, fileUrl, isUploadError, generate
|
|
|
69
73
|
handleRetry: () => void | undefined;
|
|
70
74
|
isLoading: boolean | undefined;
|
|
71
75
|
isError: boolean | undefined;
|
|
76
|
+
isDeletingFile: boolean | undefined;
|
|
72
77
|
fileName: string;
|
|
73
78
|
};
|
|
@@ -7,7 +7,7 @@ const ConfigProvider_1 = require("../../../../ConfigProvider");
|
|
|
7
7
|
const constants_1 = require("../../../constants");
|
|
8
8
|
const useGenerateLocalFileURL_1 = require("../../../hooks/useGenerateLocalFileURL");
|
|
9
9
|
const generateAttrLinkNewTab_1 = require("../../../utils/generateAttrLinkNewTab");
|
|
10
|
-
const useLogic = ({ fileId, file, fileUrl, isUploadError, generateDownloadLink, onDelete, onRetry, onView, setErrorStatusFile, selfFiles, isLoading, isError, fileName, }) => {
|
|
10
|
+
const useLogic = ({ fileId, file, fileUrl, isUploadError, generateDownloadLink, onDelete, onRetry, onView, setErrorStatusFile, selfFiles, isLoading, isError, isDeletingFile, fileName, }) => {
|
|
11
11
|
const { captureException } = (0, react_1.useContext)(ConfigProvider_1.ConfigContext);
|
|
12
12
|
const { generateUrl } = (0, useGenerateLocalFileURL_1.useGenerateLocalFileURL)();
|
|
13
13
|
const { controller } = selfFiles[fileId] || {};
|
|
@@ -74,6 +74,7 @@ const useLogic = ({ fileId, file, fileUrl, isUploadError, generateDownloadLink,
|
|
|
74
74
|
handleRetry,
|
|
75
75
|
isLoading,
|
|
76
76
|
isError,
|
|
77
|
+
isDeletingFile,
|
|
77
78
|
fileName,
|
|
78
79
|
};
|
|
79
80
|
};
|
|
@@ -17,5 +17,9 @@ export type FileUploaderFileProps = UploadFile & {
|
|
|
17
17
|
* Функция, вызываемая при удалении файла
|
|
18
18
|
*/
|
|
19
19
|
onDelete: (fileId: FileId) => void;
|
|
20
|
+
/**
|
|
21
|
+
* Флаг загрузки при удалении файла
|
|
22
|
+
*/
|
|
23
|
+
isDeletingFile?: boolean;
|
|
20
24
|
} & Pick<ActionsProps, 'selfFiles' | 'setErrorStatusFile'>;
|
|
21
25
|
export declare const FileUploaderFile: (props: FileUploaderFileProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { type PreviewFileUploaderFileProps } from '../../PreviewFileUploaderFile';
|
|
2
|
-
import {
|
|
2
|
+
import type { FileId, UploadFile } from '../../types';
|
|
3
3
|
export type FileListProps = {
|
|
4
4
|
files: UploadFile[];
|
|
5
|
+
/**
|
|
6
|
+
* Идентификатор файла, для которого выполняется удаление
|
|
7
|
+
*/
|
|
8
|
+
deletingFileId?: FileId | null;
|
|
5
9
|
} & Pick<PreviewFileUploaderFileProps, 'onDelete' | 'onRetry' | 'onView' | 'generateDownloadLink' | 'selfFiles' | 'setErrorStatusFile'>;
|
|
6
|
-
export declare const FileList: ({ files, ...restProps }: FileListProps) => import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export declare const FileList: ({ files, deletingFileId, ...restProps }: FileListProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -3,5 +3,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.FileList = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const PreviewFileUploaderFile_1 = require("../../PreviewFileUploaderFile");
|
|
6
|
-
const FileList = ({ files, ...restProps }) => ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: files?.map((file) => ((0, jsx_runtime_1.jsx)(PreviewFileUploaderFile_1.PreviewFileUploaderFile, { ...file, ...restProps }, file.id))) }));
|
|
6
|
+
const FileList = ({ files, deletingFileId, ...restProps }) => ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: files?.map((file) => ((0, jsx_runtime_1.jsx)(PreviewFileUploaderFile_1.PreviewFileUploaderFile, { ...file, ...restProps, isDeletingFile: deletingFileId === file.id }, file.id))) }));
|
|
7
7
|
exports.FileList = FileList;
|
|
@@ -42,6 +42,10 @@ export type FilePreviewProps = {
|
|
|
42
42
|
* Скрытие персональных данных от инструментов мониторинга
|
|
43
43
|
*/
|
|
44
44
|
isHidePersonalData?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Флаг загрузки при удалении файла
|
|
47
|
+
*/
|
|
48
|
+
isDeletingFile?: boolean;
|
|
45
49
|
/**
|
|
46
50
|
* Компонент для отображения превью pdf-файлов
|
|
47
51
|
*/
|
|
@@ -16,8 +16,8 @@ const styles_1 = require("./styles");
|
|
|
16
16
|
const useLogic_1 = require("./useLogic");
|
|
17
17
|
const FilePreview = (props) => {
|
|
18
18
|
const { viewButtonProps, downloadButtonProps, deleteButtonProps, isImageFile, isPdfFile, isOtherFile, } = (0, useLogic_1.useLogic)(props);
|
|
19
|
-
const { file, fileName, fileSize, fileUrl, generateDownloadLink, isHidePersonalData, PdfViewer, } = props;
|
|
19
|
+
const { file, fileName, fileSize, fileUrl, generateDownloadLink, isHidePersonalData, PdfViewer, isDeletingFile, } = props;
|
|
20
20
|
const { isMobile } = (0, useViewportType_1.useViewportType)();
|
|
21
|
-
return ((0, jsx_runtime_1.jsxs)(styles_1.Wrapper, { children: [(0, jsx_runtime_1.jsx)(Preview_1.Preview, { isImageFile: isImageFile, isPdfFile: isPdfFile, file: file, fileUrl: fileUrl, generateDownloadLink: generateDownloadLink, isHidePersonalData: isHidePersonalData, PdfViewer: PdfViewer }), (0, jsx_runtime_1.jsxs)(styles_1.Details, { className: constants_1.previewFileUploaderClassnames.details, "$isOtherFile": isOtherFile, children: [isOtherFile && (0, jsx_runtime_1.jsx)(Typography_1.Typography, { variant: "h6", children: "\u0424\u0430\u0439\u043B \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043D" }), (0, jsx_runtime_1.jsx)(styles_1.StyledFileInfo, { "$isOtherFile": isOtherFile, fileName: fileName, fileSize: fileSize }), (0, jsx_runtime_1.jsx)(styles_1.Actions, { children: isMobile && isOtherFile ? ((0, jsx_runtime_1.jsx)(Button_1.Button, { variant: "light", color: "grey", ...deleteButtonProps, children: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C" })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [!isOtherFile && ((0, jsx_runtime_1.jsx)(Tooltip_1.Tooltip, { title: "\u041F\u043E\u0441\u043C\u043E\u0442\u0440\u0435\u0442\u044C", disableInteractive: true, children: (0, jsx_runtime_1.jsx)(IconButton_1.IconButton, { variant: "light", color: "grey", ...viewButtonProps, children: (0, jsx_runtime_1.jsx)(EyeOutlineMd_1.EyeOutlineMd, {}) }) })), (0, jsx_runtime_1.jsx)(Tooltip_1.Tooltip, { title: "\u0421\u043A\u0430\u0447\u0430\u0442\u044C", disableInteractive: true, children: (0, jsx_runtime_1.jsx)(IconButton_1.IconButton, { component: "a", variant: "light", color: "grey", download: fileName, ...downloadButtonProps, children: (0, jsx_runtime_1.jsx)(DownloadOutlineMd_1.DownloadOutlineMd, {}) }) }), (0, jsx_runtime_1.jsx)(Tooltip_1.Tooltip, { title: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C", disableInteractive: true, children: (0, jsx_runtime_1.jsx)(IconButton_1.IconButton, { variant: "light", color: "grey", ...deleteButtonProps, children: (0, jsx_runtime_1.jsx)(BinOutlineMd_1.BinOutlineMd, {}) }) })] })) })] })] }));
|
|
21
|
+
return ((0, jsx_runtime_1.jsxs)(styles_1.Wrapper, { children: [(0, jsx_runtime_1.jsx)(Preview_1.Preview, { isImageFile: isImageFile, isPdfFile: isPdfFile, file: file, fileUrl: fileUrl, generateDownloadLink: generateDownloadLink, isHidePersonalData: isHidePersonalData, PdfViewer: PdfViewer }), (0, jsx_runtime_1.jsxs)(styles_1.Details, { className: constants_1.previewFileUploaderClassnames.details, "$isOtherFile": isOtherFile, children: [isOtherFile && (0, jsx_runtime_1.jsx)(Typography_1.Typography, { variant: "h6", children: "\u0424\u0430\u0439\u043B \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043D" }), (0, jsx_runtime_1.jsx)(styles_1.StyledFileInfo, { "$isOtherFile": isOtherFile, fileName: fileName, fileSize: fileSize }), (0, jsx_runtime_1.jsx)(styles_1.Actions, { children: isMobile && isOtherFile ? ((0, jsx_runtime_1.jsx)(Button_1.Button, { variant: "light", color: "grey", loading: isDeletingFile, ...deleteButtonProps, children: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C" })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [!isOtherFile && ((0, jsx_runtime_1.jsx)(Tooltip_1.Tooltip, { title: "\u041F\u043E\u0441\u043C\u043E\u0442\u0440\u0435\u0442\u044C", disableInteractive: true, children: (0, jsx_runtime_1.jsx)(IconButton_1.IconButton, { variant: "light", color: "grey", ...viewButtonProps, children: (0, jsx_runtime_1.jsx)(EyeOutlineMd_1.EyeOutlineMd, {}) }) })), (0, jsx_runtime_1.jsx)(Tooltip_1.Tooltip, { title: "\u0421\u043A\u0430\u0447\u0430\u0442\u044C", disableInteractive: true, children: (0, jsx_runtime_1.jsx)(IconButton_1.IconButton, { component: "a", variant: "light", color: "grey", download: fileName, ...downloadButtonProps, children: (0, jsx_runtime_1.jsx)(DownloadOutlineMd_1.DownloadOutlineMd, {}) }) }), (0, jsx_runtime_1.jsx)(Tooltip_1.Tooltip, { title: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C", disableInteractive: true, children: (0, jsx_runtime_1.jsx)(IconButton_1.IconButton, { variant: "light", color: "grey", loading: isDeletingFile, ...deleteButtonProps, children: (0, jsx_runtime_1.jsx)(BinOutlineMd_1.BinOutlineMd, {}) }) })] })) })] })] }));
|
|
22
22
|
};
|
|
23
23
|
exports.FilePreview = FilePreview;
|
|
@@ -23,6 +23,10 @@ export type PreviewFileUploaderFileProps = UploadFile & {
|
|
|
23
23
|
* Скрытие персональных данных от инструментов мониторинга
|
|
24
24
|
*/
|
|
25
25
|
isHidePersonalData?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Флаг загрузки при удалении файла
|
|
28
|
+
*/
|
|
29
|
+
isDeletingFile?: boolean;
|
|
26
30
|
/**
|
|
27
31
|
* Компонент для отображения превью pdf-файлов
|
|
28
32
|
*/
|
|
@@ -8,9 +8,9 @@ const FileLoading_1 = require("./FileLoading");
|
|
|
8
8
|
const FilePreview_1 = require("./FilePreview");
|
|
9
9
|
const styles_1 = require("./styles");
|
|
10
10
|
const PreviewFileUploaderFile = (props) => {
|
|
11
|
-
const { id, name, type, file, url, size, status, generateDownloadLink, onRetry, onDelete, onView, selfFiles, setErrorStatusFile, isHidePersonalData, PdfViewer, } = props;
|
|
11
|
+
const { id, name, type, file, url, size, status, generateDownloadLink, onRetry, onDelete, onView, selfFiles, setErrorStatusFile, isHidePersonalData, PdfViewer, isDeletingFile, } = props;
|
|
12
12
|
const { isLoading, isUploadError, isRestrictionError, errorMsg, progress } = status || {};
|
|
13
13
|
const isError = isUploadError || isRestrictionError;
|
|
14
|
-
return ((0, jsx_runtime_1.jsx)(Fade_1.Fade, { in: true, children: (0, jsx_runtime_1.jsxs)(styles_1.Wrapper, { "$isLoading": isLoading, "$isError": isError, children: [!isLoading && !isError && ((0, jsx_runtime_1.jsx)(FilePreview_1.FilePreview, { fileId: id, fileName: name, fileType: type, file: file, fileUrl: url, fileSize: size, generateDownloadLink: generateDownloadLink, onView: onView, onDelete: onDelete, isHidePersonalData: isHidePersonalData, PdfViewer: PdfViewer })), isLoading && ((0, jsx_runtime_1.jsx)(FileLoading_1.FileLoading, { selfFiles: selfFiles, setErrorStatusFile: setErrorStatusFile, fileId: id, fileName: name, fileSize: size, progress: progress })), isError && ((0, jsx_runtime_1.jsx)(FileError_1.FileError, { fileId: id, fileName: name, file: file, fileSize: size, errorMsg: errorMsg, isUploadError: isUploadError, onRetry: onRetry, onDelete: onDelete }))] }) }));
|
|
14
|
+
return ((0, jsx_runtime_1.jsx)(Fade_1.Fade, { in: true, children: (0, jsx_runtime_1.jsxs)(styles_1.Wrapper, { "$isLoading": isLoading, "$isError": isError, children: [!isLoading && !isError && ((0, jsx_runtime_1.jsx)(FilePreview_1.FilePreview, { fileId: id, fileName: name, fileType: type, file: file, fileUrl: url, fileSize: size, generateDownloadLink: generateDownloadLink, onView: onView, onDelete: onDelete, isHidePersonalData: isHidePersonalData, PdfViewer: PdfViewer, isDeletingFile: isDeletingFile })), isLoading && ((0, jsx_runtime_1.jsx)(FileLoading_1.FileLoading, { selfFiles: selfFiles, setErrorStatusFile: setErrorStatusFile, fileId: id, fileName: name, fileSize: size, progress: progress })), isError && ((0, jsx_runtime_1.jsx)(FileError_1.FileError, { fileId: id, fileName: name, file: file, fileSize: size, errorMsg: errorMsg, isUploadError: isUploadError, onRetry: onRetry, onDelete: onDelete }))] }) }));
|
|
15
15
|
};
|
|
16
16
|
exports.PreviewFileUploaderFile = PreviewFileUploaderFile;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type ChangeEvent } from 'react';
|
|
2
2
|
import type { FileId, FileUploaderProps, UploadFile } from '../../types';
|
|
3
3
|
export type UseFileUploaderParams = FileUploaderProps;
|
|
4
|
-
export declare const useFileUploader: ({ value, isDisabled, isMultiple, accept, restrictions, maxFileSize, maxFileCount, inputRef, notify, onChange, onUploadFile, name, isError, onView, generateDownloadLink, placeholder, helperText, label, className, getErrorMessage, }: UseFileUploaderParams) => {
|
|
4
|
+
export declare const useFileUploader: ({ value, isDisabled, isMultiple, accept, restrictions, maxFileSize, maxFileCount, inputRef, notify, onChange, onUploadFile, onDeleteFile, name, isError, onView, generateDownloadLink, placeholder, helperText, label, className, getErrorMessage, }: UseFileUploaderParams) => {
|
|
5
5
|
dropZoneProps: {
|
|
6
6
|
isLimitMaxFileCount: boolean;
|
|
7
7
|
maxFileCount: number;
|
|
@@ -53,5 +53,6 @@ export declare const useFileUploader: ({ value, isDisabled, isMultiple, accept,
|
|
|
53
53
|
selfFiles: Record<string, UploadFile & import("../../types").SpecificSelfFileParams>;
|
|
54
54
|
setErrorStatusFile: (fileId: string, errorMsg: string) => void;
|
|
55
55
|
getErrorMessage: ((fileId: string, error: Error) => string) | undefined;
|
|
56
|
+
deletingFileId: string | null;
|
|
56
57
|
};
|
|
57
58
|
};
|
|
@@ -14,8 +14,9 @@ const toArray_1 = require("../../utils/toArray");
|
|
|
14
14
|
const useDnD_1 = require("../useDnD");
|
|
15
15
|
const useUploadFiles_1 = require("../useUploadFiles");
|
|
16
16
|
const useFileUploader = ({ value, isDisabled, isMultiple, accept, restrictions = [], maxFileSize, maxFileCount = 1, // для случая, когда isMultiple=false
|
|
17
|
-
inputRef, notify, onChange, onUploadFile, name, isError, onView, generateDownloadLink, placeholder, helperText, label, className, getErrorMessage, }) => {
|
|
17
|
+
inputRef, notify, onChange, onUploadFile, onDeleteFile, name, isError, onView, generateDownloadLink, placeholder, helperText, label, className, getErrorMessage, }) => {
|
|
18
18
|
const inputId = (0, useId_1.useId)();
|
|
19
|
+
const [deletingFileId, setDeletingFileId] = (0, react_1.useState)(null);
|
|
19
20
|
const { generateId } = (0, useGenerateLocalId_1.useGenerateLocalId)();
|
|
20
21
|
// Преобразуем value к массиву
|
|
21
22
|
const files = (0, react_1.useMemo)(() => (0, toArray_1.toArray)(value), [value]);
|
|
@@ -97,10 +98,20 @@ inputRef, notify, onChange, onUploadFile, name, isError, onView, generateDownloa
|
|
|
97
98
|
},
|
|
98
99
|
});
|
|
99
100
|
const handleDelete = (fileId) => {
|
|
100
|
-
|
|
101
|
-
|
|
101
|
+
const deleteFile = () => {
|
|
102
|
+
if (isMultiple) {
|
|
103
|
+
return onChange(files?.filter(({ id }) => id !== fileId));
|
|
104
|
+
}
|
|
105
|
+
return onChange(null);
|
|
106
|
+
};
|
|
107
|
+
if (!onDeleteFile) {
|
|
108
|
+
return deleteFile();
|
|
102
109
|
}
|
|
103
|
-
|
|
110
|
+
setDeletingFileId(fileId);
|
|
111
|
+
onDeleteFile(fileId)
|
|
112
|
+
.then(deleteFile)
|
|
113
|
+
.catch(() => notify.error('Ошибка удаления файла'))
|
|
114
|
+
.finally(() => setDeletingFileId(null));
|
|
104
115
|
};
|
|
105
116
|
const getHandlerOnRetry = () => {
|
|
106
117
|
if (onUploadFile) {
|
|
@@ -158,6 +169,7 @@ inputRef, notify, onChange, onUploadFile, name, isError, onView, generateDownloa
|
|
|
158
169
|
selfFiles,
|
|
159
170
|
setErrorStatusFile,
|
|
160
171
|
getErrorMessage,
|
|
172
|
+
deletingFileId,
|
|
161
173
|
},
|
|
162
174
|
};
|
|
163
175
|
};
|
package/node/components/fileUploading/hooks/usePreviewFileUploader/usePreviewFileUploader.d.ts
CHANGED
|
@@ -117,6 +117,13 @@ export type UsePreviewFileUploaderParams = {
|
|
|
117
117
|
* - При обновлении информации о файле после успешной загрузки
|
|
118
118
|
*/
|
|
119
119
|
onChange: (value: UploadFile | null) => void;
|
|
120
|
+
/**
|
|
121
|
+
* Функция, вызываемая при удалении файла.
|
|
122
|
+
* Используется для сбора идентификаторов файлов, помеченных на удаление.
|
|
123
|
+
* Фактическое удаление файлов с сервера должно выполняться только при подтверждении формы,
|
|
124
|
+
* чтобы избежать потери данных при отмене действия или перезагрузке страницы.
|
|
125
|
+
*/
|
|
126
|
+
onDeleteFile?: (fileId: FileId) => Promise<void>;
|
|
120
127
|
/**
|
|
121
128
|
* Скрытие персональных данных от инструментов мониторинга
|
|
122
129
|
*/
|
|
@@ -126,7 +133,7 @@ export type UsePreviewFileUploaderParams = {
|
|
|
126
133
|
*/
|
|
127
134
|
PdfViewer?: ((props: PdfViewerProps) => ReactElement) | LazyExoticComponent<(props: PdfViewerProps) => ReactElement>;
|
|
128
135
|
};
|
|
129
|
-
export declare const usePreviewFileUploader: ({ value, isDisabled, accept, restrictions, maxFileSize, inputRef, notify, onChange, onUploadFile, label, isError, generateDownloadLink, onView, name, helperText, className, placeholder, placeholderImgSrc, isHidePersonalData, PdfViewer, }: UsePreviewFileUploaderParams) => {
|
|
136
|
+
export declare const usePreviewFileUploader: ({ value, isDisabled, accept, restrictions, maxFileSize, inputRef, notify, onChange, onUploadFile, onDeleteFile, label, isError, generateDownloadLink, onView, name, helperText, className, placeholder, placeholderImgSrc, isHidePersonalData, PdfViewer, }: UsePreviewFileUploaderParams) => {
|
|
130
137
|
dropZoneProps: {
|
|
131
138
|
isVisibleAddFile: boolean;
|
|
132
139
|
isVisibleFileList: boolean;
|
|
@@ -165,7 +172,7 @@ export declare const usePreviewFileUploader: ({ value, isDisabled, accept, restr
|
|
|
165
172
|
isError: boolean | undefined;
|
|
166
173
|
};
|
|
167
174
|
fileListProps: {
|
|
168
|
-
onDelete: () => void;
|
|
175
|
+
onDelete: (fileId: FileId) => void;
|
|
169
176
|
onRetry: ((fileId: FileId, file: File) => void) | undefined;
|
|
170
177
|
setErrorStatusFile: (fileId: string, errorMsg: string) => void;
|
|
171
178
|
selfFiles: Record<string, UploadFile & import("../../types").SpecificSelfFileParams>;
|
|
@@ -174,5 +181,6 @@ export declare const usePreviewFileUploader: ({ value, isDisabled, accept, restr
|
|
|
174
181
|
files: UploadFile[];
|
|
175
182
|
isHidePersonalData: boolean | undefined;
|
|
176
183
|
PdfViewer: LazyExoticComponent<(props: PdfViewerProps) => ReactElement> | ((props: PdfViewerProps) => ReactElement) | undefined;
|
|
184
|
+
deletingFileId: string | null;
|
|
177
185
|
};
|
|
178
186
|
};
|
package/node/components/fileUploading/hooks/usePreviewFileUploader/usePreviewFileUploader.js
CHANGED
|
@@ -13,8 +13,9 @@ const rulePipe_1 = require("../../utils/rulePipe");
|
|
|
13
13
|
const toArray_1 = require("../../utils/toArray");
|
|
14
14
|
const useDnD_1 = require("../useDnD");
|
|
15
15
|
const useUploadFiles_1 = require("../useUploadFiles");
|
|
16
|
-
const usePreviewFileUploader = ({ value, isDisabled, accept, restrictions = [], maxFileSize, inputRef, notify, onChange, onUploadFile, label, isError, generateDownloadLink, onView, name, helperText, className, placeholder, placeholderImgSrc, isHidePersonalData, PdfViewer, }) => {
|
|
16
|
+
const usePreviewFileUploader = ({ value, isDisabled, accept, restrictions = [], maxFileSize, inputRef, notify, onChange, onUploadFile, onDeleteFile, label, isError, generateDownloadLink, onView, name, helperText, className, placeholder, placeholderImgSrc, isHidePersonalData, PdfViewer, }) => {
|
|
17
17
|
const inputId = (0, useId_1.useId)();
|
|
18
|
+
const [deletingFileId, setDeletingFileId] = (0, react_1.useState)(null);
|
|
18
19
|
const { generateId } = (0, useGenerateLocalId_1.useGenerateLocalId)();
|
|
19
20
|
// Преобразуем value к массиву
|
|
20
21
|
const files = (0, react_1.useMemo)(() => (0, toArray_1.toArray)(value), [value]);
|
|
@@ -83,8 +84,16 @@ const usePreviewFileUploader = ({ value, isDisabled, accept, restrictions = [],
|
|
|
83
84
|
});
|
|
84
85
|
},
|
|
85
86
|
});
|
|
86
|
-
const handleDelete = () => {
|
|
87
|
-
|
|
87
|
+
const handleDelete = (fileId) => {
|
|
88
|
+
const deleteFile = () => onChange(null);
|
|
89
|
+
if (!onDeleteFile) {
|
|
90
|
+
return deleteFile();
|
|
91
|
+
}
|
|
92
|
+
setDeletingFileId(fileId);
|
|
93
|
+
onDeleteFile(fileId)
|
|
94
|
+
.then(deleteFile)
|
|
95
|
+
.catch(() => notify.error('Ошибка удаления файла'))
|
|
96
|
+
.finally(() => setDeletingFileId(null));
|
|
88
97
|
};
|
|
89
98
|
const getHandlerOnRetry = () => {
|
|
90
99
|
if (onUploadFile) {
|
|
@@ -138,6 +147,7 @@ const usePreviewFileUploader = ({ value, isDisabled, accept, restrictions = [],
|
|
|
138
147
|
files,
|
|
139
148
|
isHidePersonalData,
|
|
140
149
|
PdfViewer,
|
|
150
|
+
deletingFileId,
|
|
141
151
|
},
|
|
142
152
|
};
|
|
143
153
|
};
|
|
@@ -188,6 +188,13 @@ type BaseFileUploaderProps = {
|
|
|
188
188
|
signal: AbortSignal;
|
|
189
189
|
setProgress: (progressFileId: FileId, progressEvent: ProgressEvent) => void;
|
|
190
190
|
}) => Promise<UploadedFileData>;
|
|
191
|
+
/**
|
|
192
|
+
* Функция, вызываемая при удалении файла.
|
|
193
|
+
* Используется для сбора идентификаторов файлов, помеченных на удаление.
|
|
194
|
+
* Фактическое удаление файлов с сервера должно выполняться только при подтверждении формы,
|
|
195
|
+
* чтобы избежать потери данных при отмене действия или перезагрузке страницы.
|
|
196
|
+
*/
|
|
197
|
+
onDeleteFile?: (fileId: FileId) => Promise<void>;
|
|
191
198
|
/**
|
|
192
199
|
* Обработчик просмотра файла
|
|
193
200
|
* @param fileId - Идентификатор файла
|
package/package.json
CHANGED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import axios from 'axios';
|
|
2
|
-
import AxiosMockAdapter from 'axios-mock-adapter';
|
|
3
|
-
let globalId = 0;
|
|
4
|
-
const generateId = () => {
|
|
5
|
-
globalId += 1;
|
|
6
|
-
return globalId;
|
|
7
|
-
};
|
|
8
|
-
const progressSteps = Array.from({ length: 10 }, (_, i) => (i + 1) / 10);
|
|
9
|
-
const getRandomDelay = () => Math.random() * 300 + 200; // 200-500ms
|
|
10
|
-
const sleep = (time) => new Promise((resolve) => setTimeout(resolve, time));
|
|
11
|
-
const mock = new AxiosMockAdapter(axios);
|
|
12
|
-
mock.onPost('/api/upload').reply(async (config) => {
|
|
13
|
-
const response = {
|
|
14
|
-
id: `upl-${generateId()}`,
|
|
15
|
-
};
|
|
16
|
-
const formData = config.data;
|
|
17
|
-
const file = formData.get('file');
|
|
18
|
-
const total = file.size;
|
|
19
|
-
for (const progress of progressSteps) {
|
|
20
|
-
await sleep(getRandomDelay());
|
|
21
|
-
if (config.onUploadProgress) {
|
|
22
|
-
config.onUploadProgress({
|
|
23
|
-
loaded: Math.floor(total * progress),
|
|
24
|
-
total,
|
|
25
|
-
lengthComputable: true,
|
|
26
|
-
bytes: Math.floor(total * progress),
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return [200, response];
|
|
31
|
-
});
|
|
32
|
-
export const fakeFileUploadQuery = (formData, options) => axios.post('/api/upload', formData, {
|
|
33
|
-
headers: {
|
|
34
|
-
'Content-Type': 'multipart/form-data',
|
|
35
|
-
},
|
|
36
|
-
...(options || {}),
|
|
37
|
-
});
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import axios from 'axios';
|
|
2
|
-
import AxiosMockAdapter from 'axios-mock-adapter';
|
|
3
|
-
let globalId = 0;
|
|
4
|
-
const generateId = () => {
|
|
5
|
-
globalId += 1;
|
|
6
|
-
return globalId;
|
|
7
|
-
};
|
|
8
|
-
const progressSteps = Array.from({ length: 10 }, (_, i) => (i + 1) / 10);
|
|
9
|
-
const getRandomDelay = () => Math.random() * 300 + 200; // 200-500ms
|
|
10
|
-
const sleep = (time) => new Promise((resolve) => setTimeout(resolve, time));
|
|
11
|
-
const mock = new AxiosMockAdapter(axios);
|
|
12
|
-
mock.onPost('/api/upload').reply(async (config) => {
|
|
13
|
-
const response = {
|
|
14
|
-
id: `upl-${generateId()}`,
|
|
15
|
-
};
|
|
16
|
-
const formData = config.data;
|
|
17
|
-
const file = formData.get('file');
|
|
18
|
-
const total = file.size;
|
|
19
|
-
for (const progress of progressSteps) {
|
|
20
|
-
await sleep(getRandomDelay());
|
|
21
|
-
if (config.onUploadProgress) {
|
|
22
|
-
config.onUploadProgress({
|
|
23
|
-
loaded: Math.floor(total * progress),
|
|
24
|
-
total,
|
|
25
|
-
lengthComputable: true,
|
|
26
|
-
bytes: Math.floor(total * progress),
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return [200, response];
|
|
31
|
-
});
|
|
32
|
-
export const fakePreviewFileUploadQuery = (formData, options) => axios.post('/api/upload', formData, {
|
|
33
|
-
headers: {
|
|
34
|
-
'Content-Type': 'multipart/form-data',
|
|
35
|
-
},
|
|
36
|
-
...(options || {}),
|
|
37
|
-
});
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.fakeFileUploadQuery = void 0;
|
|
7
|
-
const axios_1 = __importDefault(require("axios"));
|
|
8
|
-
const axios_mock_adapter_1 = __importDefault(require("axios-mock-adapter"));
|
|
9
|
-
let globalId = 0;
|
|
10
|
-
const generateId = () => {
|
|
11
|
-
globalId += 1;
|
|
12
|
-
return globalId;
|
|
13
|
-
};
|
|
14
|
-
const progressSteps = Array.from({ length: 10 }, (_, i) => (i + 1) / 10);
|
|
15
|
-
const getRandomDelay = () => Math.random() * 300 + 200; // 200-500ms
|
|
16
|
-
const sleep = (time) => new Promise((resolve) => setTimeout(resolve, time));
|
|
17
|
-
const mock = new axios_mock_adapter_1.default(axios_1.default);
|
|
18
|
-
mock.onPost('/api/upload').reply(async (config) => {
|
|
19
|
-
const response = {
|
|
20
|
-
id: `upl-${generateId()}`,
|
|
21
|
-
};
|
|
22
|
-
const formData = config.data;
|
|
23
|
-
const file = formData.get('file');
|
|
24
|
-
const total = file.size;
|
|
25
|
-
for (const progress of progressSteps) {
|
|
26
|
-
await sleep(getRandomDelay());
|
|
27
|
-
if (config.onUploadProgress) {
|
|
28
|
-
config.onUploadProgress({
|
|
29
|
-
loaded: Math.floor(total * progress),
|
|
30
|
-
total,
|
|
31
|
-
lengthComputable: true,
|
|
32
|
-
bytes: Math.floor(total * progress),
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
return [200, response];
|
|
37
|
-
});
|
|
38
|
-
const fakeFileUploadQuery = (formData, options) => axios_1.default.post('/api/upload', formData, {
|
|
39
|
-
headers: {
|
|
40
|
-
'Content-Type': 'multipart/form-data',
|
|
41
|
-
},
|
|
42
|
-
...(options || {}),
|
|
43
|
-
});
|
|
44
|
-
exports.fakeFileUploadQuery = fakeFileUploadQuery;
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.fakePreviewFileUploadQuery = void 0;
|
|
7
|
-
const axios_1 = __importDefault(require("axios"));
|
|
8
|
-
const axios_mock_adapter_1 = __importDefault(require("axios-mock-adapter"));
|
|
9
|
-
let globalId = 0;
|
|
10
|
-
const generateId = () => {
|
|
11
|
-
globalId += 1;
|
|
12
|
-
return globalId;
|
|
13
|
-
};
|
|
14
|
-
const progressSteps = Array.from({ length: 10 }, (_, i) => (i + 1) / 10);
|
|
15
|
-
const getRandomDelay = () => Math.random() * 300 + 200; // 200-500ms
|
|
16
|
-
const sleep = (time) => new Promise((resolve) => setTimeout(resolve, time));
|
|
17
|
-
const mock = new axios_mock_adapter_1.default(axios_1.default);
|
|
18
|
-
mock.onPost('/api/upload').reply(async (config) => {
|
|
19
|
-
const response = {
|
|
20
|
-
id: `upl-${generateId()}`,
|
|
21
|
-
};
|
|
22
|
-
const formData = config.data;
|
|
23
|
-
const file = formData.get('file');
|
|
24
|
-
const total = file.size;
|
|
25
|
-
for (const progress of progressSteps) {
|
|
26
|
-
await sleep(getRandomDelay());
|
|
27
|
-
if (config.onUploadProgress) {
|
|
28
|
-
config.onUploadProgress({
|
|
29
|
-
loaded: Math.floor(total * progress),
|
|
30
|
-
total,
|
|
31
|
-
lengthComputable: true,
|
|
32
|
-
bytes: Math.floor(total * progress),
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
return [200, response];
|
|
37
|
-
});
|
|
38
|
-
const fakePreviewFileUploadQuery = (formData, options) => axios_1.default.post('/api/upload', formData, {
|
|
39
|
-
headers: {
|
|
40
|
-
'Content-Type': 'multipart/form-data',
|
|
41
|
-
},
|
|
42
|
-
...(options || {}),
|
|
43
|
-
});
|
|
44
|
-
exports.fakePreviewFileUploadQuery = fakePreviewFileUploadQuery;
|