+
@@ -82,7 +103,12 @@ export function FilesList({ files, loading, labelFor }: { files: FileOut[]; load
),
},
- { title: head('Период'), key: 'period', width: 110, render: (_, r) => r.period },
+ {
+ title: head('Период'),
+ key: 'period',
+ width: 110,
+ render: (_, r) => r.period,
+ },
{
title: head('Проверка'),
key: 'check',
@@ -106,6 +132,22 @@ export function FilesList({ files, loading, labelFor }: { files: FileOut[]; load
),
},
+
+ {
+ key: 'actions',
+ title: '',
+ dataIndex: 'action',
+ render: (_, r) => (
+
}
+ aria-label='Удалить файл'
+ onClick={(e) => {
+ e.stopPropagation();
+ onDeleteClick(r);
+ }}
+ />
+ ),
+ },
];
if (loading && files.length === 0) {
@@ -125,7 +167,10 @@ export function FilesList({ files, loading, labelFor }: { files: FileOut[]; load
dataSource={rows}
locale={{ emptyText: 'Документов нет' }}
onRow={(r) => ({
- onClick: r.linkable && r.documentId ? () => navigate(`/documents/${r.documentId}`) : undefined,
+ onClick:
+ r.linkable && r.documentId
+ ? () => navigate(`/documents/${r.documentId}`)
+ : () => message.warning('Просмотр данного документа недоступен'),
style: r.linkable ? { cursor: 'pointer' } : undefined,
})}
/>
diff --git a/src/widgets/FilesDrawer/ReplaceDocModal.tsx b/src/widgets/FilesDrawer/ReplaceDocModal.tsx
new file mode 100644
index 0000000..6ae979a
--- /dev/null
+++ b/src/widgets/FilesDrawer/ReplaceDocModal.tsx
@@ -0,0 +1,77 @@
+import { FileAddOutlined, UploadOutlined } from '@ant-design/icons';
+import { Button, Input, Modal, Upload } from 'antd';
+import { useEffect, useState } from 'react';
+
+const { Dragger } = Upload;
+
+type ReplaceDocModalProps = {
+ open: boolean;
+ docName: string;
+ organizationName: string | null;
+ submitting: boolean;
+ onCancel: () => void;
+ onSubmit: (file: File, reason: string) => void;
+};
+
+export default function ReplaceDocModal({ open, docName, organizationName, submitting, onCancel, onSubmit }: ReplaceDocModalProps) {
+ const [reason, setReason] = useState('');
+ const [file, setFile] = useState
(null);
+
+ // при каждом открытии — пустая форма
+ useEffect(() => {
+ if (open) {
+ setReason('');
+ setFile(null);
+ }
+ }, [open]);
+
+ return (
+ file && onSubmit(file, reason.trim())}
+ okText='Загрузить'
+ okButtonProps={{
+ icon: ,
+ disabled: file === null || reason.trim().length === 0,
+ }}
+ confirmLoading={submitting}>
+
+ {organizationName &&
{organizationName}}
+
+ Заменяемый документ: {docName}
+
+
+
setReason(e.target.value)} />
+
+
{
+ setFile(f);
+ return false;
+ }}
+ onRemove={() => setFile(null)}>
+
+
+
+
+ Перетащите файл сюда
+
+
+
+
+
+ );
+}
diff --git a/src/widgets/FilesDrawer/documentRows.test.ts b/src/widgets/FilesDrawer/documentRows.test.ts
index 88683a7..d99e3fc 100644
--- a/src/widgets/FilesDrawer/documentRows.test.ts
+++ b/src/widgets/FilesDrawer/documentRows.test.ts
@@ -145,6 +145,13 @@ describe('buildDocumentRows: предупреждения', () => {
expect(rows[0].issueCounts).toEqual({ error: 0, info: 0 });
});
+ it('fileId — id файла и у строки документа, и у строки файла без документов (удаление идёт по файлу)', () => {
+ const withDoc = buildDocumentRows([file({ id: 'f7', documents: [doc({ id: 'd7' })] })]);
+ expect(withDoc[0]).toMatchObject({ key: 'd7', documentId: 'd7', fileId: 'f7' });
+ const failed = buildDocumentRows([file({ id: 'f8', status: 'ERROR' })]);
+ expect(failed[0]).toMatchObject({ key: 'f8', documentId: null, fileId: 'f8' });
+ });
+
it('job null — пустые списки; старый формат строк не ломает', () => {
expect(buildDocumentRows([file({ documents: [doc()] })])[0]).toMatchObject({ fileWarnings: [], mappingWarnings: [] });
const legacy = buildDocumentRows([file({ job: job({ warnings: ['старое'] as never }), documents: [doc()] })]);
diff --git a/src/widgets/FilesDrawer/documentRows.ts b/src/widgets/FilesDrawer/documentRows.ts
index d5873ee..2a62265 100644
--- a/src/widgets/FilesDrawer/documentRows.ts
+++ b/src/widgets/FilesDrawer/documentRows.ts
@@ -10,6 +10,8 @@ export interface DocumentRow {
key: string;
/** id документа; null — строка файла без документов */
documentId: string | null;
+ /** id файла: удаление и замена — файлом целиком */
+ fileId: string;
name: string;
fileType: FileType;
subtitle: string;
@@ -64,6 +66,7 @@ export function buildDocumentRows(files: FileOut[], labelFor?: (f: FileOut) => s
{
key: f.id,
documentId: null,
+ fileId: f.id,
name,
fileType: f.file_type,
subtitle: join([f.file_type, date, extra]),
@@ -87,6 +90,7 @@ export function buildDocumentRows(files: FileOut[], labelFor?: (f: FileOut) => s
return {
key: d.id,
documentId: d.id,
+ fileId: f.id,
name,
fileType: f.file_type,
subtitle: join([typeText, f.file_type, date, extra]),