@@ -16,19 +16,49 @@ export const BigQueryForm: React.FC<IBigQueryFormProps> = ({ integrationId, exis
1616 const [ name , setName ] = React . useState ( existingConfig ?. name || '' ) ;
1717 const [ projectId , setProjectId ] = React . useState ( existingConfig ?. projectId || '' ) ;
1818 const [ credentials , setCredentials ] = React . useState ( existingConfig ?. credentials || '' ) ;
19+ const [ credentialsError , setCredentialsError ] = React . useState < string | null > ( null ) ;
1920
2021 // Update form fields when existingConfig changes
2122 React . useEffect ( ( ) => {
2223 if ( existingConfig ) {
2324 setName ( existingConfig . name || '' ) ;
2425 setProjectId ( existingConfig . projectId || '' ) ;
2526 setCredentials ( existingConfig . credentials || '' ) ;
27+ setCredentialsError ( null ) ;
2628 }
2729 } , [ existingConfig ] ) ;
2830
31+ const validateCredentials = ( value : string ) : boolean => {
32+ if ( ! value . trim ( ) ) {
33+ setCredentialsError ( null ) ;
34+ return false ;
35+ }
36+
37+ try {
38+ JSON . parse ( value ) ;
39+ setCredentialsError ( null ) ;
40+ return true ;
41+ } catch ( error ) {
42+ const errorMessage = error instanceof Error ? error . message : 'Invalid JSON format' ;
43+ setCredentialsError ( `Invalid JSON: ${ errorMessage } ` ) ;
44+ return false ;
45+ }
46+ } ;
47+
48+ const handleCredentialsChange = ( e : React . ChangeEvent < HTMLTextAreaElement > ) => {
49+ const value = e . target . value ;
50+ setCredentials ( value ) ;
51+ validateCredentials ( value ) ;
52+ } ;
53+
2954 const handleSubmit = ( e : React . FormEvent ) => {
3055 e . preventDefault ( ) ;
3156
57+ // Validate credentials before submitting
58+ if ( ! validateCredentials ( credentials ) ) {
59+ return ;
60+ }
61+
3262 const config : BigQueryIntegrationConfig = {
3363 id : integrationId ,
3464 name : name || integrationId ,
@@ -76,13 +106,22 @@ export const BigQueryForm: React.FC<IBigQueryFormProps> = ({ integrationId, exis
76106 < textarea
77107 id = "credentials"
78108 value = { credentials }
79- onChange = { ( e ) => setCredentials ( e . target . value ) }
109+ onChange = { handleCredentialsChange }
80110 placeholder = '{"type": "service_account", ...}'
81111 rows = { 10 }
82112 autoComplete = "off"
83113 spellCheck = { false }
114+ autoCorrect = "off"
115+ autoCapitalize = "off"
84116 required
117+ aria-invalid = { credentialsError ? 'true' : 'false' }
118+ aria-describedby = { credentialsError ? 'credentials-error' : undefined }
85119 />
120+ { credentialsError && (
121+ < div id = "credentials-error" className = "error-message" role = "alert" >
122+ { credentialsError }
123+ </ div >
124+ ) }
86125 </ div >
87126
88127 < div className = "form-actions" >
0 commit comments