import React from 'react'; import {ArrowShapeUpFromLine} from '@gravity-ui/icons'; import {Button, Icon} from '@gravity-ui/uikit'; import {uiFactory} from '../../../uiFactory/uiFactory'; import {cn} from '../../../utils/cn'; import {getIllustration} from '../../../utils/illustrations'; import {isForbiddenError, isRedirectToAuth, isUnauthenticatedError} from '../../../utils/response'; import type {EmptyStateProps} from '../../EmptyState'; import {EMPTY_STATE_SIZES, EmptyState} from '../../EmptyState'; import {Unauthenticated} from '../401'; import {AccessDenied} from '../403'; import {ResponseErrorMessage, useErrorInfo} from '../ResponseError'; import i18n from '../i18n'; import {resolvePageErrorSubtitle} from './utils'; import './PageError.scss'; const b = cn('ydb-page-error'); type PageErrorIllustrationSize = keyof typeof EMPTY_STATE_SIZES; interface PageErrorProps extends Omit { title?: React.ReactNode; error: unknown; children?: React.ReactNode; errorPageTitle?: string; defaultMessage?: string; illustrationSize?: PageErrorIllustrationSize; } export function PageError({ title, description, error, children, size = 'm', illustrationSize, errorPageTitle, defaultMessage, className, pageTitle: callerPageTitle, ...restProps }: PageErrorProps) { const resolvedPageTitle = errorPageTitle ?? callerPageTitle; if (isRedirectToAuth(error)) { return null; } if (isUnauthenticatedError(error)) { return ( ); } if (isForbiddenError(error)) { return ( ); } if (error || description) { return ( ); } return {children}; } interface PageErrorContentProps extends Omit { title?: React.ReactNode; error: unknown; errorPageTitle?: string; defaultMessage?: string; illustrationSize?: PageErrorIllustrationSize; } function PageErrorContent({ title: titleProp, description, error, size = 'm', illustrationSize, errorPageTitle, defaultMessage, className, actions: callerActions, ...restProps }: PageErrorContentProps) { const { title: errorTitle, subtitle, showSubtitle, details, } = useErrorInfo(error, defaultMessage); const resolvedTitle = titleProp || errorTitle || i18n('error.title'); const {resolvedSubtitle, resolvedShowSubtitle} = resolvePageErrorSubtitle({ hasTitleOverride: Boolean(titleProp), errorTitle, resolvedTitleString: typeof resolvedTitle === 'string' ? resolvedTitle : undefined, subtitle, showSubtitle, details, }); const reportProblemUrl = React.useMemo(() => { if (!uiFactory.getReportProblemUrl) { return undefined; } return uiFactory.getReportProblemUrl({ errorTitle: typeof resolvedTitle === 'string' ? resolvedTitle : undefined, requestUrl: details?.requestUrl, traceId: details?.traceId, }); }, [resolvedTitle, details?.requestUrl, details?.traceId]); const mergedActions = React.useMemo(() => { const result: React.ReactNode[] = []; if (callerActions) { result.push(...callerActions); } if (reportProblemUrl) { result.push( , ); } return result.length > 0 ? result : undefined; }, [callerActions, reportProblemUrl]); const resolvedIllustrationSize = EMPTY_STATE_SIZES[illustrationSize ?? size]; const InternalErrorImage = getIllustration('InternalError'); return ( } title={resolvedTitle} description={ error ? ( ) : ( description ) } {...restProps} actions={mergedActions} size={size} contentPosition="top" pageTitle={errorPageTitle} className={b(null, className)} /> ); }