Skip to content

Commit c96705b

Browse files
andyatmiamijenny-s51
authored andcommitted
fix(ws): add secrets field to backend API schema (kubeflow#331)
related: kubeflow#239 This commit brings partial support for secrets to the backend API. It enables the `frontend` component to successfully create a Workspace through the "wizard flow". **HOWEVER**, it is important to note this secrets attribute is not supported within the `controller` component yet - as kubeflow#240 is not yet merged. To unblock the `frontend` - the logic contained in this commit simply adds the necessary scaffolding to accept the `secrets` attribute defined within `volumes`. Once umarshalled, the backend essentially ignores this data. Code to fully enable the end to end flow is included in this PR - but simply commented out with `TODO:` comments denoting what can be uncommented once kubeflow#240 is merged into `notebooks-v2`. A test is also presently disabled with `XIt` - and can also be enabled when required code present. Changes were initially coded against the branch provided on kubeflow#240 to verify full end-to-end behavior. Once confirmed, commit was rebased onto `notebooks-v2`, relevant code commented out as described above, and behavior retested to ensure desired outcome. In summary, with these changes: - `backend` API accepts `volumes.secrets` in the _Create_ payload - secrets data is **NOT USED** when programmatically constructing the Workspace CR - Resultant workspace has no `secrets` data - irrespective of it if was provided in the payload or not. Signed-off-by: Andy Stoneberg <[email protected]> Signed-off-by: Jenny <[email protected]> feat(ws): Add theme dependent components Signed-off-by: Jenny <[email protected]> fix linting errors Signed-off-by: Jenny <[email protected]> move button to toolbargroup to fix toolbar alignment fix search input height fix frontend tests Signed-off-by: Jenny <[email protected]> fix testing issues Signed-off-by: Jenny <[email protected]> add export default to ThemeAwareSearchInput Signed-off-by: Jenny <[email protected]> fix linting issues fix import add ID
1 parent ea93acc commit c96705b

File tree

6 files changed

+137
-46
lines changed

6 files changed

+137
-46
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import React, { ReactNode } from 'react';
2+
3+
interface FormFieldsetProps {
4+
component: ReactNode;
5+
field?: string;
6+
className?: string;
7+
}
8+
9+
const FormFieldset: React.FC<FormFieldsetProps> = ({ component, field, className }) => (
10+
<div className={className ?? 'form-fieldset-wrapper'}>
11+
{component}
12+
<fieldset aria-hidden="true" className="form-fieldset">
13+
{field && (
14+
<legend className="form-fieldset-legend">
15+
<span>{field}</span>
16+
</legend>
17+
)}
18+
</fieldset>
19+
</div>
20+
);
21+
22+
export default FormFieldset;
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import * as React from 'react';
2+
import { SearchInput, SearchInputProps, TextInput } from '@patternfly/react-core';
3+
import FormFieldset from 'app/components/FormFieldset';
4+
import { isMUITheme } from 'app/const';
5+
6+
type ThemeAwareSearchInputProps = Omit<SearchInputProps, 'onChange' | 'onClear'> & {
7+
onChange: (value: string) => void; // Simplified onChange signature
8+
onClear?: () => void; // Simplified optional onClear signature
9+
fieldLabel?: string; // Additional prop for MUI FormFieldset label
10+
'data-testid'?: string;
11+
};
12+
13+
const ThemeAwareSearchInput: React.FC<ThemeAwareSearchInputProps> = ({
14+
value,
15+
onChange,
16+
onClear,
17+
fieldLabel,
18+
placeholder,
19+
isDisabled,
20+
className,
21+
style,
22+
'aria-label': ariaLabel = 'Search',
23+
'data-testid': dataTestId,
24+
...rest
25+
}) => {
26+
if (isMUITheme()) {
27+
// Render MUI version using TextInput + FormFieldset
28+
return (
29+
<FormFieldset
30+
className={className}
31+
field={fieldLabel}
32+
component={
33+
<TextInput
34+
value={value}
35+
type="text"
36+
onChange={(_event, newValue) => onChange(newValue)} // Adapt signature
37+
isDisabled={isDisabled}
38+
aria-label={ariaLabel}
39+
data-testid={dataTestId}
40+
style={style}
41+
/>
42+
}
43+
/>
44+
);
45+
}
46+
47+
// Render PF version using SearchInput
48+
return (
49+
<SearchInput
50+
{...rest} // Pass all other applicable SearchInputProps
51+
className={className}
52+
style={style}
53+
placeholder={placeholder}
54+
value={value}
55+
isDisabled={isDisabled}
56+
aria-label={ariaLabel}
57+
data-testid={dataTestId}
58+
onChange={(_event, newValue) => onChange(newValue)} // Adapt signature
59+
onClear={(event) => {
60+
event.stopPropagation();
61+
onChange('');
62+
onClear?.(); // Adapt signature
63+
}}
64+
/>
65+
);
66+
};
67+
68+
export default ThemeAwareSearchInput;

workspaces/frontend/src/app/pages/WorkspaceKinds/WorkspaceKinds.tsx

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import {
88
Brand,
99
Tooltip,
1010
Label,
11-
SearchInput,
1211
Toolbar,
1312
ToolbarContent,
1413
ToolbarItem,
@@ -44,6 +43,7 @@ import { WorkspaceKind } from '~/shared/api/backendApiTypes';
4443
import useWorkspaceKinds from '~/app/hooks/useWorkspaceKinds';
4544
import { useWorkspaceCountPerKind } from '~/app/hooks/useWorkspaceCountPerKind';
4645
import { WorkspaceKindsColumnNames } from '~/app/types';
46+
import ThemeAwareSearchInput from '~/app/components/ThemeAwareSearchInput';
4747

4848
export enum ActionType {
4949
ViewDetails,
@@ -178,32 +178,6 @@ export const WorkspaceKinds: React.FunctionComponent = () => {
178178
[sortedWorkspaceKinds, onFilter],
179179
);
180180

181-
// Set up name search input
182-
const searchNameInput = React.useMemo(
183-
() => (
184-
<SearchInput
185-
placeholder="Filter by name"
186-
value={searchNameValue}
187-
onChange={(_event, value) => onSearchNameChange(value)}
188-
onClear={() => onSearchNameChange('')}
189-
/>
190-
),
191-
[searchNameValue, onSearchNameChange],
192-
);
193-
194-
// Set up description search input
195-
const searchDescriptionInput = React.useMemo(
196-
() => (
197-
<SearchInput
198-
placeholder="Filter by description"
199-
value={searchDescriptionValue}
200-
onChange={(_event, value) => onSearchDescriptionChange(value)}
201-
onClear={() => onSearchDescriptionChange('')}
202-
/>
203-
),
204-
[searchDescriptionValue, onSearchDescriptionChange],
205-
);
206-
207181
// Set up status single select
208182
const [isStatusMenuOpen, setIsStatusMenuOpen] = React.useState<boolean>(false);
209183
const statusToggleRef = React.useRef<HTMLButtonElement>(null);
@@ -509,7 +483,15 @@ export const WorkspaceKinds: React.FunctionComponent = () => {
509483
categoryName="Name"
510484
showToolbarItem={activeAttributeMenu === 'Name'}
511485
>
512-
{searchNameInput}
486+
<ToolbarItem>
487+
<ThemeAwareSearchInput
488+
value={searchNameValue}
489+
onChange={onSearchNameChange}
490+
placeholder="Filter by Name"
491+
fieldLabel="Find by Name"
492+
aria-label="Filter by Name"
493+
/>
494+
</ToolbarItem>
513495
</ToolbarFilter>
514496
<ToolbarFilter
515497
labels={
@@ -522,7 +504,15 @@ export const WorkspaceKinds: React.FunctionComponent = () => {
522504
categoryName="Description"
523505
showToolbarItem={activeAttributeMenu === 'Description'}
524506
>
525-
{searchDescriptionInput}
507+
<ToolbarItem>
508+
<ThemeAwareSearchInput
509+
value={searchDescriptionValue}
510+
onChange={onSearchDescriptionChange}
511+
placeholder="Filter by Description"
512+
fieldLabel="Find by Description"
513+
aria-label="Filter by Description"
514+
/>
515+
</ToolbarItem>
526516
</ToolbarFilter>
527517
<ToolbarFilter
528518
labels={statusSelection !== '' ? [statusSelection] : ([] as string[])}

workspaces/frontend/src/app/pages/Workspaces/Workspaces.tsx

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import {
99
Label,
1010
PaginationVariant,
1111
Pagination,
12-
Button,
1312
Content,
1413
Brand,
1514
Tooltip,
@@ -32,8 +31,7 @@ import {
3231
QuestionCircleIcon,
3332
CodeIcon,
3433
} from '@patternfly/react-icons';
35-
import { useCallback, useState } from 'react';
36-
import { useNavigate } from 'react-router-dom';
34+
import { useState } from 'react';
3735
import { Workspace, WorkspaceState } from '~/shared/api/backendApiTypes';
3836
import { WorkspaceDetails } from '~/app/pages/Workspaces/Details/WorkspaceDetails';
3937
import { ExpandedWorkspaceRow } from '~/app/pages/Workspaces/ExpandedWorkspaceRow';
@@ -63,11 +61,6 @@ export enum ActionType {
6361
}
6462

6563
export const Workspaces: React.FunctionComponent = () => {
66-
const navigate = useNavigate();
67-
const createWorkspace = useCallback(() => {
68-
navigate('/workspaces/create');
69-
}, [navigate]);
70-
7164
const [workspaceKinds] = useWorkspaceKinds();
7265
const kindLogoDict = buildKindLogoDictionary(workspaceKinds);
7366
const workspaceRedirectStatus = buildWorkspaceRedirectStatus(workspaceKinds);
@@ -455,9 +448,6 @@ export const Workspaces: React.FunctionComponent = () => {
455448
<br />
456449
<Content style={{ display: 'flex', alignItems: 'flex-start', columnGap: '20px' }}>
457450
<Filter id="filter-workspaces" onFilter={onFilter} columnNames={filterableColumns} />
458-
<Button variant="primary" ouiaId="Primary" onClick={createWorkspace}>
459-
Create Workspace
460-
</Button>
461451
</Content>
462452
<Table aria-label="Sortable table" ouiaId="SortableTable">
463453
<Thead>

workspaces/frontend/src/shared/components/Filter.tsx

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import * as React from 'react';
22
import {
3+
Button,
34
Menu,
45
MenuContent,
56
MenuItem,
67
MenuList,
78
MenuToggle,
89
MenuToggleElement,
910
Popper,
10-
SearchInput,
1111
Toolbar,
1212
ToolbarContent,
1313
ToolbarFilter,
@@ -16,6 +16,9 @@ import {
1616
ToolbarToggleGroup,
1717
} from '@patternfly/react-core';
1818
import { FilterIcon } from '@patternfly/react-icons';
19+
import { useNavigate } from 'react-router';
20+
import { useCallback } from 'react';
21+
import ThemeAwareSearchInput from '~/app/components/ThemeAwareSearchInput';
1922

2023
export interface FilterProps {
2124
id: string;
@@ -41,6 +44,11 @@ const Filter: React.FC<FilterProps> = ({ id, onFilter, columnNames }) => {
4144
const filterMenuRef = React.useRef<HTMLDivElement | null>(null);
4245
const filterContainerRef = React.useRef<HTMLDivElement | null>(null);
4346

47+
const navigate = useNavigate();
48+
const createWorkspace = useCallback(() => {
49+
navigate('/workspaces/create');
50+
}, [navigate]);
51+
4452
const handleFilterMenuKeys = React.useCallback(
4553
(event: KeyboardEvent) => {
4654
if (!isFilterMenuOpen) {
@@ -202,12 +210,13 @@ const Filter: React.FC<FilterProps> = ({ id, onFilter, columnNames }) => {
202210
<ToolbarGroup variant="filter-group">
203211
<ToolbarItem id={`${id}-dropdown`}>{filterDropdown}</ToolbarItem>
204212
<ToolbarItem>
205-
<SearchInput
213+
<ThemeAwareSearchInput
206214
id={`${id}-search-input`}
207-
placeholder={`Filter by ${activeFilter.columnName}`}
208215
value={searchValue}
209-
onChange={(_event, value) => onSearchChange(value)}
210-
onClear={() => onSearchChange('')}
216+
onChange={onSearchChange}
217+
placeholder={`Filter by ${activeFilter.columnName}`}
218+
fieldLabel={`Find by ${activeFilter.columnName}`}
219+
aria-label={`Filter by ${activeFilter.columnName}`}
211220
/>
212221
</ToolbarItem>
213222
{filters.map((filter) => (
@@ -222,6 +231,9 @@ const Filter: React.FC<FilterProps> = ({ id, onFilter, columnNames }) => {
222231
</ToolbarFilter>
223232
))}
224233
</ToolbarGroup>
234+
<Button variant="primary" ouiaId="Primary" onClick={createWorkspace}>
235+
Create Workspace
236+
</Button>
225237
</ToolbarToggleGroup>
226238
</ToolbarContent>
227239
</Toolbar>

workspaces/frontend/src/shared/style/MUI-theme.scss

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@
573573

574574
}
575575

576-
.mui-theme .pf-v6-c-progress-stepper__step.pf-m-info,
576+
.mui-theme .pf-v6-c-progress-stepper__step.pf-m-info,
577577
.mui-theme .pf-v6-c-progress-stepper__step.pf-m-success {
578578
--pf-v6-c-progress-stepper__step-icon--BackgroundColor: var(--mui-palette-primary-main);
579579
--pf-v6-c-progress-stepper__step-icon--Color: var(--mui-palette-common-white);
@@ -828,4 +828,13 @@
828828
.mui-theme .pf-v6-c-masthead {
829829
padding-left: var(--kf-central-app-drawer-width);
830830
}
831+
}
832+
833+
.mui-theme .pf-v6-c-toolbar__group.pf-m-filter-group .pf-v6-c-form-control {
834+
835+
// Override default form control padding to match button padding in this context
836+
--pf-v6-c-form-control--PaddingBlockStart: var(--mui-spacing-8px);
837+
--pf-v6-c-form-control--PaddingBlockEnd: var(--mui-spacing-8px);
838+
839+
831840
}

0 commit comments

Comments
 (0)