Merge remote-tracking branch 'origin/main'

# Conflicts:
#	prisma/schema.prisma
This commit is contained in:
killian-larcher
2024-12-17 20:24:30 +01:00
13 changed files with 135 additions and 36 deletions
@@ -11,6 +11,7 @@ import {Card, CardContent, CardHeader} from "@/components/ui/card";
import {AgentModalKey} from "@/components/wrappers/dashboard/agent/AgentModalKey/AgentModalKey"; import {AgentModalKey} from "@/components/wrappers/dashboard/agent/AgentModalKey/AgentModalKey";
import {CardsWithPagination} from "@/components/wrappers/common/cards-with-pagination"; import {CardsWithPagination} from "@/components/wrappers/common/cards-with-pagination";
import {DatabaseCard} from "@/components/wrappers/dashboard/projects/ProjectCard/ProjectDatabaseCard"; import {DatabaseCard} from "@/components/wrappers/dashboard/projects/ProjectCard/ProjectDatabaseCard";
import {AgentCardKey} from "@/components/wrappers/dashboard/agent/AgentCardKey/AgentCardKey";
export default async function RoutePage(props: PageParams<{ agentId: string }>) { export default async function RoutePage(props: PageParams<{ agentId: string }>) {
@@ -53,15 +54,13 @@ export default async function RoutePage(props: PageParams<{ agentId: string }>)
href={`/dashboard/agents/${agent.id}/edit`}> href={`/dashboard/agents/${agent.id}/edit`}>
<GearIcon className="w-7 h-7"/> <GearIcon className="w-7 h-7"/>
</Link> </Link>
<AgentModalKey agent={agent}> {/*<AgentModalKey agent={agent}>*/}
<Button variant="outline"> {/* <Button variant="outline">*/}
<KeyRound/> {/* <KeyRound/>*/}
</Button> {/* </Button>*/}
</AgentModalKey> {/*</AgentModalKey>*/}
</PageTitle> </PageTitle>
<PageActions className="justify-between">
<Button>Restore</Button>
</PageActions>
</div> </div>
<PageDescription className="mt-5 sm:mt-0">{agent.description}</PageDescription> <PageDescription className="mt-5 sm:mt-0">{agent.description}</PageDescription>
<PageContent className="flex flex-col w-full h-full"> <PageContent className="flex flex-col w-full h-full">
@@ -88,7 +87,16 @@ export default async function RoutePage(props: PageParams<{ agentId: string }>)
{formatDateLastContact(agent.lastContact)} {formatDateLastContact(agent.lastContact)}
</CardContent> </CardContent>
</Card> </Card>
</div> </div>
<Card className="w-full sm:w-auto flex-1">
<CardHeader className="font-bold text-xl">
Edge Key
</CardHeader>
<CardContent>
<AgentCardKey agent={agent}/>
</CardContent>
</Card>
<CardsWithPagination data={agent.databases} cardItem={DatabaseCard}/> <CardsWithPagination data={agent.databases} cardItem={DatabaseCard}/>
</PageContent> </PageContent>
</Page> </Page>
@@ -39,6 +39,7 @@ export default async function RoutePage(props: PageParams<{ projectId: string }>
</PageTitle> </PageTitle>
<PageActions className="justify-between"> <PageActions className="justify-between">
<ButtonDeleteProject <ButtonDeleteProject
projectId={projectId}
text={"Delete Project"} text={"Delete Project"}
/> />
</PageActions> </PageActions>
@@ -0,0 +1,8 @@
/*
Warnings:
- Added the required column `isArchived` to the `projects` table without a default value. This is not possible if the table is not empty.
*/
-- AlterTable
ALTER TABLE "projects" ADD COLUMN "isArchived" BOOLEAN NOT NULL;
@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "projects" ALTER COLUMN "isArchived" SET DEFAULT false;
@@ -38,10 +38,6 @@ export const LoginForm = (props: loginFormProps) => {
<Card> <Card>
<CardHeader> <CardHeader>
<div className="grid gap-2 text-center mb-2"> <div className="grid gap-2 text-center mb-2">
{/*<div className="justify-center text-center flex">*/}
{/* <Image src="/logo.png" alt="Logo Portabase" width={100}*/}
{/* height={50}/>*/}
{/*</div>*/}
<h1 className="text-3xl font-bold">Login</h1> <h1 className="text-3xl font-bold">Login</h1>
<p className="text-balance text-muted-foreground"> <p className="text-balance text-muted-foreground">
Enter your informations bellow to login Enter your informations bellow to login
@@ -2,21 +2,24 @@
import {signInAction} from "@/features/auth/auth.action"; import {signInAction} from "@/features/auth/auth.action";
import {Button} from "@/components/ui/button"; import {Button} from "@/components/ui/button";
import Image from "next/image"; import Image from "next/image";
import {env} from "@/env.mjs";
export type SocialAuthButtonProps = {} export type SocialAuthButtonProps = {}
export const SocialAuthButton = (props: SocialAuthButtonProps) => { export const SocialAuthButton = (props: SocialAuthButtonProps) => {
return ( return (
<div className="flex flex-col gap-4 mt-5"> <div className="flex flex-col gap-4 mt-5">
<Button {env.NEXT_PUBLIC_GOOGLE_AUTH === "true" ?
onClick={(e) => { <Button
e.preventDefault(); onClick={(e) => {
void signInAction("google") e.preventDefault();
}} void signInAction("google")
> }}
<Image src="/google-icon.png" alt="Google OAuth" width={25} height={25}/> >
Sign in with google <Image src="/google-icon.png" alt="Google OAuth" width={25} height={25}/>
</Button> Sign in with google
</Button>
:null}
</div> </div>
) )
} }
@@ -13,7 +13,8 @@ export async function copyToClipboardWithMeta(value: string) {
export type CopyButtonProps = { export type CopyButtonProps = {
value: string value: string,
className: string
} }
@@ -0,0 +1,25 @@
"use client"
import {generateEdgeKey} from "@/utils/edge_key";
import {getServerUrl} from "@/utils/get-server-url";
import {Agent} from "@prisma/client";
import {PasswordInput} from "@/components/wrappers/auth/PaswordInput/password-input";
import {useState} from "react";
import {CopyButton} from "@/components/wrappers/common/button/copy-button";
export type AgentCardKeyProps = {
agent: Agent
}
export const AgentCardKey = (props: AgentCardKeyProps) => {
const edge_key = generateEdgeKey(getServerUrl(), props.agent.id);
const [code, setCode] = useState<string>(`${edge_key}`);
return(
<>
<PasswordInput value={code} onChange={(value: string) => {setCode(edge_key)} }/>
<CopyButton className="mt-5" value={code}/>
</>
)
}
@@ -2,29 +2,36 @@
import {Trash2} from "lucide-react"; import {Trash2} from "lucide-react";
import {ButtonWithConfirm} from "@/components/wrappers/common/button/button-with-confirm"; import {ButtonWithConfirm} from "@/components/wrappers/common/button/button-with-confirm";
import {useMutation} from "@tanstack/react-query";
import {deleteProjectAction} from "@/components/wrappers/dashboard/projects/ButtonDeleteProject/delete-project.action";
import {useRouter} from "next/navigation";
import {toast} from "sonner";
export type ButtonDeleteProjectProps = { export type ButtonDeleteProjectProps = {
text? : string text? : string
projectId: string
} }
export const ButtonDeleteProject = (props: ButtonDeleteProjectProps) => { export const ButtonDeleteProject = (props: ButtonDeleteProjectProps) => {
const router = useRouter()
// const mutation = useMutation({ const mutation = useMutation({
// mutationFn: () => deleteUserAction(""), mutationFn: () => deleteProjectAction(props.projectId),
// onSuccess: async () => { onSuccess: async (result) => {
// await signOutAction(); router.push("/dashboard/projects")
// }, if(result.data.success) {
// }) toast.success(result.data.actionSuccess.message);
}
},
})
return ( return (
<ButtonWithConfirm <ButtonWithConfirm
text={props.text ? props.text : ""} text={props.text ? props.text : ""}
onClick={() => { onClick={() => {
// mutation.mutate() mutation.mutate()
console.log("ok")
}} }}
variant={"destructive"} variant={"destructive"}
// isPending={mutation.isPending} isPending={mutation.isPending}
className="gap-2" className="gap-2"
icon={<Trash2/>} icon={<Trash2/>}
/> />
@@ -0,0 +1,47 @@
"use server"
import {userAction} from "@/safe-actions";
import {z} from "zod";
import {v4 as uuidv4} from "uuid";
import {prisma} from "@/prisma";
import {ServerActionResult} from "@/types/action-type";
import {Projects} from "@prisma/client";
export const deleteProjectAction = userAction
.schema(z.string())
.action(async ({parsedInput, ctx}): Promise<ServerActionResult<Projects>> => {
try {
const uuid = uuidv4()
const project = await prisma.project.update({
where: {
id: parsedInput
},
data:{
isArchived: true,
slug: uuid
}
})
return {
success: true,
value: project,
actionSuccess: {
message: "Projects has been successfully archived.",
messageParams: {projectName: parsedInput.data.name},
},
};
} catch (error) {
return {
success: false,
actionError: {
message: "Failed to archived Projects.",
status: 500, // Optional: Use a meaningful status code
cause: error instanceof Error ? error.message : "Unknown error",
messageParams: {projectName: parsedInput.data.name},
},
};
}
});
@@ -42,7 +42,7 @@ export const createProjectAction = userAction
success: true, success: true,
value: project, value: project,
actionSuccess: { actionSuccess: {
message: "ProjectsForm has been successfully created.", message: "Projects has been successfully created.",
messageParams: {projectName: parsedInput.data.name}, messageParams: {projectName: parsedInput.data.name},
}, },
}; };
@@ -50,7 +50,7 @@ export const createProjectAction = userAction
return { return {
success: false, success: false,
actionError: { actionError: {
message: "Failed to create ProjectsForm.", message: "Failed to create Projects.",
status: 500, // Optional: Use a meaningful status code status: 500, // Optional: Use a meaningful status code
cause: error instanceof Error ? error.message : "Unknown error", cause: error instanceof Error ? error.message : "Unknown error",
messageParams: {projectName: parsedInput.data.name}, messageParams: {projectName: parsedInput.data.name},
+3
View File
@@ -31,6 +31,7 @@ export const env = createEnv({
S3_USE_SSL: z.string().optional(), S3_USE_SSL: z.string().optional(),
STORAGE_TYPE: z.string().optional(), STORAGE_TYPE: z.string().optional(),
NEXT_PUBLIC_GOOGLE_AUTH: z.string().optional(),
}, },
/* /*
@@ -40,6 +41,7 @@ export const env = createEnv({
*/ */
client: { client: {
NEXT_PUBLIC_DOMAIN_NAME: z.string(), NEXT_PUBLIC_DOMAIN_NAME: z.string(),
NEXT_PUBLIC_GOOGLE_AUTH: z.string().optional(),
}, },
/* /*
* Due to how Next.js bundles environment variables on Edge and Client, * Due to how Next.js bundles environment variables on Edge and Client,
@@ -62,6 +64,7 @@ export const env = createEnv({
AUTH_GOOGLE_ID: process.env.AUTH_GOOGLE_ID, AUTH_GOOGLE_ID: process.env.AUTH_GOOGLE_ID,
AUTH_GOOGLE_SECRET: process.env.AUTH_GOOGLE_SECRET, AUTH_GOOGLE_SECRET: process.env.AUTH_GOOGLE_SECRET,
NEXT_PUBLIC_GOOGLE_AUTH: process.env.NEXT_PUBLIC_GOOGLE_AUTH,
S3_ENDPOINT: process.env.S3_ENDPOINT, S3_ENDPOINT: process.env.S3_ENDPOINT,
S3_ACCESS_KEY: process.env.S3_ACCESS_KEY, S3_ACCESS_KEY: process.env.S3_ACCESS_KEY,
-2
View File
@@ -18,8 +18,6 @@ export const signInAction = async (type: string, formData?: any) => {
email: formData.email email: formData.email
}); });
} catch (error) { } catch (error) {
// const signInError = error as CredentialsSignin
console.error(error);
return {error: "Error loging in, please try again or check your credentials !"}; return {error: "Error loging in, please try again or check your credentials !"};
} }
redirect("/") redirect("/")