Skip to content

Commit

Permalink
feat(dashboards): enable optional light mode for dashboards (#17232)
Browse files Browse the repository at this point in the history
* refactor(ui): distill presentation mode toggle into discreet component

* refactor(ui): introduce foundations for Light Mode

* fix(ui): ensure light mode does not affect dashboards index view

* feat(ui): enable light mode for some chart types

* refactor(ui): adapt dashboard page title to light mode

* refactor(ui): polish appearance of cells in light mode

* fix(ui): make detection of dashboard viewing more resilient and precise

* fix(ui): pass in missing prop

* feat(ui): allow gauge to render as either light or dark

* fix(ui): ensure light mode of gauge is scoped to dashboard cells and not veo

* feat(ui): refactor table graphs to conditionally render light mode

* feat(ui): enable Heatmap graphs to render in light mode

* feat(ui): enable histograms to render in light mode

* feat(ui): enable scatterplots to render in light mode

* fix(ui): remove console log

* fix(ui): update test

* refactor: calc theme state

* fix: type

* refactor: fix action types

* chore: remove dead code

* refactor(ui): rename props from "lightMode" to "theme"

* refactor(ui): make variables control bar respond to theme

* fix(ui): update mockState to match current appState shape

* fix(ui): update affected tests

* refactor(theme): remove currentPage from localStorage

* chore(ui): update changelog

* fix(ui): update test

Co-authored-by: Andrew Watkins <watts@influxdb.com>
Co-authored-by: Andrew Watkins <andrew.watkinz@gmail.com>
  • Loading branch information
3 people authored Mar 16, 2020
1 parent 0ec2b45 commit b0d459f
Show file tree
Hide file tree
Showing 36 changed files with 785 additions and 273 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

### Features

1. [17232](https://github.com/influxdata/influxdb/pull/17232): Allow dashboards to optionally be displayed in light mode
1. [17273](https://github.com/influxdata/influxdb/pull/17273): Add shell completions command for the influx cli

### Bug Fixes
Expand Down
60 changes: 40 additions & 20 deletions ui/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Libraries
import React, {SFC, ReactChildren} from 'react'
import {withRouter, WithRouterProps} from 'react-router'
import {connect} from 'react-redux'
import classnames from 'classnames'

// Components
import {AppWrapper} from '@influxdata/clockface'
Expand All @@ -13,44 +15,62 @@ import CloudNav from 'src/pageLayout/components/CloudNav'
import CloudOnly from 'src/shared/components/cloud/CloudOnly'

// Types
import {AppState} from 'src/types'
import {AppState, CurrentPage, Theme} from 'src/types'

interface StateProps {
inPresentationMode: boolean
currentPage: CurrentPage
theme: Theme
}
interface OwnProps {
children: ReactChildren
}

type Props = OwnProps & StateProps

const App: SFC<Props> = ({children, inPresentationMode}) => (
<>
<CloudOnly>
<CloudNav />
</CloudOnly>
<AppWrapper presentationMode={inPresentationMode}>
<Notifications />
<TooltipPortal />
<NotesPortal />
<OverlayController />
<Nav />
{children}
</AppWrapper>
</>
)
type Props = OwnProps & StateProps & WithRouterProps

const App: SFC<Props> = ({
children,
inPresentationMode,
currentPage,
theme,
}) => {
const appWrapperClass = classnames('', {
'dashboard-light-mode': currentPage === 'dashboard' && theme === 'light',
})

return (
<>
<CloudOnly>
<CloudNav />
</CloudOnly>
<AppWrapper
presentationMode={inPresentationMode}
className={appWrapperClass}
>
<Notifications />
<TooltipPortal />
<NotesPortal />
<OverlayController />
<Nav />
{children}
</AppWrapper>
</>
)
}

const mstp = (state: AppState): StateProps => {
const {
app: {
ephemeral: {inPresentationMode},
persisted: {theme},
},
currentPage,
} = state

return {inPresentationMode}
return {inPresentationMode, currentPage, theme}
}

export default connect<StateProps, {}>(
mstp,
null
)(App)
)(withRouter(App))
32 changes: 29 additions & 3 deletions ui/src/dashboards/components/DashboardContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import DashboardPage from 'src/dashboards/components/DashboardPage'
import GetTimeRange from 'src/dashboards/components/GetTimeRange'
import DashboardRoute from 'src/shared/components/DashboardRoute'

// Actions
import {setCurrentPage} from 'src/shared/reducers/currentPage'

// Utils
import {GlobalAutoRefresher} from 'src/utils/AutoRefresher'

Expand All @@ -25,9 +28,18 @@ interface StateProps {
dashboard: string
}

type Props = StateProps
interface DispatchProps {
onSetCurrentPage: typeof setCurrentPage
}

type Props = StateProps & DispatchProps

const DashboardContainer: FC<Props> = ({autoRefresh, dashboard, children}) => {
const DashboardContainer: FC<Props> = ({
autoRefresh,
dashboard,
children,
onSetCurrentPage,
}) => {
useEffect(() => {
if (autoRefresh.status === Active) {
GlobalAutoRefresher.poll(autoRefresh.interval)
Expand All @@ -41,6 +53,13 @@ const DashboardContainer: FC<Props> = ({autoRefresh, dashboard, children}) => {
}
}, [autoRefresh.status, autoRefresh.interval])

useEffect(() => {
onSetCurrentPage('dashboard')
return () => {
onSetCurrentPage('not set')
}
}, [])

return (
<DashboardRoute>
<GetResource resources={[{type: ResourceType.Dashboards, id: dashboard}]}>
Expand All @@ -63,4 +82,11 @@ const mstp = (state: AppState): StateProps => {
}
}

export default connect<StateProps>(mstp)(DashboardContainer)
const mdtp: DispatchProps = {
onSetCurrentPage: setCurrentPage,
}

export default connect<StateProps, DispatchProps>(
mstp,
mdtp
)(DashboardContainer)
24 changes: 5 additions & 19 deletions ui/src/dashboards/components/DashboardHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,14 @@ import {withRouter, WithRouterProps} from 'react-router'
// Components
import AutoRefreshDropdown from 'src/shared/components/dropdown_auto_refresh/AutoRefreshDropdown'
import TimeRangeDropdown from 'src/shared/components/TimeRangeDropdown'
import PresentationModeToggle from 'src/shared/components/PresentationModeToggle'
import DashboardLightModeToggle from 'src/dashboards/components/DashboardLightModeToggle'
import GraphTips from 'src/shared/components/graph_tips/GraphTips'
import RenamablePageTitle from 'src/pageLayout/components/RenamablePageTitle'
import TimeZoneDropdown from 'src/shared/components/TimeZoneDropdown'
import {
SquareButton,
Button,
IconFont,
ComponentColor,
Page,
} from '@influxdata/clockface'
import {Button, IconFont, ComponentColor, Page} from '@influxdata/clockface'

// Actions
import {delayEnablePresentationMode} from 'src/shared/actions/app'
import {toggleShowVariablesControls} from 'src/userSettings/actions'
import {updateDashboard} from 'src/dashboards/actions/thunks'
import {
Expand Down Expand Up @@ -65,7 +60,6 @@ interface StateProps {
}

interface DispatchProps {
handleClickPresentationButton: typeof delayEnablePresentationMode
toggleShowVariablesControls: typeof toggleShowVariablesControls
updateDashboard: typeof updateDashboard
onSetAutoRefreshStatus: typeof setAutoRefreshStatus
Expand Down Expand Up @@ -121,11 +115,8 @@ class DashboardHeader extends Component<Props> {
: ComponentColor.Default
}
/>
<SquareButton
icon={IconFont.ExpandA}
titleText="Enter Presentation Mode"
onClick={this.handleClickPresentationButton}
/>
<DashboardLightModeToggle />
<PresentationModeToggle />
<GraphTips />
</Page.ControlBarLeft>
<Page.ControlBarRight>
Expand Down Expand Up @@ -161,10 +152,6 @@ class DashboardHeader extends Component<Props> {
updateDashboard(dashboard.id, {name})
}

private handleClickPresentationButton = (): void => {
this.props.handleClickPresentationButton()
}

private handleChooseAutoRefresh = (milliseconds: number) => {
const {
handleChooseAutoRefresh,
Expand Down Expand Up @@ -234,7 +221,6 @@ const mstp = (state: AppState): StateProps => {
const mdtp: DispatchProps = {
toggleShowVariablesControls: toggleShowVariablesControls,
updateDashboard: updateDashboard,
handleClickPresentationButton: delayEnablePresentationMode,
onSetAutoRefreshStatus: setAutoRefreshStatus,
updateQueryParams: updateQueryParams,
setDashboardTimeRange: setDashboardTimeRange,
Expand Down
106 changes: 106 additions & 0 deletions ui/src/dashboards/components/DashboardLightMode.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
Light Mode for Dashboards
------------------------------------------------------------------------------
*/

.clockface--app-wrapper.dashboard-light-mode {
background-color: $g18-cloud;
color: $g8-storm;

.cf-page-contents > .cf-dapper-scrollbars--track-y {
background-color: $g15-platinum !important;
}

.cf-page--sub-title {
color: $g13-mist;
}

.cell {
background-color: $g20-white;
}

.cell--dot-grid,
.cell--dot-grid:before,
.cell--dot-grid:after {
background-color: $g13-mist;
}

.cell:hover .cell--dot-grid,
.cell:hover .cell--dot-grid:before,
.cell:hover .cell--dot-grid:after {
background-color: $g8-storm;
}

.cell:hover .cell--draggable:hover .cell--dot-grid,
.cell:hover .cell--draggable:hover .cell--dot-grid:before,
.cell:hover .cell--draggable:hover .cell--dot-grid:after {
background-color: $c-pool;
}

.cell--context {
color: $g13-mist;
}
.cell:hover .cell--context {
color: $g8-storm;
}
.cell:hover .cell--context:hover,
.cell .cell--context.cell--context__active,
.cell:hover .cell--context.cell--context__active {
color: $c-pool;
}

.cell--note-indicator {
color: $g13-mist;

&.cell--note-indicator__active,
&:hover,
.cell:hover &:hover {
color: $c-pool;
}
}

.markdown-format {
color: $g7-graphite;

code {
font-weight: 700;
color: $c-star;
}
}

.cell--view-empty {
color: $g11-sidewalk;
}
.variables-control-bar--empty,
.variables-control-bar--full {
background-color: $g20-white;
}
}

/*
Light Mode Cells
------------------------------------------------------------------------------
*/

.clockface--app-wrapper.dashboard-light-mode {
.react-resizable-handle {
border-right-color: $g14-chromium;
border-bottom-color: $g14-chromium;

&:before,
&:after {
background-color: $g20-white;
}

&:hover {
border-right-color: $c-comet;
border-bottom-color: $c-comet;
}
}
.react-grid-item.resizing .react-resizable-handle,
.react-grid-item.react-draggable-dragging .react-resizable-handle {
opacity: 1;
border-right-color: $c-comet;
border-bottom-color: $c-comet;
}
}
66 changes: 66 additions & 0 deletions ui/src/dashboards/components/DashboardLightModeToggle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Libraries
import React, {FC} from 'react'
import {connect} from 'react-redux'

// Components
import {SelectGroup} from '@influxdata/clockface'

// Actions
import {setTheme} from 'src/shared/actions/app'

// Types
import {AppState, Theme} from 'src/types'

interface StateProps {
theme: Theme
}

interface DispatchProps {
onSetTheme: typeof setTheme
}

interface OwnProps {}

type Props = OwnProps & StateProps & DispatchProps

const DashboardLightModeToggle: FC<Props> = ({theme, onSetTheme}) => {
return (
<SelectGroup testID="presentation-mode-toggle">
<SelectGroup.Option
onClick={() => onSetTheme('dark')}
value={false}
id="presentation-mode-toggle--dark"
active={theme === 'dark'}
>
Dark
</SelectGroup.Option>
<SelectGroup.Option
onClick={() => onSetTheme('light')}
id="presentation-mode-toggle--light"
value={true}
active={theme === 'light'}
>
Light
</SelectGroup.Option>
</SelectGroup>
)
}

const mstp = (state: AppState): StateProps => {
const {
app: {
persisted: {theme},
},
} = state

return {theme}
}

const mdtp: DispatchProps = {
onSetTheme: setTheme,
}

export default connect<StateProps, DispatchProps, OwnProps>(
mstp,
mdtp
)(DashboardLightModeToggle)
Loading

0 comments on commit b0d459f

Please sign in to comment.