diff --git a/.eslintrc.json b/.eslintrc.json index 5df3444a6..d15dc3367 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,4 +1,8 @@ { + "globals": { + "fetch": true, + "Headers": true + }, "env": { "es6": true, "node": true diff --git a/client/coral-admin/package.json b/client/coral-admin/package.json index 048359526..dcd26d06a 100644 --- a/client/coral-admin/package.json +++ b/client/coral-admin/package.json @@ -5,7 +5,8 @@ "main": "index.js", "scripts": { "build": "./node_modules/.bin/webpack --config webpack.config.js", - "start": "./node_modules/.bin/webpack-dev-server --config webpack.config.dev.js --inline --hot --content-base public --port 3142" + "start": "./node_modules/.bin/webpack-dev-server --config webpack.config.dev.js --inline --hot --content-base public --port 3142", + "dev": "./node_modules/.bin/webpack -w" }, "keywords": [], "author": "", diff --git a/client/coral-admin/src/actions/settings.js b/client/coral-admin/src/actions/settings.js new file mode 100644 index 000000000..73e7d9510 --- /dev/null +++ b/client/coral-admin/src/actions/settings.js @@ -0,0 +1,67 @@ +export const SETTINGS_LOADING = 'SETTINGS_LOADING' +export const SETTINGS_RECEIVED = 'SETTINGS_RECEIVED' +export const SETTINGS_FETCH_ERROR = 'SETTINGS_FETCH_ERROR' + +export const SETTINGS_UPDATED = 'SETTINGS_UPDATED' + +export const SAVE_SETTINGS_LOADING = 'SAVE_SETTINGS_LOADING' +export const SAVE_SETTINGS_SUCCESS = 'SAVE_SETTINGS_SUCCESS' +export const SAVE_SETTINGS_FAILED = 'SAVE_SETTINGS_FAILED' + +const base = '/api/v1' + +const getInit = (method, body) => { + const headers = new Headers({ + 'Content-Type': 'application/json', + 'Accept': 'application/json' + }) + + const init = {method, headers} + if (method.toLowerCase() !== 'get') { + init.body = JSON.stringify(body) + } + + return init +} + +const handleResp = res => { + if (res.status === 401) { + throw new Error('Not Authorized to make this request') + } else if (res.status > 399) { + throw new Error('Error! Status ' + res.status) + } else if (res.status === 204) { + return res.text() + } else { + return res.json() + } +} + +export const fetchSettings = () => dispatch => { + dispatch({type: SETTINGS_LOADING}) + fetch(`${base}/settings`, getInit('GET')) + .then(handleResp) + .then(settings => { + dispatch({type: SETTINGS_RECEIVED, settings}) + }) + .catch(error => { + dispatch({type: SETTINGS_FETCH_ERROR, error}) + }) +} + +export const updateSettings = settings => { + console.log('updated settings', settings) + return {type: SETTINGS_UPDATED, settings} +} + +export const saveSettingsToServer = (dispatch, getState) => { + const settings = getState().settings.settings + dispatch({type: SAVE_SETTINGS_LOADING}) + fetch(`${base}/settings`, getInit('PUT', settings)) + .then(handleResp) + .then(() => { + dispatch({type: SAVE_SETTINGS_SUCCESS, settings}) + }) + .catch(error => { + dispatch({type: SAVE_SETTINGS_FAILED, error}) + }) +} diff --git a/client/coral-admin/src/containers/Configure.css b/client/coral-admin/src/containers/Configure.css index 2c65fd5bc..b5ec3735b 100644 --- a/client/coral-admin/src/containers/Configure.css +++ b/client/coral-admin/src/containers/Configure.css @@ -20,6 +20,7 @@ border-radius: 4px; height: 90px; margin-bottom: 10px; + cursor: pointer; } .configSettingEmbed { diff --git a/client/coral-admin/src/containers/Configure.js b/client/coral-admin/src/containers/Configure.js index 4a36e56e7..70c357cc5 100644 --- a/client/coral-admin/src/containers/Configure.js +++ b/client/coral-admin/src/containers/Configure.js @@ -1,5 +1,6 @@ import React from 'react' import {connect} from 'react-redux' +import {fetchSettings, updateSettings, saveSettingsToServer} from '../actions/settings' import { List, ListItem, @@ -17,12 +18,31 @@ class Configure extends React.Component { constructor (props) { super(props) this.state = {activeSection: 'comments'} + this.updateModeration = this.updateModeration.bind(this) + this.saveSettings = this.saveSettings.bind(this) + } + + componentWillMount () { + this.props.dispatch(fetchSettings()) + } + + updateModeration () { + const moderation = this.props.settings.moderation === 'pre' ? 'post' : 'pre' + this.props.dispatch(updateSettings({moderation})) + } + + saveSettings () { + this.props.dispatch(saveSettingsToServer()) } getCommentSettings () { return - + + + Enable pre-moderation @@ -75,7 +95,7 @@ class Configure extends React.Component { icon='code'>Embed Comment Stream - @@ -93,4 +113,10 @@ class Configure extends React.Component { } } -export default connect(x => x)(Configure) +const mapStateToProps = state => { + return { + settings: state.settings.toJS() + } +} + +export default connect(mapStateToProps)(Configure) diff --git a/client/coral-admin/src/containers/ModerationQueue.js b/client/coral-admin/src/containers/ModerationQueue.js index 061786543..3f13b8bf4 100644 --- a/client/coral-admin/src/containers/ModerationQueue.js +++ b/client/coral-admin/src/containers/ModerationQueue.js @@ -20,8 +20,6 @@ class ModerationQueue extends React.Component { constructor (props) { super(props) - console.log('ModerationQueue', props) - this.state = { activeTab: 'pending', singleView: false, modalOpen: false } } @@ -60,7 +58,6 @@ class ModerationQueue extends React.Component { render () { const { comments } = this.props const { activeTab, singleView, modalOpen } = this.state - console.log('moderation queue', styles) return ( diff --git a/client/coral-admin/src/reducers/index.js b/client/coral-admin/src/reducers/index.js index 5c99e3bb2..0c95fb566 100644 --- a/client/coral-admin/src/reducers/index.js +++ b/client/coral-admin/src/reducers/index.js @@ -1,8 +1,10 @@ import { combineReducers } from 'redux' import comments from 'reducers/comments' +import settings from 'reducers/settings' // Combine all reducers into a main one export default combineReducers({ + settings, comments }) diff --git a/client/coral-admin/src/reducers/settings.js b/client/coral-admin/src/reducers/settings.js new file mode 100644 index 000000000..9d877a36d --- /dev/null +++ b/client/coral-admin/src/reducers/settings.js @@ -0,0 +1,42 @@ +import { Map } from 'immutable' +import * as types from '../actions/settings' + +const initialState = Map({ + settings: Map(), + saveSettingsError: null, + fetchSettingsError: null, + fetchingSettings: false +}) + +// Handle the comment actions +export default (state = initialState, action) => { + switch (action.type) { + case types.SETTINGS_LOADING: return state.set('fetchingSettings', true).set('fetchSettingsError', null) + case types.SETTINGS_RECEIVED: return receivedSettings(state, action) + case types.SETTINGS_FETCH_ERROR: return settingsFetchFailed(state, action) + case types.SETTINGS_UPDAETD: return state.get('settings').merge(action.settings) + case types.SAVE_SETTINGS_LOADING: return state.set('fetchingSettings', true).set('saveSettingsError', null) + case types.SAVE_SETTINGS_SUCCESS: return saveComplete(state, action) + case types.SAVE_SETTINGS_FAILED: return settingsSaveFailed(state, action) + default: return state + } +} + +const receivedSettings = (state, action) => { + state.set('fetchingSettings', false).set('fetchSettingsError', null) + return state.get('settings').merge(action.settings) +} + +const saveComplete = (state, action) => { + state.set('fetchingSettings', false).set('saveSettingsError', null) + console.log('saveComplete', action.settings) + return state.get('settings').merge(action.settings) +} + +const settingsFetchFailed = (state, action) => { + return state.set('fetchingSettings', false).set('fetchSettingsError', action.error) +} + +const settingsSaveFailed = (state, action) => { + return state.set('fetchingSettings', false).set('fetchSettingsError', action.error) +}