mirror of
https://github.com/wassname/talk.git
synced 2026-07-13 16:56:47 +08:00
This commit is contained in:
@@ -29,7 +29,7 @@ const CommentAnimatedEdit = ({ children, body }) => {
|
||||
|
||||
CommentAnimatedEdit.propTypes = {
|
||||
children: PropTypes.node,
|
||||
body: PropTypes.string,
|
||||
body: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default CommentAnimatedEdit;
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
.tombstone {
|
||||
background-color: #f0f0f0;
|
||||
padding: 1em;
|
||||
color: #1a212f;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import React from 'react';
|
||||
import styles from './CommentDeletedTombstone.css';
|
||||
import t from 'coral-framework/services/i18n';
|
||||
|
||||
const CommentDeletedTombstone = () => (
|
||||
<div className={styles.tombstone}>{t('framework.comment_is_deleted')}</div>
|
||||
);
|
||||
|
||||
export default CommentDeletedTombstone;
|
||||
@@ -96,8 +96,6 @@ class UserDetail extends React.Component {
|
||||
bulkReject,
|
||||
} = this.props;
|
||||
|
||||
console.log(rejectedComments, totalComments);
|
||||
|
||||
// if totalComments is 0, you're dividing by zero
|
||||
let rejectedPercent = rejectedComments / totalComments * 100;
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import CommentAnimatedEdit from './CommentAnimatedEdit';
|
||||
import CommentLabels from '../containers/CommentLabels';
|
||||
import ApproveButton from './ApproveButton';
|
||||
import RejectButton from 'coral-admin/src/components/RejectButton';
|
||||
import CommentDeletedTombstone from './CommentDeletedTombstone';
|
||||
|
||||
import t, { timeago } from 'coral-framework/services/i18n';
|
||||
|
||||
@@ -43,6 +44,19 @@ class UserDetailComment extends React.Component {
|
||||
body: comment.body,
|
||||
};
|
||||
|
||||
if (!comment.body) {
|
||||
return (
|
||||
<li
|
||||
tabIndex={0}
|
||||
className={cn(className, styles.root, {
|
||||
[styles.rootSelected]: selected,
|
||||
})}
|
||||
>
|
||||
<CommentDeletedTombstone />
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<li
|
||||
tabIndex={0}
|
||||
@@ -152,7 +166,7 @@ UserDetailComment.propTypes = {
|
||||
comment: PropTypes.shape({
|
||||
id: PropTypes.string.isRequired,
|
||||
status: PropTypes.string.isRequired,
|
||||
body: PropTypes.string.isRequired,
|
||||
body: PropTypes.string,
|
||||
actions: PropTypes.array,
|
||||
created_at: PropTypes.string.isRequired,
|
||||
asset: PropTypes.shape({
|
||||
|
||||
@@ -291,5 +291,36 @@ export default {
|
||||
},
|
||||
},
|
||||
}),
|
||||
SetCommentStatus: ({ variables: { status } }) => ({
|
||||
updateQueries: {
|
||||
CoralAdmin_UserDetail: prev => {
|
||||
const increment = {
|
||||
rejectedComments: {
|
||||
$apply: count => (count < prev.totalComments ? count + 1 : count),
|
||||
},
|
||||
};
|
||||
|
||||
const decrement = {
|
||||
rejectedComments: {
|
||||
$apply: count => (count > 0 ? count - 1 : 0),
|
||||
},
|
||||
};
|
||||
|
||||
// If rejected then increment rejectedComments by one
|
||||
if (status === 'REJECTED') {
|
||||
const updated = update(prev, increment);
|
||||
return updated;
|
||||
}
|
||||
|
||||
// If approved then decrement rejectedComments by one
|
||||
if (status === 'ACCEPTED') {
|
||||
const updated = update(prev, decrement);
|
||||
return updated;
|
||||
}
|
||||
|
||||
return prev;
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -57,7 +57,7 @@ class OrganizationSettings extends React.Component {
|
||||
}
|
||||
|
||||
const updater = { organizationContactEmail: { $set: email } };
|
||||
const errorUpdater = { organizationEmail: { $set: error } };
|
||||
const errorUpdater = { organizationContactEmail: { $set: error } };
|
||||
|
||||
this.props.updatePending({ updater, errorUpdater });
|
||||
};
|
||||
|
||||
@@ -85,6 +85,10 @@
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.deleted {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.moderateArticle {
|
||||
font-size: 14px;
|
||||
margin: 10px 0;
|
||||
|
||||
@@ -13,6 +13,7 @@ import IfHasLink from 'coral-admin/src/components/IfHasLink';
|
||||
import cn from 'classnames';
|
||||
import ApproveButton from 'coral-admin/src/components/ApproveButton';
|
||||
import RejectButton from 'coral-admin/src/components/RejectButton';
|
||||
import CommentDeletedTombstone from '../../../components/CommentDeletedTombstone';
|
||||
|
||||
import t, { timeago } from 'coral-framework/services/i18n';
|
||||
|
||||
@@ -75,6 +76,27 @@ class Comment extends React.Component {
|
||||
asset: comment.asset,
|
||||
};
|
||||
|
||||
if (!comment.body) {
|
||||
return (
|
||||
<li
|
||||
tabIndex={0}
|
||||
className={cn(
|
||||
className,
|
||||
'mdl-card',
|
||||
selectionStateCSS,
|
||||
styles.root,
|
||||
{ [styles.selected]: selected, [styles.dangling]: dangling },
|
||||
'talk-admin-moderate-comment',
|
||||
styles.deleted
|
||||
)}
|
||||
id={`comment_${comment.id}`}
|
||||
ref={this.handleRef}
|
||||
>
|
||||
<CommentDeletedTombstone />
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<li
|
||||
tabIndex={0}
|
||||
@@ -200,7 +222,7 @@ Comment.propTypes = {
|
||||
comment: PropTypes.shape({
|
||||
id: PropTypes.string.isRequired,
|
||||
status: PropTypes.string.isRequired,
|
||||
body: PropTypes.string.isRequired,
|
||||
body: PropTypes.string,
|
||||
action_summaries: PropTypes.array,
|
||||
actions: PropTypes.array,
|
||||
created_at: PropTypes.string.isRequired,
|
||||
|
||||
@@ -432,6 +432,7 @@ const withModQueueQuery = withQuery(
|
||||
${Object.keys(queueConfig).map(
|
||||
queue => `
|
||||
${queue}: comments(query: {
|
||||
excludeDeleted: true,
|
||||
statuses: ${
|
||||
queueConfig[queue].statuses
|
||||
? `[${queueConfig[queue].statuses.join(', ')}],`
|
||||
@@ -458,6 +459,7 @@ const withModQueueQuery = withQuery(
|
||||
${Object.keys(queueConfig).map(
|
||||
queue => `
|
||||
${queue}Count: commentCount(query: {
|
||||
excludeDeleted: true,
|
||||
statuses: ${
|
||||
queueConfig[queue].statuses
|
||||
? `[${queueConfig[queue].statuses.join(', ')}],`
|
||||
|
||||
@@ -46,7 +46,7 @@ ProfileContainer.propTypes = {
|
||||
currentUser: PropTypes.object,
|
||||
};
|
||||
|
||||
const slots = ['profileSections'];
|
||||
const slots = ['profileSections', 'profileSettings', 'profileHeader'];
|
||||
|
||||
const withProfileQuery = withQuery(
|
||||
gql`
|
||||
|
||||
@@ -214,7 +214,7 @@ AllCommentsPane.propTypes = {
|
||||
asset: PropTypes.object,
|
||||
currentUser: PropTypes.object,
|
||||
postFlag: PropTypes.func,
|
||||
postDontAgree: PropTypes.func,
|
||||
postDontAgree: PropTypes.func.isRequired,
|
||||
loadNewReplies: PropTypes.func,
|
||||
deleteAction: PropTypes.func,
|
||||
showSignInDialog: PropTypes.func,
|
||||
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
getActionSummary,
|
||||
iPerformedThisAction,
|
||||
isCommentActive,
|
||||
isCommentDeleted,
|
||||
getShallowChanges,
|
||||
} from 'coral-framework/utils';
|
||||
import t from 'coral-framework/services/i18n';
|
||||
@@ -183,7 +184,7 @@ export default class Comment extends React.Component {
|
||||
maxCharCount: PropTypes.number,
|
||||
root: PropTypes.object,
|
||||
loadMore: PropTypes.func,
|
||||
postDontAgree: PropTypes.func,
|
||||
postDontAgree: PropTypes.func.isRequired,
|
||||
animateEnter: PropTypes.bool,
|
||||
commentClassNames: PropTypes.array,
|
||||
comment: PropTypes.object.isRequired,
|
||||
@@ -409,6 +410,7 @@ export default class Comment extends React.Component {
|
||||
charCountEnable,
|
||||
showSignInDialog,
|
||||
liveUpdates,
|
||||
postDontAgree,
|
||||
emit,
|
||||
} = this.props;
|
||||
return (
|
||||
@@ -439,6 +441,7 @@ export default class Comment extends React.Component {
|
||||
key={reply.id}
|
||||
comment={reply}
|
||||
emit={emit}
|
||||
postDontAgree={postDontAgree}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
@@ -744,8 +747,14 @@ export default class Comment extends React.Component {
|
||||
|
||||
return (
|
||||
<div className={rootClassName} id={id}>
|
||||
{this.renderComment()}
|
||||
{activeReplyBox === comment.id && this.renderReplyBox()}
|
||||
{isCommentDeleted(comment) ? (
|
||||
<CommentTombstone action="deleted" />
|
||||
) : (
|
||||
<div>
|
||||
{this.renderComment()}
|
||||
{activeReplyBox === comment.id && this.renderReplyBox()}
|
||||
</div>
|
||||
)}
|
||||
{this.renderRepliesContainer()}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -13,6 +13,8 @@ class CommentTombstone extends React.Component {
|
||||
return t('framework.comment_is_ignored');
|
||||
case 'reject':
|
||||
return t('framework.comment_is_rejected');
|
||||
case 'deleted':
|
||||
return t('framework.comment_is_deleted');
|
||||
default:
|
||||
return t('framework.comment_is_hidden');
|
||||
}
|
||||
|
||||
@@ -265,7 +265,7 @@ StreamContainer.propTypes = {
|
||||
commentClassNames: PropTypes.array,
|
||||
setActiveStreamTab: PropTypes.func,
|
||||
postFlag: PropTypes.func,
|
||||
postDontAgree: PropTypes.func,
|
||||
postDontAgree: PropTypes.func.isRequired,
|
||||
deleteAction: PropTypes.func,
|
||||
showSignInDialog: PropTypes.func,
|
||||
currentUser: PropTypes.object,
|
||||
@@ -372,6 +372,7 @@ const slots = [
|
||||
'streamTabsPrepend',
|
||||
'streamTabPanes',
|
||||
'streamFilter',
|
||||
'stream',
|
||||
];
|
||||
|
||||
const fragments = {
|
||||
|
||||
@@ -26,6 +26,8 @@ export default {
|
||||
'UpdateAssetSettingsResponse',
|
||||
'UpdateAssetStatusResponse',
|
||||
'UpdateSettingsResponse',
|
||||
'ChangePasswordResponse'
|
||||
'ChangePasswordResponse',
|
||||
'UpdateEmailAddressResponse',
|
||||
'AttachLocalAuthResponse'
|
||||
),
|
||||
};
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { gql } from 'react-apollo';
|
||||
import withMutation from '../hocs/withMutation';
|
||||
import update from 'immutability-helper';
|
||||
|
||||
function convertItemType(item_type) {
|
||||
switch (item_type) {
|
||||
@@ -168,36 +167,6 @@ export const withSetCommentStatus = withMutation(
|
||||
errors: null,
|
||||
},
|
||||
},
|
||||
updateQueries: {
|
||||
CoralAdmin_UserDetail: prev => {
|
||||
const increment = {
|
||||
rejectedComments: {
|
||||
$apply: count =>
|
||||
count < prev.totalComments ? count + 1 : count,
|
||||
},
|
||||
};
|
||||
|
||||
const decrement = {
|
||||
rejectedComments: {
|
||||
$apply: count => (count > 0 ? count - 1 : 0),
|
||||
},
|
||||
};
|
||||
|
||||
// If rejected then increment rejectedComments by one
|
||||
if (status === 'REJECTED') {
|
||||
const updated = update(prev, increment);
|
||||
return updated;
|
||||
}
|
||||
|
||||
// If approved then decrement rejectedComments by one
|
||||
if (status === 'ACCEPTED') {
|
||||
const updated = update(prev, decrement);
|
||||
return updated;
|
||||
}
|
||||
|
||||
return prev;
|
||||
},
|
||||
},
|
||||
update: proxy => {
|
||||
const fragment = gql`
|
||||
fragment Talk_SetCommentStatus_Comment on Comment {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { gql } from 'react-apollo';
|
||||
import t from 'coral-framework/services/i18n';
|
||||
import union from 'lodash/union';
|
||||
import get from 'lodash/get';
|
||||
import { capitalize } from 'coral-framework/helpers/strings';
|
||||
import assignWith from 'lodash/assignWith';
|
||||
import mapValues from 'lodash/mapValues';
|
||||
@@ -221,6 +222,13 @@ export function isCommentActive(commentStatus) {
|
||||
return ['NONE', 'ACCEPTED'].indexOf(commentStatus) >= 0;
|
||||
}
|
||||
|
||||
export function isCommentDeleted(comment) {
|
||||
return (
|
||||
get(comment, 'body', null) === null ||
|
||||
get(comment, 'deleted_at', null) !== null
|
||||
);
|
||||
}
|
||||
|
||||
export function getShallowChanges(a, b) {
|
||||
return union(Object.keys(a), Object.keys(b)).filter(key => a[key] !== b[key]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user