ui updates for permissions.

This commit is contained in:
mzerone
2024-07-29 16:16:14 +02:00
parent 02320b9484
commit 8d99a6b03c
6 changed files with 116 additions and 34 deletions

View File

@@ -12,6 +12,7 @@
"dependencies": {
"@beam-australia/react-env": "^3.1.1",
"@dnd-kit/core": "^6.1.0",
"@firebase/util": "^1.9.7",
"@headlessui/react": "^1.7.13",
"@mdi/js": "^7.1.96",
"@mdi/react": "^1.6.1",
@@ -67,6 +68,7 @@
"react-select": "^5.7.5",
"react-string-replace": "^1.1.0",
"react-toastify": "^9.1.2",
"react-tooltip": "^5.27.1",
"react-xarrows": "^2.0.2",
"read-excel-file": "^5.7.1",
"short-unique-id": "5.0.2",
@@ -77,8 +79,7 @@
"use-file-picker": "^2.1.0",
"uuid": "^9.0.0",
"wavesurfer.js": "^6.6.4",
"zustand": "^4.3.6",
"react-tooltip": "^5.27.1"
"zustand": "^4.3.6"
},
"devDependencies": {
"@types/blob-stream": "^0.1.33",

View File

@@ -0,0 +1,77 @@
import { Permission } from "@/interfaces/permissions";
import {
createColumnHelper,
flexRender,
getCoreRowModel,
useReactTable,
} from "@tanstack/react-table";
import Link from "next/link";
interface Props{
permissions: Permission[]
}
const columnHelper = createColumnHelper<Permission>();
const defaultColumns = [
columnHelper.accessor('type', {
header: () => <span>Type</span>,
cell: ({row, getValue}) => (
<Link href={`/permissions/${row.original.id}`} key={row.id} className="underline text-mti-purple-light hover:text-mti-purple-dark transition ease-in-out duration-300 cursor-pointer">
{getValue() as string}
</Link>
)
})
];
export default function PermissionList({permissions}: Props) {
const table = useReactTable({
data: permissions,
columns: defaultColumns,
getCoreRowModel: getCoreRowModel(),
})
return (
<div className="w-full">
<div className="w-full flex flex-col gap-2">
<table className="rounded-xl bg-mti-purple-ultralight/40 w-full">
<thead>
{table.getHeaderGroups().map((headerGroup) => (
<tr key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<th className="py-4 px-4 text-left" key={header.id}>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
)}
</th>
))}
</tr>
))}
</thead>
<tbody className="px-2">
{table.getRowModel().rows.map((row) => (
<tr
className="odd:bg-white even:bg-mti-purple-ultralight/40 rounded-lg py-2"
key={row.id}
>
{row.getVisibleCells().map((cell) => (
<td className="px-4 py-2 items-center w-fit" key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</td>
))}
</tr>
))}
</tbody>
</table>
</div>
</div>
)
}

View File

@@ -16,7 +16,6 @@ import moment from "moment";
import axios from "axios";
import {getExam} from "@/utils/exams";
import {toast} from "react-toastify";
import {uuidv4} from "@firebase/util";
import {Assignment} from "@/interfaces/results";
import Checkbox from "@/components/Low/Checkbox";
import {InstructorGender, Variant} from "@/interfaces/exam";

View File

@@ -4,7 +4,7 @@ import {app} from "@/firebase";
import {getFirestore, collection, getDocs, query, where, setDoc, doc, getDoc, deleteDoc} from "firebase/firestore";
import {withIronSessionApiRoute} from "iron-session/next";
import {sessionOptions} from "@/lib/session";
import {uuidv4} from "@firebase/util";
const db = getFirestore(app);

View File

