feat: centralize breadcrumbs in topbar and remove history navigation

Move breadcrumb rendering from individual page templates into the core
topbar. Each page now sets $breadcrumbs in its action .php file; the
topbar renders it automatically via the shared partial.

- Remove global back/forward buttons and app-nav-history.js component
- Remove Alt+Arrow keyboard shortcuts for history navigation
- Render breadcrumb in topbar-left section (replaces button area)
- Clean up breadcrumb CSS: context-neutral base (flex, no margin)
- Recalculate sticky titlebar offset in details container
- Migrate all 41 pages (core + helpdesk, audit, addressbook, api-docs)
- Add missing breadcrumbs to addressbook detail view
- Update architecture contract tests (nav-history references removed)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-05 17:17:06 +02:00
parent 7220aa7459
commit b749b5d192
91 changed files with 231 additions and 436 deletions

View File

@@ -100,3 +100,8 @@ if ($request->isMethod('POST')) {
$validationSummaryErrors = $errorBag->toArray();
$errors = $errorBag->toFlatList();
Buffer::set('title', t('Create department'));
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Departments'), 'path' => 'admin/departments'],
['label' => t('Create department')],
];

View File

@@ -10,12 +10,6 @@
<section>
<?php
$hasTenantOptions = !empty($tenants);
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Departments'), 'path' => 'admin/departments'],
['label' => t('Create department')],
];
require templatePath('partials/app-breadcrumb.phtml');
$titlebar = [
'title' => t('Create department'),
'backHref' => 'admin/departments',

View File

@@ -151,4 +151,10 @@ if ($request->isMethod('POST')) {
$validationSummaryErrors = $errorBag->toArray();
$errors = $errorBag->toFlatList();
Buffer::set('title', $canUpdateDepartment ? t('Edit department') : t('View department'));
$titleText = $canUpdateDepartment ? t('Edit department') : t('View department');
Buffer::set('title', $titleText);
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Departments'), 'path' => 'admin/departments'],
['label' => $titleText],
];

View File

@@ -21,12 +21,6 @@ $titleText = $isReadOnly ? t('View department') : t('Edit department');
<section>
<?php
$hasTenantOptions = !empty($tenants);
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Departments'), 'path' => 'admin/departments'],
['label' => $titleText],
];
require templatePath('partials/app-breadcrumb.phtml');
$titlebar = [
'title' => $titleText,
'backHref' => 'admin/departments',

View File

@@ -42,6 +42,10 @@ usort($tenants, static function ($a, $b) {
});
Buffer::set('title', t('Departments'));
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Departments')],
];
Buffer::set('grid_lang', json_encode(gridLang(), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
$csrfKey = Session::$csrfSessionKey;
$csrfToken = $session[$csrfKey] ?? '';

View File

@@ -14,13 +14,6 @@ $activeTenant = (string) ($activeTenant ?? ($toolbarFilterState['tenant'] ?? '')
$showTenantTabs = isset($tenants) && is_array($tenants) && count($tenants) > 1;
?>
<?php
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Departments')],
];
require templatePath('partials/app-breadcrumb.phtml');
?>
<?php
$listTitle = t('Departments');
ob_start();
?>

View File

@@ -54,5 +54,11 @@ $currentSlug = $slug;
$currentTitle = (string) $allDocs[$slug];
Buffer::set('title', $currentTitle . ' - ' . t('Documentation'));
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Documentation'), 'path' => 'admin/docs/' . $defaultSlug],
['label' => $currentTitle],
];
Buffer::set('style_groups', json_encode(['docs']));
Buffer::set('docs_rendered_html', $renderedHtml);

View File

@@ -44,14 +44,6 @@
</aside>
<article class="app-docs-content">
<?php
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Documentation'), 'path' => 'admin/docs/' . $defaultSlug],
['label' => $currentTitle],
];
require templatePath('partials/app-breadcrumb.phtml');
?>
<?php MintyPHP\Buffer::get('docs_rendered_html'); ?>
</article>

View File

@@ -136,3 +136,8 @@ foreach ($profileOptions as $option) {
}
Buffer::set('title', t('Imports'));
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Imports')],
];

View File

