TT#47386 Create new call queue config item

What has been done:
- TT#47830, Implement validation for CallQueueConfiguration creation form
- TT#47829, Implement UI for creation of new CallQueueConfiguration item
- TT#47828, Create API method for adding a new CallQueueConfiguration item
- TT#47831, Implement state handling for CallQueueConfiguration creation of
item

Change-Id: Ie9832f9cfa18329a81aa65b588f2752c7c6cfb3a
changes/18/25018/11
raxelsen 7 years ago committed by Hans-Peter Herzog
parent 4320ab2a90
commit 5e29490ead

@ -5,16 +5,11 @@ case "$1" in
ngcpcfg set /etc/ngcp-config/config.yml www_admin.http_csc.csc_dev=yes
ngcpcfg set /etc/ngcp-config/config.yml www_admin.http_csc.csc_js_enable=yes
ngcpcfg set /etc/ngcp-config/config.yml rtcengine.enable=yes
ngcpcfg set /etc/ngcp-config/config.yml pbx.enable=yes
ngcpcfg set /etc/ngcp-config/config.yml www_admin.privileges.subscriberadmin.subscribers.0=write
ngcpcfg set /etc/ngcp-config/config.yml email.smarthost.hostname=mail.sipwise.com
# Mandatory flags to enable conferencing
ngcpcfg set /etc/ngcp-config/config.yml rtcengine.conference.enable=yes
ngcpcfg set /etc/ngcp-config/config.yml janus.enable=yes
ngcpcfg set /etc/ngcp-config/config.yml fileshare.enable=yes
# Apply changes
ngcpcfg set /etc/ngcp-config/config.yml pbx.enable=yes
ngcpcfg set /etc/ngcp-config/config.yml www_admin.privileges.subscriberadmin.subscribers.0=write
ngcpcfg apply 'Enable CSC, PBX and RtcEngine'
;;
esac

@ -16,7 +16,8 @@ import {
setPbxGroupIds,
getSubscribers,
getSubscriber,
getSubscribersByCallQueueEnabled
getSubscribersByCallQueueEnabled,
addNewCallQueueConfig
} from './subscriber';
import uuid from 'uuid';
import { getList, get, patchReplace } from './common'
@ -528,6 +529,7 @@ export function getCallQueueConfigurations() {
getSubscribersByCallQueueEnabled().then((subscribers)=>{
let callQueues = subscribers.map((subscriber)=>{
return {
id: _.get(subscriber, 'id', null),
display_name: _.get(subscriber, 'display_name', null),
is_pbx_group: _.get(subscriber, 'is_pbx_group', null),
max_queue_length: _.get(subscriber, 'prefs.max_queue_length', 5),
@ -542,3 +544,13 @@ export function getCallQueueConfigurations() {
});
});
}
export function addCallQueueConfig(id, config) {
return new Promise((resolve, reject)=>{
addNewCallQueueConfig(id, config).then(() => {
resolve();
}).catch((err)=>{
reject(err);
});
});
}

@ -332,3 +332,7 @@ export function getSubscribersByCallQueueEnabled() {
});
});
}
export function addNewCallQueueConfig(id, config) {
return Vue.http.put('api/subscriberpreferences/' + id, config);
}

@ -66,6 +66,7 @@
dark
readonly
:value="subscriber.max_queue_length"
suffix="callers"
/>
</q-field>
<q-field

