Skip to content

Commit 7cb1b95

Browse files
committed
fixing input and dropdown issues
1 parent 74e0332 commit 7cb1b95

File tree

9 files changed

+74
-31
lines changed

9 files changed

+74
-31
lines changed

frontend/src/pages/modelServing/screens/global/ServeModelButton.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,8 @@ const ServeModelButton: React.FC = () => {
105105
projectContext={{
106106
currentProject: project,
107107
connections,
108-
pvcs: pvcs.data,
109108
}}
109+
pvcs={pvcs.data}
110110
servingRuntimeTemplates={templatesEnabled.filter((template) =>
111111
getTemplateEnabledForPlatform(template, ServingRuntimePlatform.SINGLE),
112112
)}

frontend/src/pages/modelServing/screens/projects/DeployPrefilledModelModal.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,8 @@ const DeployPrefilledModelModalContents: React.FC<
180180
projectContext={{
181181
currentProject: selectedProject,
182182
connections,
183-
pvcs: pvcs.data,
184183
}}
184+
pvcs={pvcs.data}
185185
projectSection={projectSection}
186186
existingUriOption={
187187
modelDeployPrefillInfo.modelArtifactUri &&

frontend/src/pages/modelServing/screens/projects/InferenceServiceModal/ConnectionSection.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ type Props = {
245245
loaded?: boolean;
246246
loadError?: Error | undefined;
247247
connections?: LabeledConnection[];
248-
pvcs?: PersistentVolumeClaimKind[] | [];
248+
pvcs?: PersistentVolumeClaimKind[];
249249
connectionTypeFilter?: (ct: ConnectionTypeConfigMapObj) => boolean;
250250
};
251251

@@ -271,7 +271,6 @@ export const ConnectionSection: React.FC<Props> = ({
271271
// eslint-disable-next-line react-hooks/exhaustive-deps
272272
[modelServingConnectionTypes],
273273
);
274-
275274
const hasImagePullSecret = React.useMemo(() => !!data.imagePullSecrets, [data.imagePullSecrets]);
276275
const pvcServingEnabled = useIsAreaAvailable(SupportedArea.PVCSERVING).status;
277276
const selectedConnection = React.useMemo(
@@ -323,8 +322,7 @@ export const ConnectionSection: React.FC<Props> = ({
323322
});
324323
}}
325324
body={
326-
data.storage.type === InferenceServiceStorageType.PVC_STORAGE &&
327-
pvcs && (
325+
data.storage.type === InferenceServiceStorageType.PVC_STORAGE && (
328326
<PvcSelect
329327
pvcs={pvcs}
330328
setModelUri={(uri) => setData('storage', { ...data.storage, uri })}

frontend/src/pages/modelServing/screens/projects/InferenceServiceModal/PVCFields.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
InputGroup,
88
} from '@patternfly/react-core';
99
import { PersistentVolumeClaimKind } from '#~/k8sTypes';
10+
import { trimInputOnBlur, trimInputOnPaste } from '#~/concepts/connectionTypes/utils';
1011

1112
type PVCFieldsProps = {
1213
selectedPVC: PersistentVolumeClaimKind;
@@ -20,14 +21,20 @@ export const PVCFields: React.FC<PVCFieldsProps> = ({ selectedPVC, setModelUri,
2021
<InputGroupText>pvc://{selectedPVC.metadata.name}/</InputGroupText>
2122
<InputGroupItem isFill>
2223
<TextInput
23-
id="model-path"
24+
id="pvc-model-path"
2425
aria-label="Model path"
25-
data-testid="model-path"
26+
data-testid="pvc-model-path"
2627
type="text"
2728
value={modelPath ?? ''}
2829
isRequired
2930
onChange={(e, value: string) => {
30-
setModelUri(`pvc://${selectedPVC.metadata.name}/${value}`);
31+
setModelUri(value.trim());
32+
}}
33+
onBlur={() => {
34+
trimInputOnBlur(modelPath, setModelUri);
35+
}}
36+
onPaste={() => {
37+
trimInputOnPaste(modelPath, setModelUri);
3138
}}
3239
/>
3340
</InputGroupItem>

frontend/src/pages/modelServing/screens/projects/InferenceServiceModal/PVCSelect.tsx

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ type PvcSelectProps = {
1818
setIsConnectionValid: (isValid: boolean) => void;
1919
modelUri?: string;
2020
};
21+
2122
export const PvcSelect: React.FC<PvcSelectProps> = ({
2223
pvcs,
2324
selectedPVC,
@@ -26,12 +27,43 @@ export const PvcSelect: React.FC<PvcSelectProps> = ({
2627
setIsConnectionValid,
2728
modelUri,
2829
}) => {
30+
const [modelPath, setModelPath] = React.useState('');
31+
const lastPVCNameRef = React.useRef<string | undefined>();
32+
33+
React.useEffect(() => {
34+
if (selectedPVC && selectedPVC.metadata.name !== lastPVCNameRef.current) {
35+
const { modelPath: annotatedPath } = getModelServingPVCAnnotations(selectedPVC);
36+
const path = annotatedPath ?? '';
37+
setModelPath(path);
38+
setModelUri(generateModelUri(selectedPVC.metadata.name, path));
39+
lastPVCNameRef.current = selectedPVC.metadata.name;
40+
} else if (!selectedPVC) {
41+
setModelPath('');
42+
setModelUri('');
43+
lastPVCNameRef.current = undefined;
44+
}
45+
}, [selectedPVC, setModelUri]);
46+
47+
const handleModelPathChange = (newPath: string): void => {
48+
setModelPath(newPath);
49+
if (selectedPVC) {
50+
setModelUri(generateModelUri(selectedPVC.metadata.name, newPath));
51+
}
52+
};
53+
54+
const generateModelUri = (pvcName: string, path: string): string => `pvc://${pvcName}/${path}`;
55+
56+
React.useEffect(() => {
57+
const isValidPVCUri = (uri: string): boolean => /^pvc:\/\/[a-z0-9-]+\/\S+$/.test(uri);
58+
setIsConnectionValid(!!selectedPVC && isValidPVCUri(modelUri ?? ''));
59+
}, [selectedPVC, modelUri, setIsConnectionValid]);
60+
2961
const options: TypeaheadSelectOption[] = React.useMemo(
3062
() =>
3163
pvcs?.map((pvc) => {
3264
const displayName = getDisplayNameFromK8sResource(pvc);
33-
const { modelPath, modelName } = getModelServingPVCAnnotations(pvc);
34-
const isModelServingPVC = !!modelPath || !!modelName;
65+
const { modelPath: modelPathAnnotation, modelName } = getModelServingPVCAnnotations(pvc);
66+
const isModelServingPVC = !!modelPathAnnotation || !!modelName;
3567
return {
3668
content: displayName,
3769
value: pvc.metadata.name,
@@ -49,23 +81,9 @@ export const PvcSelect: React.FC<PvcSelectProps> = ({
4981
}) || [],
5082
[pvcs, selectedPVC],
5183
);
84+
5285
const accessMode = selectedPVC ? getModelServingPVCAccessMode(selectedPVC) : undefined;
53-
const { modelPath } = React.useMemo(() => {
54-
if (selectedPVC) {
55-
const { modelPath: selectedModelPath, modelName: selectedModelName } =
56-
getModelServingPVCAnnotations(selectedPVC);
57-
return {
58-
modelPath: selectedModelPath ?? undefined,
59-
modelName: selectedModelName ?? undefined,
60-
};
61-
}
62-
return { modelPath: undefined, modelName: undefined };
63-
}, [selectedPVC]);
64-
const isValidPVCUri = (uri: string): boolean => /^pvc:\/\/[a-z0-9-]+\/\S+$/.test(uri);
6586

66-
React.useEffect(() => {
67-
setIsConnectionValid(!!selectedPVC && isValidPVCUri(modelUri ?? ''));
68-
}, [selectedPVC, modelPath, modelUri, setIsConnectionValid]);
6987
return (
7088
<FormGroup label="Cluster storage" isRequired>
7189
<Stack hasGutter>
@@ -91,7 +109,11 @@ export const PvcSelect: React.FC<PvcSelectProps> = ({
91109
)}
92110
{selectedPVC && (
93111
<StackItem>
94-
<PVCFields selectedPVC={selectedPVC} setModelUri={setModelUri} modelPath={modelPath} />
112+
<PVCFields
113+
selectedPVC={selectedPVC}
114+
modelPath={modelPath}
115+
setModelUri={handleModelPathChange}
116+
/>
95117
</StackItem>
96118
)}
97119
</Stack>

frontend/src/pages/modelServing/screens/projects/KServeSection/KServeInferenceServiceTable.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ const KServeInferenceServiceTable: React.FC = () => {
4242
},
4343
serverSecrets: { refresh: refreshServerSecrets },
4444
filterTokens,
45+
pvcs: { data: pvcs },
4546
} = React.useContext(ProjectDetailsContext);
4647
const columns = getKServeInferenceServiceColumns();
4748

@@ -96,6 +97,7 @@ const KServeInferenceServiceTable: React.FC = () => {
9697
editKserveResources.inferenceService.spec.predictor.model?.runtime,
9798
),
9899
}}
100+
pvcs={pvcs}
99101
onClose={(submit: boolean) => {
100102
setEditKServeResources(undefined);
101103
if (submit) {

frontend/src/pages/modelServing/screens/projects/ModelServingPlatform.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,8 @@ const ModelServingPlatform: React.FC = () => {
210210

211211
return (
212212
<ManageKServeModal
213-
projectContext={{ currentProject, connections, pvcs }}
213+
projectContext={{ currentProject, connections }}
214+
pvcs={pvcs}
214215
servingRuntimeTemplates={templatesEnabled.filter((template) =>
215216
getTemplateEnabledForPlatform(template, ServingRuntimePlatform.SINGLE),
216217
)}

frontend/src/pages/modelServing/screens/projects/kServeModal/ManageKServeModal.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ import usePrefillModelDeployModal, {
6666
import { useKServeDeploymentMode } from '#~/pages/modelServing/useKServeDeploymentMode';
6767
import { SERVING_RUNTIME_SCOPE } from '#~/pages/modelServing/screens/const';
6868
import { useModelDeploymentNotification } from '#~/pages/modelServing/screens/projects/useModelDeploymentNotification';
69+
import { getDashboardPvcs } from '#~/api/k8s/pvcs';
6970
import KServeAutoscalerReplicaSection from './KServeAutoscalerReplicaSection';
7071
import EnvironmentVariablesSection from './EnvironmentVariablesSection';
7172
import ServingRuntimeArgsSection from './ServingRuntimeArgsSection';
@@ -85,12 +86,12 @@ type ManageKServeModalProps = {
8586
shouldFormHidden?: boolean;
8687
projectSection?: React.ReactNode;
8788
existingUriOption?: string;
89+
pvcs?: PersistentVolumeClaimKind[] | [];
8890
} & EitherOrNone<
8991
{
9092
projectContext?: {
9193
currentProject: ProjectKind;
9294
connections: Connection[];
93-
pvcs: PersistentVolumeClaimKind[] | [];
9495
};
9596
},
9697
{
@@ -105,6 +106,7 @@ type ManageKServeModalProps = {
105106
const ManageKServeModal: React.FC<ManageKServeModalProps> = ({
106107
onClose,
107108
servingRuntimeTemplates,
109+
pvcs,
108110
projectContext,
109111
editInfo,
110112
projectSection,
@@ -141,6 +143,16 @@ const ManageKServeModal: React.FC<ManageKServeModalProps> = ({
141143
const namespace = currentProjectName || createDataInferenceService.project;
142144

143145
const projectTemplates = useTemplates(namespace);
146+
const [fallbackPvcs, setFallbackPvcs] = React.useState<PersistentVolumeClaimKind[]>([]);
147+
React.useEffect(() => {
148+
getDashboardPvcs(namespace)
149+
.then((data) => {
150+
setFallbackPvcs(data.filter((pvc) => pvc.metadata.namespace === namespace));
151+
})
152+
.catch(() => {
153+
setFallbackPvcs([]);
154+
});
155+
}, [namespace]);
144156

145157
const customServingRuntimesEnabled = useCustomServingRuntimesEnabled();
146158
const [allowCreate] = useAccessReview({
@@ -475,7 +487,7 @@ const ManageKServeModal: React.FC<ManageKServeModalProps> = ({
475487
setConnection={setConnection}
476488
setIsConnectionValid={setIsConnectionValid}
477489
connections={connections}
478-
pvcs={projectContext?.pvcs}
490+
pvcs={pvcs?.length && pvcs.length > 0 ? pvcs : fallbackPvcs}
479491
/>
480492
</FormSection>
481493
)}

frontend/src/pages/projects/screens/detail/overview/serverModels/AddModelFooter.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ const AddModelFooter: React.FC<AddModelFooterProps> = ({ selectedPlatform, isNIM
106106
) : null}
107107
{modalShown && !isProjectModelMesh && !isNIM ? (
108108
<ManageKServeModal
109-
projectContext={{ currentProject, connections, pvcs: pvcs.data }}
109+
projectContext={{ currentProject, connections }}
110+
pvcs={pvcs.data}
110111
servingRuntimeTemplates={templatesEnabled.filter((template) =>
111112
getTemplateEnabledForPlatform(template, ServingRuntimePlatform.SINGLE),
112113
)}

0 commit comments

Comments
 (0)