diff --git a/docs/prod-project-card-port.md b/docs/prod-project-card-port.md new file mode 100644 index 000000000..042b7c860 --- /dev/null +++ b/docs/prod-project-card-port.md @@ -0,0 +1,79 @@ + + +# Выборочный перенос финальных карточек проектов на PROD + +База master: `3890ee6ccb84bf92d215ea32b4316e3f52f1d404`. +Финальный DEV source: `683da4b9b30334bab4bd6c7a1afea3ddc91fe9ad`. + +| DEV PR | Merge SHA | Назначение | +| -------------------------------------------------------------- | ------------------------------------------ | ------------------------------- | +| [#357](https://github.com/PROCOLLAB-github/procollab/pull/357) | `918e30d54b3240078f8dda43c0fbc5761c011ae6` | Карточка и lifecycle | +| [#358](https://github.com/PROCOLLAB-github/procollab/pull/358) | `1b92bf0e8e05f1edd906195770ca8fa46ab8d95a` | Общие поверхности списков | +| [#359](https://github.com/PROCOLLAB-github/procollab/pull/359) | `ec822d13b4f55b0718335ac7f0f9e64d69ed05da` | Роль и доступ | +| [#360](https://github.com/PROCOLLAB-github/procollab/pull/360) | `358e818c7ebd8b7d5916e56167a402e2848177d6` | Единый CTA | +| [#361](https://github.com/PROCOLLAB-github/procollab/pull/361) | `69b37d12000b22fd09b77b5a35d95812bf6fbda5` | Независимость lifecycle от роли | +| [#362](https://github.com/PROCOLLAB-github/procollab/pull/362) | `683da4b9b30334bab4bd6c7a1afea3ddc91fe9ad` | Защита неполного контракта | + +## Состав переноса + +Переносятся конечные изменения InfoCard, Dashboard/DashboardItem, ProjectsList, +адаптивной сетки и project-card контейнера ProgramList. Для этих 20 файлов +сравнены PROD master и DEV-база до #357 (`42cbdd65117cc56beaa6069bcc061192df7733ce`): +различие только в порядке двух SCSS-свойств. Поэтому итоговое содержимое выбранных +файлов совместимо с PROD без переноса остальных DEV-изменений. + +Архивные макеты, промежуточные варианты и DEV merge commits не переносятся. +PROD editor, detail resolver, оценивание, прочие сервисы, React, workflows, +dependencies и test harness остаются на master-реализации. + +## Инварианты + +- Карточка 156 × 180 px, аватар 70 px; название и описание по центру, до двух строк. +- Lifecycle: submitted > draft > program > published, независимо от пользователя. +- Роль берётся из `Project.leader` и `ProfileInfoService.profile()?.id`. +- Редактирование обозначается только лидеру без связи или с явным `isSubmitted === false`. + Неизвестный submission state даёт «только просмотр». +- CTA «Открыть» ведёт в detail; одна ссылка охватывает карточку и CTA. + Подписка — отдельная кнопка вне ссылки; двойной навигации нет. +- Dashboard и полный список используют my/subs/base; all/subscriptions показывают + отрасль и не получают lifecycle/роль собственного проекта. +- Приглашения сохраняют принятие/отклонение и идентичность по inviteId. +- Черновик серый, опубликованный зелёный, программа lilac/accent, сданный gold. + +## Контракт и приёмка + +Нужен backend port DEV #748: `partner_program` содержит `id`, `name`, +`program_link_id`, `program_id`, `is_submitted` той же min-PK связи, что в detail +для лидера/участника. Backend следует развернуть первым после отдельного разрешения. + +Интеграционный тест передаёт сокращённый snake_case HTTP payload через настоящий +CamelcaseInterceptor, ApiService, adapter, repository и use case в InfoCard. +Проверяются сданный проект, неизвестное состояние, восемь сочетаний lifecycle/роли, +контексты Dashboard/List, маршруты, подписки и приглашения. + +Проверки выполняются на PROD-ветке: targeted, полный `npm run test:ci`, format, +lint, scoped Stylelint, `build:prod`, diff-check. В master уже установлен `pool: forks`; +порт не меняет эту настройку и не подавляет ошибки. + +Браузерный smoke использует локальную сборку настоящих компонентов с фикстурами, +без обращений к DEV/PROD и пользовательским данным. Он не заменяет авторизованную +live-проверку после отдельно разрешённого deploy. Здесь создаётся только Draft PR. + +## Локальный visual smoke + +Измерены reference, Dashboard и полные my/subscriptions/all при viewport 1440 × 900, +а также my с длинными строками при 390 × 844 и 320 × 844 (DPR 1). +Во всех случаях карточки 156 × 180 px, аватары 70 × 70 px; горизонтального overflow +и вложенных интерактивных элементов в project link нет. Восьми сочетаниям +lifecycle/роли соответствуют одинаковые подписи в Dashboard и полном списке. + +Tab выделяет следующую ссылку рамкой 2 px; Enter показывает detail-placeholder +проекта 102. Это локальный TestBed-маршрут, не live detail. Console: ошибок нет, +есть предупреждение NG0912 о двух IconComponent в preview. Подписки и приглашения +дополнительно проверены компонентными тестами с настоящими DOM-действиями. + +Замеры: [geometry.json](prod-project-cards/geometry.json). + +![Восемь состояний](prod-project-cards/eight-states.png) + +![Длинные строки, 390 px](prod-project-cards/my-mobile-long.png) diff --git a/docs/prod-project-cards/eight-states.png b/docs/prod-project-cards/eight-states.png new file mode 100644 index 000000000..4ca9bd010 Binary files /dev/null and b/docs/prod-project-cards/eight-states.png differ diff --git a/docs/prod-project-cards/geometry.json b/docs/prod-project-cards/geometry.json new file mode 100644 index 000000000..37ba49442 --- /dev/null +++ b/docs/prod-project-cards/geometry.json @@ -0,0 +1,958 @@ +{ + "reference": { + "cards": [ + { + "access": "можно редактировать", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/101", + "nested": 0, + "role": "Лидер", + "status": "Черновик", + "statusBackground": "rgb(249, 249, 249)", + "width": 156 + }, + { + "access": "можно редактировать", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/102", + "nested": 0, + "role": "Лидер", + "status": "Опубликован", + "statusBackground": "rgb(227, 240, 232)", + "width": 156 + }, + { + "access": "можно редактировать", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/103", + "nested": 0, + "role": "Лидер", + "status": "В программе", + "statusBackground": "rgb(232, 224, 250)", + "width": 156 + }, + { + "access": "только просмотр", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/104", + "nested": 0, + "role": "Лидер", + "status": "Сдан в программу", + "statusBackground": "rgb(253, 248, 240)", + "width": 156 + }, + { + "access": "только просмотр", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/107", + "nested": 0, + "role": "Участник", + "status": "Черновик", + "statusBackground": "rgb(249, 249, 249)", + "width": 156 + }, + { + "access": "только просмотр", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/108", + "nested": 0, + "role": "Участник", + "status": "Опубликован", + "statusBackground": "rgb(227, 240, 232)", + "width": 156 + }, + { + "access": "только просмотр", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/105", + "nested": 0, + "role": "Участник", + "status": "В программе", + "statusBackground": "rgb(232, 224, 250)", + "width": 156 + }, + { + "access": "только просмотр", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/106", + "nested": 0, + "role": "Участник", + "status": "Сдан в программу", + "statusBackground": "rgb(253, 248, 240)", + "width": 156 + } + ], + "overflow": false, + "viewport": { + "dpr": 1, + "height": 900, + "width": 1440 + } + }, + "dashboard": { + "cards": [ + { + "access": "можно редактировать", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/101", + "nested": 0, + "role": "Лидер", + "status": "Черновик", + "statusBackground": "rgb(249, 249, 249)", + "width": 156 + }, + { + "access": "можно редактировать", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/102", + "nested": 0, + "role": "Лидер", + "status": "Опубликован", + "statusBackground": "rgb(227, 240, 232)", + "width": 156 + }, + { + "access": "можно редактировать", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/103", + "nested": 0, + "role": "Лидер", + "status": "В программе", + "statusBackground": "rgb(232, 224, 250)", + "width": 156 + }, + { + "access": "только просмотр", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/104", + "nested": 0, + "role": "Лидер", + "status": "Сдан в программу", + "statusBackground": "rgb(253, 248, 240)", + "width": 156 + }, + { + "access": "только просмотр", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/107", + "nested": 0, + "role": "Участник", + "status": "Черновик", + "statusBackground": "rgb(249, 249, 249)", + "width": 156 + }, + { + "access": "только просмотр", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/108", + "nested": 0, + "role": "Участник", + "status": "Опубликован", + "statusBackground": "rgb(227, 240, 232)", + "width": 156 + }, + { + "access": "только просмотр", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/105", + "nested": 0, + "role": "Участник", + "status": "В программе", + "statusBackground": "rgb(232, 224, 250)", + "width": 156 + }, + { + "access": "только просмотр", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/106", + "nested": 0, + "role": "Участник", + "status": "Сдан в программу", + "statusBackground": "rgb(253, 248, 240)", + "width": 156 + }, + { + "access": null, + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/201", + "nested": 0, + "role": null, + "status": null, + "statusBackground": null, + "width": 156 + }, + { + "access": null, + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/202", + "nested": 0, + "role": null, + "status": null, + "statusBackground": null, + "width": 156 + }, + { + "access": null, + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/203", + "nested": 0, + "role": null, + "status": null, + "statusBackground": null, + "width": 156 + }, + { + "access": null, + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/204", + "nested": 0, + "role": null, + "status": null, + "statusBackground": null, + "width": 156 + }, + { + "access": null, + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/201", + "nested": 0, + "role": null, + "status": null, + "statusBackground": null, + "width": 156 + }, + { + "access": null, + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/202", + "nested": 0, + "role": null, + "status": null, + "statusBackground": null, + "width": 156 + }, + { + "access": null, + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/203", + "nested": 0, + "role": null, + "status": null, + "statusBackground": null, + "width": 156 + }, + { + "access": null, + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/204", + "nested": 0, + "role": null, + "status": null, + "statusBackground": null, + "width": 156 + } + ], + "overflow": false, + "viewport": { + "dpr": 1, + "height": 900, + "width": 1440 + } + }, + "myDesktop": { + "cards": [ + { + "access": "можно редактировать", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/101", + "nested": 0, + "role": "Лидер", + "status": "Черновик", + "statusBackground": "rgb(249, 249, 249)", + "width": 156 + }, + { + "access": "можно редактировать", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/102", + "nested": 0, + "role": "Лидер", + "status": "Опубликован", + "statusBackground": "rgb(227, 240, 232)", + "width": 156 + }, + { + "access": "можно редактировать", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/103", + "nested": 0, + "role": "Лидер", + "status": "В программе", + "statusBackground": "rgb(232, 224, 250)", + "width": 156 + }, + { + "access": "только просмотр", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/104", + "nested": 0, + "role": "Лидер", + "status": "Сдан в программу", + "statusBackground": "rgb(253, 248, 240)", + "width": 156 + }, + { + "access": "только просмотр", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/107", + "nested": 0, + "role": "Участник", + "status": "Черновик", + "statusBackground": "rgb(249, 249, 249)", + "width": 156 + }, + { + "access": "только просмотр", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/108", + "nested": 0, + "role": "Участник", + "status": "Опубликован", + "statusBackground": "rgb(227, 240, 232)", + "width": 156 + }, + { + "access": "только просмотр", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/105", + "nested": 0, + "role": "Участник", + "status": "В программе", + "statusBackground": "rgb(232, 224, 250)", + "width": 156 + }, + { + "access": "только просмотр", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/106", + "nested": 0, + "role": "Участник", + "status": "Сдан в программу", + "statusBackground": "rgb(253, 248, 240)", + "width": 156 + } + ], + "overflow": false, + "viewport": { + "dpr": 1, + "height": 900, + "width": 1440 + } + }, + "subscriptions": { + "cards": [ + { + "access": null, + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/201", + "nested": 0, + "role": null, + "status": null, + "statusBackground": null, + "width": 156 + }, + { + "access": null, + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/202", + "nested": 0, + "role": null, + "status": null, + "statusBackground": null, + "width": 156 + }, + { + "access": null, + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/203", + "nested": 0, + "role": null, + "status": null, + "statusBackground": null, + "width": 156 + }, + { + "access": null, + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/204", + "nested": 0, + "role": null, + "status": null, + "statusBackground": null, + "width": 156 + } + ], + "overflow": false, + "viewport": { + "dpr": 1, + "height": 900, + "width": 1440 + } + }, + "all": { + "cards": [ + { + "access": null, + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/201", + "nested": 0, + "role": null, + "status": null, + "statusBackground": null, + "width": 156 + }, + { + "access": null, + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/202", + "nested": 0, + "role": null, + "status": null, + "statusBackground": null, + "width": 156 + }, + { + "access": null, + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/203", + "nested": 0, + "role": null, + "status": null, + "statusBackground": null, + "width": 156 + }, + { + "access": null, + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/204", + "nested": 0, + "role": null, + "status": null, + "statusBackground": null, + "width": 156 + } + ], + "overflow": false, + "viewport": { + "dpr": 1, + "height": 900, + "width": 1440 + } + }, + "myMobileLong": { + "cards": [ + { + "access": "можно редактировать", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/101", + "nested": 0, + "role": "Лидер", + "status": "Черновик", + "statusBackground": "rgb(249, 249, 249)", + "width": 156 + }, + { + "access": "можно редактировать", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/102", + "nested": 0, + "role": "Лидер", + "status": "Опубликован", + "statusBackground": "rgb(227, 240, 232)", + "width": 156 + }, + { + "access": "можно редактировать", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/103", + "nested": 0, + "role": "Лидер", + "status": "В программе", + "statusBackground": "rgb(232, 224, 250)", + "width": 156 + }, + { + "access": "только просмотр", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/104", + "nested": 0, + "role": "Лидер", + "status": "Сдан в программу", + "statusBackground": "rgb(253, 248, 240)", + "width": 156 + }, + { + "access": "только просмотр", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/107", + "nested": 0, + "role": "Участник", + "status": "Черновик", + "statusBackground": "rgb(249, 249, 249)", + "width": 156 + }, + { + "access": "только просмотр", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/108", + "nested": 0, + "role": "Участник", + "status": "Опубликован", + "statusBackground": "rgb(227, 240, 232)", + "width": 156 + }, + { + "access": "только просмотр", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/105", + "nested": 0, + "role": "Участник", + "status": "В программе", + "statusBackground": "rgb(232, 224, 250)", + "width": 156 + }, + { + "access": "только просмотр", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/106", + "nested": 0, + "role": "Участник", + "status": "Сдан в программу", + "statusBackground": "rgb(253, 248, 240)", + "width": 156 + } + ], + "overflow": false, + "viewport": { + "dpr": 1, + "height": 844, + "width": 390 + } + }, + "my320": { + "cards": [ + { + "access": "можно редактировать", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/101", + "nested": 0, + "role": "Лидер", + "status": "Черновик", + "statusBackground": "rgb(249, 249, 249)", + "width": 156 + }, + { + "access": "можно редактировать", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/102", + "nested": 0, + "role": "Лидер", + "status": "Опубликован", + "statusBackground": "rgb(227, 240, 232)", + "width": 156 + }, + { + "access": "можно редактировать", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/103", + "nested": 0, + "role": "Лидер", + "status": "В программе", + "statusBackground": "rgb(232, 224, 250)", + "width": 156 + }, + { + "access": "только просмотр", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/104", + "nested": 0, + "role": "Лидер", + "status": "Сдан в программу", + "statusBackground": "rgb(253, 248, 240)", + "width": 156 + }, + { + "access": "только просмотр", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/107", + "nested": 0, + "role": "Участник", + "status": "Черновик", + "statusBackground": "rgb(249, 249, 249)", + "width": 156 + }, + { + "access": "только просмотр", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/108", + "nested": 0, + "role": "Участник", + "status": "Опубликован", + "statusBackground": "rgb(227, 240, 232)", + "width": 156 + }, + { + "access": "только просмотр", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/105", + "nested": 0, + "role": "Участник", + "status": "В программе", + "statusBackground": "rgb(232, 224, 250)", + "width": 156 + }, + { + "access": "только просмотр", + "avatar": { + "height": 70, + "width": 70 + }, + "cta": "Открыть", + "height": 180, + "href": "/office/projects/106", + "nested": 0, + "role": "Участник", + "status": "Сдан в программу", + "statusBackground": "rgb(253, 248, 240)", + "width": 156 + } + ], + "overflow": false, + "viewport": { + "dpr": 1, + "height": 844, + "width": 320 + } + }, + "keyboardFocus": { + "href": "/office/projects/102", + "outline": "rgb(123, 99, 179) solid 2px", + "tag": "A" + }, + "keyboardRoute": "http://127.0.0.1:4307/office/projects/my?long", + "console": [ + { + "level": "warn", + "message": "NG0912: Component ID generation collision detected. Components '_IconComponent' and '_IconComponent2' with selector '[appIcon]' generated the same component ID. To fix this, you can change the selector of one of those components or add an extra host attribute to force a different ID. Find more at https://v20.angular.dev/errors/NG0912", + "timestamp": "2026-09-21T21:13:25.507Z", + "url": "http://127.0.0.1:4307/main.js" + }, + { + "level": "warn", + "message": "NG0912: Component ID generation collision detected. Components '_IconComponent' and '_IconComponent2' with selector '[appIcon]' generated the same component ID. To fix this, you can change the selector of one of those components or add an extra host attribute to force a different ID. Find more at https://v20.angular.dev/errors/NG0912", + "timestamp": "2026-09-21T21:14:10.706Z", + "url": "http://127.0.0.1:4307/main.js" + }, + { + "level": "warn", + "message": "NG0912: Component ID generation collision detected. Components '_IconComponent' and '_IconComponent2' with selector '[appIcon]' generated the same component ID. To fix this, you can change the selector of one of those components or add an extra host attribute to force a different ID. Find more at https://v20.angular.dev/errors/NG0912", + "timestamp": "2026-09-21T21:14:11.895Z", + "url": "http://127.0.0.1:4307/main.js" + }, + { + "level": "warn", + "message": "NG0912: Component ID generation collision detected. Components '_IconComponent' and '_IconComponent2' with selector '[appIcon]' generated the same component ID. To fix this, you can change the selector of one of those components or add an extra host attribute to force a different ID. Find more at https://v20.angular.dev/errors/NG0912", + "timestamp": "2026-09-21T21:14:24.941Z", + "url": "http://127.0.0.1:4307/main.js" + }, + { + "level": "warn", + "message": "NG0912: Component ID generation collision detected. Components '_IconComponent' and '_IconComponent2' with selector '[appIcon]' generated the same component ID. To fix this, you can change the selector of one of those components or add an extra host attribute to force a different ID. Find more at https://v20.angular.dev/errors/NG0912", + "timestamp": "2026-09-21T21:14:25.54Z", + "url": "http://127.0.0.1:4307/main.js" + }, + { + "level": "warn", + "message": "NG0912: Component ID generation collision detected. Components '_IconComponent' and '_IconComponent2' with selector '[appIcon]' generated the same component ID. To fix this, you can change the selector of one of those components or add an extra host attribute to force a different ID. Find more at https://v20.angular.dev/errors/NG0912", + "timestamp": "2026-09-21T21:14:26.098Z", + "url": "http://127.0.0.1:4307/main.js" + } + ], + "keyboardDetailRendered": "Тестовый маршрут: office/projects/:id / 102 /", + "keyboardScope": "Локальный TestBed preview: маршрут подтверждён отрисованным detail-placeholder; URL browser API остаётся URL входа." +} diff --git a/docs/prod-project-cards/my-mobile-long.png b/docs/prod-project-cards/my-mobile-long.png new file mode 100644 index 000000000..b3713b8f4 Binary files /dev/null and b/docs/prod-project-cards/my-mobile-long.png differ diff --git a/projects/social_platform/src/app/ui/pages/program/detail/list/list.component.html b/projects/social_platform/src/app/ui/pages/program/detail/list/list.component.html index c07bb3312..cc700166d 100644 --- a/projects/social_platform/src/app/ui/pages/program/detail/list/list.component.html +++ b/projects/social_platform/src/app/ui/pages/program/detail/list/list.component.html @@ -87,7 +87,15 @@