-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(atomic): add error handling for atomic-commerce queries (#3917)
* Refactor `QueryErrorCommon` into multiple functional components * Create new `atomic-commerce-query-error` component For now it does not handle any commerce API specific errors. But it should at least have the "catch all" which is "Something went wrong" with a "Show more" button https://coveord.atlassian.net/browse/KIT-3034 --------- Co-authored-by: Frederic Beaudoin <[email protected]>
- Loading branch information
1 parent
adff180
commit 39270e5
Showing
22 changed files
with
542 additions
and
202 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 1 addition & 0 deletions
1
...omic/src/components/commerce/atomic-commerce-query-error/atomic-commerce-query-error.pcss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
@import '../../../global/global.pcss'; |
115 changes: 115 additions & 0 deletions
115
...tomic/src/components/commerce/atomic-commerce-query-error/atomic-commerce-query-error.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
import {isNullOrUndefined} from '@coveo/bueno'; | ||
import { | ||
Search, | ||
ProductListing, | ||
SearchState, | ||
ProductListingState, | ||
buildProductListing, | ||
buildSearch, | ||
} from '@coveo/headless/commerce'; | ||
import {Component, h, State} from '@stencil/core'; | ||
import {AriaLiveRegion} from '../../../utils/accessibility-utils'; | ||
import { | ||
BindStateToController, | ||
InitializableComponent, | ||
InitializeBindings, | ||
} from '../../../utils/initialization-utils'; | ||
import {QueryErrorContainer} from '../../common/query-error/container'; | ||
import {QueryErrorDescription} from '../../common/query-error/description'; | ||
import {QueryErrorDetails} from '../../common/query-error/details'; | ||
import {QueryErrorGuard} from '../../common/query-error/guard'; | ||
import {QueryErrorIcon} from '../../common/query-error/icon'; | ||
import {QueryErrorLink} from '../../common/query-error/link'; | ||
import {QueryErrorShowMore} from '../../common/query-error/show-more'; | ||
import {QueryErrorTitle} from '../../common/query-error/title'; | ||
import {getAriaMessageFromErrorType} from '../../common/query-error/utils'; | ||
import {CommerceBindings} from '../atomic-commerce-interface/atomic-commerce-interface'; | ||
|
||
/** | ||
* The `atomic-commerce-query-error` component handles fatal errors when performing a query on the Commerce API. When the error is known, it displays a link to relevant documentation for debugging purposes. When the error is unknown, it displays a small text area with the JSON content of the error. | ||
* | ||
* @part icon - The SVG related to the error. | ||
* @part title - The title of the error. | ||
* @part description - A description of the error. | ||
* @part doc-link - A link to the relevant documentation. | ||
* @part more-info-btn - A button to request additional error information. | ||
* @part error-info - Additional error information. | ||
* | ||
* @internal | ||
*/ | ||
@Component({ | ||
tag: 'atomic-commerce-query-error', | ||
styleUrl: 'atomic-commerce-query-error.pcss', | ||
shadow: true, | ||
}) | ||
export class AtomicQueryError | ||
implements InitializableComponent<CommerceBindings> | ||
{ | ||
@InitializeBindings() public bindings!: CommerceBindings; | ||
public searchOrListing!: Search | ProductListing; | ||
|
||
@BindStateToController('searchOrListing') | ||
@State() | ||
private searchOrListingState!: SearchState | ProductListingState; | ||
@State() public error!: Error; | ||
@State() showMoreInfo = false; | ||
|
||
@AriaLiveRegion('commerce-query-error') | ||
protected ariaMessage!: string; | ||
|
||
public initialize() { | ||
if (this.bindings.interfaceElement.type === 'product-listing') { | ||
this.searchOrListing = buildProductListing(this.bindings.engine); | ||
} else { | ||
this.searchOrListing = buildSearch(this.bindings.engine); | ||
} | ||
} | ||
|
||
public render() { | ||
const {error} = this.searchOrListingState; | ||
|
||
const { | ||
bindings: { | ||
i18n, | ||
engine: { | ||
configuration: {organizationId, organizationEndpoints, platformUrl}, | ||
}, | ||
}, | ||
} = this; | ||
const hasError = !isNullOrUndefined(error); | ||
const actualPlatformUrl = | ||
organizationEndpoints?.platform || platformUrl || ''; | ||
if (hasError) { | ||
this.ariaMessage = getAriaMessageFromErrorType( | ||
i18n, | ||
organizationId, | ||
actualPlatformUrl, | ||
error?.type | ||
); | ||
} | ||
return ( | ||
<QueryErrorGuard hasError={hasError}> | ||
<QueryErrorContainer> | ||
<QueryErrorIcon errorType={error?.type} /> | ||
<QueryErrorTitle | ||
errorType={error?.type} | ||
i18n={i18n} | ||
organizationId={organizationId} | ||
/> | ||
<QueryErrorDescription | ||
i18n={i18n} | ||
organizationId={organizationId} | ||
url={organizationEndpoints?.platform || platformUrl || ''} | ||
errorType={error?.type} | ||
/> | ||
<QueryErrorShowMore | ||
link={<QueryErrorLink i18n={i18n} errorType={error?.type} />} | ||
onShowMore={() => (this.showMoreInfo = !this.showMoreInfo)} | ||
i18n={i18n} | ||
/> | ||
<QueryErrorDetails error={error} show={this.showMoreInfo} /> | ||
</QueryErrorContainer> | ||
</QueryErrorGuard> | ||
); | ||
} | ||
} |
5 changes: 5 additions & 0 deletions
5
packages/atomic/src/components/common/query-error/container.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import {FunctionalComponent, h} from '@stencil/core'; | ||
|
||
export const QueryErrorContainer: FunctionalComponent = (_, children) => { | ||
return <div class="text-center p-8">{children}</div>; | ||
}; |
20 changes: 20 additions & 0 deletions
20
packages/atomic/src/components/common/query-error/description.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import {FunctionalComponent, h} from '@stencil/core'; | ||
import {i18n} from 'i18next'; | ||
import {getErrorDescriptionFromErrorType} from './utils'; | ||
|
||
interface QueryErrorDescriptionProps { | ||
errorType?: string; | ||
i18n: i18n; | ||
url: string; | ||
organizationId: string; | ||
} | ||
|
||
export const QueryErrorDescription: FunctionalComponent< | ||
QueryErrorDescriptionProps | ||
> = ({errorType, i18n, url, organizationId}) => { | ||
return ( | ||
<p part="description" class="text-lg text-neutral-dark mt-2.5"> | ||
{getErrorDescriptionFromErrorType(i18n, organizationId, url, errorType)} | ||
</p> | ||
); | ||
}; |
22 changes: 22 additions & 0 deletions
22
packages/atomic/src/components/common/query-error/details.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import {FunctionalComponent, h} from '@stencil/core'; | ||
|
||
interface QueryErrorDetailsProps { | ||
error: unknown; | ||
show: boolean; | ||
} | ||
export const QueryErrorDetails: FunctionalComponent<QueryErrorDetailsProps> = ({ | ||
error, | ||
show, | ||
}) => { | ||
if (!show) { | ||
return; | ||
} | ||
return ( | ||
<pre | ||
part="error-info" | ||
class="text-left border border-neutral bg-neutral-light p-3 rounded mt-8 whitespace-pre-wrap" | ||
> | ||
<code>{JSON.stringify(error, null, 2)}</code> | ||
</pre> | ||
); | ||
}; |
16 changes: 16 additions & 0 deletions
16
packages/atomic/src/components/common/query-error/guard.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import {Fragment, FunctionalComponent, h} from '@stencil/core'; | ||
|
||
interface QueryErrorGuardProps { | ||
hasError: boolean; | ||
} | ||
|
||
export const QueryErrorGuard: FunctionalComponent<QueryErrorGuardProps> = ( | ||
{hasError}, | ||
children | ||
) => { | ||
if (!hasError) { | ||
return; | ||
} | ||
|
||
return <Fragment>{children}</Fragment>; | ||
}; |
40 changes: 40 additions & 0 deletions
40
packages/atomic/src/components/common/query-error/icon.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import {FunctionalComponent, h} from '@stencil/core'; | ||
import CannotAccess from '../../../images/cannot-access.svg'; | ||
import Indexing from '../../../images/indexing.svg'; | ||
import NoConnection from '../../../images/no-connection.svg'; | ||
import SearchInactive from '../../../images/search-inactive.svg'; | ||
import SomethingWrong from '../../../images/something-wrong.svg'; | ||
import {KnownErrorType} from './known-error-types'; | ||
|
||
interface QueryErrorIconProps { | ||
errorType?: string; | ||
} | ||
|
||
export const QueryErrorIcon: FunctionalComponent<QueryErrorIconProps> = ({ | ||
errorType, | ||
}) => { | ||
const getIconFromErrorType = () => { | ||
switch (errorType as KnownErrorType) { | ||
case 'Disconnected': | ||
return NoConnection; | ||
|
||
case 'NoEndpointsException': | ||
return Indexing; | ||
|
||
case 'InvalidTokenException': | ||
return CannotAccess; | ||
case 'OrganizationIsPausedException': | ||
return SearchInactive; | ||
default: | ||
return SomethingWrong; | ||
} | ||
}; | ||
|
||
return ( | ||
<atomic-icon | ||
part="icon" | ||
icon={getIconFromErrorType()} | ||
class="w-1/2 max-w-lg" | ||
></atomic-icon> | ||
); | ||
}; |
5 changes: 5 additions & 0 deletions
5
packages/atomic/src/components/common/query-error/known-error-types.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export type KnownErrorType = | ||
| 'Disconnected' | ||
| 'NoEndpointsException' | ||
| 'InvalidTokenException' | ||
| 'OrganizationIsPausedException'; |
34 changes: 34 additions & 0 deletions
34
packages/atomic/src/components/common/query-error/link.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import {FunctionalComponent, h} from '@stencil/core'; | ||
import {i18n} from 'i18next'; | ||
import {KnownErrorType} from './known-error-types'; | ||
|
||
interface QueryErrorLinkProps { | ||
errorType?: string; | ||
i18n: i18n; | ||
} | ||
|
||
export const QueryErrorLink: FunctionalComponent<QueryErrorLinkProps> = ({ | ||
errorType, | ||
i18n, | ||
}) => { | ||
const getErrorLink = () => { | ||
switch (errorType as KnownErrorType) { | ||
case 'NoEndpointsException': | ||
return 'https://docs.coveo.com/en/mcc80216'; | ||
case 'InvalidTokenException': | ||
return 'https://docs.coveo.com/en/102'; | ||
case 'OrganizationIsPausedException': | ||
return 'https://docs.coveo.com/l6af0467'; | ||
default: | ||
return null; | ||
} | ||
}; | ||
|
||
const link = getErrorLink(); | ||
|
||
return link ? ( | ||
<a href={link} part="doc-link" class="btn-primary p-3 mt-10 inline-block"> | ||
{i18n.t('coveo-online-help')} | ||
</a> | ||
) : null; | ||
}; |
Oops, something went wrong.