import { useEffect, useState } from 'react';
import { Alert, AlertTitle, Box, Button } from '@mui/material';
import { HttpError, isHttpError } from '../client/HttpError';
import { useDialogContext } from './dialogContext';
import { NewTabLink } from './Link';
import { createUrl } from '../../tools/url';
import { detectExtension, openPlugin } from '../../tools/extension';
import { CHROME_EXTENSION_LINK } from '../../constants';
type Props = {
error: HttpError | Error;
severity?: 'error' | 'info';
};
export const ErrorAlert = ({ error, severity }: Props) => {
const apiUrl = useDialogContext((c) => c.uiProps.apiUrl);
return (
{isHttpError(error)
? getErrorContent(error, createUrl(apiUrl).toString())
: error.message}
);
};
// Missing credentials, in the page or in the extension, is the normal state of a page nobody has connected yet,
// not a failure.
export function severityFor(error: HttpError | Error): 'error' | 'info' {
return isHttpError(error) &&
(error.code === 'api_key_not_specified' ||
error.code === 'extension_session_missing' ||
error.code === 'extension_editing_off')
? 'info'
: 'error';
}
function DocsInContext() {
return (
Learn more in Docs
);
}
function OpenExtension() {
const [present, setPresent] = useState();
useEffect(() => {
let mounted = true;
detectExtension().then((found) => mounted && setPresent(found));
return () => {
mounted = false;
};
}, []);
if (present === undefined) {
return null;
}
return (
{present ? (
) : (
)}
);
}
function DocsAPIKeys() {
return (
Learn more in Docs
);
}
export function getErrorContent(
{ code, params, message }: HttpError,
apiUrl: string
) {
switch (code) {
case 'operation_not_permitted':
return (
<>
Operation not permitted
{Boolean(params?.length) && 'Missing scopes: ' + params?.join(', ')}
>
);
case 'invalid_project_api_key':
return (
<>
Invalid API key
Check it in the code or in the chrome plugin.
>
);
case 'unauthenticated':
case 'invalid_jwt_token':
case 'expired_jwt_token':
case 'general_jwt_error':
case 'invalid_oauth_token':
case 'oauth_token_expired':
case 'extension_session_missing':
return (
<>
You're not signed in
Sign in again in the Tolgee plugin to keep editing.
>
);
case 'extension_request_too_large':
return (
<>
Image is too large to upload
This image is too large for the Tolgee plugin to send. Pick a smaller
one.
>
);
case 'api_url_not_specified':
return (
<>
Oops... I miss the API url
Add it in the code or via the chrome plugin.
>
);
case 'api_url_not_valid':
return (
<>
API url is not correct ({apiUrl})
Check it in the code or in the chrome plugin.
>
);
case 'api_key_not_specified':
return (
<>
Sign in to make changes
To edit strings here, sign in with the Tolgee browser extension or add
an API key to the Tolgee configuration.
>
);
case 'extension_editing_off':
return (
<>
In-context editing is switched off
You switched editing off for this page in the Tolgee plugin. Turn it
on to edit here.
>
);
case 'project_id_not_specified':
return (
<>
Oops... I miss the project id
An OAuth token or PAT carries no project, so projectId must be set in
the Tolgee configuration.
>
);
case 'project_not_found':
return (
<>
Project not found
The configured project doesn't exist on this server, or your account
can't access it. Check the projectId in the Tolgee configuration, or
ask for access.
>
);
case 'permissions_not_sufficient_to_edit':
return (
<>
Sorry, you don't have permissions to make changes
Update your API key or ask admin for more permissions
>
);
case 'operation_not_permitted_in_read_only_mode':
return (
<>
Read-only mode
This branch is protected or your access is read-only.
>
);
case 'branch_not_found':
return (
<>
Branch not found
Check the branch name or switch to an existing branch.
>
);
case 'fetch_error':
return `Failed to fetch (${apiUrl})`;
default:
return message;
}
}