Skip to content

Commit da2506e

Browse files
author
Liav Weiss (EXT-Nokia)
committed
feat(ws): Notebooks 2.0 // Frontend // Workspace table // Add Empty State #259
Signed-off-by: Liav Weiss (EXT-Nokia) <liav.weiss.ext@nokia.com>
1 parent a6c6654 commit da2506e

File tree

4 files changed

+129
-119
lines changed

4 files changed

+129
-119
lines changed

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

+7-10
Original file line numberDiff line numberDiff line change
@@ -241,11 +241,11 @@ export const WorkspaceKinds: React.FunctionComponent = () => {
241241
[sortedWorkspaceKinds, onFilter],
242242
);
243243

244-
const clearAllFilters = React.useCallback(() => {
245-
setSearchNameValue('');
246-
setStatusSelection('');
247-
setSearchDescriptionValue('');
248-
}, []);
244+
const clearAllFilters = React.useCallback(() => {
245+
setSearchNameValue('');
246+
setStatusSelection('');
247+
setSearchDescriptionValue('');
248+
}, []);
249249

250250
// Set up name search input
251251
const searchNameInput = React.useMemo(
@@ -538,10 +538,7 @@ export const WorkspaceKinds: React.FunctionComponent = () => {
538538
</Content>
539539
<br />
540540
<Content style={{ display: 'flex', alignItems: 'flex-start', columnGap: '20px' }}>
541-
<Toolbar
542-
id="attribute-search-filter-toolbar"
543-
clearAllFilters={clearAllFilters}
544-
>
541+
<Toolbar id="attribute-search-filter-toolbar" clearAllFilters={clearAllFilters}>
545542
<ToolbarContent>
546543
<ToolbarToggleGroup toggleIcon={<FilterIcon />} breakpoint="xl">
547544
<ToolbarGroup variant="filter-group">
@@ -668,4 +665,4 @@ export const WorkspaceKinds: React.FunctionComponent = () => {
668665
</DrawerContent>
669666
</Drawer>
670667
);
671-
};
668+
};

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

