diff --git a/examples/example_install.json b/examples/example_install.json new file mode 100644 index 0000000..cad6c60 --- /dev/null +++ b/examples/example_install.json @@ -0,0 +1,3 @@ +{ + "install": "sh test" +} \ No newline at end of file diff --git a/examples/invalid_install.json b/examples/invalid_install.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/examples/invalid_install.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/src/app/globals.css b/src/app/globals.css index 57b48f8..a7ad7ea 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -185,7 +185,7 @@ --popover-foreground: oklch(0.9108 0.0427 269.5516); --primary: oklch(0.7182 0.1105 239.784); --primary-foreground: oklch(0.3233 0.1025 253.8852); - --secondary: oklch(0.5544 0.0407 257.4166); + --secondary: oklch(0.38 0.06 258); --secondary-foreground: oklch(0.9288 0.0126 255.5078); --muted: oklch(0.3923 0.0613 254.3914); --muted-foreground: oklch(0.7584 0.0419 263.598); diff --git a/src/app/servers/[server]/AddAppDialog.tsx b/src/app/servers/[server]/AddAppDialog.tsx new file mode 100644 index 0000000..ba2937c --- /dev/null +++ b/src/app/servers/[server]/AddAppDialog.tsx @@ -0,0 +1,78 @@ +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog"; +import { Button, buttonVariants } from "@/components/ui/button"; +import { Plus } from "lucide-react"; +import { cn } from "@/lib/utils"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { useState } from "react"; +import Session from "@/lib/session"; +import { toast } from "sonner"; + +export default function AddAppDialog({ + session, +}: { + session: Session | null; +}) { + const [open, setOpen] = useState(false); + const [name, setName] = useState(""); + const [ip, setIp] = useState(""); + const [location, setLocation] = useState(undefined); + const [coordinates, setCoordinates] = useState<[number, number] | undefined>( + undefined + ); + + return ( + + setOpen(true)} + > + New + + + + Add Application + + + setName(e.currentTarget.value)} + /> + + + setIp(e.currentTarget.value)} + /> + + + + + + + + ); +} diff --git a/src/app/servers/[server]/AppComponent.tsx b/src/app/servers/[server]/AppComponent.tsx index 0c6d186..5b39d4f 100644 --- a/src/app/servers/[server]/AppComponent.tsx +++ b/src/app/servers/[server]/AppComponent.tsx @@ -87,7 +87,7 @@ export default function AppComponent({ return ( { redirect(`/servers/${index}`); }} diff --git a/src/app/servers/[server]/ClientPage.tsx b/src/app/servers/[server]/ClientPage.tsx index f5bb757..fbaf291 100644 --- a/src/app/servers/[server]/ClientPage.tsx +++ b/src/app/servers/[server]/ClientPage.tsx @@ -10,6 +10,8 @@ import AppComponent from "./AppComponent"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { toast } from "sonner"; +import AddAppDialog from "./AddAppDialog"; +import InstallAppDialog from "./IntallAppDialog"; interface Server2 extends Server { services: Service[], @@ -40,12 +42,13 @@ export default function ClientPage({ serverId }: { serverId: string }) {
- Sentryx Apps + Sentryx Applications Your Sentryx apps on this server
- +
+ + +
diff --git a/src/app/servers/[server]/IntallAppDialog.tsx b/src/app/servers/[server]/IntallAppDialog.tsx new file mode 100644 index 0000000..af1b95e --- /dev/null +++ b/src/app/servers/[server]/IntallAppDialog.tsx @@ -0,0 +1,79 @@ +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog"; +import { Button, buttonVariants } from "@/components/ui/button"; +import { HardDriveDownload, Plus } from "lucide-react"; +import { cn } from "@/lib/utils"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { useState } from "react"; +import Session from "@/lib/session"; +import { toast } from "sonner"; +import { FileUpload } from "@/components/FileUpload"; + +export default function InstallAppDialog({ + session, +}: { + session: Session | null; +}) { + const [open, setOpen] = useState(false); + const [name, setName] = useState(""); + const [script, setScript] = useState<{ install?: string } | undefined>({}); + + return ( + + setOpen(true)} + > + Install + + + + Install Application + + + + setName(e.currentTarget.value)} + /> + + + { + try { + setScript(JSON.parse(contents)) + console.log(contents) + } catch { + setScript(undefined) + } + }} /> + + + + + + + + ); +} diff --git a/src/components/FileUpload.tsx b/src/components/FileUpload.tsx new file mode 100644 index 0000000..040b708 --- /dev/null +++ b/src/components/FileUpload.tsx @@ -0,0 +1,62 @@ +import { useState, useRef } from "react" +import { Button } from "@/components/ui/button" +import { cn } from "@/lib/utils" // optional utility for combining classes + +export function FileUpload({setSelected} : {setSelected: (contents: string) => void}) { + const inputRef = useRef(null) + const [fileName, setFileName] = useState(null) + const [isDragging, setIsDragging] = useState(false) + const [isUnsupported, setIsUnsupported] = useState(false) + + const handleFiles = (files: FileList | null) => { + const file = files?.[0] + if (!file) return + + setIsUnsupported(!file.name.endsWith('.json')); + if (isUnsupported) return + + setFileName(file.name) + + const reader = new FileReader() + reader.onload = (e) => { + setSelected(e.target?.result as string) + } + reader.readAsText(file) + } + + const handleDrop = (e: React.DragEvent) => { + e.preventDefault() + setIsDragging(false) + handleFiles(e.dataTransfer.files) + } + + return ( +
+ handleFiles(e.target.files)} + className="hidden" + /> + +
inputRef.current?.click()} + onDragOver={(e) => { + e.preventDefault() + setIsDragging(true) + }} + onDragLeave={() => setIsDragging(false)} + onDrop={handleDrop} + className={cn( + "flex h-32 cursor-pointer items-center justify-center rounded-md border-2 border-dashed transition-colors", + isDragging ? "border-primary bg-muted" : "border-muted", + isUnsupported && "border-destructive" + )} + > + + {isUnsupported ? "Unsupported file type" : (fileName || "Click or drag file to upload")} + +
+
+ ) +}