Перенос, декомпозиция и перекраска форм CT/KPS/OID на @tnsu/ui-kit, config-driven дашборд-реестр по трём типам документов. Из отслеживания исключены артефакты сборки (lib-commonjs/jest-output/release) — забыты в .gitignore ранее.
19 KiB
CT — перенос в ct-forms-portal (Фаза 3)
Порядок (утверждён): Этап 1 перенос 1:1 → Этап 2 декомпозиция под структуру KPS → Этап 3 перекраска на ui-kit.
Правило: сохранить 100% поведения; build после каждого этапа. Эталон структуры — forms/kps/.
Связано: docs/REPAINT-MAP.md (перекраска), docs/BEHAVIORS.md.
Источник: ct-create-form/src/webparts/ctCreateForm/. CT = 6953 стр, god-компоненты.
Этап 1 — перенос 1:1 — ✅ ЗАВЕРШЁН (heft build зелёный)
- ✅ Скопированы
components/иservices/→forms/ct/{components,services}/(17 файлов, 1:1). - ✅ Правки для сборки в портале (минимум, поведение не менялось):
CtService: конструктор(context, siteUrl?),baseUrl = siteUrl ?? absoluteUrl(как KPS).kpFolderтоже параметризован черезsiteUrl(было жёстко наcontext.pageContext.web.serverRelativeUrl).ICtCreateFormProps+siteUrl?;CtCreateForm→new CtService(context, siteUrl).- Web-part-специфичных зависимостей (loc strings) в components/services не было — ничего убирать не пришлось.
- ✅ Обвязка портала:
ctDocumentConfig.ts:inPortal: true+buildInPortalParams: (row) => ({ [row.status==='Черновик'?'ctId':'ctid']: row.id })(сверено сuseCtForm.ts— читает именноctId/ctid, совпало 1:1). siteUrl уже/sites/sed.CtFormsPortal.tsx: веткаform==='ct'→<CtCreateForm .../>+ «← К реестру» (по образцу KPS-ветки).
- ✅
heft buildзелёный.
Открытие при переносе: CT уже частично зависел от @tnsu/ui-kit@^0.4.0 — 3 файла
(Step1PositionSelection.tsx, Step2CommercialOffers.tsx, CurrencyRatesForm.tsx) уже используют
Button/Alert из кита. API совпадает 1:1 с текущим 0.11.0 (variant="secondary"/"accent", Alert
variant="err") — конфликтов не было, работает как есть. Ускорит Этап 3.
Этап 2 — декомпозиция (карта резки god-компонентов)
Статус: [x] Step2CommercialOffers ✅ | [x] Step4Approval ✅ | [~] Step3ComparisonTable (в работе)
[~] Step3ComparisonTable (2217) — В РАБОТЕ, по чекпоинтам
- ✅ CP1 согласование (build ок):
useStep3Approval.ts(голосование/делегат, 1:1) +InlineApprovalChain.tsx(вью цепочки + диалоги решение/делегат + баннер notifyWarning; хелперы APPROVAL_STATUS_*). Контейнер 2217→1918. - ✅ CP2 AI/PDF (build ок):
useAiComment.ts(aiComment/isAiLoading/aiError/isPdfLoading/showAiPromptDialog + handleAiComment/handleGeneratePdfReport/handleDeleteAiComment + loadCtComment-effect + decodeHtmlEntities, buildPayload передаётся аргументом из контейнера — матричные данные не копируются в хук) +AiCommentBlock.tsx(только блок отображения, диалог-промпт остался в контейнере — как у KPS). PDF-ошибка идёт через колбэкonPdfErrorв общийsaveError(сохранили родной баннер). - ✅ CP3 хелперы/типы (build ок): типы (ExtraSupplier/ExtraPosition/PositionRow/CellEdit/EditableOffers) →
matrixTypes.ts; константы (SUPPLIER_STATUS_OPTIONS/DELIVERY_TYPE_OPTIONS) + чистые ф-ции (formatKzt/Num/Qty/round2Str/getSubCols/computeOffer/buildOfferKey) →matrixHelpers.ts.extraIdCounter(мутабельный) оставлен в контейнере — уедет вместе с CP4. - Контейнер после CP1-3: 2217 → 1735 строк (−22%).
- ✅ CP4 ядро матрицы (build ок): весь стейт/рефы(~15)/эффекты(loadCriteria/loadOffers/refs-sync/beforeunload/
unmount-persist)/мемо(suppliersWithOffer/allPositions/supplierCurrencies/computedOffers/minTotalByPosition/
recommendedSupplierId)/все update*/add*/delete*-хендлеры/handleSave →
useStep3Matrix.ts(856, перенос ВЕРБАТИМ). В контейнере — деструктуризация результата, поэтому render (984) НЕ менялся.CriteriaEntryпереехал в matrixTypes (общий). approval+ai хуки остались в контейнере (берут значения из деструктуризации). - Контейнер: 2217 → 984 строки (−56%). Логика матрицы вся в хуке. Этап 2 для CT ЗАВЕРШЁН.
- ✅ CP4 happy-path проверен в workbench: полный проход по всем 4 шагам (создание СТ → загрузка КП → матрица → согласование) прошёл без ошибок. Основной риск (грубый регресс/краш) снят. ⚠️ Не проверены детально: bundle-строки (комплект), перевод ед. изм. (тумблер), доп.расходы/логистика, F5 (beforeunload-persist), критерии/AI-комментарий, делегат/замена в согласовании. Смотреть при случае, не блокирует дальнейшую работу.
- ⏭️ CP4 матрица-ядро (САМЫЙ РИСК): ~15 рефов + эффекты (loadCriteria/loadOffers/beforeunload/unmount-persist) +
мемо (suppliersWithOffer/allPositions/supplierCurrencies/computedOffers/minTotalByPosition/recommendedSupplierId) +
все update*/add*/delete*-хендлеры + handleSave →
useStep3Matrix.ts(перенос ВЕРБАТИМ, не переписывать!). ⚠️ Клубок рефов; компилятор не ловит регресс поведения. ЖЕЛАТЕЛЬНО делать при возможности workbench-теста (после провижининга списков). Рендер таблицы (thead/tbody/итоги/критерии) дробить на ComparisonMatrix/ MatrixRowView/OfferCells/CriteriaTable/AddExtraRow — на Этапе 3 вместе с перекраской. Метод: чисто механический перенос блоков (логику не трогать), Fluent оставляем (перекраска — Этап 3), build после каждого god-компонента. Уточнённая граница Этап2/Этап3: Этап 2 = вынос ЛОГИКИ (хуки/persist), «раз-god-ивание». Финальное дробление оставшейся ВЬЮХИ на под-компоненты (диалоги/списки) + размеры <200 — на Этапе 3 вместе с перекраской (диалоги всё равно → ui-kit Dialog), чтобы не трогать файлы дважды.
✅ Step4Approval (886) — СДЕЛАНО (build ок)
886 → useStep4Approval.ts (вся логика: chain-ops, add/delete/replace, handleActionConfirm, send/incore/restart,
производные флаги + удобные методы selectAddSuggestion/cancelAddRow/openReplace/…) + view Step4Approval.tsx
(~370, только разметка + helpers STATUS_LABELS/getStatusClass/formatDate; Fluent). Вьюху добьём на Этапе 3.
✅ Step2CommercialOffers (597) — СДЕЛАНО (build ок, 2 чекпоинта)
597 → контейнер Step2CommercialOffers.tsx (~155) + kpTypes.ts + useKpProcessing.ts (конвейер Syntex/Flow)
step2Persist.ts(handleSave→функция, возвращает patch) + вьюхиSuppliersWithoutKp.tsx(владеет add-стейтом) /UploadedKpList.tsx. Одно семантич. уточнение: в persistformDataRef.current→formData(в момент save совпадают).
Step3ComparisonTable.tsx (2217) → по образцу Step3BuildCt/* + отдать approval в Step4
| Секции CT (строки) | Куда (аналог KPS) |
|---|---|
| 25–179 типы/хелперы/формат | types/domain.ts, utils/format.ts, useStep3Matrix.ts |
| 196–435 стейт матрицы | useStep3Matrix.ts |
| 285–394 approval-хендлеры | → Step4 useStep4Approval.ts |
| 396–405, 947–1017 AI/PDF | useAiComment.ts + AiCommentBlock.tsx |
| 439–604 useEffect загрузка/persist | step3Persist.ts + useStep3Matrix.ts |
| 606–706 useMemo производные | useStep3Matrix.ts |
| 708–789 редактируемые ячейки | OfferCells.tsx |
| 791–945 хендлеры строк | AddExtraRow.tsx + useStep3Matrix.ts |
| 1019–1193 handleSave | step3Persist.ts |
| 1197–1239 тулбар + тумблер ед.изм. | Step3BuildCt.tsx (+ доменное unitConversion) |
| 1241–1337 thead | ComparisonMatrix.tsx |
| 1339–1806 tbody + итоги | MatrixRowView.tsx + OfferCells.tsx + ComparisonMatrix.tsx |
| 1807–1864 инлайн-добавление | AddExtraRow.tsx |
| 1865–2029 критерии + AI + PDF | CriteriaTable.tsx + AiCommentBlock.tsx |
| 2030–2114 инлайн-цепочка (Teams) | → Step4 InlineApprovalChain.tsx |
| 2115–2211 диалоги (делегирование/решение) | ui-kit Dialog в Step4Approval.tsx |
Step4Approval.tsx (886) → useStep4Approval.ts + Step4Approval.tsx + InlineApprovalChain.tsx
(стейт+манипуляции цепочкой 94–352, handleActionConfirm/Send/Incore/Restart 239–474 → хук; render 476–763; диалоги 764–885 → ui-kit Dialog)
Step2CommercialOffers.tsx (597) → useKpProcessing.ts/kpPipeline.ts/kpOffers.ts/step2Persist.ts + view (Step2LoadKp,KpFileList,CurrencyRatesForm,SuppliersWithoutKp,UploadedKpList)
CtService.ts (1532) — ввести siteUrl? (крит.) + при желании обобщённые CRUD-примитивы как в KPS. Создать common/* (StepShell/FormHeader/Pill) + единый StepProps.
Доменные отличия CT (НЕ терять при декомпозиции!)
- Шаг 1 — из SP-списка (
fetchRequests(days)), не из TNSU API (KPS). - Колонки позиций: disciplineCode (марка), smrType (SMR), agskCode, uniqueCode, organization.
CT.number— строковый,generateCtNumber(projectName)(per-project).utils/unitConversion.ts— пересчёт в ед. изм. заявки (тумблер) — нет в KPS.SUPPLIER_STATUS_OPTIONS(Завод/Дистрибьютор…) — нет в KPS.- CurrencyRate/SupplierOffer — иные поля (rateToKzt; deliveryCostKzt/additionalCostsKzt/totalWithExtraKzt/pricePerUnitKzt).
getCurrentUserCompany()==='astel-k'→isRestrictedView(скрытие цен).
Этап 3 — перекраска (карта A/B/C из REPAINT-MAP)
Fluent в CT: PrimaryButton/DefaultButton→Button, TextField→TextInput/TextArea, MessageBar→Alert, IconButton/Icon, Spinner→Spinner, Dialog→ui-kit Dialog, Checkbox→Checkbox, статусы→Pill/Badge. Особые: Toggle (пересчёт ед.изм.) и NormalPeoplePicker (делегирование) — прямых аналогов в ките нет: Toggle → ui-kit Toggle (есть!); people picker → TextInput + searchUsers()+suggestions (как KPS Step4).
✅✅ Этап 3 ЗАВЕРШЁН (механическая перекраска) — Fluent полностью удалён из CT (0 импортов @fluentui
во всей forms/ct/), heft build ожидается пользователем.
- Все 12 файлов с Fluent переведены на
@tnsu/ui-kit: RequestsTable/FileUploadArea/UploadedKpList (Checkbox/IconButton), SuppliersWithoutKp/CurrencyRatesForm/Step1PositionSelection/ Step2CommercialOffers/AiCommentBlock (TextInput/Spinner/Alert/IconButton/FormField), useStep3Approval/InlineApprovalChain/Step4Approval (делегат/замена — NormalPeoplePicker заменён на паттерн KPS: query+debounce(300ms)+suggestions+select,useStep4Approval/useStep3ApprovalполучилиhandleAddQueryChange(val)/setDelegateQuery(val)вместо Fluent-сигнатуры (event, val)), и главный контейнерStep3ComparisonTable.tsx(984 строки, вся матрица/критерии/футер/AI-диалог). - Правило замен применено:
TextField→TextInput/TextArea(multiline→TextArea rows=1, автовысоты нет — принято как в KPSCriteriaTable); безclassName→обёрнуто в<div>;Toggleбезlabel→ обёрнут в<label>вручную (span рядом); иконки Fluent→спрайт (Delete→trash, Cancel→close, Add→plus, Accept/CheckMark→check, ChevronLeft→arrow-left, PDF→document, Forward→chevron-right, AddFriend/Switch→plus/swap, DoubleChevron*→chevron-left/right повторно, Lightbulb→без иконки). - SCSS: все
:global(.ms-TextField-*)-селекторы (таргетили Fluent DOM) заменены наinput/textarea(таргетят нативный тег внутри обёртки ui-kit — рабочий приём, т.к. хэши классов ui-kit непредсказуемы). - ⚠️ Осталось на будущее (сознательно НЕ делали сейчас): финальное дробление
Step3ComparisonTable.tsxrender на под-компонентыComparisonMatrix/OfferCells/MatrixRowView/AddExtraRow/CriteriaTableпо образцу KPSStep3BuildCt/*. Причина отказа сейчас: KPS-хукuseStep3Matrixдаёт чистый API (matrix.rows/matrix.rateOf/matrix.editNumber...), а CT-хукuseStep3Matrix(856 строк, CP4) перенесён ВЕРБАТИМ с сырыми именами (updateEdit/updatePriceKzt...) и НЕ верифицирован в runtime — редизайн его публичного API сейчас добавил бы риск поверх уже непроверенного риска. Делать этот шаг ТОЛЬКО после workbench-теста CP4 (см. ниже), отдельным заходом, вместе с рефакторингом API хука под форму KPS. - ✅ Workbench happy-path пройден (все 4 шага, создание→согласование, без ошибок) — основной риск CP4+перекраски снят. Не проверены детально: bundle-строки, Toggle перевода ед.изм., доп.расходы/логистика, критерии/AI, делегат/замена в согласовании, F5-persist. Смотреть по возможности, не блокирует дальнейшую работу.
- Отдельно найден и починен степпер (
Breadcrumbs.tsx) — жил вне грепа по@fluentui(свой хендрол на Fluent-синих литералах без Fluent-импорта), переведён на адаптерStepper+FormHeader+Badge(как KPS). - ✅✅ Полный проход по литералам-цветам ЗАВЕРШЁН (весь набор Fluent-палитры, не только синий):
создан мост
forms/ct/components/common/_theme.scss(точное зеркалоforms/kps/.../common/_theme.scss, тот же маппинг: $accent/$accent-bg/$accent-border/$accent-dark/$accent-hover ← Fluent-синий, $text/$muted/$muted-2/$border/$border-strong/$head-bg/$hover/$surface ← Fluent-серый, $ok/$ok-bg/$danger/$danger-bg/$warn-fg/$warn-bg ← Fluent-статусы). Импорт@import '../common/theme'добавлен в 9 файлов (Breadcrumbs, CtCreateForm, RequestsTable, Step1PositionSelection, CurrencyRatesForm, FileUploadArea, Step2CommercialOffers, Step3ComparisonTable, Step4Approval) — bulk sed-заменой всех Fluent hex-литералов на семантические переменные (~150+ подстановок). Один найденный баг при массовой замене: вCtCreateForm.module.scssесть SPFx-плейсхолдер темы"[theme:bodyText, default: #hex]"— это НЕ SCSS-код, а строка, которую парсит SPFx-лоадер во время сборки; sed случайно подставил туда$textвместо литерала — исправлено обратно на реальный hex (#111827, эквивалент$gray-900). Оставлены как есть (сознательно, вне палитры Fluent): dark-theme цвета (#1b1a19/#252423), один#fefefe(незначим). - Отдельно найден и починен степпер (
Breadcrumbs.tsx) — жил вне грепа по@fluentui(свой хендрол на Fluent-синих литералах без Fluent-импорта), переведён на адаптерStepper+FormHeader+Badge(как KPS). - Точечные UX-правки после визуальной проверки пользователем: степпер сужен до
30vw(обёртка.stepperWrap, прижат влево, откат на 100% ширины ниже$bp-md) — применено и в CT, и в KPS; подсветка «выбран поставщик» (.colSelected) переведена с$warn-bg(семантически неверно — «предупреждение») на полупрозрачную золотую заливкуrgba($gold-500, 0.02); заливка строк Логистика/Доп.расходы (.extraRow) убрана полностью (были на$warn-bg, читались слишком ярко).
✅✅✅ ФОРМА CT ПОЛНОСТЬЮ ЗАВЕРШЕНА
Этап 1 (перенос) → Этап 2 (декомпозиция, включая рискованный CP4) → Этап 3 (перекраска компонентов + полный проход по цветовым токенам + финальное дробление render Step3ComparisonTable) — всё сделано, собрано и подтверждено пользователем в workbench (полный проход по 4 шагам после каждого крупного этапа). Дальше по плану — OID, тем же маршрутом: перенос 1:1 → декомпозиция под структуру KPS → перекраска.