diff --git a/ui/src/App.js b/ui/src/App.js index e0cd5e7d7d..28bd7c5dac 100644 --- a/ui/src/App.js +++ b/ui/src/App.js @@ -9,12 +9,17 @@ const App = React.createClass({ location: PropTypes.shape({ pathname: PropTypes.string, }), + params: PropTypes.shape({ + sourceID: PropTypes.string.isRequired, + }).isRequired, }, render() { + const {sourceID} = this.props.params; + return (
- +
{this.props.children && React.cloneElement(this.props.children, { addFlashMessage: this.props.addFlashMessage, diff --git a/ui/src/CheckDataNodes.js b/ui/src/CheckDataNodes.js index 83ec93caf5..d69bd6a3d5 100644 --- a/ui/src/CheckDataNodes.js +++ b/ui/src/CheckDataNodes.js @@ -11,6 +11,9 @@ const CheckDataNodes = React.createClass({ propTypes: { addFlashMessage: func, children: node, + params: PropTypes.shape({ + sourceID: PropTypes.string, + }).isRequired, }, contextTypes: { @@ -46,14 +49,17 @@ const CheckDataNodes = React.createClass({ return
; } + const {sourceID} = this.props.params; const {sources} = this.state; - if (!sources.length) { - // this should probably be changed.... + const source = sources.find((s) => s.id === sourceID); + if (!source) { + // the id in the address bar doesn't match a source we know about + // ask paul? go to source selection page? return ; } return this.props.children && React.cloneElement(this.props.children, Object.assign({}, this.props, { - sources, + source, })); }, }); diff --git a/ui/src/chronograf/actions/view/index.js b/ui/src/chronograf/actions/view/index.js index 0ffb55f2fb..6ffadd9eed 100644 --- a/ui/src/chronograf/actions/view/index.js +++ b/ui/src/chronograf/actions/view/index.js @@ -227,11 +227,11 @@ function loadExplorer(explorer) { }; } -export function fetchExplorers({sourceLink, userID, explorerID, push}) { +export function fetchExplorers({source, userID, explorerID, push}) { return (dispatch) => { dispatch({type: 'FETCH_EXPLORERS'}); AJAX({ - url: `${sourceLink}/users/${userID}/explorations`, + url: `${source.links.self}/users/${userID}/explorations`, }).then(({data: {explorations}}) => { const explorers = explorations.map(parseRawExplorer); dispatch(loadExplorers(explorers)); @@ -249,7 +249,7 @@ export function fetchExplorers({sourceLink, userID, explorerID, push}) { if (!explorerID) { const explorer = _.maxBy(explorers, (ex) => ex.updated_at); dispatch(loadExplorer(explorer)); - push(`/chronograf/data_explorer/${btoa(explorer.link.href)}`); + push(`/sources/${source.id}/chronograf/data_explorer/${btoa(explorer.link.href)}`); return; } diff --git a/ui/src/chronograf/components/DatabaseList.js b/ui/src/chronograf/components/DatabaseList.js index 957b8bca45..fde47ff5d7 100644 --- a/ui/src/chronograf/components/DatabaseList.js +++ b/ui/src/chronograf/components/DatabaseList.js @@ -13,7 +13,11 @@ const DatabaseList = React.createClass({ }, contextTypes: { - sources: PropTypes.arrayOf(PropTypes.shape().isRequired).isRequired, + source: PropTypes.shape({ + links: PropTypes.shape({ + proxy: PropTypes.string.isRequired, + }).isRequired, + }).isRequired, }, getInitialState() { @@ -23,16 +27,16 @@ const DatabaseList = React.createClass({ }, componentDidMount() { - const {sources} = this.context; - const source = sources[0].links.proxy; - showDatabases(source).then((resp) => { + const {source} = this.context; + const proxy = source.links.proxy; + showDatabases(proxy).then((resp) => { const {errors, databases} = showDatabasesParser(resp.data); if (errors.length) { // do something } const namespaces = []; - showRetentionPolicies(source, databases).then((res) => { + showRetentionPolicies(proxy, databases).then((res) => { res.data.results.forEach((result, index) => { const {errors: errs, retentionPolicies} = showRetentionPoliciesParser(result); if (errs.length) { diff --git a/ui/src/chronograf/components/FieldList.js b/ui/src/chronograf/components/FieldList.js index 67556d3f47..eef6fd2660 100644 --- a/ui/src/chronograf/components/FieldList.js +++ b/ui/src/chronograf/components/FieldList.js @@ -19,7 +19,11 @@ const FieldList = React.createClass({ }, contextTypes: { - sources: PropTypes.arrayOf(PropTypes.shape().isRequired).isRequired, + source: PropTypes.shape({ + links: PropTypes.shape({ + proxy: PropTypes.string.isRequired, + }).isRequired, + }).isRequired, }, getInitialState() { @@ -34,8 +38,8 @@ const FieldList = React.createClass({ return; } - const {sources} = this.context; - const proxySource = sources[0].links.proxy; + const {source} = this.context; + const proxySource = source.links.proxy; showFieldKeys(proxySource, database, measurement).then((resp) => { const {errors, fieldSets} = showFieldKeysParser(resp.data); if (errors.length) { diff --git a/ui/src/chronograf/components/MeasurementList.js b/ui/src/chronograf/components/MeasurementList.js index 5bae7b451f..b807ca009a 100644 --- a/ui/src/chronograf/components/MeasurementList.js +++ b/ui/src/chronograf/components/MeasurementList.js @@ -15,7 +15,11 @@ const MeasurementList = React.createClass({ }, contextTypes: { - sources: PropTypes.arrayOf(PropTypes.shape().isRequired).isRequired, + source: PropTypes.shape({ + links: PropTypes.shape({ + proxy: PropTypes.string.isRequired, + }).isRequired, + }).isRequired, }, getInitialState() { @@ -30,9 +34,9 @@ const MeasurementList = React.createClass({ return; } - const {sources} = this.context; - const source = sources[0].links.proxy; - showMeasurements(source, this.props.query.database).then((resp) => { + const {source} = this.context; + const proxy = source.links.proxy; + showMeasurements(proxy, this.props.query.database).then((resp) => { const {errors, measurementSets} = showMeasurementsParser(resp.data); if (errors.length) { // TODO: display errors in the UI. diff --git a/ui/src/chronograf/components/Visualization.js b/ui/src/chronograf/components/Visualization.js index a17b92c278..6cbe71f78c 100644 --- a/ui/src/chronograf/components/Visualization.js +++ b/ui/src/chronograf/components/Visualization.js @@ -19,7 +19,11 @@ const Visualization = React.createClass({ }, contextTypes: { - sources: arrayOf(shape()).isRequired, + source: shape({ + links: shape({ + proxy: string.isRequired, + }).isRequired, + }).isRequired, }, getInitialState() { @@ -42,8 +46,8 @@ const Visualization = React.createClass({ render() { const {queryConfigs, timeRange, isActive, name} = this.props; - const {sources} = this.context; - const proxyLink = sources[0].links.proxy; + const {source} = this.context; + const proxyLink = source.links.proxy; const {isGraphInView} = this.state; const statements = queryConfigs.map((query) => { diff --git a/ui/src/chronograf/containers/App.js b/ui/src/chronograf/containers/App.js index 6046425ef9..2c36fd6d10 100644 --- a/ui/src/chronograf/containers/App.js +++ b/ui/src/chronograf/containers/App.js @@ -6,13 +6,12 @@ import DataExplorer from './DataExplorer'; const App = React.createClass({ propTypes: { - sources: PropTypes.arrayOf(PropTypes.shape({ + source: PropTypes.shape({ links: PropTypes.shape({ proxy: PropTypes.string.isRequired, self: PropTypes.string.isRequired, }).isRequired, }).isRequired, - ).isRequired, fetchExplorers: PropTypes.func.isRequired, router: PropTypes.shape({ push: PropTypes.func.isRequired, @@ -25,7 +24,7 @@ const App = React.createClass({ componentDidMount() { const {base64ExplorerID} = this.props.params; this.props.fetchExplorers({ - sourceLink: this.props.sources[0].links.self, + source: this.props.source, userID: 1, // TODO: get the userID explorerID: base64ExplorerID ? this.decodeID(base64ExplorerID) : null, push: this.props.router.push, @@ -36,7 +35,7 @@ const App = React.createClass({ const {base64ExplorerID} = this.props.params; return (
- +
); }, diff --git a/ui/src/chronograf/containers/DataExplorer.js b/ui/src/chronograf/containers/DataExplorer.js index bd1e70d367..342af6ff1a 100644 --- a/ui/src/chronograf/containers/DataExplorer.js +++ b/ui/src/chronograf/containers/DataExplorer.js @@ -15,7 +15,12 @@ import { const DataExplorer = React.createClass({ propTypes: { - sources: PropTypes.arrayOf(PropTypes.shape()).isRequired, + source: PropTypes.shape({ + links: PropTypes.shape({ + proxy: PropTypes.string.isRequired, + self: PropTypes.string.isRequired, + }).isRequired, + }).isRequired, explorers: PropTypes.shape({}).isRequired, explorerID: PropTypes.string, timeRange: PropTypes.shape({ @@ -30,17 +35,16 @@ const DataExplorer = React.createClass({ }, childContextTypes: { - sources: PropTypes.arrayOf(PropTypes.shape({ + source: PropTypes.shape({ links: PropTypes.shape({ proxy: PropTypes.string.isRequired, self: PropTypes.string.isRequired, }).isRequired, }).isRequired, - ).isRequired, }, getChildContext() { - return {sources: this.props.sources}; + return {source: this.props.source}; }, getInitialState() { diff --git a/ui/src/hosts/containers/HostsPage.js b/ui/src/hosts/containers/HostsPage.js index 475e95a877..af9151a404 100644 --- a/ui/src/hosts/containers/HostsPage.js +++ b/ui/src/hosts/containers/HostsPage.js @@ -4,11 +4,20 @@ import HostsTable from '../components/HostsTable'; export const HostsPage = React.createClass({ propTypes: { - sources: PropTypes.arrayOf(React.PropTypes.object), + source: PropTypes.shape({ + id: PropTypes.string.isRequired, + name: PropTypes.string.isRequired, + type: PropTypes.string.isRequired, // 'influx-enterprise' + username: PropTypes.string.isRequired, + links: PropTypes.shape({ + proxy: PropTypes.string.isRequired, + }).isRequired, + }).isRequired, }, render() { - const {sources} = this.props; + const {source} = this.props; + const sources = [source]; return (
diff --git a/ui/src/index.js b/ui/src/index.js index ffc5c51f1d..97d1c8b242 100644 --- a/ui/src/index.js +++ b/ui/src/index.js @@ -1,7 +1,7 @@ import React, {PropTypes} from 'react'; import {render} from 'react-dom'; import {Provider} from 'react-redux'; -import {Router, Route, browserHistory, IndexRoute} from 'react-router'; +import {Router, Route, browserHistory} from 'react-router'; import App from 'src/App'; import CheckDataNodes from 'src/CheckDataNodes'; @@ -120,9 +120,9 @@ const Root = React.createClass({ - + + - diff --git a/ui/src/select_source/containers/SelectSourcePage.js b/ui/src/select_source/containers/SelectSourcePage.js index 083b076a08..5341c43c38 100644 --- a/ui/src/select_source/containers/SelectSourcePage.js +++ b/ui/src/select_source/containers/SelectSourcePage.js @@ -1,8 +1,15 @@ -import React from 'react'; +import React, {PropTypes} from 'react'; +import {withRouter} from 'react-router'; import FlashMessages from 'shared/components/FlashMessages'; import {createSource, getSources} from 'shared/apis'; export const SelectSourcePage = React.createClass({ + propTypes: { + router: PropTypes.shape({ + push: PropTypes.func.isRequired, + }).isRequired, + }, + getInitialState() { return { sources: [], @@ -19,8 +26,8 @@ export const SelectSourcePage = React.createClass({ handleSelectSource(e) { e.preventDefault(); - // const source = this.state.sources.find((s) => s.name === this.selectedSource.value); - // redirect to /hosts?sourceId=source.id + const source = this.state.sources.find((s) => s.name === this.selectedSource.value); + this.props.router.push(`/sources/${source.id}/hosts`); }, handleNewSource(e) { @@ -32,7 +39,7 @@ export const SelectSourcePage = React.createClass({ password: this.sourcePassword.value, }; createSource(source).then(() => { - // redirect to /hosts?sourceId=123 + // this.props.router.push(`/sources/${source.id}/hosts`); }); }, @@ -90,4 +97,4 @@ export const SelectSourcePage = React.createClass({ }, }); -export default FlashMessages(SelectSourcePage); +export default FlashMessages(withRouter(SelectSourcePage)); diff --git a/ui/src/side_nav/components/NavItems.js b/ui/src/side_nav/components/NavItems.js index 3e2c248050..75d7248f5b 100644 --- a/ui/src/side_nav/components/NavItems.js +++ b/ui/src/side_nav/components/NavItems.js @@ -101,7 +101,7 @@ const NavBar = React.createClass({ }, render() { - const children = React.Children.map((this.props.children), (child) => { + const children = React.Children.map(this.props.children, (child) => { if (child && child.type === NavBlock) { return React.cloneElement(child, { location: this.props.location, diff --git a/ui/src/side_nav/components/SideNav.js b/ui/src/side_nav/components/SideNav.js index db39bc4988..8bff3b4917 100644 --- a/ui/src/side_nav/components/SideNav.js +++ b/ui/src/side_nav/components/SideNav.js @@ -5,42 +5,44 @@ const {string} = PropTypes; const SideNav = React.createClass({ propTypes: { location: string.isRequired, + sourceID: string.isRequired, }, render() { - const {location} = this.props; + const {location, sourceID} = this.props; + const sourcePrefix = `/sources/${sourceID}`; return (
- - - Users + + + Users - - - Overview - Queries - Tasks - Roles - Cluster Accounts - Database Manager - Retention Policies + + + Overview + Queries + Tasks + Roles + Cluster Accounts + Database Manager + Retention Policies - - - Data Explorer + + + Data Explorer - - - Settings + + + Settings Logout - - - Host List + + + Host List
); diff --git a/ui/src/side_nav/containers/SideNavApp.js b/ui/src/side_nav/containers/SideNavApp.js index 55c760aa88..e4bdc43a8f 100644 --- a/ui/src/side_nav/containers/SideNavApp.js +++ b/ui/src/side_nav/containers/SideNavApp.js @@ -6,6 +6,7 @@ const SideNavApp = React.createClass({ propTypes: { currentLocation: string.isRequired, addFlashMessage: func.isRequired, + sourceID: string.isRequired, }, contextTypes: { @@ -20,11 +21,12 @@ const SideNavApp = React.createClass({ }, render() { - const {currentLocation} = this.props; + const {currentLocation, sourceID} = this.props; const {canViewChronograf} = this.context; return (