@ -0,0 +1,200 @@
<template>
<div class="csc-form csc-pbx-call-queue-add-form">
<q-field>
<q-select
dark
:disabled="loading"
:readonly="loading"
v-model="data.subscriber_id"
chips
clearable
:float-label="$t('pbxConfig.queueExtensionName')"
:options="options"
/>
</q-field>
<q-field :error-label="maxQueueLengthErrorMessage">
<q-input
dark
@input="$v.data.max_queue_length.$touch"
@blur="$v.data.max_queue_length.$touch"
:error="$v.data.max_queue_length.$error"
:disabled="loading"
:readonly="loading"
v-model="data.max_queue_length"
autofocus
:float-label="$t('pbxConfig.queueLength')"
clearable
suffix="callers"
/>
</q-field>
<q-field :error-label="wrapUpTimeErrorMessage">
<q-input
dark
@input="$v.data.queue_wrap_up_time.$touch"
@blur="$v.data.queue_wrap_up_time.$touch"
:error="$v.data.queue_wrap_up_time.$error"
:disabled="loading"
:readonly="loading"
v-model="data.queue_wrap_up_time"
:float-label="$t('pbxConfig.wrapUpTime')"
clearable
suffix="seconds"
/>
</q-field>
<div class="csc-form-actions row justify-center">
<q-btn
v-if="!loading"
flat
color="default"
icon="clear"
@mousedown.native="cancel()"
>
{{ $t('buttons.cancel') }}
</q-btn>
<q-btn
v-if="!loading"
:disabled="$v.data.$invalid"
flat
color="primary"
icon="person"
@click="save()"
>
{{ $t('pbxConfig.createConfig') }}
</q-btn>
</div>
<q-inner-loading :visible="loading">
<q-spinner-mat size="60px" color="primary" />
</q-inner-loading>
</div>
</template>
<script>
import {
required,
maxValue,
minValue,
numeric
} from 'vuelidate/lib/validators'
import {
QCard,
QCardTitle,
QCardMain,
QCardActions,
QCardSeparator,
QBtn,
QInnerLoading,
QSpinnerMat,
QField,
QInput,
QSelect,
QIcon
} from 'quasar-framework'
export default {
name: 'csc-pbx-call-queue-add-form',
props: [
'options',
'loading'
],
components: {
QCard,
QCardTitle,
QCardMain,
QCardActions,
QCardSeparator,
QBtn,
QInnerLoading,
QSpinnerMat,
QField,
QInput,
QSelect,
QIcon
},
validations: {
data: {
subscriber_id: {
required
},
max_queue_length: {
numeric,
minValue: minValue(1),
maxValue: maxValue(3600)
},
queue_wrap_up_time: {
numeric,
minValue: minValue(1),
maxValue: maxValue(3600)
}
}
},
data () {
return {
data: this.getDefaults()
}
},
computed: {
maxQueueLengthErrorMessage() {
if (!this.$v.data.max_queue_length.numeric) {
return this.$t('validationErrors.numeric', {
field: this.$t('pbxConfig.queueLength'),
});
}
else if (!this.$v.data.max_queue_length.minValue) {
return this.$t('validationErrors.minValueSecond', {
field: this.$t('pbxConfig.queueLength'),
minValue: this.$v.data.max_queue_length.$params.minValue.min
});
}
else if (!this.$v.data.max_queue_length.maxValue) {
return this.$t('validationErrors.maxValueSecond', {
field: this.$t('pbxConfig.queueLength'),
maxValue: this.$v.data.max_queue_length.$params.maxValue.max
});
}
},
wrapUpTimeErrorMessage() {
if (!this.$v.data.queue_wrap_up_time.numeric) {
return this.$t('validationErrors.numeric', {
field: this.$t('pbxConfig.wrapUpTime'),
});
}
else if (!this.$v.data.queue_wrap_up_time.minValue) {
return this.$t('validationErrors.minValueSecond', {
field: this.$t('pbxConfig.wrapUpTime'),
minValue: this.$v.data.queue_wrap_up_time.$params.minValue.min
});
}
else if (!this.$v.data.queue_wrap_up_time.maxValue) {
return this.$t('validationErrors.maxValueSecond', {
field: this.$t('pbxConfig.wrapUpTime'),
maxValue: this.$v.data.queue_wrap_up_time.$params.maxValue.max
});
}
}
},
methods: {
getDefaults() {
return {
subscriber_id: null,
max_queue_length: null,
queue_wrap_up_time: null
}
},
cancel() {
this.$emit('cancel');
},
save() {
this.$emit('save', this.data);
},
reset() {
this.data = this.getDefaults();
this.$v.$reset();
}
}
}
</script>
<style lang="stylus" rel="stylesheet/stylus">
@import '../../../themes/app.common.styl';
</style>

