Added base for role table

This commit is contained in:
Sianida26 2024-01-26 11:42:42 +07:00
parent a11e0d4da3
commit 11d1e33486
12 changed files with 239 additions and 16 deletions

View File

@ -14,7 +14,7 @@
"@mantine/form": "^7.4.2", "@mantine/form": "^7.4.2",
"@mantine/hooks": "^7.4.2", "@mantine/hooks": "^7.4.2",
"@mantine/notifications": "^7.4.2", "@mantine/notifications": "^7.4.2",
"@prisma/client": "5.7.1", "@prisma/client": "5.8.1",
"@tanstack/react-query": "^4.36.1", "@tanstack/react-query": "^4.36.1",
"@tanstack/react-query-devtools": "^4.36.1", "@tanstack/react-query-devtools": "^4.36.1",
"@tanstack/react-table": "^8.11.7", "@tanstack/react-table": "^8.11.7",

View File

@ -7,7 +7,7 @@ settings:
dependencies: dependencies:
'@auth/prisma-adapter': '@auth/prisma-adapter':
specifier: ^1.0.16 specifier: ^1.0.16
version: 1.0.16(@prisma/client@5.7.1) version: 1.0.16(@prisma/client@5.8.1)
'@mantine/core': '@mantine/core':
specifier: ^7.4.2 specifier: ^7.4.2
version: 7.4.2(@mantine/hooks@7.4.2)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0) version: 7.4.2(@mantine/hooks@7.4.2)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
@ -21,8 +21,8 @@ dependencies:
specifier: ^7.4.2 specifier: ^7.4.2
version: 7.4.2(@mantine/core@7.4.2)(@mantine/hooks@7.4.2)(react-dom@18.2.0)(react@18.2.0) version: 7.4.2(@mantine/core@7.4.2)(@mantine/hooks@7.4.2)(react-dom@18.2.0)(react@18.2.0)
'@prisma/client': '@prisma/client':
specifier: 5.7.1 specifier: 5.8.1
version: 5.7.1(prisma@5.8.1) version: 5.8.1(prisma@5.8.1)
'@tanstack/react-query': '@tanstack/react-query':
specifier: ^4.36.1 specifier: ^4.36.1
version: 4.36.1(react-dom@18.2.0)(react@18.2.0) version: 4.36.1(react-dom@18.2.0)(react@18.2.0)
@ -159,13 +159,13 @@ packages:
preact-render-to-string: 5.2.3(preact@10.11.3) preact-render-to-string: 5.2.3(preact@10.11.3)
dev: false dev: false
/@auth/prisma-adapter@1.0.16(@prisma/client@5.7.1): /@auth/prisma-adapter@1.0.16(@prisma/client@5.8.1):
resolution: {integrity: sha512-i7+XCxrbv5n8Yp9r+FznvnOBG7BrjpfmXr4Fl7pL7LPgTGhDJPE10BokVf5tGTsR8SGnAp04qhBzgjTrTrmpPQ==} resolution: {integrity: sha512-i7+XCxrbv5n8Yp9r+FznvnOBG7BrjpfmXr4Fl7pL7LPgTGhDJPE10BokVf5tGTsR8SGnAp04qhBzgjTrTrmpPQ==}
peerDependencies: peerDependencies:
'@prisma/client': '>=2.26.0 || >=3 || >=4 || >=5' '@prisma/client': '>=2.26.0 || >=3 || >=4 || >=5'
dependencies: dependencies:
'@auth/core': 0.22.0 '@auth/core': 0.22.0
'@prisma/client': 5.7.1(prisma@5.8.1) '@prisma/client': 5.8.1(prisma@5.8.1)
transitivePeerDependencies: transitivePeerDependencies:
- nodemailer - nodemailer
dev: false dev: false
@ -509,8 +509,8 @@ packages:
dev: true dev: true
optional: true optional: true
/@prisma/client@5.7.1(prisma@5.8.1): /@prisma/client@5.8.1(prisma@5.8.1):
resolution: {integrity: sha512-TUSa4nUcC4nf/e7X3jyO1pEd6XcI/TLRCA0KjkA46RDIpxUaRsBYEOqITwXRW2c0bMFyKcCRXrH4f7h4q9oOlg==} resolution: {integrity: sha512-xQtMPfbIwLlbm0VVIVQY2yqQVOxPwRQhvIp7Z3m2900g1bu/zRHKhYZJQWELqmjl6d8YwBy0K2NvMqh47v1ubw==}
engines: {node: '>=16.13'} engines: {node: '>=16.13'}
requiresBuild: true requiresBuild: true
peerDependencies: peerDependencies:

