TT#129050 Dashboard - As Customer, I want to see the most recent items (voicemails, calls, device-registrations) on the Dashboard

Change-Id: I386acf703a13037d2235e8e2d335eb761c893054
mr10.0
Hugo Zigha 4 years ago committed by Hugo Zigha
parent f633b6cb97
commit fe970116ca

@ -113,28 +113,9 @@ export async function deleteVoicemail (id) {
return res.status >= 200 return res.status >= 200
} }
export function getAllVoicemails (options) { export async function getAllCallsOrVoicemails (options) {
return new Promise((resolve, reject) => { return await getList({
getList({ resource: 'conversations',
resource: 'voicemails', params: options
params: { subscriber_id: options.subscriberId, rows: options.rows }
}).then((result) => {
resolve(result)
}).catch((err) => {
reject(err)
})
})
}
export function getAllCalls (options) {
return new Promise((resolve, reject) => {
getList({
resource: 'conversations',
params: { subscriber_id: options.subscriberId, rows: options.rows, type: 'call' }
}).then((result) => {
resolve(result)
}).catch((err) => {
reject(err)
})
}) })
} }

@ -82,6 +82,10 @@ import {
import CscMoreMenu from 'components/CscMoreMenu' import CscMoreMenu from 'components/CscMoreMenu'
import CscPopupMenuItem from 'components/CscPopupMenuItem' import CscPopupMenuItem from 'components/CscPopupMenuItem'
import CscPopupMenuItemStartCall from 'components/CscPopupMenuItemStartCall' import CscPopupMenuItemStartCall from 'components/CscPopupMenuItemStartCall'
import {
callIconColor,
callIcon
} from 'src/helpers/call-utils'
export default { export default {
name: 'CscCallItem', name: 'CscCallItem',
components: { CscPopupMenuItemStartCall, CscPopupMenuItem, CscMoreMenu }, components: { CscPopupMenuItemStartCall, CscPopupMenuItem, CscMoreMenu },
@ -154,29 +158,10 @@ export default {
} }
}, },
icon () { icon () {
if (this.call.call_type === 'cfu' || this.call.call_type === 'cfna' || return callIcon(this.call)
this.call.call_type === 'cfb' || this.call.call_type === 'cft') {
return 'phone_forwarded'
} else if (this.call.call_type === 'call' && this.call.direction === 'in' && this.call.status === 'cancel') {
return 'call_missed'
} else if (this.call.call_type === 'call' && this.call.direction === 'in') {
return 'call_received'
} else if (this.call.call_type === 'call' && this.call.direction === 'out') {
return 'call_made'
} else {
return 'phone'
}
}, },
color () { color () {
if (this.call.call_type === 'call' && (this.call.status === 'cancel' || return callIconColor(this.call)
this.call.status === 'offline' || this.call.status === 'noanswer')) {
return 'negative'
} else if (this.call.call_type === 'call' && (this.call.direction === 'in' ||
this.call.direction === 'out')) {
return 'primary'
} else {
return 'white'
}
}, },
isMobile () { isMobile () {
return Platform.is.mobile return Platform.is.mobile

@ -50,7 +50,60 @@
<q-card-section <q-card-section
class="csc-card-list" class="csc-card-list"
/> >
<q-list
v-for="(item, index) in itemsList"
:key="item.id"
>
<q-item>
<q-item-section avatar>
<q-icon
v-if="!item.clickable_icon"
:color="item.icon.color"
clickable
:name="item.icon.name"
/>
<q-btn
v-if="item.clickable_icon"
flat
:color="item.icon.color"
:icon="item.icon.name"
@click="$emit('action', item.id)"
/>
</q-item-section>
<q-item-section>
<q-item-label>{{ item.title }}</q-item-label>
<q-item-label caption>
{{ item.sub_title }}
</q-item-label>
</q-item-section>
<q-item-section side>
<q-item-label caption>
{{ item.extra_text }}
</q-item-label>
</q-item-section>
</q-item>
<q-separator
v-if="index !== itemsList.length-1"
spaced
/>
</q-list>
<div
v-if="!loading && itemsList.length === 0"
class="text-center"
>
{{ error ? $t('Data loading error') : noItemsMessage }}
</div>
<div
class="text-center"
>
<csc-spinner
v-if="loading"
/>
</div>
</q-card-section>
<q-separator <q-separator
dark dark
@ -112,6 +165,10 @@ export default {
error: { error: {
type: Boolean, type: Boolean,
default: false default: false
},
noItemsMessage: {
type: String,
default: ''
} }
} }
} }
@ -129,5 +186,5 @@ export default {
padding-bottom: 22px padding-bottom: 22px
.csc-card-list .csc-card-list
min-height: 316px min-height: 359px
</style> </style>

@ -0,0 +1,27 @@
export function callIcon (call) {
if (call.call_type === 'cfu' || call.call_type === 'cfna' ||
call.call_type === 'cfb' || call.call_type === 'cft') {
return 'phone_forwarded'
} else if (call.call_type === 'call' && call.direction === 'in' && call.status === 'cancel') {
return 'call_missed'
} else if (call.call_type === 'call' && call.direction === 'in') {
return 'call_received'
} else if (call.call_type === 'call' && call.direction === 'out') {
return 'call_made'
} else {
return 'phone'
}
}
export function callIconColor (call) {
if (call.call_type === 'call' && (call.status === 'cancel' ||
call.status === 'offline' || call.status === 'noanswer')) {
return 'negative'
} else if (call.call_type === 'call' && (call.direction === 'in' ||
call.direction === 'out')) {
return 'primary'
} else {
return 'white'
}
}

@ -70,3 +70,8 @@ export function isWithinLastWeek (date, $today) {
return date.getTime() >= weekStart.getTime() && return date.getTime() >= weekStart.getTime() &&
date.getTime() < todayStart.getTime() date.getTime() < todayStart.getTime()
} }
export function getBrowserTimezone () {
return Intl?.DateTimeFormat()?.resolvedOptions()?.timeZone
? Intl?.DateTimeFormat()?.resolvedOptions()?.timeZone : 'UTC'
}

