Updated permissions to have a key to group them

This commit is contained in:
Joao Ramos
2024-08-14 18:44:35 +01:00
parent 859d9283a7
commit cb75ba6056
4 changed files with 197 additions and 109 deletions

View File

@@ -1,7 +1,14 @@
import {Permission} from "@/interfaces/permissions"; import React from "react";
import {createColumnHelper, flexRender, getCoreRowModel, useReactTable} from "@tanstack/react-table"; import { Permission } from "@/interfaces/permissions";
import {
createColumnHelper,
flexRender,
getCoreRowModel,
useReactTable,
Row,
} from "@tanstack/react-table";
import Link from "next/link"; import Link from "next/link";
import {convertCamelCaseToReadable} from "@/utils/string"; import { convertCamelCaseToReadable } from "@/utils/string";
interface Props { interface Props {
permissions: Permission[]; permissions: Permission[];
@@ -12,23 +19,36 @@ const columnHelper = createColumnHelper<Permission>();
const defaultColumns = [ const defaultColumns = [
columnHelper.accessor("type", { columnHelper.accessor("type", {
header: () => <span>Type</span>, header: () => <span>Type</span>,
cell: ({row, getValue}) => ( cell: ({ row, getValue }) => (
<Link <Link
href={`/permissions/${row.original.id}`} href={`/permissions/${row.original.id}`}
key={row.id} key={row.id}
className="underline text-mti-purple-light hover:text-mti-purple-dark transition ease-in-out duration-300 cursor-pointer"> className="underline text-mti-purple-light hover:text-mti-purple-dark transition ease-in-out duration-300 cursor-pointer"
>
{convertCamelCaseToReadable(getValue() as string)} {convertCamelCaseToReadable(getValue() as string)}
</Link> </Link>
), ),
}), }),
]; ];
export default function PermissionList({permissions}: Props) { export default function PermissionList({ permissions }: Props) {
const table = useReactTable({ const table = useReactTable({
data: permissions, data: permissions,
columns: defaultColumns, columns: defaultColumns,
getCoreRowModel: getCoreRowModel(), getCoreRowModel: getCoreRowModel(),
}); });
const groupedData: { [key: string]: Row<Permission>[] } = table
.getRowModel()
.rows.reduce((groups: { [key: string]: Row<Permission>[] }, row) => {
const parent = row.original.topic;
if (!groups[parent]) {
groups[parent] = [];
}
groups[parent].push(row);
return groups;
}, {});
return ( return (
<div className="w-full"> <div className="w-full">
<div className="w-full flex flex-col gap-2"> <div className="w-full flex flex-col gap-2">
@@ -38,22 +58,45 @@ export default function PermissionList({permissions}: Props) {
<tr key={headerGroup.id}> <tr key={headerGroup.id}>
{headerGroup.headers.map((header) => ( {headerGroup.headers.map((header) => (
<th className="py-4 px-4 text-left" key={header.id}> <th className="py-4 px-4 text-left" key={header.id}>
{header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())} {header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
)}
</th> </th>
))} ))}
</tr> </tr>
))} ))}
</thead> </thead>
<tbody className="px-2"> <tbody className="px-2">
{table.getRowModel().rows.map((row) => ( {Object.keys(groupedData).map((parent) => (
<tr className="odd:bg-white even:bg-mti-purple-ultralight/40 rounded-lg py-2" key={row.id}> <React.Fragment key={parent}>
<tr>
<td className="px-2 py-2 items-center w-fit">
<strong>{parent}</strong>
</td>
</tr>
{groupedData[parent].map((row, i) => (
<tr
className="odd:bg-white even:bg-mti-purple-ultralight/40 rounded-lg py-2"
key={row.id}
>
{row.getVisibleCells().map((cell) => ( {row.getVisibleCells().map((cell) => (
<td className="px-4 py-2 items-center w-fit" key={cell.id}> <td
{flexRender(cell.column.columnDef.cell, cell.getContext())} className="px-4 py-2 items-center w-fit"
key={cell.id}
>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</td> </td>
))} ))}
</tr> </tr>
))} ))}
</React.Fragment>
))}
</tbody> </tbody>
</table> </table>
</div> </div>

View File

