Skip to content

Commit

Permalink
fix(ui): error handling in UI (#374)
Browse files Browse the repository at this point in the history
  • Loading branch information
bouassaba authored Nov 13, 2024
1 parent aa55cf0 commit 8056773
Show file tree
Hide file tree
Showing 47 changed files with 2,843 additions and 2,520 deletions.
17 changes: 0 additions & 17 deletions api/errorpkg/error_constants.go

This file was deleted.

34 changes: 17 additions & 17 deletions api/errorpkg/error_creators.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func NewGroupNotFoundError(err error) *ErrorResponse {
"group_not_found",
http.StatusNotFound,
"Group not found.",
MsgResourceNotFound,
"Group not found.",
err,
)
}
Expand All @@ -35,7 +35,7 @@ func NewFileNotFoundError(err error) *ErrorResponse {
"file_not_found",
http.StatusNotFound,
"File not found.",
MsgResourceNotFound,
"File not found.",
err,
)
}
Expand All @@ -45,7 +45,7 @@ func NewInvalidPathError(err error) *ErrorResponse {
"invalid_path",
http.StatusBadRequest,
"Invalid path.",
MsgInvalidRequest,
"An invalid request was sent to the server.",
err,
)
}
Expand All @@ -55,7 +55,7 @@ func NewWorkspaceNotFoundError(err error) *ErrorResponse {
"workspace_not_found",
http.StatusNotFound,
"Workspace not found.",
MsgResourceNotFound,
"Workspace not found.",
err,
)
}
Expand All @@ -65,7 +65,7 @@ func NewOrganizationNotFoundError(err error) *ErrorResponse {
"organization_not_found",
http.StatusNotFound,
"Organization not found.",
MsgResourceNotFound,
"Organization not found.",
err,
)
}
Expand All @@ -75,7 +75,7 @@ func NewTaskNotFoundError(err error) *ErrorResponse {
"task_not_found",
http.StatusNotFound,
"Task not found.",
MsgResourceNotFound,
"Task not found.",
err,
)
}
Expand Down Expand Up @@ -105,17 +105,17 @@ func NewUserNotFoundError(err error) *ErrorResponse {
"user_not_found",
http.StatusNotFound,
"User not found.",
MsgResourceNotFound,
"User not found.",
err,
)
}

