parent
9d3294b31c
commit
5762e64e0b
|
@ -163,20 +163,40 @@ describe('Dashboard', () => {
|
|||
.pipe(getSelectedVariable(dashboard.id, 0))
|
||||
.should('equal', 'c1')
|
||||
|
||||
// sanity check on the url before beginning
|
||||
cy.location('search').should('eq', '?lower=now%28%29%20-%201h')
|
||||
|
||||
// select 3rd value in dashboard
|
||||
cy.getByTestID('variable-dropdown--button')
|
||||
.eq(0)
|
||||
.click()
|
||||
cy.get(`#c3`).click()
|
||||
|
||||
// selected value in dashboard is 3rd value
|
||||
cy.getByTestID('variable-dropdown')
|
||||
.eq(0)
|
||||
.should('contain', 'c3')
|
||||
cy.window()
|
||||
.pipe(getSelectedVariable(dashboard.id, 0))
|
||||
.should('equal', 'c3')
|
||||
|
||||
// and that it updates the variable in the URL
|
||||
cy.location('search').should(
|
||||
'eq',
|
||||
'?lower=now%28%29%20-%201h&vars%5BCSVVariable%5D=c3'
|
||||
)
|
||||
|
||||
// select 2nd value in dashboard
|
||||
cy.getByTestID('variable-dropdown--button')
|
||||
.eq(0)
|
||||
.click()
|
||||
cy.get(`#c2`).click()
|
||||
// breaks here
|
||||
|
||||
// selected value in dashboard is 2nd value
|
||||
cy.getByTestID('variable-dropdown')
|
||||
.eq(0)
|
||||
.should('contain', 'c2')
|
||||
cy.window()
|
||||
.pipe(getSelectedVariable(dashboard.id, 0))
|
||||
.should('equal', 'c2')
|
||||
// and that it updates the variable in the URL without breaking stuff
|
||||
cy.location('search').should(
|
||||
'eq',
|
||||
'?lower=now%28%29%20-%201h&vars%5BCSVVariable%5D=c2'
|
||||
)
|
||||
|
||||
// open CEO
|
||||
cy.getByTestID('cell-context--toggle').click()
|
||||
|
|
|
@ -91,6 +91,18 @@ export const updateQueryParams = (updatedQueryParams: object): RouterAction => {
|
|||
return replace(newLocation)
|
||||
}
|
||||
|
||||
export const updateQueryVars = varsObj => {
|
||||
const urlVars = qs.parse(window.location.search, {ignoreQueryPrefix: true})
|
||||
const vars = {
|
||||
...(urlVars.vars || {}),
|
||||
...varsObj,
|
||||
}
|
||||
|
||||
return updateQueryParams({
|
||||
vars,
|
||||
})
|
||||
}
|
||||
|
||||
export const updateTimeRangeFromQueryParams = (dashboardID: string) => (
|
||||
dispatch: Dispatch<Action>,
|
||||
getState
|
||||
|
|
|
@ -1,31 +1,97 @@
|
|||
import React, {PureComponent} from 'react'
|
||||
import qs from 'qs'
|
||||
import {connect} from 'react-redux'
|
||||
import {withRouter, WithRouterProps} from 'react-router'
|
||||
import {setDashboard} from 'src/shared/actions/currentDashboard'
|
||||
import {AppState} from 'src/types'
|
||||
import {getVariables} from 'src/variables/selectors'
|
||||
import {selectValue} from 'src/variables/actions/creators'
|
||||
import {AppState, Variable} from 'src/types'
|
||||
|
||||
interface StateProps {
|
||||
variables: Variable[]
|
||||
dashboard: string
|
||||
}
|
||||
|
||||
interface DispatchProps {
|
||||
updateDashboard: typeof setDashboard
|
||||
selectValue: typeof selectValue
|
||||
}
|
||||
|
||||
type Props = StateProps & DispatchProps & WithRouterProps
|
||||
|
||||
class DashboardRoute extends PureComponent<Props> {
|
||||
check(props) {
|
||||
const {dashboard, updateDashboard} = props
|
||||
const dashboardID = props.params.dashboardID
|
||||
pendingVars: [{[key: string]: any}]
|
||||
|
||||
if (dashboard !== dashboardID) {
|
||||
updateDashboard(dashboardID)
|
||||
}
|
||||
// this function takes the hydrated variables from state
|
||||
// and runs the `selectValue` action against them if the
|
||||
// selected value in the search params doesn't match the
|
||||
// selected value in the redux store
|
||||
// urlVars represents the `vars` object variable in the
|
||||
// query params here, and unwrapping / validation is
|
||||
// handled elsewhere
|
||||
syncVariables(props, urlVars) {
|
||||
const dashboardID = props.params.dashboardID
|
||||
const {variables, selectValue} = props
|
||||
|
||||
variables.forEach(v => {
|
||||
let val
|
||||
|
||||
if (v.selected) {
|
||||
val = v.selected[0]
|
||||
}
|
||||
|
||||
if (val !== urlVars[v.name]) {
|
||||
val = urlVars[v.name]
|
||||
selectValue(dashboardID, v.id, val)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.check(this.props)
|
||||
const {dashboard, updateDashboard, variables} = this.props
|
||||
const dashboardID = this.props.params.dashboardID
|
||||
const urlVars = qs.parse(this.props.location.search, {
|
||||
ignoreQueryPrefix: true,
|
||||
})
|
||||
|
||||
// always keep the dashboard in sync
|
||||
if (dashboard !== dashboardID) {
|
||||
updateDashboard(dashboardID)
|
||||
}
|
||||
|
||||
// nothing to sync as the query params aren't defining
|
||||
// any variables
|
||||
if (!urlVars.hasOwnProperty('vars')) {
|
||||
return
|
||||
}
|
||||
|
||||
// resource is still loading
|
||||
// we have to wait for it so that we can filter out arbitrary user input
|
||||
// from the redux state before commiting it back to localstorage
|
||||
if (!variables.length) {
|
||||
this.pendingVars = urlVars.vars
|
||||
return
|
||||
}
|
||||
|
||||
this.syncVariables(this.props, urlVars.vars)
|
||||
}
|
||||
|
||||
componentDidUpdate(props) {
|
||||
if (props.variables === this.props.variables) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!this.props.variables.length) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!this.pendingVars) {
|
||||
return
|
||||
}
|
||||
|
||||
this.syncVariables(this.props, this.pendingVars)
|
||||
|
||||
delete this.pendingVars
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
|
@ -42,13 +108,17 @@ class DashboardRoute extends PureComponent<Props> {
|
|||
}
|
||||
|
||||
const mstp = (state: AppState): StateProps => {
|
||||
const variables = getVariables(state, state.currentDashboard.id)
|
||||
|
||||
return {
|
||||
variables,
|
||||
dashboard: state.currentDashboard.id,
|
||||
}
|
||||
}
|
||||
|
||||
const mdtp: DispatchProps = {
|
||||
updateDashboard: setDashboard,
|
||||
selectValue: selectValue,
|
||||
}
|
||||
|
||||
export default connect<StateProps, DispatchProps>(
|
||||
|
|
|
@ -7,8 +7,10 @@ import {setExportTemplate} from 'src/templates/actions/creators'
|
|||
import {
|
||||
setVariables,
|
||||
setVariable,
|
||||
selectValue as selectValueInState,
|
||||
removeVariable,
|
||||
} from 'src/variables/actions/creators'
|
||||
import {updateQueryVars} from 'src/dashboards/actions/ranges'
|
||||
|
||||
// Schemas
|
||||
import {variableSchema, arrayOfVariables} from 'src/schemas/variables'
|
||||
|
@ -20,6 +22,7 @@ import {createVariableFromTemplate as createVariableFromTemplateAJAX} from 'src/
|
|||
|
||||
// Utils
|
||||
import {
|
||||
getVariable as getVariableFromState,
|
||||
getVariables as getVariablesFromState,
|
||||
getAllVariables as getAllVariablesFromState,
|
||||
} from 'src/variables/selectors'
|
||||
|
@ -357,3 +360,15 @@ export const removeVariableLabelAsync = (
|
|||
dispatch(notify(copy.removeVariableLabelFailed()))
|
||||
}
|
||||
}
|
||||
|
||||
export const selectValue = (
|
||||
contextID: string,
|
||||
variableID: string,
|
||||
selected: string
|
||||
) => async (dispatch: Dispatch<Action>, getState: GetState) => {
|
||||
const variable = getVariableFromState(getState(), contextID, variableID)
|
||||
|
||||
await dispatch(selectValueInState(contextID, variableID, selected))
|
||||
|
||||
dispatch(updateQueryVars({[variable.name]: selected}))
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
} from '@influxdata/clockface'
|
||||
|
||||
// Actions
|
||||
import {selectValue} from 'src/variables/actions/creators'
|
||||
import {selectValue} from 'src/variables/actions/thunks'
|
||||
|
||||
// Utils
|
||||
import {getVariable} from 'src/variables/selectors'
|
||||
|
|
Loading…
Reference in New Issue