Forge
csharp3407750f
1using AgentForge.Contracts;
2using AgentForge.Data.Entities;
3
4namespace AgentForge.Plugin.Org.Web.Components;
5
6internal static class ForgeViewOrgCatalogIndex
7{
8 internal sealed record Model(
9 IReadOnlyDictionary<string, List<RepoResponse>> ReposByGroupPath,
10 IReadOnlyDictionary<string, int> RepoCountByGroupPath,
11 IReadOnlyList<RepoResponse> Ungrouped,
12 IReadOnlyDictionary<string, List<ForgeRepoGroupEntity>> ChildrenByParentId,
13 IReadOnlyList<ForgeRepoGroupEntity> RootGroups);
14
15 internal static Model Build(
16 IReadOnlyList<ForgeRepoGroupEntity> groups,
17 IReadOnlyList<RepoResponse> repos,
18 IReadOnlyDictionary<string, string> groupPaths)
19 {
20 var reposByGroupPath = repos
21 .Where(r => !string.IsNullOrWhiteSpace(r.Group))
22 .GroupBy(r => r.Group!, StringComparer.OrdinalIgnoreCase)
23 .ToDictionary(g => g.Key, g => g.ToList(), StringComparer.OrdinalIgnoreCase);
24
25 var ungrouped = repos
26 .Where(r => string.IsNullOrWhiteSpace(r.Group))
27 .ToList();
28
29 var childrenByParentId = groups
30 .GroupBy(g => g.ParentGroupId ?? string.Empty, StringComparer.Ordinal)
31 .ToDictionary(g => g.Key, g => g.OrderBy(x => x.DisplayName, StringComparer.OrdinalIgnoreCase).ToList());
32
33 var rootGroups = childrenByParentId.GetValueOrDefault(string.Empty) ?? [];
34 var repoCountByGroupPath = BuildRepoCounts(groups, groupPaths, repos);
35 return new Model(reposByGroupPath, repoCountByGroupPath, ungrouped, childrenByParentId, rootGroups);
36 }
37
38 private static IReadOnlyDictionary<string, int> BuildRepoCounts(
39 IReadOnlyList<ForgeRepoGroupEntity> groups,
40 IReadOnlyDictionary<string, string> groupPaths,
41 IReadOnlyList<RepoResponse> repos)
42 {
43 var paths = groups
44 .Select(group => groupPaths.TryGetValue(group.Id, out var path) ? path : group.Slug)
45 .Distinct(StringComparer.OrdinalIgnoreCase)
46 .ToList();
47
48 var counts = paths.ToDictionary(path => path, _ => 0, StringComparer.OrdinalIgnoreCase);
49 foreach (var repo in repos)
50 {
51 if (string.IsNullOrWhiteSpace(repo.Group))
52 continue;
53
54 foreach (var path in paths)
55 {
56 if (IsRepoInGroupBranch(repo.Group, path))
57 counts[path]++;
58 }
59 }
60
61 return counts;
62 }
63
64 private static bool IsRepoInGroupBranch(string repoPath, string groupPath) =>
65 string.Equals(repoPath, groupPath, StringComparison.OrdinalIgnoreCase)
66 || repoPath.StartsWith(groupPath + "/", StringComparison.OrdinalIgnoreCase);
67}
68
View only · write via MCP/CIDE