feat: port stroy-bot-project-assigner as resources page

Add the "resources" section (?page=resources&projectId=): professions and
companies assigned to a project, with the same lists, fields, texts and
optimistic add/remove with rollback as the legacy web part.

PnPjs is replaced by SharePoint REST through the app's IHttpClient so the
bundle needs no new dependency: the same $select/$expand/$filter, PnP paging
replaced by following odata.nextLink, adds as POST to items with the same
body, deletes as POST with X-HTTP-Method DELETE and IF-MATCH *. Known legacy
edge cases (temporary negative id) are kept and listed in the checklist.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Тимур Городецкий
2026-10-15 17:18:19 +05:00
parent 11bf491095
commit 55ce772eaa
15 changed files with 1083 additions and 0 deletions
+9
View File
@@ -201,6 +201,15 @@
- [ ] Оптимистичное добавление / удаление с откатом и ошибкой
- [ ] На узких экранах колонки друг под другом
🐞 Удаление ещё не сохранённой записи (временный отрицательный id) уходит на сервер, падает и откатывается с ошибкой. 🐞 Если запись удалили до ответа на добавление, она пропадает из списка, хотя на сервере создана. 🐞 Два добавления в одну миллисекунду получают одинаковый временный id.
**Сознательные отличия от assigner:**
- PnPjs заменён на SharePoint REST с теми же `$select` / `$expand` / `$filter`. Постраничная загрузка PnP (`for await`) → проход по `@odata.nextLink` / `odata.nextLink` до конца (без `$top`, страницы по умолчанию — 100).
- Добавление: `POST …/items` с тем же телом (`Title`, `projectIdId`, `professionIdId` / `companyIdId`), заголовки `Accept` и `Content-Type: application/json;odata=nometadata` + пустой `odata-version` (как в binder). Удаление: `POST …/items({id})` с `X-HTTP-Method: DELETE` и `IF-MATCH: *` — так удаляет сам PnP.
- Текст после префикса ошибки («Ошибка загрузки данных: …» и т.п.) — сообщение `HttpError` (`{status} {statusText}: {ответ сервера}`), а не формат ошибки PnP.
- Счётчик во вкладке — часть подписи («Профессии (0)»): `count` в Tabs ui-kit скрывает ноль.
- Кнопки «+» / «−» — `Button` ui-kit (с подсказками «Добавить» / «Удалить»), сообщение об ошибке закрывается крестиком рядом с `Alert`.
---
## 8. Привязка к справочнику (stroy-bot-projects-binder) — `?page=binder&projectId=`