Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error Handling #752

Merged
merged 40 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
0febbda
added the ErrorBoundary component
ValeriaMaltseva Nov 21, 2024
a7b45f2
added the rtkQueryErrorLogger middleware
ValeriaMaltseva Nov 22, 2024
a20ef2a
implemented logic of saving the RTK Query errors in the store
ValeriaMaltseva Nov 22, 2024
0c75d86
merged changes from the main branch
ValeriaMaltseva Nov 25, 2024
43d872c
added the ErrorHandler logic
ValeriaMaltseva Nov 25, 2024
aa174f4
refactoring and added types
ValeriaMaltseva Nov 25, 2024
a258c37
updated the ErrorHandler component
ValeriaMaltseva Nov 25, 2024
ad10449
Update the ErrorBoundary
ValeriaMaltseva Nov 25, 2024
7a0a78d
added the test code
ValeriaMaltseva Nov 26, 2024
09444f4
updated the ErrorBoundary logic
ValeriaMaltseva Nov 26, 2024
0daa5f6
deleted the test code
ValeriaMaltseva Nov 27, 2024
0bce4fc
added the useApiErrorHandler hook
ValeriaMaltseva Nov 27, 2024
9df0983
merged changes from the main branch
ValeriaMaltseva Nov 27, 2024
3674d86
updated the test code
ValeriaMaltseva Nov 27, 2024
479cd04
updated the useApiErrorHandler and deleted unused logic
ValeriaMaltseva Nov 27, 2024
39da225
updated the ErrorBoundary
ValeriaMaltseva Nov 28, 2024
bb80580
refactoring
ValeriaMaltseva Nov 28, 2024
c5fdcab
deleted the test code
ValeriaMaltseva Nov 28, 2024
8e0a197
added styles for the ErrorBoundary
ValeriaMaltseva Nov 28, 2024
b18249c
updated the useApiErrorHandler hook
ValeriaMaltseva Nov 28, 2024
3a68a20
resolved conflicts
ValeriaMaltseva Nov 28, 2024
be47a2d
merged changes from the main branch
ValeriaMaltseva Nov 29, 2024
1401e67
deleted the test code
ValeriaMaltseva Nov 29, 2024
d67817d
updated the useApiErrorHandler hook by creating the method for tracki…
ValeriaMaltseva Nov 29, 2024
41109ff
added the ErrorHandler module and updated the error approach
ValeriaMaltseva Nov 29, 2024
afcd331
refactored the ErrorHandler logic and updated types for the Tag
ValeriaMaltseva Dec 2, 2024
defa18d
updated the ApiError class
ValeriaMaltseva Dec 2, 2024
948498a
added export file
ValeriaMaltseva Dec 2, 2024
d183157
updated the trackError method and updated the components by using it …
ValeriaMaltseva Dec 2, 2024
876ca99
added the trackError instead of using error throwing
ValeriaMaltseva Dec 2, 2024
8fa7d5e
added the trackError method instead of throwing error
ValeriaMaltseva Dec 2, 2024
906bd09
merged changes from the main branch
ValeriaMaltseva Dec 2, 2024
c0fd969
fixed types
ValeriaMaltseva Dec 2, 2024
82eb638
fixed issues
ValeriaMaltseva Dec 2, 2024
7e6b13a
fixed issues
ValeriaMaltseva Dec 2, 2024
cbb764c
fixed issue
ValeriaMaltseva Dec 2, 2024
a30df1b
updated the type
ValeriaMaltseva Dec 3, 2024
0c1734b
merged changed from the main branch
ValeriaMaltseva Dec 3, 2024
84b1acf
updated the ErrorHandler by adding the handler prop and fixed statement
ValeriaMaltseva Dec 3, 2024
03be555
Automatic frontend build
ValeriaMaltseva Dec 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions assets/js/src/core/app/api/pimcore/tags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/

import { type ElementType } from 'types/element-type.d'
import trackError, { GeneralError } from '@Pimcore/modules/app/error-handler'