@@ -1,10 +1,5 @@
<?php
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Imports')],
];
$hasAllowedProfile = !empty($allowedProfileOptions);
$renderErrorTable = static function (array $rows): void {
@@ -43,7 +38,6 @@ $renderErrorTable = static function (array $rows): void {
<div class="app-details-container">
<section>
<?php require templatePath('partials/app-breadcrumb.phtml'); ?>
<div class="app-details-titlebar" data-detail-unsaved-message="<?php e(t('You have unsaved changes. Leave without saving?')); ?>">
<h1><?php e(t('Imports')); ?></h1>
</div>

View File

@@ -11,3 +11,8 @@ $user = $session['user'] ?? null;
$first_name = $user['first_name'] ?? '';
Buffer::set('title', t('Admin'));
$breadcrumbs = [
['label' => t('Login'), 'path' => 'logout'],
['label' => t('Home')],
];

View File

@@ -6,13 +6,6 @@
*/
?>
<?php
$breadcrumbs = [
['label' => t('Login'), 'path' => 'logout'],
['label' => t('Home')],
];
require templatePath('partials/app-breadcrumb.phtml');
?>
<div class="app-dashboard-titlebar">
<h1><?php e(t('Welcome back')); ?> <?php e($first_name )?></h1>

View File

@@ -41,6 +41,10 @@ $clientFilterSchema = $listFilterContext['clientFilterSchema'];
$searchConfig = $listFilterContext['searchConfig'];
Buffer::set('title', t('Mail logs'));
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Mail logs')],
];
Buffer::set('grid_lang', json_encode(gridLang(), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
$csrfKey = Session::$csrfSessionKey;
$csrfToken = $session[$csrfKey] ?? '';

View File

@@ -10,13 +10,6 @@ $clientFilterSchema = is_array($clientFilterSchema ?? null) ? $clientFilterSchem
$searchConfig = is_array($searchConfig ?? null) ? $searchConfig : null;
?>
<?php
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Mail logs')],
];
require templatePath('partials/app-breadcrumb.phtml');
?>
<?php
$listTitle = t('Mail logs');
require templatePath('partials/app-list-titlebar.phtml');
?>

View File

@@ -17,3 +17,8 @@ if (!$mailLog) {
}
Buffer::set('title', t('View mail log'));
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Mail logs'), 'path' => 'admin/mail-log'],
['label' => t('View')],
];

View File

@@ -13,14 +13,6 @@ $statusBadge = $status->badgeVariant();
<div class="app-details-container">
<section>
<?php
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Mail logs'), 'path' => 'admin/mail-log'],
['label' => t('View')],
];
require templatePath('partials/app-breadcrumb.phtml');
?>
<div class="app-details-titlebar">
<h1>
<a href="admin/mail-log" title="<?php e(t('Back')); ?>" class="app-icon-button"><i class="bi bi-arrow-left"></i></a>

View File

@@ -66,3 +66,8 @@ if ($request->isMethod('POST')) {
$validationSummaryErrors = $errorBag->toArray();
$errors = $errorBag->toFlatList();
Buffer::set('title', t('Create permission'));
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Permissions'), 'path' => 'admin/permissions'],
['label' => t('Create permission')],
];

View File

