Forge
csharp3407750f
1using AgentForge.Abstractions;
2using AgentForge.Plugin.Grouping.Core;
3using AgentForge.Plugin.Grouping.Releases.Axes;
4using AgentForge.Plugin.View;
5using Microsoft.Extensions.DependencyInjection;
6
7namespace AgentForge.Plugin.Grouping.Releases;
8
9public sealed class ForgeReleaseListGroupingService(
10 ForgeGroupingAxisCatalog<IForgeReleaseGroupingAxis, ForgeReleaseListItem> axes) : IForgeReleaseListGrouping
11{
12 public IReadOnlyList<string> ParseGroupStack(string? groupStackQuery) =>
13 axes.ParseStack(groupStackQuery);
14
15 public string BuildListUrl(
16 in ForgeReleaseListViewContext context,
17 IReadOnlyList<string>? groupStack = null) =>
18 ForgeGroupingUrlBuilder.AppendGroupStack(
19 context.ListBasePath,
20 groupStack ?? context.GroupStack);
21
22 public string RenderToolbar(in ForgeReleaseListViewContext context)
23 {
24 var viewContext = context;
25 var presets = new (string Label, string[] Stack)[]
26 {
27 ("Flat list", []),
28 ("By channel", ["channel"]),
29 ("By platform", ["target_platform"]),
30 ("Platform → format", ["target_platform", "package_format"]),
31 ("Channel → major", ["channel", "major"]),
32 };
33
34 var links = presets.Select(preset =>
35 {
36 var href = BuildListUrl(viewContext, preset.Stack);
37 var active = viewContext.GroupStack.SequenceEqual(preset.Stack, StringComparer.OrdinalIgnoreCase);
38 return ForgeHtml.A(href, preset.Label, active ? "active" : null);
39 }).ToList();
40
41 var parts = new List<string>(links.Count * 2);
42 for (var i = 0; i < links.Count; i++)
43 {
44 if (i > 0)
45 parts.Add(ForgeHtml.Sep());
46 parts.Add(links[i]);
47 }
48
49 return ForgeHtml.P(
50 "meta release-grouping-toolbar",
51 ForgeHtml.Fragment([.. parts]));
52 }
53
54 public string RenderListBody(
55 IReadOnlyList<ForgeReleaseListItem> releases,
56 in ForgeReleaseListViewContext context)
57 {
58 if (releases.Count == 0)
59 return ForgeHtml.P("meta", ForgeHtml.Text("No releases yet. Git tag source — Phase B (FORGE-ADR-0032)."));
60
61 if (context.GroupStack.Count == 0)
62 return ForgeHtml.Ul("plain", [.. releases.Select(ForgeReleaseGroupingItemRenderer.Render)]);
63
64 var nested = ForgeGroupingNestedRenderer.Render(
65 axes,
66 releases,
67 context.GroupStack,
68 ForgeReleaseGroupingItemRenderer.Render,
69 listClass: "plain release-list");
70
71 return string.IsNullOrEmpty(nested)
72 ? ForgeHtml.Ul("plain", [.. releases.Select(ForgeReleaseGroupingItemRenderer.Render)])
73 : nested;
74 }
75
76 internal static void Register(IServiceCollection services)
77 {
78 services.AddSingleton<IForgeReleaseGroupingAxis, ReleaseChannelGroupingAxis>();
79 services.AddSingleton<IForgeReleaseGroupingAxis, ReleaseMajorVersionGroupingAxis>();
80 services.AddSingleton<IForgeReleaseGroupingAxis, ReleasePublishedGroupingAxis>();
81 services.AddSingleton<IForgeReleaseGroupingAxis, ReleaseTargetPlatformGroupingAxis>();
82 services.AddSingleton<IForgeReleaseGroupingAxis, ReleasePackageFormatGroupingAxis>();
83 services.AddSingleton<ForgeGroupingAxisCatalog<IForgeReleaseGroupingAxis, ForgeReleaseListItem>>(sp =>
84 new(sp.GetServices<IForgeReleaseGroupingAxis>(), "release"));
85 services.AddSingleton<IForgeReleaseListGrouping, ForgeReleaseListGroupingService>();
86 }
87}
88
View only · write via MCP/CIDE