Add new gettallfeed api
This commit is contained in:
@@ -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', {
|
||||
|
@@ -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;
|
||||
|
@@ -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>
|
||||
);
|
||||
|
Reference in New Issue
Block a user