@@ -9,12 +9,6 @@
<div class="app-details-container">
<section>
<?php
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Permissions'), 'path' => 'admin/permissions'],
['label' => t('Create permission')],
];
require templatePath('partials/app-breadcrumb.phtml');
$titlebar = [
'title' => t('Create permission'),
'backHref' => 'admin/permissions',

View File

@@ -112,4 +112,10 @@ if ($request->isMethod('POST')) {
$validationSummaryErrors = $errorBag->toArray();
$errors = $errorBag->toFlatList();
Buffer::set('title', $canUpdatePermission ? t('Edit permission') : t('View permission'));
$titleText = $canUpdatePermission ? t('Edit permission') : t('View permission');
Buffer::set('title', $titleText);
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Permissions'), 'path' => 'admin/permissions'],
['label' => $titleText],
];

View File

@@ -13,18 +13,12 @@ use MintyPHP\Session;
$canUpdatePermission = (bool) ($canUpdatePermission ?? false);
$canDeletePermission = (bool) ($canDeletePermission ?? false);
$isReadOnly = !$canUpdatePermission;
$titleText = $isReadOnly ? t('View permission') : t('Edit permission');
$titleText = $titleText ?? ($isReadOnly ? t('View permission') : t('Edit permission'));
?>
<div class="app-details-container">
<section>
<?php
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Permissions'), 'path' => 'admin/permissions'],
['label' => $titleText],
];
require templatePath('partials/app-breadcrumb.phtml');
$titlebar = [
'title' => $titleText,
'backHref' => 'admin/permissions',

View File

@@ -49,6 +49,10 @@ $clientFilterSchema = $listFilterContext['clientFilterSchema'];
$searchConfig = $listFilterContext['searchConfig'];
Buffer::set('title', t('Permissions'));
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Permissions')],
];
Buffer::set('grid_lang', json_encode(gridLang(), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
$csrfKey = Session::$csrfSessionKey;
$csrfToken = $session[$csrfKey] ?? '';

View File

@@ -12,13 +12,6 @@ $clientFilterSchema = is_array($clientFilterSchema ?? null) ? $clientFilterSchem
$searchConfig = is_array($searchConfig ?? null) ? $searchConfig : null;
?>
<?php
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Permissions')],
];
require templatePath('partials/app-breadcrumb.phtml');
?>
<?php
$listTitle = t('Permissions');
ob_start();
?>

View File

@@ -116,3 +116,8 @@ if ($request->isMethod('POST')) {
$validationSummaryErrors = $errorBag->toArray();
$errors = $errorBag->toFlatList();
Buffer::set('title', t('Create role'));
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Roles'), 'path' => 'admin/roles'],
['label' => t('Create role')],
];

View File

@@ -9,12 +9,6 @@
<div class="app-details-container">
<section>
<?php
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Roles'), 'path' => 'admin/roles'],
['label' => t('Create role')],
];
require templatePath('partials/app-breadcrumb.phtml');
$titlebar = [
'title' => t('Create role'),
'backHref' => 'admin/roles',

View File

@@ -128,4 +128,10 @@ if ($request->isMethod('POST')) {
$validationSummaryErrors = $errorBag->toArray();
$errors = $errorBag->toFlatList();
Buffer::set('title', $canUpdateRole ? t('Edit role') : t('View role'));
$titleText = $canUpdateRole ? t('Edit role') : t('View role');
Buffer::set('title', $titleText);
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Roles'), 'path' => 'admin/roles'],
['label' => $titleText],
];

View File

@@ -21,12 +21,6 @@ $titleText = $isReadOnly ? t('View role') : t('Edit role');
<div class="app-details-container">
<section>
<?php
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Roles'), 'path' => 'admin/roles'],
['label' => $titleText],
];
require templatePath('partials/app-breadcrumb.phtml');
$titlebar = [
'title' => $titleText,
'backHref' => 'admin/roles',

View File

@@ -49,6 +49,10 @@ $clientFilterSchema = $listFilterContext['clientFilterSchema'];
$searchConfig = $listFilterContext['searchConfig'];
Buffer::set('title', t('Roles'));
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Roles')],
];
Buffer::set('grid_lang', json_encode(gridLang(), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
$csrfKey = Session::$csrfSessionKey;
$csrfToken = $session[$csrfKey] ?? '';

View File

@@ -12,13 +12,6 @@ $clientFilterSchema = is_array($clientFilterSchema ?? null) ? $clientFilterSchem
$searchConfig = is_array($searchConfig ?? null) ? $searchConfig : null;
?>
<?php
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Roles')],
];
require templatePath('partials/app-breadcrumb.phtml');
?>
<?php
$listTitle = t('Roles');
ob_start();
?>

View File

@@ -73,5 +73,11 @@ $scheduleSummary = $scheduledJobService->scheduleSummary($job ?? []);
$validationSummaryErrors = $errorBag->toArray();
$errors = $errorBag->toFlatList();
Buffer::set('title', $canManage ? t('Edit scheduled job') : t('View scheduled job'));
$titleText = $canManage ? t('Edit scheduled job') : t('View scheduled job');
Buffer::set('title', $titleText);
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Scheduled jobs'), 'path' => 'admin/scheduled-jobs'],
['label' => $titleText],
];
Buffer::set('grid_lang', json_encode(gridLang(), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));

View File

