Skip to content

Commit 3bf1fd2

Browse files
committed
refactor: rename dialog hooks and reorganize file structure
- Rename dialog hooks to use kebab-case filenames - Remove nested index files for dialog hooks - Simplify export structure for dialog hooks fix: standardize dialog content width and error text classes - Remove `w-full` class from Dialog.Content components - Reorder error text classes for consistency across user management dialogs fix: adjust user dialog UI details - Modify info icon positioning in create user dialog - Reorder error text classes for consistency - Use useEffect to reset form values in edit user dialog refactor: remove form components from user management dialogs - Inline dialog form logic directly into dialog components - Remove separate form components for create, edit, delete, reset password, and remove admin dialogs - Simplify dialog structure by consolidating form and dialog logic - Update locales to support new dialog translations fixes dialogs width decapitalize fix cancels buttons refactor: standardize import paths in user management components - Replace relative imports with absolute paths using @/ prefix - Maintain relative imports in index.ts files - Update import paths in dialog components and providers added locales fixes added empty state added error state added skeleton and nodata refactor dialogs added state provider caption props added no search results state paddings refactor remove unnecesary props drilling remove classes sorting refactor remove unnecessary props drilling fix-margins first versions of modals replace text with span change eslint rule due to conflict between prettier and eslint, prettier already sort classnames Adds promisifyMutation helper to simplify mutation handling Updates user management handlers to use the helper Adds proper typing for handlers using IDataHandlers interface Removes duplicate type definitions added search query make pagination using usePaginationQueryStateWithStore fixes code-review: remove onErrors callbacks fix enter fix pathes refactoring dialogs refactoring types commit: refactor: use store provider for user management hooks This commit refactors the user management page to use a centralized store provider by: Creating UserManagementStoreProvider to manage shared hooks Removing hook props drilling through components Accessing hooks via useUserManagementStore hook in child components Splitting UserManagementPage into container and content components This change improves code organization and reduces prop drilling while maintaining existing functionality. commit: refactor: move dialog context to providers directory This commit reorganizes the dialog-related code by: Moving DialogsProvider from context/ to providers/ directory Updating import paths across components to use the new location 3. Removing unused context files and types Consolidating dialog-related code for better maintainability This is a structural change that improves code organization while maintaining existing functionality. remove redundant index from dialog commit: refactor: migrate dialog state management to UI layer The commit refactors the user management dialog state handling by: Moving dialog state management from container to UI layer using DialogsProvider Converting mutation handlers to return Promises for proper async handling Removing redundant dialog state management code from container Consolidating error and loading states into dedicated objects Moving EActiveTab enum to UI package for better organization This change improves separation of concerns by keeping UI state management in the UI layer while maintaining the same functionality. refactor: reorganize validation schemas and types - Move Zod schemas to dedicated schema files - Update type definitions to use schema inference - Fix import paths to use absolute imports - Remove duplicate schema definitions from components - Centralize types in dedicated type files refactor(user-management): reorganize dialogs structure - Move all dialogs to dedicated folders with proper structure - Add types and index files for each dialog - Update imports and exports - Add new translations for empty state - Improve code organization in UserManagementPage first version of filters and sorting remove unnecessary fragment added tabs fixes after design review
1 parent ae80ed0 commit 3bf1fd2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+1523
-793
lines changed

.eslintrc.json

