fix: prevent [object Object] rendering in 25 frontend components
Replace direct {error} JSX rendering with typeof check + .message fallback.
When error is an object (not a string), React showed [object Object].
Now renders error.message or fallback string.
This commit is contained in:
@@ -113,7 +113,7 @@ export function AddressList({ entityType, entityId }: AddressListProps) {
|
||||
</div>
|
||||
|
||||
{error && (
|
||||
<div className="p-3 text-sm text-red-700 bg-red-50 rounded-lg">{error}</div>
|
||||
<div className="p-3 text-sm text-red-700 bg-red-50 rounded-lg">{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}</div>
|
||||
)}
|
||||
|
||||
{showForm && (
|
||||
|
||||
@@ -179,7 +179,7 @@ export function ChatWindow({ sessionId, agentId, className, compact }: ChatWindo
|
||||
</div>
|
||||
)}
|
||||
<ActivityIndicator status={activity} />
|
||||
{error && <div className="mb-4 text-sm text-red-600">{error}</div>}
|
||||
{error && <div className="mb-4 text-sm text-red-600">{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}</div>}
|
||||
</div>
|
||||
<div className={clsx('border-t border-secondary-200', compact ? 'p-2' : 'p-4')}>
|
||||
<div className="flex items-end gap-2">
|
||||
|
||||
@@ -347,7 +347,7 @@ export function SessionList({ activeSessionId, onSelectSession, isSidebar, class
|
||||
|
||||
return (
|
||||
<div className={clsx('flex flex-col h-full', className)}>
|
||||
{error && <div className="p-2 text-xs text-red-600">{error}</div>}
|
||||
{error && <div className="p-2 text-xs text-red-600">{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}</div>}
|
||||
<div
|
||||
className="flex-1 overflow-y-auto p-2"
|
||||
onContextMenu={(e) => {
|
||||
|
||||
@@ -138,7 +138,7 @@ export function IcsControls({ calendar, onImported }: IcsControlsProps) {
|
||||
)}
|
||||
{error && (
|
||||
<span className="text-xs text-danger-700" data-testid="ics-error">
|
||||
{error}
|
||||
{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -112,7 +112,7 @@ export function ResourceBooking({ entry, resources, onBooked }: ResourceBookingP
|
||||
className="text-xs text-danger-700 bg-danger-50 border border-danger-200 rounded-md p-2"
|
||||
data-testid="resource-error"
|
||||
>
|
||||
{error}
|
||||
{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -141,7 +141,7 @@ export function SharingSettings({ calendar }: SharingSettingsProps) {
|
||||
className="text-xs text-danger-700 bg-danger-50 border border-danger-200 rounded-md p-2"
|
||||
data-testid="sharing-error"
|
||||
>
|
||||
{error}
|
||||
{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}
|
||||
</div>
|
||||
)}
|
||||
{message && (
|
||||
|
||||
@@ -212,7 +212,7 @@ export function TaskDetailPanel({ entry, onClose, onChanged }: TaskDetailPanelPr
|
||||
className="text-sm text-danger-700 bg-danger-50 border border-danger-200 rounded-md p-2"
|
||||
data-testid="task-detail-error"
|
||||
>
|
||||
{error}
|
||||
{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -583,7 +583,7 @@ function PolicyForm({ initial, entityType, onSave, onCancel }: PolicyFormProps)
|
||||
{/* Error */}
|
||||
{error && (
|
||||
<p className="text-sm text-danger-600" role="alert">
|
||||
{error}
|
||||
{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}
|
||||
</p>
|
||||
)}
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ export function AskKnowledge() {
|
||||
})}
|
||||
</div>
|
||||
|
||||
{error && <p className="text-sm text-danger-600" role="alert">{error}</p>}
|
||||
{error && <p className="text-sm text-danger-600" role="alert">{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}</p>}
|
||||
|
||||
{loading && (
|
||||
<div className="flex items-center justify-center py-10" role="status" aria-label={t('common.loading')}>
|
||||
|
||||
@@ -236,7 +236,7 @@ export function KnowledgeGraph() {
|
||||
)}
|
||||
{!loading && error && (
|
||||
<div className="py-8 text-center">
|
||||
<p className="text-danger-600 text-sm mb-4">{error}</p>
|
||||
<p className="text-danger-600 text-sm mb-4">{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}</p>
|
||||
<Button variant="secondary" onClick={() => void load()}>
|
||||
{t('common.retry')}
|
||||
</Button>
|
||||
|
||||
@@ -552,7 +552,7 @@ export function MessageSidebar() {
|
||||
<p className="text-sm text-secondary-400 text-center py-4">Laden...</p>
|
||||
)}
|
||||
{error && (
|
||||
<p className="text-sm text-red-500 text-center py-2">{error}</p>
|
||||
<p className="text-sm text-red-500 text-center py-2">{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}</p>
|
||||
)}
|
||||
{!loading && conversations.length === 0 && !error && (
|
||||
<p className="text-sm text-secondary-400 text-center py-4">Keine Konversationen</p>
|
||||
|
||||
@@ -103,7 +103,7 @@ export function LabelManager() {
|
||||
if (error) {
|
||||
return (
|
||||
<div className="p-4 bg-danger-50 border border-danger-200 rounded-md" role="alert" data-testid="label-manager-error">
|
||||
<p className="text-sm text-danger-700">{error}</p>
|
||||
<p className="text-sm text-danger-700">{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ export function PgpSettings() {
|
||||
if (error) {
|
||||
return (
|
||||
<div className="p-4 bg-danger-50 border border-danger-200 rounded-md" role="alert" data-testid="pgp-settings-error">
|
||||
<p className="text-sm text-danger-700">{error}</p>
|
||||
<p className="text-sm text-danger-700">{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ export function RuleEditor({ accountId }: { accountId: string }) {
|
||||
if (error) {
|
||||
return (
|
||||
<div className="p-4 bg-danger-50 border border-danger-200 rounded-md" role="alert" data-testid="rule-editor-error">
|
||||
<p className="text-sm text-danger-700">{error}</p>
|
||||
<p className="text-sm text-danger-700">{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ export function SignatureManager() {
|
||||
if (error) {
|
||||
return (
|
||||
<div className="p-4 bg-danger-50 border border-danger-200 rounded-md" role="alert" data-testid="signature-manager-error">
|
||||
<p className="text-sm text-danger-700">{error}</p>
|
||||
<p className="text-sm text-danger-700">{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ export function TemplatePicker({ onSelect }: TemplatePickerProps) {
|
||||
if (error) {
|
||||
return (
|
||||
<div className="p-4 bg-danger-50 border border-danger-200 rounded-md" role="alert" data-testid="template-picker-error">
|
||||
<p className="text-sm text-danger-700">{error}</p>
|
||||
<p className="text-sm text-danger-700">{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ export function CsvImportDialog({ open, onClose, onSuccess }: CsvImportDialogPro
|
||||
aria-label="CSV-Datei auswählen"
|
||||
data-testid="csv-file-input"
|
||||
/>
|
||||
{error && <p className="mt-2 text-sm text-danger-600" role="alert">{error}</p>}
|
||||
{error && <p className="mt-2 text-sm text-danger-600" role="alert">{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}</p>}
|
||||
</div>
|
||||
|
||||
{previewData && previewData.rows.length > 0 && (
|
||||
|
||||
@@ -43,7 +43,7 @@ export const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
||||
/>
|
||||
{error && (
|
||||
<p id={errorId} className="mt-1 text-sm text-danger-600" role="alert">
|
||||
{error}
|
||||
{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}
|
||||
</p>
|
||||
)}
|
||||
{helperText && !error && (
|
||||
|
||||
@@ -54,7 +54,7 @@ export const Select = React.forwardRef<HTMLSelectElement, SelectProps>(
|
||||
</select>
|
||||
{error && (
|
||||
<p id={errorId} className="mt-1 text-sm text-danger-600" role="alert">
|
||||
{error}
|
||||
{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}
|
||||
</p>
|
||||
)}
|
||||
{helperText && !error && (
|
||||
|
||||
@@ -180,7 +180,7 @@ export function WikiBrowser({ selectedArticleId, onSelectArticle }: WikiBrowserP
|
||||
<Loader2 className="animate-spin h-6 w-6 text-primary-500" aria-hidden="true" />
|
||||
</div>
|
||||
)}
|
||||
{!loading && error && <p className="text-sm text-danger-600 p-3">{error}</p>}
|
||||
{!loading && error && <p className="text-sm text-danger-600 p-3">{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}</p>}
|
||||
{!loading && !error && (
|
||||
<>
|
||||
<button
|
||||
|
||||
@@ -135,7 +135,7 @@ export function AiChatPanel({ windowTitle, windowType }: AiChatPanelProps) {
|
||||
<div className="flex-1 flex items-center justify-center p-4 text-center">
|
||||
<div>
|
||||
<Sparkles className="w-8 h-8 text-secondary-300 mx-auto mb-2" />
|
||||
<p className="text-sm text-secondary-500">{error}</p>
|
||||
<p className="text-sm text-secondary-500">{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -180,7 +180,7 @@ export function AiChatPanel({ windowTitle, windowType }: AiChatPanelProps) {
|
||||
</div>
|
||||
)}
|
||||
{error && (
|
||||
<div className="text-xs text-danger-600 px-2 py-1">{error}</div>
|
||||
<div className="text-xs text-danger-600 px-2 py-1">{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -547,7 +547,7 @@ function JsonField({ label, value, onChange }: JsonFieldProps) {
|
||||
/>
|
||||
{error && (
|
||||
<p className="mt-1 text-sm text-danger-600" role="alert">
|
||||
{error}
|
||||
{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -49,7 +49,7 @@ function ProviderTab() {
|
||||
<h2 className="text-lg font-semibold">Anbieter</h2>
|
||||
<button onClick={() => { setShowForm(!showForm); setEditId(null); setForm({ name: '', provider_type: 'openai', api_key: '', base_url: '', is_default: false }); }} className="px-3 py-1.5 text-sm bg-primary-600 text-white rounded-lg hover:bg-primary-700">+ Hinzufügen</button>
|
||||
</div>
|
||||
{error && <div className="text-sm text-red-600">{error}</div>}
|
||||
{error && <div className="text-sm text-red-600">{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}</div>}
|
||||
{showForm && (
|
||||
<div className="border border-secondary-200 rounded-lg p-4 space-y-3 bg-secondary-50">
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
@@ -134,7 +134,7 @@ function PresetTab() {
|
||||
<h2 className="text-lg font-semibold">Modelle & Presets</h2>
|
||||
<button onClick={() => { setShowForm(!showForm); setEditId(null); setForm({ name: '', model_id: '', provider_id: '', temperature: 0.7, max_tokens: 2048, top_p: 1.0, system_prompt: '' }); }} className="px-3 py-1.5 text-sm bg-primary-600 text-white rounded-lg">+ Hinzufügen</button>
|
||||
</div>
|
||||
{error && <div className="text-sm text-red-600">{error}</div>}
|
||||
{error && <div className="text-sm text-red-600">{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}</div>}
|
||||
{showForm && (
|
||||
<div className="border border-secondary-200 rounded-lg p-4 space-y-3 bg-secondary-50">
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
@@ -225,7 +225,7 @@ function AgentTab() {
|
||||
<h2 className="text-lg font-semibold">Agenten</h2>
|
||||
<button onClick={() => { setShowForm(!showForm); setEditId(null); setForm({ name: '', description: '', system_prompt: '', preset_id: '', tool_ids: [] }); }} className="px-3 py-1.5 text-sm bg-primary-600 text-white rounded-lg">+ Hinzufügen</button>
|
||||
</div>
|
||||
{error && <div className="text-sm text-red-600">{error}</div>}
|
||||
{error && <div className="text-sm text-red-600">{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}</div>}
|
||||
{showForm && (
|
||||
<div className="border border-secondary-200 rounded-lg p-4 space-y-3 bg-secondary-50">
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
@@ -291,7 +291,7 @@ function ToolsTab() {
|
||||
<div className="space-y-4">
|
||||
<h2 className="text-lg font-semibold">Verfügbare Tools</h2>
|
||||
<p className="text-sm text-secondary-500">Diese Tools werden von Plugins bereitgestellt und können Agenten zugewiesen werden.</p>
|
||||
{error && <div className="text-sm text-red-600">{error}</div>}
|
||||
{error && <div className="text-sm text-red-600">{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}</div>}
|
||||
{tools.length === 0 ? (
|
||||
<div className="text-sm text-secondary-400 py-8 text-center">Keine Tools verfügbar. Plugins können Tools registrieren.</div>
|
||||
) : (
|
||||
|
||||
@@ -555,7 +555,7 @@ export function CalendarPage() {
|
||||
<div className="flex flex-col h-full" data-testid="calendar-page">
|
||||
{error && (
|
||||
<div className="mb-2 p-3 bg-danger-50 border border-danger-200 rounded-md" role="alert" data-testid="calendar-error">
|
||||
<p className="text-sm text-danger-700">{error}</p>
|
||||
<p className="text-sm text-danger-700">{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ export function CalendarKanbanPage() {
|
||||
className="mb-3 text-sm text-danger-700 bg-danger-50 border border-danger-200 rounded-md p-2"
|
||||
data-testid="kanban-error"
|
||||
>
|
||||
{error}
|
||||
{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
@@ -501,7 +501,7 @@ function ChatWindow({ convId, category, onBack }: ChatWindowProps) {
|
||||
</div>
|
||||
)}
|
||||
{error && (
|
||||
<div className="text-sm text-red-600 bg-red-50 rounded p-3">{error}</div>
|
||||
<div className="text-sm text-red-600 bg-red-50 rounded p-3">{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}</div>
|
||||
)}
|
||||
{!loading && messages.length === 0 && !aiStreaming && (
|
||||
<div className="text-center text-secondary-400 py-8">
|
||||
|
||||
@@ -114,7 +114,7 @@ export function DmsTrashPage() {
|
||||
<div className="p-6 max-w-7xl mx-auto" data-testid="dms-trash-page">
|
||||
<EmptyState
|
||||
title={t('dms.error')}
|
||||
description={error}
|
||||
description={typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}
|
||||
action={<Button onClick={() => window.location.reload()}>{t('dms.cancel')}</Button>}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -872,7 +872,7 @@ export function MailPage() {
|
||||
<div className="flex flex-col h-full" data-testid="mail-page">
|
||||
{error && (
|
||||
<div className="mb-2 p-3 bg-danger-50 border border-danger-200 rounded-md" role="alert" data-testid="mail-error">
|
||||
<p className="text-sm text-danger-700">{error}</p>
|
||||
<p className="text-sm text-danger-700">{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ export function SettingsCurrenciesPage() {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{error && <div className="p-3 text-sm text-red-700 bg-red-50 rounded-lg">{error}</div>}
|
||||
{error && <div className="p-3 text-sm text-red-700 bg-red-50 rounded-lg">{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}</div>}
|
||||
|
||||
{showForm && (
|
||||
<form onSubmit={handleSubmit(onSubmit)} className="p-4 border border-secondary-200 rounded-lg space-y-3">
|
||||
|
||||
@@ -115,7 +115,7 @@ export function SettingsSequencesPage() {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{error && <div className="p-3 text-sm text-red-700 bg-red-50 rounded-lg">{error}</div>}
|
||||
{error && <div className="p-3 text-sm text-red-700 bg-red-50 rounded-lg">{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}</div>}
|
||||
|
||||
{showForm && (
|
||||
<form onSubmit={handleSubmit(onSubmit)} className="p-4 border border-secondary-200 rounded-lg space-y-3">
|
||||
|
||||
@@ -118,7 +118,7 @@ export function SettingsTaxesPage() {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{error && <div className="p-3 text-sm text-red-700 bg-red-50 rounded-lg">{error}</div>}
|
||||
{error && <div className="p-3 text-sm text-red-700 bg-red-50 rounded-lg">{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}</div>}
|
||||
|
||||
{showForm && (
|
||||
<form onSubmit={handleSubmit(onSubmit)} className="p-4 border border-secondary-200 rounded-lg space-y-3">
|
||||
|
||||
@@ -203,7 +203,7 @@ function WebhookFormModal({ open, onClose, webhook, onSubmit, isSubmitting, erro
|
||||
{/* Error */}
|
||||
{error && (
|
||||
<div className="rounded-md bg-danger-50 border border-danger-200 px-3 py-2 text-sm text-danger-700">
|
||||
{error}
|
||||
{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@ function TagFormModal({ open, onClose, tag, onSubmit, isSubmitting, error }: Tag
|
||||
{/* Error */}
|
||||
{error && (
|
||||
<div className="rounded-md bg-danger-50 border border-danger-200 px-3 py-2 text-sm text-danger-700">
|
||||
{error}
|
||||
{typeof error === "string" ? error : (error as any)?.message || "Ein Fehler ist aufgetreten"}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user