From 616e4bbb9888910d9f9f781485f21dbf1de7e220 Mon Sep 17 00:00:00 2001 From: Jared Scheib Date: Wed, 1 Nov 2017 00:30:30 -0700 Subject: [PATCH] Fetch live data from /chronograf/v1/users & load into Chronograf Admin Table Move DUMMY_USERS data into admin/chronograf/loadUsers spec. This adds a full roundtrip for populating the Chronograf Admin Table with live data from the server. It includes a reducer & test, action creator, and API request, which then loads the successful data into the Redux and then the React component. --- ui/spec/admin/reducers/chronografSpec.js | 176 ++++++++++++++++++ ui/src/admin/actions/chronograf.js | 23 +++ ui/src/admin/apis/chronograf.js | 13 ++ ui/src/admin/constants/dummyUsers.js | 160 ---------------- .../admin/containers/AdminChronografPage.js | 37 +++- ui/src/admin/reducers/chronograf.js | 16 ++ ui/src/admin/reducers/index.js | 3 +- 7 files changed, 257 insertions(+), 171 deletions(-) create mode 100644 ui/spec/admin/reducers/chronografSpec.js create mode 100644 ui/src/admin/actions/chronograf.js create mode 100644 ui/src/admin/apis/chronograf.js create mode 100644 ui/src/admin/reducers/chronograf.js diff --git a/ui/spec/admin/reducers/chronografSpec.js b/ui/spec/admin/reducers/chronografSpec.js new file mode 100644 index 000000000..6af150c55 --- /dev/null +++ b/ui/spec/admin/reducers/chronografSpec.js @@ -0,0 +1,176 @@ +import reducer from 'src/admin/reducers/chronograf' + +import {loadUsers} from 'src/admin/actions/chronograf' + +let state + +const users = [ + { + id: 666, + name: 'bob@billietta.com', + provider: 'GitHub', + scheme: 'OAuth2', + roles: [ + {organizationName: 'All Users', organizationID: 666, name: NO_ROLE}, + {organizationName: 'Green Team', organizationID: 1234, name: 'admin'}, + {organizationName: 'Blue Team', organizationID: 1235, name: 'editor'}, + ], + links: {self: '/chronograf/v1/users/666'}, + }, + { + id: 667, + name: 'billybob@gmail.com', + provider: 'Auth0', + scheme: 'OAuth2', + roles: [ + {organizationName: 'All Users', organizationID: 666, name: NO_ROLE}, + {organizationName: 'Green Team', organizationID: 1234, name: 'viewer'}, + {organizationName: 'Red Team', organizationID: 1236, name: 'editor'}, + ], + links: {self: '/chronograf/v1/users/667'}, + }, + { + id: 720, + name: 'shorty@gmail.com', + provider: 'Heroku', + scheme: 'LDAP', + roles: [ + {organizationName: 'All Users', organizationID: 666, name: NO_ROLE}, + {organizationName: 'Green Team', organizationID: 1234, name: 'editor'}, + ], + links: {self: '/chronograf/v1/users/720'}, + }, + { + id: 271, + name: 'shawn.ofthe.dead@gmail.com', + provider: 'GitHub', + scheme: 'OAuth2', + roles: [ + {organizationName: 'All Users', organizationID: 666, name: NO_ROLE}, + {organizationName: 'Blue Team', organizationID: 1235, name: 'editor'}, + ], + links: {self: '/chronograf/v1/users/271'}, + }, + { + id: 6389, + name: 'swogglez@gmail.com', + provider: 'Heroku', + scheme: 'OAuth2', + roles: [ + {organizationName: 'All Users', organizationID: 666, name: NO_ROLE}, + {organizationName: 'Red Team', organizationID: 1236, name: 'viewer'}, + {organizationName: 'Blue Team', organizationID: 1235, name: 'viewer'}, + ], + links: {self: '/chronograf/v1/users/6389'}, + }, + { + id: 99181, + name: 'whiskey.elbow@gmail.com', + provider: 'GitHub', + scheme: 'OAuth2', + roles: [ + {organizationName: 'All Users', organizationID: 666, name: NO_ROLE}, + {organizationName: 'Green Team', organizationID: 1234, name: 'viewer'}, + {organizationName: 'Blue Team', organizationID: 1235, name: 'viewer'}, + {organizationName: 'Red Team', organizationID: 1236, name: 'viewer'}, + ], + links: {self: '/chronograf/v1/users/99181'}, + }, + { + id: 3786, + name: 'bob.builder@gmail.com', + provider: 'Generic', + scheme: 'LDAP', + roles: [ + {organizationName: 'All Users', organizationID: 666, name: NO_ROLE}, + {organizationName: 'Red Team', organizationID: 1236, name: 'editor'}, + ], + links: {self: '/chronograf/v1/users/3786'}, + }, + { + id: 112345, + name: 'lost.in.translation@gmail.com', + provider: 'Generic', + scheme: 'LDAP', + roles: [ + {organizationName: 'All Users', organizationID: 666, name: NO_ROLE}, + ], + links: {self: '/chronograf/v1/users/112345'}, + }, + { + id: 23, + name: 'wandering.soul@gmail.com', + provider: 'Heroku', + scheme: 'LDAP', + roles: [ + {organizationName: 'All Users', organizationID: 666, name: NO_ROLE}, + ], + links: {self: '/chronograf/v1/users/23'}, + }, + { + id: 7, + name: 'disembodied@gmail.com', + provider: 'Auth0', + scheme: 'OAuth2', + roles: [ + {organizationName: 'All Users', organizationID: 666, name: NO_ROLE}, + ], + links: {self: '/chronograf/v1/users/7'}, + }, + { + id: 0, + name: 'bob.builder@gmail.com', + provider: 'Heroku', + scheme: 'LDAP', + roles: [ + {organizationName: 'All Users', organizationID: 666, name: NO_ROLE}, + {organizationName: 'Red Team', organizationID: 1236, name: 'editor'}, + ], + links: {self: '/chronograf/v1/users/0'}, + }, + { + id: 2891, + name: 'swag.bandit@gmail.com', + provider: 'Google', + scheme: 'OAuth2', + roles: [ + {organizationName: 'All Users', organizationID: 666, name: NO_ROLE}, + {organizationName: 'Blue Team', organizationID: 1234, name: 'admin'}, + ], + links: {self: '/chronograf/v1/users/2891'}, + }, + { + id: 2645, + name: 'lord.ofthe.dance@gmail.com', + provider: 'GitHub', + scheme: 'OAuth2', + superadmin: true, + roles: [ + {organizationName: 'All Users', organizationID: 666, name: NO_ROLE}, + ], + links: {self: '/chronograf/v1/users/2645'}, + }, + { + id: 47119, + name: 'ohnooeezzz@gmail.com', + provider: 'Google', + scheme: 'OAuth2', + superadmin: true, + roles: [ + {organizationName: 'All Users', organizationID: 666, name: NO_ROLE}, + {organizationName: 'Blue Team', organizationID: 1234, name: NO_ROLE}, + ], + links: {self: '/chronograf/v1/users/47119'}, + }, +] + +describe('Admin.Chronograf.Reducers', () => { + it('it can load all users', () => { + const actual = reducer(state, loadUsers({users})) + const expected = { + users, + } + + expect(actual.users).to.deep.equal(expected.users) + }) +}) diff --git a/ui/src/admin/actions/chronograf.js b/ui/src/admin/actions/chronograf.js new file mode 100644 index 000000000..ea9e1e474 --- /dev/null +++ b/ui/src/admin/actions/chronograf.js @@ -0,0 +1,23 @@ +import {getUsers as getUsersAJAX} from 'src/admin/apis/chronograf' + +import {errorThrown} from 'shared/actions/errors' + +// action creators + +// response contains `users` and `links` +export const loadUsers = ({users}) => ({ + type: 'CHRONOGRAF_LOAD_USERS', + payload: { + users, + }, +}) + +// async actions (thunks) +export const loadUsersAsync = url => async dispatch => { + try { + const {data} = await getUsersAJAX(url) + dispatch(loadUsers(data)) + } catch (error) { + dispatch(errorThrown(error)) + } +} diff --git a/ui/src/admin/apis/chronograf.js b/ui/src/admin/apis/chronograf.js new file mode 100644 index 000000000..9297f0313 --- /dev/null +++ b/ui/src/admin/apis/chronograf.js @@ -0,0 +1,13 @@ +import AJAX from 'src/utils/ajax' + +export const getUsers = async url => { + try { + return await AJAX({ + method: 'GET', + url, + }) + } catch (error) { + console.error(error) + throw error + } +} diff --git a/ui/src/admin/constants/dummyUsers.js b/ui/src/admin/constants/dummyUsers.js index a0aa30512..fddb1781d 100644 --- a/ui/src/admin/constants/dummyUsers.js +++ b/ui/src/admin/constants/dummyUsers.js @@ -1,165 +1,5 @@ export const NO_ROLE = 'No Role' -export const DUMMY_USERS = [ - { - id: 666, - name: 'bob@billietta.com', - provider: 'GitHub', - scheme: 'OAuth2', - roles: [ - {organizationName: 'All Users', organizationID: 666, name: NO_ROLE}, - {organizationName: 'Green Team', organizationID: 1234, name: 'admin'}, - {organizationName: 'Blue Team', organizationID: 1235, name: 'editor'}, - ], - links: {self: '/chronograf/v1/users/666'}, - }, - { - id: 667, - name: 'billybob@gmail.com', - provider: 'Auth0', - scheme: 'OAuth2', - roles: [ - {organizationName: 'All Users', organizationID: 666, name: NO_ROLE}, - {organizationName: 'Green Team', organizationID: 1234, name: 'viewer'}, - {organizationName: 'Red Team', organizationID: 1236, name: 'editor'}, - ], - links: {self: '/chronograf/v1/users/667'}, - }, - { - id: 720, - name: 'shorty@gmail.com', - provider: 'Heroku', - scheme: 'LDAP', - roles: [ - {organizationName: 'All Users', organizationID: 666, name: NO_ROLE}, - {organizationName: 'Green Team', organizationID: 1234, name: 'editor'}, - ], - links: {self: '/chronograf/v1/users/720'}, - }, - { - id: 271, - name: 'shawn.ofthe.dead@gmail.com', - provider: 'GitHub', - scheme: 'OAuth2', - roles: [ - {organizationName: 'All Users', organizationID: 666, name: NO_ROLE}, - {organizationName: 'Blue Team', organizationID: 1235, name: 'editor'}, - ], - links: {self: '/chronograf/v1/users/271'}, - }, - { - id: 6389, - name: 'swogglez@gmail.com', - provider: 'Heroku', - scheme: 'OAuth2', - roles: [ - {organizationName: 'All Users', organizationID: 666, name: NO_ROLE}, - {organizationName: 'Red Team', organizationID: 1236, name: 'viewer'}, - {organizationName: 'Blue Team', organizationID: 1235, name: 'viewer'}, - ], - links: {self: '/chronograf/v1/users/6389'}, - }, - { - id: 99181, - name: 'whiskey.elbow@gmail.com', - provider: 'GitHub', - scheme: 'OAuth2', - roles: [ - {organizationName: 'All Users', organizationID: 666, name: NO_ROLE}, - {organizationName: 'Green Team', organizationID: 1234, name: 'viewer'}, - {organizationName: 'Blue Team', organizationID: 1235, name: 'viewer'}, - {organizationName: 'Red Team', organizationID: 1236, name: 'viewer'}, - ], - links: {self: '/chronograf/v1/users/99181'}, - }, - { - id: 3786, - name: 'bob.builder@gmail.com', - provider: 'Generic', - scheme: 'LDAP', - roles: [ - {organizationName: 'All Users', organizationID: 666, name: NO_ROLE}, - {organizationName: 'Red Team', organizationID: 1236, name: 'editor'}, - ], - links: {self: '/chronograf/v1/users/3786'}, - }, - { - id: 112345, - name: 'lost.in.translation@gmail.com', - provider: 'Generic', - scheme: 'LDAP', - roles: [ - {organizationName: 'All Users', organizationID: 666, name: NO_ROLE}, - ], - links: {self: '/chronograf/v1/users/112345'}, - }, - { - id: 23, - name: 'wandering.soul@gmail.com', - provider: 'Heroku', - scheme: 'LDAP', - roles: [ - {organizationName: 'All Users', organizationID: 666, name: NO_ROLE}, - ], - links: {self: '/chronograf/v1/users/23'}, - }, - { - id: 7, - name: 'disembodied@gmail.com', - provider: 'Auth0', - scheme: 'OAuth2', - roles: [ - {organizationName: 'All Users', organizationID: 666, name: NO_ROLE}, - ], - links: {self: '/chronograf/v1/users/7'}, - }, - { - id: 0, - name: 'bob.builder@gmail.com', - provider: 'Heroku', - scheme: 'LDAP', - roles: [ - {organizationName: 'All Users', organizationID: 666, name: NO_ROLE}, - {organizationName: 'Red Team', organizationID: 1236, name: 'editor'}, - ], - links: {self: '/chronograf/v1/users/0'}, - }, - { - id: 2891, - name: 'swag.bandit@gmail.com', - provider: 'Google', - scheme: 'OAuth2', - roles: [ - {organizationName: 'All Users', organizationID: 666, name: NO_ROLE}, - {organizationName: 'Blue Team', organizationID: 1234, name: 'admin'}, - ], - links: {self: '/chronograf/v1/users/2891'}, - }, - { - id: 2645, - name: 'lord.ofthe.dance@gmail.com', - provider: 'GitHub', - scheme: 'OAuth2', - superadmin: true, - roles: [ - {organizationName: 'All Users', organizationID: 666, name: NO_ROLE}, - ], - links: {self: '/chronograf/v1/users/2645'}, - }, - { - id: 47119, - name: 'ohnooeezzz@gmail.com', - provider: 'Google', - scheme: 'OAuth2', - superadmin: true, - roles: [ - {organizationName: 'All Users', organizationID: 666, name: NO_ROLE}, - {organizationName: 'Blue Team', organizationID: 1234, name: NO_ROLE}, - ], - links: {self: '/chronograf/v1/users/47119'}, - }, -] - export const USER_ROLES = [ {name: NO_ROLE}, {name: 'viewer'}, diff --git a/ui/src/admin/containers/AdminChronografPage.js b/ui/src/admin/containers/AdminChronografPage.js index 93335b03f..ce9567458 100644 --- a/ui/src/admin/containers/AdminChronografPage.js +++ b/ui/src/admin/containers/AdminChronografPage.js @@ -1,4 +1,8 @@ import React, {Component, PropTypes} from 'react' +import {connect} from 'react-redux' +import {bindActionCreators} from 'redux' + +import {loadUsersAsync} from 'src/admin/actions/chronograf' import PageHeader from 'src/admin/components/chronograf/PageHeader' import UsersTableHeader from 'src/admin/components/chronograf/UsersTableHeader' @@ -8,12 +12,7 @@ import CreateOrgOverlay from 'src/admin/components/chronograf/CreateOrgOverlay' import FancyScrollbar from 'shared/components/FancyScrollbar' -import { - DUMMY_USERS, - DUMMY_ORGS, - DEFAULT_ORG, - NO_ORG, -} from 'src/admin/constants/dummyUsers' +import {DUMMY_ORGS, DEFAULT_ORG, NO_ORG} from 'src/admin/constants/dummyUsers' class AdminChronografPage extends Component { constructor(props) { @@ -28,6 +27,14 @@ class AdminChronografPage extends Component { } } + componentDidMount() { + const {loadUsers} = this.props + + // TODO: determine this url from server + const urlThatsProbablySourceLinksUsersChronograf = '/chronograf/v1/users' + loadUsers(urlThatsProbablySourceLinksUsersChronograf) + } + isSameUser = (userA, userB) => { return ( userA.name === userB.name && @@ -106,7 +113,9 @@ class AdminChronografPage extends Component { filteredUsers, showCreateOverlay, } = this.state + const numUsersSelected = Object.keys(selectedUsers).length + return (
@@ -132,7 +141,7 @@ class AdminChronografPage extends Component { />
({ + users, +}) + +const mapDispatchToProps = dispatch => ({ + loadUsers: bindActionCreators(loadUsersAsync, dispatch), +}) + +export default connect(mapStateToProps, mapDispatchToProps)(AdminChronografPage) diff --git a/ui/src/admin/reducers/chronograf.js b/ui/src/admin/reducers/chronograf.js new file mode 100644 index 000000000..db9da94e4 --- /dev/null +++ b/ui/src/admin/reducers/chronograf.js @@ -0,0 +1,16 @@ +const initialState = { + users: [], + organizations: [], +} + +const adminChronograf = (state = initialState, action) => { + switch (action.type) { + case 'CHRONOGRAF_LOAD_USERS': { + return {...state, ...action.payload} + } + } + + return state +} + +export default adminChronograf diff --git a/ui/src/admin/reducers/index.js b/ui/src/admin/reducers/index.js index d4344ab52..7356e32f4 100644 --- a/ui/src/admin/reducers/index.js +++ b/ui/src/admin/reducers/index.js @@ -1,3 +1,4 @@ +import adminChronograf from './chronograf' import adminInfluxDB from './influxdb' -export default {adminInfluxDB} +export default {adminChronograf, adminInfluxDB}