@ -113,6 +113,7 @@
"Customer Details": "Customer Details", "Customer Details": "Customer Details",
"Daily": "Daily", "Daily": "Daily",
"Dashboard": "Dashboard", "Dashboard": "Dashboard",
"Data loading error": "Data loading error",
"Default": "Default", "Default": "Default",
"Default sound": "Default sound", "Default sound": "Default sound",
"Default sound set for all seats and groups": "Default sound set for all seats and groups", "Default sound set for all seats and groups": "Default sound set for all seats and groups",
@ -245,14 +246,17 @@
"No Faxes found": "No Faxes found", "No Faxes found": "No Faxes found",
"No Voicemails found": "No Voicemails found", "No Voicemails found": "No Voicemails found",
"No call queues created yet": "No call queues created yet", "No call queues created yet": "No call queues created yet",
"No calls yet": "No calls yet",
"No data found": "No data found", "No data found": "No data found",
"No data to save. Please provide at least one time range.": "No data to save. Please provide at least one time range.", "No data to save. Please provide at least one time range.": "No data to save. Please provide at least one time range.",
"No destinations created yet": "No destinations created yet", "No destinations created yet": "No destinations created yet",
"No devices created yet": "No devices created yet", "No devices created yet": "No devices created yet",
"No devices registered": "No devices registered",
"No file": "No file", "No file": "No file",
"No groups": "No groups", "No groups": "No groups",
"No groups created yet": "No groups created yet", "No groups created yet": "No groups created yet",
"No manager secretary configuration created yet": "No manager secretary configuration created yet", "No manager secretary configuration created yet": "No manager secretary configuration created yet",
"No new messages": "No new messages",
"No numbers assigned": "No numbers assigned", "No numbers assigned": "No numbers assigned",
"No numbers found": "No numbers found", "No numbers found": "No numbers found",
"No seats": "No seats", "No seats": "No seats",

