Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PAN-868]: workspaces added #1279

Merged
merged 1 commit into from
Jul 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading