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>
181 lines
6.7 KiB
PHTML
181 lines
6.7 KiB
PHTML
<?php
|
|
|
|
/**
|
|
* @var array $overview
|
|
* @var list<array{id: string, version: string, enabled_by_default: bool, requires: list<string>, permissions_count: int}> $modules
|
|
* @var array{active_count: int, inactive_count: int, by_source: array<string, int>} $permissions
|
|
* @var list<array{status: string, name: string, message: string}> $healthChecks
|
|
*/
|
|
|
|
$overview = $overview ?? [];
|
|
$modules = $modules ?? [];
|
|
$permissions = $permissions ?? [];
|
|
$healthChecks = $healthChecks ?? [];
|
|
|
|
?>
|
|
<div class="app-dashboard-titlebar">
|
|
<h1><?php e(t('System Info')); ?></h1>
|
|
</div>
|
|
<div class="app-dashboard">
|
|
<div class="app-tabs" data-tabs data-app-component="tabs" data-tabs-param="tab" data-tabs-storage-key="admin-system-info-tabs-v1">
|
|
<div class="app-tabs-nav">
|
|
<button data-tab="overview" data-tab-default class="transparent tab-button">
|
|
<?php e(t('Overview')); ?>
|
|
</button>
|
|
<button data-tab="modules" class="transparent tab-button">
|
|
<?php e(t('Modules')); ?>
|
|
</button>
|
|
<button data-tab="permissions" class="transparent tab-button">
|
|
<?php e(t('Permissions')); ?>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Tab Panel: Overview -->
|
|
<div data-tab-panel="overview">
|
|
<div class="app-stats-table">
|
|
<div class="app-stats-table-header">
|
|
<small><?php e(t('Environment')); ?></small>
|
|
</div>
|
|
<table>
|
|
<tbody>
|
|
<tr>
|
|
<th scope="row"><?php e(t('PHP version')); ?></th>
|
|
<td><?php e((string) ($overview['php_version'] ?? '')); ?></td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row"><?php e(t('PHP SAPI')); ?></th>
|
|
<td><?php e((string) ($overview['php_sapi'] ?? '')); ?></td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row"><?php e(t('Environment')); ?></th>
|
|
<td><?php e((string) ($overview['app_environment'] ?? '')); ?></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="app-stats-table">
|
|
<div class="app-stats-table-header">
|
|
<small><?php e(t('Health Status')); ?></small>
|
|
</div>
|
|
<?php if (empty($healthChecks)): ?>
|
|
<div class="app-stats-table-empty">
|
|
<p><?php e(t('No health checks available.')); ?></p>
|
|
</div>
|
|
<?php else: ?>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th scope="col"><?php e(t('Check')); ?></th>
|
|
<th scope="col"><?php e(t('Status')); ?></th>
|
|
<th scope="col"><?php e(t('Details')); ?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($healthChecks as $check): ?>
|
|
<?php $checkStatus = (string) ($check['status'] ?? 'fail'); ?>
|
|
<tr>
|
|
<td><?php e((string) ($check['name'] ?? '')); ?></td>
|
|
<td>
|
|
<?php if ($checkStatus === 'ok'): ?>
|
|
<span class="badge" data-variant="success"><i class="bi bi-check-circle-fill"></i> OK</span>
|
|
<?php elseif ($checkStatus === 'warn'): ?>
|
|
<span class="badge" data-variant="warn"><i class="bi bi-exclamation-triangle-fill"></i> <?php e(t('Warning')); ?></span>
|
|
<?php else: ?>
|
|
<span class="badge" data-variant="danger"><i class="bi bi-x-circle-fill"></i> <?php e(t('Fail')); ?></span>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td><?php e((string) ($check['message'] ?? '')); ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Tab Panel: Modules -->
|
|
<div data-tab-panel="modules">
|
|
<?php if (empty($modules)): ?>
|
|
<div class="app-stats-table-empty">
|
|
<p><?php e(t('No modules active.')); ?></p>
|
|
</div>
|
|
<?php else: ?>
|
|
<div class="app-stats-table">
|
|
<div class="app-stats-table-header">
|
|
<small><?php e(t('Active modules')); ?> (<?php e((string) count($modules)); ?>)</small>
|
|
</div>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th scope="col"><?php e(t('Module')); ?></th>
|
|
<th scope="col"><?php e(t('Version')); ?></th>
|
|
<th scope="col"><?php e(t('Default')); ?></th>
|
|
<th scope="col"><?php e(t('Dependencies')); ?></th>
|
|
<th scope="col"><?php e(t('Permissions')); ?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($modules as $module): ?>
|
|
<tr>
|
|
<td><code><?php e((string) $module['id']); ?></code></td>
|
|
<td><?php e((string) $module['version']); ?></td>
|
|
<td><?php e($module['enabled_by_default'] ? t('Yes') : t('No')); ?></td>
|
|
<td><?php e(!empty($module['requires']) ? implode(', ', $module['requires']) : '—'); ?></td>
|
|
<td><?php e((string) (int) $module['permissions_count']); ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<!-- Tab Panel: Permissions -->
|
|
<div data-tab-panel="permissions">
|
|
<div class="app-stats-table">
|
|
<div class="app-stats-table-header">
|
|
<small><?php e(t('Permission summary')); ?></small>
|
|
</div>
|
|
<table>
|
|
<tbody>
|
|
<tr>
|
|
<th scope="row"><?php e(t('Active permissions')); ?></th>
|
|
<td><?php e((string) (int) ($permissions['active_count'] ?? 0)); ?></td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row"><?php e(t('Inactive (orphaned) permissions')); ?></th>
|
|
<td><?php e((string) (int) ($permissions['inactive_count'] ?? 0)); ?></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<?php $bySource = $permissions['by_source'] ?? []; ?>
|
|
<?php if (!empty($bySource)): ?>
|
|
<div class="app-stats-table">
|
|
<div class="app-stats-table-header">
|
|
<small><?php e(t('Permissions by source')); ?></small>
|
|
</div>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th scope="col"><?php e(t('Source')); ?></th>
|
|
<th scope="col"><?php e(t('Count')); ?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($bySource as $source => $count): ?>
|
|
<tr>
|
|
<td><code><?php e((string) $source); ?></code></td>
|
|
<td><?php e((string) (int) $count); ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|