@ -3,6 +3,32 @@
<csc-page
:is-list="true"
>
<div
v-show="!addFormEnabled"
class="row justify-center"
>
<q-btn
color="primary"
icon="add"
flat
@click="enableAddForm"
>
{{ $t('pbxConfig.addConfig') }}
</q-btn>
</div>
<div
class="row justify-center"
v-show="addFormEnabled"
>
<csc-pbx-call-queue-add-form
class="col-xs-12 col-md-6 csc-list-form"
ref="addForm"
:options="callQueueGroupsAndSeatsOptions"
:loading="isAdding"
@save="addConfig"
@cancel="disableAddForm"
/>
</div>
<div
v-if="isListLoadingVisible"
class="row justify-center"
@ -38,6 +64,7 @@
<script>
import CscPage from '../../CscPage'
import CscPbxCallQueue from './CscPbxCallQueue'
import CscPbxCallQueueAddForm from './CscPbxCallQueueAddForm'
import { mapGetters } from 'vuex'
import {
QField,
@ -51,12 +78,14 @@
QItemMain,
QItemTile,
Platform,
QSpinnerDots
QSpinnerDots,
QBtn
} from 'quasar-framework'
export default {
components: {
CscPbxCallQueue,
CscPage,
CscPbxCallQueue,
CscPbxCallQueueAddForm,
QField,
QInput,
QIcon,
@ -67,28 +96,60 @@
QItemSide,
QItemMain,
QItemTile,
QSpinnerDots
QSpinnerDots,
QBtn
},
data () {
return {
addFormEnabled: false
}
},
mounted() {
this.$store.dispatch('pbxConfig/listCallQueueGroupsAndSeats');
this.$store.dispatch('pbxConfig/getAllGroupsAndSeats');
},
computed: {
...mapGetters('pbxConfig', [
'callQueueGroupsAndSeats',
'isListLoadingVisible',
'isListRequesting'
'isListRequesting',
'callQueueGroupsAndSeatsOptions',
'isAdding',
'addState'
]),
isMobile() {
return Platform.is.mobile;
}
},
methods: {
addConfig(data) {
let config = {
max_queue_length: data.max_queue_length,
queue_wrap_up_time: data.queue_wrap_up_time
};
this.$store.dispatch('pbxConfig/addCallQueueConfig', {
id: data.subscriber_id,
config: config
});
},
enableAddForm() {
this.resetAddForm();
this.addFormEnabled = true;
},
disableAddForm() {
this.resetAddForm();
this.addFormEnabled = false;
},
resetAddForm() {
this.$refs.addForm.reset();
}
},
watch: {
addState(state) {
if (state === 'succeeded') {
this.disableAddForm();
}
}
}
}
</script>

@ -29,7 +29,6 @@
@cancel="disableAddForm"
/>
</div>
<div
v-if="isListLoadingVisible"
class="row justify-center"

@ -393,7 +393,9 @@
"createGroup": "Create group",
"queueLength": "Queue Length",
"wrapUpTime": "Wrap Up Time",
"queueExtensionName": "Group/Seat/Pilot"
"queueExtensionName": "Group/Seat/Pilot",
"addConfig": "Add Call Queue",
"createConfig": "Create Call Queue"
},
"callBlocking": {
"privacyEnabledToast": "Your number is hidden to the callee",

@ -31,7 +31,8 @@ import {
setProfile,
getGroup,
getSeat,
getCallQueueConfigurations
getCallQueueConfigurations,
addCallQueueConfig
} from '../../api/pbx-config'
export default {
@ -426,5 +427,18 @@ export default {
}).catch((err) => {
context.commit('callQueueListFailed', err.message);
});
},
addCallQueueConfig(context, data) {
let config = Object.assign(data.config, {
cloud_pbx_callqueue: true
});
context.commit('addItemRequesting', config);
addCallQueueConfig(data.id, config).then(() => {
return context.dispatch('listCallQueueGroupsAndSeats', true);
}).then(() => {
context.commit('addItemSucceeded');
}).catch((err) => {
context.commit('addItemFailed', err.message);
});
}
}

@ -298,5 +298,21 @@ export default {
},
callQueueGroupsAndSeats(state) {
return state.callQueueGroupsAndSeats;
},
assignableGroupsAndSeatsOptions(state, getters) {
return getters.groupsAndSeatsOptions.filter((option) => {
return option.label !== 'Unassigned';
});
},
callQueueGroupsAndSeatsOptions(state, getters) {
let ids = state.callQueueGroupsAndSeats.map((item) => {
return item.id;
});
let options = getters.assignableGroupsAndSeatsOptions
.filter((item) => {
return ids.indexOf(item.value) === -1;
}
);
return options;
}
}

@ -49,4 +49,30 @@ describe('PBX Configuration Store', () => {
assert.equal(state.groups[5], data.groups.items[1]);
assert.deepEqual(state.numbers, data.numbers);
});
it('should list all group/seat/pilot call queue configs', function(){
let state = {
callQueueGroupsAndSeats: []
};
let data = {
items: [
{
display_name: "123",
is_pbx_group: false,
max_queue_length: "10",
queue_wrap_up_time: "5"
},
{
display_name: "456",
is_pbx_group: false,
max_queue_length: "5",
queue_wrap_up_time: "10"
}
]
};
PbxConfig.mutations.callQueueListSucceeded(state, data);
assert.deepEqual(state.callQueueGroupsAndSeats[0], data.items[0]);
assert.deepEqual(state.callQueueGroupsAndSeats[1], data.items[1]);
});
});

Loading…
Cancel
Save