feat: added toxic labels (#2396)

This commit is contained in:
Wyatt Johnson
2019-07-12 20:41:34 +00:00
committed by GitHub
parent b5b9cb7e2f
commit f95b705585
42 changed files with 727 additions and 526 deletions
@@ -6,6 +6,7 @@ import { Field } from "react-final-form";
import { formatPercentage, parsePercentage } from "coral-framework/lib/form";
import {
TOXICITY_ENDPOINT_DEFAULT,
TOXICITY_MODEL_DEFAULT,
TOXICITY_THRESHOLD_DEFAULT,
} from "coral-common/constants";
@@ -220,7 +221,7 @@ const PerspectiveConfig: FunctionComponent<Props> = ({ disabled }) => {
</Localized>
<Localized
id="configure-moderation-perspective-defaultEndpoint"
$default="https://commentanalyzer.googleapis.com/v1alpha1"
$default={TOXICITY_ENDPOINT_DEFAULT}
>
<InputDescription>
By default the endpoint is set to $default. You may override this
@@ -242,6 +243,7 @@ const PerspectiveConfig: FunctionComponent<Props> = ({ disabled }) => {
autoComplete="off"
autoCorrect="off"
autoCapitalize="off"
placeholder={TOXICITY_ENDPOINT_DEFAULT}
spellCheck={false}
/>
{meta.touched && (meta.error || meta.submitError) && (
@@ -1,3 +0,0 @@
.category {
color: var(--palette-error-darkest);
}
@@ -2,8 +2,6 @@ import React, { FunctionComponent } from "react";
import { HorizontalGutter, Typography } from "coral-ui/components";
import styles from "./FlagDetailsCategory.css";
interface Props {
category: React.ReactNode;
children?: React.ReactNode;
@@ -15,9 +13,7 @@ const FlagDetailsCategory: FunctionComponent<Props> = ({
}) => {
return (
<HorizontalGutter size="half">
<Typography variant="bodyCopyBold" className={styles.category}>
{category}
</Typography>
<Typography variant="bodyCopyBold">{category}</Typography>
<HorizontalGutter size="half">{children}</HorizontalGutter>
</HorizontalGutter>
);
@@ -1,80 +1,94 @@
import { Localized } from "fluent-react/compat";
import React from "react";
import React, { FunctionComponent } from "react";
import { graphql } from "react-relay";
import { FlagDetailsContainer_comment as CommentData } from "coral-admin/__generated__/FlagDetailsContainer_comment.graphql";
import { FlagDetailsContainer_comment } from "coral-admin/__generated__/FlagDetailsContainer_comment.graphql";
import { FlagDetailsContainer_settings } from "coral-admin/__generated__/FlagDetailsContainer_settings.graphql";
import NotAvailable from "coral-admin/components/NotAvailable";
import { TOXICITY_THRESHOLD_DEFAULT } from "coral-common/constants";
import { withFragmentContainer } from "coral-framework/lib/relay";
import { GQLCOMMENT_FLAG_REASON } from "coral-framework/schema";
import { HorizontalGutter } from "coral-ui/components";
import FlagDetailsCategory from "./FlagDetailsCategory";
import FlagDetailsEntry from "./FlagDetailsEntry";
import ToxicityLabel from "./ToxicityLabel";
interface Props {
comment: CommentData;
comment: FlagDetailsContainer_comment;
settings: FlagDetailsContainer_settings;
}
export class FlagDetailsContainer extends React.Component<Props> {
public render() {
const nodes = this.props.comment.flags.nodes;
const offensiveList: React.ReactElement[] = [];
const spamList: React.ReactElement[] = [];
nodes.forEach((n, i) => {
switch (n.reason) {
case GQLCOMMENT_FLAG_REASON.COMMENT_REPORTED_OFFENSIVE:
offensiveList.push(
const FlagDetailsContainer: FunctionComponent<Props> = ({
comment: {
revision: { metadata },
flags: { nodes },
},
settings,
}) => {
const offensive = nodes.filter(
({ reason }) => reason === GQLCOMMENT_FLAG_REASON.COMMENT_REPORTED_OFFENSIVE
);
const spam = nodes.filter(
({ reason }) => reason === GQLCOMMENT_FLAG_REASON.COMMENT_REPORTED_SPAM
);
return (
<HorizontalGutter size="oneAndAHalf">
{metadata.perspective && (
<FlagDetailsCategory
category={
<Localized id="moderate-flagDetails-toxicityScore">
<span>Toxicity Score</span>
</Localized>
}
>
<ToxicityLabel
score={metadata.perspective.score}
threshold={
settings.integrations.perspective.threshold ||
TOXICITY_THRESHOLD_DEFAULT / 100
}
/>
</FlagDetailsCategory>
)}
{offensive.length > 0 && (
<FlagDetailsCategory
category={
<Localized id="moderate-flagDetails-offensive">
<span>Offensive</span>
</Localized>
}
>
{offensive.map((flag, i) => (
<FlagDetailsEntry
key={i}
user={n.flagger ? n.flagger.username : <NotAvailable />}
details={n.additionalDetails}
user={flag.flagger ? flag.flagger.username : <NotAvailable />}
details={flag.additionalDetails}
/>
);
return;
case GQLCOMMENT_FLAG_REASON.COMMENT_REPORTED_SPAM:
spamList.push(
))}
</FlagDetailsCategory>
)}
{spam.length > 0 && (
<FlagDetailsCategory
category={
<Localized id="moderate-flagDetails-spam">
<span>Spam</span>
</Localized>
}
>
{spam.map((flag, i) => (
<FlagDetailsEntry
key={i}
user={n.flagger ? n.flagger.username : <NotAvailable />}
details={n.additionalDetails}
user={flag.flagger ? flag.flagger.username : <NotAvailable />}
details={flag.additionalDetails}
/>
);
return;
default:
return;
}
});
if (offensiveList.length + spamList.length === 0) {
return null;
}
return (
<HorizontalGutter size="oneAndAHalf">
{offensiveList.length > 0 && (
<FlagDetailsCategory
category={
<Localized id="moderate-flagDetails-offensive">
<span>Offensive</span>
</Localized>
}
>
{offensiveList}
</FlagDetailsCategory>
)}
{spamList.length > 0 && (
<FlagDetailsCategory
category={
<Localized id="moderate-flagDetails-spam">
<span>Spam</span>
</Localized>
}
>
{spamList}
</FlagDetailsCategory>
)}
</HorizontalGutter>
);
}
}
))}
</FlagDetailsCategory>
)}
</HorizontalGutter>
);
};
const enhanced = withFragmentContainer<Props>({
comment: graphql`
@@ -88,6 +102,22 @@ const enhanced = withFragmentContainer<Props>({
additionalDetails
}
}
revision {
metadata {
perspective {
score
}
}
}
}
`,
settings: graphql`
fragment FlagDetailsContainer_settings on Settings {
integrations {
perspective {
threshold
}
}
}
`,
})(FlagDetailsContainer);
@@ -14,3 +14,7 @@
.detailsText {
margin: 0;
}
.detailsDivider {
border: 1px solid var(--palette-grey-lightest);
}
@@ -18,9 +18,9 @@ const Markers: FunctionComponent<Props> = ({ children, details }) => {
showDetails,
]);
return (
<HorizontalGutter size="double">
<Flex>
<Flex itemGutter>{children}</Flex>
<HorizontalGutter>
<Flex itemGutter>
{children}
{details && (
<Button
size="small"
@@ -39,7 +39,12 @@ const Markers: FunctionComponent<Props> = ({ children, details }) => {
</Button>
)}
</Flex>
{showDetails && <div id={uuid}>{details}</div>}
{showDetails && (
<div id={uuid}>
<hr className={styles.detailsDivider} />
{details}
</div>
)}
</HorizontalGutter>
);
};
@@ -1,6 +1,7 @@
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { TOXICITY_THRESHOLD_DEFAULT } from "coral-common/constants";
import { removeFragmentRefs } from "coral-framework/testHelpers";
import { PropTypesOf } from "coral-framework/types";
@@ -12,19 +13,33 @@ it("renders all markers", () => {
const props: PropTypesOf<typeof MarkersContainerN> = {
comment: {
status: "PREMOD",
actionCounts: {
flag: {
reasons: {
COMMENT_DETECTED_TOXIC: 1,
COMMENT_DETECTED_SPAM: 1,
COMMENT_DETECTED_TRUST: 1,
COMMENT_DETECTED_LINKS: 1,
COMMENT_DETECTED_BANNED_WORD: 1,
COMMENT_DETECTED_SUSPECT_WORD: 1,
COMMENT_REPORTED_OFFENSIVE: 2,
COMMENT_REPORTED_SPAM: 3,
revision: {
actionCounts: {
flag: {
reasons: {
COMMENT_DETECTED_TOXIC: 1,
COMMENT_DETECTED_SPAM: 1,
COMMENT_DETECTED_TRUST: 1,
COMMENT_DETECTED_LINKS: 1,
COMMENT_DETECTED_BANNED_WORD: 1,
COMMENT_DETECTED_SUSPECT_WORD: 1,
COMMENT_REPORTED_OFFENSIVE: 2,
COMMENT_REPORTED_SPAM: 3,
},
},
},
metadata: {
perspective: {
score: 0,
},
},
},
},
settings: {
integrations: {
perspective: {
threshold: TOXICITY_THRESHOLD_DEFAULT / 100,
},
},
},
};
@@ -37,19 +52,33 @@ it("renders some markers", () => {
const props: PropTypesOf<typeof MarkersContainerN> = {
comment: {
status: "PREMOD",
actionCounts: {
flag: {
reasons: {
COMMENT_DETECTED_TOXIC: 1,
COMMENT_DETECTED_SPAM: 0,
COMMENT_DETECTED_TRUST: 1,
COMMENT_DETECTED_LINKS: 0,
COMMENT_DETECTED_BANNED_WORD: 1,
COMMENT_DETECTED_SUSPECT_WORD: 0,
COMMENT_REPORTED_OFFENSIVE: 2,
COMMENT_REPORTED_SPAM: 0,
revision: {
actionCounts: {
flag: {
reasons: {
COMMENT_DETECTED_TOXIC: 1,
COMMENT_DETECTED_SPAM: 0,
COMMENT_DETECTED_TRUST: 1,
COMMENT_DETECTED_LINKS: 0,
COMMENT_DETECTED_BANNED_WORD: 1,
COMMENT_DETECTED_SUSPECT_WORD: 0,
COMMENT_REPORTED_OFFENSIVE: 2,
COMMENT_REPORTED_SPAM: 0,
},
},
},
metadata: {
perspective: {
score: 1,
},
},
},
},
settings: {
integrations: {
perspective: {
threshold: TOXICITY_THRESHOLD_DEFAULT / 100,
},
},
},
};
@@ -2,26 +2,30 @@ import { Localized } from "fluent-react/compat";
import React from "react";
import { graphql } from "react-relay";
import { MarkersContainer_comment as CommentData } from "coral-admin/__generated__/MarkersContainer_comment.graphql";
import { MarkersContainer_comment } from "coral-admin/__generated__/MarkersContainer_comment.graphql";
import { MarkersContainer_settings } from "coral-admin/__generated__/MarkersContainer_settings.graphql";
import { withFragmentContainer } from "coral-framework/lib/relay";
import { Marker, MarkerCount } from "coral-ui/components";
import FlagDetailsContainer from "./FlagDetailsContainer";
import Markers from "./Markers";
interface MarkersContainerProps {
comment: CommentData;
comment: MarkersContainer_comment;
settings: MarkersContainer_settings;
}
function hasDetails(c: CommentData) {
function hasDetails(c: MarkersContainer_comment) {
return (
c.actionCounts.flag.reasons.COMMENT_REPORTED_OFFENSIVE +
c.actionCounts.flag.reasons.COMMENT_REPORTED_SPAM >
0
c.revision.actionCounts.flag.reasons.COMMENT_REPORTED_OFFENSIVE +
c.revision.actionCounts.flag.reasons.COMMENT_REPORTED_SPAM >
0 || c.revision.metadata.perspective
);
}
let keyCounter = 0;
const markers: Array<(c: CommentData) => React.ReactElement<any> | null> = [
const markers: Array<
(c: MarkersContainer_comment) => React.ReactElement<any> | null
> = [
c =>
(c.status === "PREMOD" && (
<Localized id="moderate-marker-preMod" key={keyCounter++}>
@@ -30,21 +34,21 @@ const markers: Array<(c: CommentData) => React.ReactElement<any> | null> = [
)) ||
null,
c =>
(c.actionCounts.flag.reasons.COMMENT_DETECTED_LINKS && (
(c.revision.actionCounts.flag.reasons.COMMENT_DETECTED_LINKS && (
<Localized id="moderate-marker-link" key={keyCounter++}>
<Marker color="primary">Link</Marker>
</Localized>
)) ||
null,
c =>
(c.actionCounts.flag.reasons.COMMENT_DETECTED_BANNED_WORD && (
(c.revision.actionCounts.flag.reasons.COMMENT_DETECTED_BANNED_WORD && (
<Localized id="moderate-marker-bannedWord" key={keyCounter++}>
<Marker color="error">Banned Word</Marker>
</Localized>
)) ||
null,
c =>
(c.actionCounts.flag.reasons.COMMENT_DETECTED_SUSPECT_WORD && (
(c.revision.actionCounts.flag.reasons.COMMENT_DETECTED_SUSPECT_WORD && (
<Localized id="moderate-marker-suspectWord" key={keyCounter++}>
<Marker color="error" variant="filled">
Suspect Word
@@ -53,46 +57,46 @@ const markers: Array<(c: CommentData) => React.ReactElement<any> | null> = [
)) ||
null,
c =>
(c.actionCounts.flag.reasons.COMMENT_DETECTED_SPAM && (
(c.revision.actionCounts.flag.reasons.COMMENT_DETECTED_SPAM && (
<Localized id="moderate-marker-spam" key={keyCounter++}>
<Marker color="error">Spam</Marker>
</Localized>
)) ||
null,
c =>
(c.actionCounts.flag.reasons.COMMENT_DETECTED_TOXIC && (
(c.revision.actionCounts.flag.reasons.COMMENT_DETECTED_TOXIC && (
<Localized id="moderate-marker-toxic" key={keyCounter++}>
<Marker color="error">Toxic</Marker>
</Localized>
)) ||
null,
c =>
(c.actionCounts.flag.reasons.COMMENT_DETECTED_TRUST && (
(c.revision.actionCounts.flag.reasons.COMMENT_DETECTED_TRUST && (
<Localized id="moderate-marker-karma" key={keyCounter++}>
<Marker color="error">Karma</Marker>
</Localized>
)) ||
null,
c =>
(c.actionCounts.flag.reasons.COMMENT_REPORTED_OFFENSIVE && (
(c.revision.actionCounts.flag.reasons.COMMENT_REPORTED_OFFENSIVE && (
<Marker key={keyCounter++} color="error">
<Localized id="moderate-marker-offensive">
<span>Offensive</span>
</Localized>{" "}
<MarkerCount>
{c.actionCounts.flag.reasons.COMMENT_REPORTED_OFFENSIVE}
{c.revision.actionCounts.flag.reasons.COMMENT_REPORTED_OFFENSIVE}
</MarkerCount>
</Marker>
)) ||
null,
c =>
(c.actionCounts.flag.reasons.COMMENT_REPORTED_SPAM && (
(c.revision.actionCounts.flag.reasons.COMMENT_REPORTED_SPAM && (
<Marker key={keyCounter++} color="error">
<Localized id="moderate-marker-spam">
<span>Spam</span>
</Localized>{" "}
<MarkerCount>
{c.actionCounts.flag.reasons.COMMENT_REPORTED_SPAM}
{c.revision.actionCounts.flag.reasons.COMMENT_REPORTED_SPAM}
</MarkerCount>
</Marker>
)) ||
@@ -102,20 +106,25 @@ const markers: Array<(c: CommentData) => React.ReactElement<any> | null> = [
export class MarkersContainer extends React.Component<MarkersContainerProps> {
public render() {
const elements = markers.map(cb => cb(this.props.comment)).filter(m => m);
if (elements.length) {
return (
<Markers
details={
hasDetails(this.props.comment) ? (
<FlagDetailsContainer comment={this.props.comment} />
) : null
}
>
{elements}
</Markers>
);
const doesHaveDetails = hasDetails(this.props.comment);
if (elements.length === 0 && !doesHaveDetails) {
return null;
}
return null;
return (
<Markers
details={
doesHaveDetails ? (
<FlagDetailsContainer
comment={this.props.comment}
settings={this.props.settings}
/>
) : null
}
>
{elements}
</Markers>
);
}
}
@@ -124,22 +133,34 @@ const enhanced = withFragmentContainer<MarkersContainerProps>({
fragment MarkersContainer_comment on Comment {
...FlagDetailsContainer_comment
status
actionCounts {
flag {
reasons {
COMMENT_DETECTED_TOXIC
COMMENT_DETECTED_SPAM
COMMENT_DETECTED_TRUST
COMMENT_DETECTED_LINKS
COMMENT_DETECTED_BANNED_WORD
COMMENT_DETECTED_SUSPECT_WORD
COMMENT_REPORTED_OFFENSIVE
COMMENT_REPORTED_SPAM
revision {
actionCounts {
flag {
reasons {
COMMENT_DETECTED_TOXIC
COMMENT_DETECTED_SPAM
COMMENT_DETECTED_TRUST
COMMENT_DETECTED_LINKS
COMMENT_DETECTED_BANNED_WORD
COMMENT_DETECTED_SUSPECT_WORD
COMMENT_REPORTED_OFFENSIVE
COMMENT_REPORTED_SPAM
}
}
}
metadata {
perspective {
score
}
}
}
}
`,
settings: graphql`
fragment MarkersContainer_settings on Settings {
...FlagDetailsContainer_settings
}
`,
})(MarkersContainer);
export default enhanced;
@@ -16,6 +16,7 @@ const baseProps: PropTypesOf<typeof ModerateCardN> = {
body: "content",
inReplyTo: null,
comment: {},
settings: {},
status: "undecided",
featured: false,
viewContextHref: "http://localhost/comment",
@@ -29,6 +29,7 @@ interface Props {
body: string;
inReplyTo: string | null;
comment: PropTypesOf<typeof MarkersContainer>["comment"];
settings: PropTypesOf<typeof MarkersContainer>["settings"];
status: "approved" | "rejected" | "undecided";
featured: boolean;
moderatedBy: React.ReactNode | null;
@@ -60,6 +61,7 @@ const ModerateCard: FunctionComponent<Props> = ({
body,
inReplyTo,
comment,
settings,
viewContextHref,
status,
featured,
@@ -146,7 +148,7 @@ const ModerateCard: FunctionComponent<Props> = ({
</Localized>
</div>
)}
<MarkersContainer comment={comment} />
<MarkersContainer comment={comment} settings={settings} />
</HorizontalGutter>
</div>
</div>
@@ -141,6 +141,7 @@ const ModerateCardContainer: FunctionComponent<Props> = ({
body={comment.body!}
inReplyTo={comment.parent && comment.parent.author!.username!}
comment={comment}
settings={settings}
dangling={danglingLogic(comment.status)}
status={getStatus(comment)}
featured={isFeatured(comment)}
@@ -211,6 +212,7 @@ const enhanced = withFragmentContainer<Props>({
banned
suspect
}
...MarkersContainer_settings
}
`,
viewer: graphql`
@@ -0,0 +1,3 @@
.root {
font-size: calc(14rem / var(--rem-base));
}
@@ -0,0 +1,45 @@
import { Localized } from "fluent-react/compat";
import React, { FunctionComponent } from "react";
import { Counter, Typography } from "coral-ui/components";
import styles from "./ToxicityLabel.css";
const ToxicityCounter: FunctionComponent<{ score: number }> = ({ score }) => (
<Counter>{Math.round(score * 100)}%</Counter>
);
const ToxicityLabel: FunctionComponent<{
score: number;
threshold: number;
}> = ({ score, threshold }) => {
const counter = <ToxicityCounter score={score} />;
if (score > threshold) {
return (
<Localized id="moderate-toxicityLabel-likely" score={counter}>
<Typography
className={styles.root}
variant="bodyCopy"
color="errorDark"
>
Likely
</Typography>
</Localized>
);
} else if (score <= 0.5) {
return (
<Localized id="moderate-toxicityLabel-unlikely" score={counter}>
<Typography className={styles.root}>Unlikely</Typography>
</Localized>
);
}
return (
<Localized id="moderate-toxicityLabel-maybe" score={counter}>
<Typography className={styles.root}>Maybe</Typography>
</Localized>
);
};
export default ToxicityLabel;
@@ -6,23 +6,39 @@ exports[`renders all markers 1`] = `
<Relay(FlagDetailsContainer)
comment={
Object {
"actionCounts": Object {
"flag": Object {
"reasons": Object {
"COMMENT_DETECTED_BANNED_WORD": 1,
"COMMENT_DETECTED_LINKS": 1,
"COMMENT_DETECTED_SPAM": 1,
"COMMENT_DETECTED_SUSPECT_WORD": 1,
"COMMENT_DETECTED_TOXIC": 1,
"COMMENT_DETECTED_TRUST": 1,
"COMMENT_REPORTED_OFFENSIVE": 2,
"COMMENT_REPORTED_SPAM": 3,
"revision": Object {
"actionCounts": Object {
"flag": Object {
"reasons": Object {
"COMMENT_DETECTED_BANNED_WORD": 1,
"COMMENT_DETECTED_LINKS": 1,
"COMMENT_DETECTED_SPAM": 1,
"COMMENT_DETECTED_SUSPECT_WORD": 1,
"COMMENT_DETECTED_TOXIC": 1,
"COMMENT_DETECTED_TRUST": 1,
"COMMENT_REPORTED_OFFENSIVE": 2,
"COMMENT_REPORTED_SPAM": 3,
},
},
},
"metadata": Object {
"perspective": Object {
"score": 0,
},
},
},
"status": "PREMOD",
}
}
settings={
Object {
"integrations": Object {
"perspective": Object {
"threshold": 0.8,
},
},
}
}
/>
}
>
@@ -129,23 +145,39 @@ exports[`renders some markers 1`] = `
<Relay(FlagDetailsContainer)
comment={
Object {
"actionCounts": Object {
"flag": Object {
"reasons": Object {
"COMMENT_DETECTED_BANNED_WORD": 1,
"COMMENT_DETECTED_LINKS": 0,
"COMMENT_DETECTED_SPAM": 0,
"COMMENT_DETECTED_SUSPECT_WORD": 0,
"COMMENT_DETECTED_TOXIC": 1,
"COMMENT_DETECTED_TRUST": 1,
"COMMENT_REPORTED_OFFENSIVE": 2,
"COMMENT_REPORTED_SPAM": 0,
"revision": Object {
"actionCounts": Object {
"flag": Object {
"reasons": Object {
"COMMENT_DETECTED_BANNED_WORD": 1,
"COMMENT_DETECTED_LINKS": 0,
"COMMENT_DETECTED_SPAM": 0,
"COMMENT_DETECTED_SUSPECT_WORD": 0,
"COMMENT_DETECTED_TOXIC": 1,
"COMMENT_DETECTED_TRUST": 1,
"COMMENT_REPORTED_OFFENSIVE": 2,
"COMMENT_REPORTED_SPAM": 0,
},
},
},
"metadata": Object {
"perspective": Object {
"score": 1,
},
},
},
"status": "PREMOD",
}
}
settings={
Object {
"integrations": Object {
"perspective": Object {
"threshold": 0.8,
},
},
}
}
/>
}
>
@@ -66,6 +66,7 @@ exports[`renders approved correctly 1`] = `
</div>
<Relay(MarkersContainer)
comment={Object {}}
settings={Object {}}
/>
</ForwardRef(forwardRef)>
</div>
@@ -174,6 +175,7 @@ exports[`renders correctly 1`] = `
</div>
<Relay(MarkersContainer)
comment={Object {}}
settings={Object {}}
/>
</ForwardRef(forwardRef)>
</div>
@@ -281,6 +283,7 @@ exports[`renders dangling correctly 1`] = `
</div>
<Relay(MarkersContainer)
comment={Object {}}
settings={Object {}}
/>
</ForwardRef(forwardRef)>
</div>
@@ -390,6 +393,7 @@ exports[`renders rejected correctly 1`] = `
</div>
<Relay(MarkersContainer)
comment={Object {}}
settings={Object {}}
/>
</ForwardRef(forwardRef)>
</div>
@@ -503,6 +507,7 @@ exports[`renders reply correctly 1`] = `
</div>
<Relay(MarkersContainer)
comment={Object {}}
settings={Object {}}
/>
</ForwardRef(forwardRef)>
</div>
@@ -639,6 +644,7 @@ exports[`renders story info 1`] = `
</div>
<Relay(MarkersContainer)
comment={Object {}}
settings={Object {}}
/>
</ForwardRef(forwardRef)>
</div>
@@ -352,7 +352,7 @@ comment is toxic, according to Perspective API. By default the threshold is set
placeholder="80"
spellCheck={false}
type="text"
value=""
value="80"
/>
<div
className="TextField-adornment"
@@ -545,7 +545,7 @@ improve the API over time.
id="configure-moderation-perspective-customEndpoint"
name="integrations.perspective.endpoint"
onChange={[Function]}
placeholder=""
placeholder="https://commentanalyzer.googleapis.com/v1alpha1"
spellCheck={false}
type="text"
value=""
+65 -40
View File
@@ -1,3 +1,4 @@
import { TOXICITY_THRESHOLD_DEFAULT } from "coral-common/constants";
import { pureMerge } from "coral-common/utils";
import {
GQLComment,
@@ -66,6 +67,7 @@ export const settings = createFixture<GQLSettings>({
},
perspective: {
enabled: false,
threshold: TOXICITY_THRESHOLD_DEFAULT / 100,
},
},
auth: {
@@ -432,19 +434,22 @@ export const baseComment = createFixture<GQLComment>({
edges: [],
pageInfo: { endCursor: null, hasNextPage: false },
},
actionCounts: {
flag: {
reasons: {
COMMENT_DETECTED_TOXIC: 0,
COMMENT_DETECTED_SPAM: 0,
COMMENT_DETECTED_TRUST: 0,
COMMENT_DETECTED_LINKS: 0,
COMMENT_DETECTED_BANNED_WORD: 0,
COMMENT_DETECTED_SUSPECT_WORD: 0,
COMMENT_REPORTED_OFFENSIVE: 0,
COMMENT_REPORTED_SPAM: 0,
revision: {
actionCounts: {
flag: {
reasons: {
COMMENT_DETECTED_TOXIC: 0,
COMMENT_DETECTED_SPAM: 0,
COMMENT_DETECTED_TRUST: 0,
COMMENT_DETECTED_LINKS: 0,
COMMENT_DETECTED_BANNED_WORD: 0,
COMMENT_DETECTED_SUSPECT_WORD: 0,
COMMENT_REPORTED_OFFENSIVE: 0,
COMMENT_REPORTED_SPAM: 0,
},
},
},
metadata: {},
},
flags: {
nodes: [],
@@ -498,17 +503,22 @@ export const reportedComments = createFixtures<GQLComment>(
author: users.commenters[0],
revision: {
id: "comment-0-revision-0",
actionCounts: {
flag: {
reasons: {
COMMENT_REPORTED_SPAM: 2,
},
},
},
metadata: {
perspective: {
score: 0.1,
},
},
},
permalink: "http://localhost/comment/0",
body:
"This is the last random sentence I will be writing and I am going to stop mid-sent",
actionCounts: {
flag: {
reasons: {
COMMENT_REPORTED_SPAM: 2,
},
},
},
flags: {
nodes: [
{
@@ -528,17 +538,22 @@ export const reportedComments = createFixtures<GQLComment>(
id: "comment-1",
revision: {
id: "comment-1-revision-1",
actionCounts: {
flag: {
reasons: {
COMMENT_REPORTED_OFFENSIVE: 3,
},
},
},
metadata: {
perspective: {
score: 0.1,
},
},
},
permalink: "http://localhost/comment/1",
author: users.commenters[1],
body: "Don't fool with me",
actionCounts: {
flag: {
reasons: {
COMMENT_REPORTED_OFFENSIVE: 3,
},
},
},
flags: {
nodes: [
{
@@ -563,19 +578,24 @@ export const reportedComments = createFixtures<GQLComment>(
id: "comment-2",
revision: {
id: "comment-2-revision-2",
actionCounts: {
flag: {
reasons: {
COMMENT_REPORTED_SPAM: 1,
COMMENT_REPORTED_OFFENSIVE: 1,
},
},
},
metadata: {
perspective: {
score: 0.1,
},
},
},
permalink: "http://localhost/comment/2",
status: GQLCOMMENT_STATUS.PREMOD,
author: users.commenters[2],
body: "I think I deserve better",
actionCounts: {
flag: {
reasons: {
COMMENT_REPORTED_SPAM: 1,
COMMENT_REPORTED_OFFENSIVE: 1,
},
},
},
flags: {
nodes: [
{
@@ -595,18 +615,23 @@ export const reportedComments = createFixtures<GQLComment>(
id: "comment-3",
revision: {
id: "comment-3-revision-3",
actionCounts: {
flag: {
reasons: {
COMMENT_REPORTED_SPAM: 1,
},
},
},
metadata: {
perspective: {
score: 0.1,
},
},
},
permalink: "http://localhost/comment/3",
status: GQLCOMMENT_STATUS.PREMOD,
author: users.commenters[3],
body: "World peace at last",
actionCounts: {
flag: {
reasons: {
COMMENT_REPORTED_SPAM: 1,
},
},
},
flags: {
nodes: [
{
@@ -120,28 +120,24 @@ exports[`approves comment in reported queue: dangling 1`] = `
</a>
</div>
<div
className="Box-root HorizontalGutter-root HorizontalGutter-double"
className="Box-root HorizontalGutter-root HorizontalGutter-full"
>
<div
className="Box-root Flex-root Flex-flex"
className="Box-root Flex-root Flex-flex Flex-itemGutter gutter"
>
<div
className="Box-root Flex-root Flex-flex Flex-itemGutter gutter"
<span
className="Marker-root Marker-colorError Marker-variantRegular"
>
<span
className="Marker-root Marker-colorError Marker-variantRegular"
>
<span>
Spam
</span>
<span
className="Count-root"
>
2
</span>
<span>
Spam
</span>
</div>
<span
className="Count-root"
>
2
</span>
</span>
<button
aria-controls="uuid-0"
aria-expanded={false}
@@ -349,28 +345,24 @@ exports[`rejects comment in reported queue: dangling 1`] = `
</a>
</div>
<div
className="Box-root HorizontalGutter-root HorizontalGutter-double"
className="Box-root HorizontalGutter-root HorizontalGutter-full"
>
<div
className="Box-root Flex-root Flex-flex"
className="Box-root Flex-root Flex-flex Flex-itemGutter gutter"
>
<div
className="Box-root Flex-root Flex-flex Flex-itemGutter gutter"
<span
className="Marker-root Marker-colorError Marker-variantRegular"
>
<span
className="Marker-root Marker-colorError Marker-variantRegular"
>
<span>
Spam
</span>
<span
className="Count-root"
>
2
</span>
<span>
Spam
</span>
</div>
<span
className="Count-root"
>
2
</span>
</span>
<button
aria-controls="uuid-0"
aria-expanded={false}
@@ -575,28 +567,24 @@ exports[`renders reported queue with comments 1`] = `
</a>
</div>
<div
className="Box-root HorizontalGutter-root HorizontalGutter-double"
className="Box-root HorizontalGutter-root HorizontalGutter-full"
>
<div
className="Box-root Flex-root Flex-flex"
className="Box-root Flex-root Flex-flex Flex-itemGutter gutter"
>
<div
className="Box-root Flex-root Flex-flex Flex-itemGutter gutter"
<span
className="Marker-root Marker-colorError Marker-variantRegular"
>
<span
className="Marker-root Marker-colorError Marker-variantRegular"
>
<span>
Spam
</span>
<span
className="Count-root"
>
2
</span>
<span>
Spam
</span>
</div>
<span
className="Count-root"
>
2
</span>
</span>
<button
aria-controls="uuid-0"
aria-expanded={false}
@@ -788,28 +776,24 @@ exports[`renders reported queue with comments 1`] = `
</a>
</div>
<div
className="Box-root HorizontalGutter-root HorizontalGutter-double"
className="Box-root HorizontalGutter-root HorizontalGutter-full"
>
<div
className="Box-root Flex-root Flex-flex"
className="Box-root Flex-root Flex-flex Flex-itemGutter gutter"
>
<div
className="Box-root Flex-root Flex-flex Flex-itemGutter gutter"
<span
className="Marker-root Marker-colorError Marker-variantRegular"
>
<span
className="Marker-root Marker-colorError Marker-variantRegular"
>
<span>
Offensive
</span>
<span
className="Count-root"
>
3
</span>
<span>
Offensive
</span>
</div>
<span
className="Count-root"
>
3
</span>
</span>
<button
aria-controls="uuid-1"
aria-expanded={false}
@@ -1017,28 +1001,24 @@ exports[`renders reported queue with comments 2`] = `
</a>
</div>
<div
className="Box-root HorizontalGutter-root HorizontalGutter-double"
className="Box-root HorizontalGutter-root HorizontalGutter-full"
>
<div
className="Box-root Flex-root Flex-flex"
className="Box-root Flex-root Flex-flex Flex-itemGutter gutter"
>
<div
className="Box-root Flex-root Flex-flex Flex-itemGutter gutter"
<span
className="Marker-root Marker-colorError Marker-variantRegular"
>
<span
className="Marker-root Marker-colorError Marker-variantRegular"
>
<span>
Spam
</span>
<span
className="Count-root"
>
2
</span>
<span>
Spam
</span>
</div>
<span
className="Count-root"
>
2
</span>
</span>
<button
aria-controls="uuid-0"
aria-expanded={false}
@@ -1230,28 +1210,24 @@ exports[`renders reported queue with comments 2`] = `
</a>
</div>
<div
className="Box-root HorizontalGutter-root HorizontalGutter-double"
className="Box-root HorizontalGutter-root HorizontalGutter-full"
>
<div
className="Box-root Flex-root Flex-flex"
className="Box-root Flex-root Flex-flex Flex-itemGutter gutter"
>
<div
className="Box-root Flex-root Flex-flex Flex-itemGutter gutter"
<span
className="Marker-root Marker-colorError Marker-variantRegular"
>
<span
className="Marker-root Marker-colorError Marker-variantRegular"
>
<span>
Offensive
</span>
<span
className="Count-root"
>
3
</span>
<span>
Offensive
</span>
</div>
<span
className="Count-root"
>
3
</span>
</span>
<button
aria-controls="uuid-1"
aria-expanded={false}
@@ -1449,46 +1425,42 @@ exports[`renders reported queue with comments and load more 1`] = `
</a>
</div>
<div
className="Box-root HorizontalGutter-root HorizontalGutter-double"
className="Box-root HorizontalGutter-root HorizontalGutter-full"
>
<div
className="Box-root Flex-root Flex-flex"
className="Box-root Flex-root Flex-flex Flex-itemGutter gutter"
>
<div
className="Box-root Flex-root Flex-flex Flex-itemGutter gutter"
<span
className="Marker-root Marker-colorPrimary Marker-variantRegular"
>
<span
className="Marker-root Marker-colorPrimary Marker-variantRegular"
>
Pre-Mod
Pre-Mod
</span>
<span
className="Marker-root Marker-colorError Marker-variantRegular"
>
<span>
Offensive
</span>
<span
className="Marker-root Marker-colorError Marker-variantRegular"
className="Count-root"
>
<span>
Offensive
</span>
<span
className="Count-root"
>
1
</span>
1
</span>
</span>
<span
className="Marker-root Marker-colorError Marker-variantRegular"
>
<span>
Spam
</span>
<span
className="Marker-root Marker-colorError Marker-variantRegular"
className="Count-root"
>
<span>
Spam
</span>
<span
className="Count-root"
>
1
</span>
1
</span>
</div>
</span>
<button
aria-controls="uuid-2"
aria-expanded={false}
@@ -120,28 +120,24 @@ exports[`approves comment in rejected queue: dangling 1`] = `
</a>
</div>
<div
className="Box-root HorizontalGutter-root HorizontalGutter-double"
className="Box-root HorizontalGutter-root HorizontalGutter-full"
>
<div
className="Box-root Flex-root Flex-flex"
className="Box-root Flex-root Flex-flex Flex-itemGutter gutter"
>
<div
className="Box-root Flex-root Flex-flex Flex-itemGutter gutter"
<span
className="Marker-root Marker-colorError Marker-variantRegular"
>
<span
className="Marker-root Marker-colorError Marker-variantRegular"
>
<span>
Spam
</span>
<span
className="Count-root"
>
2
</span>
<span>
Spam
</span>
</div>
<span
className="Count-root"
>
2
</span>
</span>
<button
aria-controls="uuid-0"
aria-expanded={false}
@@ -346,28 +342,24 @@ exports[`renders rejected queue with comments 1`] = `
</a>
</div>
<div
className="Box-root HorizontalGutter-root HorizontalGutter-double"
className="Box-root HorizontalGutter-root HorizontalGutter-full"
>
<div
className="Box-root Flex-root Flex-flex"
className="Box-root Flex-root Flex-flex Flex-itemGutter gutter"
>
<div
className="Box-root Flex-root Flex-flex Flex-itemGutter gutter"
<span
className="Marker-root Marker-colorError Marker-variantRegular"
>
<span
className="Marker-root Marker-colorError Marker-variantRegular"
>
<span>
Spam
</span>
<span
className="Count-root"
>
2
</span>
<span>
Spam
</span>
</div>
<span
className="Count-root"
>
2
</span>
</span>
<button
aria-controls="uuid-0"
aria-expanded={false}
@@ -559,28 +551,24 @@ exports[`renders rejected queue with comments 1`] = `
</a>
</div>
<div
className="Box-root HorizontalGutter-root HorizontalGutter-double"
className="Box-root HorizontalGutter-root HorizontalGutter-full"
>
<div
className="Box-root Flex-root Flex-flex"
className="Box-root Flex-root Flex-flex Flex-itemGutter gutter"
>
<div
className="Box-root Flex-root Flex-flex Flex-itemGutter gutter"
<span
className="Marker-root Marker-colorError Marker-variantRegular"
>
<span
className="Marker-root Marker-colorError Marker-variantRegular"
>
<span>
Offensive
</span>
<span
className="Count-root"
>
3
</span>
<span>
Offensive
</span>
</div>
<span
className="Count-root"
>
3
</span>
</span>
<button
aria-controls="uuid-1"
aria-expanded={false}
@@ -778,41 +766,37 @@ exports[`renders rejected queue with comments and load more 1`] = `
</a>
</div>
<div
className="Box-root HorizontalGutter-root HorizontalGutter-double"
className="Box-root HorizontalGutter-root HorizontalGutter-full"
>
<div
className="Box-root Flex-root Flex-flex"
className="Box-root Flex-root Flex-flex Flex-itemGutter gutter"
>
<div
className="Box-root Flex-root Flex-flex Flex-itemGutter gutter"
<span
className="Marker-root Marker-colorError Marker-variantRegular"
>
<span
className="Marker-root Marker-colorError Marker-variantRegular"
>
<span>
Offensive
</span>
<span
className="Count-root"
>
1
</span>
<span>
Offensive
</span>
<span
className="Marker-root Marker-colorError Marker-variantRegular"
className="Count-root"
>
<span>
Spam
</span>
<span
className="Count-root"
>
1
</span>
1
</span>
</div>
</span>
<span
className="Marker-root Marker-colorError Marker-variantRegular"
>
<span>
Spam
</span>
<span
className="Count-root"
>
1
</span>
</span>
<button
aria-controls="uuid-2"
aria-expanded={false}
@@ -86,28 +86,24 @@ exports[`approves single comment 1`] = `
</a>
</div>
<div
className="Box-root HorizontalGutter-root HorizontalGutter-double"
className="Box-root HorizontalGutter-root HorizontalGutter-full"
>
<div
className="Box-root Flex-root Flex-flex"
className="Box-root Flex-root Flex-flex Flex-itemGutter gutter"
>
<div
className="Box-root Flex-root Flex-flex Flex-itemGutter gutter"
<span
className="Marker-root Marker-colorError Marker-variantRegular"
>
<span
className="Marker-root Marker-colorError Marker-variantRegular"
>
<span>
Spam
</span>
<span
className="Count-root"
>
2
</span>
<span>
Spam
</span>
</div>
<span
className="Count-root"
>
2
</span>
</span>
<button
aria-controls="uuid-0"
aria-expanded={false}
@@ -281,28 +277,24 @@ exports[`rejects single comment 1`] = `
</a>
</div>
<div
className="Box-root HorizontalGutter-root HorizontalGutter-double"
className="Box-root HorizontalGutter-root HorizontalGutter-full"
>
<div
className="Box-root Flex-root Flex-flex"
className="Box-root Flex-root Flex-flex Flex-itemGutter gutter"
>
<div
className="Box-root Flex-root Flex-flex Flex-itemGutter gutter"
<span
className="Marker-root Marker-colorError Marker-variantRegular"
>
<span
className="Marker-root Marker-colorError Marker-variantRegular"
>
<span>
Spam
</span>
<span
className="Count-root"
>
2
</span>
<span>
Spam
</span>
</div>
<span
className="Count-root"
>
2
</span>
</span>
<button
aria-controls="uuid-0"
aria-expanded={false}
@@ -511,28 +503,24 @@ exports[`renders single comment view 1`] = `
</a>
</div>
<div
className="Box-root HorizontalGutter-root HorizontalGutter-double"
className="Box-root HorizontalGutter-root HorizontalGutter-full"
>
<div
className="Box-root Flex-root Flex-flex"
className="Box-root Flex-root Flex-flex Flex-itemGutter gutter"
>
<div
className="Box-root Flex-root Flex-flex Flex-itemGutter gutter"
<span
className="Marker-root Marker-colorError Marker-variantRegular"
>
<span
className="Marker-root Marker-colorError Marker-variantRegular"
>
<span>
Spam
</span>
<span
className="Count-root"
>
2
</span>
<span>
Spam
</span>
</div>
<span
className="Count-root"
>
2
</span>
</span>
<button
aria-controls="uuid-0"
aria-expanded={false}