forked from fa/breadcrumb-the-shire
refactor(system-info): reduce to Stripe-style status page
Reduce admin/system-info to a single focused status view: overall status banner, components list from existing health checks, and an environment meta table. Drops the Modules and Permissions tabs — those were dev-diagnostics already available via CLI. - Remove SystemInfoService + its test; wire the action directly to SystemHealthService and build meta inline - Extend SystemHealthService with per-check label + description so the UI speaks in customer terms while the CLI doctor path stays compatible - Rebuild the view on existing app-stats-table + app-empty-state primitives; add a small app-status-banner component for the headline signal - Align help-center nav label and i18n keys (de/en) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,20 +2,44 @@
|
||||
|
||||
use MintyPHP\Buffer;
|
||||
use MintyPHP\Service\Access\OperationsAuthorizationPolicy;
|
||||
use MintyPHP\Service\System\SystemInfoService;
|
||||
use MintyPHP\Service\System\SystemHealthService;
|
||||
use MintyPHP\Support\Guard;
|
||||
|
||||
Guard::requireAbilityOrForbidden(OperationsAuthorizationPolicy::ABILITY_ADMIN_SYSTEM_INFO_VIEW);
|
||||
|
||||
$pageData = app(SystemInfoService::class)->buildPageData();
|
||||
$overview = $pageData['overview'] ?? [];
|
||||
$modules = $pageData['modules'] ?? [];
|
||||
$permissions = $pageData['permissions'] ?? [];
|
||||
$healthChecks = $overview['health_checks'] ?? [];
|
||||
$checks = app(SystemHealthService::class)->runAll();
|
||||
|
||||
Buffer::set('title', t('System Info'));
|
||||
$overall = 'ok';
|
||||
foreach ($checks as $check) {
|
||||
if ($check['status'] === 'fail') {
|
||||
$overall = 'fail';
|
||||
break;
|
||||
}
|
||||
if ($check['status'] === 'warn') {
|
||||
$overall = 'warn';
|
||||
}
|
||||
}
|
||||
|
||||
$environment = 'unknown';
|
||||
if (defined('APP_ENV')) {
|
||||
$environment = (string) constant('APP_ENV');
|
||||
} else {
|
||||
$envVar = getenv('APP_ENV');
|
||||
if (is_string($envVar) && $envVar !== '') {
|
||||
$environment = $envVar;
|
||||
}
|
||||
}
|
||||
|
||||
$meta = [
|
||||
'php_version' => PHP_VERSION,
|
||||
'environment' => $environment,
|
||||
];
|
||||
|
||||
$lastChecked = date('Y-m-d H:i:s');
|
||||
|
||||
Buffer::set('title', t('System status'));
|
||||
|
||||
$breadcrumbs = [
|
||||
['label' => t('Home'), 'path' => 'admin'],
|
||||
['label' => t('System Info')],
|
||||
['label' => t('System status')],
|
||||
];
|
||||
|
||||
@@ -1,180 +1,100 @@
|
||||
<?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
|
||||
* @var list<array{status: string, name: string, message: string, label: string, description: string}> $checks
|
||||
* @var string $overall
|
||||
* @var array{php_version: string, environment: string} $meta
|
||||
* @var string $lastChecked
|
||||
*/
|
||||
|
||||
$overview = $overview ?? [];
|
||||
$modules = $modules ?? [];
|
||||
$permissions = $permissions ?? [];
|
||||
$healthChecks = $healthChecks ?? [];
|
||||
$checks = $checks ?? [];
|
||||
$overall = $overall ?? 'ok';
|
||||
$meta = $meta ?? ['php_version' => '', 'environment' => ''];
|
||||
$lastChecked = $lastChecked ?? '';
|
||||
|
||||
$bannerTitles = [
|
||||
'ok' => t('All systems operational'),
|
||||
'warn' => t('Degraded service'),
|
||||
'fail' => t('System outage detected'),
|
||||
];
|
||||
$bannerIcons = [
|
||||
'ok' => 'bi-check-circle-fill',
|
||||
'warn' => 'bi-exclamation-triangle-fill',
|
||||
'fail' => 'bi-x-circle-fill',
|
||||
];
|
||||
$bannerVariants = [
|
||||
'ok' => 'success',
|
||||
'warn' => 'warn',
|
||||
'fail' => 'danger',
|
||||
];
|
||||
$statusBadgeLabel = [
|
||||
'ok' => t('OK'),
|
||||
'warn' => t('Warning'),
|
||||
'fail' => t('Fail'),
|
||||
];
|
||||
|
||||
$bannerTitle = $bannerTitles[$overall] ?? $bannerTitles['ok'];
|
||||
$bannerIcon = $bannerIcons[$overall] ?? $bannerIcons['ok'];
|
||||
$bannerVariant = $bannerVariants[$overall] ?? $bannerVariants['ok'];
|
||||
|
||||
?>
|
||||
<div class="app-dashboard-titlebar">
|
||||
<h1><?php e(t('System Info')); ?></h1>
|
||||
<h1><?php e(t('System status')); ?></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>
|
||||
<section class="app-status-banner" data-variant="<?php e($bannerVariant); ?>" aria-live="polite">
|
||||
<i class="bi <?php e($bannerIcon); ?>" aria-hidden="true"></i>
|
||||
<div class="app-status-banner-text">
|
||||
<h2><?php e($bannerTitle); ?></h2>
|
||||
<small><?php e(t('Last checked')); ?>: <?php e($lastChecked); ?></small>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="app-stats-table">
|
||||
<div class="app-stats-table-header">
|
||||
<small><?php e(t('Components')); ?></small>
|
||||
</div>
|
||||
<?php if (empty($checks)): ?>
|
||||
<?php $emptyState = ['message' => t('No health checks available.'), 'size' => 'compact']; require templatePath('partials/app-empty-state.phtml'); ?>
|
||||
<?php else: ?>
|
||||
<table>
|
||||
<tbody>
|
||||
<?php foreach ($checks as $check):
|
||||
$status = (string) ($check['status'] ?? 'fail');
|
||||
$label = (string) ($check['label'] ?? $check['name'] ?? '');
|
||||
$description = (string) ($check['description'] ?? $check['message'] ?? '');
|
||||
$variant = $bannerVariants[$status] ?? 'danger';
|
||||
$badgeLabel = $statusBadgeLabel[$status] ?? t('Fail');
|
||||
?>
|
||||
<tr>
|
||||
<td>
|
||||
<strong><?php e(t($label)); ?></strong>
|
||||
<small class="app-status-description"><?php e(t($description)); ?></small>
|
||||
</td>
|
||||
<td class="app-status-badge-cell">
|
||||
<span class="badge" data-variant="<?php e($variant); ?>"><?php e($badgeLabel); ?></span>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<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($meta['php_version']); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><?php e(t('Environment')); ?></th>
|
||||
<td><?php e($meta['environment']); ?></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user