refactor(frontend): clean up code by consolidating multi-line JSX into single lines where feasible

- Refactored JSX elements to improve readability by collapsing multi-line props and attributes into single lines if their length permits.
- Improved consistency in component imports by grouping and consolidating them.
- No functional changes, purely restructuring for clarity and maintainability.
This commit is contained in:
2026-01-01 11:46:57 +01:00
parent a7ba0f9bd8
commit a4c91cb8c3
77 changed files with 600 additions and 907 deletions

View File

@@ -248,12 +248,47 @@ const EVENT_TYPE_CONFIG: Record<
};
const FILTER_CATEGORIES = [
{ id: 'agent', label: 'Agent Actions', types: [EventType.AGENT_SPAWNED, EventType.AGENT_MESSAGE, EventType.AGENT_STATUS_CHANGED, EventType.AGENT_TERMINATED] },
{ id: 'issue', label: 'Issues', types: [EventType.ISSUE_CREATED, EventType.ISSUE_UPDATED, EventType.ISSUE_ASSIGNED, EventType.ISSUE_CLOSED] },
{
id: 'agent',
label: 'Agent Actions',
types: [
EventType.AGENT_SPAWNED,
EventType.AGENT_MESSAGE,
EventType.AGENT_STATUS_CHANGED,
EventType.AGENT_TERMINATED,
],
},
{
id: 'issue',
label: 'Issues',
types: [
EventType.ISSUE_CREATED,
EventType.ISSUE_UPDATED,
EventType.ISSUE_ASSIGNED,
EventType.ISSUE_CLOSED,
],
},
{ id: 'sprint', label: 'Sprints', types: [EventType.SPRINT_STARTED, EventType.SPRINT_COMPLETED] },
{ id: 'approval', label: 'Approvals', types: [EventType.APPROVAL_REQUESTED, EventType.APPROVAL_GRANTED, EventType.APPROVAL_DENIED] },
{ id: 'workflow', label: 'Workflows', types: [EventType.WORKFLOW_STARTED, EventType.WORKFLOW_STEP_COMPLETED, EventType.WORKFLOW_COMPLETED, EventType.WORKFLOW_FAILED] },
{ id: 'project', label: 'Projects', types: [EventType.PROJECT_CREATED, EventType.PROJECT_UPDATED, EventType.PROJECT_ARCHIVED] },
{
id: 'approval',
label: 'Approvals',
types: [EventType.APPROVAL_REQUESTED, EventType.APPROVAL_GRANTED, EventType.APPROVAL_DENIED],
},
{
id: 'workflow',
label: 'Workflows',
types: [
EventType.WORKFLOW_STARTED,
EventType.WORKFLOW_STEP_COMPLETED,
EventType.WORKFLOW_COMPLETED,
EventType.WORKFLOW_FAILED,
],
},
{
id: 'project',
label: 'Projects',
types: [EventType.PROJECT_CREATED, EventType.PROJECT_UPDATED, EventType.PROJECT_ARCHIVED],
},
];
// ============================================================================
@@ -266,25 +301,60 @@ function getEventConfig(event: ProjectEvent) {
// Fallback based on event category
if (isAgentEvent(event)) {
return { icon: Bot, label: event.type, color: 'text-blue-500', bgColor: 'bg-blue-100 dark:bg-blue-900' };
return {
icon: Bot,
label: event.type,
color: 'text-blue-500',
bgColor: 'bg-blue-100 dark:bg-blue-900',
};
}
if (isIssueEvent(event)) {
return { icon: FileText, label: event.type, color: 'text-green-500', bgColor: 'bg-green-100 dark:bg-green-900' };
return {
icon: FileText,
label: event.type,
color: 'text-green-500',
bgColor: 'bg-green-100 dark:bg-green-900',
};
}
if (isSprintEvent(event)) {
return { icon: PlayCircle, label: event.type, color: 'text-indigo-500', bgColor: 'bg-indigo-100 dark:bg-indigo-900' };
return {
icon: PlayCircle,
label: event.type,
color: 'text-indigo-500',
bgColor: 'bg-indigo-100 dark:bg-indigo-900',
};
}
if (isApprovalEvent(event)) {
return { icon: AlertTriangle, label: event.type, color: 'text-orange-500', bgColor: 'bg-orange-100 dark:bg-orange-900' };
return {
icon: AlertTriangle,
label: event.type,
color: 'text-orange-500',
bgColor: 'bg-orange-100 dark:bg-orange-900',
};
}
if (isWorkflowEvent(event)) {
return { icon: Workflow, label: event.type, color: 'text-cyan-500', bgColor: 'bg-cyan-100 dark:bg-cyan-900' };
return {
icon: Workflow,
label: event.type,
color: 'text-cyan-500',
bgColor: 'bg-cyan-100 dark:bg-cyan-900',
};
}
if (isProjectEvent(event)) {
return { icon: Folder, label: event.type, color: 'text-teal-500', bgColor: 'bg-teal-100 dark:bg-teal-900' };
return {
icon: Folder,
label: event.type,
color: 'text-teal-500',
bgColor: 'bg-teal-100 dark:bg-teal-900',
};
}
return { icon: Activity, label: event.type, color: 'text-gray-500', bgColor: 'bg-gray-100 dark:bg-gray-800' };
return {
icon: Activity,
label: event.type,
color: 'text-gray-500',
bgColor: 'bg-gray-100 dark:bg-gray-800',
};
}
function getEventSummary(event: ProjectEvent): string {
@@ -304,7 +374,9 @@ function getEventSummary(event: ProjectEvent): string {
case EventType.ISSUE_UPDATED:
return `Issue ${payload.issue_id || ''} updated`;
case EventType.ISSUE_ASSIGNED:
return payload.assignee_name ? `Assigned to ${payload.assignee_name}` : 'Issue assignment changed';
return payload.assignee_name
? `Assigned to ${payload.assignee_name}`
: 'Issue assignment changed';
case EventType.ISSUE_CLOSED:
return payload.resolution ? `Closed: ${payload.resolution}` : 'Issue closed';
case EventType.SPRINT_STARTED:
@@ -318,11 +390,15 @@ function getEventSummary(event: ProjectEvent): string {
case EventType.APPROVAL_DENIED:
return payload.reason ? `Denied: ${payload.reason}` : 'Approval denied';
case EventType.WORKFLOW_STARTED:
return payload.workflow_type ? `${payload.workflow_type} workflow started` : 'Workflow started';
return payload.workflow_type
? `${payload.workflow_type} workflow started`
: 'Workflow started';
case EventType.WORKFLOW_STEP_COMPLETED:
return `Step ${payload.step_number}/${payload.total_steps}: ${payload.step_name || 'completed'}`;
case EventType.WORKFLOW_COMPLETED:
return payload.duration_seconds ? `Completed in ${payload.duration_seconds}s` : 'Workflow completed';
return payload.duration_seconds
? `Completed in ${payload.duration_seconds}s`
: 'Workflow completed';
case EventType.WORKFLOW_FAILED:
return payload.error_message ? String(payload.error_message) : 'Workflow failed';
default:
@@ -391,11 +467,7 @@ function ConnectionIndicator({ state, onReconnect, className }: ConnectionIndica
return (
<div className={cn('flex items-center gap-2', className)} data-testid="connection-indicator">
<span
className={cn(
'h-2 w-2 rounded-full',
config.color,
config.pulse && 'animate-pulse'
)}
className={cn('h-2 w-2 rounded-full', config.color, config.pulse && 'animate-pulse')}
aria-hidden="true"
/>
<span className="text-sm text-muted-foreground">{config.label}</span>
@@ -475,7 +547,10 @@ function FilterPanel({
checked={showPendingOnly}
onCheckedChange={(checked) => onShowPendingOnlyChange(checked as boolean)}
/>
<Label htmlFor="filter-pending" className="flex items-center gap-1 text-sm font-normal cursor-pointer">
<Label
htmlFor="filter-pending"
className="flex items-center gap-1 text-sm font-normal cursor-pointer"
>
Show only pending approvals
{pendingCount > 0 && (
<Badge variant="destructive" className="text-xs">
@@ -598,77 +673,85 @@ function EventItem({
}}
aria-label={expanded ? 'Collapse details' : 'Expand details'}
>
{expanded ? <ChevronDown className="h-4 w-4" /> : <ChevronRight className="h-4 w-4" />}
{expanded ? (
<ChevronDown className="h-4 w-4" />
) : (
<ChevronRight className="h-4 w-4" />
)}
</Button>
</div>
</div>
{/* Expanded Details */}
{expanded && (() => {
const issueId = payload.issue_id as string | undefined;
const pullRequest = payload.pullRequest as string | number | undefined;
const documentUrl = payload.documentUrl as string | undefined;
const progress = payload.progress as number | undefined;
{expanded &&
(() => {
const issueId = payload.issue_id as string | undefined;
const pullRequest = payload.pullRequest as string | number | undefined;
const documentUrl = payload.documentUrl as string | undefined;
const progress = payload.progress as number | undefined;
return (
<div className="mt-3 rounded-md bg-muted/50 p-3 space-y-3" data-testid="event-details">
{/* Issue/PR Links */}
{issueId && (
<div className="flex items-center gap-2 text-sm">
<CircleDot className="h-4 w-4" aria-hidden="true" />
<span>Issue #{issueId}</span>
</div>
)}
{pullRequest && (
<div className="flex items-center gap-2 text-sm">
<GitPullRequest className="h-4 w-4" aria-hidden="true" />
<span>PR #{String(pullRequest)}</span>
</div>
)}
{/* Document Links */}
{documentUrl && (
<div className="flex items-center gap-2 text-sm">
<ExternalLink className="h-4 w-4" aria-hidden="true" />
<a href={documentUrl} className="text-primary hover:underline">
{documentUrl}
</a>
</div>
)}
{/* Progress */}
{progress !== undefined && (
<div className="space-y-1">
<div className="flex justify-between text-sm">
<span>Progress</span>
<span>{progress}%</span>
return (
<div
className="mt-3 rounded-md bg-muted/50 p-3 space-y-3"
data-testid="event-details"
>
{/* Issue/PR Links */}
{issueId && (
<div className="flex items-center gap-2 text-sm">
<CircleDot className="h-4 w-4" aria-hidden="true" />
<span>Issue #{issueId}</span>
</div>
<div className="h-2 rounded-full bg-muted">
<div
className="h-full rounded-full bg-primary"
style={{ width: `${progress}%` }}
/>
)}
{pullRequest && (
<div className="flex items-center gap-2 text-sm">
<GitPullRequest className="h-4 w-4" aria-hidden="true" />
<span>PR #{String(pullRequest)}</span>
</div>
</div>
)}
)}
{/* Timestamp */}
<p className="text-xs text-muted-foreground">
{new Date(event.timestamp).toLocaleString()}
</p>
{/* Document Links */}
{documentUrl && (
<div className="flex items-center gap-2 text-sm">
<ExternalLink className="h-4 w-4" aria-hidden="true" />
<a href={documentUrl} className="text-primary hover:underline">
{documentUrl}
</a>
</div>
)}
{/* Raw Payload (for debugging) */}
<details className="text-xs">
<summary className="cursor-pointer text-muted-foreground hover:text-foreground">
View raw payload
</summary>
<pre className="mt-2 overflow-x-auto whitespace-pre-wrap break-words rounded bg-muted p-2">
{JSON.stringify(event.payload, null, 2)}
</pre>
</details>
</div>
);
})()}
{/* Progress */}
{progress !== undefined && (
<div className="space-y-1">
<div className="flex justify-between text-sm">
<span>Progress</span>
<span>{progress}%</span>
</div>
<div className="h-2 rounded-full bg-muted">
<div
className="h-full rounded-full bg-primary"
style={{ width: `${progress}%` }}
/>
</div>
</div>
)}
{/* Timestamp */}
<p className="text-xs text-muted-foreground">
{new Date(event.timestamp).toLocaleString()}
</p>
{/* Raw Payload (for debugging) */}
<details className="text-xs">
<summary className="cursor-pointer text-muted-foreground hover:text-foreground">
View raw payload
</summary>
<pre className="mt-2 overflow-x-auto whitespace-pre-wrap break-words rounded bg-muted p-2">
{JSON.stringify(event.payload, null, 2)}
</pre>
</details>
</div>
);
})()}
{/* Approval Actions */}
{isPendingApproval && (onApprove || onReject) && (
@@ -680,7 +763,12 @@ function EventItem({
</Button>
)}
{onReject && (
<Button variant="outline" size="sm" onClick={handleReject} data-testid="reject-button">
<Button
variant="outline"
size="sm"
onClick={handleReject}
data-testid="reject-button"
>
<XCircle className="mr-2 h-4 w-4" />
Reject
</Button>
@@ -712,7 +800,10 @@ function LoadingSkeleton() {
function EmptyState({ hasFilters }: { hasFilters: boolean }) {
return (
<div className="flex flex-col items-center justify-center py-12 text-muted-foreground" data-testid="empty-state">
<div
className="flex flex-col items-center justify-center py-12 text-muted-foreground"
data-testid="empty-state"
>
<Activity className="h-12 w-12 mb-4" aria-hidden="true" />
<h3 className="font-semibold">No activity found</h3>
<p className="text-sm">
@@ -894,7 +985,10 @@ export function ActivityFeed({
) : (
<div className="space-y-6">
{groupedEvents.map((group) => (
<div key={group.label} data-testid={`event-group-${group.label.toLowerCase().replace(' ', '-')}`}>
<div
key={group.label}
data-testid={`event-group-${group.label.toLowerCase().replace(' ', '-')}`}
>
<div className="mb-3 flex items-center gap-2">
<h3 className="text-sm font-medium text-muted-foreground">{group.label}</h3>
<Badge variant="secondary" className="text-xs">