Skip to content

Commit 2a904df

Browse files
refactor: style improvements for the User Management page (#1131)
* 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 * fix: minor changes * chore: add small adjustments * fix: prettier --------- Co-authored-by: Timofei Ponomarev <[email protected]>
1 parent 47b1265 commit 2a904df

Some content is hidden

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

71 files changed

+1540
-812
lines changed

apps/gitness/src/pages-v2/pull-request/__tests__/pull-request-utils.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { TypesCodeOwnerEvaluationEntry, TypesOwnerEvaluation, TypesPrincipalInfo } from '@harnessio/code-service-client'
2+
import { generateAlphaNumericHash } from '@harnessio/ui/utils'
23

34
import { PullReqReviewDecision, TypeCheckData } from '../../../pages/pull-request/types/types'
45
import {
@@ -11,7 +12,6 @@ import {
1112
extractSpecificViolations,
1213
findChangeReqDecisions,
1314
findWaitingDecisions,
14-
generateAlphaNumericHash,
1515
generateStatusSummary,
1616
normalizeGitFilePath,
1717
processReviewDecision

apps/gitness/src/pages-v2/pull-request/hooks/usePRCommonInteractions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import {
88
// repoArtifactUpload,
99
TypesPullReqActivity
1010
} from '@harnessio/code-service-client'
11+
import { generateAlphaNumericHash } from '@harnessio/ui/utils'
1112
import { CommitSuggestion } from '@harnessio/ui/views'
12-
import { generateAlphaNumericHash } from '@harnessio/views'
1313

1414
import { useAPIPath } from '../../../hooks/useAPIPath'
1515
import { getErrorMessage } from '../pull-request-utils'

apps/gitness/src/pages-v2/pull-request/pull-request-utils.ts

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -478,18 +478,6 @@ export enum ViewStyle {
478478
LINE_BY_LINE = 'line-by-line'
479479
}
480480

481-
export function generateAlphaNumericHash(length: number) {
482-
let result = ''
483-
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
484-
const charactersLength = characters.length
485-
486-
for (let i = 0; i < length; i++) {
487-
result += characters.charAt(Math.floor(Math.random() * charactersLength))
488-
}
489-
490-
return result
491-
}
492-
493481
export const getErrorMessage = (error: unknown): string | undefined =>
494482
error ? (get(error, 'data.error', get(error, 'data.message', get(error, 'message', error))) as string) : undefined
495483

apps/gitness/src/pages-v2/repo/repo-summary.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
useSummaryQuery,
1717
useUpdateRepositoryMutation
1818
} from '@harnessio/code-service-client'
19+
import { generateAlphaNumericHash } from '@harnessio/ui/utils'
1920
import {
2021
BranchSelectorListItem,
2122
BranchSelectorTab,
@@ -38,7 +39,6 @@ import { timeAgoFromISOTime } from '../../pages/pipeline-edit/utils/time-utils'
3839
import { PathParams } from '../../RouteDefinitions'
3940
import { sortFilesByType } from '../../utils/common-utils'
4041
import { decodeGitContent, getTrimmedSha, normalizeGitRef, REFS_TAGS_PREFIX } from '../../utils/git-utils'
41-
import { generateAlphaNumericHash } from '../pull-request/pull-request-utils'
4242

4343
// import { useRepoBranchesStore } from './stores/repo-branches-store'
4444

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
)

apps/gitness/src/pages/pull-request/utils.ts

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -473,17 +473,5 @@ export enum ViewStyle {
473473
LINE_BY_LINE = 'line-by-line'
474474
}
475475

476-
export function generateAlphaNumericHash(length: number) {
477-
let result = ''
478-
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
479-
const charactersLength = characters.length
480-
481-
for (let i = 0; i < length; i++) {
482-
result += characters.charAt(Math.floor(Math.random() * charactersLength))
483-
}
484-
485-
return result
486-
}
487-
488476
export const getErrorMessage = (error: unknown): string | undefined =>
489477
error ? (get(error, 'data.error', get(error, 'data.message', get(error, 'message', error))) as string) : undefined

0 commit comments

Comments
 (0)