feat: add catalogs group with site links to the sidebar

"Справочники" in the sidebar expands into links to the site's lists and
pages (projects, companies, professions, units, equipment, archive,
manual, recycle bin), each opening in a new tab. Uses the new Sidebar
groups and links from @tnsu/ui-kit 0.13.0.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Тимур Городецкий
2026-10-23 10:20:12 +05:00
parent ee282b61b7
commit 10ba9a6623
5 changed files with 76 additions and 15 deletions
+4 -4
View File
@@ -17,7 +17,7 @@
"@microsoft/sp-office-ui-fabric-core": "1.22.1", "@microsoft/sp-office-ui-fabric-core": "1.22.1",
"@microsoft/sp-property-pane": "1.22.1", "@microsoft/sp-property-pane": "1.22.1",
"@microsoft/sp-webpart-base": "1.22.1", "@microsoft/sp-webpart-base": "1.22.1",
"@tnsu/ui-kit": "^0.12.0", "@tnsu/ui-kit": "^0.13.0",
"react": "17.0.1", "react": "17.0.1",
"react-dom": "17.0.1", "react-dom": "17.0.1",
"tslib": "2.3.1" "tslib": "2.3.1"
@@ -6659,9 +6659,9 @@
"license": "0BSD" "license": "0BSD"
}, },
"node_modules/@tnsu/ui-kit": { "node_modules/@tnsu/ui-kit": {
"version": "0.12.0", "version": "0.13.0",
"resolved": "http://git.tnsu.kz/api/packages/timur.gorodetskiy/npm/%40tnsu%2Fui-kit/-/0.12.0/ui-kit-0.12.0.tgz", "resolved": "http://git.tnsu.kz/api/packages/timur.gorodetskiy/npm/%40tnsu%2Fui-kit/-/0.13.0/ui-kit-0.13.0.tgz",
"integrity": "sha512-lJYf2DoYaydrktbSotRNY0umeJlQw8Ekhh6fu1FGB0p+/TXTozpBfAs+TxK/mvOXlS9yYenEuGBi85fd/dRF2A==", "integrity": "sha512-FfIfPIXQyDwEb5v8n7EIxfn5V9CYURP98veTK9XUEplq/1lAJF8CXpVDZ/6i1DBOiNqSSs/zGMrydphXw6IMzQ==",
"license": "ISC", "license": "ISC",
"peerDependencies": { "peerDependencies": {
"@fluentui/react": "^8.106.4", "@fluentui/react": "^8.106.4",
+1 -1
View File
@@ -21,7 +21,7 @@
"@microsoft/sp-office-ui-fabric-core": "1.22.1", "@microsoft/sp-office-ui-fabric-core": "1.22.1",
"@microsoft/sp-property-pane": "1.22.1", "@microsoft/sp-property-pane": "1.22.1",
"@microsoft/sp-webpart-base": "1.22.1", "@microsoft/sp-webpart-base": "1.22.1",
"@tnsu/ui-kit": "^0.12.0", "@tnsu/ui-kit": "^0.13.0",
"react": "17.0.1", "react": "17.0.1",
"react-dom": "17.0.1", "react-dom": "17.0.1",
"tslib": "2.3.1" "tslib": "2.3.1"
+23 -6
View File
@@ -1,8 +1,8 @@
import { buildSidebarItems, navPageFor } from './navigation'; import { buildSidebarItems, CATALOGS_GROUP, navPageFor } from './navigation';
describe('buildSidebarItems', () => { describe('buildSidebarItems', () => {
it('без проекта в меню только главная', () => { it('без проекта в меню только главная и справочники', () => {
expect(buildSidebarItems(undefined).map((item) => item.id)).toEqual(['hub']); expect(buildSidebarItems(undefined).map((item) => item.id)).toEqual(['hub', 'catalogs']);
}); });
it('с проектом — все разделы', () => { it('с проектом — все разделы', () => {
@@ -15,13 +15,30 @@ describe('buildSidebarItems', () => {
'import', 'import',
'worksImport', 'worksImport',
'resources', 'resources',
'binder' 'binder',
'catalogs'
]); ]);
}); });
it('недоступные разделы скрываются, главная остаётся всегда', () => { it('недоступные разделы скрываются, главная и справочники остаются всегда', () => {
const onlyReports = (page: string): boolean => page === 'reports'; const onlyReports = (page: string): boolean => page === 'reports';
expect(buildSidebarItems('5', onlyReports).map((item) => item.id)).toEqual(['hub', 'reports']); expect(buildSidebarItems('5', onlyReports).map((item) => item.id)).toEqual(['hub', 'reports', 'catalogs']);
});
it('справочники — группа из 8 ссылок на сайт StroyBot', () => {
const links = CATALOGS_GROUP.children || [];
expect(links.map((link) => link.title)).toEqual([
'Проекты',
'Компании',
'Профессии',
'Единицы измерения',
'Техника',
'Архив',
'Инструкция',
'Корзина'
]);
links.forEach((link) => expect(link.href).toMatch(/^https:\/\/tnsukz\.sharepoint\.com\/sites\/stroy\//));
expect(links[2].href).toEqual('https://tnsukz.sharepoint.com/sites/stroy/Lists/List5/AllItems.aspx');
}); });
}); });
+17 -4
View File
@@ -1,5 +1,6 @@
import { IconName, ISidebarItem } from '@tnsu/ui-kit'; import { IconName, ISidebarItem } from '@tnsu/ui-kit';
import { PageId } from './routing/routes'; import { PageId } from './routing/routes';
import { CATALOG_LINKS } from '../config/catalogLinks';
export interface INavItem { export interface INavItem {
page: PageId; page: PageId;
@@ -33,14 +34,26 @@ export function navPageFor(page: PageId): PageId {
} }
/** /**
* Пункты меню для текущего состояния. Без проекта — только главная. * «Справочники» — раскрывающаяся группа ссылок на списки сайта (новая вкладка).
* Разделом приложения не является: onChange меню её не получает. Права проверяет SharePoint.
*/
export const CATALOGS_GROUP: ISidebarItem = {
id: 'catalogs',
title: 'Справочники',
icon: 'info',
children: CATALOG_LINKS.map((link) => ({ id: link.id, title: link.title, href: link.url }))
};
/**
* Пункты меню для текущего состояния. Без проекта — только главная и справочники.
* isAvailable — правила доступа к разделу (статус проекта, права); по умолчанию всё доступно. * isAvailable — правила доступа к разделу (статус проекта, права); по умолчанию всё доступно.
*/ */
export function buildSidebarItems( export function buildSidebarItems(
projectId: string | undefined, projectId: string | undefined,
isAvailable: (page: PageId) => boolean = () => true isAvailable: (page: PageId) => boolean = () => true
): ISidebarItem[] { ): ISidebarItem[] {
return NAV_ITEMS.filter((item) => !item.needsProject || (projectId !== undefined && isAvailable(item.page))).map( const sections = NAV_ITEMS.filter(
(item) => ({ id: item.page, title: item.title, icon: item.icon }) (item) => !item.needsProject || (projectId !== undefined && isAvailable(item.page))
); ).map((item) => ({ id: item.page, title: item.title, icon: item.icon }));
return [...sections, CATALOGS_GROUP];
} }
@@ -0,0 +1,31 @@
import { SITE_URL } from './constants';
// Ссылки группы «Справочники» в боковом меню: списки и страницы сайта StroyBot.
// Открываются в новой вкладке. Адреса списков — по внутренним именам (List, List2…), а не по названиям.
export interface ICatalogLink {
id: string;
title: string;
url: string;
}
export const CATALOG_LINKS: ICatalogLink[] = [
{ id: 'catalog-projects', title: 'Проекты', url: `${SITE_URL}/Lists/List/AllItems.aspx` },
{ id: 'catalog-companies', title: 'Компании', url: `${SITE_URL}/Lists/List2/AllItems.aspx` },
{ id: 'catalog-professions', title: 'Профессии', url: `${SITE_URL}/Lists/List5/AllItems.aspx` },
{ id: 'catalog-units', title: 'Единицы измерения', url: `${SITE_URL}/Lists/List3/AllItems.aspx` },
{ id: 'catalog-technics', title: 'Техника', url: `${SITE_URL}/Lists/List4/AllItems.aspx` },
{
id: 'catalog-archive',
title: 'Архив',
url:
`${SITE_URL}/Shared%20Documents/Forms/AllItems.aspx` +
'?id=%2Fsites%2Fstroy%2FShared%20Documents%2F%D0%90%D1%80%D1%85%D0%B8%D0%B2'
},
{
id: 'catalog-manual',
title: 'Инструкция',
url: `${SITE_URL}/_layouts/15/Doc.aspx?sourcedoc=%7BC380799B-FF81-4D34-BB61-B4F05B6C43A5%7D&file=stroybot_manual.docx&action=default`
},
{ id: 'catalog-recycle-bin', title: 'Корзина', url: `${SITE_URL}/_layouts/15/RecycleBin.aspx?view=5` }
];