From 4268e38037152a69e16b9cb3268c7c8edeb10f02 Mon Sep 17 00:00:00 2001 From: Jared Scheib Date: Tue, 12 Dec 2017 14:39:40 -0800 Subject: [PATCH] Move & rename Settings boilerplate to dedicated shared Config boilerplate --- ui/src/admin/actions/chronograf.js | 62 ----------------- ui/src/admin/apis/chronograf.js | 25 ------- .../chronograf/OrganizationsTable.js | 18 ++--- ui/src/admin/containers/OrganizationsPage.js | 54 +++++++++------ ui/src/admin/reducers/chronograf.js | 12 +--- ui/src/shared/actions/config.js | 67 +++++++++++++++++++ ui/src/shared/apis/config.js | 26 +++++++ ui/src/shared/reducers/config.js | 22 ++++++ ui/src/shared/reducers/index.js | 2 + .../style/components/organizations-table.scss | 2 +- 10 files changed, 160 insertions(+), 130 deletions(-) create mode 100644 ui/src/shared/actions/config.js create mode 100644 ui/src/shared/apis/config.js create mode 100644 ui/src/shared/reducers/config.js diff --git a/ui/src/admin/actions/chronograf.js b/ui/src/admin/actions/chronograf.js index 473cc923e..d7a64731e 100644 --- a/ui/src/admin/actions/chronograf.js +++ b/ui/src/admin/actions/chronograf.js @@ -10,8 +10,6 @@ import { createOrganization as createOrganizationAJAX, updateOrganization as updateOrganizationAJAX, deleteOrganization as deleteOrganizationAJAX, - getAuthSettings as getAuthSettingsAJAX, - updateAuthSettings as updateAuthSettingsAJAX, } from 'src/admin/apis/chronograf' import {publishAutoDismissingNotification} from 'shared/dispatchers' @@ -96,39 +94,6 @@ export const removeOrganization = organization => ({ }, }) -export const getAuthSettingsRequested = () => ({ - type: 'CHRONOGRAF_GET_AUTH_SETTINGS_REQUESTED', -}) - -export const getAuthSettingsCompleted = authSettings => ({ - type: 'CHRONOGRAF_GET_AUTH_SETTINGS_COMPLETED', - payload: { - authSettings, - }, -}) - -export const getAuthSettingsFailed = () => ({ - type: 'CHRONOGRAF_GET_AUTH_SETTINGS_FAILED', -}) - -export const updateAuthSettingsRequested = authSettings => ({ - type: 'CHRONOGRAF_UPDATE_AUTH_SETTINGS_REQUESTED', - payload: { - authSettings, - }, -}) - -export const updateAuthSettingsCompleted = () => ({ - type: 'CHRONOGRAF_UPDATE_AUTH_SETTINGS_COMPLETED', -}) - -export const updateAuthSettingsFailed = authSettings => ({ - type: 'CHRONOGRAF_UPDATE_AUTH_SETTINGS_FAILED', - payload: { - authSettings, - }, -}) - // async actions (thunks) export const loadUsersAsync = url => async dispatch => { try { @@ -266,30 +231,3 @@ export const deleteOrganizationAsync = organization => async dispatch => { dispatch(addOrganization(organization)) } } - -export const getAuthSettingsAsync = url => async dispatch => { - dispatch(getAuthSettingsRequested()) - try { - const {data} = await getAuthSettingsAJAX(url) - dispatch(getAuthSettingsCompleted(data)) // TODO: change authSettings in actions & reducers to reflect final shape - } catch (error) { - dispatch(errorThrown(error)) - dispatch(getAuthSettingsFailed()) - } -} - -export const updateAuthSettingsAsync = ( - url, - oldAuthSettings, - updatedAuthSettings -) => async dispatch => { - const newAuthSettings = {...oldAuthSettings, ...updatedAuthSettings} - dispatch(updateAuthSettingsRequested(newAuthSettings)) - try { - await updateAuthSettingsAJAX(url, newAuthSettings) - dispatch(updateAuthSettingsCompleted()) - } catch (error) { - dispatch(errorThrown(error)) - dispatch(updateAuthSettingsFailed(oldAuthSettings)) - } -} diff --git a/ui/src/admin/apis/chronograf.js b/ui/src/admin/apis/chronograf.js index e28566acd..300884928 100644 --- a/ui/src/admin/apis/chronograf.js +++ b/ui/src/admin/apis/chronograf.js @@ -102,28 +102,3 @@ export const deleteOrganization = async organization => { throw error } } - -export const getAuthSettings = async url => { - try { - return await AJAX({ - method: 'GET', - url, - }) - } catch (error) { - console.error(error) - throw error - } -} - -export const updateAuthSettings = async (url, authSettings) => { - try { - return await AJAX({ - method: 'PATCH', - url, - data: authSettings, - }) - } catch (error) { - console.error(error) - throw error - } -} diff --git a/ui/src/admin/components/chronograf/OrganizationsTable.js b/ui/src/admin/components/chronograf/OrganizationsTable.js index 588fa4b84..c3acfa025 100644 --- a/ui/src/admin/components/chronograf/OrganizationsTable.js +++ b/ui/src/admin/components/chronograf/OrganizationsTable.js @@ -34,9 +34,9 @@ class OrganizationsTable extends Component { this.setState({isCreatingOrganization: false}) } - handleChangeAuthSettingsSuperAdminFirstUserOnly = superAdminFirstUserOnly => { - const {onUpdateAuthSettings} = this.props - onUpdateAuthSettings({superAdminFirstUserOnly}) + handleChangeAuthConfigSuperAdminFirstUserOnly = superAdminFirstUserOnly => { + const {onUpdateAuthConfig} = this.props + onUpdateAuthConfig({superAdminFirstUserOnly}) } render() { @@ -47,7 +47,7 @@ class OrganizationsTable extends Component { onChooseDefaultRole, onTogglePublic, currentOrganization, - authSettings: {superAdminFirstUserOnly}, + authConfig: {superAdminFirstUserOnly}, } = this.props const {isCreatingOrganization} = this.state @@ -102,7 +102,7 @@ class OrganizationsTable extends Component { - + @@ -113,7 +113,7 @@ class OrganizationsTable extends Component { size="xs" active={superAdminFirstUserOnly} onToggle={ - this.handleChangeAuthSettingsSuperAdminFirstUserOnly + this.handleChangeAuthConfigSuperAdminFirstUserOnly } /> @@ -146,9 +146,9 @@ OrganizationsTable.propTypes = { onRenameOrg: func.isRequired, onTogglePublic: func.isRequired, onChooseDefaultRole: func.isRequired, - onUpdateAuthSettings: func.isRequired, - authSettings: shape({ - superAdminFirstUserOnly: bool.isRequired, + onUpdateAuthConfig: func.isRequired, + authConfig: shape({ + superAdminFirstUserOnly: bool, }), } export default OrganizationsTable diff --git a/ui/src/admin/containers/OrganizationsPage.js b/ui/src/admin/containers/OrganizationsPage.js index 29da6bff2..7679a991f 100644 --- a/ui/src/admin/containers/OrganizationsPage.js +++ b/ui/src/admin/containers/OrganizationsPage.js @@ -3,6 +3,7 @@ import {connect} from 'react-redux' import {bindActionCreators} from 'redux' import * as adminChronografActionCreators from 'src/admin/actions/chronograf' +import * as configActionCreators from 'shared/actions/config' import {getMeAsync} from 'shared/actions/auth' import OrganizationsTable from 'src/admin/components/chronograf/OrganizationsTable' @@ -11,26 +12,27 @@ class OrganizationsPage extends Component { componentDidMount() { const { links, - actions: {loadOrganizationsAsync, getAuthSettingsAsync}, + actionsAdmin: {loadOrganizationsAsync}, + actionsConfig: {getAuthConfigAsync}, } = this.props loadOrganizationsAsync(links.organizations) - getAuthSettingsAsync(links.config) + getAuthConfigAsync(links.config) } handleCreateOrganization = async organization => { - const {links, actions: {createOrganizationAsync}} = this.props + const {links, actionsAdmin: {createOrganizationAsync}} = this.props await createOrganizationAsync(links.organizations, organization) this.refreshMe() } handleRenameOrganization = async (organization, name) => { - const {actions: {updateOrganizationAsync}} = this.props + const {actionsAdmin: {updateOrganizationAsync}} = this.props await updateOrganizationAsync(organization, {...organization, name}) this.refreshMe() } handleDeleteOrganization = organization => { - const {actions: {deleteOrganizationAsync}} = this.props + const {actionsAdmin: {deleteOrganizationAsync}} = this.props deleteOrganizationAsync(organization) this.refreshMe() } @@ -41,7 +43,7 @@ class OrganizationsPage extends Component { } handleTogglePublic = organization => { - const {actions: {updateOrganizationAsync}} = this.props + const {actionsAdmin: {updateOrganizationAsync}} = this.props updateOrganizationAsync(organization, { ...organization, public: !organization.public, @@ -49,19 +51,23 @@ class OrganizationsPage extends Component { } handleChooseDefaultRole = (organization, defaultRole) => { - const {actions: {updateOrganizationAsync}} = this.props + const {actionsAdmin: {updateOrganizationAsync}} = this.props updateOrganizationAsync(organization, {...organization, defaultRole}) // refreshMe is here to update the org's defaultRole in `me.organizations` this.refreshMe() } - handleUpdateAuthSettings = updatedAuthSettings => { - const {actions: {updateAuthSettingsAsync}, authSettings, links} = this.props - updateAuthSettingsAsync(links.config, authSettings, updatedAuthSettings) + handleUpdateAuthConfig = updatedAuthConfig => { + const { + actionsConfig: {updateAuthConfigAsync}, + authConfig, + links, + } = this.props + updateAuthConfigAsync(links.config, authConfig, updatedAuthConfig) } render() { - const {organizations, currentOrganization, authSettings} = this.props + const {organizations, currentOrganization, authConfig} = this.props return ( ) } @@ -84,7 +90,7 @@ const {arrayOf, bool, func, shape, string} = PropTypes OrganizationsPage.propTypes = { links: shape({ organizations: string.isRequired, - application: string.isRequired, + config: string.isRequired, }), organizations: arrayOf( shape({ @@ -93,35 +99,39 @@ OrganizationsPage.propTypes = { link: string, }) ), - actions: shape({ + actionsAdmin: shape({ loadOrganizationsAsync: func.isRequired, createOrganizationAsync: func.isRequired, updateOrganizationAsync: func.isRequired, deleteOrganizationAsync: func.isRequired, - getAuthSettingsAsync: func.isRequired, - updateAuthSettingsAsync: func.isRequired, + }), + actionsConfig: shape({ + getAuthConfigAsync: func.isRequired, + updateAuthConfigAsync: func.isRequired, }), getMe: func.isRequired, currentOrganization: shape({ name: string.isRequired, id: string.isRequired, }), - authSettings: shape({ - superAdminFirstUserOnly: bool.isRequired, + authConfig: shape({ + superAdminFirstUserOnly: bool, }), } const mapStateToProps = ({ links, - adminChronograf: {organizations, authSettings}, + adminChronograf: {organizations}, + config: {auth: authConfig}, }) => ({ links, organizations, - authSettings, + authConfig, }) const mapDispatchToProps = dispatch => ({ - actions: bindActionCreators(adminChronografActionCreators, dispatch), + actionsAdmin: bindActionCreators(adminChronografActionCreators, dispatch), + actionsConfig: bindActionCreators(configActionCreators, dispatch), getMe: bindActionCreators(getMeAsync, dispatch), }) diff --git a/ui/src/admin/reducers/chronograf.js b/ui/src/admin/reducers/chronograf.js index da6b64462..5c66a45d4 100644 --- a/ui/src/admin/reducers/chronograf.js +++ b/ui/src/admin/reducers/chronograf.js @@ -3,7 +3,7 @@ import {isSameUser} from 'shared/reducers/helpers/auth' const initialState = { users: [], organizations: [], - authSettings: { + authConfig: { superAdminFirstUserOnly: true, }, } @@ -94,16 +94,6 @@ const adminChronograf = (state = initialState, action) => { ), } } - - case 'CHRONOGRAF_GET_AUTH_SETTINGS_COMPLETED': - case 'CHRONOGRAF_UPDATE_AUTH_SETTINGS_REQUESTED': - case 'CHRONOGRAF_UPDATE_AUTH_SETTINGS_FAILED': { - const {authSettings} = action.payload - return { - ...state, - authSettings: {...authSettings}, // TODO: change to reflect final data shape - } - } } return state diff --git a/ui/src/shared/actions/config.js b/ui/src/shared/actions/config.js new file mode 100644 index 000000000..7d4bc4b13 --- /dev/null +++ b/ui/src/shared/actions/config.js @@ -0,0 +1,67 @@ +import { + getAuthConfig as getAuthConfigAJAX, + updateAuthConfig as updateAuthConfigAJAX, +} from 'shared/apis/config' + +import {errorThrown} from 'shared/actions/errors' + +export const getAuthConfigRequested = () => ({ + type: 'CHRONOGRAF_GET_AUTH_CONFIG_REQUESTED', +}) + +export const getAuthConfigCompleted = authConfig => ({ + type: 'CHRONOGRAF_GET_AUTH_CONFIG_COMPLETED', + payload: { + authConfig, + }, +}) + +export const getAuthConfigFailed = () => ({ + type: 'CHRONOGRAF_GET_AUTH_CONFIG_FAILED', +}) + +export const updateAuthConfigRequested = authConfig => ({ + type: 'CHRONOGRAF_UPDATE_AUTH_CONFIG_REQUESTED', + payload: { + authConfig, + }, +}) + +export const updateAuthConfigCompleted = () => ({ + type: 'CHRONOGRAF_UPDATE_AUTH_CONFIG_COMPLETED', +}) + +export const updateAuthConfigFailed = authConfig => ({ + type: 'CHRONOGRAF_UPDATE_AUTH_CONFIG_FAILED', + payload: { + authConfig, + }, +}) + +// async actions (thunks) +export const getAuthConfigAsync = url => async dispatch => { + dispatch(getAuthConfigRequested()) + try { + const {data} = await getAuthConfigAJAX(url) + dispatch(getAuthConfigCompleted(data)) // TODO: change authConfig in actions & reducers to reflect final shape + } catch (error) { + dispatch(errorThrown(error)) + dispatch(getAuthConfigFailed()) + } +} + +export const updateAuthConfigAsync = ( + url, + oldAuthConfig, + updatedAuthConfig +) => async dispatch => { + const newAuthConfig = {...oldAuthConfig, ...updatedAuthConfig} + dispatch(updateAuthConfigRequested(newAuthConfig)) + try { + await updateAuthConfigAJAX(url, newAuthConfig) + dispatch(updateAuthConfigCompleted()) + } catch (error) { + dispatch(errorThrown(error)) + dispatch(updateAuthConfigFailed(oldAuthConfig)) + } +} diff --git a/ui/src/shared/apis/config.js b/ui/src/shared/apis/config.js new file mode 100644 index 000000000..5d745cef3 --- /dev/null +++ b/ui/src/shared/apis/config.js @@ -0,0 +1,26 @@ +import AJAX from 'src/utils/ajax' + +export const getAuthConfig = async url => { + try { + return await AJAX({ + method: 'GET', + url, + }) + } catch (error) { + console.error(error) + throw error + } +} + +export const updateAuthConfig = async (url, authConfig) => { + try { + return await AJAX({ + method: 'PATCH', + url, + data: authConfig, + }) + } catch (error) { + console.error(error) + throw error + } +} diff --git a/ui/src/shared/reducers/config.js b/ui/src/shared/reducers/config.js new file mode 100644 index 000000000..08a731a00 --- /dev/null +++ b/ui/src/shared/reducers/config.js @@ -0,0 +1,22 @@ +const initialState = { + links: {}, + auth: {}, +} + +const config = (state = initialState, action) => { + switch (action.type) { + case 'CHRONOGRAF_GET_AUTH_CONFIG_COMPLETED': + case 'CHRONOGRAF_UPDATE_AUTH_CONFIG_REQUESTED': + case 'CHRONOGRAF_UPDATE_AUTH_CONFIG_FAILED': { + const {authConfig: auth} = action.payload + return { + ...state, + auth: {...auth}, + } + } + } + + return state +} + +export default config diff --git a/ui/src/shared/reducers/index.js b/ui/src/shared/reducers/index.js index b8824ab25..93b4126a7 100644 --- a/ui/src/shared/reducers/index.js +++ b/ui/src/shared/reducers/index.js @@ -1,5 +1,6 @@ import app from './app' import auth from './auth' +import config from './config' import errors from './errors' import links from './links' import {notifications, dismissedNotifications} from './notifications' @@ -8,6 +9,7 @@ import sources from './sources' export default { app, auth, + config, errors, links, notifications, diff --git a/ui/src/style/components/organizations-table.scss b/ui/src/style/components/organizations-table.scss index f98696691..b5556e1ac 100644 --- a/ui/src/style/components/organizations-table.scss +++ b/ui/src/style/components/organizations-table.scss @@ -165,7 +165,7 @@ input[type="text"].form-control.orgs-table--input { } -/* Settings table beneath organizations table */ +/* Config table beneath organizations table */ .panel .panel-body table.table.superadmin-settings { margin-top: 60px; }
SettingsConfig