Skip to content

Commit

Permalink
frontend Sidebar: Move "isSelected" logic outside individual items
Browse files Browse the repository at this point in the history
Change logic that determines if the item is selected to the parent
component. This allows for better memoization of individual items.

Signed-off-by: Oleksandr Dubenko <[email protected]>
  • Loading branch information
sniok committed Dec 12, 2024
1 parent d0eea72 commit 6b65c95
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 35 deletions.
45 changes: 39 additions & 6 deletions frontend/src/components/Sidebar/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { InlineIcon } from '@iconify/react';
import { Button } from '@mui/material';
import { Button, selectClasses } from '@mui/material';

Check failure on line 2 in frontend/src/components/Sidebar/Sidebar.tsx

View workflow job for this annotation

GitHub Actions / lint (20.x, ubuntu-22.04)

'selectClasses' is defined but never used

Check failure on line 2 in frontend/src/components/Sidebar/Sidebar.tsx

View workflow job for this annotation

GitHub Actions / lint (20.x, ubuntu-22.04)

'selectClasses' is defined but never used
import Box from '@mui/material/Box';
import Drawer from '@mui/material/Drawer';
import Grid from '@mui/material/Grid';
Expand All @@ -17,7 +17,7 @@ import { ActionButton } from '../common';
import CreateButton from '../common/Resource/CreateButton';
import NavigationTabs from './NavigationTabs';
import prepareRoutes from './prepareRoutes';
import SidebarItem from './SidebarItem';
import SidebarItem, { SidebarItemProps } from './SidebarItem';
import {
DefaultSidebars,
setSidebarSelected,
Expand Down Expand Up @@ -153,6 +153,34 @@ const DefaultLinkArea = memo((props: { sidebarName: string; isOpen: boolean }) =
);
});

/**
* Checks if item or any sub items are selected
*/
function getIsSelected(item: SidebarItemProps, selectedName?: string | null): boolean {
if (!selectedName) return false;
return (
item.name === selectedName || Boolean(item.subList?.find(it => getIsSelected(it, selectedName)))
);
}

/**
* Updates the isSelected field of an item
*/
function updateItemSelected(
item: SidebarItemProps,
selectedName?: string | null
): SidebarItemProps {
const isSelected = getIsSelected(item, selectedName);
if (isSelected === false) return item;
return {
...item,
isSelected: isSelected,
subList: item.subList
? item.subList.map(it => updateItemSelected(it, selectedName))
: item.subList,
};
}

export default function Sidebar() {
const { t, i18n } = useTranslation(['glossary', 'translation']);

Expand All @@ -177,7 +205,7 @@ export default function Sidebar() {
return prepareRoutes(t, sidebar.selected.sidebar || '');
}, [
cluster,
sidebar.selected,
sidebar.selected.sidebar,
sidebar.entries,
sidebar.filters,
i18n.language,
Expand All @@ -195,13 +223,18 @@ export default function Sidebar() {
[sidebar.selected.sidebar, isOpen]
);

const processedItems = useMemo(
() => items.map(item => updateItemSelected(item, sidebar.selected.item)),
[items, sidebar.selected.item]
);

if (sidebar.selected.sidebar === null || !sidebar?.isVisible) {
return null;
}

return (
<PureSidebar
items={items}
items={processedItems}
open={isOpen}
openUserSelected={isUserOpened}
isNarrowOnly={isNarrowOnly}
Expand All @@ -220,7 +253,7 @@ export interface PureSidebarProps {
/** If the user has selected to open/shrink the sidebar */
openUserSelected?: boolean;
/** To show in the sidebar. */
items: SidebarEntry[];
items: SidebarItemProps[];
/** The selected route name of the sidebar open. */
selectedName: string | null;
/** If the sidebar is the temporary one (full sidebar when user selects it in mobile). */
Expand Down Expand Up @@ -292,7 +325,7 @@ export const PureSidebar = memo(
{items.map(item => (
<SidebarItem
key={item.name}
selectedName={selectedName}
isSelected={item.isSelected}
fullWidth={largeSideBarOpen}
search={search}
{...item}
Expand Down
33 changes: 4 additions & 29 deletions frontend/src/components/Sidebar/SidebarItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { SidebarEntry } from './sidebarSlice';
*/
export interface SidebarItemProps extends ListItemProps, SidebarEntry {
/** The route name which is selected. */
selectedName?: string | null;
isSelected?: boolean;
/** The navigation is a child. */
hasParent?: boolean;
/** Displayed wide with icon and text, otherwise with just a small icon. */
Expand All @@ -36,7 +36,7 @@ const SidebarItem = memo((props: SidebarItemProps) => {
search,
useClusterURL = false,
subList = [],
selectedName,
isSelected,
hasParent = false,
icon,
fullWidth = true,
Expand All @@ -61,31 +61,6 @@ const SidebarItem = memo((props: SidebarItemProps) => {
fullURL = createRouteURL(routeName);
}

const isSelected = React.useMemo(() => {
if (name === selectedName) {
return true;
}

let subListToCheck = [...subList];
for (let i = 0; i < subListToCheck.length; i++) {
const subItem = subListToCheck[i];
if (subItem.name === selectedName) {
return true;
}

if (!!subItem.subList) {
subListToCheck = subListToCheck.concat(subItem.subList);
}
}
return false;
}, [subList, name, selectedName]);

function shouldExpand() {
return isSelected || !!subList.find(item => item.name === selectedName);
}

const expanded = subList.length > 0 && shouldExpand();

return hide ? null : (
<React.Fragment>
<ListItemLink
Expand Down Expand Up @@ -221,7 +196,7 @@ const SidebarItem = memo((props: SidebarItemProps) => {
padding: 0,
}}
>
<Collapse in={fullWidth && expanded} sx={{ width: '100%' }}>
<Collapse in={fullWidth && isSelected} sx={{ width: '100%' }}>
<List
component="ul"
disablePadding
Expand All @@ -236,7 +211,7 @@ const SidebarItem = memo((props: SidebarItemProps) => {
{subList.map((item: SidebarItemProps) => (
<SidebarItem
key={item.name}
selectedName={selectedName}
isSelected={item.isSelected}
hasParent
search={search}
{...item}
Expand Down

0 comments on commit 6b65c95

Please sign in to comment.