go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/analysis/frontend/ui/src/components/top_bar/top_bar.tsx (about)

     1  // Copyright 2022 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 {
    16    useContext,
    17    useMemo,
    18  } from 'react';
    19  import {
    20    Link as RouterLink,
    21    useParams,
    22  } from 'react-router-dom';
    23  
    24  import Link from '@mui/material/Link';
    25  import RuleIcon from '@mui/icons-material/Rule';
    26  import SpokeIcon from '@mui/icons-material/Spoke';
    27  import AppBar from '@mui/material/AppBar';
    28  import Box from '@mui/material/Box';
    29  import Button from '@mui/material/Button';
    30  // eslint-disable-next-line import/no-unresolved
    31  import { OverridableComponent } from '@mui/material/OverridableComponent';
    32  import { SvgIconTypeMap } from '@mui/material/SvgIcon';
    33  import Toolbar from '@mui/material/Toolbar';
    34  
    35  import { DynamicComponentNoProps } from '@/tools/rendering_tools';
    36  
    37  import CollapsedMenu from './collapsed_menu/collapsed_menu';
    38  import Logo from './logo/logo';
    39  import {
    40    TopBarContext,
    41    TopBarContextProvider,
    42  } from './top_bar_context';
    43  import UserActions from './user_actions/user_actions';
    44  
    45  type AppBarPageTitle = 'Clusters' | 'Rules';
    46  
    47  export interface AppBarPage {
    48    title: AppBarPageTitle;
    49    url: string;
    50    icon: OverridableComponent<SvgIconTypeMap>;
    51  }
    52  
    53  function generatePages(projectId: string | undefined): AppBarPage[] {
    54    if (!projectId) {
    55      return [];
    56    }
    57    return [
    58      {
    59        title: 'Clusters',
    60        url: `/p/${projectId}/clusters`,
    61        icon: SpokeIcon,
    62      },
    63      {
    64        title: 'Rules',
    65        url: `/p/${projectId}/rules`,
    66        icon: RuleIcon,
    67      },
    68    ];
    69  }
    70  
    71  const TopBar = () => {
    72    const { setAnchorElNav } = useContext(TopBarContext);
    73  
    74    const handleCloseNavMenu = () => {
    75      setAnchorElNav(null);
    76    };
    77  
    78    const { project: projectId } = useParams();
    79  
    80    const pages = useMemo<AppBarPage[]>(() => generatePages(projectId), [projectId]);
    81  
    82    return (
    83      <TopBarContextProvider>
    84        <AppBar position="static">
    85          <Toolbar >
    86            <Box sx={{
    87              display: {
    88                xs: 'none',
    89                md: 'flex',
    90              },
    91              mr: 1,
    92              width: '3rem',
    93            }}>
    94              <Logo />
    95            </Box>
    96            <Link
    97              variant="h6"
    98              noWrap
    99              component={RouterLink}
   100              to="/"
   101              underline="none"
   102              color="inherit"
   103              sx={{
   104                mr: 2,
   105                display: { xs: 'none', md: 'flex' },
   106              }}>
   107              LUCI Analysis
   108            </Link>
   109            <CollapsedMenu pages={pages}/>
   110            <Box sx={{ flexGrow: 1, display: { xs: 'none', md: 'flex' } }}>
   111              {pages.map((page) => (
   112                <Button
   113                  component={RouterLink}
   114                  to={page.url}
   115                  key={page.title}
   116                  onClick={handleCloseNavMenu}
   117                  sx={{ color: 'white' }}
   118                  startIcon={<DynamicComponentNoProps component={page.icon}/>}
   119                >
   120                  {page.title}
   121                </Button>
   122              ))}
   123            </Box>
   124            <UserActions />
   125          </Toolbar>
   126        </AppBar>
   127      </TopBarContextProvider>
   128    );
   129  };
   130  
   131  export default TopBar;