Skip to content

Commit ab19c57

Browse files
committed
fix: show success criteria on first render
1 parent 4d13093 commit ab19c57

File tree

7 files changed

+140
-28
lines changed

7 files changed

+140
-28
lines changed

apps/app/package.json

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@
4949
"@tiptap/extension-table-cell": "^3.4.4",
5050
"@tiptap/extension-table-header": "^3.4.4",
5151
"@tiptap/extension-table-row": "^3.4.4",
52-
"@trigger.dev/react-hooks": "4.0.0",
53-
"@trigger.dev/sdk": "4.0.0",
52+
"@trigger.dev/react-hooks": "4.0.6",
53+
"@trigger.dev/sdk": "4.0.6",
5454
"@trycompai/db": "^1.3.7",
5555
"@trycompai/email": "workspace:*",
5656
"@types/canvas-confetti": "^1.9.0",
@@ -117,7 +117,7 @@
117117
"@testing-library/dom": "^10.4.0",
118118
"@testing-library/jest-dom": "^6.6.3",
119119
"@testing-library/react": "^16.3.0",
120-
"@trigger.dev/build": "4.0.0",
120+
"@trigger.dev/build": "4.0.6",
121121
"@types/d3": "^7.4.3",
122122
"@types/jspdf": "^2.0.0",
123123
"@types/node": "^24.0.3",
@@ -157,7 +157,7 @@
157157
"db:getschema": "node ../../packages/db/scripts/combine-schemas.js && cp ../../packages/db/dist/schema.prisma prisma/schema.prisma",
158158
"db:migrate": "cd ../../packages/db && bunx prisma migrate dev && cd ../../apps/app",
159159
"deploy:trigger-prod": "npx [email protected] deploy",
160-
"dev": "bun i && bunx concurrently --kill-others --names \"next,trigger\" --prefix-colors \"yellow,blue\" \"next dev --turbo -p 3000\" \"bun run trigger:dev\"",
160+
"dev": "bun i && bunx concurrently --kill-others --names \"next,trigger\" --prefix-colors \"yellow,blue\" \"next dev --turbo -p 3000\" \"bunx trigger[email protected] dev\"",
161161
"lint": "next lint && prettier --check .",
162162
"prebuild": "bun run db:generate",
163163
"start": "next start",
@@ -173,7 +173,6 @@
173173
"test:e2e:ui": "playwright test --ui",
174174
"test:ui": "vitest --ui",
175175
"test:watch": "vitest --watch",
176-
"trigger:dev": "npx [email protected] dev",
177176
"typecheck": "tsc --noEmit"
178177
}
179178
}

apps/app/src/app/(app)/[orgId]/tasks/[taskId]/automation/[automationId]/components/evaluation/EvaluationCriteriaCard.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
import { Button } from '@comp/ui/button';
44
import { Textarea } from '@comp/ui/textarea';
55
import { Save } from 'lucide-react';
6-
import { useState } from 'react';
6+
import { useEffect, useState } from 'react';
77
import { toast } from 'sonner';
88
import { updateEvaluationCriteria } from '../../actions/task-automation-actions';
9+
import { useTaskAutomation } from '../../hooks/use-task-automation';
910

