From 9c00050f6a277dd067b00e9d173c418389e0d2c3 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Thu, 5 Oct 2017 21:05:05 +0700 Subject: [PATCH 01/20] Load settings from graph --- client/coral-admin/src/actions/configure.js | 5 + client/coral-admin/src/actions/settings.js | 58 --------- .../coral-admin/src/components/UserDetail.js | 6 - .../src/components/UserDetailComment.js | 21 ++-- client/coral-admin/src/constants/configure.js | 3 + .../coral-admin/src/containers/UserDetail.js | 2 - .../src/containers/UserDetailComment.js | 7 +- client/coral-admin/src/reducers/configure.js | 35 ++++++ client/coral-admin/src/reducers/dashboard.js | 15 +++ client/coral-admin/src/reducers/index.js | 6 +- client/coral-admin/src/reducers/settings.js | 92 -------------- .../routes/Configure/components/Configure.js | 75 ++--------- .../components/ModerationSettings.js | 1 + .../Configure/components/StreamSettings.js | 14 +-- .../Configure/components/TechSettings.js | 1 + .../routes/Configure/containers/Configure.js | 116 +++++++++++++++--- .../routes/Dashboard/containers/Dashboard.js | 10 +- .../routes/Moderation/components/Comment.js | 9 +- .../Moderation/components/Moderation.js | 7 +- .../Moderation/components/ModerationQueue.js | 6 - .../routes/Moderation/containers/Comment.js | 7 +- .../Moderation/containers/Moderation.js | 4 - 22 files changed, 218 insertions(+), 282 deletions(-) create mode 100644 client/coral-admin/src/actions/configure.js delete mode 100644 client/coral-admin/src/actions/settings.js create mode 100644 client/coral-admin/src/constants/configure.js create mode 100644 client/coral-admin/src/reducers/configure.js create mode 100644 client/coral-admin/src/reducers/dashboard.js delete mode 100644 client/coral-admin/src/reducers/settings.js diff --git a/client/coral-admin/src/actions/configure.js b/client/coral-admin/src/actions/configure.js new file mode 100644 index 000000000..cdb2a3d1b --- /dev/null +++ b/client/coral-admin/src/actions/configure.js @@ -0,0 +1,5 @@ +import * as actions from 'constants/configure'; + +export const updatePending = ({updater, errorUpdater}) => { + return {type: actions.UPDATE_PENDING, updater, errorUpdater}; +}; diff --git a/client/coral-admin/src/actions/settings.js b/client/coral-admin/src/actions/settings.js deleted file mode 100644 index 35f2013c9..000000000 --- a/client/coral-admin/src/actions/settings.js +++ /dev/null @@ -1,58 +0,0 @@ -import t from 'coral-framework/services/i18n'; - -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'; - -export const WORDLIST_UPDATED = 'WORDLIST_UPDATED'; -export const DOMAINLIST_UPDATED = 'DOMAINLIST_UPDATED'; - -export const fetchSettings = () => (dispatch, _, {rest}) => { - dispatch({type: SETTINGS_LOADING}); - rest('/settings') - .then((settings) => { - dispatch({type: SETTINGS_RECEIVED, settings}); - }) - .catch((error) => { - console.error(error); - const errorMessage = error.translation_key ? t(`error.${error.translation_key}`) : error.toString(); - dispatch({type: SETTINGS_FETCH_ERROR, error: errorMessage}); - }); -}; - -// for updating top-level settings -export const updateSettings = (settings) => { - return {type: SETTINGS_UPDATED, settings}; -}; - -// this is a nested property, so it needs a special action. -export const updateWordlist = (listName, list) => { - return {type: WORDLIST_UPDATED, listName, list}; -}; - -export const updateDomainlist = (listName, list) => { - return {type: DOMAINLIST_UPDATED, listName, list}; -}; - -export const saveSettingsToServer = () => (dispatch, getState, {rest}) => { - let settings = getState().settings; - if (settings.charCount) { - settings.charCount = parseInt(settings.charCount); - } - dispatch({type: SAVE_SETTINGS_LOADING}); - rest('/settings', {method: 'PUT', body: settings}) - .then(() => { - dispatch({type: SAVE_SETTINGS_SUCCESS, settings}); - }) - .catch((error) => { - console.error(error); - const errorMessage = error.translation_key ? t(`error.${error.translation_key}`) : error.toString(); - dispatch({type: SAVE_SETTINGS_FAILED, error: errorMessage}); - }); -}; diff --git a/client/coral-admin/src/components/UserDetail.js b/client/coral-admin/src/components/UserDetail.js index a5955af45..275503085 100644 --- a/client/coral-admin/src/components/UserDetail.js +++ b/client/coral-admin/src/components/UserDetail.js @@ -17,8 +17,6 @@ export default class UserDetail extends React.Component { userId: PropTypes.string.isRequired, hideUserDetail: PropTypes.func.isRequired, root: PropTypes.object.isRequired, - bannedWords: PropTypes.array.isRequired, - suspectWords: PropTypes.array.isRequired, acceptComment: PropTypes.func.isRequired, rejectComment: PropTypes.func.isRequired, changeStatus: PropTypes.func.isRequired, @@ -79,8 +77,6 @@ export default class UserDetail extends React.Component { }, activeTab, selectedCommentIds, - bannedWords, - suspectWords, toggleSelect, bulkAccept, bulkReject, @@ -184,8 +180,6 @@ export default class UserDetail extends React.Component { root={root} data={data} comment={comment} - suspectWords={suspectWords} - bannedWords={bannedWords} acceptComment={this.acceptThenReload} rejectComment={this.rejectThenReload} selected={selected} diff --git a/client/coral-admin/src/components/UserDetailComment.js b/client/coral-admin/src/components/UserDetailComment.js index f8d81ce8b..e3e89d00a 100644 --- a/client/coral-admin/src/components/UserDetailComment.js +++ b/client/coral-admin/src/components/UserDetailComment.js @@ -30,12 +30,11 @@ class UserDetailComment extends React.Component { render() { const { comment, - suspectWords, - bannedWords, selected, toggleSelect, className, data, + root: {settings: {wordlist: {banned, suspect}}}, } = this.props; return ( @@ -72,8 +71,8 @@ class UserDetailComment extends React.Component {
{' '} @@ -123,9 +122,15 @@ UserDetailComment.propTypes = { acceptComment: PropTypes.func.isRequired, rejectComment: PropTypes.func.isRequired, className: PropTypes.string, - suspectWords: PropTypes.arrayOf(PropTypes.string).isRequired, - bannedWords: PropTypes.arrayOf(PropTypes.string).isRequired, toggleSelect: PropTypes.func, + root: PropTypes.shape({ + settings: PropTypes.shape({ + wordlist: PropTypes.shape({ + suspect: PropTypes.arrayOf(PropTypes.string).isRequired, + banned: PropTypes.arrayOf(PropTypes.string).isRequired, + }), + }), + }), comment: PropTypes.shape({ id: PropTypes.string.isRequired, status: PropTypes.string.isRequired, @@ -136,8 +141,8 @@ UserDetailComment.propTypes = { title: PropTypes.string, url: PropTypes.string, id: PropTypes.string - }) - }) + }), + }), }; export default UserDetailComment; diff --git a/client/coral-admin/src/constants/configure.js b/client/coral-admin/src/constants/configure.js new file mode 100644 index 000000000..00985e3ff --- /dev/null +++ b/client/coral-admin/src/constants/configure.js @@ -0,0 +1,3 @@ +const prefix = 'CORAL_ADMIN'; + +export const UPDATE_PENDING = `${prefix}_UPDATE_PENDING`; diff --git a/client/coral-admin/src/containers/UserDetail.js b/client/coral-admin/src/containers/UserDetail.js index 2ae842b1d..ffc661150 100644 --- a/client/coral-admin/src/containers/UserDetail.js +++ b/client/coral-admin/src/containers/UserDetail.js @@ -179,8 +179,6 @@ const mapStateToProps = (state) => ({ selectedCommentIds: state.userDetail.selectedCommentIds, statuses: state.userDetail.statuses, activeTab: state.userDetail.activeTab, - bannedWords: state.settings.wordlist.banned, - suspectWords: state.settings.wordlist.suspect, }); const mapDispatchToProps = (dispatch) => ({ diff --git a/client/coral-admin/src/containers/UserDetailComment.js b/client/coral-admin/src/containers/UserDetailComment.js index 9eef5934f..fe95f4ae4 100644 --- a/client/coral-admin/src/containers/UserDetailComment.js +++ b/client/coral-admin/src/containers/UserDetailComment.js @@ -8,7 +8,12 @@ import CommentDetails from './CommentDetails'; export default withFragments({ root: gql` fragment CoralAdmin_UserDetailComment_root on RootQuery { - __typename + settings { + wordlist { + banned + suspect + } + } ...${getDefinitionName(CommentLabels.fragments.root)} ...${getDefinitionName(CommentDetails.fragments.root)} } diff --git a/client/coral-admin/src/reducers/configure.js b/client/coral-admin/src/reducers/configure.js new file mode 100644 index 000000000..116c8663f --- /dev/null +++ b/client/coral-admin/src/reducers/configure.js @@ -0,0 +1,35 @@ +import * as actions from '../constants/configure'; +import isEmpty from 'lodash/isEmpty'; +import update from 'immutability-helper'; + +const initialState = { + canSave: false, + pending: {}, + errors: {}, +}; + +export default function configure(state = initialState, action) { + switch (action.type) { + case actions.UPDATE_PENDING: { + let next = state; + if (action.updater) { + next = update(next, { + pending: action.updater, + }); + } + if (action.errorUpdater) { + next = update(next, { + errors: action.errorUpdater, + }); + } + const noErrors = Object.keys(next.errors).reduce((res, error) => res && !next.errors[error], true); + const canSave = !isEmpty(next.pending) && noErrors; + next = update(next, { + canSave: {$set: canSave}, + }); + + return next; + } + } + return state; +} diff --git a/client/coral-admin/src/reducers/dashboard.js b/client/coral-admin/src/reducers/dashboard.js new file mode 100644 index 000000000..3b3414d3a --- /dev/null +++ b/client/coral-admin/src/reducers/dashboard.js @@ -0,0 +1,15 @@ +// this is initialized here because +// currently you have to reload the dashboard to get new stats +// cleaner updates are planned in the future. +const DASHBOARD_WINDOW_MINUTES = 5; +let then = new Date(); +then.setMinutes(then.getMinutes() - DASHBOARD_WINDOW_MINUTES); + +const initialState = { + windowStart: then.toISOString(), + windowEnd: new Date().toISOString(), +}; + +export default function dashboard (state = initialState, _action) { + return state; +} diff --git a/client/coral-admin/src/reducers/index.js b/client/coral-admin/src/reducers/index.js index b329675a4..372fedbae 100644 --- a/client/coral-admin/src/reducers/index.js +++ b/client/coral-admin/src/reducers/index.js @@ -1,6 +1,7 @@ import auth from './auth'; import assets from './assets'; -import settings from './settings'; +import dashboard from './dashboard'; +import configure from './configure'; import community from './community'; import moderation from './moderation'; import install from './install'; @@ -12,10 +13,11 @@ import userDetail from './userDetail'; export default { auth, banUserDialog, + dashboard, + configure, suspendUserDialog, userDetail, assets, - settings, community, moderation, install, diff --git a/client/coral-admin/src/reducers/settings.js b/client/coral-admin/src/reducers/settings.js deleted file mode 100644 index 336047e5b..000000000 --- a/client/coral-admin/src/reducers/settings.js +++ /dev/null @@ -1,92 +0,0 @@ -import * as actions from '../actions/settings'; -import update from 'immutability-helper'; - -// this is initialized here because -// currently you have to reload the dashboard to get new stats -// cleaner updates are planned in the future. -// TODO: if there are more than two fields for the dashboard being created here, -// please create a new reducer specifically for the Dashboard. -const DASHBOARD_WINDOW_MINUTES = 5; -let then = new Date(); -then.setMinutes(then.getMinutes() - DASHBOARD_WINDOW_MINUTES); - -const initialState = { - wordlist: { - banned: [], - suspect: [] - }, - dashboardWindowStart: then.toISOString(), - dashboardWindowEnd: new Date().toISOString(), - domains: { - whitelist: [] - }, - saveSettingsError: null, - fetchSettingsError: null, - fetchingSettings: false -}; - -export default function settings (state = initialState, action) { - switch (action.type) { - case actions.SETTINGS_LOADING: - return { - ...state, - fetchingSettings: true, - fetchSettingsError: null, - }; - case actions.SETTINGS_RECEIVED: - return { - ...state, - fetchingSettings: false, - fetchSettingsError: null, - ...action.settings - }; - case actions.SETTINGS_FETCH_ERROR: - return { - ...state, - fetchingSettings: false, - fetchSettingsError: action.error, - }; - case actions.SETTINGS_UPDATED: - return { - ...state, - fetchingSettings: false, - fetchSettingsError: null, - ...action.settings - }; - case actions.SAVE_SETTINGS_LOADING: - return { - ...state, - fetchingSettings: true, - saveSettingsError: null, - }; - case actions.SAVE_SETTINGS_SUCCESS: - return { - ...state, - fetchingSettings: false, - fetchSettingsError: null, - ...action.settings - }; - case actions.SAVE_SETTINGS_FAILED: - return { - ...state, - fetchingSettings: false, - fetchSettingsError: action.error, - }; - case actions.WORDLIST_UPDATED: - return update(state, { - wordlist: { - [action.listName]: { - $set: action.list - } - } - }); - case actions.DOMAINLIST_UPDATED: - return update(state, { - domains: { - [action.listName]: {$set: action.list}, - } - }); - default: - return state; - } -} diff --git a/client/coral-admin/src/routes/Configure/components/Configure.js b/client/coral-admin/src/routes/Configure/components/Configure.js index 15ff69b69..f60951de3 100644 --- a/client/coral-admin/src/routes/Configure/components/Configure.js +++ b/client/coral-admin/src/routes/Configure/components/Configure.js @@ -1,6 +1,6 @@ import React, {Component} from 'react'; -import {Button, List, Item, Card, Spinner} from 'coral-ui'; +import {Button, List, Item} from 'coral-ui'; import styles from './Configure.css'; import StreamSettings from './StreamSettings'; import ModerationSettings from './ModerationSettings'; @@ -12,104 +12,57 @@ export default class Configure extends Component { state = { activeSection: 'stream', - changed: false, - errors: {} }; saveSettings = () => { this.props.saveSettingsToServer(); - this.setState({changed: false}); } changeSection = (activeSection) => { this.setState({activeSection}); } - onChangeWordlist = (listName, list) => { - this.setState({changed: true}); - this.props.updateWordlist(listName, list); - } - - onChangeDomainlist = (listName, list) => { - this.setState({changed: true}); - this.props.updateDomainlist(listName, list); - } - - onSettingUpdate = (setting) => { - this.setState({changed: true}); - this.props.updateSettings(setting); - } - - // Sets an arbitrary error string and a boolean state. - // This allows the system to track multiple errors. - onSettingError = (error, state) => { - this.setState((prevState) => { - prevState.errors[error] = state; - return prevState; - }); - } - getSection (section) { - const pageTitle = this.getPageTitle(section); let sectionComponent; switch(section){ case 'stream': sectionComponent = ; + updateSettings={this.props.updateSettings} + errors={this.props.errors} + />; break; case 'moderation': sectionComponent = ; + updateSettings={this.props.updateSettings} + />; break; case 'tech': sectionComponent = ; - } - - if (this.props.settings.fetchingSettings) { - return Loading settings...; + updateSettings={this.props.updateSettings} + />; } return (
-

{pageTitle}

{sectionComponent}
); } - getPageTitle (section) { - switch(section) { - case 'stream': - return t('configure.stream_settings'); - case 'moderation': - return t('configure.moderation_settings'); - case 'tech': - return t('configure.tech_settings'); - default: - return ''; - } - } - render () { const {activeSection} = this.state; const section = this.getSection(activeSection); - const {auth: {user}} = this.props; + const {auth: {user}, canSave} = this.props; if (!can(user, 'UPDATE_CONFIG')) { return

You must be an administrator to access config settings. Please find the nearest Admin and ask them to level you up!

; } - const showSave = Object.keys(this.state.errors).reduce( - (bool, error) => this.state.errors[error] ? false : bool, this.state.changed); - return (
@@ -126,7 +79,7 @@ export default class Configure extends Component {
{ - showSave ? + canSave ?
); diff --git a/client/coral-admin/src/routes/Configure/components/ModerationSettings.js b/client/coral-admin/src/routes/Configure/components/ModerationSettings.js index 92a5413e2..b3f51d843 100644 --- a/client/coral-admin/src/routes/Configure/components/ModerationSettings.js +++ b/client/coral-admin/src/routes/Configure/components/ModerationSettings.js @@ -28,6 +28,7 @@ const ModerationSettings = ({settings, updateSettings, onChangeWordlist}) => { return (
+

{t('configure.moderation_settings')}

() => { updateSettings({charCountEnable}); }; -const updateCharCount = (updateSettings, settingsError) => (event) => { +const updateCharCount = (updateSettings) => (event) => { + let error = null; const charCount = event.target.value; if (charCount.match(/[^0-9]/) || charCount.length === 0) { - settingsError('charCount', true); - } else { - settingsError('charCount', false); + error = true; } - updateSettings({charCount: charCount}); + updateSettings({charCount: charCount}, {setError: {'charCount': error}}); }; const updateInfoBoxEnable = (updateSettings, infoBox) => () => { @@ -68,7 +67,7 @@ const updateEditCommentWindowLength = (updateSettings) => (e) => { updateSettings({editCommentWindowLength: milliseconds || value}); }; -const StreamSettings = ({updateSettings, settingsError, settings, errors}) => { +const StreamSettings = ({updateSettings, settings, errors}) => { // just putting this here for shorthand below const on = styles.enabledSetting; @@ -76,6 +75,7 @@ const StreamSettings = ({updateSettings, settingsError, settings, errors}) => { return (
+

{t('configure.stream_settings')}

{ diff --git a/client/coral-admin/src/routes/Configure/components/TechSettings.js b/client/coral-admin/src/routes/Configure/components/TechSettings.js index 4f1202a67..2fc7afb7f 100644 --- a/client/coral-admin/src/routes/Configure/components/TechSettings.js +++ b/client/coral-admin/src/routes/Configure/components/TechSettings.js @@ -14,6 +14,7 @@ const updateCustomCssUrl = (updateSettings) => (event) => { const TechSettings = ({settings, onChangeDomainlist, updateSettings}) => { return (
+

{t('configure.tech_settings')}

diff --git a/client/coral-admin/src/routes/Configure/containers/Configure.js b/client/coral-admin/src/routes/Configure/containers/Configure.js index aff1e57b2..f6edbe2ae 100644 --- a/client/coral-admin/src/routes/Configure/containers/Configure.js +++ b/client/coral-admin/src/routes/Configure/containers/Configure.js @@ -1,42 +1,124 @@ import React, {Component} from 'react'; import {connect} from 'react-redux'; import {bindActionCreators} from 'redux'; -import {compose} from 'react-apollo'; +import {compose, gql} from 'react-apollo'; +import withQuery from 'coral-framework/hocs/withQuery'; +import {Spinner} from 'coral-ui'; +import {notify} from 'coral-framework/actions/notification'; +import merge from 'lodash/merge'; import { - fetchSettings, - updateSettings, - saveSettingsToServer, - updateWordlist, - updateDomainlist -} from '../../../actions/settings'; + updatePending, +} from '../../../actions/configure'; import Configure from '../components/Configure'; class ConfigureContainer extends Component { - componentWillMount = () => { - this.props.fetchSettings(); - } + + updateWordlist = (listName, list) => { + this.props.updatePending({updater: { + wordlist: {$apply: (wordlist) => { + const changeSet = {[listName]: list}; + if (!wordlist) { + return changeSet; + } + return { + ...wordlist, + ...changeSet, + }; + }}, + }}); + }; + + updateDomainlist = (listName, list) => { + this.props.updatePending({updater: { + domains: {$apply: (domains) => { + const changeSet = {[listName]: list}; + if (!domains) { + return changeSet; + } + return { + ...domains, + ...changeSet, + }; + }}, + }}); + }; + + updateSettings = (settings, {setError = {}} = {}) => { + this.props.updatePending({updater: {$merge: settings}, errorUpdater: {$merge: setError}}); + }; render () { - return ; + if(this.props.data.loading) { + return ; + } + + const merged = merge({}, this.props.root.settings, this.props.pending); + + return ; } } +const withConfigureQuery = withQuery(gql` + query CoralEmbedStream_Embed { + settings { + moderation + requireEmailConfirmation + infoBoxEnable + infoBoxContent + questionBoxEnable + questionBoxContent + premodLinksEnable + questionBoxIcon + autoCloseStream + customCssUrl + closedTimeout + closedMessage + editCommentWindowLength + charCountEnable + charCount + organizationName + wordlist { + suspect + banned + } + domains { + whitelist + } + } + } + `, { + options: () => ({ + variables: {}, + }), + }); + const mapStateToProps = (state) => ({ auth: state.auth, - settings: state.settings + pending: state.configure.pending, + canSave: state.configure.canSave, + errors: state.configure.errors, }); const mapDispatchToProps = (dispatch) => bindActionCreators({ - fetchSettings, - updateSettings, - saveSettingsToServer, - updateWordlist, - updateDomainlist + notify, + updatePending, }, dispatch); export default compose( + withConfigureQuery, connect(mapStateToProps, mapDispatchToProps), )(ConfigureContainer); diff --git a/client/coral-admin/src/routes/Dashboard/containers/Dashboard.js b/client/coral-admin/src/routes/Dashboard/containers/Dashboard.js index 2bb192f2e..e2e9ef28c 100644 --- a/client/coral-admin/src/routes/Dashboard/containers/Dashboard.js +++ b/client/coral-admin/src/routes/Dashboard/containers/Dashboard.js @@ -42,11 +42,11 @@ export const witDashboardQuery = withQuery(gql` } } `, { - options: ({settings: {dashboardWindowStart, dashboardWindowEnd}}) => { + options: ({windowStart, windowEnd}) => { return { variables: { - from: dashboardWindowStart, - to: dashboardWindowEnd + from: windowStart, + to: windowEnd, } }; } @@ -54,8 +54,8 @@ export const witDashboardQuery = withQuery(gql` const mapStateToProps = (state) => { return { - settings: state.settings, - moderation: state.moderation + windowStart: state.dashboard.windowStart, + windowEnd: state.dashboard.windowEnd, }; }; diff --git a/client/coral-admin/src/routes/Moderation/components/Comment.js b/client/coral-admin/src/routes/Moderation/components/Comment.js index 42c9c2d13..aedc69739 100644 --- a/client/coral-admin/src/routes/Moderation/components/Comment.js +++ b/client/coral-admin/src/routes/Moderation/components/Comment.js @@ -58,12 +58,11 @@ class Comment extends React.Component { render() { const { comment, - suspectWords, - bannedWords, selected, className, data, root, + root: {settings}, currentUserId, currentAsset, } = this.props; @@ -130,8 +129,8 @@ class Comment extends React.Component {
{' '} @@ -188,8 +187,6 @@ Comment.propTypes = { acceptComment: PropTypes.func.isRequired, rejectComment: PropTypes.func.isRequired, className: PropTypes.string, - suspectWords: PropTypes.arrayOf(PropTypes.string).isRequired, - bannedWords: PropTypes.arrayOf(PropTypes.string).isRequired, currentAsset: PropTypes.object, showBanUserDialog: PropTypes.func.isRequired, showSuspendUserDialog: PropTypes.func.isRequired, diff --git a/client/coral-admin/src/routes/Moderation/components/Moderation.js b/client/coral-admin/src/routes/Moderation/components/Moderation.js index 668d013b0..222890cf5 100644 --- a/client/coral-admin/src/routes/Moderation/components/Moderation.js +++ b/client/coral-admin/src/routes/Moderation/components/Moderation.js @@ -56,7 +56,7 @@ class Moderation extends Component { const comments = this.getComments(); const commentIdx = comments.findIndex((comment) => comment.id === selectedCommentId); const comment = comments[commentIdx]; - + if (accept) { comment.status !== 'ACCEPTED' && acceptComment({commentId: comment.id}); } else { @@ -196,7 +196,7 @@ class Moderation extends Component { } render () { - const {root, data, moderation, settings, viewUserDetail, activeTab, getModPath, queueConfig, handleCommentChange, ...props} = this.props; + const {root, data, moderation, viewUserDetail, activeTab, getModPath, queueConfig, handleCommentChange, ...props} = this.props; const {asset} = root; const assetId = asset && asset.id; @@ -235,8 +235,6 @@ class Moderation extends Component { activeTab={activeTab} singleView={moderation.singleView} selectedCommentId={this.state.selectedCommentId} - bannedWords={settings.wordlist.banned} - suspectWords={settings.wordlist.suspect} showBanUserDialog={props.showBanUserDialog} showSuspendUserDialog={props.showSuspendUserDialog} acceptComment={props.acceptComment} @@ -281,7 +279,6 @@ Moderation.propTypes = { storySearchChange: PropTypes.func.isRequired, moderation: PropTypes.object.isRequired, auth: PropTypes.object.isRequired, - settings: PropTypes.object.isRequired, queueConfig: PropTypes.object.isRequired, handleCommentChange: PropTypes.func.isRequired, setSortOrder: PropTypes.func.isRequired, diff --git a/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js b/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js index 47ed56925..dc4a8c74c 100644 --- a/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js +++ b/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js @@ -147,8 +147,6 @@ class ModerationQueue extends React.Component { key={comment.id} comment={comment} selected={true} - suspectWords={props.suspectWords} - bannedWords={props.bannedWords} viewUserDetail={viewUserDetail} showBanUserDialog={props.showBanUserDialog} showSuspendUserDialog={props.showSuspendUserDialog} @@ -193,8 +191,6 @@ class ModerationQueue extends React.Component { key={comment.id} comment={comment} selected={comment.id === selectedCommentId} - suspectWords={props.suspectWords} - bannedWords={props.bannedWords} viewUserDetail={viewUserDetail} showBanUserDialog={props.showBanUserDialog} showSuspendUserDialog={props.showSuspendUserDialog} @@ -218,8 +214,6 @@ class ModerationQueue extends React.Component { ModerationQueue.propTypes = { viewUserDetail: PropTypes.func.isRequired, - bannedWords: PropTypes.arrayOf(PropTypes.string).isRequired, - suspectWords: PropTypes.arrayOf(PropTypes.string).isRequired, currentAsset: PropTypes.object, showBanUserDialog: PropTypes.func.isRequired, showSuspendUserDialog: PropTypes.func.isRequired, diff --git a/client/coral-admin/src/routes/Moderation/containers/Comment.js b/client/coral-admin/src/routes/Moderation/containers/Comment.js index b060b9f9e..9748359ae 100644 --- a/client/coral-admin/src/routes/Moderation/containers/Comment.js +++ b/client/coral-admin/src/routes/Moderation/containers/Comment.js @@ -15,7 +15,12 @@ const slots = [ export default withFragments({ root: gql` fragment CoralAdmin_ModerationComment_root on RootQuery { - __typename + settings { + wordlist { + banned + suspect + } + } ${getSlotFragmentSpreads(slots, 'root')} ...${getDefinitionName(CommentLabels.fragments.root)} ...${getDefinitionName(CommentDetails.fragments.root)} diff --git a/client/coral-admin/src/routes/Moderation/containers/Moderation.js b/client/coral-admin/src/routes/Moderation/containers/Moderation.js index 7aa839292..8787d77cd 100644 --- a/client/coral-admin/src/routes/Moderation/containers/Moderation.js +++ b/client/coral-admin/src/routes/Moderation/containers/Moderation.js @@ -13,7 +13,6 @@ import {isPremod, getModPath} from '../../../utils'; import {withSetCommentStatus} from 'coral-framework/graphql/mutations'; import {handleCommentChange} from '../graphql'; -import {fetchSettings} from 'actions/settings'; import {showBanUserDialog} from 'actions/banUserDialog'; import {showSuspendUserDialog} from 'actions/suspendUserDialog'; import {viewUserDetail} from '../../../actions/userDetail'; @@ -146,7 +145,6 @@ class ModerationContainer extends Component { componentWillMount() { this.props.clearState(); - this.props.fetchSettings(); this.subscribeToUpdates(); } @@ -384,7 +382,6 @@ const withModQueueQuery = withQuery(({queueConfig}) => gql` const mapStateToProps = (state) => ({ moderation: state.moderation, - settings: state.settings, auth: state.auth, }); @@ -392,7 +389,6 @@ const mapDispatchToProps = (dispatch) => ({ ...bindActionCreators({ toggleModal, singleView, - fetchSettings, showBanUserDialog, hideShortcutsNote, toggleStorySearch, From 5073ef6c1b8804aa61d378d3a85cfd481e2220e5 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Fri, 6 Oct 2017 18:27:10 +0700 Subject: [PATCH 02/20] Implement save settings --- client/coral-admin/src/actions/configure.js | 4 ++++ client/coral-admin/src/constants/configure.js | 1 + client/coral-admin/src/graphql/index.js | 10 ++++++++++ client/coral-admin/src/reducers/configure.js | 6 ++++++ .../routes/Configure/components/Configure.js | 8 ++------ .../routes/Configure/containers/Configure.js | 18 +++++++++++++++++- client/coral-framework/graphql/fragments.js | 1 + client/coral-framework/graphql/mutations.js | 18 ++++++++++++++++++ 8 files changed, 59 insertions(+), 7 deletions(-) diff --git a/client/coral-admin/src/actions/configure.js b/client/coral-admin/src/actions/configure.js index cdb2a3d1b..cf33a4d11 100644 --- a/client/coral-admin/src/actions/configure.js +++ b/client/coral-admin/src/actions/configure.js @@ -3,3 +3,7 @@ import * as actions from 'constants/configure'; export const updatePending = ({updater, errorUpdater}) => { return {type: actions.UPDATE_PENDING, updater, errorUpdater}; }; + +export const clearPending = () => { + return {type: actions.CLEAR_PENDING}; +}; diff --git a/client/coral-admin/src/constants/configure.js b/client/coral-admin/src/constants/configure.js index 00985e3ff..f2d55a2c2 100644 --- a/client/coral-admin/src/constants/configure.js +++ b/client/coral-admin/src/constants/configure.js @@ -1,3 +1,4 @@ const prefix = 'CORAL_ADMIN'; export const UPDATE_PENDING = `${prefix}_UPDATE_PENDING`; +export const CLEAR_PENDING = `${prefix}_CLEAR_PENDING`; diff --git a/client/coral-admin/src/graphql/index.js b/client/coral-admin/src/graphql/index.js index 6b8aa7456..bb83199e5 100644 --- a/client/coral-admin/src/graphql/index.js +++ b/client/coral-admin/src/graphql/index.js @@ -29,6 +29,16 @@ export default { } } }), + UpdateSettings: ({variables: {input}}) => ({ + updateQueries: { + TalkAdmin_Configure: (prev) => { + const updated = update(prev, { + settings: {$merge: input}, + }); + return updated; + } + } + }), }, }; diff --git a/client/coral-admin/src/reducers/configure.js b/client/coral-admin/src/reducers/configure.js index 116c8663f..a692addc1 100644 --- a/client/coral-admin/src/reducers/configure.js +++ b/client/coral-admin/src/reducers/configure.js @@ -30,6 +30,12 @@ export default function configure(state = initialState, action) { return next; } + case actions.CLEAR_PENDING: + return { + ...state, + pending: {}, + canSave: false, + }; } return state; } diff --git a/client/coral-admin/src/routes/Configure/components/Configure.js b/client/coral-admin/src/routes/Configure/components/Configure.js index f60951de3..5b5f9a524 100644 --- a/client/coral-admin/src/routes/Configure/components/Configure.js +++ b/client/coral-admin/src/routes/Configure/components/Configure.js @@ -14,10 +14,6 @@ export default class Configure extends Component { activeSection: 'stream', }; - saveSettings = () => { - this.props.saveSettingsToServer(); - } - changeSection = (activeSection) => { this.setState({activeSection}); } @@ -57,7 +53,7 @@ export default class Configure extends Component { render () { const {activeSection} = this.state; const section = this.getSection(activeSection); - const {auth: {user}, canSave} = this.props; + const {auth: {user}, canSave, savePending} = this.props; if (!can(user, 'UPDATE_CONFIG')) { return

You must be an administrator to access config settings. Please find the nearest Admin and ask them to level you up!

; @@ -82,7 +78,7 @@ export default class Configure extends Component { canSave ?