Skip to content

Commit 87c330f

Browse files
authored
Fixing comment create and comment edit loading indicators. (#3765)
- This moves all the incorrect *internal* loading logic, above to the actual API calls. - It was a little complicated by the CommentNodes component, so the loading indicator also has to point to which specific comment is being edited (or the parent comment if its a comment creation). - Fixes #3666
1 parent 0829442 commit 87c330f

File tree

16 files changed

+279
-86
lines changed

16 files changed

+279
-86
lines changed

src/shared/components/comment/comment-form.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ interface CommentFormProps {
2929
myUserInfo: MyUserInfo | undefined;
3030
onCreateComment(form: CreateComment): void;
3131
onEditComment(form: EditComment): void;
32+
loading: boolean;
3233
}
3334

3435
export class CommentForm extends Component<CommentFormProps, any> {
@@ -71,6 +72,7 @@ export class CommentForm extends Component<CommentFormProps, any> {
7172
allLanguages={this.props.allLanguages}
7273
siteLanguages={this.props.siteLanguages}
7374
myUserInfo={this.props.myUserInfo}
75+
loading={this.props.loading}
7476
/>
7577
) : (
7678
<div className="alert alert-warning" role="alert">

src/shared/components/comment/comment-node.tsx

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { numToSI } from "@utils/helpers";
33
import { futureDaysToUnixTime } from "@utils/date";
44
import classNames from "classnames";
55
import { isBefore, parseISO, subMinutes } from "date-fns";
6-
import { Component, InfernoNode, InfernoMouseEvent, linkEvent } from "inferno";
6+
import { Component, InfernoMouseEvent, InfernoNode, linkEvent } from "inferno";
77
import { Link } from "inferno-router";
88
import {
99
AddAdmin,
@@ -64,10 +64,6 @@ type CommentNodeState = {
6464
collapsed: boolean;
6565
viewSource: boolean;
6666
showAdvanced: boolean;
67-
createOrEditCommentLoading: boolean;
68-
upvoteLoading: boolean;
69-
downvoteLoading: boolean;
70-
markLoading: boolean;
7167
fetchChildrenLoading: boolean;
7268
};
7369

@@ -87,6 +83,8 @@ type CommentNodeProps = {
8783
hideImages: boolean;
8884
myUserInfo: MyUserInfo | undefined;
8985
localSite: LocalSite;
86+
createLoading: CommentId | undefined;
87+
editLoading: CommentId | undefined;
9088
onSaveComment(form: SaveComment): void;
9189
onCreateComment(form: CreateComment): void;
9290
onEditComment(form: EditComment): void;
@@ -118,10 +116,6 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
118116
collapsed: this.initCommentCollapsed(),
119117
viewSource: false,
120118
showAdvanced: false,
121-
createOrEditCommentLoading: false,
122-
upvoteLoading: false,
123-
downvoteLoading: false,
124-
markLoading: false,
125119
fetchChildrenLoading: false,
126120
};
127121

@@ -131,9 +125,20 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
131125

132126
componentWillReceiveProps(
133127
nextProps: Readonly<{ children?: InfernoNode } & CommentNodeProps>,
134-
) {
135-
if (this.props.node.view !== nextProps.node.view) {
136-
this.setState({ markLoading: false });
128+
): void {
129+
if (
130+
this.props.editLoading === this.props.node.view.comment_view.comment.id &&
131+
this.props.editLoading !== nextProps.editLoading
132+
) {
133+
this.setState({ showEdit: false });
134+
}
135+
136+
if (
137+
this.props.createLoading ===
138+
this.props.node.view.comment_view.comment.id &&
139+
this.props.createLoading !== nextProps.createLoading
140+
) {
141+
this.setState({ showReply: false });
137142
}
138143
}
139144

@@ -264,6 +269,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
264269
myUserInfo={this.props.myUserInfo}
265270
onEditComment={form => handleEditComment(this, form)}
266271
onCreateComment={() => {}}
272+
loading={this.props.editLoading === id}
267273
/>
268274
)}
269275
{!this.state.showEdit && !this.state.collapsed && (
@@ -365,10 +371,13 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
365371
myUserInfo={this.props.myUserInfo}
366372
onCreateComment={form => handleCreateComment(this, form)}
367373
onEditComment={() => {}}
374+
loading={this.props.createLoading === id}
368375
/>
369376
)}
370377
{!this.state.collapsed && node.view.children.length > 0 && (
371378
<CommentNodes
379+
createLoading={this.props.createLoading}
380+
editLoading={this.props.editLoading}
372381
nodes={buildNodeChildren(this.props.node)}
373382
postCreatorId={this.postCreatorId}
374383
community={this.community}
@@ -488,12 +497,10 @@ function handleToggleViewSource(i: CommentNode) {
488497

489498
function handleCreateComment(i: CommentNode, form: CreateComment) {
490499
i.props.onCreateComment(form);
491-
i.setState({ showReply: false, showEdit: false });
492500
}
493501

494502
function handleEditComment(i: CommentNode, form: EditComment) {
495503
i.props.onEditComment(form);
496-
i.setState({ showReply: false, showEdit: false });
497504
}
498505

499506
function handleCommentCollapse(i: CommentNode, event: InfernoMouseEvent<any>) {

src/shared/components/comment/comment-nodes.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
BanPerson,
99
BlockCommunity,
1010
BlockPerson,
11+
CommentId,
1112
Community,
1213
CreateComment,
1314
CreateCommentLike,
@@ -59,6 +60,8 @@ interface CommentNodesProps {
5960
depth?: number;
6061
myUserInfo: MyUserInfo | undefined;
6162
localSite: LocalSite;
63+
createLoading: CommentId | undefined;
64+
editLoading: CommentId | undefined;
6265
onSaveComment(form: SaveComment): void;
6366
onCreateComment(form: CreateComment): void;
6467
onEditComment(form: EditComment): void;
@@ -116,6 +119,8 @@ export class CommentNodes extends Component<CommentNodesProps, any> {
116119
postLockedOrRemovedOrDeleted={
117120
this.props.postLockedOrRemovedOrDeleted
118121
}
122+
createLoading={this.props.createLoading}
123+
editLoading={this.props.editLoading}
119124
admins={this.props.admins}
120125
readCommentsAt={this.props.readCommentsAt}
121126
showContext={this.props.showContext}

src/shared/components/comment/comment-report.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ export class CommentReport extends Component<
9595
node={commentToFlatNode(comment_view)}
9696
admins={this.props.admins}
9797
viewType={"flat"}
98+
createLoading={undefined}
99+
editLoading={undefined}
98100
viewOnly
99101
showCommunity
100102
showContext={false}

src/shared/components/common/markdown-textarea.tsx

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ interface MarkdownTextAreaProps {
5555
siteLanguages?: LanguageId[];
5656
renderAsDiv?: boolean;
5757
myUserInfo: MyUserInfo | undefined;
58+
loading?: boolean;
5859
}
5960

6061
interface ImageUploadStatus {
@@ -67,8 +68,6 @@ interface MarkdownTextAreaState {
6768
languageId?: number;
6869
previewMode: boolean;
6970
imageUploadStatus?: ImageUploadStatus;
70-
loading: boolean;
71-
submitted: boolean;
7271
}
7372

7473
@tippyMixin
@@ -83,8 +82,6 @@ export class MarkdownTextArea extends Component<
8382
content: this.props.initialContent,
8483
languageId: this.props.initialLanguageId,
8584
previewMode: false,
86-
loading: false,
87-
submitted: false,
8885
};
8986

9087
constructor(props: any, context: any) {
@@ -132,8 +129,7 @@ export class MarkdownTextArea extends Component<
132129
message={I18NextService.i18n.t("block_leaving")}
133130
when={
134131
!this.props.hideNavigationWarnings &&
135-
((!!this.state.content && !this.state.submitted) ||
136-
this.state.loading)
132+
(!!this.state.content || this.props.loading)
137133
}
138134
/>
139135
<div className="mb-3 row">
@@ -271,7 +267,7 @@ export class MarkdownTextArea extends Component<
271267
className="btn btn-sm btn-secondary ms-2"
272268
disabled={this.isDisabled || !this.state.content}
273269
>
274-
{this.state.loading && <Spinner className="me-1" />}
270+
{this.props.loading && <Spinner className="me-1" />}
275271
{this.props.buttonTitle}
276272
</button>
277273
)}
@@ -578,9 +574,7 @@ export class MarkdownTextArea extends Component<
578574
handleSubmit(i: MarkdownTextArea, event: any) {
579575
event.preventDefault();
580576
if (i.state.content) {
581-
i.setState({ loading: true, submitted: true });
582577
i.props.onSubmit?.(i.state.content, i.state.languageId);
583-
i.setState({ loading: false });
584578
}
585579
}
586580

@@ -796,7 +790,7 @@ export class MarkdownTextArea extends Component<
796790

797791
get isDisabled() {
798792
return (
799-
this.state.loading ||
793+
this.props.loading ||
800794
this.props.disabled ||
801795
!!this.state.imageUploadStatus
802796
);

src/shared/components/community/community.tsx

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ import {
2121
bareRoutePush,
2222
} from "@utils/helpers";
2323
import { scrollMixin } from "../mixins/scroll-mixin";
24-
import type { QueryParams, StringBoolean } from "@utils/types";
25-
import { RouteDataResponse } from "@utils/types";
24+
import type { CommentIdAndRes, QueryParams, StringBoolean } from "@utils/types";
25+
import { commentLoading, RouteDataResponse } from "@utils/types";
2626
import {
2727
Component,
2828
InfernoNode,
@@ -134,6 +134,8 @@ interface State {
134134
communityRes: RequestState<GetCommunityResponse>;
135135
postsRes: RequestState<PagedResponse<PostView>>;
136136
commentsRes: RequestState<PagedResponse<CommentView>>;
137+
createCommentRes: CommentIdAndRes;
138+
editCommentRes: CommentIdAndRes;
137139
siteRes: GetSiteResponse;
138140
showSidebarMobile: boolean;
139141
isIsomorphic: boolean;
@@ -213,6 +215,8 @@ export class Community extends Component<CommunityRouteProps, State> {
213215
communityRes: EMPTY_REQUEST,
214216
postsRes: EMPTY_REQUEST,
215217
commentsRes: EMPTY_REQUEST,
218+
createCommentRes: { commentId: 0, res: EMPTY_REQUEST },
219+
editCommentRes: { commentId: 0, res: EMPTY_REQUEST },
216220
siteRes: this.isoData.siteRes,
217221
showSidebarMobile: false,
218222
isIsomorphic: false,
@@ -645,6 +649,8 @@ export class Community extends Component<CommunityRouteProps, State> {
645649
<CommentNodes
646650
nodes={commentsToFlatNodes(this.state.commentsRes.data.items)}
647651
viewType={"flat"}
652+
createLoading={commentLoading(this.state.createCommentRes)}
653+
editLoading={commentLoading(this.state.editCommentRes)}
648654
isTopLevel
649655
showContext
650656
showCommunity={false}
@@ -968,29 +974,43 @@ export class Community extends Component<CommunityRouteProps, State> {
968974
}
969975

970976
async handleCreateComment(form: CreateComment) {
971-
const createCommentRes = await HttpService.client.createComment(form);
972-
this.createAndUpdateComments(createCommentRes);
977+
this.setState({
978+
createCommentRes: {
979+
commentId: form.parent_id ?? 0,
980+
res: LOADING_REQUEST,
981+
},
982+
});
983+
const res = await HttpService.client.createComment(form);
984+
this.setState({
985+
createCommentRes: {
986+
commentId: form.parent_id ?? 0,
987+
res,
988+
},
989+
});
990+
this.createAndUpdateComments(res);
973991

974-
if (createCommentRes.state === "failed") {
975-
toast(
976-
I18NextService.i18n.t(createCommentRes.err.name as NoOptionI18nKeys),
977-
"danger",
978-
);
992+
if (res.state === "failed") {
993+
toast(I18NextService.i18n.t(res.err.name as NoOptionI18nKeys), "danger");
979994
}
980-
return createCommentRes;
995+
return res;
981996
}
982997

983998
async handleEditComment(form: EditComment) {
984-
const editCommentRes = await HttpService.client.editComment(form);
985-
this.findAndUpdateCommentEdit(editCommentRes);
999+
this.setState({
1000+
editCommentRes: { commentId: form.comment_id, res: LOADING_REQUEST },
1001+
});
9861002

987-
if (editCommentRes.state === "failed") {
988-
toast(
989-
I18NextService.i18n.t(editCommentRes.err.name as NoOptionI18nKeys),
990-
"danger",
991-
);
1003+
const res = await HttpService.client.editComment(form);
1004+
this.setState({
1005+
editCommentRes: { commentId: form.comment_id, res },
1006+
});
1007+
1008+
this.findAndUpdateCommentEdit(res);
1009+
1010+
if (res.state === "failed") {
1011+
toast(I18NextService.i18n.t(res.err.name as NoOptionI18nKeys), "danger");
9921012
}
993-
return editCommentRes;
1013+
return res;
9941014
}
9951015

9961016
async handleDeleteComment(form: DeleteComment) {

0 commit comments

Comments
 (0)