diff options
| author | Melodi <62381002+Melodi17@users.noreply.github.com> | 2026-09-14 06:15:40 +1000 |
|---|---|---|
| committer | Melodi <62381002+Melodi17@users.noreply.github.com> | 2026-09-14 06:15:40 +1000 |
| commit | 88ee626cb3686dc176cd7911b073c4e65fa54d34 (patch) | |
| tree | ffd4d27de8b6cce5a43add9fa4222b1d50f1e500 | |
| parent | df0737e55afeb5c01eb39909605970d1d3a73ffc (diff) | |
feat: ui cleanup
| -rw-r--r-- | src/marlin.core/functional/GitBinaryClient.cs | 3 | ||||
| -rw-r--r-- | src/marlin.web/Controllers/VCSController.cs | 43 | ||||
| -rw-r--r-- | src/marlin.web/Models/VersionControlSource.cs | 2 | ||||
| -rw-r--r-- | src/marlin.web/Services/VersionControlSyncService.cs | 1 | ||||
| -rw-r--r-- | src/marlin.web/Views/Agents/Create.cshtml | 9 | ||||
| -rw-r--r-- | src/marlin.web/Views/VCS/Create.cshtml | 1 | ||||
| -rw-r--r-- | src/marlin.web/Views/VCS/Details.cshtml | 74 | ||||
| -rw-r--r-- | src/marlin.web/Views/VCS/ListSecret.cshtml | 16 | ||||
| -rw-r--r-- | src/marlin.web/wwwroot/css/site.css | 8 |
9 files changed, 114 insertions, 43 deletions
diff --git a/src/marlin.core/functional/GitBinaryClient.cs b/src/marlin.core/functional/GitBinaryClient.cs index 001f2c8..3a703da 100644 --- a/src/marlin.core/functional/GitBinaryClient.cs +++ b/src/marlin.core/functional/GitBinaryClient.cs @@ -125,6 +125,9 @@ public class GitBinaryClient : IGitClient if (parts.Length != 2) continue; // ignore a malformed line rather than throw over one bad entry + if (parts[1].EndsWith("^{}", StringComparison.Ordinal)) + continue; // peeled tag marker from ls-remote, not a real ref/refspec + result[parts[1]] = parts[0]; } diff --git a/src/marlin.web/Controllers/VCSController.cs b/src/marlin.web/Controllers/VCSController.cs index 8086e99..10ef59b 100644 --- a/src/marlin.web/Controllers/VCSController.cs +++ b/src/marlin.web/Controllers/VCSController.cs @@ -22,8 +22,6 @@ public class VCSController(ApplicationDbContext dbContext, VersionControlSyncSer return this.View(items); } - public record SecretOption(Guid Id, string Label); - [HttpGet("details/{id}")] public async Task<IActionResult> Details(Guid id, CancellationToken ct) { @@ -37,12 +35,7 @@ public class VCSController(ApplicationDbContext dbContext, VersionControlSyncSer if (item == null) return this.NotFound(); - var secretOptions = await dbContext.Secrets - .Where(x => x.SourceId == id) - .Select(x => new SecretOption(x.Id, x.Label)) - .ToListAsync(ct); - - return this.View((item, secretOptions)); + return this.View(item); } [HttpGet("details/{sourceId}/{commitId}/blobs")] @@ -87,9 +80,7 @@ public class VCSController(ApplicationDbContext dbContext, VersionControlSyncSer item.UpstreamUrl = vcs.UpstreamUrl; item.BranchFilter = vcs.BranchFilter; - item.MainBranch = vcs.MainBranch; item.MinPollingInterval = vcs.MinPollingInterval; - item.AccessSecretId = vcs.AccessSecretId; await dbContext.SaveChangesAsync(ct); await syncService.FetchSources(ct); @@ -97,6 +88,37 @@ public class VCSController(ApplicationDbContext dbContext, VersionControlSyncSer return this.RedirectToAction("List"); } + [HttpPost("details/{sourceId}/secrets/access")] + public async Task<IActionResult> SetAccessSecret(Guid sourceId, Guid? secretId, CancellationToken ct) + { + var item = await dbContext.Sources + .FirstOrDefaultAsync(x => x.Id == sourceId, ct); + + if (item == null) + return this.NotFound(); + + item.AccessSecretId = secretId; + await dbContext.SaveChangesAsync(ct); + await syncService.FetchSources(ct); + + return this.RedirectToAction("ListSecret", new { sourceId }); + } + + [HttpPost("details/{sourceId}/main-branch")] + public async Task<IActionResult> SetMainBranch(Guid sourceId, string branchName, CancellationToken ct) + { + var item = await dbContext.Sources + .FirstOrDefaultAsync(x => x.Id == sourceId, ct); + + if (item == null) + return this.NotFound(); + + item.MainBranch = branchName; + await dbContext.SaveChangesAsync(ct); + + return this.RedirectToAction("Details", new { id = sourceId }); + } + [HttpGet("create")] public async Task<IActionResult> Create() { @@ -107,6 +129,7 @@ public class VCSController(ApplicationDbContext dbContext, VersionControlSyncSer public async Task<IActionResult> CreatePost(VersionControlSource vcs, CancellationToken ct) { vcs.Id = Guid.Empty; + vcs.MainBranch = ""; await dbContext.AddAsync(vcs, ct); await dbContext.SaveChangesAsync(ct); diff --git a/src/marlin.web/Models/VersionControlSource.cs b/src/marlin.web/Models/VersionControlSource.cs index 270df12..12d5a7a 100644 --- a/src/marlin.web/Models/VersionControlSource.cs +++ b/src/marlin.web/Models/VersionControlSource.cs @@ -5,7 +5,7 @@ public class VersionControlSource public Guid Id { get; set; } public string UpstreamUrl { get; set; } - public string MainBranch { get; set; } + public string? MainBranch { get; set; } public string BranchFilter { get; set; } public int MinPollingInterval { get; set; } diff --git a/src/marlin.web/Services/VersionControlSyncService.cs b/src/marlin.web/Services/VersionControlSyncService.cs index cd75ed6..8f2046e 100644 --- a/src/marlin.web/Services/VersionControlSyncService.cs +++ b/src/marlin.web/Services/VersionControlSyncService.cs @@ -142,6 +142,7 @@ public class VersionControlSyncService : BackgroundService await dbContext.SourceCommits .Include(x => x.Branches) .Where(x => !x.Branches.Any()) + .Where(x => !dbContext.Jobs.Any(j => j.CommitId == x.Id)) .ExecuteDeleteAsync(ct); } diff --git a/src/marlin.web/Views/Agents/Create.cshtml b/src/marlin.web/Views/Agents/Create.cshtml index 4f0f31a..e112eeb 100644 --- a/src/marlin.web/Views/Agents/Create.cshtml +++ b/src/marlin.web/Views/Agents/Create.cshtml @@ -1,8 +1,13 @@ @using marlin.core.models <form method="post" asp-action="Create"> - Name: <input type="text" name="@nameof(Agent.Name)" /><br/> - Max Concurrent Jobs: <input type="number" name="@nameof(Agent.MaxConcurrentJobs)" value="1"/><br/> + <dl> + <dt>Name</dt> + <dd><input type="text" name="@nameof(Agent.Name)" placeholder="myagent-1"/></dd> + + <dt>Max Concurrent Jobs</dt> + <dd><input type="number" name="@nameof(Agent.MaxConcurrentJobs)" value="1"/></dd> + </dl> <button type="submit">Create</button> </form> diff --git a/src/marlin.web/Views/VCS/Create.cshtml b/src/marlin.web/Views/VCS/Create.cshtml index e04592d..5f76192 100644 --- a/src/marlin.web/Views/VCS/Create.cshtml +++ b/src/marlin.web/Views/VCS/Create.cshtml @@ -4,7 +4,6 @@ <form method="post" asp-action="Create"> URL: <input type="text" name="@nameof(VersionControlSource.UpstreamUrl)" /><br/> Filter: <input type="text" name="@nameof(VersionControlSource.BranchFilter)" /><br/> - Main Branch: <input type="text" name="@nameof(VersionControlSource.MainBranch)" /><br/> Polling Interval: <input type="number" name="@nameof(VersionControlSource.MinPollingInterval)" /><br/> <button type="submit">Create</button> </form> diff --git a/src/marlin.web/Views/VCS/Details.cshtml b/src/marlin.web/Views/VCS/Details.cshtml index a9ef0ea..44fa91e 100644 --- a/src/marlin.web/Views/VCS/Details.cshtml +++ b/src/marlin.web/Views/VCS/Details.cshtml @@ -1,55 +1,73 @@ @using marlin.core @using marlin.core.models -@using marlin.web.Controllers -@model (VersionControlSource Source, List<VCSController.SecretOption> SecretOptions) +@model VersionControlSource -<form method="post" asp-route-id="@Model.Source.Id" asp-action="Edit"> - URL: <input type="text" name="@nameof(VersionControlSource.UpstreamUrl)" value="@Model.Source.UpstreamUrl"/><br/> - Filter: <input type="text" name="@nameof(VersionControlSource.BranchFilter)" value="@Model.Source.BranchFilter"/><br/> - Main Branch: <input type="text" name="@nameof(VersionControlSource.MainBranch)" value="@Model.Source.MainBranch"/><br/> - Polling Interval: <input type="number" name="@nameof(VersionControlSource.MinPollingInterval)" value="@Model.Source.MinPollingInterval"/><br/> - Access Secret: - <select name="@nameof(VersionControlSource.AccessSecretId)"> - <option value="">(none)</option> - @foreach (var secret in Model.SecretOptions) - { - <option value="@secret.Id" selected="@(secret.Id == Model.Source.AccessSecretId)">@secret.Label</option> - } - </select><br/> - <button type="submit">Save</button> -</form> +<div class="row"> + <div class="col"> + <h3>Details</h3> + <hr/> + <form method="post" asp-route-id="@Model.Id" asp-action="Edit"> + <dl> + <dt>URL</dt> + <dd><input type="text" name="@nameof(VersionControlSource.UpstreamUrl)" value="@Model.UpstreamUrl"/></dd> + <dt>Filter</dt> + <dd><input type="text" name="@nameof(VersionControlSource.BranchFilter)" value="@Model.BranchFilter"/></dd> + + <dt>Polling Interval</dt> + <dd><input type="number" name="@nameof(VersionControlSource.MinPollingInterval)" value="@Model.MinPollingInterval"/></dd> + </dl> + + <button type="submit">Save</button> + <a asp-action="ListSecret" asp-route-sourceId="@Model.Id">Secrets</a> + <a asp-action="List">Back</a> + </form> + </div> +</div> +<br/> + +<h3>Branches</h3> +<hr/> <table> <thead> <tr> - <th></th> <th>branch</th> <th>commit</th> - <th>status</th> + <th>actions</th> </tr> </thead> <tbody> - @foreach (var branch in Model.Source.Branches) + @foreach (var branch in Model.Branches.OrderByDescending(b => b.Name == Model.MainBranch)) { - <tr> - <td>@(branch.Name == Model.Source.MainBranch ? "@" : "")</td> - <td>@branch.Name</td> + <tr class="@(branch.Name == Model.MainBranch ? "highlighted" : "")"> + <td> + @branch.Name + @if (branch.Name == Model.MainBranch) + { + <span>(primary)</span> + } + </td> <td>@branch.Commit.Hash</td> <td> @if (branch.Commit.BlobsFetched) { <a asp-action="Blobs" asp-route-commitId="@branch.CommitId" asp-route-sourceId="@branch.SourceId">blobs</a> } - + @if (branch.Commit.WorkflowScanned) { <a asp-action="Workflow" asp-route-commitId="@branch.CommitId" asp-route-sourceId="@branch.SourceId">workflow</a> } + + @if (branch.Name != Model.MainBranch) + { + <form method="post" asp-action="SetMainBranch" asp-route-sourceId="@Model.Id" style="display:inline"> + <input type="hidden" name="branchName" value="@branch.Name"/> + <button type="submit" class="btn btn-link p-0">make primary</button> + </form> + } </td> </tr> } </tbody> -</table> - -<a asp-action="ListSecret" asp-route-sourceId="@Model.Source.Id">Secrets</a> -<a asp-action="List">Back</a> +</table>
\ No newline at end of file diff --git a/src/marlin.web/Views/VCS/ListSecret.cshtml b/src/marlin.web/Views/VCS/ListSecret.cshtml index 25db7fe..84e3061 100644 --- a/src/marlin.web/Views/VCS/ListSecret.cshtml +++ b/src/marlin.web/Views/VCS/ListSecret.cshtml @@ -1,5 +1,19 @@ @model (VersionControlSource Source, List<ISecret> Secrets) +<form method="post" asp-action="SetAccessSecret" asp-route-sourceId="@Model.Source.Id"> + <label> + Access Secret + <select name="secretId"> + <option value="">(none)</option> + @foreach (var secret in Model.Secrets) + { + <option value="@secret.Id" selected="@(secret.Id == Model.Source.AccessSecretId)">@secret.Label</option> + } + </select> + </label> + <button type="submit">Save</button> +</form> + <a asp-action="CreateSecret" asp-route-sourceId="@Model.Source.Id">New</a> <table> @@ -42,4 +56,4 @@ </tbody> </table> -<a asp-action="Details", asp-route-id="@Model.Source.Id">back</a> +<a asp-action="Details" asp-route-id="@Model.Source.Id">back</a> diff --git a/src/marlin.web/wwwroot/css/site.css b/src/marlin.web/wwwroot/css/site.css index fa66346..d5d64db 100644 --- a/src/marlin.web/wwwroot/css/site.css +++ b/src/marlin.web/wwwroot/css/site.css @@ -66,6 +66,14 @@ table tr:hover { background-color: #fafafa } +table tr.highlighted { + background-color: #e1eaf6; +} + +table tr.highlighted:hover { + background-color: #d3e9f6; +} + th, td { border: 1px solid #ccc; text-align: left; |
