Skip to content

Commit 005e0c4

Browse files
feature/run details
1 parent f41a40c commit 005e0c4

File tree

13 files changed

+522
-97
lines changed

13 files changed

+522
-97
lines changed

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -185,8 +185,8 @@
185185
"dev:debug": "NODE_OPTIONS='--inspect' next dev",
186186
"email:dev": "email dev",
187187
"start": "next start",
188-
"generate:types": "supabase gen types typescript --linked --schema public > src/lib/database.types.ts",
189-
"generate:types:local": "supabase gen types typescript --local > src/lib/database.types.ts",
188+
"generate:types": "supabase gen types --lang=typescript --linked --schema public > src/lib/database.types.ts",
189+
"generate:types:local": "supabase gen types --lang=typescript --local > src/lib/database.types.ts",
190190
"build": "next build",
191191
"test:e2e": "cross-env NODE_ENV=test playwright test",
192192
"test:e2e:ui": "cross-env NODE_ENV=test playwright test --ui",

src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/runs/[runId]/ProjectRunDetails.tsx

+342
Large diffs are not rendered by default.

src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/runs/[runId]/RunDetails.tsx

-80
This file was deleted.

src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/runs/[runId]/page.tsx

+31-5
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11

22
import { PageHeading } from "@/components/PageHeading";
33
import { T } from "@/components/ui/Typography";
4+
import { getLoggedInUserOrganizationRole } from "@/data/user/organizations";
5+
import { getSlimProjectById } from "@/data/user/projects";
46
import { getRunById } from "@/data/user/runs";
7+
import { getUserProfile } from "@/data/user/user";
8+
import { Table } from "@/types";
9+
import { serverGetLoggedInUser } from "@/utils/server/serverGetLoggedInUser";
510
import {
611
runIdParamSchema
712
} from "@/utils/zod-schemas/params";
813
import type { Metadata } from "next";
9-
import { Suspense } from "react";
10-
import { RunDetails } from "./RunDetails";
14+
import dynamic from 'next/dynamic';
15+
import { ComponentType, Suspense } from "react";
1116

1217
export const metadata: Metadata = {
1318
title: "Projects",
@@ -20,22 +25,43 @@ type RunDetailPageProps = {
2025
};
2126
};
2227

28+
type ProjectRunDetailsProps = {
29+
run: Table<'digger_runs'>,
30+
loggedInUser: Table<'user_profiles'>,
31+
isUserOrgAdmin: boolean
32+
}
33+
34+
35+
36+
const DynamicProjectRunDetails = dynamic<ProjectRunDetailsProps>(() =>
37+
import('./ProjectRunDetails').then((mod) => mod.ProjectRunDetails as ComponentType<ProjectRunDetailsProps>),
38+
{ ssr: false }
39+
)
40+
2341

