Blog/Components/Pages/Git/GitLog.razor 5.7 K · 153 lines · raw · history

1 @page "/git/{Repository}/log"
2 @inherits GitPage
3
4 <PageTitle>@Repository log — git</PageTitle>
5
6 <GitBar Repository="@Repository" Reference="@Current" Tab="log"/>
7
8 <main class="git-main">
9 @if (Page is not { } page)
10 {
11 <section class="block">
12 <p class="empty">
13 @(BranchNames.Count == 0
14 ? $"Nothing has been pushed to {Repository} yet."
15 : $"No revision called {Reference ?? "HEAD"} in {Repository}.")
16 </p>
17 </section>
18 }
19 else
20 {
21 <section class="block">
22 <h2 class="block-head">
23 <span>log</span>
24 <span class="block-note">@Where</span>
25 </h2>
26
27 @* A plain GET form: the log is a URL, and narrowing it should produce one you can
28 link to. Nothing here needs script. *@
29 <div class="block-body">
30 <form method="get" action="@($"{RepoLink()}/log")" class="controls">
31 <label>
32 branch
33 <select name="h">
34 @foreach (var branch in BranchNames)
35 {
36 <option value="@branch" selected="@(branch == Current)">@branch</option>
37 }
38 </select>
39 </label>
40 <label>
41 path
42 <input type="text" name="path" value="@Path" placeholder="Blog/Services" size="24"/>
43 </label>
44 <button type="submit">show</button>
45 </form>
46 </div>
47
48 @if (page.Commits.Count == 0)
49 {
50 <p class="empty">No commits@(string.IsNullOrEmpty(Path) ? "" : $" touching {Path}").</p>
51 }
52 else
53 {
54 <div class="scroll">
55 <table>
56 <thead>
57 <tr>
58 <th>age</th>
59 <th>commit</th>
60 <th class="wide">subject</th>
61 <th class="when-wide">author</th>
62 </tr>
63 </thead>
64 <tbody>
65 @foreach (var commit in page.Commits)
66 {
67 <tr>
68 <td class="dim" title="@Exact(commit.Author.When)">@Age(commit.Author.When)</td>
69 <td class="sha dim"><a href="@CommitLink(commit.Sha)">@commit.ShortSha</a></td>
70 <td class="wide">
71 <a href="@CommitLink(commit.Sha)" class="subject">@commit.Summary</a>
72 @if (commit.IsMerge)
73 {
74 <span class="ref">merge</span>
75 }
76 @foreach (var name in commit.Refs)
77 {
78 <span class="ref @(name == Current ? "head" : null)">@name</span>
79 }
80 </td>
81 <td class="dim when-wide" title="@commit.Author.Email">@commit.Author.Name</td>
82 </tr>
83 }
84 </tbody>
85 </table>
86 </div>
87
88 <div class="pager">
89 @if (Skip > 0)
90 {
91 <a href="@LogLink(Current, Path, Math.Max(0, Skip - PageSize))">newer</a>
92 }
93 else
94 {
95 <span>newest</span>
96 }
97
98 @if (page.HasMore)
99 {
100 <a href="@LogLink(Current, Path, Skip + PageSize)">older</a>
101 }
102 else
103 {
104 <span>oldest</span>
105 }
106 </div>
107 }
108 </section>
109 }
110 </main>
111
112 @code {
113 private const int PageSize = 50;
114
115 /// <summary>Narrows the log to the commits that touched one file or directory.</summary>
116 [SupplyParameterFromQuery(Name = "path")]
117 public string? Path { get; set; }
118
119 /// <summary>How many commits to skip — the offset cgit paged with, under the name it used.</summary>
120 [SupplyParameterFromQuery(Name = "ofs")]
121 public int Skip { get; set; }
122
123 private GitLogPage? Page { get; set; }
124
125 private IReadOnlyList<string> BranchNames { get; set; } = [];
126
127 /// <summary>The branch this page is of, which is HEAD's when the query string named none.</summary>
128 private string? Current { get; set; }
129
130 private string Where => string.IsNullOrEmpty(Path) ? Current ?? "" : $"{Current} · {Path}";
131
132 protected override void OnParametersSet()
133 {
134 Skip = Math.Max(0, Skip);
135
136 // GetRefs lists HEAD's branch first, so the picker's first entry is also what this page
137 // defaults to — one repository open rather than two.
138 if (Service.GetRefs(Repository) is not { } refs)
139 {
140 NotFound();
141 return;
142 }
143
144 BranchNames = refs.Branches.Select(branch => branch.Name).ToArray();
145 Current = Reference ?? BranchNames.FirstOrDefault();
146
147 Page = Service.GetLog(Repository, Reference, Path, Skip, PageSize);
148
149 // A repository with branches but nothing at this revision was reached by a bad URL. One
150 // with no branches at all is a repository nobody has pushed to, which is not an error.
151 if (Page is null && BranchNames.Count > 0) NotFound();
152 }
153 }