-
Notifications
You must be signed in to change notification settings - Fork 13.8k
[IMPROVE][Omnichannel] More info and better design of Past Chats List #17346
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
Changes from 10 commits
7ac2a47
428c047
cf71487
759eaff
faaa0e8
1dd9fae
19d6184
2650e56
8388d6e
6ec867f
65d03ae
45ee0dd
4a7e476
2996e42
63ee375
1450021
866130c
ff89afc
74e51a6
efee120
3cf7fa9
845b7e9
36e5ad7
57d6457
587cd3d
048c1d4
6e14f32
7db6ce0
685a770
7317eac
12111e1
9536f15
c0990b2
9607da0
b5ed51a
1e98343
0e4bc40
127132e
bba74e3
0dacdf9
9d2e42e
a6d8ef4
5d28d35
26a5c98
0632ee2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,73 @@ | ||||||
| <template name='customerChatHistory'> | ||||||
| <div class="content"> | ||||||
| <div class="list-view"> | ||||||
| <div> | ||||||
| <div class="active-pink-4 mb-4 inner-addon right-addon"> | ||||||
| <i class="glyphicon glyphicon-search icon-search"></i> | ||||||
| <input type="text" id="searchInput" class="" placeholder="Search" aria-label="Search"> | ||||||
| </div> | ||||||
| </div> | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix the indentation.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||||||
| {{#if isAllChat}} | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do you need this {{#if isAllChat}}? |
||||||
| <div class="vistior-history-block"> | ||||||
| <ul id='allist'> | ||||||
| {{#if isSearching}} | ||||||
| {{#if isfound }} | ||||||
| {{#each searchResults}} | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You don't need a
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Designs of both search result and history room is different so no need to use same template for both |
||||||
| <li class='search-li'> | ||||||
| <div class="history-main"> | ||||||
| <div class="history-img"> | ||||||
| <img src="/avatar/{{u.username}}" > | ||||||
| </div> | ||||||
| <div class="history-detail-main"> | ||||||
| <div class="detail-main-upper"> | ||||||
| <h1>{{u.name}}</h1> | ||||||
| <p>{{time}}</p> | ||||||
| </div> | ||||||
| <div class="detail-main-lower"> | ||||||
| <p>{{msg}}</p> | ||||||
| </div> | ||||||
| </div> | ||||||
| </div> | ||||||
| </li> | ||||||
| {{/each}} | ||||||
| {{else}} | ||||||
| <h1 class='noresult'>No result found</h1> | ||||||
| {{/if}} | ||||||
| {{else}} | ||||||
| {{#each previousChats}} | ||||||
| <li class='list-chat' id='{{_id}}' aria='{{v.token}}' > | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. created A template called chatRoomHistoyItem |
||||||
| <div class="history-div"> | ||||||
| <div class="visitor-img"> | ||||||
| <img src="/avatar/{{responseBy.username}}" alt=""> | ||||||
| </div> | ||||||
| <div class="visitor-history-details"> | ||||||
| <div class="visitor-details"> | ||||||
| <h1>{{responseBy.username}}</h1> | ||||||
| {{#if open}} | ||||||
| <p class='open'>Open</p> | ||||||
| {{else}} | ||||||
| <p>Close at time {{time}}</p> | ||||||
| {{/if}} | ||||||
| </div> | ||||||
| <div class="total-messages"> | ||||||
| <p>{{room.msgs}} messages</p> | ||||||
| </div> | ||||||
| <div class="agent-comment"> | ||||||
| <p class="comment-heading">Agent comment:</p> | ||||||
| <p class="comment-text">"{{lastMessage.msg}}"</p> | ||||||
| </div> | ||||||
| </div> | ||||||
| </div> | ||||||
| </li> | ||||||
| {{/each}} | ||||||
| {{/if}} | ||||||
| </ul> | ||||||
| </div> | ||||||
| {{else}} | ||||||
| {{#if isChatClicked}} | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can move this to the top of the template, don't need any if/else statement. |
||||||
| {{> customerChatHistoryMessages}} | ||||||
| {{/if}} | ||||||
| {{/if}} | ||||||
| </div> | ||||||
| </div> | ||||||
| </template> | ||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,138 @@ | ||||||
| import { Template } from 'meteor/templating'; | ||||||
| import moment from 'moment'; | ||||||
| import { ReactiveVar } from 'meteor/reactive-var'; | ||||||
| import './customerChatHistory.html'; | ||||||
| import { APIClient, t } from '../../../../../utils/client'; | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 't' is defined but never used.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed |
||||||
| import { Session } from 'meteor/session'; | ||||||
|
|
||||||
| const ITEMS_COUNT = 50; | ||||||
| let historyResult | ||||||
| let len, msgs | ||||||
| let allHistoryChat ; | ||||||
| Template.customerChatHistory.helpers({ | ||||||
| isSearching(){ | ||||||
| return Template.instance().isSearching.get() | ||||||
| }, | ||||||
| isAllChat() { | ||||||
| // will return is have to load all chat | ||||||
| return Template.instance().isAllChat.get(); | ||||||
| }, | ||||||
| isChatClicked() { | ||||||
| // will return that if you have clicked in a single chatHistory | ||||||
| return Template.instance().isChatClicked.get(); | ||||||
| }, | ||||||
| isfound() { | ||||||
| // will return if find any search result | ||||||
| return Session.get('found'); | ||||||
| }, | ||||||
| searchResults(){ | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You don't need this.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i have removed it |
||||||
| // will return search result | ||||||
| var r = Session.get('searchResult'); | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do you need this?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||||||
| return Template.instance().searchResult.get(); | ||||||
| }, | ||||||
| previousChats() { | ||||||
| // will return pervious chats list | ||||||
| let history = Template.instance().history.get(); | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. changed |
||||||
| let newHisTory = [] | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You don't need any of this code between the lines 46 ~ 58.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i need this because of i am adding a time property inside the message object then pushing into a new array
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can create a helper method to return the history item, as I mentioned above(customerChatHistoryItem) and then you can have a method like: |
||||||
| for(i=1; i<history.length; i++){ | ||||||
| history[i].time = moment(history[i].ts).format('LT'); | ||||||
| history[i].count = history[i].msgs-3; | ||||||
| newHisTory.push(history[i]); | ||||||
| } | ||||||
| return newHisTory; | ||||||
| }, | ||||||
| title() { | ||||||
|
|
||||||
| let title = moment(this.ts).format('L LTS'); | ||||||
|
|
||||||
| if (this.label) { | ||||||
| title += ` - ${ this.label }`; | ||||||
| } | ||||||
| return title; | ||||||
| }, | ||||||
| }); | ||||||
|
|
||||||
| Template.customerChatHistory.onCreated(function() { | ||||||
| const currentData = Template.currentData(); | ||||||
| this.visitorId = new ReactiveVar(); | ||||||
| this.history = new ReactiveVar([]); | ||||||
| this.offset = new ReactiveVar(0); | ||||||
| this.total = new ReactiveVar(0); | ||||||
| this.isAllChat = new ReactiveVar(true); | ||||||
| this.isSearching = new ReactiveVar(false); | ||||||
| this.isChatClicked = new ReactiveVar(true); | ||||||
| this.autorun(async () => { | ||||||
| const { room } = await APIClient.v1.get(`rooms.info?roomId=${ currentData.rid }`); | ||||||
| if (room && room.v) { | ||||||
| this.visitorId.set(room.v._id); | ||||||
| } | ||||||
| }); | ||||||
| this.autorun(async () => { | ||||||
|
|
||||||
| if (!this.visitorId.get() || !currentData || !currentData.rid) { | ||||||
| return; | ||||||
| } | ||||||
| const offset = this.offset.get(); | ||||||
| const { history, total } = await APIClient.v1.get(`livechat/visitors.chatHistory/room/${ currentData.rid }/visitor/${ this.visitorId.get() }?count=${ ITEMS_COUNT }&offset=${ offset }`); | ||||||
| this.total.set(total); | ||||||
| this.history.set(this.history.get().concat(history)); | ||||||
| }); | ||||||
| }); | ||||||
|
|
||||||
| Template.customerChatHistory.events({ | ||||||
| 'scroll .visitor-scroll': _.throttle(function(e, instance) { | ||||||
| if (e.target.scrollTop >= (e.target.scrollHeight - e.target.clientHeight)) { | ||||||
| const history = instance.history.get(); | ||||||
| if (instance.total.get() <= history.length) { | ||||||
| return; | ||||||
| } | ||||||
| return instance.offset.set(instance.offset.get() + ITEMS_COUNT); | ||||||
| } | ||||||
| }, 200), | ||||||
| 'keyup #searchInput': async function(event,template){ | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You need to filter the rooms on the server-side which means you need to have a specific method to load the customer history chats and here you will use the same method, but you will pass the search term to the server and get the results. Also, you need to use Please, take a look at that code and use it as inspiration.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. now i am using the search api to search the message inside a room
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are performing a loop of each customer history room, this is not a good practice. It's simple:
|
||||||
| template.isSearching.set(true); | ||||||
| searchResults = []; | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All of the code below is not necessary.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. have done some changes please check
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As I mentioned, all of this code below is unnecessary. Is not much more simple? There is no reason for this loop, well you call the endpoint, searching or not, then you'll get the |
||||||
| let text = event.target.value; | ||||||
| template.isChatClicked.set(false); | ||||||
| template.isAllChat.set(true); | ||||||
| Session.set('found',false); | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do you need this? I didn't get yet why you're using
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. now i am not using session anywhere |
||||||
| if(event.target.value == ''){ | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You don't need this
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i have performed check on loadRoom method and removed it from here |
||||||
| template.isSearching.set(false); | ||||||
| }else{ | ||||||
|
|
||||||
| Template.instance().searchResult = new ReactiveVar([]); | ||||||
| let history = Template.instance().history.get(); | ||||||
| let array = []; | ||||||
| for(var j=0; j<history.length; j++){ | ||||||
| var rid = history[j]._id; | ||||||
| const search = await APIClient.v1.get(`chat.search?roomId=${rid}&searchText=${text}`); | ||||||
| for(k=0; k<search.messages.length; k++){ | ||||||
| search.messages[k].time = moment(search.messages[k].ts).format('LT'); | ||||||
| array.push(search.messages[k]); | ||||||
| } | ||||||
| } | ||||||
| if(array.length >0){ | ||||||
| Session.set('found',true); | ||||||
| Session.set('searchResult',array); | ||||||
| template.searchResult.set(array) | ||||||
| } | ||||||
| }}, | ||||||
| 'click .list-chat': async function(event,template){ | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here you just need to get the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i am getting the Room Id and token and storing into the session and getting from the customer chat history messages
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use |
||||||
| event.preventDefault(); | ||||||
| template.isAllChat.set(false); | ||||||
| template.isChatClicked.set(true); | ||||||
| let id = event.currentTarget.id | ||||||
| let token = event.currentTarget.attributes.aria.value; | ||||||
| Session.set('FetchID',id); | ||||||
| Session.set('FetchToken',token) | ||||||
| } | ||||||
|
|
||||||
| }); | ||||||
|
|
||||||
| Template.customerChatHistory.onDestroyed(function(){ | ||||||
| var header = document.getElementsByClassName('Contextualheading'); | ||||||
| if(header[0]){ | ||||||
| header[0].innerText = '' | ||||||
| header[0].className = 'contextual-bar__header-title'; | ||||||
| } | ||||||
| }) | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| <template name='customerChatHistoryMessages'> | ||
| {{#if isLoading}} | ||
| <h2 class='loding'> | ||
| {{_ "Loading..."}} | ||
| </h2> | ||
| {{else}} | ||
| <div class="chatHistory"> | ||
| <div class='msgcount'> | ||
| <p><span>{{len}} messages</span></p> | ||
| </div> | ||
| <ul> | ||
| {{#each historyResult}} | ||
| {{#unless t}} | ||
| <li> | ||
| <div class="history-main"> | ||
| <div class="history-img"> | ||
| <img src="/avatar/{{u.username}}" > | ||
| </div> | ||
| <div class="history-detail-main"> | ||
| <div class="detail-main-upper"> | ||
| <h1>{{u.name}}</h1> | ||
| <p>{{time}}</p> | ||
| </div> | ||
| <div class="detail-main-lower"> | ||
| <p>{{msg}}</p> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </li> | ||
| {{else}} | ||
| {{#if u.name}} | ||
| <div class="closed-div"> | ||
| <p class='closed-div-p'><span>Conversation closed</span></p> | ||
| <div class="history-main"> | ||
| <div class="history-img"> | ||
| <div class='belldiv'> | ||
| <i class="icon-bell"></i> | ||
| </div> | ||
| </div> | ||
| <div class="history-detail-main"> | ||
| <div class="detail-main-upper closed-h1"> | ||
| <h1>Agent comment:</h1> | ||
| </div> | ||
| <div class="detail-main-lower closed-p"> | ||
| <p>"{{msg}}".</p> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| {{/if}} | ||
| {{/unless}} | ||
| {{/each}} | ||
| </ul> | ||
| </div> | ||
| {{/if}} | ||
| </template> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| import { Template } from 'meteor/templating'; | ||
| import moment from 'moment'; | ||
| import './customerChatHistoryMessages.html'; | ||
| import { APIClient, t } from '../../../../../utils/client'; | ||
| import { Session } from 'meteor/session'; | ||
|
|
||
| let Messages | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove all of these variables.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removed |
||
| let len, msgs | ||
| let allHistoryChat ; | ||
|
|
||
| Template.customerChatHistoryMessages.helpers({ | ||
| historyResult() { | ||
| // will return all the messages in history room | ||
| return Template.instance().historyResult.get().reverse(); | ||
| }, | ||
| len() { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You don't need this.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The helper method is still there. |
||
| // will return length of total messages in room | ||
| len = Template.instance().historyResult.get(); | ||
| return len = len.length-1; | ||
| }, | ||
| }) | ||
| Template.customerChatHistoryMessages.onCreated(function() { | ||
| this.historyResult = new ReactiveVar([]); | ||
| var id = Session.get('FetchID'); | ||
| var token = Session.get('FetchToken') | ||
| this.autorun(async () => { | ||
| Messages = await APIClient.v1.get(`livechat/messages.history/${ id }?token=${token}`); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Create a
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
| // will return pervious chats list | ||
| let history = Messages.messages; | ||
| let newHisTory = [] | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All of the code below is unnecessary.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removed the unnecessary code only required code is here |
||
| for(i=1; i<history.length; i++){ | ||
| history[i].time = moment(history[i].ts).format('LT') | ||
| newHisTory.push(history[i]); | ||
| } | ||
| var header = document.getElementsByClassName('contextual-bar__header-title'); | ||
| var day,agentName; | ||
|
|
||
| if(newHisTory.length !== 0){ | ||
| var len = newHisTory.length-1; | ||
| agentName = newHisTory[len].u.username; | ||
| day = moment(newHisTory[len].ts).format('dddd'); | ||
| } | ||
| if(header[0]){ | ||
| header[0].innerText= `${agentName}, closed at ${day}` | ||
| header[0].className = 'Contextualheading'; | ||
| } | ||
| this.historyResult.set(newHisTory); | ||
| }) | ||
| }) | ||
|
|
||
|
|
||
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's check if the customer already has chat history, if not, let's display a message.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added a check if there is chat history available or not