-2
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,8 @@
4343
"import/no-unresolved": "off",
4444
"react/prop-types": "off",
4545
"react/react-in-jsx-scope": "off",
46-
4746
"jsx-a11y/click-events-have-key-events": "warn",
4847
"jsx-a11y/no-autofocus": "off",
49-
5048
"@typescript-eslint/no-unused-vars": [
5149
"error",
5250
{

apps/gitness/src/pages-v2/user-management/user-management-container.tsx

+73-122
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useEffect, useState } from 'react'
1+
import { useEffect } from 'react'
22

33
import { useQueryClient } from '@tanstack/react-query'
44

@@ -9,65 +9,32 @@ import {
99
useAdminUpdateUserMutation,
1010
useUpdateUserAdminMutation
1111
} from '@harnessio/code-service-client'
12-
import {
13-
AdminDialog,
14-
CreateUserDialog,
15-
DeleteUserDialog,
16-
DialogLabels,
17-
EditUserDialog,
18-
ResetPasswordDialog,
19-
UserManagementPage,
20-
UsersProps
21-
} from '@harnessio/ui/views'
22-
23-
import { parseAsInteger, useQueryState } from '../../framework/hooks/useQueryState'
12+
import { IDataHandlers, UserManagementPage } from '@harnessio/ui/views'
13+
14+
import { useQueryState } from '../../framework/hooks/useQueryState'
15+
import usePaginationQueryStateWithStore from '../../hooks/use-pagination-query-state-with-store'
2416
import { useTranslationStore } from '../../i18n/stores/i18n-store'
25-
import { generateAlphaNumericHash } from '../pull-request/pull-request-utils'
2617
import { useAdminListUsersStore } from './stores/admin-list-store'
18+
import { promisifyMutation } from './utils/promisify-mutation'
2719

2820
export const UserManagementPageContainer = () => {
29-
const [queryPage, setQueryPage] = useQueryState('page', parseAsInteger.withDefault(1))
30-
const { setUsers, setTotalPages, setPage, page, password, setUser, setPassword, setGeteneratePassword } =
31-
useAdminListUsersStore()
3221
const queryClient = useQueryClient()
3322

34-
const [isDeleteUserDialogOpen, setDeleteUserDialogOpen] = useState(false)
35-
const [isEditUserDialogOpen, setEditUserDialogOpen] = useState(false)
36-
const [isAdminDialogOpen, setAdminDialogOpen] = useState(false)
37-
const [isResetPasswordDialogOpen, setResetPasswordDialogOpen] = useState(false)
38-
const [isCreateUserDialogOpen, setCreateUserDialogOpen] = useState(false)
39-
40-
const handleDialogOpen = (user: UsersProps | null, dialogTypeLabel: string) => {
41-
if (user) setUser(user)
42-
43-
switch (dialogTypeLabel) {
44-
case DialogLabels.DELETE_USER:
45-
setDeleteUserDialogOpen(true)
46-
break
47-
case DialogLabels.EDIT_USER:
48-
setEditUserDialogOpen(true)
49-
break
50-
case DialogLabels.TOGGLE_ADMIN:
51-
setAdminDialogOpen(true)
52-
break
53-
case DialogLabels.RESET_PASSWORD:
54-
setGeteneratePassword(false)
55-
setPassword(generateAlphaNumericHash(10))
56-
setResetPasswordDialogOpen(true)
57-
break
58-
case DialogLabels.CREATE_USER:
59-
setPassword(generateAlphaNumericHash(10))
60-
setCreateUserDialogOpen(true)
61-
setGeteneratePassword(true)
62-
break
63-
default:
64-
break
65-
}
66-
}
23+
const { setUsers, setTotalPages, setPage, page, password } = useAdminListUsersStore()
6724

68-
const { data: { body: userData, headers } = {} } = useAdminListUsersQuery({
25+
const [query, setQuery] = useQueryState('query')
26+
const { queryPage } = usePaginationQueryStateWithStore({ page, setPage })
27+
28+
const {
29+
isFetching,
30+
error,
31+
data: { body: userData, headers } = {}
32+
} = useAdminListUsersQuery({
6933
queryParams: {
70-
page: queryPage
34+
page: queryPage,
35+
// TODO: add search functionality by query parameter
36+
//@ts-expect-error - query is not typed
37+
query: query ?? ''
7138
}
7239
})
7340

@@ -80,45 +47,41 @@ export const UserManagementPageContainer = () => {
8047
}
8148
}, [userData, setUsers, setTotalPages, headers])
8249

83-
useEffect(() => {
84-
setQueryPage(page)
85-
}, [queryPage, page, setPage])
86-
87-
const { mutate: updateUser, isLoading: isUpdatingUser } = useAdminUpdateUserMutation(
50+
const {
51+
mutate: updateUser,
52+
isLoading: isUpdatingUser,
53+
error: updateUserError
54+
} = useAdminUpdateUserMutation(
8855
{},
8956
{
9057
onSuccess: () => {
91-
setEditUserDialogOpen(false)
9258
queryClient.invalidateQueries({ queryKey: ['adminListUsers'] })
93-
},
94-
onError: error => {
95-
console.error(error)
9659
}
9760
}
9861
)
9962

100-
const { mutate: deleteUser, isLoading: isDeletingUser } = useAdminDeleteUserMutation(
63+
const {
64+
mutate: deleteUser,
65+
isLoading: isDeletingUser,
66+
error: deleteUserError
67+
} = useAdminDeleteUserMutation(
10168
{},
10269
{
10370
onSuccess: () => {
104-
setDeleteUserDialogOpen(false)
10571
queryClient.invalidateQueries({ queryKey: ['adminListUsers'] })
106-
},
107-
onError: error => {
108-
console.error(error)
10972
}
11073
}
11174
)
11275

113-
const { mutate: updateUserAdmin, isLoading: isUpdatingUserAdmin } = useUpdateUserAdminMutation(
76+
const {
77+
mutate: updateUserAdmin,
78+
isLoading: isUpdatingUserAdmin,
79+
error: updateUserAdminError
80+
} = useUpdateUserAdminMutation(
11481
{},
11582
{
11683
onSuccess: () => {
117-
setAdminDialogOpen(false)
11884
queryClient.invalidateQueries({ queryKey: ['adminListUsers'] })
119-
},
120-
onError: error => {
121-
console.error(error)
12285
}
12386
}
12487
)
@@ -131,18 +94,13 @@ export const UserManagementPageContainer = () => {
13194
{},
13295
{
13396
onSuccess: () => {
134-
setCreateUserDialogOpen(false)
135-
setResetPasswordDialogOpen(true)
13697
queryClient.invalidateQueries({ queryKey: ['adminListUsers'] })
137-
},
138-
onError: error => {
139-
console.error(error)
14098
}
14199
}
142100
)
143101

144-
const handleCreateUser = (data: { uid: string; email: string; display_name: string }) => {
145-
createUser({
102+
const handleCreateUser: IDataHandlers['handleCreateUser'] = data => {
103+
return promisifyMutation(createUser, {
146104
body: {
147105
uid: data.uid,
148106
email: data.email,
@@ -152,8 +110,8 @@ export const UserManagementPageContainer = () => {
152110
})
153111
}
154112

155-
const handleUpdateUser = (data: { email: string; displayName: string; userID: string }) => {
156-
updateUser({
113+
const handleUpdateUser: IDataHandlers['handleUpdateUser'] = data => {
114+
return promisifyMutation(updateUser, {
157115
user_uid: data.userID,
158116
body: {
159117
email: data.email,
@@ -162,71 +120,64 @@ export const UserManagementPageContainer = () => {
162120
})
163121
}
164122

165-
const handleDeleteUser = (userUid: string) => {
166-
deleteUser({
123+
const handleDeleteUser: IDataHandlers['handleDeleteUser'] = userUid => {
124+
return promisifyMutation(deleteUser, {
167125
user_uid: userUid
168126
})
169127
}
170128

171-
const handleUpdateUserAdmin = (userUid: string, isAdmin: boolean) => {
172-
updateUserAdmin({
129+
const handleUpdateUserAdmin: IDataHandlers['handleUpdateUserAdmin'] = (userUid, isAdmin) => {
130+
return promisifyMutation(updateUserAdmin, {
173131
user_uid: userUid,
174132
body: {
175133
admin: isAdmin
176134
}
177135
})
178136
}
179137

180-
const handleUpdatePassword = (userId: string) => {
181-
updateUser({
138+
const handleUpdatePassword: IDataHandlers['handleUpdatePassword'] = userId => {
139+
return promisifyMutation(updateUser, {
182140
user_uid: userId,
183141
body: {
184142
password: password
185143
}
186144
})
187145
}
188146

147+
const handlers = {
148+
handleUpdateUser,
149+
handleDeleteUser,
150+
handleUpdateUserAdmin,
151+
handleUpdatePassword,
152+
handleCreateUser
153+
}
154+
155+
const loadingStates = {
156+
isFetchingUsers: isFetching,
157+
isUpdatingUser,
158+
isDeletingUser,
159+
isUpdatingUserAdmin,
160+
isCreatingUser
161+
}
162+
163+
const errorStates = {
164+
fetchUsersError: error?.message?.toString() ?? '',
165+
updateUserError: updateUserError?.message?.toString() ?? '',
166+
deleteUserError: deleteUserError?.message?.toString() ?? '',
167+
updateUserAdminError: updateUserAdminError?.message?.toString() ?? '',
168+
createUserError: createUserError?.message?.toString() ?? ''
169+
}
170+
189171
return (
190172
<>
191173
<UserManagementPage
192174
useAdminListUsersStore={useAdminListUsersStore}
193175
useTranslationStore={useTranslationStore}
194-
handleDialogOpen={handleDialogOpen}
195-
/>
196-
197-
<DeleteUserDialog
198-
open={isDeleteUserDialogOpen}
199-
useAdminListUsersStore={useAdminListUsersStore}
200-
onClose={() => setDeleteUserDialogOpen(false)}
201-
isDeleting={isDeletingUser}
202-
handleDeleteUser={handleDeleteUser}
203-
/>
204-
<EditUserDialog
205-
open={isEditUserDialogOpen}
206-
useAdminListUsersStore={useAdminListUsersStore}
207-
isSubmitting={isUpdatingUser}
208-
onClose={() => setEditUserDialogOpen(false)}
209-
handleUpdateUser={handleUpdateUser}
210-
/>
211-
<AdminDialog
212-
open={isAdminDialogOpen}
213-
useAdminListUsersStore={useAdminListUsersStore}
214-
onClose={() => setAdminDialogOpen(false)}
215-
isLoading={isUpdatingUserAdmin}
216-
updateUserAdmin={handleUpdateUserAdmin}
217-
/>
218-
<ResetPasswordDialog
219-
open={isResetPasswordDialogOpen}
220-
useAdminListUsersStore={useAdminListUsersStore}
221-
onClose={() => setResetPasswordDialogOpen(false)}
222-
handleUpdatePassword={handleUpdatePassword}
223-
/>
224-
<CreateUserDialog
225-
open={isCreateUserDialogOpen}
226-
onClose={() => setCreateUserDialogOpen(false)}
227-
isLoading={isCreatingUser}
228-
apiError={createUserError?.message?.toString() ?? ''}
229-
handleCreateUser={handleCreateUser}
176+
handlers={handlers}
177+
loadingStates={loadingStates}
178+
errorStates={errorStates}
179+
searchQuery={query}
180+
setSearchQuery={setQuery}
230181
/>
231182
</>
232183
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export type MutationFn<T> = (params: T, options: { onSuccess: () => void; onError: (error: any) => void }) => void
2+
3+
export const promisifyMutation = <T>(mutation: MutationFn<T>, params: T): Promise<void> => {
4+
return new Promise<void>((resolve, reject) => {
5+
mutation(params, {
6+
onSuccess: () => resolve(),
7+
onError: error => reject(error)
8+
})
9+
})
10+
}

0 commit comments

Comments
 (0)