This is an automated email from the ASF dual-hosted git repository.

rusackas pushed a commit to branch SO-164
in repository https://gitbox.apache.org/repos/asf/superset.git

commit 29a001140af62dca088b1266b34efd52403dcd99
Author: Isaac Jaynes <[email protected]>
AuthorDate: Thu Dec 11 13:36:09 2025 -0800

    SO-164: Added validation to db credential input
---
 .../src/components/Form/LabeledErrorBoundInput.tsx | 10 +++++
 .../superset-ui-core/src/components/Form/types.ts  |  2 +
 .../DatabaseConnectionForm/EncryptedField.tsx      | 49 ++++++++++++++--------
 .../src/features/databases/DatabaseModal/styles.ts | 25 ++++++-----
 4 files changed, 55 insertions(+), 31 deletions(-)

diff --git 
a/superset-frontend/packages/superset-ui-core/src/components/Form/LabeledErrorBoundInput.tsx
 
b/superset-frontend/packages/superset-ui-core/src/components/Form/LabeledErrorBoundInput.tsx
index 2095cca2f03..5d23490f9b1 100644
--- 
a/superset-frontend/packages/superset-ui-core/src/components/Form/LabeledErrorBoundInput.tsx
+++ 
b/superset-frontend/packages/superset-ui-core/src/components/Form/LabeledErrorBoundInput.tsx
@@ -28,6 +28,10 @@ const StyledInput = styled(Input)`
   margin: ${({ theme }) => `${theme.sizeUnit}px 0 ${theme.sizeUnit * 2}px`};
 `;
 
+const StyledTextArea = styled(Input.TextArea)`
+  margin: ${({ theme }) => `${theme.sizeUnit}px 0 ${theme.sizeUnit * 2}px`};
+`;
+
 const StyledInputPassword = styled(Input.Password)`
   margin: ${({ theme }) => `${theme.sizeUnit}px 0 ${theme.sizeUnit * 2}px`};
 `;
@@ -98,6 +102,12 @@ export const LabeledErrorBoundInput = ({
             }
             role="textbox"
           />
+        ) : props.renderAsTextArea ? (
+          <StyledTextArea
+            css={props.textAreaCss}
+            {...props}
+            {...validationMethods}
+          />
         ) : (
           <StyledInput {...props} {...validationMethods} />
         )}
diff --git 
a/superset-frontend/packages/superset-ui-core/src/components/Form/types.ts 
b/superset-frontend/packages/superset-ui-core/src/components/Form/types.ts
index ffff65dc35a..be9fc7e2268 100644
--- a/superset-frontend/packages/superset-ui-core/src/components/Form/types.ts
+++ b/superset-frontend/packages/superset-ui-core/src/components/Form/types.ts
@@ -31,5 +31,7 @@ export interface LabeledErrorBoundInputProps {
   classname?: string;
   visibilityToggle?: boolean;
   isValidating?: boolean;
+  renderAsTextArea?: boolean;
+  textAreaCss?: any;
   [x: string]: any;
 }
diff --git 
a/superset-frontend/src/features/databases/DatabaseModal/DatabaseConnectionForm/EncryptedField.tsx
 
b/superset-frontend/src/features/databases/DatabaseModal/DatabaseConnectionForm/EncryptedField.tsx
index 5c1eec0a302..e4a3edd5a8e 100644
--- 
a/superset-frontend/src/features/databases/DatabaseModal/DatabaseConnectionForm/EncryptedField.tsx
+++ 
b/superset-frontend/src/features/databases/DatabaseModal/DatabaseConnectionForm/EncryptedField.tsx
@@ -20,17 +20,21 @@ import { useState, useEffect } from 'react';
 import { t } from '@apache-superset/core/translation';
 import { SupersetTheme } from '@apache-superset/core/theme';
 import {
-  Input,
   Button,
   FormLabel,
   Select,
   Upload,
   type UploadFile,
+  LabeledErrorBoundInput as ValidatedInput,
 } from '@superset-ui/core/components';
 import { Icons } from '@superset-ui/core/components/Icons';
 import { useToasts } from 'src/components/MessageToasts/withToasts';
 import { DatabaseParameters, Engines, FieldPropTypes } from '../../types';
