Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc2f6e1c

Browse files
committed
feat: Add suspend user action
1 parentd139a16 commitc2f6e1c

File tree

5 files changed

+104
-16
lines changed

5 files changed

+104
-16
lines changed

‎site/src/api/index.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ export const getApiKey = async (): Promise<Types.APIKeyResponse> => {
7676
}
7777

7878
exportconstgetUsers=async():Promise<TypesGen.User[]>=>{
79-
constresponse=awaitaxios.get<TypesGen.User[]>("/api/v2/users?offset=0&limit=1000")
79+
constresponse=awaitaxios.get<TypesGen.User[]>("/api/v2/users?status=active")
8080
returnresponse.data
8181
}
8282

@@ -135,3 +135,8 @@ export const updateProfile = async (userId: string, data: Types.UpdateProfileReq
135135
constresponse=awaitaxios.put(`/api/v2/users/${userId}/profile`,data)
136136
returnresponse.data
137137
}
138+
139+
exportconstsuspendUser=async(userId:TypesGen.User["id"]):Promise<TypesGen.User>=>{
140+
constresponse=awaitaxios.put<TypesGen.User>(`/api/v2/users/${userId}/suspend`)
141+
returnresponse.data
142+
}

‎site/src/components/UsersTable/UsersTable.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ const columns: Column<UserResponse>[] = [
2727

2828
exportinterfaceUsersTableProps{
2929
users:UserResponse[]
30+
onSuspendUser:(user:UserResponse)=>void
3031
}
3132

32-
exportconstUsersTable:React.FC<UsersTableProps>=({ users})=>{
33+
exportconstUsersTable:React.FC<UsersTableProps>=({ users, onSuspendUser})=>{
3334
return(
3435
<Table
3536
columns={columns}
@@ -42,9 +43,7 @@ export const UsersTable: React.FC<UsersTableProps> = ({ users }) => {
4243
menuItems={[
4344
{
4445
label:Language.suspendMenuItem,
45-
onClick:()=>{
46-
// TO-DO: Add suspend action here
47-
},
46+
onClick:onSuspendUser,
4847
},
4948
]}
5049
/>

‎site/src/pages/UsersPage/UsersPage.tsx

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import{useActor}from"@xstate/react"
22
importReact,{useContext,useEffect}from"react"
33
import{useNavigate}from"react-router"
4+
import{ConfirmDialog}from"../../components/ConfirmDialog/ConfirmDialog"
45
import{ErrorSummary}from"../../components/ErrorSummary/ErrorSummary"
56
import{FullScreenLoader}from"../../components/Loader/FullScreenLoader"
67
import{XServiceContext}from"../../xServices/StateContext"
@@ -9,8 +10,9 @@ import { UsersPageView } from "./UsersPageView"
910
exportconstUsersPage:React.FC=()=>{
1011
constxServices=useContext(XServiceContext)
1112
const[usersState,usersSend]=useActor(xServices.usersXService)
12-
const{ users, getUsersError}=usersState.context
13+
const{ users, getUsersError, userIdToSuspend}=usersState.context
1314
constnavigate=useNavigate()
15+
constuserToBeSuspended=users?.find((u)=>u.id===userIdToSuspend)
1416

1517
/**
1618
* Fetch users on component mount
@@ -27,12 +29,37 @@ export const UsersPage: React.FC = () => {
2729
return<FullScreenLoader/>
2830
}else{
2931
return(
30-
<UsersPageView
31-
users={users}
32-
openUserCreationDialog={()=>{
33-
navigate("/users/create")
34-
}}
35-
/>
32+
<>
33+
<UsersPageView
34+
users={users}
35+
openUserCreationDialog={()=>{
36+
navigate("/users/create")
37+
}}
38+
onSuspendUser={(user)=>{
39+
usersSend({type:"SUSPEND_USER",userId:user.id})
40+
}}
41+
/>
42+
43+
<ConfirmDialog
44+
type="delete"
45+
hideCancel={false}
46+
open={usersState.matches("confirmUserSuspension")}
47+
confirmLoading={usersState.matches("suspendingUser")}
48+
title="Suspend user"
49+
confirmText="Suspend"
50+
onConfirm={()=>{
51+
usersSend("CONFIRM_USER_SUSPENSION")
52+
}}
53+
onClose={()=>{
54+
usersSend("CANCEL_USER_SUSPENSION")
55+
}}
56+
description={
57+
<>
58+
Do you want to suspend the user<strong>{userToBeSuspended?.username}</strong>?
59+
</>
60+
}
61+
/>
62+
</>
3663
)
3764
}
3865
}

‎site/src/pages/UsersPage/UsersPageView.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,17 @@ export const Language = {
1313
exportinterfaceUsersPageViewProps{
1414
users:UserResponse[]
1515
openUserCreationDialog:()=>void
16+
onSuspendUser:(user:UserResponse)=>void
1617
}
1718

18-
exportconstUsersPageView:React.FC<UsersPageViewProps>=({ users, openUserCreationDialog})=>{
19+
exportconstUsersPageView:React.FC<UsersPageViewProps>=({ users, openUserCreationDialog, onSuspendUser})=>{
1920
conststyles=useStyles()
2021

2122
return(
2223
<divclassName={styles.flexColumn}>
2324
<Headertitle={Language.pageTitle}action={{text:Language.newUserButton,onClick:openUserCreationDialog}}/>
2425
<Paperstyle={{maxWidth:"1380px",margin:"1em auto",width:"100%"}}>
25-
<UsersTableusers={users}/>
26+
<UsersTableusers={users}onSuspendUser={onSuspendUser}/>
2627
</Paper>
2728
</div>
2829
)

‎site/src/xServices/users/usersXService.ts

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,24 @@ import { displaySuccess } from "../../components/GlobalSnackbar/utils"
77

88
exportconstLanguage={
99
createUserSuccess:"Successfully created user.",
10+
suspendUserSuccess:"Successfully suspended the user.",
1011
}
1112

1213
exportinterfaceUsersContext{
1314
users?:TypesGen.User[]
15+
userIdToSuspend?:TypesGen.User["id"]
1416
getUsersError?:Error|unknown
1517
createUserError?:Error|unknown
1618
createUserFormErrors?:FieldErrors
19+
suspendUserError?:Error|unknown
1720
}
1821

19-
exporttypeUsersEvent={type:"GET_USERS"}|{type:"CREATE";user:Types.CreateUserRequest}
22+
exporttypeUsersEvent=
23+
|{type:"GET_USERS"}
24+
|{type:"CREATE";user:Types.CreateUserRequest}
25+
|{type:"SUSPEND_USER";userId:TypesGen.User["id"]}
26+
|{type:"CONFIRM_USER_SUSPENSION"}
27+
|{type:"CANCEL_USER_SUSPENSION"}
2028

2129
exportconstusersMachine=createMachine(
2230
{
@@ -31,18 +39,25 @@ export const usersMachine = createMachine(
3139
createUser:{
3240
data:TypesGen.User
3341
}
42+
suspendUser:{
43+
data:TypesGen.User
44+
}
3445
},
3546
},
3647
id:"usersState",
48+
initial:"idle",
3749
context:{
3850
users:[],
3951
},
40-
initial:"idle",
4152
states:{
4253
idle:{
4354
on:{
4455
GET_USERS:"gettingUsers",
4556
CREATE:"creatingUser",
57+
SUSPEND_USER:{
58+
target:"confirmUserSuspension",
59+
actions:["assignUserIdToSuspend"],
60+
},
4661
},
4762
},
4863
gettingUsers:{
@@ -86,6 +101,28 @@ export const usersMachine = createMachine(
86101
},
87102
tags:"loading",
88103
},
104+
confirmUserSuspension:{
105+
on:{
106+
CONFIRM_USER_SUSPENSION:"suspendingUser",
107+
CANCEL_USER_SUSPENSION:"idle",
108+
},
109+
},
110+
suspendingUser:{
111+
entry:"clearSuspendUserError",
112+
invoke:{
113+
src:"suspendUser",
114+
id:"suspendUser",
115+
onDone:{
116+
// Update users list
117+
target:"gettingUsers",
118+
actions:["displaySuspendSuccess"],
119+
},
120+
onError:{
121+
target:"error",
122+
actions:["assignSuspendUserError"],
123+
},
124+
},
125+
},
89126
error:{
90127
on:{
91128
GET_USERS:"gettingUsers",
@@ -97,6 +134,13 @@ export const usersMachine = createMachine(
97134
services:{
98135
getUsers:API.getUsers,
99136
createUser:(_,event)=>API.createUser(event.user),
137+
suspendUser:(context)=>{
138+
if(!context.userIdToSuspend){
139+
thrownewError("userIdToSuspend is undefined")
140+
}
141+
142+
returnAPI.suspendUser(context.userIdToSuspend)
143+
},
100144
},
101145
guards:{
102146
isFormError:(_,event)=>isApiError(event.data),
@@ -108,6 +152,9 @@ export const usersMachine = createMachine(
108152
assignGetUsersError:assign({
109153
getUsersError:(_,event)=>event.data,
110154
}),
155+
assignUserIdToSuspend:assign({
156+
userIdToSuspend:(_,event)=>event.userId,
157+
}),
111158
clearGetUsersError:assign((context:UsersContext)=>({
112159
...context,
113160
getUsersError:undefined,
@@ -119,13 +166,22 @@ export const usersMachine = createMachine(
119166
// the guard ensures it is ApiError
120167
createUserFormErrors:(_,event)=>mapApiErrorToFieldErrors((event.dataasApiError).response.data),
121168
}),
169+
assignSuspendUserError:assign({
170+
suspendUserError:(_,event)=>event.data,
171+
}),
122172
clearCreateUserError:assign((context:UsersContext)=>({
123173
...context,
124174
createUserError:undefined,
125175
})),
176+
clearSuspendUserError:assign({
177+
suspendUserError:(_)=>undefined,
178+
}),
126179
displayCreateUserSuccess:()=>{
127180
displaySuccess(Language.createUserSuccess)
128181
},
182+
displaySuspendSuccess:()=>{
183+
displaySuccess(Language.suspendUserSuccess)
184+
},
129185
},
130186
},
131187
)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp