Compare commits

..

2 commits

Author SHA1 Message Date
6cbdcb81ff qs 2025-03-23 03:41:05 +01:00
d7737ef3b9 all working 2025-03-23 03:35:50 +01:00
17 changed files with 264 additions and 519 deletions

3
.bolt/config.json Normal file
View file

@ -0,0 +1,3 @@
{
"template": "bolt-vite-react-ts"
}

8
.bolt/prompt Normal file
View file

@ -0,0 +1,8 @@
For all designs I ask you to make, have them be beautiful, not cookie cutter. Make webpages that are fully featured and worthy for production.
By default, this template supports JSX syntax with Tailwind CSS classes, React hooks, and Lucide React for icons. Do not install other packages for UI themes, icons, etc unless absolutely necessary or I request them.
Use icons from lucide-react for logos.
Use stock photos from unsplash where appropriate, only valid URLs you know exist. Do not download the images, only link to them in image tags.

View file

@ -0,0 +1,53 @@
/*
# Create servers table for Proxmox dashboard
1. New Tables
- `servers`
- `id` (uuid, primary key)
- `name` (text, server name)
- `model` (text, server model)
- `cpu_model` (text, CPU model)
- `cpu_cores` (integer, number of CPU cores)
- `ram_gb` (integer, RAM in GB)
- `created_at` (timestamp)
- `updated_at` (timestamp)
2. Security
- Enable RLS on `servers` table
- Add policies for authenticated users to manage their servers
*/
CREATE TABLE IF NOT EXISTS servers (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
name text NOT NULL,
model text NOT NULL,
cpu_model text NOT NULL,
cpu_cores integer NOT NULL,
ram_gb integer NOT NULL,
created_at timestamptz DEFAULT now(),
updated_at timestamptz DEFAULT now()
);
ALTER TABLE servers ENABLE ROW LEVEL SECURITY;
-- Allow authenticated users to read all servers
CREATE POLICY "Users can read all servers"
ON servers
FOR SELECT
TO authenticated
USING (true);
-- Allow authenticated users to insert their own servers
CREATE POLICY "Users can insert servers"
ON servers
FOR INSERT
TO authenticated
WITH CHECK (true);
-- Allow authenticated users to update their own servers
CREATE POLICY "Users can update their own servers"
ON servers
FOR UPDATE
TO authenticated
USING (true)
WITH CHECK (true);

View file

@ -0,0 +1,62 @@
/*
# Create servers table
1. New Tables
- `servers`
- `id` (uuid, primary key)
- `name` (text)
- `model` (text)
- `cpus` (jsonb array)
- `ram_gb` (integer)
- `proxmox_url` (text)
- `user_id` (uuid, foreign key)
- `created_at` (timestamp)
- `status` (text)
- `specs` (jsonb)
- `last_ping` (integer)
2. Security
- Enable RLS on `servers` table
- Add policies for authenticated users to manage their own servers
*/
CREATE TABLE IF NOT EXISTS servers (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
name text NOT NULL,
model text NOT NULL,
cpus jsonb NOT NULL DEFAULT '[]'::jsonb,
ram_gb integer NOT NULL,
proxmox_url text NOT NULL,
user_id uuid NOT NULL REFERENCES auth.users(id),
created_at timestamptz DEFAULT now(),
status text NOT NULL DEFAULT 'checking',
specs jsonb NOT NULL DEFAULT '{}'::jsonb,
last_ping integer
);
ALTER TABLE servers ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Users can read their own servers"
ON servers
FOR SELECT
TO authenticated
USING (auth.uid() = user_id);
CREATE POLICY "Users can insert their own servers"
ON servers
FOR INSERT
TO authenticated
WITH CHECK (auth.uid() = user_id);
CREATE POLICY "Users can update their own servers"
ON servers
FOR UPDATE
TO authenticated
USING (auth.uid() = user_id)
WITH CHECK (auth.uid() = user_id);
CREATE POLICY "Users can delete their own servers"
ON servers
FOR DELETE
TO authenticated
USING (auth.uid() = user_id);

6
.env
View file

@ -1,6 +0,0 @@
DB_HOST=172.10.1.4
DB_USER=prox
DB_PASSWORD=2104
DB_NAME=prox
PORT=3006
VITE_API_URL=/api

23
.gitignore vendored
View file

