Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse Comment & Abuse responses of the Discussion API #10364

Merged
merged 2 commits into from
Jan 29, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
feat(discussion): parse comment & abuse responses
reduce the complexity of the possible types,
and remove any unused parts of the API response
mxdvl committed Jan 26, 2024
commit 7aed9736bdb51a97e644ac5668e811298b6834d2
Original file line number Diff line number Diff line change
@@ -167,9 +167,9 @@ export const AbuseReportForm = ({
authStatus,
})
.then((response) => {
if (response.status !== 'ok') {
if (response.kind === 'error') {
// Fallback to errors returned from the API
setErrors({ ...errors, response: response.message });
setErrors({ ...errors, response: response.error });
} else {
setSuccessMessage('Report submitted');
}
8 changes: 4 additions & 4 deletions dotcom-rendering/src/components/Discussion/Comment.tsx
Original file line number Diff line number Diff line change
@@ -314,8 +314,8 @@ export const Comment = ({
setError('');

const response = await pickComment(staffUser.authStatus, comment.id);
if (response.status === 'error') {
setError(response.message);
if (response.kind === 'error') {
setError(response.error.message);
} else {
setIsHighlighted(true);
}
@@ -324,8 +324,8 @@ export const Comment = ({
const unPick = async (staffUser: SignedInUser) => {
setError('');
const response = await unPickComment(staffUser.authStatus, comment.id);
if (response.status === 'error') {
setError(response.message);
if (response.kind === 'error') {
setError(response.error.message);
} else {
setIsHighlighted(false);
}
Original file line number Diff line number Diff line change
@@ -2,9 +2,9 @@ import { css } from '@emotion/react';
import { palette as sourcePalette, space } from '@guardian/source-foundations';
import { SvgPlus } from '@guardian/source-react-components';
import { useEffect, useState } from 'react';
import type { comment, reply } from '../../lib/discussionApi';
import { getMoreResponses } from '../../lib/discussionApi';
import type {
CommentResponse,
CommentType,
SignedInUser,
ThreadsType,
@@ -27,12 +27,8 @@ type Props = {
toggleMuteStatus: (userId: string) => void;
onPermalinkClick: (commentId: number) => void;
onRecommend?: (commentId: number) => Promise<boolean>;
onComment?: (shortUrl: string, body: string) => Promise<CommentResponse>;
onReply?: (
shortUrl: string,
body: string,
parentCommentId: number,
) => Promise<CommentResponse>;
onComment?: ReturnType<typeof comment>;
onReply?: ReturnType<typeof reply>;
onPreview?: (body: string) => Promise<string>;
showPreview: boolean;
setShowPreview: (showPreview: boolean) => void;
134 changes: 65 additions & 69 deletions dotcom-rendering/src/components/Discussion/CommentForm.tsx
Original file line number Diff line number Diff line change
@@ -13,11 +13,7 @@ import {
reply as defaultReply,
} from '../../lib/discussionApi';
import { palette as schemedPalette } from '../../palette';
import type {
CommentResponse,
CommentType,
SignedInUser,
} from '../../types/discussion';
import type { CommentType, SignedInUser } from '../../types/discussion';
import { FirstCommentWelcome } from './FirstCommentWelcome';
import { PillarButton } from './PillarButton';
import { Preview } from './Preview';
@@ -29,12 +25,8 @@ type Props = {
onAddComment: (response: CommentType) => void;
setCommentBeingRepliedTo?: () => void;
commentBeingRepliedTo?: CommentType;
onComment?: (shortUrl: string, body: string) => Promise<CommentResponse>;
onReply?: (
shortUrl: string,
body: string,
parentCommentId: number,
) => Promise<CommentResponse>;
onComment?: ReturnType<typeof defaultComment>;
onReply?: ReturnType<typeof defaultReply>;
onPreview?: (body: string) => Promise<string>;
showPreview: boolean;
setShowPreview: (showPreview: boolean) => void;
@@ -325,88 +317,92 @@ export const CommentForm = ({
if (body) {
const comment = onComment ?? defaultComment(user.authStatus);
const reply = onReply ?? defaultReply(user.authStatus);
const response: CommentResponse = commentBeingRepliedTo
const response = commentBeingRepliedTo
? await reply(shortUrl, body, commentBeingRepliedTo.id)
: await comment(shortUrl, body);
// Check response message for error states
if (response.errorCode === 'USERNAME_MISSING') {
// Reader has never posted before and needs to choose a username
setUserNameMissing(true);
} else if (response.errorCode === 'EMPTY_COMMENT_BODY') {
setError('Please write a comment.');
} else if (response.errorCode === 'COMMENT_TOO_LONG') {
setError(
'Your comment must be fewer than 5000 characters long.',
);
} else if (response.errorCode === 'USER_BANNED') {
setError(
'Commenting has been disabled for this account (<a href="/community-faqs#321a">why?</a>).',
);
} else if (response.errorCode === 'IP_THROTTLED') {
setError(
'Commenting has been temporarily blocked for this IP address (<a href="/community-faqs">why?</a>).',
);
} else if (response.errorCode === 'DISCUSSION_CLOSED') {
setError(
'Sorry your comment can not be published as the discussion is now closed for comments.',
);
} else if (response.errorCode === 'PARENT_COMMENT_MODERATED') {
setError(
'Sorry the comment can not be published as the comment you replied to has been moderated since.',
);
} else if (response.errorCode === 'COMMENT_RATE_LIMIT_EXCEEDED') {
setError(
'You can only post one comment every minute. Please try again in a moment.',
);
} else if (response.errorCode === 'INVALID_PROTOCOL') {
setError(`Sorry your comment can not be published as it was not sent over
if (response.kind === 'error') {
if (response.error.code === 'USERNAME_MISSING') {
// Reader has never posted before and needs to choose a username
setUserNameMissing(true);
} else if (response.error.code === 'EMPTY_COMMENT_BODY') {
setError('Please write a comment.');
} else if (response.error.code === 'COMMENT_TOO_LONG') {
setError(
'Your comment must be fewer than 5000 characters long.',
);
} else if (response.error.code === 'USER_BANNED') {
setError(
'Commenting has been disabled for this account (<a href="/community-faqs#321a">why?</a>).',
);
} else if (response.error.code === 'IP_THROTTLED') {
setError(
'Commenting has been temporarily blocked for this IP address (<a href="/community-faqs">why?</a>).',
);
} else if (response.error.code === 'DISCUSSION_CLOSED') {
setError(
'Sorry your comment can not be published as the discussion is now closed for comments.',
);
} else if (response.error.code === 'PARENT_COMMENT_MODERATED') {
setError(
'Sorry the comment can not be published as the comment you replied to has been moderated since.',
);
} else if (
response.error.code === 'COMMENT_RATE_LIMIT_EXCEEDED'
) {
setError(
'You can only post one comment every minute. Please try again in a moment.',
);
} else if (response.error.code === 'INVALID_PROTOCOL') {
setError(`Sorry your comment can not be published as it was not sent over
a secure channel. Please report us this issue using the technical issue link
in the page footer.`);
} else if (response.errorCode === 'AUTH_COOKIE_INVALID') {
setError(
'Sorry, your comment was not published as you are no longer signed in. Please sign in and try again.',
);
} else if (response.errorCode === 'READ-ONLY-MODE') {
setError(`Sorry your comment can not currently be published as
} else if (response.error.code === 'AUTH_COOKIE_INVALID') {
setError(
'Sorry, your comment was not published as you are no longer signed in. Please sign in and try again.',
);
} else if (response.error.code === 'READ-ONLY-MODE') {
setError(`Sorry your comment can not currently be published as
commenting is undergoing maintenance but will be back shortly. Please try
again in a moment.`);
} else if (response.errorCode === 'API_CORS_BLOCKED') {
setError(`Could not post due to your internet settings, which might be
} else if (response.error.code === 'API_CORS_BLOCKED') {
setError(`Could not post due to your internet settings, which might be
controlled by your provider. Please contact your administrator
or disable any proxy servers or VPNs and try again.`);
} else if (response.errorCode === 'API_ERROR') {
setError(`Sorry, there was a problem posting your comment. Please try
} else if (response.error.code === 'API_ERROR') {
setError(`Sorry, there was a problem posting your comment. Please try
another browser or network connection. Reference code `);
} else if (response.errorCode === 'EMAIL_VERIFIED') {
setInfo(
'Sent. Please check your email to verify your email address. Once verified post your comment.',
);
} else if (response.errorCode === 'EMAIL_VERIFIED_FAIL') {
// TODO: Support resending verification email
setError(`We are having technical difficulties. Please try again later or
} else if (response.error.code === 'EMAIL_VERIFIED') {
setInfo(
'Sent. Please check your email to verify your email address. Once verified post your comment.',
);
} else if (response.error.code === 'EMAIL_VERIFIED_FAIL') {
// TODO: Support resending verification email
setError(`We are having technical difficulties. Please try again later or
<a href="#">
<strong>resend the verification</strong></a>.`);
} else if (response.errorCode === 'EMAIL_NOT_VALIDATED') {
// TODO: Support resending verification email
setError(`Please confirm your email address to comment.<br />
} else if (response.error.code === 'EMAIL_NOT_VALIDATED') {
// TODO: Support resending verification email
setError(`Please confirm your email address to comment.<br />
If you can't find the email, we can
<a href="#">
<strong>resend the verification email</strong></a> to your email
address.`);
} else if (response.status === 'ok') {
} else {
setError(
'Sorry, there was a problem posting your comment.',
);
}
} else {
onAddComment(
simulateNewComment(
// response.errorCode is the id of the comment that was created on the server
// it is returned as a string, so we need to cast to an number to be compatable
parseInt(response.message),
response.value,
body,
user.profile,
commentBeingRepliedTo,
),
);
resetForm();
} else {
setError('Sorry, there was a problem posting your comment.');
}
}
};
10 changes: 3 additions & 7 deletions dotcom-rendering/src/components/Discussion/Comments.tsx
Original file line number Diff line number Diff line change
@@ -6,10 +6,10 @@ import {
textSans,
} from '@guardian/source-foundations';
import { useEffect, useState } from 'react';
import type { comment, reply } from '../../lib/discussionApi';
import { getPicks, initialiseApi } from '../../lib/discussionApi';
import type {
AdditionalHeadersType,
CommentResponse,
CommentType,
FilterOptions,
SignedInUser,
@@ -32,12 +32,8 @@ type Props = {
onPermalinkClick: (commentId: number) => void;
apiKey: string;
onRecommend?: (commentId: number) => Promise<boolean>;
onComment?: (shortUrl: string, body: string) => Promise<CommentResponse>;
onReply?: (
shortUrl: string,
body: string,
parentCommentId: number,
) => Promise<CommentResponse>;
onComment?: ReturnType<typeof comment>;
onReply?: ReturnType<typeof reply>;
onPreview?: (body: string) => Promise<string>;
onExpand: () => void;
idApiUrl: string;
Loading