mirror of
https://github.com/wassname/talk.git
synced 2026-08-11 11:27:10 +08:00
fix: added Other as flagging reason to ui (#3014)
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
import React, { FunctionComponent } from "react";
|
||||
|
||||
import NotAvailable from "coral-admin/components/NotAvailable";
|
||||
|
||||
import FlagDetailsCategory from "./FlagDetailsCategory";
|
||||
import FlagDetailsEntry from "./FlagDetailsEntry";
|
||||
|
||||
interface Props {
|
||||
category: React.ReactNode;
|
||||
nodes: ReadonlyArray<{
|
||||
flagger: { id: string; username: string | null } | null;
|
||||
additionalDetails: string | null;
|
||||
}>;
|
||||
onUsernameClick: (id?: string) => void;
|
||||
}
|
||||
|
||||
const FlagDetails: FunctionComponent<Props> = ({
|
||||
category,
|
||||
nodes,
|
||||
onUsernameClick,
|
||||
}) => {
|
||||
if (nodes.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<FlagDetailsCategory category={category}>
|
||||
{nodes.map((flag, i) => (
|
||||
<FlagDetailsEntry
|
||||
key={i}
|
||||
onClick={() =>
|
||||
flag.flagger ? onUsernameClick(flag.flagger.id) : null
|
||||
}
|
||||
user={
|
||||
flag.flagger && flag.flagger.username ? (
|
||||
flag.flagger.username
|
||||
) : (
|
||||
<NotAvailable />
|
||||
)
|
||||
}
|
||||
details={flag.additionalDetails}
|
||||
/>
|
||||
))}
|
||||
</FlagDetailsCategory>
|
||||
);
|
||||
};
|
||||
|
||||
export default FlagDetails;
|
||||
@@ -1,8 +1,8 @@
|
||||
$moderateCardFlagsCategoryColor: var(--v2-colors-mono-500);
|
||||
|
||||
.category {
|
||||
font-size: var(--v2-font-size-4);
|
||||
font-weight: var(--v2-font-weight-primary-regular);
|
||||
font-size: var(--v2-font-size-3);
|
||||
font-weight: var(--v2-font-weight-primary-bold);
|
||||
font-family: var(--v2-font-family-primary);
|
||||
line-height: var(--v2-line-height-body-short);
|
||||
color: $moderateCardFlagsCategoryColor;
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
.detailsDivider {
|
||||
border-top: 1px solid var(--v2-colors-grey-100);
|
||||
}
|
||||
@@ -1,20 +1,61 @@
|
||||
import { Localized } from "@fluent/react/compat";
|
||||
import React, { FunctionComponent } from "react";
|
||||
import React, { FunctionComponent, useMemo } from "react";
|
||||
import { graphql } from "react-relay";
|
||||
|
||||
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/v2";
|
||||
|
||||
import { FlagDetailsContainer_comment } from "coral-admin/__generated__/FlagDetailsContainer_comment.graphql";
|
||||
import {
|
||||
COMMENT_FLAG_REASON,
|
||||
FlagDetailsContainer_comment,
|
||||
} from "coral-admin/__generated__/FlagDetailsContainer_comment.graphql";
|
||||
import { FlagDetailsContainer_settings } from "coral-admin/__generated__/FlagDetailsContainer_settings.graphql";
|
||||
|
||||
import FlagDetails from "./FlagDetails";
|
||||
import FlagDetailsCategory from "./FlagDetailsCategory";
|
||||
import FlagDetailsEntry from "./FlagDetailsEntry";
|
||||
import ToxicityLabel from "./ToxicityLabel";
|
||||
|
||||
import styles from "./FlagDetailsContainer.css";
|
||||
|
||||
interface Reasons<T> {
|
||||
offensive: T[];
|
||||
abusive: T[];
|
||||
spam: T[];
|
||||
other: T[];
|
||||
}
|
||||
|
||||
function reduceReasons<
|
||||
T extends { readonly reason: COMMENT_FLAG_REASON | null }
|
||||
>(nodes: ReadonlyArray<T>) {
|
||||
const initialValue: Reasons<T> = {
|
||||
offensive: [],
|
||||
abusive: [],
|
||||
spam: [],
|
||||
other: [],
|
||||
};
|
||||
|
||||
return nodes.reduce((reasons, node) => {
|
||||
switch (node.reason) {
|
||||
case GQLCOMMENT_FLAG_REASON.COMMENT_REPORTED_OFFENSIVE:
|
||||
reasons.offensive.push(node);
|
||||
break;
|
||||
case GQLCOMMENT_FLAG_REASON.COMMENT_REPORTED_ABUSIVE:
|
||||
reasons.abusive.push(node);
|
||||
break;
|
||||
case GQLCOMMENT_FLAG_REASON.COMMENT_REPORTED_SPAM:
|
||||
reasons.spam.push(node);
|
||||
break;
|
||||
case GQLCOMMENT_FLAG_REASON.COMMENT_REPORTED_OTHER:
|
||||
reasons.other.push(node);
|
||||
break;
|
||||
}
|
||||
|
||||
return reasons;
|
||||
}, initialValue);
|
||||
}
|
||||
|
||||
interface Props {
|
||||
comment: FlagDetailsContainer_comment;
|
||||
settings: FlagDetailsContainer_settings;
|
||||
@@ -26,21 +67,16 @@ const FlagDetailsContainer: FunctionComponent<Props> = ({
|
||||
onUsernameClick,
|
||||
settings,
|
||||
}) => {
|
||||
const metadata = comment.revision ? comment.revision.metadata : null;
|
||||
const nodes = comment.flags.nodes;
|
||||
const { offensive, abusive, spam, other } = useMemo(
|
||||
() => reduceReasons(comment.flags.nodes),
|
||||
[comment.flags.nodes]
|
||||
);
|
||||
|
||||
const offensive = nodes.filter(
|
||||
({ reason }) => reason === GQLCOMMENT_FLAG_REASON.COMMENT_REPORTED_OFFENSIVE
|
||||
);
|
||||
const abusive = nodes.filter(
|
||||
({ reason }) => reason === GQLCOMMENT_FLAG_REASON.COMMENT_REPORTED_ABUSIVE
|
||||
);
|
||||
const spam = nodes.filter(
|
||||
({ reason }) => reason === GQLCOMMENT_FLAG_REASON.COMMENT_REPORTED_SPAM
|
||||
);
|
||||
const metadata = comment.revision ? comment.revision.metadata : null;
|
||||
|
||||
return (
|
||||
<HorizontalGutter size="oneAndAHalf">
|
||||
<hr className={styles.detailsDivider} />
|
||||
{metadata && metadata.perspective && (
|
||||
<FlagDetailsCategory
|
||||
category={
|
||||
@@ -58,66 +94,42 @@ const FlagDetailsContainer: FunctionComponent<Props> = ({
|
||||
/>
|
||||
</FlagDetailsCategory>
|
||||
)}
|
||||
{offensive.length > 0 && (
|
||||
<FlagDetailsCategory
|
||||
category={
|
||||
<Localized id="moderate-flagDetails-offensive">
|
||||
<span>Offensive</span>
|
||||
</Localized>
|
||||
}
|
||||
>
|
||||
{offensive.map((flag, i) => (
|
||||
<FlagDetailsEntry
|
||||
key={i}
|
||||
onClick={() =>
|
||||
flag.flagger ? onUsernameClick(flag.flagger.id) : null
|
||||
}
|
||||
user={flag.flagger ? flag.flagger.username : <NotAvailable />}
|
||||
details={flag.additionalDetails}
|
||||
/>
|
||||
))}
|
||||
</FlagDetailsCategory>
|
||||
)}
|
||||
{abusive.length > 0 && (
|
||||
<FlagDetailsCategory
|
||||
category={
|
||||
<Localized id="moderate-flagDetails-abusive">
|
||||
<span>Abusive</span>
|
||||
</Localized>
|
||||
}
|
||||
>
|
||||
{abusive.map((flag, i) => (
|
||||
<FlagDetailsEntry
|
||||
key={i}
|
||||
onClick={() =>
|
||||
flag.flagger ? onUsernameClick(flag.flagger.id) : null
|
||||
}
|
||||
user={flag.flagger ? flag.flagger.username : <NotAvailable />}
|
||||
details={flag.additionalDetails}
|
||||
/>
|
||||
))}
|
||||
</FlagDetailsCategory>
|
||||
)}
|
||||
{spam.length > 0 && (
|
||||
<FlagDetailsCategory
|
||||
category={
|
||||
<Localized id="moderate-flagDetails-spam">
|
||||
<span>Spam</span>
|
||||
</Localized>
|
||||
}
|
||||
>
|
||||
{spam.map((flag, i) => (
|
||||
<FlagDetailsEntry
|
||||
onClick={() =>
|
||||
flag.flagger ? onUsernameClick(flag.flagger.id) : null
|
||||
}
|
||||
key={i}
|
||||
user={flag.flagger ? flag.flagger.username : <NotAvailable />}
|
||||
details={flag.additionalDetails}
|
||||
/>
|
||||
))}
|
||||
</FlagDetailsCategory>
|
||||
)}
|
||||
<FlagDetails
|
||||
category={
|
||||
<Localized id="moderate-flagDetails-offensive">
|
||||
<span>Offensive</span>
|
||||
</Localized>
|
||||
}
|
||||
nodes={offensive}
|
||||
onUsernameClick={onUsernameClick}
|
||||
/>
|
||||
<FlagDetails
|
||||
category={
|
||||
<Localized id="moderate-flagDetails-abusive">
|
||||
<span>Abusive</span>
|
||||
</Localized>
|
||||
}
|
||||
nodes={abusive}
|
||||
onUsernameClick={onUsernameClick}
|
||||
/>
|
||||
<FlagDetails
|
||||
category={
|
||||
<Localized id="moderate-flagDetails-spam">
|
||||
<span>Spam</span>
|
||||
</Localized>
|
||||
}
|
||||
nodes={spam}
|
||||
onUsernameClick={onUsernameClick}
|
||||
/>
|
||||
<FlagDetails
|
||||
category={
|
||||
<Localized id="moderate-flagDetails-other">
|
||||
<span>Other</span>
|
||||
</Localized>
|
||||
}
|
||||
nodes={other}
|
||||
onUsernameClick={onUsernameClick}
|
||||
/>
|
||||
</HorizontalGutter>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -12,6 +12,7 @@ $moderateCardReasonTextColor: var(--v2-colors-mono-500);
|
||||
|
||||
.details {
|
||||
color: $moderateCardReasonTextColor;
|
||||
display: block;
|
||||
font-size: var(--v2-font-size-2);
|
||||
font-weight: var(--v2-font-weight-primary-regular);
|
||||
font-family: var(--v2-font-family-primary);
|
||||
|
||||
@@ -19,18 +19,10 @@ const FlagDetailsEntry: FunctionComponent<Props> = ({
|
||||
<div>
|
||||
{onClick && (
|
||||
<BaseButton className={styles.flagger} onClick={onClick}>
|
||||
<span className={styles.user}>
|
||||
{user}
|
||||
{details && ":"}
|
||||
</span>
|
||||
<span className={styles.user}>{user}</span>
|
||||
</BaseButton>
|
||||
)}
|
||||
{!onClick && (
|
||||
<span className={styles.user}>
|
||||
{user}
|
||||
{details && ":"}
|
||||
</span>
|
||||
)}
|
||||
{!onClick && <span className={styles.user}>{user}</span>}
|
||||
{details && <span className={styles.details}>{details}</span>}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
$moderateCardDetailsHeaderColor: var(--v2-colors-mono-500);
|
||||
$moderateCardDetailsDividerColor: var(--v2-colors-grey-100);
|
||||
|
||||
.detailsButton {
|
||||
font-size: var(--v2-font-size-1);
|
||||
@@ -21,7 +20,3 @@ $moderateCardDetailsDividerColor: var(--v2-colors-grey-100);
|
||||
.detailsText {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.detailsDivider {
|
||||
border-color: $moderateCardDetailsDividerColor;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Localized } from "@fluent/react/compat";
|
||||
import React, { FunctionComponent, useCallback, useState } from "react";
|
||||
import React, { FunctionComponent } from "react";
|
||||
|
||||
import { useUUID } from "coral-framework/hooks";
|
||||
import { useToggleState, useUUID } from "coral-framework/hooks";
|
||||
import {
|
||||
Button,
|
||||
ButtonIcon,
|
||||
@@ -18,10 +18,8 @@ interface Props {
|
||||
|
||||
const Markers: FunctionComponent<Props> = ({ children, details }) => {
|
||||
const uuid = useUUID();
|
||||
const [showDetails, setShowDetails] = useState<boolean>(false);
|
||||
const toggleDetails = useCallback(() => setShowDetails(!showDetails), [
|
||||
showDetails,
|
||||
]);
|
||||
const [showDetails, , toggleDetails] = useToggleState();
|
||||
|
||||
return (
|
||||
<HorizontalGutter>
|
||||
<Flex itemGutter>
|
||||
@@ -43,12 +41,7 @@ const Markers: FunctionComponent<Props> = ({ children, details }) => {
|
||||
</Button>
|
||||
)}
|
||||
</Flex>
|
||||
{showDetails && (
|
||||
<div id={uuid}>
|
||||
<hr className={styles.detailsDivider} />
|
||||
{details}
|
||||
</div>
|
||||
)}
|
||||
{showDetails && <div id={uuid}>{details}</div>}
|
||||
</HorizontalGutter>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -17,17 +17,18 @@ it("renders all markers", () => {
|
||||
actionCounts: {
|
||||
flag: {
|
||||
reasons: {
|
||||
COMMENT_DETECTED_TOXIC: 1,
|
||||
COMMENT_DETECTED_SPAM: 1,
|
||||
COMMENT_DETECTED_RECENT_HISTORY: 1,
|
||||
COMMENT_DETECTED_LINKS: 1,
|
||||
COMMENT_DETECTED_BANNED_WORD: 1,
|
||||
COMMENT_DETECTED_SUSPECT_WORD: 1,
|
||||
COMMENT_REPORTED_SPAM: 3,
|
||||
COMMENT_REPORTED_OTHER: 0,
|
||||
COMMENT_REPORTED_OFFENSIVE: 2,
|
||||
COMMENT_REPORTED_ABUSIVE: 0,
|
||||
COMMENT_REPORTED_SPAM: 3,
|
||||
COMMENT_DETECTED_NEW_COMMENTER: 0,
|
||||
COMMENT_DETECTED_TOXIC: 1,
|
||||
COMMENT_DETECTED_SUSPECT_WORD: 1,
|
||||
COMMENT_DETECTED_SPAM: 1,
|
||||
COMMENT_DETECTED_REPEAT_POST: 1,
|
||||
COMMENT_DETECTED_RECENT_HISTORY: 1,
|
||||
COMMENT_DETECTED_NEW_COMMENTER: 0,
|
||||
COMMENT_DETECTED_LINKS: 1,
|
||||
COMMENT_DETECTED_BANNED_WORD: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -55,17 +56,18 @@ it("renders some markers", () => {
|
||||
actionCounts: {
|
||||
flag: {
|
||||
reasons: {
|
||||
COMMENT_DETECTED_TOXIC: 1,
|
||||
COMMENT_DETECTED_SPAM: 0,
|
||||
COMMENT_DETECTED_RECENT_HISTORY: 1,
|
||||
COMMENT_DETECTED_LINKS: 0,
|
||||
COMMENT_DETECTED_BANNED_WORD: 1,
|
||||
COMMENT_DETECTED_SUSPECT_WORD: 0,
|
||||
COMMENT_REPORTED_SPAM: 0,
|
||||
COMMENT_REPORTED_OTHER: 0,
|
||||
COMMENT_REPORTED_OFFENSIVE: 2,
|
||||
COMMENT_REPORTED_ABUSIVE: 0,
|
||||
COMMENT_REPORTED_SPAM: 0,
|
||||
COMMENT_DETECTED_NEW_COMMENTER: 0,
|
||||
COMMENT_DETECTED_TOXIC: 1,
|
||||
COMMENT_DETECTED_SUSPECT_WORD: 0,
|
||||
COMMENT_DETECTED_SPAM: 0,
|
||||
COMMENT_DETECTED_REPEAT_POST: 0,
|
||||
COMMENT_DETECTED_RECENT_HISTORY: 1,
|
||||
COMMENT_DETECTED_NEW_COMMENTER: 0,
|
||||
COMMENT_DETECTED_LINKS: 0,
|
||||
COMMENT_DETECTED_BANNED_WORD: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -123,6 +123,19 @@ const markers: Array<(
|
||||
</Marker>
|
||||
)) ||
|
||||
null,
|
||||
(c) =>
|
||||
(c.revision &&
|
||||
c.revision.actionCounts.flag.reasons.COMMENT_REPORTED_OTHER && (
|
||||
<Marker key={keyCounter++} color="reported">
|
||||
<Localized id="moderate-marker-other">
|
||||
<span>Other</span>
|
||||
</Localized>{" "}
|
||||
<MarkerCount>
|
||||
{c.revision.actionCounts.flag.reasons.COMMENT_REPORTED_OTHER}
|
||||
</MarkerCount>
|
||||
</Marker>
|
||||
)) ||
|
||||
null,
|
||||
(c) =>
|
||||
(c.revision &&
|
||||
c.revision.actionCounts.flag.reasons.COMMENT_DETECTED_NEW_COMMENTER && (
|
||||
@@ -138,7 +151,7 @@ export const MarkersContainer: React.FunctionComponent<MarkersContainerProps> =
|
||||
) => {
|
||||
const elements = useMemo(
|
||||
() => markers.map((cb) => cb(props.comment)).filter((m) => m),
|
||||
[markers, props.comment]
|
||||
[props.comment]
|
||||
);
|
||||
|
||||
return (
|
||||
@@ -165,17 +178,18 @@ const enhanced = withFragmentContainer<MarkersContainerProps>({
|
||||
actionCounts {
|
||||
flag {
|
||||
reasons {
|
||||
COMMENT_DETECTED_TOXIC
|
||||
COMMENT_DETECTED_SPAM
|
||||
COMMENT_DETECTED_RECENT_HISTORY
|
||||
COMMENT_DETECTED_LINKS
|
||||
COMMENT_DETECTED_BANNED_WORD
|
||||
COMMENT_DETECTED_SUSPECT_WORD
|
||||
COMMENT_REPORTED_SPAM
|
||||
COMMENT_REPORTED_OTHER
|
||||
COMMENT_REPORTED_OFFENSIVE
|
||||
COMMENT_REPORTED_ABUSIVE
|
||||
COMMENT_REPORTED_SPAM
|
||||
COMMENT_DETECTED_NEW_COMMENTER
|
||||
COMMENT_DETECTED_TOXIC
|
||||
COMMENT_DETECTED_SUSPECT_WORD
|
||||
COMMENT_DETECTED_SPAM
|
||||
COMMENT_DETECTED_REPEAT_POST
|
||||
COMMENT_DETECTED_RECENT_HISTORY
|
||||
COMMENT_DETECTED_NEW_COMMENTER
|
||||
COMMENT_DETECTED_LINKS
|
||||
COMMENT_DETECTED_BANNED_WORD
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ function hasFlagDetails(c: ModerateCardDetailsContainer_comment) {
|
||||
return c.revision
|
||||
? c.revision.actionCounts.flag.reasons.COMMENT_REPORTED_OFFENSIVE +
|
||||
c.revision.actionCounts.flag.reasons.COMMENT_REPORTED_ABUSIVE +
|
||||
c.revision.actionCounts.flag.reasons.COMMENT_REPORTED_OTHER +
|
||||
c.revision.actionCounts.flag.reasons.COMMENT_REPORTED_SPAM >
|
||||
0 || c.revision.metadata.perspective
|
||||
: false;
|
||||
@@ -82,14 +83,11 @@ const ModerateCardDetailsContainer: FunctionComponent<Props> = ({
|
||||
<>
|
||||
<LinkDetailsContainer comment={comment} settings={settings} />
|
||||
{doesHaveFlagDetails && (
|
||||
<>
|
||||
<hr />
|
||||
<FlagDetailsContainer
|
||||
comment={comment}
|
||||
settings={settings}
|
||||
onUsernameClick={onUsernameClick}
|
||||
/>
|
||||
</>
|
||||
<FlagDetailsContainer
|
||||
comment={comment}
|
||||
settings={settings}
|
||||
onUsernameClick={onUsernameClick}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
@@ -113,6 +111,7 @@ const enhanced = withFragmentContainer<Props>({
|
||||
COMMENT_REPORTED_OFFENSIVE
|
||||
COMMENT_REPORTED_ABUSIVE
|
||||
COMMENT_REPORTED_SPAM
|
||||
COMMENT_REPORTED_OTHER
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -20,6 +20,7 @@ exports[`renders all markers 1`] = `
|
||||
"COMMENT_DETECTED_TOXIC": 1,
|
||||
"COMMENT_REPORTED_ABUSIVE": 0,
|
||||
"COMMENT_REPORTED_OFFENSIVE": 2,
|
||||
"COMMENT_REPORTED_OTHER": 0,
|
||||
"COMMENT_REPORTED_SPAM": 3,
|
||||
},
|
||||
},
|
||||
@@ -166,6 +167,7 @@ exports[`renders some markers 1`] = `
|
||||
"COMMENT_DETECTED_TOXIC": 1,
|
||||
"COMMENT_REPORTED_ABUSIVE": 0,
|
||||
"COMMENT_REPORTED_OFFENSIVE": 2,
|
||||
"COMMENT_REPORTED_OTHER": 0,
|
||||
"COMMENT_REPORTED_SPAM": 0,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -643,17 +643,18 @@ export const baseComment = createFixture<GQLComment>({
|
||||
actionCounts: {
|
||||
flag: {
|
||||
reasons: {
|
||||
COMMENT_DETECTED_TOXIC: 0,
|
||||
COMMENT_DETECTED_SPAM: 0,
|
||||
COMMENT_DETECTED_RECENT_HISTORY: 0,
|
||||
COMMENT_DETECTED_LINKS: 0,
|
||||
COMMENT_DETECTED_BANNED_WORD: 0,
|
||||
COMMENT_DETECTED_SUSPECT_WORD: 0,
|
||||
COMMENT_REPORTED_SPAM: 0,
|
||||
COMMENT_REPORTED_OTHER: 0,
|
||||
COMMENT_REPORTED_OFFENSIVE: 0,
|
||||
COMMENT_REPORTED_ABUSIVE: 0,
|
||||
COMMENT_REPORTED_SPAM: 0,
|
||||
COMMENT_DETECTED_NEW_COMMENTER: 0,
|
||||
COMMENT_DETECTED_TOXIC: 0,
|
||||
COMMENT_DETECTED_SUSPECT_WORD: 0,
|
||||
COMMENT_DETECTED_SPAM: 0,
|
||||
COMMENT_DETECTED_REPEAT_POST: 0,
|
||||
COMMENT_DETECTED_RECENT_HISTORY: 0,
|
||||
COMMENT_DETECTED_NEW_COMMENTER: 0,
|
||||
COMMENT_DETECTED_LINKS: 0,
|
||||
COMMENT_DETECTED_BANNED_WORD: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -829,11 +829,13 @@ moderate-marker-offensive = Offensive
|
||||
moderate-marker-abusive = Abusive
|
||||
moderate-marker-newCommenter = New commenter
|
||||
moderate-marker-repeatPost = Repeat comment
|
||||
moderate-marker-other = Other
|
||||
|
||||
moderate-markers-details = Details
|
||||
moderate-flagDetails-offensive = Offensive
|
||||
moderate-flagDetails-abusive = Abusive
|
||||
moderate-flagDetails-spam = Spam
|
||||
moderate-flagDetails-other = Other
|
||||
|
||||
moderate-flagDetails-toxicityScore = Toxicity Score
|
||||
moderate-toxicityLabel-likely = Likely <score></score>
|
||||
|
||||
Reference in New Issue
Block a user