mirror of
https://github.com/borbann-platform/backend-api.git
synced 2025-12-19 12:44:04 +01:00
feat: implement data fetching and error handling for DataPipelinePage, update PipelineCard component to use 'name' prop, and add API functions for pipeline management
This commit is contained in:
parent
8b730e14ae
commit
a687636b07
@ -1,13 +1,34 @@
|
|||||||
import { Button } from "@/components/ui/button";
|
"use client";
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
|
||||||
import { Plus } from "lucide-react";
|
|
||||||
import Link from "next/link";
|
|
||||||
import PageHeader from "@/components/page-header";
|
import PageHeader from "@/components/page-header";
|
||||||
import { PipelineCard } from "@/components/pipeline/card";
|
import { PipelineCard } from "@/components/pipeline/card";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||||
|
import { listPipelines } from "@/lib/api/pipelines";
|
||||||
|
import { Pipeline } from "@/lib/api/pipelines/types";
|
||||||
|
import { Plus } from "lucide-react";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
export default function DataPipelinePage() {
|
export default function DataPipelinePage() {
|
||||||
|
const [pipelines, setPipelines] = useState<Pipeline[]>([]);
|
||||||
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchPipelines = async () => {
|
||||||
|
try {
|
||||||
|
const data = await listPipelines();
|
||||||
|
setPipelines(data);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Error fetching pipelines:", err);
|
||||||
|
setError("Failed to load pipelines");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchPipelines();
|
||||||
|
}, []);
|
||||||
return (
|
return (
|
||||||
<div className="container mx-auto p-6">
|
<div className="container mx-auto p-6">
|
||||||
|
{error && <p className="text-red-500">{error}</p>}
|
||||||
<PageHeader
|
<PageHeader
|
||||||
title="Data Pipelines"
|
title="Data Pipelines"
|
||||||
description="Manage your automated data collection pipelines"
|
description="Manage your automated data collection pipelines"
|
||||||
@ -37,7 +58,7 @@ export default function DataPipelinePage() {
|
|||||||
<TabsContent value="active" className="mt-4">
|
<TabsContent value="active" className="mt-4">
|
||||||
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
|
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
|
||||||
<PipelineCard
|
<PipelineCard
|
||||||
title="Property Listings"
|
name="Property Listings"
|
||||||
description="Scrapes real estate listings from multiple websites"
|
description="Scrapes real estate listings from multiple websites"
|
||||||
status="active"
|
status="active"
|
||||||
lastRun="2 hours ago"
|
lastRun="2 hours ago"
|
||||||
@ -48,7 +69,7 @@ export default function DataPipelinePage() {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<PipelineCard
|
<PipelineCard
|
||||||
title="Rental Market Data"
|
name="Rental Market Data"
|
||||||
description="Collects rental prices and availability"
|
description="Collects rental prices and availability"
|
||||||
status="active"
|
status="active"
|
||||||
lastRun="Yesterday"
|
lastRun="Yesterday"
|
||||||
@ -59,7 +80,7 @@ export default function DataPipelinePage() {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<PipelineCard
|
<PipelineCard
|
||||||
title="Price Comparison"
|
name="Price Comparison"
|
||||||
description="Tracks property price changes over time"
|
description="Tracks property price changes over time"
|
||||||
status="error"
|
status="error"
|
||||||
lastRun="2 days ago"
|
lastRun="2 days ago"
|
||||||
@ -74,7 +95,7 @@ export default function DataPipelinePage() {
|
|||||||
<TabsContent value="paused" className="mt-4">
|
<TabsContent value="paused" className="mt-4">
|
||||||
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
|
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
|
||||||
<PipelineCard
|
<PipelineCard
|
||||||
title="Commercial Properties"
|
name="Commercial Properties"
|
||||||
description="Collects data on commercial real estate"
|
description="Collects data on commercial real estate"
|
||||||
status="paused"
|
status="paused"
|
||||||
lastRun="1 week ago"
|
lastRun="1 week ago"
|
||||||
@ -88,7 +109,7 @@ export default function DataPipelinePage() {
|
|||||||
<TabsContent value="all" className="mt-4">
|
<TabsContent value="all" className="mt-4">
|
||||||
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
|
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
|
||||||
<PipelineCard
|
<PipelineCard
|
||||||
title="Property Listings"
|
name="Property Listings"
|
||||||
description="Scrapes real estate listings from multiple websites"
|
description="Scrapes real estate listings from multiple websites"
|
||||||
status="active"
|
status="active"
|
||||||
lastRun="2 hours ago"
|
lastRun="2 hours ago"
|
||||||
@ -100,7 +121,7 @@ export default function DataPipelinePage() {
|
|||||||
|
|
||||||
{/* mock pipeline card with data */}
|
{/* mock pipeline card with data */}
|
||||||
<PipelineCard
|
<PipelineCard
|
||||||
title="Rental Market Data"
|
name="Rental Market Data"
|
||||||
description="Collects rental prices and availability"
|
description="Collects rental prices and availability"
|
||||||
status="active"
|
status="active"
|
||||||
lastRun="Yesterday"
|
lastRun="Yesterday"
|
||||||
@ -111,7 +132,7 @@ export default function DataPipelinePage() {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<PipelineCard
|
<PipelineCard
|
||||||
title="Price Comparison"
|
name="Price Comparison"
|
||||||
description="Tracks property price changes over time"
|
description="Tracks property price changes over time"
|
||||||
status="error"
|
status="error"
|
||||||
lastRun="2 days ago"
|
lastRun="2 days ago"
|
||||||
@ -122,7 +143,7 @@ export default function DataPipelinePage() {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<PipelineCard
|
<PipelineCard
|
||||||
title="Commercial Properties"
|
name="Commercial Properties"
|
||||||
description="Collects data on commercial real estate"
|
description="Collects data on commercial real estate"
|
||||||
status="paused"
|
status="paused"
|
||||||
lastRun="1 week ago"
|
lastRun="1 week ago"
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import { PropertyInfoPanel } from "@/components/map/property-info-panel";
|
|||||||
import MapWithSearch from "@/components/map/map-with-search";
|
import MapWithSearch from "@/components/map/map-with-search";
|
||||||
import { TopNavigation } from "@/components/navigation/top-navigation";
|
import { TopNavigation } from "@/components/navigation/top-navigation";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { BarChart2, Filter, MapPin, MessageCircle } from "lucide-react";
|
import { BarChart2, Filter, MessageCircle } from "lucide-react";
|
||||||
import { useRef, useState } from "react";
|
import { useRef, useState } from "react";
|
||||||
import Draggable from "react-draggable";
|
import Draggable from "react-draggable";
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ export default function MapsPage() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Sample Property Markers */}
|
{/* Sample Property Markers */}
|
||||||
<div
|
{/* <div
|
||||||
className="absolute left-1/4 top-1/3 text-primary cursor-pointer group"
|
className="absolute left-1/4 top-1/3 text-primary cursor-pointer group"
|
||||||
onClick={handlePropertyClick}
|
onClick={handlePropertyClick}
|
||||||
>
|
>
|
||||||
@ -74,7 +74,7 @@ export default function MapsPage() {
|
|||||||
Sold
|
Sold
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> */}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Top Navigation Bar */}
|
{/* Top Navigation Bar */}
|
||||||
@ -91,7 +91,6 @@ export default function MapsPage() {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
setShowAnalytics(!showAnalytics);
|
setShowAnalytics(!showAnalytics);
|
||||||
if (showAnalytics) {
|
if (showAnalytics) {
|
||||||
setShowFilters(false);
|
|
||||||
setShowPropertyInfo(false);
|
setShowPropertyInfo(false);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
@ -107,7 +106,6 @@ export default function MapsPage() {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
setShowFilters(!showFilters);
|
setShowFilters(!showFilters);
|
||||||
if (showFilters) {
|
if (showFilters) {
|
||||||
setShowAnalytics(false);
|
|
||||||
setShowPropertyInfo(false);
|
setShowPropertyInfo(false);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|||||||
@ -1,31 +1,32 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState } from "react";
|
// import { ModelCard } from "@/components/models/model-card";
|
||||||
|
import PageHeader from "@/components/page-header";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
|
import {
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
Card,
|
||||||
import { Badge } from "@/components/ui/badge";
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@/components/ui/card";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
|
||||||
import { Switch } from "@/components/ui/switch";
|
|
||||||
import { Progress } from "@/components/ui/progress";
|
import { Progress } from "@/components/ui/progress";
|
||||||
|
import { Switch } from "@/components/ui/switch";
|
||||||
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||||
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
|
import { useModelState } from "@/store/model-store";
|
||||||
import {
|
import {
|
||||||
|
AlertTriangle,
|
||||||
BrainCircuit,
|
BrainCircuit,
|
||||||
Clock,
|
Check,
|
||||||
Database,
|
Database,
|
||||||
Play,
|
Play,
|
||||||
Plus,
|
Plus,
|
||||||
Settings,
|
|
||||||
Sliders,
|
|
||||||
Trash2,
|
|
||||||
AlertTriangle,
|
|
||||||
Check,
|
|
||||||
ArrowRight,
|
|
||||||
Info,
|
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import Link from "next/link";
|
import { useState } from "react";
|
||||||
import PageHeader from "@/components/page-header";
|
import { useShallow } from "zustand/react/shallow";
|
||||||
|
|
||||||
export default function ModelsPage() {
|
export default function ModelsPage() {
|
||||||
const [activeTab, setActiveTab] = useState("my-models");
|
const [activeTab, setActiveTab] = useState("my-models");
|
||||||
@ -34,85 +35,36 @@ export default function ModelsPage() {
|
|||||||
const [isTraining, setIsTraining] = useState(false);
|
const [isTraining, setIsTraining] = useState(false);
|
||||||
const [modelName, setModelName] = useState("");
|
const [modelName, setModelName] = useState("");
|
||||||
const [modelDescription, setModelDescription] = useState("");
|
const [modelDescription, setModelDescription] = useState("");
|
||||||
|
const { models } = useModelState(
|
||||||
|
useShallow((state) => ({
|
||||||
|
models: state.models,
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
const dataPipelines = [
|
const dataPipelines = [
|
||||||
{ id: "pipeline-1", name: "Property Listings", records: 1240, lastUpdated: "2 hours ago" },
|
|
||||||
{ id: "pipeline-2", name: "Rental Market Data", records: 830, lastUpdated: "Yesterday" },
|
|
||||||
{ id: "pipeline-3", name: "Price Comparison", records: 1560, lastUpdated: "2 days ago" },
|
|
||||||
{ id: "pipeline-4", name: "Commercial Properties", records: 450, lastUpdated: "1 week ago" },
|
|
||||||
];
|
|
||||||
|
|
||||||
const models = [
|
|
||||||
{
|
{
|
||||||
id: "model-1",
|
id: "pipeline-1",
|
||||||
name: "Standard ML Model v2.4",
|
name: "Property Listings",
|
||||||
type: "Regression",
|
records: 1240,
|
||||||
hyperparameters: {
|
lastUpdated: "2 hours ago",
|
||||||
learningRate: "0.01",
|
|
||||||
maxDepth: "6",
|
|
||||||
numEstimators: "100",
|
|
||||||
},
|
|
||||||
dataSource: "System Base Model",
|
|
||||||
status: "active",
|
|
||||||
lastUpdated: "3 days ago",
|
|
||||||
isSystem: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "model-2",
|
id: "pipeline-2",
|
||||||
name: "Enhanced Neural Network v1.8",
|
name: "Rental Market Data",
|
||||||
type: "Neural Network",
|
records: 830,
|
||||||
hyperparameters: {
|
lastUpdated: "Yesterday",
|
||||||
layers: "4",
|
},
|
||||||
neurons: "128,64,32,16",
|
{
|
||||||
dropout: "0.2",
|
id: "pipeline-3",
|
||||||
},
|
name: "Price Comparison",
|
||||||
dataSource: "System Base Model",
|
records: 1560,
|
||||||
status: "active",
|
lastUpdated: "2 days ago",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "pipeline-4",
|
||||||
|
name: "Commercial Properties",
|
||||||
|
records: 450,
|
||||||
lastUpdated: "1 week ago",
|
lastUpdated: "1 week ago",
|
||||||
isSystem: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "model-3",
|
|
||||||
name: "Geospatial Regression v3.1",
|
|
||||||
type: "Geospatial",
|
|
||||||
hyperparameters: {
|
|
||||||
spatialWeight: "0.7",
|
|
||||||
kernelType: "gaussian",
|
|
||||||
bandwidth: "adaptive",
|
|
||||||
},
|
|
||||||
dataSource: "System Base Model",
|
|
||||||
status: "active",
|
|
||||||
lastUpdated: "2 weeks ago",
|
|
||||||
isSystem: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "model-4",
|
|
||||||
name: "Time Series Forecast v2.0",
|
|
||||||
type: "Time Series",
|
|
||||||
hyperparameters: {
|
|
||||||
p: "2",
|
|
||||||
d: "1",
|
|
||||||
q: "2",
|
|
||||||
seasonal: "true",
|
|
||||||
},
|
|
||||||
dataSource: "System Base Model",
|
|
||||||
status: "active",
|
|
||||||
lastUpdated: "1 month ago",
|
|
||||||
isSystem: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "model-5",
|
|
||||||
name: "Custom Model (User #1242)",
|
|
||||||
type: "Ensemble",
|
|
||||||
hyperparameters: {
|
|
||||||
baseEstimators: "3",
|
|
||||||
votingMethod: "weighted",
|
|
||||||
weights: "0.4,0.4,0.2",
|
|
||||||
},
|
|
||||||
dataSource: "Property Listings Pipeline",
|
|
||||||
status: "active",
|
|
||||||
lastUpdated: "5 days ago",
|
|
||||||
isSystem: false,
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -146,7 +98,11 @@ export default function ModelsPage() {
|
|||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Tabs defaultValue="my-models" className="mt-6" onValueChange={setActiveTab}>
|
<Tabs
|
||||||
|
defaultValue="my-models"
|
||||||
|
className="mt-6"
|
||||||
|
onValueChange={setActiveTab}
|
||||||
|
>
|
||||||
<div className="flex justify-between items-center mb-6">
|
<div className="flex justify-between items-center mb-6">
|
||||||
<TabsList>
|
<TabsList>
|
||||||
<TabsTrigger value="my-models">My Models</TabsTrigger>
|
<TabsTrigger value="my-models">My Models</TabsTrigger>
|
||||||
@ -155,7 +111,10 @@ export default function ModelsPage() {
|
|||||||
</TabsList>
|
</TabsList>
|
||||||
|
|
||||||
{activeTab !== "train-model" && (
|
{activeTab !== "train-model" && (
|
||||||
<Button onClick={() => setActiveTab("train-model")} className="gap-2">
|
<Button
|
||||||
|
onClick={() => setActiveTab("train-model")}
|
||||||
|
className="gap-2"
|
||||||
|
>
|
||||||
<Plus className="h-4 w-4" />
|
<Plus className="h-4 w-4" />
|
||||||
Train New Model
|
Train New Model
|
||||||
</Button>
|
</Button>
|
||||||
@ -164,35 +123,34 @@ export default function ModelsPage() {
|
|||||||
|
|
||||||
<TabsContent value="my-models">
|
<TabsContent value="my-models">
|
||||||
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
|
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
|
||||||
{models
|
{/* {models} */}
|
||||||
.filter((model) => !model.isSystem)
|
|
||||||
.map((model) => (
|
|
||||||
<ModelCard key={model.id} model={model} />
|
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{models.filter((model) => !model.isSystem).length === 0 && (
|
{models && (
|
||||||
<Card className="border-dashed">
|
<Card className="border-dashed">
|
||||||
<CardContent className="pt-6 text-center">
|
<CardContent className="pt-6 text-center">
|
||||||
<BrainCircuit className="h-12 w-12 text-muted-foreground mx-auto mb-4" />
|
<BrainCircuit className="h-12 w-12 text-muted-foreground mx-auto mb-4" />
|
||||||
<h3 className="text-lg font-medium mb-2">No Custom Models Yet</h3>
|
<h3 className="text-lg font-medium mb-2">
|
||||||
|
No Custom Models Yet
|
||||||
|
</h3>
|
||||||
<p className="text-sm text-muted-foreground mb-4">
|
<p className="text-sm text-muted-foreground mb-4">
|
||||||
Train your first custom model to get started with personalized property predictions.
|
Train your first custom model to get started with personalized
|
||||||
|
property predictions.
|
||||||
</p>
|
</p>
|
||||||
<Button onClick={() => setActiveTab("train-model")}>Train Your First Model</Button>
|
<Button onClick={() => setActiveTab("train-model")}>
|
||||||
|
Train Your First Model
|
||||||
|
</Button>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
)}
|
)}
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
|
|
||||||
<TabsContent value="system-models">
|
<TabsContent value="system-models">
|
||||||
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
|
{/* <div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
|
||||||
{models
|
{models.map((model) => (
|
||||||
.filter((model) => model.isSystem)
|
<ModelCard model={model} />
|
||||||
.map((model) => (
|
))}
|
||||||
<ModelCard key={model.id} model={model} />
|
</div> */}
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
|
|
||||||
<TabsContent value="train-model">
|
<TabsContent value="train-model">
|
||||||
@ -215,7 +173,9 @@ export default function ModelsPage() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label htmlFor="model-description">Description (Optional)</Label>
|
<Label htmlFor="model-description">
|
||||||
|
Description (Optional)
|
||||||
|
</Label>
|
||||||
<Textarea
|
<Textarea
|
||||||
id="model-description"
|
id="model-description"
|
||||||
placeholder="Describe the purpose of this model..."
|
placeholder="Describe the purpose of this model..."
|
||||||
@ -237,28 +197,42 @@ export default function ModelsPage() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="pt-2">
|
<div className="pt-2">
|
||||||
<h3 className="text-sm font-medium mb-2">Advanced Settings</h3>
|
<h3 className="text-sm font-medium mb-2">
|
||||||
|
Advanced Settings
|
||||||
|
</h3>
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="space-y-0.5">
|
<div className="space-y-0.5">
|
||||||
<Label htmlFor="feature-selection">Automatic Feature Selection</Label>
|
<Label htmlFor="feature-selection">
|
||||||
<p className="text-xs text-muted-foreground">Let AI select the most relevant features</p>
|
Automatic Feature Selection
|
||||||
|
</Label>
|
||||||
|
<p className="text-xs text-muted-foreground">
|
||||||
|
Let AI select the most relevant features
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<Switch id="feature-selection" defaultChecked />
|
<Switch id="feature-selection" defaultChecked />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="space-y-0.5">
|
<div className="space-y-0.5">
|
||||||
<Label htmlFor="hyperparameter-tuning">Hyperparameter Tuning</Label>
|
<Label htmlFor="hyperparameter-tuning">
|
||||||
<p className="text-xs text-muted-foreground">Optimize model parameters automatically</p>
|
Hyperparameter Tuning
|
||||||
|
</Label>
|
||||||
|
<p className="text-xs text-muted-foreground">
|
||||||
|
Optimize model parameters automatically
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<Switch id="hyperparameter-tuning" defaultChecked />
|
<Switch id="hyperparameter-tuning" defaultChecked />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="space-y-0.5">
|
<div className="space-y-0.5">
|
||||||
<Label htmlFor="cross-validation">Cross-Validation</Label>
|
<Label htmlFor="cross-validation">
|
||||||
<p className="text-xs text-muted-foreground">Use k-fold cross-validation</p>
|
Cross-Validation
|
||||||
|
</Label>
|
||||||
|
<p className="text-xs text-muted-foreground">
|
||||||
|
Use k-fold cross-validation
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<Switch id="cross-validation" defaultChecked />
|
<Switch id="cross-validation" defaultChecked />
|
||||||
</div>
|
</div>
|
||||||
@ -272,7 +246,9 @@ export default function ModelsPage() {
|
|||||||
<Card className="mb-6">
|
<Card className="mb-6">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>Select Data Source</CardTitle>
|
<CardTitle>Select Data Source</CardTitle>
|
||||||
<CardDescription>Choose a data pipeline to train your model</CardDescription>
|
<CardDescription>
|
||||||
|
Choose a data pipeline to train your model
|
||||||
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
@ -280,20 +256,26 @@ export default function ModelsPage() {
|
|||||||
<div
|
<div
|
||||||
key={pipeline.id}
|
key={pipeline.id}
|
||||||
className={`p-4 border rounded-lg cursor-pointer transition-all ${
|
className={`p-4 border rounded-lg cursor-pointer transition-all ${
|
||||||
selectedPipeline === pipeline.id ? "border-primary bg-primary/5" : "hover:border-primary/50"
|
selectedPipeline === pipeline.id
|
||||||
|
? "border-primary bg-primary/5"
|
||||||
|
: "hover:border-primary/50"
|
||||||
}`}
|
}`}
|
||||||
onClick={() => setSelectedPipeline(pipeline.id)}>
|
onClick={() => setSelectedPipeline(pipeline.id)}
|
||||||
|
>
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<Database className="h-5 w-5 text-primary" />
|
<Database className="h-5 w-5 text-primary" />
|
||||||
<div>
|
<div>
|
||||||
<h3 className="font-medium">{pipeline.name}</h3>
|
<h3 className="font-medium">{pipeline.name}</h3>
|
||||||
<p className="text-xs text-muted-foreground">
|
<p className="text-xs text-muted-foreground">
|
||||||
{pipeline.records.toLocaleString()} records • Updated {pipeline.lastUpdated}
|
{pipeline.records.toLocaleString()} records •
|
||||||
|
Updated {pipeline.lastUpdated}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{selectedPipeline === pipeline.id && <Check className="h-5 w-5 text-primary" />}
|
{selectedPipeline === pipeline.id && (
|
||||||
|
<Check className="h-5 w-5 text-primary" />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
@ -304,7 +286,9 @@ export default function ModelsPage() {
|
|||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>Training Process</CardTitle>
|
<CardTitle>Training Process</CardTitle>
|
||||||
<CardDescription>Monitor and control the training process</CardDescription>
|
<CardDescription>
|
||||||
|
Monitor and control the training process
|
||||||
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
{isTraining ? (
|
{isTraining ? (
|
||||||
@ -335,7 +319,11 @@ export default function ModelsPage() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{trainingProgress < 100 && (
|
{trainingProgress < 100 && (
|
||||||
<Button variant="outline" className="w-full" onClick={() => setIsTraining(false)}>
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
className="w-full"
|
||||||
|
onClick={() => setIsTraining(false)}
|
||||||
|
>
|
||||||
Cancel Training
|
Cancel Training
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
@ -363,7 +351,9 @@ export default function ModelsPage() {
|
|||||||
<BrainCircuit className="h-8 w-8 text-primary" />
|
<BrainCircuit className="h-8 w-8 text-primary" />
|
||||||
<div>
|
<div>
|
||||||
<h3 className="font-medium">Ready to Train</h3>
|
<h3 className="font-medium">Ready to Train</h3>
|
||||||
<p className="text-sm text-muted-foreground">Configure your settings and start training</p>
|
<p className="text-sm text-muted-foreground">
|
||||||
|
Configure your settings and start training
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -383,13 +373,18 @@ export default function ModelsPage() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<Button variant="outline" className="flex-1" onClick={() => setActiveTab("my-models")}>
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
className="flex-1"
|
||||||
|
onClick={() => setActiveTab("my-models")}
|
||||||
|
>
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
className="flex-1 gap-2"
|
className="flex-1 gap-2"
|
||||||
onClick={handleStartTraining}
|
onClick={handleStartTraining}
|
||||||
disabled={!selectedPipeline || !modelName}>
|
disabled={!selectedPipeline || !modelName}
|
||||||
|
>
|
||||||
<Play className="h-4 w-4" />
|
<Play className="h-4 w-4" />
|
||||||
Start Training
|
Start Training
|
||||||
</Button>
|
</Button>
|
||||||
@ -405,96 +400,3 @@ export default function ModelsPage() {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ModelCardProps {
|
|
||||||
model: {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
type: string;
|
|
||||||
hyperparameters: {
|
|
||||||
[key: string]: string;
|
|
||||||
};
|
|
||||||
dataSource: string;
|
|
||||||
status: string;
|
|
||||||
lastUpdated: string;
|
|
||||||
isSystem: boolean;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function ModelCard({ model }: ModelCardProps) {
|
|
||||||
return (
|
|
||||||
<Card className={model.isSystem ? "border-primary/20" : ""}>
|
|
||||||
<CardHeader className="pb-2">
|
|
||||||
<div className="flex justify-between items-start">
|
|
||||||
<CardTitle className="text-lg">{model.name}</CardTitle>
|
|
||||||
<Badge variant={model.status === "active" ? "default" : "secondary"}>
|
|
||||||
{model.status === "active" ? "Active" : "Inactive"}
|
|
||||||
</Badge>
|
|
||||||
</div>
|
|
||||||
<CardDescription>{model.type} Model</CardDescription>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<div className="space-y-4">
|
|
||||||
<div>
|
|
||||||
<div className="flex items-center gap-1 mb-1">
|
|
||||||
<Database className="h-4 w-4 text-primary" />
|
|
||||||
<span className="text-sm font-medium">Data Source:</span>
|
|
||||||
</div>
|
|
||||||
{model.isSystem ? (
|
|
||||||
<div className="flex items-center gap-1 text-sm">
|
|
||||||
<Badge variant="outline" className="bg-primary/5">
|
|
||||||
System Base Model
|
|
||||||
</Badge>
|
|
||||||
<Info
|
|
||||||
className="h-4 w-4 text-muted-foreground cursor-help"
|
|
||||||
title="This is a pre-trained system model"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<span className="text-sm">{model.dataSource}</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div className="flex items-center gap-1 mb-1">
|
|
||||||
<Sliders className="h-4 w-4 text-primary" />
|
|
||||||
<span className="text-sm font-medium">Hyperparameters:</span>
|
|
||||||
</div>
|
|
||||||
<div className="grid grid-cols-1 gap-1">
|
|
||||||
{Object.entries(model.hyperparameters).map(([key, value]) => (
|
|
||||||
<div key={key} className="flex justify-between text-xs">
|
|
||||||
<span className="text-muted-foreground">{key}:</span>
|
|
||||||
<span>{value}</span>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex items-center text-sm">
|
|
||||||
<Clock className="h-4 w-4 mr-2 text-muted-foreground" />
|
|
||||||
<span className="text-muted-foreground">Last updated:</span>
|
|
||||||
<span className="ml-1 font-medium">{model.lastUpdated}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
<CardFooter className="flex justify-between">
|
|
||||||
<Button variant="outline" size="sm" asChild>
|
|
||||||
<Link href={model.isSystem ? "/documentation/models" : "/models/details"}>View Details</Link>
|
|
||||||
</Button>
|
|
||||||
<div className="flex gap-2">
|
|
||||||
<Button variant="outline" size="icon" className="h-8 w-8 text-primary border-primary/20 hover:border-primary">
|
|
||||||
<Settings className="h-4 w-4" />
|
|
||||||
</Button>
|
|
||||||
{!model.isSystem && (
|
|
||||||
<Button variant="outline" size="icon" className="h-8 w-8 border-primary/20 hover:border-primary">
|
|
||||||
<Trash2 className="h-4 w-4" />
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
<Button variant="outline" size="icon" className="h-8 w-8 border-primary/20 hover:border-primary">
|
|
||||||
<ArrowRight className="h-4 w-4" />
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</CardFooter>
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|||||||
128
frontend/components/models/model-card.tsx
Normal file
128
frontend/components/models/model-card.tsx
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
// import {
|
||||||
|
// ArrowRight,
|
||||||
|
// Clock,
|
||||||
|
// Database,
|
||||||
|
// Info,
|
||||||
|
// Link,
|
||||||
|
// Settings,
|
||||||
|
// Sliders,
|
||||||
|
// Trash2,
|
||||||
|
// } from "lucide-react";
|
||||||
|
// import { Badge } from "../ui/badge";
|
||||||
|
// import { Button } from "../ui/button";
|
||||||
|
// import {
|
||||||
|
// Card,
|
||||||
|
// CardContent,
|
||||||
|
// CardDescription,
|
||||||
|
// CardFooter,
|
||||||
|
// CardHeader,
|
||||||
|
// CardTitle,
|
||||||
|
// } from "../ui/card";
|
||||||
|
|
||||||
|
// interface ModelCardProps {
|
||||||
|
// model: {
|
||||||
|
// id: string;
|
||||||
|
// name: string;
|
||||||
|
// type: string;
|
||||||
|
// // hyperparameters: {
|
||||||
|
// // [key: string]: string;
|
||||||
|
// // };
|
||||||
|
// // dataSource: string;
|
||||||
|
// status: string;
|
||||||
|
// // lastUpdated: string;
|
||||||
|
// // isSystem: boolean;
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
|
||||||
|
// export function ModelCard({ model }: ModelCardProps) {
|
||||||
|
// return (
|
||||||
|
// <Card>
|
||||||
|
// <CardHeader className="pb-2">
|
||||||
|
// <div className="flex justify-between items-start">
|
||||||
|
// <CardTitle className="text-lg">{model.name}</CardTitle>
|
||||||
|
// <Badge variant={model.status === "active" ? "default" : "secondary"}>
|
||||||
|
// {model.status === "active" ? "Active" : "Inactive"}
|
||||||
|
// </Badge>
|
||||||
|
// </div>
|
||||||
|
// <CardDescription>{model.type} Model</CardDescription>
|
||||||
|
// </CardHeader>
|
||||||
|
// <CardContent>
|
||||||
|
// <div className="space-y-4">
|
||||||
|
// <div>
|
||||||
|
// <div className="flex items-center gap-1 mb-1">
|
||||||
|
// <Database className="h-4 w-4 text-primary" />
|
||||||
|
// <span className="text-sm font-medium">Data Source:</span>
|
||||||
|
// </div>
|
||||||
|
// {model.isSystem ? (
|
||||||
|
// <div className="flex items-center gap-1 text-sm">
|
||||||
|
// <Badge variant="outline" className="bg-primary/5">
|
||||||
|
// System Base Model
|
||||||
|
// </Badge>
|
||||||
|
// <span title="This is a pre-trained system model">
|
||||||
|
// <Info className="h-4 w-4 text-muted-foreground cursor-help" />
|
||||||
|
// </span>
|
||||||
|
// </div>
|
||||||
|
// ) : (
|
||||||
|
// <span className="text-sm">{model.dataSource}</span>
|
||||||
|
// )}
|
||||||
|
// </div>
|
||||||
|
|
||||||
|
// <div>
|
||||||
|
// <div className="flex items-center gap-1 mb-1">
|
||||||
|
// <Sliders className="h-4 w-4 text-primary" />
|
||||||
|
// <span className="text-sm font-medium">Hyperparameters:</span>
|
||||||
|
// </div>
|
||||||
|
// <div className="grid grid-cols-1 gap-1">
|
||||||
|
// {Object.entries(model.hyperparameters).map(([key, value]) => (
|
||||||
|
// <div key={key} className="flex justify-between text-xs">
|
||||||
|
// <span className="text-muted-foreground">{key}:</span>
|
||||||
|
// <span>{value}</span>
|
||||||
|
// </div>
|
||||||
|
// ))}
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
|
||||||
|
// <div className="flex items-center text-sm">
|
||||||
|
// <Clock className="h-4 w-4 mr-2 text-muted-foreground" />
|
||||||
|
// <span className="text-muted-foreground">Last updated:</span>
|
||||||
|
// <span className="ml-1 font-medium">{model.lastUpdated}</span>
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// </CardContent>
|
||||||
|
// <CardFooter className="flex justify-between">
|
||||||
|
// <Button variant="outline" size="sm" asChild>
|
||||||
|
// <Link
|
||||||
|
// href={model.isSystem ? "/documentation/models" : "/models/details"}
|
||||||
|
// >
|
||||||
|
// View Details
|
||||||
|
// </Link>
|
||||||
|
// </Button>
|
||||||
|
// <div className="flex gap-2">
|
||||||
|
// <Button
|
||||||
|
// variant="outline"
|
||||||
|
// size="icon"
|
||||||
|
// className="h-8 w-8 text-primary border-primary/20 hover:border-primary"
|
||||||
|
// >
|
||||||
|
// <Settings className="h-4 w-4" />
|
||||||
|
// </Button>
|
||||||
|
// {!model.isSystem && (
|
||||||
|
// <Button
|
||||||
|
// variant="outline"
|
||||||
|
// size="icon"
|
||||||
|
// className="h-8 w-8 border-primary/20 hover:border-primary"
|
||||||
|
// >
|
||||||
|
// <Trash2 className="h-4 w-4" />
|
||||||
|
// </Button>
|
||||||
|
// )}
|
||||||
|
// <Button
|
||||||
|
// variant="outline"
|
||||||
|
// size="icon"
|
||||||
|
// className="h-8 w-8 border-primary/20 hover:border-primary"
|
||||||
|
// >
|
||||||
|
// <ArrowRight className="h-4 w-4" />
|
||||||
|
// </Button>
|
||||||
|
// </div>
|
||||||
|
// </CardFooter>
|
||||||
|
// </Card>
|
||||||
|
// );
|
||||||
|
// }
|
||||||
@ -1,26 +1,25 @@
|
|||||||
import {
|
import { Button } from "@/components/ui/button";
|
||||||
Clock,
|
|
||||||
Database,
|
|
||||||
Play,
|
|
||||||
RefreshCw,
|
|
||||||
Pause,
|
|
||||||
AlertTriangle,
|
|
||||||
Copy,
|
|
||||||
} from "lucide-react";
|
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
CardContent,
|
CardContent,
|
||||||
CardDescription,
|
|
||||||
CardFooter,
|
CardFooter,
|
||||||
CardHeader,
|
CardHeader,
|
||||||
CardTitle,
|
CardTitle,
|
||||||
} from "@/components/ui/card";
|
} from "@/components/ui/card";
|
||||||
import { StatusBadge } from "./badge";
|
import {
|
||||||
|
AlertTriangle,
|
||||||
|
Clock,
|
||||||
|
Copy,
|
||||||
|
Database,
|
||||||
|
Pause,
|
||||||
|
Play,
|
||||||
|
RefreshCw,
|
||||||
|
} from "lucide-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { Button } from "@/components/ui/button";
|
import { StatusBadge } from "./badge";
|
||||||
|
|
||||||
interface PipelineCardProps {
|
interface PipelineCardProps {
|
||||||
title: string;
|
name: string;
|
||||||
description: string;
|
description: string;
|
||||||
status: "active" | "paused" | "error";
|
status: "active" | "paused" | "error";
|
||||||
lastRun: string;
|
lastRun: string;
|
||||||
@ -32,7 +31,7 @@ interface PipelineCardProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function PipelineCard({
|
export function PipelineCard({
|
||||||
title,
|
name,
|
||||||
description,
|
description,
|
||||||
status,
|
status,
|
||||||
lastRun,
|
lastRun,
|
||||||
@ -51,10 +50,10 @@ export function PipelineCard({
|
|||||||
>
|
>
|
||||||
<CardHeader className="pb-2">
|
<CardHeader className="pb-2">
|
||||||
<div className="flex justify-between items-start">
|
<div className="flex justify-between items-start">
|
||||||
<CardTitle className="text-lg">{title}</CardTitle>
|
<CardTitle className="text-lg">{name}</CardTitle>
|
||||||
<StatusBadge status={status} />
|
<StatusBadge status={status} />
|
||||||
</div>
|
</div>
|
||||||
<CardDescription>{description}</CardDescription>
|
{/* <CardDescription>{description}</CardDescription> */}
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
@ -86,7 +85,7 @@ export function PipelineCard({
|
|||||||
</CardContent>
|
</CardContent>
|
||||||
<CardFooter className="flex justify-between">
|
<CardFooter className="flex justify-between">
|
||||||
<Link
|
<Link
|
||||||
href={`/data-pipeline/${title.toLowerCase().replace(/\s+/g, "-")}`}
|
href={`/data-pipeline/${name.toLowerCase().replace(/\s+/g, "-")}`}
|
||||||
>
|
>
|
||||||
<Button variant="outline" size="sm">
|
<Button variant="outline" size="sm">
|
||||||
View Details
|
View Details
|
||||||
|
|||||||
110
frontend/lib/api/pipelines/index.ts
Normal file
110
frontend/lib/api/pipelines/index.ts
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
import { Pipeline, PipelineCreate, Run } from "./types";
|
||||||
|
|
||||||
|
// Base URL for your API
|
||||||
|
const API_BASE = process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
// if (typeof window !== "undefined") {
|
||||||
|
// console.log(API_BASE);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Utility for handling fetch responses
|
||||||
|
async function handleResponse<T>(res: Response): Promise<T> {
|
||||||
|
if (!res.ok) {
|
||||||
|
const errorBody = await res.json();
|
||||||
|
throw new Error(JSON.stringify(errorBody));
|
||||||
|
}
|
||||||
|
return res.json();
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /pipelines
|
||||||
|
export async function listPipelines(): Promise<Pipeline[]> {
|
||||||
|
const res = await fetch(`${API_BASE}/pipelines`);
|
||||||
|
return handleResponse<Pipeline[]>(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /pipelines
|
||||||
|
export async function createPipeline(
|
||||||
|
payload: PipelineCreate
|
||||||
|
): Promise<Pipeline> {
|
||||||
|
const res = await fetch(`${API_BASE}/pipelines`, {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify(payload),
|
||||||
|
});
|
||||||
|
return handleResponse<Pipeline>(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /pipelines/{pipeline_id}
|
||||||
|
export async function getPipeline(pipeline_id: string): Promise<Pipeline> {
|
||||||
|
const res = await fetch(`${API_BASE}/pipelines/${pipeline_id}`);
|
||||||
|
return handleResponse<Pipeline>(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /pipelines/{pipeline_id}/run
|
||||||
|
export async function runPipeline(pipeline_id: string): Promise<Run> {
|
||||||
|
const res = await fetch(`${API_BASE}/pipelines/${pipeline_id}/run`, {
|
||||||
|
method: "POST",
|
||||||
|
});
|
||||||
|
return handleResponse<Run>(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /pipelines/{pipeline_id}/runs
|
||||||
|
export async function listRuns(pipeline_id: string): Promise<Run[]> {
|
||||||
|
const res = await fetch(`${API_BASE}/pipelines/${pipeline_id}/runs`);
|
||||||
|
return handleResponse<Run[]>(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /pipelines/{pipeline_id}/runs/{run_id}
|
||||||
|
export async function getRun(
|
||||||
|
pipeline_id: string,
|
||||||
|
run_id: string
|
||||||
|
): Promise<Run> {
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE}/pipelines/${pipeline_id}/runs/${run_id}`
|
||||||
|
);
|
||||||
|
return handleResponse<Run>(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /pipelines/{pipeline_id}/runs/{run_id}/results
|
||||||
|
export async function getRunResults(
|
||||||
|
pipeline_id: string,
|
||||||
|
run_id: string
|
||||||
|
): Promise<any[]> {
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE}/pipelines/${pipeline_id}/runs/${run_id}/results`
|
||||||
|
);
|
||||||
|
return handleResponse<any[]>(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /pipelines/{pipeline_id}/runs/{run_id}/error
|
||||||
|
export async function getRunError(
|
||||||
|
pipeline_id: string,
|
||||||
|
run_id: string
|
||||||
|
): Promise<string> {
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE}/pipelines/${pipeline_id}/runs/${run_id}/error`
|
||||||
|
);
|
||||||
|
return handleResponse<string>(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SSE: /pipelines/{pipeline_id}/runs/{run_id}/logs/stream
|
||||||
|
export function streamLogs(
|
||||||
|
pipeline_id: string,
|
||||||
|
run_id: string,
|
||||||
|
onMessage: (data: string) => void,
|
||||||
|
onError?: (event: Event) => void
|
||||||
|
): EventSource {
|
||||||
|
const url = `${API_BASE}/pipelines/${pipeline_id}/runs/${run_id}/logs/stream`;
|
||||||
|
const eventSource = new EventSource(url);
|
||||||
|
|
||||||
|
eventSource.onmessage = (event) => {
|
||||||
|
onMessage(event.data);
|
||||||
|
};
|
||||||
|
|
||||||
|
eventSource.onerror = (event) => {
|
||||||
|
if (onError) onError(event);
|
||||||
|
eventSource.close();
|
||||||
|
};
|
||||||
|
|
||||||
|
return eventSource;
|
||||||
|
}
|
||||||
64
frontend/lib/api/pipelines/types.ts
Normal file
64
frontend/lib/api/pipelines/types.ts
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
// types.ts
|
||||||
|
|
||||||
|
export interface ApiConfig {
|
||||||
|
url: string;
|
||||||
|
token?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ApiSource {
|
||||||
|
type: "api";
|
||||||
|
config: ApiConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FileConfig {
|
||||||
|
path: string;
|
||||||
|
format?: "csv" | "json" | "sqlite";
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FileSource {
|
||||||
|
type: "file";
|
||||||
|
config: FileConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ScrapeConfig {
|
||||||
|
urls: string[];
|
||||||
|
schema_file?: string | null;
|
||||||
|
prompt?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ScrapeSource {
|
||||||
|
type: "scrape";
|
||||||
|
config: ScrapeConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type DataSource = ApiSource | FileSource | ScrapeSource;
|
||||||
|
|
||||||
|
export interface Pipeline {
|
||||||
|
id: string;
|
||||||
|
name?: string | null;
|
||||||
|
sources: DataSource[];
|
||||||
|
created_at: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PipelineCreate {
|
||||||
|
name?: string | null;
|
||||||
|
sources: DataSource[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Run {
|
||||||
|
id: string;
|
||||||
|
pipeline_id: string;
|
||||||
|
status: "PENDING" | "RUNNING" | "COMPLETED" | "FAILED";
|
||||||
|
started_at: string;
|
||||||
|
finished_at?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ValidationError {
|
||||||
|
loc: (string | number)[];
|
||||||
|
msg: string;
|
||||||
|
type: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HTTPValidationError {
|
||||||
|
detail: ValidationError[];
|
||||||
|
}
|
||||||
@ -26,9 +26,18 @@ export interface SuccessResponse {
|
|||||||
/**
|
/**
|
||||||
* Property Data Types
|
* Property Data Types
|
||||||
*/
|
*/
|
||||||
export type PropertyType = "Condominium" | "House" | "Townhouse" | "Land" | "Apartment" | "Other";
|
export type PropertyType =
|
||||||
|
| "Condominium"
|
||||||
|
| "House"
|
||||||
|
| "Townhouse"
|
||||||
|
| "Land"
|
||||||
|
| "Apartment"
|
||||||
|
| "Other";
|
||||||
export type OwnershipType = "Freehold" | "Leasehold";
|
export type OwnershipType = "Freehold" | "Leasehold";
|
||||||
export type FurnishingStatus = "Unfurnished" | "Partly Furnished" | "Fully Furnished";
|
export type FurnishingStatus =
|
||||||
|
| "Unfurnished"
|
||||||
|
| "Partly Furnished"
|
||||||
|
| "Fully Furnished";
|
||||||
|
|
||||||
export interface PriceHistoryEntry {
|
export interface PriceHistoryEntry {
|
||||||
date: string; // Consider using Date object after parsing
|
date: string; // Consider using Date object after parsing
|
||||||
@ -134,8 +143,19 @@ export interface DataPipeline {
|
|||||||
/**
|
/**
|
||||||
* Model Types
|
* Model Types
|
||||||
*/
|
*/
|
||||||
export type ModelType = "Regression" | "Neural Network" | "Geospatial" | "Time Series" | "Ensemble" | "Classification";
|
export type ModelType =
|
||||||
export type ModelStatus = "active" | "inactive" | "training" | "error" | "pending";
|
| "Regression"
|
||||||
|
| "Neural Network"
|
||||||
|
| "Geospatial"
|
||||||
|
| "Time Series"
|
||||||
|
| "Ensemble"
|
||||||
|
| "Classification";
|
||||||
|
export type ModelStatus =
|
||||||
|
| "active"
|
||||||
|
| "inactive"
|
||||||
|
| "training"
|
||||||
|
| "error"
|
||||||
|
| "pending";
|
||||||
|
|
||||||
export interface Model {
|
export interface Model {
|
||||||
id: string;
|
id: string;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user