148 lines
4.7 KiB
TypeScript
148 lines
4.7 KiB
TypeScript
"use client";
|
|
|
|
import { Plus } from "lucide-react";
|
|
import { invoke } from "@tauri-apps/api/core";
|
|
import {
|
|
Dialog,
|
|
DialogClose,
|
|
DialogContent,
|
|
DialogDescription,
|
|
DialogFooter,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
DialogTrigger,
|
|
} from "@/components/ui/dialog";
|
|
import { Button } from "@/components/ui/button";
|
|
import { AnimatePresence, motion } from "motion/react";
|
|
import { Field, FieldGroup, FieldLabel } from "./ui/field";
|
|
import { Label } from "./ui/label";
|
|
import { Input } from "./ui/input";
|
|
import { Textarea } from "./ui/textarea";
|
|
import { Checkbox } from "./ui/checkbox";
|
|
import { useState } from "react";
|
|
|
|
export default function PlusButton() {
|
|
const [differentAddr, setDifferentAddr] = useState(false);
|
|
const [name, setName] = useState("");
|
|
const [address, setAddress] = useState("");
|
|
const [description, setDescription] = useState<string>("");
|
|
const [sshAddr, setSSHAddr] = useState<string>("");
|
|
|
|
const onSubmit = async () => {
|
|
let tmp_description = undefined;
|
|
let tmp_ssh = undefined;
|
|
|
|
if (!name.trim()) return;
|
|
if (!address.trim()) return;
|
|
if (description.trim()) tmp_description = description.trim();
|
|
if (sshAddr.trim()) tmp_ssh = sshAddr.trim();
|
|
|
|
await invoke("new_app", {
|
|
name: name,
|
|
address: address,
|
|
description: description,
|
|
sshAddress: sshAddr,
|
|
});
|
|
};
|
|
|
|
return (
|
|
<Dialog>
|
|
<form onSubmit={() => onSubmit()}>
|
|
<DialogTrigger asChild>
|
|
<motion.button
|
|
whileHover={{ scale: 1.05 }}
|
|
whileTap={{ scale: 0.95 }}
|
|
transition={{ type: "spring", stiffness: 300, damping: 20 }}
|
|
className="absolute right-3 bottom-3 bg-emerald-700 p-2 rounded-full"
|
|
>
|
|
<Plus className="w-8 h-8 text-white" />
|
|
</motion.button>
|
|
</DialogTrigger>
|
|
<DialogContent className="sm:max-w-sm">
|
|
<DialogHeader>
|
|
<DialogTitle>Create Service</DialogTitle>
|
|
<DialogDescription>
|
|
Create a new service. Click save when you're finished.
|
|
</DialogDescription>
|
|
</DialogHeader>
|
|
<FieldGroup>
|
|
<Field>
|
|
<Label htmlFor="name">Service Name</Label>
|
|
<Input
|
|
id="name"
|
|
name="name"
|
|
value={name}
|
|
onChange={(e) => setName(e.target.value.trim())}
|
|
defaultValue="Kubernetes"
|
|
/>
|
|
</Field>
|
|
<Field>
|
|
<Label htmlFor="address">IP Address</Label>
|
|
<Input
|
|
id="address"
|
|
name="address"
|
|
value={address}
|
|
onChange={(e) => setAddress(e.target.value.trim())}
|
|
defaultValue="192.168.1.10"
|
|
/>
|
|
</Field>
|
|
<Field>
|
|
<Label htmlFor="description">
|
|
Description{" "}
|
|
<span className="text-sm text-black/25">(Optional)</span>
|
|
</Label>
|
|
<Textarea
|
|
id="description"
|
|
value={description}
|
|
onChange={(e) => setDescription(e.target.value.trim())}
|
|
name="description"
|
|
/>
|
|
</Field>
|
|
<Field orientation="horizontal">
|
|
<Checkbox
|
|
checked={differentAddr}
|
|
onCheckedChange={(checked: boolean | "indeterminate") =>
|
|
setDifferentAddr(checked === true)
|
|
}
|
|
id="toggle-ssh"
|
|
name="toggle-ssh"
|
|
/>
|
|
<FieldLabel htmlFor="toggle-ssh">
|
|
Use Different URL for SSH
|
|
</FieldLabel>
|
|
</Field>
|
|
<AnimatePresence>
|
|
{differentAddr && (
|
|
<motion.div
|
|
key={"ssh-addr-field"}
|
|
initial={{ opacity: 0, y: -8 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
exit={{ opacity: 0, y: -8 }}
|
|
transition={{ duration: 0.3 }}
|
|
>
|
|
<Field>
|
|
<Label htmlFor="ssh-addr">SSH Address</Label>
|
|
<Input
|
|
id="ssh-addr"
|
|
name="ssh-addr"
|
|
value={sshAddr}
|
|
onChange={(e) => setSSHAddr(e.target.value.trim())}
|
|
defaultValue="192.168.1.10"
|
|
/>
|
|
</Field>
|
|
</motion.div>
|
|
)}
|
|
</AnimatePresence>
|
|
</FieldGroup>
|
|
<DialogFooter>
|
|
<DialogClose asChild>
|
|
<Button variant="outline">Cancel</Button>
|
|
</DialogClose>
|
|
<Button type="submit">Save changes</Button>
|
|
</DialogFooter>
|
|
</DialogContent>
|
|
</form>
|
|
</Dialog>
|
|
);
|
|
}
|