From d0738754f7d60636b244a9f82ccd32db478421c2 Mon Sep 17 00:00:00 2001 From: Luiz Kowalski Date: Thu, 12 Sep 2024 15:10:50 -0300 Subject: [PATCH] Title Optimization: improve error handling (#39340) * Save the error object so we can use it to display the error message * Move error message to it's own component * Show the provided error message when the error is related to moderation * Use an error notice to show the errors * Show FairUsageNotice when the error is a quota exceeded one * Changelog * Use the QuotaExceededMessage component so we handle automatically the free and paid plan quotas * Support JSON error handling * Reuse the generic error message * Change code to trust the message provided by the error object, when available * Do not show retry button when the error will not go away * Include type suggestions --- ...ai-handle-errors-on-title-improvement-tool | 4 + .../components/title-optimization/index.tsx | 83 +++++++++++++++---- 2 files changed, 72 insertions(+), 15 deletions(-) create mode 100644 projects/plugins/jetpack/changelog/update-jetpack-ai-handle-errors-on-title-improvement-tool diff --git a/projects/plugins/jetpack/changelog/update-jetpack-ai-handle-errors-on-title-improvement-tool b/projects/plugins/jetpack/changelog/update-jetpack-ai-handle-errors-on-title-improvement-tool new file mode 100644 index 0000000000000..fa385b0412fcc --- /dev/null +++ b/projects/plugins/jetpack/changelog/update-jetpack-ai-handle-errors-on-title-improvement-tool @@ -0,0 +1,4 @@ +Significance: patch +Type: other + +Title Optimization: properly handle errors and show the correct UI for each. diff --git a/projects/plugins/jetpack/extensions/plugins/ai-assistant-plugin/components/title-optimization/index.tsx b/projects/plugins/jetpack/extensions/plugins/ai-assistant-plugin/components/title-optimization/index.tsx index c272caf73a022..01acfac40d607 100644 --- a/projects/plugins/jetpack/extensions/plugins/ai-assistant-plugin/components/title-optimization/index.tsx +++ b/projects/plugins/jetpack/extensions/plugins/ai-assistant-plugin/components/title-optimization/index.tsx @@ -1,15 +1,23 @@ /** * External dependencies */ -import { useAiSuggestions } from '@automattic/jetpack-ai-client'; +import { + useAiSuggestions, + RequestingErrorProps, + ERROR_QUOTA_EXCEEDED, + ERROR_NETWORK, + ERROR_SERVICE_UNAVAILABLE, + ERROR_UNCLEAR_PROMPT, +} from '@automattic/jetpack-ai-client'; import { useAnalytics } from '@automattic/jetpack-shared-extension-utils'; -import { Button, Spinner, ExternalLink } from '@wordpress/components'; +import { Button, Spinner, ExternalLink, Notice } from '@wordpress/components'; import { useDispatch } from '@wordpress/data'; import { useState, useCallback } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ +import QuotaExceededMessage from '../../../../blocks/ai-assistant/components/quota-exceeded-message'; import { getFeatureAvailability } from '../../../../blocks/ai-assistant/lib/utils/get-feature-availability'; import useAutoSaveAndRedirect from '../../../../shared/use-autosave-and-redirect'; import usePostContent from '../../hooks/use-post-content'; @@ -25,6 +33,43 @@ const isKeywordsFeatureAvailable = getFeatureAvailability( 'ai-title-optimization-keywords-support' ); +/** + * A generic error message that we can reuse. + */ +const genericErrorMessage = __( + 'The generation of your suggested titles failed. Please try again.', + 'jetpack' +); + +const ERROR_JSON_PARSE = 'json-parse-error'; +type TitleOptimizationJSONError = { + code: typeof ERROR_JSON_PARSE; + message: string; +}; + +type TitleOptimizationError = RequestingErrorProps | TitleOptimizationJSONError; + +const TitleOptimizationErrorMessage = ( { error }: { error: TitleOptimizationError } ) => { + if ( error.code === ERROR_QUOTA_EXCEEDED ) { + return ( +
+ +
+ ); + } + + // Use the provided message, if available, otherwise use the generic error message + const errorMessage = error.message ? error.message : genericErrorMessage; + + return ( +
+ + { errorMessage } + +
+ ); +}; + export default function TitleOptimization( { placement, busy, @@ -58,7 +103,7 @@ export default function TitleOptimization( { const [ isTitleOptimizationModalVisible, setIsTitleOptimizationModalVisible ] = useState( false ); const [ generating, setGenerating ] = useState( false ); const [ options, setOptions ] = useState( [] ); - const [ error, setError ] = useState( false ); + const [ error, setError ] = useState< TitleOptimizationError | null >( null ); const [ optimizationKeywords, setOptimizationKeywords ] = useState( '' ); const { editPost } = useDispatch( 'core/editor' ); const { autosave } = useAutoSaveAndRedirect(); @@ -80,7 +125,11 @@ export default function TitleOptimization( { setOptions( parsedContent ); setSelected( parsedContent?.[ 0 ]?.title ); } catch ( e ) { - // Do nothing + const jsonError: TitleOptimizationJSONError = { + code: ERROR_JSON_PARSE, + message: genericErrorMessage, + }; + setError( jsonError ); } }, [ increaseAiAssistantRequestsCount ] @@ -88,8 +137,8 @@ export default function TitleOptimization( { const { request, stopSuggestion } = useAiSuggestions( { onDone: handleDone, - onError: () => { - setError( true ); + onError: ( e: RequestingErrorProps ) => { + setError( e ); setGenerating( false ); }, } ); @@ -127,7 +176,7 @@ export default function TitleOptimization( { }, [ handleRequest, toggleTitleOptimizationModal ] ); const handleTryAgain = useCallback( () => { - setError( false ); + setError( null ); handleRequest( true ); // retry the generation }, [ handleRequest ] ); @@ -160,6 +209,14 @@ export default function TitleOptimization( { stopSuggestion(); }, [ stopSuggestion, toggleTitleOptimizationModal ] ); + // When can we retry? + const showTryAgainButton = + error && + [ ERROR_JSON_PARSE, ERROR_NETWORK, ERROR_SERVICE_UNAVAILABLE, ERROR_UNCLEAR_PROMPT ].includes( + error.code + ); + const showReplaceTitleButton = ! error; + return (

{ sidebarDescription }

@@ -190,12 +247,7 @@ export default function TitleOptimization( { ) : ( <> { error ? ( -
- { __( - 'The generation of your suggested titles failed. Please try again.', - 'jetpack' - ) } -
+ ) : ( <> { isKeywordsFeatureAvailable && ( @@ -226,11 +278,12 @@ export default function TitleOptimization( { - { error ? ( + { showTryAgainButton && ( - ) : ( + ) } + { showReplaceTitleButton && (