@@ -14,10 +14,11 @@ import Select from "@/components/Low/Select";
import Button from "@/components/Low/Button";
import axios from "axios";
import { toast, ToastContainer } from "react-toastify";
import {Type as UserType} from '@/interfaces/user'
interface BasicUser {
id: string;
name: string;
type: UserType
}
interface PermissionWithBasicUsers {
@@ -61,11 +62,13 @@ export const getServerSideProps = withIronSessionSsr(async (context) => {
const permission: Permission = await getPermissionDoc(params.id as string);
const allUserData: User[] = await getUsers();
const users = allUserData.map((u) => ({
id: u.id,
name: u.name,
type: u.type
})) as BasicUser[];
// const res = await fetch("api/permissions");
// const permissions: Permission[] = await res.json();
// Pass data to the page via props
@@ -101,16 +104,15 @@ interface Props {
}
export default function Page(props: Props) {
console.log("Props", props);
const { permission, user, users } = props;
const [selectedUsers, setSelectedUsers] = useState<string[]>(() =>
permission.users.map((u) => u.id)
);
const onChange = (value: any) => {
console.log("value", value);
setSelectedUsers((prev) => {
if (value?.value) {
return [...prev, value?.value];
@@ -123,7 +125,7 @@ export default function Page(props: Props) {
};
const update = async () => {
console.log("update", selectedUsers);
try {
await axios.patch(`/api/permissions/${permission.id}`, {
users: selectedUsers,
@@ -133,7 +135,7 @@ export default function Page(props: Props) {
toast.error("Failed to update permission");
}
};
return (
<>
<Head>
@@ -156,24 +158,25 @@ export default function Page(props: Props) {
options={users
.filter((u) => !selectedUsers.includes(u.id))
.map((u) => ({
label: u.name,
label: `${u?.type}-${u?.name}`,
value: u.id,
}))}
onChange={onChange}
/>
<Button onClick={update}>Update</Button>
</div>
<div className="flex flex-col gap-3">
<div className="flex flex-row justify-between">
<div className="flex flex-col gap-3">
<h2>Blacklisted Users</h2>
<div className="flex gap-3 flex-wrap">
{selectedUsers.map((userId) => {
const name = users.find((u) => u.id === userId)?.name;
const user = users.find((u) => u.id === userId);
return (
<div
className="flex p-4 rounded-xl w-auto bg-mti-purple-light text-white gap-4"
key={userId}
>
<span className="text-base">{name}</span>
<span className="text-base first-letter:uppercase">{user?.type}-{user?.name}</span>
<BsTrash
style={{ cursor: "pointer" }}
onClick={() => removeUser(userId)}
@@ -184,6 +187,22 @@ export default function Page(props: Props) {
})}
</div>
</div>
<div className="flex flex-col gap-3">
<h2>Whitelisted Users</h2>
<div className="flex flex-col gap-3 flex-wrap">
{users.filter(user => !selectedUsers.includes(user.id)).map((user) => {
return (
<div
className="flex p-4 rounded-xl w-auto bg-mti-purple-light text-white gap-4"
key={user.id}
>
<span className="text-base first-letter:uppercase">{user?.type}-{user?.name}</span>
</div>
);
})}
</div>
</div>
</div>
</Layout>
</>
);

View File

@@ -7,7 +7,7 @@ import { Permission } from "@/interfaces/permissions";
import { getPermissionDocs } from "@/utils/permissions.be";
import { User } from "@/interfaces/user";
import Layout from "@/components/High/Layout";
import Link from "next/link";
import PermissionList from '@/components/PermissionList'
export const getServerSideProps = withIronSessionSsr(async ({ req }) => {
const user = req.session.user;
@@ -33,7 +33,6 @@ export const getServerSideProps = withIronSessionSsr(async ({ req }) => {
// Fetch data from external API
const permissions: Permission[] = await getPermissionDocs();
console.log("Permissions", permissions);
// const res = await fetch("api/permissions");
// const permissions: Permission[] = await res.json();
@@ -56,10 +55,9 @@ interface Props {
}
export default function Page(props: Props) {
console.log("Props", props);
const { permissions, user } = props;
return (
<>
<Head>
@@ -74,19 +72,7 @@ export default function Page(props: Props) {
<Layout user={user} className="gap-6">
<h1 className="text-2xl font-semibold">Permissions</h1>
<div className="flex gap-3 flex-wrap">
{permissions.map((permission: Permission) => {
const id = permission.id as string;
const type = permission.type as string;
return (
<Link href={`/permissions/${id}`} key={id}>
<div className="card bg-primary text-primary-content">
<div className="card-body">
<h1 className="card-title">{type}</h1>
</div>
</div>
</Link>
);
})}
<PermissionList permissions={permissions} />
</div>
</Layout>
</>