Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: navbar navigation dropdown #511

Merged
merged 5 commits into from
Jun 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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