From b51d9f7728d6eecacac0e01f95ddc5aeb285c584 Mon Sep 17 00:00:00 2001 From: Marcos Spessatto Defendi Date: Wed, 13 Nov 2019 17:35:57 -0300 Subject: [PATCH] [IMPROVE] Replace livechat:externalMessages publication by REST (#15643) * Replace livechat:externalMessages publication by REST * Fix lint * Add pagination to livechat external messages * Add index and remove obsolete collection --- app/livechat/client/index.js | 1 - .../views/app/tabbar/externalSearch.html | 15 ++++--- .../client/views/app/tabbar/externalSearch.js | 44 ++++++++++++++++--- app/livechat/imports/server/rest/messages.js | 26 +++++++++++ app/livechat/lib/LivechatExternalMessage.js | 22 ---------- app/livechat/server/api.js | 1 + app/livechat/server/api/lib/messages.js | 20 +++++++++ app/livechat/server/hooks/externalMessage.js | 2 +- app/livechat/server/index.js | 1 - .../server/publications/externalMessages.js | 3 +- app/models/server/index.js | 2 + .../server/models/LivechatExternalMessages.js | 18 ++++++++ .../server/raw/LivechatExternalMessages.js | 9 ++++ app/models/server/raw/index.js | 3 ++ tests/end-to-end/api/livechat/messages.js | 29 ++++++++++++ 15 files changed, 157 insertions(+), 39 deletions(-) create mode 100644 app/livechat/imports/server/rest/messages.js delete mode 100644 app/livechat/lib/LivechatExternalMessage.js create mode 100644 app/livechat/server/api/lib/messages.js create mode 100644 app/models/server/models/LivechatExternalMessages.js create mode 100644 app/models/server/raw/LivechatExternalMessages.js create mode 100644 tests/end-to-end/api/livechat/messages.js diff --git a/app/livechat/client/index.js b/app/livechat/client/index.js index 4e0a0c603c3..bc8c68d9676 100644 --- a/app/livechat/client/index.js +++ b/app/livechat/client/index.js @@ -1,5 +1,4 @@ import '../lib/messageTypes'; -import '../lib/LivechatExternalMessage'; import './roomType'; import './route'; import './ui'; diff --git a/app/livechat/client/views/app/tabbar/externalSearch.html b/app/livechat/client/views/app/tabbar/externalSearch.html index b0f1dd3ed30..a08f388c9d8 100644 --- a/app/livechat/client/views/app/tabbar/externalSearch.html +++ b/app/livechat/client/views/app/tabbar/externalSearch.html @@ -3,13 +3,16 @@

{{_ "Knowledge_Base"}}

-
+
{{#each messages}} -
- - {{msg}} -
+
+ + {{msg}} +
{{/each}} + {{#if hasMore}} + + {{/if}}
- + \ No newline at end of file diff --git a/app/livechat/client/views/app/tabbar/externalSearch.js b/app/livechat/client/views/app/tabbar/externalSearch.js index e98b788f622..2bea37e8c91 100644 --- a/app/livechat/client/views/app/tabbar/externalSearch.js +++ b/app/livechat/client/views/app/tabbar/externalSearch.js @@ -1,27 +1,57 @@ import { Template } from 'meteor/templating'; +import { ReactiveVar } from 'meteor/reactive-var'; -import { LivechatExternalMessage } from '../../../../lib/LivechatExternalMessage'; import './externalSearch.html'; +import { APIClient } from '../../../../../utils/client'; + +const MESSAGES_COUNT = 50; Template.externalSearch.helpers({ messages() { - return LivechatExternalMessage.findByRoomId(this.rid, { ts: 1 }); + return Template.instance().externalMessages.get(); + }, + hasMore() { + const instance = Template.instance(); + const externalMessages = instance.externalMessages.get(); + return instance.total.get() > externalMessages.length; }, }); Template.externalSearch.events({ 'click button.pick-message'(event, instance) { event.preventDefault(); - - $(`#chat-window-${ instance.roomId } .input-message`).val(this.msg).focus(); + $(`#chat-window-${ instance.roomId } .js-input-message`).val(this.msg).focus(); + }, + 'click .load-more'(e, t) { + e.preventDefault(); + e.stopPropagation(); + t.offset.set(t.offset.get() + MESSAGES_COUNT); + }, + 'click .load-more-livechat-external-messages'(event, instance) { + return instance.offset.set(instance.offset.get() + MESSAGES_COUNT); }, }); Template.externalSearch.onCreated(function() { this.roomId = null; - // console.log('externalSearch.this ->',this); - this.autorun(() => { + this.externalMessages = new ReactiveVar([]); + this.offset = new ReactiveVar(0); + this.ready = new ReactiveVar(true); + this.total = new ReactiveVar(0); + + this.autorun(async () => { + this.ready.set(false); + const offset = this.offset.get(); this.roomId = Template.currentData().rid; - this.subscribe('livechat:externalMessages', Template.currentData().rid); + if (this.roomId) { + const { messages, total } = await APIClient.v1.get(`livechat/messages.external/${ this.roomId }?count=${ MESSAGES_COUNT }&offset=${ offset }`); + this.total.set(total); + if (offset === 0) { + this.externalMessages.set(messages); + } else { + this.externalMessages.set(this.externalMessages.get().concat(messages)); + } + } + this.ready.set(true); }); }); diff --git a/app/livechat/imports/server/rest/messages.js b/app/livechat/imports/server/rest/messages.js new file mode 100644 index 00000000000..a40557231b5 --- /dev/null +++ b/app/livechat/imports/server/rest/messages.js @@ -0,0 +1,26 @@ + +import { check } from 'meteor/check'; + +import { API } from '../../../../api'; +import { findExternalMessages } from '../../../server/api/lib/messages'; + +API.v1.addRoute('livechat/messages.external/:roomId', { authRequired: true }, { + get() { + check(this.urlParams, { + roomId: String, + }); + const { offset, count } = this.getPaginationItems(); + const { sort } = this.parseJsonQuery(); + + const departments = Promise.await(findExternalMessages({ + roomId: this.urlParams.roomId, + pagination: { + offset, + count, + sort, + }, + })); + + return API.v1.success(departments); + }, +}); diff --git a/app/livechat/lib/LivechatExternalMessage.js b/app/livechat/lib/LivechatExternalMessage.js deleted file mode 100644 index cf8eedae67c..00000000000 --- a/app/livechat/lib/LivechatExternalMessage.js +++ /dev/null @@ -1,22 +0,0 @@ -import { Meteor } from 'meteor/meteor'; - -import { Base } from '../../models'; - -class LivechatExternalMessageClass extends Base { - constructor() { - super('livechat_external_message'); - - if (Meteor.isClient) { - this._initModel('livechat_external_message'); - } - } - - // FIND - findByRoomId(roomId, sort = { ts: -1 }) { - const query = { rid: roomId }; - - return this.find(query, { sort }); - } -} - -export const LivechatExternalMessage = new LivechatExternalMessageClass(); diff --git a/app/livechat/server/api.js b/app/livechat/server/api.js index 95cd633247c..daa85569a53 100644 --- a/app/livechat/server/api.js +++ b/app/livechat/server/api.js @@ -9,4 +9,5 @@ import '../imports/server/rest/rooms.js'; import '../imports/server/rest/appearance.js'; import '../imports/server/rest/triggers.js'; import '../imports/server/rest/integrations.js'; +import '../imports/server/rest/messages.js'; import '../imports/server/rest/visitors.js'; diff --git a/app/livechat/server/api/lib/messages.js b/app/livechat/server/api/lib/messages.js new file mode 100644 index 00000000000..0260d195a6f --- /dev/null +++ b/app/livechat/server/api/lib/messages.js @@ -0,0 +1,20 @@ +import { LivechatExternalMessage } from '../../../../models/server/raw'; + +export async function findExternalMessages({ roomId, pagination: { offset, count, sort } }) { + const cursor = await LivechatExternalMessage.findByRoomId(roomId, { + sort: sort || { ts: -1 }, + skip: offset, + limit: count, + }); + + const total = await cursor.count(); + + const messages = await cursor.toArray(); + + return { + messages, + count: messages.length, + offset, + total, + }; +} diff --git a/app/livechat/server/hooks/externalMessage.js b/app/livechat/server/hooks/externalMessage.js index 1e1f4ee242c..41bb98396fa 100644 --- a/app/livechat/server/hooks/externalMessage.js +++ b/app/livechat/server/hooks/externalMessage.js @@ -4,7 +4,7 @@ import _ from 'underscore'; import { settings } from '../../../settings'; import { callbacks } from '../../../callbacks'; import { SystemLogger } from '../../../logger'; -import { LivechatExternalMessage } from '../../lib/LivechatExternalMessage'; +import { LivechatExternalMessage } from '../../../models/server'; import { normalizeMessageFileUpload } from '../../../utils/server/functions/normalizeMessageFileUpload'; let knowledgeEnabled = false; diff --git a/app/livechat/server/index.js b/app/livechat/server/index.js index 52e30d9701e..458b660e15a 100644 --- a/app/livechat/server/index.js +++ b/app/livechat/server/index.js @@ -67,7 +67,6 @@ import './methods/saveOfficeHours'; import './methods/sendTranscript'; import './methods/getFirstRoomMessage'; import './methods/getTagsList'; -import '../lib/LivechatExternalMessage'; import '../lib/LivechatInquiry'; import './lib/Analytics'; import './lib/QueueManager'; diff --git a/app/livechat/server/publications/externalMessages.js b/app/livechat/server/publications/externalMessages.js index ac4af8a5a84..c7b5357153b 100644 --- a/app/livechat/server/publications/externalMessages.js +++ b/app/livechat/server/publications/externalMessages.js @@ -1,7 +1,8 @@ import { Meteor } from 'meteor/meteor'; -import { LivechatExternalMessage } from '../../lib/LivechatExternalMessage'; +import { LivechatExternalMessage } from '../../../models/server'; Meteor.publish('livechat:externalMessages', function(roomId) { + console.warn('The publication "livechat:externalMessages" is deprecated and will be removed after version v3.0.0'); return LivechatExternalMessage.findByRoomId(roomId); }); diff --git a/app/models/server/index.js b/app/models/server/index.js index dc92464edf6..d607ab70aca 100644 --- a/app/models/server/index.js +++ b/app/models/server/index.js @@ -34,6 +34,7 @@ import LivechatTrigger from './models/LivechatTrigger'; import LivechatVisitors from './models/LivechatVisitors'; import LivechatAgentActivity from './models/LivechatAgentActivity'; import ReadReceipts from './models/ReadReceipts'; +import LivechatExternalMessage from './models/LivechatExternalMessages'; export { AppsLogsModel } from './models/apps-logs-model'; export { AppsPersistenceModel } from './models/apps-persistence-model'; @@ -80,4 +81,5 @@ export { LivechatVisitors, LivechatAgentActivity, ReadReceipts, + LivechatExternalMessage, }; diff --git a/app/models/server/models/LivechatExternalMessages.js b/app/models/server/models/LivechatExternalMessages.js new file mode 100644 index 00000000000..4c13f0c233c --- /dev/null +++ b/app/models/server/models/LivechatExternalMessages.js @@ -0,0 +1,18 @@ +import { Base } from './_Base'; + +export class LivechatExternalMessage extends Base { + constructor() { + super('livechat_external_message'); + + this.tryEnsureIndex({ rid: 1 }); + } + + // FIND + findByRoomId(roomId, sort = { ts: -1 }) { + const query = { rid: roomId }; + + return this.find(query, { sort }); + } +} + +export default new LivechatExternalMessage(); diff --git a/app/models/server/raw/LivechatExternalMessages.js b/app/models/server/raw/LivechatExternalMessages.js new file mode 100644 index 00000000000..642bb43d657 --- /dev/null +++ b/app/models/server/raw/LivechatExternalMessages.js @@ -0,0 +1,9 @@ +import { BaseRaw } from './BaseRaw'; + +export class LivechatExternalMessageRaw extends BaseRaw { + findByRoomId(roomId, options) { + const query = { rid: roomId }; + + return this.find(query, options); + } +} diff --git a/app/models/server/raw/index.js b/app/models/server/raw/index.js index d12ed55f0ad..cb65c641894 100644 --- a/app/models/server/raw/index.js +++ b/app/models/server/raw/index.js @@ -20,6 +20,8 @@ import LivechatRoomsModel from '../models/LivechatRooms'; import { LivechatRoomsRaw } from './LivechatRooms'; import MessagesModel from '../models/Messages'; import { MessagesRaw } from './Messages'; +import LivechatExternalMessagesModel from '../models/LivechatExternalMessages'; +import { LivechatExternalMessageRaw } from './LivechatExternalMessages'; import LivechatVisitorsModel from '../models/LivechatVisitors'; import { LivechatVisitorsRaw } from './LivechatVisitors'; @@ -34,4 +36,5 @@ export const LivechatDepartment = new LivechatDepartmentRaw(LivechatDepartmentMo export const LivechatDepartmentAgents = new LivechatDepartmentAgentsRaw(LivechatDepartmentAgentsModel.model.rawCollection()); export const LivechatRooms = new LivechatRoomsRaw(LivechatRoomsModel.model.rawCollection()); export const Messages = new MessagesRaw(MessagesModel.model.rawCollection()); +export const LivechatExternalMessage = new LivechatExternalMessageRaw(LivechatExternalMessagesModel.model.rawCollection()); export const LivechatVisitors = new LivechatVisitorsRaw(LivechatVisitorsModel.model.rawCollection()); diff --git a/tests/end-to-end/api/livechat/messages.js b/tests/end-to-end/api/livechat/messages.js new file mode 100644 index 00000000000..fd22248c350 --- /dev/null +++ b/tests/end-to-end/api/livechat/messages.js @@ -0,0 +1,29 @@ +import { getCredentials, api, request, credentials } from '../../../data/api-data.js'; +import { updateSetting } from '../../../data/permissions.helper'; + +describe('LIVECHAT - messages', function() { + this.retries(0); + + before((done) => getCredentials(done)); + + before((done) => { + updateSetting('Livechat_enabled', true).then(done); + }); + + describe('livechat/messages.external', () => { + it('should return an array of messages', (done) => { + request.get(api('livechat/messages.external/roomId')) + .set(credentials) + .expect('Content-Type', 'application/json') + .expect(200) + .expect((res) => { + expect(res.body).to.have.property('success', true); + expect(res.body.messages).to.be.an('array'); + expect(res.body).to.have.property('offset'); + expect(res.body).to.have.property('total'); + expect(res.body).to.have.property('count'); + }) + .end(done); + }); + }); +});