diff --git a/apps/meteor/app/livechat/imports/server/rest/visitors.ts b/apps/meteor/app/livechat/imports/server/rest/visitors.ts index 43dff642c4b72..1409b30ab0405 100644 --- a/apps/meteor/app/livechat/imports/server/rest/visitors.ts +++ b/apps/meteor/app/livechat/imports/server/rest/visitors.ts @@ -163,6 +163,7 @@ API.v1.addRoute( async get() { const { offset, count } = this.getPaginationItems(); const { sort } = this.parseJsonQuery(); + const { searchTerm } = this.requestParams(); const room = LivechatRooms.findOneById(this.urlParams.rid); @@ -174,7 +175,7 @@ API.v1.addRoute( throw new Error('not-allowed'); } - const { cursor, totalCount } = Messages.findLivechatClosedMessages(this.urlParams.rid, { + const { cursor, totalCount } = Messages.findLivechatClosedMessages(this.urlParams.rid, searchTerm, { sort: sort || { ts: -1 }, skip: offset, limit: count, diff --git a/apps/meteor/server/models/raw/Messages.ts b/apps/meteor/server/models/raw/Messages.ts index e5e587088fa4e..74a29de0e706d 100644 --- a/apps/meteor/server/models/raw/Messages.ts +++ b/apps/meteor/server/models/raw/Messages.ts @@ -221,11 +221,12 @@ export class MessagesRaw extends BaseRaw implements IMessagesModel { return this.col.aggregate(params).toArray(); } - findLivechatClosedMessages(rid: IRoom['_id'], options: FindOptions): FindPaginated> { + findLivechatClosedMessages(rid: IRoom['_id'], searchTerm?: string, options?: FindOptions): FindPaginated> { return this.findPaginated( { rid, $or: [{ t: { $exists: false } }, { t: 'livechat-close' }], + ...(searchTerm && { msg: new RegExp(escapeRegExp(searchTerm), 'ig') }), }, options, ); diff --git a/apps/meteor/tests/end-to-end/api/livechat/00-rooms.ts b/apps/meteor/tests/end-to-end/api/livechat/00-rooms.ts index f633fd7a538ff..61ee8674aaed5 100644 --- a/apps/meteor/tests/end-to-end/api/livechat/00-rooms.ts +++ b/apps/meteor/tests/end-to-end/api/livechat/00-rooms.ts @@ -687,6 +687,63 @@ describe('LIVECHAT - rooms', function () { expect(body.total).to.be.an('number').equal(1); expect(body.messages[0]).to.have.property('msg', 'Hello'); }); + it('should return the messages of the room matching by searchTerm', async () => { + const visitor = await createVisitor(); + const room = await createLivechatRoom(visitor.token); + await sendMessage(room._id, 'Hello', visitor.token); + await sendMessage(room._id, 'Random', visitor.token); + + const { body } = await request + .get(api(`livechat/${room._id}/messages`)) + .query({ searchTerm: 'Ran' }) + .set(credentials) + .expect('Content-Type', 'application/json') + .expect(200); + + expect(body).to.have.property('success', true); + expect(body).to.have.property('messages'); + expect(body.messages).to.be.an('array'); + expect(body.total).to.be.an('number').equal(1); + expect(body.messages[0]).to.have.property('msg', 'Random'); + }); + it('should return the messages of the room matching by partial searchTerm', async () => { + const visitor = await createVisitor(); + const room = await createLivechatRoom(visitor.token); + await sendMessage(room._id, 'Hello', visitor.token); + await sendMessage(room._id, 'Random', visitor.token); + + const { body } = await request + .get(api(`livechat/${room._id}/messages`)) + .query({ searchTerm: 'ndo' }) + .set(credentials) + .expect('Content-Type', 'application/json') + .expect(200); + + expect(body).to.have.property('success', true); + expect(body).to.have.property('messages'); + expect(body.messages).to.be.an('array'); + expect(body.total).to.be.an('number').equal(1); + expect(body.messages[0]).to.have.property('msg', 'Random'); + }); + it('should return everything when searchTerm is ""', async () => { + const visitor = await createVisitor(); + const room = await createLivechatRoom(visitor.token); + await sendMessage(room._id, 'Hello', visitor.token); + await sendMessage(room._id, 'Random', visitor.token); + + const { body } = await request + .get(api(`livechat/${room._id}/messages`)) + .query({ searchTerm: '' }) + .set(credentials) + .expect('Content-Type', 'application/json') + .expect(200); + + expect(body).to.have.property('success', true); + expect(body).to.have.property('messages'); + expect(body.messages).to.be.an('array'); + expect(body.messages).to.be.an('array').with.lengthOf.greaterThan(1); + expect(body.messages[0]).to.have.property('msg'); + }); }); describe('[GET] livechat/message/:_id', () => { diff --git a/packages/model-typings/src/models/IMessagesModel.ts b/packages/model-typings/src/models/IMessagesModel.ts index 7550ad37989de..c9d925165b6a3 100644 --- a/packages/model-typings/src/models/IMessagesModel.ts +++ b/packages/model-typings/src/models/IMessagesModel.ts @@ -34,7 +34,7 @@ export interface IMessagesModel extends IBaseModel { getTotalOfMessagesSentByDate(params: { start: Date; end: Date; options?: any }): Promise; - findLivechatClosedMessages(rid: IRoom['_id'], options: FindOptions): FindPaginated>; + findLivechatClosedMessages(rid: IRoom['_id'], searchTerm?: string, options?: FindOptions): FindPaginated>; countRoomsWithStarredMessages(options: AggregateOptions): Promise; diff --git a/packages/rest-typings/src/v1/omnichannel.ts b/packages/rest-typings/src/v1/omnichannel.ts index 94747ce3292d4..b940cc4f729db 100644 --- a/packages/rest-typings/src/v1/omnichannel.ts +++ b/packages/rest-typings/src/v1/omnichannel.ts @@ -970,7 +970,7 @@ const LivechatRoomsSchema = { export const isLivechatRoomsProps = ajv.compile(LivechatRoomsSchema); -type LivechatRidMessagesProps = PaginatedRequest; +type LivechatRidMessagesProps = PaginatedRequest<{ searchTerm?: string }>; const LivechatRidMessagesSchema = { type: 'object', @@ -987,6 +987,10 @@ const LivechatRidMessagesSchema = { type: 'string', nullable: true, }, + searchTerm: { + type: 'string', + nullable: true, + }, }, required: [], additionalProperties: false,