now paging in tha house

alphons <alphons@heijden.com> 26 Jul 2026, 16:48
3358ca8412540a2628565a3d90d6cda9a573b683
25 files changed
  • src/GitServer/Localization/ar.json
  • src/GitServer/Localization/de.json
  • src/GitServer/Localization/en.json
  • src/GitServer/Localization/es.json
  • src/GitServer/Localization/fr.json
  • src/GitServer/Localization/ja.json
  • src/GitServer/Localization/nl.json
  • src/GitServer/Localization/pt.json
  • src/GitServer/Localization/ru.json
  • src/GitServer/Localization/zh.json
  • src/GitServer/Services/GitServerOptions.cs
  • src/GitServer/Services/RepositoryService.cs
  • src/GitServer/appsettings.json
  • src/GitServer/gitserver.db-shm
  • src/GitServer/gitserver.db-wal
  • src/GitServer/wwwroot/Explore.cshtml
  • src/GitServer/wwwroot/Explore.cshtml.cs
  • src/GitServer/wwwroot/ExploreUsers.cshtml
  • src/GitServer/wwwroot/ExploreUsers.cshtml.cs
  • src/GitServer/wwwroot/Index.cshtml
  • src/GitServer/wwwroot/Index.cshtml.cs
  • src/GitServer/wwwroot/Shared/_Pagination.cshtml
  • src/GitServer/wwwroot/User/Profile.cshtml
  • src/GitServer/wwwroot/User/Profile.cshtml.cs
  • src/GitServer/wwwroot/css/main.css