View File

@ -0,0 +1,66 @@
-- CreateTable
CREATE TABLE `Role` (
`id` VARCHAR(191) NOT NULL,
`code` VARCHAR(191) NOT NULL,
`name` VARCHAR(191) NOT NULL,
`description` VARCHAR(191) NOT NULL DEFAULT '',
UNIQUE INDEX `Role_code_key`(`code`),
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- CreateTable
CREATE TABLE `Permission` (
`id` VARCHAR(191) NOT NULL,
`code` VARCHAR(191) NOT NULL,
`name` VARCHAR(191) NOT NULL,
`description` VARCHAR(191) NOT NULL DEFAULT '',
UNIQUE INDEX `Permission_code_key`(`code`),
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- CreateTable
CREATE TABLE `_RoleToUser` (
`A` VARCHAR(191) NOT NULL,
`B` VARCHAR(191) NOT NULL,
UNIQUE INDEX `_RoleToUser_AB_unique`(`A`, `B`),
INDEX `_RoleToUser_B_index`(`B`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- CreateTable
CREATE TABLE `_PermissionToRole` (
`A` VARCHAR(191) NOT NULL,
`B` VARCHAR(191) NOT NULL,
UNIQUE INDEX `_PermissionToRole_AB_unique`(`A`, `B`),
INDEX `_PermissionToRole_B_index`(`B`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- CreateTable
CREATE TABLE `_PermissionToUser` (
`A` VARCHAR(191) NOT NULL,
`B` VARCHAR(191) NOT NULL,
UNIQUE INDEX `_PermissionToUser_AB_unique`(`A`, `B`),
INDEX `_PermissionToUser_B_index`(`B`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- AddForeignKey
ALTER TABLE `_RoleToUser` ADD CONSTRAINT `_RoleToUser_A_fkey` FOREIGN KEY (`A`) REFERENCES `Role`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE `_RoleToUser` ADD CONSTRAINT `_RoleToUser_B_fkey` FOREIGN KEY (`B`) REFERENCES `User`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE `_PermissionToRole` ADD CONSTRAINT `_PermissionToRole_A_fkey` FOREIGN KEY (`A`) REFERENCES `Permission`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE `_PermissionToRole` ADD CONSTRAINT `_PermissionToRole_B_fkey` FOREIGN KEY (`B`) REFERENCES `Role`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE `_PermissionToUser` ADD CONSTRAINT `_PermissionToUser_A_fkey` FOREIGN KEY (`A`) REFERENCES `Permission`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE `_PermissionToUser` ADD CONSTRAINT `_PermissionToUser_B_fkey` FOREIGN KEY (`B`) REFERENCES `User`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;

View File

@ -0,0 +1,5 @@
-- AlterTable
ALTER TABLE `Permission` ADD COLUMN `isActive` BOOLEAN NOT NULL DEFAULT false;
-- AlterTable
ALTER TABLE `Role` ADD COLUMN `isActive` BOOLEAN NOT NULL DEFAULT false;

View File

@ -11,12 +11,14 @@ datasource db {
} }
model User { model User {
id String @id @default(cuid()) id String @id @default(cuid())
name String? name String?
email String? @unique email String? @unique
emailVerified DateTime? emailVerified DateTime?
passwordHash String? passwordHash String?
photoProfile UserPhotoProfiles? photoProfile UserPhotoProfiles?
roles Role[]
directPermissions Permission[]
} }
model UserPhotoProfiles { model UserPhotoProfiles {
@ -24,4 +26,24 @@ model UserPhotoProfiles {
userId String @unique userId String @unique
path String path String
user User @relation(fields: [userId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}
model Role {
id String @id @default(cuid())
code String @unique
name String
description String @default("")
isActive Boolean @default(false)
users User[]
permissions Permission[]
}
model Permission {
id String @id @default(cuid())
code String @unique
name String
description String @default("")
isActive Boolean @default(false)
roles Role[]
directUsers User[]
} }

View File

@ -0,0 +1,71 @@
"use client";
import { Table, Text } from "@mantine/core";
import {
flexRender,
getCoreRowModel,
useReactTable,
} from "@tanstack/react-table";
import React from "react";
import columns from "./columns";
export default function RolesTable() {
const table = useReactTable({
data: [],
columns,
getCoreRowModel: getCoreRowModel(),
defaultColumn: {
cell: (props) => <Text>{props.getValue() as React.ReactNode}</Text>,
},
});
// TODO: Add view when data is empty
return (
<Table verticalSpacing="xs" horizontalSpacing="xs">
{/* Thead */}
<Table.Thead>
{table.getHeaderGroups().map((headerGroup) => (
<Table.Tr key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<Table.Th
key={header.id}
style={{
maxWidth: `${header.column.columnDef.maxSize}px`,
width: `${header.getSize()}`,
}}
>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
)}
</Table.Th>
))}
</Table.Tr>
))}
</Table.Thead>
{/* Tbody */}
<Table.Tbody>
{table.getRowModel().rows.map((row) => (
<Table.Tr key={row.id}>
{row.getVisibleCells().map((cell) => (
<Table.Td
key={cell.id}
style={{
maxWidth: `${cell.column.columnDef.maxSize}px`,
}}
>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</Table.Td>
))}
</Table.Tr>
))}
</Table.Tbody>
</Table>
);
}

View File

@ -0,0 +1,38 @@
import { createColumnHelper } from "@tanstack/react-table";
import { StringifyOptions } from "querystring";
export interface RoleRow {
id: string,
code: string,
name: string,
permissionCount: number,
userCount: number,
}
const columnHelper = createColumnHelper<RoleRow>()
const columns = [
columnHelper.accessor("id",{
id: "sequence",
header: "#",
cell: props => props.row.index + 1,
}),
columnHelper.accessor("code", {
header: 'Code',
}),
columnHelper.accessor("name", {
header: "Name"
}),
columnHelper.accessor("permissionCount", {
header: "Permissions"
}),
columnHelper.accessor("userCount", {
header: "Users"
}),
]
export default columns;

View File

@ -0,0 +1,17 @@
import { Card, Stack, Title } from "@mantine/core";
import { Metadata } from "next";
import React from "react";
import RolesTable from "./_tables/RolesTable/RolesTable";
export const metadata: Metadata = {
title: "Roles",
};
export default function RolesPage() {
return <Stack>
<Title order={1}>Roles</Title>
<Card>
<RolesTable />
</Card>
</Stack>;
}

View File

@ -24,6 +24,8 @@ export default function UsersTable({users}: Props) {
} }
}); });
// TODO: Add view when data is empty
return ( return (
<> <>
<Table verticalSpacing="xs" horizontalSpacing="xs"> <Table verticalSpacing="xs" horizontalSpacing="xs">

View File

@ -15,7 +15,7 @@ const columnHelper = createColumnHelper<UserRow>()
const columns = [ const columns = [
columnHelper.display({ columnHelper.display({
id: "seequence", id: "sequence",
header: "#", header: "#",
cell: props => props.row.index + 1, cell: props => props.row.index + 1,
size: 1 size: 1

View File

@ -46,6 +46,8 @@ export default async function UsersPage({searchParams}: Props) {
return null; return null;
} }
// TODO: Add functinoality for create new user
return ( return (
<Stack className="flex flex-col"> <Stack className="flex flex-col">
<Title order={1}>Users</Title> <Title order={1}>Users</Title>

View File

@ -29,7 +29,7 @@ const allMenu: MenuItem[] = [
color: "grape", color: "grape",
children: [ children: [
{ label: "Users", link: "/users" }, { label: "Users", link: "/users" },
{ label: "Roles", link: "#" }, { label: "Roles", link: "/roles" },
{ label: "Permissions", link: "#" }, { label: "Permissions", link: "#" },
], ],
}, },