feat: добавил инструкцию пользователя в боковую панел
Tests / frontend-test (push) Successful in 1m16s

This commit is contained in:
Тимур Городецкий
2026-09-24 12:21:43 +05:00
parent c623d93b56
commit b7bd8537a4
2 changed files with 23 additions and 1 deletions
@@ -21,6 +21,7 @@ import {
OwnTab, OwnTab,
} from '../shared/routing'; } from '../shared/routing';
import { onRequestsChanged, emitRequestsChanged } from '../shared/requestEvents'; import { onRequestsChanged, emitRequestsChanged } from '../shared/requestEvents';
import { USER_GUIDE_URL } from '../shared/config';
import { getImpersonatedEmail, getImpersonatedDisplayName } from '../shared/impersonation'; import { getImpersonatedEmail, getImpersonatedDisplayName } from '../shared/impersonation';
import { confirmDiscardFormChanges, markFormClean, markFormDirty } from '../shared/unsavedChanges'; import { confirmDiscardFormChanges, markFormClean, markFormDirty } from '../shared/unsavedChanges';
import { Drawer } from './Drawer/Drawer'; import { Drawer } from './Drawer/Drawer';
@@ -298,6 +299,11 @@ const RequestPortal: React.FC<IRequestPortalProps> = ({ hasTeamsContext, context
// Разделы бокового меню для пакетного Sidebar (счётчики — из navCounts). // Разделы бокового меню для пакетного Sidebar (счётчики — из navCounts).
// «Отчёты» — только у тех, кому разрешено (см. canSeeReports выше): скрыт из // «Отчёты» — только у тех, кому разрешено (см. canSeeReports выше): скрыт из
// меню совсем, а не показан неактивным, — раздела для остальных как бы не существует. // меню совсем, а не показан неактивным, — раздела для остальных как бы не существует.
//
// «Инструкция пользователя» — не раздел портала, а внешняя ссылка (docx в базе
// знаний). id 'instructions' НЕ входит в NavSection специально: обработчик
// onChange ниже перехватывает его до вызова goto() и открывает ссылку в новой
// вкладке, не меняя текущий раздел/маршрут.
const navItems: ISidebarItem[] = [ const navItems: ISidebarItem[] = [
{ id: 'new', title: 'Новая заявка', icon: 'plus' }, { id: 'new', title: 'Новая заявка', icon: 'plus' },
{ id: 'approvals', title: 'На согласовании', icon: 'user-check', count: navCounts?.approvals }, { id: 'approvals', title: 'На согласовании', icon: 'user-check', count: navCounts?.approvals },
@@ -306,8 +312,17 @@ const RequestPortal: React.FC<IRequestPortalProps> = ({ hasTeamsContext, context
{ id: 'own', title: 'Мои заявки', icon: 'clipboard' }, { id: 'own', title: 'Мои заявки', icon: 'clipboard' },
{ id: 'search', title: 'Поиск', icon: 'search' }, { id: 'search', title: 'Поиск', icon: 'search' },
...(canSeeReports ? [{ id: 'reports', title: 'Отчёты', icon: 'chart' } as ISidebarItem] : []), ...(canSeeReports ? [{ id: 'reports', title: 'Отчёты', icon: 'chart' } as ISidebarItem] : []),
{ id: 'instructions', title: 'Инструкция пользователя', icon: 'info' },
]; ];
const handleNavChange = (id: string): void => {
if (id === 'instructions') {
window.open(USER_GUIDE_URL, '_blank', 'noopener');
return;
}
goto(id as NavSection);
};
return ( return (
<section className={rootClasses}> <section className={rootClasses}>
<IconSprite /> <IconSprite />
@@ -329,7 +344,7 @@ const RequestPortal: React.FC<IRequestPortalProps> = ({ hasTeamsContext, context
<Sidebar <Sidebar
items={navItems} items={navItems}
activeId={route.nav} activeId={route.nav}
onChange={(id) => goto(id as NavSection)} onChange={handleNavChange}
brand="Портал заявок" brand="Портал заявок"
collapsed={navCollapsed} collapsed={navCollapsed}
onToggleCollapsed={() => setNavCollapsed((v) => !v)} onToggleCollapsed={() => setNavCollapsed((v) => !v)}
@@ -8,6 +8,13 @@
*/ */
export const DATA_SITE_URL = 'https://tnsukz.sharepoint.com/sites/requests'; export const DATA_SITE_URL = 'https://tnsukz.sharepoint.com/sites/requests';
/**
* Инструкция пользователя по порталу (docx на сайте базы знаний) — ссылка в
* боковом меню (см. components/RequestPortal.tsx), открывается в новой вкладке.
*/
export const USER_GUIDE_URL =
'https://tnsukz.sharepoint.com/:w:/r/sites/knowledge/DocLib8/%D0%98%D0%BD%D1%81%D1%82%D1%80%D1%83%D0%BA%D1%86%D0%B8%D0%B8%20%D0%BA%20IT%20%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%B0%D0%BC/%D0%98%D0%BD%D1%81%D1%82%D1%80%D1%83%D0%BA%D1%86%D0%B8%D1%8F%20-%20%D0%9F%D0%BE%D1%80%D1%82%D0%B0%D0%BB%20%D0%B7%D0%B0%D1%8F%D0%B2%D0%BE%D0%BA.docx?d=wce77e8a0d19d49b5b2fcdf13828e8bb3&csf=1&web=1&e=p9V3hU';
/** /**
* Внешний approval-route API (маршруты согласования по ролям). * Внешний approval-route API (маршруты согласования по ролям).
* Авторизация — AadHttpClient (SSO текущего пользователя) по clientId * Авторизация — AadHttpClient (SSO текущего пользователя) по clientId