Dave Jarvis' Repositories

git clone https://repo.autonoma.ca/repo/treetrek.git

Adds pagination for commits

Author Dave Jarvis <email>
Date 2026-02-20 18:32:59 GMT-0800
Commit eb6df67ea660dc89b630b810577fa1f5eb21193c
Parent 58e41d4
pages/CommitsPage.php
echo '<div class="commit-list">';
- $start = $this->hash ?: $main['hash'];
- $count = 0;
- $nextHash = '';
- $prevHash = '';
-
- if( $start !== $main['hash'] ) {
- $prevHash = $this->getPreviousHash( $main['hash'], $start );
- }
+ $start = $this->hash !== '' ? $this->hash : $main['hash'];
+ $count = 0;
$this->git->history(
$start,
self::PER_PAGE,
- function( $commit ) use ( &$count, &$nextHash ) {
- $msg = htmlspecialchars( explode( "\n", $commit->message )[0] );
-
- $url = (new UrlBuilder())
- ->withRepo( $this->currentRepo['safe_name'] )
- ->withAction( 'commit' )
- ->withHash( $commit->sha )
- ->build();
-
- echo '<div class="commit-row">';
- echo '<a href="' . $url . '" class="sha">' .
- substr( $commit->sha, 0, 7 ) . '</a>';
- echo '<span class="message">' . $msg . '</span>';
- echo '<span class="meta">' .
- htmlspecialchars( $commit->author ) .
- ' &bull; ' . date( 'Y-m-d', $commit->date ) . '</span>';
- echo '</div>';
-
+ function( $commit ) use ( &$count ) {
+ $this->renderCommitRow( $commit );
$count++;
- $nextHash = $commit->parentSha;
}
);
echo '</div>';
- $this->renderPagination( $prevHash, $nextHash, $count );
+ $this->renderPagination( $main['hash'], $count );
}
}, $this->currentRepo );
}
- private function renderPagination(
- string $prevHash,
- string $nextHash,
- int $count
- ) {
- $hasPrev = $prevHash !== '';
- $hasNext = $count === self::PER_PAGE && $nextHash !== '';
+ private function renderCommitRow( object $commit ) {
+ $msg = htmlspecialchars( explode( "\n", $commit->message )[0] );
+ $url = $this->buildCommitUrl( $commit->sha );
+
+ echo '<div class="commit-row">';
+ echo '<a href="' . $url . '" class="sha">' .
+ substr( $commit->sha, 0, 7 ) . '</a>';
+ echo '<span class="message">' . $msg . '</span>';
+ echo '<span class="meta">' . htmlspecialchars( $commit->author ) .
+ ' &bull; ' . date( 'Y-m-d', $commit->date ) . '</span>';
+ echo '</div>';
+ }
+
+ private function renderPagination( string $mainHash, int $count ) {
+ $nav = $this->buildPaginationData( $mainHash, $count );
+ $pages = $nav['pages'];
+ $current = $nav['current'];
+ $hasNext = $nav['hasNext'];
+ $hasPrev = $current > 1;
if( $hasPrev || $hasNext ) {
echo '<div class="pagination">';
if( $hasPrev ) {
- $url = (new UrlBuilder())
- ->withRepo( $this->currentRepo['safe_name'] )
- ->withAction( 'commits' )
- ->withHash( $prevHash )
- ->build();
-
- echo '<a href="' . $url . '">&larr; Back</a>';
+ $prevSha = $pages[$current - 2];
+ $prevUrl = $this->buildPageUrl( $prevSha );
- if( $hasNext ) {
- echo ' &bull; ';
- }
+ echo '<a href="' . $prevUrl . '" class="page-link">&larr; Back</a>';
}
+
+ $this->renderPageNumbers( $pages, $current );
if( $hasNext ) {
- $url = (new UrlBuilder())
- ->withRepo( $this->currentRepo['safe_name'] )
- ->withAction( 'commits' )
- ->withHash( $nextHash )
- ->build();
+ $nextSha = $pages[$current];
+ $nextUrl = $this->buildPageUrl( $nextSha );
- echo '<a href="' . $url . '">Next &rarr;</a>';
+ echo '<a href="' . $nextUrl . '" class="page-link">Next &rarr;</a>';
}
echo '</div>';
}
}
- private function getPreviousHash( string $head, string $target ): string {
- $prevHash = '';
- $window = [];
+ private function renderPageNumbers( array $pages, int $current ) {
+ $total = count( $pages );
+ $actual = 1;
+ $start = 1;
+ $end = $total;
- if( $target !== '' && $target !== $head ) {
- $this->git->history(
- $head,
- PHP_INT_MAX,
- function( $commit ) use ( $target, &$window, &$prevHash ) {
- $result = true;
+ if( $total > 10 ) {
+ if( $current >= 5 ) {
+ $start = $current;
+ $end = $current + 10;
+ } else {
+ $start = 1;
+ $end = 10;
+ }
+ }
- if( $commit->sha === $target ) {
- if( !empty( $window ) ) {
- $prevHash = $window[0];
- }
+ if( $end > $total ) {
+ $end = $total;
+ }
- $result = false;
- }
+ while( $actual <= $total ) {
+ if( $actual >= $start && $actual <= $end ) {
+ if( $actual === $current ) {
+ echo '<span class="page-badge">(' . $actual . ')</span>';
+ } else {
+ $sha = $pages[$actual - 1];
+ $url = $this->buildPageUrl( $sha );
- if( $result ) {
- $window[] = $commit->sha;
+ echo '<a href="' . $url . '" class="page-link">' . $actual . '</a>';
+ }
+ }
- if( count( $window ) > self::PER_PAGE ) {
- array_shift( $window );
- }
- }
+ $actual++;
+ }
+ }
- return $result;
+ private function buildPaginationData( string $mainHash, int $count ): array {
+ $target = $this->hash !== '' ? $this->hash : $mainHash;
+ $pageHashes = [];
+ $commits = 0;
+ $currentPage = 1;
+ $found = false;
+ $result = [];
+
+ $this->git->history(
+ $mainHash,
+ PHP_INT_MAX,
+ function( $commit ) use (
+ $target,
+ &$pageHashes,
+ &$commits,
+ &$currentPage,
+ &$found
+ ) {
+ $continue = true;
+
+ if( $commits % self::PER_PAGE === 0 ) {
+ $pageHashes[] = $commit->sha;
}
- );
- }
- return $prevHash;
+ if( $commit->sha === $target ) {
+ $currentPage = count( $pageHashes );
+ $found = true;
+ }
+
+ if( $found && count( $pageHashes ) > $currentPage + 10 ) {
+ $continue = false;
+ }
+
+ if( $continue ) {
+ $commits++;
+ }
+
+ return $continue;
+ }
+ );
+
+ $result['pages'] = $pageHashes;
+ $result['current'] = $currentPage;
+ $result['hasNext'] = $count === self::PER_PAGE &&
+ isset( $pageHashes[$currentPage] );
+
+ return $result;
+ }
+
+ private function buildCommitUrl( string $targetHash ): string {
+ $builder = new UrlBuilder();
+ $result = '';
+
+ $builder->withRepo( $this->currentRepo['safe_name'] );
+ $builder->withAction( 'commit' );
+ $builder->withHash( $targetHash );
+
+ $result = $builder->build();
+
+ return $result;
+ }
+
+ private function buildPageUrl( string $targetHash ): string {
+ $builder = new UrlBuilder();
+ $result = '';
+
+ $builder->withRepo( $this->currentRepo['safe_name'] );
+ $builder->withAction( 'commits' );
+ $builder->withHash( $targetHash );
+
+ $result = $builder->build();
+
+ return $result;
}
}
styles/repo.css
}
+.pagination {
+ margin-top: 20px;
+ display: flex;
+ gap: 8px;
+ align-items: center;
+ justify-content: center;
+ flex-wrap: wrap;
+}
+
+.page-link {
+ color: #58a6ff;
+ text-decoration: none;
+ padding: 4px 8px;
+ border-radius: 6px;
+ border: 1px solid transparent;
+}
+
+.page-link:hover {
+ text-decoration: underline;
+ background: #1f242c;
+ border-color: #30363d;
+}
+
+.page-badge {
+ background: #21262d;
+ color: #f0f6fc;
+ padding: 4px 8px;
+ border-radius: 6px;
+ border: 1px solid #58a6ff;
+ font-weight: 600;
+}
+
Delta 165 lines added, 76 lines removed, 89-line increase