mirror of
https://github.com/borbann-platform/backend-api.git
synced 2025-12-18 12:14:05 +01:00
feat: add PipelineDataSource, PipelineExportData, PipelineDataSchema, and PipelineDataPreview components to enhance data pipeline details page
This commit is contained in:
parent
668847edc3
commit
7783d00f56
@ -2,13 +2,17 @@ import { Button } from "@/components/ui/button"
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import { ArrowLeft, Download, Edit, Play, Trash, Copy, Check, Plus } from "lucide-react"
|
||||
import { ArrowLeft, Download, Edit, Play, Trash, Copy, Check } from "lucide-react"
|
||||
import Link from "next/link"
|
||||
import PageHeader from "@/components/page-header"
|
||||
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion"
|
||||
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Label } from "@/components/ui/label"
|
||||
import { PipelineStatus } from "@/components/pipeline/status"
|
||||
import { PipelineDataSource } from "@/components/pipeline/data-source"
|
||||
import { PipelineExportData } from "@/components/pipeline/export-data"
|
||||
import { PipelineDataSchema } from "@/components/pipeline/data-schema"
|
||||
import { PipelineDataPreview } from "@/components/pipeline/data-preview"
|
||||
|
||||
export default function PipelineDetailsPage() {
|
||||
return (
|
||||
@ -51,133 +55,8 @@ export default function PipelineDetailsPage() {
|
||||
|
||||
<div className="grid gap-6 md:grid-cols-3 mt-6">
|
||||
<PipelineStatus />
|
||||
|
||||
<Card className="border-2 hover:border-highlight-border transition-all duration-200">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-lg">Data Sources</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="space-y-4">
|
||||
<div className="p-3 border-2 rounded-md hover:border-highlight-border transition-all duration-200">
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="font-medium">example-realty.com</span>
|
||||
<Badge>Website</Badge>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground mt-1">Last updated: 2 hours ago</p>
|
||||
<p className="text-sm mt-1">540 records</p>
|
||||
</div>
|
||||
|
||||
<div className="p-3 border-2 rounded-md hover:border-highlight-border transition-all duration-200">
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="font-medium">property-listings.com</span>
|
||||
<Badge>Website</Badge>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground mt-1">Last updated: 2 hours ago</p>
|
||||
<p className="text-sm mt-1">420 records</p>
|
||||
</div>
|
||||
|
||||
<div className="p-3 border-2 rounded-md hover:border-highlight-border transition-all duration-200">
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="font-medium">real-estate-api.com</span>
|
||||
<Badge>API</Badge>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground mt-1">Last updated: 2 hours ago</p>
|
||||
<p className="text-sm mt-1">280 records</p>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="border-2 hover:border-highlight-border transition-all duration-200">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-lg">Export Options</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="space-y-4">
|
||||
<Accordion type="single" collapsible className="w-full" defaultValue="format-1">
|
||||
<AccordionItem value="format-1" className="border-0">
|
||||
<div className="border rounded-md p-2 hover:border-highlight-border transition-all duration-200">
|
||||
<AccordionTrigger className="py-1 px-2">
|
||||
<div className="flex items-center">
|
||||
<Download className="mr-2 h-4 w-4 text-primary" />
|
||||
<span>Export as JSON</span>
|
||||
</div>
|
||||
</AccordionTrigger>
|
||||
<AccordionContent className="pt-2 pb-1 px-2">
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center space-x-2">
|
||||
<input type="checkbox" id="pretty-json" className="h-4 w-4" defaultChecked />
|
||||
<label htmlFor="pretty-json" className="text-sm">
|
||||
Pretty print
|
||||
</label>
|
||||
</div>
|
||||
<Button size="sm" className="w-full">
|
||||
Download JSON
|
||||
</Button>
|
||||
</div>
|
||||
</AccordionContent>
|
||||
</div>
|
||||
</AccordionItem>
|
||||
|
||||
<AccordionItem value="format-2" className="border-0">
|
||||
<div className="border rounded-md p-2 hover:border-highlight-border transition-all duration-200">
|
||||
<AccordionTrigger className="py-1 px-2">
|
||||
<div className="flex items-center">
|
||||
<Download className="mr-2 h-4 w-4 text-primary" />
|
||||
<span>Export as CSV</span>
|
||||
</div>
|
||||
</AccordionTrigger>
|
||||
<AccordionContent className="pt-2 pb-1 px-2">
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center space-x-2">
|
||||
<input type="checkbox" id="include-headers" className="h-4 w-4" defaultChecked />
|
||||
<label htmlFor="include-headers" className="text-sm">
|
||||
Include headers
|
||||
</label>
|
||||
</div>
|
||||
<Button size="sm" className="w-full">
|
||||
Download CSV
|
||||
</Button>
|
||||
</div>
|
||||
</AccordionContent>
|
||||
</div>
|
||||
</AccordionItem>
|
||||
|
||||
<AccordionItem value="format-3" className="border-0">
|
||||
<div className="border rounded-md p-2 hover:border-highlight-border transition-all duration-200">
|
||||
<AccordionTrigger className="py-1 px-2">
|
||||
<div className="flex items-center">
|
||||
<Download className="mr-2 h-4 w-4 text-primary" />
|
||||
<span>Export as SQLite</span>
|
||||
</div>
|
||||
</AccordionTrigger>
|
||||
<AccordionContent className="pt-2 pb-1 px-2">
|
||||
<Button size="sm" className="w-full">
|
||||
Download SQLite
|
||||
</Button>
|
||||
</AccordionContent>
|
||||
</div>
|
||||
</AccordionItem>
|
||||
|
||||
<AccordionItem value="format-4" className="border-0">
|
||||
<div className="border rounded-md p-2 hover:border-highlight-border transition-all duration-200">
|
||||
<AccordionTrigger className="py-1 px-2">
|
||||
<div className="flex items-center">
|
||||
<Download className="mr-2 h-4 w-4 text-primary" />
|
||||
<span>Export as YAML</span>
|
||||
</div>
|
||||
</AccordionTrigger>
|
||||
<AccordionContent className="pt-2 pb-1 px-2">
|
||||
<Button size="sm" className="w-full">
|
||||
Download YAML
|
||||
</Button>
|
||||
</AccordionContent>
|
||||
</div>
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<PipelineDataSource />
|
||||
<PipelineExportData />
|
||||
</div>
|
||||
|
||||
<div className="mt-6">
|
||||
@ -191,226 +70,11 @@ export default function PipelineDetailsPage() {
|
||||
</TabsList>
|
||||
|
||||
<TabsContent value="schema" className="mt-4">
|
||||
<Card className="border-2 hover:border-highlight-border transition-all duration-200">
|
||||
<CardHeader>
|
||||
<div className="flex justify-between items-center">
|
||||
<div>
|
||||
<CardTitle>Data Schema & Field Management</CardTitle>
|
||||
<CardDescription>Customize fields detected from your data sources</CardDescription>
|
||||
</div>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<h3 className="text-sm font-medium">Detected Fields</h3>
|
||||
<Button variant="outline" size="sm">
|
||||
Refresh Detection
|
||||
</Button>
|
||||
</div>
|
||||
<PipelineDataSchema />
|
||||
</TabsContent>
|
||||
|
||||
<div className="border rounded-md p-4">
|
||||
<div className="space-y-3">
|
||||
<div className="field-mapping-item flex items-center">
|
||||
<input type="checkbox" id="field-title" className="h-4 w-4 mr-3" defaultChecked />
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center">
|
||||
<Label htmlFor="field-title" className="font-medium">
|
||||
Title
|
||||
</Label>
|
||||
<Badge className="ml-2 bg-green-500 text-white">Auto-detected</Badge>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">Property title or name</p>
|
||||
</div>
|
||||
<select className="h-8 rounded-md border border-input bg-background px-2 py-1 text-xs">
|
||||
<option>String</option>
|
||||
<option>Number</option>
|
||||
<option>Boolean</option>
|
||||
<option>Date</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="field-mapping-item flex items-center">
|
||||
<input type="checkbox" id="field-price" className="h-4 w-4 mr-3" defaultChecked />
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center">
|
||||
<Label htmlFor="field-price" className="font-medium">
|
||||
Price
|
||||
</Label>
|
||||
<Badge className="ml-2 bg-green-500 text-white">Auto-detected</Badge>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">Property price</p>
|
||||
</div>
|
||||
<select className="h-8 rounded-md border border-input bg-background px-2 py-1 text-xs">
|
||||
<option>Number</option>
|
||||
<option>String</option>
|
||||
<option>Boolean</option>
|
||||
<option>Date</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="field-mapping-item flex items-center">
|
||||
<input type="checkbox" id="field-location" className="h-4 w-4 mr-3" defaultChecked />
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center">
|
||||
<Label htmlFor="field-location" className="font-medium">
|
||||
Location
|
||||
</Label>
|
||||
<Badge className="ml-2 bg-green-500 text-white">Auto-detected</Badge>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">Property location</p>
|
||||
</div>
|
||||
<select className="h-8 rounded-md border border-input bg-background px-2 py-1 text-xs">
|
||||
<option>String</option>
|
||||
<option>Number</option>
|
||||
<option>Boolean</option>
|
||||
<option>Date</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="field-mapping-item flex items-center">
|
||||
<input type="checkbox" id="field-bedrooms" className="h-4 w-4 mr-3" defaultChecked />
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center">
|
||||
<Label htmlFor="field-bedrooms" className="font-medium">
|
||||
Bedrooms
|
||||
</Label>
|
||||
<Badge className="ml-2 bg-green-500 text-white">Auto-detected</Badge>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">Number of bedrooms</p>
|
||||
</div>
|
||||
<select className="h-8 rounded-md border border-input bg-background px-2 py-1 text-xs">
|
||||
<option>Number</option>
|
||||
<option>String</option>
|
||||
<option>Boolean</option>
|
||||
<option>Date</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="field-mapping-item flex items-center">
|
||||
<input type="checkbox" id="field-bathrooms" className="h-4 w-4 mr-3" defaultChecked />
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center">
|
||||
<Label htmlFor="field-bathrooms" className="font-medium">
|
||||
Bathrooms
|
||||
</Label>
|
||||
<Badge className="ml-2 bg-green-500 text-white">Auto-detected</Badge>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">Number of bathrooms</p>
|
||||
</div>
|
||||
<select className="h-8 rounded-md border border-input bg-background px-2 py-1 text-xs">
|
||||
<option>Number</option>
|
||||
<option>String</option>
|
||||
<option>Boolean</option>
|
||||
<option>Date</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="field-mapping-item flex items-center border-dashed">
|
||||
<input type="checkbox" id="field-custom" className="h-4 w-4 mr-3" />
|
||||
<div className="flex-1">
|
||||
<Input placeholder="Add custom field" className="border-none text-sm p-0 h-6" />
|
||||
</div>
|
||||
<Button variant="ghost" size="sm" className="h-8 px-2">
|
||||
<Plus className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2 mt-4">
|
||||
<Label htmlFor="derived-fields">Derived Fields</Label>
|
||||
<Card className="border border-dashed">
|
||||
<CardHeader className="py-3">
|
||||
<CardTitle className="text-sm">Create calculated fields</CardTitle>
|
||||
<CardDescription>Use formulas to generate new fields from existing data</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="py-0">
|
||||
<div className="space-y-3">
|
||||
<div className="field-mapping-item">
|
||||
<div className="flex items-center justify-between">
|
||||
<Label className="font-medium">Price Per Square Foot</Label>
|
||||
<Badge variant="outline">Derived</Badge>
|
||||
</div>
|
||||
<div className="flex items-center mt-2">
|
||||
<span className="text-xs text-muted-foreground mr-2">Formula:</span>
|
||||
<code className="text-xs bg-muted/50 p-1 rounded">price / squareFeet</code>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Button variant="outline" size="sm" className="w-full">
|
||||
<Plus className="h-4 w-4 mr-2" />
|
||||
Add Derived Field
|
||||
</Button>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end">
|
||||
<Button variant="outline" className="gap-2 mr-2">
|
||||
Reset to Default
|
||||
</Button>
|
||||
<Button>Save Field Configuration</Button>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="preview" className="mt-4">
|
||||
<Card className="border-2 hover:border-highlight-border transition-all duration-200">
|
||||
<CardHeader>
|
||||
<CardTitle>Data Preview</CardTitle>
|
||||
<CardDescription>Sample of the collected data</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="border rounded-md overflow-x-auto">
|
||||
<table className="w-full">
|
||||
<thead className="bg-muted">
|
||||
<tr>
|
||||
<th className="px-4 py-2 text-left text-sm font-medium">ID</th>
|
||||
<th className="px-4 py-2 text-left text-sm font-medium">Title</th>
|
||||
<th className="px-4 py-2 text-left text-sm font-medium">Price</th>
|
||||
<th className="px-4 py-2 text-left text-sm font-medium">Bedrooms</th>
|
||||
<th className="px-4 py-2 text-left text-sm font-medium">Bathrooms</th>
|
||||
<th className="px-4 py-2 text-left text-sm font-medium">Location</th>
|
||||
<th className="px-4 py-2 text-left text-sm font-medium">Sq. Ft.</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y">
|
||||
<tr>
|
||||
<td className="px-4 py-2 text-sm">P001</td>
|
||||
<td className="px-4 py-2 text-sm">Modern Apartment</td>
|
||||
<td className="px-4 py-2 text-sm">$350,000</td>
|
||||
<td className="px-4 py-2 text-sm">2</td>
|
||||
<td className="px-4 py-2 text-sm">2</td>
|
||||
<td className="px-4 py-2 text-sm">Downtown</td>
|
||||
<td className="px-4 py-2 text-sm">1,200</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 text-sm">P002</td>
|
||||
<td className="px-4 py-2 text-sm">Luxury Villa</td>
|
||||
<td className="px-4 py-2 text-sm">$1,250,000</td>
|
||||
<td className="px-4 py-2 text-sm">5</td>
|
||||
<td className="px-4 py-2 text-sm">4</td>
|
||||
<td className="px-4 py-2 text-sm">Suburbs</td>
|
||||
<td className="px-4 py-2 text-sm">3,500</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 text-sm">P003</td>
|
||||
<td className="px-4 py-2 text-sm">Cozy Studio</td>
|
||||
<td className="px-4 py-2 text-sm">$180,000</td>
|
||||
<td className="px-4 py-2 text-sm">1</td>
|
||||
<td className="px-4 py-2 text-sm">1</td>
|
||||
<td className="px-4 py-2 text-sm">City Center</td>
|
||||
<td className="px-4 py-2 text-sm">650</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<TabsContent value="preview" className="mt-4">
|
||||
<PipelineDataPreview />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="output" className="mt-4">
|
||||
|
||||
70
frontend/components/pipeline/data-preview.tsx
Normal file
70
frontend/components/pipeline/data-preview.tsx
Normal file
@ -0,0 +1,70 @@
|
||||
import { Card, CardHeader, CardTitle, CardDescription, CardContent } from "../ui/card";
|
||||
|
||||
export function PipelineDataPreview() {
|
||||
return (
|
||||
<Card className="border-2 hover:border-highlight-border transition-all duration-200">
|
||||
<CardHeader>
|
||||
<CardTitle>Data Preview</CardTitle>
|
||||
<CardDescription>Sample of the collected data</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="border rounded-md overflow-x-auto">
|
||||
<table className="w-full">
|
||||
<thead className="bg-muted">
|
||||
<tr>
|
||||
<th className="px-4 py-2 text-left text-sm font-medium">ID</th>
|
||||
<th className="px-4 py-2 text-left text-sm font-medium">
|
||||
Title
|
||||
</th>
|
||||
<th className="px-4 py-2 text-left text-sm font-medium">
|
||||
Price
|
||||
</th>
|
||||
<th className="px-4 py-2 text-left text-sm font-medium">
|
||||
Bedrooms
|
||||
</th>
|
||||
<th className="px-4 py-2 text-left text-sm font-medium">
|
||||
Bathrooms
|
||||
</th>
|
||||
<th className="px-4 py-2 text-left text-sm font-medium">
|
||||
Location
|
||||
</th>
|
||||
<th className="px-4 py-2 text-left text-sm font-medium">
|
||||
Sq. Ft.
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y">
|
||||
<tr>
|
||||
<td className="px-4 py-2 text-sm">P001</td>
|
||||
<td className="px-4 py-2 text-sm">Modern Apartment</td>
|
||||
<td className="px-4 py-2 text-sm">$350,000</td>
|
||||
<td className="px-4 py-2 text-sm">2</td>
|
||||
<td className="px-4 py-2 text-sm">2</td>
|
||||
<td className="px-4 py-2 text-sm">Downtown</td>
|
||||
<td className="px-4 py-2 text-sm">1,200</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 text-sm">P002</td>
|
||||
<td className="px-4 py-2 text-sm">Luxury Villa</td>
|
||||
<td className="px-4 py-2 text-sm">$1,250,000</td>
|
||||
<td className="px-4 py-2 text-sm">5</td>
|
||||
<td className="px-4 py-2 text-sm">4</td>
|
||||
<td className="px-4 py-2 text-sm">Suburbs</td>
|
||||
<td className="px-4 py-2 text-sm">3,500</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="px-4 py-2 text-sm">P003</td>
|
||||
<td className="px-4 py-2 text-sm">Cozy Studio</td>
|
||||
<td className="px-4 py-2 text-sm">$180,000</td>
|
||||
<td className="px-4 py-2 text-sm">1</td>
|
||||
<td className="px-4 py-2 text-sm">1</td>
|
||||
<td className="px-4 py-2 text-sm">City Center</td>
|
||||
<td className="px-4 py-2 text-sm">650</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
246
frontend/components/pipeline/data-schema.tsx
Normal file
246
frontend/components/pipeline/data-schema.tsx
Normal file
@ -0,0 +1,246 @@
|
||||
import { Plus } from "lucide-react";
|
||||
import { Button } from "../ui/button";
|
||||
import { Label } from "../ui/label";
|
||||
import {
|
||||
Card,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
CardDescription,
|
||||
CardContent,
|
||||
} from "../ui/card";
|
||||
import { Input } from "../ui/input";
|
||||
import { Badge } from "../ui/badge";
|
||||
|
||||
export function PipelineDataSchema() {
|
||||
return (
|
||||
<Card className="border-2 hover:border-highlight-border transition-all duration-200">
|
||||
<CardHeader>
|
||||
<div className="flex justify-between items-center">
|
||||
<div>
|
||||
<CardTitle>Data Schema & Field Management</CardTitle>
|
||||
<CardDescription>
|
||||
Customize fields detected from your data sources
|
||||
</CardDescription>
|
||||
</div>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<h3 className="text-sm font-medium">Detected Fields</h3>
|
||||
<Button variant="outline" size="sm">
|
||||
Refresh Detection
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="border rounded-md p-4">
|
||||
<div className="space-y-3">
|
||||
<div className="field-mapping-item flex items-center">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="field-title"
|
||||
className="h-4 w-4 mr-3"
|
||||
defaultChecked
|
||||
/>
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center">
|
||||
<Label htmlFor="field-title" className="font-medium">
|
||||
Title
|
||||
</Label>
|
||||
<Badge className="ml-2 bg-green-500 text-white">
|
||||
Auto-detected
|
||||
</Badge>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Property title or name
|
||||
</p>
|
||||
</div>
|
||||
<select className="h-8 rounded-md border border-input bg-background px-2 py-1 text-xs">
|
||||
<option>String</option>
|
||||
<option>Number</option>
|
||||
<option>Boolean</option>
|
||||
<option>Date</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="field-mapping-item flex items-center">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="field-price"
|
||||
className="h-4 w-4 mr-3"
|
||||
defaultChecked
|
||||
/>
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center">
|
||||
<Label htmlFor="field-price" className="font-medium">
|
||||
Price
|
||||
</Label>
|
||||
<Badge className="ml-2 bg-green-500 text-white">
|
||||
Auto-detected
|
||||
</Badge>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Property price
|
||||
</p>
|
||||
</div>
|
||||
<select className="h-8 rounded-md border border-input bg-background px-2 py-1 text-xs">
|
||||
<option>Number</option>
|
||||
<option>String</option>
|
||||
<option>Boolean</option>
|
||||
<option>Date</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="field-mapping-item flex items-center">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="field-location"
|
||||
className="h-4 w-4 mr-3"
|
||||
defaultChecked
|
||||
/>
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center">
|
||||
<Label htmlFor="field-location" className="font-medium">
|
||||
Location
|
||||
</Label>
|
||||
<Badge className="ml-2 bg-green-500 text-white">
|
||||
Auto-detected
|
||||
</Badge>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Property location
|
||||
</p>
|
||||
</div>
|
||||
<select className="h-8 rounded-md border border-input bg-background px-2 py-1 text-xs">
|
||||
<option>String</option>
|
||||
<option>Number</option>
|
||||
<option>Boolean</option>
|
||||
<option>Date</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="field-mapping-item flex items-center">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="field-bedrooms"
|
||||
className="h-4 w-4 mr-3"
|
||||
defaultChecked
|
||||
/>
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center">
|
||||
<Label htmlFor="field-bedrooms" className="font-medium">
|
||||
Bedrooms
|
||||
</Label>
|
||||
<Badge className="ml-2 bg-green-500 text-white">
|
||||
Auto-detected
|
||||
</Badge>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Number of bedrooms
|
||||
</p>
|
||||
</div>
|
||||
<select className="h-8 rounded-md border border-input bg-background px-2 py-1 text-xs">
|
||||
<option>Number</option>
|
||||
<option>String</option>
|
||||
<option>Boolean</option>
|
||||
<option>Date</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="field-mapping-item flex items-center">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="field-bathrooms"
|
||||
className="h-4 w-4 mr-3"
|
||||
defaultChecked
|
||||
/>
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center">
|
||||
<Label htmlFor="field-bathrooms" className="font-medium">
|
||||
Bathrooms
|
||||
</Label>
|
||||
<Badge className="ml-2 bg-green-500 text-white">
|
||||
Auto-detected
|
||||
</Badge>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Number of bathrooms
|
||||
</p>
|
||||
</div>
|
||||
<select className="h-8 rounded-md border border-input bg-background px-2 py-1 text-xs">
|
||||
<option>Number</option>
|
||||
<option>String</option>
|
||||
<option>Boolean</option>
|
||||
<option>Date</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="field-mapping-item flex items-center border-dashed">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="field-custom"
|
||||
className="h-4 w-4 mr-3"
|
||||
/>
|
||||
<div className="flex-1">
|
||||
<Input
|
||||
placeholder="Add custom field"
|
||||
className="border-none text-sm p-0 h-6"
|
||||
/>
|
||||
</div>
|
||||
<Button variant="ghost" size="sm" className="h-8 px-2">
|
||||
<Plus className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2 mt-4">
|
||||
<Label htmlFor="derived-fields">Derived Fields</Label>
|
||||
<Card className="border border-dashed">
|
||||
<CardHeader className="py-3">
|
||||
<CardTitle className="text-sm">
|
||||
Create calculated fields
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
Use formulas to generate new fields from existing data
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="py-0">
|
||||
<div className="space-y-3">
|
||||
<div className="field-mapping-item">
|
||||
<div className="flex items-center justify-between">
|
||||
<Label className="font-medium">
|
||||
Price Per Square Foot
|
||||
</Label>
|
||||
<Badge variant="outline">Derived</Badge>
|
||||
</div>
|
||||
<div className="flex items-center mt-2">
|
||||
<span className="text-xs text-muted-foreground mr-2">
|
||||
Formula:
|
||||
</span>
|
||||
<code className="text-xs bg-muted/50 p-1 rounded">
|
||||
price / squareFeet
|
||||
</code>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Button variant="outline" size="sm" className="w-full">
|
||||
<Plus className="h-4 w-4 mr-2" />
|
||||
Add Derived Field
|
||||
</Button>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end">
|
||||
<Button variant="outline" className="gap-2 mr-2">
|
||||
Reset to Default
|
||||
</Button>
|
||||
<Button>Save Field Configuration</Button>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
48
frontend/components/pipeline/data-source.tsx
Normal file
48
frontend/components/pipeline/data-source.tsx
Normal file
@ -0,0 +1,48 @@
|
||||
import { Badge } from "../ui/badge";
|
||||
import { Card, CardHeader, CardTitle, CardContent } from "../ui/card";
|
||||
|
||||
export function PipelineDataSource(){
|
||||
return (
|
||||
<Card className="border-2 hover:border-highlight-border transition-all duration-200">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-lg">Data Sources</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="space-y-4">
|
||||
<div className="p-3 border-2 rounded-md hover:border-highlight-border transition-all duration-200">
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="font-medium">example-realty.com</span>
|
||||
<Badge>Website</Badge>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground mt-1">
|
||||
Last updated: 2 hours ago
|
||||
</p>
|
||||
<p className="text-sm mt-1">540 records</p>
|
||||
</div>
|
||||
|
||||
<div className="p-3 border-2 rounded-md hover:border-highlight-border transition-all duration-200">
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="font-medium">property-listings.com</span>
|
||||
<Badge>Website</Badge>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground mt-1">
|
||||
Last updated: 2 hours ago
|
||||
</p>
|
||||
<p className="text-sm mt-1">420 records</p>
|
||||
</div>
|
||||
|
||||
<div className="p-3 border-2 rounded-md hover:border-highlight-border transition-all duration-200">
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="font-medium">real-estate-api.com</span>
|
||||
<Badge>API</Badge>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground mt-1">
|
||||
Last updated: 2 hours ago
|
||||
</p>
|
||||
<p className="text-sm mt-1">280 records</p>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
119
frontend/components/pipeline/export-data.tsx
Normal file
119
frontend/components/pipeline/export-data.tsx
Normal file
@ -0,0 +1,119 @@
|
||||
import {
|
||||
Accordion,
|
||||
AccordionContent,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
} from "@/components/ui/accordion";
|
||||
import { Download } from "lucide-react";
|
||||
import { Button } from "../ui/button";
|
||||
import { Card, CardHeader, CardTitle, CardContent } from "../ui/card";
|
||||
|
||||
export function PipelineExportData() {
|
||||
return (
|
||||
<Card className="border-2 hover:border-highlight-border transition-all duration-200">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-lg">Export Options</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="space-y-4">
|
||||
<Accordion
|
||||
type="single"
|
||||
collapsible
|
||||
className="w-full"
|
||||
defaultValue="format-1"
|
||||
>
|
||||
<AccordionItem value="format-1" className="border-0">
|
||||
<div className="border rounded-md p-2 hover:border-highlight-border transition-all duration-200">
|
||||
<AccordionTrigger className="py-1 px-2">
|
||||
<div className="flex items-center">
|
||||
<Download className="mr-2 h-4 w-4 text-primary" />
|
||||
<span>Export as JSON</span>
|
||||
</div>
|
||||
</AccordionTrigger>
|
||||
<AccordionContent className="pt-2 pb-1 px-2">
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center space-x-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="pretty-json"
|
||||
className="h-4 w-4"
|
||||
defaultChecked
|
||||
/>
|
||||
<label htmlFor="pretty-json" className="text-sm">
|
||||
Pretty print
|
||||
</label>
|
||||
</div>
|
||||
<Button size="sm" className="w-full">
|
||||
Download JSON
|
||||
</Button>
|
||||
</div>
|
||||
</AccordionContent>
|
||||
</div>
|
||||
</AccordionItem>
|
||||
|
||||
<AccordionItem value="format-2" className="border-0">
|
||||
<div className="border rounded-md p-2 hover:border-highlight-border transition-all duration-200">
|
||||
<AccordionTrigger className="py-1 px-2">
|
||||
<div className="flex items-center">
|
||||
<Download className="mr-2 h-4 w-4 text-primary" />
|
||||
<span>Export as CSV</span>
|
||||
</div>
|
||||
</AccordionTrigger>
|
||||
<AccordionContent className="pt-2 pb-1 px-2">
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center space-x-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="include-headers"
|
||||
className="h-4 w-4"
|
||||
defaultChecked
|
||||
/>
|
||||
<label htmlFor="include-headers" className="text-sm">
|
||||
Include headers
|
||||
</label>
|
||||
</div>
|
||||
<Button size="sm" className="w-full">
|
||||
Download CSV
|
||||
</Button>
|
||||
</div>
|
||||
</AccordionContent>
|
||||
</div>
|
||||
</AccordionItem>
|
||||
|
||||
<AccordionItem value="format-3" className="border-0">
|
||||
<div className="border rounded-md p-2 hover:border-highlight-border transition-all duration-200">
|
||||
<AccordionTrigger className="py-1 px-2">
|
||||
<div className="flex items-center">
|
||||
<Download className="mr-2 h-4 w-4 text-primary" />
|
||||
<span>Export as SQLite</span>
|
||||
</div>
|
||||
</AccordionTrigger>
|
||||
<AccordionContent className="pt-2 pb-1 px-2">
|
||||
<Button size="sm" className="w-full">
|
||||
Download SQLite
|
||||
</Button>
|
||||
</AccordionContent>
|
||||
</div>
|
||||
</AccordionItem>
|
||||
|
||||
<AccordionItem value="format-4" className="border-0">
|
||||
<div className="border rounded-md p-2 hover:border-highlight-border transition-all duration-200">
|
||||
<AccordionTrigger className="py-1 px-2">
|
||||
<div className="flex items-center">
|
||||
<Download className="mr-2 h-4 w-4 text-primary" />
|
||||
<span>Export as YAML</span>
|
||||
</div>
|
||||
</AccordionTrigger>
|
||||
<AccordionContent className="pt-2 pb-1 px-2">
|
||||
<Button size="sm" className="w-full">
|
||||
Download YAML
|
||||
</Button>
|
||||
</AccordionContent>
|
||||
</div>
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user