Feature: Add online status to each user (#452)
* Feature: Add online status to each user * Add OnlineStatusable, add availability status to thumbnail
This commit is contained in:
@@ -1,5 +1,10 @@
|
||||
class RoomChannel < ApplicationCable::Channel
|
||||
def subscribed
|
||||
stream_from params[:pubsub_token]
|
||||
::OnlineStatusTracker.add_subscription(params[:pubsub_token])
|
||||
end
|
||||
|
||||
def unsubscribed
|
||||
::OnlineStatusTracker.remove_subscription(params[:pubsub_token])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,7 +4,7 @@ class Api::V1::AgentsController < Api::BaseController
|
||||
before_action :build_agent, only: [:create]
|
||||
|
||||
def index
|
||||
render json: agents
|
||||
@agents = agents
|
||||
end
|
||||
|
||||
def destroy
|
||||
|
||||
@@ -16,12 +16,17 @@
|
||||
:size="avatarSize"
|
||||
/>
|
||||
<img
|
||||
v-if="badge === 'Channel::FacebookPage'"
|
||||
v-if="badge === 'Channel::FacebookPage' && status !== ''"
|
||||
id="badge"
|
||||
class="source-badge"
|
||||
:style="badgeStyle"
|
||||
src="~dashboard/assets/images/fb-badge.png"
|
||||
/>
|
||||
<div
|
||||
v-else-if="status === 'online'"
|
||||
class="source-badge user--online"
|
||||
:style="statusStyle"
|
||||
></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
@@ -41,6 +46,7 @@ export default {
|
||||
props: {
|
||||
src: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
@@ -52,6 +58,11 @@ export default {
|
||||
},
|
||||
username: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
@@ -67,6 +78,10 @@ export default {
|
||||
const badgeSize = `${this.avatarSize / 3}px`;
|
||||
return { width: badgeSize, height: badgeSize };
|
||||
},
|
||||
statusStyle() {
|
||||
const statusSize = `${this.avatarSize / 4}px`;
|
||||
return { width: statusSize, height: statusSize };
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onImgError() {
|
||||
@@ -78,6 +93,7 @@ export default {
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '~dashboard/assets/scss/variables';
|
||||
@import '~dashboard/assets/scss/foundation-settings';
|
||||
@import '~dashboard/assets/scss/mixins';
|
||||
|
||||
.user-thumbnail-box {
|
||||
@@ -91,11 +107,21 @@ export default {
|
||||
}
|
||||
|
||||
.source-badge {
|
||||
bottom: -$space-micro / 2;
|
||||
bottom: -$space-micro;
|
||||
height: $space-slab;
|
||||
position: absolute;
|
||||
right: $zero;
|
||||
width: $space-slab;
|
||||
}
|
||||
|
||||
.user--online {
|
||||
background: $success-color;
|
||||
border-radius: 50%;
|
||||
bottom: $space-micro;
|
||||
|
||||
&:after {
|
||||
content: ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
size="56px"
|
||||
:badge="contact.channel"
|
||||
:username="contact.name"
|
||||
:status="contact.availability_status"
|
||||
/>
|
||||
<div class="contact--details">
|
||||
<div class="contact--name">
|
||||
|
||||
@@ -26,10 +26,11 @@
|
||||
<!-- Gravtar Image -->
|
||||
<td>
|
||||
<thumbnail
|
||||
:src="gravatarUrl(agent.email)"
|
||||
:src="agent.thumbnail"
|
||||
class="columns"
|
||||
:username="agent.name"
|
||||
size="40px"
|
||||
:status="agent.availability_status"
|
||||
/>
|
||||
</td>
|
||||
<!-- Agent Name + Email -->
|
||||
|
||||
@@ -49,7 +49,6 @@ export const getters = {
|
||||
Object.values(_state.conversations),
|
||||
message => new DateHelper(message.created_at).format()
|
||||
);
|
||||
|
||||
return Object.keys(conversationGroupedByDate).map(date => {
|
||||
const messages = conversationGroupedByDate[date].map((message, index) => {
|
||||
let showAvatar = false;
|
||||
@@ -59,12 +58,11 @@ export const getters = {
|
||||
const nextMessage = conversationGroupedByDate[date][index + 1];
|
||||
const currentSender = message.sender ? message.sender.name : '';
|
||||
const nextSender = nextMessage.sender ? nextMessage.sender.name : '';
|
||||
showAvatar = currentSender !== nextSender;
|
||||
showAvatar =
|
||||
currentSender !== nextSender ||
|
||||
message.message_type !== nextMessage.message_type;
|
||||
}
|
||||
return {
|
||||
showAvatar,
|
||||
...message,
|
||||
};
|
||||
return { showAvatar, ...message };
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
@@ -61,19 +61,27 @@ describe('#getters', () => {
|
||||
id: 1,
|
||||
content: 'Thanks for the help',
|
||||
created_at: 1574075964,
|
||||
message_type: 0,
|
||||
},
|
||||
2: {
|
||||
id: 2,
|
||||
content: 'Yes, It makes sense',
|
||||
created_at: 1574092218,
|
||||
message_type: 0,
|
||||
},
|
||||
3: {
|
||||
id: 3,
|
||||
content: 'Hey',
|
||||
created_at: 1576340623,
|
||||
created_at: 1574092218,
|
||||
message_type: 1,
|
||||
},
|
||||
4: {
|
||||
id: 4,
|
||||
content: 'Hey',
|
||||
created_at: 1576340623,
|
||||
},
|
||||
5: {
|
||||
id: 5,
|
||||
content: 'How may I help you',
|
||||
created_at: 1576340626,
|
||||
},
|
||||
@@ -88,12 +96,21 @@ describe('#getters', () => {
|
||||
content: 'Thanks for the help',
|
||||
created_at: 1574075964,
|
||||
showAvatar: false,
|
||||
message_type: 0,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
content: 'Yes, It makes sense',
|
||||
created_at: 1574092218,
|
||||
showAvatar: true,
|
||||
message_type: 0,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
content: 'Hey',
|
||||
created_at: 1574092218,
|
||||
showAvatar: true,
|
||||
message_type: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -101,13 +118,13 @@ describe('#getters', () => {
|
||||
date: 'Dec 14, 2019',
|
||||
messages: [
|
||||
{
|
||||
id: 3,
|
||||
id: 4,
|
||||
content: 'Hey',
|
||||
created_at: 1576340623,
|
||||
showAvatar: false,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
id: 5,
|
||||
content: 'How may I help you',
|
||||
created_at: 1576340626,
|
||||
showAvatar: true,
|
||||
|
||||
11
app/models/concerns/availability_statusable.rb
Normal file
11
app/models/concerns/availability_statusable.rb
Normal file
@@ -0,0 +1,11 @@
|
||||
module AvailabilityStatusable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def online?
|
||||
::OnlineStatusTracker.subscription_count(pubsub_token) != 0
|
||||
end
|
||||
|
||||
def availability_status
|
||||
online? ? 'online' : 'offline'
|
||||
end
|
||||
end
|
||||
@@ -20,6 +20,7 @@
|
||||
class Contact < ApplicationRecord
|
||||
include Pubsubable
|
||||
include Avatarable
|
||||
include AvailabilityStatusable
|
||||
validates :account_id, presence: true
|
||||
|
||||
belongs_to :account
|
||||
|
||||
@@ -48,6 +48,7 @@ class User < ApplicationRecord
|
||||
include Events::Types
|
||||
include Pubsubable
|
||||
include Avatarable
|
||||
include AvailabilityStatusable
|
||||
include Rails.application.routes.url_helpers
|
||||
|
||||
devise :database_authenticatable,
|
||||
|
||||
10
app/views/api/v1/agents/index.json.jbuilder
Normal file
10
app/views/api/v1/agents/index.json.jbuilder
Normal file
@@ -0,0 +1,10 @@
|
||||
json.array! @agents do |agent|
|
||||
json.account_id agent.account_id
|
||||
json.availability_status agent.availability_status
|
||||
json.confirmed agent.confirmed?
|
||||
json.email agent.email
|
||||
json.id agent.id
|
||||
json.name agent.name
|
||||
json.role agent.role
|
||||
json.thumbnail agent.avatar_url
|
||||
end
|
||||
@@ -1,7 +1,8 @@
|
||||
json.payload do
|
||||
json.availability_status @contact.availability_status
|
||||
json.email @contact.email
|
||||
json.id @contact.id
|
||||
json.name @contact.name
|
||||
json.email @contact.email
|
||||
json.phone_number @contact.phone_number
|
||||
json.thumbnail @contact.avatar_url
|
||||
end
|
||||
|
||||
@@ -2,5 +2,6 @@ json.payload do
|
||||
json.array! @inbox_members do |inbox_member|
|
||||
json.name inbox_member.user.name
|
||||
json.avatar_url inbox_member.user.avatar_url
|
||||
json.availability_status inbox_member.user.availability_status
|
||||
end
|
||||
end
|
||||
|
||||
19
lib/online_status_tracker.rb
Normal file
19
lib/online_status_tracker.rb
Normal file
@@ -0,0 +1,19 @@
|
||||
module OnlineStatusTracker
|
||||
def self.add_subscription(channel_id)
|
||||
count = subscription_count(channel_id)
|
||||
::Redis::Alfred.setex(channel_id, count + 1)
|
||||
end
|
||||
|
||||
def self.remove_subscription(channel_id)
|
||||
count = subscription_count(channel_id)
|
||||
if count == 1
|
||||
::Redis::Alfred.delete(channel_id)
|
||||
elsif count != 0
|
||||
::Redis::Alfred.setex(channel_id, count - 1)
|
||||
end
|
||||
end
|
||||
|
||||
def self.subscription_count(channel_id)
|
||||
::Redis::Alfred.get(channel_id).to_i
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user