11bf491095
Common rules for moving the remaining stroy-bot-* sections into the monorepo, so every section follows the same structure and keeps 1:1 behaviour with its old web part. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
5.7 KiB
5.7 KiB
Как переносится раздел из stroy-bot-* в монорепо
Образец — главная страница: src/webparts/stroyBot/pages/hub/ + app/project/.
Главное правило
Поведение 1:1 со старым web part. Те же запросы (URL, $select, $filter, $expand, $top, $orderby), те же поля, те же правила доступа, те же тексты (дословно), те же валидации. Известные баги переносятся как есть. Любое сознательное отличие записывается в docs/MIGRATION-CHECKLIST.md в блок «Сознательные отличия».
Меняется только слой интерфейса: HTML-строки и innerHTML → React-компоненты на @tnsu/ui-kit.
Структура раздела
pages/<раздел>/
<Раздел>Page.tsx — страница: собирает компоненты, обрабатывает loading / error / empty
<Раздел>Page.module.scss
texts.ts — ВСЕ пользовательские тексты раздела (дословно из старого кода)
<раздел>Types.ts — типы данных
<раздел>Repository.ts — запросы: функции-конструкторы URL + функции загрузки/записи
<раздел>Repository.test.ts — тесты URL и сценариев на fakeHttpClient
<раздел>Rules.ts — чистые функции (права, валидация, дерево, форматирование)
<раздел>Rules.test.ts
use<Что-то>.ts — хуки состояния (загрузка, сохранение)
<Компонент>.tsx — под-компоненты, один компонент — один файл
Правила кода (стайл-гайд проекта)
- TypeScript строго, без
any. Ответы сервера описываются интерфейсами. - Компонент ≤ ~300 строк, функция ≤ ~50 строк. Больше — разбивать.
- Логика — в
*Rules.ts/*Repository.ts/ хуках, не в JSX. - Имена списков —
LISTSизconfig/lists.ts; таблицы Dataverse —DV_TABLESизconfig/dataverse.ts; адреса — изuseAppServices().settings. - Внутренние имена полей SharePoint / колонок Dataverse — константами в
*Repository.tsраздела (схемы в разных старых репо отличаются — не унифицировать без проверки). - Комментарии — «почему», а не «что». Без мёртвого кода.
nullв своих типах не использовать (линтер) —undefined. Внешние ответы сnullприводить через?? undefined.- Стили: SCSS-модули,
@import '../../../../styles/design-tokens';, токены вместо цветов. Без magic numbers без комментария. - Форматирование —
.prettierrc(одинарные кавычки, 120 символов, без висячих запятых).
Данные
- Клиенты:
const { sharePoint, dataverse, tnsuApi, settings, page } = useAppServices(); - SharePoint:
shared/sharepoint/spRest.ts(listItemsUrl,getJson,fetchCurrentUserId). Запись —sharePoint.fetch(url, { method: 'POST', headers, body })с теми же заголовками, что в старом коде (verbose__metadata/X-HTTP-Method: MERGE/IF-MATCH— как было). - Dataverse:
shared/dataverse/dataverseRest.ts(dataverseUrl,dataverseGet/Post/Patch/Delete). - Корпоративный API:
tnsuApi.fetch(${settings.apiBaseUrl}/...). - Текущий пользователь:
page.userId(legacyPageContext.userId) илиfetchCurrentUserId— как в старом коде раздела. - Маршрут:
useRouter()→route.projectId,route.objectId,route.reportId,route.copyFromId; переход —navigate({ page, projectId, ... }); ссылка —<RouteLink to={...}>. - Ссылки старых web parts на другие страницы (
SendReport.aspx?...,worksPageUrl) →navigate/RouteLinkна раздел приложения.
UI
- ui-kit:
Button,IconButton,Dialog,confirmModal,Alert,Badge,Spinner,TextInput,TextArea,Select,Checkbox,Tabs,DataTable,FormCard,FormField,FormGrid,FormActions,FormHeader,Icon(имена —ICON_NAMESв ките). alert()/confirm()→Alert/confirmModal(тексты те же).- Чего нет в ките (дерево, тосты, контекстное меню, хлебные крошки) — делать в
pages/<раздел>/своего раздела. Существующие файлы вshared/не менять;EmptyStateиuseOutsideClose— переиспользовать. - Всегда явные состояния: загрузка (
Spinner), ошибка (Alert variant="err"), пусто (EmptyState).
Тесты
shared/testing/fakeHttpClient.ts— заглушка: проверяем точные URL и тела запросов против старого кода, сценарии успеха и ошибок.- Чистые функции правил — отдельными тестами.
- Запуск:
npx heft test --clean. Должно быть 0 ошибок линтера и все тесты зелёные.