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

feat: implemented Reply functionality for chat #2584

Merged
merged 52 commits into from
Oct 21, 2024
Merged
Show file tree
Hide file tree
Changes from 51 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
a8c02f8
Updated subscriptions and added mutations for directChat and groupChat
disha1202 Jul 15, 2024
fe6907d
Update index.ts
disha1202 Jul 16, 2024
3a9799d
Update messageSentToDirectChat.ts
disha1202 Jul 16, 2024
2fa65b1
Update createDirectChat.spec.ts
disha1202 Jul 16, 2024
f68bb01
Update createDirectChat.spec.ts
disha1202 Jul 16, 2024
f7089b9
fix: linting errors
disha1202 Jul 16, 2024
2fe5353
fix: lint errors
disha1202 Jul 16, 2024
7e31c14
fix: formatting issues
disha1202 Jul 16, 2024
0bf28a2
Merge branch 'develop' into chat-feature
disha1202 Jul 16, 2024
9c44ea4
fix: formatting issues
disha1202 Jul 16, 2024
fa5f6ec
fix: test cases
disha1202 Jul 16, 2024
3db8381
fix test cases
disha1202 Jul 16, 2024
a1379bf
Update messageSentToDirectChat.ts
disha1202 Jul 18, 2024
bd98a6b
Update messageSentToDirectChat.ts
disha1202 Jul 18, 2024
7ec1773
added test cases for query directChatById
Jul 18, 2024
3781ede
Update directChatById.spec.ts
disha1202 Jul 18, 2024
8aaf5f3
Update directChatById.spec.ts
disha1202 Jul 18, 2024
e83657d
Update directChatById.spec.ts
disha1202 Jul 18, 2024
23a9676
Added test cases
disha1202 Jul 18, 2024
9576d4a
fix: test cases
disha1202 Jul 18, 2024
c2af22d
fix: tests
disha1202 Jul 18, 2024
ad48619
fix test cases
disha1202 Jul 18, 2024
77c7fde
Merge branch 'chat-feature' of https://github.com/disha1202/talawa-ap…
disha1202 Jul 18, 2024
d18843a
added support to reply to direct chat and group chat
disha1202 Jul 24, 2024
cf27ca6
Merge branch 'develop' of https://github.com/disha1202/talawa-api int…
disha1202 Jul 24, 2024
8469653
fix: test cases
disha1202 Jul 24, 2024
f936adc
removed console logs
disha1202 Jul 28, 2024
babf1c0
Merge branch 'develop' into reply-functionality
disha1202 Jul 28, 2024
c84f33a
Merge branch 'develop' into reply-functionality
disha1202 Jul 30, 2024
ef2d45d
Merge branch 'develop' into reply-functionality
disha1202 Aug 18, 2024
a2ccfb0
Removed unwanted code
disha1202 Aug 18, 2024
52165f1
Merge branch 'reply-functionality' of https://github.com/disha1202/ta…
disha1202 Aug 18, 2024
369a81d
Merge branch 'develop' into reply-functionality
disha1202 Aug 21, 2024
979bf37
Merge branch 'develop' into reply-functionality
disha1202 Aug 21, 2024
dd9120f
Merge branch 'develop' into reply-functionality
disha1202 Aug 23, 2024
08a6fed
Merge branch 'develop' into reply-functionality
disha1202 Aug 24, 2024
b6fa93e
added test cases
disha1202 Aug 24, 2024
0e0b1d3
Merge branch 'reply-functionality' of https://github.com/disha1202/ta…
disha1202 Aug 24, 2024
4f9ea48
removed unwanted comments
disha1202 Aug 24, 2024
7baed1d
Merge branch 'develop' into reply-functionality
disha1202 Sep 1, 2024
b3032db
Merge branch 'develop' into reply-functionality
disha1202 Sep 22, 2024
d0b54f6
Merge branch 'develop' into reply-functionality
disha1202 Oct 6, 2024
670f79e
Merge branch 'develop' of https://github.com/PalisadoesFoundation/tal…
disha1202 Oct 7, 2024
b66d394
Merge branch 'reply-functionality' of https://github.com/disha1202/ta…
disha1202 Oct 7, 2024
03a26d8
fix: linting errors'
disha1202 Oct 7, 2024
45f663f
Merge branch 'develop' into reply-functionality
disha1202 Oct 13, 2024
eb66ac0
fix: eslint errors
disha1202 Oct 13, 2024
da87a78
fix: removed unused imports
disha1202 Oct 13, 2024
08ad877
Merge branch 'develop' into reply-functionality
disha1202 Oct 16, 2024
6d9ca1f
Update eslint.config.mjs
disha1202 Oct 16, 2024
fad02e3
fix: formatting issues
disha1202 Oct 16, 2024
66719d5
Merge branch 'develop' into reply-functionality
DMills27 Oct 21, 2024
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
1 change: 0 additions & 1 deletion eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ export default [
patterns: ["**/src/**"],
},
],

