diff --git a/frontend/src/__mocks__/mockConnectionType.ts b/frontend/src/__mocks__/mockConnectionType.ts index 9731c3ad9b..988f9ae23e 100644 --- a/frontend/src/__mocks__/mockConnectionType.ts +++ b/frontend/src/__mocks__/mockConnectionType.ts @@ -23,7 +23,7 @@ export const mockConnectionTypeConfigMap = ( export const mockConnectionTypeConfigMapObj = ({ name = 'connection-type-sample', namespace = 'opendatahub', - displayName = name, + displayName = name.replace(/-/g, ' '), description = 'Connection type description', enabled = true, username = 'dashboard-admin', @@ -93,46 +93,66 @@ const mockFields: ConnectionTypeField[] = [ type: 'short-text', name: 'Short text 3', description: 'Test short text with default value and read only', - envVar: 'short-text-1', + envVar: 'short-text-3', required: false, properties: { defaultValue: 'This is the default value and is read only', defaultReadOnly: true, }, }, + { + type: 'short-text', + name: 'Short text 4', + description: 'Test short text with no default value and read only', + envVar: 'short-text-4', + required: false, + properties: { + defaultReadOnly: true, + }, + }, { type: 'section', - name: 'Paragraph', - description: 'This section contains paragraph fields.', + name: 'Text', + description: 'This section contains text fields.', }, { - type: 'paragraph', - name: 'Paragraph 1', - description: 'Test paragraph', - envVar: 'paragraph-1', + type: 'text', + name: 'Text 1', + description: 'Test text', + envVar: 'text-1', required: false, properties: {}, }, { - type: 'paragraph', - name: 'Paragraph 2', - description: 'Test paragraph with default value', - envVar: 'paragraph-2', + type: 'text', + name: 'Text 2', + description: 'Test text with default value', + envVar: 'text-2', required: true, properties: { - defaultValue: 'This is the default value', + defaultValue: 'This is the default value\nOne\nTwo\nThree\nFour', defaultReadOnly: false, }, }, { - type: 'paragraph', - name: 'Paragraph 3', - description: 'Test paragraph with default value and read only', - envVar: 'paragraph-3', + type: 'text', + name: 'Text 3', + description: 'Test text with default value and read only', + envVar: 'text-3', + required: false, + properties: { + defaultValue: 'This is the default value\nOne\nTwo\nThree\nFour', + defaultReadOnly: true, + }, + }, + { + type: 'text', + name: 'Text 4', + description: 'Test text with no default value and read only', + envVar: 'text-4', required: false, properties: { - defaultValue: 'This is the default value', defaultReadOnly: true, }, }, @@ -172,6 +192,16 @@ const mockFields: ConnectionTypeField[] = [ defaultReadOnly: true, }, }, + { + type: 'hidden', + name: 'Hidden 4', + description: 'Test hidden with no default value and read only', + envVar: 'hidden-4', + required: false, + properties: { + defaultReadOnly: true, + }, + }, { type: 'section', @@ -208,6 +238,16 @@ const mockFields: ConnectionTypeField[] = [ defaultReadOnly: true, }, }, + { + type: 'uri', + name: 'URI 4', + description: 'Test URI with no default value and read only', + envVar: 'uri-4', + required: false, + properties: { + defaultReadOnly: true, + }, + }, { type: 'section', @@ -244,6 +284,16 @@ const mockFields: ConnectionTypeField[] = [ defaultReadOnly: true, }, }, + { + type: 'file', + name: 'File 4', + description: 'Test file with no default value and read only', + envVar: 'file-4', + required: false, + properties: { + defaultReadOnly: true, + }, + }, { type: 'section', @@ -278,7 +328,18 @@ const mockFields: ConnectionTypeField[] = [ required: false, properties: { label: 'Input label', - defaultValue: false, + defaultValue: true, + defaultReadOnly: true, + }, + }, + { + type: 'boolean', + name: 'Boolean 4', + description: 'Test boolean with no default value and read only', + envVar: 'boolean-4', + required: false, + properties: { + label: 'Input label', defaultReadOnly: true, }, }, @@ -314,21 +375,31 @@ const mockFields: ConnectionTypeField[] = [ envVar: 'numeric-3', required: false, properties: { - defaultValue: 3, + defaultValue: 2, + defaultReadOnly: true, + }, + }, + { + type: 'numeric', + name: 'Numeric 4', + description: 'Test numeric with no default value and read only', + envVar: 'numeric-4', + required: false, + properties: { defaultReadOnly: true, }, }, { type: 'section', - name: 'Dropdown', - description: 'This section contains dropdown fields.', + name: 'Dropdown - single', + description: 'This section contains single variant dropdown fields.', }, { type: 'dropdown', - name: 'Dropdown 1', + name: 'Dropdown single 1', description: 'Test dropdown single variant', - envVar: 'dropdown-1', + envVar: 'dropdown-single-1', required: false, properties: { variant: 'single', @@ -342,7 +413,7 @@ const mockFields: ConnectionTypeField[] = [ }, { type: 'dropdown', - name: 'Dropdown 2', + name: 'Dropdown single 2', description: 'Test dropdown single variant with default value', envVar: 'dropdown-2', required: true, @@ -355,13 +426,55 @@ const mockFields: ConnectionTypeField[] = [ { value: '4', label: 'Four' }, ], defaultValue: ['3'], + defaultReadOnly: false, }, }, { type: 'dropdown', - name: 'Dropdown 3', - description: 'Test dropdown multi variant', + name: 'Dropdown single 3', + description: 'Test dropdown single variant with default value and read only', envVar: 'dropdown-3', + required: true, + properties: { + variant: 'single', + items: [ + { value: '1', label: 'One' }, + { value: '2', label: 'Two' }, + { value: '3', label: 'Three' }, + { value: '4', label: 'Four' }, + ], + defaultValue: ['3'], + defaultReadOnly: true, + }, + }, + { + type: 'dropdown', + name: 'Dropdown single 4', + description: 'Test dropdown single variant with no default value and read only', + envVar: 'dropdown-4', + required: true, + properties: { + variant: 'single', + items: [ + { value: '1', label: 'One' }, + { value: '2', label: 'Two' }, + { value: '3', label: 'Three' }, + { value: '4', label: 'Four' }, + ], + defaultReadOnly: true, + }, + }, + + { + type: 'section', + name: 'Dropdown - multi', + description: 'This section contains multi variant dropdown fields.', + }, + { + type: 'dropdown', + name: 'Dropdown multi 1', + description: 'Test dropdown multi variant', + envVar: 'dropdown-multi-1', required: false, properties: { variant: 'multi', @@ -375,9 +488,9 @@ const mockFields: ConnectionTypeField[] = [ }, { type: 'dropdown', - name: 'Dropdown 4', + name: 'Dropdown multi 2', description: 'Test dropdown multi variant with default values', - envVar: 'dropdown-4', + envVar: 'dropdown-multi-2', required: false, properties: { variant: 'multi', @@ -388,6 +501,42 @@ const mockFields: ConnectionTypeField[] = [ { value: '4', label: 'Four' }, ], defaultValue: ['2', '3'], + defaultReadOnly: false, + }, + }, + { + type: 'dropdown', + name: 'Dropdown multi 3', + description: 'Test dropdown multi variant with default values and read only', + envVar: 'dropdown-multi-3', + required: false, + properties: { + variant: 'multi', + items: [ + { value: '1', label: 'One' }, + { value: '2', label: 'Two' }, + { value: '3', label: 'Three' }, + { value: '4', label: 'Four' }, + ], + defaultValue: ['2', '3'], + defaultReadOnly: true, + }, + }, + { + type: 'dropdown', + name: 'Dropdown multi 4', + description: 'Test dropdown multi variant with no default values and read only', + envVar: 'dropdown-multi-4', + required: false, + properties: { + variant: 'multi', + items: [ + { value: '1', label: 'One' }, + { value: '2', label: 'Two' }, + { value: '3', label: 'Three' }, + { value: '4', label: 'Four' }, + ], + defaultReadOnly: true, }, }, ]; diff --git a/frontend/src/components/FormGroupText.scss b/frontend/src/components/FormGroupText.scss new file mode 100644 index 0000000000..80bc60b0b8 --- /dev/null +++ b/frontend/src/components/FormGroupText.scss @@ -0,0 +1,8 @@ +.odh-form-group-text { + // applies the same form element font size as overriden by App.scss + font-size: var(--pf-v5-global--FontSize--sm); + + @at-root pre#{&} { + font-family: var(--pf-v5-global--FontFamily--text); + } +} diff --git a/frontend/src/components/FormGroupText.tsx b/frontend/src/components/FormGroupText.tsx new file mode 100644 index 0000000000..bbea3a3a5a --- /dev/null +++ b/frontend/src/components/FormGroupText.tsx @@ -0,0 +1,17 @@ +import * as React from 'react'; + +import './FormGroupText.scss'; + +type Props = { + component?: 'div' | 'pre'; + children?: React.ReactNode; + id?: string; +}; + +const FormGroupText: React.FC = ({ component: Component = 'div', id, children }) => ( + + {children} + +); + +export default FormGroupText; diff --git a/frontend/src/components/NumberInputWrapper.tsx b/frontend/src/components/NumberInputWrapper.tsx index 34cbcd654e..e0373a0bc9 100644 --- a/frontend/src/components/NumberInputWrapper.tsx +++ b/frontend/src/components/NumberInputWrapper.tsx @@ -3,7 +3,7 @@ import { NumberInput } from '@patternfly/react-core'; type NumberInputWrapperProps = { onBlur?: (blurValue: number) => void; - onChange: (newValue: number) => void; + onChange?: (newValue: number) => void; } & Omit, 'onChange' | 'onPlus' | 'onMinus'>; const NumberInputWrapper: React.FC = ({ @@ -21,24 +21,28 @@ const NumberInputWrapper: React.FC = ({ max={max} validated={validated} value={value} - onChange={(e) => { - let v = parseInt(e.currentTarget.value); - if (min) { - v = Math.max(v, min); - } - if (max) { - v = Math.min(v, max); - } - onChange(v); - }} + onChange={ + onChange + ? (e) => { + let v = parseInt(e.currentTarget.value); + if (min) { + v = Math.max(v, min); + } + if (max) { + v = Math.min(v, max); + } + onChange(v); + } + : undefined + } onBlur={ onBlur && ((e) => { onBlur(parseInt(e.currentTarget.value)); }) } - onPlus={() => onChange((value || 0) + 1)} - onMinus={() => onChange((value || 0) - 1)} + onPlus={onChange ? () => onChange((value || 0) + 1) : undefined} + onMinus={onChange ? () => onChange((value || 0) - 1) : undefined} /> ); diff --git a/frontend/src/components/PasswordInput.tsx b/frontend/src/components/PasswordInput.tsx index 787cd66b72..0f16d8bf2c 100644 --- a/frontend/src/components/PasswordInput.tsx +++ b/frontend/src/components/PasswordInput.tsx @@ -2,7 +2,16 @@ import * as React from 'react'; import { Button, InputGroup, TextInput, InputGroupItem } from '@patternfly/react-core'; import { EyeIcon, EyeSlashIcon } from '@patternfly/react-icons'; -const PasswordInput: React.FC> = (props) => { +type Props = React.ComponentProps & { + ariaLabelShow?: string; + ariaLabelHide?: string; +}; + +const PasswordInput: React.FC = ({ + ariaLabelShow = 'Show password', + ariaLabelHide = 'Hide password', + ...props +}) => { const [isPasswordHidden, setPasswordHidden] = React.useState(true); return ( @@ -12,7 +21,7 @@ const PasswordInput: React.FC> = (props)