little refactore
This commit is contained in:
@@ -211,8 +211,6 @@ $componentPageConfig = [
|
||||
'tenantSsoToggle' => [],
|
||||
'standardDetailPage' => [],
|
||||
'globalSearch' => [
|
||||
'inputSelector' => '#side-search',
|
||||
'resultsSelector' => '[data-global-search-results]',
|
||||
'appBase' => localeBase(),
|
||||
],
|
||||
'tabs' => [
|
||||
@@ -339,6 +337,7 @@ $componentPageConfig['moduleRuntimeComponents'] = $moduleRuntimeComponents;
|
||||
<script src="<?php e(assetVersion('vendor/fslightbox/fslightbox.js')); ?>"></script>
|
||||
<?php require __DIR__ . '/partials/app-confirm-dialog.phtml'; ?>
|
||||
<?php if ($isLoggedIn): ?>
|
||||
<?php require __DIR__ . '/partials/app-search-dialog.phtml'; ?>
|
||||
<?php require __DIR__ . '/partials/app-session-warning-dialog.phtml'; ?>
|
||||
<?php endif; ?>
|
||||
<?php foreach ($moduleBodyEndTemplateSlots as $slot): ?>
|
||||
|
||||
@@ -15,13 +15,6 @@ $hasAdminPanel = layoutHasAdminPanel($layoutAuth);
|
||||
<i class="bi bi-house"></i>
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button type="button" id="aside-tab-search" data-aside-target="search" role="tab" aria-selected="false"
|
||||
aria-controls="aside-panel-search" aria-label="<?php e(t('Search')); ?>"
|
||||
data-tooltip="<?php e(t('Search')); ?>" data-tooltip-pos="right">
|
||||
<i class="bi bi-search"></i>
|
||||
</button>
|
||||
</li>
|
||||
<?php
|
||||
// ── Module-contributed aside tabs (aside.tab_panel slot) ──
|
||||
$moduleSlots = is_array($layoutNav['moduleSlots'] ?? null) ? $layoutNav['moduleSlots'] : [];
|
||||
|
||||
@@ -279,7 +279,6 @@ $csrfKey = trim((string) ($layoutNav['csrfKey'] ?? \MintyPHP\Session::$csrfSessi
|
||||
$csrfToken = (string) ($layoutNav['csrfToken'] ?? '');
|
||||
$moduleSlots = is_array($layoutNav['moduleSlots'] ?? null) ? $layoutNav['moduleSlots'] : [];
|
||||
$modulePanelSlots = is_array($moduleSlots['aside.tab_panel'] ?? null) ? $moduleSlots['aside.tab_panel'] : [];
|
||||
$moduleSearchSlots = is_array($moduleSlots['search.resource_item'] ?? null) ? $moduleSlots['search.resource_item'] : [];
|
||||
?>
|
||||
<aside class="app-sidebar" id="app-sidebar" data-app-component="sidebar-toggle">
|
||||
<?php if ($currentTenant): ?>
|
||||
@@ -376,163 +375,5 @@ $moduleSearchSlots = is_array($moduleSlots['search.resource_item'] ?? null) ? $m
|
||||
</nav>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<div id="aside-panel-search" class="app-sidebar-panel" data-app-component="global-search" data-aside-panel="search"
|
||||
data-aside-title="<?php e(t('Search')); ?>" role="tabpanel" aria-labelledby="aside-tab-search" hidden>
|
||||
<form class="app-search" >
|
||||
<input type="search" name="side-search" id="side-search" placeholder="<?php e(t('Search...')); ?>"
|
||||
aria-label="<?php e(t('Search')); ?>">
|
||||
<span class="app-search-shortcut" data-search-shortcut aria-hidden="true"></span>
|
||||
</form>
|
||||
<div class="app-search-empty-state" data-global-search-empty>
|
||||
<i class="bi bi-search" aria-hidden="true"></i>
|
||||
<p><?php e(t('To start searching, type in the search field.')); ?></p>
|
||||
<small class="muted" data-search-empty-hint-template="<?php e(t('Tip: Use {shortcut} to focus search quickly.')); ?>"></small>
|
||||
</div>
|
||||
<nav id="global-search">
|
||||
<ul class="app-search-results" data-global-search-results aria-live="polite">
|
||||
<?php if ($canViewUsers): ?>
|
||||
<?php $usersSearch = navActive('admin/users', true); ?>
|
||||
<li data-search-key="users" data-search-base="<?php e(lurl('admin/users')); ?>">
|
||||
<a href="<?php e(lurl('admin/users')); ?>" class="<?php e($usersSearch['class']); ?>" <?php echo $usersSearch['aria']; ?>>
|
||||
<span><?php e(t('Users')); ?></span>
|
||||
<span class="badge" data-search-count>0</span>
|
||||
</a>
|
||||
<ul class="app-search-preview" data-search-preview></ul>
|
||||
</li>
|
||||
<?php endif; ?>
|
||||
<?php if ($canViewTenants): ?>
|
||||
<?php $tenantsSearch = navActive('admin/tenants', true); ?>
|
||||
<li data-search-key="tenants" data-search-base="<?php e(lurl('admin/tenants')); ?>">
|
||||
<a href="<?php e(lurl('admin/tenants')); ?>" class="<?php e($tenantsSearch['class']); ?>" <?php echo $tenantsSearch['aria']; ?>>
|
||||
<span><?php e(t('Tenants')); ?></span>
|
||||
<span class="badge" data-search-count>0</span>
|
||||
</a>
|
||||
<ul class="app-search-preview" data-search-preview></ul>
|
||||
</li>
|
||||
<?php endif; ?>
|
||||
<?php if ($canViewDepartments): ?>
|
||||
<?php $departmentsSearch = navActive('admin/departments', true); ?>
|
||||
<li data-search-key="departments" data-search-base="<?php e(lurl('admin/departments')); ?>">
|
||||
<a href="<?php e(lurl('admin/departments')); ?>"
|
||||
class="<?php e($departmentsSearch['class']); ?>" <?php echo $departmentsSearch['aria']; ?>>
|
||||
<span><?php e(t('Departments')); ?></span>
|
||||
<span class="badge" data-search-count>0</span>
|
||||
</a>
|
||||
<ul class="app-search-preview" data-search-preview></ul>
|
||||
</li>
|
||||
<?php endif; ?>
|
||||
<?php if ($canViewRoles): ?>
|
||||
<?php $rolesSearch = navActive('admin/roles', true); ?>
|
||||
<li data-search-key="roles" data-search-base="<?php e(lurl('admin/roles')); ?>">
|
||||
<a href="<?php e(lurl('admin/roles')); ?>" class="<?php e($rolesSearch['class']); ?>" <?php echo $rolesSearch['aria']; ?>>
|
||||
<span><?php e(t('Roles')); ?></span>
|
||||
<span class="badge" data-search-count>0</span>
|
||||
</a>
|
||||
<ul class="app-search-preview" data-search-preview></ul>
|
||||
</li>
|
||||
<?php endif; ?>
|
||||
<?php if ($canViewPermissions): ?>
|
||||
<?php $permissionsSearch = navActive('admin/permissions', true); ?>
|
||||
<li data-search-key="permissions" data-search-base="<?php e(lurl('admin/permissions')); ?>">
|
||||
<a href="<?php e(lurl('admin/permissions')); ?>"
|
||||
class="<?php e($permissionsSearch['class']); ?>" <?php echo $permissionsSearch['aria']; ?>>
|
||||
<span><?php e(t('Permissions')); ?></span>
|
||||
<span class="badge" data-search-count>0</span>
|
||||
</a>
|
||||
<ul class="app-search-preview" data-search-preview></ul>
|
||||
</li>
|
||||
<?php endif; ?>
|
||||
<?php if ($canViewJobs): ?>
|
||||
<?php $scheduledJobsSearch = navActive('admin/scheduled-jobs', true); ?>
|
||||
<li data-search-key="scheduled-jobs" data-search-base="<?php e(lurl('admin/scheduled-jobs')); ?>">
|
||||
<a href="<?php e(lurl('admin/scheduled-jobs')); ?>"
|
||||
class="<?php e($scheduledJobsSearch['class']); ?>" <?php echo $scheduledJobsSearch['aria']; ?>>
|
||||
<span><?php e(t('Scheduled jobs')); ?></span>
|
||||
<span class="badge" data-search-count>0</span>
|
||||
</a>
|
||||
<ul class="app-search-preview" data-search-preview></ul>
|
||||
</li>
|
||||
<?php endif; ?>
|
||||
<?php
|
||||
$pagesSearch = navActivePublicPages();
|
||||
?>
|
||||
<li data-search-key="pages" data-search-base="<?php e(lurl('')); ?>">
|
||||
<a href="<?php e(lurl('')); ?>" class="<?php e($pagesSearch['class']); ?>" <?php echo $pagesSearch['aria']; ?>>
|
||||
<span><?php e(t('Pages')); ?></span>
|
||||
<span class="badge" data-search-count>0</span>
|
||||
</a>
|
||||
<ul class="app-search-preview" data-search-preview></ul>
|
||||
</li>
|
||||
<?php if ($canViewDocs): ?>
|
||||
<?php $docsSearch = navActive('admin/docs', true); ?>
|
||||
<li data-search-key="docs" data-search-base="<?php e(lurl($docsDefaultPath)); ?>">
|
||||
<a href="<?php e(lurl($docsDefaultPath)); ?>" class="<?php e($docsSearch['class']); ?>" <?php echo $docsSearch['aria']; ?>>
|
||||
<span><?php e(t('Documentation')); ?></span>
|
||||
<span class="badge" data-search-count>0</span>
|
||||
</a>
|
||||
<ul class="app-search-preview" data-search-preview></ul>
|
||||
</li>
|
||||
<?php endif; ?>
|
||||
<?php $hotkeysSearch = navActive('help/hotkeys', true); ?>
|
||||
<li data-search-key="hotkeys" data-search-base="<?php e(lurl('help/hotkeys')); ?>">
|
||||
<a href="<?php e(lurl('help/hotkeys')); ?>" class="<?php e($hotkeysSearch['class']); ?>" <?php echo $hotkeysSearch['aria']; ?>>
|
||||
<span><?php e(t('Keyboard shortcuts')); ?></span>
|
||||
<span class="badge" data-search-count>0</span>
|
||||
</a>
|
||||
<ul class="app-search-preview" data-search-preview></ul>
|
||||
</li>
|
||||
<?php if ($canViewMailLog): ?>
|
||||
<?php $mailLogSearch = navActive('admin/mail-log', true); ?>
|
||||
<li data-search-key="mail-log" data-search-base="<?php e(lurl('admin/mail-log')); ?>">
|
||||
<a href="<?php e(lurl('admin/mail-log')); ?>" class="<?php e($mailLogSearch['class']); ?>"
|
||||
<?php echo $mailLogSearch['aria']; ?>>
|
||||
<span><?php e(t('Mail logs')); ?></span>
|
||||
<span class="badge" data-search-count>0</span>
|
||||
</a>
|
||||
<ul class="app-search-preview" data-search-preview></ul>
|
||||
</li>
|
||||
<?php endif; ?>
|
||||
<?php
|
||||
$coreSearchKeys = [
|
||||
'users' => true,
|
||||
'tenants' => true,
|
||||
'departments' => true,
|
||||
'roles' => true,
|
||||
'permissions' => true,
|
||||
'scheduled-jobs' => true,
|
||||
'pages' => true,
|
||||
'docs' => true,
|
||||
'hotkeys' => true,
|
||||
'mail-log' => true,
|
||||
];
|
||||
foreach ($moduleSearchSlots as $searchSlot):
|
||||
if (!is_array($searchSlot)) { continue; }
|
||||
$slotKey = trim((string) ($searchSlot['key'] ?? ''));
|
||||
if ($slotKey === '' || isset($coreSearchKeys[$slotKey])) { continue; }
|
||||
$slotPermission = trim((string) ($searchSlot['permission'] ?? ''));
|
||||
if ($slotPermission !== '' && empty($layoutAuth[$slotPermission])) { continue; }
|
||||
$slotLabel = trim((string) ($searchSlot['label'] ?? ''));
|
||||
if ($slotLabel === '') { continue; }
|
||||
$slotBase = trim((string) ($searchSlot['base_url'] ?? ''));
|
||||
if ($slotBase === '') { continue; }
|
||||
$slotHref = $slotBase;
|
||||
$slotActive = ['class' => '', 'aria' => ''];
|
||||
if (!str_starts_with($slotBase, '/') && !str_starts_with($slotBase, 'http://') && !str_starts_with($slotBase, 'https://')) {
|
||||
$slotHref = lurl($slotBase);
|
||||
$slotActive = navActive($slotBase, true);
|
||||
}
|
||||
?>
|
||||
<li data-search-key="<?php e($slotKey); ?>" data-search-base="<?php e($slotHref); ?>">
|
||||
<a href="<?php e($slotHref); ?>" class="<?php e($slotActive['class'] ?? ''); ?>"
|
||||
<?php echo $slotActive['aria'] ?? ''; ?>>
|
||||
<span><?php e(t($slotLabel)); ?></span>
|
||||
<span class="badge" data-search-count>0</span>
|
||||
</a>
|
||||
<ul class="app-search-preview" data-search-preview></ul>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
66
templates/partials/app-search-dialog.phtml
Normal file
66
templates/partials/app-search-dialog.phtml
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
/**
|
||||
* Command-palette search dialog.
|
||||
*
|
||||
* Opened via Ctrl+K / Cmd+K or topbar search trigger.
|
||||
* Results are rendered dynamically by JS from the /admin/search/data API.
|
||||
*/
|
||||
?>
|
||||
<dialog
|
||||
data-app-search-dialog
|
||||
data-app-component="global-search"
|
||||
data-search-endpoint="<?php e(lurl('admin/search/data')); ?>"
|
||||
data-search-results-page="<?php e(lurl('search')); ?>"
|
||||
aria-labelledby="app-search-dialog-title"
|
||||
>
|
||||
<article class="app-dialog-lg app-search-dialog">
|
||||
<header class="app-search-dialog-header">
|
||||
<h2 id="app-search-dialog-title" class="visually-hidden"><?php e(t('Search')); ?></h2>
|
||||
<form class="app-search-dialog-form" autocomplete="off">
|
||||
<i class="bi bi-search app-search-dialog-icon" aria-hidden="true"></i>
|
||||
<input
|
||||
type="search"
|
||||
name="search-dialog-input"
|
||||
id="search-dialog-input"
|
||||
class="app-search-dialog-input"
|
||||
placeholder="<?php e(t('Search...')); ?>"
|
||||
aria-label="<?php e(t('Search')); ?>"
|
||||
aria-autocomplete="list"
|
||||
aria-controls="app-search-dialog-results"
|
||||
autocomplete="off"
|
||||
>
|
||||
<kbd class="app-search-dialog-shortcut" data-search-shortcut aria-hidden="true"></kbd>
|
||||
</form>
|
||||
<button type="button" class="close" data-app-search-dialog-close aria-label="<?php e(t('Close')); ?>" title="<?php e(t('Close')); ?>"></button>
|
||||
</header>
|
||||
<div class="app-search-dialog-body">
|
||||
<div class="app-search-dialog-empty-state" data-search-dialog-empty data-no-results-text="<?php e(t('No results found')); ?>">
|
||||
<p class="muted"><?php e(t('To start searching, type in the search field.')); ?></p>
|
||||
<small class="muted" data-search-empty-hint-template="<?php e(t('Tip: Use {shortcut} to focus search quickly.')); ?>"></small>
|
||||
</div>
|
||||
<div class="app-search-dialog-loading" data-search-dialog-loading hidden>
|
||||
<p class="muted" aria-live="polite"><?php e(t('Searching...')); ?></p>
|
||||
</div>
|
||||
<div class="app-search-dialog-error" data-search-dialog-error hidden>
|
||||
<p class="muted"><?php e(t('Search failed. Please try again.')); ?></p>
|
||||
</div>
|
||||
<ul
|
||||
id="app-search-dialog-results"
|
||||
class="app-search-dialog-results"
|
||||
data-search-dialog-results
|
||||
role="listbox"
|
||||
aria-label="<?php e(t('Search results')); ?>"
|
||||
hidden
|
||||
></ul>
|
||||
</div>
|
||||
<footer class="app-search-dialog-footer" data-search-dialog-footer hidden>
|
||||
<a href="<?php e(lurl('search')); ?>" data-search-dialog-view-all class="app-search-dialog-view-all">
|
||||
<?php e(t('View all results')); ?>
|
||||
<i class="bi bi-arrow-right" aria-hidden="true"></i>
|
||||
</a>
|
||||
<span class="app-search-dialog-footer-hint muted">
|
||||
<kbd>Esc</kbd> <?php e(t('to close')); ?>
|
||||
</span>
|
||||
</footer>
|
||||
</article>
|
||||
</dialog>
|
||||
@@ -38,7 +38,13 @@ $moduleTopbarSlots = is_array($moduleSlots['topbar.right_item'] ?? null) ? $modu
|
||||
</li>
|
||||
<li id="async-messages" role="status" aria-live="polite" aria-hidden="true"></li>
|
||||
</ul>
|
||||
<div class="app-topbar-center" aria-hidden="true"></div>
|
||||
<div class="app-topbar-center">
|
||||
<button type="button" class="app-topbar-search-trigger" data-app-search-trigger aria-label="<?php e(t('Search')); ?>" title="<?php e(t('Search')); ?>">
|
||||
<i class="bi bi-search" aria-hidden="true"></i>
|
||||
<span class="app-topbar-search-trigger-text"><?php e(t('Search...')); ?></span>
|
||||
<kbd class="app-topbar-search-trigger-shortcut" data-search-trigger-shortcut aria-hidden="true"></kbd>
|
||||
</button>
|
||||
</div>
|
||||
<ul class="app-topbar-right">
|
||||
<?php if ($canSwitchTenant): ?>
|
||||
<li class="app-topbar-tenant-slot" data-app-component="tenant-switcher" data-tenant-switcher data-tooltip="<?php e(t('Tenant')); ?>" data-tooltip-pos="bottom">
|
||||
|
||||
Reference in New Issue
Block a user