diff --git a/clients/ui/frontend/src/app/app.css b/clients/ui/frontend/src/app/app.css index 06f062d46b..c66c6942e5 100644 --- a/clients/ui/frontend/src/app/app.css +++ b/clients/ui/frontend/src/app/app.css @@ -3,3 +3,13 @@ body, #root { height: 100%; } + +.toolbar-fieldset-wrapper { + flex: 1 1 0; + min-width: 0; +} + +.toolbar-fieldset-wrapper > .pf-v6-c-input-group__item:not(.pf-m-search-action) { + flex: 1 1 0; + min-width: 0; +} diff --git a/clients/ui/frontend/src/app/pages/modelCatalogSettings/components/SourceDetailsSection.tsx b/clients/ui/frontend/src/app/pages/modelCatalogSettings/components/SourceDetailsSection.tsx index 0e01a56fe6..b21ba39763 100644 --- a/clients/ui/frontend/src/app/pages/modelCatalogSettings/components/SourceDetailsSection.tsx +++ b/clients/ui/frontend/src/app/pages/modelCatalogSettings/components/SourceDetailsSection.tsx @@ -9,8 +9,7 @@ import { Flex, FlexItem, } from '@patternfly/react-core'; -import { UpdateObjectAtPropAndValue } from 'mod-arch-shared'; -import FormFieldset from '~/app/pages/modelRegistry/screens/components/FormFieldset'; +import { UpdateObjectAtPropAndValue, ThemeAwareFormGroupWrapper } from 'mod-arch-shared'; import FormSection from '~/app/pages/modelRegistry/components/pf-overrides/FormSection'; import { ManageSourceFormData } from '~/app/pages/modelCatalogSettings/useManageSourceData'; import { @@ -55,24 +54,31 @@ const SourceDetailsSection: React.FC = ({ /> ); + const nameHelperTextNode = hasNameError ? ( + + + + {isSourceNameEmpty(formData.name) + ? VALIDATION_MESSAGES.NAME_REQUIRED + : formData.name.length > SOURCE_NAME_CHARACTER_LIMIT + ? `Cannot exceed ${SOURCE_NAME_CHARACTER_LIMIT} characters` + : null} + + + + ) : undefined; + return ( - - - {hasNameError && ( - - - - {isSourceNameEmpty(formData.name) - ? VALIDATION_MESSAGES.NAME_REQUIRED - : formData.name.length > SOURCE_NAME_CHARACTER_LIMIT - ? `Cannot exceed ${SOURCE_NAME_CHARACTER_LIMIT} characters` - : null} - - - - )} - + + {nameInput} + = ({ isRequired fieldId="yaml-content" > - + {isMUITheme ? : yamlInput} {yamlHelperTxtNode} diff --git a/clients/ui/frontend/src/app/pages/modelRegistry/screens/RegisterModel/PrefilledModelRegistryField.tsx b/clients/ui/frontend/src/app/pages/modelRegistry/screens/RegisterModel/PrefilledModelRegistryField.tsx index d16cfcad0e..99999dd41f 100644 --- a/clients/ui/frontend/src/app/pages/modelRegistry/screens/RegisterModel/PrefilledModelRegistryField.tsx +++ b/clients/ui/frontend/src/app/pages/modelRegistry/screens/RegisterModel/PrefilledModelRegistryField.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { FormGroup, TextInput } from '@patternfly/react-core'; -import FormFieldset from '~/app/pages/modelRegistry/screens/components/FormFieldset'; +import { TextInput } from '@patternfly/react-core'; +import { ThemeAwareFormGroupWrapper } from 'mod-arch-shared'; type PrefilledModelRegistryFieldProps = { mrName?: string; @@ -12,9 +12,14 @@ const PrefilledModelRegistryField: React.FC = ); return ( - - - + + {mrNameInput} + ); }; diff --git a/clients/ui/frontend/src/app/pages/modelRegistry/screens/RegisterModel/RegisterModelDetailsFormSection.tsx b/clients/ui/frontend/src/app/pages/modelRegistry/screens/RegisterModel/RegisterModelDetailsFormSection.tsx index 65fe626aef..b10bdfe97f 100644 --- a/clients/ui/frontend/src/app/pages/modelRegistry/screens/RegisterModel/RegisterModelDetailsFormSection.tsx +++ b/clients/ui/frontend/src/app/pages/modelRegistry/screens/RegisterModel/RegisterModelDetailsFormSection.tsx @@ -7,8 +7,12 @@ import { TextInput, } from '@patternfly/react-core'; import React from 'react'; -import { UpdateObjectAtPropAndValue } from 'mod-arch-shared'; -import FormFieldset from '~/app/pages/modelRegistry/screens/components/FormFieldset'; +import { + UpdateObjectAtPropAndValue, + FormFieldset, + ThemeAwareFormGroupWrapper, +} from 'mod-arch-shared'; +import { useThemeContext } from 'mod-arch-kubeflow'; import FormSection from '~/app/pages/modelRegistry/components/pf-overrides/FormSection'; import { MR_CHARACTER_LIMIT } from './const'; import RegisterModelTypeField from './RegisterModelTypeField'; @@ -32,6 +36,8 @@ const RegisterModelDetailsFormSection = ({ isModelTypeRequired = false, isModelTypeReadOnly = false, }: RegisterModelDetailsFormSectionProp): React.ReactNode => { + const { isMUITheme } = useThemeContext(); + const modelNameInput = ( ({ /> ); + const modelNameHelperTextNode = hasModelNameError ? ( + + + + {isModelNameDuplicate + ? 'Model name already exists' + : `Cannot exceed ${MR_CHARACTER_LIMIT} characters`} + + + + ) : undefined; + + const modelDescriptionHelperTextNode = ( + + + Enter a brief summary of the model's key details. + + + ); + return ( - - - {hasModelNameError && ( - - - - {isModelNameDuplicate - ? 'Model name already exists' - : `Cannot exceed ${MR_CHARACTER_LIMIT} characters`} - - - - )} - + + {modelNameInput} + - - - - Enter a brief summary of the model's key details. - - + {isMUITheme ? ( + + ) : ( + modelDescriptionInput + )} + {modelDescriptionHelperTextNode} = ({ }; return ( - - - } + + - + ); }; diff --git a/clients/ui/frontend/src/app/pages/modelRegistry/screens/RegisterModel/RegisteredModelSelector.tsx b/clients/ui/frontend/src/app/pages/modelRegistry/screens/RegisterModel/RegisteredModelSelector.tsx index 0ee96a0aa0..396fe31e9f 100644 --- a/clients/ui/frontend/src/app/pages/modelRegistry/screens/RegisterModel/RegisteredModelSelector.tsx +++ b/clients/ui/frontend/src/app/pages/modelRegistry/screens/RegisterModel/RegisteredModelSelector.tsx @@ -1,9 +1,8 @@ import React from 'react'; -import { FormGroup, TextInput } from '@patternfly/react-core'; -import { TypeaheadSelect } from 'mod-arch-shared'; +import { TextInput } from '@patternfly/react-core'; +import { ThemeAwareFormGroupWrapper, TypeaheadSelect } from 'mod-arch-shared'; import { TypeaheadSelectOption } from 'mod-arch-shared/dist/components/TypeaheadSelect'; import { RegisteredModel } from '~/app/types'; -import FormFieldset from '~/app/pages/modelRegistry/screens/components/FormFieldset'; type RegisteredModelSelectorProps = { registeredModels: RegisteredModel[]; @@ -46,9 +45,14 @@ const RegisteredModelSelector: React.FC = ({ See related PatternFly issue https://github.com/patternfly/patternfly-react/issues/10842 */ return ( - - - + + {modelNameInput} + ); } diff --git a/clients/ui/frontend/src/app/pages/modelRegistry/screens/RegisterModel/RegistrationCommonFormSections.tsx b/clients/ui/frontend/src/app/pages/modelRegistry/screens/RegisterModel/RegistrationCommonFormSections.tsx index 11cb37aaba..744c2aba7a 100644 --- a/clients/ui/frontend/src/app/pages/modelRegistry/screens/RegisterModel/RegistrationCommonFormSections.tsx +++ b/clients/ui/frontend/src/app/pages/modelRegistry/screens/RegisterModel/RegistrationCommonFormSections.tsx @@ -11,10 +11,12 @@ import { ToggleGroupItem, } from '@patternfly/react-core'; import spacing from '@patternfly/react-styles/css/utilities/Spacing/spacing'; -import { UpdateObjectAtPropAndValue } from 'mod-arch-shared'; -// import { DataConnection, UpdateObjectAtPropAndValue } from '~/pages/projects/types'; -// import { convertAWSSecretData } from '~/pages/projects/screens/detail/data-connections/utils'; -import FormFieldset from '~/app/pages/modelRegistry/screens/components/FormFieldset'; +import { + UpdateObjectAtPropAndValue, + FormFieldset, + ThemeAwareFormGroupWrapper, +} from 'mod-arch-shared'; +import { useThemeContext } from 'mod-arch-kubeflow'; import { ModelVersion } from '~/app/types'; import FormSection from '~/app/pages/modelRegistry/components/pf-overrides/FormSection'; import { RegistrationMode } from '~/app/pages/modelRegistry/screens/const'; @@ -23,7 +25,6 @@ import RegistrationModelLocationFields from './RegistrationModelLocationFields'; import RegisterAndStoreFields from './RegisterAndStoreFields'; import { isNameValid, isOciUri } from './utils'; import { MR_CHARACTER_LIMIT } from './const'; -// import { ConnectionModal } from './ConnectionModal'; type RegistrationCommonFormSectionsProps = { formData: D; @@ -50,6 +51,7 @@ const RegistrationCommonFormSections = ({ namespaceCannotCheck, registryName, }: RegistrationCommonFormSectionsProps): React.ReactNode => { + const { isMUITheme } = useThemeContext(); const isVersionNameValid = isNameValid(formData.versionName); const registrationMode = formData.registrationMode || RegistrationMode.Register; @@ -122,6 +124,21 @@ const RegistrationCommonFormSections = ({ /> ); + const versionNameHelperTextNode = latestVersion ? ( + + + Current version is {latestVersion.name} + + {!isVersionNameValid && ( + + + Cannot exceed {MR_CHARACTER_LIMIT} characters + + + )} + + ) : undefined; + return ( <> ({ : 'Configure details for the version of this model.' } > - - - {latestVersion && ( - - - Current version is {latestVersion.name} - - {!isVersionNameValid && ( - - - Cannot exceed {MR_CHARACTER_LIMIT} characters - - - )} - - )} - + + {versionNameInput} + - - - - - - - + {isMUITheme ? ( + + ) : ( + versionDescriptionInput + )} + + {sourceModelFormatInput} + + + {sourceModelFormatVersionInput} + = { @@ -67,18 +66,18 @@ const RegistrationDestinationLocationFields = - - - - - - - - - - - - + + {ociRegistryInput} + + + {ociUriInput} + + + {ociUsernameInput} + + + {ociPasswordInput} + ); }; diff --git a/clients/ui/frontend/src/app/pages/modelRegistry/screens/RegisterModel/RegistrationModelLocationFields.tsx b/clients/ui/frontend/src/app/pages/modelRegistry/screens/RegisterModel/RegistrationModelLocationFields.tsx index 52af4cd4de..4ecedda74e 100644 --- a/clients/ui/frontend/src/app/pages/modelRegistry/screens/RegisterModel/RegistrationModelLocationFields.tsx +++ b/clients/ui/frontend/src/app/pages/modelRegistry/screens/RegisterModel/RegistrationModelLocationFields.tsx @@ -1,17 +1,8 @@ import React from 'react'; -import { - FormGroup, - TextInput, - Radio, - HelperText, - HelperTextItem, - TextInputGroupMain, - TextInputGroup, -} from '@patternfly/react-core'; +import { TextInput, Radio, TextInputGroupMain, TextInputGroup } from '@patternfly/react-core'; import spacing from '@patternfly/react-styles/css/utilities/Spacing/spacing'; -import { UpdateObjectAtPropAndValue } from 'mod-arch-shared'; +import { UpdateObjectAtPropAndValue, ThemeAwareFormGroupWrapper } from 'mod-arch-shared'; import PasswordInput from '~/app/shared/components/PasswordInput'; -import FormFieldset from '~/app/pages/modelRegistry/screens/components/FormFieldset'; import { ModelLocationType, RegistrationCommonFormData } from './useRegisterModelData'; type RegistrationModelLocationFieldsProps = { @@ -116,6 +107,10 @@ const RegistrationModelLocationFields = ({ /> ); + const pathHelperTextNode = ( + Enter a path to a model or folder. This path cannot point to a root folder. + ); + return ( <> ({ /> {modelLocationType === ModelLocationType.ObjectStorage && ( <> - - - - - - - - - - + + {bucketInput} + + + {regionInput} + + - - - - Enter a path to a model or folder. This path cannot point to a root folder. - - - + {pathInput} + {includeCredentialFields && ( <> - - - - + - - + {s3SecretAccessKeyInput} + )} @@ -189,11 +189,14 @@ const RegistrationModelLocationFields = ({ id="location-type-uri" /> {modelLocationType === ModelLocationType.URI && ( - <> - - - - + + {uriInput} + )} ); diff --git a/clients/ui/frontend/src/app/pages/modelRegistry/screens/components/FormFieldset.scss b/clients/ui/frontend/src/app/pages/modelRegistry/screens/components/FormFieldset.scss deleted file mode 100644 index dacb608533..0000000000 --- a/clients/ui/frontend/src/app/pages/modelRegistry/screens/components/FormFieldset.scss +++ /dev/null @@ -1,9 +0,0 @@ -.toolbar-fieldset-wrapper { - flex: 1 1 0; - min-width: 0; - - > .pf-v6-c-input-group__item:not(.pf-m-search-action) { - flex: 1 1 0; - min-width: 0; - } -} \ No newline at end of file diff --git a/clients/ui/frontend/src/app/pages/modelRegistry/screens/components/FormFieldset.tsx b/clients/ui/frontend/src/app/pages/modelRegistry/screens/components/FormFieldset.tsx deleted file mode 100644 index 431e8ede89..0000000000 --- a/clients/ui/frontend/src/app/pages/modelRegistry/screens/components/FormFieldset.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { useThemeContext } from 'mod-arch-kubeflow'; -import React, { CSSProperties, ReactNode } from 'react'; -import './FormFieldset.scss'; - -interface FormFieldsetProps { - component: ReactNode; - field?: string; - className?: string; - fieldsetStyle?: CSSProperties; -} - -const FormFieldset: React.FC = ({ - component, - field, - className, - fieldsetStyle, -}) => { - const { isMUITheme } = useThemeContext(); - - if (!isMUITheme) { - return <>{component}; - } - - return ( -
- {component} - -
- ); -}; - -export default FormFieldset; diff --git a/clients/ui/frontend/src/app/pages/modelRegistry/screens/components/ModelPropertiesTableRow.tsx b/clients/ui/frontend/src/app/pages/modelRegistry/screens/components/ModelPropertiesTableRow.tsx index aac582a6df..5730855907 100644 --- a/clients/ui/frontend/src/app/pages/modelRegistry/screens/components/ModelPropertiesTableRow.tsx +++ b/clients/ui/frontend/src/app/pages/modelRegistry/screens/components/ModelPropertiesTableRow.tsx @@ -11,8 +11,8 @@ import { } from '@patternfly/react-core'; import { CheckIcon, ExternalLinkAltIcon, TimesIcon } from '@patternfly/react-icons'; import { KeyValuePair, EitherNotBoth } from 'mod-arch-core'; +import { FormFieldset } from 'mod-arch-shared'; import { useThemeContext } from 'mod-arch-kubeflow'; -import FormFieldset from '~/app/pages/modelRegistry/screens/components/FormFieldset'; import { isValidHttpUrl } from '~/app/pages/modelRegistry/screens/utils'; import useDeletePropertiesModalAvailability from '~/app/hooks/useDeletePropertiesModalAvailability'; import DeletePropertiesModal from './DeletePropertiesModal'; diff --git a/clients/ui/frontend/src/concepts/k8s/K8sNameDescriptionField/K8sNameDescriptionField.tsx b/clients/ui/frontend/src/concepts/k8s/K8sNameDescriptionField/K8sNameDescriptionField.tsx index 5d3b4e8b30..4b6aa0cae7 100644 --- a/clients/ui/frontend/src/concepts/k8s/K8sNameDescriptionField/K8sNameDescriptionField.tsx +++ b/clients/ui/frontend/src/concepts/k8s/K8sNameDescriptionField/K8sNameDescriptionField.tsx @@ -7,8 +7,9 @@ import { TextArea, TextInput, } from '@patternfly/react-core'; +import { FormFieldset, ThemeAwareFormGroupWrapper } from 'mod-arch-shared'; +import { useThemeContext } from 'mod-arch-kubeflow'; import ResourceNameDefinitionTooltip from '~/concepts/k8s/ResourceNameDefinitionTooltip'; -import FormFieldset from '~/app/pages/modelRegistry/screens/components/FormFieldset'; import { K8sNameDescriptionFieldData, K8sNameDescriptionFieldUpdateFunction, @@ -56,6 +57,7 @@ const K8sNameDescriptionField: React.FC = ({ nameHelperText, hideDescription, }) => { + const { isMUITheme } = useThemeContext(); const [showK8sField, setShowK8sField] = React.useState(false); const { name, description, k8sName } = data; @@ -86,36 +88,43 @@ const K8sNameDescriptionField: React.FC = ({ /> ); + const nameHelperTextNode = + nameHelperText || (!showK8sField && !k8sName.state.immutable) ? ( + + {nameHelperText && {nameHelperText}} + {!showK8sField && !k8sName.state.immutable && ( + <> + {k8sName.value && ( + + The resource name will be {k8sName.value}. + + )} + + {' '} + + + + )} + + ) : null; + return ( <> - - - {nameHelperText || (!showK8sField && !k8sName.state.immutable) ? ( - - {nameHelperText && {nameHelperText}} - {!showK8sField && !k8sName.state.immutable && ( - <> - {k8sName.value && ( - - The resource name will be {k8sName.value}. - - )} - - {' '} - - - - )} - - ) : null} - + + {nameInput} + = ({ {!hideDescription && ( - + {isMUITheme ? ( + + ) : ( + descriptionTextArea + )} )} diff --git a/clients/ui/frontend/src/concepts/k8s/K8sNameDescriptionField/ResourceNameField.tsx b/clients/ui/frontend/src/concepts/k8s/K8sNameDescriptionField/ResourceNameField.tsx index 51929c26fa..1148c7dc91 100644 --- a/clients/ui/frontend/src/concepts/k8s/K8sNameDescriptionField/ResourceNameField.tsx +++ b/clients/ui/frontend/src/concepts/k8s/K8sNameDescriptionField/ResourceNameField.tsx @@ -1,12 +1,6 @@ import * as React from 'react'; -import { - FormGroup, - HelperText, - HelperTextItem, - TextInput, - ValidatedOptions, -} from '@patternfly/react-core'; -import FormFieldset from '~/app/pages/modelRegistry/screens/components/FormFieldset'; +import { HelperText, HelperTextItem, TextInput, ValidatedOptions } from '@patternfly/react-core'; +import { ThemeAwareFormGroupWrapper } from 'mod-arch-shared'; import { K8sNameDescriptionFieldData, K8sNameDescriptionFieldUpdateFunction } from './types'; type ResourceNameFieldProps = { @@ -25,9 +19,9 @@ const ResourceNameField: React.FC = ({ }) => { if (k8sName.state.immutable) { return ( - - {k8sName.value}} field="Resource name" /> - + +
{k8sName.value}
+
); } @@ -56,36 +50,39 @@ const ResourceNameField: React.FC = ({ /> ); + const helperTextNode = ( + + {k8sName.state.invalidLength && ( + + Cannot exceed {k8sName.state.maxLength} characters + + )} + {k8sName.state.invalidCharacters && ( + + Must start and end with a lowercase letter or number. Valid characters include lowercase + letters, numbers, and hyphens (-). + + )} + {!k8sName.state.invalidLength && !k8sName.state.invalidCharacters && ( + + The resource name is used to identify your resource, and is generated based on the name + you enter. The resource name cannot be edited after creation. + + )} + + ); + return ( - <> - - - - - {k8sName.state.invalidLength && ( - - Cannot exceed {k8sName.state.maxLength} characters - - )} - {k8sName.state.invalidCharacters && ( - - Must start and end with a lowercase letter or number. Valid characters include lowercase - letters, numbers, and hyphens (-). - - )} - {!k8sName.state.invalidLength && !k8sName.state.invalidCharacters && ( - - The resource name is used to identify your resource, and is generated based on the name - you enter. The resource name cannot be edited after creation. - - )} - - + + {textInput} + ); };