Skip to content

Commit

Permalink
feat(dashboard): add ability to change order of variable dropdowns
Browse files Browse the repository at this point in the history
  • Loading branch information
AlirieGray committed Mar 22, 2019
1 parent 8196a00 commit 678f4a3
Show file tree
Hide file tree
Showing 11 changed files with 242 additions and 23 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
1. [12655](https://github.com/influxdata/influxdb/pull/12655): Add a variable control bar to dashboards to select values for variables.
1. [12706](https://github.com/influxdata/influxdb/pull/12706): Add ability to add variable to script from the side menu.
1. [12791](https://github.com/influxdata/influxdb/pull/12791): Use time range for metaqueries in Data Explorer and Cell Editor Overlay
1. [12827](https://github.com/influxdata/influxdb/pull/12827): Fix screen tearing bug in Raw Data View
1. [12821](https://github.com/influxdata/influxdb/pull/12821): Allow variables to be re-ordered within control bar on a dashboard.

### Bug Fixes

Expand All @@ -17,6 +17,7 @@
1. [12790](https://github.com/influxdata/influxdb/pull/12790): Fix bucket creation error when changing rentention rules types.
1. [12793](https://github.com/influxdata/influxdb/pull/12793): Fix task creation error when switching schedule types.
1. [12805](https://github.com/influxdata/influxdb/pull/12805): Fix hidden horizonal scrollbars in flux raw data view
1. [12827](https://github.com/influxdata/influxdb/pull/12827): Fix screen tearing bug in Raw Data View

### UI Improvements

Expand Down
118 changes: 118 additions & 0 deletions ui/src/dashboards/components/variablesControlBar/DraggableDropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// Libraries
import * as React from 'react'
import {
DragSource,
DropTarget,
ConnectDropTarget,
ConnectDragSource,
DropTargetConnector,
DragSourceConnector,
DragSourceMonitor,
} from 'react-dnd'
import classnames from 'classnames'

// Components
import VariableDropdown from './VariableDropdown'

// Constants
const dropdownType = 'dropdown'

const dropdownSource = {
beginDrag(props: Props) {
return {
id: props.id,
index: props.index,
}
},
}

interface Props {
id: string
index: number
name: string
moveDropdown: (dragIndex: number, hoverIndex: number) => void
dashboardID: string
}

interface DropdownSourceCollectedProps {
isDragging: boolean
connectDragSource: ConnectDragSource
}

interface DropdownTargetCollectedProps {
connectDropTarget?: ConnectDropTarget
}

const dropdownTarget = {
hover(props, monitor, component) {
if (!component) {
return null
}
const dragIndex = monitor.getItem().index
const hoverIndex = props.index

// Don't replace items with themselves
if (dragIndex === hoverIndex) {
return
}

// Time to actually perform the action
props.moveDropdown(dragIndex, hoverIndex)

monitor.getItem().index = hoverIndex
},
}

class Dropdown extends React.Component<
Props & DropdownSourceCollectedProps & DropdownTargetCollectedProps
> {
public render() {
const {
name,
id,
dashboardID,
isDragging,
connectDragSource,
connectDropTarget,
} = this.props

const className = classnames('variable-dropdown', {
'variable-dropdown__dragging': isDragging,
})

return connectDragSource(
connectDropTarget(
<div style={{display: 'inline-block'}}>
<div className={className}>
{/* TODO: Add variable description to title attribute when it is ready */}
<div className="variable-dropdown--label">
<div className="customizable-field--drag">
<span className="hamburger" />
</div>
<span>{name}</span>
</div>
<div className="variable-dropdown--placeholder" />
<VariableDropdown variableID={id} dashboardID={dashboardID} />
</div>
</div>
)
)
}
}

export default DropTarget<Props & DropdownTargetCollectedProps>(
dropdownType,
dropdownTarget,
(connect: DropTargetConnector) => ({
connectDropTarget: connect.dropTarget(),
})
)(
DragSource<Props & DropdownSourceCollectedProps>(
dropdownType,
dropdownSource,
(connect: DragSourceConnector, monitor: DragSourceMonitor) => ({
connectDragSource: connect.dragSource(),
isDragging: monitor.isDragging(),
})
)(Dropdown)
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
display: flex;
flex-direction: row;
height: $form-sm-height;
position: relative;
border-radius: $radius;
}

.variable-dropdown--dropdown {
Expand All @@ -21,14 +23,33 @@
color: $c-comet;
white-space: nowrap;
overflow: hidden;
padding: 0 $form-sm-padding;
padding: 0 $form-sm-padding 0 0;
border-radius: $radius 0 0 $radius;
background-color: $g3-castle;
background-attachment: fixed;
display: flex;

> span {
@include gradient-h($c-comet, $c-laser);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
}

.variable-dropdown--placeholder {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
border-radius: $radius;
@include gradient-h($c-comet, $c-pool);
opacity: 0;
pointer-events: none;
z-index: 2;
transition: opacity 0.25s ease;

.variable-dropdown__dragging & {
opacity: 1;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ interface DispatchProps {
}

interface OwnProps {
name: string
variableID: string
dashboardID: string
}
Expand All @@ -38,15 +37,12 @@ type Props = StateProps & DispatchProps & OwnProps

class VariableDropdown extends PureComponent<Props> {
render() {
const {name, selectedValue} = this.props
const {selectedValue} = this.props
const dropdownValues = this.props.values || []

return (
<div className="variable-dropdown">
{/* TODO: Add variable description to title attribute when it is ready */}
<div className="variable-dropdown--label">
<span>{name}</span>
</div>
<Dropdown
selectedID={selectedValue}
onChange={this.handleSelect}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
// Libraries
import React, {PureComponent} from 'react'
import {connect} from 'react-redux'
import _ from 'lodash'
import {isEmpty} from 'lodash'
import {DragDropContext} from 'react-dnd'
import HTML5Backend from 'react-dnd-html5-backend'

// Components
import VariableDropdown from 'src/dashboards/components/variablesControlBar/VariableDropdown'
// import VariableDropdown from 'src/dashboards/components/variablesControlBar/VariableDropdown'
import {EmptyState, ComponentSize} from 'src/clockface'
import {TechnoSpinner} from '@influxdata/clockface'

Expand All @@ -14,13 +16,20 @@ import {
getDashboardValuesStatus,
} from 'src/variables/selectors'

// Styles
import 'src/dashboards/components/variablesControlBar/VariablesControlBar.scss'

// Actions
import {moveVariable} from 'src/variables/actions'

// Types
import {AppState} from 'src/types/v2'
import {Variable} from '@influxdata/influx'

// Decorators
import {ErrorHandling} from 'src/shared/decorators/errors'
import {RemoteDataState} from 'src/types'
import DraggableDropdown from 'src/dashboards/components/variablesControlBar/DraggableDropdown'

interface OwnProps {
dashboardID: string
Expand All @@ -31,14 +40,18 @@ interface StateProps {
valuesStatus: RemoteDataState
}

type Props = StateProps & OwnProps
interface DispatchProps {
moveVariable: typeof moveVariable
}

type Props = StateProps & DispatchProps & OwnProps

@ErrorHandling
class VariablesControlBar extends PureComponent<Props> {
render() {
const {dashboardID, variables, valuesStatus} = this.props

if (_.isEmpty(variables)) {
if (isEmpty(variables)) {
return (
<div className="variables-control-bar">
<EmptyState
Expand All @@ -53,12 +66,14 @@ class VariablesControlBar extends PureComponent<Props> {

return (
<div className="variables-control-bar">
{variables.map(v => (
<VariableDropdown
{variables.map((v, i) => (
<DraggableDropdown
key={v.id}
name={v.name}
variableID={v.id}
id={v.id}
index={i}
dashboardID={dashboardID}
moveDropdown={this.handleMoveDropdown}
/>
))}
{valuesStatus === RemoteDataState.Loading && (
Expand All @@ -67,6 +82,18 @@ class VariablesControlBar extends PureComponent<Props> {
</div>
)
}

private handleMoveDropdown = (
originalIndex: number,
newIndex: number
): void => {
const {dashboardID, moveVariable} = this.props
moveVariable(originalIndex, newIndex, dashboardID)
}
}

const mdtp = {
moveVariable,
}

const mstp = (state: AppState, props: OwnProps): StateProps => {
Expand All @@ -76,4 +103,9 @@ const mstp = (state: AppState, props: OwnProps): StateProps => {
return {variables, valuesStatus}
}

export default connect<StateProps, {}, OwnProps>(mstp)(VariablesControlBar)
export default DragDropContext(HTML5Backend)(
connect<StateProps, DispatchProps, OwnProps>(
mstp,
mdtp
)(VariablesControlBar)
)
2 changes: 2 additions & 0 deletions ui/src/localStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export const loadLocalStorage = (): LocalStorage => {
export const saveToLocalStorage = ({
app: {persisted},
ranges,
variables,
}: LocalStorage): void => {
try {
const appPersisted = {app: {persisted}}
Expand All @@ -39,6 +40,7 @@ export const saveToLocalStorage = ({
...appPersisted,
VERSION,
ranges: normalizer(ranges),
variables,
})
)
} catch (err) {
Expand Down
2 changes: 2 additions & 0 deletions ui/src/mockState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {Provider} from 'react-redux'
import {Router, createMemoryHistory} from 'react-router'

import {render} from 'react-testing-library'
import {initialState} from 'src/variables/reducers'
import configureStore from 'src/store/configureStore'

const localState = {
Expand All @@ -24,6 +25,7 @@ const localState = {
duration: '15m',
},
],
variables: initialState(),
}

const history = createMemoryHistory({entries: ['/']})
Expand Down
2 changes: 2 additions & 0 deletions ui/src/types/localStorage.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import {AppState} from 'src/shared/reducers/app'
import {VariablesState} from 'src/variables/reducers'

export interface LocalStorage {
VERSION: string
app: AppState
ranges: any[]
variables: VariablesState
}
15 changes: 15 additions & 0 deletions ui/src/variables/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export type Action =
| SetVariables
| SetVariable
| RemoveVariable
| MoveVariable
| SetValues
| SelectValue

Expand Down Expand Up @@ -75,6 +76,20 @@ const removeVariable = (id: string): RemoveVariable => ({
payload: {id},
})

interface MoveVariable {
type: 'MOVE_VARIABLE'
payload: {originalIndex: number; newIndex: number; contextID: string}
}

export const moveVariable = (
originalIndex: number,
newIndex: number,
contextID: string
): MoveVariable => ({
type: 'MOVE_VARIABLE',
payload: {originalIndex, newIndex, contextID},
})

interface SetValues {
type: 'SET_VARIABLE_VALUES'
payload: {
Expand Down
Loading

0 comments on commit 678f4a3

Please sign in to comment.