Compare commits

...

2 Commits

Author SHA1 Message Date
Тимур Городецкий a9af74ba02 feat: add dividers to the sidebar and wrap long titles
Update @tnsu/ui-kit to 0.14.0: thin lines between sidebar items make the
long menu easier to scan, and long titles such as "Загрузить работы из
сметы" wrap to a second line instead of being cut off.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-23 17:56:48 +05:00
Тимур Городецкий f3e098ee84 feat: add "back to objects" link on the works page
The works page of an object had no way back except the sidebar. The link
goes straight to the objects of the same project, so it also works when
the page was opened by a direct URL.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-23 17:52:12 +05:00
7 changed files with 31 additions and 7 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.13.0", "@tnsu/ui-kit": "^0.14.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.13.0", "version": "0.14.0",
"resolved": "http://git.tnsu.kz/api/packages/timur.gorodetskiy/npm/%40tnsu%2Fui-kit/-/0.13.0/ui-kit-0.13.0.tgz", "resolved": "http://git.tnsu.kz/api/packages/timur.gorodetskiy/npm/%40tnsu%2Fui-kit/-/0.14.0/ui-kit-0.14.0.tgz",
"integrity": "sha512-FfIfPIXQyDwEb5v8n7EIxfn5V9CYURP98veTK9XUEplq/1lAJF8CXpVDZ/6i1DBOiNqSSs/zGMrydphXw6IMzQ==", "integrity": "sha512-Vun9AUM9jL8rttbsbKo5Yh6TUz1srkNqxiO6mmzebrSo1JOASNJqNjJPMTS+8Jt3MTrJPklvh0TbeqGQzw7qxQ==",
"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.13.0", "@tnsu/ui-kit": "^0.14.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"
+1
View File
@@ -37,6 +37,7 @@ export const AppShell: React.FC = () => {
onToggleCollapsed={() => setIsCollapsed((prev) => !prev)} onToggleCollapsed={() => setIsCollapsed((prev) => !prev)}
mobileOpen={isMobileMenuOpen} mobileOpen={isMobileMenuOpen}
onMobileClose={() => setIsMobileMenuOpen(false)} onMobileClose={() => setIsMobileMenuOpen(false)}
dividers
/> />
} }
mobileToggle={<SidebarToggle onClick={() => setIsMobileMenuOpen(true)} />} mobileToggle={<SidebarToggle onClick={() => setIsMobileMenuOpen(true)} />}
@@ -10,6 +10,20 @@ $toggle-size: 20px;
width: 100%; width: 100%;
} }
// «← К объектам» — как «← Вернуться назад» в форме отчёта.
.backLink {
align-self: flex-start;
color: $navy-600;
font-size: $fs-sm;
font-weight: 500;
text-decoration: none;
&:hover {
color: $navy-900;
text-decoration: underline;
}
}
.container { .container {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -8,5 +8,7 @@ import { WorksPageContent } from './WorksPageContent';
*/ */
export const WorksPage: React.FC = () => { export const WorksPage: React.FC = () => {
const { route } = useRouter(); const { route } = useRouter();
return <WorksPageContent key={route.objectId ?? ''} objectId={route.objectId ?? ''} />; return (
<WorksPageContent key={route.objectId ?? ''} objectId={route.objectId ?? ''} projectId={route.projectId} />
);
}; };
@@ -2,6 +2,7 @@ import * as React from 'react';
import { Alert, Button, confirmModal, Spinner } from '@tnsu/ui-kit'; import { Alert, Button, confirmModal, Spinner } from '@tnsu/ui-kit';
import { useAppServices } from '../../app/AppServicesContext'; import { useAppServices } from '../../app/AppServicesContext';
import { EmptyState } from '../../shared/components/EmptyState'; import { EmptyState } from '../../shared/components/EmptyState';
import { RouteLink } from '../../app/routing/RouteLink';
import { ContextMenu, IContextMenuItem, IMenuAnchor } from '../_tree/ContextMenu'; import { ContextMenu, IContextMenuItem, IMenuAnchor } from '../_tree/ContextMenu';
import { TreePageHeader } from '../_tree/TreePageHeader'; import { TreePageHeader } from '../_tree/TreePageHeader';
import { flattenVisible, toggleId } from '../_tree/treeRules'; import { flattenVisible, toggleId } from '../_tree/treeRules';
@@ -28,9 +29,11 @@ const MENU_OFFSET_PX = 4;
interface Props { interface Props {
objectId: string; objectId: string;
/** Для ссылки «← К объектам» — объекты того же проекта. */
projectId: string | undefined;
} }
export const WorksPageContent: React.FC<Props> = ({ objectId }) => { export const WorksPageContent: React.FC<Props> = ({ objectId, projectId }) => {
const services = useAppServices(); const services = useAppServices();
const repository = React.useMemo( const repository = React.useMemo(
() => () =>
@@ -112,6 +115,9 @@ export const WorksPageContent: React.FC<Props> = ({ objectId }) => {
return ( return (
<div className={styles.page}> <div className={styles.page}>
<RouteLink className={styles.backLink} to={{ page: 'objects', projectId }}>
{WORKS_TEXTS.backToObjects}
</RouteLink>
<TreePageHeader icon="clipboard" title={data.headerLabel} /> <TreePageHeader icon="clipboard" title={data.headerLabel} />
<div className={styles.container}> <div className={styles.container}>
{data.canEdit && <div className={styles.toolbar}>{addButton(WORKS_TEXTS.addWork)}</div>} {data.canEdit && <div className={styles.toolbar}>{addButton(WORKS_TEXTS.addWork)}</div>}
@@ -2,6 +2,7 @@
export const WORKS_TEXTS = { export const WORKS_TEXTS = {
defaultHeader: 'ОБЪЕКТЫ ПРОЕКТА', defaultHeader: 'ОБЪЕКТЫ ПРОЕКТА',
backToObjects: '← К объектам',
addWork: 'Добавить работу', addWork: 'Добавить работу',
addFirst: '+ Добавить работу', addFirst: '+ Добавить работу',
columns: { columns: {