основное сделано

This commit is contained in:
gorbenko.pavel
2026-08-12 15:12:11 +05:00
parent 4b83d666f1
commit 9fc089c37a
47 changed files with 2481 additions and 52 deletions
@@ -2,6 +2,7 @@ import * as React from 'react';
import styles from './ManageRequestsScreen.module.scss';
import { ManageRequestsApproverModal } from './ManageRequestsApproverModal';
import { ManageRequestsPhaseTable } from './ManageRequestsPhaseTable';
import { ManageRequestsSlaModal } from './ManageRequestsSlaModal';
import { ApprovalRouteApi } from '../../services/api';
import { PortalDictionaryClient } from '../../services/portalDictionary';
import { RequestManageService } from '../../services/requestManageService';
@@ -178,6 +179,7 @@ export const ManageRequestsScreen: React.FC<IManageRequestsScreenProps> = ({ api
const [matrixLoading, setMatrixLoading] = React.useState(false);
const [matrixError, setMatrixError] = React.useState<string | undefined>();
const [modal, setModal] = React.useState<ManagedApprovalRow | undefined>();
const [slaRow, setSlaRow] = React.useState<ManagedApprovalRow | undefined>();
const [deleteRow, setDeleteRow] = React.useState<ManagedApprovalRow | undefined>();
const [saveError, setSaveError] = React.useState<string | undefined>();
const [notifyResult, setNotifyResult] = React.useState<{ message: string; kind: 'ok' | 'err' } | undefined>();
@@ -348,6 +350,31 @@ export const ManageRequestsScreen: React.FC<IManageRequestsScreenProps> = ({ api
const openReassign = (row: ManagedApprovalRow): void => setModal(row);
const closeModal = (): void => setModal(undefined);
const openSla = (row: ManagedApprovalRow): void => setSlaRow(row);
const closeSla = (): void => setSlaRow(undefined);
// SLA правится так же оптимистично, как переназначение: строка в матрице
// обновляется по ответу сервера, без перезагрузки всей матрицы.
const saveSla = (
// eslint-disable-next-line @rushstack/no-new-null -- null = «не задано», работает SLA типа заявки
slaHours: number | null,
// eslint-disable-next-line @rushstack/no-new-null -- см. выше
askOverdueReason: boolean | null
): Promise<void> => {
if (!matrix || !slaRow) return Promise.resolve();
setSaveError(undefined);
const rowId = slaRow.id;
return requestManage
.updateRowSla(matrix, rowId, slaHours, askOverdueReason)
.then(() => {
setMatrix(prev => (prev ? patchRow(prev, rowId, { slaHours, askOverdueReason }) : prev));
closeSla();
})
.catch((e: Error) => {
setSaveError(reportError(e, 'saveSla: updateRowSla'));
throw e;
});
};
// Кого нельзя выбрать при переназначении — все остальные согласующие/
// исполнители ТОЙ ЖЕ фазы (сама строка modal исключена, иначе нельзя было
@@ -424,7 +451,11 @@ export const ManageRequestsScreen: React.FC<IManageRequestsScreenProps> = ({ api
comment: '',
order,
allowReassign: false,
phase
phase,
// Шаг, добавленный вручную, маршрутом-шаблоном не порождён и своего SLA не
// имеет — работает SLA типа заявки, пока его не зададут отдельно.
slaHours: null,
askOverdueReason: null
};
const previous = matrix;
@@ -548,6 +579,7 @@ export const ManageRequestsScreen: React.FC<IManageRequestsScreenProps> = ({ api
requestRejected={requestRejected}
statusVariant={statusVariant}
onReassign={openReassign}
onEditSla={openSla}
onRemove={askDelete}
onNotify={handleNotify}
notifyingRowId={notifyingRowId}
@@ -564,6 +596,7 @@ export const ManageRequestsScreen: React.FC<IManageRequestsScreenProps> = ({ api
requestRejected={requestRejected}
statusVariant={statusVariant}
onReassign={openReassign}
onEditSla={openSla}
onRemove={askDelete}
onNotify={handleNotify}
notifyingRowId={notifyingRowId}
@@ -590,6 +623,16 @@ export const ManageRequestsScreen: React.FC<IManageRequestsScreenProps> = ({ api
/>
)}
{slaRow && (
<ManageRequestsSlaModal
orderNo={slaRow.order}
slaHours={slaRow.slaHours}
askOverdueReason={slaRow.askOverdueReason}
onSave={saveSla}
onClose={closeSla}
/>
)}
{deleteRow && (
<ConfirmDialog
title={texts.manageRequests.deleteTitle}