1+ import { IconAlertTriangle } from "@tabler/icons-react" ;
2+ import { useQueryClient } from "@tanstack/react-query" ;
13import EasyModal , { type InnerModalProps } from "ez-modal-react" ;
2- import { Form , Formik } from "formik" ;
4+ import { Field , Form , Formik } from "formik" ;
35import { type ReactNode , useState } from "react" ;
46import { Alert } from "react-bootstrap" ;
57import Modal from "react-bootstrap/Modal" ;
6- import { Button , DomainNamesField } from "src/components " ;
7- import { useSetProxyHost } from "src/hooks " ;
8+ import { type Certificate , createCertificate , uploadCertificate , validateCertificate } from "src/api/backend " ;
9+ import { Button } from "src/components " ;
810import { T } from "src/locale" ;
11+ import { validateString } from "src/modules/Validations" ;
912import { showObjectSuccess } from "src/notifications" ;
1013
1114const showCustomCertificateModal = ( ) => {
1215 EasyModal . show ( CustomCertificateModal ) ;
1316} ;
1417
1518const CustomCertificateModal = EasyModal . create ( ( { visible, remove } : InnerModalProps ) => {
16- const { mutate : setProxyHost } = useSetProxyHost ( ) ;
19+ const queryClient = useQueryClient ( ) ;
1720 const [ errorMsg , setErrorMsg ] = useState < ReactNode | null > ( null ) ;
1821 const [ isSubmitting , setIsSubmitting ] = useState ( false ) ;
1922
@@ -22,25 +25,47 @@ const CustomCertificateModal = EasyModal.create(({ visible, remove }: InnerModal
2225 setIsSubmitting ( true ) ;
2326 setErrorMsg ( null ) ;
2427
25- setProxyHost ( values , {
26- onError : ( err : any ) => setErrorMsg ( < T id = { err . message } /> ) ,
27- onSuccess : ( ) => {
28- showObjectSuccess ( "certificate" , "saved" ) ;
29- remove ( ) ;
30- } ,
31- onSettled : ( ) => {
32- setIsSubmitting ( false ) ;
33- setSubmitting ( false ) ;
34- } ,
35- } ) ;
28+ try {
29+ const { niceName, provider, certificate, certificateKey, intermediateCertificate } = values ;
30+ const formData = new FormData ( ) ;
31+
32+ formData . append ( "certificate" , certificate ) ;
33+ formData . append ( "certificate_key" , certificateKey ) ;
34+ if ( intermediateCertificate !== null ) {
35+ formData . append ( "intermediate_certificate" , intermediateCertificate ) ;
36+ }
37+
38+ // Validate
39+ await validateCertificate ( formData ) ;
40+
41+ // Create certificate, as other without anything else
42+ const cert = await createCertificate ( { niceName, provider } as Certificate ) ;
43+
44+ // Upload the certificates to the created certificate
45+ await uploadCertificate ( cert . id , formData ) ;
46+
47+ // Success
48+ showObjectSuccess ( "certificate" , "saved" ) ;
49+ remove ( ) ;
50+ } catch ( err : any ) {
51+ setErrorMsg ( < T id = { err . message } /> ) ;
52+ }
53+
54+ queryClient . invalidateQueries ( { queryKey : [ "certificates" ] } ) ;
55+ setIsSubmitting ( false ) ;
56+ setSubmitting ( false ) ;
3657 } ;
3758
3859 return (
3960 < Modal show = { visible } onHide = { remove } >
4061 < Formik
4162 initialValues = {
4263 {
43- domainNames : [ ] ,
64+ niceName : "" ,
65+ provider : "other" ,
66+ certificate : null ,
67+ certificateKey : null ,
68+ intermediateCertificate : null ,
4469 } as any
4570 }
4671 onSubmit = { onSubmit }
@@ -49,17 +74,136 @@ const CustomCertificateModal = EasyModal.create(({ visible, remove }: InnerModal
4974 < Form >
5075 < Modal . Header closeButton >
5176 < Modal . Title >
52- < T id = "object.add" tData = { { object : "certificate " } } />
77+ < T id = "object.add" tData = { { object : "lets-encrypt-via-dns " } } />
5378 </ Modal . Title >
5479 </ Modal . Header >
5580 < Modal . Body className = "p-0" >
5681 < Alert variant = "danger" show = { ! ! errorMsg } onClose = { ( ) => setErrorMsg ( null ) } dismissible >
5782 { errorMsg }
5883 </ Alert >
5984 < div className = "card m-0 border-0" >
60- < div className = "card-header" > asd</ div >
6185 < div className = "card-body" >
62- < DomainNamesField />
86+ < p className = "text-warning" >
87+ < IconAlertTriangle size = { 16 } className = "me-1" />
88+ < T id = "certificates.custom.warning" />
89+ </ p >
90+ < Field name = "niceName" validate = { validateString ( 1 , 255 ) } >
91+ { ( { field, form } : any ) => (
92+ < div className = "mb-3" >
93+ < label htmlFor = "niceName" className = "form-label" >
94+ < T id = "column.name" />
95+ </ label >
96+ < input
97+ id = "niceName"
98+ type = "text"
99+ required
100+ autoComplete = "off"
101+ className = "form-control"
102+ { ...field }
103+ />
104+ { form . errors . niceName ? (
105+ < div className = "invalid-feedback" >
106+ { form . errors . niceName && form . touched . niceName
107+ ? form . errors . niceName
108+ : null }
109+ </ div >
110+ ) : null }
111+ </ div >
112+ ) }
113+ </ Field >
114+ < Field name = "certificateKey" >
115+ { ( { field, form } : any ) => (
116+ < div className = "mb-3" >
117+ < label htmlFor = "certificateKey" className = "form-label" >
118+ < T id = "certificate.custom-certificate-key" />
119+ </ label >
120+ < input
121+ id = "certificateKey"
122+ type = "file"
123+ required
124+ autoComplete = "off"
125+ className = "form-control"
126+ onChange = { ( event ) => {
127+ form . setFieldValue (
128+ field . name ,
129+ event . currentTarget . files ?. length
130+ ? event . currentTarget . files [ 0 ]
131+ : null ,
132+ ) ;
133+ } }
134+ />
135+ { form . errors . certificateKey ? (
136+ < div className = "invalid-feedback" >
137+ { form . errors . certificateKey && form . touched . certificateKey
138+ ? form . errors . certificateKey
139+ : null }
140+ </ div >
141+ ) : null }
142+ </ div >
143+ ) }
144+ </ Field >
145+ < Field name = "certificate" >
146+ { ( { field, form } : any ) => (
147+ < div className = "mb-3" >
148+ < label htmlFor = "certificate" className = "form-label" >
149+ < T id = "certificate.custom-certificate" />
150+ </ label >
151+ < input
152+ id = "certificate"
153+ type = "file"
154+ required
155+ autoComplete = "off"
156+ className = "form-control"
157+ onChange = { ( event ) => {
158+ form . setFieldValue (
159+ field . name ,
160+ event . currentTarget . files ?. length
161+ ? event . currentTarget . files [ 0 ]
162+ : null ,
163+ ) ;
164+ } }
165+ />
166+ { form . errors . certificate ? (
167+ < div className = "invalid-feedback" >
168+ { form . errors . certificate && form . touched . certificate
169+ ? form . errors . certificate
170+ : null }
171+ </ div >
172+ ) : null }
173+ </ div >
174+ ) }
175+ </ Field >
176+ < Field name = "intermediateCertificate" >
177+ { ( { field, form } : any ) => (
178+ < div className = "mb-3" >
179+ < label htmlFor = "intermediateCertificate" className = "form-label" >
180+ < T id = "certificate.custom-intermediate" />
181+ </ label >
182+ < input
183+ id = "intermediateCertificate"
184+ type = "file"
185+ autoComplete = "off"
186+ className = "form-control"
187+ onChange = { ( event ) => {
188+ form . setFieldValue (
189+ field . name ,
190+ event . currentTarget . files ?. length
191+ ? event . currentTarget . files [ 0 ]
192+ : null ,
193+ ) ;
194+ } }
195+ />
196+ { form . errors . intermediateCertificate ? (
197+ < div className = "invalid-feedback" >
198+ { form . errors . intermediateCertificate &&
199+ form . touched . intermediateCertificate
200+ ? form . errors . intermediateCertificate
201+ : null }
202+ </ div >
203+ ) : null }
204+ </ div >
205+ ) }
206+ </ Field >
63207 </ div >
64208 </ div >
65209 </ Modal . Body >
@@ -70,7 +214,7 @@ const CustomCertificateModal = EasyModal.create(({ visible, remove }: InnerModal
70214 < Button
71215 type = "submit"
72216 actionType = "primary"
73- className = "ms-auto bg-lime "
217+ className = "ms-auto bg-pink "
74218 data-bs-dismiss = "modal"
75219 isLoading = { isSubmitting }
76220 disabled = { isSubmitting }
0 commit comments