mirror of
git://f0xx.org/ac/ac-platform-php
synced 2026-07-29 00:57:39 +03:00
feat(platform): shared nav shell and common footer config
Signed-off-by: Anton Afanasyeu <a.afanasieff@gmail.com>
This commit is contained in:
@@ -21,11 +21,11 @@ return [
|
||||
|
||||
// --- Default left column when `left` is null ---
|
||||
// Use holder_name + holder_url for a safe link (holder HTML is escaped if used alone).
|
||||
'holder_name' => 'Anton Afanaasyeu',
|
||||
'holder_name' => 'Anton Afanasyeu',
|
||||
'holder_url' => 'https://f0xx.org',
|
||||
'holder' => null,
|
||||
'copyright_symbol' => "\u{00A9}",
|
||||
'show_year' => false,
|
||||
'copyright_symbol' => '',
|
||||
'show_year' => true,
|
||||
// null = current calendar year at render time (end of range).
|
||||
'year' => null,
|
||||
// Integer start year. With year_through_current: "2026 - current" (literal suffix).
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/nav_shell.php';
|
||||
|
||||
/**
|
||||
* Shared footer fragment for Android Cast web consoles and hub.
|
||||
*
|
||||
|
||||
126
platform/nav_shell.php
Normal file
126
platform/nav_shell.php
Normal file
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Shared left nav shell (hub / landing style) for all Android Cast web consoles.
|
||||
*
|
||||
* Usage: platform_render_nav_shell(['project_base' => '/app/androidcast_project', 'active' => 'builder', ...]);
|
||||
*/
|
||||
|
||||
function platform_nav_h(string $s): string
|
||||
{
|
||||
return htmlspecialchars($s, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
|
||||
}
|
||||
|
||||
/** @param array<string, mixed> $opts */
|
||||
function platform_render_nav_shell(array $opts = []): void
|
||||
{
|
||||
$projectBase = rtrim((string) ($opts['project_base'] ?? '/app/androidcast_project'), '/');
|
||||
$issuesBase = rtrim((string) ($opts['issues_base'] ?? $projectBase . '/issues'), '/');
|
||||
$active = (string) ($opts['active'] ?? '');
|
||||
$username = trim((string) ($opts['username'] ?? ''));
|
||||
$paneId = (string) ($opts['pane_id'] ?? 'nav-pane');
|
||||
$handleId = (string) ($opts['handle_id'] ?? 'nav-handle');
|
||||
$extraClass = trim((string) ($opts['extra_class'] ?? 'landing-left'));
|
||||
|
||||
$navClass = 'nav-pane' . ($extraClass !== '' ? ' ' . platform_nav_h($extraClass) : '');
|
||||
|
||||
$isActive = static fn(string $id): string => $active === $id ? ' active' : '';
|
||||
|
||||
$items = [
|
||||
['id' => 'console', 'href' => $issuesBase . '/?view=home', 'icon' => 'home', 'label' => 'Console', 'desc' => 'Crash triage home and workspace cards.', 'i18n' => 'nav.console', 'i18n_desc' => 'nav.console_desc'],
|
||||
['id' => 'git', 'href' => $projectBase . '/git/', 'icon' => 'git', 'label' => 'Git', 'desc' => 'Browse repos, branches, and tags.', 'i18n' => 'nav.git', 'i18n_desc' => 'nav.git_desc'],
|
||||
['id' => 'issues', 'href' => $issuesBase . '/?view=reports', 'icon' => 'reports', 'label' => 'Issues', 'desc' => 'Browse and triage crash reports.', 'i18n' => 'nav.issues', 'i18n_desc' => 'nav.issues_desc'],
|
||||
['id' => 'tickets', 'href' => $issuesBase . '/?view=tickets', 'icon' => 'tickets', 'label' => 'Tickets', 'desc' => 'Roadmap tasks, QA items, and tags.', 'i18n' => 'nav.tickets', 'i18n_desc' => 'nav.tickets_desc'],
|
||||
['id' => 'graphs', 'href' => $projectBase . '/graphs/', 'icon' => 'graphs', 'label' => 'Analytics', 'desc' => 'Sessions, live cast stats, and device activity.', 'i18n' => 'nav.graphs', 'i18n_desc' => 'nav.graphs_desc'],
|
||||
['id' => 'monitor', 'href' => $projectBase . '/monitor/', 'icon' => 'monitor', 'label' => 'Monitoring', 'desc' => 'Grafana dashboards — cluster health, alerts, exporters.', 'i18n' => 'nav.monitor', 'i18n_desc' => 'nav.monitor_desc'],
|
||||
['id' => 'live_sessions', 'href' => $issuesBase . '/?view=live_sessions', 'icon' => 'live', 'label' => 'Live sessions', 'desc' => 'Cast intents, join stats, session history.', 'i18n' => 'nav.live_sessions', 'i18n_desc' => 'nav.live_sessions_desc'],
|
||||
['id' => 'education', 'href' => $issuesBase . '/live/education', 'icon' => 'education', 'label' => 'Education (demo)', 'desc' => 'Browser screen-share trial (5 min).', 'i18n' => 'nav.education', 'i18n_desc' => 'nav.education_desc'],
|
||||
['id' => 'remote', 'href' => $issuesBase . '/?view=remote_access', 'icon' => 'remote', 'label' => 'Remote access', 'desc' => 'WireGuard sessions and device reachability.', 'i18n' => 'nav.remote', 'i18n_desc' => 'nav.remote_desc'],
|
||||
['id' => 'short_links', 'href' => $issuesBase . '/?view=short_links', 'icon' => 'link', 'label' => 'Short links', 'desc' => 'Mint bearer tokens and shorten URLs for s.f0xx.org.', 'i18n' => 'nav.short_links', 'i18n_desc' => 'nav.short_links_desc'],
|
||||
['id' => 'builder', 'href' => $projectBase . '/build/', 'icon' => 'builder', 'label' => 'Builder', 'desc' => 'Docker CI for APK baking and OTA artifacts.', 'i18n' => 'nav.builder', 'i18n_desc' => 'nav.builder_desc'],
|
||||
];
|
||||
?>
|
||||
<nav class="<?= $navClass ?>" id="<?= platform_nav_h($paneId) ?>" aria-label="Android Cast apps">
|
||||
<button type="button" class="nav-handle" id="<?= platform_nav_h($handleId) ?>"
|
||||
data-i18n-aria="nav.toggle" data-i18n-title="nav.toggle"
|
||||
aria-label="Navigation" title="Navigation">
|
||||
<span class="nav-icon nav-icon--menu" aria-hidden="true"></span>
|
||||
</button>
|
||||
<ul class="nav-list">
|
||||
<?php foreach ($items as $item): ?>
|
||||
<li>
|
||||
<a href="<?= platform_nav_h((string) $item['href']) ?>"
|
||||
class="nav-link<?= $isActive((string) $item['id']) ?>"
|
||||
data-i18n-title="<?= platform_nav_h((string) $item['i18n']) ?>"
|
||||
title="<?= platform_nav_h((string) $item['label']) ?>">
|
||||
<span class="nav-icon nav-icon--<?= platform_nav_h((string) $item['icon']) ?>" aria-hidden="true"></span>
|
||||
<span class="nav-text">
|
||||
<span class="nav-label" data-i18n="<?= platform_nav_h((string) $item['i18n']) ?>"><?= platform_nav_h((string) $item['label']) ?></span>
|
||||
<span class="nav-desc" data-i18n="<?= platform_nav_h((string) $item['i18n_desc']) ?>"><?= platform_nav_h((string) $item['desc']) ?></span>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<div class="nav-locale">
|
||||
<label class="toolbar-select locale-toolbar-select" data-i18n-title="lang.label" title="Language">
|
||||
<span class="locale-flag" id="locale-flag" aria-hidden="true">🇬🇧</span>
|
||||
<select class="lang-select" id="lang-select" data-i18n-aria="lang.label" aria-label="Language">
|
||||
<option value="en">EN</option>
|
||||
<option value="ru">RU</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<div class="nav-user">
|
||||
<?php if ($username !== ''): ?>
|
||||
<span class="nav-user-name" title="<?= platform_nav_h($username) ?>">
|
||||
<span class="nav-icon nav-icon--user" aria-hidden="true"></span>
|
||||
<span class="nav-label"><?= platform_nav_h($username) ?></span>
|
||||
</span>
|
||||
<a href="<?= platform_nav_h($issuesBase) ?>/account-security"
|
||||
class="nav-link"
|
||||
data-i18n-aria="nav.security" data-i18n-title="nav.security"
|
||||
aria-label="Security" title="Security">
|
||||
<span class="nav-icon nav-icon--user" aria-hidden="true"></span>
|
||||
<span class="nav-label" data-i18n="nav.security">Security</span>
|
||||
</a>
|
||||
<a href="<?= platform_nav_h($projectBase) ?>/logout"
|
||||
class="nav-link nav-link--logout"
|
||||
data-i18n-aria="nav.logout" data-i18n-title="nav.logout"
|
||||
aria-label="Logout" title="Logout">
|
||||
<span class="nav-icon nav-icon--logout" aria-hidden="true"></span>
|
||||
<span class="nav-label" data-i18n="nav.logout">Logout</span>
|
||||
</a>
|
||||
<?php else: ?>
|
||||
<a href="<?= platform_nav_h($projectBase) ?>/login"
|
||||
class="nav-link"
|
||||
data-i18n-aria="nav.sign_in" data-i18n-title="nav.sign_in"
|
||||
aria-label="Sign in" title="Sign in">
|
||||
<span class="nav-icon nav-icon--user" aria-hidden="true"></span>
|
||||
<span class="nav-label" data-i18n="nav.sign_in">Sign in</span>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</nav>
|
||||
<?php
|
||||
}
|
||||
|
||||
/** Map issues/build view names to nav_shell active ids. */
|
||||
function platform_nav_active_from_view(?string $view): string
|
||||
{
|
||||
$view = (string) ($view ?? '');
|
||||
return match ($view) {
|
||||
'home' => 'console',
|
||||
'reports', 'report' => 'issues',
|
||||
'tickets', 'ticket' => 'tickets',
|
||||
'graphs' => 'graphs',
|
||||
'live_sessions' => 'live_sessions',
|
||||
'live_education' => 'education',
|
||||
'remote_access' => 'remote',
|
||||
'short_links' => 'short_links',
|
||||
'media_pipelines' => 'console',
|
||||
'rbac' => 'console',
|
||||
default => '',
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user