Skip to content

Commit

Permalink
feat: navbar navigation dropdown (#511)
Browse files Browse the repository at this point in the history
* feat: navbar navigstion dropdown
* chore: storybook update
* chore: fix test + add base readme

Signed-off-by: Nastya <[email protected]>
  • Loading branch information
anrusina authored Jun 16, 2022
1 parent 32686cc commit 1386b40
Show file tree
Hide file tree
Showing 11 changed files with 563 additions and 68 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ OR
necessary when hosting the API and console on the same domain (with prefixes of
`/api/v1` and `/console` for example). For local development, this is
usually not needed, so the default behavior is to run without a prefix.
* `FLYTE_NAVIGATION` (default: `undefined`)
UI related. Allows you to change colors of the navigation bar and add links
to other internal pages or external sites. **[More info](packages/zapp/console/src/components/Navigation/Readme.md)**
### Running from docker image as localhost
Expand Down Expand Up @@ -136,6 +141,11 @@ will be stalled until the bundles have finished. The application will be accessi
at http://localhost:3000 (if using the default port).
### 🎱 Using items in your own application
* Authorize your app to call flyte admin api. **[More info](packages/plugins/flyte-api/README.md)**
## 🛠 Development
For continious development we are using:
Expand Down
3 changes: 3 additions & 0 deletions packages/zapp/console/env.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ const STATUS_URL = process.env.STATUS_URL;
const ENABLE_GA = process.env.ENABLE_GA || false;
const GA_TRACKING_ID = process.env.GA_TRACKING_ID || 'G-0QW4DJWJ20';

const FLYTE_NAVIGATION = process.env.FLYTE_NAVIGATION || '';

module.exports = {
ADMIN_API_URL,
ADMIN_API_USE_SSL,
Expand All @@ -58,5 +60,6 @@ module.exports = {
GA_TRACKING_ID,
NODE_ENV,
STATUS_URL,
FLYTE_NAVIGATION,
},
};
6 changes: 3 additions & 3 deletions packages/zapp/console/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
"@types/pure-render-decorator": "^0.2.27",
"@types/react": "^16.9.34",
"@types/react-dom": "^16.9.7",
"@types/react-router-dom": "^4.3.2",
"@types/react-router-dom": "^5.3.3",
"@types/react-virtualized": "^9.21.4",
"@types/serve-static": "^1.7.31",
"@types/shallowequal": "^0.2.3",
Expand Down Expand Up @@ -141,8 +141,8 @@
"react-loading-skeleton": "^1.1.2",
"react-query": "^3.3.0",
"react-query-devtools": "^3.0.0-beta",
"react-router": "^5.0.1",
"react-router-dom": "^5.0.1",
"react-router": "^5.2.0",
"react-router-dom": "^5.2.0",
"react-virtualized": "^9.21.1",
"resolve-url-loader": "^5.0.0",
"semantic-release": "^19.0.3",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import { Routes } from 'routes/routes';
import { FeatureFlag, useFeatureFlag } from 'basics/FeatureFlags';
import { useAdminVersion } from 'components/hooks/useVersion';
import { env } from 'common/env';
import { NavigationDropdown } from './NavigationDropdown';
import { UserInformation } from './UserInformation';
import { OnlyMine } from './OnlyMine';
import { FlyteNavItem } from './utils';
import t, { patternKey } from './strings';

const { version: platformVersion } = require('../../../package.json');
Expand All @@ -24,8 +26,12 @@ const useStyles = makeStyles((theme: Theme) => ({
},
}));

interface DefaultAppBarProps {
items: FlyteNavItem[];
}

