docs: add porting guide and shared Dataverse helpers

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>
This commit is contained in:
Тимур Городецкий
2026-10-15 16:50:54 +05:00
parent bed230f045
commit 11bf491095
2 changed files with 116 additions and 0 deletions
+54
View File
@@ -0,0 +1,54 @@
# Как переносится раздел из 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 ошибок линтера и все тесты зелёные.