diff --git a/src/api/conversations.js b/src/api/conversations.js index c026fdb7..5f7a8dae 100644 --- a/src/api/conversations.js +++ b/src/api/conversations.js @@ -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 }) } diff --git a/src/components/pages/Conversations/CscCallItem.vue b/src/components/pages/Conversations/CscCallItem.vue index 79e7437c..01ba472a 100644 --- a/src/components/pages/Conversations/CscCallItem.vue +++ b/src/components/pages/Conversations/CscCallItem.vue @@ -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 diff --git a/src/components/pages/Dashboard/CscCardDashboard.vue b/src/components/pages/Dashboard/CscCardDashboard.vue index bd8eecd2..ae5c616d 100644 --- a/src/components/pages/Dashboard/CscCardDashboard.vue +++ b/src/components/pages/Dashboard/CscCardDashboard.vue @@ -50,7 +50,60 @@ + > + + + + + + + + + {{ item.title }} + + {{ item.sub_title }} + + + + + + {{ item.extra_text }} + + + + + +
+ {{ error ? $t('Data loading error') : noItemsMessage }} +
+
+ +
+
diff --git a/src/helpers/call-utils.js b/src/helpers/call-utils.js new file mode 100644 index 00000000..f2685004 --- /dev/null +++ b/src/helpers/call-utils.js @@ -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' + } +} diff --git a/src/helpers/date-helper.js b/src/helpers/date-helper.js index a5b02873..3dadda38 100644 --- a/src/helpers/date-helper.js +++ b/src/helpers/date-helper.js @@ -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' +} diff --git a/src/i18n/en.json b/src/i18n/en.json index 6ca297c6..ca61ce6a 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -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", diff --git a/src/pages/CscPageDashboard.vue b/src/pages/CscPageDashboard.vue index 6c9b7aae..6f1f0ff3 100644 --- a/src/pages/CscPageDashboard.vue +++ b/src/pages/CscPageDashboard.vue @@ -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" /> @@ -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) } } } diff --git a/src/store/dashboard.js b/src/store/dashboard.js index 1bf0368d..7522d3a6 100644 --- a/src/store/dashboard.js +++ b/src/store/dashboard.js @@ -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 }