Skip to content

Commit 5003a47

Browse files
authored
Merge pull request #68 from sauravpanda/feature/non-ai-semantic-abstraction
WIP: Feature/non ai semantic abstraction
2 parents fc823f7 + b18fcc3 commit 5003a47

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+12291
-849
lines changed

extension/package-lock.json

Lines changed: 604 additions & 499 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

extension/src/entrypoints/background.ts

Lines changed: 267 additions & 15 deletions
Large diffs are not rendered by default.

extension/src/entrypoints/content.ts

Lines changed: 431 additions & 1 deletion
Large diffs are not rendered by default.

extension/src/entrypoints/sidepanel/components/event-viewer.tsx

Lines changed: 120 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,67 @@ const getScreenshot = (step: Step): string | undefined => {
1717
return undefined;
1818
};
1919

20+
// Helper function to format step details based on type
21+
const formatStepDetails = (step: any): string => {
22+
switch (step.type) {
23+
case "navigation":
24+
return step.url;
25+
case "click":
26+
return step.targetText || step.elementText || step.cssSelector || "Click action";
27+
case "input":
28+
const value = step.value || "";
29+
const target = step.targetText || step.cssSelector || "Input field";
30+
return `${target}: "${value}"`;
31+
case "key_press":
32+
return `Key: ${step.key}`;
33+
case "scroll":
34+
return `(${step.scrollX}, ${step.scrollY})`;
35+
case "extract":
36+
return step.extractionGoal || "AI Extraction";
37+
default:
38+
return "Unknown action";
39+
}
40+
};
41+
42+
// Helper function to get step icon based on type
43+
const getStepIcon = (step: any): string => {
44+
switch (step.type) {
45+
case "navigation":
46+
return "🔗";
47+
case "click":
48+
return "👆";
49+
case "input":
50+
return "✏️";
51+
case "key_press":
52+
return "⌨️";
53+
case "scroll":
54+
return "📜";
55+
case "extract":
56+
return "🤖";
57+
default:
58+
return "❓";
59+
}
60+
};
61+
62+
// Helper function to get background color based on step type
63+
const getStepBgColor = (step: any, isSelected: boolean): string => {
64+
if (isSelected) {
65+
switch (step.type) {
66+
case "extract":
67+
return "bg-blue-100 border-blue-300";
68+
default:
69+
return "bg-blue-50 border-blue-200";
70+
}
71+
} else {
72+
switch (step.type) {
73+
case "extract":
74+
return "bg-blue-25 border-blue-100 hover:bg-blue-50";
75+
default:
76+
return "bg-white border-gray-200 hover:bg-gray-50";
77+
}
78+
}
79+
};
80+
2081
// Component to render a single step as a card
2182
const StepCard: React.FC<{
2283
step: Step;
@@ -32,23 +93,36 @@ const StepCard: React.FC<{
3293
switch (step.type) {
3394
case "click": {
3495
const s = step as ClickStep;
96+
// Enhanced display for radio buttons
97+
if (s.radioButtonInfo && s.radioButtonInfo.fieldName && s.radioButtonInfo.optionValue) {
98+
return (
99+
<div className="flex items-center space-x-2">
100+
<span className="text-lg">📻</span>
101+
<span className="truncate">
102+
Select <strong>{s.radioButtonInfo.optionValue}</strong> for <strong>{s.radioButtonInfo.fieldName}</strong>
103+
</span>
104+
</div>
105+
);
106+
}
107+
// Standard click display
108+
const targetDescription = s.targetText || s.elementText || s.elementTag;
35109
return (
36110
<div className="flex items-center space-x-2">
37111
<span className="text-lg">🖱️</span>
38112
<span className="truncate">
39-
Click on <strong>{s.elementTag}</strong>
40-
{s.elementText && `: "${s.elementText}"`}
113+
Click on <strong>{targetDescription}</strong>
41114
</span>
42115
</div>
43116
);
44117
}
45118
case "input": {
46119
const s = step as InputStep;
120+
const targetDescription = s.targetText || s.elementTag;
47121
return (
48122
<div className="flex items-center space-x-2">
49123
<span className="text-lg">⌨️</span>
50124
<span className="truncate">
51-
Input into <strong>{s.elementTag}</strong>: "{s.value}"
125+
Input into <strong>{targetDescription}</strong>: "{s.value}"
52126
</span>
53127
</div>
54128
);
@@ -138,6 +212,24 @@ const StepCard: React.FC<{
138212
<strong>Element:</strong> {s.elementTag}
139213
</p>
140214
)}
215+
{(s as ClickStep | InputStep).targetText && (
216+
<p>
217+
<strong>Target Text:</strong> {(s as ClickStep | InputStep).targetText}
218+
</p>
219+
)}
220+
{(s as ClickStep).radioButtonInfo && (
221+
<div>
222+
<p>
223+
<strong>Field Name:</strong> {(s as ClickStep).radioButtonInfo?.fieldName}
224+
</p>
225+
<p>
226+
<strong>Selected Option:</strong> {(s as ClickStep).radioButtonInfo?.optionValue}
227+
</p>
228+
<p>
229+
<strong>All Options:</strong> {(s as ClickStep).radioButtonInfo?.allOptions?.join(', ')}
230+
</p>
231+
</div>
232+
)}
141233
{(s as ClickStep).elementText && (
142234
<p>
143235
<strong>Text:</strong> {(s as ClickStep).elementText}
@@ -178,6 +270,17 @@ const StepCard: React.FC<{
178270
);
179271
break;
180272
}
273+
case "extract": {
274+
const s = step as any; // ExtractStep
275+
specificInfo = (
276+
<>
277+
<p>
278+
<strong>Extraction Goal:</strong> {s.extractionGoal}
279+
</p>
280+
</>
281+
);
282+
break;
283+
}
181284
default:
182285
specificInfo = (
183286
<p>Details not available for type: {(step as any).type}</p>
@@ -192,19 +295,20 @@ const StepCard: React.FC<{
192295
);
193296
};
194297

195-
return (
196-
<div
197-
id={`event-item-${index}`} // Keep ID for potential scrolling
198-
onClick={onSelect}
199-
className={`
200-
border rounded-lg mb-3 overflow-hidden cursor-pointer transition-all duration-150 ease-in-out
201-
${
202-
isSelected
203-
? "border-primary shadow-md scale-[1.01]"
204-
: "border-border hover:border-muted-foreground/50 hover:shadow-sm"
205-
}
206-
`}
207-
>
298+
return (
299+
<div
300+
id={`event-item-${index}`} // Keep ID for potential scrolling
301+
onClick={onSelect}
302+
className={`
303+
border rounded-lg mb-3 overflow-hidden cursor-pointer transition-all duration-150 ease-in-out
304+
${getStepBgColor(step, isSelected)}
305+
${
306+
isSelected
307+
? "shadow-md scale-[1.01]"
308+
: "hover:shadow-sm"
309+
}
310+
`}
311+
>
208312
{/* Card Content using Flexbox */}
209313
<div className="flex items-start p-3 space-x-3">
210314
{/* Left side: Summary and Details */}
Lines changed: 118 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,129 @@
1-
import React from "react";
1+
import React, { useState } from "react";
22
import { useWorkflow } from "../context/workflow-provider";
33
import { Button } from "@/components/ui/button"; // Reverted to alias path
44

55
export const InitialView: React.FC = () => {
66
const { startRecording } = useWorkflow();
7+
const [showTemplates, setShowTemplates] = useState(false);
8+
9+
const workflowTemplates = [
10+
{
11+
name: "E-commerce Product Research",
12+
description: "Navigate product pages and extract prices, reviews, specifications",
13+
steps: "Search → Product page → Extract pricing & reviews",
14+
icon: "🛒"
15+
},
16+
{
17+
name: "Job Listings Scraper",
18+
description: "Browse job boards and extract job details, requirements, salaries",
19+
steps: "Search jobs → Job listings → Extract job details",
20+
icon: "💼"
21+
},
22+
{
23+
name: "Travel Booking Flow",
24+
description: "Search flights/hotels and extract prices, availability, options",
25+
steps: "Search → Results → Extract pricing & options",
26+
icon: "✈️"
27+
},
28+
{
29+
name: "Lead Generation",
30+
description: "Navigate directories and extract contact information",
31+
steps: "Directory → Company pages → Extract contact info",
32+
icon: "📊"
33+
},
34+
{
35+
name: "Social Media Monitoring",
36+
description: "Browse social platforms and extract posts, metrics, engagement",
37+
steps: "Profile/hashtag → Posts → Extract content & metrics",
38+
icon: "📱"
39+
},
40+
{
41+
name: "Custom Workflow",
42+
description: "Record any workflow with manual actions and AI extraction",
43+
steps: "Start recording and add AI extraction when needed",
44+
icon: "🎯"
45+
}
46+
];
747

848
return (
9-
<div className="flex flex-col items-center justify-center h-full space-y-4">
10-
<h2 className="text-lg font-semibold">Record a Workflow</h2>
49+
<div className="flex flex-col h-full bg-white">
50+
<div className="flex-grow flex flex-col items-center justify-center space-y-6 p-4">
51+
<div className="text-center space-y-2">
52+
<h2 className="text-xl font-semibold text-gray-900">Create a Workflow</h2>
53+
<p className="text-sm text-gray-600 max-w-md">
54+
Record your actions and add AI extraction steps to automatically gather data from web pages
55+
</p>
56+
</div>
57+
58+
<div className="space-y-3 w-full max-w-md">
59+
<Button
60+
onClick={startRecording}
61+
className="w-full h-12 text-base font-medium"
62+
size="lg"
63+
>
64+
🔴 Start Recording Workflow
65+
</Button>
66+
67+
<Button
68+
variant="outline"
69+
onClick={() => setShowTemplates(!showTemplates)}
70+
className="w-full text-sm"
71+
>
72+
📋 View Workflow Templates
73+
</Button>
74+
</div>
75+
76+
{showTemplates && (
77+
<div className="w-full max-w-2xl space-y-3">
78+
<h3 className="text-sm font-medium text-center text-gray-900">Workflow Templates</h3>
79+
<div className="grid grid-cols-1 md:grid-cols-2 gap-3 max-h-64 overflow-y-auto">
80+
{workflowTemplates.map((template, index) => (
81+
<div
82+
key={index}
83+
className="border border-gray-200 rounded-lg p-3 hover:bg-gray-50 hover:border-gray-300 cursor-pointer transition-all"
84+
onClick={() => {
85+
setShowTemplates(false);
86+
startRecording();
87+
}}
88+
>
89+
<div className="flex items-start space-x-3">
90+
<span className="text-2xl">{template.icon}</span>
91+
<div className="flex-1 min-w-0">
92+
<h4 className="text-sm font-medium text-gray-900 truncate">{template.name}</h4>
93+
<p className="text-xs text-gray-600 mt-1">{template.description}</p>
94+
<div className="text-xs text-blue-600 mt-2 font-medium">
95+
{template.steps}
96+
</div>
97+
</div>
98+
</div>
99+
</div>
100+
))}
101+
</div>
102+
<div className="text-xs text-center text-gray-600 bg-blue-50 p-3 rounded border border-blue-200">
103+
💡 <strong>Pro tip:</strong> Add AI extraction steps during recording to automatically capture data from the final page.
104+
The AI can extract structured information like prices, contact details, or any specific data you describe.
105+
</div>
106+
</div>
107+
)}
11108

12-
<Button onClick={startRecording}>Start Recording</Button>
109+
<div className="text-center space-y-2 max-w-md">
110+
<h3 className="text-sm font-medium text-gray-900">How it works:</h3>
111+
<div className="text-xs text-gray-600 space-y-1">
112+
<div className="flex items-center space-x-2">
113+
<span>1️⃣</span>
114+
<span>Record your actions (clicks, inputs, navigation)</span>
115+
</div>
116+
<div className="flex items-center space-x-2">
117+
<span>2️⃣</span>
118+
<span>Add AI extraction steps when you want to gather data</span>
119+
</div>
120+
<div className="flex items-center space-x-2">
121+
<span>3️⃣</span>
122+
<span>Save and run your workflow to automate the process</span>
123+
</div>
124+
</div>
125+
</div>
126+
</div>
13127
</div>
14128
);
15129
};

0 commit comments

Comments
 (0)