diff --git a/mailpoet/assets/js/src/automation/api/index.ts b/mailpoet/assets/js/src/automation/api/index.ts index 37e5b8f5aa..be5cd4dd05 100644 --- a/mailpoet/assets/js/src/automation/api/index.ts +++ b/mailpoet/assets/js/src/automation/api/index.ts @@ -5,6 +5,16 @@ export * from './hooks'; const apiUrl = `${api.root}/mailpoet/v1/automation/`; +export type ApiError = { + code?: string; + message?: string; + data?: { + status?: number; + details?: Error; + params?: Record; + }; +}; + export const initializeApi = () => { apiFetch.use(apiFetch.createRootURLMiddleware(apiUrl)); apiFetch.use(apiFetch.createNonceMiddleware(api.nonce)); diff --git a/mailpoet/assets/js/src/automation/editor/api-error-handler.tsx b/mailpoet/assets/js/src/automation/editor/api-error-handler.tsx new file mode 100644 index 0000000000..eeba8a3246 --- /dev/null +++ b/mailpoet/assets/js/src/automation/editor/api-error-handler.tsx @@ -0,0 +1,36 @@ +import apiFetch, { APIFetchOptions } from '@wordpress/api-fetch'; +import { dispatch, StoreDescriptor } from '@wordpress/data'; +import { __ } from '@wordpress/i18n'; +import { store as noticesStore } from '@wordpress/notices'; +import { ApiError } from '../api'; + +export const registerApiErrorHandler = (): void => + apiFetch.use( + async ( + options: APIFetchOptions, + next: (nextOptions: APIFetchOptions) => Promise, + ) => { + try { + const result = await next(options); + return result; + } catch (error) { + const errorObject = error as ApiError; + const status = errorObject.data?.status; + + if (status && status >= 400 && status < 500) { + const message = errorObject.message; + void dispatch(noticesStore as StoreDescriptor).createErrorNotice( + message ?? __('An unknown error occurred.', 'mailpoet'), + { explicitDismiss: true }, + ); + return undefined; + } + + void dispatch(noticesStore as StoreDescriptor).createErrorNotice( + __('An unknown error occurred.', 'mailpoet'), + { explicitDismiss: true }, + ); + throw error; + } + }, + ); diff --git a/mailpoet/assets/js/src/automation/editor/components/workflow/index.tsx b/mailpoet/assets/js/src/automation/editor/components/workflow/index.tsx index 0f66a40544..1099fa680c 100644 --- a/mailpoet/assets/js/src/automation/editor/components/workflow/index.tsx +++ b/mailpoet/assets/js/src/automation/editor/components/workflow/index.tsx @@ -12,7 +12,6 @@ import { Separator } from './separator'; import { Step } from './step'; import { Step as StepData } from './types'; import { InserterPopover } from '../inserter-popover'; -import { EditorNotices } from '../notices'; import { storeName } from '../../store'; import { AddTrigger } from './add-trigger'; @@ -95,7 +94,6 @@ export function Workflow(): JSX.Element { return ( - } - content={} + content={ + <> + + + + } sidebar={} secondarySidebar={ showInserterSidebar && isInserterOpened ? : null @@ -96,6 +103,7 @@ window.addEventListener('DOMContentLoaded', () => { const root = document.getElementById('mailpoet_automation_editor'); if (root) { + registerApiErrorHandler(); initializeApi(); initializeCoreIntegration(); initializeMailPoetIntegration(); diff --git a/mailpoet/assets/js/src/automation/editor/store/actions.ts b/mailpoet/assets/js/src/automation/editor/store/actions.ts index 823690619b..4c8f366e4c 100644 --- a/mailpoet/assets/js/src/automation/editor/store/actions.ts +++ b/mailpoet/assets/js/src/automation/editor/store/actions.ts @@ -54,12 +54,12 @@ export function* save() { const data = yield apiFetch({ path: `/workflows/${workflow.id}`, method: 'PUT', - data: workflow, + data: { ...workflow }, }); return { type: 'SAVE', - workflow: data.data, + workflow: data?.data ?? workflow, } as const; } @@ -76,7 +76,7 @@ export function* activate() { return { type: 'ACTIVATE', - workflow: data.data, + workflow: data?.data ?? workflow, } as const; }