Уведомления назначенным пользователям (#9)
Co-authored-by: gorbenko.pavel <gorbenko.pavel@tansu.kz> Reviewed-on: http://git.tnsu.kz/gorbenko.pavel/tnsu-approval-route/pulls/9
This commit was merged in pull request #9.
This commit is contained in:
+28
-2
@@ -1,7 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import tableStyles from '../ui/DataTable.module.scss';
|
||||
import styles from './ManageRequestsScreen.module.scss';
|
||||
import { Employee, ManagedApprovalRow, isEditableRowStatus, isMovableRowStatus } from '../../models';
|
||||
import { Employee, ManagedApprovalRow, REQUEST_STATUS, isEditableRowStatus, isMovableRowStatus } from '../../models';
|
||||
import { texts } from '../../texts';
|
||||
import { toEmployeeOption } from '../../utils/employee';
|
||||
import { blockIndexOf, blockRanges, markParallel, withOrdersFrom } from '../../utils/orderBlocks';
|
||||
@@ -27,6 +27,9 @@ export interface IManageRequestsPhaseTableProps {
|
||||
statusVariant: (status: string) => BadgeVariant;
|
||||
onReassign: (row: ManagedApprovalRow) => void;
|
||||
onRemove: (row: ManagedApprovalRow) => void;
|
||||
onNotify: (row: ManagedApprovalRow) => void;
|
||||
/** Id строки, для которой сейчас в процессе отправка уведомления — кнопка на ней отключена. */
|
||||
notifyingRowId?: number;
|
||||
employees: Employee[];
|
||||
employeesLoading: boolean;
|
||||
/** Плейсхолдер плашки-пикера под таблицей — разный для согласования/исполнения. */
|
||||
@@ -77,6 +80,8 @@ export const ManageRequestsPhaseTable: React.FC<IManageRequestsPhaseTableProps>
|
||||
statusVariant,
|
||||
onReassign,
|
||||
onRemove,
|
||||
onNotify,
|
||||
notifyingRowId,
|
||||
employees,
|
||||
employeesLoading,
|
||||
addPlaceholder,
|
||||
@@ -127,6 +132,13 @@ export const ManageRequestsPhaseTable: React.FC<IManageRequestsPhaseTableProps>
|
||||
// добавлять туда исполнителя всё равно бессмысленно).
|
||||
const phaseClosed = requestRejected || (rows.length > 0 && rows.every(r => !isEditableRowStatus(r.status)));
|
||||
|
||||
// Один и тот же человек не может стоять в фазе дважды (в т.ч. призрачной
|
||||
// строкой, которая ещё не подтверждена сервером, — см. handleAddApprover в
|
||||
// ManageRequestsScreen) — исключаем уже занятых из пикера, а не проверяем
|
||||
// постфактум: так дубликат физически нельзя выбрать.
|
||||
const usedEmails = new Set(rows.map(r => r.approverEmail.toLowerCase()).filter(Boolean));
|
||||
const addableEmployees = employees.filter(e => !usedEmails.has(e.email.toLowerCase()));
|
||||
|
||||
const applyReorder = (mutate: (rows: Row[]) => Row[]): void => {
|
||||
const renumbered = withOrdersFrom(mutate(withParallel), 0);
|
||||
const updates = diffOrders(rows, renumbered);
|
||||
@@ -186,6 +198,13 @@ export const ManageRequestsPhaseTable: React.FC<IManageRequestsPhaseTableProps>
|
||||
const isBlockStart = block.start === i;
|
||||
const movable = blockIndex > lastLockedBlockIndex;
|
||||
const rowEditable = isEditableRowStatus(r.status);
|
||||
// Уведомлять можно только активный шаг (флоу шлёт письмо тому,
|
||||
// чей RowID мы передали, независимо от статуса — сам он не
|
||||
// проверяет очередь). «Ждёт очереди» — шаг ещё не наступил,
|
||||
// слать по нему нечего: согласующий/исполнитель пока не
|
||||
// должен действовать (см. request-portal/notify.service.ts,
|
||||
// где по той же причине уведомляется только активный шаг).
|
||||
const notifiable = r.status === REQUEST_STATUS.onApproval || r.status === REQUEST_STATUS.onExecution;
|
||||
// Переключение параллельности — тоже перестановка (меняет order
|
||||
// относительно соседней строки), поэтому смотрим на isMovableRowStatus,
|
||||
// а не на rowEditable: у «Возвращена на доработку» кнопка
|
||||
@@ -261,6 +280,13 @@ export const ManageRequestsPhaseTable: React.FC<IManageRequestsPhaseTableProps>
|
||||
disabled={!canToggle}
|
||||
onClick={() => toggleParallel(i)}
|
||||
/>
|
||||
<IconButton
|
||||
icon="mail"
|
||||
className={styles.iconBtnVisible}
|
||||
label={notifiable ? texts.manageRequests.notify : texts.manageRequests.notifyNotActive}
|
||||
disabled={!notifiable || notifyingRowId === r.id}
|
||||
onClick={() => onNotify(r)}
|
||||
/>
|
||||
<IconButton
|
||||
icon="edit"
|
||||
className={styles.iconBtnVisible}
|
||||
@@ -303,7 +329,7 @@ export const ManageRequestsPhaseTable: React.FC<IManageRequestsPhaseTableProps>
|
||||
{!readOnly && !phaseClosed && (
|
||||
<div className={styles.addRow}>
|
||||
<SearchableSelect
|
||||
options={employees.map(toEmployeeOption)}
|
||||
options={addableEmployees.map(toEmployeeOption)}
|
||||
value=""
|
||||
loading={employeesLoading}
|
||||
placeholder={addPlaceholder}
|
||||
|
||||
Reference in New Issue
Block a user