Skip to content

Commit e5068b3

Browse files
committed
feat: enhance task and project services with user context
- Updated task and project service functions to accept userId for improved data retrieval based on user-specific workspaces. - Refactored execToolByName method to include userId, ensuring tools operate within the correct user context. - Enhanced KanbanBoard and Sidebar components with TypeScript type annotations for better type safety and clarity.
1 parent 4e126c2 commit e5068b3

File tree

4 files changed

+82
-40
lines changed

4 files changed

+82
-40
lines changed

backend/src/ai-agent/ask.service.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -71,32 +71,32 @@ export class AskService {
7171
* Helper: execute a tool by name (serial)
7272
* Returns the raw tool result (JS object/array) or { error: ... }
7373
*/
74-
private async execToolByName(fn: string, args: any) {
74+
private async execToolByName(fn: string, args: any, userId: string) {
7575
try {
7676
if (fn === "getRepos") {
7777
return await getRepos();
7878
} else if (fn === "getContributors") {
7979
return await getContributors(args.repo);
8080
} else if (fn === "getProjects") {
81-
return await getProjects();
81+
return await getProjects(userId);
8282
} else if (fn === "getMembers") {
83-
return await getMembers();
83+
return await getMembers(userId);
8484
} else if (fn === "getAllTasks") {
85-
return await getAllTasks(args?.projectId || "");
85+
return await getAllTasks(args?.projectId || "", userId);
8686
} else if (fn === "getTodoTasks") {
87-
return await getTodoTasks(args?.projectId || "");
87+
return await getTodoTasks(args?.projectId || "", userId);
8888
} else if (fn === "getInProgressTasks") {
89-
return await getInProgressTasks(args?.projectId || "");
89+
return await getInProgressTasks(args?.projectId || "", userId);
9090
} else if (fn === "getDoneTasks") {
91-
return await getDoneTasks(args?.projectId || "");
91+
return await getDoneTasks(args?.projectId || "", userId);
9292
} else if (fn === "getUnassignedTasks") {
93-
return await getUnassignedTasks(args?.projectId || "");
93+
return await getUnassignedTasks(args?.projectId || "", userId);
9494
} else if (fn === "getUrgentTasks") {
95-
return await getUrgentTasks(args?.projectId || "");
95+
return await getUrgentTasks(args?.projectId || "", userId);
9696
} else if (fn === "getLowTasks") {
97-
return await getLowTasks(args?.projectId || "");
97+
return await getLowTasks(args?.projectId || "", userId);
9898
} else if (fn === "getMediumTasks") {
99-
return await getMediumTasks(args?.projectId || "");
99+
return await getMediumTasks(args?.projectId || "", userId);
100100
} else {
101101
return { error: `Unknown tool: ${fn}` };
102102
}
@@ -223,7 +223,7 @@ export class AskService {
223223
} else {
224224
// Execute actual tool
225225
this.emitToolCall(socket, fn, args);
226-
toolResult = await this.execToolByName(fn, args);
226+
toolResult = await this.execToolByName(fn, args, userId ?? "");
227227
this.emitToolResult(socket, fn, toolResult);
228228

229229
// push tool result into conversation

backend/src/ai-agent/project.service.ts

Lines changed: 59 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,23 @@ const prisma = new PrismaClient();
99
* PROJECTS
1010
* =====================================
1111
*/
12-
export async function getProjects() {
12+
export async function getProjects(userId: string) {
1313
try {
1414
console.log("getProjects");
15+
const team = await prisma.teamMember.findMany({
16+
where: {
17+
userId,
18+
},
19+
});
20+
const workspaceIds = team.map((item: any) => item.workspaceId);
1521

1622
const results = await prisma.project.findMany({
17-
where: { isTrash: false },
23+
where: {
24+
isTrash: false,
25+
workspaceId: {
26+
in: workspaceIds,
27+
},
28+
},
1829
include: {
1930
tasks: {
2031
where: { isTrash: false },
@@ -79,9 +90,37 @@ function baseTaskInclude() {
7990
};
8091
}
8192

82-
function buildTaskWhere(projectId?: string, status?: string) {
93+
async function buildTaskWhere(
94+
userId: string,
95+
projectId?: string,
96+
status?: string
97+
) {
98+
const team = await prisma.teamMember.findMany({
99+
where: {
100+
userId,
101+
},
102+
});
103+
const workspaceIds = team.map((item: any) => item.workspaceId);
104+
const whereProject: any = {
105+
workspaceId: {
106+
in: workspaceIds,
107+
},
108+
};
109+
if (projectId) {
110+
whereProject.id = projectId;
111+
}
112+
113+
const projects = await prisma.project.findMany({
114+
where: whereProject,
115+
});
116+
117+
const projectIds = projects.map((item: any) => item.id);
118+
83119
const where: any = { isTrash: false };
84-
if (projectId) where.projectId = projectId;
120+
if (projectId)
121+
where.projectId = {
122+
in: projectIds,
123+
};
85124
if (status) where.status = status;
86125
return where;
87126
}
@@ -91,12 +130,12 @@ function buildTaskWhere(projectId?: string, status?: string) {
91130
* ALL TASKS
92131
* =====================================
93132
*/
94-
export async function getAllTasks(projectId = "") {
133+
export async function getAllTasks(projectId = "", userId: string) {
95134
try {
96135
console.log("getAllTasks");
97136

98137
const results = await prisma.task.findMany({
99-
where: buildTaskWhere(projectId),
138+
where: await buildTaskWhere(userId, projectId),
100139
include: baseTaskInclude(),
101140
orderBy: { createdAt: "desc" },
102141
});
@@ -113,12 +152,12 @@ export async function getAllTasks(projectId = "") {
113152
* TODO TASKS
114153
* =====================================
115154
*/
116-
export async function getTodoTasks(projectId = "") {
155+
export async function getTodoTasks(projectId = "", userId: string) {
117156
try {
118157
console.log("getTodoTasks");
119158

120159
const results = await prisma.task.findMany({
121-
where: buildTaskWhere(projectId, "todo"),
160+
where: await buildTaskWhere(userId, projectId, "todo"),
122161
include: baseTaskInclude(),
123162
orderBy: { createdAt: "desc" },
124163
});
@@ -135,12 +174,12 @@ export async function getTodoTasks(projectId = "") {
135174
* IN PROGRESS TASKS
136175
* =====================================
137176
*/
138-
export async function getInProgressTasks(projectId = "") {
177+
export async function getInProgressTasks(projectId = "", userId: string) {
139178
try {
140179
console.log("getInProgressTasks");
141180

142181
const results = await prisma.task.findMany({
143-
where: buildTaskWhere(projectId, "inprogress"),
182+
where: await buildTaskWhere(userId, projectId, "inprogress"),
144183
include: baseTaskInclude(),
145184
orderBy: { createdAt: "desc" },
146185
});
@@ -157,12 +196,12 @@ export async function getInProgressTasks(projectId = "") {
157196
* DONE TASKS
158197
* =====================================
159198
*/
160-
export async function getDoneTasks(projectId = "") {
199+
export async function getDoneTasks(projectId = "", userId: string) {
161200
try {
162201
console.log("getDoneTasks");
163202

164203
const results = await prisma.task.findMany({
165-
where: buildTaskWhere(projectId, "done"),
204+
where: await buildTaskWhere(userId, projectId, "done"),
166205
include: baseTaskInclude(),
167206
orderBy: { createdAt: "desc" },
168207
});
@@ -179,7 +218,7 @@ export async function getDoneTasks(projectId = "") {
179218
* MEMBERS
180219
* =====================================
181220
*/
182-
export async function getMembers() {
221+
export async function getMembers(userId: string) {
183222
try {
184223
console.log("getMembers");
185224

@@ -229,7 +268,10 @@ export async function getMembers() {
229268
}
230269
}
231270

232-
export async function getUnassignedTasks(projectId: string = "") {
271+
export async function getUnassignedTasks(
272+
projectId: string = "",
273+
userId: string
274+
) {
233275
try {
234276
console.log("getUnassignedTasks");
235277

@@ -253,7 +295,7 @@ export async function getUnassignedTasks(projectId: string = "") {
253295
}
254296
}
255297

256-
export async function getUrgentTasks(projectId: string = "") {
298+
export async function getUrgentTasks(projectId: string = "", userId: string) {
257299
try {
258300
console.log("getUrgentTasks");
259301

@@ -277,7 +319,7 @@ export async function getUrgentTasks(projectId: string = "") {
277319
}
278320
}
279321

280-
export async function getLowTasks(projectId: string = "") {
322+
export async function getLowTasks(projectId: string = "", userId: string) {
281323
try {
282324
console.log("getLowTasks");
283325

@@ -301,7 +343,7 @@ export async function getLowTasks(projectId: string = "") {
301343
}
302344
}
303345

304-
export async function getMediumTasks(projectId: string = "") {
346+
export async function getMediumTasks(projectId: string = "", userId: string) {
305347
try {
306348
console.log("getMediumTasks");
307349

frontend/src/components/KanbanBoard.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ function hslaStr(h: number, s = 75, l = 50, a = 1) {
1414
return `hsla(${h} ${s}% ${l}% / ${a})`;
1515
}
1616

17-
function formatDateShort(d) {
17+
function formatDateShort(d: any) {
1818
if (!d) return null;
1919
// expect ISO-like YYYY-MM-DD or any Date-parsable string
2020
const dt = new Date(d);
@@ -47,7 +47,7 @@ function parseDateOnlySafe(v?: string | null) {
4747
return new Date(dt.getFullYear(), dt.getMonth(), dt.getDate());
4848
}
4949

50-
function relativeInfo(d) {
50+
function relativeInfo(d: any) {
5151
if (!d) return null;
5252
const dt = new Date(d);
5353
const now = new Date();

frontend/src/components/Sidebar.tsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ function nameToHue(name = "") {
6969
return name.split("").reduce((acc, c) => acc + c.charCodeAt(0), 0) % 360;
7070
}
7171

72-
function handleKeyActivate(e, fn) {
72+
function handleKeyActivate(e: any, fn: any) {
7373
if (e.key === "Enter" || e.key === " ") {
7474
e.preventDefault();
7575
fn();
@@ -457,7 +457,7 @@ export default function Sidebar({
457457
</div>
458458
{/* projects list */}
459459
<div className="space-y-2 mb-4 mt-4">
460-
{projects.map((p, idx) => {
460+
{projects.map((p: any, idx: number) => {
461461
const palette = PROJECT_PALETTE[idx % PROJECT_PALETTE.length];
462462
const active = p.id === activeProjectId;
463463

@@ -516,7 +516,7 @@ export default function Sidebar({
516516
{p.name}
517517
</div>
518518
<div className="text-xs text-gray-500 dark:text-gray-400 truncate">
519-
{p.meta ?? ""}
519+
{p?.meta ?? ""}
520520
</div>
521521
</div>
522522
</div>
@@ -579,7 +579,7 @@ export default function Sidebar({
579579
</div>
580580
{/* team list */}
581581
<div className="space-y-2 mb-4">
582-
{team.map((member) => {
582+
{team.map((member: any) => {
583583
const hue = nameToHue(member.name ?? "user");
584584
// pilih lightness berdasarkan theme agar contrast baik
585585
const avatarBg = isDark
@@ -591,7 +591,7 @@ export default function Sidebar({
591591

592592
const initials = (member.name ?? "No Name")
593593
.split(" ")
594-
.map((n) => n[0] ?? "")
594+
.map((n: any) => n[0] ?? "")
595595
.slice(0, 2)
596596
.join("")
597597
.toUpperCase();
@@ -628,19 +628,19 @@ export default function Sidebar({
628628
)}
629629

630630
{/* small presence/status dot (optional) */}
631-
{member.status && (
631+
{member?.status && (
632632
<span
633633
className={`absolute -bottom-0.5 -right-0.5 w-3 h-3 rounded-full ring-2 ring-white dark:ring-black`}
634634
style={{
635635
background:
636-
member.status === "online"
636+
member?.status === "online"
637637
? "rgb(34 197 94)"
638-
: member.status === "away"
638+
: member?.status === "away"
639639
? "rgb(250 204 21)"
640640
: "rgb(148 163 184)",
641641
}}
642642
aria-hidden="true"
643-
title={member.status}
643+
title={member?.status}
644644
/>
645645
)}
646646
</div>

0 commit comments

Comments
 (0)