diff --git a/src/GitServer/Localization/ar.json b/src/GitServer/Localization/ar.json
index 4a5e6a7..58be608 100644
--- a/src/GitServer/Localization/ar.json
+++ b/src/GitServer/Localization/ar.json
@@ -30,6 +30,8 @@
"repo_card_collaborators": "مشارك مع:",
"index_recent_repos": "المستودعات الأخيرة",
+ "index_all_repos": "جميع المستودعات العامة",
+ "index_all_my_repos": "جميع مستودعاتي",
"index_empty": "لا توجد مستودعات عامة حتى الآن.",
"index_empty_create": "أنشئ أول مستودع!",
diff --git a/src/GitServer/Localization/de.json b/src/GitServer/Localization/de.json
index 65fea7f..5601b79 100644
--- a/src/GitServer/Localization/de.json
+++ b/src/GitServer/Localization/de.json
@@ -30,6 +30,8 @@
"repo_card_collaborators": "Geteilt mit:",
"index_recent_repos": "Neueste Repositories",
+ "index_all_repos": "Alle öffentlichen Repositories",
+ "index_all_my_repos": "Alle meine Repositories",
"index_empty": "Noch keine öffentlichen Repositories.",
"index_empty_create": "Erstes erstellen!",
diff --git a/src/GitServer/Localization/en.json b/src/GitServer/Localization/en.json
index 5932ee4..3416710 100644
--- a/src/GitServer/Localization/en.json
+++ b/src/GitServer/Localization/en.json
@@ -32,6 +32,8 @@
"repo_card_collaborators": "Shared with:",
"index_recent_repos": "Recent repositories",
+ "index_all_repos": "All public repositories",
+ "index_all_my_repos": "All my repositories",
"index_empty": "No public repositories yet.",
"index_empty_create": "Create the first one!",
diff --git a/src/GitServer/Localization/es.json b/src/GitServer/Localization/es.json
index ed0d512..fda4fe4 100644
--- a/src/GitServer/Localization/es.json
+++ b/src/GitServer/Localization/es.json
@@ -30,6 +30,8 @@
"repo_card_collaborators": "Compartido con:",
"index_recent_repos": "Repositorios recientes",
+ "index_all_repos": "Todos los repositorios públicos",
+ "index_all_my_repos": "Todos mis repositorios",
"index_empty": "Aún no hay repositorios públicos.",
"index_empty_create": "¡Crea el primero!",
diff --git a/src/GitServer/Localization/fr.json b/src/GitServer/Localization/fr.json
index 86d1839..5eb44f1 100644
--- a/src/GitServer/Localization/fr.json
+++ b/src/GitServer/Localization/fr.json
@@ -30,6 +30,8 @@
"repo_card_collaborators": "Partagé avec :",
"index_recent_repos": "Dépôts récents",
+ "index_all_repos": "Tous les dépôts publics",
+ "index_all_my_repos": "Tous mes dépôts",
"index_empty": "Aucun dépôt public pour l'instant.",
"index_empty_create": "Créer le premier !",
diff --git a/src/GitServer/Localization/ja.json b/src/GitServer/Localization/ja.json
index ac790ea..000c620 100644
--- a/src/GitServer/Localization/ja.json
+++ b/src/GitServer/Localization/ja.json
@@ -30,6 +30,8 @@
"repo_card_collaborators": "共有先:",
"index_recent_repos": "最近のリポジトリ",
+ "index_all_repos": "すべての公開リポジトリ",
+ "index_all_my_repos": "自分のすべてのリポジトリ",
"index_empty": "公開リポジトリはまだありません。",
"index_empty_create": "最初のものを作成!",
diff --git a/src/GitServer/Localization/nl.json b/src/GitServer/Localization/nl.json
index 25b705e..89c9598 100644
--- a/src/GitServer/Localization/nl.json
+++ b/src/GitServer/Localization/nl.json
@@ -32,6 +32,8 @@
"repo_card_collaborators": "Gedeeld met:",
"index_recent_repos": "Recente repositories",
+ "index_all_repos": "Alle publieke repositories",
+ "index_all_my_repos": "Al mijn repositories",
"index_empty": "Nog geen publieke repositories.",
"index_empty_create": "Maak de eerste aan!",
diff --git a/src/GitServer/Localization/pt.json b/src/GitServer/Localization/pt.json
index 84faed3..5ee03df 100644
--- a/src/GitServer/Localization/pt.json
+++ b/src/GitServer/Localization/pt.json
@@ -30,6 +30,8 @@
"repo_card_collaborators": "Compartilhado com:",
"index_recent_repos": "Repositórios recentes",
+ "index_all_repos": "Todos os repositórios públicos",
+ "index_all_my_repos": "Todos os meus repositórios",
"index_empty": "Nenhum repositório público ainda.",
"index_empty_create": "Crie o primeiro!",
diff --git a/src/GitServer/Localization/ru.json b/src/GitServer/Localization/ru.json
index 7de6a44..370b209 100644
--- a/src/GitServer/Localization/ru.json
+++ b/src/GitServer/Localization/ru.json
@@ -30,6 +30,8 @@
"repo_card_collaborators": "Доступ есть у:",
"index_recent_repos": "Последние репозитории",
+ "index_all_repos": "Все публичные репозитории",
+ "index_all_my_repos": "Все мои репозитории",
"index_empty": "Публичных репозиториев пока нет.",
"index_empty_create": "Создать первый!",
diff --git a/src/GitServer/Localization/zh.json b/src/GitServer/Localization/zh.json
index 97ea24c..24a0a71 100644
--- a/src/GitServer/Localization/zh.json
+++ b/src/GitServer/Localization/zh.json
@@ -30,6 +30,8 @@
"repo_card_collaborators": "共享给:",
"index_recent_repos": "最近的仓库",
+ "index_all_repos": "所有公开仓库",
+ "index_all_my_repos": "我的所有仓库",
"index_empty": "暂无公开仓库。",
"index_empty_create": "创建第一个!",
diff --git a/src/GitServer/Services/GitServerOptions.cs b/src/GitServer/Services/GitServerOptions.cs
index 5c181bd..69d2966 100644
--- a/src/GitServer/Services/GitServerOptions.cs
+++ b/src/GitServer/Services/GitServerOptions.cs
@@ -25,4 +25,16 @@ public class GitServerOptions
/// <summary>Max size in MB for a single push (Kestrel request body). Null = unlimited.
/// Note: IIS's own limit in Web.Config (maxAllowedContentLength) is separate and not driven by this setting.</summary>
public long? MaxPushSizeMb { get; set; } = null;
+
+ /// <summary>Number of items per page on the /explore repo listing.</summary>
+ public int ExploreRepoPageSize { get; set; } = 10;
+
+ /// <summary>Number of items per page on the /explore/users listing.</summary>
+ public int ExploreUserPageSize { get; set; } = 10;
+
+ /// <summary>Number of repos shown on the home page's "recent repositories" list.</summary>
+ public int IndexRecentReposCount { get; set; } = 20;
+
+ /// <summary>Number of items per page on a user's profile repository listing.</summary>
+ public int ProfileRepoPageSize { get; set; } = 10;
}
diff --git a/src/GitServer/Services/RepositoryService.cs b/src/GitServer/Services/RepositoryService.cs
index d6029b5..1dbb8f1 100644
--- a/src/GitServer/Services/RepositoryService.cs
+++ b/src/GitServer/Services/RepositoryService.cs
@@ -85,11 +85,12 @@ public class RepositoryService(AppDbContext db,
.ToListAsync();
}
- public async Task<List<Repository>> GetUserReposAsync(string userId, bool includePrivate, string? query = null)
+ public async Task<List<Repository>> GetUserReposAsync(string userId, bool includePrivate, string? query = null, int skip = 0, int take = int.MaxValue)
{
var q = _db.Repositories
.Include(r => r.Owner)
.Include(r => r.Accesses).ThenInclude(a => a.User)
+ .Include(r => r.Accesses).ThenInclude(a => a.Group)
.Where(r => r.OwnerId == userId);
if (!includePrivate)
@@ -103,7 +104,7 @@ public class RepositoryService(AppDbContext db,
(r.Description != null && r.Description.ToLower().Contains(lower)));
}
- return await q.OrderByDescending(r => r.UpdatedAt).ToListAsync();
+ return await q.OrderByDescending(r => r.UpdatedAt).Skip(skip).Take(take).ToListAsync();
}
public async Task<List<Repository>> SearchAsync(string query, int skip = 0, int take = 20)
diff --git a/src/GitServer/appsettings.json b/src/GitServer/appsettings.json
index 4d64281..25a4a78 100644
--- a/src/GitServer/appsettings.json
+++ b/src/GitServer/appsettings.json
@@ -5,7 +5,11 @@
"AllowRegistration": true,
"GitPathPrefix": "",
"DefaultPrivateOnAutoCreate": true,
- "MaxPushSizeMb": 2048
+ "MaxPushSizeMb": 2048,
+ "ExploreRepoPageSize": 20,
+ "ExploreUserPageSize": 20,
+ "ProfileRepoPageSize": 20,
+ "IndexRecentReposCount": 5
},
"Authentication": {
"KeysPath": "C:\\Data\\DataProtection\\Keys",
diff --git a/src/GitServer/gitserver.db-shm b/src/GitServer/gitserver.db-shm
index 8b01324..11b0e42 100644
Binary files a/src/GitServer/gitserver.db-shm and b/src/GitServer/gitserver.db-shm differ
diff --git a/src/GitServer/gitserver.db-wal b/src/GitServer/gitserver.db-wal
index 8254da9..6791595 100644
Binary files a/src/GitServer/gitserver.db-wal and b/src/GitServer/gitserver.db-wal differ
diff --git a/src/GitServer/wwwroot/Explore.cshtml b/src/GitServer/wwwroot/Explore.cshtml
index db85b91..b1a74eb 100644
--- a/src/GitServer/wwwroot/Explore.cshtml
+++ b/src/GitServer/wwwroot/Explore.cshtml
@@ -21,6 +21,15 @@
<p class="search-results-info">@Model.Repos.Count @L["explore_results_for"] "<strong>@Model.Query</strong>"</p>
}
+ @{
+ var prevUrl = $"/explore?q={Uri.EscapeDataString(Model.Query)}&p={Model.Page - 1}";
+ var nextUrl = $"/explore?q={Uri.EscapeDataString(Model.Query)}&p={Model.Page + 1}";
+ }
+ @if (Model.Page > 0 || Model.HasNextPage)
+ {
+ @await Html.PartialAsync("_Pagination", (Model.Page, Model.HasNextPage, prevUrl, nextUrl))
+ }
+
@if (Model.Repos.Any())
{
<div class="repo-list">
@@ -31,6 +40,7 @@
<a class="repo-name" href="/@repo.Owner.UserName/@repo.Name">
@repo.Owner.UserName / @repo.Name
</a>
+ <span class="badge badge-success">@L["badge_public"]</span>
</div>
@if (!string.IsNullOrEmpty(repo.Description))
{
@@ -43,19 +53,13 @@
</div>
}
</div>
- <div class="pagination">
- @if (Model.Page > 0)
- {
- <a class="btn btn-secondary" href="/explore?q=@Model.Query&page=@(Model.Page - 1)">@L["pagination_prev"]</a>
- }
- @if (Model.Repos.Count == 20)
- {
- <a class="btn btn-secondary" href="/explore?q=@Model.Query&page=@(Model.Page + 1)">@L["pagination_next"]</a>
- }
- </div>
}
- else if (!string.IsNullOrEmpty(Model.Query))
+ else if (!string.IsNullOrEmpty(Model.Query) || Model.Page > 0)
{
<div class="empty-state">@L["explore_no_results"]</div>
}
+ @if (Model.Page > 0 || Model.HasNextPage)
+ {
+ @await Html.PartialAsync("_Pagination", (Model.Page, Model.HasNextPage, prevUrl, nextUrl))
+ }
</div>
diff --git a/src/GitServer/wwwroot/Explore.cshtml.cs b/src/GitServer/wwwroot/Explore.cshtml.cs
index e6cc9e3..4166a4f 100644
--- a/src/GitServer/wwwroot/Explore.cshtml.cs
+++ b/src/GitServer/wwwroot/Explore.cshtml.cs
@@ -1,23 +1,28 @@
using GitServer.Models;
using GitServer.Services;
using Microsoft.AspNetCore.Mvc.RazorPages;
+using Microsoft.Extensions.Options;
namespace GitServer.wwwroot;
-public class ExploreModel(RepositoryService repos) : PageModel
+public class ExploreModel(RepositoryService repos, IOptions<GitServerOptions> options) : PageModel
{
public string Query { get; set; } = "";
public new int Page { get; set; }
+ public int PageSize { get; } = options.Value.ExploreRepoPageSize;
public List<Repository> Repos { get; set; } = [];
+ public bool HasNextPage { get; set; }
- public async Task OnGetAsync(string? q, int page = 0)
+ public async Task OnGetAsync(string? q, int p = 0)
{
Query = q ?? "";
- Page = page;
+ Page = p;
- if (!string.IsNullOrWhiteSpace(Query))
- Repos = await repos.SearchAsync(Query, page * 20, 20);
- else
- Repos = await repos.GetPublicReposAsync(page * 20, 20);
+ var fetched = !string.IsNullOrWhiteSpace(Query)
+ ? await repos.SearchAsync(Query, p * PageSize, PageSize + 1)
+ : await repos.GetPublicReposAsync(p * PageSize, PageSize + 1);
+
+ HasNextPage = fetched.Count > PageSize;
+ Repos = fetched.Take(PageSize).ToList();
}
}
diff --git a/src/GitServer/wwwroot/ExploreUsers.cshtml b/src/GitServer/wwwroot/ExploreUsers.cshtml
index b0fa307..b2d6eed 100644
--- a/src/GitServer/wwwroot/ExploreUsers.cshtml
+++ b/src/GitServer/wwwroot/ExploreUsers.cshtml
@@ -21,6 +21,15 @@
<p class="search-results-info">@Model.Users.Count @L["explore_results_for"] "<strong>@Model.Query</strong>"</p>
}
+ @{
+ var prevUrl = $"/explore/users?q={Uri.EscapeDataString(Model.Query)}&p={Model.Page - 1}";
+ var nextUrl = $"/explore/users?q={Uri.EscapeDataString(Model.Query)}&p={Model.Page + 1}";
+ }
+ @if (Model.Page > 0 || Model.HasNextPage)
+ {
+ @await Html.PartialAsync("_Pagination", (Model.Page, Model.HasNextPage, prevUrl, nextUrl))
+ }
+
@if (Model.Users.Any())
{
<div class="user-list">
@@ -52,19 +61,13 @@
</a>
}
</div>
- <div class="pagination">
- @if (Model.Page > 0)
- {
- <a class="btn btn-secondary" href="/explore/users?q=@Model.Query&page=@(Model.Page - 1)">@L["pagination_prev"]</a>
- }
- @if (Model.Users.Count == 20)
- {
- <a class="btn btn-secondary" href="/explore/users?q=@Model.Query&page=@(Model.Page + 1)">@L["pagination_next"]</a>
- }
- </div>
}
else
{
<div class="empty-state">@L["explore_no_results"]</div>
}
+ @if (Model.Page > 0 || Model.HasNextPage)
+ {
+ @await Html.PartialAsync("_Pagination", (Model.Page, Model.HasNextPage, prevUrl, nextUrl))
+ }
</div>
diff --git a/src/GitServer/wwwroot/ExploreUsers.cshtml.cs b/src/GitServer/wwwroot/ExploreUsers.cshtml.cs
index dffacf9..739ee4b 100644
--- a/src/GitServer/wwwroot/ExploreUsers.cshtml.cs
+++ b/src/GitServer/wwwroot/ExploreUsers.cshtml.cs
@@ -1,20 +1,24 @@
using GitServer.Data;
using GitServer.Models;
+using GitServer.Services;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Options;
namespace GitServer.wwwroot;
-public class ExploreUsersModel(AppDbContext db) : PageModel
+public class ExploreUsersModel(AppDbContext db, IOptions<GitServerOptions> options) : PageModel
{
public string Query { get; set; } = "";
public new int Page { get; set; }
+ public int PageSize { get; } = options.Value.ExploreUserPageSize;
public List<AppUser> Users { get; set; } = [];
+ public bool HasNextPage { get; set; }
- public async Task OnGetAsync(string? q, int page = 0)
+ public async Task OnGetAsync(string? q, int p = 0)
{
Query = q ?? "";
- Page = page;
+ Page = p;
var query = db.Users.Where(u => u.EmailConfirmed);
@@ -29,10 +33,13 @@ public class ExploreUsersModel(AppDbContext db) : PageModel
(u.Country != null && u.Country.ToLower().Contains(lower)));
}
- Users = await query
+ var fetched = await query
.OrderBy(u => u.UserName)
- .Skip(page * 20)
- .Take(20)
+ .Skip(p * PageSize)
+ .Take(PageSize + 1)
.ToListAsync();
+
+ HasNextPage = fetched.Count > PageSize;
+ Users = fetched.Take(PageSize).ToList();
}
}
diff --git a/src/GitServer/wwwroot/Index.cshtml b/src/GitServer/wwwroot/Index.cshtml
index fd67ab5..8b79904 100644
--- a/src/GitServer/wwwroot/Index.cshtml
+++ b/src/GitServer/wwwroot/Index.cshtml
@@ -45,5 +45,15 @@
</div>
}
</div>
+ <p class="text-muted">
+ @if (Model.CurrentUserName != null)
+ {
+ <a href="/User/@Model.CurrentUserName">@L["index_all_my_repos"]</a>
+ }
+ else
+ {
+ <a href="/explore">@L["index_all_repos"]</a>
+ }
+ </p>
}
</div>
diff --git a/src/GitServer/wwwroot/Index.cshtml.cs b/src/GitServer/wwwroot/Index.cshtml.cs
index 766da29..d124446 100644
--- a/src/GitServer/wwwroot/Index.cshtml.cs
+++ b/src/GitServer/wwwroot/Index.cshtml.cs
@@ -2,29 +2,34 @@
using GitServer.Services;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc.RazorPages;
+using Microsoft.Extensions.Options;
namespace GitServer.wwwroot;
-public class IndexModel(RepositoryService repos, UserManager<AppUser> userManager) : PageModel
+public class IndexModel(RepositoryService repos, UserManager<AppUser> userManager, IOptions<GitServerOptions> options) : PageModel
{
+ private readonly int _recentCount = options.Value.IndexRecentReposCount;
+
public List<Repository> Repos { get; set; } = [];
+ public string? CurrentUserName { get; set; }
public async Task OnGetAsync()
{
- var userId = userManager.GetUserId(User);
- if (userId != null)
+ var currentUser = await userManager.GetUserAsync(User);
+ if (currentUser != null)
{
// Show own repos + public repos
- var myRepos = await repos.GetUserReposAsync(userId, includePrivate: true);
- var publicRepos = await repos.GetPublicReposAsync(0, 30);
+ CurrentUserName = currentUser.UserName;
+ var myRepos = await repos.GetUserReposAsync(currentUser.Id, includePrivate: true);
+ var publicRepos = await repos.GetPublicReposAsync(0, _recentCount + 10);
Repos = [.. myRepos.Concat(publicRepos)
.DistinctBy(r => r.Id)
.OrderByDescending(r => r.UpdatedAt)
- .Take(20)];
+ .Take(_recentCount)];
}
else
{
- Repos = await repos.GetPublicReposAsync(0, 20);
+ Repos = await repos.GetPublicReposAsync(0, _recentCount);
}
}
}
diff --git a/src/GitServer/wwwroot/Shared/_Pagination.cshtml b/src/GitServer/wwwroot/Shared/_Pagination.cshtml
new file mode 100644
index 0000000..87554d7
--- /dev/null
+++ b/src/GitServer/wwwroot/Shared/_Pagination.cshtml
@@ -0,0 +1,12 @@
+@model (int Page, bool HasNextPage, string PrevUrl, string NextUrl)
+@inject GitServer.Services.LocalizationService L
+<div class="pagination">
+ @if (Model.Page > 0)
+ {
+ <a class="btn btn-secondary" href="@Model.PrevUrl">@L["pagination_prev"]</a>
+ }
+ @if (Model.HasNextPage)
+ {
+ <a class="btn btn-secondary" href="@Model.NextUrl">@L["pagination_next"]</a>
+ }
+</div>
diff --git a/src/GitServer/wwwroot/User/Profile.cshtml b/src/GitServer/wwwroot/User/Profile.cshtml
index 626e6f8..7fe6cdd 100644
--- a/src/GitServer/wwwroot/User/Profile.cshtml
+++ b/src/GitServer/wwwroot/User/Profile.cshtml
@@ -21,6 +21,13 @@
<p class="search-results-info">@Model.Repos.Count @L["explore_results_for"] "<strong>@Model.Query</strong>"</p>
}
+ var prevUrl = $"/User/{Model.ProfileUser.UserName}?q={Uri.EscapeDataString(Model.Query)}&p={Model.CurrentPage - 1}";
+ var nextUrl = $"/User/{Model.ProfileUser.UserName}?q={Uri.EscapeDataString(Model.Query)}&p={Model.CurrentPage + 1}";
+ @if (Model.Repos.Any() && (Model.CurrentPage > 0 || Model.HasNextPage))
+ {
+ @await Html.PartialAsync("_Pagination", (Model.CurrentPage, Model.HasNextPage, prevUrl, nextUrl))
+ }
+
@if (!Model.Repos.Any())
{
<div class="empty-state">@(string.IsNullOrEmpty(Model.Query) ? L["profile_no_repos"] : L["explore_no_results"])</div>
@@ -39,6 +46,10 @@
{
<span class="badge badge-warning">@L["badge_private"]</span>
}
+ else
+ {
+ <span class="badge badge-success">@L["badge_public"]</span>
+ }
</div>
@if (!string.IsNullOrEmpty(repo.Description))
{
@@ -51,7 +62,14 @@
@for (var i = 0; i < repo.Accesses.Count; i++)
{
var access = repo.Accesses.ElementAt(i);
- <a href="/User/@access.User.UserName">@access.User.UserName</a>
+ if (access.User != null)
+ {
+ <a href="/User/@access.User.UserName">@access.User.UserName</a>
+ }
+ else if (access.Group != null)
+ {
+ <span>@access.Group.Name</span>
+ }
if (i < repo.Accesses.Count - 1)
{
@:,
@@ -66,6 +84,10 @@
</div>
}
</div>
+ @if (Model.CurrentPage > 0 || Model.HasNextPage)
+ {
+ @await Html.PartialAsync("_Pagination", (Model.CurrentPage, Model.HasNextPage, prevUrl, nextUrl))
+ }
}
}
else
diff --git a/src/GitServer/wwwroot/User/Profile.cshtml.cs b/src/GitServer/wwwroot/User/Profile.cshtml.cs
index 3dd5ff7..98f2cef 100644
--- a/src/GitServer/wwwroot/User/Profile.cshtml.cs
+++ b/src/GitServer/wwwroot/User/Profile.cshtml.cs
@@ -3,17 +3,21 @@ using GitServer.Services;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
+using Microsoft.Extensions.Options;
namespace GitServer.wwwroot.User;
-public class ProfileModel(UserManager<AppUser> userManager, RepositoryService repos) : PageModel
+public class ProfileModel(UserManager<AppUser> userManager, RepositoryService repos, IOptions<GitServerOptions> options) : PageModel
{
public AppUser? ProfileUser { get; set; }
public List<Repository> Repos { get; set; } = new();
public bool IsOwner { get; set; }
public string Query { get; set; } = "";
+ public int CurrentPage { get; set; }
+ public int PageSize { get; } = options.Value.ProfileRepoPageSize;
+ public bool HasNextPage { get; set; }
- public async Task<IActionResult> OnGetAsync(string username, string? q)
+ public async Task<IActionResult> OnGetAsync(string username, string? q, int p = 0)
{
ProfileUser = await userManager.FindByNameAsync(username);
if (ProfileUser == null) return NotFound();
@@ -21,8 +25,12 @@ public class ProfileModel(UserManager<AppUser> userManager, RepositoryService re
var currentUserId = userManager.GetUserId(User);
IsOwner = currentUserId == ProfileUser.Id;
Query = q ?? "";
+ CurrentPage = p;
- Repos = await repos.GetUserReposAsync(ProfileUser.Id, includePrivate: IsOwner, query: Query);
+ var fetched = await repos.GetUserReposAsync(ProfileUser.Id, includePrivate: IsOwner, query: Query,
+ skip: p * PageSize, take: PageSize + 1);
+ HasNextPage = fetched.Count > PageSize;
+ Repos = fetched.Take(PageSize).ToList();
return Page();
}
}
diff --git a/src/GitServer/wwwroot/css/main.css b/src/GitServer/wwwroot/css/main.css
index 7cef417..1fccfea 100644
--- a/src/GitServer/wwwroot/css/main.css
+++ b/src/GitServer/wwwroot/css/main.css
@@ -252,6 +252,7 @@ p { margin-bottom: 0.75rem; }
display: flex;
gap: 0.5rem;
margin-top: 1.5rem;
+ margin-bottom: 1.5rem;
justify-content: center;
}