add a drawer for the user details

This commit is contained in:
riley
2017-05-04 13:58:43 -06:00
parent d255ea84b1
commit 57b0b5ec67
12 changed files with 96 additions and 32 deletions
@@ -20,3 +20,4 @@ export const hideShortcutsNote = () => {
};
export const viewUserDetail = userId => ({type: actions.VIEW_USER_DETAIL, userId});
export const hideUserDetail = () => ({type: actions.HIDE_USER_DETAIL});
@@ -16,7 +16,8 @@ import {
showBanUserDialog,
hideBanUserDialog,
hideShortcutsNote,
viewUserDetail
viewUserDetail,
hideUserDetail
} from 'actions/moderation';
import {Spinner} from 'coral-ui';
@@ -118,7 +119,7 @@ class ModerationContainer extends Component {
}
render () {
const {data, moderation, settings, assets, onClose, viewUserDetail, ...props} = this.props;
const {data, moderation, settings, assets, onClose, viewUserDetail, hideUserDetail, ...props} = this.props;
const providedAssetId = this.props.params.id;
const activeTab = this.props.route.path === ':id' ? 'premod' : this.props.route.path;
@@ -189,6 +190,7 @@ class ModerationContainer extends Component {
sort={this.state.sort}
commentCount={activeTabCount}
viewUserDetail={viewUserDetail}
hideUserDetail={hideUserDetail}
/>
<BanUserDialog
open={moderation.banDialog}
@@ -204,7 +206,7 @@ class ModerationContainer extends Component {
shortcutsNoteVisible={moderation.shortcutsNoteVisible}
open={moderation.modalOpen}
onClose={onClose}/>
{moderation.userDetailId && <UserDetail id={moderation.userDetailId} />}
{moderation.userDetailId && <UserDetail id={moderation.userDetailId} hideUserDetail={hideUserDetail}/>}
</div>
);
}
@@ -223,6 +225,7 @@ const mapDispatchToProps = dispatch => ({
updateAssets: assets => dispatch(updateAssets(assets)),
fetchSettings: () => dispatch(fetchSettings()),
viewUserDetail: id => dispatch(viewUserDetail(id)),
hideUserDetail: () => dispatch(hideUserDetail()),
showBanUserDialog: (user, commentId, showRejectedNote) => dispatch(showBanUserDialog(user, commentId, showRejectedNote)),
hideBanUserDialog: () => dispatch(hideBanUserDialog(false)),
hideShortcutsNote: () => dispatch(hideShortcutsNote()),
@@ -0,0 +1,12 @@
.copyButton {
float: right;
top: -10px;
}
.memberSince {
clear: both;
}
.small {
color: #aaa;
}
@@ -1,16 +1,27 @@
import React, {PropTypes} from 'react';
import {Button, Drawer} from 'coral-ui';
import styles from './UserDetail.js';
import styles from './UserDetail.css';
import {compose} from 'react-apollo';
import {getUserDetail} from 'coral-admin/src/graphql/queries';
class UserDetail extends React.Component {
static propTypes = {
id: PropTypes.string.isRequired
id: PropTypes.string.isRequired,
hideUserDetail: PropTypes.func.isRequired
}
copyPermalink () {
this.profile.select();
try {
document.execCommand('copy');
} catch (e) {
/* nothing */
}
}
render () {
const {data} = this.props;
const {data, hideUserDetail} = this.props;
if (!('user' in data)) {
return null;
@@ -27,13 +38,16 @@ class UserDetail extends React.Component {
}
return (
<Drawer>
<Drawer handleClickOutside={hideUserDetail}>
<h3>{user.username}</h3>
<p>{profile}</p> <Button>Copy</Button>
<strong>Member since</strong> {user.created_at}
<Button className={styles.copyButton}>Copy</Button>
<p ref={ref => this.profile = ref} contentEditable="true">{profile}</p>
<p className={styles.memberSince}><strong>Member since</strong> {new Date(user.created_at).toLocaleString()}</p>
<hr/>
<strong>Account summary</strong>
<br/><span className={styles.small}>Data represents the last six months of activity</span>
<p>
<strong>Account summary</strong>
<br/><small className={styles.small}>Data represents the last six months of activity</small>
</p>
<div className={styles.stats}>
</div>
</Drawer>
@@ -2,5 +2,10 @@ query UserDetail ($id: ID!) {
user(id: $id) {
id
username
created_at
profiles {
id
provider
}
}
}
+27 -8
View File
@@ -1,12 +1,31 @@
.wrapper {
transition: opacity 250ms;
.drawer {
max-width: 700px;
padding: 20px;
position: fixed;
z-index: 10000;
background-color: rgba(0, 0, 0, .2);
height: 100%;
width: 100%;
top: 0;
right: 0;
bottom: 0;
background-color: white;
transition: transform 500ms ease-in-out;
box-shadow: -3px 0px 4px 0px rgba(0,0,0,0.15);
}
.drawer {
transition: transform 500ms ease-in-out;
.closeButton {
position: absolute;
width: 40px;
height: 40px;
left: -40px;
background-color: white;
border-radius: 4px 0 0 4px;
box-sizing: border-box;
font-size: 32px;
top: 60px;
box-shadow: -1px 3px 4px 0px rgba(0,0,0,0.15);
text-align: center;
padding-top: 10px;
cursor: pointer;
&:hover {
color: #ccc;
}
}
+8 -6
View File
@@ -1,17 +1,19 @@
import React, {PropTypes} from 'react';
import styles from './Drawer.css';
import onClickOutside from 'react-onclickoutside';
const Drawer = (props) => {
const Drawer = ({children, handleClickOutside}) => {
return (
<div className={styles.wrapper}>
<div className={styles.drawer}>{props.children}</div>
<div className={styles.closeButton} onClick={props.close}>×</div>
<div className={styles.drawer}>
<div className={styles.closeButton} onClick={handleClickOutside}>×</div>
{children}
</div>
);
};
Drawer.propTypes = {
active: PropTypes.bool
active: PropTypes.bool,
handleClickOutside: PropTypes.func.isRequired
};
export default Drawer;
export default onClickOutside(Drawer);
+9 -2
View File
@@ -10,6 +10,13 @@ const User = {
}
},
created_at({roles, created_at}, _, {user}) {
if (user && user.hasRoles('ADMIN')) {
return created_at;
}
return null;
},
comments({id}, _, {loaders: {Comments}, user}) {
// If the user is not an admin, only return comment list for the owner of
@@ -20,10 +27,10 @@ const User = {
return null;
},
profiles({id, profiles}, _, {user}) {
profiles({profiles}, _, {user}) {
// if the user is not an admin, do not return the profiles
if (user && (user.hasRoles('ADMIN') || user.id === id)) {
if (user && user.hasRoles('ADMIN')) {
return profiles;
}
+3
View File
@@ -38,6 +38,9 @@ type User {
# Username of a user.
username: String!
# creation date of user
created_at: String!
# Action summaries against the user.
action_summaries: [ActionSummary]!
+2 -4
View File
@@ -98,12 +98,10 @@
"react-recaptcha": "^2.2.6",
"recompose": "^0.23.1",
"redis": "^2.7.1",
"uuid": "^3.0.1",
"simplemde": "^1.11.2",
"subscriptions-transport-ws": "^0.5.5-alpha.0",
"resolve": "^1.3.2",
"semver": "^5.3.0",
"simplemde": "^1.11.2",
"subscriptions-transport-ws": "^0.5.5-alpha.0",
"uuid": "^3.0.1"
},
"devDependencies": {
@@ -174,7 +172,7 @@
"react-linkify": "^0.1.3",
"react-mdl": "^1.7.2",
"react-mdl-selectfield": "^0.2.0",
"react-onclickoutside": "^5.7.1",
"react-onclickoutside": "^5.11.1",
"react-redux": "^4.4.5",
"react-router": "^3.0.0",
"react-tagsinput": "^3.14.0",
+1 -1
View File
@@ -6780,7 +6780,7 @@ react-mdl@^1.7.1, react-mdl@^1.7.2:
lodash.isequal "^4.4.0"
prop-types "^15.5.0"
react-onclickoutside@^5.7.1:
react-onclickoutside@^5.11.1:
version "5.11.1"
resolved "https://registry.yarnpkg.com/react-onclickoutside/-/react-onclickoutside-5.11.1.tgz#00314e52567cf55faba94cabbacd119619070623"
dependencies: