Skip to content

Commit d088fa0

Browse files
athens-serverhiderr
authored andcommitted
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 9ee4846 commit d088fa0

Some content is hidden

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

64 files changed

+1549
-770
lines changed

apps/gitness/src/pages-v2/user-management/stores/admin-list-store.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export const useAdminListUsersStore = create<IAdminListUsersStore>(set => ({
3737
user
3838
})
3939
},
40-
setGeteneratePassword: (generatePassword: boolean) => {
40+
setGeneratePassword: (generatePassword: boolean) => {
4141
set({
4242
generatePassword
4343
})

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

Lines changed: 70 additions & 120 deletions
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,31 @@ 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 { ICreateUserData, IUpdateUserData, 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'
2718

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

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-
}
22+
const { setUsers, setTotalPages, setPage, page, password } = useAdminListUsersStore()
6723

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

@@ -80,69 +46,60 @@ export const UserManagementPageContainer = () => {
8046
}
8147
}, [userData, setUsers, setTotalPages, headers])
8248

83-
useEffect(() => {
84-
setQueryPage(page)
85-
}, [queryPage, page, setPage])
86-
87-
const { mutate: updateUser, isLoading: isUpdatingUser } = useAdminUpdateUserMutation(
49+
const {
50+
mutateAsync: updateUser,
51+
isLoading: isUpdatingUser,
52+
error: updateUserError
53+
} = useAdminUpdateUserMutation(
8854
{},
8955
{
9056
onSuccess: () => {
91-
setEditUserDialogOpen(false)
9257
queryClient.invalidateQueries({ queryKey: ['adminListUsers'] })
93-
},
94-
onError: error => {
95-
console.error(error)
9658
}
9759
}
9860
)
9961

100-
const { mutate: deleteUser, isLoading: isDeletingUser } = useAdminDeleteUserMutation(
62+
const {
63+
mutateAsync: deleteUser,
64+
isLoading: isDeletingUser,
65+
error: deleteUserError
66+
} = useAdminDeleteUserMutation(
10167
{},
10268
{
10369
onSuccess: () => {
104-
setDeleteUserDialogOpen(false)
10570
queryClient.invalidateQueries({ queryKey: ['adminListUsers'] })
106-
},
107-
onError: error => {
108-
console.error(error)
10971
}
11072
}
11173
)
11274

113-
const { mutate: updateUserAdmin, isLoading: isUpdatingUserAdmin } = useUpdateUserAdminMutation(
75+
const {
76+
mutateAsync: updateUserAdmin,
77+
isLoading: isUpdatingUserAdmin,
78+
error: updateUserAdminError
79+
} = useUpdateUserAdminMutation(
11480
{},
11581
{
11682
onSuccess: () => {
117-
setAdminDialogOpen(false)
11883
queryClient.invalidateQueries({ queryKey: ['adminListUsers'] })
119-
},
120-
onError: error => {
121-
console.error(error)
12284
}
12385
}
12486
)
12587

12688
const {
127-
mutate: createUser,
89+
mutateAsync: createUser,
12890
isLoading: isCreatingUser,
12991
error: createUserError
13092
} = useAdminCreateUserMutation(
13193
{},
13294
{
13395
onSuccess: () => {
134-
setCreateUserDialogOpen(false)
135-
setResetPasswordDialogOpen(true)
13696
queryClient.invalidateQueries({ queryKey: ['adminListUsers'] })
137-
},
138-
onError: error => {
139-
console.error(error)
14097
}
14198
}
14299
)
143100

144-
const handleCreateUser = (data: { uid: string; email: string; display_name: string }) => {
145-
createUser({
101+
const handleCreateUser = (data: ICreateUserData) => {
102+
return createUser({
146103
body: {
147104
uid: data.uid,
148105
email: data.email,
@@ -152,8 +109,8 @@ export const UserManagementPageContainer = () => {
152109
})
153110
}
154111

155-
const handleUpdateUser = (data: { email: string; displayName: string; userID: string }) => {
156-
updateUser({
112+
const handleUpdateUser = (data: IUpdateUserData) => {
113+
return updateUser({
157114
user_uid: data.userID,
158115
body: {
159116
email: data.email,
@@ -163,13 +120,13 @@ export const UserManagementPageContainer = () => {
163120
}
164121

165122
const handleDeleteUser = (userUid: string) => {
166-
deleteUser({
123+
return deleteUser({
167124
user_uid: userUid
168125
})
169126
}
170127

171128
const handleUpdateUserAdmin = (userUid: string, isAdmin: boolean) => {
172-
updateUserAdmin({
129+
return updateUserAdmin({
173130
user_uid: userUid,
174131
body: {
175132
admin: isAdmin
@@ -178,55 +135,48 @@ export const UserManagementPageContainer = () => {
178135
}
179136

180137
const handleUpdatePassword = (userId: string) => {
181-
updateUser({
138+
return updateUser({
182139
user_uid: userId,
183140
body: {
184141
password: password
185142
}
186143
})
187144
}
188145

146+
const handlers = {
147+
handleUpdateUser,
148+
handleDeleteUser,
149+
handleUpdateUserAdmin,
150+
handleUpdatePassword,
151+
handleCreateUser
152+
}
153+
154+
const loadingStates = {
155+
isFetchingUsers: isFetching,
156+
isUpdatingUser,
157+
isDeletingUser,
158+
isUpdatingUserAdmin,
159+
isCreatingUser
160+
}
161+
162+
const errorStates = {
163+
fetchUsersError: error?.message?.toString() ?? '',
164+
updateUserError: updateUserError?.message?.toString() ?? '',
165+
deleteUserError: deleteUserError?.message?.toString() ?? '',
166+
updateUserAdminError: updateUserAdminError?.message?.toString() ?? '',
167+
createUserError: createUserError?.message?.toString() ?? ''
168+
}
169+
189170
return (
190171
<>
191172
<UserManagementPage
192173
useAdminListUsersStore={useAdminListUsersStore}
193174
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}
175+
handlers={handlers}
176+
loadingStates={loadingStates}
177+
errorStates={errorStates}
178+
searchQuery={query}
179+
setSearchQuery={setQuery}
230180
/>
231181
</>
232182
)

packages/ui/locales/en/views.json

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,8 @@
213213
"noWebhookExecutionsDescription": "Your webhook executions will appear here once they're completed. Trigger your webhook to see the results.",
214214
"noWebhooks": "No webhooks yet",
215215
"noWebhooksDescription": "Add or manage webhooks to automate tasks and connect external services to your project.",
216+
"noUsers": "No Users Found",
217+
"noUsersDescription": "There are no users in this scope. Click on the button below to start adding them.",
216218
"commit": "Commit",
217219
"noLabels": "No labels yet",
218220
"noLabelsDescription": "Use labels to organize, prioritize, and categorize tasks efficiently."
@@ -477,6 +479,87 @@
477479
"edit": "Edit webhook",
478480
"delete": "Delete webhook"
479481
},
482+
"userManagement": {
483+
"createUser": {
484+
"title": "Add a new user",
485+
"enterDisplayName": "Enter display name",
486+
"inviting": "Inviting...",
487+
"inviteNewUser": "Invite new user",
488+
"validation": {
489+
"userIdRequired": "Please provide a user ID",
490+
"invalidEmail": "Please enter a valid email address",
491+
"displayNameRequired": "Please provide a display name",
492+
"emailInvalid": "Please enter a valid email"
493+
}
494+
},
495+
"userId": "User ID",
496+
"userIdHint": "User ID cannot be changed once created",
497+
"enterName": "Enter name",
498+
"enterEmail": "Enter email address",
499+
"email": "Email",
500+
"displayName": "Display name",
501+
"cancel": "Cancel",
502+
"deleteUser": {
503+
"title": "Are you sure you want to delete {{name}}?",
504+
"message": "This will permanently delete the user \"{{name}}\" from the system.",
505+
"pending": "Deleting user...",
506+
"confirm": "Yes, delete user"
507+
},
508+
"editUser": {
509+
"title": "Update user",
510+
"message": "Update information for {{name}} and confirm changes.",
511+
"email": "Email",
512+
"pending": "Saving...",
513+
"save": "Save",
514+
"validation": {
515+
"invalidEmail": "Please enter a valid email address",
516+
"displayNameRequired": "Please provide a display name"
517+
}
518+
},
519+
"removeAdmin": {
520+
"title": "Are you sure you want to remove {{name}} as an admin?",
521+
"message": "This will remove the admin tag for \"{{name}}\".",
522+
"pending": "Removing admin...",
523+
"confirm": "Yes, remove admin"
524+
},
525+
"grantAdmin": {
526+
"title": "Are you sure you want to grant {{name}} admin privileges?",
527+
"message": "This will grant admin privileges to \"{{name}}\".",
528+
"pending": "Granting admin...",
529+
"confirm": "Yes, grant admin"
530+
},
531+
"resetPassword": {
532+
"title": "Are you sure you want to reset password for {{name}}?",
533+
"passwordGeneratedMessage": "Your password has been generated. Please make sure to copy and store your password somewhere safe, you won't be able to see it again.",
534+
"message": "A new password will be generated to assist {{name}} in resetting their current password.",
535+
"pending": "Resetting password...",
536+
"confirm": "Confirm"
537+
},
538+
"close": "Close",
539+
"newUserButton": "New user",
540+
"searchPlaceholder": "Search",
541+
"usersHeader": "Users",
542+
"tabs": {
543+
"active": "Active users",
544+
"inactive": "Pending users"
545+
},
546+
"usersList": {
547+
"user": "User",
548+
"email": "Email",
549+
"roleBinding": "Role binding"
550+
},
551+
"roles": {
552+
"admin": "Admin",
553+
"user": "User"
554+
},
555+
"actions": {
556+
"removeAdmin": "Remove admin",
557+
"setAsAdmin": "Set as admin",
558+
"resetPassword": "Reset password",
559+
"editUser": "Edit user",
560+
"deleteUser": "Delete user"
561+
}
562+
},
480563
"secrets": {
481564
"secretsTitle": "Secrets"
482565
}

0 commit comments

Comments
 (0)