Skip to content

Commit

Permalink
fix : projects performance fix test
Browse files Browse the repository at this point in the history
  • Loading branch information
psiddharthdesign committed Aug 5, 2024
1 parent cd80bfc commit 4f5a12e
Show file tree
Hide file tree
Showing 4 changed files with 199 additions and 71 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
TableHeader,
TableRow,
} from '@/components/ui/table';
import { getRepoDetails } from '@/data/user/repos';
import type { Tables } from '@/lib/database.types';
import {
flexRender,
Expand All @@ -24,32 +23,18 @@ import {
import { GitBranch } from 'lucide-react';
import moment from 'moment';
import Link from 'next/link';
import { useEffect, useState } from 'react';
import { useState } from 'react';
import { ProjectListType } from './ProjectsWithPagination';

type ProjectWithRepo = Tables<'projects'> & { repoFullName: string | null };

type Props = {
projects: Tables<'projects'>[];
projects: ProjectListType[];
};

export function OrganizationProjectsTable({ projects }: Props) {
const [projectsWithRepos, setProjectsWithRepos] = useState<ProjectWithRepo[]>([]);

useEffect(() => {
const fetchRepoDetails = async () => {
const updatedProjects = await Promise.all(
projects.map(async (project) => {
const repoDetails = await getRepoDetails(project.repo_id);
return { ...project, repoFullName: repoDetails?.repo_full_name ?? null };
})
);
setProjectsWithRepos(updatedProjects);
};

fetchRepoDetails();
}, [projects]);

const columns: ColumnDef<ProjectWithRepo>[] = [
const columns: ColumnDef<ProjectListType>[] = [
{
accessorKey: 'name',
header: 'Name',
Expand Down Expand Up @@ -79,8 +64,8 @@ export function OrganizationProjectsTable({ projects }: Props) {
<div className="flex items-center bg-muted/50 p-1 rounded-md border w-fit px-2">
<GitBranch className="mr-1 h-4 w-4" />
<span>
{row.original.repoFullName ? `${row.original.repoFullName.toLowerCase().replace(/\s+/g, '-').replace(/[A-Z]/g, (letter) => letter.toLowerCase())}` : ''}
{row.original.repoFullName && ((row.getValue('terraform_working_dir') as string) || '') ? '/' : ''}
{row.original.repo_full_name ? `${row.original.repo_full_name.toLowerCase().replace(/\s+/g, '-').replace(/[A-Z]/g, (letter) => letter.toLowerCase())}` : ''}
{row.original.repo_full_name && ((row.getValue('terraform_working_dir') as string) || '') ? '/' : ''}
{((row.getValue('terraform_working_dir') as string) || '').replace(/\s+/g, '-').replace(/[A-Z]/g, (letter) => letter.toLowerCase())}
</span>
</div>
Expand All @@ -90,7 +75,7 @@ export function OrganizationProjectsTable({ projects }: Props) {

const [sorting, setSorting] = useState<SortingState>([]);
const table = useReactTable({
data: projectsWithRepos,
data: projects,
columns,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
import { Pagination } from "@/components/Pagination";
import { getLoggedInUserOrganizationRole } from "@/data/user/organizations";
import { getAllProjectsInOrganization, getProjects, getProjectsCountForUser, getProjectsForUser, getProjectsTotalCount } from "@/data/user/projects";
import { getAllProjectsListInOrganization, getProjectsCountForUser, getProjectsList, getProjectsListForUser, getProjectsTotalCount } from "@/data/user/projects";
import { serverGetLoggedInUser } from "@/utils/server/serverGetLoggedInUser";
import { projectsfilterSchema } from "@/utils/zod-schemas/params";
import { OrganizationProjectsTable } from "./OrganizationProjectsTable";

export type ProjectListType = {
name: string;
latest_action_on: string | null;
created_at: string;
repo_full_name: string | null;
slug: string;
}

export async function UserProjectsWithPagination({
organizationId,
searchParams,
Expand All @@ -15,7 +23,7 @@ export async function UserProjectsWithPagination({
getLoggedInUserOrganizationRole(organizationId)
]);
const [projects, totalPages] = await Promise.all([
getProjectsForUser({ ...filters, organizationId, userRole, userId }),
getProjectsListForUser({ ...filters, organizationId, userRole, userId }),
getProjectsCountForUser({ ...filters, organizationId, userId }),
]);

Expand All @@ -33,10 +41,9 @@ export async function AllProjectsTableWithPagination({
}: { organizationId: string; searchParams: unknown }) {
const filters = projectsfilterSchema.parse(searchParams);
const [projects, totalPages] = await Promise.all([
getAllProjectsInOrganization({ ...filters, organizationId }),
getAllProjectsListInOrganization({ ...filters, organizationId }),
getProjectsTotalCount({ ...filters, organizationId }),
]);

return (
<>
<OrganizationProjectsTable projects={projects} />
Expand All @@ -53,7 +60,7 @@ export async function ProjectsTableWithPagination({
}: { organizationId: string; teamId: number | null; searchParams: unknown }) {
const filters = projectsfilterSchema.parse(searchParams);
const [projects, totalPages] = await Promise.all([
getProjects({ ...filters, organizationId, teamId }),
getProjectsList({ ...filters, organizationId, teamId }),
getProjectsTotalCount({ ...filters, organizationId }),
]);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Pagination } from "@/components/Pagination";
import { getProjects, getProjectsTotalCount } from "@/data/user/projects";
import { getProjectsList, getProjectsTotalCount } from "@/data/user/projects";
import { projectsfilterSchema } from "@/utils/zod-schemas/params";
import { OrganizationProjectsTable } from "../../../(specific-organization-pages)/projects/OrganizationProjectsTable";

Expand All @@ -10,7 +10,7 @@ export async function TeamProjectsWithPagination({
}: { organizationId: string; teamId: number | null; searchParams: unknown }) {
const filters = projectsfilterSchema.parse(searchParams);
const [projects, totalPages] = await Promise.all([
getProjects({ ...filters, organizationId, teamId }),
getProjectsList({ ...filters, organizationId, teamId }),
getProjectsTotalCount({ ...filters, organizationId }),
]);

Expand Down
220 changes: 178 additions & 42 deletions src/data/user/projects.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"use server";
import { ProjectListType } from "@/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/org/[organizationId]/(specific-organization-pages)/projects/ProjectsWithPagination";
import { CommentList } from "@/components/Projects/CommentList";
import type { Tables } from "@/lib/database.types";
import { supabaseAdminClient } from "@/supabase-clients/admin/supabaseAdminClient";
Expand All @@ -9,6 +10,7 @@ import { normalizeComment } from "@/utils/comments";
import { serverGetLoggedInUser } from "@/utils/server/serverGetLoggedInUser";
import { revalidatePath } from "next/cache";
import { Suspense } from "react";
import { getRepoDetails } from "./repos";

export async function getSlimProjectById(projectId: string) {
const supabaseClient = createSupabaseUserServerComponentClient();
Expand Down Expand Up @@ -242,48 +244,6 @@ export const markProjectAsCompletedAction = async (projectId: string): Promise<S
return { status: 'success', data };
};

// export async function getProjectsForUser(userId: string, organizationId: string): Promise<Tables<'projects'>[]> {
// const supabase = createSupabaseUserServerComponentClient();

// // First, get the user's role in the organization
// const { data: userRole } = await supabase
// .from('organization_members')
// .select('member_role')
// .eq('organization_id', organizationId)
// .eq('member_id', userId)
// .single();

// if (!userRole) {
// throw new Error('User not found in organization');
// }

// let query = supabase
// .from('projects')
// .select('*')
// .eq('organization_id', organizationId);

// if (userRole.member_role === 'admin') {
// // Admins can see all projects
// const { data, error } = await query;
// if (error) throw error;
// return data;
// } else {
// // Regular members can see organization-level projects and projects from their teams
// const { data: userTeams } = await supabase
// .from('team_members')
// .select('team_id')
// .eq('user_id', userId);

// const teamIds = userTeams?.map(team => team.team_id) || [];

// const { data, error } = await query
// .or(`team_id.is.null,team_id.in.(${teamIds.join(',')})`);

// if (error) throw error;
// return data;
// }
// }

export async function getProjectsForUser({
userId,
userRole,
Expand Down Expand Up @@ -329,6 +289,71 @@ export async function getProjectsForUser({
return data || [];
}

export async function getProjectsListForUser({
userId,
userRole,
organizationId,
query = '',
teamIds = [],
}: {
userId: string;
userRole: Enum<'organization_member_role'>;
organizationId: string;
query?: string;
teamIds?: number[];
}): Promise<ProjectListType[]> {
const supabase = createSupabaseUserServerComponentClient();

let supabaseQuery = supabase
.from('projects')
.select('name, slug, latest_action_on, created_at, repo_id')
.eq('organization_id', organizationId)
.ilike('name', `%${query}%`);

if (userRole !== 'admin' || userId !== 'owner') {
// For non-admin users, get their team memberships
const { data: userTeams } = await supabase
.from('team_members')
.select('team_id')
.eq('user_id', userId);

const userTeamIds = userTeams?.map(team => team.team_id) || [];

// Filter by user's teams and organization-level projects
supabaseQuery = supabaseQuery.or(`team_id.is.null,team_id.in.(${userTeamIds.join(',')})`);
}

// Apply team filter if provided
if (teamIds.length > 0) {
supabaseQuery = supabaseQuery.in('team_id', teamIds);
}

const { data, error } = await supabaseQuery.order('latest_action_on', {
ascending: false,
});

if (error) {
console.error("Error fetching projects:", error);
return [];
}

if (!data) return [];

// Fetch repo details for each project
const projectsWithRepoDetails = await Promise.all(
data.map(async (project) => {
const repoDetails = await getRepoDetails(project.repo_id);
const { repo_id, ...projectWithoutRepoId } = project;
return {
...projectWithoutRepoId,
repo_full_name: repoDetails?.repo_full_name || null,
};
})
);

return projectsWithRepoDetails;
}

export async function getProjectsCountForUser({
userId,
organizationId,
Expand Down Expand Up @@ -423,6 +448,9 @@ export const getAllProjectsInOrganization = async ({
return data || [];
};




export const getOrganizationLevelProjects = async ({
organizationId,
query = "",
Expand Down Expand Up @@ -459,6 +487,7 @@ export const getOrganizationLevelProjects = async ({
return data || [];
};


export const getProjects = async ({
organizationId,
teamId,
Expand Down Expand Up @@ -505,6 +534,113 @@ export const getProjects = async ({
return data || [];
};

export const getAllProjectsListInOrganization = async ({
organizationId,
query = "",
page = 1,
limit = 20,
}: {
query?: string;
page?: number;
organizationId: string;
limit?: number;
}) => {
const zeroIndexedPage = page - 1;
const supabase = createSupabaseUserServerComponentClient();
let supabaseQuery = supabase
.from("projects")
.select("name, slug, latest_action_on, created_at, repo_id")
.eq("organization_id", organizationId)
.range(zeroIndexedPage * limit, (zeroIndexedPage + 1) * limit - 1);

if (query) {
supabaseQuery = supabaseQuery.ilike("name", `%${query}%`);
}

const { data, error } = await supabaseQuery.order("latest_action_on", {
ascending: false,
});

if (error) {
console.error("Error fetching projects:", error);
return [];
}

if (!data) return [];

// Fetch repo details for each project
const projectsWithRepoDetails = await Promise.all(
data.map(async (project) => {
const repoDetails = await getRepoDetails(project.repo_id);
const { repo_id, ...projectWithoutRepoId } = project;
return {
...projectWithoutRepoId,
repo_full_name: repoDetails?.repo_full_name || null,
};
})
);

return projectsWithRepoDetails;
};

export const getProjectsList = async ({
organizationId,
teamId,
query = "",
page = 1,
limit = 5,
}: {
query?: string;
page?: number;
organizationId: string;
teamId: number | null;
limit?: number;
}) => {
const zeroIndexedPage = page - 1;
const supabase = createSupabaseUserServerComponentClient();
let supabaseQuery = supabase
.from("projects")
.select("name, slug, latest_action_on, created_at, repo_id")
.eq("organization_id", organizationId)
.range(zeroIndexedPage * limit, (zeroIndexedPage + 1) * limit - 1);

// Add team filter
if (teamId !== null) {
supabaseQuery = supabaseQuery.eq('team_id', teamId);
} else {
supabaseQuery = supabaseQuery.is('team_id', null);
}

if (query) {
supabaseQuery = supabaseQuery.ilike("name", `%${query}%`);
}

const { data, error } = await supabaseQuery.order("latest_action_on", {
ascending: false,
});

if (error) {
console.error("Error fetching projects:", error);
return [];
}

if (!data) return [];

// Fetch repo details for each project
const projectsWithRepoDetails: ProjectListType[] = await Promise.all(
data.map(async (project) => {
const repoDetails = await getRepoDetails(project.repo_id);
const { repo_id, ...projectWithoutRepoId } = project;
return {
...projectWithoutRepoId,
repo_full_name: repoDetails?.repo_full_name || null,
};
})
);

return projectsWithRepoDetails;
};

export const getProjectsTotalCount = async ({
organizationId,
query = "",
Expand Down

0 comments on commit 4f5a12e

Please sign in to comment.