"import/no-duplicates": "error",
"tsdoc/syntax": "error",
"@typescript-eslint/ban-ts-comment": "error",
Expand Down
8 changes: 4 additions & 4 deletions schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ input ActionItemWhereInput {
assigneeName: String
categoryName: String
event_id: ID
is_active: Boolean
is_completed: Boolean
}

Expand Down Expand Up @@ -567,6 +566,7 @@ type DirectChatMessage {
directChatMessageBelongsTo: DirectChat!
messageContent: String!
receiver: User!
replyTo: DirectChatMessage
sender: User!
updatedAt: DateTime!
}
Expand Down Expand Up @@ -950,6 +950,7 @@ type GroupChatMessage {
createdAt: DateTime!
groupChatMessageBelongsTo: GroupChat!
messageContent: String!
replyTo: GroupChatMessage
sender: User!
updatedAt: DateTime!
}
Expand Down Expand Up @@ -1150,7 +1151,6 @@ type Mutation {
removeEventVolunteer(id: ID!): EventVolunteer!
removeEventVolunteerGroup(id: ID!): EventVolunteerGroup!
removeFundraisingCampaignPledge(id: ID!): FundraisingCampaignPledge!
removeGroupChat(chatId: ID!): GroupChat!
removeMember(data: UserAndOrganizationInput!): Organization!
removeOrganization(id: ID!): UserData!
removeOrganizationCustomField(customFieldId: ID!, organizationId: ID!): OrganizationCustomField!
Expand All @@ -1167,8 +1167,8 @@ type Mutation {
revokeRefreshTokenForUser: Boolean!
saveFcmToken(token: String): Boolean!
sendMembershipRequest(organizationId: ID!): MembershipRequest!
sendMessageToDirectChat(chatId: ID!, messageContent: String!): DirectChatMessage!
sendMessageToGroupChat(chatId: ID!, messageContent: String!): GroupChatMessage!
sendMessageToDirectChat(chatId: ID!, messageContent: String!, replyTo: ID): DirectChatMessage!
sendMessageToGroupChat(chatId: ID!, messageContent: String!, replyTo: ID): GroupChatMessage!
signUp(data: UserInput!, file: String): AuthData!
togglePostPin(id: ID!, title: String): Post!
unassignUserTag(input: ToggleUserTagAssignInput!): User
Expand Down
7 changes: 7 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@ export const CHAT_NOT_FOUND_ERROR = Object.freeze({
PARAM: "chat",
});

export const MESSAGE_NOT_FOUND_ERROR = Object.freeze({
DESC: "Message not found",
CODE: "message.notFound",
MESSAGE: "message.notFound",
PARAM: "message",
});

export const COMMUNITY_NOT_FOUND_ERROR = Object.freeze({
DESC: "Community not found",
CODE: "community.notFound",
Expand Down
6 changes: 6 additions & 0 deletions src/models/DirectChatMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export interface InterfaceDirectChatMessage {
directChatMessageBelongsTo: PopulatedDoc<InterfaceDirectChat & Document>;
sender: PopulatedDoc<InterfaceUser & Document>;
receiver: PopulatedDoc<InterfaceUser & Document>;
replyTo: PopulatedDoc<InterfaceDirectChatMessage & Document>;
messageContent: string;
status: string;
createdAt: Date;
Expand Down Expand Up @@ -45,6 +46,11 @@ const directChatMessageSchema = new Schema(
ref: "User",
required: true,
},
replyTo: {
type: Schema.Types.ObjectId,
ref: "DirectChatMessage",
required: false,
},
messageContent: {
type: String,
required: true,
Expand Down
6 changes: 6 additions & 0 deletions src/models/GroupChatMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export interface InterfaceGroupChatMessage {
sender: PopulatedDoc<InterfaceUser & Document>;
createdAt: Date;
updatedAt: Date;
replyTo: PopulatedDoc<InterfaceGroupChatMessage & Document>;
messageContent: string;
status: string;
}
Expand All @@ -39,6 +40,11 @@ const groupChatMessageSchema = new Schema(
ref: "User",
required: true,
},
replyTo: {
type: Schema.Types.ObjectId,
ref: "GroupChatMessage",
required: false,
},
messageContent: {
type: String,
required: true,
Expand Down
2 changes: 2 additions & 0 deletions src/resolvers/DirectChatMessage/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import type { DirectChatMessageResolvers } from "../../types/generatedGraphQLTypes";
import { directChatMessageBelongsTo } from "./directChatMessageBelongsTo";
import { receiver } from "./receiver";
import { replyTo } from "./replyTo";
import { sender } from "./sender";

export const DirectChatMessage: DirectChatMessageResolvers = {
directChatMessageBelongsTo,
receiver,
sender,
replyTo,
};
30 changes: 30 additions & 0 deletions src/resolvers/DirectChatMessage/replyTo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import type { DirectChatMessageResolvers } from "../../types/generatedGraphQLTypes";
import { DirectChatMessage } from "../../models";
import { MESSAGE_NOT_FOUND_ERROR } from "../../constants";
import { errors, requestContext } from "../../libraries";
/**
* This resolver function will fetch and return the reply to message of the Direct chat from the database.
* @param parent - An object that is the return value of the resolver for this field's parent.
* @returns An `object` that contains User's data.
*/
export const replyTo: DirectChatMessageResolvers["replyTo"] = async (
parent,
) => {
if (parent.replyTo) {
const result = await DirectChatMessage.findOne({
_id: parent.replyTo,
}).lean();

if (result) {
return result;
} else {
throw new errors.NotFoundError(
requestContext.translate(MESSAGE_NOT_FOUND_ERROR.MESSAGE),
MESSAGE_NOT_FOUND_ERROR.CODE,
MESSAGE_NOT_FOUND_ERROR.PARAM,
);
}
} else {
return null;
}
};
2 changes: 2 additions & 0 deletions src/resolvers/GroupChatMessage/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import type { GroupChatMessageResolvers } from "../../types/generatedGraphQLTypes";
import { groupChatMessageBelongsTo } from "./groupChatMessageBelongsTo";
import { replyTo } from "./replyTo";
import { sender } from "./sender";

export const GroupChatMessage: GroupChatMessageResolvers = {
groupChatMessageBelongsTo,
sender,
replyTo,
};
28 changes: 28 additions & 0 deletions src/resolvers/GroupChatMessage/replyTo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import type { GroupChatMessageResolvers } from "../../types/generatedGraphQLTypes";
import { GroupChatMessage } from "../../models";
import { MESSAGE_NOT_FOUND_ERROR } from "../../constants";
import { errors, requestContext } from "../../libraries";
/**
* This resolver function will fetch and return the replied-to message in a group chat from the database.
* @param parent - An object that is the return value of the resolver for this field's parent.
* @returns An `object` that contains User's data.
*/
export const replyTo: GroupChatMessageResolvers["replyTo"] = async (parent) => {
if (parent.replyTo) {
const result = await GroupChatMessage.findOne({
_id: parent.replyTo,
}).lean();

if (result) {
return result;
} else {
throw new errors.NotFoundError(
requestContext.translate(MESSAGE_NOT_FOUND_ERROR.MESSAGE),
MESSAGE_NOT_FOUND_ERROR.CODE,
MESSAGE_NOT_FOUND_ERROR.PARAM,
);
}
} else {
return null;
}
};
2 changes: 0 additions & 2 deletions src/resolvers/Mutation/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ import { removeEventAttendee } from "./removeEventAttendee";
import { removeEventVolunteer } from "./removeEventVolunteer";
import { removeEventVolunteerGroup } from "./removeEventVolunteerGroup";
import { removeFundraisingCampaignPledge } from "./removeFundraisingCampaingPledge";
import { removeGroupChat } from "./removeGroupChat";
import { removeMember } from "./removeMember";
import { removeOrganization } from "./removeOrganization";
import { removeOrganizationCustomField } from "./removeOrganizationCustomField";
Expand Down Expand Up @@ -199,7 +198,6 @@ export const Mutation: MutationResolvers = {
removeEventAttendee,
removeEventVolunteer,
removeEventVolunteerGroup,
removeGroupChat,
removeMember,
removeOrganization,
removeOrganizationCustomField,
Expand Down
80 changes: 0 additions & 80 deletions src/resolvers/Mutation/removeGroupChat.ts

This file was deleted.

1 change: 1 addition & 0 deletions src/resolvers/Mutation/sendMessageToDirectChat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export const sendMessageToDirectChat: MutationResolvers["sendMessageToDirectChat
sender: context.userId,
receiver: directChat.users[receiverIndex],
messageContent: args.messageContent,
replyTo: args.replyTo,
});

// add createdDirectChatMessage to directChat
Expand Down
1 change: 1 addition & 0 deletions src/resolvers/Mutation/sendMessageToGroupChat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export const sendMessageToGroupChat: MutationResolvers["sendMessageToGroupChat"]
sender: context.userId,
createdAt: new Date(),
messageContent: args.messageContent,
replyTo: args.replyTo,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider adding validation for the replyTo field.

While the implementation of the reply functionality is correct, it might benefit from additional validation to ensure data integrity and prevent potential misuse. Consider adding checks to verify that:

  1. The replyTo message exists.
  2. The replyTo message belongs to the same group chat.

This could be implemented before creating the new message, for example:

if (args.replyTo) {
  const replyToMessage = await GroupChatMessage.findOne({
    _id: args.replyTo,
    groupChatMessageBelongsTo: groupChat._id
  });
  if (!replyToMessage) {
    throw new errors.NotFoundError(
      requestContext.translate(REPLY_TO_MESSAGE_NOT_FOUND_ERROR.MESSAGE),
      REPLY_TO_MESSAGE_NOT_FOUND_ERROR.CODE,
      REPLY_TO_MESSAGE_NOT_FOUND_ERROR.PARAM
    );
  }
}

This additional check would ensure that users can only reply to existing messages within the same group chat.

});

// add createdGroupChatMessage to groupChat
Expand Down
4 changes: 2 additions & 2 deletions src/typeDefs/mutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,6 @@ export const mutations = gql`

removeEventVolunteerGroup(id: ID!): EventVolunteerGroup! @auth

removeGroupChat(chatId: ID!): GroupChat! @auth

removeMember(data: UserAndOrganizationInput!): Organization! @auth

removeOrganization(id: ID!): UserData! @auth @role(requires: SUPERADMIN)
Expand Down Expand Up @@ -249,11 +247,13 @@ export const mutations = gql`
sendMessageToDirectChat(
chatId: ID!
messageContent: String!
replyTo: ID
): DirectChatMessage! @auth

sendMessageToGroupChat(
chatId: ID!
messageContent: String!
replyTo: ID
): GroupChatMessage! @auth

signUp(data: UserInput!, file: String): AuthData!
Expand Down
2 changes: 2 additions & 0 deletions src/typeDefs/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ export const types = gql`
directChatMessageBelongsTo: DirectChat!
sender: User!
receiver: User!
replyTo: DirectChatMessage
createdAt: DateTime!
updatedAt: DateTime!
messageContent: String!
Expand Down Expand Up @@ -388,6 +389,7 @@ export const types = gql`
_id: ID!
groupChatMessageBelongsTo: GroupChat!
sender: User!
replyTo: GroupChatMessage
createdAt: DateTime!
updatedAt: DateTime!
messageContent: String!
Expand Down
Loading
Loading