diff --git a/assets/js/src/core/components/focal-point/focal-point.tsx b/assets/js/src/core/components/focal-point/focal-point.tsx index 1f867a1ad..116696910 100644 --- a/assets/js/src/core/components/focal-point/focal-point.tsx +++ b/assets/js/src/core/components/focal-point/focal-point.tsx @@ -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) @@ -44,7 +45,9 @@ 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')) + + return null } const { @@ -57,7 +60,9 @@ export const FocalPoint = ({ activationConstraint, children }: FocalPointProps): } = focalPointContext if (!isValidElement(Image)) { - throw new Error('Children must be a valid react component') + trackError(new GeneralError('Children must be a valid react component')) + + return null } const ImageComponent = Image.type diff --git a/assets/js/src/core/modules/app/utils/app-runner.tsx b/assets/js/src/core/modules/app/utils/app-runner.tsx index 6861bc871..7b04d1367 100644 --- a/assets/js/src/core/modules/app/utils/app-runner.tsx +++ b/assets/js/src/core/modules/app/utils/app-runner.tsx @@ -14,12 +14,15 @@ import React from 'react' import { createRoot } from 'react-dom/client' import { AppView } from '../app-view' +import trackError, { GeneralError } from '@Pimcore/modules/app/error-handler' export function runApp (): void { const domElement = document.getElementById('app') if (domElement === null) { - throw new Error('Root element not found') + trackError(new GeneralError('Root element not found')) + + return undefined } const root = createRoot(domElement) diff --git a/assets/js/src/core/modules/asset/editor/types/folder/tab-manager/tabs/list/list-container-inner.tsx b/assets/js/src/core/modules/asset/editor/types/folder/tab-manager/tabs/list/list-container-inner.tsx index e140887e2..d4ba146e2 100644 --- a/assets/js/src/core/modules/asset/editor/types/folder/tab-manager/tabs/list/list-container-inner.tsx +++ b/assets/js/src/core/modules/asset/editor/types/folder/tab-manager/tabs/list/list-container-inner.tsx @@ -14,6 +14,7 @@ import { api, type AssetGetGridApiResponse, type AssetPatchByIdApiArg, useAssetGetGridMutation, useAssetPatchByIdMutation } from '@Pimcore/modules/asset/asset-api-slice-enhanced' import React, { useContext, useEffect, useMemo, useState } from 'react' import { type FetchBaseQueryError } from '@reduxjs/toolkit/query' +import { isUndefined } from 'lodash' import { encodeColumnIdentifier, GridContainer } from './grid-container' import { GridToolbarContainer } from './toolbar/grid-toolbar-container' import { AssetContext } from '@Pimcore/modules/asset/asset-provider' @@ -35,6 +36,7 @@ import { Content } from '@Pimcore/components/content/content' import { eventBus } from '@Pimcore/lib/event-bus' import { generateQueryArgsForGrid } from './helpers/gridHelpers' import usePagination from '@Pimcore/utils/hooks/use-pagination' +import trackError, { GeneralError } from '@Pimcore/modules/app/error-handler' interface DataPatch { columnId: string @@ -94,12 +96,12 @@ export const ListContainerInner = (): React.JSX.Element => { const initialColumns = initialGridConfig.data!.columns.map((column) => { const availableColumn = availableGridConfig.data?.columns?.find((availableColumn) => availableColumn.key === column.key) - if (availableColumn === undefined) { - throw new Error(`Column with key ${column.key} is not available`) + if (isUndefined(availableColumn)) { + trackError(new GeneralError(`Column with key ${column.key} is not available`)) } return availableColumn - }) + }).filter((column) => !isUndefined(column)) setGridColumns(initialColumns) availableGridConfigPromise.unsubscribe() @@ -206,7 +208,7 @@ export const ListContainerInner = (): React.JSX.Element => { const backendType = column.type.split('.') if (backendType[0] !== 'metadata') { - throw new Error('Only metadata columns are supported for now') + trackError(new GeneralError('Only metadata columns are supported for now')) } const update: AssetPatchByIdApiArg = { diff --git a/assets/js/src/core/modules/element/dynamic-types/registry/dynamic-type-registry-abstract.tsx b/assets/js/src/core/modules/element/dynamic-types/registry/dynamic-type-registry-abstract.tsx index 2198a05fa..36ab8cfe0 100644 --- a/assets/js/src/core/modules/element/dynamic-types/registry/dynamic-type-registry-abstract.tsx +++ b/assets/js/src/core/modules/element/dynamic-types/registry/dynamic-type-registry-abstract.tsx @@ -12,6 +12,7 @@ */ import { injectable } from 'inversify' +import trackError, { GeneralError } from '@Pimcore/modules/app/error-handler' @injectable() export abstract class DynamicTypeAbstract { @@ -24,7 +25,7 @@ export abstract class DynamicTypeRegistryAbstract({ target, dynamicType }: { target: keyof ITargetCallbackNameMap, dynamicType: DynamicTypeAbstract }): (props: T) => ReactElement { if (!this.hasCallable(target, dynamicType)) { - throw new Error(`DynamicTypeResolver: ${dynamicType.id} does not have a callable ${targetCallbackNameMap[target]}`) + trackError(new GeneralError(`DynamicTypeResolver: ${dynamicType.id} does not have a callable ${targetCallbackNameMap[target]}`)) } return (props: T) => dynamicType[targetCallbackNameMap[target]].bind(dynamicType)(props) diff --git a/assets/js/src/core/modules/element/editor/services/type-registry.ts b/assets/js/src/core/modules/element/editor/services/type-registry.ts index b767323cb..aaf613ed7 100644 --- a/assets/js/src/core/modules/element/editor/services/type-registry.ts +++ b/assets/js/src/core/modules/element/editor/services/type-registry.ts @@ -12,6 +12,7 @@ */ import { injectable } from 'inversify' +import trackError, { GeneralError } from '@Pimcore/modules/app/error-handler' export interface ElementEditorType { name: string @@ -29,14 +30,15 @@ export class TypeRegistry implements TypeRegistryInterface { register (type: ElementEditorType): void { if (this.has(type.name)) { - throw new Error(`Type with the name "${type.name}" already exists.`) + trackError(new GeneralError(`Type with the name "${type.name}" already exists.`)) } + this.registry[type.name] = type } get (name: string): ElementEditorType { if (!this.has(name)) { - throw new Error(`No type with the name "${name}" found`) + trackError(new GeneralError(`No type with the name "${name}" found`)) } return this.registry[name] diff --git a/assets/js/src/core/modules/element/upload/hook/use-file-uploader.ts b/assets/js/src/core/modules/element/upload/hook/use-file-uploader.ts index 817fe77f7..4140d6c76 100644 --- a/assets/js/src/core/modules/element/upload/hook/use-file-uploader.ts +++ b/assets/js/src/core/modules/element/upload/hook/use-file-uploader.ts @@ -21,6 +21,7 @@ import { useJobs } from '@Pimcore/modules/execution-engine/hooks/useJobs' import { createJob } from '@Pimcore/modules/execution-engine/jobs/zip-upload/factory' import { defaultTopics, topics } from '@Pimcore/modules/execution-engine/topics' import { type UploadChangeParam } from '@Pimcore/components/upload/upload' +import trackError, { GeneralError } from '@Pimcore/modules/app/error-handler' interface UseFileUploaderProps { parentId?: string @@ -40,17 +41,17 @@ export const UseFileUploader = ({ parentId }: UseFileUploaderProps): UseFileUplo const uploadFile = async ({ fileList, file }: UploadChangeParam>): Promise => { if (parentId === undefined) { - throw new Error('Parent ID is required') + trackError(new GeneralError('Parent ID is required')) } const fileStates = fileList.map((file) => file.status) const allFullFilled = fileStates.every(item => item === 'done') uploadContext.setUploadFileList(fileList) - uploadContext.setUploadingNode(parentId) + uploadContext.setUploadingNode(parentId!) if (allFullFilled) { - dispatch(assetApi.util.invalidateTags(invalidatingTags.ASSET_TREE_ID(parseInt(parentId)))) + dispatch(assetApi.util.invalidateTags(invalidatingTags.ASSET_TREE_ID(parseInt(parentId!)))) uploadContext.setUploadFileList([]) uploadContext.setUploadingNode(null) } diff --git a/assets/js/src/core/modules/widget-manager/utils/widget-manager-factory.tsx b/assets/js/src/core/modules/widget-manager/utils/widget-manager-factory.tsx index 6355afd46..4069c9263 100644 --- a/assets/js/src/core/modules/widget-manager/utils/widget-manager-factory.tsx +++ b/assets/js/src/core/modules/widget-manager/utils/widget-manager-factory.tsx @@ -18,6 +18,7 @@ import { WidgetManagerInnerContainer } from '../widget-manager-inner-container' import { container } from '@Pimcore/app/depency-injection' import { serviceIds } from '@Pimcore/app/config/services/service-ids' import { type WidgetRegistry } from '../services/widget-registry' +import trackError, { GeneralError } from '@Pimcore/modules/app/error-handler' export const widgetManagerFactory = (node: TabNode): ReactNode | undefined => { if (node.getComponent() === 'inner-widget-manager') { @@ -34,7 +35,9 @@ export const widgetManagerFactory = (node: TabNode): ReactNode | undefined => { const widget = widgetRegistryService.getWidget(widgetName) if (widget === undefined) { - throw new Error(`Widget ${widgetName} not found`) + trackError(new GeneralError(`Widget ${widgetName} not found`)) + + return undefined } const { component } = widget diff --git a/assets/js/src/core/utils/hooks/use-server-side-event.ts b/assets/js/src/core/utils/hooks/use-server-side-event.ts index 6a308bedc..b80b3d5ac 100644 --- a/assets/js/src/core/utils/hooks/use-server-side-event.ts +++ b/assets/js/src/core/utils/hooks/use-server-side-event.ts @@ -15,6 +15,7 @@ import { useEffect } from 'react' import { type topics } from '../../modules/execution-engine/topics' import { type NonEmptyArray } from 'types/non-empty-array' import { appConfig } from '@Pimcore/app/config/app-config' +import trackError, { GeneralError } from '@Pimcore/modules/app/error-handler' const ServerSideEventDomain = appConfig.mercureUrl @@ -33,7 +34,7 @@ export const useServerSideEvent = ({ topics, messageHandler, openHandler }: UseS let event: EventSource | undefined if (topics.length === 0) { - throw new Error('No topics provided') + trackError(new GeneralError('No topics provided')) } function open (): void { diff --git a/assets/js/src/core/utils/polling-helper.ts b/assets/js/src/core/utils/polling-helper.ts index 2b8247c48..eb5b5fe3a 100644 --- a/assets/js/src/core/utils/polling-helper.ts +++ b/assets/js/src/core/utils/polling-helper.ts @@ -11,6 +11,8 @@ * @license https://github.com/pimcore/studio-ui-bundle/blob/1.x/LICENSE.md POCL and PCL */ +import trackError, { GeneralError } from '@Pimcore/modules/app/error-handler' + interface FetchBlobWithPollingParams { url: string onSuccess: (blob: Blob) => void @@ -30,7 +32,7 @@ export async function fetchBlobWithPolling ({ } else if (response.status === 202) { setTimeout(fetchUrl, interval) } else { - throw new Error(`Unexpected response status: ${response.status}`) + trackError(new GeneralError(`Unexpected response status: ${response.status}`)) } }