| 1 | using AgentForge.Abstractions; |
| 2 | using AgentForge.Plugin.Grouping.Core; |
| 3 | |
| 4 | namespace AgentForge.Plugin.Grouping.Repositories.Axes; |
| 5 | |
| 6 | internal abstract class ForgeFixedSectionRepositoryGroupingAxis( |
| 7 | string id, |
| 8 | string label, |
| 9 | int order, |
| 10 | IReadOnlyList<ForgeGroupingSection> sections) |
| 11 | : ForgeFixedSectionGroupingAxis<ForgeCatalogGroupingRepoRow>(id, label, order, sections), |
| 12 | IForgeCatalogGroupingAxis; |
| 13 | |
| 14 | internal sealed class VisibilityCatalogGroupingAxis() |
| 15 | : ForgeFixedSectionRepositoryGroupingAxis( |
| 16 | "visibility", |
| 17 | "Visibility", |
| 18 | order: 10, |
| 19 | sections: |
| 20 | [ |
| 21 | new("public", "Public"), |
| 22 | new("private", "Private"), |
| 23 | ]) |
| 24 | { |
| 25 | public override string GetKey(ForgeCatalogGroupingRepoRow row, DateTimeOffset utcNow) => |
| 26 | row.Item.Visibility; |
| 27 | } |
| 28 | |
| 29 | internal sealed class DriveModeCatalogGroupingAxis() |
| 30 | : ForgeFixedSectionRepositoryGroupingAxis( |
| 31 | "drive_mode", |
| 32 | "Drive mode", |
| 33 | order: 20, |
| 34 | sections: |
| 35 | [ |
| 36 | new("agent-driven", "Agent-driven"), |
| 37 | new("human-driven", "Human-driven"), |
| 38 | ]) |
| 39 | { |
| 40 | public override string GetKey(ForgeCatalogGroupingRepoRow row, DateTimeOffset utcNow) => |
| 41 | row.Item.DriveMode; |
| 42 | } |
| 43 | |
| 44 | internal sealed class LastCommitCatalogGroupingAxis() |
| 45 | : ForgeFixedSectionRepositoryGroupingAxis( |
| 46 | "last_commit", |
| 47 | "Last commit", |
| 48 | order: 30, |
| 49 | ForgeGroupingDateBuckets.Sections()) |
| 50 | { |
| 51 | public override string GetKey(ForgeCatalogGroupingRepoRow row, DateTimeOffset utcNow) => |
| 52 | ForgeGroupingDateBuckets.Bucket(row.LastCommitAt, utcNow); |
| 53 | } |
| 54 | |
| 55 | internal sealed class CreatedAtCatalogGroupingAxis() |
| 56 | : ForgeFixedSectionRepositoryGroupingAxis( |
| 57 | "created_at", |
| 58 | "Created", |
| 59 | order: 40, |
| 60 | ForgeGroupingDateBuckets.Sections()) |
| 61 | { |
| 62 | public override string GetKey(ForgeCatalogGroupingRepoRow row, DateTimeOffset utcNow) => |
| 63 | ForgeGroupingDateBuckets.Bucket(row.Item.CreatedAt, utcNow); |
| 64 | } |
| 65 | |
| 66 | internal sealed class OrgCatalogGroupingAxis : IForgeCatalogGroupingAxis |
| 67 | { |
| 68 | public string Id => "org"; |
| 69 | |
| 70 | public string Label => "Organization"; |
| 71 | |
| 72 | public int Order => 50; |
| 73 | |
| 74 | public string GetKey(ForgeCatalogGroupingRepoRow row, DateTimeOffset utcNow) => |
| 75 | string.IsNullOrWhiteSpace(row.Item.Org) ? "unknown" : row.Item.Org.Trim(); |
| 76 | |
| 77 | public IReadOnlyList<ForgeGroupingSection> SectionsFor( |
| 78 | IReadOnlyList<ForgeCatalogGroupingRepoRow> rows, |
| 79 | DateTimeOffset utcNow) => |
| 80 | ForgeRepositoryDynamicSections.FromRows( |
| 81 | rows, |
| 82 | row => GetKey(row, utcNow), |
| 83 | key => string.Equals(key, "unknown", StringComparison.OrdinalIgnoreCase) ? "Unknown" : key); |
| 84 | } |
| 85 | |
| 86 | internal sealed class GroupCatalogGroupingAxis : IForgeCatalogGroupingAxis |
| 87 | { |
| 88 | public string Id => "group"; |
| 89 | |
| 90 | public string Label => "Repo group"; |
| 91 | |
| 92 | public int Order => 60; |
| 93 | |
| 94 | public string GetKey(ForgeCatalogGroupingRepoRow row, DateTimeOffset utcNow) => |
| 95 | string.IsNullOrWhiteSpace(row.Item.Group) ? "ungrouped" : row.Item.Group.Trim(); |
| 96 | |
| 97 | public IReadOnlyList<ForgeGroupingSection> SectionsFor( |
| 98 | IReadOnlyList<ForgeCatalogGroupingRepoRow> rows, |
| 99 | DateTimeOffset utcNow) => |
| 100 | ForgeRepositoryDynamicSections.FromRows( |
| 101 | rows, |
| 102 | row => GetKey(row, utcNow), |
| 103 | key => string.Equals(key, "ungrouped", StringComparison.OrdinalIgnoreCase) ? "Ungrouped" : key); |
| 104 | } |
| 105 | |
| 106 | internal static class ForgeRepositoryDynamicSections |
| 107 | { |
| 108 | internal static IReadOnlyList<ForgeGroupingSection> FromRows( |
| 109 | IReadOnlyList<ForgeCatalogGroupingRepoRow> rows, |
| 110 | Func<ForgeCatalogGroupingRepoRow, string> keySelector, |
| 111 | Func<string, string> labelForKey) => |
| 112 | rows |
| 113 | .Select(keySelector) |
| 114 | .Distinct(StringComparer.OrdinalIgnoreCase) |
| 115 | .OrderBy(key => key, StringComparer.OrdinalIgnoreCase) |
| 116 | .Select(key => new ForgeGroupingSection(key, labelForKey(key))) |
| 117 | .ToList(); |
| 118 | } |
| 119 | |