Skip to content

RBAC integration done in the client side #59

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

Merged
merged 8 commits into from
Mar 29, 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
4 changes: 4 additions & 0 deletions client/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,7 @@
background: #0F172A; /* Color of the scrollbar handle on hover */
border: 2px solid white; /* Color of the scrollbar handle on hover */
}

nextjs-portal {
display: none;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export default function EmptyFillContainer({children}: {children: React.ReactNode}) {
export default function EmptyFillContainer({children, className = ""}: {children: React.ReactNode, className?: string}) {
return (
<div className="rounded-xl border bg-card text-card-foreground shadow w-full h-full p-4">{children}</div>
<div className={"rounded-xl border bg-card text-card-foreground shadow w-full h-full p-4 " + className}>{children}</div>
);

}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Button } from "@/components/ui/button";
import { Cog, UserRoundCog } from "lucide-react";
import EmptyFillContainer from "../../cards/EmptyFillContainer";
import { RoleCreateModal } from "@/components/modals/userControls/RoleModal";
import { RoleCreateModal } from "@/components/modals/userControls/RoleModal";
import PermissonList from "@/components/lists/PermissonList";
import { RoleDeleteModal } from "@/components/modals/userControls/RoleDeleteModal";

export default function AdminRolesManagementPanel() {
return (
Expand All @@ -11,32 +13,30 @@ export default function AdminRolesManagementPanel() {
<div className="flex-grow-1"></div>
<div className="flex gap-2">
<RoleCreateModal>
<Button size="sm" className="w-full bg-black text-white">
<UserRoundCog size={16} className="mr-2" />
ADD NEW ROLE
</Button>
<Button size="sm" className="w-full bg-black text-white">
<UserRoundCog size={16} className="mr-2" />
ADD NEW ROLE
</Button>
</RoleCreateModal>
<RoleDeleteModal>
<Button size="sm" className="w-full bg-black text-white">
<UserRoundCog size={16} className="mr-2" />
DELETE ROLE
</Button>
</RoleDeleteModal>
<Button size="sm" className="w-full">
<Cog size={16} className="mr-2" />
ADD NEW PERMISSON
</Button>
</div>
</div>
<div className="flex flex-1 items-center justify-center rounded-lg border border-dashed shadow-sm">
<div className="grid grid-cols-2 md:grid-cols-7 grid-rows-9 grid-flow-row gap-2 md:gap-4 w-full md:h-full max-h-max">
<div className="col-span-2 row-span-3 min-h-36">
<EmptyFillContainer>Roles List</EmptyFillContainer>
</div>
<div className="col-span-2 md:col-span-5 row-span-9">
<EmptyFillContainer>Permisson List</EmptyFillContainer>
</div>
<div className="col-span-2 row-span-3 min-h-36">
<EmptyFillContainer>Role Distribution chart</EmptyFillContainer>
</div>
<div className="col-span-2 row-span-3 min-h-36">
<EmptyFillContainer>Role Requests</EmptyFillContainer>
</div>
</div>
<div className="flex max-w-[90vw] md:max-w-[100vw] items-center justify-center rounded-lg border border-dashed shadow-sm h-full">
<EmptyFillContainer className="flex flex-col">
<h1 className="text-2xl p-4 w-full text-center mb-2">
<b>PERMISSON LIST</b> BY ROLE
</h1>
<PermissonList />
</EmptyFillContainer>
</div>
</main>
);
Expand Down
197 changes: 197 additions & 0 deletions client/components/lists/PermissonList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
"usr client";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import { Label } from "@/components/ui/label";
import EmptyFillContainer from "../dashboard-componenets/cards/EmptyFillContainer";
import { use, useEffect, useState } from "react";
import useGetAllRole from "@/hooks/user_data/useGetAllRole";
import { fetchAllPermissons } from "@/hooks/user_data/getAllPermissonList";
import { set } from "react-hook-form";
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "../ui/alert-dialog";
import { Button } from "../ui/button";
import { updatePermisson } from "@/hooks/user_data/updatePermisson";
import { Pointer, SquareMousePointer } from "lucide-react";

type RolesWithPermisson = {
id: string;
name: string;
permissions: [
{
name: string;
description: string;
}
];
};

type Permisson = {
name: string;
description: string;
};

type EditPermisson = {
role: string;
permission: string;
action: string;
};

function PermissonList() {
const { fetchAllRoles, rolesWithPermissions } = useGetAllRole();
const [roles, setRoles] = useState<RolesWithPermisson[]>([]);
const [permissions, setPermissions] = useState<Permisson[]>([]);
const [msg, setMsg] = useState<EditPermisson>();

async function getPermissons() {
setPermissions(await fetchAllPermissons());
}

useEffect(() => {
fetchAllRoles();
getPermissons();
}, []);

useEffect(() => {
setRoles(rolesWithPermissions);
//setSelectedRole(rolesWithPermissions[0]?.name);
}, [rolesWithPermissions]);

const [selectedRole, setSelectedRole] = useState<string>();

return (
<div className="flex flex-col flex-grow">
<RadioGroup
className="flex flex-wrap justify-center content-center gap-4 w-full mb-2"
onValueChange={(e) => setSelectedRole(e)}
>
{roles.map((role) => (
<div key={role.id} className="flex items-center space-x-2">
<RadioGroupItem value={role.name} className="hidden" id={role.id} />
<Label htmlFor={role.id}>
<div
className={
"hover:cursor-pointer hover:scale-125 " +
(selectedRole === role.name
? "p-2.5 border text-card rounded-lg bg-card-foreground tracking-wider capitalize shadow-md border-black shadow-slate-600"
: "text-card-forground bg-card shadow-lg rounded-lg p-2")
}
>
{role.name}
</div>
</Label>
</div>
))}
</RadioGroup>

{selectedRole ? (
<div className="mt-4 flex flex-col gap-2">
<div className="grid grid-cols-1 gap-2">
{roles
.filter((role) => role.name === selectedRole)
.map((role) => (
<AlertDialog>
<AlertDialogTrigger>
<div
key={role.id}
className="mt-4 flex flex-wrap gap-4 w-full content-center justify-center"
>
{permissions.map((permission) => (
<div
key={permission.name}
onClick={async () => {
const str = role.permissions.find(
(perm) => perm.name === permission.name
)
? "REMOVE"
: "ADD";
await setMsg({
role: role.name,
permission: permission.name,
action: str,
});
}}
className={
"flex flex-col gap-1 my-2 px-6 py-4 bg-green-100 text-card-foreground shadow-md rounded-lg hover:cursor-pointer hover:scale-110 hover:text-white" +
(role.permissions.find(
(perm) => perm.name === permission.name
)
? " bg-green-500"
: " bg-red-500")
}
>
<h1 className="text-lg font-bold">
{permission.name}
</h1>
<p className="text-sm">{permission.description}</p>
</div>
))}
</div>
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle className="flex justify-center items-center mt-3">
<div className="text-center">
CONFIRM THAT YOU WANT TO{" "}
{msg?.action === "ADD" ? (
<div>
<span className="text-green-700">
ADD "{msg?.permission}"
</span>{" "}
PERMISSION TO{" "}
</div>
) : (
<div>
<span className="text-red-700">
REMOVE "{msg?.permission}"
</span>{" "}
PERMISSION FROM{" "}
</div>
)}
<i>{msg?.role}</i> ?
</div>
</AlertDialogTitle>
<AlertDialogDescription>
<div className="flex flex-col justify-center items-center my-5">
<div>
ACTION : <b>{msg?.action} PERMISSON</b>
</div>
<div>
ROLE : <b>{msg?.role}</b>
</div>
<div>
PERMISSION : <b>{msg?.permission}</b>
</div>
</div>
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction
onClick={async () => {
msg && alert(await updatePermisson(msg));
await fetchAllRoles();
setMsg(undefined);
}}
>
Confirm
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
))}
</div>
</div>
) : (
<h1 className="text-2xl flex-grow flex flex-col justify-center items-center gap-5"><Pointer size={56} />Select a role from above to view permissions</h1>
)}
</div>
);
}
export default PermissonList;
72 changes: 72 additions & 0 deletions client/components/modals/userControls/RoleDeleteModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
DialogClose
} from "@/components/ui/dialog";

import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import addNewRole from "@/hooks/user_data/addNewRole";
import deleteRole from "@/hooks/user_data/deleteRole";
import React , {useState} from "react";

interface DialogWrapperProps {
children: React.ReactNode;
}

export const RoleDeleteModal: React.FC<DialogWrapperProps> = ({
children,
}) => {
const [roleName, setRoleName] = useState("");

const handleSaveChanges = async () => {
await deleteRole(roleName);
window.location.reload();
};


return (
<Dialog>
<DialogTrigger asChild>
{/* <Button variant="outline">Edit Profile</Button> */}
{children}
</DialogTrigger>
<DialogContent className="w-[825px]">
<DialogHeader>
<DialogTitle>Delete Role</DialogTitle>
<DialogDescription>
Select a role to delete. Click delete when you're done.
</DialogDescription>
</DialogHeader>
<div className="grid gap-4 py-4">
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="name" className="text-right">
Select Role
</Label>
<Input
id="name"
placeholder="Vehicle Manager"
className="col-span-3"
value={roleName}
onChange={(e) => setRoleName(e.target.value)}
/>
</div>
</div>
<DialogFooter>
<DialogClose asChild>
<div><Button type="button" className="mr-3">Cancel</Button>
<Button type="button" onClick={handleSaveChanges}>DELETE</Button>
</div>
</DialogClose>
</DialogFooter>

</DialogContent>
</Dialog>
);
};
23 changes: 5 additions & 18 deletions client/components/modals/userControls/RoleModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {

import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import addNewRole from "@/hooks/user_data/addNewRole";
import React , {useState} from "react";

interface DialogWrapperProps {
Expand All @@ -21,13 +22,11 @@ interface DialogWrapperProps {
export const RoleCreateModal: React.FC<DialogWrapperProps> = ({
children,
}) => {
const [description, setDescription] = useState("");
const [roleName, setRoleName] = useState("");

const handleSaveChanges = () => {
console.log("Vehicle Number:", description);
console.log("Vehicle Number:", roleName);

const handleSaveChanges = async () => {
await addNewRole(roleName);
window.location.reload();
};


Expand Down Expand Up @@ -56,19 +55,7 @@ export const RoleCreateModal: React.FC<DialogWrapperProps> = ({
value={roleName}
onChange={(e) => setRoleName(e.target.value)}
/>
</div>
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="description" className="text-right">
Role Description
</Label>
<Input
id="capacity"
placeholder="1-100"
className="col-span-3"
value={description}
onChange={(e) => setDescription(e.target.value)}
/>
</div>
</div>
</div>
<DialogFooter>
<DialogClose asChild>
Expand Down
Loading