mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-03-01 11:13:25 +08:00
feat: Add comprehensive tests for contentPattern and glob pattern matching
- Implemented final verification tests for contentPattern to validate behavior with empty strings, dangerous patterns, and normal patterns. - Created glob pattern matching tests to verify regex conversion and matching functionality. - Developed infinite loop risk tests using Worker threads to isolate potential blocking operations. - Introduced optimized contentPattern tests to validate improvements in the findMatches function. - Added verification tests to assess the effectiveness of contentPattern optimizations. - Conducted safety tests for contentPattern to identify edge cases and potential vulnerabilities. - Implemented unrestricted loop tests to analyze infinite loop risks without match limits. - Developed tests for zero-width pattern detection logic to ensure proper handling of dangerous regex patterns.
This commit is contained in:
118
ccw/frontend/src/pages/TeamPage.tsx
Normal file
118
ccw/frontend/src/pages/TeamPage.tsx
Normal file
@@ -0,0 +1,118 @@
|
||||
// ========================================
|
||||
// TeamPage
|
||||
// ========================================
|
||||
// Main page for team execution visualization
|
||||
|
||||
import { useEffect } from 'react';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { Users } from 'lucide-react';
|
||||
import { Card, CardContent } from '@/components/ui/Card';
|
||||
import { useTeamStore } from '@/stores/teamStore';
|
||||
import { useTeams, useTeamMessages, useTeamStatus } from '@/hooks/useTeamData';
|
||||
import { TeamEmptyState } from '@/components/team/TeamEmptyState';
|
||||
import { TeamHeader } from '@/components/team/TeamHeader';
|
||||
import { TeamPipeline } from '@/components/team/TeamPipeline';
|
||||
import { TeamMembersPanel } from '@/components/team/TeamMembersPanel';
|
||||
import { TeamMessageFeed } from '@/components/team/TeamMessageFeed';
|
||||
|
||||
export function TeamPage() {
|
||||
const { formatMessage } = useIntl();
|
||||
const {
|
||||
selectedTeam,
|
||||
setSelectedTeam,
|
||||
autoRefresh,
|
||||
toggleAutoRefresh,
|
||||
messageFilter,
|
||||
setMessageFilter,
|
||||
clearMessageFilter,
|
||||
timelineExpanded,
|
||||
setTimelineExpanded,
|
||||
} = useTeamStore();
|
||||
|
||||
// Data hooks
|
||||
const { teams, isLoading: teamsLoading } = useTeams();
|
||||
const { messages, total: messageTotal, isLoading: messagesLoading } = useTeamMessages(
|
||||
selectedTeam,
|
||||
messageFilter
|
||||
);
|
||||
const { members, totalMessages, isLoading: statusLoading } = useTeamStatus(selectedTeam);
|
||||
|
||||
// Auto-select first team if none selected
|
||||
useEffect(() => {
|
||||
if (!selectedTeam && teams.length > 0) {
|
||||
setSelectedTeam(teams[0].name);
|
||||
}
|
||||
}, [selectedTeam, teams, setSelectedTeam]);
|
||||
|
||||
// Show empty state when no teams exist
|
||||
if (!teamsLoading && teams.length === 0) {
|
||||
return (
|
||||
<div className="p-6">
|
||||
<div className="flex items-center gap-2 mb-6">
|
||||
<Users className="w-5 h-5" />
|
||||
<h1 className="text-xl font-semibold">{formatMessage({ id: 'team.title' })}</h1>
|
||||
</div>
|
||||
<TeamEmptyState />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="p-6 space-y-6">
|
||||
{/* Page title */}
|
||||
<div className="flex items-center gap-2">
|
||||
<Users className="w-5 h-5" />
|
||||
<h1 className="text-xl font-semibold">{formatMessage({ id: 'team.title' })}</h1>
|
||||
</div>
|
||||
|
||||
{/* Team Header: selector + stats + controls */}
|
||||
<TeamHeader
|
||||
teams={teams}
|
||||
selectedTeam={selectedTeam}
|
||||
onSelectTeam={setSelectedTeam}
|
||||
members={members}
|
||||
totalMessages={totalMessages}
|
||||
autoRefresh={autoRefresh}
|
||||
onToggleAutoRefresh={toggleAutoRefresh}
|
||||
/>
|
||||
|
||||
{selectedTeam ? (
|
||||
<>
|
||||
{/* Main content grid: Pipeline (left) + Members (right) */}
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||||
{/* Pipeline visualization */}
|
||||
<Card className="lg:col-span-2">
|
||||
<CardContent className="p-4">
|
||||
<TeamPipeline messages={messages} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Members panel */}
|
||||
<Card>
|
||||
<CardContent className="p-4">
|
||||
<TeamMembersPanel members={members} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{/* Message timeline */}
|
||||
<TeamMessageFeed
|
||||
messages={messages}
|
||||
total={messageTotal}
|
||||
filter={messageFilter}
|
||||
onFilterChange={setMessageFilter}
|
||||
onClearFilter={clearMessageFilter}
|
||||
expanded={timelineExpanded}
|
||||
onExpandedChange={setTimelineExpanded}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<div className="text-center py-12 text-muted-foreground">
|
||||
{formatMessage({ id: 'team.noTeamSelected' })}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default TeamPage;
|
||||
@@ -34,3 +34,4 @@ export { CodexLensManagerPage } from './CodexLensManagerPage';
|
||||
export { ApiSettingsPage } from './ApiSettingsPage';
|
||||
export { CliViewerPage } from './CliViewerPage';
|
||||
export { IssueManagerPage } from './IssueManagerPage';
|
||||
export { TeamPage } from './TeamPage';
|
||||
|
||||
Reference in New Issue
Block a user