Skip to content

Commit 944e1ee

Browse files
authored
Add additional temp feature flag to hide HF access token field from catalog settings (#2024)
* Add additional temp feature flag to hide HF access token field from catalog settings Signed-off-by: Mike Turley <[email protected]> * Update tests Signed-off-by: Mike Turley <[email protected]> --------- Signed-off-by: Mike Turley <[email protected]>
1 parent 9430849 commit 944e1ee

File tree

7 files changed

+124
-71
lines changed

7 files changed

+124
-71
lines changed

clients/ui/frontend/src/__tests__/cypress/cypress/pages/modelCatalog.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { TEMP_DEV_CATALOG_ADVANCED_FILTERS_FEATURE_KEY } from '~/app/hooks/useTempDevCatalogAdvancedFiltersFeatureAvailable';
1+
import { TempDevFeature } from '~/app/hooks/useTempDevFeatureAvailable';
22
import { appChrome } from './appChrome';
33

44
class ModelCatalogFilter {
@@ -36,7 +36,7 @@ class ModelCatalog {
3636
enableTempDevCatalogAdvancedFiltersFeature = false,
3737
}: { enableTempDevCatalogAdvancedFiltersFeature?: boolean } = {}) {
3838
if (enableTempDevCatalogAdvancedFiltersFeature) {
39-
window.localStorage.setItem(TEMP_DEV_CATALOG_ADVANCED_FILTERS_FEATURE_KEY, 'true');
39+
window.localStorage.setItem(TempDevFeature.CatalogAdvancedFilters, 'true');
4040
}
4141
cy.visit('/model-catalog');
4242
this.wait();

clients/ui/frontend/src/__tests__/cypress/cypress/pages/modelCatalogSettings.ts

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { TempDevFeature } from '~/app/hooks/useTempDevFeatureAvailable';
12
import { appChrome } from './appChrome';
23
import { TableRow } from './components/table';
34
import { Modal } from './components/Modal';
@@ -112,7 +113,13 @@ class CatalogSourceConfigRow extends TableRow {
112113
}
113114

114115
class ModelCatalogSettings {
115-
visit(wait = true) {
116+
visit({
117+
wait = true,
118+
enableTempDevCatalogHuggingFaceApiKeyFeature = false,
119+
}: { wait?: boolean; enableTempDevCatalogHuggingFaceApiKeyFeature?: boolean } = {}) {
120+
if (enableTempDevCatalogHuggingFaceApiKeyFeature) {
121+
window.localStorage.setItem(TempDevFeature.CatalogHuggingFaceApiKey, 'true');
122+
}
116123
cy.visit('/model-catalog-settings');
117124
if (wait) {
118125
this.wait();
@@ -194,14 +201,29 @@ class ModelCatalogSettings {
194201
}
195202

196203
class ManageSourcePage {
197-
visitAddSource(wait = true) {
204+
visitAddSource({
205+
wait = true,
206+
enableTempDevCatalogHuggingFaceApiKeyFeature = false,
207+
}: { wait?: boolean; enableTempDevCatalogHuggingFaceApiKeyFeature?: boolean } = {}) {
208+
if (enableTempDevCatalogHuggingFaceApiKeyFeature) {
209+
window.localStorage.setItem(TempDevFeature.CatalogHuggingFaceApiKey, 'true');
210+
}
198211
cy.visit('/model-catalog-settings/add-source');
199212
if (wait) {
200213
this.wait();
201214
}
202215
}
203216

204-
visitManageSource(catalogSourceId: string, wait = true) {
217+
visitManageSource(
218+
catalogSourceId: string,
219+
{
220+
wait = true,
221+
enableTempDevCatalogHuggingFaceApiKeyFeature = false,
222+
}: { wait?: boolean; enableTempDevCatalogHuggingFaceApiKeyFeature?: boolean } = {},
223+
) {
224+
if (enableTempDevCatalogHuggingFaceApiKeyFeature) {
225+
window.localStorage.setItem(TempDevFeature.CatalogHuggingFaceApiKey, 'true');
226+
}
205227
cy.visit(`/model-catalog-settings/manage-source/${encodeURIComponent(catalogSourceId)}`);
206228
if (wait) {
207229
this.wait();

clients/ui/frontend/src/__tests__/cypress/cypress/tests/mocked/modelCatalogSettings/modelCatalogSettings.cy.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,7 @@ describe('Manage Source Page', () => {
593593
});
594594

595595
it('should show Hugging Face fields by default', () => {
596-
manageSourcePage.visitAddSource();
596+
manageSourcePage.visitAddSource({ enableTempDevCatalogHuggingFaceApiKeyFeature: true });
597597
manageSourcePage.findSourceTypeHuggingFace().should('be.checked');
598598
manageSourcePage.findCredentialsSection().should('exist');
599599
manageSourcePage.findAccessTokenInput().should('exist');
@@ -628,15 +628,15 @@ describe('Manage Source Page', () => {
628628
});
629629

630630
it('should enable Add button when all required HF fields are filled', () => {
631-
manageSourcePage.visitAddSource();
631+
manageSourcePage.visitAddSource({ enableTempDevCatalogHuggingFaceApiKeyFeature: true });
632632
manageSourcePage.fillSourceName('Test Source');
633633
manageSourcePage.fillAccessToken('test-token-123');
634634
manageSourcePage.fillOrganization('Google');
635635
manageSourcePage.findSubmitButton().should('not.be.disabled');
636636
});
637637

638638
it('should enable Preview button when HF credentials are filled', () => {
639-
manageSourcePage.visitAddSource();
639+
manageSourcePage.visitAddSource({ enableTempDevCatalogHuggingFaceApiKeyFeature: true });
640640
manageSourcePage.fillAccessToken('test-token-123');
641641
manageSourcePage.fillOrganization('Google');
642642
manageSourcePage.findPreviewButton().should('not.be.disabled');
@@ -735,7 +735,7 @@ describe('Manage Source Page', () => {
735735
});
736736

737737
it('should maintain form state when switching between source types', () => {
738-
manageSourcePage.visitAddSource();
738+
manageSourcePage.visitAddSource({ enableTempDevCatalogHuggingFaceApiKeyFeature: true });
739739

740740
// Fill name and HF fields
741741
manageSourcePage.fillSourceName('Test Source');
@@ -815,7 +815,7 @@ describe('Manage Source Page', () => {
815815
});
816816

817817
it('should enable all three preview buttons when credentials are filled', () => {
818-
manageSourcePage.visitAddSource();
818+
manageSourcePage.visitAddSource({ enableTempDevCatalogHuggingFaceApiKeyFeature: true });
819819
manageSourcePage.fillAccessToken('test-token');
820820
manageSourcePage.fillOrganization('Google');
821821
manageSourcePage.findPreviewButton().should('not.be.disabled');
@@ -864,7 +864,7 @@ describe('Manage Source Page', () => {
864864
cy.intercept('POST', '/model-registry/api/v1/settings/model_catalog/source_configs', {
865865
data: mockHuggingFaceCatalogSourceConfig({}),
866866
}).as('addSourcewithHuggingFaceType');
867-
manageSourcePage.visitAddSource();
867+
manageSourcePage.visitAddSource({ enableTempDevCatalogHuggingFaceApiKeyFeature: true });
868868
manageSourcePage.findNameInput().type('sample source');
869869
manageSourcePage.selectSourceType('huggingface');
870870
manageSourcePage.findSourceTypeHuggingFace().should('be.checked');
@@ -1084,7 +1084,9 @@ describe('Manage Source Page', () => {
10841084
},
10851085
).as('manageSourcewithHuggingFaceType');
10861086

1087-
manageSourcePage.visitManageSource('huggingface_source_3');
1087+
manageSourcePage.visitManageSource('huggingface_source_3', {
1088+
enableTempDevCatalogHuggingFaceApiKeyFeature: true,
1089+
});
10881090
manageSourcePage.findNameInput().should('have.value', 'Huggingface source 3');
10891091

10901092
manageSourcePage.findAccessTokenInput().should('have.value', 'apikey');

clients/ui/frontend/src/app/hooks/useTempDevCatalogAdvancedFiltersFeatureAvailable.ts

Lines changed: 0 additions & 37 deletions
This file was deleted.
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* Temporary development hook for toggling incomplete features in the browser.
3+
*
4+
* This hook provides a browser storage-backed feature flag that can be toggled
5+
* via the browser console using:
6+
* window.setTempDevCatalogAdvancedFiltersFeatureAvailable(true/false);
7+
* window.setTempDevCatalogHuggingFaceApiKeyFeatureAvailable(true/false);
8+
* The state persists across page reloads using browser storage.
9+
*
10+
* Each TempDevFeature and corresponding window.set* here should be removed once that feature is ready.
11+
* This entire hook should be removed once all these features are ready.
12+
*
13+
* @returns {boolean} Whether the catalog advanced filters feature is enabled
14+
*/
15+
16+
import * as React from 'react';
17+
import { useBrowserStorage } from 'mod-arch-core';
18+
19+
declare global {
20+
interface Window {
21+
setTempDevCatalogAdvancedFiltersFeatureAvailable?: (enabled: boolean) => void;
22+
setTempDevCatalogHuggingFaceApiKeyFeatureAvailable?: (enabled: boolean) => void;
23+
}
24+
}
25+
26+
export enum TempDevFeature {
27+
CatalogAdvancedFilters = 'tempDevCatalogAdvancedFiltersFeatureAvailable',
28+
CatalogHuggingFaceApiKey = 'tempDevCatalogHuggingFaceApiKeyFeatureAvailable',
29+
}
30+
31+
export const useTempDevFeatureAvailable = (feature: TempDevFeature): boolean => {
32+
const [isAvailable, setIsAvailable] = useBrowserStorage(feature, false);
33+
34+
// Expose setter to window for easy toggling via browser console
35+
React.useEffect(() => {
36+
switch (feature) {
37+
case TempDevFeature.CatalogAdvancedFilters:
38+
window.setTempDevCatalogAdvancedFiltersFeatureAvailable = setIsAvailable;
39+
break;
40+
case TempDevFeature.CatalogHuggingFaceApiKey:
41+
window.setTempDevCatalogHuggingFaceApiKeyFeatureAvailable = setIsAvailable;
42+
break;
43+
}
44+
}, [feature, setIsAvailable]);
45+
46+
return isAvailable;
47+
};

clients/ui/frontend/src/app/pages/modelCatalog/components/ModelPerformanceViewToggleCard.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@ import {
99
CardBody,
1010
} from '@patternfly/react-core';
1111
import { ModelCatalogContext } from '~/app/context/modelCatalog/ModelCatalogContext';
12-
import { useTempDevCatalogAdvancedFiltersFeatureAvailable } from '~/app/hooks/useTempDevCatalogAdvancedFiltersFeatureAvailable';
12+
import { TempDevFeature, useTempDevFeatureAvailable } from '~/app/hooks/useTempDevFeatureAvailable';
1313

1414
const ModelPerformanceViewToggleCard: React.FC = () => {
1515
const { performanceViewEnabled, setPerformanceViewEnabled } =
1616
React.useContext(ModelCatalogContext);
1717

18-
const isPerformanceToggleAvailable = useTempDevCatalogAdvancedFiltersFeatureAvailable();
18+
const isPerformanceToggleAvailable = useTempDevFeatureAvailable(
19+
TempDevFeature.CatalogAdvancedFilters,
20+
);
1921
if (!isPerformanceToggleAvailable) {
2022
return null;
2123
}

clients/ui/frontend/src/app/pages/modelCatalogSettings/components/CredentialsSection.tsx

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
HELP_TEXT,
2323
PLACEHOLDERS,
2424
} from '~/app/pages/modelCatalogSettings/constants';
25+
import { TempDevFeature, useTempDevFeatureAvailable } from '~/app/hooks/useTempDevFeatureAvailable';
2526

2627
type CredentialsSectionProps = {
2728
formData: ManageSourceFormData;
@@ -61,6 +62,26 @@ const CredentialsSection: React.FC<CredentialsSectionProps> = ({
6162
/>
6263
);
6364

65+
const organizationFormGroup = (
66+
<FormGroup label={FORM_LABELS.ORGANIZATION} isRequired fieldId="organization">
67+
<FormHelperText>
68+
<HelperText>
69+
<HelperTextItem>{HELP_TEXT.ORGANIZATION}</HelperTextItem>
70+
</HelperText>
71+
</FormHelperText>
72+
<FormFieldset component={organizationInput} field="Allowed organization" />
73+
{isOrganizationTouched && !isOrganizationValid && (
74+
<FormHelperText>
75+
<HelperText>
76+
<HelperTextItem variant="error" data-testid="organization-error">
77+
{VALIDATION_MESSAGES.ORGANIZATION_REQUIRED}
78+
</HelperTextItem>
79+
</HelperText>
80+
</FormHelperText>
81+
)}
82+
</FormGroup>
83+
);
84+
6485
const accessTokenInput = (
6586
<PasswordInput
6687
isRequired
@@ -74,26 +95,8 @@ const CredentialsSection: React.FC<CredentialsSectionProps> = ({
7495
/>
7596
);
7697

77-
return (
78-
<FormSection title={FORM_LABELS.CREDENTIALS} data-testid="credentials-section">
79-
<FormGroup label={FORM_LABELS.ORGANIZATION} isRequired fieldId="organization">
80-
<FormHelperText>
81-
<HelperText>
82-
<HelperTextItem>{HELP_TEXT.ORGANIZATION}</HelperTextItem>
83-
</HelperText>
84-
</FormHelperText>
85-
<FormFieldset component={organizationInput} field="Allowed organization" />
86-
{isOrganizationTouched && !isOrganizationValid && (
87-
<FormHelperText>
88-
<HelperText>
89-
<HelperTextItem variant="error" data-testid="organization-error">
90-
{VALIDATION_MESSAGES.ORGANIZATION_REQUIRED}
91-
</HelperTextItem>
92-
</HelperText>
93-
</FormHelperText>
94-
)}
95-
</FormGroup>
96-
98+
const accessTokenFormGroup = (
99+
<>
97100
<FormGroup label={FORM_LABELS.ACCESS_TOKEN} fieldId="access-token">
98101
<FormHelperText>
99102
<HelperText>
@@ -129,6 +132,20 @@ const CredentialsSection: React.FC<CredentialsSectionProps> = ({
129132
Validate
130133
</Button>
131134
</ActionList>
135+
</>
136+
);
137+
138+
const accessTokenFeatureAvailable = useTempDevFeatureAvailable(
139+
TempDevFeature.CatalogHuggingFaceApiKey,
140+
);
141+
142+
return (
143+
<FormSection
144+
title={accessTokenFeatureAvailable ? FORM_LABELS.CREDENTIALS : undefined}
145+
data-testid="credentials-section"
146+
>
147+
{organizationFormGroup}
148+
{accessTokenFeatureAvailable && accessTokenFormGroup}
132149
</FormSection>
133150
);
134151
};

0 commit comments

Comments
 (0)