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
}
export function getAllVoicemails (options) {
return new Promise((resolve, reject) => {
getList({
resource: 'voicemails',
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)
})
export async function getAllCallsOrVoicemails (options) {
return await getList({
resource: 'conversations',
params: options
})
}

@ -82,6 +82,10 @@ import {
import CscMoreMenu from 'components/CscMoreMenu'
import CscPopupMenuItem from 'components/CscPopupMenuItem'
import CscPopupMenuItemStartCall from 'components/CscPopupMenuItemStartCall'
import {
callIconColor,
callIcon
} from 'src/helpers/call-utils'
export default {
name: 'CscCallItem',
components: { CscPopupMenuItemStartCall, CscPopupMenuItem, CscMoreMenu },
@ -154,29 +158,10 @@ export default {
}
},
icon () {
if (this.call.call_type === 'cfu' || this.call.call_type === 'cfna' ||
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'
}
return callIcon(this.call)
},
color () {
if (this.call.call_type === 'call' && (this.call.status === 'cancel' ||
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'
}
return callIconColor(this.call)
},
isMobile () {
return Platform.is.mobile

@ -50,7 +50,60 @@
<q-card-section
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
dark
@ -112,6 +165,10 @@ export default {
error: {
type: Boolean,
default: false
},
noItemsMessage: {
type: String,
default: ''
}
}
}
@ -129,5 +186,5 @@ export default {
padding-bottom: 22px
.csc-card-list
min-height: 316px
min-height: 359px
</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() &&
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",
"Daily": "Daily",
"Dashboard": "Dashboard",
"Data loading error": "Data loading error",
"Default": "Default",
"Default sound": "Default sound",
"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 Voicemails found": "No Voicemails found",
"No call queues created yet": "No call queues created yet",
"No calls yet": "No calls yet",
"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 destinations created yet": "No destinations created yet",
"No devices created yet": "No devices created yet",
"No devices registered": "No devices registered",
"No file": "No file",
"No groups": "No groups",
"No groups created yet": "No groups 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 found": "No numbers found",
"No seats": "No seats",

@ -11,7 +11,9 @@
:items-list="voicemailItems"
:route-to="{ name: 'CscConversations', params: { initialTab: 'voicemail' } }"
:loading="$wait.is('getVoicemailsData')"
:no-items-message="$t('No new messages')"
:error="voicemailsError"
@action="downloadVoicemail"
/>
<csc-card-dashboard
:title="$t('Call List')"
@ -20,6 +22,7 @@
:button-title="$t('View Call List')"
:items-list="callItems"
:route-to="{ name: 'CscConversations', params: { initialTab: 'call' } }"
:no-items-message="$t('No calls yet')"
:loading="$wait.is('getCallsData')"
:error="callsError"
/>
@ -30,6 +33,7 @@
:button-title="$t('View All Registered Devices')"
:items-list="registeredDevicesItems"
:route-to="{ name: 'RegisteredDevices', params: { initialTab: 'null' } }"
:no-items-message="$t('No devices registered')"
:loading="$wait.is('getRegisteredDevicesData')"
:error="registeredDevicesError"
/>
@ -43,6 +47,14 @@ import { mapWaitingActions } from 'vue-wait'
import {
showGlobalError
} 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 {
name: 'CscPageDashboard',
components: {
@ -77,36 +89,78 @@ export default {
this.getVoicemailsData(),
this.getRegisteredDevicesData()
])
this.checkResponses('calls', values[0])
this.checkResponses('voicemails', values[1])
this.checkResponses('registered-devices', values[2])
this.manageCallsData(values[0])
this.manageVoicemailsData(values[1])
this.manageDevicesData(values[2])
},
checkResponses (type, response) {
if (type === 'calls') {
if (response.status === 'rejected') {
this.callsError = true
showGlobalError(response?.reason?.data?.message)
} else {
this.callsCount = response.value.totalCount
this.callItems = response.value.items
}
} else if (type === 'voicemails') {
if (response.status === 'rejected') {
this.voicemailsError = true
showGlobalError(response?.reason?.data?.message)
} else {
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
}
manageCallsData (calls) {
if (calls.status === 'rejected') {
this.callsError = true
showGlobalError(calls?.reason?.data?.message)
} else {
this.callsCount = calls.value.totalCount
this.callItems = calls.value.items.map((item) => {
return {
id: item.id,
icon: { name: callIcon(item), color: callIconColor(item) },
clickable_icon: false,
title: this.checkTitleToShow(item),
sub_title: date.formatDate(item.start_time, INTERNAL_DATE_FORMAT_DASH_HOUR),
extra_text: item.duration.split('.')[0]
}
})
}
},
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 {
getAllVoicemails,
getAllCalls
getAllCallsOrVoicemails
} from '../api/conversations'
import {
getSubscriberRegistrations
} from '../api/subscriber'
import {
getBrowserTimezone
} from '../helpers/date-helper'
export default {
namespaced: true,
getters: {
@ -15,23 +18,34 @@ export default {
},
actions: {
async getVoicemailsData (context) {
const res = await getAllVoicemails({
subscriberId: context.getters.getSubscriberId,
rows: 5
const res = await getAllCallsOrVoicemails({
subscriber_id: context.getters.getSubscriberId,
rows: 5,
order_by: 'timestamp',
order_by_direction: 'desc',
type: 'voicemail',
tz: getBrowserTimezone()
})
return res
},
async getCallsData (context) {
const res = await getAllCalls({
subscriberId: context.getters.getSubscriberId,
rows: 5
const res = await getAllCallsOrVoicemails({
subscriber_id: context.getters.getSubscriberId,
rows: 5,
order_by: 'timestamp',
order_by_direction: 'desc',
type: 'call',
tz: getBrowserTimezone()
})
return res
},
async getRegisteredDevicesData (context) {
const res = await getSubscriberRegistrations({
subscriber_id: context.getters.getSubscriberId,
rows: 5
rows: 5,
order_by: 'timestamp',
order_by_direction: 'desc',
tz: getBrowserTimezone()
})
return res
}

Loading…
Cancel
Save