1011
interface EvaluationCriteriaCardProps {
1112
automationId: string;
@@ -17,17 +18,27 @@ export function EvaluationCriteriaCard({
1718
automationId,
1819
initialCriteria,
1920
}: EvaluationCriteriaCardProps) {
21+
const { automation } = useTaskAutomation();
2022
const [isEditing, setIsEditing] = useState(false);
2123
const [criteria, setCriteria] = useState(initialCriteria || '');
2224
const [isSaving, setIsSaving] = useState(false);
2325

26+
// Update local state when automation data changes
27+
useEffect(() => {
28+
if (automation?.evaluationCriteria) {
29+
setCriteria(automation.evaluationCriteria);
30+
}
31+
}, [automation?.evaluationCriteria]);
32+
2433
const handleSave = async () => {
2534
setIsSaving(true);
2635
try {
2736
const result = await updateEvaluationCriteria(automationId, criteria);
2837
if (result.success) {
2938
toast.success('Success criteria updated');
3039
setIsEditing(false);
40+
// Emit event to trigger refresh across the app
41+
window.dispatchEvent(new CustomEvent('task-automation:criteria-updated'));
3142
} else {
3243
toast.error(result.error || 'Failed to update criteria');
3344
}

apps/app/src/app/(app)/[orgId]/tasks/[taskId]/automation/[automationId]/components/workflow/components/UnifiedWorkflowCard.tsx

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { Card, CardContent, CardHeader, CardTitle } from '@comp/ui/card';
44
import { Loader2, Play, Zap } from 'lucide-react';
55
import Image from 'next/image';
66
import { useEffect, useState } from 'react';
7+
import { useTaskAutomation } from '../../../hooks/use-task-automation';
8+
import { useSharedChatContext } from '../../../lib/chat-context';
79
import { EvaluationCriteriaCard } from '../../evaluation/EvaluationCriteriaCard';
810

911
interface WorkflowStep {
@@ -42,8 +44,19 @@ export function UnifiedWorkflowCard({
4244
evaluationCriteria,
4345
automationId,
4446
}: Props) {
47+
const { automationIdRef } = useSharedChatContext();
4548
const [isAnimationComplete, setIsAnimationComplete] = useState(false);
4649

50+
// Use the real automation ID from ref (not "new")
51+
const realAutomationId =
52+
automationIdRef.current !== 'new' ? automationIdRef.current : automationId;
53+
54+
// Fetch automation data with the correct ID
55+
const { automation } = useTaskAutomation(realAutomationId);
56+
57+
// Use live automation data for criteria, fallback to prop
58+
const liveCriteria = automation?.evaluationCriteria || evaluationCriteria;
59+
4760
useEffect(() => {
4861
// Calculate total animation time: card (1s) + expansion (1s) + all steps
4962
const totalAnimationTime = 2500 + steps.length * 1200;
@@ -140,14 +153,14 @@ export function UnifiedWorkflowCard({
140153
</Card>
141154
</CardContent>
142155

143-
{/* Evaluation Criteria Section */}
144-
{evaluationCriteria !== undefined && automationId && isAnimationComplete && (
145-
<div className="px-4 pb-4 pt-2">
156+
{/* Evaluation Criteria Section - Show after animation */}
157+
{realAutomationId && realAutomationId !== 'new' && isAnimationComplete && (
158+
<div className="px-4 pb-4 pt-2 animate-in fade-in duration-500">
146159
<div className="max-w-[650px] mx-auto">
147160
<EvaluationCriteriaCard
148-
automationId={automationId}
149-
initialCriteria={evaluationCriteria}
150-
isAiGenerated={!!evaluationCriteria}
161+
automationId={realAutomationId}
162+
initialCriteria={liveCriteria}
163+
isAiGenerated={!!liveCriteria}
151164
/>
152165
</div>
153166
</div>

apps/app/src/app/(app)/[orgId]/tasks/[taskId]/automation/[automationId]/components/workflow/workflow-visualizer-simple.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,11 @@ export function WorkflowVisualizerSimple({ className }: Props) {
6363
const [publishDialogOpen, setPublishDialogOpen] = useState(false);
6464
const [isRestoring, setIsRestoring] = useState(false);
6565
const [confirmRestore, setConfirmRestore] = useState<EvidenceAutomationVersion | null>(null);
66-
const { automation, mutate: mutateAutomation } = useTaskAutomation();
66+
const {
67+
automation,
68+
mutate: mutateAutomation,
69+
isLoading: isLoadingAutomation,
70+
} = useTaskAutomation();
6771
const { versions } = useAutomationVersions();
6872

6973
// Update shared ref when automation is loaded from hook
@@ -110,8 +114,15 @@ export function WorkflowVisualizerSimple({ className }: Props) {
110114
// Also refresh automation data to get updated evaluationCriteria
111115
mutateAutomation();
112116
};
117+
const handleCriteriaUpdated = () => {
118+
mutateAutomation();
119+
};
113120
window.addEventListener('task-automation:script-saved', handleScriptSaved);
114-
return () => window.removeEventListener('task-automation:script-saved', handleScriptSaved);
121+
window.addEventListener('task-automation:criteria-updated', handleCriteriaUpdated);
122+
return () => {
123+
window.removeEventListener('task-automation:script-saved', handleScriptSaved);
124+
window.removeEventListener('task-automation:criteria-updated', handleCriteriaUpdated);
125+
};
115126
}, [refresh, mutateAutomation]);
116127

117128
useEffect(() => {
@@ -327,6 +338,7 @@ Please fix the automation script to resolve this error.`;
327338
<WorkflowSkeleton />
328339
) : steps.length > 0 ? (
329340
<UnifiedWorkflowCard
341+
key={`workflow-${automation?.id}-${automation?.evaluationCriteria ? 'with-criteria' : 'no-criteria'}`}
330342
steps={steps}
331343
title={title || 'Automation Workflow'}
332344
onTest={handleTest}

apps/app/src/app/(app)/[orgId]/tasks/[taskId]/automation/[automationId]/hooks/use-task-automation.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,29 +23,43 @@ interface UseTaskAutomationReturn {
2323
mutate: () => Promise<any>;
2424
}
2525

26-
export function useTaskAutomation(): UseTaskAutomationReturn {
27-
const { orgId, taskId, automationId } = useParams<{
26+
export function useTaskAutomation(overrideAutomationId?: string): UseTaskAutomationReturn {
27+
const {
28+
orgId,
29+
taskId,
30+
automationId: paramsAutomationId,
31+
} = useParams<{
2832
orgId: string;
2933
taskId: string;
3034
automationId: string;
3135
}>();
3236

37+
// Use override ID if provided, otherwise use params
38+
const automationId = overrideAutomationId || paramsAutomationId;
39+
40+
// Skip fetching if automationId is "new"
41+
const shouldFetch = automationId && automationId !== 'new';
42+
3343
const { data, error, isLoading, mutate } = useSWR(
34-
[`automation-${automationId}`, orgId, taskId, automationId],
44+
shouldFetch ? [`automation-${automationId}`, orgId, taskId, automationId] : null,
3545
async () => {
3646
const response = await api.get<{
3747
success: boolean;
3848
automation: TaskAutomationData;
3949
}>(`/v1/tasks/${taskId}/automations/${automationId}`, orgId);
4050

4151
if (response.error) {
52+
console.log('failed to fetch automation', response.error);
4253
throw new Error(response.error);
4354
}
4455

4556
if (!response.data?.success) {
57+
console.log('failed to fetch automation', response.data);
4658
throw new Error('Failed to fetch automation');
4759
}
4860

61+
console.log('response.data.automation', response.data.automation);
62+
4963
return response.data.automation;
5064
},
5165
{

apps/app/src/app/(app)/[orgId]/tasks/[taskId]/automations/[automationId]/overview/components/AutomationOverview.tsx

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@ import {
1616
DropdownMenuItem,
1717
DropdownMenuTrigger,
1818
} from '@comp/ui/dropdown-menu';
19+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@comp/ui/select';
1920
import { Textarea } from '@comp/ui/textarea';
2021
import { EvidenceAutomation, EvidenceAutomationRun, EvidenceAutomationVersion, Task } from '@db';
21-
import { ChevronRight, MoreVertical, Trash2 } from 'lucide-react';
22+
import { ChevronRight, Loader2, MoreVertical, Play, Trash2 } from 'lucide-react';
2223
import Link from 'next/link';
2324
import { useParams } from 'next/navigation';
2425
import { useMemo, useRef, useState } from 'react';
@@ -58,6 +59,8 @@ export function AutomationOverview({
5859
const [isTogglingEnabled, setIsTogglingEnabled] = useState(false);
5960
const [editingDescription, setEditingDescription] = useState(false);
6061
const [descriptionValue, setDescriptionValue] = useState('');
62+
const [selectedVersion, setSelectedVersion] = useState<number | null>(null);
63+
const [isTestingVersion, setIsTestingVersion] = useState(false);
6164
const descriptionInputRef = useRef<HTMLTextAreaElement>(null);
6265

6366
// Use the automation hook to get live data and mutate function
@@ -66,6 +69,12 @@ export function AutomationOverview({
6669
// Use live data from hook if available, fallback to initial data
6770
const automation = liveAutomation || initialAutomation;
6871

72+
// Set initial selected version to latest
73+
const latestVersion = initialVersions.length > 0 ? initialVersions[0].version : null;
74+
if (selectedVersion === null && latestVersion !== null) {
75+
setSelectedVersion(latestVersion);
76+
}
77+
6978
const handleToggleEnabled = async (enabled: boolean) => {
7079
if (!automation?.id) return;
7180

@@ -93,6 +102,21 @@ export function AutomationOverview({
93102
setTimeout(() => descriptionInputRef.current?.focus(), 0);
94103
};
95104

105+
const handleTestVersion = async () => {
106+
if (!selectedVersion) return;
107+
108+
setIsTestingVersion(true);
109+
try {
110+
// TODO: Call API to execute specific version
111+
toast.success(`Testing version ${selectedVersion}...`);
112+
// The actual test execution would happen here
113+
} catch (error) {
114+
toast.error('Failed to start test');
115+
} finally {
116+
setIsTestingVersion(false);
117+
}
118+
};
119+
96120
const saveDescriptionEdit = async () => {
97121
if (descriptionValue === (automation.description || '')) {
98122
setEditingDescription(false);
@@ -245,6 +269,45 @@ export function AutomationOverview({
245269
</p>
246270
)}
247271
</div>
272+
273+
{/* Version Selector */}
274+
{initialVersions.length > 0 && (
275+
<div className="flex flex-col gap-2">
276+
<p className="text-xs font-medium text-muted-foreground">Test Version</p>
277+
<div className="flex items-center gap-2">
278+
<Select
279+
value={selectedVersion?.toString() || ''}
280+
onValueChange={(value) => setSelectedVersion(parseInt(value))}
281+
>
282+
<SelectTrigger className="h-9 text-sm flex-1">
283+
<SelectValue placeholder="Select version" />
284+
</SelectTrigger>
285+
<SelectContent>
286+
{initialVersions.map((v) => (
287+
<SelectItem key={v.version} value={v.version.toString()}>
288+
v{v.version}
289+
{v.changelog &&
290+
` - ${v.changelog.substring(0, 30)}${v.changelog.length > 30 ? '...' : ''}`}
291+
</SelectItem>
292+
))}
293+
</SelectContent>
294+
</Select>
295+
<Button
296+
size="sm"
297+
variant="outline"
298+
onClick={handleTestVersion}
299+
disabled={!selectedVersion || isTestingVersion}
300+
>
301+
{isTestingVersion ? (
302+
<Loader2 className="w-3.5 h-3.5 animate-spin" />
303+
) : (
304+
<Play className="w-3.5 h-3.5" />
305+
)}
306+
</Button>
307+
</div>
308+
</div>
309+
)}
310+
248311
<div className="flex flex-col gap-1">
249312
<p className="text-xs font-medium text-muted-foreground">Created</p>
250313
<p className="text-sm">

0 commit comments

Comments
 (0)