@@ -1,58 +1,89 @@
export const markets = ["au", "br", "de"] as const; export interface PermissionTopic {
topic: string;
list: string[];
}
export const permissions = [ export const permissions = [
// generate codes are basicly invites {
"createCodeStudent", topic: "Manage Corporate",
"createCodeTeacher", list: [
"viewCorporate",
"editCorporate",
"deleteCorporate",
"createCodeCorporate", "createCodeCorporate",
],
},
{
topic: "Manage Admin",
list: ["viewAdmin", "editAdmin", "deleteAdmin", "createCodeAdmin"],
},
{
topic: "Manage Student",
list: ["viewStudent", "editStudent", "deleteStudent", "createCodeStudent"],
},
{
topic: "Manage Teacher",
list: ["viewTeacher", "editTeacher", "deleteTeacher", "createCodeTeacher"],
},
{
topic: "Manage Country Manager",
list: [
"viewCountryManager",
"editCountryManager",
"deleteCountryManager",
"createCodeCountryManager", "createCodeCountryManager",
"createCodeAdmin", ],
// exams },
{
topic: "Manage Exams",
list: [
"createReadingExam", "createReadingExam",
"createListeningExam", "createListeningExam",
"createWritingExam", "createWritingExam",
"createSpeakingExam", "createSpeakingExam",
"createLevelExam", "createLevelExam",
// view pages ],
},
{
topic: "View Pages",
list: [
"viewExams", "viewExams",
"viewExercises", "viewExercises",
"viewRecords", "viewRecords",
"viewStats", "viewStats",
"viewTickets", "viewTickets",
"viewPaymentRecords", "viewPaymentRecords",
// view data ],
"viewStudent", },
"viewTeacher", {
"viewCorporate", topic: "Manage Group",
"viewCountryManager", list: ["viewGroup", "editGroup", "deleteGroup", "createGroup"],
"viewAdmin", },
"viewGroup", {
"viewCodes", topic: "Manage Codes",
// edit data list: ["viewCodes", "deleteCodes", "createCodes"],
"editStudent", },
"editTeacher", {
"editCorporate", topic: "Others",
"editCountryManager", list: ["all"],
"editAdmin", },
"editGroup",
// delete data
"deleteStudent",
"deleteTeacher",
"deleteCorporate",
"deleteCountryManager",
"deleteAdmin",
"deleteGroup",
"deleteCodes",
// create options
"createGroup",
"createCodes",
"all",
] as const; ] as const;
export type PermissionType = (typeof permissions)[keyof typeof permissions]; const permissionsList = [
...new Set(
permissions.reduce(
(accm: string[], permission) => [...accm, ...permission.list],
[]
)
),
];
export type PermissionType =
(typeof permissionsList)[keyof typeof permissionsList];
export interface Permission { export interface Permission {
id: string; id: string;
type: PermissionType; type: PermissionType;
topic: string;
users: string[]; users: string[];
} }

View File

@@ -55,9 +55,7 @@ interface Props {
} }
export default function Page(props: Props) { export default function Page(props: Props) {
const { permissions, user } = props; const { permissions, user } = props;
return ( return (
<> <>
<Head> <Head>

View File

@@ -16,12 +16,13 @@ import {
Permission, Permission,
PermissionType, PermissionType,
permissions, permissions,
PermissionTopic,
} from "@/interfaces/permissions"; } from "@/interfaces/permissions";
import {v4} from "uuid"; import { v4 } from "uuid";
const db = getFirestore(app); const db = getFirestore(app);
async function createPermission(type: string) { async function createPermission(topic: string, type: string) {
const permData = doc(db, "permissions", v4()); const permData = doc(db, "permissions", v4());
const permDoc = await getDoc(permData); const permDoc = await getDoc(permData);
if (permDoc.exists()) { if (permDoc.exists()) {
@@ -30,9 +31,14 @@ async function createPermission(type: string) {
await setDoc(permData, { await setDoc(permData, {
type, type,
topic,
users: [], users: [],
}); });
} }
interface PermissionsHelperList {
topic: string;
type: string;
}
export function getPermissions(userId: string | undefined, docs: Permission[]) { export function getPermissions(userId: string | undefined, docs: Permission[]) {
if (!userId) { if (!userId) {
return []; return [];
@@ -52,8 +58,18 @@ export function getPermissions(userId: string | undefined, docs: Permission[]) {
} }
export async function bootstrap() { export async function bootstrap() {
await permissions.forEach(async (type) => { await permissions
await createPermission(type); .reduce((accm: PermissionsHelperList[], permissionData) => {
return [
...accm,
...permissionData.list.map((type) => ({
topic: permissionData.topic,
type,
})),
];
}, [])
.forEach(async ({ topic, type }) => {
await createPermission(topic, type);
}); });
} }