11import { useState } from "react" ;
2- import { FormProvider , useForm } from "react-hook-form" ;
2+ import { Controller , FormProvider , useForm } from "react-hook-form" ;
3+ import { faQuestionCircle } from "@fortawesome/free-solid-svg-icons" ;
4+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome" ;
5+ import { Tab } from "@headlessui/react" ;
36import { zodResolver } from "@hookform/resolvers/zod" ;
47import { z } from "zod" ;
58
6- import { Button , ModalClose } from "@app/components/v2" ;
9+ import {
10+ Button ,
11+ FormControl ,
12+ Input ,
13+ ModalClose ,
14+ Switch ,
15+ TextArea ,
16+ Tooltip
17+ } from "@app/components/v2" ;
718import { PamResourceType , TRedisResource } from "@app/hooks/api/pam" ;
819
9- import { RedisResourceFields } from "./shared/RedisResourceFields" ;
1020import { GenericResourceFields , genericResourceFieldsSchema } from "./GenericResourceFields" ;
1121
1222type Props = {
@@ -51,9 +61,13 @@ export const RedisResourceForm = ({ resource, onSubmit }: Props) => {
5161
5262 const {
5363 handleSubmit,
64+ control,
65+ watch,
5466 formState : { isSubmitting, isDirty }
5567 } = form ;
5668
69+ const sslEnabled = watch ( "connectionDetails.sslEnabled" ) ;
70+
5771 return (
5872 < FormProvider { ...form } >
5973 < form
@@ -63,10 +77,135 @@ export const RedisResourceForm = ({ resource, onSubmit }: Props) => {
6377 } }
6478 >
6579 < GenericResourceFields />
66- < RedisResourceFields
67- selectedTabIndex = { selectedTabIndex }
68- setSelectedTabIndex = { setSelectedTabIndex }
69- />
80+ < Tab . Group selectedIndex = { selectedTabIndex } onChange = { setSelectedTabIndex } >
81+ < Tab . List className = "-pb-1 mb-6 w-full border-b-2 border-mineshaft-600" >
82+ < Tab
83+ className = { ( { selected } ) =>
84+ `-mb-[0.14rem] px-4 py-2 text-sm font-medium whitespace-nowrap outline-hidden disabled:opacity-60 ${
85+ selected
86+ ? "border-b-2 border-mineshaft-300 text-mineshaft-200"
87+ : "text-bunker-300"
88+ } `
89+ }
90+ >
91+ Configuration
92+ </ Tab >
93+ < Tab
94+ className = { ( { selected } ) =>
95+ `-mb-[0.14rem] px-4 py-2 text-sm font-medium whitespace-nowrap outline-hidden disabled:opacity-60 ${
96+ selected
97+ ? "border-b-2 border-mineshaft-300 text-mineshaft-200"
98+ : "text-bunker-300"
99+ } `
100+ }
101+ >
102+ SSL ({ sslEnabled ? "Enabled" : "Disabled" } )
103+ </ Tab >
104+ </ Tab . List >
105+ < Tab . Panels className = "mb-4 rounded-sm border border-mineshaft-600 bg-mineshaft-700/70 p-3 pb-0" >
106+ < Tab . Panel >
107+ < div className = "mt-[0.675rem] flex items-start gap-2" >
108+ < Controller
109+ name = "connectionDetails.host"
110+ control = { control }
111+ render = { ( { field, fieldState : { error } } ) => (
112+ < FormControl
113+ className = "flex-1"
114+ errorText = { error ?. message }
115+ isError = { Boolean ( error ?. message ) }
116+ label = "Host"
117+ >
118+ < Input { ...field } />
119+ </ FormControl >
120+ ) }
121+ />
122+ < Controller
123+ name = "connectionDetails.port"
124+ control = { control }
125+ render = { ( { field, fieldState : { error } } ) => (
126+ < FormControl
127+ className = "w-28"
128+ errorText = { error ?. message }
129+ isError = { Boolean ( error ?. message ) }
130+ label = "Port"
131+ >
132+ < Input type = "number" { ...field } />
133+ </ FormControl >
134+ ) }
135+ />
136+ </ div >
137+ </ Tab . Panel >
138+ < Tab . Panel >
139+ < Controller
140+ name = "connectionDetails.sslEnabled"
141+ control = { control }
142+ render = { ( { field : { value, onChange } , fieldState : { error } } ) => (
143+ < FormControl isError = { Boolean ( error ?. message ) } errorText = { error ?. message } >
144+ < Switch
145+ className = "bg-mineshaft-400/50 shadow-inner data-[state=checked]:bg-green/80"
146+ id = "ssl-enabled"
147+ thumbClassName = "bg-mineshaft-800"
148+ isChecked = { value }
149+ onCheckedChange = { onChange }
150+ >
151+ Enable SSL
152+ </ Switch >
153+ </ FormControl >
154+ ) }
155+ />
156+ < Controller
157+ name = "connectionDetails.sslCertificate"
158+ control = { control }
159+ render = { ( { field, fieldState : { error } } ) => (
160+ < FormControl
161+ errorText = { error ?. message }
162+ isError = { Boolean ( error ?. message ) }
163+ className = { sslEnabled ? "" : "opacity-50" }
164+ label = "Trusted CA SSL Certificate"
165+ isOptional
166+ >
167+ < TextArea className = "h-14 resize-none!" { ...field } isDisabled = { ! sslEnabled } />
168+ </ FormControl >
169+ ) }
170+ />
171+ < Controller
172+ name = "connectionDetails.sslRejectUnauthorized"
173+ control = { control }
174+ render = { ( { field : { value, onChange } , fieldState : { error } } ) => (
175+ < FormControl
176+ className = { sslEnabled ? "" : "opacity-50" }
177+ isError = { Boolean ( error ?. message ) }
178+ errorText = { error ?. message }
179+ >
180+ < Switch
181+ className = "bg-mineshaft-400/50 shadow-inner data-[state=checked]:bg-green/80"
182+ id = "ssl-reject-unauthorized"
183+ thumbClassName = "bg-mineshaft-800"
184+ isChecked = { sslEnabled ? value : false }
185+ onCheckedChange = { onChange }
186+ isDisabled = { ! sslEnabled }
187+ >
188+ < p className = "w-38" >
189+ Reject Unauthorized
190+ < Tooltip
191+ className = "max-w-md"
192+ content = {
193+ < p >
194+ If enabled, Infisical will only connect to the server if it has a
195+ valid, trusted SSL certificate.
196+ </ p >
197+ }
198+ >
199+ < FontAwesomeIcon icon = { faQuestionCircle } size = "sm" className = "ml-1" />
200+ </ Tooltip >
201+ </ p >
202+ </ Switch >
203+ </ FormControl >
204+ ) }
205+ />
206+ </ Tab . Panel >
207+ </ Tab . Panels >
208+ </ Tab . Group >
70209 < div className = "mt-6 flex items-center" >
71210 < Button
72211 className = "mr-4"
0 commit comments