-import { infoTooltip, CredentialInfoForm } from '../styles';
+import {
+  infoTooltip,
+  CredentialInfoForm,
+  CredentialInfoFormTextArea,
+} from '../styles';
 
 enum CredentialInfoOptions {
   JsonUpload,
@@ -53,6 +57,9 @@ export const EncryptedField = ({
   editNewDb,
   isPublic = true,
   setIsPublic,
+  isValidating,
+  validationErrors,
+  getValidation,
 }: FieldPropTypes) => {
   const [fileList, setFileList] = useState<UploadFile[]>([]);
   const [uploadOption, setUploadOption] = useState<number>(
@@ -168,22 +175,27 @@ export const EncryptedField = ({
       (uploadOption === CredentialInfoOptions.CopyPaste ||
         isEditMode ||
         editNewDb) ? (
-        <div className="input-container">
-          <FormLabel>{t('Service Account')}</FormLabel>
-          <Input.TextArea
-            className="input-form"
-            name={encryptedField}
-            value={
-              typeof encryptedValue === 'boolean'
-                ? String(encryptedValue)
-                : encryptedValue
-            }
-            onChange={changeMethods.onParametersChange}
-            placeholder={t(
-              'Paste content of service credentials JSON file here',
-            )}
-          />
-        </div>
+        <ValidatedInput
+          id={encryptedField}
+          name={encryptedField}
+          required={false}
+          isValidating={isValidating}
+          value={
+            typeof encryptedValue === 'boolean'
+              ? String(encryptedValue)
+              : encryptedValue
+          }
+          validationMethods={{ onBlur: getValidation }}
+          errorMessage={validationErrors?.query}
+          placeholder={t('Paste content of service credentials JSON file 
here')}
+          label={t('Service Account')}
+          onChange={changeMethods.onParametersChange}
+          helpText={t('Add service credentials')}
+          renderAsTextArea
+          textAreaCss={(theme: SupersetTheme) =>
+            CredentialInfoFormTextArea(theme)
+          }
+        />
       ) : (
         showCredentialsInfo && (
           <div
@@ -220,6 +232,7 @@ export const EncryptedField = ({
                       },
                     });
                     setFileList(info.fileList);
+                    getValidation();
                   } catch {
                     setFileList([]);
                     addDangerToast(
diff --git a/superset-frontend/src/features/databases/DatabaseModal/styles.ts 
b/superset-frontend/src/features/databases/DatabaseModal/styles.ts
index 6e065acebb6..545d5182078 100644
--- a/superset-frontend/src/features/databases/DatabaseModal/styles.ts
+++ b/superset-frontend/src/features/databases/DatabaseModal/styles.ts
@@ -383,6 +383,18 @@ export const EditHeaderSubtitle = styled.div`
   font-weight: ${({ theme }) => theme.fontWeightStrong};
 `;
 
+export const CredentialInfoFormTextArea = (theme: SupersetTheme) => css`
+  height: 100px;
+  width: 100%;
+  border: 1px solid ${theme.colorBorder};
+  border-radius: ${theme.borderRadius}px;
+  resize: vertical;
+  padding: ${theme.sizeUnit * 1.5}px ${theme.sizeUnit * 2}px;
+  &::placeholder {
+    color: ${theme.colorTextPlaceholder};
+  }
+`;
+
 export const CredentialInfoForm = styled.div`
   margin-top: ${({ theme }) => theme.sizeUnit * 4}px;
 
@@ -413,19 +425,6 @@ export const CredentialInfoForm = styled.div`
     margin: ${({ theme }) => theme.sizeUnit * 4}px 0;
     display: flex;
     flex-direction: column;
-}
-  }
-  .input-form {
-    height: 100px;
-    width: 100%;
-    border: 1px solid ${({ theme }) => theme.colorBorder};
-    border-radius: ${({ theme }) => theme.borderRadius}px;
-    resize: vertical;
-    padding: ${({ theme }) => theme.sizeUnit * 1.5}px
-      ${({ theme }) => theme.sizeUnit * 2}px;
-    &::placeholder {
-      color: ${({ theme }) => theme.colorTextPlaceholder};
-    }
   }
 
   .input-container {

Reply via email to