@ -11,7 +11,9 @@
:items-list="voicemailItems" :items-list="voicemailItems"
:route-to="{ name: 'CscConversations', params: { initialTab: 'voicemail' } }" :route-to="{ name: 'CscConversations', params: { initialTab: 'voicemail' } }"
:loading="$wait.is('getVoicemailsData')" :loading="$wait.is('getVoicemailsData')"
:no-items-message="$t('No new messages')"
:error="voicemailsError" :error="voicemailsError"
@action="downloadVoicemail"
/> />
<csc-card-dashboard <csc-card-dashboard
:title="$t('Call List')" :title="$t('Call List')"
@ -20,6 +22,7 @@
:button-title="$t('View Call List')" :button-title="$t('View Call List')"
:items-list="callItems" :items-list="callItems"
:route-to="{ name: 'CscConversations', params: { initialTab: 'call' } }" :route-to="{ name: 'CscConversations', params: { initialTab: 'call' } }"
:no-items-message="$t('No calls yet')"
:loading="$wait.is('getCallsData')" :loading="$wait.is('getCallsData')"
:error="callsError" :error="callsError"
/> />
@ -30,6 +33,7 @@
:button-title="$t('View All Registered Devices')" :button-title="$t('View All Registered Devices')"
:items-list="registeredDevicesItems" :items-list="registeredDevicesItems"
:route-to="{ name: 'RegisteredDevices', params: { initialTab: 'null' } }" :route-to="{ name: 'RegisteredDevices', params: { initialTab: 'null' } }"
:no-items-message="$t('No devices registered')"
:loading="$wait.is('getRegisteredDevicesData')" :loading="$wait.is('getRegisteredDevicesData')"
:error="registeredDevicesError" :error="registeredDevicesError"
/> />
@ -43,6 +47,14 @@ import { mapWaitingActions } from 'vue-wait'
import { import {
showGlobalError showGlobalError
} from 'src/helpers/ui' } from 'src/helpers/ui'
import {
date
} from 'quasar'
import { INTERNAL_DATE_FORMAT_DASH_HOUR } from 'src/constants'
import {
callIconColor,
callIcon
} from 'src/helpers/call-utils'
export default { export default {
name: 'CscPageDashboard', name: 'CscPageDashboard',
components: { components: {
@ -77,36 +89,78 @@ export default {
this.getVoicemailsData(), this.getVoicemailsData(),
this.getRegisteredDevicesData() this.getRegisteredDevicesData()
]) ])
this.checkResponses('calls', values[0]) this.manageCallsData(values[0])
this.checkResponses('voicemails', values[1]) this.manageVoicemailsData(values[1])
this.checkResponses('registered-devices', values[2]) this.manageDevicesData(values[2])
}, },
checkResponses (type, response) { manageCallsData (calls) {
if (type === 'calls') { if (calls.status === 'rejected') {
if (response.status === 'rejected') { this.callsError = true
this.callsError = true showGlobalError(calls?.reason?.data?.message)
showGlobalError(response?.reason?.data?.message) } else {
} else { this.callsCount = calls.value.totalCount
this.callsCount = response.value.totalCount this.callItems = calls.value.items.map((item) => {
this.callItems = response.value.items return {
} id: item.id,
} else if (type === 'voicemails') { icon: { name: callIcon(item), color: callIconColor(item) },
if (response.status === 'rejected') { clickable_icon: false,
this.voicemailsError = true title: this.checkTitleToShow(item),
showGlobalError(response?.reason?.data?.message) sub_title: date.formatDate(item.start_time, INTERNAL_DATE_FORMAT_DASH_HOUR),
} else { extra_text: item.duration.split('.')[0]
this.voicemailsCount = response.value.totalCount }
this.voicemailItems = response.value.items })
}
} else if (type === 'registered-devices') {
if (response.status === 'rejected') {
this.registeredDevicesError = true
showGlobalError(response?.reason?.data?.message)
} else {
this.registeredDevicesCount = response.value.totalCount
this.registeredDevicesItems = response.value.items
}
} }
},
manageVoicemailsData (voicemails) {
if (voicemails.status === 'rejected') {
this.voicemailsError = true
showGlobalError(voicemails?.reason?.data?.message)
} else {
this.voicemailsCount = voicemails.value.totalCount
this.voicemailItems = voicemails.value.items.map((item) => {
return {
id: item.id,
icon: { name: 'download', color: 'primary' },
clickable_icon: true,
title: item.caller,
sub_title: date.formatDate(item.start_time, INTERNAL_DATE_FORMAT_DASH_HOUR),
extra_text: new Date(item.duration * 1000).toISOString().substr(11, 8)
}
})
}
},
manageDevicesData (devices) {
if (devices.status === 'rejected') {
this.registeredDevicesError = true
showGlobalError(devices?.reason?.data?.message)
} else {
this.registeredDevicesCount = devices.value.totalCount
this.registeredDevicesItems = devices.value.items.map((item) => {
return {
id: item.id,
icon: { name: 'devices', color: 'primary' },
clickable_icon: false,
title: item.user_agent,
sub_title: date.formatDate(item.expires, INTERNAL_DATE_FORMAT_DASH_HOUR),
extra_text: ''
}
})
}
},
checkTitleToShow (call) {
if (call.call_type === 'cfu' || call.call_type === 'cfna' ||
call.call_type === 'cfb' || call.call_type === 'cft') {
return 'vmu' + call.caller
} else if (call.direction === 'out') {
return call.callee
} else if (call.direction === 'in') {
return call.caller
} else {
return call.caller
}
},
downloadVoicemail (id) {
this.$store.dispatch('conversations/downloadVoiceMail', id)
} }
} }
} }

