+ {isLocalEnvironment && (
+
+
+
+ Drift Detected
+
+
+ Changes have been detected in your infrastructure that differ from your Terraform configuration. Please review and reconcile these differences.
+
+
+ )}
+
diff --git a/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/@sidebar/ProjectSidebar.tsx b/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/@sidebar/ProjectSidebar.tsx
index 50609dcf..f792a511 100644
--- a/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/@sidebar/ProjectSidebar.tsx
+++ b/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/@sidebar/ProjectSidebar.tsx
@@ -5,7 +5,7 @@ import { fetchSlimOrganizations } from '@/data/user/organizations';
import { getSlimProjectById, getSlimProjectBySlug } from '@/data/user/projects';
import { cn } from '@/utils/cn';
import { projectSlugParamSchema } from '@/utils/zod-schemas/params';
-import { Activity, ArrowLeft, FileText, Layers, MessageCircle, Users } from 'lucide-react';
+import { Activity, ArrowLeft, FileText, FlagIcon, Layers, MessageCircle, Users } from 'lucide-react';
import { Suspense } from 'react';
async function ProjectSidebarInternal({ projectId, projectSlug }: { projectId: string; projectSlug: string }) {
@@ -37,6 +37,11 @@ async function ProjectSidebarInternal({ projectId, projectSlug }: { projectId: s
href={`/org/${organizationId}/projects`}
icon={
}
/>
+
}
+ />
;
+ projectIds: string[];
+ teamIds?: number[];
+}): Promise {
+ const supabase = createSupabaseUserServerComponentClient();
+
+ let supabaseQuery = supabase
+ .from('projects')
+ .select('id,name, slug, latest_action_on, created_at, repo_id')
+ .in('id', projectIds);
+
+ 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 getProjectsIdsListForUser({
userId,
userRole,
@@ -518,7 +580,43 @@ export const getAllProjectsInOrganization = async ({
return data || [];
};
+export const getAllProjectIdsInOrganization = async (organizationId: string) => {
+ const supabase = createSupabaseUserServerComponentClient();
+ const supabaseQuery = supabase
+ .from("projects")
+ .select("id")
+ .eq("organization_id", organizationId)
+ .order("created_at", { ascending: false });
+
+ const { data, error } = await supabaseQuery;
+
+ if (error) {
+ console.error("Error fetching project IDs:", error);
+ return [];
+ }
+
+ return data?.map(project => project.id) || [];
+};
+
+export const getProjectIdsInOrganization = async (organizationId: string, count: number) => {
+ const supabase = createSupabaseUserServerComponentClient();
+ const supabaseQuery = supabase
+ .from("projects")
+ .select("id")
+ .eq("organization_id", organizationId);
+
+ const { data, error } = await supabaseQuery;
+
+ if (error) {
+ console.error("Error fetching project IDs:", error);
+ return [];
+ }
+ const projectIds = data?.map(project => project.id) || [];
+
+ // Shuffle the array and slice to get random project IDs
+ return projectIds.sort(() => Math.random() - 0.5).slice(0, count);
+};
export const getOrganizationLevelProjects = async ({
@@ -619,7 +717,7 @@ export const getAllProjectsListInOrganization = async ({
const supabase = createSupabaseUserServerComponentClient();
let supabaseQuery = supabase
.from("projects")
- .select("name, slug, latest_action_on, created_at, repo_id")
+ .select("id,name, slug, latest_action_on, created_at, repo_id")
.eq("organization_id", organizationId)
.range(zeroIndexedPage * limit, (zeroIndexedPage + 1) * limit - 1);
@@ -670,7 +768,7 @@ export const getProjectsList = async ({
const supabase = createSupabaseUserServerComponentClient();
let supabaseQuery = supabase
.from("projects")
- .select("name, slug, latest_action_on, created_at, repo_id")
+ .select("id,name, slug, latest_action_on, created_at, repo_id")
.eq("organization_id", organizationId)
.range(zeroIndexedPage * limit, (zeroIndexedPage + 1) * limit - 1);
diff --git a/src/lib/utils.ts b/src/lib/utils.ts
index 5e8a35ec..d0de0cf2 100644
--- a/src/lib/utils.ts
+++ b/src/lib/utils.ts
@@ -34,3 +34,6 @@ export const ToSnakeCase = (str: string) => {
.map((word) => word.toLowerCase())
.join('_');
};
+
+export const isLocalEnvironment =
+ process.env.NEXT_PUBLIC_SITE_URL?.includes('localhost');