gitscope
← marzneshin / v0.3.0-alpha2 / dashboard/src/features/hosts/dialogs/mutation/index.tsx
https://dev.kronoz.win/r/marzneshin.git
dashboard/src/features/hosts/dialogs/mutation/index.tsx · TypeScript
Blame Raw
  1
  2import { FC, useEffect, useState } from "react";
  3import {
  4    DialogTitle,
  5    DialogContent,
  6    Dialog,
  7    DialogHeader,
  8    Form,
  9    FormItem,
 10    FormControl,
 11    FormMessage,
 12    FormLabel,
 13    Input,
 14    FormField,
 15    Checkbox,
 16    Button,
 17    SelectItem,
 18    SelectContent,
 19    SelectValue,
 20    Select,
 21    SelectTrigger,
 22    Alert,
 23    AlertTitle,
 24    AlertDescription
 25} from '@marzneshin/components';
 26import { useForm } from 'react-hook-form';
 27import { zodResolver } from '@hookform/resolvers/zod';
 28import { useTranslation } from 'react-i18next';
 29import {
 30    HostSchema,
 31    HostType,
 32    getDefaultValues,
 33    useHostsCreationMutation,
 34    useHostsUpdateMutation
 35} from "@marzneshin/features/hosts";
 36import { ExclamationTriangleIcon } from "@radix-ui/react-icons";
 37
 38interface MutationDialogProps {
 39    entity: HostType | null
 40    open: boolean
 41    inboundId: number
 42    onOpenChange: (state: boolean) => void
 43}
 44
 45
 46export const HostsMutationDialog: FC<MutationDialogProps> = ({
 47    inboundId,
 48    entity,
 49    open,
 50    onOpenChange,
 51}) => {
 52    const form = useForm({
 53        defaultValues: entity ? entity : getDefaultValues(),
 54        resolver: zodResolver(HostSchema)
 55    });
 56    const updateMutation = useHostsUpdateMutation();
 57    const createMutation = useHostsCreationMutation();
 58    const { t } = useTranslation();
 59    const security = form.watch().security
 60    const [extraSecurity, setExtraSecurity] = useState<boolean>(["tls", "inbound_default"].includes(security))
 61
 62    useEffect(() => {
 63        setExtraSecurity(["tls", "inbound_default"].includes(security))
 64    }, [security, setExtraSecurity])
 65
 66    const submit = (values: HostType) => {
 67        if (entity) {
 68            updateMutation.mutate({ inboundId, host: values });
 69        } else {
 70            createMutation.mutate({ inboundId, host: values });
 71        }
 72        onOpenChange(false);
 73    };
 74
 75    useEffect(() => {
 76        if (entity) form.reset(entity);
 77        else form.reset(getDefaultValues());
 78    }, [entity, form]);
 79
 80    return (
 81        <Dialog open={open} onOpenChange={onOpenChange} defaultOpen={true}>
 82            <DialogContent>
 83                <DialogHeader>
 84                    <DialogTitle className="text-primary">
 85                        {entity
 86                            ? t('page.hosts.dialogs.edition.title')
 87                            : t('page.hosts.dialogs.creation.title')}
 88                    </DialogTitle>
 89                </DialogHeader>
 90                <Form {...form}>
 91                    <form onSubmit={form.handleSubmit(submit)}>
 92                        <FormField
 93                            control={form.control}
 94                            name="remark"
 95                            render={({ field }) => (
 96                                <FormItem >
 97                                    <FormLabel>{t('name')}</FormLabel>
 98                                    <FormControl>
 99                                        <Input {...field} />
100                                    </FormControl>
101                                    <FormMessage />
102                                </FormItem>
103                            )}
104                        />
105                        <div className="flex flex-row gap-1 items-center">
106                            <FormField
107                                control={form.control}
108                                name="address"
109                                render={({ field }) => (
110                                    <FormItem className="w-2/3">
111                                        <FormLabel>{t('address')}</FormLabel>
112                                        <FormControl>
113                                            <Input {...field} />
114                                        </FormControl>
115                                        <FormMessage />
116                                    </FormItem>
117                                )}
118                            />
119                            <FormField
120                                control={form.control}
121                                name="port"
122                                render={({ field }) => (
123                                    <FormItem className="w-1/3">
124                                        <FormLabel>{t('port')}</FormLabel>
125                                        <FormControl>
126                                            <Input type="number" {...field} />
127                                        </FormControl>
128                                        <FormMessage />
129                                    </FormItem>
130                                )}
131                            />
132                        </div>
133                        <FormField
134                            control={form.control}
135                            name="path"
136                            render={({ field }) => (
137                                <FormItem >
138                                    <FormLabel>{t('path')}</FormLabel>
139                                    <FormControl>
140                                        <Input {...field} />
141                                    </FormControl>
142                                    <FormMessage />
143                                </FormItem>
144                            )}
145                        />
146
147                        <FormField
148                            control={form.control}
149                            name="host"
150                            render={({ field }) => (
151                                <FormItem >
152                                    <FormLabel>{t('host')}</FormLabel>
153                                    <FormControl>
154                                        <Input {...field} />
155                                    </FormControl>
156                                    <FormMessage />
157                                </FormItem>
158                            )}
159                        />
160
161                        <FormField
162                            control={form.control}
163                            name="security"
164                            render={({ field }) => (
165                                <FormItem>
166                                    <FormLabel>{t('security')}</FormLabel>
167                                    <Select onValueChange={field.onChange} defaultValue={field.value}>
168                                        <FormControl>
169                                            <SelectTrigger>
170                                                <SelectValue placeholder="Select a verified email to display" />
171                                            </SelectTrigger>
172                                        </FormControl>
173                                        <SelectContent>
174                                            <SelectItem value="none">None</SelectItem>
175                                            <SelectItem value="tls">TLS</SelectItem>
176                                            <SelectItem value="inbound_default">Inbound Default</SelectItem>
177                                        </SelectContent>
178                                    </Select>
179                                    <FormMessage />
180                                </FormItem>
181                            )}
182                        />
183                        {extraSecurity &&
184                            <>
185                                <FormField
186                                    control={form.control}
187                                    name="sni"
188                                    render={({ field }) => (
189                                        <FormItem >
190                                            <FormLabel>{t('SNI')}</FormLabel>
191                                            <FormControl>
192                                                <Input {...field} />
193                                            </FormControl>
194                                            <FormMessage />
195                                        </FormItem>
196                                    )}
197                                />
198
199                                <FormField
200                                    control={form.control}
201                                    name="alpn"
202                                    render={({ field }) => (
203                                        <FormItem>
204                                            <FormLabel>{t('alpn')}</FormLabel>
205                                            <Select onValueChange={field.onChange} defaultValue={field.value}>
206                                                <FormControl>
207                                                    <SelectTrigger>
208                                                        <SelectValue placeholder="Select ALPN" />
209                                                    </SelectTrigger>
210                                                </FormControl>
211                                                <SelectContent>
212                                                    <SelectItem value="none">None</SelectItem>
213                                                    <SelectItem value="h2">h2</SelectItem>
214                                                    <SelectItem value="http/1.1">HTTP 1.1</SelectItem>
215                                                    <SelectItem value="h2,http/1.1"> H2 HTTP 1.1</SelectItem>
216                                                </SelectContent>
217                                            </Select>
218                                            <FormMessage />
219                                        </FormItem>
220                                    )}
221                                />
222
223                                <FormField
224                                    control={form.control}
225                                    name="fingerprint"
226                                    render={({ field }) => (
227                                        <FormItem>
228                                            <FormLabel>{t('fingerprint')}</FormLabel>
229                                            <Select onValueChange={field.onChange} defaultValue={field.value}>
230                                                <FormControl>
231                                                    <SelectTrigger>
232                                                        <SelectValue placeholder="Select fingerprint" />
233                                                    </SelectTrigger>
234                                                </FormControl>
235                                                <SelectContent>
236                                                    <SelectItem value="none">None</SelectItem>
237                                                    <SelectItem value="chrome">Chrome</SelectItem>
238                                                    <SelectItem value="firefox">Firefox</SelectItem>
239                                                    <SelectItem value="safari">Safari</SelectItem>
240                                                    <SelectItem value="ios">iOS</SelectItem>
241                                                    <SelectItem value="android">Android</SelectItem>
242                                                    <SelectItem value="edge">Edge</SelectItem>
243                                                    <SelectItem value="360">360</SelectItem>
244                                                    <SelectItem value="qq">qq</SelectItem>
245                                                    <SelectItem value="random">Random</SelectItem>
246                                                    <SelectItem value="randomized">Randomized</SelectItem>
247                                                </SelectContent>
248                                            </Select>
249                                            <FormMessage />
250                                        </FormItem>
251                                    )}
252                                />
253
254                                <FormField
255                                    control={form.control}
256                                    name="allowinsecure"
257                                    render={({ field }) => (
258                                        <FormItem className="my-2">
259                                            <FormControl>
260                                                <div className="flex flex-row gap-1 items-center">
261                                                    <Checkbox
262                                                        checked={field.value}
263                                                        onCheckedChange={field.onChange}
264                                                    />
265                                                    <FormLabel>
266                                                        {t('page.hosts.allowinsecure')}
267                                                    </FormLabel>
268                                                </div>
269                                            </FormControl>
270                                            <FormMessage />
271                                            {form.getValues().allowinsecure &&
272                                                <Alert variant="destructive">
273                                                    <ExclamationTriangleIcon className="w-4 h-4" />
274                                                    <AlertTitle>
275                                                        Warning
276                                                    </AlertTitle>
277                                                    <AlertDescription>
278                                                        {t('page.hosts.dialogs.mutation.allowinsecure.alert')}
279                                                    </AlertDescription>
280                                                </Alert>}
281                                        </FormItem>
282                                    )}
283                                />
284                            </>
285                        }
286                        <Button
287                            className="mt-3 w-full font-semibold"
288                            type="submit"
289                            disabled={form.formState.isSubmitting}
290                        >
291                            {t('submit')}
292                        </Button>
293                    </form>
294                </Form>
295            </DialogContent>
296        </Dialog>
297    );
298};