Skip to content

Commit

Permalink
Merge pull request #1279 from Sinaptik-AI/feature/PAN-868
Browse files Browse the repository at this point in the history
[PAN-868]: workspaces added
  • Loading branch information
ArslanSaleem authored Jul 18, 2024
2 parents 9045ee9 + d7990be commit 6e18055
Show file tree
Hide file tree
Showing 21 changed files with 885 additions and 24 deletions.
8 changes: 6 additions & 2 deletions client/app/settings/datasets/AddNewCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import Card from "@/components/card";
import { useAppStore } from "@/store";
import React from "react";

const AddNewCard = () => {
interface IProps {
text: string;
}

const AddNewCard = ({ text }: IProps) => {
const darkMode = useAppStore((state) => state.darkMode);
return (
<Card
Expand All @@ -13,7 +17,7 @@ const AddNewCard = () => {
<div className="flex flex-col justify-center items-center h-full gap-6 py-[30px]">
<AddWorkSpaceLarge color={darkMode ? "white" : "black"} />
<h1 className="dark:text-white font-bold font-montserrat text-[15px] text-center">
New dataset
{text}
</h1>
</div>
</Card>
Expand Down
2 changes: 1 addition & 1 deletion client/app/settings/datasets/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export default async function Datasets() {
))}

<Link href={`/settings/datasets/add`}>
<AddNewCard />
<AddNewCard text="New dataset" />
</Link>
</div>
</div>
Expand Down
79 changes: 79 additions & 0 deletions client/app/settings/workspaces/[id]/WorkspaceCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
"use client";
import Card from "@/components/card";
import ConfirmationDialog from "@/components/ConfirmationDialog";
import { Button } from "@/components/ui/button";
import { useDeleteWorkspace } from "@/hooks/useSpaces";
import { revalidateWorkspaces } from "@/lib/actions";
import Link from "next/link";
import { useRouter } from "next/navigation";
import React, { useState } from "react";
import { toast } from "react-toastify";

interface IProps {
data: any;
}

const WorkspaceCard = ({ data }: IProps) => {
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
const { isPending, mutateAsync: deleteSpace } = useDeleteWorkspace();
const router = useRouter();

const handleDeleteSpace = () => {
deleteSpace(
{ id: data.id },
{
onSuccess(response) {
toast.success(response?.data?.message);
setIsDeleteModalOpen(false);
revalidateWorkspaces();
router.push("/settings/workspaces");
},
onError(error) {
toast.error(error?.message);
},
}
);
};
return (
<>
<Card extra={"w-full py-4 px-6 h-full mb-4"}>
<div className="flex flex-col justify-between min-h-[300px]">
<div>
<h3 className="font-bold text-[20px] mb-1">{data?.name}</h3>
<h3 className="font-bold text-sm mb-1">
<span className="font-normal">
{`This is the workspace dedicated to the ${data?.name} team.`}
</span>
</h3>
</div>
<div className="flex justify-start gap-4 items-center flex-wrap">
<Link href={`/settings/workspaces/editspaces?id=${data?.id}`}>
<Button>Edit</Button>
</Link>

<div
onClick={() => {
setIsDeleteModalOpen(true);
}}
className={`px-8 py-1 rounded-[10px] flex flex-wrap items-center justify-center cursor-pointer dark:bg-[#D30000] neon-on-hovers`}
>
<span className="font-bold text-white">Delete</span>
</div>
</div>
</div>
</Card>
{isDeleteModalOpen && (
<ConfirmationDialog
text={`Are you sure you want to delete this Workspace?`}
onCancel={() => {
setIsDeleteModalOpen(false);
}}
onSubmit={handleDeleteSpace}
isLoading={isPending}
/>
)}
</>
);
};

export default WorkspaceCard;
79 changes: 79 additions & 0 deletions client/app/settings/workspaces/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import React from "react";
import Card from "components/card";

import { GetWorkspaceDetails } from "@/services/spaces";
import Link from "next/link";
import { Button } from "@/components/ui/button";
import AddNewCard from "../../datasets/AddNewCard";
import { FaFileCsv } from "react-icons/fa";
import WorkspaceCard from "./WorkspaceCard";

interface PageProps {
params: {
id: string;
};
}

export default async function WorkSpacesDetails({ params }: PageProps) {
const data = await GetWorkspaceDetails(params.id);

return (
<div className="w-full h-full overflow-y-auto custom-scroll mt-5 px-2 md:px-4">
<h1 className="text-2xl font-bold dark:text-white mb-10">
<Link href="/settings/workspaces">Workspaces</Link>
<small>{data?.name && ` › ${data?.name}`}</small>
</h1>

<div className="flex flex-col p-2 md:p-4 font-montserrat">
<div className="flex items-center md:flex-row flex-col justify-center gap-4">
<WorkspaceCard data={data} />
<Card extra={"w-full py-4 px-6 h-full mb-4"}>
<div className="flex flex-col justify-between min-h-[300px]">
<div>
<h3 className="font-bold text-[20px] mb-1">People</h3>
<div className="flex flex-col mt-2">
<span>{data?.name}</span>
</div>
</div>
</div>
</Card>
</div>

<h1 className="text-neutral-500 mt-6 text-xl font-bold dark:text-white">
Datasets
</h1>
<div className="mt-2 grid h-full gap-5 grid-cols-1 md:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4">
{data?.dataset_spaces?.map((df) => (
<Card
key={df.dataset_id}
extra={
"w-full pt-4 px-6 h-full border dark:border-none border-[#ccc] pb-8"
}
>
<header className="relative flex items-center justify-between">
<div className="w-full">
<div className="flex justify-center h-24">
<FaFileCsv size="4em" key={0} />
</div>
<div className="h-[65px] w-full overflow-hidden">
<h1 className="dark:text-white font-bold font-montserrat text-[20px] text-center customellipsis">
{df?.dataset?.name}
</h1>
</div>
</div>
</header>
<div className="w-full flex flex-wrap items-center justify-center mt-1">
<Link href={`/settings/datasets/${df?.dataset?.id}`}>
<Button>Details</Button>
</Link>
</div>
</Card>
))}
<Link href={`/settings/datasets/add?space_id=${params.id}`}>
<AddNewCard text="New dataset" />
</Link>
</div>
</div>
</div>
);
}
127 changes: 127 additions & 0 deletions client/app/settings/workspaces/addspaces/AddSpaceCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
"use client";
import React, { useState } from "react";
import { Loader } from "components/loader/Loader";
import Multiselect from "multiselect-react-dropdown";
import { useRouter } from "next/navigation";
import { toast } from "react-toastify";
import { AddWorkspace } from "@/services/spaces";
import { revalidateWorkspaces } from "@/lib/actions";

interface IProps {
datasets: any;
}

interface DataFrame {
id: number;
name: string;
}
const AddSpaceCard = ({ datasets }: IProps) => {
const [name, setName] = useState<string>("");
const [items, setItems] = useState<DataFrame[]>([]);
const [isLoading, setIsLoading] = useState<boolean>(false);
const [nameError, setNameError] = useState<string>("");
const [dataFramesError, setDataFramesError] = useState<string>("");
const dataFrameNames = [];
const dataFrameIds: number[] = [];
const router = useRouter();

items.forEach((data) => {
return dataFrameIds?.push(data.id);
});

datasets?.map((data) => {
return dataFrameNames.push({ id: data?.id, name: data?.name });
});

const handleSelect = (selectedList) => {
setItems(selectedList);
};

const handleSelectRemove = (selectedList) => {
setItems(selectedList);
};

const handleSubmit = async () => {
setNameError("");
let isValid = true;
if (name?.trim() === "") {
setNameError("Name field is required");
isValid = false;
}

if (items?.length === 0) {
setDataFramesError("Tables is required");
isValid = false;
}

if (!isValid) {
return;
}
setIsLoading(true);
const payLoad = {
name: name,
datasets: [...dataFrameIds],
};
await AddWorkspace(payLoad)
.then((response) => {
toast.success(response?.data?.message);
setName("");
revalidateWorkspaces();
router.push("/settings/workspaces");
})
.catch((error) => {
toast.error(
error?.response?.data?.message
? error?.response?.data?.message
: error?.message
);
})
.finally(() => setIsLoading(false));
};

return (
<div className="!z-5 mx-auto relative rounded-[20px] bg-white bg-clip-border shadow-3xl shadow-shadow-100 dark:shadow-none dark:!bg-darkMain dark:text-white max-w-xl p-4 mb-4">
<div className="mb-4">
<label className="w-full">Name*</label>
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
className={`w-full p-2 border rounded dark:!bg-darkMain `}
/>
{nameError && name?.length < 1 && (
<div className="mb-2 rounded-lg bg-red-50 p-2 text-sm text-red-800 dark:bg-gray-800 dark:text-red-500 mt-2 inline-flex">
{nameError}
</div>
)}
</div>
<div className="mb-4 ">
<label className="w-full">Tables*</label>
<Multiselect
className="selectBox"
options={dataFrameNames}
selectedValues={items}
onSelect={handleSelect}
onRemove={handleSelectRemove}
displayValue="name"
/>
{dataFramesError && items?.length < 1 && (
<div className="mb-2 rounded-lg bg-red-50 p-2 text-sm text-red-800 dark:bg-gray-800 dark:text-red-500 mt-2 inline-flex">
{dataFramesError}
</div>
)}
</div>
<div className="text-right">
<button
className="px-4 py-1 text-md rounded linear bg-[#191919] font-medium text-white transition duration-200 dark:bg-[#191919 dark:text-white dark:hover:bg-[#191919 dark:active:bg-[#191919"
onClick={handleSubmit}
disabled={isLoading}
>
{isLoading ? <Loader height="h-6" width="w-10" /> : "Save"}
</button>
</div>
</div>
);
};

export default AddSpaceCard;
12 changes: 12 additions & 0 deletions client/app/settings/workspaces/addspaces/loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Loader } from "@/components/loader/Loader";
import React from "react";

const Loading = () => {
return (
<div className="flex items-center justify-center w-full h-full mx-auto">
<Loader />
</div>
);
};

export default Loading;
31 changes: 31 additions & 0 deletions client/app/settings/workspaces/addspaces/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from "react";
import Link from "next/link";
import { GetAllDataSets } from "@/services/datasets";
import AddSpaceCard from "./AddSpaceCard";
import { Button } from "@/components/ui/button";

export default async function AddSpaces() {
const data = await GetAllDataSets();

return (
<div className="w-full h-full overflow-y-auto custom-scroll mt-5 px-2 md:px-4">
<h1 className="text-2xl font-bold dark:text-white mb-10">
<Link href="/settings/workspaces">Workspaces</Link>
<small> › New</small>
</h1>

{data?.datasets?.length === 0 ? (
<div className="flex flex-col items-center justify-center m-auto">
<p className="dark:text-white font-montserrat text-lg mb-3">
No datasets available, please add one
</p>

<Link href={"/settings/datasets/add"}></Link>
<Button>Add</Button>
</div>
) : (
<AddSpaceCard datasets={data?.datasets} />
)}
</div>
);
}
Loading

0 comments on commit 6e18055

Please sign in to comment.