What has been done: - TT#23719, Conversations: Discover the conversations endpoint and investigate dev tests - TT#23812, Conversations: Implement store with needed states - TT#23813, Conversations: Implement minimal card component - TT#23814, Conversations: Implement store and api tests - TT#23815, Conversations: Implement action and api request Change-Id: I40231aded1309695d9a2ab15e196db7c83b62018changes/36/16436/16
parent
6ab38fcbb7
commit
256cd94cb5
@ -0,0 +1,13 @@
|
||||
|
||||
import Vue from 'vue';
|
||||
import { getJsonBody } from './utils'
|
||||
|
||||
export function getConversations(id) {
|
||||
return new Promise((resolve, reject) => {
|
||||
Vue.http.get('/api/conversations/?subscriber_id=' + id).then((result)=>{
|
||||
resolve(getJsonBody(result.body)._embedded['ngcp:conversations']);
|
||||
}).catch((err)=>{
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
<template>
|
||||
<div class="csc-collapsible">
|
||||
<q-collapsible :icon="icon"
|
||||
:label="label"
|
||||
:sublabel="sublabel">
|
||||
</q-collapsible>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { QCollapsible } from 'quasar-framework'
|
||||
export default {
|
||||
name: 'csc-collapsible',
|
||||
props: [
|
||||
'icon',
|
||||
'label',
|
||||
'sublabel'
|
||||
],
|
||||
components: {
|
||||
QCollapsible
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus">
|
||||
@import '~variables'
|
||||
.csc-collapsible
|
||||
.q-collapsible
|
||||
.q-item-icon
|
||||
font-size 22px
|
||||
padding-right 12px
|
||||
color $secondary
|
||||
.q-item-label
|
||||
color black
|
||||
font-size 18px
|
||||
font-weight 400
|
||||
</style>
|
@ -1,18 +1,88 @@
|
||||
<template>
|
||||
<csc-page title="Conversations"></csc-page>
|
||||
<csc-page :title="$t('pages.conversations.title')">
|
||||
<q-card v-for="conversation in conversations" :key="conversation.caller"
|
||||
class="conversation-card">
|
||||
<csc-collapsible :icon="getCollapsibleIcons(conversation)"
|
||||
:label="getCollapsibleLabel(conversation)"
|
||||
:sublabel="conversation.start_time | readableDate">
|
||||
</csc-collapsible>
|
||||
<div v-if="hasCallOption(conversation.type)">
|
||||
<q-card-separator />
|
||||
<q-card-actions align="center">
|
||||
<q-btn flat round small color="primary" icon="call">{{ $t('pages.conversations.buttons.call') }}</q-btn>
|
||||
</q-card-actions>
|
||||
</div>
|
||||
</q-card>
|
||||
</csc-page>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CscPage from '../CscPage'
|
||||
import CscCollapsible from '../card/CscCollapsible'
|
||||
import { QBtn, QCardActions, QCard,
|
||||
QCardSeparator } from 'quasar-framework'
|
||||
export default {
|
||||
data () {
|
||||
return {}
|
||||
return {
|
||||
conversations: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$store.dispatch('conversations/loadConversations').then(() => {
|
||||
this.conversations = this.$store.state.conversations.
|
||||
conversations;
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
},
|
||||
components: {
|
||||
CscPage
|
||||
CscPage,
|
||||
QBtn,
|
||||
QCard,
|
||||
QCardActions,
|
||||
QCardSeparator,
|
||||
CscCollapsible
|
||||
},
|
||||
methods: {
|
||||
hasCallOption(type) {
|
||||
return (['call', 'call forward', 'sms', 'voicemail']
|
||||
.indexOf(type) > -1);
|
||||
},
|
||||
getCollapsibleIcons(item) {
|
||||
let directionIcon = item.direction == 'out' ? 'call_made' :
|
||||
'call_received';
|
||||
switch (item.type) {
|
||||
case 'call':
|
||||
return 'phone ' + directionIcon;
|
||||
break;
|
||||
case 'call forward':
|
||||
return 'call_merge ' + directionIcon;
|
||||
break;
|
||||
case 'voicemail':
|
||||
return 'voicemail ' + directionIcon;
|
||||
break;
|
||||
case 'fax':
|
||||
return 'insert_drive_file ' + directionIcon;
|
||||
break;
|
||||
case 'sms':
|
||||
return 'txtsms ' + directionIcon;
|
||||
break;
|
||||
};
|
||||
},
|
||||
getCollapsibleLabel(item) {
|
||||
let prefix = item.status == 'ok' ? this.$t('pages.conversations.labels.successful')
|
||||
: this.$t('pages.conversations.labels.unsuccessful');
|
||||
let direction = item.direction == 'in' ? this.$t('pages.conversations.labels.from') : this.$t('pages.conversations.labels.to');
|
||||
return `${prefix} ${item.type} ${direction} ${item.caller}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
<style lang="stylus">
|
||||
@import '~variables'
|
||||
.conversation-card
|
||||
padding 15px
|
||||
.q-btn
|
||||
margin-bottom -10px
|
||||
</style>
|
||||
|
@ -0,0 +1,7 @@
|
||||
import { date } from 'quasar'
|
||||
const { formatDate } = date
|
||||
|
||||
export default function(value) {
|
||||
var timeStamp = new Date(value);
|
||||
return `${formatDate(timeStamp, 'MMMM D, YYYY')} at ${formatDate(timeStamp, 'h:mm a')}`;
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
|
||||
import Vue from 'vue';
|
||||
import NumberFilter from './number'
|
||||
import DateFilter from './date'
|
||||
|
||||
Vue.filter('number', NumberFilter);
|
||||
Vue.filter('readableDate', DateFilter);
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 7.0 KiB |
@ -0,0 +1,41 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
import _ from 'lodash';
|
||||
import { getConversations } from '../api/conversations';
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state: {
|
||||
conversations: [
|
||||
]
|
||||
},
|
||||
mutations: {
|
||||
loadConversations(state, options) {
|
||||
let list = [];
|
||||
_.forEach(options, function(item) {
|
||||
delete item._links;
|
||||
if (item.type == 'call') {
|
||||
item.type = item.call_type != 'call' ? 'call forward'
|
||||
: item.type;
|
||||
};
|
||||
list.push(item);
|
||||
})
|
||||
state.conversations = list;
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
loadConversations(context) {
|
||||
return new Promise((resolve, reject)=>{
|
||||
getConversations(localStorage.getItem('subscriberId'))
|
||||
.then((result)=>{
|
||||
context.commit('loadConversations', result);
|
||||
resolve();
|
||||
})
|
||||
.catch((err)=>{
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
@ -0,0 +1,72 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
import Vue from 'vue';
|
||||
import VueResource from 'vue-resource';
|
||||
import { getConversations } from '../../src/api/conversations';
|
||||
import { assert } from 'chai';
|
||||
|
||||
Vue.use(VueResource);
|
||||
|
||||
describe('Conversations', function(){
|
||||
|
||||
const subscriberId = 123;
|
||||
|
||||
it('should get all data regarding conversations', function(done){
|
||||
|
||||
let innerData = [{
|
||||
"_links" : {
|
||||
"collection" : {
|
||||
"href" : "/api/conversations/"
|
||||
},
|
||||
"curies" : {
|
||||
"href" : "http://purl.org/sipwise/ngcp-api/#rel-{rel}",
|
||||
"name" : "ngcp",
|
||||
"templated" : true
|
||||
},
|
||||
"ngcp:calls" : {
|
||||
"href" : "/api/calls/5"
|
||||
},
|
||||
"ngcp:conversations" : {
|
||||
"href" : "/api/conversations/5?type=call"
|
||||
},
|
||||
"profile" : {
|
||||
"href" : "http://purl.org/sipwise/ngcp-api/"
|
||||
},
|
||||
"self" : {
|
||||
"href" : "/api/conversations/5?type=call"
|
||||
}
|
||||
},
|
||||
"call_id" : "cT1miqD5Nw",
|
||||
"call_type" : "cfu",
|
||||
"callee" : "vmu43993006@voicebox.local",
|
||||
"caller" : "43993006",
|
||||
"direction" : "out",
|
||||
"duration" : "0:00:19.672",
|
||||
"id" : 5,
|
||||
"rating_status" : "ok",
|
||||
"start_time" : "2017-11-10 08:51:10.452",
|
||||
"status" : "ok",
|
||||
"type" : "call"
|
||||
}];
|
||||
let data = {
|
||||
"_embedded": {
|
||||
"ngcp:conversations": innerData
|
||||
}
|
||||
};
|
||||
|
||||
Vue.http.interceptors = [];
|
||||
Vue.http.interceptors.unshift((request, next)=>{
|
||||
next(request.respondWith(JSON.stringify(data), {
|
||||
status: 200
|
||||
}));
|
||||
});
|
||||
getConversations(subscriberId).then((result)=>{
|
||||
assert.deepEqual(result, innerData);
|
||||
done();
|
||||
}).catch((err)=>{
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
@ -0,0 +1,44 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
import ConversationsModule from '../../src/store/conversations';
|
||||
import { assert } from 'chai';
|
||||
|
||||
describe('Conversations', function(){
|
||||
|
||||
it('should load conversations', function(){
|
||||
let state = {
|
||||
conversations: [
|
||||
]
|
||||
};
|
||||
let data = [
|
||||
{
|
||||
"_links": {
|
||||
},
|
||||
"call_type": "cfu",
|
||||
"caller": "43993010",
|
||||
"type": "call"
|
||||
},
|
||||
{
|
||||
"_links": {
|
||||
},
|
||||
"caller": "43993011",
|
||||
"type": "fax"
|
||||
}
|
||||
];
|
||||
ConversationsModule.mutations.loadConversations(state, data);
|
||||
assert.deepEqual(state.conversations, [
|
||||
{
|
||||
"call_type": "cfu",
|
||||
"caller": "43993010",
|
||||
"type": "call forward"
|
||||
},
|
||||
{
|
||||
"caller": "43993011",
|
||||
"type": "fax"
|
||||
}
|
||||
]);
|
||||
|
||||
});
|
||||
|
||||
});
|
Loading…
Reference in new issue