основное готово
This commit is contained in:
@@ -73,6 +73,14 @@
|
||||
margin-bottom: $sp-6;
|
||||
}
|
||||
|
||||
// Раздел «Новая заявка», когда открыта другая вкладка. Именно скрытие, а не
|
||||
// размонтирование: заполненная форма должна пережить переключение вкладок
|
||||
// (см. RequestPortal.tsx). display:none выводит содержимое и из потока, и из
|
||||
// последовательности табуляции — скрытая форма не ловит фокус с клавиатуры.
|
||||
.hiddenPane {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// На узких экранах рейл уходит наверх.
|
||||
@media (max-width: 900px) {
|
||||
.layout {
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { IRequestPortalProps } from './IRequestPortalProps';
|
||||
import { IconSprite } from '../shared/ui/Icon/IconSprite';
|
||||
import { navigate, useRoute, NavSection } from '../shared/routing';
|
||||
import { onRequestsChanged, emitRequestsChanged } from '../shared/requestEvents';
|
||||
import { confirmDiscardFormChanges, markFormClean, markFormDirty } from '../shared/unsavedChanges';
|
||||
import { SideNav } from './SideNav/SideNav';
|
||||
import { Drawer } from './Drawer/Drawer';
|
||||
import { CategoryTabs } from './CategoryTabs/CategoryTabs';
|
||||
@@ -68,13 +69,28 @@ const RequestPortal: React.FC<IRequestPortalProps> = ({ hasTeamsContext, context
|
||||
|
||||
// Переход «создать на основе» (в т.ч. из открытой заявки в панели): переключаем
|
||||
// вкладку категорий на категорию целевой формы, чтобы она совпала с открытой формой.
|
||||
// Форма при этом пересоздаётся (см. key у SubmitFeature), поэтому прежние
|
||||
// несохранённые правки к ней уже не относятся — снимаем флаг.
|
||||
React.useEffect(() => {
|
||||
if (route.mode === 'create' && route.formKey) {
|
||||
const found = REQUEST_TYPES.filter((r) => r.id === route.formKey)[0];
|
||||
if (found) setActiveCategoryId(found.categoryId);
|
||||
markFormClean();
|
||||
}
|
||||
}, [route.mode, route.formKey]);
|
||||
|
||||
// Сохранение (в том числе черновика) шлёт rp-requests-changed — после него
|
||||
// терять нечего, предупреждать при «создать на основе» больше не о чем.
|
||||
React.useEffect(() => onRequestsChanged(markFormClean), []);
|
||||
|
||||
// Смена категории закрывает открытую форму (SubmitFeature сбрасывает выбор,
|
||||
// когда категория перестаёт совпадать) — значит введённое пропадёт.
|
||||
const changeCategory = (categoryId: string): void => {
|
||||
if (!confirmDiscardFormChanges()) return;
|
||||
markFormClean();
|
||||
setActiveCategoryId(categoryId);
|
||||
};
|
||||
|
||||
const goto = (nav: NavSection): void => {
|
||||
// Клик по УЖЕ активному пункту меню не меняет маршрут, значит эффект
|
||||
// загрузки в таблице не перезапустится сам. Шлём событие обновления —
|
||||
@@ -100,26 +116,46 @@ const RequestPortal: React.FC<IRequestPortalProps> = ({ hasTeamsContext, context
|
||||
</div>
|
||||
|
||||
<main className={styles.main}>
|
||||
{route.nav === 'new' ? (
|
||||
<>
|
||||
<div className={styles.tabsWrap}>
|
||||
<CategoryTabs
|
||||
categories={CATEGORIES}
|
||||
activeId={activeCategoryId}
|
||||
onChange={setActiveCategoryId}
|
||||
/>
|
||||
</div>
|
||||
<SubmitFeature
|
||||
context={context}
|
||||
activeCategoryId={activeCategoryId}
|
||||
initialForm={
|
||||
route.mode === 'create' && route.formKey && route.sourceId
|
||||
? { formKey: route.formKey, sourceId: route.sourceId }
|
||||
: undefined
|
||||
}
|
||||
{/* Раздел «Новая заявка» держим СМОНТИРОВАННЫМ и просто прячем стилем,
|
||||
когда открыта другая вкладка. Иначе React размонтировал бы форму, и
|
||||
всё введённое пропадало бы при переключении на «Мои заявки» и
|
||||
обратно. Ключ завязан на «создать на основе»: обычные переключения
|
||||
вкладок его не меняют (состояние живёт), а вот открытие новой
|
||||
заявки на основе исходной пересоздаёт форму — SubmitFeature читает
|
||||
initialForm только при монтировании. */}
|
||||
<div
|
||||
className={route.nav === 'new' ? undefined : styles.hiddenPane}
|
||||
// Делегирование: любой пользовательский ввод внутри раздела помечает
|
||||
// форму изменённой. Так не нужно инструментировать каждую форму по
|
||||
// отдельности, и программное заполнение (предзаполнение «на основе»)
|
||||
// сюда не попадает — React выставляет значения без этих событий.
|
||||
onInput={markFormDirty}
|
||||
onChange={markFormDirty}
|
||||
>
|
||||
<div className={styles.tabsWrap}>
|
||||
<CategoryTabs
|
||||
categories={CATEGORIES}
|
||||
activeId={activeCategoryId}
|
||||
onChange={changeCategory}
|
||||
/>
|
||||
</>
|
||||
) : route.nav === 'search' ? (
|
||||
</div>
|
||||
<SubmitFeature
|
||||
key={
|
||||
route.mode === 'create' && route.formKey && route.sourceId
|
||||
? `create-${route.formKey}-${route.sourceId}`
|
||||
: 'blank'
|
||||
}
|
||||
context={context}
|
||||
activeCategoryId={activeCategoryId}
|
||||
initialForm={
|
||||
route.mode === 'create' && route.formKey && route.sourceId
|
||||
? { formKey: route.formKey, sourceId: route.sourceId }
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{route.nav === 'search' && (
|
||||
<SearchView
|
||||
context={context}
|
||||
onOpen={(request) =>
|
||||
@@ -131,7 +167,9 @@ const RequestPortal: React.FC<IRequestPortalProps> = ({ hasTeamsContext, context
|
||||
})
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
)}
|
||||
|
||||
{(route.nav === 'approvals' || route.nav === 'own') && (
|
||||
<RequestsTableView
|
||||
context={context}
|
||||
kind={route.nav === 'approvals' ? 'approvals' : 'own'}
|
||||
|
||||
Reference in New Issue
Block a user