blob: c58b600602932a9efcb45c6ff53316486c3eb7f5 [file] [log] [blame]
giod0026612025-05-08 13:00:36 +00001import { NodeRect } from "./node-rect";
gio69148322025-06-19 23:16:12 +04002import { nodeIsConnectable, nodeLabel, useStateStore } from "@/lib/state";
giod0026612025-05-08 13:00:36 +00003import { 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";
gio3fb133d2025-06-13 07:20:24 +000011import { Name } from "./node-name";
12import { NodeDetailsProps } from "@/lib/types";
gio69148322025-06-19 23:16:12 +040013import { VolumeNode } from "config";
gio5f2f1002025-03-20 18:38:48 +040014
15export function NodeVolume(node: VolumeNode) {
giod0026612025-05-08 13:00:36 +000016 const { id, data, selected } = node;
17 const isConnectable = useMemo(() => nodeIsConnectable(node, "volume"), [node]);
18 return (
gio69148322025-06-19 23:16:12 +040019 <NodeRect id={id} selected={selected} node={node} state={node.data.state}>
giod0026612025-05-08 13:00:36 +000020 <div style={{ padding: "10px 20px" }}>
21 <div>{nodeLabel(node)}</div>
22 <div>{data.type && `${data.type}`}</div>
23 <div>{data.size && `${data.size}`}</div>
24 <Handle
25 id="volume"
26 type={"source"}
27 position={Position.Top}
28 isConnectableStart={isConnectable}
29 isConnectableEnd={isConnectable}
30 isConnectable={isConnectable}
31 />
32 </div>
33 </NodeRect>
34 );
gio5f2f1002025-03-20 18:38:48 +040035}
36
37const volumeTypes = ["ReadWriteOnce", "ReadOnlyMany", "ReadWriteMany", "ReadWriteOncePod"] as const;
38
39const schema = z.object({
giod0026612025-05-08 13:00:36 +000040 type: z.enum(volumeTypes),
41 size: z.string().min(1).default("1Gi"),
gio5f2f1002025-03-20 18:38:48 +040042});
43
gio3fb133d2025-06-13 07:20:24 +000044export function NodeVolumeDetails({ node, disabled, showName = true }: NodeDetailsProps<VolumeNode>) {
gio08acd3a2025-06-12 12:15:30 +000045 const { id, data } = node;
giod0026612025-05-08 13:00:36 +000046 const store = useStateStore();
47 const form = useForm<z.infer<typeof schema>>({
48 resolver: zodResolver(schema),
49 mode: "onChange",
50 defaultValues: {
giod0026612025-05-08 13:00:36 +000051 type: undefined,
52 size: "",
53 },
54 });
55 useEffect(() => {
56 const sub = form.watch(
57 (
58 value: DeepPartial<z.infer<typeof schema>>,
59 { name, type }: { name?: keyof z.infer<typeof schema> | undefined; type?: EventType | undefined },
60 ) => {
61 if (type !== "change") {
62 return;
63 }
64 console.log({ name, type, value });
65 store.updateNodeData<"volume">(id, {
giod0026612025-05-08 13:00:36 +000066 type: value.type,
67 size: value.size,
68 });
69 },
70 );
71 return () => sub.unsubscribe();
72 }, [id, form, store]);
73 useEffect(() => {
74 form.reset({
giod0026612025-05-08 13:00:36 +000075 type: data.type,
76 size: data.size,
77 });
78 }, [form, data]);
79 return (
80 <>
gio3fb133d2025-06-13 07:20:24 +000081 {showName ? <Name node={node} disabled={disabled} /> : null}
giod0026612025-05-08 13:00:36 +000082 <Form {...form}>
83 <form className="space-y-2">
84 <FormField
85 control={form.control}
giod0026612025-05-08 13:00:36 +000086 name="type"
87 render={({ field }) => (
88 <FormItem>
gio3ec94242025-05-16 12:46:57 +000089 <Select onValueChange={field.onChange} defaultValue={field.value} disabled={disabled}>
giod0026612025-05-08 13:00:36 +000090 <FormControl>
91 <SelectTrigger>
92 <SelectValue placeholder="Volume Type" />
93 </SelectTrigger>
94 </FormControl>
95 <SelectContent>
96 {volumeTypes.map((t) => (
97 <SelectItem key={t} value={t}>
98 {t}
99 </SelectItem>
100 ))}
101 </SelectContent>
102 </Select>
103 <FormMessage />
104 </FormItem>
105 )}
106 />
107 <FormField
108 control={form.control}
109 name="size"
110 render={({ field }) => (
111 <FormItem>
112 <FormControl>
gio3ec94242025-05-16 12:46:57 +0000113 <Input placeholder="size" {...field} disabled={disabled} />
giod0026612025-05-08 13:00:36 +0000114 </FormControl>
115 <FormMessage />
116 </FormItem>
117 )}
118 />
119 </form>
120 </Form>
121 </>
122 );
123}