diff --git a/client/.babelrc b/.babelrc
similarity index 60%
rename from client/.babelrc
rename to .babelrc
index 2af1a3dad..92a64c2a4 100644
--- a/client/.babelrc
+++ b/.babelrc
@@ -1,9 +1,8 @@
{
"presets": [
- "es2015"
+ ["es2015", {modules: false}]
],
"plugins": [
- "add-module-exports",
"transform-class-properties",
"transform-decorators-legacy",
"transform-object-assign",
@@ -11,5 +10,12 @@
"transform-async-to-generator",
"transform-react-jsx",
"syntax-dynamic-import"
- ]
-}
\ No newline at end of file
+ ],
+ "env": {
+ "test": {
+ "plugins": [
+ ["transform-es2015-modules-commonjs", "dynamic-import-node"]
+ ]
+ }
+ }
+}
diff --git a/.eslintignore b/.eslintignore
index fc0214dd2..fd85e4523 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -26,5 +26,7 @@ plugins/*
!plugins/talk-plugin-toxic-comments
!plugins/talk-plugin-remember-sort
!plugins/talk-plugin-deep-reply-count
+!plugins/talk-plugin-subscriber
+!plugins/talk-plugin-flag-details
node_modules
diff --git a/.gitignore b/.gitignore
index bcc7c89b1..9c55f2708 100644
--- a/.gitignore
+++ b/.gitignore
@@ -43,5 +43,7 @@ plugins/*
!plugins/talk-plugin-toxic-comments
!plugins/talk-plugin-remember-sort
!plugins/talk-plugin-deep-reply-count
+!plugins/talk-plugin-subscriber
+!plugins/talk-plugin-flag-details
**/node_modules/*
diff --git a/bin/templates/plugin/client/.babelrc b/bin/templates/plugin/client/.babelrc
deleted file mode 100644
index 60be246eb..000000000
--- a/bin/templates/plugin/client/.babelrc
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "presets": [
- "es2015"
- ],
- "plugins": [
- "add-module-exports",
- "transform-class-properties",
- "transform-decorators-legacy",
- "transform-object-assign",
- "transform-object-rest-spread",
- "transform-async-to-generator",
- "transform-react-jsx"
- ]
-}
\ No newline at end of file
diff --git a/client/coral-admin/src/components/ActionButton.css b/client/coral-admin/src/components/ActionButton.css
deleted file mode 100644
index 226006c6b..000000000
--- a/client/coral-admin/src/components/ActionButton.css
+++ /dev/null
@@ -1,24 +0,0 @@
-.actionButton {
- transform: scale(.8);
- margin: 0;
-}
-
-.minimal {
- width: 45px;
- min-width: 0;
-}
-
-.approve__active {
- box-shadow: none;
- color: white;
- background-color: #519954;
- cursor: not-allowed;
-}
-
-.reject__active, .rejected__active {
- color: white;
- background-color: #D03235;
- box-shadow: none;
- cursor: not-allowed;
-}
-
diff --git a/client/coral-admin/src/components/ActionButton.js b/client/coral-admin/src/components/ActionButton.js
deleted file mode 100644
index 77456b939..000000000
--- a/client/coral-admin/src/components/ActionButton.js
+++ /dev/null
@@ -1,38 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-
-import styles from './ActionButton.css';
-import {Button} from 'coral-ui';
-import {menuActionsMap} from '../utils/moderationQueueActionsMap';
-
-import t from 'coral-framework/services/i18n';
-
-const ActionButton = ({type = '', active, ...props}) => {
- const typeName = type.toLowerCase();
- let text = menuActionsMap[type].text;
-
- if (text === 'approve' && active) {
- text = 'approved';
- } else if (text === 'reject' && active) {
- text = 'rejected';
- }
-
- return (
-
- );
-};
-
-ActionButton.propTypes = {
- active: PropTypes.bool,
- type: PropTypes.oneOf(['APPROVE', 'REJECT']),
- minimal: PropTypes.bool,
- acceptComment: PropTypes.func,
- rejectComment: PropTypes.func,
-};
-
-export default ActionButton;
diff --git a/client/coral-admin/src/components/ApproveButton.css b/client/coral-admin/src/components/ApproveButton.css
new file mode 100644
index 000000000..4c42cc233
--- /dev/null
+++ b/client/coral-admin/src/components/ApproveButton.css
@@ -0,0 +1,44 @@
+.root {
+ display: block;
+ color: #519954;
+ border: solid 2px rgba(81, 153, 84, 0.75);
+ background: white;
+ padding: 10px 12px;
+ box-sizing: border-box;
+ vertical-align: middle;
+ line-height: 24px;
+ font-size: 17px;
+ height: 47px;
+ border-radius: 3px;
+ text-transform: capitalize;
+ box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.03), 0 3px 1px -2px rgba(0,0,0,.2), 0 1px 5px 0 rgba(0,0,0,.09);
+ width: 129px;
+ transform: scale(.8);
+ margin: 0;
+
+ &:hover {
+ box-shadow: none;
+ color: white;
+ background-color: #519954;
+ cursor: pointer;
+ }
+}
+
+.active {
+ box-shadow: none;
+ color: white;
+ background-color: #519954;
+
+ &:hover {
+ cursor: not-allowed;
+ }
+}
+
+.minimal {
+ width: 45px;
+ min-width: 0;
+}
+
+.icon {
+ margin-right: 5px;
+}
diff --git a/client/coral-admin/src/components/ApproveButton.js b/client/coral-admin/src/components/ApproveButton.js
new file mode 100644
index 000000000..151a5ca29
--- /dev/null
+++ b/client/coral-admin/src/components/ApproveButton.js
@@ -0,0 +1,30 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+import cn from 'classnames';
+import styles from './ApproveButton.css';
+import {Icon} from 'coral-ui';
+
+import t from 'coral-framework/services/i18n';
+
+const ApproveButton = ({active, minimal, onClick}) => {
+ const text = active ? t('modqueue.approved') : t('modqueue.approve');
+ return (
+
+ );
+};
+
+ApproveButton.propTypes = {
+ active: PropTypes.bool,
+ minimal: PropTypes.bool,
+ onClick: PropTypes.func,
+};
+
+export default ApproveButton;
+
diff --git a/client/coral-admin/src/components/CommentDetails.css b/client/coral-admin/src/components/CommentDetails.css
new file mode 100644
index 000000000..1ee1c46dd
--- /dev/null
+++ b/client/coral-admin/src/components/CommentDetails.css
@@ -0,0 +1,18 @@
+.root {
+ min-height: 25px;
+ padding: 0 16px;
+}
+
+.moreDetail {
+ position: absolute;
+ font-size: 12px;
+ font-weight: 500;
+ color: black;
+ right: 16px;
+
+ &:hover {
+ opacity: 0.9;
+ cursor: pointer;
+ }
+}
+
diff --git a/client/coral-admin/src/components/CommentDetails.js b/client/coral-admin/src/components/CommentDetails.js
new file mode 100644
index 000000000..cd504a40f
--- /dev/null
+++ b/client/coral-admin/src/components/CommentDetails.js
@@ -0,0 +1,66 @@
+import React, {Component} from 'react';
+import PropTypes from 'prop-types';
+import styles from './CommentDetails.css';
+import t from 'coral-framework/services/i18n';
+import Slot from 'coral-framework/components/Slot';
+import IfSlotIsNotEmpty from 'coral-framework/components/IfSlotIsNotEmpty';
+
+class CommentDetails extends Component {
+ state = {
+ showDetail: false
+ };
+
+ constructor () {
+ super();
+ this.state = {
+ showDetail: false
+ };
+ }
+
+ toggleDetail = () => {
+ this.setState((state) => ({
+ showDetail: !state.showDetail
+ }));
+ }
+
+ render() {
+ const {data, root, comment} = this.props;
+ const {showDetail} = this.state;
+ const queryData = {
+ root,
+ comment,
+ };
+
+ return (
+
+ );
+ }
+}
+
+CommentDetails.propTypes = {
+ data: PropTypes.object.isRequired,
+ root: PropTypes.object.isRequired,
+ comment: PropTypes.object.isRequired,
+};
+
+export default CommentDetails;
diff --git a/client/coral-admin/src/components/FlagBox.css b/client/coral-admin/src/components/FlagBox.css
deleted file mode 100644
index 232803203..000000000
--- a/client/coral-admin/src/components/FlagBox.css
+++ /dev/null
@@ -1,83 +0,0 @@
-.flagBox {
- border-top: 1px solid rgba(66, 66, 66, 0.12);
- margin-top: 10px;
- .container {
- padding: 0 14px;
- }
-
- .detail {
- padding: 0 20px 16px;
- ul {
- padding: 0;
- list-style: none;
- font-size: 12px;
- font-weight: 500;
- }
- }
-
- .header {
- position: relative;
- .moreDetail {
- float: right;
- font-size: 12px;
- font-weight: 500;
- margin-right: 10px;
- margin-top: 8px;
- color: black;
-
- &:hover {
- opacity: 0.9;
- cursor: pointer;
- }
- }
- i {
- vertical-align: middle;
- font-size: 12px;
- }
- ul {
- vertical-align: middle;
- list-style: none;
- display: inline-block;
- padding: 0;
- margin-left: 10px;
- font-size: 12px;
- }
- }
-
- h3 {
- vertical-align: middle;
- margin: 0;
- font-weight: 500;
- display: inline-block;
- margin-left: 7px;
- font-size: 12px;
- }
-}
-
-.lessDetail {
- display: inline-block;
- margin-right: 10px;
-}
-
-.subDetail {
- font-weight: normal;
- color: #888;
-
- span {
- color: black;
- }
-}
-
-.username {
- color: #393B44;
- text-decoration: none;
- cursor: pointer;
- font-weight: 600;
- padding: 2px 5px;
- border-radius: 2px;
- margin-left: -5px;
- transition: background-color 200ms ease;
-&:hover {
- background-color: #E0E0E0;
- }
-}
diff --git a/client/coral-admin/src/components/FlagBox.js b/client/coral-admin/src/components/FlagBox.js
deleted file mode 100644
index 05fd14128..000000000
--- a/client/coral-admin/src/components/FlagBox.js
+++ /dev/null
@@ -1,97 +0,0 @@
-import React, {Component} from 'react';
-import PropTypes from 'prop-types';
-import {Icon} from 'coral-ui';
-import styles from './FlagBox.css';
-import t from 'coral-framework/services/i18n';
-
-const shortReasons = {
- 'This comment is offensive': t('modqueue.offensive'),
- 'This looks like an ad/marketing': t('modqueue.spam_ads'),
- 'This user is impersonating': t('modqueue.impersonating'),
- 'I don\'t like this username': t('modqueue.dont_like_username'),
- 'Other': t('modqueue.other')
-};
-
-class FlagBox extends Component {
- constructor () {
- super();
- this.state = {
- showDetail: false
- };
- }
-
- toggleDetail = () => {
- this.setState((state) => ({
- showDetail: !state.showDetail
- }));
- }
-
- reasonMap = (reason) => {
- const shortReason = shortReasons[reason];
-
- // if the short reason isn't found, just return the long one.
- return shortReason ? shortReason : reason;
- }
-
- render() {
- const {actionSummaries, actions, viewUserDetail} = this.props;
- const {showDetail} = this.state;
-
- return (
-
-
-
- {showDetail && (
-
-
- {actionSummaries.map((summary, i) => {
-
- const actionList = actions.filter((a) => a.reason === summary.reason);
-
- return (
- -
- {this.reasonMap(summary.reason)} ({summary.count})
-
-
- );
- })}
-
-
- )}
-
-
- );
- }
-}
-
-FlagBox.propTypes = {
- actionSummaries: PropTypes.arrayOf(PropTypes.shape({
- reason: PropTypes.string,
- count: PropTypes.number
- })).isRequired,
- actions: PropTypes.arrayOf(PropTypes.shape({
- message: PropTypes.string,
- user: PropTypes.shape({username: PropTypes.string})
- })).isRequired
-};
-
-export default FlagBox;
diff --git a/client/coral-admin/src/components/RejectButton.css b/client/coral-admin/src/components/RejectButton.css
new file mode 100644
index 000000000..a06cf5f43
--- /dev/null
+++ b/client/coral-admin/src/components/RejectButton.css
@@ -0,0 +1,44 @@
+.root {
+ display: block;
+ color: #D03235;
+ border: solid 1px #D03235;
+ background: white;
+ padding: 10px 11px;
+ box-sizing: border-box;
+ vertical-align: middle;
+ line-height: 24px;
+ font-size: 17px;
+ height: 47px;
+ border-radius: 3px;
+ text-transform: capitalize;
+ box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.03), 0 3px 1px -2px rgba(0,0,0,.2), 0 1px 5px 0 rgba(0,0,0,.09);
+ width: 129px;
+ transform: scale(.8);
+ margin: 0;
+
+ &:hover {
+ color: white;
+ background-color: #D03235;
+ box-shadow: none;
+ cursor: pointer;
+ }
+}
+
+.active {
+ color: white;
+ background-color: #D03235;
+ box-shadow: none;
+
+ &:hover {
+ cursor: not-allowed;
+ }
+}
+
+.minimal {
+ width: 45px;
+ min-width: 0;
+}
+
+.icon {
+ margin-right: 5px;
+}
diff --git a/client/coral-admin/src/components/RejectButton.js b/client/coral-admin/src/components/RejectButton.js
new file mode 100644
index 000000000..e01102dc3
--- /dev/null
+++ b/client/coral-admin/src/components/RejectButton.js
@@ -0,0 +1,30 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+import cn from 'classnames';
+import styles from './RejectButton.css';
+import {Icon} from 'coral-ui';
+
+import t from 'coral-framework/services/i18n';
+
+const RejectButton = ({active, minimal, onClick}) => {
+ const text = active ? t('modqueue.rejected') : t('modqueue.reject');
+ return (
+
+ );
+};
+
+RejectButton.propTypes = {
+ active: PropTypes.bool,
+ minimal: PropTypes.bool,
+ onClick: PropTypes.func,
+};
+
+export default RejectButton;
+
diff --git a/client/coral-admin/src/components/UserDetail.js b/client/coral-admin/src/components/UserDetail.js
index b6b239057..a5955af45 100644
--- a/client/coral-admin/src/components/UserDetail.js
+++ b/client/coral-admin/src/components/UserDetail.js
@@ -5,7 +5,6 @@ import styles from './UserDetail.css';
import {Icon, Button, Drawer, Spinner} from 'coral-ui';
import {Slot} from 'coral-framework/components';
import ButtonCopyToClipboard from './ButtonCopyToClipboard';
-import {actionsMap} from '../utils/moderationQueueActionsMap';
import ClickOutside from 'coral-framework/components/ClickOutside';
import LoadMore from '../components/LoadMore';
import cn from 'classnames';
@@ -70,6 +69,7 @@ export default class UserDetail extends React.Component {
renderLoaded() {
const {
+ data,
root,
root: {
user,
@@ -177,15 +177,15 @@ export default class UserDetail extends React.Component {
{
nodes.map((comment) => {
- const status = comment.action_summaries ? 'FLAGGED' : comment.status;
const selected = selectedCommentIds.indexOf(comment.id) !== -1;
return
(this.props.comment.status === 'ACCEPTED'
+ ? null
+ : this.props.acceptComment({commentId: this.props.comment.id})
+ );
+
+ reject = () => (this.props.comment.status === 'REJECTED'
+ ? null
+ : this.props.rejectComment({commentId: this.props.comment.id})
+ );
+
render() {
const {
- actions = [],
comment,
- viewUserDetail,
suspectWords,
bannedWords,
selected,
toggleSelect,
className,
- user,
- ...props
+ data,
} = this.props;
- const flagActionSummaries = getActionSummary('FlagActionSummary', comment);
- const flagActions = comment.actions && comment.actions.filter((a) => a.__typename === 'FlagAction');
-
return (
-
+
{t('comment.view_context')}
-
+
@@ -88,41 +92,26 @@ class UserDetailComment extends React.Component {
- {actions.map((action, i) => {
- const active =
- (action === 'REJECT' && comment.status === 'REJECTED') ||
- (action === 'APPROVE' && comment.status === 'ACCEPTED');
- return (
-
- (comment.status === 'ACCEPTED'
- ? null
- : props.acceptComment({commentId: comment.id}))}
- rejectComment={() =>
- (comment.status === 'REJECTED'
- ? null
- : props.rejectComment({commentId: comment.id}))}
- />
- );
- })}
+
+
- {flagActions && flagActions.length
- ?
- : null}
+
);
}
@@ -138,8 +127,9 @@ UserDetailComment.propTypes = {
bannedWords: PropTypes.arrayOf(PropTypes.string).isRequired,
toggleSelect: PropTypes.func,
comment: PropTypes.shape({
+ id: PropTypes.string.isRequired,
+ status: PropTypes.string.isRequired,
body: PropTypes.string.isRequired,
- action_summaries: PropTypes.array,
actions: PropTypes.array,
created_at: PropTypes.string.isRequired,
asset: PropTypes.shape({
diff --git a/client/coral-admin/src/containers/CommentDetails.js b/client/coral-admin/src/containers/CommentDetails.js
new file mode 100644
index 000000000..cf8c2c307
--- /dev/null
+++ b/client/coral-admin/src/containers/CommentDetails.js
@@ -0,0 +1,24 @@
+import {gql} from 'react-apollo';
+import CommentDetails from '../components/CommentDetails';
+import {getSlotFragmentSpreads} from 'coral-framework/utils';
+import withFragments from 'coral-framework/hocs/withFragments';
+
+const slots = [
+ 'adminCommentDetailArea',
+ 'adminCommentMoreDetails',
+];
+
+export default withFragments({
+ root: gql`
+ fragment CoralAdmin_CommentDetails_root on RootQuery {
+ __typename
+ ${getSlotFragmentSpreads(slots, 'root')}
+ }
+ `,
+ comment: gql`
+ fragment CoralAdmin_CommentDetails_comment on Comment {
+ __typename
+ ${getSlotFragmentSpreads(slots, 'comment')}
+ }
+ `
+})(CommentDetails);
diff --git a/client/coral-admin/src/containers/CommentLabels.js b/client/coral-admin/src/containers/CommentLabels.js
index af6a0d963..1942d1ad0 100644
--- a/client/coral-admin/src/containers/CommentLabels.js
+++ b/client/coral-admin/src/containers/CommentLabels.js
@@ -8,6 +8,12 @@ const slots = [
];
export default withFragments({
+ root: gql`
+ fragment CoralAdmin_CommentLabels_root on RootQuery {
+ __typename
+ ${getSlotFragmentSpreads(slots, 'root')}
+ }
+ `,
comment: gql`
fragment CoralAdmin_CommentLabels_comment on Comment {
hasParent
diff --git a/client/coral-admin/src/containers/UserDetail.js b/client/coral-admin/src/containers/UserDetail.js
index 5effb2b84..2ae842b1d 100644
--- a/client/coral-admin/src/containers/UserDetail.js
+++ b/client/coral-admin/src/containers/UserDetail.js
@@ -160,8 +160,10 @@ export const withUserDetailQuery = withQuery(gql`
}) {
...CoralAdmin_Moderation_CommentConnection
}
+ ...${getDefinitionName(UserDetailComment.fragments.root)}
${getSlotFragmentSpreads(slots, 'root')}
}
+ ${UserDetailComment.fragments.root}
${commentConnectionFragment}
`, {
options: ({userId, statuses}) => {
diff --git a/client/coral-admin/src/containers/UserDetailComment.js b/client/coral-admin/src/containers/UserDetailComment.js
index 9f0199bce..9eef5934f 100644
--- a/client/coral-admin/src/containers/UserDetailComment.js
+++ b/client/coral-admin/src/containers/UserDetailComment.js
@@ -3,10 +3,20 @@ import UserDetailComment from '../components/UserDetailComment';
import withFragments from 'coral-framework/hocs/withFragments';
import {getDefinitionName} from 'coral-framework/utils';
import CommentLabels from './CommentLabels';
+import CommentDetails from './CommentDetails';
export default withFragments({
+ root: gql`
+ fragment CoralAdmin_UserDetailComment_root on RootQuery {
+ __typename
+ ...${getDefinitionName(CommentLabels.fragments.root)}
+ ...${getDefinitionName(CommentDetails.fragments.root)}
+ }
+ ${CommentLabels.fragments.root}
+ ${CommentDetails.fragments.root}
+ `,
comment: gql`
- fragment CoralAdmin_UserDetail_comment on Comment {
+ fragment CoralAdmin_UserDetailComment_comment on Comment {
id
body
created_at
@@ -17,28 +27,13 @@ export default withFragments({
title
url
}
- action_summaries {
- count
- ... on FlagActionSummary {
- reason
- }
- }
- actions {
- ... on FlagAction {
- id
- reason
- message
- user {
- id
- username
- }
- }
- }
editing {
edited
}
...${getDefinitionName(CommentLabels.fragments.comment)}
+ ...${getDefinitionName(CommentDetails.fragments.comment)}
}
${CommentLabels.fragments.comment}
+ ${CommentDetails.fragments.comment}
`
})(UserDetailComment);
diff --git a/client/coral-admin/src/routes/Community/components/ActionButton.css b/client/coral-admin/src/routes/Community/components/ActionButton.css
deleted file mode 100644
index 8f328e8b8..000000000
--- a/client/coral-admin/src/routes/Community/components/ActionButton.css
+++ /dev/null
@@ -1,4 +0,0 @@
-.actionButton {
- transform: scale(.8);
- margin: 0;
-}
diff --git a/client/coral-admin/src/routes/Community/components/ActionButton.js b/client/coral-admin/src/routes/Community/components/ActionButton.js
deleted file mode 100644
index 0ef9b8a39..000000000
--- a/client/coral-admin/src/routes/Community/components/ActionButton.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import React from 'react';
-import styles from './ActionButton.css';
-import {Button} from 'coral-ui';
-import {menuActionsMap} from '../../../utils/moderationQueueActionsMap';
-
-import t from 'coral-framework/services/i18n';
-
-// TODO: Needs refactoring.
-const ActionButton = ({type = '', user, ...props}) => {
- return (
-
- );
-};
-
-export default ActionButton;
diff --git a/client/coral-admin/src/routes/Community/components/FlaggedAccounts.js b/client/coral-admin/src/routes/Community/components/FlaggedAccounts.js
index 1d78c015a..e617def53 100644
--- a/client/coral-admin/src/routes/Community/components/FlaggedAccounts.js
+++ b/client/coral-admin/src/routes/Community/components/FlaggedAccounts.js
@@ -47,7 +47,6 @@ class FlaggedAccounts extends React.Component {
this.props.viewUserDetail(this.props.user.id);
+ showRejectUsernameDialog = () => this.props.showRejectUsernameDialog({id: this.props.user.id});
+ approveUser = () => this.props.approveUser({
+ userId: this.props.user.id,
+ });
render() {
const {
user,
- modActionButtons,
viewUserDetail,
selected,
- approveUser,
- showRejectUsernameDialog,
me,
className,
} = this.props;
@@ -125,14 +126,12 @@ class User extends React.Component {
- {modActionButtons.map((action, i) =>
-
- )}
+
+
diff --git a/client/coral-admin/src/routes/Community/components/RejectUsernameDialog.js b/client/coral-admin/src/routes/Community/components/RejectUsernameDialog.js
index a9877368a..20c411e52 100644
--- a/client/coral-admin/src/routes/Community/components/RejectUsernameDialog.js
+++ b/client/coral-admin/src/routes/Community/components/RejectUsernameDialog.js
@@ -51,7 +51,7 @@ class RejectUsernameDialog extends Component {
const next = () => this.setState({stage: stage + 1});
const suspend = async () => {
try {
- await rejectUsername({id: user.user.id, message: this.state.email});
+ await rejectUsername({id: user.id, message: this.state.email});
this.props.handleClose();
} catch (err) {
diff --git a/client/coral-admin/src/routes/Community/containers/Community.js b/client/coral-admin/src/routes/Community/containers/Community.js
index 4e60c64d7..6e20a3167 100644
--- a/client/coral-admin/src/routes/Community/containers/Community.js
+++ b/client/coral-admin/src/routes/Community/containers/Community.js
@@ -78,7 +78,11 @@ const withData = withQuery(gql`
${FlaggedAccounts.fragments.root}
${FlaggedUser.fragments.root}
${FlaggedUser.fragments.me}
-`);
+`, {
+ options: {
+ fetchPolicy: 'network-only',
+ },
+});
export default compose(
connect(mapStateToProps, mapDispatchToProps),
diff --git a/client/coral-admin/src/routes/Moderation/components/Comment.css b/client/coral-admin/src/routes/Moderation/components/Comment.css
index a1862640f..10cc707fb 100644
--- a/client/coral-admin/src/routes/Moderation/components/Comment.css
+++ b/client/coral-admin/src/routes/Moderation/components/Comment.css
@@ -58,6 +58,7 @@
font-size: 14px;
line-height: 1.5;
font-weight: 300;
+ margin-bottom: 8px;
}
.body {
diff --git a/client/coral-admin/src/routes/Moderation/components/Comment.js b/client/coral-admin/src/routes/Moderation/components/Comment.js
index f72b0ef12..42c9c2d13 100644
--- a/client/coral-admin/src/routes/Moderation/components/Comment.js
+++ b/client/coral-admin/src/routes/Moderation/components/Comment.js
@@ -3,18 +3,18 @@ import PropTypes from 'prop-types';
import {Link} from 'react-router';
import {Icon} from 'coral-ui';
-import FlagBox from 'coral-admin/src/components/FlagBox';
+import CommentDetails from 'coral-admin/src/components/CommentDetails';
import styles from './Comment.css';
import CommentLabels from 'coral-admin/src/components/CommentLabels';
import CommentAnimatedEdit from 'coral-admin/src/components/CommentAnimatedEdit';
import Slot from 'coral-framework/components/Slot';
-import {getActionSummary} from 'coral-framework/utils';
-import ActionButton from 'coral-admin/src/components/ActionButton';
import ActionsMenu from 'coral-admin/src/components/ActionsMenu';
import ActionsMenuItem from 'coral-admin/src/components/ActionsMenuItem';
import CommentBodyHighlighter from 'coral-admin/src/components/CommentBodyHighlighter';
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 t, {timeago} from 'coral-framework/services/i18n';
@@ -45,11 +45,19 @@ class Comment extends React.Component {
return viewUserDetail(comment.user.id);
};
+ approve = () => (this.props.comment.status === 'ACCEPTED'
+ ? null
+ : this.props.acceptComment({commentId: this.props.comment.id})
+ );
+
+ reject = () => (this.props.comment.status === 'REJECTED'
+ ? null
+ : this.props.rejectComment({commentId: this.props.comment.id})
+ );
+
render() {
const {
- actions = [],
comment,
- viewUserDetail,
suspectWords,
bannedWords,
selected,
@@ -58,15 +66,9 @@ class Comment extends React.Component {
root,
currentUserId,
currentAsset,
- acceptComment,
- rejectComment,
} = this.props;
- const flagActionSummaries = getActionSummary('FlagActionSummary', comment);
- const flagActions = comment.actions && comment.actions.filter((a) => a.__typename === 'FlagAction');
-
const selectionStateCSS = selected ? 'mdl-shadow--16dp' : 'mdl-shadow--2dp';
-
const queryData = {root, comment, asset: comment.asset};
return (
@@ -153,28 +155,14 @@ class Comment extends React.Component {
- {actions.map((action, i) => {
- const active =
- (action === 'REJECT' && comment.status === 'REJECTED') ||
- (action === 'APPROVE' && comment.status === 'ACCEPTED');
- return (
-
- (comment.status === 'ACCEPTED'
- ? null
- : acceptComment({commentId: comment.id}))}
- rejectComment={() =>
- (comment.status === 'REJECTED'
- ? null
- : rejectComment({commentId: comment.id}))}
- />
- );
- })}
+
+
-
- {flagActions && flagActions.length
- ?
- : null}
);
}
@@ -214,6 +195,8 @@ Comment.propTypes = {
showSuspendUserDialog: PropTypes.func.isRequired,
currentUserId: PropTypes.string.isRequired,
comment: PropTypes.shape({
+ id: PropTypes.string.isRequired,
+ status: PropTypes.string.isRequired,
body: PropTypes.string.isRequired,
action_summaries: PropTypes.array,
actions: PropTypes.array,
@@ -230,7 +213,6 @@ Comment.propTypes = {
}),
data: PropTypes.object.isRequired,
root: PropTypes.object.isRequired,
- actions: PropTypes.array.isRequired,
selected: PropTypes.bool,
};
diff --git a/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js b/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js
index 517892a77..47ed56925 100644
--- a/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js
+++ b/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js
@@ -4,7 +4,6 @@ import PropTypes from 'prop-types';
import Comment from '../containers/Comment';
import styles from './ModerationQueue.css';
import EmptyCard from '../../../components/EmptyCard';
-import {actionsMap} from '../../../utils/moderationQueueActionsMap';
import LoadMore from '../../../components/LoadMore';
import ViewMore from './ViewMore';
import t from 'coral-framework/services/i18n';
@@ -140,7 +139,6 @@ class ModerationQueue extends React.Component {
if (singleView) {
const index = comments.findIndex((comment) => comment.id === selectedCommentId);
const comment = comments[index];
- const status = comment.action_summaries ? 'FLAGGED' : comment.status;
return (
{
- const status = comment.action_summaries ? 'FLAGGED' : comment.status;
return gql`
organizationName
moderation
}
+ ...${getDefinitionName(Comment.fragments.root)}
}
+ ${Comment.fragments.root}
${commentConnectionFragment}
`, {
options: (props) => {
diff --git a/client/coral-admin/src/utils/moderationQueueActionsMap.js b/client/coral-admin/src/utils/moderationQueueActionsMap.js
deleted file mode 100644
index 95b0ecb55..000000000
--- a/client/coral-admin/src/utils/moderationQueueActionsMap.js
+++ /dev/null
@@ -1,14 +0,0 @@
-export const actionsMap = {
- PREMOD: ['APPROVE', 'REJECT'],
- FLAGGED: ['APPROVE', 'REJECT'],
- REJECTED: ['APPROVE', 'REJECTED']
-};
-
-export const menuActionsMap = {
- 'REJECT': {status: 'REJECTED', text: 'reject', icon: 'close', key: 'f'},
- 'REJECTED': {status: 'REJECTED', text: 'rejected', icon: 'close'},
- 'APPROVE': {status: 'ACCEPTED', text: 'approve', icon: 'done', key: 'd'},
- 'FLAGGED': {status: 'FLAGGED', text: 'flag', icon: 'flag', filter: 'Untouched'},
- 'BAN': {status: 'BANNED', text: 'ban_user', icon: 'not interested'},
- '': {icon: 'done'}
-};
diff --git a/client/coral-configure/components/QuestionBoxBuilder.js b/client/coral-configure/components/QuestionBoxBuilder.js
index 285df40ed..28dfc30b3 100644
--- a/client/coral-configure/components/QuestionBoxBuilder.js
+++ b/client/coral-configure/components/QuestionBoxBuilder.js
@@ -8,7 +8,7 @@ import styles from './QuestionBoxBuilder.css';
class QuestionBoxBuilder extends React.Component {
constructor() {
super();
-
+
this.state = {
loading: true
};
@@ -17,9 +17,9 @@ class QuestionBoxBuilder extends React.Component {
componentWillMount() {
this.loadEditor();
}
-
+
async loadEditor() {
- const MarkdownEditor = await import('coral-framework/components/MarkdownEditor');
+ const {default: MarkdownEditor} = await import('coral-framework/components/MarkdownEditor');
return this.setState({
loading : false,
@@ -79,17 +79,17 @@ class QuestionBoxBuilder extends React.Component {
- handleChange({}, {questionBoxContent: value})}
/>
-
+
);
}
diff --git a/client/coral-embed-stream/src/components/Comment.css b/client/coral-embed-stream/src/components/Comment.css
index e32b7333b..3ca7b842f 100644
--- a/client/coral-embed-stream/src/components/Comment.css
+++ b/client/coral-embed-stream/src/components/Comment.css
@@ -45,6 +45,12 @@
border-left: 3px solid rgb(35,118,216);
}
+.bylineSecondary {
+ display: flex;
+ color: #696969;
+ font-size: 12px;
+}
+
.pendingComment {
filter: blur(2px);
pointer-events: none;
diff --git a/client/coral-embed-stream/src/graphql/index.js b/client/coral-embed-stream/src/graphql/index.js
index 20ed8a1d6..3f6fd4832 100644
--- a/client/coral-embed-stream/src/graphql/index.js
+++ b/client/coral-embed-stream/src/graphql/index.js
@@ -96,6 +96,11 @@ export default {
user {
id
username
+ tags {
+ tag {
+ name
+ }
+ }
}
action_summaries {
count
@@ -129,7 +134,19 @@ export default {
user: {
__typename: 'User',
id: auth.user.id,
- username: auth.user.username
+ username: auth.user.username,
+ tags: tags.map((tag) => ({
+ tag: {
+ name: tag,
+ created_at: new Date().toISOString(),
+ __typename: 'Tag'
+ },
+ assigned_by: {
+ id: auth.user.id,
+ __typename: 'User'
+ },
+ __typename: 'TagLink'
+ })),
},
created_at: new Date().toISOString(),
body,
@@ -140,10 +157,6 @@ export default {
created_at: new Date().toISOString(),
__typename: 'Tag'
},
- assigned_by: {
- id: auth.user.id,
- __typename: 'User'
- },
__typename: 'TagLink'
})),
status: 'NONE',
diff --git a/client/coral-embed-stream/style/default.css b/client/coral-embed-stream/style/default.css
index a20c94d1a..0dcbf856e 100644
--- a/client/coral-embed-stream/style/default.css
+++ b/client/coral-embed-stream/style/default.css
@@ -270,6 +270,7 @@ button.comment__action-button[disabled],
width: 75%;
font-size: 16px;
border: 1px solid #ccc;
+ max-width: calc(100% - 40px);
}
/* Close comments */
diff --git a/client/coral-embed/src/index.js b/client/coral-embed/src/index.js
index 34bee1797..f60a88439 100644
--- a/client/coral-embed/src/index.js
+++ b/client/coral-embed/src/index.js
@@ -2,101 +2,98 @@ import URLSearchParams from 'url-search-params';
import Stream from './Stream';
import StreamInterface from './StreamInterface';
-// This function should return value of window.Coral
-const Coral = {};
-const Talk = (Coral.Talk = {});
+export class Talk {
-/**
- * Render a Talk stream
- * @param {HTMLElement} el - Element to render the stream in
- * @param {Object} opts - Configuration options for talk
- * @param {String} opts.talk - Talk base URL
- * @param {String} [opts.title] - Title of Stream (rendered in iframe)
- * @param {String} [opts.asset_url] - Asset URL
- * @param {String} [opts.asset_id] - Asset ID
- * @param {String} [opts.auth_token] - (optional) A jwt representing the session
- * @return {Object}
- *
- * Example:
- * ```
- * const embed = Talk.render(document.getElementById('talkStreamEmbed'), opts);
- *
- * // trigger a login with optional token.
- * embed.login(token);
- *
- * // trigger a logout.
- * embed.logout();
- *
- * // listen to events (in this case all events).
- * embed.on('**', function(value) {
- * console.log(this.event, value);
- * });
- * ```
- */
-Talk.render = (el, opts) => {
- if (!el) {
- throw new Error('Please provide Coral.Talk.render() the HTMLElement you want to render Talk in.');
- }
- if (typeof el !== 'object') {
- throw new Error(`Coral.Talk.render() expected HTMLElement but got ${el} (${typeof el})`);
- }
-
- opts = opts || {};
-
- // TODO: infer this URL without explicit user input (if possible, may have to be added at build/render time of this script)
- if (!opts.talk) {
- throw new Error(
- 'Coral.Talk.render() expects opts.talk as the Talk Base URL'
- );
- }
-
- // Ensure el has an id, as pym can't directly accept the HTMLElement.
- if (!el.id) {
- el.id = `_${Math.random()}`;
- }
-
- // Compose the query to send down to the Talk API so it knows what to load.
- const query = {};
-
- // Parse the url parameters to extract some of the information.
- const urlParams = new URLSearchParams(window.location.search);
- if (urlParams.get('commentId')) {
- query.comment_id = urlParams.get('commentId');
- }
-
- // Extract the asset id from the options.
- if (opts.asset_id) {
- query.asset_id = opts.asset_id;
- }
-
- // Extract the asset url.
- if (opts.asset_url) {
- query.asset_url = opts.asset_url;
- } else if (!opts.asset_id) {
-
- // The asset url was not provided and the asset id was also not provided,
- // we need to infer the asset url from details on the page.
-
- try {
- query.asset_url = document.querySelector('link[rel="canonical"]').href;
- } catch (e) {
- console.warn(
- 'This page does not include a canonical link tag. Talk has inferred this asset_url from the window object. Query params have been stripped, which may cause a single thread to be present across multiple pages.'
- );
-
- if (!window.location.origin) {
- window.location.origin = `${window.location.protocol}//${window.location.hostname}${window.location.port ? `:${window.location.port}` : ''}`;
- }
-
- query.asset_url = window.location.origin + window.location.pathname;
+ /**
+ * Render a Talk stream
+ * @param {HTMLElement} el - Element to render the stream in
+ * @param {Object} opts - Configuration options for talk
+ * @param {String} opts.talk - Talk base URL
+ * @param {String} [opts.title] - Title of Stream (rendered in iframe)
+ * @param {String} [opts.asset_url] - Asset URL
+ * @param {String} [opts.asset_id] - Asset ID
+ * @param {String} [opts.auth_token] - (optional) A jwt representing the session
+ * @return {Object}
+ *
+ * Example:
+ * ```
+ * const embed = Talk.render(document.getElementById('talkStreamEmbed'), opts);
+ *
+ * // trigger a login with optional token.
+ * embed.login(token);
+ *
+ * // trigger a logout.
+ * embed.logout();
+ *
+ * // listen to events (in this case all events).
+ * embed.on('**', function(value) {
+ * console.log(this.event, value);
+ * });
+ * ```
+ */
+ static render(el, opts) {
+ if (!el) {
+ throw new Error('Please provide Coral.Talk.render() the HTMLElement you want to render Talk in.');
}
+ if (typeof el !== 'object') {
+ throw new Error(`Coral.Talk.render() expected HTMLElement but got ${el} (${typeof el})`);
+ }
+
+ opts = opts || {};
+
+ // TODO: infer this URL without explicit user input (if possible, may have to be added at build/render time of this script)
+ if (!opts.talk) {
+ throw new Error(
+ 'Coral.Talk.render() expects opts.talk as the Talk Base URL'
+ );
+ }
+
+ // Ensure el has an id, as pym can't directly accept the HTMLElement.
+ if (!el.id) {
+ el.id = `_${Math.random()}`;
+ }
+
+ // Compose the query to send down to the Talk API so it knows what to load.
+ const query = {};
+
+ // Parse the url parameters to extract some of the information.
+ const urlParams = new URLSearchParams(window.location.search);
+ if (urlParams.get('commentId')) {
+ query.comment_id = urlParams.get('commentId');
+ }
+
+ // Extract the asset id from the options.
+ if (opts.asset_id) {
+ query.asset_id = opts.asset_id;
+ }
+
+ // Extract the asset url.
+ if (opts.asset_url) {
+ query.asset_url = opts.asset_url;
+ } else if (!opts.asset_id) {
+
+ // The asset url was not provided and the asset id was also not provided,
+ // we need to infer the asset url from details on the page.
+
+ try {
+ query.asset_url = document.querySelector('link[rel="canonical"]').href;
+ } catch (e) {
+ console.warn(
+ 'This page does not include a canonical link tag. Talk has inferred this asset_url from the window object. Query params have been stripped, which may cause a single thread to be present across multiple pages.'
+ );
+
+ if (!window.location.origin) {
+ window.location.origin = `${window.location.protocol}//${window.location.hostname}${window.location.port ? `:${window.location.port}` : ''}`;
+ }
+
+ query.asset_url = window.location.origin + window.location.pathname;
+ }
+ }
+
+ // Create the new Stream.
+ const stream = new Stream(el, opts.talk, query, opts);
+
+ // Return the public interface for the stream.
+ return new StreamInterface(stream);
}
-
- // Create the new Stream.
- const stream = new Stream(el, opts.talk, query, opts);
-
- // Return the public interface for the stream.
- return new StreamInterface(stream);
-};
-
-export default Coral;
+}
diff --git a/client/coral-framework/components/CommentDetail.css b/client/coral-framework/components/CommentDetail.css
new file mode 100644
index 000000000..4806b9522
--- /dev/null
+++ b/client/coral-framework/components/CommentDetail.css
@@ -0,0 +1,37 @@
+.root {
+}
+
+.headerContainer {
+ display: flex;
+ justify-content: flex-start;
+ align-items: center;
+}
+
+.header {
+ vertical-align: middle;
+ margin: 0;
+ font-weight: 500;
+ display: inline-block;
+ font-size: 12px;
+ line-height: 12px;
+ margin-right: 7px;
+}
+
+.info {
+ font-size: 12px;
+}
+
+.details {
+ padding: 0 20px 16px;
+ font-size: 12px;
+
+ &:empty {
+ display: none;
+ }
+}
+
+.icon {
+ vertical-align: middle;
+ font-size: 12px;
+ margin-right: 7px;
+}
diff --git a/client/coral-framework/components/CommentDetail.js b/client/coral-framework/components/CommentDetail.js
new file mode 100644
index 000000000..2e1a89089
--- /dev/null
+++ b/client/coral-framework/components/CommentDetail.js
@@ -0,0 +1,32 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import cn from 'classnames';
+import styles from './CommentDetail.css';
+import {Icon} from 'coral-ui';
+
+const CommentDetail = ({icon, header, info, children, className}) => {
+ return (
+
+
+ {icon &&
}
+ {header}:
+ {info}
+
+ {children &&
+
+ {children}
+
+ }
+
+ );
+};
+
+CommentDetail.propTypes = {
+ className: PropTypes.string,
+ header: PropTypes.node,
+ icon: PropTypes.string,
+ info: PropTypes.node,
+ children: PropTypes.node,
+};
+
+export default CommentDetail;
diff --git a/client/coral-framework/components/IfSlotIsEmpty.js b/client/coral-framework/components/IfSlotIsEmpty.js
index 72dc8c988..51a849448 100644
--- a/client/coral-framework/components/IfSlotIsEmpty.js
+++ b/client/coral-framework/components/IfSlotIsEmpty.js
@@ -23,8 +23,9 @@ class IfSlotIsEmpty extends React.Component {
}
isSlotEmpty(props = this.props) {
- const {slot, className: _a, reduxState, component: _b = 'div', children: _c, ...rest} = props;
- return this.context.plugins.isSlotEmpty(slot, reduxState, rest);
+ const {slot, className: _a, reduxState, component: _b = 'div', children: _c, queryData, ...rest} = props;
+ const slots = Array.isArray(slot) ? slot : [slot];
+ return slots.every((slot) => this.context.plugins.isSlotEmpty(slot, reduxState, rest, queryData));
}
render() {
@@ -34,7 +35,7 @@ class IfSlotIsEmpty extends React.Component {
}
IfSlotIsEmpty.propTypes = {
- slot: PropTypes.string,
+ slot: PropTypes.oneOfType([PropTypes.string, PropTypes.array]),
};
const mapStateToProps = (state) => ({
diff --git a/client/coral-framework/components/IfSlotIsNotEmpty.js b/client/coral-framework/components/IfSlotIsNotEmpty.js
index 46e68fe60..6186e2166 100644
--- a/client/coral-framework/components/IfSlotIsNotEmpty.js
+++ b/client/coral-framework/components/IfSlotIsNotEmpty.js
@@ -23,8 +23,9 @@ class IfSlotIsNotEmpty extends React.Component {
}
isSlotEmpty(props = this.props) {
- const {slot, className: _a, reduxState, component: _b = 'div', children: _c, ...rest} = props;
- return this.context.plugins.isSlotEmpty(slot, reduxState, rest);
+ const {slot, className: _a, reduxState, component: _b = 'div', children: _c, queryData, ...rest} = props;
+ const slots = Array.isArray(slot) ? slot : [slot];
+ return slots.every((slot) => this.context.plugins.isSlotEmpty(slot, reduxState, rest, queryData));
}
render() {
@@ -34,7 +35,7 @@ class IfSlotIsNotEmpty extends React.Component {
}
IfSlotIsNotEmpty.propTypes = {
- slot: PropTypes.string,
+ slot: PropTypes.oneOfType([PropTypes.string, PropTypes.array]),
};
const mapStateToProps = (state) => ({
diff --git a/client/talk-plugin-infobox/__tests__/markdown.spec.js b/client/coral-framework/components/__tests__/Markdown.spec.js
similarity index 81%
rename from client/talk-plugin-infobox/__tests__/markdown.spec.js
rename to client/coral-framework/components/__tests__/Markdown.spec.js
index 1d98dabae..ab2c1afd1 100644
--- a/client/talk-plugin-infobox/__tests__/markdown.spec.js
+++ b/client/coral-framework/components/__tests__/Markdown.spec.js
@@ -1,6 +1,5 @@
import React from 'react';
import {shallow} from 'enzyme';
-import {expect} from 'chai';
import Markdown from '../Markdown';
const render = (props) => shallow();
@@ -9,12 +8,12 @@ describe('Markdown', () => {
it('should convert Markdown to html', () => {
const wrapper = render({content: '*test*'});
const html = wrapper.html();
- expect(html).to.contain('');
+ expect(html).toMatch('');
});
it('should set target="_parent" for links', () => {
const wrapper = render({content: '[link](https://coralproject.net)'});
const html = wrapper.html();
- expect(html).to.contain('target="_parent"');
+ expect(html).toMatch('target="_parent"');
});
});
diff --git a/client/coral-framework/hocs/excludeIf.js b/client/coral-framework/hocs/excludeIf.js
index ec2f0f27a..524c97eb3 100644
--- a/client/coral-framework/hocs/excludeIf.js
+++ b/client/coral-framework/hocs/excludeIf.js
@@ -1,4 +1,19 @@
-export default (condition) => (BaseComponent) => {
- BaseComponent.isExcluded = condition;
- return BaseComponent;
-};
+import React from 'react';
+import hoistStatics from 'recompose/hoistStatics';
+
+/**
+ * ExcludeIf provides a property `emit: (eventName, value)`
+ * to the wrapped component.
+ */
+export default (condition) => hoistStatics((WrappedComponent) => {
+ class ExcludeIf extends React.Component {
+ render() {
+ return ;
+ }
+ }
+
+ WrappedComponent.isExcluded = condition;
+ return ExcludeIf;
+});
diff --git a/client/coral-framework/loaders/plugins-loader.js b/client/coral-framework/loaders/plugins-loader.js
index a9fed95ab..7683dae8d 100644
--- a/client/coral-framework/loaders/plugins-loader.js
+++ b/client/coral-framework/loaders/plugins-loader.js
@@ -21,7 +21,7 @@ module.exports = function(source) {
this.cacheable();
const config = this.exec(source, this.resourcePath);
const plugins = getPluginList(config).map((plugin) => `{
- module: require('${plugin}/client'),
+ module: require('${plugin}/client').default,
name: '${plugin}'
}`);
diff --git a/client/coral-framework/services/client.js b/client/coral-framework/services/client.js
index 52088ad79..dc5a67d03 100644
--- a/client/coral-framework/services/client.js
+++ b/client/coral-framework/services/client.js
@@ -1,4 +1,4 @@
-import ApolloClient, {addTypename, IntrospectionFragmentMatcher, createNetworkInterface} from 'apollo-client';
+import ApolloClient, {IntrospectionFragmentMatcher, createNetworkInterface} from 'apollo-client';
import {SubscriptionClient, addGraphQLSubscriptions} from 'subscriptions-transport-ws';
import MessageTypes from 'subscriptions-transport-ws/dist/message-types';
@@ -64,7 +64,6 @@ export function createClient(options = {}) {
connectToDevTools: true,
addTypename: true,
fragmentMatcher: new IntrospectionFragmentMatcher({introspectionQueryResultData: introspectionData}),
- queryTransformer: addTypename,
dataIdFromObject: (result) => {
if (result.id && result.__typename) { // eslint-disable-line no-underscore-dangle
return `${result.__typename}_${result.id}`; // eslint-disable-line no-underscore-dangle
diff --git a/client/coral-framework/services/i18n.js b/client/coral-framework/services/i18n.js
index 1a4910b21..87e375853 100644
--- a/client/coral-framework/services/i18n.js
+++ b/client/coral-framework/services/i18n.js
@@ -13,7 +13,7 @@ import pt_BR from '../../../locales/pt_BR.yml';
// Translations are happening at https://translate.lingohub.com/the-coral-project/dashboard
-const defaultLanguage = 'en';
+const defaultLanguage = process.env.TALK_DEFAULT_LANG;
const translations = {...en, ...es, ...fr, ...pt_BR};
let lang;
diff --git a/client/coral-ui/components/Button.css b/client/coral-ui/components/Button.css
index 1b7efb205..ce2cff350 100644
--- a/client/coral-ui/components/Button.css
+++ b/client/coral-ui/components/Button.css
@@ -130,59 +130,6 @@
background: #00a291;
}
-.type--approve {
- display: block;
- color: #519954;
- border: solid 2px rgba(81, 153, 84, 0.75);
- background: white;
- padding: 10px 12px;
- box-sizing: border-box;
- vertical-align: middle;
- line-height: 24px;
- font-size: 17px;
- height: 47px;
- border-radius: 3px;
- text-transform: capitalize;
- box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.03), 0 3px 1px -2px rgba(0,0,0,.2), 0 1px 5px 0 rgba(0,0,0,.09);
- width: 129px;
-
- &:hover {
- box-shadow: none;
- color: white;
- background-color: #519954;
- }
-}
-
-.type--reject, .type--rejected {
- display: block;
- color: #D03235;
- border: solid 1px #D03235;
- background: white;
- padding: 10px 11px;
- box-sizing: border-box;
- vertical-align: middle;
- line-height: 24px;
- font-size: 17px;
- height: 47px;
- border-radius: 3px;
- text-transform: capitalize;
- box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.03), 0 3px 1px -2px rgba(0,0,0,.2), 0 1px 5px 0 rgba(0,0,0,.09);
- width: 129px;
-
- &:hover {
- color: white;
- background-color: #D03235;
- box-shadow: none;
- }
-}
-
-.type--rejected {
- color: white;
- background-color: #D03235;
- box-shadow: none;
- cursor: not-allowed;
-}
-
.type--ban, .type--actions {
display: block;
color: #616161;
diff --git a/client/talk-plugin-commentbox/__tests__/commentBox.spec.js b/client/talk-plugin-commentbox/__tests__/commentBox.spec.js
deleted file mode 100644
index 6ae09e786..000000000
--- a/client/talk-plugin-commentbox/__tests__/commentBox.spec.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import React from 'react';
-import {shallow} from 'enzyme';
-import {expect} from 'chai';
-import CommentBox from '../CommentBox';
-
-describe('CommentBox', () => {
- let comment;
- let render;
- beforeEach(() => {
- comment = {};
- const postItem = (item) => {
- comment.posted = item;
- return Promise.resolve(4);
- };
- render = shallow( comment.text = e.target.value}
- item_id={'1'}
- comments={['1', '2', '3']}/>);
- });
-
- it('should render the CommentBox appropriately', () => {
- expect(render.contains('