diff --git a/client/src/core/client/admin/components/ModerateCard/DecisionDetailsContainer.css b/client/src/core/client/admin/components/ModerateCard/DecisionDetailsContainer.css new file mode 100644 index 0000000000..5588b5a93c --- /dev/null +++ b/client/src/core/client/admin/components/ModerateCard/DecisionDetailsContainer.css @@ -0,0 +1,15 @@ +.wrapper { + background-color: var(--palette-grey-200); + font-family: var(--font-family-primary); +} + +.full { + width: 100%; +} + +.label { + font-size: var(--font-size-1); + font-weight: var(--font-weight-primary-semi-bold); + text-transform: uppercase; + color: var(--palette-grey-500); +} diff --git a/client/src/core/client/admin/components/ModerateCard/DecisionDetailsContainer.tsx b/client/src/core/client/admin/components/ModerateCard/DecisionDetailsContainer.tsx new file mode 100644 index 0000000000..3c63efd2e5 --- /dev/null +++ b/client/src/core/client/admin/components/ModerateCard/DecisionDetailsContainer.tsx @@ -0,0 +1,64 @@ +// import { Localized } from "@fluent/react/compat"; +import React, { FunctionComponent } from "react"; +import { graphql } from "react-relay"; + +import { withFragmentContainer } from "coral-framework/lib/relay"; +import { Flex, HorizontalGutter } from "coral-ui/components/v2"; + +import { DecisionDetailsContainer_comment } from "coral-admin/__generated__/DecisionDetailsContainer_comment.graphql"; + +import styles from "./DecisionDetailsContainer.css"; + +interface Props { + comment: DecisionDetailsContainer_comment; +} + +const DecisionDetailsContainer: FunctionComponent = ({ comment }) => { + const statusHistory = comment.statusHistory.edges[0].node; + return ( + + + +
Decision
+
Rejected
+
+ +
Reason
+
{statusHistory.rejectionReason?.code}
+
+
+ {statusHistory.rejectionReason?.detailedExplanation && ( + +
Detailed explanation
+
{statusHistory.rejectionReason?.detailedExplanation}
+
+ )} + +
{statusHistory.createdAt}
+
+
+ ); +}; + +const enhanced = withFragmentContainer({ + comment: graphql` + fragment DecisionDetailsContainer_comment on Comment { + id + statusHistory(first: 1) { + edges { + node { + createdAt + status + rejectionReason { + code + legalGrounds + detailedExplanation + } + } + } + } + } + `, +})(DecisionDetailsContainer); + +export default enhanced; diff --git a/client/src/core/client/admin/components/ModerateCard/ModerateCardDetailsContainer.tsx b/client/src/core/client/admin/components/ModerateCard/ModerateCardDetailsContainer.tsx index 8dde7527e3..ccd814df31 100644 --- a/client/src/core/client/admin/components/ModerateCard/ModerateCardDetailsContainer.tsx +++ b/client/src/core/client/admin/components/ModerateCard/ModerateCardDetailsContainer.tsx @@ -8,6 +8,7 @@ import React, { import { graphql } from "react-relay"; import { withFragmentContainer } from "coral-framework/lib/relay"; +import { GQLCOMMENT_STATUS } from "coral-framework/schema"; import { CheckDoubleIcon, LikeIcon, @@ -22,6 +23,7 @@ import { ModerateCardDetailsContainer_settings } from "coral-admin/__generated__ import AutomatedActionsContainer from "./AutomatedActionsContainer"; import CommentRevisionContainer from "./CommentRevisionContainer"; +import DecisionDetailsContainer from "./DecisionDetailsContainer"; import FlagDetailsContainer from "./FlagDetailsContainer"; import LinkDetailsContainer from "./LinkDetailsContainer"; import ReactionDetailsQuery from "./ReactionDetailsQuery"; @@ -34,7 +36,12 @@ interface Props { onUsernameClick: (id?: string) => void; } -type DetailsTabs = "INFO" | "REACTIONS" | "HISTORY" | "EXTERNAL_MOD"; +type DetailsTabs = + | "INFO" + | "REACTIONS" + | "HISTORY" + | "EXTERNAL_MOD" + | "DECISION"; function hasFlagDetails(c: ModerateCardDetailsContainer_comment) { return c.revision @@ -76,9 +83,27 @@ const ModerateCardDetailsContainer: FunctionComponent = ({ comment.revision.actionCounts.reaction.total > 0 ); + const hasDecision = + comment.status === GQLCOMMENT_STATUS.REJECTED && + comment.statusHistory.edges[0] && + comment.statusHistory.edges[0].node.rejectionReason && + comment.statusHistory.edges[0].node.rejectionReason.code; + return ( + {hasDecision && ( + + + {/* TODO: Update this icon */} + + {/* TODO: Add this translation */} + + Decision + + + + )} @@ -118,6 +143,9 @@ const ModerateCardDetailsContainer: FunctionComponent = ({ )} + {activeTab === "DECISION" && ( + + )} {activeTab === "INFO" && ( <> @@ -156,6 +184,15 @@ const enhanced = withFragmentContainer({ editing { edited } + statusHistory(first: 1) { + edges { + node { + rejectionReason { + code + } + } + } + } revision { actionCounts { flag { @@ -193,6 +230,7 @@ const enhanced = withFragmentContainer({ ...CommentRevisionContainer_comment ...LinkDetailsContainer_comment ...AutomatedActionsContainer_comment + ...DecisionDetailsContainer_comment } `, settings: graphql` diff --git a/server/src/core/server/graph/schema/schema.graphql b/server/src/core/server/graph/schema/schema.graphql index c2ab69385a..fa8bf3adbd 100644 --- a/server/src/core/server/graph/schema/schema.graphql +++ b/server/src/core/server/graph/schema/schema.graphql @@ -3488,7 +3488,7 @@ type CommentModerationAction { """ reason is the reason the comment was rejected, if it was rejected """ - reason: RejectionReason + rejectionReason: RejectionReason """ createdAt is the time that the CommentModerationAction was created.