| | <?php |
| | -require_once __DIR__ . '/BasePage.php'; |
| | +require_once __DIR__ . '/../File.php'; |
| | require_once __DIR__ . '/../UrlBuilder.php'; |
| | +require_once __DIR__ . '/Page.php'; |
| | |
| | -class HomePage extends BasePage { |
| | +abstract class BasePage implements Page { |
| | private $repositories; |
| | - private $git; |
| | + private $title; |
| | |
| | - public function __construct( array $repositories, Git $git ) { |
| | - parent::__construct( $repositories ); |
| | + public function __construct( array $repositories, string $title = '' ) { |
| | $this->repositories = $repositories; |
| | - $this->git = $git; |
| | - } |
| | - |
| | - public function render() { |
| | - $this->renderLayout( function() { |
| | - echo '<h2>Repositories</h2>'; |
| | - |
| | - if( empty( $this->repositories ) ) { |
| | - echo '<div class="empty-state">No repositories found.</div>'; |
| | - } else { |
| | - echo '<div class="repo-grid">'; |
| | - |
| | - foreach( $this->repositories as $repo ) { |
| | - $this->renderRepoCard( $repo ); |
| | - } |
| | - |
| | - echo '</div>'; |
| | - } |
| | - } ); |
| | + $this->title = $title; |
| | } |
| | - |
| | - private function renderRepoCard( $repo ) { |
| | - $this->git->setRepository( $repo['path'] ); |
| | - |
| | - $main = $this->git->getMainBranch(); |
| | - $stats = [ |
| | - 'branches' => 0, |
| | - 'tags' => 0 |
| | - ]; |
| | |
| | - $this->git->eachBranch( function() use ( &$stats ) { |
| | - $stats['branches']++; |
| | - } ); |
| | + protected function renderLayout( |
| | + $contentCallback, |
| | + array $currentRepo = [] |
| | + ) { |
| | + $siteTitle = Config::SITE_TITLE; |
| | + $pageTitle = $this->title |
| | + ? ' - ' . htmlspecialchars( $this->title ) |
| | + : ''; |
| | |
| | - $this->git->eachTag( function() use ( &$stats ) { |
| | - $stats['tags']++; |
| | - } ); |
| | + ?> |
| | +<!DOCTYPE html> |
| | +<html lang="en"> |
| | +<head> |
| | + <meta charset="UTF-8"> |
| | + <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| | + <title><?php echo $siteTitle . $pageTitle; ?></title> |
| | + <link rel="stylesheet" |
| | + href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/7.0.1/css/all.min.css"> |
| | + <link rel="stylesheet" href="/styles/repo.css"> |
| | +</head> |
| | +<body> |
| | +<div class="container"> |
| | + <header> |
| | + <h1><?php echo Config::SITE_TITLE; ?></h1> |
| | |
| | - $url = (new UrlBuilder())->withRepo( $repo['safe_name'] )->build(); |
| | - echo '<a href="' . $url . '" class="repo-card">'; |
| | - echo '<h3>' . htmlspecialchars( $repo['name'] ) . '</h3>'; |
| | - echo '<p class="repo-meta">'; |
| | + <?php if( $currentRepo ) { ?> |
| | + <input type="checkbox" id="clone-toggle" class="clone-checkbox"> |
| | + <?php } ?> |
| | |
| | - $branchLabel = $stats['branches'] === 1 ? 'branch' : 'branches'; |
| | - $tagLabel = $stats['tags'] === 1 ? 'tag' : 'tags'; |
| | + <nav class="nav"> |
| | + <?php if( $currentRepo ) { ?> |
| | + <a href="<?php echo (new UrlBuilder())->build(); ?>">Home</a> |
| | + <?php $safeName = $currentRepo['safe_name']; ?> |
| | + <a href="<?php echo (new UrlBuilder()) |
| | + ->withRepo( $safeName ) |
| | + ->withAction( 'tree' ) |
| | + ->build(); ?>">Files</a> |
| | + <a href="<?php echo (new UrlBuilder()) |
| | + ->withRepo( $safeName ) |
| | + ->withAction( 'commits' ) |
| | + ->build(); ?>">Commits</a> |
| | + <a href="<?php echo (new UrlBuilder()) |
| | + ->withRepo( $safeName ) |
| | + ->withAction( 'tags' ) |
| | + ->build(); ?>">Tags</a> |
| | |
| | - echo $stats['branches'] . ' ' . $branchLabel . ', ' . |
| | - $stats['tags'] . ' ' . $tagLabel; |
| | + <label for="clone-toggle" class="clone-link">Clone</label> |
| | + <?php } ?> |
| | |
| | - if( $main ) { |
| | - echo ', '; |
| | + <?php if( $currentRepo ) { ?> |
| | + <div class="repo-selector"> |
| | + <label>Repository:</label> |
| | + <select onchange="<?php echo (new UrlBuilder()) |
| | + ->withSwitcher( 'this.value' ) |
| | + ->build(); ?>"> |
| | + <?php foreach( $this->repositories as $r ) { ?> |
| | + <option |
| | + value="<?php echo htmlspecialchars( $r['safe_name'] ); ?>" |
| | + <?php |
| | + echo $r['safe_name'] === $currentRepo['safe_name'] |
| | + ? 'selected' |
| | + : ''; |
| | + ?>> |
| | + <?php echo htmlspecialchars( $r['name'] ); ?> |
| | + </option> |
| | + <?php } ?> |
| | + </select> |
| | + </div> |
| | + <?php } ?> |
| | + </nav> |
| | |
| | - $this->git->history( 'HEAD', 1, function( $c ) use ( $repo ) { |
| | - $renderer = new HtmlFileRenderer( $repo['safe_name'] ); |
| | - $renderer->renderTime( $c->date ); |
| | - } ); |
| | - } |
| | + <?php if( $currentRepo ) { ?> |
| | + <div class="clone-region"> |
| | + <div class="clone-wrapper"> |
| | + <?php |
| | + $cloneCmd = 'git clone https://repo.autonoma.ca/repo/' . |
| | + $currentRepo['safe_name'] . '.git'; |
| | + ?> |
| | + <span class="clone-sizer"><?php echo htmlspecialchars( $cloneCmd ); ?></span> |
| | + <input type="text" class="clone-input" readonly |
| | + value="<?php echo htmlspecialchars( $cloneCmd ); ?>"> |
| | + </div> |
| | + </div> |
| | + <?php } ?> |
| | + </header> |
| | |
| | - echo '</p>'; |
| | + <?php call_user_func( $contentCallback ); ?> |
| | |
| | - $descPath = $repo['path'] . '/description'; |
| | +</div> |
| | +</body> |
| | +</html> |
| | + <?php |
| | + } |
| | |
| | - if( file_exists( $descPath ) ) { |
| | - $description = trim( file_get_contents( $descPath ) ); |
| | + protected function renderBreadcrumbs( array $repo, array $trail = [] ) { |
| | + $repoUrl = (new UrlBuilder())->withRepo( $repo['safe_name'] )->build(); |
| | |
| | - if( $description !== '' ) { |
| | - echo '<p style="margin-top: 1.5em;">' . |
| | - htmlspecialchars( $description ) . '</p>'; |
| | - } |
| | - } |
| | + $parts = array_merge( |
| | + [ |
| | + '<a href="' . $repoUrl . '" class="repo-breadcrumb">' . |
| | + htmlspecialchars( $repo['name'] ) . '</a>' |
| | + ], |
| | + $trail |
| | + ); |
| | |
| | - echo '</a>'; |
| | + echo '<div class="breadcrumb">' . implode( ' / ', $parts ) . '</div>'; |
| | } |
| | } |