feat: согласующий с полным правом правит вложения в подборе и приёме
Алтынай на своём шаге согласования теперь может добавлять и удалять файлы, а не только поля. Удаление — сразу, новые файлы загружаются вместе с «Сохранить» или решением. Блоки вложений вынесены из просмотров в отдельные компоненты на общем хуке useAttachmentEditor. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
import { useState } from 'react';
|
||||
import { deleteAttachment, getAttachments, IAttachmentInfo, uploadAttachments } from './attachments.service';
|
||||
import { friendlyErrorMessage } from '../diagnostics';
|
||||
|
||||
/**
|
||||
* Подготовка новых файлов группы к загрузке — напр. префикс категории в имени
|
||||
* (см. forms/RecruitingHire/attachmentCategories). По умолчанию — как есть.
|
||||
*/
|
||||
export type PrepareFiles = (groupKey: string, files: File[]) => File[];
|
||||
|
||||
export interface IAttachmentEditor {
|
||||
/** Вложения, уже прикреплённые к заявке. */
|
||||
items: IAttachmentInfo[];
|
||||
setItems: (items: IAttachmentInfo[]) => void;
|
||||
/** Выбранные, но ещё не загруженные файлы — по группам (категориям) формы. */
|
||||
pending: Record<string, File[]>;
|
||||
setPending: (groupKey: string, files: File[]) => void;
|
||||
/** Удалить прикреплённый файл сразу из заявки (по полному имени файла в SP). */
|
||||
remove: (fileName: string) => void;
|
||||
/** Загрузить все выбранные файлы и перечитать список вложений. */
|
||||
uploadPending: (prepare?: PrepareFiles) => Promise<void>;
|
||||
/** Ошибка последнего удаления — показать рядом со списком. */
|
||||
error: string | undefined;
|
||||
}
|
||||
|
||||
const keepAsIs: PrepareFiles = (_groupKey, files) => files;
|
||||
|
||||
/**
|
||||
* Правка вложений уже поданной заявки — для согласующего с полным правом
|
||||
* (см. shared/approval/fullEditRights.ts). Удаление — сразу, как в форме
|
||||
* автора; новые файлы копятся и загружаются вместе с сохранением полей
|
||||
* (кнопка «Сохранить» или решение), чтобы не было второй кнопки сохранения.
|
||||
*
|
||||
* listRef — Title текущей партиции или url архивной (см. attachments.service).
|
||||
*/
|
||||
export function useAttachmentEditor(listRef: string, itemId: number): IAttachmentEditor {
|
||||
const [items, setItems] = useState<IAttachmentInfo[]>([]);
|
||||
const [pending, setPendingState] = useState<Record<string, File[]>>({});
|
||||
const [error, setError] = useState<string | undefined>(undefined);
|
||||
|
||||
const setPending = (groupKey: string, files: File[]): void =>
|
||||
setPendingState((prev) => ({ ...prev, [groupKey]: files }));
|
||||
|
||||
const remove = (fileName: string): void => {
|
||||
setError(undefined);
|
||||
deleteAttachment(listRef, itemId, fileName)
|
||||
.then(() => setItems((prev) => prev.filter((a) => a.fileName !== fileName)))
|
||||
.catch((e) => setError(`Не удалось удалить файл «${fileName}»: ${friendlyErrorMessage(e)}`));
|
||||
};
|
||||
|
||||
const uploadPending = async (prepare: PrepareFiles = keepAsIs): Promise<void> => {
|
||||
const files = Object.keys(pending).reduce<File[]>(
|
||||
(acc, groupKey) => acc.concat(prepare(groupKey, pending[groupKey])),
|
||||
[]
|
||||
);
|
||||
if (files.length === 0) return;
|
||||
await uploadAttachments(listRef, itemId, files);
|
||||
// Загруженные убираем из выбора, иначе повторное сохранение продублирует их.
|
||||
setPendingState({});
|
||||
setItems(await getAttachments(listRef, itemId));
|
||||
};
|
||||
|
||||
return { items, setItems, pending, setPending, remove, uploadPending, error };
|
||||
}
|
||||
Reference in New Issue
Block a user