+58-49
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
Content,
1414
Brand,
1515
Tooltip,
16+
Bullseye,
1617
} from '@patternfly/react-core';
1718
import {
1819
Table,
@@ -47,10 +48,9 @@ import { WorkspaceConnectAction } from '~/app/pages/Workspaces/WorkspaceConnectA
4748
import { WorkspaceStartActionModal } from '~/app/pages/Workspaces/workspaceActions/WorkspaceStartActionModal';
4849
import { WorkspaceRestartActionModal } from '~/app/pages/Workspaces/workspaceActions/WorkspaceRestartActionModal';
4950
import { WorkspaceStopActionModal } from '~/app/pages/Workspaces/workspaceActions/WorkspaceStopActionModal';
51+
import EmptyStateWithClearFilters from '~/shared/components/EmptyStateWithClearFilters'; // Import the new component
5052
import Filter, { FilteredColumn, FilterRef } from 'shared/components/Filter'; // Import FilterRef
5153
import { formatRam } from 'shared/utilities/WorkspaceUtils';
52-
import EmptyStateWithClearFilters from '~/shared/components/EmptyStateWithClearFilters'; // Import the new component
53-
import { Bullseye } from '@patternfly/react-core'; // Import Bullseye if not already imported
5454

5555
export enum ActionType {
5656
ViewDetails,
@@ -200,19 +200,21 @@ export const Workspaces: React.FunctionComponent = () => {
200200
> = {}; // Initialize the redirect status dictionary
201201
workspaceRedirectStatus = buildWorkspaceRedirectStatus(workspaceKinds); // Populate the dictionary
202202

203-
// Table columns
204-
const columnNames: WorkspacesColumnNames = {
205-
redirectStatus: 'Redirect Status',
206-
name: 'Name',
207-
kind: 'Kind',
208-
image: 'Image',
209-
podConfig: 'Pod Config',
210-
state: 'State',
211-
homeVol: 'Home Vol',
212-
cpu: 'CPU',
213-
ram: 'Memory',
214-
lastActivity: 'Last Activity',
215-
};
203+
const columnNames: WorkspacesColumnNames = React.useMemo(
204+
() => ({
205+
redirectStatus: 'Redirect Status',
206+
name: 'Name',
207+
kind: 'Kind',
208+
image: 'Image',
209+
podConfig: 'Pod Config',
210+
state: 'State',
211+
homeVol: 'Home Vol',
212+
cpu: 'CPU',
213+
ram: 'Memory',
214+
lastActivity: 'Last Activity',
215+
}),
216+
[],
217+
);
216218

217219
const filterableColumns = {
218220
name: 'Name',
@@ -258,41 +260,43 @@ export const Workspaces: React.FunctionComponent = () => {
258260
expandedWorkspacesNames.includes(workspace.name);
259261

260262
// filter function to pass to the filter component
261-
const onFilter = React.useCallback((filters: FilteredColumn[]) => {
262-
// Search name with search value
263-
let filteredWorkspaces = initialWorkspaces;
264-
filters.forEach((filter) => {
265-
let searchValueInput: RegExp;
266-
try {
267-
searchValueInput = new RegExp(filter.value, 'i');
268-
} catch {
269-
searchValueInput = new RegExp(filter.value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'i');
270-
}
271-
272-
filteredWorkspaces = filteredWorkspaces.filter((workspace) => {
273-
if (filter.value === '') {
274-
return true;
263+
const onFilter = React.useCallback(
264+
(filters: FilteredColumn[]) => {
265+
// Search name with search value
266+
let filteredWorkspaces = initialWorkspaces;
267+
filters.forEach((filter) => {
268+
let searchValueInput: RegExp;
269+
try {
270+
searchValueInput = new RegExp(filter.value, 'i');
271+
} catch {
272+
searchValueInput = new RegExp(filter.value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'i');
275273
}
276-
switch (filter.columnName) {
277-
case columnNames.name:
278-
return workspace.name.search(searchValueInput) >= 0;
279-
case columnNames.kind:
280-
return workspace.kind.search(searchValueInput) >= 0;
281-
case columnNames.image:
282-
return workspace.options.imageConfig.search(searchValueInput) >= 0;
283-
case columnNames.podConfig:
284-
return workspace.options.podConfig.search(searchValueInput) >= 0;
285-
case columnNames.state:
286-
return WorkspaceState[workspace.status.state].search(searchValueInput) >= 0;
287-
case columnNames.homeVol:
288-
return workspace.podTemplate.volumes.home.search(searchValueInput) >= 0;
289-
default:
274+
275+
filteredWorkspaces = filteredWorkspaces.filter((workspace) => {
276+
if (filter.value === '') {
290277
return true;
291-
}
278+
}
279+
switch (filter.columnName) {
280+
case columnNames.name:
281+
return workspace.name.search(searchValueInput) >= 0;
282+
case columnNames.kind:
283+
return workspace.kind.search(searchValueInput) >= 0;
284+
case columnNames.image:
285+
return workspace.options.imageConfig.search(searchValueInput) >= 0;
286+
case columnNames.podConfig:
287+
return workspace.options.podConfig.search(searchValueInput) >= 0;
288+
case columnNames.state:
289+
return WorkspaceState[workspace.status.state].search(searchValueInput) >= 0;
290+
case columnNames.homeVol:
291+
return workspace.podTemplate.volumes.home.search(searchValueInput) >= 0;
292+
default:
293+
return true;
294+
}
295+
});
292296
});
293-
});
294-
setWorkspaces(filteredWorkspaces);
295-
}, [initialWorkspaces, columnNames]
297+
setWorkspaces(filteredWorkspaces);
298+
},
299+
[initialWorkspaces, columnNames],
296300
);
297301

298302
const emptyState = React.useMemo(
@@ -576,7 +580,12 @@ export const Workspaces: React.FunctionComponent = () => {
576580
</Content>
577581
<br />
578582
<Content style={{ display: 'flex', alignItems: 'flex-start', columnGap: '20px' }}>
579-
<Filter ref={filterRef} id="filter-workspaces" onFilter={onFilter} columnNames={filterableColumns} />
583+
<Filter
584+
ref={filterRef}
585+
id="filter-workspaces"
586+
onFilter={onFilter}
587+
columnNames={filterableColumns}
588+
/>
580589
<Button variant="primary" ouiaId="Primary" onClick={createWorkspace}>
581590
Create Workspace
582591
</Button>
@@ -705,4 +714,4 @@ export const Workspaces: React.FunctionComponent = () => {
705714
</DrawerContent>
706715
</Drawer>
707716
);
708-
};
717+
};

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

+27-29
Original file line numberDiff line numberDiff line change
@@ -21,33 +21,31 @@ const EmptyStateWithClearFilters: React.FC<EmptyStateWithClearFiltersProps> = ({
2121
body,
2222
onClearFilters,
2323
colSpan,
24-
}) => (
25-
colSpan !== undefined ? (
24+
}) =>
25+
colSpan !== undefined ? (
26+
<Bullseye>
27+
<EmptyState headingLevel="h4" titleText={title} icon={SearchIcon}>
28+
<EmptyStateBody>{body}</EmptyStateBody>
29+
<EmptyStateFooter>
30+
<EmptyStateActions>
31+
<Button variant="link" onClick={onClearFilters}>
32+
Clear all filters
33+
</Button>
34+
</EmptyStateActions>
35+
</EmptyStateFooter>
36+
</EmptyState>
37+
</Bullseye>
38+
) : (
39+
<EmptyState headingLevel="h4" titleText={title} icon={SearchIcon}>
40+
<EmptyStateBody>{body}</EmptyStateBody>
41+
<EmptyStateFooter>
42+
<EmptyStateActions>
43+
<Button variant="link" onClick={onClearFilters}>
44+
Clear all filters
45+
</Button>
46+
</EmptyStateActions>
47+
</EmptyStateFooter>
48+
</EmptyState>
49+
);
2650

27-
<Bullseye>
28-
<EmptyState headingLevel="h4" titleText={title} icon={SearchIcon}>
29-
<EmptyStateBody>{body}</EmptyStateBody>
30-
<EmptyStateFooter>
31-
<EmptyStateActions>
32-
<Button variant="link" onClick={onClearFilters}>
33-
Clear all filters
34-
</Button>
35-
</EmptyStateActions>
36-
</EmptyStateFooter>
37-
</EmptyState>
38-
</Bullseye>
39-
) : (
40-
<EmptyState headingLevel="h4" titleText={title} icon={SearchIcon}>
41-
<EmptyStateBody>{body}</EmptyStateBody>
42-
<EmptyStateFooter>
43-
<EmptyStateActions>
44-
<Button variant="link" onClick={onClearFilters}>
45-
Clear all filters
46-
</Button>
47-
</EmptyStateActions>
48-
</EmptyStateFooter>
49-
</EmptyState>
50-
)
51-
);
52-
53-
export default EmptyStateWithClearFilters;
51+
export default EmptyStateWithClearFilters;

0 commit comments

Comments
 (0)