Files
breadcrumb-the-shire/modules/addressbook/module.php
fs 811588290c feat(core): detail drawer + address book list redesign
Introduces a reusable core detail-drawer primitive that slides in from the
right and loads any view via a `*-fragment(none).phtml` endpoint. Bundles the
address book list overhaul that is its first consumer.

Core additions:
- `app-detail-drawer.js` — generic drawer with stepper, focus trap, body
  scroll-lock, URL-hash deep-linking, session-expiry detection
- `app-fragment-init.js` — auto-wires tabs/lookups/confirm/file-upload/
  fslightbox inside injected HTML; consumers do not re-initialize components
- `app-focus-trap.js` — shared focus-trap + refcounted scroll-lock, used by
  both filter-drawer and detail-drawer
- `getHtml()` in `app-http.js` + `SessionExpiredError`; drawer reloads the
  page on auth redirect instead of rendering the login form in the panel
- `DetailDrawerFragmentContractTest` enforces that every `initDetailDrawer`
  consumer ships matching `*-fragment($id).php` + `*-fragment(none).phtml`

Address book list:
- Grid collapses from 9 columns to 4 (identity / context / phone / actions)
  with a two-line identity cell (avatar + name + email)
- Tenant register tabs above the grid using the `app-list-tabs` partial;
  tenant filter wired via hidden toolbar field so grid.js forwards it on
  every data fetch
- Profile body extracted to a shared partial so the full-page view and the
  new drawer fragment share the same markup
- New i18n keys for the drawer/list labels

Also refactors `app-filter-drawer` to reuse the shared focus-trap and
scroll-lock instead of maintaining its own copy, and documents the
detail-drawer convention in CLAUDE.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 15:22:26 +02:00

96 lines
2.8 KiB
PHP

<?php
/**
* Address Book module manifest.
*
* Contributes routes, explorer nav link, search entry, user-edit aside action,
* and authorization policy.
*/
return [
'id' => 'addressbook',
'version' => '1.0.0',
'enabled_by_default' => false,
'load_order' => 10,
'requires' => [],
'routes' => [
// Keep canonical route stable without forcing a /index target to avoid Router redirect loops.
['path' => 'address-book', 'target' => 'address-book'],
['path' => 'address-book/data', 'target' => 'address-book/data'],
['path' => 'address-book/view-fragment', 'target' => 'address-book/view-fragment'],
// Legacy aliases for existing bookmarks/links.
['path' => 'addressbook', 'target' => 'address-book'],
['path' => 'adressbook', 'target' => 'address-book'],
],
'public_paths' => [],
'container_registrars' => [
\MintyPHP\Module\AddressBook\AddressBookContainerRegistrar::class,
],
'ui_slots' => [
'explorer.nav_item' => [
[
'key' => 'address-book',
'label' => 'Address book',
'href' => 'address-book',
'permission' => 'addressbook.view',
'order' => 110,
],
],
'search.resource_item' => [
[
'key' => 'address-book',
'label' => 'Address book',
'base_url' => 'address-book',
'permission' => 'addressbook.view',
'order' => 110,
],
],
'user.edit.aside_action' => [
[
'key' => 'address-book-view-user',
'type' => 'link',
'label' => 'View in address book',
'href' => 'address-book/view/{user_uuid}',
'permission' => 'addressbook.view',
'order' => 110,
],
],
],
'authorization_policies' => [
\MintyPHP\Module\AddressBook\AddressBookAuthorizationPolicy::class,
],
'search_resources' => [
\MintyPHP\Module\AddressBook\Providers\AddressBookSearchProvider::class,
],
'asset_groups' => [
'address-book' => [
'modules/addressbook/css/pages/address-book-view.css',
'modules/addressbook/css/pages/address-book-banner.css',
],
'address-book-index' => [
'modules/addressbook/css/pages/address-book-index.css',
],
],
'scheduler_jobs' => [],
'layout_context_providers' => [],
'session_providers' => [],
'permissions' => [
[
'key' => 'address_book.view',
'description' => 'Can view address book',
'active' => true,
'is_system' => true,
],
],
'migrations_path' => 'db/updates',
'i18n_path' => 'i18n',
];