/** Renders the default content for the app bar, which is the logo and help links */
export const DefaultAppBarContent: React.FC = () => {
export const DefaultAppBarContent = (props: DefaultAppBarProps) => {
const commonStyles = useCommonStyles();
const styles = useStyles();

Expand Down Expand Up @@ -55,6 +61,7 @@ export const DefaultAppBarContent: React.FC = () => {
<Link className={classnames(commonStyles.linkUnstyled)} to={Routes.SelectProject.path}>
<FlyteLogo size={32} />
</Link>
{props.items?.length > 0 ? <NavigationDropdown items={props.items} /> : false}
<div className={styles.spacer} />
{isFlagEnabled && <OnlyMine />}
<UserInformation />
Expand Down
27 changes: 21 additions & 6 deletions packages/zapp/console/src/components/Navigation/NavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,30 @@ import Toolbar from '@material-ui/core/Toolbar';
import { navBarContentId } from 'common/constants';
import * as React from 'react';
import { DefaultAppBarContent } from './DefaultAppBarContent';
import { FlyteNavigation, getFlyteNavigationData } from './utils';

export interface NavBarProps {
useCustomContent?: boolean;
navigationData?: FlyteNavigation;
}

/** Contains all content in the top navbar of the application. */
export const NavBar: React.FC<{ useCustomContent?: boolean }> = ({
/** Allow injection of custom content. */
useCustomContent = false,
}) => {
const content = useCustomContent ? <div id={navBarContentId} /> : <DefaultAppBarContent />;
export const NavBar = (props: NavBarProps) => {
const navData = props.navigationData ?? getFlyteNavigationData();
const content = props.useCustomContent ? (
<div id={navBarContentId} />
) : (
<DefaultAppBarContent items={navData?.items ?? []} />
);

return (
<AppBar color="secondary" elevation={0} id="navbar" position="fixed">
<AppBar
color="secondary"
elevation={0}
id="navbar"
position="fixed"
style={{ color: navData?.color, background: navData?.background }}
>
<Toolbar id={navBarContentId}>{content}</Toolbar>
</AppBar>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import * as React from 'react';
import { makeStyles, Theme } from '@material-ui/core/styles';
import { MenuItem, Select } from '@material-ui/core';
import { useHistory } from 'react-router-dom';
import { makeRoute } from 'routes/utils';
import { headerFontFamily } from 'components/Theme/constants';
import { FlyteNavItem } from './utils';

const useStyles = makeStyles((theme: Theme) => ({
selectStyling: {
minWidth: '120px',
margin: theme.spacing(0, 2),
color: 'inherit',
'&:hover': {
color: 'inherit',
},
'&:before, &:after, &:not(.Mui-disabled):hover::before': {
border: 'none',
},
},
colorInherit: {
color: 'inherit',
fontFamily: headerFontFamily,
fontWeight: 600,
lineHeight: 1.75,
},
}));

interface NavigationDropdownProps {
items: FlyteNavItem[];
}

// Flyte Console list item - always there ans is first in the list
const ConsoleItem: FlyteNavItem = {
title: 'Console',
url: makeRoute('/'),
};

/** Renders the default content for the app bar, which is the logo and help links */
export const NavigationDropdown = (props: NavigationDropdownProps) => {
const [selectedPage, setSelectedPage] = React.useState<string>(ConsoleItem.title);
const [open, setOpen] = React.useState(false);

const history = useHistory();
const styles = useStyles();

const handleItemSelection = (item: FlyteNavItem) => {
setSelectedPage(item.title);

if (item.url.startsWith('/')) {
// local navigation without BASE_URL addition
history.push(item.url);
} else {
// external navigation
window.location.assign(item.url);
}
};

return (
<Select
labelId="demo-controlled-open-select-label"
id="demo-controlled-open-select"
open={open}
onClose={() => setOpen(false)}
onOpen={() => setOpen(true)}
value={selectedPage}
className={styles.selectStyling}
classes={{
// update color of text and icon
root: styles.colorInherit,
icon: styles.colorInherit,
}}
MenuProps={{
anchorOrigin: {
vertical: 'bottom',
horizontal: 'left',
},
transformOrigin: {
vertical: 'top',
horizontal: 'left',
},
getContentAnchorEl: null,
}}
>
<MenuItem
key={ConsoleItem.title}
value={ConsoleItem.title}
onClick={() => handleItemSelection(ConsoleItem)}
>
{ConsoleItem.title}
</MenuItem>
{props.items.map((item) => (
<MenuItem key={item.title} value={item.title} onClick={() => handleItemSelection(item)}>
{item.title}
</MenuItem>
))}
</Select>
);
};
47 changes: 47 additions & 0 deletions packages/zapp/console/src/components/Navigation/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
## Customize NavBar component

From this point forward you can modify your FlyteConsole navigatio bar by:

- using your company colors
- providing entrypoint navigation to sites, or places inside flyteconsole.

To use it you will need to define `FLYTE_NAVIGATION` environment variable during the build.

If you are building locally add next or similar export to your `.zshrc` (or equivalent) file:

```bash
export FLYTE_NAVIGATION='{"color":"white","background":"black","items":[{"title":"Hosted","url":"https://hosted.cloud-staging.union.ai/dashboard"}, {"title":"Dashboard","url":"/projects/flytesnacks/executions?domain=development&duration=all"},{"title":"Execution", "url":"/projects/flytesnacks/domains/development/executions/awf2lx4g58htr8svwb7x?duration=all"}]}'
```

If you are building a docker image - modify [Makefile](./Makefile) `build_prod` step to include FLYTE_NAVIGATION setup.

### The structure of FLYTE_NAVIGATION

Essentially FLYTE_NAVIGATION is a JSON object

```
{
color:"white", // default NavBar text color
background:"black", // default NavBar background color
items:[
{title:"Remote", url:"https://remote.site/"},
{title:"Dashboard", url:"/projects/flytesnacks/executions?domain=development&duration=all"},
{title:"Execution", url:"/projects/flytesnacks/domains/development/executions/awf2lx4g58htr8svwb7x?duration=all"}
]
}
```

If at least one item in `items` array is present the dropdown will appear in NavBar main view.
It will contain at least two items:

- default "Console" item which navigates to ${BASE_URL}
- all items you have provided

Feel free to play around with the views in Storybook:

<img width="874" alt="Screen Shot 2022-06-15 at 2 01 29 PM" src="https://user-images.githubusercontent.com/55718143/173962811-a3603d6c-3fe4-4cab-b57a-4d4806c88cfc.png">


#### Note

Please let us know in [Slack #flyte-console](https://flyte-org.slack.com/archives/CTJJLM8BY) channel if you found bugs or need more support than.
Loading

0 comments on commit 1386b40

Please sign in to comment.