This is an automated email from the ASF dual-hosted git repository. hugh pushed a commit to branch hugh-validation-db-modal-bg in repository https://gitbox.apache.org/repos/asf/superset.git
commit 5e029e081365fec74e66d8966f4d05b3f053614f Author: Elizabeth Thompson <[email protected]> AuthorDate: Fri May 21 10:57:08 2021 -0700 use new validation component --- superset-frontend/src/components/Form/FormItem.tsx | 4 + .../src/components/Form/LabeledErrorBoundInput.tsx | 12 +- .../DatabaseModal/DatabaseConnectionForm.tsx | 193 +++++++++++---------- .../CRUD/data/database/DatabaseModal/index.tsx | 2 +- .../CRUD/data/database/DatabaseModal/styles.ts | 14 +- 5 files changed, 124 insertions(+), 101 deletions(-) diff --git a/superset-frontend/src/components/Form/FormItem.tsx b/superset-frontend/src/components/Form/FormItem.tsx index ab301a8..2731a21 100644 --- a/superset-frontend/src/components/Form/FormItem.tsx +++ b/superset-frontend/src/components/Form/FormItem.tsx @@ -41,6 +41,10 @@ const StyledItem = styled(Form.Item)` } } } + .ant-form-item-explain { + color: ${theme.colors.grayscale.light1}; + font-size: ${theme.typography.sizes.s - 1}px; + } `} `; diff --git a/superset-frontend/src/components/Form/LabeledErrorBoundInput.tsx b/superset-frontend/src/components/Form/LabeledErrorBoundInput.tsx index 8569b55..c8663a6 100644 --- a/superset-frontend/src/components/Form/LabeledErrorBoundInput.tsx +++ b/superset-frontend/src/components/Form/LabeledErrorBoundInput.tsx @@ -31,6 +31,7 @@ export interface LabeledErrorBoundInputProps { helpText?: string; required?: boolean; id?: string; + classname?: string; [x: string]: any; } @@ -60,6 +61,12 @@ const alertIconStyles = (theme: SupersetTheme, hasError: boolean) => css` } }`} `; +const StyledFormGroup = styled('div')` + margin-bottom: ${({ theme }) => theme.gridUnit * 6}px; + .ant-form-item { + margin-bottom: 0; + } +`; const LabeledErrorBoundInput = ({ label, @@ -68,9 +75,10 @@ const LabeledErrorBoundInput = ({ helpText, required = false, id, + className, ...props }: LabeledErrorBoundInputProps) => ( - <> + <StyledFormGroup className={className}> <FormLabel htmlFor={id} required={required}> {label} </FormLabel> @@ -83,7 +91,7 @@ const LabeledErrorBoundInput = ({ > <StyledInput {...props} {...validationMethods} /> </FormItem> - </> + </StyledFormGroup> ); export default LabeledErrorBoundInput; diff --git a/superset-frontend/src/views/CRUD/data/database/DatabaseModal/DatabaseConnectionForm.tsx b/superset-frontend/src/views/CRUD/data/database/DatabaseModal/DatabaseConnectionForm.tsx index f0542e4..1eeab48 100644 --- a/superset-frontend/src/views/CRUD/data/database/DatabaseModal/DatabaseConnectionForm.tsx +++ b/superset-frontend/src/views/CRUD/data/database/DatabaseModal/DatabaseConnectionForm.tsx @@ -17,11 +17,14 @@ * under the License. */ import React, { FormEvent } from 'react'; -import cx from 'classnames'; +import { SupersetTheme } from '@superset-ui/core'; import { InputProps } from 'antd/lib/input'; -import { FormLabel, FormItem } from 'src/components/Form'; -import { Input } from 'src/common/components'; -import { StyledFormHeader, formScrollableStyles } from './styles'; +import ValidatedInput from 'src/components/Form/LabeledErrorBoundInput'; +import { + StyledFormHeader, + formScrollableStyles, + validatedFormStyles, +} from './styles'; import { DatabaseForm } from '../types'; export const FormFieldOrder = [ @@ -33,58 +36,91 @@ export const FormFieldOrder = [ 'database_name', ]; -const CHANGE_METHOD = { - onChange: 'onChange', - onPropertiesChange: 'onPropertiesChange', -}; +interface FieldPropTypes { + required: boolean; + changeMethods: { onPropertiesChange: (value: any) => string } & { + onChange: (value: any) => string; + }; +} + +const hostField = ({ required, changeMethods }: FieldPropTypes) => ( + <ValidatedInput + id="host" + required={required} + validationMethods={{ onBlur: () => '' }} + errorMessage="" + placeholder="e.g. 127.0.0.1" + className="form-group-w-50" + label="Host" + onChange={changeMethods.onPropertiesChange} + /> +); +const portField = ({ required, changeMethods }: FieldPropTypes) => ( + <ValidatedInput + id="host" + required={required} + validationMethods={{ onBlur: () => '' }} + errorMessage="" + placeholder="e.g. 5432" + className="form-group-w-50" + label="Port" + onChange={changeMethods.onPropertiesChange} + /> +); +const databaseField = ({ required, changeMethods }: FieldPropTypes) => ( + <ValidatedInput + id="host" + required={required} + validationMethods={{ onBlur: () => '' }} + errorMessage="" + placeholder="e.g. world_population" + label="Database name" + onChange={changeMethods.onPropertiesChange} + helpText="Copy the name of the PostgreSQL database you are trying to connect to." + /> +); +const usernameField = ({ required, changeMethods }: FieldPropTypes) => ( + <ValidatedInput + id="host" + required={required} + validationMethods={{ onBlur: () => '' }} + errorMessage="" + placeholder="e.g. Analytics" + label="Username" + onChange={changeMethods.onPropertiesChange} + /> +); +const passwordField = ({ required, changeMethods }: FieldPropTypes) => ( + <ValidatedInput + id="host" + required={required} + validationMethods={{ onBlur: () => '' }} + errorMessage="" + placeholder="e.g. ********" + label="Password" + onChange={changeMethods.onPropertiesChange} + /> +); +const displayField = ({ required, changeMethods }: FieldPropTypes) => ( + <ValidatedInput + id="host" + required={required} + validationMethods={{ onBlur: () => '' }} + errorMessage="" + placeholder="e.g. ********" + label="Display Name" + onChange={changeMethods.onChange} + helpText="Pick a nickname for this database to display as in Superset." + /> +); const FORM_FIELD_MAP = { - host: { - description: 'Host', - type: 'text', - className: 'w-50', - placeholder: 'e.g. 127.0.0.1', - changeMethod: CHANGE_METHOD.onPropertiesChange, - }, - port: { - description: 'Port', - type: 'text', - className: 'w-50', - placeholder: 'e.g. 5432', - changeMethod: CHANGE_METHOD.onPropertiesChange, - }, - database: { - description: 'Database name', - type: 'text', - label: - 'Copy the name of the PostgreSQL database you are trying to connect to.', - placeholder: 'e.g. world_population', - changeMethod: CHANGE_METHOD.onPropertiesChange, - }, - username: { - description: 'Username', - type: 'text', - placeholder: 'e.g. Analytics', - changeMethod: CHANGE_METHOD.onPropertiesChange, - }, - password: { - description: 'Password', - type: 'text', - placeholder: 'e.g. ********', - changeMethod: CHANGE_METHOD.onPropertiesChange, - }, - database_name: { - description: 'Display Name', - type: 'text', - label: 'Pick a nickname for this database to display as in Superset.', - changeMethod: CHANGE_METHOD.onChange, - }, - query: { - additionalProperties: {}, - description: 'Additional parameters', - type: 'object', - changeMethod: CHANGE_METHOD.onPropertiesChange, - }, + host: hostField, + port: portField, + database: databaseField, + username: usernameField, + password: passwordField, + database_name: displayField, }; const DatabaseConnectionForm = ({ @@ -107,48 +143,23 @@ const DatabaseConnectionForm = ({ Need help? Learn more about connecting to {name}. </p> </StyledFormHeader> - <div css={formScrollableStyles}> + <div + css={(theme: SupersetTheme) => [ + formScrollableStyles, + validatedFormStyles(theme), + ]} + > {parameters && FormFieldOrder.filter( (key: string) => Object.keys(parameters.properties).includes(key) || key === 'database_name', - ).map(field => { - const { - className, - description, - type, - placeholder, - label, - changeMethod, - } = FORM_FIELD_MAP[field]; - const onEdit = - changeMethod === CHANGE_METHOD.onChange - ? onChange - : onParametersChange; - return ( - <FormItem - className={cx(className, `form-group-${className}`)} - key={field} - > - <FormLabel - htmlFor={field} - required={parameters.required.includes(field)} - > - {description} - </FormLabel> - <Input - name={field} - type={type} - id={field} - autoComplete="off" - placeholder={placeholder} - onChange={onEdit} - /> - <p className="helper">{label}</p> - </FormItem> - ); - })} + ).map(field => + FORM_FIELD_MAP[field]({ + required: parameters.required.includes(field), + changeMethods: { onParametersChange, onChange }, + }), + )} </div> </> ); diff --git a/superset-frontend/src/views/CRUD/data/database/DatabaseModal/index.tsx b/superset-frontend/src/views/CRUD/data/database/DatabaseModal/index.tsx index 5cecee7..e7be206 100644 --- a/superset-frontend/src/views/CRUD/data/database/DatabaseModal/index.tsx +++ b/superset-frontend/src/views/CRUD/data/database/DatabaseModal/index.tsx @@ -297,7 +297,7 @@ const DatabaseModal: FunctionComponent<DatabaseModalProps> = ({ type: ActionType.dbSelected, payload: { parameters: { engine: 'postgresql' }, - configuration_method: CONFIGURATION_METHOD.SQLALCHEMY_URI, + configuration_method: CONFIGURATION_METHOD.DYNAMIC_FORM, }, // todo hook this up to step 1 }); } diff --git a/superset-frontend/src/views/CRUD/data/database/DatabaseModal/styles.ts b/superset-frontend/src/views/CRUD/data/database/DatabaseModal/styles.ts index 8c33756..d9afc22 100644 --- a/superset-frontend/src/views/CRUD/data/database/DatabaseModal/styles.ts +++ b/superset-frontend/src/views/CRUD/data/database/DatabaseModal/styles.ts @@ -164,13 +164,6 @@ export const formStyles = (theme: SupersetTheme) => css` margin-left: ${theme.gridUnit * 8}px; } } - .text-danger { - color: ${theme.colors.error.base}; - font-size: ${theme.typography.sizes.s - 1}px; - strong { - font-weight: normal; - } - } } .control-label { color: ${theme.colors.grayscale.dark1}; @@ -191,6 +184,13 @@ export const formStyles = (theme: SupersetTheme) => css` } `; +export const validatedFormStyles = (theme: SupersetTheme) => css` + label { + color: ${theme.colors.grayscale.dark1}; + font-size: ${theme.typography.sizes.s - 1}px; + } +`; + export const StyledInputContainer = styled.div` margin-bottom: ${({ theme }) => theme.gridUnit * 6}px; &.mb-0 {
