Skip to content

Davidgu/bug automatic link user to project on creation - #66

Open
shaply wants to merge 14 commits into
mainfrom
davidgu/bug_automaticLinkUserToProjectOnCreation
Open

Davidgu/bug automatic link user to project on creation#66
shaply wants to merge 14 commits into
mainfrom
davidgu/bug_automaticLinkUserToProjectOnCreation

Conversation

@shaply

@shaply shaply commented Feb 7, 2026

Copy link
Copy Markdown
Contributor

closes #41

Reproduction Steps

  1. Navigate to per-project user page, e.g. http://localhost:3000/projects/0/users
  2. Attempt to create a new user. The user will show up in the user table for this project despite not belonging to any projects
  3. Refresh the user page: this user will now disappear (as it isn't assigned to this project)

Fix

When a user is created on a per-project page, they should automatically be assigned to that particular project page.

Screen.Recording.2026-02-07.at.5.03.25.PM.mov

@shaply
shaply requested a review from llam36 February 7, 2026 22:05
@netlify

netlify Bot commented Feb 7, 2026

Copy link
Copy Markdown

Deploy Preview for juno-dashboard failed. Why did it fail? →

Name Link
🔨 Latest commit f8abe9a
🔍 Latest deploy log https://app.netlify.com/projects/juno-dashboard/deploys/6987bcb549dbe100086010a4

@greptile-apps

greptile-apps Bot commented Feb 7, 2026

Copy link
Copy Markdown
Contributor

Greptile Overview

Greptile Summary

Fixes bug where users created on per-project pages weren't automatically linked to that project, causing them to disappear on page refresh.

Key Changes:

  • Added linkUserToProjectId action to link users by project ID instead of project name
  • Modified AddUserForm to accept projectIds prop and automatically link newly created users to specified projects
  • Updated project users page to pass originatingProjectId through component hierarchy
  • Improved breadcrumb display by caching project name in state

Issues Found:

  • Missing error handling when linkUserToProjectId fails - user will be created but not linked, reproducing the original bug
  • Form doesn't reset loading state in catch block, leaving UI stuck in loading state on errors
  • console.error statement left in production code (violates project guidelines)

Confidence Score: 3/5

  • This PR fixes the reported bug but introduces error handling gaps that could cause the same issue to reoccur
  • The implementation correctly identifies and addresses the root cause (missing automatic project linking), but missing error handling means if the link operation fails, users will experience the same bug. The loading state issue could also lead to poor UX. These are fixable issues that don't break existing functionality.
  • Pay close attention to src/components/forms/AddUserForm.tsx - error handling gaps need to be addressed before merge

Important Files Changed

Filename Overview
src/components/forms/AddUserForm.tsx Added automatic project linking when user is created from a project-specific page; missing error handling for failed link operations
src/lib/actions.ts New linkUserToProjectId function duplicates linkUserToProject logic with ID-based lookup instead of name-based
src/app/(dashboard)/projects/[projectId]/users/page.tsx Added state management for projectName and originatingProjectId to pass to child components for automatic linking

Sequence Diagram

sequenceDiagram
    participant User
    participant Page as ProjectUsersPage
    participant DataTable as UserDataTable
    participant Form as CreateUserForm
    participant Actions as actions.ts
    participant JunoAPI as Juno API

    User->>Page: Navigate to /projects/{projectId}/users
    Page->>Actions: getProjectUsers(projectId)
    Actions->>JunoAPI: Fetch project users
    JunoAPI-->>Page: Return users
    Page->>Page: Set originatingProjectId state
    Page->>DataTable: Pass originatingProjectId

    User->>DataTable: Click "Add User"
    DataTable->>Form: Open with projectIds=[originatingProjectId]
    
    User->>Form: Fill form & submit
    Form->>Actions: createUserAction({name, email, password})
    Actions->>JunoAPI: Create user
    JunoAPI-->>Form: Return new user
    
    alt projectIds provided
        loop For each projectId
            Form->>Actions: linkUserToProjectId({projectId, userId})
            Actions->>JunoAPI: Link user to project
            JunoAPI-->>Form: Return success/failure
        end
        Form->>Form: Update newUser.projects array
    end
    
    Form->>DataTable: onUserAction(user, "add")
    DataTable->>Page: Update users state
    Page->>User: Display updated user list
Loading

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile

Comment thread src/components/forms/AddUserForm.tsx Outdated
Comment on lines +65 to +87
if (projectIds) {
const projectPromises: Promise<{success:boolean}>[] = [];

for (const projectId of projectIds) {
projectPromises.push(
linkUserToProjectId({
projectId: projectId,
userId: String(result.user.id),
})
);
}
const linkResults = await Promise.all(projectPromises);
if (!newUser.projects) {
newUser.projects = [];
}
for (let i = 0; i < linkResults.length; i++) {
if (linkResults[i].success) {
newUser.projects.push(projectIds[i]);
}
}

newUser.projects = Array.from(new Set(newUser.projects));
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No error handling if linkUserToProjectId fails - user will be created but not linked to project, reproducing the original bug

Suggested change
if (projectIds) {
const projectPromises: Promise<{success:boolean}>[] = [];
for (const projectId of projectIds) {
projectPromises.push(
linkUserToProjectId({
projectId: projectId,
userId: String(result.user.id),
})
);
}
const linkResults = await Promise.all(projectPromises);
if (!newUser.projects) {
newUser.projects = [];
}
for (let i = 0; i < linkResults.length; i++) {
if (linkResults[i].success) {
newUser.projects.push(projectIds[i]);
}
}
newUser.projects = Array.from(new Set(newUser.projects));
}
if (projectIds) {
const projectPromises: Promise<{success:boolean}>[] = [];
for (const projectId of projectIds) {
projectPromises.push(
linkUserToProjectId({
projectId: projectId,
userId: String(result.user.id),
})
);
}
const linkResults = await Promise.all(projectPromises);
if (!newUser.projects) {
newUser.projects = [];
}
for (let i = 0; i < linkResults.length; i++) {
if (linkResults[i].success) {
newUser.projects.push(projectIds[i]);
} else {
console.error(`Failed to link user to project ${projectIds[i]}`);
toast.error("Warning", {
description: "User created but failed to link to project",
});
}
}
newUser.projects = Array.from(new Set(newUser.projects));
}

Comment thread src/lib/actions.ts
@greptile-apps

greptile-apps Bot commented Feb 7, 2026

Copy link
Copy Markdown
Contributor
Additional Comments (1)

src/components/forms/AddUserForm.tsx
Missing setLoading(false) in catch block - form remains in loading state if error occurs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Fall 2025] Creating a user under a per-project page should auto assign user to role

1 participant