Download desktop/src/components/layout/StartupErrorView.tsx from chenbhao/codev: direct link, hf CLI and curl.
- Browser
- Download file 3.63 kB
-
https://huggingface.co/chenbhao/codev/resolve/e40073cc959cd4729bf4009662bca374c5c4e266/desktop/src/components/layout/StartupErrorView.tsx
- Command line
-
hf download hf://chenbhao/codev@e40073cc959cd4729bf4009662bca374c5c4e266/desktop/src/components/layout/StartupErrorView.tsx
-
curl -L -o StartupErrorView.tsx https://huggingface.co/chenbhao/codev/resolve/e40073cc959cd4729bf4009662bca374c5c4e266/desktop/src/components/layout/StartupErrorView.tsx
3.63 kB
| import { Copy, RefreshCw } from 'lucide-react' | |
| import { useMemo, useState } from 'react' | |
| import { useTranslation } from '../../i18n' | |
| import { Button } from '../shared/Button' | |
| import { DoctorPanel } from '../doctor/DoctorPanel' | |
| import { copyTextToClipboard } from '../chat/clipboard' | |
| const LOG_MARKER = '\n\nRecent server logs:\n' | |
| export function splitStartupError(error: string) { | |
| const markerIndex = error.indexOf(LOG_MARKER) | |
| if (markerIndex === -1) { | |
| return { | |
| message: error, | |
| logs: '', | |
| diagnostics: error, | |
| } | |
| } | |
| const message = error.slice(0, markerIndex).trim() | |
| const logs = error.slice(markerIndex + LOG_MARKER.length).trim() | |
| return { | |
| message, | |
| logs, | |
| diagnostics: `${message}\n\nRecent server logs:\n${logs}`, | |
| } | |
| } | |
| type StartupErrorViewProps = { | |
| error: string | |
| } | |
| export function StartupErrorView({ error }: StartupErrorViewProps) { | |
| const t = useTranslation() | |
| const { message, logs, diagnostics } = useMemo(() => splitStartupError(error), [error]) | |
| const [copied, setCopied] = useState(false) | |
| const handleCopy = async () => { | |
| const ok = await copyTextToClipboard(diagnostics) | |
| if (!ok) return | |
| setCopied(true) | |
| window.setTimeout(() => setCopied(false), 1600) | |
| } | |
| return ( | |
| <div className="h-screen flex items-center justify-center bg-[var(--color-surface)] px-6"> | |
| <section className="w-full max-w-3xl rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-container-low)] p-6 shadow-[var(--shadow-md)]"> | |
| <div className="flex flex-col gap-4"> | |
| <div> | |
| <h1 className="text-lg font-semibold text-[var(--color-text-primary)]"> | |
| {t('app.serverFailed')} | |
| </h1> | |
| <p className="mt-2 text-sm text-[var(--color-text-secondary)]"> | |
| {t('app.serverFailedHint')} | |
| </p> | |
| </div> | |
| <div className="rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4"> | |
| <div className="text-xs font-medium uppercase text-[var(--color-text-tertiary)]"> | |
| {t('app.startupError')} | |
| </div> | |
| <pre className="mt-2 max-h-28 overflow-auto whitespace-pre-wrap break-words font-mono text-xs text-[var(--color-error)]"> | |
| {message} | |
| </pre> | |
| </div> | |
| {logs ? ( | |
| <div className="rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4"> | |
| <div className="text-xs font-medium uppercase text-[var(--color-text-tertiary)]"> | |
| {t('app.serverLogs')} | |
| </div> | |
| <pre className="mt-2 max-h-64 overflow-auto whitespace-pre-wrap break-words font-mono text-xs leading-relaxed text-[var(--color-text-secondary)]"> | |
| {logs} | |
| </pre> | |
| </div> | |
| ) : null} | |
| <div className="flex flex-wrap items-center gap-2"> | |
| <Button | |
| type="button" | |
| variant="secondary" | |
| size="sm" | |
| icon={<Copy className="h-4 w-4" aria-hidden="true" />} | |
| onClick={handleCopy} | |
| > | |
| {copied ? t('app.copiedDiagnostics') : t('app.copyDiagnostics')} | |
| </Button> | |
| <Button | |
| type="button" | |
| variant="ghost" | |
| size="sm" | |
| icon={<RefreshCw className="h-4 w-4" aria-hidden="true" />} | |
| onClick={() => window.location.reload()} | |
| > | |
| {t('common.retry')} | |
| </Button> | |
| </div> | |
| <DoctorPanel compact /> | |
| </div> | |
| </section> | |
| </div> | |
| ) | |
| } | |