diff --git a/client/coral-admin/src/actions/moderation.js b/client/coral-admin/src/actions/moderation.js index b7117181e..557954b70 100644 --- a/client/coral-admin/src/actions/moderation.js +++ b/client/coral-admin/src/actions/moderation.js @@ -18,3 +18,5 @@ export const hideShortcutsNote = () => { return {type: actions.HIDE_SHORTCUTS_NOTE}; }; + +export const viewUserDetail = userId => ({type: actions.VIEW_USER_DETAIL, userId}); diff --git a/client/coral-admin/src/components/UserDetail.js b/client/coral-admin/src/components/UserDetail.js deleted file mode 100644 index aa6997dc4..000000000 --- a/client/coral-admin/src/components/UserDetail.js +++ /dev/null @@ -1,39 +0,0 @@ -import React, {PropTypes} from 'react'; -import {Button, Drawer} from 'coral-ui'; -import styles from './UserDetail.js'; - -const UserDetail = ({user}) => { - const localProfile = user.profiles.find(p => p.provider === 'local'); - const facebookProfile = user.profiles.find(p => p.provider === 'facebook'); - let profile; - if (localProfile) { - profile = profile.id; - } else if (facebookProfile) { - profile = {facebookProfile.id}; - } - - return ( - -

{user.username}

-

{profile}

- Member since {user.created_at} -
- Account summary -
Data represents the last six months of activity -
-
-
- ); -}; - -UserDetail.propTypes = { - user: PropTypes.shape({ - username: PropTypes.string.isRequired, - profiles: PropTypes.arrayOf(PropTypes.shape({ - id: PropTypes.string, - provider: PropTypes.string - })) - }) -}; - -export default UserDetail; diff --git a/client/coral-admin/src/constants/moderation.js b/client/coral-admin/src/constants/moderation.js index 14672146e..1d09b0e1a 100644 --- a/client/coral-admin/src/constants/moderation.js +++ b/client/coral-admin/src/constants/moderation.js @@ -3,3 +3,5 @@ export const SINGLE_VIEW = 'SINGLE_VIEW'; export const SHOW_BANUSER_DIALOG = 'SHOW_BANUSER_DIALOG'; export const HIDE_BANUSER_DIALOG = 'HIDE_BANUSER_DIALOG'; export const HIDE_SHORTCUTS_NOTE = 'HIDE_SHORTCUTS_NOTE'; +export const VIEW_USER_DETAIL = 'VIEW_USER_DETAIL'; +export const HIDE_USER_DETAIL = 'HIDE_USER_DETAIL'; diff --git a/client/coral-admin/src/containers/ModerationQueue/ModerationContainer.js b/client/coral-admin/src/containers/ModerationQueue/ModerationContainer.js index fac092a77..b76de1d05 100644 --- a/client/coral-admin/src/containers/ModerationQueue/ModerationContainer.js +++ b/client/coral-admin/src/containers/ModerationQueue/ModerationContainer.js @@ -5,12 +5,19 @@ import key from 'keymaster'; import isEqual from 'lodash/isEqual'; import styles from './components/styles.css'; -import {modQueueQuery, getUserDetail} from '../../graphql/queries'; +import {modQueueQuery} from '../../graphql/queries'; import {banUser, setCommentStatus} from '../../graphql/mutations'; import {fetchSettings} from 'actions/settings'; import {updateAssets} from 'actions/assets'; -import {toggleModal, singleView, showBanUserDialog, hideBanUserDialog, hideShortcutsNote} from 'actions/moderation'; +import { + toggleModal, + singleView, + showBanUserDialog, + hideBanUserDialog, + hideShortcutsNote, + viewUserDetail +} from 'actions/moderation'; import {Spinner} from 'coral-ui'; import BanUserDialog from '../../components/BanUserDialog'; @@ -19,7 +26,7 @@ import ModerationMenu from './components/ModerationMenu'; import ModerationHeader from './components/ModerationHeader'; import NotFoundAsset from './components/NotFoundAsset'; import ModerationKeysModal from '../../components/ModerationKeysModal'; -import UserDetail from '../../components/UserDetail'; +import UserDetail from './UserDetail'; class ModerationContainer extends Component { state = { @@ -77,15 +84,6 @@ class ModerationContainer extends Component { } } - viewUserDetail = (id) => { - console.log('getting user detail', id, typeof getUserDetail); - try { - getUserDetail({id}); - } catch (e) { - console.log(e); - } - } - selectSort = (sort) => { this.setState({sort}); this.props.modQueueResort(sort); @@ -120,7 +118,7 @@ class ModerationContainer extends Component { } render () { - const {data, moderation, settings, assets, onClose, ...props} = this.props; + const {data, moderation, settings, assets, onClose, viewUserDetail, ...props} = this.props; const providedAssetId = this.props.params.id; const activeTab = this.props.route.path === ':id' ? 'premod' : this.props.route.path; @@ -190,7 +188,7 @@ class ModerationContainer extends Component { assetId={providedAssetId} sort={this.state.sort} commentCount={activeTabCount} - viewUserDetail={this.viewUserDetail} + viewUserDetail={viewUserDetail} /> - {data.user && } + {moderation.userDetailId && } ); } @@ -224,6 +222,7 @@ const mapDispatchToProps = dispatch => ({ singleView: () => dispatch(singleView()), updateAssets: assets => dispatch(updateAssets(assets)), fetchSettings: () => dispatch(fetchSettings()), + viewUserDetail: id => dispatch(viewUserDetail(id)), showBanUserDialog: (user, commentId, showRejectedNote) => dispatch(showBanUserDialog(user, commentId, showRejectedNote)), hideBanUserDialog: () => dispatch(hideBanUserDialog(false)), hideShortcutsNote: () => dispatch(hideShortcutsNote()), diff --git a/client/coral-admin/src/containers/ModerationQueue/UserDetail.js b/client/coral-admin/src/containers/ModerationQueue/UserDetail.js new file mode 100644 index 000000000..45d98c56c --- /dev/null +++ b/client/coral-admin/src/containers/ModerationQueue/UserDetail.js @@ -0,0 +1,46 @@ +import React, {PropTypes} from 'react'; +import {Button, Drawer} from 'coral-ui'; +import styles from './UserDetail.js'; +import {compose} from 'react-apollo'; +import {getUserDetail} from 'coral-admin/src/graphql/queries'; + +class UserDetail extends React.Component { + static propTypes = { + id: PropTypes.string.isRequired + } + + render () { + const {data} = this.props; + + if (!('user' in data)) { + return null; + } + + const {user} = data; + const localProfile = user.profiles.find(p => p.provider === 'local'); + const facebookProfile = user.profiles.find(p => p.provider === 'facebook'); + let profile; + if (localProfile) { + profile = localProfile.id; + } else if (facebookProfile) { + profile = {facebookProfile.id}; + } + + return ( + +

{user.username}

+

{profile}

+ Member since {user.created_at} +
+ Account summary +
Data represents the last six months of activity +
+
+
+ ); + } +} + +export default compose( + getUserDetail +)(UserDetail); diff --git a/client/coral-admin/src/containers/ModerationQueue/components/Comment.js b/client/coral-admin/src/containers/ModerationQueue/components/Comment.js index b35c688cd..8956e6e03 100644 --- a/client/coral-admin/src/containers/ModerationQueue/components/Comment.js +++ b/client/coral-admin/src/containers/ModerationQueue/components/Comment.js @@ -35,10 +35,7 @@ const Comment = ({actions = [], comment, viewUserDetail, ...props}) => {
- { - console.log('clickt', comment.user.id); - viewUserDetail(comment.user.id); - }}> + viewUserDetail(comment.user.id)}> {comment.user.name} diff --git a/client/coral-admin/src/graphql/queries/index.js b/client/coral-admin/src/graphql/queries/index.js index aa5ffa505..8ab3c7292 100644 --- a/client/coral-admin/src/graphql/queries/index.js +++ b/client/coral-admin/src/graphql/queries/index.js @@ -95,16 +95,10 @@ export const modQueueResort = (id, fetchMore) => (sort) => { }); }; -export const getUserDetail = ({id}) => { - console.log('close', id); - return graphql(USER_DETAIL, { - options: () => { - console.log('so close!', id); - return { - variables: { - id - } - }; - } - }); -}; +export const getUserDetail = graphql(USER_DETAIL, { + options: ({id}) => { + return { + variables: {id} + }; + } +}); diff --git a/client/coral-admin/src/reducers/moderation.js b/client/coral-admin/src/reducers/moderation.js index a40ac865f..d8b9c59bb 100644 --- a/client/coral-admin/src/reducers/moderation.js +++ b/client/coral-admin/src/reducers/moderation.js @@ -6,6 +6,7 @@ const initialState = Map({ modalOpen: false, user: Map({}), commentId: null, + userDetailId: null, banDialog: false, shortcutsNoteVisible: window.localStorage.getItem('coral:shortcutsNote') || 'show' }); @@ -35,6 +36,10 @@ export default function moderation (state = initialState, action) { case actions.HIDE_SHORTCUTS_NOTE: return state .set('shortcutsNoteVisible', 'hide'); + case actions.VIEW_USER_DETAIL: + return state.set('userDetailId', action.userId); + case actions.HIDE_USER_DETAIL: + return state.set('userDetailId', null); default : return state; } diff --git a/graph/resolvers/root_query.js b/graph/resolvers/root_query.js index 622584310..9dd78c2fc 100644 --- a/graph/resolvers/root_query.js +++ b/graph/resolvers/root_query.js @@ -98,7 +98,6 @@ const RootQuery = { // this returns an arbitrary user user(_, {id}, {user, loaders: {Users}}) { - console.log("user id!", id); if (user == null || !user.hasRoles('ADMIN')) { return null; } diff --git a/graph/resolvers/user.js b/graph/resolvers/user.js index d8ed7ee15..4f6528454 100644 --- a/graph/resolvers/user.js +++ b/graph/resolvers/user.js @@ -20,6 +20,15 @@ const User = { return null; }, + profiles({id, profiles}, _, {user}) { + + // if the user is not an admin, do not return the profiles + if (user && (user.hasRoles('ADMIN') || user.id === id)) { + return profiles; + } + + return null; + }, roles({id, roles}, _, {user}) { // If the user is not an admin, only return the current user's roles. diff --git a/graph/typeDefs.graphql b/graph/typeDefs.graphql index 4fa7a1531..f1d0acac4 100644 --- a/graph/typeDefs.graphql +++ b/graph/typeDefs.graphql @@ -20,6 +20,14 @@ enum USER_ROLES { MODERATOR } +type UserProfile { + # the id is an identifier for the user profile (email, facebook id, etc) + id: String! + + # name of the provider attached to the authentication mode + provider: String! +} + # Any person who can author comments, create actions, and view comments on a # stream. type User { @@ -39,6 +47,9 @@ type User { # the current roles of the user. roles: [USER_ROLES] + # the current profiles of the user. + profiles: [UserProfile] + # determines whether the user can edit their username canEditName: Boolean