go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/milo/ui/src/common/layouts/side_bar/sidebar.tsx (about)

     1  // Copyright 2023 The LUCI Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  import LaunchIcon from '@mui/icons-material/Launch';
    16  import MenuIcon from '@mui/icons-material/Menu';
    17  import { Typography } from '@mui/material';
    18  import Drawer from '@mui/material/Drawer';
    19  import MaterialLink from '@mui/material/Link';
    20  import List from '@mui/material/List';
    21  import ListItem from '@mui/material/ListItem';
    22  import ListItemButton from '@mui/material/ListItemButton';
    23  import ListItemIcon from '@mui/material/ListItemIcon';
    24  import ListItemText from '@mui/material/ListItemText';
    25  import ListSubheader from '@mui/material/ListSubheader';
    26  import Toolbar from '@mui/material/Toolbar';
    27  import { Fragment, useMemo } from 'react';
    28  import { Link } from 'react-router-dom';
    29  
    30  import {
    31    useSelectedPage,
    32    useProject,
    33  } from '@/common/components/page_meta/page_meta_provider';
    34  import { UiPage, CommonColors } from '@/common/constants/view';
    35  
    36  import { PAGE_LABEL_MAP, drawerWidth } from '../constants';
    37  
    38  import { generateSidebarSections } from './pages';
    39  
    40  interface Props {
    41    open: boolean;
    42  }
    43  
    44  export const Sidebar = ({ open }: Props) => {
    45    const project = useProject();
    46    const selectedPage = useSelectedPage();
    47  
    48    const sidebarSections = useMemo(() => {
    49      return generateSidebarSections(project);
    50    }, [project]);
    51  
    52    return (
    53      <Drawer
    54        sx={{
    55          width: drawerWidth,
    56          flexShrink: 0,
    57          '& .MuiDrawer-paper': {
    58            width: drawerWidth,
    59            boxSizing: 'border-box',
    60          },
    61        }}
    62        variant="persistent"
    63        anchor="left"
    64        open={open}
    65        role="complementary"
    66      >
    67        <Toolbar variant="dense" />
    68        <List sx={{ mb: '40px', pt: 0 }}>
    69          {sidebarSections.map((sidebarSection) => (
    70            <Fragment key={sidebarSection.title}>
    71              <ListSubheader>{sidebarSection.title}</ListSubheader>
    72              {sidebarSection.pages.map((sidebarPage) => (
    73                <ListItem
    74                  dense
    75                  key={sidebarPage.page}
    76                  disablePadding
    77                  sx={{ display: 'block' }}
    78                >
    79                  <ListItemButton
    80                    sx={{
    81                      justifyContent: 'center',
    82                      px: 2.5,
    83                    }}
    84                    selected={sidebarPage.page === selectedPage}
    85                    component={sidebarPage.external ? MaterialLink : Link}
    86                    to={sidebarPage.url}
    87                    target={sidebarPage.external ? '_blank' : ''}
    88                  >
    89                    <ListItemIcon
    90                      sx={{
    91                        minWidth: 0,
    92                        mr: 1,
    93                        justifyContent: 'center',
    94                      }}
    95                    >
    96                      {sidebarPage.icon}
    97                    </ListItemIcon>
    98                    <ListItemText
    99                      primary={
   100                        // Add "(Consoles)" to "Builder groups" to let help users
   101                        // find the link if they are looking for "Consoles" page,
   102                        // which is the old name of the builder groups page.
   103                        //
   104                        // TODO: remove this once most users are aware of the name
   105                        // change.
   106                        sidebarPage.page === UiPage.BuilderGroups
   107                          ? 'Builder groups (Consoles)'
   108                          : PAGE_LABEL_MAP[sidebarPage.page]
   109                      }
   110                    />
   111  
   112                    {sidebarPage.external && (
   113                      <ListItemIcon
   114                        sx={{
   115                          minWidth: 0,
   116                          mr: 1,
   117                          justifyContent: 'center',
   118                        }}
   119                      >
   120                        <LaunchIcon color="inherit" />
   121                      </ListItemIcon>
   122                    )}
   123                  </ListItemButton>
   124                </ListItem>
   125              ))}
   126            </Fragment>
   127          ))}
   128          <div style={{ margin: '40px 20px', color: CommonColors.FADED_TEXT }}>
   129            {!project && (
   130              <div style={{ margin: '10px 0', color: CommonColors.FADED_TEXT }}>
   131                <Typography variant="caption">
   132                  To see more options, <Link to="/ui/">choose a project</Link>.
   133                </Typography>
   134              </div>
   135            )}
   136            <Typography variant="caption">
   137              Click{' '}
   138              <MenuIcon
   139                fontSize="small"
   140                style={{ position: 'relative', top: '5px' }}
   141              />{' '}
   142              above to hide this menu.
   143            </Typography>
   144          </div>
   145        </List>
   146      </Drawer>
   147    );
   148  };