func NewUserPictureNotFoundError(err error) *ErrorResponse {
func NewPictureNotFoundError(err error) *ErrorResponse {
return NewErrorResponse(
"user_picture_not_found",
"Picture_not_found",
http.StatusNotFound,
"User picture not found.",
MsgResourceNotFound,
"Picture not found.",
"Picture not found.",
err,
)
}
Expand Down Expand Up @@ -145,7 +145,7 @@ func NewInvitationNotFoundError(err error) *ErrorResponse {
"invitation_not_found",
http.StatusNotFound,
"Invitation not found.",
MsgResourceNotFound,
"Invitation not found.",
err,
)
}
Expand Down Expand Up @@ -195,7 +195,7 @@ func NewInternalServerError(err error) *ErrorResponse {
"internal_server_error",
http.StatusInternalServerError,
"Internal server error.",
MsgSomethingWentWrong,
"Oops! something went wrong.",
err,
)
}
Expand Down Expand Up @@ -277,7 +277,7 @@ func NewS3Error(message string) *ErrorResponse {
"s3_error",
http.StatusInternalServerError,
message,
MsgSomethingWentWrong,
"Storage error occurred.",
nil,
)
}
Expand All @@ -287,7 +287,7 @@ func NewMissingQueryParamError(param string) *ErrorResponse {
"missing_query_param",
http.StatusBadRequest,
fmt.Sprintf("Query param '%s' is required.", param),
MsgInvalidRequest,
"An invalid request was sent to the server.",
nil,
)
}
Expand All @@ -297,7 +297,7 @@ func NewInvalidQueryParamError(param string) *ErrorResponse {
"invalid_query_param",
http.StatusBadRequest,
fmt.Sprintf("Query param '%s' is invalid.", param),
MsgInvalidRequest,
"An invalid request was sent to the server.",
nil,
)
}
Expand Down Expand Up @@ -332,7 +332,7 @@ func NewRequestBodyValidationError(err error) *ErrorResponse {
"request_validation_error",
http.StatusBadRequest,
fmt.Sprintf("Failed validation for fields: %s.", strings.Join(fields, ",")),
MsgInvalidRequest,
"An invalid request was sent to the server.",
err,
)
}
Expand Down
2 changes: 1 addition & 1 deletion api/router/user_router.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ func (r *UserRouter) DownloadPicture(c *fiber.Ctx) error {
return err
}
if *ext != c.Params("extension") {
return errorpkg.NewUserPictureNotFoundError(nil)
return errorpkg.NewPictureNotFoundError(nil)
}
c.Set("Content-Type", *mime)
c.Set("Content-Disposition", fmt.Sprintf("filename=\"picture%s\"", *ext))
Expand Down
12 changes: 6 additions & 6 deletions api/service/user_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,13 +270,13 @@ func (svc *UserService) ExtractPicture(id string, justification ExtractPictureJu
return nil, nil, nil, err
}
if user.GetPicture() == nil {
return nil, nil, nil, errorpkg.NewUserPictureNotFoundError(nil)
return nil, nil, nil, errorpkg.NewPictureNotFoundError(nil)
}
mime := helper.Base64ToMIME(*user.GetPicture())
ext := helper.Base64ToExtension(*user.GetPicture())
b, err := helper.Base64ToBytes(*user.GetPicture())
if err != nil {
return nil, nil, nil, errorpkg.NewUserPictureNotFoundError(nil)
return nil, nil, nil, errorpkg.NewPictureNotFoundError(nil)
}
return b, &ext, &mime, nil
}
Expand All @@ -290,7 +290,7 @@ func (svc *UserService) findUserForPicture(id string, justification ExtractPictu
return user, nil
}
if justification.OrganizationID == nil && justification.GroupID == nil && justification.InvitationID == nil {
return nil, errorpkg.NewUserPictureNotFoundError(nil)
return nil, errorpkg.NewPictureNotFoundError(nil)
}
if justification.OrganizationID != nil {
org, err := svc.orgCache.Get(*justification.OrganizationID)
Expand All @@ -301,7 +301,7 @@ func (svc *UserService) findUserForPicture(id string, justification ExtractPictu
return nil, err
}
if !slices.Contains(org.GetMembers(), id) {
return nil, errorpkg.NewUserPictureNotFoundError(nil)
return nil, errorpkg.NewPictureNotFoundError(nil)
}
} else if justification.GroupID != nil {
group, err := svc.groupCache.Get(*justification.GroupID)
Expand All @@ -312,15 +312,15 @@ func (svc *UserService) findUserForPicture(id string, justification ExtractPictu
return nil, err
}
if !slices.Contains(group.GetMembers(), id) {
return nil, errorpkg.NewUserPictureNotFoundError(nil)
return nil, errorpkg.NewPictureNotFoundError(nil)
}
} else if justification.InvitationID != nil {
invitation, err := svc.invitationRepo.Find(*justification.InvitationID)
if err != nil {
return nil, err
}
if invitation.GetOwnerID() != id {
return nil, errorpkg.NewUserPictureNotFoundError(nil)
return nil, errorpkg.NewPictureNotFoundError(nil)
}
}
return user, nil
Expand Down
Binary file modified ui/bun.lockb
Binary file not shown.
2 changes: 1 addition & 1 deletion ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"@emotion/react": "11.13.3",
"@emotion/styled": "11.13.0",
"@google/model-viewer": "4.0.0",
"@koupr/ui": "1.10.9",
"@koupr/ui": "1.10.10",
"@nivo/core": "0.87.0",
"@nivo/pie": "0.87.0",
"@reduxjs/toolkit": "2.3.0",
Expand Down
145 changes: 72 additions & 73 deletions ui/src/components/common/group-selector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,16 @@ const GroupSelector = ({
const [selected, setSelected] = useState<Group>()
const {
data: list,
error,
error: listError,
isLoading: isListLoading,
mutate,
} = GroupAPI.useList(
{ query, organizationId, page, size: 5, sortOrder: SortOrder.Desc },
swrConfig(),
)
const isListError = !list && listError
const isListEmpty = list && !listError && list.totalElements === 0
const isListReady = list && !listError && list.totalElements > 0

useEffect(() => {
mutate().then()
Expand Down Expand Up @@ -116,84 +120,79 @@ const GroupSelector = ({
query={query}
onChange={handleSearchInputChange}
/>
{!list && error ? (
{isListLoading ? <SectionSpinner /> : null}
{isListError ? (
<SectionError text="Failed to load groups." />
) : null}
{!list && !error ? <SectionSpinner /> : null}
{list && !error ? (
<>
{list.totalElements > 0 ? (
<div
className={cx(
'flex',
'flex-col',
'justify-between',
'gap-1.5',
'h-[320px]',
)}
>
<Table variant="simple" size="sm">
<colgroup>
<col className={cx('w-[40px]')} />
<col className={cx('w-[auto]')} />
</colgroup>
<Tbody>
{list.data.map((g) => (
<Tr
key={g.id}
{isListEmpty ? (
<SectionPlaceholder text="There are no groups." />
) : null}
{isListReady ? (
<div
className={cx(
'flex',
'flex-col',
'justify-between',
'gap-1.5',
'h-[320px]',
)}
>
<Table variant="simple" size="sm">
<colgroup>
<col className={cx('w-[40px]')} />
<col className={cx('w-[auto]')} />
</colgroup>
<Tbody>
{list.data.map((g) => (
<Tr
key={g.id}
className={cx(
'cursor-pointer',
'h-[52px]',
{ 'bg-gray-100': selected?.id === g.id },
{ 'dark:bg-gray-600': selected?.id === g.id },
{ 'bg-transparent': selected?.id !== g.id },
)}
onClick={() => setSelected(g)}
>
<Td className={cx('px-0.5', 'text-center')}>
<Radio
size="md"
isChecked={selected?.id === g.id}
/>
</Td>
<Td className={cx('p-0.5')}>
<div
className={cx(
'cursor-pointer',
'h-[52px]',
{ 'bg-gray-100': selected?.id === g.id },
{ 'dark:bg-gray-600': selected?.id === g.id },
{ 'bg-transparent': selected?.id !== g.id },
'flex',
'flex-row',
'items-center',
'gap-1.5',
)}
onClick={() => setSelected(g)}
>
<Td className={cx('px-0.5', 'text-center')}>
<Radio
size="md"
isChecked={selected?.id === g.id}
/>
</Td>
<Td className={cx('p-0.5')}>
<div
className={cx(
'flex',
'flex-row',
'items-center',
'gap-1.5',
)}
>
<Avatar
name={g.name}
size="sm"
className={cx('w-[40px]', 'h-[40px]')}
/>
<span className={cx('text-base')}>
{g.name}
</span>
</div>
</Td>
</Tr>
))}
</Tbody>
</Table>
{list.totalPages > 1 ? (
<div className={cx('self-end')}>
<Pagination
maxButtons={3}
page={page}
totalPages={list.totalPages}
onPageChange={(value) => setPage(value)}
/>
</div>
) : null}
<Avatar
name={g.name}
size="sm"
className={cx('w-[40px]', 'h-[40px]')}
/>
<span className={cx('text-base')}>{g.name}</span>
</div>
</Td>
</Tr>
))}
</Tbody>
</Table>
{list.totalPages > 1 ? (
<div className={cx('self-end')}>
<Pagination
maxButtons={3}
page={page}
totalPages={list.totalPages}
onPageChange={(value) => setPage(value)}
/>
</div>
) : (
<SectionPlaceholder text="There are no groups." />
)}
</>
) : null}
</div>
) : null}
</div>
</ModalBody>
Expand Down
Loading

0 comments on commit 8056773

Please sign in to comment.