@ -1 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,215 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="200.000000pt" height="200.000000pt" viewBox="0 0 200.000000 200.000000"
preserveAspectRatio="xMidYMid meet">
<g transform="translate(0.000000,200.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M542 1551 c2 -5 40 -49 84 -97 45 -49 93 -101 105 -115 13 -14 60
-65 104 -114 44 -49 99 -109 123 -134 l42 -46 48 50 c26 28 88 95 137 149 122
135 182 201 232 255 24 25 43 49 43 54 0 4 -67 7 -149 7 -143 0 -149 -1 -164
-22 -9 -13 -45 -54 -81 -93 l-65 -69 -87 92 -86 92 -145 0 c-79 0 -143 -4
-141 -9z"/>
<path d="M410 1470 c-8 -5 -10 -10 -5 -10 6 0 17 5 25 10 8 5 11 10 5 10 -5 0
-17 -5 -25 -10z"/>
<path d="M1589 1471 c9 -6 10 -10 2 -14 -8 -4 -8 -5 1 -3 20 4 21 26 1 26 -14
0 -15 -2 -4 -9z"/>
<path d="M360 1461 c0 -10 19 -25 25 -20 1 2 -3 10 -11 17 -8 7 -14 8 -14 3z"/>
<path d="M446 1453 c-6 -14 -5 -15 5 -6 7 7 10 15 7 18 -3 3 -9 -2 -12 -12z"/>
<path d="M1510 1460 c-9 -6 -10 -10 -3 -10 6 0 15 5 18 10 8 12 4 12 -15 0z"/>
<path d="M1626 1456 c4 -12 13 -15 28 -10 19 6 20 5 6 -11 -14 -17 -14 -17 7
-4 19 11 20 15 7 22 -9 5 -18 6 -21 3 -4 -3 -12 -1 -20 6 -11 8 -12 7 -7 -6z"/>
<path d="M476 1451 c8 -8 43 -8 38 0 -2 4 -13 7 -24 6 -10 -1 -17 -3 -14 -6z"/>
<path d="M300 1442 c0 -6 -6 -12 -14 -14 -11 -2 -9 -10 9 -31 l24 -27 -3 35
c-2 31 -16 63 -16 37z m10 -28 c0 -8 -5 -12 -10 -9 -6 4 -8 11 -5 16 9 14 15
11 15 -7z"/>
<path d="M1457 1430 c-9 -11 -12 -20 -7 -20 6 0 13 7 16 15 4 10 14 14 28 10
17 -5 18 -4 6 4 -20 14 -23 14 -43 -9z"/>
<path d="M505 1403 c3 -29 10 -37 25 -28 9 6 9 10 -1 17 -11 7 -11 11 -1 15
19 7 14 22 -7 20 -13 -1 -18 -8 -16 -24z"/>
<path d="M1684 1418 c-5 -8 -2 -9 10 -5 9 4 14 3 11 -2 -3 -5 -1 -12 4 -15 10
-7 23 19 14 28 -10 10 -31 7 -39 -6z"/>
<path d="M563 1405 c0 -8 4 -12 9 -9 5 3 6 10 3 15 -9 13 -12 11 -12 -6z"/>
<path d="M1479 1403 c-13 -15 -12 -15 9 -4 23 12 28 21 13 21 -5 0 -15 -7 -22
-17z"/>
<path d="M1410 1395 c-20 -24 4 -45 26 -24 13 14 13 17 1 27 -11 10 -17 9 -27
-3z m16 -22 c-10 -10 -19 5 -10 18 6 11 8 11 12 0 2 -7 1 -15 -2 -18z"/>
<path d="M420 1390 c0 -5 5 -10 10 -10 6 0 10 5 10 10 0 6 -4 10 -10 10 -5 0
-10 -4 -10 -10z"/>
<path d="M1570 1390 c0 -5 7 -10 16 -10 8 0 12 5 9 10 -3 6 -10 10 -16 10 -5
0 -9 -4 -9 -10z"/>
<path d="M1685 1390 c-3 -5 -1 -10 4 -10 6 0 11 5 11 10 0 6 -2 10 -4 10 -3 0
-8 -4 -11 -10z"/>
<path d="M574 1379 c-4 -8 -3 -9 4 -5 7 4 12 1 12 -8 0 -9 5 -16 10 -16 14 0
12 16 -4 29 -11 9 -16 9 -22 0z"/>
<path d="M1503 1378 c-19 -25 -24 -38 -14 -38 6 0 11 6 11 14 0 8 6 16 13 19
6 2 9 7 6 11 -3 4 -11 1 -16 -6z"/>
<path d="M330 1350 c0 -5 5 -12 10 -15 6 -3 10 -1 10 5 0 6 6 8 13 4 6 -4 8
-3 4 1 -10 12 -37 15 -37 5z"/>
<path d="M381 1353 c3 -19 -2 -34 -10 -28 -21 12 -19 -14 2 -31 12 -10 17 -12
10 -5 -9 11 -8 19 3 36 10 16 12 25 4 30 -6 3 -10 3 -9 -2z"/>
<path d="M1605 1351 c-3 -5 0 -13 6 -17 8 -4 7 -9 -2 -15 -11 -7 -10 -9 4 -9
9 0 17 7 17 15 0 8 -6 15 -12 15 -9 0 -8 4 2 10 9 6 10 10 3 10 -6 0 -14 -4
-18 -9z"/>
<path d="M1647 1353 c-10 -9 -9 -23 1 -23 5 0 9 7 9 15 0 17 -1 18 -10 8z"/>
<path d="M1558 1323 c7 -3 16 -2 19 1 4 3 -2 6 -13 5 -11 0 -14 -3 -6 -6z"/>
<path d="M1337 1308 c-13 -10 -14 -17 -6 -28 9 -12 10 -12 5 4 -4 13 -2 17 7
13 8 -3 14 1 14 9 0 17 1 17 -20 2z"/>
<path d="M1425 1310 c-3 -5 3 -10 14 -10 12 0 21 5 21 10 0 6 -6 10 -14 10 -8
0 -18 -4 -21 -10z"/>
<path d="M644 1288 c1 -29 16 -40 16 -12 0 8 5 12 10 9 6 -3 10 -1 10 5 0 7
-6 10 -14 7 -8 -3 -17 -1 -19 6 -2 7 -4 0 -3 -15z"/>
<path d="M1380 1280 c0 -5 7 -7 15 -4 8 4 15 8 15 10 0 2 -7 4 -15 4 -8 0 -15
-4 -15 -10z"/>
<path d="M410 1260 c9 -16 15 -18 30 -10 25 14 35 13 22 -2 -16 -20 -16 -22
-3 -45 6 -13 18 -23 26 -23 8 0 14 -6 13 -12 -2 -7 3 -12 10 -10 6 1 12 -4 12
-12 0 -21 20 -30 33 -17 9 9 8 11 -6 5 -13 -5 -16 -2 -11 10 3 9 11 16 16 16
7 0 6 5 -1 13 -6 8 -9 16 -6 18 2 3 -5 5 -16 5 -19 0 -19 -1 -3 -13 10 -7 15
-16 11 -20 -4 -3 -15 1 -25 10 -10 10 -24 17 -31 17 -7 0 -9 5 -6 10 3 6 1 10
-5 10 -6 0 -8 5 -3 13 4 6 8 22 9 34 1 19 -2 21 -19 11 -11 -5 -22 -6 -26 -2
-3 5 -12 10 -19 12 -10 2 -10 -2 -2 -18z"/>
<path d="M690 1271 c0 -6 4 -13 10 -16 6 -3 7 1 4 9 -7 18 -14 21 -14 7z"/>
<path d="M1295 1266 c-6 -8 -20 -28 -33 -44 -14 -19 -18 -33 -12 -37 6 -4 10
-3 9 2 -4 20 2 27 12 13 9 -12 10 -12 5 4 -4 12 1 27 15 43 13 12 20 25 18 27
-3 3 -9 -1 -14 -8z"/>
<path d="M1555 1270 c-3 -5 0 -12 6 -16 8 -4 9 -3 5 4 -4 8 -2 10 7 6 8 -3 17
-1 20 3 3 5 -3 9 -13 10 -11 1 -22 -2 -25 -7z"/>
<path d="M676 1237 c3 -10 9 -15 12 -12 3 3 0 11 -7 18 -10 9 -11 8 -5 -6z"/>
<path d="M1465 1241 c-3 -5 -1 -12 5 -16 5 -3 10 1 10 9 0 18 -6 21 -15 7z"/>
<path d="M1538 1219 c-3 -16 -4 -29 -3 -29 1 0 13 13 27 29 l26 29 -23 0 c-18
0 -24 -7 -27 -29z"/>
<path d="M728 1228 c9 -9 9 -15 -1 -27 -10 -14 -10 -14 4 -4 12 10 18 10 27 1
7 -7 12 -9 12 -5 0 4 -9 16 -20 27 -11 11 -23 20 -27 20 -4 0 -2 -5 5 -12z"/>
<path d="M1300 1229 c0 -5 5 -7 10 -4 6 3 10 8 10 11 0 2 -4 4 -10 4 -5 0 -10
-5 -10 -11z"/>
<path d="M1330 1230 c0 -5 5 -10 10 -10 6 0 10 5 10 10 0 6 -4 10 -10 10 -5 0
-10 -4 -10 -10z"/>
<path d="M1318 1203 c7 -3 16 -2 19 1 4 3 -2 6 -13 5 -11 0 -14 -3 -6 -6z"/>
<path d="M1461 1186 c18 -14 18 -34 0 -45 -7 -5 -10 -14 -7 -20 4 -6 12 -9 17
-5 5 3 7 9 4 14 -3 5 -1 11 5 15 6 4 8 11 5 16 -4 5 -1 9 5 9 7 0 7 5 -2 13
-7 8 -19 14 -26 14 -13 0 -13 -2 -1 -11z"/>
<path d="M1443 1165 c0 -8 4 -15 9 -15 4 0 8 4 8 9 0 6 -4 12 -8 15 -5 3 -9
-1 -9 -9z"/>
<path d="M1205 1161 c3 -5 -1 -12 -7 -14 -7 -3 -3 -6 9 -6 12 -1 23 -6 25 -11
2 -7 10 -6 22 3 17 13 17 14 -1 28 -16 13 -17 13 -4 -3 12 -16 11 -18 -3 -18
-9 0 -16 4 -16 9 0 5 -7 12 -16 15 -8 3 -13 2 -9 -3z"/>
<path d="M797 1149 c6 -6 9 -19 6 -28 -4 -14 -3 -14 6 -1 15 21 14 27 -6 35
-14 5 -15 3 -6 -6z"/>
<path d="M844 1103 c5 -15 3 -23 -5 -23 -9 0 -8 -4 1 -15 7 -8 18 -15 24 -14
7 0 6 2 -1 6 -20 7 -15 23 5 16 15 -6 15 -3 -3 18 -11 13 -22 26 -24 29 -2 3
0 -5 3 -17z"/>
<path d="M1142 1100 c-18 -29 -15 -38 4 -12 9 13 14 25 12 27 -2 2 -9 -5 -16
-15z"/>
<path d="M1436 1107 c3 -10 9 -15 12 -12 3 3 0 11 -7 18 -10 9 -11 8 -5 -6z"/>
<path d="M1366 1094 c-5 -14 -4 -15 9 -4 17 14 19 20 6 20 -5 0 -12 -7 -15
-16z"/>
<path d="M580 1084 c0 -21 47 -77 54 -65 3 5 -1 12 -10 15 -10 4 -14 13 -10
28 3 13 3 17 0 11 -9 -21 -26 -15 -19 7 4 11 2 20 -4 20 -6 0 -11 -7 -11 -16z"/>
<path d="M1160 1078 c-12 -22 -12 -22 6 -6 10 10 15 20 12 24 -4 3 -12 -5 -18
-18z"/>
<path d="M1409 1091 c8 -5 10 -14 6 -21 -5 -9 -4 -11 3 -6 18 11 14 36 -5 36
-14 0 -15 -2 -4 -9z"/>
<path d="M807 1069 c4 -13 8 -18 11 -10 2 7 -1 18 -6 23 -8 8 -9 4 -5 -13z"/>
<path d="M1094 1049 c-18 -19 -29 -73 -13 -63 4 2 12 -2 18 -10 9 -11 9 -15
-1 -18 -8 -3 -7 -6 4 -10 19 -8 18 12 -1 36 -12 14 -11 20 5 38 11 12 13 18 5
13 -9 -5 -12 -3 -9 6 3 8 11 13 17 11 7 -1 10 2 6 8 -8 13 -9 13 -31 -11z m6
-23 c0 -3 -4 -8 -10 -11 -5 -3 -10 -1 -10 4 0 6 5 11 10 11 6 0 10 -2 10 -4z"/>
<path d="M1180 1061 c0 -6 4 -13 10 -16 6 -3 7 1 4 9 -7 18 -14 21 -14 7z"/>
<path d="M1376 1035 c-11 -8 -15 -15 -9 -15 6 0 16 7 23 15 16 19 11 19 -14 0z"/>
<path d="M899 1021 c-5 -22 -3 -38 4 -48 4 -6 4 -14 -2 -17 -5 -4 -13 3 -16
15 -5 16 -10 18 -18 9 -9 -8 -8 -14 5 -24 16 -12 16 -14 0 -32 -9 -10 2 -1 26
21 39 36 59 62 29 36 -8 -6 -16 -8 -20 -5 -8 8 3 35 12 29 4 -2 8 2 8 9 0 12
-26 19 -28 7z"/>
<path d="M616 972 c-3 -5 1 -9 9 -9 8 0 12 4 9 9 -3 4 -7 8 -9 8 -2 0 -6 -4
-9 -8z"/>
<path d="M800 963 c0 -12 5 -25 11 -28 16 -11 17 -2 2 25 -12 24 -13 24 -13 3z"/>
<path d="M926 876 c-41 -44 -83 -90 -93 -102 -19 -22 -150 -166 -238 -262 -27
-30 -51 -58 -53 -63 -2 -5 61 -9 141 -9 l146 0 83 90 c73 80 108 106 108 83 0
-5 19 -29 43 -54 23 -25 57 -62 75 -82 l32 -37 145 0 c80 0 145 3 145 8 0 4
-19 27 -42 52 -78 86 -133 147 -213 235 -44 49 -87 96 -95 105 -8 9 -36 39
-62 67 l-47 51 -75 -82z"/>
<path d="M1131 947 c2 -1 12 -9 22 -16 15 -12 17 -12 11 3 -3 9 -13 16 -22 16
-8 0 -13 -1 -11 -3z"/>
<path d="M1323 935 c-9 -25 4 -29 17 -6 7 15 7 21 0 21 -6 0 -13 -7 -17 -15z"/>
<path d="M1395 937 c-23 -25 -22 -32 1 -33 20 -2 23 1 13 12 -6 8 -7 14 -2 14
14 0 54 -46 46 -53 -10 -11 -13 -57 -3 -57 5 0 12 5 15 10 4 6 11 7 17 4 7 -4
8 -2 4 5 -4 6 -11 9 -16 6 -4 -3 -11 2 -14 11 -4 12 -2 15 9 10 22 -8 5 21
-32 56 -21 20 -31 23 -38 15z"/>
<path d="M575 929 c-4 -6 -5 -12 -2 -15 2 -3 7 2 10 11 7 17 1 20 -8 4z"/>
<path d="M619 913 c0 -12 -2 -13 -6 -5 -4 10 -8 10 -19 1 -8 -6 -14 -17 -14
-23 0 -6 5 -4 11 4 8 12 12 12 16 2 4 -10 8 -9 19 5 16 22 18 33 4 33 -5 0
-10 -8 -11 -17z"/>
<path d="M1120 926 c0 -2 7 -9 15 -16 9 -7 15 -8 15 -2 0 5 -7 12 -15 16 -8 3
-15 4 -15 2z"/>
<path d="M800 914 c0 -5 4 -16 10 -24 6 -9 5 -20 -3 -30 -10 -13 -10 -13 5 -1
14 10 15 17 6 35 -14 27 -18 32 -18 20z"/>
<path d="M1171 884 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z"/>
<path d="M525 869 c-11 -16 -1 -19 13 -3 7 8 8 14 3 14 -5 0 -13 -5 -16 -11z"/>
<path d="M1246 855 c13 -13 24 -34 24 -47 -1 -20 -2 -19 -14 8 -8 18 -18 34
-24 38 -5 3 -1 -12 10 -34 13 -25 24 -37 33 -33 12 4 12 10 0 40 -18 43 -18
46 -2 37 6 -4 9 -3 5 1 -5 5 -19 9 -32 11 l-23 2 23 -23z"/>
<path d="M495 840 c-3 -5 -3 -10 1 -10 4 0 -5 -10 -20 -21 -15 -12 -25 -24
-22 -27 3 -3 1 -11 -6 -19 -8 -11 -8 -17 2 -26 10 -9 11 -9 6 1 -10 18 4 38
15 21 7 -11 9 -10 9 4 0 9 -5 17 -11 17 -8 0 -8 5 1 15 7 8 15 13 19 11 4 -3
12 4 19 14 7 11 8 21 2 25 -5 3 -11 1 -15 -5z"/>
<path d="M755 839 c-11 -17 1 -21 15 -4 8 9 8 15 2 15 -6 0 -14 -5 -17 -11z"/>
<path d="M1209 826 c14 -15 26 -26 28 -26 9 0 -24 40 -37 45 -8 4 -4 -5 9 -19z"/>
<path d="M519 813 c-13 -16 -12 -17 4 -4 9 7 17 15 17 17 0 8 -8 3 -21 -13z"/>
<path d="M674 810 c0 -11 6 -20 13 -20 11 0 11 5 3 20 -6 11 -12 20 -13 20 -2
0 -3 -9 -3 -20z"/>
<path d="M1523 793 c0 -14 -6 -28 -11 -32 -7 -4 -6 -12 3 -24 11 -16 13 -16
19 -2 3 9 2 13 -4 10 -11 -7 -14 8 -3 19 10 10 14 44 5 50 -4 2 -8 -7 -9 -21z"/>
<path d="M718 783 c-6 -7 -8 -16 -5 -20 4 -3 -1 -12 -11 -19 -9 -7 -14 -15
-11 -18 3 -3 16 6 30 21 13 14 18 23 10 18 -9 -5 -12 -3 -9 6 3 8 10 14 16 14
5 0 13 3 16 6 3 3 -1 6 -9 6 -8 0 -20 -6 -27 -14z"/>
<path d="M1341 784 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z"/>
<path d="M544 774 c3 -9 6 -18 6 -20 0 -3 5 -2 10 1 16 10 12 35 -6 35 -11 0
-14 -5 -10 -16z"/>
<path d="M1550 781 c0 -6 4 -13 10 -16 6 -3 7 1 4 9 -7 18 -14 21 -14 7z"/>
<path d="M646 764 c-9 -24 -2 -26 12 -4 7 11 8 20 3 20 -5 0 -12 -7 -15 -16z"/>
<path d="M1310 765 c7 -9 15 -13 17 -11 7 7 -7 26 -19 26 -6 0 -6 -6 2 -15z"/>
<path d="M1560 740 l-25 -20 27 4 c15 3 30 0 33 -5 4 -5 12 -9 18 -9 7 0 3 8
-8 16 -11 8 -19 20 -17 25 3 12 1 12 -28 -11z"/>
<path d="M1292 736 c7 -8 15 -12 17 -11 5 6 -10 25 -20 25 -5 0 -4 -6 3 -14z"/>
<path d="M662 728 c3 -7 -2 -19 -9 -27 -8 -7 -11 -16 -8 -20 8 -7 35 28 35 46
0 7 -5 13 -11 13 -6 0 -9 -6 -7 -12z"/>
<path d="M408 723 c7 -3 16 -2 19 1 4 3 -2 6 -13 5 -11 0 -14 -3 -6 -6z"/>
<path d="M1326 722 c-4 -7 -3 -12 2 -12 5 0 12 -9 15 -20 3 -11 11 -20 19 -20
9 0 9 3 2 8 -6 4 -10 15 -8 25 1 9 -1 15 -6 12 -5 -3 -10 0 -12 7 -3 9 -6 9
-12 0z"/>
<path d="M354 679 c-19 -22 -19 -22 4 -10 12 6 22 16 22 21 0 15 -5 12 -26
-11z"/>
<path d="M1625 690 c-3 -5 -3 -10 1 -10 4 0 -1 -10 -12 -22 -10 -12 -14 -18
-7 -15 6 4 14 1 16 -5 4 -10 6 -10 6 -1 1 7 7 10 15 7 8 -3 17 -1 21 5 3 7 0
8 -10 5 -11 -5 -14 -2 -9 10 3 9 1 16 -6 16 -6 0 -8 5 -5 10 3 6 4 10 1 10 -3
0 -8 -4 -11 -10z"/>
<path d="M371 661 l-23 -18 23 2 c12 1 23 9 25 18 3 21 4 21 -25 -2z"/>
<path d="M1410 669 c0 -5 5 -7 10 -4 6 3 10 8 10 11 0 2 -4 4 -10 4 -5 0 -10
-5 -10 -11z"/>
<path d="M628 663 c7 -3 16 -2 19 1 4 3 -2 6 -13 5 -11 0 -14 -3 -6 -6z"/>
<path d="M599 648 c-6 -21 -5 -37 2 -32 5 3 7 9 4 14 -3 4 1 11 7 13 10 4 10
6 1 6 -7 1 -13 0 -14 -1z"/>
<path d="M1400 625 c32 -43 38 -46 36 -15 0 19 -4 26 -12 20 -6 -6 -16 -5 -24
3 -11 9 -10 7 0 -8z"/>
<path d="M1670 630 c0 -6 5 -8 11 -4 13 8 10 -55 -4 -73 -6 -9 -5 -13 2 -13 6
0 11 5 11 10 0 6 3 9 8 8 10 -4 14 5 8 22 -3 8 -6 24 -8 34 -3 21 -28 35 -28
16z"/>
<path d="M287 603 c-3 -5 -2 -15 4 -23 7 -12 9 -11 9 5 0 17 2 18 11 5 9 -12
10 -12 7 -1 -5 17 -24 26 -31 14z"/>
<path d="M1716 597 c3 -10 9 -15 12 -12 3 3 0 11 -7 18 -10 9 -11 8 -5 -6z"/>
<path d="M304 559 c-4 -7 -3 -9 4 -5 5 3 13 0 15 -6 4 -9 6 -10 6 -1 1 17 -16
25 -25 12z"/>
<path d="M1604 562 c3 -6 2 -13 -4 -17 -5 -3 -10 -10 -10 -16 0 -12 27 -12 35
1 4 6 -1 7 -12 3 -15 -6 -16 -4 -5 9 10 13 10 18 1 24 -7 4 -9 3 -5 -4z"/>
<path d="M366 543 c-6 -14 -5 -15 5 -6 7 7 10 15 7 18 -3 3 -9 -2 -12 -12z"/>
<path d="M405 550 c-3 -5 0 -7 8 -4 8 3 17 -3 21 -13 7 -17 8 -17 22 1 8 11
14 14 14 7 0 -7 5 -9 11 -5 8 4 7 9 -2 15 -21 13 -29 11 -29 -8 -1 -17 -1 -17
-11 0 -11 19 -25 22 -34 7z"/>
<path d="M1490 549 c0 -15 21 -21 34 -10 8 7 17 7 24 1 9 -7 9 -7 2 2 -11 14
-60 19 -60 7z"/>
<path d="M1567 543 c3 -7 6 -13 8 -13 2 0 5 6 8 13 3 8 -1 14 -8 14 -7 0 -11
-6 -8 -14z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 12 KiB