2442
export default async function RunDetailPage({
2543
params,
2644

2745
}: RunDetailPageProps) {
2846
const { runId } = runIdParamSchema.parse(params);
2947
const run = await getRunById(runId);
48+
const project_id = run.project_id;
49+
const [project, user] = await Promise.all([
50+
getSlimProjectById(project_id),
51+
serverGetLoggedInUser()
52+
]);
53+
const userProfile = await getUserProfile(user.id);
54+
const organizationRole = await getLoggedInUserOrganizationRole(project.organization_id);
3055

56+
const isOrganizationAdmin =
57+
organizationRole === "admin" || organizationRole === "owner";
3158
return (
32-
<div className="flex flex-col space-y-4 max-w-5xl mt-8">
59+
<div className="flex flex-col space-y-4 w-full mt-8">
3360
<PageHeading
3461
title="Run Details"
3562
subTitle="Details about the specific project run will be displayed here."
3663
/>
3764
<div className="flex justify-between gap-2">
38-
3965
</div>
4066
{
4167
<Suspense
@@ -45,7 +71,7 @@ export default async function RunDetailPage({
4571
</T.P>
4672
}
4773
>
48-
<RunDetails run={run} />
74+
<DynamicProjectRunDetails run={run} loggedInUser={userProfile} isUserOrgAdmin={isOrganizationAdmin} />
4975
</Suspense>
5076
}
5177
</div>

src/app/layout.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import '@/styles/globals.css';
22
import '@/styles/prosemirror.css';
3+
import { GeistMono } from 'geist/font/mono';
34
import { GeistSans } from 'geist/font/sans';
45
import { Metadata } from 'next';
56
import 'server-only';
@@ -22,7 +23,7 @@ export default async function RootLayout({
2223
children: React.ReactNode;
2324
}) {
2425
return (
25-
<html lang="en" className={GeistSans.className} suppressHydrationWarning>
26+
<html lang="en" className={`${GeistSans.className} ${GeistMono.variable}`} suppressHydrationWarning>
2627
<head></head>
2728
<body className="">
2829
<AppProviders>{children}</AppProviders>

src/data/user/projects.tsx

+17
Original file line numberDiff line numberDiff line change
@@ -346,4 +346,21 @@ export async function updateProjectSettingsAction({
346346
console.error("Error updating project settings:", error);
347347
return { status: 'error', message: 'Failed to update project settings' };
348348
}
349+
}
350+
351+
export async function deleteProject(projectId: string): Promise<SAPayload<unknown>> {
352+
const supabase = createSupabaseUserServerComponentClient();
353+
const { data, error } = await supabase
354+
.from('projects')
355+
.update({
356+
deleted_at: new Date().toISOString(),
357+
})
358+
.eq('id', projectId)
359+
.single();
360+
361+
if (error) {
362+
return { status: 'error', message: error.message };
363+
}
364+
365+
return { status: 'success', data };
349366
}

src/data/user/runs.ts

+74
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use server';
22

33
import { createSupabaseUserServerComponentClient } from '@/supabase-clients/user/createSupabaseUserServerComponentClient';
4+
import { SAPayload } from '@/types';
45

56
export async function getTFVarsByProjectId(projectId: string) {
67
const supabaseClient = createSupabaseUserServerComponentClient();
@@ -122,3 +123,76 @@ export async function getRunsByProjectId(projectId: string) {
122123
if (error) throw error;
123124
return data;
124125
}
126+
127+
export async function requestRunApproval(
128+
runId: string,
129+
): Promise<SAPayload<string>> {
130+
const supabase = createSupabaseUserServerComponentClient();
131+
const { data, error } = await supabase
132+
.from('digger_runs')
133+
.update({ status: 'pending_approval' })
134+
.eq('id', runId)
135+
.select('id')
136+
.single();
137+
138+
if (error) {
139+
return { status: 'error', message: error.message };
140+
}
141+
return { status: 'success', data: data.id };
142+
}
143+
144+
export async function approveRun(
145+
runId: string,
146+
userId: string,
147+
): Promise<SAPayload<string>> {
148+
const supabase = createSupabaseUserServerComponentClient();
149+
const { data, error } = await supabase
150+
.from('digger_runs')
151+
.update({
152+
status: 'pending_apply',
153+
approver_user_id: userId,
154+
is_approved: true,
155+
})
156+
.eq('id', runId)
157+
.select('id')
158+
.single();
159+
160+
if (error) {
161+
return { status: 'error', message: error.message };
162+
}
163+
return { status: 'success', data: data.id };
164+
}
165+
166+
export async function rejectRun(
167+
runId: string,
168+
userId: string,
169+
): Promise<SAPayload<string>> {
170+
const supabase = createSupabaseUserServerComponentClient();
171+
const { data, error } = await supabase
172+
.from('digger_runs')
173+
.update({
174+
status: 'rejected',
175+
approver_user_id: userId,
176+
is_approved: false,
177+
})
178+
.eq('id', runId)
179+
.select('id')
180+
.single();
181+
182+
if (error) {
183+
return { status: 'error', message: error.message };
184+
}
185+
return { status: 'success', data: data.id };
186+
}
187+
188+
export async function changeRunStatus(runId: string, status: string) {
189+
const supabase = createSupabaseUserServerComponentClient();
190+
const { error } = await supabase
191+
.from('digger_runs')
192+
.update({ status: status })
193+
.eq('id', runId)
194+
.select('id')
195+
.single();
196+
197+
if (error) throw error;
198+
}

0 commit comments

Comments
 (0)