diff --git a/src/webparts/requestPortal/RequestPortalWebPart.ts b/src/webparts/requestPortal/RequestPortalWebPart.ts index d4524ff..e36543c 100644 --- a/src/webparts/requestPortal/RequestPortalWebPart.ts +++ b/src/webparts/requestPortal/RequestPortalWebPart.ts @@ -12,7 +12,7 @@ import { initSP } from './shared/pnp/pnpjs'; import { installErrorLogging } from './shared/diagnostics'; import { setImpersonatedIdentity } from './shared/impersonation'; import { APPROVAL_API_BASE_URL_LOCAL, APPROVAL_API_BASE_URL_PROD, setApprovalApiBaseUrl } from './shared/config'; -import { initListPartitions } from './shared/approval/listPartitions'; +import { initListPartitions } from './shared/approval'; import { ErrorOverlay } from './shared/ui'; import { PropertyPaneDebugUser } from './propertyPane/PropertyPaneDebugUser'; @@ -76,7 +76,18 @@ export default class RequestPortalWebPart extends BaseClientSideWebPart { + // + // НЕ ждём эту загрузку здесь (не Promise.all, а просто вызов) — onInit + // блокирует ПЕРВЫЙ render() всего портала (SPFx не рисует веб-часть, пока + // его промис не разрешится), а два новых AAD-запроса к внешнему api.tnsu.kz + // не обязаны попадать в этот путь: раньше onInit резолвился почти мгновенно + // (только _getEnvironmentMessage, без сети), и весь портал — включая + // «Мои заявки» и «Новая заявка», которым партиции вообще не нужны сразу — + // ждал открытия форм. Партиции при этом гарантированно успевают раньше, + // чем смонтируется первая форма (ленивый чанк грузится дольше). + // eslint-disable-next-line no-void -- без void это «висячий» промис, а no-floating-promises здесь уровня error + void initListPartitions(this.context); + return this._getEnvironmentMessage().then(message => { this._environmentMessage = message; }); } diff --git a/src/webparts/requestPortal/components/RequestPortal.tsx b/src/webparts/requestPortal/components/RequestPortal.tsx index 2a70890..212b451 100644 --- a/src/webparts/requestPortal/components/RequestPortal.tsx +++ b/src/webparts/requestPortal/components/RequestPortal.tsx @@ -7,6 +7,7 @@ import type { ISidebarItem } from '@tnsu/ui-kit'; import { ConfirmHost } from '../shared/ui'; import { navigate, + persistNav, persistOwnTab, persistOwnStatus, persistPage, @@ -130,6 +131,9 @@ const RequestPortal: React.FC = ({ hasTeamsContext, context }; const goto = (nav: NavSection): void => { + // Запоминаем раздел, чтобы следующий заход на портал (без rpnav в адресе) + // открыл его же, а не всегда «Новую заявку» (см. persistNav в routing.ts). + persistNav(nav); // Клик по УЖЕ активному пункту меню не меняет маршрут, значит эффект // загрузки в таблице не перезапустится сам. Шлём событие обновления — // таблица на него подписана и перечитает данные фоном, не убирая с экрана diff --git a/src/webparts/requestPortal/shared/routing.ts b/src/webparts/requestPortal/shared/routing.ts index 216b98c..53992b9 100644 --- a/src/webparts/requestPortal/shared/routing.ts +++ b/src/webparts/requestPortal/shared/routing.ts @@ -101,6 +101,11 @@ const ROUTE_CHANGE_EVENT = 'rp-route-change'; // вернувшись обратно, фильтр каждый раз сбрасывался на «Все статусы». const OWN_TAB_STORAGE_KEY = 'rp-own-tab'; const OWN_STATUS_STORAGE_KEY = 'rp-own-status'; +// Раздел бокового меню — тем же приёмом: запоминается только по явному клику +// (см. persistNav в goto() RequestPortal.tsx), чтобы заход на портал без +// rpnav в адресе открывал тот раздел, на котором остановились в прошлый раз, +// а не всегда «Новую заявку». +const NAV_STORAGE_KEY = 'rp-nav'; // Страница запоминается ОТДЕЛЬНО ДЛЯ КАЖДОЙ таблицы (см. viewKeyOf): один общий // номер переносился бы между разделами, где у каждого свой объём данных, — // уйдя со страницы 3 «Моих заявок» в «На согласовании», где страница всего @@ -246,17 +251,45 @@ export function persistOwnStatus(ownStatus: string | undefined): void { } } +function readStoredNav(): NavSection { + try { + const raw = window.localStorage.getItem(NAV_STORAGE_KEY); + return raw === 'approvals' || + raw === 'execution' || + raw === 'rework' || + raw === 'own' || + raw === 'search' || + raw === 'new' + ? raw + : 'new'; + } catch { + return 'new'; + } +} + +/** Запомнить раздел бокового меню — вызывать только при явном выборе пользователя. */ +export function persistNav(nav: NavSection): void { + try { + window.localStorage.setItem(NAV_STORAGE_KEY, nav); + } catch { + // localStorage недоступен (приватный режим и т.п.) — просто не сохраняем. + } +} + function parseNav(raw: string | undefined): NavSection { if ( raw === 'approvals' || raw === 'execution' || raw === 'rework' || raw === 'own' || - raw === 'search' + raw === 'search' || + raw === 'new' ) { return raw; } - return 'new'; + // В адресе раздела нет (rpnav отсутствует, в т.ч. при заходе на портал по + // голой ссылке) — открываем запомненный раздел, а не всегда «Новую заявку». + return readStoredNav(); } function parseOwnTab(raw: string | undefined): OwnTab {