mirror of
https://github.com/crocofied/CoreControl.git
synced 2025-12-29 16:14:43 +00:00
Type fixes & Docker
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { NextResponse, NextRequest } from "next/server";
|
||||
import { PrismaClient } from '@/lib/generated/prisma'
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
interface AddRequest {
|
||||
serverId: number;
|
||||
@@ -10,8 +10,6 @@ interface AddRequest {
|
||||
localURL: string;
|
||||
}
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const body: AddRequest = await request.json();
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import { NextResponse, NextRequest } from "next/server";
|
||||
import { PrismaClient } from '@/lib/generated/prisma'
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
|
||||
@@ -1,53 +1,49 @@
|
||||
import { NextResponse, NextRequest } from "next/server";
|
||||
import { PrismaClient } from '@/lib/generated/prisma'
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
interface GetRequest {
|
||||
page: number;
|
||||
ITEMS_PER_PAGE: number;
|
||||
interface PostRequest {
|
||||
page?: number;
|
||||
ITEMS_PER_PAGE?: number;
|
||||
}
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const body: GetRequest = await request.json();
|
||||
const page = Math.max(1, body.page || 1);
|
||||
const ITEMS_PER_PAGE = body.ITEMS_PER_PAGE;
|
||||
|
||||
const applications = await prisma.application.findMany({
|
||||
skip: (page - 1) * ITEMS_PER_PAGE,
|
||||
take: ITEMS_PER_PAGE,
|
||||
orderBy: { name: 'asc' }
|
||||
});
|
||||
try {
|
||||
const body: PostRequest = await request.json();
|
||||
const page = Math.max(1, body.page || 1);
|
||||
const ITEMS_PER_PAGE = body.ITEMS_PER_PAGE || 10;
|
||||
|
||||
const serverIds = applications
|
||||
.map(app => app.serverId)
|
||||
.filter((id): id is number => id !== null);
|
||||
const [applications, totalCount, servers_all] = await Promise.all([
|
||||
prisma.application.findMany({
|
||||
skip: (page - 1) * ITEMS_PER_PAGE,
|
||||
take: ITEMS_PER_PAGE,
|
||||
orderBy: { name: "asc" }
|
||||
}),
|
||||
prisma.application.count(),
|
||||
prisma.server.findMany()
|
||||
]);
|
||||
|
||||
const servers = await prisma.server.findMany({
|
||||
where: {
|
||||
id: {
|
||||
in: serverIds
|
||||
}
|
||||
}
|
||||
});
|
||||
const serverIds = applications
|
||||
.map((app: { serverId: number | null }) => app.serverId)
|
||||
.filter((id:any): id is number => id !== null);
|
||||
|
||||
const servers_all = await prisma.server.findMany()
|
||||
const servers = await prisma.server.findMany({
|
||||
where: { id: { in: serverIds } }
|
||||
});
|
||||
|
||||
const applicationsWithServers = applications.map(app => ({
|
||||
...app,
|
||||
server: servers.find(s => s.id === app.serverId)?.name || 'No server'
|
||||
}));
|
||||
const applicationsWithServers = applications.map((app: any) => ({
|
||||
...app,
|
||||
server: servers.find((s: any) => s.id === app.serverId)?.name || "No server"
|
||||
}));
|
||||
|
||||
const totalCount = await prisma.application.count();
|
||||
const maxPage = Math.ceil(totalCount / ITEMS_PER_PAGE);
|
||||
const maxPage = Math.ceil(totalCount / ITEMS_PER_PAGE);
|
||||
|
||||
return NextResponse.json({
|
||||
applications: applicationsWithServers,
|
||||
servers: servers_all,
|
||||
maxPage
|
||||
});
|
||||
} catch (error: any) {
|
||||
return NextResponse.json({ error: error.message }, { status: 500 });
|
||||
}
|
||||
return NextResponse.json({
|
||||
applications: applicationsWithServers,
|
||||
servers: servers_all,
|
||||
maxPage
|
||||
});
|
||||
} catch (error: unknown) {
|
||||
const message = error instanceof Error ? error.message : "Unknown error";
|
||||
return NextResponse.json({ error: message }, { status: 500 });
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
import { NextResponse, NextRequest } from "next/server";
|
||||
import { PrismaClient } from '@/lib/generated/prisma';
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
|
||||
@@ -1,7 +1,40 @@
|
||||
import { NextResponse, NextRequest } from "next/server";
|
||||
import { PrismaClient } from "@/lib/generated/prisma";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
interface Node {
|
||||
id: string;
|
||||
type: string;
|
||||
data: {
|
||||
label: string;
|
||||
[key: string]: any;
|
||||
};
|
||||
position: { x: number; y: number };
|
||||
style: React.CSSProperties;
|
||||
}
|
||||
|
||||
interface Edge {
|
||||
id: string;
|
||||
source: string;
|
||||
target: string;
|
||||
type: string;
|
||||
style: {
|
||||
stroke: string;
|
||||
strokeWidth: number;
|
||||
};
|
||||
}
|
||||
|
||||
interface Server {
|
||||
id: number;
|
||||
name: string;
|
||||
ip: string;
|
||||
}
|
||||
|
||||
interface Application {
|
||||
id: number;
|
||||
name: string;
|
||||
localURL: string;
|
||||
serverId: number;
|
||||
}
|
||||
|
||||
const NODE_WIDTH = 220;
|
||||
const NODE_HEIGHT = 60;
|
||||
@@ -15,13 +48,13 @@ export async function GET() {
|
||||
const [servers, applications] = await Promise.all([
|
||||
prisma.server.findMany({
|
||||
orderBy: { id: "asc" },
|
||||
}),
|
||||
}) as Promise<Server[]>,
|
||||
prisma.application.findMany({
|
||||
orderBy: { serverId: "asc" },
|
||||
}),
|
||||
}) as Promise<Application[]>,
|
||||
]);
|
||||
|
||||
const rootNode = {
|
||||
const rootNode: Node = {
|
||||
id: "root",
|
||||
type: "infrastructure",
|
||||
data: { label: "My Infrastructure" },
|
||||
@@ -39,7 +72,7 @@ export async function GET() {
|
||||
},
|
||||
};
|
||||
|
||||
const serverNodes = servers.map((server, index) => {
|
||||
const serverNodes: Node[] = servers.map((server, index) => {
|
||||
const xPos =
|
||||
index * HORIZONTAL_SPACING -
|
||||
((servers.length - 1) * HORIZONTAL_SPACING) / 2;
|
||||
@@ -67,11 +100,10 @@ export async function GET() {
|
||||
};
|
||||
});
|
||||
|
||||
const appNodes: any[] = [];
|
||||
const appNodes: Node[] = [];
|
||||
servers.forEach((server) => {
|
||||
const serverX =
|
||||
serverNodes.find((n) => n.id === `server-${server.id}`)?.position.x ||
|
||||
0;
|
||||
serverNodes.find((n) => n.id === `server-${server.id}`)?.position.x || 0;
|
||||
const serverY = START_Y;
|
||||
|
||||
applications
|
||||
@@ -104,7 +136,7 @@ export async function GET() {
|
||||
});
|
||||
});
|
||||
|
||||
const connections = [
|
||||
const connections: Edge[] = [
|
||||
...servers.map((server) => ({
|
||||
id: `conn-root-${server.id}`,
|
||||
source: "root",
|
||||
@@ -131,12 +163,13 @@ export async function GET() {
|
||||
nodes: [rootNode, ...serverNodes, ...appNodes],
|
||||
edges: connections,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
||||
return NextResponse.json(
|
||||
{
|
||||
error: `Error fetching flowchart: ${error.message}`,
|
||||
error: `Error fetching flowchart: ${errorMessage}`,
|
||||
},
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { NextResponse, NextRequest } from "next/server";
|
||||
import { PrismaClient } from '@/lib/generated/prisma'
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
interface AddRequest {
|
||||
name: string;
|
||||
@@ -13,8 +13,6 @@ interface AddRequest {
|
||||
|
||||
}
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const body: AddRequest = await request.json();
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import { NextResponse, NextRequest } from "next/server";
|
||||
import { PrismaClient } from '@/lib/generated/prisma'
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { NextResponse, NextRequest } from "next/server";
|
||||
import { PrismaClient } from '@/lib/generated/prisma'
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
interface EditRequest {
|
||||
id: number;
|
||||
@@ -13,8 +13,6 @@ interface EditRequest {
|
||||
disk: string;
|
||||
}
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
export async function PUT(request: NextRequest) {
|
||||
try {
|
||||
const body: EditRequest = await request.json();
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { NextResponse, NextRequest } from "next/server";
|
||||
import { PrismaClient } from '@/lib/generated/prisma'
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
interface GetRequest {
|
||||
page: number;
|
||||
}
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
const ITEMS_PER_PAGE = 5;
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AppSidebar } from "@/components/app-sidebar"
|
||||
import { AppSidebar } from "@/components/app-sidebar";
|
||||
import {
|
||||
Breadcrumb,
|
||||
BreadcrumbItem,
|
||||
@@ -6,40 +6,38 @@ import {
|
||||
BreadcrumbList,
|
||||
BreadcrumbPage,
|
||||
BreadcrumbSeparator,
|
||||
} from "@/components/ui/breadcrumb"
|
||||
import { Separator } from "@/components/ui/separator"
|
||||
} from "@/components/ui/breadcrumb";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import {
|
||||
SidebarInset,
|
||||
SidebarProvider,
|
||||
SidebarTrigger,
|
||||
} from "@/components/ui/sidebar"
|
||||
import { useEffect, useState } from "react"
|
||||
import axios from "axios"
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card"
|
||||
import { Skeleton } from "@/components/ui/skeleton"
|
||||
} from "@/components/ui/sidebar";
|
||||
import { useEffect, useState } from "react";
|
||||
import axios from "axios"; // Korrekter Import
|
||||
import { Card, CardHeader } from "@/components/ui/card";
|
||||
|
||||
interface StatsResponse {
|
||||
serverCount: number;
|
||||
applicationCount: number;
|
||||
onlineApplicationsCount: number;
|
||||
}
|
||||
|
||||
export default function Dashboard() {
|
||||
const [serverCount, setServerCount] = useState(0)
|
||||
const [applicationCount, setApplicationCount] = useState(0)
|
||||
const [onlineApplicationsCount, setOnlineApplicationsCount] = useState(0)
|
||||
const [serverCount, setServerCount] = useState<number>(0);
|
||||
const [applicationCount, setApplicationCount] = useState<number>(0);
|
||||
const [onlineApplicationsCount, setOnlineApplicationsCount] = useState<number>(0);
|
||||
|
||||
const getStats = async () => {
|
||||
try {
|
||||
const response = await axios.post('/api/dashboard/get', { });
|
||||
setServerCount(response.data.serverCount)
|
||||
setApplicationCount(response.data.applicationCount)
|
||||
setOnlineApplicationsCount(response.data.onlineApplicationsCount)
|
||||
const response = await axios.post<StatsResponse>('/api/dashboard/get', {});
|
||||
setServerCount(response.data.serverCount);
|
||||
setApplicationCount(response.data.applicationCount);
|
||||
setOnlineApplicationsCount(response.data.onlineApplicationsCount);
|
||||
} catch (error: any) {
|
||||
console.log(error.response);
|
||||
console.log("Axios error:", error.response?.data);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getStats();
|
||||
@@ -94,7 +92,9 @@ export default function Dashboard() {
|
||||
<CardHeader>
|
||||
<div className="flex items-center justify-center w-full">
|
||||
<div className="flex flex-col items-center justify-center">
|
||||
<span className="text-2xl font-bold">{onlineApplicationsCount}/{applicationCount}</span>
|
||||
<span className="text-2xl font-bold">
|
||||
{onlineApplicationsCount}/{applicationCount}
|
||||
</span>
|
||||
<span className="text-md">Applications are online</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -102,15 +102,15 @@ export default function Dashboard() {
|
||||
</Card>
|
||||
</div>
|
||||
<div className="h-72 w-full rounded-xl flex items-center justify-center bg-muted">
|
||||
<span className="text-gray-400 text-2xl">COMMING SOON</span>
|
||||
<span className="text-gray-400 text-2xl">COMING SOON</span>
|
||||
</div>
|
||||
<div className="pt-4">
|
||||
<div className="h-72 w-full rounded-xl flex items-center justify-center bg-muted">
|
||||
<span className="text-gray-400 text-2xl">COMMING SOON</span>
|
||||
<span className="text-gray-400 text-2xl">COMING SOON</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</SidebarInset>
|
||||
</SidebarProvider>
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -57,28 +57,51 @@ import {
|
||||
} from "@/components/ui/select";
|
||||
import Cookies from "js-cookie";
|
||||
import { useState, useEffect } from "react";
|
||||
import axios from 'axios';
|
||||
import axios from "axios";
|
||||
|
||||
interface Application {
|
||||
id: number;
|
||||
name: string;
|
||||
description?: string;
|
||||
icon?: string;
|
||||
publicURL: string;
|
||||
localURL?: string;
|
||||
server?: string;
|
||||
online: boolean;
|
||||
serverId: number;
|
||||
}
|
||||
|
||||
interface Server {
|
||||
id: number;
|
||||
name: string;
|
||||
}
|
||||
|
||||
interface ApplicationsResponse {
|
||||
applications: Application[];
|
||||
servers: Server[];
|
||||
maxPage: number;
|
||||
}
|
||||
|
||||
export default function Dashboard() {
|
||||
const [name, setName] = useState("");
|
||||
const [description, setDescription] = useState("");
|
||||
const [icon, setIcon] = useState("");
|
||||
const [publicURL, setPublicURL] = useState("");
|
||||
const [localURL, setLocalURL] = useState("");
|
||||
const [name, setName] = useState<string>("");
|
||||
const [description, setDescription] = useState<string>("");
|
||||
const [icon, setIcon] = useState<string>("");
|
||||
const [publicURL, setPublicURL] = useState<string>("");
|
||||
const [localURL, setLocalURL] = useState<string>("");
|
||||
const [serverId, setServerId] = useState<number | null>(null);
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [maxPage, setMaxPage] = useState(1);
|
||||
const [itemsPerPage, setItemsPerPage] = useState(5);
|
||||
const [applications, setApplications] = useState([]);
|
||||
const [servers, setServers] = useState([]);
|
||||
const [isGridLayout, setIsGridLayout] = useState(false);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [currentPage, setCurrentPage] = useState<number>(1);
|
||||
const [maxPage, setMaxPage] = useState<number>(1);
|
||||
const [itemsPerPage, setItemsPerPage] = useState<number>(5);
|
||||
const [applications, setApplications] = useState<Application[]>([]);
|
||||
const [servers, setServers] = useState<Server[]>([]);
|
||||
const [isGridLayout, setIsGridLayout] = useState<boolean>(false);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
|
||||
useEffect(() => {
|
||||
const savedLayout = Cookies.get('layoutPreference-app');
|
||||
const layout_bool = savedLayout === 'grid'
|
||||
const layout_bool = savedLayout === 'grid';
|
||||
setIsGridLayout(layout_bool);
|
||||
setItemsPerPage(layout_bool ? 15 : 5)
|
||||
setItemsPerPage(layout_bool ? 15 : 5);
|
||||
}, []);
|
||||
|
||||
const toggleLayout = () => {
|
||||
@@ -104,20 +127,23 @@ export default function Dashboard() {
|
||||
});
|
||||
getApplications();
|
||||
} catch (error: any) {
|
||||
console.log(error.response.data);
|
||||
console.log(error.response?.data);
|
||||
}
|
||||
}
|
||||
|
||||
const getApplications = async () => {
|
||||
try {
|
||||
setLoading(true)
|
||||
const response = await axios.post('/api/applications/get', { page: currentPage, ITEMS_PER_PAGE: itemsPerPage });
|
||||
setLoading(true);
|
||||
const response = await axios.post<ApplicationsResponse>(
|
||||
'/api/applications/get',
|
||||
{ page: currentPage, ITEMS_PER_PAGE: itemsPerPage }
|
||||
);
|
||||
setApplications(response.data.applications);
|
||||
setServers(response.data.servers);
|
||||
setMaxPage(response.data.maxPage);
|
||||
setLoading(false)
|
||||
setLoading(false);
|
||||
} catch (error: any) {
|
||||
console.log(error.response);
|
||||
console.log(error.response?.data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +159,7 @@ export default function Dashboard() {
|
||||
await axios.post('/api/applications/delete', { id });
|
||||
getApplications();
|
||||
} catch (error: any) {
|
||||
console.log(error.response.data);
|
||||
console.log(error.response?.data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -315,7 +341,7 @@ export default function Dashboard() {
|
||||
<div className='inline-block' role='status' aria-label='loading'>
|
||||
<svg className='w-6 h-6 stroke-white animate-spin ' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'>
|
||||
<g clip-path='url(#clip0_9023_61563)'>
|
||||
<path d='M14.6437 2.05426C11.9803 1.2966 9.01686 1.64245 6.50315 3.25548C1.85499 6.23817 0.504864 12.4242 3.48756 17.0724C6.47025 21.7205 12.6563 23.0706 17.3044 20.088C20.4971 18.0393 22.1338 14.4793 21.8792 10.9444' stroke='stroke-current' stroke-width='1.4' stroke-linecap='round' class='my-path'></path>
|
||||
<path d='M14.6437 2.05426C11.9803 1.2966 9.01686 1.64245 6.50315 3.25548C1.85499 6.23817 0.504864 12.4242 3.48756 17.0724C6.47025 21.7205 12.6563 23.0706 17.3044 20.088C20.4971 18.0393 22.1338 14.4793 21.8792 10.9444' stroke='stroke-current' stroke-width='1.4' stroke-linecap='round' className='my-path'></path>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id='clip0_9023_61563'>
|
||||
|
||||
@@ -41,7 +41,7 @@ export default function DashboardPage() {
|
||||
<div className='inline-block' role='status' aria-label='loading'>
|
||||
<svg className='w-6 h-6 stroke-white animate-spin ' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'>
|
||||
<g clip-path='url(#clip0_9023_61563)'>
|
||||
<path d='M14.6437 2.05426C11.9803 1.2966 9.01686 1.64245 6.50315 3.25548C1.85499 6.23817 0.504864 12.4242 3.48756 17.0724C6.47025 21.7205 12.6563 23.0706 17.3044 20.088C20.4971 18.0393 22.1338 14.4793 21.8792 10.9444' stroke='stroke-current' stroke-width='1.4' stroke-linecap='round' class='my-path'></path>
|
||||
<path d='M14.6437 2.05426C11.9803 1.2966 9.01686 1.64245 6.50315 3.25548C1.85499 6.23817 0.504864 12.4242 3.48756 17.0724C6.47025 21.7205 12.6563 23.0706 17.3044 20.088C20.4971 18.0393 22.1338 14.4793 21.8792 10.9444' stroke='stroke-current' stroke-width='1.4' stroke-linecap='round' className='my-path'></path>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id='clip0_9023_61563'>
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
SidebarProvider,
|
||||
SidebarTrigger,
|
||||
} from "@/components/ui/sidebar";
|
||||
import { ReactFlow, Controls, Background } from "@xyflow/react";
|
||||
import { ReactFlow, Controls, Background, ConnectionLineType } from "@xyflow/react";
|
||||
import "@xyflow/react/dist/style.css";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
@@ -78,12 +78,12 @@ export default function Dashboard() {
|
||||
className="dark:bg-black rounded-lg"
|
||||
>
|
||||
<ReactFlow
|
||||
nodes={nodes}
|
||||
edges={edges}
|
||||
fitView
|
||||
fitViewOptions={{ padding: 0.2 }}
|
||||
connectionLineType="straight"
|
||||
className="dark:[&_.react-flow__edge-path]:stroke-slate-500"
|
||||
nodes={nodes}
|
||||
edges={edges}
|
||||
fitView
|
||||
fitViewOptions={{ padding: 0.2 }}
|
||||
connectionLineType={ConnectionLineType.Straight}
|
||||
className="dark:[&_.react-flow__edge-path]:stroke-slate-500"
|
||||
>
|
||||
<Background
|
||||
color="#64748b"
|
||||
|
||||
@@ -41,7 +41,7 @@ export default function DashboardPage() {
|
||||
<div className='inline-block' role='status' aria-label='loading'>
|
||||
<svg className='w-6 h-6 stroke-white animate-spin ' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'>
|
||||
<g clip-path='url(#clip0_9023_61563)'>
|
||||
<path d='M14.6437 2.05426C11.9803 1.2966 9.01686 1.64245 6.50315 3.25548C1.85499 6.23817 0.504864 12.4242 3.48756 17.0724C6.47025 21.7205 12.6563 23.0706 17.3044 20.088C20.4971 18.0393 22.1338 14.4793 21.8792 10.9444' stroke='stroke-current' stroke-width='1.4' stroke-linecap='round' class='my-path'></path>
|
||||
<path d='M14.6437 2.05426C11.9803 1.2966 9.01686 1.64245 6.50315 3.25548C1.85499 6.23817 0.504864 12.4242 3.48756 17.0724C6.47025 21.7205 12.6563 23.0706 17.3044 20.088C20.4971 18.0393 22.1338 14.4793 21.8792 10.9444' stroke='stroke-current' stroke-width='1.4' stroke-linecap='round' className='my-path'></path>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id='clip0_9023_61563'>
|
||||
|
||||
@@ -41,7 +41,7 @@ export default function DashboardPage() {
|
||||
<div className='inline-block' role='status' aria-label='loading'>
|
||||
<svg className='w-6 h-6 stroke-white animate-spin ' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'>
|
||||
<g clip-path='url(#clip0_9023_61563)'>
|
||||
<path d='M14.6437 2.05426C11.9803 1.2966 9.01686 1.64245 6.50315 3.25548C1.85499 6.23817 0.504864 12.4242 3.48756 17.0724C6.47025 21.7205 12.6563 23.0706 17.3044 20.088C20.4971 18.0393 22.1338 14.4793 21.8792 10.9444' stroke='stroke-current' stroke-width='1.4' stroke-linecap='round' class='my-path'></path>
|
||||
<path d='M14.6437 2.05426C11.9803 1.2966 9.01686 1.64245 6.50315 3.25548C1.85499 6.23817 0.504864 12.4242 3.48756 17.0724C6.47025 21.7205 12.6563 23.0706 17.3044 20.088C20.4971 18.0393 22.1338 14.4793 21.8792 10.9444' stroke='stroke-current' stroke-width='1.4' stroke-linecap='round' className='my-path'></path>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id='clip0_9023_61563'>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { AppSidebar } from "@/components/app-sidebar"
|
||||
import { AppSidebar } from "@/components/app-sidebar";
|
||||
import {
|
||||
Breadcrumb,
|
||||
BreadcrumbItem,
|
||||
@@ -8,15 +8,15 @@ import {
|
||||
BreadcrumbList,
|
||||
BreadcrumbPage,
|
||||
BreadcrumbSeparator,
|
||||
} from "@/components/ui/breadcrumb"
|
||||
import { Separator } from "@/components/ui/separator"
|
||||
} from "@/components/ui/breadcrumb";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import {
|
||||
SidebarInset,
|
||||
SidebarProvider,
|
||||
SidebarTrigger,
|
||||
} from "@/components/ui/sidebar"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Plus, Link, MonitorCog, FileDigit, Trash2, LayoutGrid, List, Pencil, Cpu, Microchip, MemoryStick, HardDrive } from "lucide-react"
|
||||
} from "@/components/ui/sidebar";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Plus, Link, MonitorCog, FileDigit, Trash2, LayoutGrid, List, Pencil, Cpu, Microchip, MemoryStick, HardDrive } from "lucide-react";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
@@ -24,7 +24,7 @@ import {
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card"
|
||||
} from "@/components/ui/card";
|
||||
import {
|
||||
Pagination,
|
||||
PaginationContent,
|
||||
@@ -33,7 +33,7 @@ import {
|
||||
PaginationLink,
|
||||
PaginationNext,
|
||||
PaginationPrevious,
|
||||
} from "@/components/ui/pagination"
|
||||
} from "@/components/ui/pagination";
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
@@ -44,55 +44,70 @@ import {
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from "@/components/ui/alert-dialog"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Label } from "@/components/ui/label"
|
||||
} from "@/components/ui/alert-dialog";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select"
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip"
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip";
|
||||
import Cookies from "js-cookie";
|
||||
import { useState, useEffect } from "react";
|
||||
import axios from 'axios';
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
|
||||
interface Server {
|
||||
id: number;
|
||||
name: string;
|
||||
os?: string;
|
||||
ip?: string;
|
||||
url?: string;
|
||||
cpu?: string;
|
||||
gpu?: string;
|
||||
ram?: string;
|
||||
disk?: string;
|
||||
}
|
||||
|
||||
interface GetServersResponse {
|
||||
servers: Server[];
|
||||
maxPage: number;
|
||||
}
|
||||
|
||||
export default function Dashboard() {
|
||||
const [name, setName] = useState("");
|
||||
const [os, setOs] = useState("");
|
||||
const [ip, setIp] = useState("");
|
||||
const [url, setUrl] = useState("");
|
||||
const [cpu, setCpu] = useState("");
|
||||
const [gpu, setGpu] = useState("");
|
||||
const [ram, setRam] = useState("");
|
||||
const [disk, setDisk] = useState("");
|
||||
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [maxPage, setMaxPage] = useState(1);
|
||||
const [servers, setServers] = useState([]);
|
||||
const [isGridLayout, setIsGridLayout] = useState(false);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [name, setName] = useState<string>("");
|
||||
const [os, setOs] = useState<string>("");
|
||||
const [ip, setIp] = useState<string>("");
|
||||
const [url, setUrl] = useState<string>("");
|
||||
const [cpu, setCpu] = useState<string>("");
|
||||
const [gpu, setGpu] = useState<string>("");
|
||||
const [ram, setRam] = useState<string>("");
|
||||
const [disk, setDisk] = useState<string>("");
|
||||
|
||||
const [currentPage, setCurrentPage] = useState<number>(1);
|
||||
const [maxPage, setMaxPage] = useState<number>(1);
|
||||
const [servers, setServers] = useState<Server[]>([]);
|
||||
const [isGridLayout, setIsGridLayout] = useState<boolean>(false);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
|
||||
const [editId, setEditId] = useState<number | null>(null);
|
||||
const [editName, setEditName] = useState("");
|
||||
const [editOs, setEditOs] = useState("");
|
||||
const [editIp, setEditIp] = useState("");
|
||||
const [editUrl, setEditUrl] = useState("");
|
||||
const [editCpu, setEditCpu] = useState("");
|
||||
const [editGpu, setEditGpu] = useState("");
|
||||
const [editRam, setEditRam] = useState("");
|
||||
const [editDisk, setEditDisk] = useState("");
|
||||
const [editName, setEditName] = useState<string>("");
|
||||
const [editOs, setEditOs] = useState<string>("");
|
||||
const [editIp, setEditIp] = useState<string>("");
|
||||
const [editUrl, setEditUrl] = useState<string>("");
|
||||
const [editCpu, setEditCpu] = useState<string>("");
|
||||
const [editGpu, setEditGpu] = useState<string>("");
|
||||
const [editRam, setEditRam] = useState<string>("");
|
||||
const [editDisk, setEditDisk] = useState<string>("");
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const savedLayout = Cookies.get('layoutPreference-servers');
|
||||
setIsGridLayout(savedLayout === 'grid');
|
||||
@@ -110,7 +125,16 @@ export default function Dashboard() {
|
||||
|
||||
const add = async () => {
|
||||
try {
|
||||
const response = await axios.post('/api/servers/add', { name, os, ip, url, cpu, gpu, ram, disk });
|
||||
await axios.post('/api/servers/add', {
|
||||
name,
|
||||
os,
|
||||
ip,
|
||||
url,
|
||||
cpu,
|
||||
gpu,
|
||||
ram,
|
||||
disk
|
||||
});
|
||||
getServers();
|
||||
} catch (error: any) {
|
||||
console.log(error.response.data);
|
||||
@@ -120,9 +144,10 @@ export default function Dashboard() {
|
||||
const getServers = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const response = await axios.post('/api/servers/get', { page: currentPage });
|
||||
const response = await axios.post<GetServersResponse>('/api/servers/get', {
|
||||
page: currentPage
|
||||
});
|
||||
setServers(response.data.servers);
|
||||
console.log(response.data.servers)
|
||||
setMaxPage(response.data.maxPage);
|
||||
setLoading(false);
|
||||
} catch (error: any) {
|
||||
@@ -151,19 +176,21 @@ export default function Dashboard() {
|
||||
}
|
||||
}
|
||||
|
||||
const openEditDialog = (server: any) => {
|
||||
const openEditDialog = (server: Server) => {
|
||||
setEditId(server.id);
|
||||
setEditName(server.name);
|
||||
setEditOs(server.os);
|
||||
setEditIp(server.ip);
|
||||
setEditUrl(server.url);
|
||||
setEditCpu(server.cpu);
|
||||
setEditGpu(server.gpu);
|
||||
setEditRam(server.ram);
|
||||
setEditDisk(server.disk);
|
||||
setEditOs(server.os || "");
|
||||
setEditIp(server.ip || "");
|
||||
setEditUrl(server.url || "");
|
||||
setEditCpu(server.cpu || "");
|
||||
setEditGpu(server.gpu || "");
|
||||
setEditRam(server.ram || "");
|
||||
setEditDisk(server.disk || "");
|
||||
};
|
||||
|
||||
const edit = async () => {
|
||||
if (!editId) return;
|
||||
|
||||
try {
|
||||
await axios.put('/api/servers/edit', {
|
||||
id: editId,
|
||||
@@ -507,7 +534,7 @@ export default function Dashboard() {
|
||||
<div className='inline-block' role='status' aria-label='loading'>
|
||||
<svg className='w-6 h-6 stroke-white animate-spin ' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'>
|
||||
<g clip-path='url(#clip0_9023_61563)'>
|
||||
<path d='M14.6437 2.05426C11.9803 1.2966 9.01686 1.64245 6.50315 3.25548C1.85499 6.23817 0.504864 12.4242 3.48756 17.0724C6.47025 21.7205 12.6563 23.0706 17.3044 20.088C20.4971 18.0393 22.1338 14.4793 21.8792 10.9444' stroke='stroke-current' stroke-width='1.4' stroke-linecap='round' class='my-path'></path>
|
||||
<path d='M14.6437 2.05426C11.9803 1.2966 9.01686 1.64245 6.50315 3.25548C1.85499 6.23817 0.504864 12.4242 3.48756 17.0724C6.47025 21.7205 12.6563 23.0706 17.3044 20.088C20.4971 18.0393 22.1338 14.4793 21.8792 10.9444' stroke='stroke-current' stroke-width='1.4' stroke-linecap='round' className='my-path'></path>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id='clip0_9023_61563'>
|
||||
|
||||
@@ -41,7 +41,7 @@ export default function DashboardPage() {
|
||||
<div className='inline-block' role='status' aria-label='loading'>
|
||||
<svg className='w-6 h-6 stroke-white animate-spin ' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'>
|
||||
<g clip-path='url(#clip0_9023_61563)'>
|
||||
<path d='M14.6437 2.05426C11.9803 1.2966 9.01686 1.64245 6.50315 3.25548C1.85499 6.23817 0.504864 12.4242 3.48756 17.0724C6.47025 21.7205 12.6563 23.0706 17.3044 20.088C20.4971 18.0393 22.1338 14.4793 21.8792 10.9444' stroke='stroke-current' stroke-width='1.4' stroke-linecap='round' class='my-path'></path>
|
||||
<path d='M14.6437 2.05426C11.9803 1.2966 9.01686 1.64245 6.50315 3.25548C1.85499 6.23817 0.504864 12.4242 3.48756 17.0724C6.47025 21.7205 12.6563 23.0706 17.3044 20.088C20.4971 18.0393 22.1338 14.4793 21.8792 10.9444' stroke='stroke-current' stroke-width='1.4' stroke-linecap='round' className='my-path'></path>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id='clip0_9023_61563'>
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
import { AppSidebar } from "@/components/app-sidebar"
|
||||
import { AppSidebar } from "@/components/app-sidebar";
|
||||
import {
|
||||
Breadcrumb,
|
||||
BreadcrumbItem,
|
||||
BreadcrumbList,
|
||||
BreadcrumbPage,
|
||||
BreadcrumbSeparator,
|
||||
} from "@/components/ui/breadcrumb"
|
||||
import { Separator } from "@/components/ui/separator"
|
||||
} from "@/components/ui/breadcrumb";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import {
|
||||
SidebarInset,
|
||||
SidebarProvider,
|
||||
SidebarTrigger,
|
||||
} from "@/components/ui/sidebar"
|
||||
import { Card, CardHeader } from "@/components/ui/card"
|
||||
import { useTheme } from "next-themes"
|
||||
} from "@/components/ui/sidebar";
|
||||
import { Card, CardHeader } from "@/components/ui/card";
|
||||
import { useTheme } from "next-themes";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select"
|
||||
} from "@/components/ui/select";
|
||||
|
||||
export default function Settings() {
|
||||
const { theme, setTheme } = useTheme()
|
||||
const { theme, setTheme } = useTheme();
|
||||
|
||||
return (
|
||||
<SidebarProvider>
|
||||
@@ -56,10 +56,13 @@ export default function Settings() {
|
||||
<Card className="w-full mb-4 relative">
|
||||
<CardHeader>
|
||||
<span className="text-xl font-bold">Theme</span>
|
||||
<Select value={theme} onValueChange={setTheme}>
|
||||
<Select
|
||||
value={theme}
|
||||
onValueChange={(value: string) => setTheme(value)}
|
||||
>
|
||||
<SelectTrigger className="w-full [&_svg]:hidden">
|
||||
<SelectValue>
|
||||
{theme?.charAt(0).toUpperCase() + theme?.slice(1)}
|
||||
{(theme ?? 'system').charAt(0).toUpperCase() + (theme ?? 'system').slice(1)}
|
||||
</SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
@@ -74,5 +77,5 @@ export default function Settings() {
|
||||
</div>
|
||||
</SidebarInset>
|
||||
</SidebarProvider>
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -41,7 +41,7 @@ export default function DashboardPage() {
|
||||
<div className='inline-block' role='status' aria-label='loading'>
|
||||
<svg className='w-6 h-6 stroke-white animate-spin ' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'>
|
||||
<g clip-path='url(#clip0_9023_61563)'>
|
||||
<path d='M14.6437 2.05426C11.9803 1.2966 9.01686 1.64245 6.50315 3.25548C1.85499 6.23817 0.504864 12.4242 3.48756 17.0724C6.47025 21.7205 12.6563 23.0706 17.3044 20.088C20.4971 18.0393 22.1338 14.4793 21.8792 10.9444' stroke='stroke-current' stroke-width='1.4' stroke-linecap='round' class='my-path'></path>
|
||||
<path d='M14.6437 2.05426C11.9803 1.2966 9.01686 1.64245 6.50315 3.25548C1.85499 6.23817 0.504864 12.4242 3.48756 17.0724C6.47025 21.7205 12.6563 23.0706 17.3044 20.088C20.4971 18.0393 22.1338 14.4793 21.8792 10.9444' stroke='stroke-current' stroke-width='1.4' stroke-linecap='round' className='my-path'></path>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id='clip0_9023_61563'>
|
||||
|
||||
Reference in New Issue
Block a user