Add new gettallfeed api

This commit is contained in:
2025-05-07 22:28:02 +03:30
parent 117edf2cf1
commit 8e36304b5a
3 changed files with 122 additions and 101 deletions

View File

@@ -3,8 +3,8 @@ import { toast } from 'sonner';
import { getToken, clearToken } from './auth';
// Set up API base URLs
const USER_DATA_API_URL = 'https://io-userdata.monasefloadbalancer.ir';
const DATA_API_URL = 'https://io-data.monasefloadbalancer.ir/api';
const USER_DATA_API_URL = 'http://127.0.0.1:5001';
const DATA_API_URL = 'http://127.0.0.1:5002/api';
// Create axios instances
const userDataApi = axios.create({
@@ -87,43 +87,32 @@ export const getAllFeeds = async () => {
}
};
export const updateFeed = async (feedId: string, name: string, isPublic: boolean) => {
const token = getToken();
if (!token) throw new Error('Authentication required');
const response = await userDataApi.patch('/api/updatefeed', {
feedId,
Name: name,
IsPublic: isPublic,
}, {
headers: {
Authorization: `Bearer ${token}`
}
});
return response.data;
};
export const addNewFeed = async (name: string, isPublic: boolean) => {
const token = getToken();
if (!token) throw new Error('Authentication required');
try {
const response = await userDataApi.post('/api/addnewfeed', {
Name: name,
IsPublic: isPublic
}, {
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json'
const token = getToken();
if (!token) {
throw new Error('Authentication required');
}
const response = await userDataApi.post(
'/api/addnewfeed',
{
Name: name,
IsPublic: isPublic,
},
{
headers: {
Authorization: `Bearer ${token}`,
},
}
});
);
return response.data;
} catch (error: any) {
throw error.response?.data || { success: false, message: 'Network error' };
}
};
export const deleteFeed = async (feedId: string) => {
try {
const response = await userDataApi.delete('/api/deletefeed', {

View File

@@ -25,7 +25,7 @@ export interface ApiKeyResponse {
apiKey: string;
}
// New ApiKey Typez
// New ApiKey Type
export interface ApiKey {
createdAt: string;
key: string;
@@ -37,11 +37,17 @@ export interface Feed {
createdAt: string;
}
export interface AddFeedRequest {
Name: string;
IsPublic: boolean;
}
export interface AddFeedResponse {
success: boolean;
feedId: string;
}
export interface FeedDataPoint {
timestamp: string;
data: string;

View File

@@ -61,7 +61,9 @@ export function DashboardPage() {
// Handle add new feed
const handleAddNewFeed = async () => {
try {
const response = await addNewFeed();
const defaultName = `Untitled Feed ${new Date().toLocaleString()}`;
const response = await addNewFeed(defaultName);
if (response.success) {
toast.success("New feed created successfully");
fetchFeeds();
@@ -166,8 +168,9 @@ export function DashboardPage() {
>
<div className="flex flex-col items-start w-full overflow-hidden">
<div className="font-medium truncate w-full">
Feed {feed.id.substring(0, 8)}...
{feed.name || `Feed ${feed.id.substring(0, 8)}...`}
</div>
<div className="text-xs text-muted-foreground truncate w-full">
Created: {formatDateTime(feed.createdAt)}
</div>
@@ -182,75 +185,98 @@ export function DashboardPage() {
</Card>
<Card className="md:col-span-3 relative">
<CardHeader className="flex flex-col md:flex-row md:items-center md:justify-between space-y-2 md:space-y-0">
<div>
<CardTitle>Feed Data</CardTitle>
<CardDescription>
{selectedFeed
? `Showing data for Feed ${selectedFeed.id.substring(0, 8)}...`
: "Select a feed to view data"
}
</CardDescription>
</div>
<CardHeader className="flex flex-col md:flex-row md:items-center md:justify-between space-y-2 md:space-y-0">
<div>
<CardHeader>
<CardTitle>
{selectedFeed ? `Feed Data: ${selectedFeed.name}` : "Feed Data"}
</CardTitle>
<CardDescription className="flex flex-col">
{selectedFeed ? (
<>
<span className="text-sm text-muted-foreground flex items-center gap-2">
Feed ID:
<code className="bg-muted px-1 py-0.5 rounded text-xs">{selectedFeed.id}</code>
<Button
size="icon"
variant="ghost"
className="h-5 w-5 p-1"
onClick={() => {
navigator.clipboard.writeText(selectedFeed.id);
toast.success("Feed ID copied to clipboard");
}}
>
<svg xmlns="http://www.w3.org/2000/svg" className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 16h8M8 12h8m-6 8h6a2 2 0 002-2v-5m0-4V6a2 2 0 00-2-2h-6l-2 2H6a2 2 0 00-2 2v12a2 2 0 002 2h2" />
</svg>
</Button>
</span>
</>
) : (
"Select a feed to view data"
)}
</CardDescription>
</CardHeader>
</div>
{/* Flex container for the select box and button */}
<div className="flex items-center space-x-2">
<Select
value={timeRangeValue}
onValueChange={handleTimeRangeChange}
disabled={!selectedFeed || isLoading}
>
<SelectTrigger className="w-[180px]">
<SelectValue placeholder="Select time range" />
</SelectTrigger>
<SelectContent>
{getTimeRangeOptions().map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
{/* Flex container for the select box and button */}
<div className="flex items-center space-x-2">
<Select
value={timeRangeValue}
onValueChange={handleTimeRangeChange}
disabled={!selectedFeed || isLoading}
>
<SelectTrigger className="w-[180px]">
<SelectValue placeholder="Select time range" />
</SelectTrigger>
<SelectContent>
{getTimeRangeOptions().map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
{/* Button to refresh feed data */}
<button
className={`flex items-center p-1 border rounded-md
{/* Button to refresh feed data */}
<button
className={`flex items-center p-1 border rounded-md
${isLoading || !selectedFeed
? "border-gray-300 text-gray-400 bg-gray-200"
: "border-blue-500 text-blue-700 hover:bg-blue-100"}
? "border-gray-300 text-gray-400 bg-gray-200"
: "border-blue-500 text-blue-700 hover:bg-blue-100"}
shadow-sm hover:shadow-md focus:outline-none focus:ring-2 focus:ring-blue-500`}
onClick={() => selectedFeed && refreshCurrentFeedData()}
disabled={isLoading || !selectedFeed}
>
<RefreshCw className="h-5 w-5" />
</button>
</div>
</CardHeader>
onClick={() => selectedFeed && refreshCurrentFeedData()}
disabled={isLoading || !selectedFeed}
>
<RefreshCw className="h-5 w-5" />
</button>
</div>
</CardHeader>
<CardContent className="pt-6">
{isLoading ? (
<Skeleton className="h-[350px] w-full" />
) : !selectedFeed ? (
<div className="flex flex-col items-center justify-center h-[350px] text-center">
<ScanBarcode className="mb-2 h-10 w-10 text-muted-foreground" />
<h3 className="text-lg font-medium">No feed selected</h3>
<p className="text-sm text-muted-foreground">
Select a feed from the sidebar to view its data
</p>
</div>
) : feedData.length === 0 ? (
<div className="flex flex-col items-center justify-center h-[350px] text-center">
<ScanBarcode className="mb-2 h-10 w-10 text-muted-foreground" />
<h3 className="text-lg font-medium">No data available</h3>
<p className="text-sm text-muted-foreground">
This feed has no data for the selected time range
</p>
</div>
) : (
<FeedChart data={feedData} />
)}
</CardContent>
</Card>
<CardContent className="pt-6">
{isLoading ? (
<Skeleton className="h-[350px] w-full" />
) : !selectedFeed ? (
<div className="flex flex-col items-center justify-center h-[350px] text-center">
<ScanBarcode className="mb-2 h-10 w-10 text-muted-foreground" />
<h3 className="text-lg font-medium">No feed selected</h3>
<p className="text-sm text-muted-foreground">
Select a feed from the sidebar to view its data
</p>
</div>
) : feedData.length === 0 ? (
<div className="flex flex-col items-center justify-center h-[350px] text-center">
<ScanBarcode className="mb-2 h-10 w-10 text-muted-foreground" />
<h3 className="text-lg font-medium">No data available</h3>
<p className="text-sm text-muted-foreground">
This feed has no data for the selected time range
</p>
</div>
) : (
<FeedChart data={feedData} />
)}
</CardContent>
</Card>
</div>
</div>
);