@@ -39,13 +39,6 @@ if ($canRunNow) {
<section>
<?php
$titleText = $canManage ? t('Edit scheduled job') : t('View scheduled job');
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Scheduled jobs'), 'path' => 'admin/scheduled-jobs'],
['label' => $titleText],
];
require templatePath('partials/app-breadcrumb.phtml');
$titlebar = [
'title' => $titleText,
'backHref' => 'admin/scheduled-jobs',

View File

@@ -46,4 +46,8 @@ $clientFilterSchema = $listFilterContext['clientFilterSchema'];
$searchConfig = $listFilterContext['searchConfig'];
Buffer::set('title', t('Scheduled jobs'));
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Scheduled jobs')],
];
Buffer::set('grid_lang', json_encode(gridLang(), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));

View File

@@ -10,13 +10,6 @@ $clientFilterSchema = is_array($clientFilterSchema ?? null) ? $clientFilterSchem
$searchConfig = is_array($searchConfig ?? null) ? $searchConfig : null;
?>
<?php
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Scheduled jobs')],
];
require templatePath('partials/app-breadcrumb.phtml');
?>
<?php
$listTitle = t('Scheduled jobs');
ob_start();
?>

View File

@@ -81,3 +81,8 @@ if ($request->isMethod('POST')) {
}
Buffer::set('title', t('Settings'));
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Settings')],
];

View File

@@ -104,11 +104,6 @@ $disabledAttr = $isReadOnly ? 'disabled' : '';
<div class="app-details-container">
<section>
<?php
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Settings')],
];
require templatePath('partials/app-breadcrumb.phtml');
$titlebar = [
'title' => t('Settings'),
'actions' => $canUpdateSettings ? [

View File

@@ -17,3 +17,8 @@ $currentUserId = (int) ($session['user']['id'] ?? 0);
$viewAuth['page'] = app(UiAccessService::class)->pageCapabilities($currentUserId, UiCapabilityMap::PAGE_STATS_INDEX);
Buffer::set('title', t('Statistics'));
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Statistics')],
];

View File

@@ -107,13 +107,6 @@ $canViewAuditTab = (bool) ($auditStatsAvailable ?? false) && (
|| ($canViewUserLifecycleAudit && (bool) ($userLifecycleAuditStatsAvailable ?? false))
);
?>
<?php
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Statistics')],
];
require templatePath('partials/app-breadcrumb.phtml');
?>
<div class="app-dashboard-titlebar">
<h1><?php e(t('Statistics')); ?></h1>

View File

@@ -14,3 +14,8 @@ $permissions = $pageData['permissions'] ?? [];
$healthChecks = $overview['health_checks'] ?? [];
Buffer::set('title', t('System Info'));
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('System Info')],
];

View File

@@ -12,13 +12,6 @@ $modules = $modules ?? [];
$permissions = $permissions ?? [];
$healthChecks = $healthChecks ?? [];
?>
<?php
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('System Info')],
];
require templatePath('partials/app-breadcrumb.phtml');
?>
<div class="app-dashboard-titlebar">
<h1><?php e(t('System Info')); ?></h1>

View File

@@ -135,3 +135,8 @@ if ($request->isMethod('POST')) {
$validationSummaryErrors = $errorBag->toArray();
$errors = $errorBag->toFlatList();
Buffer::set('title', t('Create tenant'));
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Tenants'), 'path' => 'admin/tenants'],
['label' => t('Create tenant')],
];

View File