@ -1,11 +1,14 @@
import { import {
getAllVoicemails, getAllCallsOrVoicemails
getAllCalls
} from '../api/conversations' } from '../api/conversations'
import { import {
getSubscriberRegistrations getSubscriberRegistrations
} from '../api/subscriber' } from '../api/subscriber'
import {
getBrowserTimezone
} from '../helpers/date-helper'
export default { export default {
namespaced: true, namespaced: true,
getters: { getters: {
@ -15,23 +18,34 @@ export default {
}, },
actions: { actions: {
async getVoicemailsData (context) { async getVoicemailsData (context) {
const res = await getAllVoicemails({ const res = await getAllCallsOrVoicemails({
subscriberId: context.getters.getSubscriberId, subscriber_id: context.getters.getSubscriberId,
rows: 5 rows: 5,
order_by: 'timestamp',
order_by_direction: 'desc',
type: 'voicemail',
tz: getBrowserTimezone()
}) })
return res return res
}, },
async getCallsData (context) { async getCallsData (context) {
const res = await getAllCalls({ const res = await getAllCallsOrVoicemails({
subscriberId: context.getters.getSubscriberId, subscriber_id: context.getters.getSubscriberId,
rows: 5 rows: 5,
order_by: 'timestamp',
order_by_direction: 'desc',
type: 'call',
tz: getBrowserTimezone()
}) })
return res return res
}, },
async getRegisteredDevicesData (context) { async getRegisteredDevicesData (context) {
const res = await getSubscriberRegistrations({ const res = await getSubscriberRegistrations({
subscriber_id: context.getters.getSubscriberId, subscriber_id: context.getters.getSubscriberId,
rows: 5 rows: 5,
order_by: 'timestamp',
order_by_direction: 'desc',
tz: getBrowserTimezone()
}) })
return res return res
} }

Loading…
Cancel
Save