mirror of
https://github.com/RayLabsHQ/gitea-mirror.git
synced 2025-12-09 21:16:48 +03:00
Add fork tags to repository UI and enhance organization cards with repository breakdown
- Add fork tags to repository table and dashboard list components - Display 'Fork' badge for repositories where isForked is true - Enhance organization cards to show breakdown of public, private, and fork repositories - Update organization API to respect user configuration filters (private repos, forks) - Add visual indicators with colored dots for each repository type - Ensure consistent filtering between repository and organization APIs - Fix issue where private repositories weren't showing due to configuration filtering
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import type { APIRoute } from "astro";
|
||||
import { db } from "@/lib/db";
|
||||
import { organizations } from "@/lib/db";
|
||||
import { eq, sql } from "drizzle-orm";
|
||||
import { organizations, repositories, configs } from "@/lib/db";
|
||||
import { eq, sql, and, count } from "drizzle-orm";
|
||||
import {
|
||||
membershipRoleEnum,
|
||||
type OrganizationsApiResponse,
|
||||
@@ -25,24 +25,114 @@ export const GET: APIRoute = async ({ request }) => {
|
||||
}
|
||||
|
||||
try {
|
||||
// Fetch the user's active configuration to respect filtering settings
|
||||
const [config] = await db
|
||||
.select()
|
||||
.from(configs)
|
||||
.where(and(eq(configs.userId, userId), eq(configs.isActive, true)));
|
||||
|
||||
if (!config) {
|
||||
return jsonResponse({
|
||||
data: {
|
||||
success: false,
|
||||
error: "No active configuration found for this user",
|
||||
},
|
||||
status: 404,
|
||||
});
|
||||
}
|
||||
|
||||
const githubConfig = config.githubConfig as {
|
||||
mirrorStarred: boolean;
|
||||
skipForks: boolean;
|
||||
privateRepositories: boolean;
|
||||
};
|
||||
|
||||
const rawOrgs = await db
|
||||
.select()
|
||||
.from(organizations)
|
||||
.where(eq(organizations.userId, userId))
|
||||
.orderBy(sql`name COLLATE NOCASE`);
|
||||
|
||||
const orgsWithIds: Organization[] = rawOrgs.map((org) => ({
|
||||
...org,
|
||||
status: repoStatusEnum.parse(org.status),
|
||||
membershipRole: membershipRoleEnum.parse(org.membershipRole),
|
||||
lastMirrored: org.lastMirrored ?? undefined,
|
||||
errorMessage: org.errorMessage ?? undefined,
|
||||
}));
|
||||
// Calculate repository breakdowns for each organization
|
||||
const orgsWithBreakdown = await Promise.all(
|
||||
rawOrgs.map(async (org) => {
|
||||
// Build base conditions for this organization (without private/fork filters)
|
||||
const baseConditions = [
|
||||
eq(repositories.userId, userId),
|
||||
eq(repositories.organization, org.name)
|
||||
];
|
||||
|
||||
if (!githubConfig.mirrorStarred) {
|
||||
baseConditions.push(eq(repositories.isStarred, false));
|
||||
}
|
||||
|
||||
// Get total count with all user config filters applied
|
||||
const totalConditions = [...baseConditions];
|
||||
if (githubConfig.skipForks) {
|
||||
totalConditions.push(eq(repositories.isForked, false));
|
||||
}
|
||||
if (!githubConfig.privateRepositories) {
|
||||
totalConditions.push(eq(repositories.isPrivate, false));
|
||||
}
|
||||
|
||||
const [totalCount] = await db
|
||||
.select({ count: count() })
|
||||
.from(repositories)
|
||||
.where(and(...totalConditions));
|
||||
|
||||
// Get public count
|
||||
const publicConditions = [...baseConditions, eq(repositories.isPrivate, false)];
|
||||
if (githubConfig.skipForks) {
|
||||
publicConditions.push(eq(repositories.isForked, false));
|
||||
}
|
||||
|
||||
const [publicCount] = await db
|
||||
.select({ count: count() })
|
||||
.from(repositories)
|
||||
.where(and(...publicConditions));
|
||||
|
||||
// Get private count (only if private repos are enabled in config)
|
||||
const [privateCount] = githubConfig.privateRepositories ? await db
|
||||
.select({ count: count() })
|
||||
.from(repositories)
|
||||
.where(
|
||||
and(
|
||||
...baseConditions,
|
||||
eq(repositories.isPrivate, true),
|
||||
...(githubConfig.skipForks ? [eq(repositories.isForked, false)] : [])
|
||||
)
|
||||
) : [{ count: 0 }];
|
||||
|
||||
// Get fork count (only if forks are enabled in config)
|
||||
const [forkCount] = !githubConfig.skipForks ? await db
|
||||
.select({ count: count() })
|
||||
.from(repositories)
|
||||
.where(
|
||||
and(
|
||||
...baseConditions,
|
||||
eq(repositories.isForked, true),
|
||||
...(!githubConfig.privateRepositories ? [eq(repositories.isPrivate, false)] : [])
|
||||
)
|
||||
) : [{ count: 0 }];
|
||||
|
||||
return {
|
||||
...org,
|
||||
status: repoStatusEnum.parse(org.status),
|
||||
membershipRole: membershipRoleEnum.parse(org.membershipRole),
|
||||
lastMirrored: org.lastMirrored ?? undefined,
|
||||
errorMessage: org.errorMessage ?? undefined,
|
||||
repositoryCount: totalCount.count,
|
||||
publicRepositoryCount: publicCount.count,
|
||||
privateRepositoryCount: privateCount.count,
|
||||
forkRepositoryCount: forkCount.count,
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
const resPayload: OrganizationsApiResponse = {
|
||||
success: true,
|
||||
message: "Organizations fetched successfully",
|
||||
organizations: orgsWithIds,
|
||||
organizations: orgsWithBreakdown,
|
||||
};
|
||||
|
||||
return jsonResponse({ data: resPayload, status: 200 });
|
||||
|
||||
Reference in New Issue
Block a user