Skip to content

fix(vue): изоляция PrimeVue Confirm/Toast через UI groups (#539) - #543

Open
Ibochkarev wants to merge 3 commits into
betafrom
fix/539-primevue-ui-group
Open

fix(vue): изоляция PrimeVue Confirm/Toast через UI groups (#539)#543
Ibochkarev wants to merge 3 commits into
betafrom
fix/539-primevue-ui-group

Conversation

@Ibochkarev

Copy link
Copy Markdown
Member

Описание

PrimeVue в общем Import Map → один ConfirmationEventBus / ToastEventBus на страницу. Ungrouped <ConfirmDialog> / <Toast> ловят каждый confirm.require / toast.add.

Живые репро:

Фикс: provideUiGroup / useGroupedToast / toUiGroup, группы на product gallery vs links, namespace toast+confirm на category.

Тип изменений

  • Исправление бага (non-breaking change)
  • Новая функциональность (non-breaking change)
  • Breaking change (изменение, ломающее обратную совместимость)
  • Рефакторинг (без изменения функциональности)
  • Документация
  • Другое (опишите):

Связанные Issues

Closes #539

Как это было протестировано?

cd vueManager
npx eslint <touched files> --max-warnings 0   # exit 0
npm run test -- src/composables/uiGroup.test.js   # 2 tests, exit 0
npm run test:smoke   # includes check-ui-group-smoke, exit 0
npm run build   # exit 0
  • Ручное тестирование
  • Автоматические тесты (vitest + smoke)
  • Тестирование на разных версиях PHP/MODX

Конфигурация тестирования:

  • MiniShop3: fix/539-primevue-ui-group
  • MODX: n/a
  • PHP: n/a (Vue-only)

Скриншоты (если применимо)

До После
два confirm / два toast один

Чеклист

  • Код соответствует стилю проекта
  • Добавлены/обновлены комментарии в сложных местах
  • Изменения не ломают существующую функциональность
  • Лексиконы — n/a
  • PHPStan — n/a
  • ESLint по затронутым путям
  • CHANGELOG — нет (политика репо)

Дополнительные заметки

Что сделано

  • composables/uiGroup.js: MS3_UI_GROUP, provideUiGroup, useUiGroup, useGroupedToast, toUiGroup / withToastGroup (Confirm === vs Toast ==)
  • useActions / useSelection: confirm + toast через resolved group
  • ProductGallery product-gallery, ProductLinksTab product-links
  • Category entries provideUiGroup; grids берут useUiGroup() (+ fallback) и группируют Toast/Confirm

Не в этом PR (follow-up)

  • Остальные single-app гриды (OrdersGrid, ProductData, …) — баг проявляется при multi-mount / нескольких ungrouped dialogs. Паттерн готов: provideUiGroup + useGroupedToast / group на ConfirmDialog.
  • Lint-rule «запрет ungrouped ConfirmDialog» — опционально позже.

Ручная проверка

  1. product/update → удаление в галерее → один confirm
  2. category/update → удаление товара → один toast

Shared Import Map makes ConfirmationEventBus/ToastEventBus module
singletons, so ungrouped dialogs/toasts on multi-app or non-lazy tab
pages all fire together. Add provide/inject + useGroupedToast, group
product gallery vs links confirms, and namespace category toast/confirm.
@Ibochkarev Ibochkarev added javascript Pull requests that update javascript code bug Something isn't working labels Aug 12, 2026
@Ibochkarev
Ibochkarev requested a review from biz87 August 12, 2026 15:41
Import node:process and use console.warn so lint:ci --max-warnings 0
passes for the #539 smoke check.

@biz87 biz87 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Разобрал. Блокеров нет, фикс корректный — ниже что проверил и что стоит поправить.

Базовая посылка подтверждается

Сверил с установленным PrimeVue 4.3.1:

  • toast/index.mjs:342this.group == message.group (нестрогое)
  • confirmdialog/index.mjs:48options.group === _this.group (строгое)

Докблок uiGroup.js описывает семантику точно, и toUiGroup()undefined вместо null действительно load-bearing. Заодно: Toast.removeGroup (строка 353) сравнивает строго — это к пункту 1.

Полнота фикса — дыр не нашёл

  • Все confirm.require в изменённых файлах несут группу: ProductGallery 4/4, ProductLinksTab 1/1, CategoryOptionsTab 2/2, CategoryProductsGrid — через useSelection и ActionsColumn. Забытых нет.
  • На product/update после PR остаются ровно два <ConfirmDialog> (галерея и ссылки), оба сгруппированы. Других producer'ов confirm в этом приложении нет — ProductTabs, ProductOptionsTab, ProductCategoriesTab, ProductDataFields не вызывают confirm.require и не рендерят диалог. Мёртвых кнопок не появилось.
  • Все producer'ы toast внутри двух category-приложений идут через сгруппированный фасад, включая useCategoryProductsInlineEdit (получает фасад через deps, использует только .add — все три вызова проверил).
  • category-products.js держит single-mount guard ($el.dataset.vApp), так что два приложения с одинаковой группой на странице не появятся.

Замечания

1. Фасад useGroupedToast возвращает только { add }. remove, removeGroup, removeAllGroups молча теряются. Сейчас их никто не вызывает (проверил весь src), но это мина: первый же toast.removeGroup(UI_GROUP) даст TypeError. Чинится двумя строками:

return { ...toast, add(payload) { return toast.add(withToastGroup(payload, group)) } }

2. confirmGroup теперь управляет и группой toast — имя перестало соответствовать. Любой компонент, который передаст confirmGroup в useActions/useSelection, но оставит <Toast /> без группы, потеряет тосты молча (null == 'x' → false). Сегодня confirmGroup передаёт только CategoryProductsGrid, и он свой Toast сгруппировал, так что живой поломки нет. Но это ровно та ловушка, в которую упрётся заявленный follow-up по OrdersGrid и остальным гридам. Логичнее переименовать в uiGroup, оставив confirmGroup алиасом.

3. App-level provide протекает на всё поддерево. Любой компонент внутри category-products/category-options, который отрендерит собственный ungrouped <Toast />/<ConfirmDialog /> и при этом использует useActions/useSelection/useGroupedToast, уйдёт в группу приложения и погаснет. Сейчас в обоих приложениях монтируется по одному компоненту — вопрос теоретический, но follow-up будет добавлять туда компоненты, так что стоит зафиксировать в докблоке.

4. Два разных паттерна в одном PR. Category: provideUiGroup в entry + useUiGroup() || 'литерал' в компоненте. Product: просто локальная константа. Для product обоснование понятно — галерея и ссылки живут в одном приложении и им нужны разные группы, provide тут не поможет. Но для category слой provide сегодня не даёт ничего (в каждом приложении ровно один компонент), зато строка группы дублируется в двух файлах, и smoke-скрипт прибивает обе. Правило стоит записать явно в докблоке: одна группа на приложение → provide; несколько групп внутри приложения → локальная константа.

5. Тесты проверяют не поведение. @vue/test-utils уже в devDependencies, и интересная часть (provideUiGroupuseUiGroup → штамповка группы в add) проверяется одним монтированием двух приложений. Вместо этого — два ассерта на чистые хелперы и 71 строка grep'а по исходникам с проверками наличия подстрок UI_GROUP = 'product-gallery', :group="UI_GROUP". Такой скрипт краснеет от переименования константы и остаётся зелёным при реальной регрессии — забытом group: в новом confirm.require. Если статическая проверка нужна, проверять стоит инвариант: в каждом файле со сгруппированным <ConfirmDialog> каждый confirm.require( обязан передавать group:.

6. Мелочь. useActions вызывает resolveUiGroup(confirmGroup), а следом useGroupedToast(confirmGroup), который резолвит второй раз — два inject() на одно значение. Безвредно, но useGroupedToast(uiGroup) после первого резолва читается лучше.

Не про этот PR

В follow-up указан ProductData, но vueManager/src/components/ProductData.vue не импортируется ни из одного entry и ни из одного компонента, в бандл не попадает, точки монтирования на PHP-стороне у него тоже нет. Похоже на мёртвый файл — прежде чем чинить в нём группы, стоит проверить, не проще ли удалить.

Spread ToastService through useGroupedToast, rename confirmGroup to
uiGroup (keep alias), document provide vs local constants, and tighten
mount/smoke coverage from #543 review.
@Ibochkarev

Copy link
Copy Markdown
Member Author

Addressed #543 (review):

  1. useGroupedToast{ ...toast, add } so remove / removeGroup stay available
  2. Option/prop uiGroup (+ deprecated confirmGroup alias) in useActions / useSelection / ActionsColumn
    3–4. Docblock: provide vs local constants; subtree leak warning
  3. Vitest: provide→inject + stamped add / removeGroup; smoke checks group: on confirm.require (or uiGroup wiring)
  4. Resolve once, then useGroupedToast(uiGroup)

Gates: npm run test -- src/composables/uiGroup.test.js, npm run test:smoke, eslint touched paths — exit 0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working javascript Pull requests that update javascript code

Projects

None yet

2 participants