|
| 1 | +import * as React from 'react'; |
| 2 | +import { |
| 3 | + Button, |
| 4 | + Form, |
| 5 | + FormGroup, |
| 6 | + HelperText, |
| 7 | + HelperTextItem, |
| 8 | + TextInput, |
| 9 | +} from '@patternfly/react-core'; |
| 10 | +import { Modal } from '@patternfly/react-core/deprecated'; |
| 11 | +import { useNavigate } from 'react-router'; |
| 12 | +import ModelRegistryCreateModalFooter from '~/app/pages/settings/ModelRegistryCreateModalFooter'; |
| 13 | +import FormSection from '~/shared/components/pf-overrides/FormSection'; |
| 14 | + |
| 15 | +import ModelRegistryDatabasePassword from '~/app/pages/settings/ModelRegistryDatabasePassword'; |
| 16 | +import K8sNameDescriptionField from '~/concepts/k8s/K8sNameDescriptionField/K8sNameDescriptionField'; |
| 17 | + |
| 18 | +type CreateModalProps = { |
| 19 | + onClose: () => void; |
| 20 | + // refresh: () => Promise<unknown>; |
| 21 | + // modelRegistry: ModelRegistry; |
| 22 | +}; |
| 23 | + |
| 24 | +const CreateModal: React.FC<CreateModalProps> = ({ |
| 25 | + onClose, |
| 26 | + // refresh, |
| 27 | + // modelRegistry, |
| 28 | +}) => { |
| 29 | + const [error, setError] = React.useState<Error>(); |
| 30 | + |
| 31 | + const [host, setHost] = React.useState(''); |
| 32 | + const [port, setPort] = React.useState(''); |
| 33 | + const [username, setUsername] = React.useState(''); |
| 34 | + const [password, setPassword] = React.useState(''); |
| 35 | + const [database, setDatabase] = React.useState(''); |
| 36 | + // const [addSecureDB, setAddSecureDB] = React.useState(false); |
| 37 | + const [isHostTouched, setIsHostTouched] = React.useState(false); |
| 38 | + const [isPortTouched, setIsPortTouched] = React.useState(false); |
| 39 | + const [isUsernameTouched, setIsUsernameTouched] = React.useState(false); |
| 40 | + const [isPasswordTouched, setIsPasswordTouched] = React.useState(false); |
| 41 | + const [isDatabaseTouched, setIsDatabaseTouched] = React.useState(false); |
| 42 | + const [showPassword, setShowPassword] = React.useState(false); |
| 43 | + |
| 44 | + const navigate = useNavigate(); |
| 45 | + |
| 46 | + const onBeforeClose = () => { |
| 47 | + // setIsSubmitting(false); |
| 48 | + setError(undefined); |
| 49 | + |
| 50 | + setHost(''); |
| 51 | + setPort(''); |
| 52 | + setUsername(''); |
| 53 | + setPassword(''); |
| 54 | + setDatabase(''); |
| 55 | + setIsHostTouched(false); |
| 56 | + setIsPortTouched(false); |
| 57 | + setIsUsernameTouched(false); |
| 58 | + setIsPasswordTouched(false); |
| 59 | + setIsDatabaseTouched(false); |
| 60 | + setShowPassword(false); |
| 61 | + onClose(); |
| 62 | + }; |
| 63 | + |
| 64 | + const hasContent = (value: string): boolean => !!value.trim().length; |
| 65 | + |
| 66 | + const canSubmit = () => |
| 67 | + // TODO: implement once we have the endpoint |
| 68 | + // !isSubmitting && |
| 69 | + // isValidK8sName(nameDesc.k8sName.value || translateDisplayNameForK8s(nameDesc.name)) |
| 70 | + // && |
| 71 | + hasContent(host) && |
| 72 | + hasContent(password) && |
| 73 | + hasContent(port) && |
| 74 | + hasContent(username) && |
| 75 | + hasContent(database); |
| 76 | + // && |
| 77 | + // (!addSecureDB || (secureDBInfo.isValid && !configSecretsError)) |
| 78 | + |
| 79 | + const onSubmit = () => { |
| 80 | + navigate(`/model-registry-settings`); |
| 81 | + onClose(); |
| 82 | + }; |
| 83 | + |
| 84 | + return ( |
| 85 | + <Modal |
| 86 | + isOpen |
| 87 | + title="Create model registry" |
| 88 | + onClose={onBeforeClose} |
| 89 | + actions={[ |
| 90 | + <Button key="create-button" variant="primary" isDisabled={!canSubmit()} onClick={onSubmit}> |
| 91 | + Create |
| 92 | + </Button>, |
| 93 | + <Button key="cancel-button" variant="secondary" onClick={onBeforeClose}> |
| 94 | + Cancel |
| 95 | + </Button>, |
| 96 | + ]} |
| 97 | + variant="medium" |
| 98 | + footer={ |
| 99 | + <ModelRegistryCreateModalFooter |
| 100 | + onCancel={onBeforeClose} |
| 101 | + onSubmit={onSubmit} |
| 102 | + submitLabel="Create" |
| 103 | + // isSubmitLoading={isSubmitting} |
| 104 | + isSubmitDisabled={!canSubmit()} |
| 105 | + error={error} |
| 106 | + alertTitle={`Error ${'creating'} model registry`} |
| 107 | + /> |
| 108 | + } |
| 109 | + > |
| 110 | + <Form> |
| 111 | + <K8sNameDescriptionField |
| 112 | + dataTestId="mr" |
| 113 | + // data={nameDesc} |
| 114 | + // onDataChange={setNameDesc} |
| 115 | + /> |
| 116 | + <FormSection |
| 117 | + title="Connect to external MySQL database" |
| 118 | + description="This external database is where model data is stored." |
| 119 | + > |
| 120 | + <FormGroup label="Host" isRequired fieldId="mr-host"> |
| 121 | + <TextInput |
| 122 | + isRequired |
| 123 | + type="text" |
| 124 | + id="mr-host" |
| 125 | + name="mr-host" |
| 126 | + value={host} |
| 127 | + onBlur={() => setIsHostTouched(true)} |
| 128 | + onChange={(_e, value) => setHost(value)} |
| 129 | + validated={isHostTouched && !hasContent(host) ? 'error' : 'default'} |
| 130 | + /> |
| 131 | + {isHostTouched && !hasContent(host) && ( |
| 132 | + <HelperText> |
| 133 | + <HelperTextItem variant="error" data-testid="mr-host-error"> |
| 134 | + Host cannot be empty |
| 135 | + </HelperTextItem> |
| 136 | + </HelperText> |
| 137 | + )} |
| 138 | + </FormGroup> |
| 139 | + <FormGroup label="Port" isRequired fieldId="mr-port"> |
| 140 | + <TextInput |
| 141 | + isRequired |
| 142 | + type="text" |
| 143 | + id="mr-port" |
| 144 | + name="mr-port" |
| 145 | + value={port} |
| 146 | + onBlur={() => setIsPortTouched(true)} |
| 147 | + onChange={(_e, value) => setPort(value)} |
| 148 | + validated={isPortTouched && !hasContent(port) ? 'error' : 'default'} |
| 149 | + /> |
| 150 | + {isPortTouched && !hasContent(port) && ( |
| 151 | + <HelperText> |
| 152 | + <HelperTextItem variant="error" data-testid="mr-port-error"> |
| 153 | + Port cannot be empty |
| 154 | + </HelperTextItem> |
| 155 | + </HelperText> |
| 156 | + )} |
| 157 | + </FormGroup> |
| 158 | + <FormGroup label="Username" isRequired fieldId="mr-username"> |
| 159 | + <TextInput |
| 160 | + isRequired |
| 161 | + type="text" |
| 162 | + id="mr-username" |
| 163 | + name="mr-username" |
| 164 | + value={username} |
| 165 | + onBlur={() => setIsUsernameTouched(true)} |
| 166 | + onChange={(_e, value) => setUsername(value)} |
| 167 | + validated={isUsernameTouched && !hasContent(username) ? 'error' : 'default'} |
| 168 | + /> |
| 169 | + {isUsernameTouched && !hasContent(username) && ( |
| 170 | + <HelperText> |
| 171 | + <HelperTextItem variant="error" data-testid="mr-username-error"> |
| 172 | + Username cannot be empty |
| 173 | + </HelperTextItem> |
| 174 | + </HelperText> |
| 175 | + )} |
| 176 | + </FormGroup> |
| 177 | + <FormGroup label="Password" isRequired fieldId="mr-password"> |
| 178 | + <ModelRegistryDatabasePassword |
| 179 | + password={password || ''} |
| 180 | + setPassword={setPassword} |
| 181 | + isPasswordTouched={isPasswordTouched} |
| 182 | + setIsPasswordTouched={setIsPasswordTouched} |
| 183 | + showPassword={showPassword} |
| 184 | + // editRegistry={mr} |
| 185 | + /> |
| 186 | + </FormGroup> |
| 187 | + <FormGroup label="Database" isRequired fieldId="mr-database"> |
| 188 | + <TextInput |
| 189 | + isRequired |
| 190 | + type="text" |
| 191 | + id="mr-database" |
| 192 | + name="mr-database" |
| 193 | + value={database} |
| 194 | + onBlur={() => setIsDatabaseTouched(true)} |
| 195 | + onChange={(_e, value) => setDatabase(value)} |
| 196 | + validated={isDatabaseTouched && !hasContent(database) ? 'error' : 'default'} |
| 197 | + /> |
| 198 | + {isDatabaseTouched && !hasContent(database) && ( |
| 199 | + <HelperText> |
| 200 | + <HelperTextItem variant="error" data-testid="mr-database-error"> |
| 201 | + Database cannot be empty |
| 202 | + </HelperTextItem> |
| 203 | + </HelperText> |
| 204 | + )} |
| 205 | + </FormGroup> |
| 206 | + {/* {secureDbEnabled && ( |
| 207 | + <> |
| 208 | + <FormGroup> |
| 209 | + <Checkbox |
| 210 | + label="Add CA certificate to secure database connection" |
| 211 | + isChecked={addSecureDB} |
| 212 | + onChange={(_e, value) => setAddSecureDB(value)} |
| 213 | + id="add-secure-db" |
| 214 | + data-testid="add-secure-db-mr-checkbox" |
| 215 | + name="add-secure-db" |
| 216 | + /> |
| 217 | + </FormGroup> |
| 218 | + {addSecureDB && |
| 219 | + (!configSecretsLoaded && !configSecretsError ? ( |
| 220 | + <EmptyState icon={Spinner} /> |
| 221 | + ) : configSecretsLoaded ? ( |
| 222 | + <CreateMRSecureDBSection |
| 223 | + secureDBInfo={secureDBInfo} |
| 224 | + modelRegistryNamespace={modelRegistryNamespace} |
| 225 | + k8sName={nameDesc.k8sName.value} |
| 226 | + existingCertConfigMaps={configSecrets.configMaps} |
| 227 | + existingCertSecrets={configSecrets.secrets} |
| 228 | + setSecureDBInfo={setSecureDBInfo} |
| 229 | + /> |
| 230 | + ) : ( |
| 231 | + <Alert |
| 232 | + isInline |
| 233 | + variant="danger" |
| 234 | + title="Error fetching config maps and secrets" |
| 235 | + data-testid="error-fetching-resource-alert" |
| 236 | + > |
| 237 | + {configSecretsError?.message} |
| 238 | + </Alert> |
| 239 | + ))} |
| 240 | + </> |
| 241 | + )} */} |
| 242 | + </FormSection> |
| 243 | + </Form> |
| 244 | + </Modal> |
| 245 | + ); |
| 246 | +}; |
| 247 | + |
| 248 | +export default CreateModal; |
0 commit comments