From 005e0c4f83f1b690ef320510c60ab30883ee2b43 Mon Sep 17 00:00:00 2001 From: psiddharthdesign <107192927+psiddharthdesign@users.noreply.github.com> Date: Sat, 27 Jul 2024 02:18:49 +0530 Subject: [PATCH] feature/run details --- package.json | 4 +- .../runs/[runId]/ProjectRunDetails.tsx | 342 ++++++++++++++++++ .../[projectSlug]/runs/[runId]/RunDetails.tsx | 80 ---- .../[projectSlug]/runs/[runId]/page.tsx | 36 +- src/app/layout.tsx | 3 +- src/data/user/projects.tsx | 17 + src/data/user/runs.ts | 74 ++++ src/lib/database.types.ts | 35 +- src/styles/globals.css | 10 +- .../20240726135234_remote_schema.sql | 7 + ...726181205_add_terraform_column_to_runs.sql | 8 + .../20240726184158_add_changes_to_runs.sql | 2 + tailwind.config.cjs | 1 + 13 files changed, 522 insertions(+), 97 deletions(-) create mode 100644 src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/runs/[runId]/ProjectRunDetails.tsx delete mode 100644 src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/runs/[runId]/RunDetails.tsx create mode 100644 supabase/migrations/20240726135234_remote_schema.sql create mode 100644 supabase/migrations/20240726181205_add_terraform_column_to_runs.sql create mode 100644 supabase/migrations/20240726184158_add_changes_to_runs.sql diff --git a/package.json b/package.json index 556610c9..3bd30226 100644 --- a/package.json +++ b/package.json @@ -185,8 +185,8 @@ "dev:debug": "NODE_OPTIONS='--inspect' next dev", "email:dev": "email dev", "start": "next start", - "generate:types": "supabase gen types typescript --linked --schema public > src/lib/database.types.ts", - "generate:types:local": "supabase gen types typescript --local > src/lib/database.types.ts", + "generate:types": "supabase gen types --lang=typescript --linked --schema public > src/lib/database.types.ts", + "generate:types:local": "supabase gen types --lang=typescript --local > src/lib/database.types.ts", "build": "next build", "test:e2e": "cross-env NODE_ENV=test playwright test", "test:e2e:ui": "cross-env NODE_ENV=test playwright test --ui", 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 new file mode 100644 index 00000000..e1db78f5 --- /dev/null +++ b/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/runs/[runId]/ProjectRunDetails.tsx @@ -0,0 +1,342 @@ +'use client'; + +import { T } from "@/components/ui/Typography"; +import { Badge } from "@/components/ui/badge"; +import { Button } from "@/components/ui/button"; +import { Card, CardContent } from "@/components/ui/card"; +import { approveRun, changeRunStatus, rejectRun } from "@/data/user/runs"; +import { useSAToastMutation } from "@/hooks/useSAToastMutation"; +import { Table } from "@/types"; +import { DotFilledIcon } from "@radix-ui/react-icons"; +import { AnimatePresence, motion } from 'framer-motion'; +import { CheckCircle2, Clock, GitPullRequest, Loader2, Play, XCircle } from 'lucide-react'; +import Image from 'next/image'; +import { useRouter } from 'next/navigation'; +import React, { useEffect, useState } from 'react'; +import { statusColors } from "../../(specific-project-pages)/RunsTable"; + +type RunStage = 'pending_approval' | 'pending_apply' | 'rejected' | 'applied'; + + +const logEntries = [ + { time: "2024-07-01T12:34:56Z", author: "Siddharth Ponnapalli", title: "Added basic VPC setup" }, + { time: "2024-07-01T13:45:22Z", author: "Siddharth Ponnapalli", title: "Added subnets and associated them with VPC" }, + { time: "2024-07-02T09:14:33Z", author: "Siddharth Ponnapalli", title: "Created security groups for web servers" }, + { time: "2024-07-02T10:22:12Z", author: "Siddharth Ponnapalli", title: "Added EC2 instances in different subnets" }, + { time: "2024-07-03T11:55:47Z", author: "Siddharth Ponnapalli", title: "Configured S3 buckets and objects" }, + { time: "2024-07-03T14:33:29Z", author: "Siddharth Ponnapalli", title: "Added RDS instance with MySQL" }, + { time: "2024-07-04T08:45:22Z", author: "Siddharth Ponnapalli", title: "Created IAM role, policy, and instance profile" }, + { time: "2024-07-04T10:12:09Z", author: "Siddharth Ponnapalli", title: "Added third EC2 instance with IAM role" }, + { time: "2024-07-05T11:34:56Z", author: "Siddharth Ponnapalli", title: "Updated security group rules for enhanced security" }, + { time: "2024-07-05T13:45:22Z", author: "Siddharth Ponnapalli", title: "Refactored subnet CIDR blocks for better segmentation" }, + { time: "2024-07-06T09:14:33Z", author: "Siddharth Ponnapalli", title: "Improved S3 bucket policies for enhanced security" }, + { time: "2024-07-06T10:22:12Z", author: "Siddharth Ponnapalli", title: "Added outputs for easier infrastructure management" }, + { time: "2024-07-07T11:55:47Z", author: "Siddharth Ponnapalli", title: "Enhanced instance tagging for better identification" }, + { time: "2024-07-07T14:33:29Z", author: "Siddharth Ponnapalli", title: "Updated RDS instance settings for improved performance" }, + { time: "2024-07-08T08:45:22Z", author: "Siddharth Ponnapalli", title: "Optimized VPC and subnet configurations" }, + { time: "2024-07-08T10:12:09Z", author: "Siddharth Ponnapalli", title: "Cleaned up IAM policies for better security practices" }, + { time: "2024-07-09T11:34:56Z", author: "Siddharth Ponnapalli", title: "Added new S3 bucket for log storage" }, + { time: "2024-07-09T13:45:22Z", author: "Siddharth Ponnapalli", title: "Implemented CloudWatch logs for monitoring" }, + { time: "2024-07-10T09:14:33Z", author: "Siddharth Ponnapalli", title: "Configured CloudFront distribution for S3 bucket" }, + { time: "2024-07-10T10:22:12Z", author: "Siddharth Ponnapalli", title: "Added Route 53 records for domain management" }, + { time: "2024-07-11T11:55:47Z", author: "Siddharth Ponnapalli", title: "Updated EC2 instance types for better performance" }, + { time: "2024-07-11T14:33:29Z", author: "Siddharth Ponnapalli", title: "Refined security group rules for better protection" }, + { time: "2024-07-12T08:45:22Z", author: "Siddharth Ponnapalli", title: "Added auto-scaling configuration for EC2 instances" }, + { time: "2024-07-12T10:12:09Z", author: "Siddharth Ponnapalli", title: "Configured RDS backup and retention policies" }, + { time: "2024-07-13T11:34:56Z", author: "Siddharth Ponnapalli", title: "Updated IAM role policies for least privilege access" }, + { time: "2024-07-13T13:45:22Z", author: "Siddharth Ponnapalli", title: "Implemented Lambda function for automated backups" }, + { time: "2024-07-14T09:14:33Z", author: "Siddharth Ponnapalli", title: "Integrated CloudWatch alarms for monitoring" }, + { time: "2024-07-14T10:22:12Z", author: "Siddharth Ponnapalli", title: "Updated S3 bucket lifecycle policies for cost optimization" }, + { time: "2024-07-15T11:55:47Z", author: "Siddharth Ponnapalli", title: "Configured VPC peering for multi-region setup" }, + { time: "2024-07-15T14:33:29Z", author: "Siddharth Ponnapalli", title: "Enhanced CloudFront caching settings" }, + { time: "2024-07-16T08:45:22Z", author: "Siddharth Ponnapalli", title: "Added new security group for database access" }, + { time: "2024-07-16T10:12:09Z", author: "Siddharth Ponnapalli", title: "Updated RDS instance class for better performance" }, + { time: "2024-07-17T11:34:56Z", author: "Siddharth Ponnapalli", title: "Implemented SNS for notification alerts" }, + { time: "2024-07-17T13:45:22Z", author: "Siddharth Ponnapalli", title: "Configured SES for email notifications" }, + { time: "2024-07-18T09:14:33Z", author: "Siddharth Ponnapalli", title: "Added DynamoDB table for session management" }, + { time: "2024-07-18T10:22:12Z", author: "Siddharth Ponnapalli", title: "Updated IAM policies for DynamoDB access" }, + { time: "2024-07-19T11:55:47Z", author: "Siddharth Ponnapalli", title: "Enhanced EC2 instance monitoring with detailed metrics" }, + { time: "2024-07-19T14:33:29Z", author: "Siddharth Ponnapalli", title: "Configured VPC flow logs for network monitoring" }, + { time: "2024-07-20T08:45:22Z", author: "Siddharth Ponnapalli", title: "Updated security group ingress rules for specific IP ranges" }, + { time: "2024-07-20T10:12:09Z", author: "Siddharth Ponnapalli", title: "Added IAM policy for S3 read-only access" }, + { time: "2024-07-21T11:34:56Z", author: "Siddharth Ponnapalli", title: "Refined Lambda function code for efficiency" }, + { time: "2024-07-21T13:45:22Z", author: "Siddharth Ponnapalli", title: "Enhanced VPC subnet configuration for better isolation" }, + { time: "2024-07-22T09:14:33Z", author: "Siddharth Ponnapalli", title: "Configured CloudFormation stack for infrastructure as code" }, + { time: "2024-07-22T10:22:12Z", author: "Siddharth Ponnapalli", title: "Updated EC2 instance AMI for latest security patches" }, + { time: "2024-07-23T11:55:47Z", author: "Siddharth Ponnapalli", title: "Implemented SSM for instance management" }, + { time: "2024-07-23T14:33:29Z", author: "Siddharth Ponnapalli", title: "Enhanced IAM roles for cross-account access" }, + { time: "2024-07-24T08:45:22Z", author: "Siddharth Ponnapalli", title: "Configured RDS read replicas for high availability" }, + { time: "2024-07-24T10:12:09Z", author: "Siddharth Ponnapalli", title: "Added CloudFront invalidation for cache management" }, + { time: "2024-07-25T11:34:56Z", author: "Siddharth Ponnapalli", title: "Updated Route 53 health checks for better uptime monitoring" }, + { time: "2024-07-25T13:45:22Z", author: "Siddharth Ponnapalli", title: "Enhanced S3 bucket encryption settings for data security" }, + { time: "2024-07-26T09:14:33Z", author: "Siddharth Ponnapalli", title: "Configured ELB for load balancing EC2 instances" }, + { time: "2024-07-26T10:22:12Z", author: "Siddharth Ponnapalli", title: "Updated IAM policies for better resource access control" }, + { time: "2024-07-27T11:55:47Z", author: "Siddharth Ponnapalli", title: "Enhanced CloudWatch dashboards for better visibility" }, + { time: "2024-07-27T14:33:29Z", author: "Siddharth Ponnapalli", title: "Configured EC2 instance user data for automation" } +]; + + +function RenderContent({ + activeStage, + run, +}: { + activeStage: string; + run: Table<'digger_runs'>; +}) { + if (activeStage === 'plan') { + return ( +
+

Terraform Plan Output

+
+                    {run.terraform_output || 'No plan output available'}
+                
+
+ ); + } else if (activeStage === 'apply') { + if (run.status === 'pending_approval' || run.status === 'rejected') { + return ( +
+
+

Apply not available

+

The run needs to be approved before applying changes.

+
+
+ ); + } + return ( +
+

Apply logs

+
+ {logEntries.map((log, index) => ( +
+

{log.time}

+

{log.author}

+

{log.title}

+
+ ))} +
+
+ ); + } +} + + +export const ProjectRunDetails: React.FC<{ + run: Table<'digger_runs'>, + loggedInUser: Table<'user_profiles'> + isUserOrgAdmin: boolean +}> = ({ run, loggedInUser, isUserOrgAdmin }) => { + const router = useRouter(); + const [activeStage, setActiveStage] = useState<'plan' | 'apply'>('plan'); + const [applyLogs, setApplyLogs] = useState([]); + + useEffect(() => { + if (run.status === 'pending_apply') { + const timer = setTimeout(async () => { + await changeRunStatus(run.id, 'applied'); + setActiveStage('apply'); + router.refresh(); + }, 5000); + + return () => clearTimeout(timer); + } + }, [run.status, run.id, router]); + + useEffect(() => { + if (run.apply_logs) { + setApplyLogs(run.apply_logs.split('\n')); + } + }, [run.apply_logs]); + + const { mutate: approveMutation, isLoading: isApproving } = useSAToastMutation( + async () => await approveRun(run.id, loggedInUser.id), + { + loadingMessage: 'Approving run...', + successMessage: 'Run approved successfully', + errorMessage: 'Failed to approve run', + onSuccess: () => { + router.refresh(); + }, + } + ); + + const { mutate: rejectMutation, isLoading: isRejecting } = useSAToastMutation( + async () => await rejectRun(run.id, loggedInUser.id), + { + loadingMessage: 'Rejecting run...', + successMessage: 'Run rejected successfully', + errorMessage: 'Failed to reject run', + onSuccess: () => { + router.refresh(); + }, + } + ); + + + + return ( +
+ + +

Run Details

+
+ + + + + + {run.status.toUpperCase()} + + } /> + {run.pr_number && } +
+
+ +
+ } + name="Plan" + isActive={activeStage === 'plan'} + isComplete={run.status !== 'pending_approval'} + onClick={() => setActiveStage('plan')} + /> + {run.status === 'pending_approval' && isUserOrgAdmin && ( + + +

Do you approve the proposed changes?

+
+ + +
+
+
+ )} + } + name="Apply" + isActive={activeStage === 'apply'} + isComplete={run.status === 'applied'} + isDisabled={run.status === 'pending_approval' || run.status === 'rejected'} + onClick={() => setActiveStage('apply')} + /> + + {run.status === 'pending_apply' && run.is_approved && ( + + + Applying changes... + + )} +
+ {run.is_approved && run.status !== 'rejected' || 'pending_approval' && ( + Approved by: + )} + {run.status === 'rejected' && ( +

Rejected by:

+ )} + {(run.status === 'pending_apply' || run.status === 'applied' || run.status === 'rejected') && ( + +
+ {loggedInUser.avatar_url ? ( + {loggedInUser.full_name + ) : ( +
+ {loggedInUser.full_name?.charAt(0).toUpperCase() || 'A'} +
+ )} + +
+

{loggedInUser.full_name}

+

+ {isUserOrgAdmin ? 'Organization Admin' : 'Member'} +

+
+
+
+ )} +
+
+ +

Total Duration

+
+

4s

+
+
+ +
+ + + + + +
+
+
+ ); +}; + +const RunStage: React.FC<{ + icon: React.ReactNode, + name: string, + isActive: boolean, + isComplete: boolean, + isDisabled?: boolean, + onClick: () => void +}> = ({ icon, name, isActive, isComplete, isDisabled = false, onClick }) => ( + +
+ {icon} +

{name}

+
+ {isActive && !isComplete && } + {isComplete && } +
+); + +const DetailItem: React.FC<{ label: string, value: string | React.ReactNode }> = ({ label, value }) => ( +
+

{label}:

+ {typeof value === 'string' ?

{value}

: value} +
+); \ No newline at end of file diff --git a/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/runs/[runId]/RunDetails.tsx b/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/runs/[runId]/RunDetails.tsx deleted file mode 100644 index e60583ac..00000000 --- a/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/runs/[runId]/RunDetails.tsx +++ /dev/null @@ -1,80 +0,0 @@ -'use client'; - -import { Badge } from "@/components/ui/badge"; -import { Button } from "@/components/ui/button"; -import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; -import { Tables } from "@/lib/database.types"; -import { AnimatePresence, motion } from 'framer-motion'; -import { ChevronDown } from 'lucide-react'; -import React, { useState } from 'react'; -import { statusColors } from "../../(specific-project-pages)/RunsTable"; - -export const RunDetails: React.FC<{ run: Tables<'digger_runs'> }> = ({ run }) => { - const [isExpanded, setIsExpanded] = useState(false); - - return ( - - - - - Run {run.id} - - - {run.status.toUpperCase()} - - - -
-
-

Commit: {run.commit_id}

-

Date: {run.created_at}

-
- -
- - {isExpanded && run.status && ( - -

Plan Summary

-
-
- {run.status} - Created -
-
- {run.status} - Updated -
-
- {run.status} - Deleted -
-
-
- )} -
-
-
-
- ); -}; diff --git a/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/runs/[runId]/page.tsx b/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/runs/[runId]/page.tsx index bd604628..c862c521 100644 --- a/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/runs/[runId]/page.tsx +++ b/src/app/(dynamic-pages)/(authenticated-pages)/(application-pages)/project/[projectSlug]/runs/[runId]/page.tsx @@ -1,13 +1,18 @@ import { PageHeading } from "@/components/PageHeading"; import { T } from "@/components/ui/Typography"; +import { getLoggedInUserOrganizationRole } from "@/data/user/organizations"; +import { getSlimProjectById } from "@/data/user/projects"; import { getRunById } from "@/data/user/runs"; +import { getUserProfile } from "@/data/user/user"; +import { Table } from "@/types"; +import { serverGetLoggedInUser } from "@/utils/server/serverGetLoggedInUser"; import { runIdParamSchema } from "@/utils/zod-schemas/params"; import type { Metadata } from "next"; -import { Suspense } from "react"; -import { RunDetails } from "./RunDetails"; +import dynamic from 'next/dynamic'; +import { ComponentType, Suspense } from "react"; export const metadata: Metadata = { title: "Projects", @@ -20,6 +25,19 @@ type RunDetailPageProps = { }; }; +type ProjectRunDetailsProps = { + run: Table<'digger_runs'>, + loggedInUser: Table<'user_profiles'>, + isUserOrgAdmin: boolean +} + + + +const DynamicProjectRunDetails = dynamic(() => + import('./ProjectRunDetails').then((mod) => mod.ProjectRunDetails as ComponentType), + { ssr: false } +) + export default async function RunDetailPage({ params, @@ -27,15 +45,23 @@ export default async function RunDetailPage({ }: RunDetailPageProps) { const { runId } = runIdParamSchema.parse(params); const run = await getRunById(runId); + const project_id = run.project_id; + const [project, user] = await Promise.all([ + getSlimProjectById(project_id), + serverGetLoggedInUser() + ]); + const userProfile = await getUserProfile(user.id); + const organizationRole = await getLoggedInUserOrganizationRole(project.organization_id); + const isOrganizationAdmin = + organizationRole === "admin" || organizationRole === "owner"; return ( -
+
-
{ } > - + }
diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 6998ca25..c457c761 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,5 +1,6 @@ import '@/styles/globals.css'; import '@/styles/prosemirror.css'; +import { GeistMono } from 'geist/font/mono'; import { GeistSans } from 'geist/font/sans'; import { Metadata } from 'next'; import 'server-only'; @@ -22,7 +23,7 @@ export default async function RootLayout({ children: React.ReactNode; }) { return ( - + {children} diff --git a/src/data/user/projects.tsx b/src/data/user/projects.tsx index 5f351431..2c2f68cd 100644 --- a/src/data/user/projects.tsx +++ b/src/data/user/projects.tsx @@ -346,4 +346,21 @@ export async function updateProjectSettingsAction({ console.error("Error updating project settings:", error); return { status: 'error', message: 'Failed to update project settings' }; } +} + +export async function deleteProject(projectId: string): Promise> { + const supabase = createSupabaseUserServerComponentClient(); + const { data, error } = await supabase + .from('projects') + .update({ + deleted_at: new Date().toISOString(), + }) + .eq('id', projectId) + .single(); + + if (error) { + return { status: 'error', message: error.message }; + } + + return { status: 'success', data }; } \ No newline at end of file diff --git a/src/data/user/runs.ts b/src/data/user/runs.ts index 40b2e24c..f4585578 100644 --- a/src/data/user/runs.ts +++ b/src/data/user/runs.ts @@ -1,6 +1,7 @@ 'use server'; import { createSupabaseUserServerComponentClient } from '@/supabase-clients/user/createSupabaseUserServerComponentClient'; +import { SAPayload } from '@/types'; export async function getTFVarsByProjectId(projectId: string) { const supabaseClient = createSupabaseUserServerComponentClient(); @@ -122,3 +123,76 @@ export async function getRunsByProjectId(projectId: string) { if (error) throw error; return data; } + +export async function requestRunApproval( + runId: string, +): Promise> { + const supabase = createSupabaseUserServerComponentClient(); + const { data, error } = await supabase + .from('digger_runs') + .update({ status: 'pending_approval' }) + .eq('id', runId) + .select('id') + .single(); + + if (error) { + return { status: 'error', message: error.message }; + } + return { status: 'success', data: data.id }; +} + +export async function approveRun( + runId: string, + userId: string, +): Promise> { + const supabase = createSupabaseUserServerComponentClient(); + const { data, error } = await supabase + .from('digger_runs') + .update({ + status: 'pending_apply', + approver_user_id: userId, + is_approved: true, + }) + .eq('id', runId) + .select('id') + .single(); + + if (error) { + return { status: 'error', message: error.message }; + } + return { status: 'success', data: data.id }; +} + +export async function rejectRun( + runId: string, + userId: string, +): Promise> { + const supabase = createSupabaseUserServerComponentClient(); + const { data, error } = await supabase + .from('digger_runs') + .update({ + status: 'rejected', + approver_user_id: userId, + is_approved: false, + }) + .eq('id', runId) + .select('id') + .single(); + + if (error) { + return { status: 'error', message: error.message }; + } + return { status: 'success', data: data.id }; +} + +export async function changeRunStatus(runId: string, status: string) { + const supabase = createSupabaseUserServerComponentClient(); + const { error } = await supabase + .from('digger_runs') + .update({ status: status }) + .eq('id', runId) + .select('id') + .single(); + + if (error) throw error; +} diff --git a/src/lib/database.types.ts b/src/lib/database.types.ts index 93568bdd..6aa0a1e3 100644 --- a/src/lib/database.types.ts +++ b/src/lib/database.types.ts @@ -208,7 +208,7 @@ export type Database = { deleted_at: string | null expiry: string | null id: number - organisation_id: number | null + organisation_id: string | null type: string | null updated_at: string | null value: string | null @@ -218,7 +218,7 @@ export type Database = { deleted_at?: string | null expiry?: string | null id?: number - organisation_id?: number | null + organisation_id?: string | null type?: string | null updated_at?: string | null value?: string | null @@ -228,12 +228,20 @@ export type Database = { deleted_at?: string | null expiry?: string | null id?: number - organisation_id?: number | null + organisation_id?: string | null type?: string | null updated_at?: string | null value?: string | null } - Relationships: [] + Relationships: [ + { + foreignKeyName: "fk_jt_organisation_id" + columns: ["organisation_id"] + isOneToOne: false + referencedRelation: "organizations" + referencedColumns: ["id"] + }, + ] } digger_jobs: { Row: { @@ -403,9 +411,11 @@ export type Database = { } digger_runs: { Row: { + apply_logs: string | null apply_stage_id: string | null approval_author: string | null approval_date: string | null + approver_user_id: string | null commit_id: string created_at: string deleted_at: string | null @@ -415,17 +425,21 @@ export type Database = { is_approved: boolean | null plan_stage_id: string | null pr_number: number | null + project_id: string project_name: string | null repo_id: number run_type: string status: string + terraform_output: string | null triggertype: string updated_at: string } Insert: { + apply_logs?: string | null apply_stage_id?: string | null approval_author?: string | null approval_date?: string | null + approver_user_id?: string | null commit_id: string created_at?: string deleted_at?: string | null @@ -435,17 +449,21 @@ export type Database = { is_approved?: boolean | null plan_stage_id?: string | null pr_number?: number | null + project_id: string project_name?: string | null repo_id?: number run_type: string status: string + terraform_output?: string | null triggertype: string updated_at?: string } Update: { + apply_logs?: string | null apply_stage_id?: string | null approval_author?: string | null approval_date?: string | null + approver_user_id?: string | null commit_id?: string created_at?: string deleted_at?: string | null @@ -455,10 +473,12 @@ export type Database = { is_approved?: boolean | null plan_stage_id?: string | null pr_number?: number | null + project_id?: string project_name?: string | null repo_id?: number run_type?: string status?: string + terraform_output?: string | null triggertype?: string updated_at?: string } @@ -477,6 +497,13 @@ export type Database = { referencedRelation: "digger_run_stages" referencedColumns: ["id"] }, + { + foreignKeyName: "fk_digger_runs_project" + columns: ["project_id"] + isOneToOne: false + referencedRelation: "projects" + referencedColumns: ["id"] + }, { foreignKeyName: "fk_digger_runs_repo" columns: ["repo_id"] diff --git a/src/styles/globals.css b/src/styles/globals.css index a8a3233b..100df39e 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -22,10 +22,10 @@ --destructive-foreground: 0 0% 98%; --border: 240 5.9% 90%; --input: 240 5.9% 90%; - --ring: 240 10% 3.9%; + --ring: 240 5.9% 10%; --radius: 0.5rem; - --chart-1: 173 58% 39%; - --chart-2: 12 76% 61%; + --chart-1: 12 76% 61%; + --chart-2: 173 58% 39%; --chart-3: 197 37% 24%; --chart-4: 43 74% 66%; --chart-5: 27 87% 67%; @@ -52,10 +52,10 @@ --input: 240 3.7% 15.9%; --ring: 240 4.9% 83.9%; --chart-1: 220 70% 50%; - --chart-5: 160 60% 45%; + --chart-2: 160 60% 45%; --chart-3: 30 80% 55%; --chart-4: 280 65% 60%; - --chart-2: 340 75% 55%; + --chart-5: 340 75% 55%; } } diff --git a/supabase/migrations/20240726135234_remote_schema.sql b/supabase/migrations/20240726135234_remote_schema.sql new file mode 100644 index 00000000..7e9f4d77 --- /dev/null +++ b/supabase/migrations/20240726135234_remote_schema.sql @@ -0,0 +1,7 @@ +drop index if exists "public"."idx_digger_runs_approval_status"; + +alter table "public"."digger_runs" drop column "approval_status"; + +drop type "public"."digger_run_approval_status"; + + diff --git a/supabase/migrations/20240726181205_add_terraform_column_to_runs.sql b/supabase/migrations/20240726181205_add_terraform_column_to_runs.sql new file mode 100644 index 00000000..e544a795 --- /dev/null +++ b/supabase/migrations/20240726181205_add_terraform_column_to_runs.sql @@ -0,0 +1,8 @@ +ALTER TABLE "public"."digger_runs" +ADD COLUMN "terraform_output" text; + +ALTER TABLE "public"."digger_runs" +ADD COLUMN "apply_logs" text; + +ALTER TABLE "public"."digger_runs" +ADD COLUMN "approver_user_id" uuid NULL; \ No newline at end of file diff --git a/supabase/migrations/20240726184158_add_changes_to_runs.sql b/supabase/migrations/20240726184158_add_changes_to_runs.sql new file mode 100644 index 00000000..af0da71a --- /dev/null +++ b/supabase/migrations/20240726184158_add_changes_to_runs.sql @@ -0,0 +1,2 @@ +ALTER TABLE "public"."digger_runs" +ALTER COLUMN "project_id" SET NOT NULL diff --git a/tailwind.config.cjs b/tailwind.config.cjs index 897db6c0..18acb7f0 100644 --- a/tailwind.config.cjs +++ b/tailwind.config.cjs @@ -59,6 +59,7 @@ module.exports = { fontFamily: { sans: ['var(--font-satoshi)'], display: ['Lexend', ...defaultTheme.fontFamily.sans], + mono: ['var(--font-geist-mono)'], }, keyframes: { accordionDown: {