TT#20309 Conversations: As a Customer, I want to filter items by type (call, voicemail, fax, etc. ...)

What has been done:

TT#38957 Implement UI for the tab navigation
TT#38958 Implement filtering method
TT#38959 Implement update list method/incorporate existing reloadItems method

Change-Id: Ib606c25082c02b606c571cb033eb4f4a96f45eb6
changes/13/22213/9
Tijana Maksimovic 7 years ago committed by Hans-Peter Herzog
parent a64f92b9c4
commit dbea287fdc

@ -35,9 +35,10 @@ mysql < ./conversations_dump.sql
## VOICEMAIL
1. Go to Settings > Subscribers > Details > Master Data, and set "Primary Number"/E164 to the desired number (for example 43993007)
1. Go to Settings > Subscribers > Details > Preferences, and under "Call Forwards" create a call forward destination under "Call Forward Unconditional" to voicemail
1. Initiate a call from another subscriber to the subscriber you just set call forward for, and leave a voicemail
1. Go to Settings > Subscribers, choose a subscriber (for example 43993007) who will be a caller. Go to Details > Master Data > Edit, and set "Primary Number"/E164 to the desired number (in this case 43993007)
1. Go back to Settings > Subscribers, choose another subscriber (for example 43993006) who will act as a callee. Go to Details > Master Data > Edit, and set "Primary Number"/E164 to the desired number (in this case 43993006)
1. While in the second subscriber's details, go to Preferences, and under "Call Forwards" create a call forward destination under "Call Forward Unconditional" to voicemail
1. Initiate a call from the first subscriber to the subscriber you just set call forward for, and leave a voicemail
See [calls section](#calls) for information on how to initiate calls.

@ -1,19 +1,32 @@
import _ from 'lodash'
import { saveAs } from 'file-saver'
import Vue from 'vue'
import { getList } from './common'
export function getConversations(id, page, rows) {
return getList({
path: 'api/conversations/',
root: '_embedded.ngcp:conversations',
params: {
subscriber_id: id,
page: page,
rows: rows,
order_by: 'timestamp',
export function getConversations(options) {
return new Promise((resolve, reject)=>{
let type = _.get(options, 'type', null);
let params ={
subscriber_id: _.get(options, 'subscriberId'),
page: _.get(options, 'page', 1),
rows: _.get(options, 'rows', 25),
order_by: _.get(options, 'order_by', 'timestamp'),
order_by_direction: 'desc'
};
if(type !== null) {
params.type = type;
}
getList({
path: 'api/conversations/',
root: '_embedded.ngcp:conversations',
params: params
}).then((list)=>{
resolve(list);
}).catch((err)=>{
reject(err);
});
});
}

@ -3,41 +3,78 @@
ref="page"
class="csc-list-page"
>
<q-list
no-border
inset-separator
sparse
multiline
<q-tabs
inverted
color="primary"
align="justify"
v-model="selectedTab"
class="conversations-tabs"
>
<csc-conversation-item
v-for="(item, index) in items"
:key="item._id"
:item="item"
:call-available="isCallAvailable"
@init-call="initCall"
@download-fax="downloadFax"
@download-voice-mail="downloadVoiceMail"
@play-voice-mail="playVoiceMail"
<q-tab
default
name="call-fax-voicemail"
slot="title"
icon="inbox"
label="All"
@click="filterByType('call-fax-voicemail')"
/>
</q-list>
<div
v-if="isNextPageRequesting"
class="row justify-center"
>
<q-spinner-dots
color="primary"
:size="40"
<q-tab
name="call"
slot="title"
icon="call"
label="Calls"
@click="filterByType('call')"
/>
</div>
<div
v-if="!isNextPageRequesting && items.length === 0"
class="row justify-center"
>
{{ $t('pages.conversations.emptyListMessage') }}
</div>
<q-scroll-observable
@scroll="scroll"
/>
<q-tab
name="fax"
slot="title"
icon="description"
label="Faxes"
@click="filterByType('fax')"
/>
<q-tab
name="voicemail"
slot="title"
icon="voicemail"
label="Voicemails"
@click="filterByType('voicemail')"
/>
<q-list
no-border
inset-separator
sparse
multiline
>
<csc-conversation-item
v-for="(item, index) in items"
:key="item._id"
:item="item"
:call-available="isCallAvailable"
@init-call="initCall"
@download-fax="downloadFax"
@download-voice-mail="downloadVoiceMail"
@play-voice-mail="playVoiceMail"
/>
</q-list>
<div
v-if="isNextPageRequesting"
class="row justify-center"
>
<q-spinner-dots
color="primary"
:size="40"
/>
</div>
<div
v-if="!isNextPageRequesting && items.length === 0"
class="row justify-center"
>
{{ noResultsMessage }}
</div>
<q-scroll-observable
@scroll="scroll"
/>
</q-tabs>
</csc-page>
</template>
@ -58,13 +95,35 @@
scroll,
QList,
QSpinnerDots,
dom
dom,
QTabs,
QTab,
QTabPane
} from 'quasar-framework'
const { offset } = dom
export default {
data () {
return {
scrollEventEmitted: false
scrollEventEmitted: false,
selectedTab: 'call-fax-voicemail',
tabs: [
{
label: this.$t('pages.conversations.tabLabelAll'),
value: 'call-fax-voicemail'
},
{
label: this.$t('pages.conversations.tabLabelCalls'),
value: 'call'
},
{
label: this.$t('pages.conversations.tabLabelFaxes'),
value: 'fax'
},
{
label: this.$t('pages.conversations.tabLabelVoicemails'),
value: 'voicemail'
}
]
}
},
components: {
@ -72,7 +131,10 @@
CscConversationItem,
QScrollObservable,
QList,
QSpinnerDots
QSpinnerDots,
QTabs,
QTab,
QTabPane
},
mounted() {
this.$store.commit('conversations/resetList');
@ -92,7 +154,21 @@
...mapGetters('call', [
'callState',
'isCallAvailable'
])
]),
noResultsMessage() {
if(this.selectedTab === 'call-fax-voicemail') {
return this.$t('pages.conversations.emptyListMessage');
}
else if(this.selectedTab === 'call') {
return this.$t('pages.conversations.noCallsMessage');
}
else if(this.selectedTab === 'fax') {
return this.$t('pages.conversations.noFaxesMessage');
}
else if(this.selectedTab === 'voicemail') {
return this.$t('pages.conversations.noVoicemailsMessage');
}
}
},
methods: {
scroll(data) {
@ -105,8 +181,11 @@
this.scrollEventEmitted = false;
}
},
nextPage() {
this.$store.dispatch('conversations/nextPage');
nextPage(type) {
if(type === 'call-fax-voicemail') {
type = null;
}
this.$store.dispatch('conversations/nextPage', type);
},
initCall(call) {
this.layout.showRight();
@ -128,7 +207,20 @@
});
},
reloadItems() {
this.$store.dispatch('conversations/reloadItems', 1);
let type = this.selectedTab;
if(type === 'call-fax-voicemail') {
type = null;
}
this.$store.dispatch('conversations/reloadItems', {
retryCount: 1,
type: type
});
},
filterByType(type) {
if(type !== this.selectedTab) {
this.$store.commit('conversations/resetList');
this.$store.dispatch('conversations/nextPage', type);
}
}
},
watch: {
@ -168,7 +260,10 @@
let endedB = oldState === 'established' && newState === 'input';
let endedC = oldState === 'ringing' && newState === 'input';
let endedD = oldState === 'incoming' && newState === 'input';
if (endedA || endedB || endedC || endedD) {
if (endedA && ((this.selectedTab === 'call') || (this.selectedTab === 'call-fax-voicemail'))
|| endedB && ((this.selectedTab === 'call') || (this.selectedTab === 'call-fax-voicemail'))
|| endedC && ((this.selectedTab === 'call') || (this.selectedTab === 'call-fax-voicemail'))
|| endedD && ((this.selectedTab === 'call') || (this.selectedTab === 'call-fax-voicemail'))) {
this.reloadItems();
}
},

@ -120,7 +120,14 @@
"downloadFaxSuccessMessage": "Fax downloaded successfully",
"downloadFaxErrorMessage": "Downloading of fax failed",
"emptyListMessage": "No Calls, Voicemails or Faxes found",
"reloadItemsErrorMessage": "Reloading conversation items failed"
"noFaxesMessage": "No Faxes found",
"noVoicemailsMessage": "No Voicemails found",
"noCallsMessage": "No Calls found",
"reloadItemsErrorMessage": "Reloading conversation items failed",
"tabLabelAll": "All",
"tabLabelCalls": "Calls",
"tabLabelFaxes": "Faxes",
"tabLabelVoicemails": "Voicemails"
},
"reminder": {
"toggleEnabled": "Reminder is enabled",

@ -194,22 +194,26 @@ export default {
}
},
actions: {
reloadItems(context, retryCount) {
reloadItems(context, options) {
context.commit('reloadItemsRequesting');
let rows = context.state.currentPage * ROWS_PER_PAGE;
let firstStateItemTimestamp = context.state.items[0] ?
context.state.items[0].start_time : null;
if (retryCount < ReloadConfig.retryLimit) {
getConversations(
context.getters.getSubscriberId,
1,
rows
).then((result) => {
if (options.retryCount < ReloadConfig.retryLimit) {
getConversations({
subscriberId: context.getters.getSubscriberId,
page: 1,
rows: rows,
type: options.type
}).then((result) => {
let firstResultItemTimestamp = result.items[0] ?
result.items[0].start_time : null;
if (_.isEqual(firstStateItemTimestamp, firstResultItemTimestamp)) {
setTimeout(() => {
context.dispatch('reloadItems', ++retryCount);
context.dispatch('reloadItems', {
retryCount: ++options.retryCount,
type: options.type
});
}, ReloadConfig.retryDelay);
}
else {
@ -247,15 +251,16 @@ export default {
context.commit('playVoiceMailFailed', options.id, err.mesage);
});
},
nextPage(context) {
nextPage(context, type) {
let page = context.getters.currentPage + 1;
if(context.getters.lastPage === null || page <= context.getters.lastPage) {
context.commit('nextPageRequesting');
getConversations(
context.getters.getSubscriberId,
page,
ROWS_PER_PAGE
).then((result) => {
getConversations({
subscriberId: context.getters.getSubscriberId,
page: page,
rows: ROWS_PER_PAGE,
type: type
}).then((result) => {
context.commit('nextPageSucceeded', result);
}).catch((err)=>{
context.commit('nextPageFailed', err.message);

Loading…
Cancel
Save