improve: UX Enhancements in workspace summary (#473)

* Workspace Kinds Summary:UX Enchancements

Signed-off-by: DominikKawka <dkawka@redhat.com>

* frontend build and test fix

Signed-off-by: DominikKawka <dkawka@redhat.com>

* replaced inline styling with PF utility classes

Signed-off-by: DominikKawka <dkawka@redhat.com>

* prettier check

Signed-off-by: DominikKawka <dkawka@redhat.com>

* fix(ws): apply left alignment and fix padding to match other items

Signed-off-by: Jenny <32821331+jenny-s51@users.noreply.github.com>

* prettier check

Signed-off-by: DominikKawka <dkawka@redhat.com>

* resolved merge conflict

Signed-off-by: DominikKawka <dkawka@redhat.com>

* fixed merge conflicts

Signed-off-by: DominikKawka <dkawka@redhat.com>

---------

Signed-off-by: DominikKawka <dkawka@redhat.com>
Signed-off-by: Jenny <32821331+jenny-s51@users.noreply.github.com>
Signed-off-by: Dominik Kawka  <31955648+dominikkawka@users.noreply.github.com>
Co-authored-by: Jenny <32821331+jenny-s51@users.noreply.github.com>
This commit is contained in:
Dominik Kawka 2025-07-24 16:17:01 +01:00 committed by Bhakti Narvekar
parent b18812a567
commit 4b88c153e2
2 changed files with 29 additions and 43 deletions

View File

@ -1,10 +1,10 @@
import React, { useCallback, useRef, useState } from 'react'; import React, { useCallback, useRef, useState } from 'react';
import { Button } from '@patternfly/react-core/dist/esm/components/Button';
import { Content, ContentVariants } from '@patternfly/react-core/dist/esm/components/Content'; import { Content, ContentVariants } from '@patternfly/react-core/dist/esm/components/Content';
import { PageSection } from '@patternfly/react-core/dist/esm/components/Page'; import { PageSection } from '@patternfly/react-core/dist/esm/components/Page';
import { Stack, StackItem } from '@patternfly/react-core/dist/esm/layouts/Stack'; import { Stack, StackItem } from '@patternfly/react-core/dist/esm/layouts/Stack';
import { ArrowLeftIcon } from '@patternfly/react-icons/dist/esm/icons/arrow-left-icon'; import { Breadcrumb } from '@patternfly/react-core/dist/esm/components/Breadcrumb';
import { useTypedLocation, useTypedNavigate, useTypedParams } from '~/app/routerHelper'; import { BreadcrumbItem } from '@patternfly/react-core/dist/esm/components/Breadcrumb/BreadcrumbItem';
import { useTypedLocation, useTypedParams } from '~/app/routerHelper';
import WorkspaceTable, { import WorkspaceTable, {
WorkspaceTableFilteredColumn, WorkspaceTableFilteredColumn,
WorkspaceTableRef, WorkspaceTableRef,
@ -18,7 +18,6 @@ import { useWorkspaceRowActions } from '~/app/hooks/useWorkspaceRowActions';
import { usePolling } from '~/app/hooks/usePolling'; import { usePolling } from '~/app/hooks/usePolling';
const WorkspaceKindSummary: React.FC = () => { const WorkspaceKindSummary: React.FC = () => {
const navigate = useTypedNavigate();
const [isSummaryExpanded, setIsSummaryExpanded] = useState(true); const [isSummaryExpanded, setIsSummaryExpanded] = useState(true);
const { state } = useTypedLocation<'workspaceKindSummary'>(); const { state } = useTypedLocation<'workspaceKindSummary'>();
@ -56,18 +55,15 @@ const WorkspaceKindSummary: React.FC = () => {
} }
return ( return (
<PageSection isFilled> <PageSection>
<Stack hasGutter> <Stack hasGutter>
<StackItem> <StackItem>
<Button <Breadcrumb>
variant="link" <BreadcrumbItem to="workspaceKinds">Workspace Kinds</BreadcrumbItem>
icon={<ArrowLeftIcon />} <BreadcrumbItem to="#" isActive>
iconPosition="left" Workspaces in {kind}
onClick={() => navigate('workspaceKinds')} </BreadcrumbItem>
aria-label="Back to Workspace Kinds" </Breadcrumb>
>
Back
</Button>
</StackItem> </StackItem>
<StackItem> <StackItem>
<Content component={ContentVariants.h1}>{kind}</Content> <Content component={ContentVariants.h1}>{kind}</Content>
@ -83,7 +79,7 @@ const WorkspaceKindSummary: React.FC = () => {
onAddFilter={onAddFilter} onAddFilter={onAddFilter}
/> />
</StackItem> </StackItem>
<StackItem isFilled> <StackItem>
<WorkspaceTable <WorkspaceTable
ref={workspaceTableRef} ref={workspaceTableRef}
workspaces={workspaces} workspaces={workspaces}

View File

@ -1,5 +1,4 @@
import React, { useMemo } from 'react'; import React, { useMemo } from 'react';
import { Bullseye } from '@patternfly/react-core/dist/esm/layouts/Bullseye';
import { Button } from '@patternfly/react-core/dist/esm/components/Button'; import { Button } from '@patternfly/react-core/dist/esm/components/Button';
import { import {
Card, Card,
@ -12,11 +11,7 @@ import { Content, ContentVariants } from '@patternfly/react-core/dist/esm/compon
import { Divider } from '@patternfly/react-core/dist/esm/components/Divider'; import { Divider } from '@patternfly/react-core/dist/esm/components/Divider';
import { Flex, FlexItem } from '@patternfly/react-core/dist/esm/layouts/Flex'; import { Flex, FlexItem } from '@patternfly/react-core/dist/esm/layouts/Flex';
import { Stack, StackItem } from '@patternfly/react-core/dist/esm/layouts/Stack'; import { Stack, StackItem } from '@patternfly/react-core/dist/esm/layouts/Stack';
import { import { t_global_spacer_md as MediumPadding } from '@patternfly/react-tokens';
t_global_spacer_md as MediumPadding,
t_global_font_size_4xl as LargeFontSize,
t_global_font_weight_heading_bold as BoldFontWeight,
} from '@patternfly/react-tokens';
import { Workspace } from '~/shared/api/backendApiTypes'; import { Workspace } from '~/shared/api/backendApiTypes';
import { import {
countGpusFromWorkspaces, countGpusFromWorkspaces,
@ -51,7 +46,7 @@ const WorkspaceKindSummaryExpandableCard: React.FC<WorkspaceKindSummaryExpandabl
); );
return ( return (
<Card isExpanded={isExpanded}> <Card isExpanded={isExpanded} variant="secondary">
<CardHeader onExpand={onExpandToggle}> <CardHeader onExpand={onExpandToggle}>
<CardTitle> <CardTitle>
<Content component={ContentVariants.h2}>Workspaces summary</Content> <Content component={ContentVariants.h2}>Workspaces summary</Content>
@ -62,7 +57,7 @@ const WorkspaceKindSummaryExpandableCard: React.FC<WorkspaceKindSummaryExpandabl
<Flex wrap="wrap"> <Flex wrap="wrap">
<SectionFlex title="Total GPUs in use"> <SectionFlex title="Total GPUs in use">
<FlexItem> <FlexItem>
<Content> <Content className="pf-v6-u-font-size-4xl pf-v6-u-font-weight-bold">
{countGpusFromWorkspaces(filterRunningWorkspaces(workspaces))} GPUs {countGpusFromWorkspaces(filterRunningWorkspaces(workspaces))} GPUs
</Content> </Content>
</FlexItem> </FlexItem>
@ -73,29 +68,25 @@ const WorkspaceKindSummaryExpandableCard: React.FC<WorkspaceKindSummaryExpandabl
<SectionDivider /> <SectionDivider />
<SectionFlex title="Idle GPU workspaces"> <SectionFlex title="Idle GPU workspaces">
<FlexItem> <FlexItem>
<Bullseye>
<Button <Button
variant="link" variant="link"
isInline isInline
style={{ fontSize: LargeFontSize.value, fontWeight: BoldFontWeight.value }} className="pf-v6-u-font-size-4xl pf-v6-u-font-weight-bold"
onClick={() => { onClick={() => {
onAddFilter({ columnKey: 'idleGpu', value: YesNoValue.Yes }); onAddFilter({ columnKey: 'idleGpu', value: YesNoValue.Yes });
}} }}
> >
{filterIdleWorkspacesWithGpu(workspaces).length} {filterIdleWorkspacesWithGpu(workspaces).length}
</Button> </Button>
</Bullseye>
</FlexItem> </FlexItem>
<FlexItem> <FlexItem>
<Bullseye> <Content>Idle GPU Workspaces</Content>
<Content>Idle GPU workspaces</Content>
</Bullseye>
</FlexItem> </FlexItem>
</SectionFlex> </SectionFlex>
<SectionDivider /> <SectionDivider />
<SectionFlex title="Top GPU consumer namespaces"> <SectionFlex title="Top GPU Consumer Namespaces">
<FlexItem> <Content>
<Stack hasGutter> <Stack className="pf-v6-u-pt-sm">
{topGpuConsumersByNamespace.length > 0 ? ( {topGpuConsumersByNamespace.length > 0 ? (
topGpuConsumersByNamespace.map(([ns, record]) => ( topGpuConsumersByNamespace.map(([ns, record]) => (
<StackItem key={ns}> <StackItem key={ns}>
@ -112,7 +103,7 @@ const WorkspaceKindSummaryExpandableCard: React.FC<WorkspaceKindSummaryExpandabl
</StackItem> </StackItem>
)} )}
</Stack> </Stack>
</FlexItem> </Content>
</SectionFlex> </SectionFlex>
</Flex> </Flex>
</CardBody> </CardBody>
@ -134,7 +125,6 @@ const SectionFlex: React.FC<SectionFlexProps> = ({ children, title }) => (
<Flex <Flex
direction={{ default: 'column' }} direction={{ default: 'column' }}
justifyContent={{ default: 'justifyContentSpaceBetween' }} justifyContent={{ default: 'justifyContentSpaceBetween' }}
style={{ height: '100%' }}
> >
<FlexItem> <FlexItem>
<Content component={ContentVariants.h3}>{title}</Content> <Content component={ContentVariants.h3}>{title}</Content>