fix: внес изменения в заявках рекрутинга от 16.09.26
Tests / frontend-test (push) Successful in 1m20s

This commit is contained in:
Тимур Городецкий
2026-09-16 17:59:45 +05:00
parent 428122d32a
commit 6f8bea33a2
31 changed files with 595 additions and 101 deletions
@@ -6,6 +6,10 @@ import {
FormCard,
InitiatorLine,
FormModeProvider,
FileDropzone,
AttachmentList,
CollapseSection,
FormField,
Icon,
RequestNumber,
SubmitActions,
@@ -26,6 +30,12 @@ import {
APPROVAL_PHASE,
initialSubmitStatus
} from '../../shared/approval';
import {
uploadAttachments,
getAttachments,
deleteAttachment,
IAttachmentInfo
} from '../../shared/attachments/attachments.service';
import { IRequestFormProps } from '../../models/types';
import { getEmployeeOrganizations, formatEmployeeOrganizations } from '../../shared/dictionary';
import { friendlyErrorMessage } from '../../shared/diagnostics';
@@ -55,6 +65,8 @@ const ReferralForm: React.FC<IRequestFormProps> = ({
onCodeLoaded
}) => {
const [data, setData] = useState<IFormData>(EMPTY_DATA);
const [files, setFiles] = useState<File[]>([]);
const [existingAttachments, setExistingAttachments] = useState<IAttachmentInfo[]>([]);
const [requestId, setRequestId] = useState<number | undefined>(editId);
const [requestStatus, setRequestStatus] = useState<string | undefined>(undefined);
const [requestCode, setRequestCode] = useState<string | undefined>(undefined);
@@ -86,13 +98,14 @@ const ReferralForm: React.FC<IRequestFormProps> = ({
return;
}
let alive = true;
loadReferralRequest(editId, editListId)
.then((loaded) => {
Promise.all([loadReferralRequest(editId, editListId), getAttachments(editListId || dataListTitle(FORM_ID), editId)])
.then(([loaded, atts]) => {
if (alive) {
setData(loaded.data);
setRequestStatus(loaded.status);
setRequestCode(loaded.code || undefined);
if (loaded.code) notifyCode(loaded.code);
setExistingAttachments(atts);
}
})
.catch((e) => {
@@ -272,6 +285,15 @@ const ReferralForm: React.FC<IRequestFormProps> = ({
autoApprove: r.autoApprove
}));
const handleRemoveAttachment = (fileName: string): void => {
if (requestId === undefined) {
return;
}
deleteAttachment(editListId || dataListTitle(FORM_ID), requestId, fileName)
.then(() => setExistingAttachments((prev) => prev.filter((a) => a.fileName !== fileName)))
.catch(() => undefined);
};
const save = (status: string): (() => Promise<void>) => async (): Promise<void> => {
// validate()/validateSubmit() уже гарантировали requestTypeId к моменту вызова
// (см. useRequestSubmit.run — валидирует ДО save), но TS этого через границу
@@ -298,6 +320,11 @@ const ReferralForm: React.FC<IRequestFormProps> = ({
if (code) {
setRequestCode(code);
}
if (files.length > 0) {
await uploadAttachments(writeListId || dataListTitle(FORM_ID), id, files); // файлы — после создания элемента
setFiles([]); // выгруженные файлы убираем, чтобы пересохранение не дублировало
setExistingAttachments(await getAttachments(writeListId || dataListTitle(FORM_ID), id));
}
if (onSaved) {
onSaved();
}
@@ -397,6 +424,19 @@ const ReferralForm: React.FC<IRequestFormProps> = ({
<AssessmentSection {...sectionProps} />
</FormModeProvider>
{!readOnly && (
<CollapseSection title="Вложения" icon="upload">
{existingAttachments.length > 0 && (
<FormField label="Прикреплённые файлы" full>
<AttachmentList items={existingAttachments} onRemove={handleRemoveAttachment} />
</FormField>
)}
<FormField label={existingAttachments.length > 0 ? 'Добавить файлы' : 'Файлы'} full>
<FileDropzone files={files} onChange={setFiles} />
</FormField>
</CollapseSection>
)}
{/* Блок остаётся видимым и пустым (не скрываем по noApprovalPhase) —
маршрут без согласующих не значит, что их нельзя добавить: матрица
редактируема, заявитель вправе вписать согласующего сам. */}
@@ -2,7 +2,17 @@ import * as React from 'react';
import { useState, useEffect, useMemo, useCallback } from 'react';
import type { WebPartContext } from '@microsoft/sp-webpart-base';
import styles from './ReferralView.module.scss';
import { Alert, FormCard, InitiatorLine, FormModeProvider, PrintSplitButton, OrgLetterhead } from '../../shared/ui';
import {
Alert,
FormCard,
InitiatorLine,
FormModeProvider,
CollapseSection,
FormField,
AttachmentList,
PrintSplitButton,
OrgLetterhead
} from '../../shared/ui';
import {
ApproverService,
DecisionPanel,
@@ -14,6 +24,7 @@ import {
APPROVAL_PHASE,
isApprovedStatus
} from '../../shared/approval';
import { getAttachments, IAttachmentInfo } from '../../shared/attachments/attachments.service';
import { friendlyErrorMessage } from '../../shared/diagnostics';
import {
approvalListTitle,
@@ -57,6 +68,7 @@ const ReferralView: React.FC<IReferralViewProps> = ({ context, itemId, formKey,
const [data, setData] = useState<IFormData>(EMPTY_DATA);
const [status, setStatus] = useState<string>('');
const [code, setCode] = useState<string>('');
const [attachments, setAttachments] = useState<IAttachmentInfo[]>([]);
const [loading, setLoading] = useState<boolean>(true);
const [error, setError] = useState<string | null>(null);
// Какая из организаций рекомендателя (см. OrganizationField) идёт в печать —
@@ -101,13 +113,14 @@ const ReferralView: React.FC<IReferralViewProps> = ({ context, itemId, formKey,
useEffect(() => {
let alive = true;
setLoading(true);
loadReferralRequest(itemId, listId)
.then((loaded) => {
Promise.all([loadReferralRequest(itemId, listId), getAttachments(listId || dataListTitle(FORM_ID), itemId)])
.then(([loaded, files]) => {
if (alive) {
setData(loaded.data);
setStatus(loaded.status);
setCode(loaded.code);
notifyCode(loaded.code);
setAttachments(files);
setError(null);
setLoading(false);
}
@@ -176,6 +189,14 @@ const ReferralView: React.FC<IReferralViewProps> = ({ context, itemId, formKey,
<CandidateInfoSection {...sectionProps} />
<AssessmentSection {...sectionProps} />
</FormModeProvider>
<div className="rp-no-print">
<CollapseSection title="Вложения" icon="upload">
<FormField label="Файлы" full>
<AttachmentList items={attachments} />
</FormField>
</CollapseSection>
</div>
</FormCard>
<ApprovalMatrix editor={approvers} search={(q) => approval.searchUsers(q)} />