refactor(ui): implement cloud top nav design (#16470)
* refactor: add stylesheet for cloud nav * refactor: remove cloud icon from side nav * refactor: move cloud nav to top of app * chore: add declaration so PNG files are typed as any when imported * refactor: modify cloud nav to use specified components * fix: Remove comment * refactor: update nav item text * refactor: do not show logout in sidenav for cloud users * refactor: add unique class for google tag manager * chore: update changelog * refactor: don't render user menu if org isn't available * chore: add image file for logo Adds-Binary: ui/src/pageLayout/images/influxdata-logo.png * chore: prettier and eslintpull/16494/head
parent
ba7502aaf5
commit
63b3a07281
|
@ -1,3 +1,9 @@
|
|||
## v2.0.0-beta.2 [Unreleased]
|
||||
|
||||
### UI Improvements
|
||||
|
||||
1. [16203](https://github.com/influxdata/influxdb/pull/16203): Move cloud navigation to top of page instead of within left side navigation
|
||||
|
||||
## v2.0.0-beta.1 [2020-01-08]
|
||||
|
||||
### Features
|
||||
|
|
|
@ -647,16 +647,14 @@ describe('DataExplorer', () => {
|
|||
|
||||
describe('as a task', () => {
|
||||
beforeEach(() => {
|
||||
cy.getByTestID('task--radio-button')
|
||||
.click()
|
||||
cy.getByTestID('task--radio-button').click()
|
||||
})
|
||||
|
||||
it('should autoselect the first bucket', () => {
|
||||
cy.getByTestID('task-options-bucket-dropdown--button').within(() => {
|
||||
cy.get('span.cf-dropdown--selected')
|
||||
.then((elem) => {
|
||||
expect(elem.text()).to.include('defbuck')
|
||||
})
|
||||
cy.get('span.cf-dropdown--selected').then(elem => {
|
||||
expect(elem.text()).to.include('defbuck')
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -2,3 +2,4 @@
|
|||
// got some globals here that only exist during compilation
|
||||
//
|
||||
|
||||
declare module '*.png'
|
||||
|
|
|
@ -9,6 +9,8 @@ import TooltipPortal from 'src/portals/TooltipPortal'
|
|||
import NotesPortal from 'src/portals/NotesPortal'
|
||||
import Notifications from 'src/shared/components/notifications/Notifications'
|
||||
import OverlayController from 'src/overlays/components/OverlayController'
|
||||
import CloudNav from 'src/pageLayout/components/CloudNav'
|
||||
import CloudOnly from 'src/shared/components/cloud/CloudOnly'
|
||||
|
||||
// Types
|
||||
import {AppState} from 'src/types'
|
||||
|
@ -23,14 +25,19 @@ interface OwnProps {
|
|||
type Props = OwnProps & StateProps
|
||||
|
||||
const App: SFC<Props> = ({children, inPresentationMode}) => (
|
||||
<AppWrapper presentationMode={inPresentationMode}>
|
||||
<Notifications />
|
||||
<TooltipPortal />
|
||||
<NotesPortal />
|
||||
<OverlayController />
|
||||
<Nav />
|
||||
{children}
|
||||
</AppWrapper>
|
||||
<>
|
||||
<CloudOnly>
|
||||
<CloudNav />
|
||||
</CloudOnly>
|
||||
<AppWrapper presentationMode={inPresentationMode}>
|
||||
<Notifications />
|
||||
<TooltipPortal />
|
||||
<NotesPortal />
|
||||
<OverlayController />
|
||||
<Nav />
|
||||
{children}
|
||||
</AppWrapper>
|
||||
</>
|
||||
)
|
||||
|
||||
const mstp = (state: AppState): StateProps => {
|
||||
|
|
|
@ -30,30 +30,26 @@ class AccountNavSubItem extends PureComponent<Props> {
|
|||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<CloudExclude key="feature-flag">
|
||||
{orgs.length > 1 && (
|
||||
<NavMenu.SubItem
|
||||
titleLink={className => (
|
||||
<div onClick={showOrganizationsView} className={className}>
|
||||
Switch Organizations
|
||||
</div>
|
||||
)}
|
||||
active={false}
|
||||
key="switch-orgs"
|
||||
/>
|
||||
)}
|
||||
|
||||
<CloudExclude key="feature-flag">
|
||||
{orgs.length > 1 && (
|
||||
<NavMenu.SubItem
|
||||
titleLink={className => (
|
||||
<Link to="/orgs/new" className={className}>
|
||||
Create Organization
|
||||
</Link>
|
||||
<div onClick={showOrganizationsView} className={className}>
|
||||
Switch Organizations
|
||||
</div>
|
||||
)}
|
||||
active={false}
|
||||
key="switch-orgs"
|
||||
/>
|
||||
</CloudExclude>
|
||||
|
||||
)}
|
||||
<NavMenu.SubItem
|
||||
titleLink={className => (
|
||||
<Link to="/orgs/new" className={className}>
|
||||
Create Organization
|
||||
</Link>
|
||||
)}
|
||||
active={false}
|
||||
/>
|
||||
<NavMenu.SubItem
|
||||
titleLink={className => (
|
||||
<Link to="/logout" className={className}>
|
||||
|
@ -63,7 +59,7 @@ class AccountNavSubItem extends PureComponent<Props> {
|
|||
active={false}
|
||||
key="logout"
|
||||
/>
|
||||
</>
|
||||
</CloudExclude>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
CloudNav
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
.cloud-nav {
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
.cloud-nav--logo {
|
||||
display: inline-block;
|
||||
height: 26px;
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
.cloud-nav--logo-link {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.cloud-nav--account {
|
||||
width: 100%;
|
||||
padding: 6px 16px 8px 16px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: $c-neutrino;
|
||||
margin: 0;
|
||||
display: block;
|
||||
user-select: none;
|
||||
position: relative;
|
||||
|
||||
strong {
|
||||
font-weight: 900;
|
||||
color: $g20-white;
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
height: $ix-border;
|
||||
@include gradient-h($c-ocean, $c-amethyst);
|
||||
}
|
||||
}
|
|
@ -1,63 +1,111 @@
|
|||
import React, {PureComponent} from 'react'
|
||||
// Libraries
|
||||
import React, {FC} from 'react'
|
||||
import {Link} from 'react-router'
|
||||
import {connect} from 'react-redux'
|
||||
|
||||
// Components
|
||||
import {FeatureFlag} from 'src/shared/utils/featureFlag'
|
||||
import {NavMenu, Icon} from '@influxdata/clockface'
|
||||
import CloudOnly from 'src/shared/components/cloud/CloudOnly'
|
||||
import {
|
||||
AppHeader,
|
||||
PopNav,
|
||||
Button,
|
||||
ComponentColor,
|
||||
FlexBox,
|
||||
FlexDirection,
|
||||
ComponentSize,
|
||||
} from '@influxdata/clockface'
|
||||
|
||||
// Constants
|
||||
import {
|
||||
CLOUD_URL,
|
||||
CLOUD_USAGE_PATH,
|
||||
CLOUD_BILLING_PATH,
|
||||
CLOUD_SIGNOUT_URL,
|
||||
} from 'src/shared/constants'
|
||||
|
||||
// Types
|
||||
import {IconFont} from '@influxdata/clockface'
|
||||
import {AppState, Organization} from 'src/types'
|
||||
|
||||
export default class CloudNav extends PureComponent {
|
||||
render() {
|
||||
// Images
|
||||
import Logo from '../images/influxdata-logo.png'
|
||||
|
||||
// Selectors
|
||||
import {getOrg} from 'src/organizations/selectors'
|
||||
|
||||
interface StateProps {
|
||||
org: Organization
|
||||
}
|
||||
|
||||
const CloudNav: FC<StateProps> = ({org}) => {
|
||||
const usageURL = `${CLOUD_URL}${CLOUD_USAGE_PATH}`
|
||||
const billingURL = `${CLOUD_URL}${CLOUD_BILLING_PATH}`
|
||||
const handleUpgradeClick = () => {
|
||||
window.location.assign(billingURL)
|
||||
}
|
||||
|
||||
if (!org) {
|
||||
return (
|
||||
<CloudOnly>
|
||||
<NavMenu.Item
|
||||
active={false}
|
||||
titleLink={className => (
|
||||
<a className={className} href={this.usageURL}>
|
||||
Usage
|
||||
</a>
|
||||
)}
|
||||
iconLink={className => (
|
||||
<a className={className} href={this.usageURL}>
|
||||
<Icon glyph={IconFont.Cloud} />
|
||||
</a>
|
||||
)}
|
||||
>
|
||||
<AppHeader className="cloud-nav">
|
||||
<AppHeader.Logo>
|
||||
<img className="cloud-nav--logo" alt="InfluxData Logo" src={Logo} />
|
||||
</AppHeader.Logo>
|
||||
</AppHeader>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<AppHeader className="cloud-nav">
|
||||
<AppHeader.Logo>
|
||||
<Link to={`/orgs/${org.id}`} className="cloud-nav--logo-link">
|
||||
<img className="cloud-nav--logo" alt="InfluxData Logo" src={Logo} />
|
||||
</Link>
|
||||
</AppHeader.Logo>
|
||||
<FlexBox direction={FlexDirection.Row} margin={ComponentSize.Medium}>
|
||||
<Button
|
||||
color={ComponentColor.Success}
|
||||
text="Upgrade"
|
||||
onClick={handleUpgradeClick}
|
||||
className="upgrade-payg--button"
|
||||
/>
|
||||
<PopNav>
|
||||
<p className="cloud-nav--account">
|
||||
Logged in as <strong>{org.name}</strong>
|
||||
</p>
|
||||
<PopNav.Item
|
||||
active={false}
|
||||
titleLink={className => (
|
||||
<a className={className} href={usageURL}>
|
||||
Usage
|
||||
</a>
|
||||
)}
|
||||
/>
|
||||
<FeatureFlag name="cloudBilling">
|
||||
<NavMenu.SubItem
|
||||
<PopNav.Item
|
||||
active={false}
|
||||
titleLink={className => (
|
||||
<a className={className} href={this.usageURL}>
|
||||
Usage
|
||||
</a>
|
||||
)}
|
||||
/>
|
||||
<NavMenu.SubItem
|
||||
active={false}
|
||||
titleLink={className => (
|
||||
<a className={className} href={this.billingURL}>
|
||||
<a className={className} href={billingURL}>
|
||||
Billing
|
||||
</a>
|
||||
)}
|
||||
/>
|
||||
</FeatureFlag>
|
||||
</NavMenu.Item>
|
||||
</CloudOnly>
|
||||
)
|
||||
}
|
||||
|
||||
private get usageURL(): string {
|
||||
return `${CLOUD_URL}${CLOUD_USAGE_PATH}`
|
||||
}
|
||||
|
||||
private get billingURL(): string {
|
||||
return `${CLOUD_URL}${CLOUD_BILLING_PATH}`
|
||||
}
|
||||
<PopNav.Item
|
||||
active={false}
|
||||
titleLink={className => (
|
||||
<a className={className} href={CLOUD_SIGNOUT_URL}>
|
||||
Logout
|
||||
</a>
|
||||
)}
|
||||
/>
|
||||
</PopNav>
|
||||
</FlexBox>
|
||||
</AppHeader>
|
||||
)
|
||||
}
|
||||
|
||||
const mstp = (state: AppState) => {
|
||||
const org = getOrg(state)
|
||||
return {org}
|
||||
}
|
||||
|
||||
export default connect<StateProps>(mstp)(CloudNav)
|
||||
|
|
|
@ -6,7 +6,6 @@ import {get} from 'lodash'
|
|||
|
||||
// Components
|
||||
import {NavMenu, Icon} from '@influxdata/clockface'
|
||||
import CloudNav from 'src/pageLayout/components/CloudNav'
|
||||
import AccountNavSubItem from 'src/pageLayout/components/AccountNavSubItem'
|
||||
import CloudExclude from 'src/shared/components/cloud/CloudExclude'
|
||||
import CloudOnly from 'src/shared/components/cloud/CloudOnly'
|
||||
|
@ -96,7 +95,7 @@ class SideNav extends PureComponent<Props, State> {
|
|||
<NavMenu.Item
|
||||
titleLink={className => (
|
||||
<Link className={className} to={orgPrefix}>
|
||||
<CloudOnly>{me.name}</CloudOnly>
|
||||
<CloudOnly>Getting Started</CloudOnly>
|
||||
<CloudExclude>{`${me.name} (${orgName})`}</CloudExclude>
|
||||
</Link>
|
||||
)}
|
||||
|
@ -309,7 +308,6 @@ class SideNav extends PureComponent<Props, State> {
|
|||
key="profile"
|
||||
/>
|
||||
</NavMenu.Item>
|
||||
<CloudNav />
|
||||
<NavMenu.Item
|
||||
titleLink={className => (
|
||||
<a className={className} href={feedbackLink} target="_blank">
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 9.8 KiB |
|
@ -81,6 +81,7 @@
|
|||
@import 'src/me/graphics/DashboardingGraphic.scss';
|
||||
@import 'src/me/graphics/CollectorGraphic.scss';
|
||||
@import 'src/pageLayout/components/RenamablePageTitle.scss';
|
||||
@import 'src/pageLayout/components/CloudNav.scss';
|
||||
@import 'src/timeMachine/components/SelectorList.scss';
|
||||
@import 'src/timeMachine/components/Queries.scss';
|
||||
@import 'src/timeMachine/components/EditorShortcutsTooltip.scss';
|
||||
|
|
|
@ -125,8 +125,9 @@ class TaskOptionsBucketDropdown extends PureComponent<Props> {
|
|||
}
|
||||
|
||||
const mstp = (state: AppState): StateProps => {
|
||||
const buckets = getAll<Bucket>(state, ResourceType.Buckets)
|
||||
.filter((bucket: Bucket): boolean => bucket.type !== 'system')
|
||||
const buckets = getAll<Bucket>(state, ResourceType.Buckets).filter(
|
||||
(bucket: Bucket): boolean => bucket.type !== 'system'
|
||||
)
|
||||
const status = getStatus(state, ResourceType.Buckets)
|
||||
|
||||
return {
|
||||
|
|
Loading…
Reference in New Issue