@@ -11,12 +11,6 @@
<div class="app-details-container">
<section>
<?php
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Tenants'), 'path' => 'admin/tenants'],
['label' => t('Create tenant')],
];
require templatePath('partials/app-breadcrumb.phtml');
$titlebar = [
'title' => t('Create tenant'),
'backHref' => 'admin/tenants',

View File

@@ -182,4 +182,10 @@ if ($canManageSso && empty($ldapUiState)) {
$validationSummaryErrors = $errorBag->toArray();
$errors = $errorBag->toFlatList();
Buffer::set('title', $canUpdateTenant ? t('Edit tenant') : t('View tenant'));
$titleText = $canUpdateTenant ? t('Edit tenant') : t('View tenant');
Buffer::set('title', $titleText);
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Tenants'), 'path' => 'admin/tenants'],
['label' => $titleText],
];

View File

@@ -27,12 +27,6 @@ $hasFavicon = $avatarUuid !== '' && $tenantFaviconService->hasFavicon($avatarUui
<div class="app-details-container">
<section>
<?php
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Tenants'), 'path' => 'admin/tenants'],
['label' => $titleText],
];
require templatePath('partials/app-breadcrumb.phtml');
$titlebar = [
'title' => $titleText,
'backHref' => 'admin/tenants',

View File

@@ -46,6 +46,10 @@ $clientFilterSchema = $listFilterContext['clientFilterSchema'];
$searchConfig = $listFilterContext['searchConfig'];
Buffer::set('title', t('Tenants'));
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Tenants')],
];
Buffer::set('grid_lang', json_encode(gridLang(), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
$csrfKey = Session::$csrfSessionKey;
$csrfToken = $session[$csrfKey] ?? '';

View File

@@ -12,13 +12,6 @@ $clientFilterSchema = is_array($clientFilterSchema ?? null) ? $clientFilterSchem
$searchConfig = is_array($searchConfig ?? null) ? $searchConfig : null;
?>
<?php
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Tenants')],
];
require templatePath('partials/app-breadcrumb.phtml');
?>
<?php
$listTitle = t('Tenants');
ob_start();
?>

View File

@@ -214,3 +214,8 @@ if (!$customFieldDefinitionsByTenant && $selectedTenantIds) {
$validationSummaryErrors = $errorBag->toArray();
$errors = $errorBag->toFlatList();
Buffer::set('title', t('Create user'));
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Users'), 'path' => 'admin/users'],
['label' => t('Create user')],
];

View File

@@ -12,12 +12,6 @@
<section>
<?php
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Users'), 'path' => 'admin/users'],
['label' => t('Create user')],
];
require templatePath('partials/app-breadcrumb.phtml');
$titlebar = [
'title' => t('Create user'),
'backHref' => 'admin/users',

View File

@@ -300,4 +300,12 @@ if ($request->isMethod('POST')) {
$validationSummaryErrors = $errorBag->toArray();
$errors = $errorBag->toFlatList();
Buffer::set('title', $isOwnAccount ? t('My account') : ($canEditUser ? t('Edit user') : t('View user')));
$titleText = $isOwnAccount ? t('My account') : ($canEditUser ? t('Edit user') : t('View user'));
Buffer::set('title', $titleText);
if (!($isOwnAccount && !$canViewUsers)) {
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Users'), 'path' => 'admin/users'],
['label' => $titleText],
];
}

View File

@@ -46,16 +46,6 @@ if ($lastLoginAt !== '') {
<div class="app-details-container">
<section>
<?php if (!$hideNavigation): ?>
<?php
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Users'), 'path' => 'admin/users'],
['label' => $titleText],
];
require templatePath('partials/app-breadcrumb.phtml');
?>
<?php endif; ?>
<?php
$asideActions = [];
$moduleSlots = is_array($layoutNav['moduleSlots'] ?? null) ? $layoutNav['moduleSlots'] : [];

View File

@@ -56,6 +56,10 @@ $viewAuth['page'] = [
];
Buffer::set('title', t('Users'));
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Users')],
];
Buffer::set('grid_lang', json_encode(gridLang(), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
$csrfKey = Session::$csrfSessionKey;
$csrfToken = $session[$csrfKey] ?? '';

View File

@@ -22,13 +22,6 @@ $currentUserUuid = (string) ($_SESSION['user']['uuid'] ?? '');
$showTenantTabs = isset($tenants) && is_array($tenants) && count($tenants) > 1;
?>
<?php
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Users')],
];
require templatePath('partials/app-breadcrumb.phtml');
?>
<?php
$listTitle = t('Users');
ob_start();
?>

View File

@@ -13,7 +13,6 @@ $hotkeyRows = HotkeyService::list();
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Keyboard shortcuts')],
];
require templatePath('partials/app-breadcrumb.phtml');
?>
<?php

View File

@@ -29,6 +29,11 @@ $csrfKey = Session::$csrfSessionKey;
$csrfToken = $session[$csrfKey] ?? '';
Buffer::set('title', t('Search results'));
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Search')],
];
Buffer::set('grid_lang', json_encode(gridLang(), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
Buffer::set(
'grid_csrf',

View File

@@ -8,13 +8,6 @@ $clientFilterSchema = is_array($clientFilterSchema ?? null) ? $clientFilterSchem
$searchConfig = is_array($searchConfig ?? null) ? $searchConfig : null;
?>
<?php
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Search')],
];
require templatePath('partials/app-breadcrumb.phtml');
?>
<?php
$listTitle = t('Search results');
require templatePath('partials/app-list-titlebar.phtml');
?>