namespace PlanTempusAdmin.Models; public class ForgejoRepository { public long Id { get; set; } public string OwnerName { get; set; } = string.Empty; public string Name { get; set; } = string.Empty; public string FullName => $"{OwnerName}/{Name}"; public string? Description { get; set; } public bool IsPrivate { get; set; } public bool IsFork { get; set; } public bool IsArchived { get; set; } public bool IsMirror { get; set; } // Stats public int NumStars { get; set; } public int NumForks { get; set; } public int NumWatches { get; set; } public int NumIssues { get; set; } public int NumClosedIssues { get; set; } public int NumPulls { get; set; } public int NumClosedPulls { get; set; } public long Size { get; set; } // in KB // Timestamps public DateTime CreatedAt { get; set; } public DateTime UpdatedAt { get; set; } // Calculated public int OpenIssues => NumIssues - NumClosedIssues; public int OpenPulls => NumPulls - NumClosedPulls; public string SizeFormatted => FormatSize(Size * 1024); // Size is in KB private static string FormatSize(long bytes) { if (bytes == 0) return "0 B"; var sizes = new[] { "B", "KB", "MB", "GB", "TB" }; var i = (int)Math.Floor(Math.Log(bytes) / Math.Log(1024)); return $"{Math.Round(bytes / Math.Pow(1024, i), 1)} {sizes[i]}"; } } public class ForgejoActionRun { public long Id { get; set; } public long RepoId { get; set; } public string RepoName { get; set; } = string.Empty; public string OwnerName { get; set; } = string.Empty; public string FullRepoName => $"{OwnerName}/{RepoName}"; public string WorkflowId { get; set; } = string.Empty; public long Index { get; set; } public string TriggerUser { get; set; } = string.Empty; public string Ref { get; set; } = string.Empty; public string CommitSha { get; set; } = string.Empty; public string Event { get; set; } = string.Empty; // push, pull_request, etc. public string Title { get; set; } = string.Empty; // Status: 0=unknown, 1=waiting, 2=running, 3=success, 4=failure, 5=cancelled, 6=skipped public int Status { get; set; } public string StatusText => Status switch { 1 => "waiting", 2 => "running", 3 => "success", 4 => "failure", 5 => "cancelled", 6 => "skipped", _ => "unknown" }; public DateTime? Started { get; set; } public DateTime? Stopped { get; set; } public DateTime Created { get; set; } public DateTime Updated { get; set; } public TimeSpan? Duration => Started.HasValue && Stopped.HasValue ? Stopped.Value - Started.Value : Started.HasValue ? DateTime.UtcNow - Started.Value : null; } public class ForgejoActionJob { public long Id { get; set; } public long RunId { get; set; } public string Name { get; set; } = string.Empty; public int Status { get; set; } public string StatusText => Status switch { 1 => "waiting", 2 => "running", 3 => "success", 4 => "failure", 5 => "cancelled", 6 => "skipped", _ => "unknown" }; public DateTime? Started { get; set; } public DateTime? Stopped { get; set; } } public class ForgejoDashboard { // Repository stats public int TotalRepos { get; set; } public int PublicRepos { get; set; } public int PrivateRepos { get; set; } public int ForkedRepos { get; set; } public int ArchivedRepos { get; set; } public int MirrorRepos { get; set; } public long TotalSize { get; set; } public int TotalStars { get; set; } public int TotalForks { get; set; } public int TotalOpenIssues { get; set; } public int TotalOpenPRs { get; set; } // Actions stats public int TotalRuns { get; set; } public int RunsToday { get; set; } public int RunsThisWeek { get; set; } public int SuccessfulRuns { get; set; } public int FailedRunsCount { get; set; } public int RunningNow { get; set; } public double SuccessRate => TotalRuns > 0 ? (double)SuccessfulRuns / TotalRuns * 100 : 0; // Recent activity public List RecentlyUpdated { get; set; } = new(); public List LargestRepos { get; set; } = new(); public List RecentRuns { get; set; } = new(); public List FailedRuns { get; set; } = new(); public List RunningRuns { get; set; } = new(); } public class ForgejoActionStats { public string WorkflowId { get; set; } = string.Empty; public string RepoName { get; set; } = string.Empty; public int TotalRuns { get; set; } public int Successful { get; set; } public int Failed { get; set; } public double SuccessRate => TotalRuns > 0 ? (double)Successful / TotalRuns * 100 : 0; public DateTime? LastRun { get; set; } public double? AvgDurationSeconds { get; set; } }