скелет готов
This commit is contained in:
@@ -24,8 +24,25 @@ import * as React from 'react';
|
||||
// отклонённую) на редактирование в той же выезжающей панели, что и просмотр.
|
||||
export type PortalMode = 'submit' | 'approve' | 'create' | 'edit';
|
||||
|
||||
/** Раздел бокового меню. */
|
||||
export type NavSection = 'new' | 'approvals' | 'own' | 'search';
|
||||
/**
|
||||
* Раздел бокового меню.
|
||||
*
|
||||
* Три раздела — очереди действий текущего пользователя, и они НЕ пересекаются
|
||||
* (см. ApprovalQueueKind в myRequests.service.ts):
|
||||
* 'approvals' — ждут его согласования (статус строки «На согласовании»),
|
||||
* 'execution' — ждут его исполнения (статус строки «На исполнении»),
|
||||
* 'rework' — ЕГО заявки, которые вернули ему на доработку (статус ЗАЯВКИ
|
||||
* «Возвращена на доработку»); в отличие от первых двух смотрит
|
||||
* на список данных по автору, а не на строки маршрута.
|
||||
*/
|
||||
export type NavSection = 'new' | 'approvals' | 'execution' | 'rework' | 'own' | 'search';
|
||||
|
||||
/**
|
||||
* Подвкладка раздела «Мои заявки». 'created' — заявки, где пользователь автор
|
||||
* (единственная, где есть фильтр по статусу); остальные — история его решений
|
||||
* как участника чужих маршрутов.
|
||||
*/
|
||||
export type OwnTab = 'created' | 'approved' | 'rejected' | 'executed';
|
||||
|
||||
export interface IRoute {
|
||||
mode: PortalMode;
|
||||
@@ -37,15 +54,32 @@ export interface IRoute {
|
||||
itemId?: number;
|
||||
/** Id исходной заявки для предзаполнения — для 'create' (напр. орг. места на основе прием). */
|
||||
sourceId?: number;
|
||||
/** Подвкладка «Моих заявок»; задана только при nav='own'. */
|
||||
ownTab?: OwnTab;
|
||||
/** Фильтр по статусу заявки; задан только при nav='own' и ownTab='created'. */
|
||||
ownStatus?: string;
|
||||
}
|
||||
|
||||
const ROUTE_CHANGE_EVENT = 'rp-route-change';
|
||||
|
||||
function parseNav(raw: string | undefined): NavSection {
|
||||
if (raw === 'approvals' || raw === 'own' || raw === 'search') return raw;
|
||||
if (
|
||||
raw === 'approvals' ||
|
||||
raw === 'execution' ||
|
||||
raw === 'rework' ||
|
||||
raw === 'own' ||
|
||||
raw === 'search'
|
||||
) {
|
||||
return raw;
|
||||
}
|
||||
return 'new';
|
||||
}
|
||||
|
||||
function parseOwnTab(raw: string | undefined): OwnTab {
|
||||
if (raw === 'approved' || raw === 'rejected' || raw === 'executed') return raw;
|
||||
return 'created';
|
||||
}
|
||||
|
||||
/** Разобрать строку запроса (по умолчанию — из адреса страницы) в маршрут. */
|
||||
export function parseRoute(search: string = window.location.search): IRoute {
|
||||
const params = new URLSearchParams(search);
|
||||
@@ -57,19 +91,28 @@ export function parseRoute(search: string = window.location.search): IRoute {
|
||||
const sourceRaw = params.get('rpsource');
|
||||
const sourceId = sourceRaw ? Number(sourceRaw) : undefined;
|
||||
|
||||
// Подвкладка и фильтр — состояние раздела «Мои заявки», поэтому вне его не
|
||||
// читаются вовсе (иначе чужой rptab из ссылки «протёк» бы в другой раздел).
|
||||
// Фильтр по статусу живёт только на вкладке «Инициированные»: у вкладок с
|
||||
// решениями отбор задаёт сама вкладка.
|
||||
const ownTab = nav === 'own' ? parseOwnTab(params.get('rptab') ?? undefined) : undefined;
|
||||
const ownStatus = ownTab === 'created' ? params.get('rpstatus') ?? undefined : undefined;
|
||||
|
||||
// Открытая заявка (панель поверх раздела) — при полном наборе параметров.
|
||||
// Раздел под панелью сохраняется целиком, вместе с подвкладкой и фильтром:
|
||||
// закрыв панель, пользователь должен вернуться ровно в тот же список.
|
||||
if (mode === 'approve' && formKey && itemId && !isNaN(itemId)) {
|
||||
return { mode: 'approve', nav, formKey, itemId };
|
||||
return { mode: 'approve', nav, formKey, itemId, ownTab, ownStatus };
|
||||
}
|
||||
// Редактирование собственной незавершённой заявки — та же панель, но с формой.
|
||||
if (mode === 'edit' && formKey && itemId && !isNaN(itemId)) {
|
||||
return { mode: 'edit', nav, formKey, itemId };
|
||||
return { mode: 'edit', nav, formKey, itemId, ownTab, ownStatus };
|
||||
}
|
||||
// Создание производной заявки с предзаполнением из исходной.
|
||||
if (formKey && sourceId && !isNaN(sourceId)) {
|
||||
return { mode: 'create', nav: 'new', formKey, sourceId };
|
||||
}
|
||||
return { mode: 'submit', nav };
|
||||
return { mode: 'submit', nav, ownTab, ownStatus };
|
||||
}
|
||||
|
||||
// Собрать query-строку маршрута, сохранив посторонние параметры страницы.
|
||||
@@ -80,10 +123,19 @@ function buildQuery(route: IRoute): string {
|
||||
params.delete('rptype');
|
||||
params.delete('rpid');
|
||||
params.delete('rpsource');
|
||||
params.delete('rptab');
|
||||
params.delete('rpstatus');
|
||||
|
||||
if (route.nav !== 'new') {
|
||||
params.set('rpnav', route.nav);
|
||||
}
|
||||
// Значения по умолчанию в адрес не пишем — чтобы обычный переход на «Мои
|
||||
// заявки» давал чистую ссылку, а не ?rpnav=own&rptab=created.
|
||||
if (route.nav === 'own') {
|
||||
const ownTab = route.ownTab ?? 'created';
|
||||
if (ownTab !== 'created') params.set('rptab', ownTab);
|
||||
else if (route.ownStatus) params.set('rpstatus', route.ownStatus);
|
||||
}
|
||||
if ((route.mode === 'approve' || route.mode === 'edit') && route.formKey && route.itemId) {
|
||||
params.set('rpmode', route.mode);
|
||||
params.set('rptype', route.formKey);
|
||||
|
||||
Reference in New Issue
Block a user