Move current dashboard into dashboard reducer

pull/10616/head
Andrew Watkins 2017-02-17 11:30:38 -06:00
parent 808c59eb03
commit 0ed15c74f7
5 changed files with 108 additions and 37 deletions

View File

@ -1,7 +1,8 @@
import reducer from 'src/dashboards/reducers/ui'; import reducer from 'src/dashboards/reducers/ui'
import { import {
loadDashboards, loadDashboards,
setDashboard,
} from 'src/dashboards/actions'; } from 'src/dashboards/actions';
const noopAction = () => { const noopAction = () => {
@ -11,21 +12,37 @@ const noopAction = () => {
let state = undefined; let state = undefined;
describe('DataExplorer.Reducers.UI', () => { describe('DataExplorer.Reducers.UI', () => {
it('it sets the default state for UI', () => {
const actual = reducer(state, noopAction());
const expected = {
dashboards: [],
};
expect(actual).to.deep.equal(expected);
});
it('can load the dashboards', () => { it('can load the dashboards', () => {
const dashboards = [{cell: {}, name: "d1"}] const dashboard = {id: 2, cells: [], name: "d2"}
const actual = reducer(state, loadDashboards(dashboards)); const dashboards = [
{id: 1, cells: [], name: "d1"},
dashboard,
]
const actual = reducer(state, loadDashboards(dashboards, dashboard.id))
const expected = { const expected = {
dashboards, dashboards,
dashboard,
} }
expect(actual).to.deep.equal(expected);
expect(actual).to.deep.equal(expected)
});
it('can set a dashboard', () => {
const d1 = {id: 2, cells: [], name: "d2"}
const d2 = {id: 2, cells: [], name: "d2"}
const dashboards = [
d1,
d2,
]
const loadedState = reducer(state, loadDashboards(dashboards, d1.id))
const actual = reducer(loadedState, setDashboard(d2.id))
const expected = {
dashboards,
dashboard: d2,
}
expect(actual).to.deep.equal(expected)
}); });
}); });

View File

@ -1,8 +1,28 @@
export function loadDashboards(dashboards) { import {getDashboards as getDashboardsAPI} from 'src/dashboards/apis'
export function loadDashboards(dashboards, dashboardID) {
return { return {
type: 'LOAD_DASHBOARDS', type: 'LOAD_DASHBOARDS',
payload: { payload: {
dashboards, dashboards,
dashboardID,
}, },
} }
} }
export function setDashboard(dashboardID) {
return {
type: 'SET_DASHBOARD',
payload: {
dashboardID,
},
}
}
export function getDashboards(dashboardID) {
return (dispatch) => {
getDashboardsAPI().then(({data: {dashboards}}) => {
dispatch(loadDashboards(dashboards, dashboardID))
});
}
}

View File

@ -0,0 +1,12 @@
export const EMPTY_DASHBOARD = {
id: 0,
name: '',
cells: [
{
x: 0,
y: 0,
queries: [],
name: 'Loading...',
},
],
}

View File

@ -2,7 +2,6 @@ import React, {PropTypes} from 'react';
import {Link} from 'react-router'; import {Link} from 'react-router';
import {connect} from 'react-redux' import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'; import {bindActionCreators} from 'redux';
import _ from 'lodash';
import Header from 'src/dashboards/components/DashboardHeader'; import Header from 'src/dashboards/components/DashboardHeader';
import EditHeader from 'src/dashboards/components/DashboardHeaderEdit'; import EditHeader from 'src/dashboards/components/DashboardHeaderEdit';
@ -11,7 +10,6 @@ import timeRanges from 'hson!../../shared/data/timeRanges.hson';
import * as dashboardActionCreators from 'src/dashboards/actions'; import * as dashboardActionCreators from 'src/dashboards/actions';
import {getDashboards} from '../apis';
import {presentationButtonDispatcher} from 'shared/dispatchers' import {presentationButtonDispatcher} from 'shared/dispatchers'
const { const {
@ -39,12 +37,17 @@ const DashboardPage = React.createClass({
pathname: string.isRequired, pathname: string.isRequired,
}).isRequired, }).isRequired,
dashboardActions: shape({ dashboardActions: shape({
loadDashboards: func.isRequired, getDashboards: func.isRequired,
setDashboard: func.isRequired,
}).isRequired, }).isRequired,
dashboards: arrayOf(shape({ dashboards: arrayOf(shape({
id: number.isRequired, id: number.isRequired,
cells: arrayOf(shape({})).isRequired, cells: arrayOf(shape({})).isRequired,
})).isRequired, })).isRequired,
dashboard: shape({
id: number.isRequired,
cells: arrayOf(shape({})).isRequired,
}).isRequired,
inPresentationMode: bool.isRequired, inPresentationMode: bool.isRequired,
handleClickPresentationButton: func, handleClickPresentationButton: func,
}, },
@ -53,34 +56,36 @@ const DashboardPage = React.createClass({
const fifteenMinutesIndex = 1; const fifteenMinutesIndex = 1;
return { return {
dashboard: null,
timeRange: timeRanges[fifteenMinutesIndex], timeRange: timeRanges[fifteenMinutesIndex],
isEditMode: this.props.location.pathname.includes('/edit'), isEditMode: this.props.location.pathname.includes('/edit'),
}; };
}, },
componentDidMount() { componentDidMount() {
const {params: {dashboardID}, dashboardActions: {loadDashboards}} = this.props; const {
params: {dashboardID},
dashboardActions: {getDashboards},
} = this.props;
getDashboards().then(({data: {dashboards}}) => { getDashboards(dashboardID)
loadDashboards(dashboards)
this.setState({
dashboard: _.find(dashboards, (d) => d.id.toString() === dashboardID),
});
});
}, },
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps) {
const {location: {pathname}} = this.props const {location: {pathname}} = this.props
const {location: {pathname: nextPathname}, params: {dashboardID: nextID}} = nextProps const {
location: {pathname: nextPathname},
params: {dashboardID: nextID},
dashboardActions: {setDashboard},
} = nextProps
if (nextPathname.pathname === pathname) { if (nextPathname.pathname === pathname) {
return return
} }
setDashboard(nextID)
this.setState({ this.setState({
isEditMode: nextPathname.includes('/edit'), isEditMode: nextPathname.includes('/edit'),
dashboard: _.find(this.state.dashboards, (d) => d.id.toString() === nextID),
}) })
}, },
@ -90,20 +95,17 @@ const DashboardPage = React.createClass({
}, },
render() { render() {
const {timeRange, isEditMode, dashboard} = this.state; const {timeRange, isEditMode} = this.state;
const { const {
dashboards, dashboards,
dashboard,
params: {sourceID}, params: {sourceID},
inPresentationMode, inPresentationMode,
handleClickPresentationButton, handleClickPresentationButton,
source, source,
} = this.props } = this.props
if (!dashboard) {
return null
}
return ( return (
<div className="page"> <div className="page">
{ {
@ -141,10 +143,15 @@ const DashboardPage = React.createClass({
}, },
}); });
const mapStateToProps = (state) => ({ const mapStateToProps = (state) => {
inPresentationMode: state.appUI.presentationMode, const {appUI, dashboardUI: {dashboards, dashboard}} = state
dashboards: state.dashboardUI.dashboards,
}) return {
inPresentationMode: appUI.presentationMode,
dashboards,
dashboard,
}
}
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
handleClickPresentationButton: presentationButtonDispatcher(dispatch), handleClickPresentationButton: presentationButtonDispatcher(dispatch),

View File

@ -1,17 +1,32 @@
import _ from 'lodash';
import {EMPTY_DASHBOARD} from 'src/dashboards/constants'
const initialState = { const initialState = {
dashboards: [], dashboards: [],
dashboard: EMPTY_DASHBOARD,
}; };
export default function ui(state = initialState, action) { export default function ui(state = initialState, action) {
switch (action.type) { switch (action.type) {
case 'LOAD_DASHBOARDS': { case 'LOAD_DASHBOARDS': {
const {dashboards} = action.payload; const {dashboards, dashboardID} = action.payload;
const newState = { const newState = {
dashboards, dashboards,
dashboard: _.find(dashboards, (d) => d.id === +dashboardID),
}; };
return {...state, ...newState}; return {...state, ...newState};
} }
case 'SET_DASHBOARD': {
const {dashboardID} = action.payload
const newState = {
dashboard: _.find(state.dashboards, (d) => d.id === +dashboardID),
};
return {...state, ...newState}
}
} }
return state; return state;