blob: 35b3722c0a7a1d89cd401fd4d6087b6be97fd7f0 [file] [log] [blame]
giod0026612025-05-08 13:00:36 +00001import { NodeRect } from "./node-rect";
2import { nodeIsConnectable, nodeLabel, useStateStore, VolumeNode } from "@/lib/state";
3import { useEffect, useMemo } from "react";
gio5f2f1002025-03-20 18:38:48 +04004import { z } from "zod";
giod0026612025-05-08 13:00:36 +00005import { DeepPartial, EventType, useForm } from "react-hook-form";
6import { zodResolver } from "@hookform/resolvers/zod";
7import { Form, FormControl, FormField, FormItem, FormMessage } from "./ui/form";
8import { Input } from "./ui/input";
gio5f2f1002025-03-20 18:38:48 +04009import { Handle, Position } from "@xyflow/react";
10import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./ui/select";
11
12export function NodeVolume(node: VolumeNode) {
giod0026612025-05-08 13:00:36 +000013 const { id, data, selected } = node;
14 const isConnectable = useMemo(() => nodeIsConnectable(node, "volume"), [node]);
15 return (
16 <NodeRect id={id} selected={selected} type={node.type} state={node.data.state}>
17 <div style={{ padding: "10px 20px" }}>
18 <div>{nodeLabel(node)}</div>
19 <div>{data.type && `${data.type}`}</div>
20 <div>{data.size && `${data.size}`}</div>
21 <Handle
22 id="volume"
23 type={"source"}
24 position={Position.Top}
25 isConnectableStart={isConnectable}
26 isConnectableEnd={isConnectable}
27 isConnectable={isConnectable}
28 />
29 </div>
30 </NodeRect>
31 );
gio5f2f1002025-03-20 18:38:48 +040032}
33
34const volumeTypes = ["ReadWriteOnce", "ReadOnlyMany", "ReadWriteMany", "ReadWriteOncePod"] as const;
35
36const schema = z.object({
giod0026612025-05-08 13:00:36 +000037 name: z.string().min(1),
38 type: z.enum(volumeTypes),
39 size: z.string().min(1).default("1Gi"),
gio5f2f1002025-03-20 18:38:48 +040040});
41
gio08acd3a2025-06-12 12:15:30 +000042export function NodeVolumeDetails({ node, disabled }: { node: VolumeNode; disabled?: boolean }) {
43 const { id, data } = node;
giod0026612025-05-08 13:00:36 +000044 const store = useStateStore();
45 const form = useForm<z.infer<typeof schema>>({
46 resolver: zodResolver(schema),
47 mode: "onChange",
48 defaultValues: {
49 name: "",
50 type: undefined,
51 size: "",
52 },
53 });
54 useEffect(() => {
55 const sub = form.watch(
56 (
57 value: DeepPartial<z.infer<typeof schema>>,
58 { name, type }: { name?: keyof z.infer<typeof schema> | undefined; type?: EventType | undefined },
59 ) => {
60 if (type !== "change") {
61 return;
62 }
63 console.log({ name, type, value });
64 store.updateNodeData<"volume">(id, {
65 label: value.name,
66 type: value.type,
67 size: value.size,
68 });
69 },
70 );
71 return () => sub.unsubscribe();
72 }, [id, form, store]);
73 useEffect(() => {
74 form.reset({
75 name: data.label,
76 type: data.type,
77 size: data.size,
78 });
79 }, [form, data]);
80 return (
81 <>
82 <Form {...form}>
83 <form className="space-y-2">
84 <FormField
85 control={form.control}
86 name="name"
87 render={({ field }) => (
88 <FormItem>
89 <FormControl>
gio3ec94242025-05-16 12:46:57 +000090 <Input placeholder="name" {...field} disabled={disabled} />
giod0026612025-05-08 13:00:36 +000091 </FormControl>
92 <FormMessage />
93 </FormItem>
94 )}
95 />
96 <FormField
97 control={form.control}
98 name="type"
99 render={({ field }) => (
100 <FormItem>
gio3ec94242025-05-16 12:46:57 +0000101 <Select onValueChange={field.onChange} defaultValue={field.value} disabled={disabled}>
giod0026612025-05-08 13:00:36 +0000102 <FormControl>
103 <SelectTrigger>
104 <SelectValue placeholder="Volume Type" />
105 </SelectTrigger>
106 </FormControl>
107 <SelectContent>
108 {volumeTypes.map((t) => (
109 <SelectItem key={t} value={t}>
110 {t}
111 </SelectItem>
112 ))}
113 </SelectContent>
114 </Select>
115 <FormMessage />
116 </FormItem>
117 )}
118 />
119 <FormField
120 control={form.control}
121 name="size"
122 render={({ field }) => (
123 <FormItem>
124 <FormControl>
gio3ec94242025-05-16 12:46:57 +0000125 <Input placeholder="size" {...field} disabled={disabled} />
giod0026612025-05-08 13:00:36 +0000126 </FormControl>
127 <FormMessage />
128 </FormItem>
129 )}
130 />
131 </form>
132 </Form>
133 </>
134 );
135}