export type Tag = string | {
type: string
Expand Down Expand Up @@ -97,13 +98,13 @@ export const invalidatingTags = {
ELEMENT_NOTES_AND_EVENTS: (elementType: ElementType, id: number) => [getElementDetailTag(elementType, id), tagNames.NOTES_AND_EVENTS]
}

const getElementDetailTag = (elementType: ElementType, id: number): Tag => {
const getElementDetailTag = (elementType: ElementType, id: number): Tag | undefined => {
switch (elementType) {
case 'asset':
return { type: tagNames.ASSET_DETAIL, id }
case 'data-object':
return { type: tagNames.DATA_OBJECT_DETAIL, id }
}

throw new Error(`Unknown element type: ${elementType}`)
trackError(new GeneralError(`Unknown element type: ${elementType}`))
}
4 changes: 3 additions & 1 deletion assets/js/src/core/components/drag-and-drop/draggable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { useDraggable } from '@dnd-kit/core'
import { type DragAndDropInfo } from './context-provider'
import { uuid } from '@Pimcore/utils/uuid'
import { GlobalStyle } from './draggable.styles'
import trackError, { GeneralError } from '@Pimcore/modules/app/error-handler'

interface DraggableProps {
children: React.ReactNode
Expand All @@ -32,7 +33,8 @@ function Draggable (props: DraggableProps): React.JSX.Element {
const Child = Children.only(props.children)

if (!isValidElement(Child)) {
throw new Error('Children must be a valid react component')
trackError(new GeneralError('Children must be a valid react component'))
throw new Error('Invalid React child element.')
}

const Component = Child.type
Expand Down
7 changes: 5 additions & 2 deletions assets/js/src/core/components/drag-and-drop/droppable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { useStyle } from './droppable.styles'
import { DroppableContextProvider } from './droppable-context-provider'
import { uuid } from '@Pimcore/utils/uuid'
import cn from 'classnames'
import trackError, { GeneralError } from '@Pimcore/modules/app/error-handler'

export interface DroppableContentProps {
isDragActive: boolean
Expand All @@ -35,7 +36,7 @@ export interface DroppableProps {
onDrop: (info: DragAndDropInfo) => void
}

export const Droppable = (props: DroppableProps): React.JSX.Element => {
export const Droppable = (props: DroppableProps): React.JSX.Element | null => {
const { styles } = useStyle()
const context = useContext(DragAndDropInfoContext)
const [isValidContext, setIsValidContext] = useState(false)
Expand Down Expand Up @@ -77,7 +78,9 @@ export const Droppable = (props: DroppableProps): React.JSX.Element => {
const Child = Children.only(props.children)

if (!isValidElement(Child)) {
throw new Error('Children must be a valid react component')
trackError(new GeneralError('Children must be a valid react component'))

return null
}

const Component = Child.type
Expand Down
21 changes: 12 additions & 9 deletions assets/js/src/core/components/focal-point/focal-point.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,14 @@ import { restrictToParentElement } from '@dnd-kit/modifiers'
import { useAssetDraft } from '@Pimcore/modules/asset/hooks/use-asset-draft'
import { AssetContext } from '@Pimcore/modules/asset/asset-provider'
import { FocalPointContext } from '@Pimcore/components/focal-point/context/focal-point-context'
import trackError, { GeneralError } from '@Pimcore/modules/app/error-handler'

interface FocalPointProps {
activationConstraint?: PointerActivationConstraint
children: React.ReactNode
}

export const FocalPoint = ({ activationConstraint, children }: FocalPointProps): React.JSX.Element => {
export const FocalPoint = ({ activationConstraint, children }: FocalPointProps): React.JSX.Element | null => {
const Image = Children.only(children)
const { id } = useContext(AssetContext)
const focalPointContext = useContext(FocalPointContext)
Expand All @@ -44,7 +45,7 @@ export const FocalPoint = ({ activationConstraint, children }: FocalPointProps):
const { addImageSettings, removeImageSetting } = useAssetDraft(id)

if (focalPointContext === undefined) {
throw new Error('FocalPoint must be used within the FocalPointProvider')
trackError(new GeneralError('FocalPoint must be used within the FocalPointProvider'))
}

const {
Expand All @@ -54,13 +55,7 @@ export const FocalPoint = ({ activationConstraint, children }: FocalPointProps):
setIsActive,
disabled,
containerRef
} = focalPointContext

if (!isValidElement(Image)) {
throw new Error('Children must be a valid react component')
}

const ImageComponent = Image.type
} = focalPointContext!

const onLoad = (): void => {
if (
Expand All @@ -87,6 +82,14 @@ export const FocalPoint = ({ activationConstraint, children }: FocalPointProps):
}
}, [isActive])

if (!isValidElement(Image)) {
trackError(new GeneralError('Children must be a valid react component'))

return null
}

const ImageComponent = Image.type

return (
<DndContext
modifiers={ [restrictToParentElement] }
Expand Down
3 changes: 2 additions & 1 deletion assets/js/src/core/components/grid/columns/default-cell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { useKeyboardNavigation } from '../keyboard-navigation/use-keyboard-navig
import { usePrevious } from '@Pimcore/utils/hooks/use-previous'
import { type ExtendedCellContext } from '../grid'
import { useDynamicTypeResolver } from '@Pimcore/modules/element/dynamic-types/resolver/hooks/use-dynamic-type-resolver'
import trackError, { GeneralError } from '@Pimcore/modules/app/error-handler'

export interface DefaultCellProps extends ExtendedCellContext {}

Expand Down Expand Up @@ -102,7 +103,7 @@ export const DefaultCell = ({ ...props }: DefaultCellProps): React.JSX.Element =
}

if (isEditable && table.options.meta?.onUpdateCellData === undefined) {
throw new Error('onUpdateCellData is required when using editable cells')
trackError(new GeneralError('onUpdateCellData is required when using editable cells'))
}

setIsInEditMode(true)
Expand Down
3 changes: 2 additions & 1 deletion assets/js/src/core/components/grid/grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import { GridRow } from './grid-cell/grid-row'
import { SortButton, type SortDirection, SortDirections } from '../sort-button/sort-button'
import { DynamicTypeRegistryProvider } from '@Pimcore/modules/element/dynamic-types/registry/provider/dynamic-type-registry-provider'
import { type GridProps } from '@Pimcore/types/components/types'
import trackError, { GeneralError } from '@Pimcore/modules/app/error-handler'

declare module '@tanstack/react-table' {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
Expand Down Expand Up @@ -174,7 +175,7 @@ export const Grid = ({ enableMultipleRowSelection = false, modifiedCells = [], s
for (const column of columns) {
if (column.meta?.autoWidth === true) {
if (autoWidthColumnFound) {
throw new Error('Only one column can have autoWidth set to true')
trackError(new GeneralError('Only one column can have autoWidth set to true'))
}
autoWidthColumnFound = true
}
Expand Down
13 changes: 7 additions & 6 deletions assets/js/src/core/components/login-form/login-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ import { useMessage } from '@Pimcore/components/message/useMessage'
import { useTranslation } from 'react-i18next'
import { setUser } from '@Pimcore/modules/auth/user/user-slice'
import { Icon } from '../icon/icon'
import { type Credentials, useLoginMutation, type UserInformation } from '@Pimcore/modules/auth/authorization-api-slice.gen'
import { type Credentials, useLoginMutation } from '@Pimcore/modules/auth/authorization-api-slice.gen'
import trackError, { ApiError } from '@Pimcore/modules/app/error-handler'

export interface IAdditionalLogins {
key: string
Expand Down Expand Up @@ -49,19 +50,19 @@ export const LoginForm = ({ additionalLogins }: ILoginFormProps): React.JSX.Elem
const handleAuthentication = async (event: React.FormEvent<HTMLFormElement>): Promise<void> => {
const loginTask = login({ credentials: formState })

loginTask.catch((error) => {
throw new Error(error.message as string)
loginTask.catch((error: Error) => {
trackError(new ApiError(error))
})

try {
event.preventDefault()
const response = (await loginTask) as any
const response = (await loginTask)

if (response.error !== undefined) {
throw new Error(response.error.data.error as string)
trackError(new ApiError(response.error))
}

const userInformation = response.data as UserInformation
const userInformation = response.data!
dispatch(setUser(userInformation))
} catch (e: any) {
void messageApi.error({
Expand Down
5 changes: 3 additions & 2 deletions assets/js/src/core/components/sidebar/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import { useStyle } from './sidebar.styles'
import React, { isValidElement, useState } from 'react'
import { type ISidebarButton, type ISidebarEntry } from '@Pimcore/modules/element/sidebar/sidebar-manager'
import trackError, { GeneralError } from '@Pimcore/modules/app/error-handler'

interface SidebarProps {
entries: ISidebarEntry[]
Expand Down Expand Up @@ -89,11 +90,11 @@ export const Sidebar = ({ entries, buttons = [], sizing = 'default', highlights
const { component, key, ...props } = button

if (!isValidElement(component)) {
throw new Error('SidebarButton must be a valid react component')
trackError(new GeneralError('SidebarButton must be a valid react component'))
}

const SidebarButton = component.type
const sidebarButtonProps = component.props as any
const sidebarButtonProps = component.props

return (
<SidebarButton
Expand Down
20 changes: 17 additions & 3 deletions assets/js/src/core/modules/app/app-loader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,36 @@ import {
} from '../asset/editor/types/folder/tab-manager/tabs/list/toolbar/tools/mercure-api-slice.gen'
import { Content } from '@Pimcore/components/content/content'
import { GlobalStyles } from '@Pimcore/styles/global.styles'
import { useAlertModal } from '@Pimcore/components/modal/alert-modal/hooks/use-alert-modal'
import { ErrorModalService } from '@Pimcore/modules/app/error-handler/services/error-modal-service'
import trackError, { ApiError } from '@Pimcore/modules/app/error-handler'

export interface IAppLoaderProps {
children: React.ReactNode
}

export const AppLoader = (props: IAppLoaderProps): React.JSX.Element => {
const dispatch = useAppDispatch()
const [translations] = useTranslationGetCollectionMutation()
const { i18n } = useTranslation()

const [isLoading, setIsLoading] = useState(true)

const [translations] = useTranslationGetCollectionMutation()
const [fetchMercureCookie] = useMercureCreateCookieMutation()

const modal = useAlertModal()

// Register the modal instance to allow centralized error message display throughout the project
ErrorModalService.setModalInstance(modal)

async function initLoadUser (): Promise<any> {
const userFetcher = dispatch(api.endpoints.userGetCurrentInformation.initiate())
await fetchMercureCookie()

userFetcher
.then(({ data, isSuccess }) => {
.then(({ data, isSuccess, isError, error }) => {
isError && trackError(new ApiError(error))

if (isSuccess && data !== undefined) {
dispatch(setUser(data))
}
Expand All @@ -55,7 +67,9 @@ export const AppLoader = (props: IAppLoaderProps): React.JSX.Element => {
const settingsFetcher = dispatch(settingsApi.endpoints.systemSettingsGet.initiate())

settingsFetcher
.then(({ data, isSuccess }) => {
.then(({ data, isSuccess, isError, error }) => {
isError && trackError(new ApiError(error))

if (isSuccess && data !== undefined) {
dispatch(setSettings(data))
}
Expand Down
22 changes: 12 additions & 10 deletions assets/js/src/core/modules/app/app-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,22 @@ import { RouterProvider } from 'react-router-dom'
import { router } from '@Pimcore/app/router/router'
import { AppLoader } from '@Pimcore/modules/app/app-loader'
import { DateTimeConfig } from '@Pimcore/app/config/date-time'
import ErrorBoundary from '@Pimcore/modules/app/error-boundary/error-boundary'

export const AppView = (): React.JSX.Element => {
return (
<>

<GlobalProvider>
<AntApp>
<DateTimeConfig>
<AppLoader>
<RouterProvider router={ router } />
</AppLoader>
</DateTimeConfig>
</AntApp>
</GlobalProvider>
<ErrorBoundary>
<GlobalProvider>
<AntApp>
<DateTimeConfig>
<AppLoader>
<RouterProvider router={ router } />
</AppLoader>
</DateTimeConfig>
</AntApp>
</GlobalProvider>
</ErrorBoundary>
</>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

import { injectable } from 'inversify'
import type React from 'react'
import trackError, { GeneralError } from '@Pimcore/modules/app/error-handler'

interface ComponentRegistryEntry<T> {
name: string
Expand All @@ -33,7 +34,7 @@ export class ComponentRegistry implements ComponentRegistryInterface {

register (component: ComponentRegistryEntry<any>): void {
if (this.has(component.name)) {
throw new Error(`Component with the name "${component.name}" already exists. Use the override method to override it`)
trackError(new GeneralError(`Component with the name "${component.name}" already exists. Use the override method to override it`))
}

this.registry[component.name] = component
Expand All @@ -45,7 +46,7 @@ export class ComponentRegistry implements ComponentRegistryInterface {

get<T>(name: string): ComponentRegistryEntry<T>['component'] {
if (!this.has(name)) {
throw new Error(`No component with the name "${name}" found`)
trackError(new GeneralError(`No component with the name "${name}" found`))
}

return this.registry[name].component
Expand All @@ -57,7 +58,7 @@ export class ComponentRegistry implements ComponentRegistryInterface {

override <T>(name: string, component: ComponentRegistryEntry<T>): void {
if (!this.has(name)) {
throw new Error(`No component named "${name}" found to override`)
trackError(new GeneralError(`No component named "${name}" found to override`))
}

this.registry[name] = component
Expand Down
Loading
Loading