From fa4c629f7b7b97a5a0325a119ee5b1d1af45de82 Mon Sep 17 00:00:00 2001
From: psiddharthdesign <107192927+psiddharthdesign@users.noreply.github.com>
Date: Tue, 30 Jul 2024 18:24:53 +0530
Subject: [PATCH] supabase realtime updates on digger runs
---
.../@navbar/[...catchAll]/page.tsx | 3 -
.../AllRunsDetails.tsx | 90 ++++++++++++++++++-
.../(specific-project-pages)/page.tsx | 79 +---------------
.../runs/[runId]/ProjectRunDetails.tsx | 30 ++++++-
src/data/user/tfvars.ts | 0
.../user/supabaseUserClientComponentClient.ts | 5 --
...20240730102713_realtime-to-digger-runs.sql | 4 +
7 files changed, 123 insertions(+), 88 deletions(-)
create mode 100644 src/data/user/tfvars.ts
create mode 100644 supabase/migrations/20240730102713_realtime-to-digger-runs.sql
diff --git a/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/org/[organizationId]/(specific-organization-pages)/@navbar/[...catchAll]/page.tsx b/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/org/[organizationId]/(specific-organization-pages)/@navbar/[...catchAll]/page.tsx
index 425023f1..104a5d09 100644
--- a/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/org/[organizationId]/(specific-organization-pages)/@navbar/[...catchAll]/page.tsx
+++ b/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/org/[organizationId]/(specific-organization-pages)/@navbar/[...catchAll]/page.tsx
@@ -11,9 +11,6 @@ import { Suspense } from 'react';
export async function generateMetadata({ params }: { params: unknown }) {
try {
const { organizationId } = organizationParamSchema.parse(params);
- console.log('----------------------------------------')
- console.log('in [...catchAll]/page organizationId', organizationId)
- console.log('----------------------------------------')
const organizationTitle = await getOrganizationTitle(organizationId);
return {
diff --git a/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/(specific-project-pages)/AllRunsDetails.tsx b/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/(specific-project-pages)/AllRunsDetails.tsx
index ab0fb901..f5b99b1d 100644
--- a/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/(specific-project-pages)/AllRunsDetails.tsx
+++ b/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/(specific-project-pages)/AllRunsDetails.tsx
@@ -1,11 +1,95 @@
'use client';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
-import { Tables } from "@/lib/database.types";
+import { Skeleton } from "@/components/ui/skeleton";
+import { getRunsByProjectId } from "@/data/user/runs";
+import { supabaseUserClientComponentClient } from "@/supabase-clients/user/supabaseUserClientComponentClient";
+import { useQuery } from "@tanstack/react-query";
import { motion } from "framer-motion";
+import { useEffect } from "react";
import { AllRunsTable } from "./AllRunsTable";
-export default function AllRunsDetails({ runs, project }: { runs: Tables<'digger_runs'>[], project: Tables<'projects'> }) {
+export default function AllRunsDetails({
+ projectId,
+ projectSlug
+}: {
+ projectId: string;
+ projectSlug: string;
+}) {
+
+ const { data: runs, refetch, isLoading } = useQuery(
+ ['runs', projectId],
+ async () => {
+ return getRunsByProjectId(projectId);
+ },
+ {
+ refetchOnWindowFocus: false,
+ }
+ );
+
+ useEffect(() => {
+ const channel = supabaseUserClientComponentClient
+ .channel('digger_runs_realtime')
+ .on(
+ 'postgres_changes',
+ {
+ event: 'INSERT',
+ schema: 'public',
+ table: 'digger_runs',
+ filter: `project_id=eq.${projectId}`
+ },
+ (payload) => {
+ refetch();
+ }
+ )
+ .on(
+ 'postgres_changes',
+ {
+ event: 'UPDATE',
+ schema: 'public',
+ table: 'digger_runs',
+ filter: `project_id=eq.${projectId}`
+ },
+ (payload) => {
+ refetch();
+ },
+ )
+ .subscribe();
+
+ return () => {
+ channel.unsubscribe();
+ };
+ }, [projectId, refetch]);
+
+ if (isLoading) {
+ return (
+
+
+ {[...Array(3)].map((_, index) => (
+
+
+
+
+
+
+ ))}
+
+
+ );
+ }
+
+ if (!runs) {
+ return
+
+ Project Runs
+ View all runs for this project
+
+
+ No runs found
+
+
+ }
+
return (
-
+
diff --git a/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/(specific-project-pages)/page.tsx b/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/(specific-project-pages)/page.tsx
index 5c4d5a5a..a559a4a5 100644
--- a/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/(specific-project-pages)/page.tsx
+++ b/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/(specific-project-pages)/page.tsx
@@ -1,8 +1,7 @@
-
-
-import { getProjectById, getSlimProjectBySlug } from "@/data/user/projects";
+import { getSlimProjectBySlug } from "@/data/user/projects";
import { projectSlugParamSchema } from "@/utils/zod-schemas/params";
import type { Metadata } from "next";
+import AllRunsDetails from "./AllRunsDetails";
type ProjectPageProps = {
params: {
@@ -22,84 +21,14 @@ export async function generateMetadata({
};
}
-
-import { getRunsByProjectId } from "@/data/user/runs";
-import AllRunsDetails from "./AllRunsDetails";
-
-// const dummyRuns: Run[] = [
-// {
-// runId: "run-001",
-// commitId: "abc123",
-// status: "queued",
-// date: "2023-06-01",
-// user: "Alice"
-// },
-// {
-// runId: "run-002",
-// commitId: "def456",
-// status: "pending approval",
-// date: "2023-06-02",
-// user: "Bob"
-// },
-// {
-// runId: "run-003",
-// commitId: "ghi789",
-// status: "running",
-// date: "2023-06-03",
-// user: "Charlie"
-// },
-// {
-// runId: "run-004",
-// commitId: "jkl012",
-// status: "approved",
-// date: "2023-06-04",
-// user: "Diana"
-// },
-// {
-// runId: "run-005",
-// commitId: "mno345",
-// status: "succeeded",
-// date: "2023-06-05",
-// user: "Ethan"
-// },
-// {
-// runId: "run-006",
-// commitId: "pqr678",
-// status: "failed",
-// date: "2023-06-06",
-// user: "Fiona"
-// },
-// {
-// runId: "run-007",
-// commitId: "stu901",
-// status: "queued",
-// date: "2023-06-07",
-// user: "George"
-// },
-// {
-// runId: "run-008",
-// commitId: "vwx234",
-// status: "running",
-// date: "2023-06-08",
-// user: "Hannah"
-// }
-// ];
-
-// const runs = dummyRuns;
-
-
export default async function ProjectPage({ params }: { params: unknown }) {
const { projectSlug } = projectSlugParamSchema.parse(params);
const slimProject = await getSlimProjectBySlug(projectSlug);
- const project = await getProjectById(slimProject.id);
- const runs = await getRunsByProjectId(slimProject.id);
+
return (
);
};
\ No newline at end of file
diff --git a/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/runs/[runId]/ProjectRunDetails.tsx b/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/runs/[runId]/ProjectRunDetails.tsx
index 316c2909..dbc5b1c1 100644
--- a/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/runs/[runId]/ProjectRunDetails.tsx
+++ b/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/runs/[runId]/ProjectRunDetails.tsx
@@ -8,6 +8,7 @@ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/comp
import { approveRun, rejectRun } from "@/data/user/runs";
import { useSAToastMutation } from "@/hooks/useSAToastMutation";
import { ToSnakeCase, ToTitleCase } from "@/lib/utils";
+import { supabaseUserClientComponentClient } from "@/supabase-clients/user/supabaseUserClientComponentClient";
import { Table } from "@/types";
import { DotFilledIcon } from "@radix-ui/react-icons";
import { AnimatePresence, motion } from 'framer-motion';
@@ -15,7 +16,7 @@ import { CheckCircle2, Clock, GitPullRequest, LinkIcon, Loader2, Play, XCircle }
import Image from 'next/image';
import Link from "next/link";
import { useRouter } from 'next/navigation';
-import React, { useState } from 'react';
+import React, { useEffect, useState } from 'react';
import { statusColors } from "../../(specific-project-pages)/AllRunsTable";
@@ -121,7 +122,7 @@ export const ProjectRunDetails: React.FC<{
applyTerraformOutput: string | null
applyWorkflowRunUrl: string | null
fullRepoName: string | null
-}> = ({ run, loggedInUser, isUserOrgAdmin, tfOutput, workflowRunUrl, applyTerraformOutput, applyWorkflowRunUrl, fullRepoName }) => {
+}> = ({ run: initialRun, loggedInUser, isUserOrgAdmin, tfOutput, workflowRunUrl, applyTerraformOutput, applyWorkflowRunUrl, fullRepoName }) => {
const router = useRouter();
const [activeStage, setActiveStage] = useState<'plan' | 'apply'>('plan');
@@ -149,6 +150,31 @@ export const ProjectRunDetails: React.FC<{
}
);
+ const [run, setRun] = useState(initialRun);
+
+
+ useEffect(() => {
+ const channel = supabaseUserClientComponentClient
+ .channel(`digger_run_${run.id}`)
+ .on(
+ 'postgres_changes',
+ {
+ event: 'UPDATE',
+ schema: 'public',
+ table: 'digger_runs',
+ filter: `id=eq.${run.id}`
+ },
+ (payload) => {
+ setRun(payload.new as Table<'digger_runs'>);
+ }
+ )
+ .subscribe();
+
+ return () => {
+ supabaseUserClientComponentClient.removeChannel(channel);
+ };
+ }, [run.id]);
+
return (
({
- options: {
- global: {
- fetch,
- },
- },
cookieOptions: optionalCookieOptions,
});
diff --git a/supabase/migrations/20240730102713_realtime-to-digger-runs.sql b/supabase/migrations/20240730102713_realtime-to-digger-runs.sql
new file mode 100644
index 00000000..cf9e156f
--- /dev/null
+++ b/supabase/migrations/20240730102713_realtime-to-digger-runs.sql
@@ -0,0 +1,4 @@
+ ALTER PUBLICATION supabase_realtime ADD TABLE public.digger_runs;
+ ALTER TABLE public.digger_runs REPLICA IDENTITY FULL;
+
+CREATE INDEX ON digger_runs (project_id);
\ No newline at end of file