14
dist/index.html vendored
View file

@ -1,14 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/x-icon" href="/assets/proxmox-removebg-preview-DD3TFQ_P.svg">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Proxmox Dashboard</title>
<script type="module" crossorigin src="/assets/index-D7GdPwQ6.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-5jcJrdyB.css">
</head>
<body>
<div id="root"></div>
</body>
</html>

14
ecosystem.config.cjs Normal file
View file

@ -0,0 +1,14 @@
module.exports = {
apps: [{
name: 'proxmox-dashboard',
script: 'server/index.js',
env: {
NODE_ENV: 'production',
PORT: '3006'
},
instances: 1,
autorestart: true,
watch: false,
max_memory_restart: '1G'
}]
}

View file

@ -10,4 +10,4 @@
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
</html>

46
nginx.conf Normal file
View file

@ -0,0 +1,46 @@
server {
listen 159 ssl;
server_name gabve.ddns.net;
# SSL Configuration
ssl_certificate /etc/nginx/ssl/gabve.ddns.net_2048/fullchain.cer;
ssl_certificate_key /etc/nginx/ssl/gabve.ddns.net_2048/private.key;
# SSL Security Settings
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
root /var/www/proxmoxchoose/proxmox_choose_page/dist;
index index.html;
# Main location block
location / {
try_files $uri $uri/ /index.html;
# Security headers
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
}
# API proxy
location /api/ {
proxy_pass http://localhost:3006;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# Let's Encrypt verification
location /.well-known/acme-challenge {
proxy_set_header Host $host;
proxy_set_header X-Real_IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr:$remote_port;
proxy_pass http://127.0.0.1:9180;
}
}

View file

@ -5,7 +5,7 @@
"type": "module",
"scripts": {
"dev": "concurrently \"vite\" \"node server/index.js\"",
"build": "vite build",
"build": "tsc && vite build",
"lint": "eslint .",
"preview": "vite preview",
"server": "node server/index.js",

View file

@ -1,2 +0,0 @@
screen -S pve
npm run server

View file

@ -1,5 +1,5 @@
import React from 'react';
import { Server, Cpu, MemoryStick as Memory, Trash2, ExternalLink } from 'lucide-react';
import React, { useState } from 'react';
import { Server, Cpu, MemoryStick as Memory, Trash2, ExternalLink, AlertCircle } from 'lucide-react';
import type { Server as ServerType } from '../types';
interface ServerCardProps {
@ -8,18 +8,66 @@ interface ServerCardProps {
}
export function ServerCard({ server, onDelete }: ServerCardProps) {
const [showConfirmation, setShowConfirmation] = useState(false);
const handleProxmoxClick = () => {
window.open(server.proxmox_url, '_blank');
};
const handleDeleteClick = (e: React.MouseEvent) => {
e.stopPropagation();
setShowConfirmation(true);
};
const handleConfirmDelete = (e: React.MouseEvent) => {
e.stopPropagation();
onDelete(server.id);
setShowConfirmation(false);
};
const handleCancelDelete = (e: React.MouseEvent) => {
e.stopPropagation();
setShowConfirmation(false);
};
const totalCores = server.cpus.reduce((sum, cpu) => sum + cpu.cores, 0);
const firstCpu = server.cpus[0];
return (
<div
className="bg-gray-800/50 backdrop-blur-sm rounded-xl p-6 hover:bg-gray-700/50 transition-all duration-300 cursor-pointer transform hover:scale-102 hover:shadow-xl hover:shadow-purple-500/10 border border-gray-700/50 animate-fadeIn hover:animate-glow"
className="bg-gray-800/50 backdrop-blur-sm rounded-xl p-6 hover:bg-gray-700/50 transition-all duration-300 cursor-pointer transform hover:scale-102 hover:shadow-xl hover:shadow-purple-500/10 border border-gray-700/50 animate-fadeIn hover:animate-glow relative"
onClick={handleProxmoxClick}
>
{showConfirmation && (
<div
className="absolute inset-0 bg-gray-900/95 backdrop-blur-sm rounded-xl p-6 flex flex-col items-center justify-center gap-4 z-10 animate-fadeIn"
onClick={(e) => e.stopPropagation()}
>
<AlertCircle size={48} className="text-red-400 animate-pulse" />
<h4 className="text-xl font-semibold text-white text-center">
Delete {server.name}?
</h4>
<p className="text-gray-400 text-center max-w-sm">
This action cannot be undone. The server will be removed from the dashboard.
</p>
<div className="flex gap-3 mt-2">
<button
onClick={handleConfirmDelete}
className="bg-red-500 hover:bg-red-600 text-white px-4 py-2 rounded-lg transition-colors duration-200 flex items-center gap-2"
>
<Trash2 size={16} />
Delete
</button>
<button
onClick={handleCancelDelete}
className="bg-gray-700 hover:bg-gray-600 text-white px-4 py-2 rounded-lg transition-colors duration-200"
>
Cancel
</button>
</div>
</div>
)}
<div className="flex items-center justify-between mb-6">
<h3 className="text-xl font-semibold text-white flex items-center gap-2 group">
<Server className="text-purple-400 group-hover:text-purple-300 transition-colors animate-pulse" size={24} />
@ -27,10 +75,7 @@ export function ServerCard({ server, onDelete }: ServerCardProps) {
<ExternalLink size={16} className="text-purple-400 group-hover:text-purple-300 transition-colors" />
</h3>
<button
onClick={(e) => {
e.stopPropagation();
onDelete(server.id);
}}
onClick={handleDeleteClick}
className="text-gray-400 hover:text-red-400 transition-colors p-2 hover:bg-red-400/10 rounded-lg"
title="Delete server"
>

2
start.sh Executable file → Normal file
View file

@ -29,4 +29,4 @@ screen -ls
echo "Servers started successfully!"
echo "To attach to the screens:"
echo " API server: screen -r proxmox-api"
echo " Vite server: screen -r proxmox-vite"
echo " Vite server: screen -r proxmox-vite"