Files
talk/src/core/client/stream/mutations/CreateCommentMutation.ts
T
KiwiandGitHub 37959f9398 [CORL-130] Handle non-visible comment status (#2213)
* feat: support blue color in message

* feat: Show message when comment is in review

* feat: handle non-visible comment status

* test: add feature test for handling invisible comment status

* fix: apply review

* chore: better comment :-)

* Update isVisible.ts
2019-03-05 19:15:33 +01:00

180 lines
4.5 KiB
TypeScript

import { graphql } from "react-relay";
import {
ConnectionHandler,
Environment,
RecordProxy,
RecordSourceSelectorProxy,
} from "relay-runtime";
import { getMe } from "talk-framework/helpers";
import { TalkContext } from "talk-framework/lib/bootstrap";
import {
commitMutationPromiseNormalized,
createMutationContainer,
MutationInput,
MutationResponsePromise,
} from "talk-framework/lib/relay";
import { CreateCommentMutation as MutationTypes } from "talk-stream/__generated__/CreateCommentMutation.graphql";
import {
incrementStoryCommentCounts,
isRolePriviledged,
isVisible,
prependCommentEdgeToProfile,
} from "../helpers";
export type CreateCommentInput = MutationInput<MutationTypes>;
function sharedUpdater(
environment: Environment,
store: RecordSourceSelectorProxy,
input: CreateCommentInput
) {
const commentEdge = store
.getRootField("createComment")!
.getLinkedRecord("edge")!;
const status = commentEdge.getLinkedRecord("node")!.getValue("status");
// If comment is not visible, we don't need to add it.
if (!isVisible(status)) {
return;
}
incrementStoryCommentCounts(store, input.storyID);
prependCommentEdgeToProfile(environment, store, commentEdge);
addCommentToStory(store, input, commentEdge);
}
/**
* update integrates new comment into the CommentConnection.
*/
function addCommentToStory(
store: RecordSourceSelectorProxy,
input: CreateCommentInput,
commentEdge: RecordProxy
) {
// Get stream proxy.
const streamProxy = store.get(input.storyID);
const connectionKey = "Stream_comments";
const filters = { orderBy: "CREATED_AT_DESC" };
if (streamProxy) {
const con = ConnectionHandler.getConnection(
streamProxy,
connectionKey,
filters
);
if (con) {
ConnectionHandler.insertEdgeBefore(con, commentEdge);
}
}
}
/** These are needed to be included when querying for the stream. */
// tslint:disable-next-line:no-unused-expression
graphql`
fragment CreateCommentMutation_story on Story {
moderation
}
fragment CreateCommentMutation_me on User {
role
}
`;
/** end */
const mutation = graphql`
mutation CreateCommentMutation($input: CreateCommentInput!) {
createComment(input: $input) {
edge {
cursor
node {
...StreamContainer_comment @relay(mask: false)
status
}
}
clientMutationId
}
}
`;
let clientMutationId = 0;
function commit(
environment: Environment,
input: CreateCommentInput,
{ uuidGenerator, relayEnvironment }: TalkContext
) {
const me = getMe(environment)!;
const currentDate = new Date().toISOString();
const id = uuidGenerator();
const story = relayEnvironment
.getStore()
.getSource()
.get(input.storyID);
if (!story || !story.moderation) {
throw new Error("Moderation mode of the story was not included");
}
// TODO: Generate and use schema types.
const expectPremoderation =
!isRolePriviledged(me.role) && story.moderation === "PRE";
return commitMutationPromiseNormalized<MutationTypes>(environment, {
mutation,
variables: {
input: {
storyID: input.storyID,
body: input.body,
clientMutationId: clientMutationId.toString(),
},
},
optimisticResponse: {
createComment: {
edge: {
cursor: currentDate,
node: {
id,
createdAt: currentDate,
status: "NONE",
author: {
id: me.id,
username: me.username,
},
body: input.body,
editing: {
editableUntil: new Date(Date.now() + 10000),
},
actionCounts: {
reaction: {
total: 0,
},
},
},
},
clientMutationId: (clientMutationId++).toString(),
},
} as any, // TODO: (cvle) generated types should contain one for the optimistic response.
optimisticUpdater: store => {
// Skip optimistic update if comment is probably premoderated.
if (expectPremoderation) {
return;
}
sharedUpdater(environment, store, input);
store.get(id)!.setValue(true, "pending");
},
updater: store => {
sharedUpdater(environment, store, input);
},
});
}
export const withCreateCommentMutation = createMutationContainer(
"createComment",
commit
);
export type CreateCommentMutation = (
input: CreateCommentInput
) => MutationResponsePromise<MutationTypes, "createComment">;