Added base for role table
This commit is contained in:
parent
a11e0d4da3
commit
11d1e33486
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -17,6 +17,8 @@ model User {
|
||||||
emailVerified DateTime?
|
emailVerified DateTime?
|
||||||
passwordHash String?
|
passwordHash String?
|
||||||
photoProfile UserPhotoProfiles?
|
photoProfile UserPhotoProfiles?
|
||||||
|
roles Role[]
|
||||||
|
directPermissions Permission[]
|
||||||
}
|
}
|
||||||
|
|
||||||
model UserPhotoProfiles {
|
model UserPhotoProfiles {
|
||||||
|
|
@ -25,3 +27,23 @@ model UserPhotoProfiles {
|
||||||
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[]
|
||||||
|
}
|
||||||
|
|
@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
17
src/app/dashboard/(auth)/roles/page.tsx
Normal file
17
src/app/dashboard/(auth)/roles/page.tsx
Normal 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>;
|
||||||
|
}
|
||||||
|
|
@ -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">
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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: "#" },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user