Skip to content

Commit 67860e2

Browse files
committed
Fix edit user roles and and submit button and add better styling
1 parent 5c17066 commit 67860e2

File tree

9 files changed

+130
-26
lines changed

9 files changed

+130
-26
lines changed

backend/circles/handler.go

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,17 @@ func GetInviteUsersHandler(w http.ResponseWriter, r *http.Request) {
8585
json.NewEncoder(w).Encode(users)
8686
}
8787

88+
func EditUsersHandler(w http.ResponseWriter, r *http.Request) {
89+
switch r.Method {
90+
case "POST":
91+
GetEditUsersHandler(w, r)
92+
case "PUT":
93+
UpdateEditUsersHandler(w, r)
94+
default:
95+
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
96+
}
97+
}
98+
8899
func GetEditUsersHandler(w http.ResponseWriter, r *http.Request) {
89100
userID := r.Context().Value(middleware.UserIDKey).(string)
90101
type Circle struct {
@@ -98,19 +109,48 @@ func GetEditUsersHandler(w http.ResponseWriter, r *http.Request) {
98109
json.NewEncoder(w).Encode("HTTP 400 bad request")
99110
return
100111
}
101-
fmt.Println("Circle ID EDIT: " + circle.ID + " USER ID: " + userID)
102-
users, err := postgres.GetInviteUsersInCircle(userID, circle.ID)
112+
users, err := postgres.GetExistingUsersInCircle(userID, circle.ID)
103113
if err != nil {
104114
fmt.Printf("Failed to get users in circle\n")
105115
w.WriteHeader(http.StatusInternalServerError)
106116
json.NewEncoder(w).Encode("Failed to get users in circle")
107117
return
108118
}
109-
fmt.Printf("Users in circle: %v\n", users)
110119
w.WriteHeader(http.StatusOK)
111120
json.NewEncoder(w).Encode(users)
112121
}
113122

123+
func UpdateEditUsersHandler(w http.ResponseWriter, r *http.Request) {
124+
userID := r.Context().Value(middleware.UserIDKey).(string)
125+
type EditData struct {
126+
ID string `json:"circle_id"`
127+
UserID []struct {
128+
ID string `json:"id"`
129+
Role string `json:"role"`
130+
} `json:"users"`
131+
}
132+
var circle EditData
133+
err := json.NewDecoder(r.Body).Decode(&circle)
134+
if err != nil {
135+
fmt.Printf("HTTP 400 bad request\n")
136+
w.WriteHeader(http.StatusBadRequest)
137+
json.NewEncoder(w).Encode("HTTP 400 bad request")
138+
return
139+
}
140+
for _, user := range circle.UserID {
141+
fmt.Println("Circle ID EDIT: " + circle.ID + " USER ID: " + userID + " EDIT USER ID: " + user.ID + " ROLE: " + user.Role)
142+
err = postgres.EditRoleInCircle(circle.ID, user.ID, user.Role)
143+
}
144+
if err != nil {
145+
fmt.Printf("Failed to edit users in circle\n")
146+
w.WriteHeader(http.StatusInternalServerError)
147+
json.NewEncoder(w).Encode("Failed to edit users in circle")
148+
return
149+
}
150+
w.WriteHeader(http.StatusOK)
151+
json.NewEncoder(w).Encode("Users edited in circle")
152+
}
153+
114154
func CreateCircleHandler(w http.ResponseWriter, r *http.Request, hub *websockets.Hub) {
115155
var createCircleData models.CreateCircleData
116156
err := json.NewDecoder(r.Body).Decode(&createCircleData)

backend/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ func main() {
8787
mux.Handle("/api/circles/edit", middleware.AddCorsHeaders(
8888
middleware.AuthMiddleware(
8989
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
90-
circles.GetEditUsersHandler(w, r)
90+
circles.EditUsersHandler(w, r)
9191
}),
9292
),
9393
))

backend/middleware/middleware.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ func AddCorsHeaders(handler http.HandlerFunc) http.HandlerFunc {
1717
w.Header().Set("Access-Control-Allow-Origin", "https://leo7deng.github.io")
1818
}
1919
w.Header().Set("Access-Control-Allow-Credentials", "true")
20-
w.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, DELETE, GET")
20+
w.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, DELETE, GET, PUT")
2121
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
2222
// Handle preflight OPTIONS requests
2323
if r.Method == "OPTIONS" {

backend/models/user.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ type User struct {
1010
}
1111

1212
type UserRole struct {
13-
User User
14-
Role string
13+
UserID string `json:"id"`
14+
Username string `json:"username"`
15+
Role string `json:"role"`
1516
}
1617

1718
type RegisterData struct {

backend/postgres/circles_repo.go

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ package postgres
33
import (
44
"context"
55
"fmt"
6-
"github.com/Leo7Deng/ChatApp/models"
76
"os"
87
"time"
8+
9+
"github.com/Leo7Deng/ChatApp/models"
910
)
1011

1112
func GetUserCircles(userID string) ([]models.Circle, error) {
@@ -221,17 +222,76 @@ func GetInviteUsersInCircle(userID string, circleID string) ([]models.User, erro
221222
return users, nil
222223
}
223224

224-
func GetExistingUsersInCircle(circleID string) ([]models.UserRole, error) {
225+
func EditRoleInCircle(circleID string, targetUserID string, role string) error {
226+
ctx := context.Background()
227+
conn, err := pool.Acquire(ctx)
228+
if err != nil {
229+
fmt.Fprintf(os.Stderr, "Unable to acquire a connection from the pool: %v\n", err)
230+
}
231+
defer conn.Release()
232+
233+
err = conn.QueryRow(
234+
ctx,
235+
`
236+
UPDATE users_circles
237+
SET role = $1
238+
WHERE user_id = $2 AND circle_id = $3
239+
RETURNING role;
240+
`,
241+
role,
242+
targetUserID,
243+
circleID,
244+
).Scan(&role)
245+
if err != nil {
246+
fmt.Fprintf(os.Stderr, "Unable to query PSQL: %v\n", err)
247+
return err
248+
}
249+
fmt.Printf("Role updated: %v\n", role)
250+
return nil
251+
}
252+
253+
254+
func GetRoleInCircle(userID string, circleID string) (string, error) {
255+
var role string
256+
err := pool.QueryRow(
257+
context.Background(),
258+
`
259+
SELECT role
260+
FROM users_circles
261+
WHERE user_id = $1 AND circle_id = $2;
262+
`,
263+
userID,
264+
circleID,
265+
).Scan(&role)
266+
if err != nil {
267+
fmt.Fprintf(os.Stderr, "Unable to query PSQL: %v\n", err)
268+
return "", err
269+
}
270+
return role, nil
271+
}
272+
273+
func GetExistingUsersInCircle(userID string, circleID string) ([]models.UserRole, error) {
274+
requestingRole, err := GetRoleInCircle(userID, circleID)
275+
if err != nil {
276+
fmt.Fprintf(os.Stderr, "Unable to get role in circle: %v\n", err)
277+
return nil, err
278+
}
279+
if requestingRole != "admin" {
280+
fmt.Fprintf(os.Stderr, "User is not admin of circle\n")
281+
return nil, fmt.Errorf("permission error")
282+
}
283+
225284
var users []models.UserRole
226285
rows, err := pool.Query(
227286
context.Background(),
228287
`
229288
SELECT u.id, u.username, uc.role
230289
FROM users u
231290
INNER JOIN users_circles uc ON u.id = uc.user_id
232-
WHERE uc.circle_id = $1
291+
WHERE u.id != $1 AND uc.circle_id = $2
233292
ORDER BY u.username ASC;
234293
`,
294+
userID,
235295
circleID,
236296
)
237297
if err != nil {
@@ -242,7 +302,7 @@ func GetExistingUsersInCircle(circleID string) ([]models.UserRole, error) {
242302

243303
for rows.Next() {
244304
var user models.UserRole
245-
err = rows.Scan(&user.User.ID, &user.User.Username, &user.Role)
305+
err = rows.Scan(&user.UserID, &user.Username, &user.Role)
246306
if err != nil {
247307
fmt.Fprintf(os.Stderr, "Unable to scan row: %v\n", err)
248308
return nil, err

frontend/app/components/Dashboard.css

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,13 @@
1919
}
2020

2121
.modal {
22-
width: 35vw;
22+
width: 24rem;
2323
max-height: 50vh;
2424
background: white;
2525
border-radius: 10px;
26+
padding: 2rem;
27+
padding-top: 1rem;
28+
padding-bottom: 1rem;
2629
}
2730

2831
.chat-container {

frontend/app/components/EditModal.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,9 @@
4444
width: 5rem;
4545
padding: 0.25rem;
4646
padding-left: 0.5rem;
47+
}
48+
49+
.username {
50+
width: 5rem;
51+
overflow: scroll;
4752
}

frontend/app/components/EditModal.tsx

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,10 @@ function EditModal({ isOpen, setOpen, circleId }: InviteModalProps) {
1818
const [users, setUsers] = useState<EditUser[]>([]);
1919

2020
useEffect(() => {
21-
async function fetchInviteUsers() {
21+
async function fetchEditUsers() {
2222
const token = await getAccessToken();
2323
const headers = {
2424
'Authorization': `Bearer ${token}`,
25-
'Content-Type': 'application/json'
2625
};
2726
const body = {
2827
circle_id: circleId,
@@ -38,11 +37,10 @@ function EditModal({ isOpen, setOpen, circleId }: InviteModalProps) {
3837
console.log("Error:", data);
3938
} else {
4039
console.log("Data:", data);
41-
// Initialize each user with a default role of "member"
4240
const mappedUsers = data.map((user: any) => ({
4341
id: user.id,
4442
username: user.username,
45-
role: 'member'
43+
role: user.role,
4644
}));
4745
setUsers(mappedUsers);
4846
}
@@ -51,10 +49,9 @@ function EditModal({ isOpen, setOpen, circleId }: InviteModalProps) {
5149
console.log(error);
5250
});
5351
}
54-
fetchInviteUsers();
52+
fetchEditUsers();
5553
}, [circleId, getAccessToken]);
5654

57-
// Update the role for the specified user
5855
const handleRoleChange = (userId: string, newRole: string) => {
5956
setUsers(prevUsers =>
6057
prevUsers.map(user =>
@@ -68,16 +65,14 @@ function EditModal({ isOpen, setOpen, circleId }: InviteModalProps) {
6865
const token = await getAccessToken();
6966
const headers = {
7067
'Authorization': `Bearer ${token}`,
71-
'Content-Type': 'application/json'
7268
};
73-
// Send each user's id and the chosen role
7469
const body = {
7570
circle_id: circleId,
7671
users: users.map(user => ({ id: user.id, role: user.role })),
7772
};
7873
console.log(body);
79-
fetch('http://localhost:8000/api/circles/edit/add', {
80-
method: 'POST',
74+
fetch('http://localhost:8000/api/circles/edit', {
75+
method: 'PUT',
8176
headers: headers,
8277
body: JSON.stringify(body),
8378
})
@@ -98,7 +93,7 @@ function EditModal({ isOpen, setOpen, circleId }: InviteModalProps) {
9893
if (!isOpen) return null;
9994

10095
return (
101-
<div className="mx-auto max-w-screen-xl px-4 py-2 sm:px-6 lg:px-8 relative z-10 focus:outline-none">
96+
<div className="mx-auto max-w-screen-xl relative z-10 focus:outline-none">
10297
<form action="#" className="mx-auto mb-4 mt-6 max-w-md space-y-4" onSubmit={handleSubmit}>
10398
<div>
10499
<div className="search w-full relative rounded-md">
@@ -120,12 +115,12 @@ function EditModal({ isOpen, setOpen, circleId }: InviteModalProps) {
120115
<ul>
121116
{users.length === 0 && (
122117
<li className="user-item flex items-center gap-2">
123-
<p className="font-medium text-sm text-gray-500">No users found</p>
118+
<p className="font-medium text-sm text-gray-500">You don't have admin access to this circle</p>
124119
</li>
125120
)}
126121
{users.length != 0 && users.map(user => (
127122
<li key={user.id} className="user-item flex items-center gap-2">
128-
<p className="font-medium text-sm text-gray-500">{user.username}</p>
123+
<p className="font-medium text-sm text-gray-500 username">{user.username}</p>
129124
<select
130125
value={user.role}
131126
onChange={(e) => handleRoleChange(user.id, e.target.value)}

frontend/app/components/InviteModal.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ function InviteModal({ isOpen, setOpen, circleId }: InviteModalProps) {
101101
if (!isOpen) return null;
102102

103103
return (
104-
<div className="mx-auto max-w-screen-xl px-4 py-2 sm:px-6 lg:px-8 relative z-10 focus:outline-none">
104+
<div className="mx-auto max-w-screen-xl relative z-10 focus:outline-none">
105105
<form action="#" className="mx-auto mb-4 mt-6 max-w-md space-y-4" onSubmit={handleSubmit}>
106106
<div>
107107
<div className="search w-full relative rounded-md">

0 commit comments

Comments
 (0)