Skip to content

Commit 34dd643

Browse files
authored
Merge pull request #18 from jmacuga/add-sql-db
migrated relational data to mariadb database
2 parents da10eb0 + c06fe70 commit 34dd643

40 files changed

+858
-446
lines changed

.env.example

+4-1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,7 @@ NEXT_PUBLIC_WEBSOCKET_URL="ws://localhost:3000/api/socket"
33

44
# `openssl rand -base64 32`
55
AUTH_SECRET=
6-
AUTH_URL=
6+
AUTH_URL=
7+
8+
#mariadb
9+
DATABASE_URL="mysql://root:root1234@localhost:3306/collaboard"

README.md

+12
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,18 @@ Add `.env` file based on `.env.example`
6868

6969
`docker compose up`
7070

71+
5. Generate prisma client
72+
73+
```
74+
npx prisma generate
75+
```
76+
77+
6. Initialize MariaDB by applying migrations
78+
79+
```
80+
npx prisma migrate
81+
```
82+
7183
3. Run app node.js development server
7284

7385
`npm run dev`

components/boards/board-cards.tsx

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { IBoard } from "@/db/models/Board";
1+
import { Board } from "@prisma/client";
22
import {
33
Card,
44
CardHeader,
@@ -13,12 +13,12 @@ import { getColorForIndex } from "@/lib/utils/colors";
1313
import { format } from "date-fns";
1414
import { DeleteBoardDialog } from "@/components/boards/delete-board-dialog";
1515

16-
export function BoardCards({ teamBoards }: { teamBoards: IBoard[] | null }) {
16+
export function BoardCards({ teamBoards }: { teamBoards: Board[] | null }) {
1717
return (
1818
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
1919
{teamBoards ? (
2020
teamBoards.map((board, index) => (
21-
<Card key={board._id as string} className="relative group">
21+
<Card key={board.id} className="relative group">
2222
<div
2323
className="absolute inset-0 opacity-5"
2424
style={{
@@ -35,7 +35,7 @@ export function BoardCards({ teamBoards }: { teamBoards: IBoard[] | null }) {
3535
{board.name}
3636
</CardTitle>
3737
<DeleteBoardDialog
38-
boardId={board._id as string}
38+
boardId={board.id}
3939
boardName={board.name}
4040
teamId={board.teamId}
4141
/>
@@ -47,7 +47,7 @@ export function BoardCards({ teamBoards }: { teamBoards: IBoard[] | null }) {
4747
</p>
4848
</CardContent>
4949
<CardFooter className="relative justify-end">
50-
<Link href={`/board/${board._id}`} className="ml-auto">
50+
<Link href={`/board/${board.id}`} className="ml-auto">
5151
<Button
5252
variant="ghost"
5353
className="hover:bg-accent/50 transition-colors flex items-center gap-2"

components/teams/teams-cards.tsx

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import Link from "next/link";
22
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
3-
import { ITeam } from "@/db/models/Team";
3+
import { Team } from "@prisma/client";
44
import { Users } from "lucide-react";
55

6-
export default function TeamsCards({ teams }: { teams: ITeam[] }) {
6+
export default function TeamsCards({ teams }: { teams: Team[] }) {
77
return (
88
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
99
{teams ? (
1010
teams.map((team) => (
11-
<Card key={team._id} className="hover:bg-accent/50 transition-colors">
12-
<Link href={`/teams/${team._id}/boards`}>
11+
<Card key={team.id} className="hover:bg-accent/50 transition-colors">
12+
<Link href={`/teams/${team.id}/boards`}>
1313
<a className="block">
1414
<CardHeader>
1515
<CardTitle className="flex items-center gap-2">
@@ -18,7 +18,7 @@ export default function TeamsCards({ teams }: { teams: ITeam[] }) {
1818
</CardTitle>
1919
</CardHeader>
2020
<CardContent className="text-sm text-muted-foreground">
21-
Team ID: {team._id}
21+
Team ID: {team.id}
2222
</CardContent>
2323
</a>
2424
</Link>

db/data.ts

+66-45
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,27 @@
11
"use server";
22

3-
import { Board, IBoard } from "@/db/models/Board";
4-
import dbConnect from "@/db/dbConnect";
5-
import { ObjectId } from "mongoose";
6-
import { IUser, User } from "@/db/models/User";
7-
import { ITeam, Team } from "@/db/models/Team";
8-
import { TeamMember } from "@/db/models/TeamMember";
9-
import { IDoc, Doc } from "@/db/models/Doc";
3+
import { prisma } from "@/db/prisma";
4+
import { Board, Team, User } from "@prisma/client";
105

11-
export async function createTeam({
6+
export async function createBoard({
127
name,
138
teamId,
149
isMergeRequestRequired,
15-
docId,
10+
docUrl,
1611
}: {
1712
name: string;
18-
teamId: ObjectId;
13+
teamId: string;
1914
isMergeRequestRequired?: boolean;
20-
docId?: string;
21-
}): Promise<IBoard | null> {
15+
docUrl?: string;
16+
}): Promise<Board | null> {
2217
try {
23-
await dbConnect();
24-
const board = await Board.create({
25-
name,
26-
teamId,
27-
isMergeRequestRequired,
28-
docId,
18+
const board = await prisma.board.create({
19+
data: {
20+
name,
21+
teamId,
22+
isMergeRequestRequired: isMergeRequestRequired ?? true,
23+
docUrl,
24+
},
2925
});
3026
return board;
3127
} catch (e) {
@@ -34,60 +30,81 @@ export async function createTeam({
3430
}
3531
}
3632

37-
export async function getBoardById(id: string): Promise<IBoard | null> {
33+
export async function deleteBoard(boardId: string): Promise<Board | null> {
34+
try {
35+
const board = await prisma.board.delete({
36+
where: { id: boardId },
37+
});
38+
return board;
39+
} catch (e) {
40+
console.error(e);
41+
return null;
42+
}
43+
}
44+
45+
export async function getBoardById(id: string): Promise<Board | null> {
3846
try {
3947
if (!id) {
4048
console.error("Board ID is required");
4149
return null;
4250
}
43-
await dbConnect();
44-
const board = await Board.findById(id);
45-
return JSON.parse(JSON.stringify(board));
51+
const board = await prisma.board.findUnique({
52+
where: { id },
53+
});
54+
return board;
4655
} catch (e) {
4756
console.error(e);
4857
return null;
4958
}
5059
}
5160

52-
export async function getUser(email: string): Promise<IUser | null> {
61+
export async function getUser(email: string): Promise<User | null> {
5362
try {
54-
await dbConnect();
55-
return await User.findOne({ email: email });
63+
return await prisma.user.findUnique({
64+
where: { email },
65+
});
5666
} catch (error) {
5767
console.error("Failed to fetch user:", error);
5868
return null;
5969
}
6070
}
6171

62-
export async function getUserTeams(userId: string): Promise<ITeam[] | null> {
72+
export async function getUserTeams(userId: string): Promise<Team[] | null> {
6373
try {
64-
await dbConnect();
65-
const userTeamMemberships = await TeamMember.find({ userId });
66-
const teamIds = userTeamMemberships.map((membership) => membership.teamId);
67-
const teams = await Team.find({ _id: { $in: teamIds } });
68-
return JSON.parse(JSON.stringify(teams));
74+
const teams = await prisma.team.findMany({
75+
where: {
76+
members: {
77+
some: {
78+
userId,
79+
},
80+
},
81+
},
82+
});
83+
return teams;
6984
} catch (e) {
7085
console.error(e);
7186
return null;
7287
}
7388
}
7489

75-
export async function getTeamBoards(teamId: string): Promise<IBoard[] | null> {
90+
export async function getTeamBoards(teamId: string): Promise<Board[] | null> {
7691
try {
77-
await dbConnect();
78-
const boards = await Board.find({ teamId });
79-
return JSON.parse(JSON.stringify(boards));
92+
const boards = await prisma.board.findMany({
93+
where: { teamId },
94+
});
95+
return boards;
8096
} catch (e) {
8197
console.error(e);
8298
return null;
8399
}
84100
}
85101

86-
export async function getTeam(id: string): Promise<ITeam | null> {
102+
export async function getTeam(id: string): Promise<Team | null> {
87103
try {
88-
await dbConnect();
89-
const team = await Team.findById(id);
90-
return JSON.parse(JSON.stringify(team));
104+
const team = await prisma.team.findUnique({
105+
where: { id },
106+
});
107+
return team;
91108
} catch (e) {
92109
console.error(e);
93110
return null;
@@ -96,15 +113,17 @@ export async function getTeam(id: string): Promise<ITeam | null> {
96113

97114
export async function updateBoard(
98115
boardId: string,
99-
updateData: Partial<IBoard>
100-
) {
116+
updateData: Partial<Board>
117+
): Promise<Board | null> {
101118
if (!boardId) {
102119
console.error("Board ID is required");
103120
return null;
104121
}
105122
try {
106-
await dbConnect();
107-
return await Board.findByIdAndUpdate(boardId, updateData);
123+
return await prisma.board.update({
124+
where: { id: boardId },
125+
data: updateData,
126+
});
108127
} catch (e) {
109128
console.error(e);
110129
return null;
@@ -113,8 +132,10 @@ export async function updateBoard(
113132

114133
export async function getBoardDocUrl(boardId: string): Promise<string | null> {
115134
try {
116-
await dbConnect();
117-
const board = await Board.findById(boardId);
135+
const board = await prisma.board.findUnique({
136+
where: { id: boardId },
137+
select: { docUrl: true },
138+
});
118139
return board?.docUrl || null;
119140
} catch (e) {
120141
console.error(e);

db/data/populateMongodb.ts

-43
This file was deleted.

db/data/user.sql

-1
This file was deleted.

db/models/Board.ts

-33
This file was deleted.

db/models/BoardLog.ts

-36
This file was deleted.

0 commit comments

Comments
 (0)