mirror of
https://github.com/Portabase/portabase.git
synced 2026-07-14 11:16:13 +02:00
migration
This commit is contained in:
+19
-23
@@ -1,42 +1,38 @@
|
||||
"use client"
|
||||
import {ButtonWithConfirm} from "@/components/wrappers/common/button/button-with-confirm";
|
||||
import {
|
||||
deleteOrganizationAction,
|
||||
} from "@/components/wrappers/dashboard/organization/organization.action";
|
||||
import {useMutation} from "@tanstack/react-query";
|
||||
import {setCurrentOrganizationSlug} from "@/features/dashboard/organization-cookie";
|
||||
import {useRouter} from "next/navigation";
|
||||
import {toast} from "sonner";
|
||||
"use client";
|
||||
import { ButtonWithConfirm } from "@/components/wrappers/common/button/button-with-confirm";
|
||||
import { deleteOrganizationAction } from "@/components/wrappers/dashboard/organization/organization.action";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import { setCurrentOrganizationSlug } from "@/features/dashboard/organization-cookie";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { toast } from "sonner";
|
||||
|
||||
export type DeleteOrganizationButtonProps = {
|
||||
organizationSlug: string;
|
||||
}
|
||||
};
|
||||
|
||||
export const DeleteOrganizationButton = (props: DeleteOrganizationButtonProps) => {
|
||||
const router = useRouter();
|
||||
const mutation = useMutation({
|
||||
mutationFn: () => deleteOrganizationAction(props.organizationSlug),
|
||||
onSuccess: async (result) => {
|
||||
console.log(result);
|
||||
if(result.data.success) {
|
||||
await setCurrentOrganizationSlug("default")
|
||||
router.push("/")
|
||||
if (result.data.success) {
|
||||
await setCurrentOrganizationSlug("default");
|
||||
router.push("/");
|
||||
toast.success(result.data.actionSuccess.message);
|
||||
}else{
|
||||
} else {
|
||||
toast.error(result.data.actionError.message);
|
||||
}
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
|
||||
return(
|
||||
return (
|
||||
<ButtonWithConfirm
|
||||
onClick={() => {
|
||||
mutation.mutate()
|
||||
mutation.mutate();
|
||||
}}
|
||||
isPending={mutation.isPending}
|
||||
text="Delete Organization"
|
||||
variant="destructive"/>
|
||||
)
|
||||
}
|
||||
variant="destructive"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
+51
-78
@@ -1,111 +1,86 @@
|
||||
"use client";
|
||||
|
||||
import {Card, CardContent, CardHeader} from "@/components/ui/card";
|
||||
import {
|
||||
FormControl,
|
||||
FormDescription,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
useZodForm
|
||||
} from "@/components/ui/form";
|
||||
import {Input} from "@/components/ui/input";
|
||||
import {Form} from "@/components/ui/form"
|
||||
import {Button} from "@/components/ui/button";
|
||||
import {useMutation} from "@tanstack/react-query";
|
||||
import {useRouter} from "next/navigation";
|
||||
import {Organization, User} from "@prisma/client"
|
||||
import {MultiSelect} from "@/components/wrappers/common/multiSelect/MultiSelect";
|
||||
import {
|
||||
OrganizationFormSchema,
|
||||
OrganizationFormType
|
||||
} from "@/components/wrappers/dashboard/organization/OrganizationForm/organization-form.schema";
|
||||
import {
|
||||
createOrganizationAction,
|
||||
updateOrganizationAction
|
||||
} from "@/components/wrappers/dashboard/organization/organization.action";
|
||||
import {toast} from "sonner";
|
||||
|
||||
import { Card, CardContent, CardHeader } from "@/components/ui/card";
|
||||
import { FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, useZodForm } from "@/components/ui/form";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Form } from "@/components/ui/form";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { Organization, User } from "@prisma/client";
|
||||
import { MultiSelect } from "@/components/wrappers/common/multiselect/multi-select";
|
||||
import { OrganizationFormSchema, OrganizationFormType } from "@/components/wrappers/dashboard/organization/OrganizationForm/organization-form.schema";
|
||||
import { createOrganizationAction, updateOrganizationAction } from "@/components/wrappers/dashboard/organization/organization.action";
|
||||
import { toast } from "sonner";
|
||||
|
||||
export type organizationFormProps = {
|
||||
defaultValues?: Organization;
|
||||
users: User[]
|
||||
|
||||
}
|
||||
users: User[];
|
||||
};
|
||||
|
||||
export const OrganizationForm = (props: organizationFormProps) => {
|
||||
|
||||
const router = useRouter();
|
||||
const isCreate = !Boolean(props.defaultValues)
|
||||
|
||||
const isCreate = !Boolean(props.defaultValues);
|
||||
|
||||
const formatUsersList = (users: User[]) => {
|
||||
return users.map(user => ({
|
||||
return users.map((user) => ({
|
||||
value: user.id,
|
||||
label: `${user.name} | ${user.email}`,
|
||||
}));
|
||||
};
|
||||
|
||||
const formatDefaultUsers = (users: OrganizationFormType['users']): string[] => {
|
||||
console.log(users)
|
||||
return users.map(user => user.userId );
|
||||
const formatDefaultUsers = (users: OrganizationFormType["users"]): string[] => {
|
||||
console.log(users);
|
||||
return users.map((user) => user.userId);
|
||||
};
|
||||
|
||||
const formattedDefaultValues = {
|
||||
...props.defaultValues,
|
||||
users: !isCreate ? formatDefaultUsers(props.defaultValues?.users) : []
|
||||
}
|
||||
|
||||
users: !isCreate ? formatDefaultUsers(props.defaultValues?.users) : [],
|
||||
};
|
||||
|
||||
const form = useZodForm({
|
||||
schema: OrganizationFormSchema,
|
||||
defaultValues: formattedDefaultValues,
|
||||
|
||||
});
|
||||
|
||||
const mutation = useMutation({
|
||||
mutationFn: async (values: OrganizationFormType) => {
|
||||
console.log(values)
|
||||
const organization = await updateOrganizationAction({data: values, organizationId: props.defaultValues.id})
|
||||
console.log(organization)
|
||||
console.log(values);
|
||||
const organization = await updateOrganizationAction({ data: values, organizationId: props.defaultValues.id });
|
||||
console.log(organization);
|
||||
if (organization.data.success) {
|
||||
toast.success(organization.data.actionSuccess.message);
|
||||
router.push(`/dashboard/${organization.data.value.slug}/settings`);
|
||||
router.refresh()
|
||||
router.refresh();
|
||||
} else {
|
||||
toast.success(organization.data.actionError.message);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
|
||||
</CardHeader>
|
||||
<CardHeader></CardHeader>
|
||||
<CardContent>
|
||||
<Form form={form}
|
||||
className="flex flex-col gap-4"
|
||||
onSubmit={async (values) => {
|
||||
await mutation.mutateAsync(values);
|
||||
}}
|
||||
<Form
|
||||
form={form}
|
||||
className="flex flex-col gap-4"
|
||||
onSubmit={async (values) => {
|
||||
await mutation.mutateAsync(values);
|
||||
}}
|
||||
>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="name"
|
||||
defaultValue=""
|
||||
render={({field}) => (
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Name</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
placeholder="Organization 1" {...field} />
|
||||
<Input placeholder="Organization 1" {...field} />
|
||||
</FormControl>
|
||||
<FormMessage/>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
@@ -113,29 +88,30 @@ export const OrganizationForm = (props: organizationFormProps) => {
|
||||
control={form.control}
|
||||
name="slug"
|
||||
defaultValue=""
|
||||
render={({field}) => (
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Slug</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
placeholder="project-1" {...field}
|
||||
placeholder="project-1"
|
||||
{...field}
|
||||
onChange={(e) => {
|
||||
const value = e.target.value.replaceAll(" ", "-").toLowerCase()
|
||||
field.onChange(value)
|
||||
}}/>
|
||||
const value = e.target.value.replaceAll(" ", "-").toLowerCase();
|
||||
field.onChange(value);
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage/>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="users"
|
||||
render={({field}) => (
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Databases</FormLabel>
|
||||
<FormControl>
|
||||
|
||||
<MultiSelect
|
||||
options={formatUsersList(props.users)}
|
||||
onValueChange={field.onChange}
|
||||
@@ -147,16 +123,13 @@ export const OrganizationForm = (props: organizationFormProps) => {
|
||||
/>
|
||||
</FormControl>
|
||||
<FormDescription>Select users you want to add to this organization</FormDescription>
|
||||
<FormMessage/>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)
|
||||
}
|
||||
)}
|
||||
/>
|
||||
<Button>
|
||||
{isCreate ? `Create Organization` : `Update Organization`}
|
||||
</Button>
|
||||
<Button>{isCreate ? `Create Organization` : `Update Organization`}</Button>
|
||||
</Form>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
"use client"
|
||||
"use client";
|
||||
|
||||
import {useMutation} from "@tanstack/react-query";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
|
||||
import {Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, DialogTrigger} from "@/components/ui/dialog";
|
||||
import {Button} from "@/components/ui/button";
|
||||
import {Form, FormControl, FormField, FormItem, FormLabel, FormMessage, useZodForm} from "@/components/ui/form";
|
||||
import {Input} from "@/components/ui/input";
|
||||
import {OrganizationSchema} from "@/components/wrappers/dashboard/organization/organization.schema";
|
||||
import {createOrganizationAction} from "@/components/wrappers/dashboard/organization/organization.action";
|
||||
import {useRouter} from "next/navigation";
|
||||
import {useState} from "react";
|
||||
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, useZodForm } from "@/components/ui/form";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { OrganizationSchema } from "@/components/wrappers/dashboard/organization/organization.schema";
|
||||
import { createOrganizationAction } from "@/components/wrappers/dashboard/organization/organization.action";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
import { authClient } from "@/lib/auth/auth-client";
|
||||
|
||||
export type createOrganizationModalProps = {
|
||||
children: any
|
||||
}
|
||||
|
||||
children: any;
|
||||
};
|
||||
|
||||
export function CreateOrganizationModal(props: createOrganizationModalProps) {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const {children} = props;
|
||||
const { children } = props;
|
||||
|
||||
const router = useRouter()
|
||||
const router = useRouter();
|
||||
|
||||
const form = useZodForm({
|
||||
schema: OrganizationSchema,
|
||||
@@ -29,46 +29,49 @@ export function CreateOrganizationModal(props: createOrganizationModalProps) {
|
||||
|
||||
const mutation = useMutation({
|
||||
mutationFn: async (values: OrganizationSchema) => {
|
||||
console.log(values)
|
||||
const result = await createOrganizationAction(values)
|
||||
setOpen(false);
|
||||
router.refresh()
|
||||
}
|
||||
})
|
||||
console.log(values);
|
||||
|
||||
const result = await createOrganizationAction(values);
|
||||
|
||||
if (result && result.data) {
|
||||
if (result.data.success && result.data.value) {
|
||||
setOpen(false);
|
||||
await authClient.organization.setActive({ organizationSlug: result.data.value.slug });
|
||||
router.replace(`/dashboard/${result.data.value.slug}/home`);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
|
||||
<DialogTrigger asChild>
|
||||
{children}
|
||||
</DialogTrigger>
|
||||
<DialogTrigger asChild>{children}</DialogTrigger>
|
||||
|
||||
<DialogContent className="sm:max-w-[425px] w-full">
|
||||
|
||||
<DialogHeader>
|
||||
<DialogTitle>Create a new organization</DialogTitle>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="sm:max-w-[375px] w-full">
|
||||
<Form form={form}
|
||||
className="flex flex-col gap-4"
|
||||
onSubmit={async (values) => {
|
||||
console.log(values)
|
||||
await mutation.mutateAsync(values);
|
||||
}}
|
||||
<Form
|
||||
form={form}
|
||||
className="flex flex-col gap-4"
|
||||
onSubmit={async (values) => {
|
||||
console.log(values);
|
||||
await mutation.mutateAsync(values);
|
||||
}}
|
||||
>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="name"
|
||||
defaultValue=""
|
||||
render={({field}) => (
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Name</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormMessage/>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
@@ -76,18 +79,19 @@ export function CreateOrganizationModal(props: createOrganizationModalProps) {
|
||||
control={form.control}
|
||||
name="slug"
|
||||
defaultValue=""
|
||||
render={({field}) => (
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Slug</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field}
|
||||
onChange={(e) => {
|
||||
const value = e.target.value.replaceAll(" ", "-").toLowerCase()
|
||||
field.onChange(value)
|
||||
}}
|
||||
<Input
|
||||
{...field}
|
||||
onChange={(e) => {
|
||||
const value = e.target.value.replaceAll(" ", "-").toLowerCase();
|
||||
field.onChange(value);
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage/>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
@@ -98,10 +102,7 @@ export function CreateOrganizationModal(props: createOrganizationModalProps) {
|
||||
</DialogFooter>
|
||||
</Form>
|
||||
</div>
|
||||
|
||||
|
||||
</DialogContent>
|
||||
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,76 +1,36 @@
|
||||
"use client"
|
||||
"use client";
|
||||
|
||||
import {useEffect, useState} from "react";
|
||||
import { ComboBox } from "@/components/wrappers/common/combobox";
|
||||
import { useSidebar } from "@/components/ui/sidebar";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { authClient } from "@/lib/auth/auth-client";
|
||||
|
||||
import {ComboBox} from "@/components/wrappers/common/combobox";
|
||||
import {Organization} from "@prisma/client";
|
||||
import {
|
||||
getCurrentOrganizationSlug,
|
||||
setCurrentOrganizationSlug
|
||||
} from "@/features/dashboard/organization-cookie";
|
||||
import {useSidebar} from "@/components/ui/sidebar";
|
||||
import {useRouter} from "next/navigation";
|
||||
export function OrganizationCombobox() {
|
||||
const router = useRouter();
|
||||
|
||||
export type organizationComboBoxProps = {
|
||||
organizations: Organization[]
|
||||
defaultOrganization: Organization
|
||||
}
|
||||
const { data: organizations } = authClient.useListOrganizations();
|
||||
const { data: activeOrganization } = authClient.useActiveOrganization();
|
||||
|
||||
if (!organizations) return null;
|
||||
|
||||
export function OrganizationCombobox(props: organizationComboBoxProps) {
|
||||
const router = useRouter()
|
||||
// const {organizationId, moveToAnotherOrganization} = useStore((state) => state);
|
||||
console.log("organizations", organizations);
|
||||
console.log("activeOrganization", activeOrganization);
|
||||
|
||||
const [organizationSlug, setOrganizationSlug] = useState<string>()
|
||||
|
||||
const {organizations, defaultOrganization} = props
|
||||
|
||||
useEffect(() => {
|
||||
getCurrentOrganizationSlug().then(slug => {
|
||||
|
||||
if (slug == "") {
|
||||
setOrganizationSlug(defaultOrganization.id)
|
||||
setCurrentOrganizationSlug(defaultOrganization.slug)
|
||||
} else {
|
||||
setOrganizationSlug(slug)
|
||||
const organization = organizations.find(organization => organization.slug === slug)
|
||||
if (!organization) {
|
||||
setOrganizationSlug(defaultOrganization.id)
|
||||
setCurrentOrganizationSlug(defaultOrganization.slug)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}, [organizationSlug])
|
||||
|
||||
const values = organizations.map(organization => {
|
||||
return ({
|
||||
const values = organizations.map((organization) => {
|
||||
return {
|
||||
value: organization.slug,
|
||||
label: organization.name,
|
||||
})
|
||||
})
|
||||
};
|
||||
});
|
||||
|
||||
const onValueChange = (slug: string) => {
|
||||
if (organizationSlug !== slug) {
|
||||
setOrganizationSlug(slug)
|
||||
setCurrentOrganizationSlug(slug)
|
||||
router.replace("/dashboard")
|
||||
}
|
||||
}
|
||||
const {state, isMobile} = useSidebar();
|
||||
const onValueChange = async (slug: string) => {
|
||||
await authClient.organization.setActive({
|
||||
organizationSlug: slug,
|
||||
});
|
||||
router.replace(`/dashboard/${slug}/home`);
|
||||
router.refresh();
|
||||
};
|
||||
const { state } = useSidebar();
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
{state === 'expanded' && (
|
||||
<ComboBox
|
||||
sideBar
|
||||
values={values}
|
||||
defaultValue={organizationSlug}
|
||||
onValueChange={onValueChange}/>
|
||||
)}
|
||||
|
||||
</>
|
||||
|
||||
)
|
||||
}
|
||||
return <>{state === "expanded" && <ComboBox sideBar values={values} defaultValue={activeOrganization?.slug} onValueChange={onValueChange} />}</>;
|
||||
}
|
||||
|
||||
@@ -1,218 +1,160 @@
|
||||
"use server"
|
||||
"use server";
|
||||
|
||||
import {ActionError, userAction} from "@/safe-actions";
|
||||
import {prisma} from "@/prisma";
|
||||
import {OrganizationSchema} from "@/components/wrappers/dashboard/organization/organization.schema";
|
||||
import {ServerActionResult} from "@/types/action-type";
|
||||
import {Organization} from "@prisma/client";
|
||||
import {z} from "zod";
|
||||
import {v4 as uuidv4} from "uuid";
|
||||
import {getDb} from "@/db";
|
||||
import {
|
||||
OrganizationFormSchema
|
||||
} from "@/components/wrappers/dashboard/organization/OrganizationForm/organization-form.schema";
|
||||
import {ProjectSchema} from "@/components/wrappers/dashboard/projects/ProjectsForm/ProjectForm.schema";
|
||||
import { userAction } from "@/safe-actions";
|
||||
import { OrganizationSchema } from "@/components/wrappers/dashboard/organization/organization.schema";
|
||||
import { ServerActionResult } from "@/types/action-type";
|
||||
import { z } from "zod";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { OrganizationFormSchema } from "@/components/wrappers/dashboard/organization/OrganizationForm/organization-form.schema";
|
||||
import { db } from "@/db";
|
||||
import { Organization, organization as drizzleOrganization, organizationMember as drizzleOrganizationMember } from "@/db/schema";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { checkSlugOrganization, createOrganization } from "@/lib/auth/auth";
|
||||
|
||||
|
||||
const verifySlugUniqueness = async (slug: string) => {
|
||||
const slugExists = await prisma.organization.count({
|
||||
where: {
|
||||
slug: slug
|
||||
},
|
||||
})
|
||||
|
||||
if (slugExists) {
|
||||
throw new ActionError("Slug already exists.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export const createOrganizationAction = userAction
|
||||
.schema(OrganizationSchema)
|
||||
.action(async ({parsedInput, ctx}): Promise<ServerActionResult<Organization>> => {
|
||||
|
||||
try {
|
||||
|
||||
await verifySlugUniqueness(parsedInput.slug)
|
||||
|
||||
const organization = await prisma.organization.create({
|
||||
data: {
|
||||
...parsedInput
|
||||
}
|
||||
})
|
||||
|
||||
await prisma.userOrganization.create({
|
||||
data: {
|
||||
userId: ctx.user.id,
|
||||
organizationId: organization.id,
|
||||
role: "admin"
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
value: organization,
|
||||
actionSuccess: {
|
||||
message: "Organization has been successfully created.",
|
||||
messageParams: {organizationId: organization.id},
|
||||
},
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
console.error("Error creating organization:", error);
|
||||
export const createOrganizationAction = userAction.schema(OrganizationSchema).action(async ({ parsedInput }): Promise<ServerActionResult<Organization>> => {
|
||||
try {
|
||||
if (!checkSlugOrganization(parsedInput.slug)) {
|
||||
return {
|
||||
success: false,
|
||||
actionError: {
|
||||
message: "Failed to create organization.",
|
||||
message: "Slug is already taken",
|
||||
status: 500,
|
||||
cause: error.message ?? "Unknown error",
|
||||
messageParams: {message: "Error creating the organization"},
|
||||
messageParams: { message: "Error creating the organization" },
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
const organization = await createOrganization(parsedInput.name, parsedInput.slug);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
value: organization!,
|
||||
actionSuccess: {
|
||||
message: "Organization has been successfully created.",
|
||||
messageParams: { organizationId: organization!.id },
|
||||
},
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("Error creating organization:", error);
|
||||
return {
|
||||
success: false,
|
||||
actionError: {
|
||||
message: "Failed to create organization.",
|
||||
status: 500,
|
||||
messageParams: { message: "Error creating the organization" },
|
||||
},
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
export const updateOrganizationAction = userAction
|
||||
.schema(
|
||||
z.object({
|
||||
data: OrganizationFormSchema,
|
||||
organizationId: z.string()
|
||||
}))
|
||||
.action(async ({parsedInput, ctx}): Promise<ServerActionResult<Organization>> => {
|
||||
organizationId: z.string(),
|
||||
})
|
||||
)
|
||||
.action(async ({ parsedInput }): Promise<ServerActionResult<Organization>> => {
|
||||
try {
|
||||
const newUserList = parsedInput.data.users;
|
||||
|
||||
const newUserList = parsedInput.data.users
|
||||
const organization = await db.select().from(organization).where(eq(organization.id, parsedInput.organizationId)).execute();
|
||||
|
||||
const organization = await prisma.organization.findFirst({
|
||||
where:{
|
||||
id: parsedInput.organizationId,
|
||||
},
|
||||
include: {
|
||||
users : {}
|
||||
}
|
||||
})
|
||||
|
||||
const existingItemIds = organization.users.map((user) => user.userId);
|
||||
const usersToAdd = newUserList.filter(
|
||||
(id) => !existingItemIds.includes(id)
|
||||
);
|
||||
const usersToRemove = existingItemIds.filter(
|
||||
(id) => !newUserList.includes(id)
|
||||
);
|
||||
|
||||
console.log(usersToAdd);
|
||||
console.log(usersToRemove);
|
||||
if (organization.length === 0) {
|
||||
throw new Error("Organization not found.");
|
||||
}
|
||||
|
||||
const existingItemIds = organization[0].users.map((user) => user.userId);
|
||||
const usersToAdd = newUserList.filter((id) => !existingItemIds.includes(id));
|
||||
const usersToRemove = existingItemIds.filter((id) => !newUserList.includes(id));
|
||||
|
||||
if (usersToAdd.length > 0) {
|
||||
|
||||
await prisma.userOrganization.createMany({
|
||||
data: usersToAdd.map((userId) => ({
|
||||
userId: userId,
|
||||
organizationId: organization.id,
|
||||
role: "member"
|
||||
})),
|
||||
skipDuplicates: true, // Optional: to avoid duplicate insertion errors
|
||||
});
|
||||
await db
|
||||
.insert(userOrganization)
|
||||
.values(
|
||||
usersToAdd.map((userId) => ({
|
||||
userId,
|
||||
organizationId: organization[0].id,
|
||||
role: "member",
|
||||
}))
|
||||
)
|
||||
.execute();
|
||||
}
|
||||
|
||||
if (usersToRemove.length > 0) {
|
||||
await prisma.userOrganization.deleteMany({
|
||||
where: {
|
||||
userId: { in: usersToRemove },
|
||||
},
|
||||
|
||||
});
|
||||
await db.delete().from(userOrganization).where(inArray(userOrganization.userId, usersToRemove)).execute();
|
||||
}
|
||||
|
||||
const updatedOrganization = await prisma.organization.update({
|
||||
where:{
|
||||
id: organization.id
|
||||
},
|
||||
data:{
|
||||
const updatedOrganization = await db
|
||||
.update(organization)
|
||||
.set({
|
||||
name: parsedInput.data.name,
|
||||
slug: parsedInput.data.slug,
|
||||
}
|
||||
})
|
||||
|
||||
})
|
||||
.where(eq(organization.id, parsedInput.organizationId))
|
||||
.returning()
|
||||
.execute();
|
||||
|
||||
return {
|
||||
success: true,
|
||||
value: updatedOrganization,
|
||||
value: updatedOrganization[0],
|
||||
actionSuccess: {
|
||||
message: "Organization has been successfully updated.",
|
||||
messageParams: {organizationId: updatedOrganization.id},
|
||||
messageParams: { organizationId: updatedOrganization[0].id },
|
||||
},
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
console.error("Error updating organization:", error);
|
||||
return {
|
||||
success: false,
|
||||
actionError: {
|
||||
message: "Failed to update organization.",
|
||||
status: 500,
|
||||
cause: error.message ?? "Unknown error",
|
||||
messageParams: {message: "Error updating the organization"},
|
||||
messageParams: { message: "Error updating the organization" },
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
export const deleteOrganizationAction = userAction.schema(z.string()).action(async ({ parsedInput, ctx }): Promise<ServerActionResult<Organization>> => {
|
||||
try {
|
||||
const uuid = uuidv4();
|
||||
const organization = await db.select().from(organization).where(eq(organization.slug, parsedInput)).execute();
|
||||
|
||||
|
||||
|
||||
|
||||
export const deleteOrganizationAction = userAction
|
||||
.schema(z.string())
|
||||
.action(async ({parsedInput, ctx}): Promise<ServerActionResult<Organization>> => {
|
||||
console.log(parsedInput);
|
||||
try {
|
||||
|
||||
const db = await getDb()
|
||||
const uuid = uuidv4()
|
||||
const organization = await db.organization.findFirst({
|
||||
where: {
|
||||
slug: parsedInput,
|
||||
}
|
||||
})
|
||||
console.log(organization);
|
||||
const organizationUpdated = await db.organization.update({
|
||||
where: {
|
||||
slug: parsedInput,
|
||||
},
|
||||
data: {
|
||||
name: `${organization.name}-${uuid}`,
|
||||
slug: `${organization.slug}-${uuid}`,
|
||||
deleted : true
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
return {
|
||||
success: true,
|
||||
value: organizationUpdated,
|
||||
actionSuccess: {
|
||||
message: "Organization has been successfully deleted.",
|
||||
messageParams: {organizationId: organizationUpdated.id},
|
||||
},
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
console.error("Error deleting organization:", error);
|
||||
return {
|
||||
success: false,
|
||||
actionError: {
|
||||
message: "Failed to delete organization.",
|
||||
status: 500,
|
||||
cause: error.message ?? "Unknown error",
|
||||
messageParams: {message: "Error deleting the organization"},
|
||||
},
|
||||
};
|
||||
if (organization.length === 0) {
|
||||
throw new Error("Organization not found.");
|
||||
}
|
||||
|
||||
});
|
||||
const updatedOrganization = await db
|
||||
.update(organization)
|
||||
.set({
|
||||
name: `${organization[0].name}-${uuid}`,
|
||||
slug: `${organization[0].slug}-${uuid}`,
|
||||
deleted: true,
|
||||
})
|
||||
.where(eq(organization.id, organization[0].id))
|
||||
.returning()
|
||||
.execute();
|
||||
|
||||
return {
|
||||
success: true,
|
||||
value: updatedOrganization[0],
|
||||
actionSuccess: {
|
||||
message: "Organization has been successfully deleted.",
|
||||
messageParams: { organizationId: updatedOrganization[0].id },
|
||||
},
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("Error deleting organization:", error);
|
||||
return {
|
||||
success: false,
|
||||
actionError: {
|
||||
message: "Failed to delete organization.",
|
||||
status: 500,
|
||||
cause: error.message ?? "Unknown error",
|
||||
messageParams: { message: "Error deleting the organization" },
|
||||
},
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import {z} from "zod";
|
||||
|
||||
import { z } from "zod";
|
||||
|
||||
export const OrganizationSchema = z.object({
|
||||
name: z.string().min(5, 'Name must be at least 5 characters long').max(40, 'Name must be at most 40 characters long'),
|
||||
slug: z.string()
|
||||
.regex(/^[a-zA-Z0-9_-]*$/, 'Slug can only contain letters, numbers, underscores, and hyphens')
|
||||
.min(5, 'Slug must be at least 5 characters long')
|
||||
.max(20, 'Slug must be at most 20 characters long'),
|
||||
name: z.string().min(5, "Name must be at least 5 characters long").max(40, "Name must be at most 40 characters long"),
|
||||
slug: z
|
||||
.string()
|
||||
.regex(/^[a-zA-Z0-9_-]*$/, "Slug can only contain letters, numbers, underscores, and hyphens")
|
||||
.min(5, "Slug must be at least 5 characters long")
|
||||
.max(20, "Slug must be at most 20 characters long"),
|
||||
});
|
||||
|
||||
export type OrganizationSchema = z.infer<typeof OrganizationSchema>;
|
||||
|
||||
Reference in New Issue
Block a user