From 4f822f0d7d10554e642c18a4e41f143b5996cadc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0t=C4=9Bp=C3=A1n=20Gran=C3=A1t?= Date: Tue, 11 Jun 2024 17:20:33 +0200 Subject: [PATCH 1/7] fix: improve in-context errors --- packages/web/package.json | 3 +- .../src/package/ui/KeyDialog/ErrorAlert.tsx | 89 + .../web/src/package/ui/KeyDialog/KeyForm.tsx | 24 +- .../web/src/package/ui/KeyDialog/Link.tsx | 26 + .../ui/KeyDialog/dialogContext/index.ts | 4 +- .../web/src/package/ui/client/HttpError.ts | 36 + .../package/ui/client/apiSchema.generated.ts | 6943 ++++++++--------- packages/web/src/package/ui/client/client.ts | 51 +- pnpm-lock.yaml | 34 +- 9 files changed, 3646 insertions(+), 3564 deletions(-) create mode 100644 packages/web/src/package/ui/KeyDialog/ErrorAlert.tsx create mode 100644 packages/web/src/package/ui/KeyDialog/Link.tsx create mode 100644 packages/web/src/package/ui/client/HttpError.ts diff --git a/packages/web/package.json b/packages/web/package.json index b0cda46243..819234a919 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -30,7 +30,7 @@ "test": "jest --collect-coverage", "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", "preview": "vite preview", - "schema": "openapi-typescript http://localhost:8202/v3/api-docs/Accessible%20with%20API%20key --output ./src/ui/client/apiSchema.generated.ts", + "schema": "openapi-typescript 'http://localhost:8080/v3/api-docs/Accessible%20with%20Project%20API%20key%20(V2)' --output ./src/package/ui/client/apiSchema.generated.ts", "tsc": "tsc --noEmit", "clean": "rm -rf dist lib coverage" }, @@ -69,6 +69,7 @@ "fast-text-encoding": "^1.0.6", "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", + "openapi-typescript": "^6.7.6", "react": "^18.3.1", "react-dom": "^18.3.1", "react-query": "^3.39.3", diff --git a/packages/web/src/package/ui/KeyDialog/ErrorAlert.tsx b/packages/web/src/package/ui/KeyDialog/ErrorAlert.tsx new file mode 100644 index 0000000000..15eca36ab4 --- /dev/null +++ b/packages/web/src/package/ui/KeyDialog/ErrorAlert.tsx @@ -0,0 +1,89 @@ +import { Alert, AlertTitle } from '@mui/material'; +import { HttpError } from '../client/HttpError'; +import { useDialogContext } from './dialogContext'; +import { NewTabLink } from './Link'; + +type Props = { + error: HttpError | Error; + severity?: 'error' | 'info'; +}; + +export const ErrorAlert = ({ error, severity = 'error' }: Props) => { + const apiUrl = useDialogContext((c) => c.uiProps.apiUrl); + + return ( + + {error instanceof HttpError + ? getErrorContent(error, apiUrl) + : error.message} + + ); +}; + +function DocsInContext() { + return ( + + Learn more in Docs + + ); +} + +function DocsAPIKeys() { + return ( + + Learn more in Docs + + ); +} + +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 'api_url_not_specified': + return ( + <> + Oops... I miss the API url + Add it in the code or via the chrome plugin. + + ); + + case 'api_key_not_specified': + return ( + <> + Oops... I miss the API key + Add it in the code or via the chrome plugin. + + ); + + 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 'fetch_error': + return `Failed to fetch (${apiUrl})`; + + default: + return message; + } +} diff --git a/packages/web/src/package/ui/KeyDialog/KeyForm.tsx b/packages/web/src/package/ui/KeyDialog/KeyForm.tsx index 774036d9fa..c8505d2379 100644 --- a/packages/web/src/package/ui/KeyDialog/KeyForm.tsx +++ b/packages/web/src/package/ui/KeyDialog/KeyForm.tsx @@ -11,6 +11,8 @@ import { NsSelect } from './NsSelect'; import { TOLGEE_RESTRICT_ATTRIBUTE } from '../../constants'; import { Tags } from './Tags/Tags'; import { PluralFormCheckbox } from './PluralFormCheckbox'; +import { ErrorAlert } from './ErrorAlert'; +import { HttpError } from '../client/HttpError'; const ScContainer = styled('div')` font-family: Rubik, Roboto, Arial; @@ -73,11 +75,6 @@ const ScRestriction = styled('div')` color: ${({ theme }) => theme.palette.text.secondary}; `; -const ScError = styled('div')` - padding-top: 16px; - color: red; -`; - export const KeyForm = () => { const theme = useTheme(); const { setUseBrowserWindow, onClose, onSave, setSelectedNs } = @@ -145,7 +142,6 @@ export const KeyForm = () => { )} {!loading && } - Key {input} @@ -153,41 +149,35 @@ export const KeyForm = () => { {!keyExists && ready && " (key doesn't exist yet)"} - - {ready && ( Tags )} - {ready && viewPluralCheckbox && } - {!error && ( )} - {screenshotsView && ready && ( )} - {formDisabled && ready && ( - - Modification is restricted due to missing permissions. - + )} - - {generalError && {generalError}} + {generalError && }