MT#32999 Customer admin must be able to configure seat's call forward

With this improvement the customer administrator can configure
the call forwards of subscribers that belong to it.
The setting can be done in the CSC Seat page inside the
PBX Configurations.

Change-Id: I3dd4c7ba7e34725705da69bdf28fae93a379aee0
pull/27/merge
CORP\franci11 3 years ago committed by Marco Capetta
parent 64e8ff3d14
commit 58361b087e

@ -19,36 +19,30 @@ export async function cfLoadDestinationSets (subscriberId) {
return getList({ return getList({
resource: 'cfdestinationsets', resource: 'cfdestinationsets',
all: true, all: true,
params: { params: (subscriberId) ? { subscriber_id: subscriberId } : {}
subscriber_id: subscriberId
}
}) })
} }
export async function cfLoadSourceSets (subscriberId) { export async function cfLoadSourceSets (subscriberId) {
return getList({ return getList({
resource: 'cfsourcesets', resource: 'cfsourcesets',
params: { params: (subscriberId) ? { subscriber_id: subscriberId } : {}
subscriber_id: subscriberId
}
}) })
} }
export async function cfLoadTimeSets (subscriberId) { export async function cfLoadTimeSets (subscriberId) {
return getList({ return getList({
resource: 'cftimesets', resource: 'cftimesets',
params: { params: (subscriberId) ? { subscriber_id: subscriberId } : {}
subscriber_id: subscriberId
}
}) })
} }
export async function cfLoadMappingsFull (subscriberId) { export async function cfLoadMappingsFull (subscriberId) {
return await Promise.all([ return await Promise.all([
cfLoadMappings(subscriberId), cfLoadMappings(subscriberId),
cfLoadDestinationSets(subscriberId), cfLoadDestinationSets(),
cfLoadSourceSets(subscriberId), cfLoadSourceSets(),
cfLoadTimeSets(subscriberId) cfLoadTimeSets()
]) ])
} }

@ -1,33 +1,46 @@
<template> <template>
<csc-page-sticky <csc-page-sticky-tabs
id="csc-page-pbx-seats-details" id="csc-page-pbx-seats-details"
class="row q-pa-lg" ref="pageSticky"
:value="selectedTab"
> >
<template <template
v-slot:header-align-left v-slot:tabs
> >
<q-breadcrumbs <q-breadcrumbs
v-if="seatSelected" v-if="seatSelected"
class="text-weight-light q-mr-md" class="q-item absolute absolute-left text-weight-light"
active-color="primary" active-color="primary"
separator-color="primary" separator-color="primary"
> >
<q-breadcrumbs-el <q-breadcrumbs-el
key="seats" key="seats"
class="cursor-pointer" class="cursor-pointer"
to="/user/pbx-configuration/seats" to="/user/pbx-configuration/seats"
:label="$t('Seats')" :label="$t('Seats')"
icon="person" icon="person"
/> />
<q-breadcrumbs-el <q-breadcrumbs-el
key="seat" key="seat"
:label="seatSelected.display_name" :label="seatSelected.display_name"
/> />
</q-breadcrumbs> </q-breadcrumbs>
<q-tab
v-for="tab in tabs"
class="d-flex justify-content-center"
:key="tab.value"
:name="tab.value"
:icon="tab.icon"
:label="tab.label"
:default="tab.value === selectedTab"
@click="selectTab(tab.value)"
/>
</template> </template>
<q-item <q-item
class="col col-xs-12 col-md-6" class="col col-xs-12 col-md-6"
v-if="selectedTab === 'preferences'"
> >
<q-list <q-list
@ -236,7 +249,93 @@
</q-list> </q-list>
</q-item> </q-item>
</csc-page-sticky> <q-list
class="col col-xs-12 col-md-6"
v-else
>
<!-- v-else-if="selectedTab === 'callForwards'" -->
<!-- v-if="hasSubscriberProfileAttributes(['cfu', 'cfna', 'cfb'])" -->
<q-item
class="row justify-center q-pt-lg"
>
<q-btn
flat
icon="add"
color="primary"
:label="$t('Add forwarding')"
:disable="$wait.is('csc-cf-mappings-full')"
:loading="$wait.is('csc-cf-mappings-full')"
>
<csc-popup-menu>
<csc-popup-menu-item
v-if="hasSubscriberProfileAttribute('cfu')"
color="primary"
:label="$t('If available')"
@click="createMapping({ type: 'cfu', subscriberId: id})"
/>
<csc-popup-menu-item
v-if="hasSubscriberProfileAttribute('cfna')"
color="primary"
:label="$t('If not available')"
@click="createMapping({ type: 'cfna', subscriberId: id})"
/>
<csc-popup-menu-item
v-if="hasSubscriberProfileAttribute('cfb')"
color="primary"
:label="$t('If busy')"
@click="createMapping({ type: 'cfb', subscriberId: id})"
/>
</csc-popup-menu>
<template
v-slot:loading
>
<csc-spinner />
</template>
</q-btn>
</q-item>
<q-item
class="row justify-center q-pt-lg"
>
<div
id="csc-wrapper-call-forwarding"
class="col-xs-12 col-lg-8"
>
<q-list
v-if="groups.length === 0 && !$wait.is('csc-cf-mappings-full')"
dense
separator
>
<q-item
:disable="$wait.is('csc-cf-mappings-full')"
>
<q-item-section>
<q-item-label
class="text-weight-bold"
>
{{ $t('Always') }}
</q-item-label>
</q-item-section>
</q-item>
<csc-cf-group-item-primary-number />
</q-list>
<template
v-for="group in groups"
>
<csc-cf-group
:key="group.cfm_id"
class="q-mb-lg"
:loading="$wait.is('csc-cf-mappings-full')"
:mapping="group"
:destination-set="destinationSetMap[group.destinationset_id]"
:source-set="sourceSetMap[group.sourceset_id]"
:time-set="timeSetMap[group.timeset_id]"
/>
</template>
</div>
</q-item>
</q-list>
</csc-page-sticky-tabs>
</template> </template>
<script> <script>
@ -254,10 +353,16 @@ import {
mapGetters, mapGetters,
mapActions mapActions
} from 'vuex' } from 'vuex'
import CscCfGroup from 'components/call-forwarding/CscCfGroup'
import CscCfGroupItemPrimaryNumber from 'components/call-forwarding/CscCfGroupItemPrimaryNumber'
import CscPopupMenu from 'components/CscPopupMenu'
import CscPopupMenuItem from 'components/CscPopupMenuItem'
import CscPageStickyTabs from 'components/CscPageStickyTabs'
import CscInputButtonSave from 'components/form/CscInputButtonSave' import CscInputButtonSave from 'components/form/CscInputButtonSave'
import CscInputButtonReset from 'components/form/CscInputButtonReset' import CscInputButtonReset from 'components/form/CscInputButtonReset'
import CscChangePasswordDialog from 'src/components/CscChangePasswordDialog' import CscChangePasswordDialog from 'src/components/CscChangePasswordDialog'
import CscPageSticky from 'src/components/CscPageSticky' import CscPageSticky from 'src/components/CscPageSticky'
import CscSpinner from 'components/CscSpinner'
import { inRange } from 'src/helpers/validation' import { inRange } from 'src/helpers/validation'
import numberFilter from '../filters/number' import numberFilter from '../filters/number'
import { import {
@ -271,16 +376,27 @@ export default {
CscInputButtonReset, CscInputButtonReset,
CscInputButtonSave, CscInputButtonSave,
CscChangePasswordDialog, CscChangePasswordDialog,
CscPageSticky CscPageSticky,
CscPageStickyTabs,
CscPopupMenu,
CscPopupMenuItem,
CscCfGroupItemPrimaryNumber,
CscCfGroup,
CscSpinner
}, },
props: { props: {
initialTab: {
type: String,
default: 'preferences'
}
}, },
data () { data () {
return { return {
changes: null, changes: null,
id: this.$route.params.id, id: this.$route.params.id,
soundSet: null, soundSet: null,
currentCli: "" currentCli: "",
selectedTab: this.initialTab
} }
}, },
validations: { validations: {
@ -301,11 +417,38 @@ export default {
} }
}, },
computed: { computed: {
tabs () {
return [
{
label: this.$t('Preferences'),
value: 'preferences',
icon: 'perm_phone_msg'
},
{
label: this.$t('Call Forwards'),
value: 'callForwards',
icon: 'forward_to_inbox'
}
]
},
...mapState('pbxSeats', [ ...mapState('pbxSeats', [
'seatSelected', 'seatSelected',
'seatUpdateState', 'seatUpdateState',
'seatUpdateError' 'seatUpdateError'
]), ]),
...mapState('callForwarding', [
'mappings',
'destinationSetMap',
'sourceSetMap',
'timeSetMap'
]),
...mapGetters('callForwarding', [
'groups'
]),
...mapGetters('user', [
'hasSubscriberProfileAttribute',
'hasSubscriberProfileAttributes'
]),
...mapGetters('pbxSeats', [ ...mapGetters('pbxSeats', [
'getSoundSetBySeatId', 'getSoundSetBySeatId',
'hasCallQueue', 'hasCallQueue',
@ -443,6 +586,8 @@ export default {
}, },
async mounted () { async mounted () {
this.selectSeat(this.id) this.selectSeat(this.id)
await this.loadAnnouncements()
this.loadMappingsFull(this.id)
}, },
beforeDestroy () { beforeDestroy () {
this.resetSelectedSeat() this.resetSelectedSeat()
@ -460,6 +605,11 @@ export default {
'loadPreferences', 'loadPreferences',
'setCli' 'setCli'
]), ]),
...mapActions('callForwarding', [
'loadMappingsFull',
'createMapping',
'loadAnnouncements'
]),
...mapActions('pbxCallQueues', [ ...mapActions('pbxCallQueues', [
'jumpToCallQueue' 'jumpToCallQueue'
]), ]),
@ -471,6 +621,14 @@ export default {
'getPrimaryNumberOptions', 'getPrimaryNumberOptions',
'numbers' 'numbers'
]), ]),
selectTab (tabName) {
if (this.selectedTab !== tabName) {
this.forceTabReload(tabName)
}
},
forceTabReload (tabName) {
this.selectedTab = tabName
},
getAliasNumberIds () { getAliasNumberIds () {
const numberIds = [] const numberIds = []
this.seatSelected.alias_numbers.forEach((number) => { this.seatSelected.alias_numbers.forEach((number) => {

@ -42,9 +42,14 @@ function createDefaultDestination (destination, defaultAnnouncementId) {
return payload return payload
} }
export async function loadMappingsFull ({ dispatch, commit, rootGetters }) { export async function loadMappingsFull ({ dispatch, commit, rootGetters }, payload) {
dispatch('wait/start', WAIT_IDENTIFIER, { root: true }) dispatch('wait/start', WAIT_IDENTIFIER, { root: true })
const res = await cfLoadMappingsFull(rootGetters['user/getSubscriberId']) let res = null
if (payload) {
res = await cfLoadMappingsFull(payload)
} else {
res = await cfLoadMappingsFull(rootGetters['user/getSubscriberId'])
}
commit('dataSucceeded', { commit('dataSucceeded', {
mappings: res[0], mappings: res[0],
destinationSets: res[1].items, destinationSets: res[1].items,
@ -60,12 +65,13 @@ export async function createMapping ({ dispatch, commit, state, rootGetters }, p
if (payload.type === 'cfu' && state.mappings.cft && state.mappings.cft.length > 0) { if (payload.type === 'cfu' && state.mappings.cft && state.mappings.cft.length > 0) {
type = 'cft' type = 'cft'
} }
const subscriberId = (payload.subscriberId) ? (payload.subscriberId) : rootGetters['user/getSubscriberId']
const mappings = _.cloneDeep(state.mappings[type]) const mappings = _.cloneDeep(state.mappings[type])
const destinationSetId = await post({ const destinationSetId = await post({
resource: 'cfdestinationsets', resource: 'cfdestinationsets',
body: { body: {
name: 'csc-' + v4(), name: 'csc-' + v4(),
subscriber_id: rootGetters['user/getSubscriberId'], subscriber_id: subscriberId,
destinations: [createDefaultDestination()] destinations: [createDefaultDestination()]
} }
}) })
@ -75,7 +81,7 @@ export async function createMapping ({ dispatch, commit, state, rootGetters }, p
const res = await Promise.all([ const res = await Promise.all([
patchReplaceFull({ patchReplaceFull({
resource: 'cfmappings', resource: 'cfmappings',
resourceId: rootGetters['user/getSubscriberId'], resourceId: subscriberId,
fieldPath: type, fieldPath: type,
value: mappings value: mappings
}), }),
@ -104,7 +110,7 @@ export async function deleteMapping ({ dispatch, commit, state, rootGetters }, p
value: updatedMappings value: updatedMappings
}) })
await cfDeleteDestinationSet(payload.destinationset_id) await cfDeleteDestinationSet(payload.destinationset_id)
const destinationSets = await cfLoadDestinationSets(rootGetters['user/getSubscriberId']) const destinationSets = await cfLoadDestinationSets()
commit('dataSucceeded', { commit('dataSucceeded', {
mappings: patchRes, mappings: patchRes,
destinationSets: destinationSets.items destinationSets: destinationSets.items
@ -138,7 +144,7 @@ export async function updateDestination ({ dispatch, commit, state, rootGetters
fieldPath: 'destinations', fieldPath: 'destinations',
value: destinations value: destinations
}) })
const destinationSets = await cfLoadDestinationSets(rootGetters['user/getSubscriberId']) const destinationSets = await cfLoadDestinationSets()
commit('dataSucceeded', { commit('dataSucceeded', {
destinationSets: destinationSets.items destinationSets: destinationSets.items
}) })
@ -155,7 +161,7 @@ export async function addDestination ({ dispatch, commit, state, rootGetters },
fieldPath: 'destinations', fieldPath: 'destinations',
value: destinations value: destinations
}) })
const destinationSets = await cfLoadDestinationSets(rootGetters['user/getSubscriberId']) const destinationSets = await cfLoadDestinationSets()
commit('dataSucceeded', { commit('dataSucceeded', {
destinationSets: destinationSets.items destinationSets: destinationSets.items
}) })
@ -193,7 +199,7 @@ export async function removeDestination ({ dispatch, commit, state, rootGetters
fieldPath: 'destinations', fieldPath: 'destinations',
value: updatedDestinations value: updatedDestinations
}) })
const destinationSets = await cfLoadDestinationSets(rootGetters['user/getSubscriberId']) const destinationSets = await cfLoadDestinationSets()
commit('dataSucceeded', { commit('dataSucceeded', {
destinationSets: destinationSets.items destinationSets: destinationSets.items
}) })
@ -210,7 +216,7 @@ export async function updateDestinationTimeout ({ dispatch, commit, state, rootG
fieldPath: 'destinations', fieldPath: 'destinations',
value: destinations value: destinations
}) })
const destinationSets = await cfLoadDestinationSets(rootGetters['user/getSubscriberId']) const destinationSets = await cfLoadDestinationSets()
commit('dataSucceeded', { commit('dataSucceeded', {
destinationSets: destinationSets.items destinationSets: destinationSets.items
}) })
@ -219,7 +225,7 @@ export async function updateDestinationTimeout ({ dispatch, commit, state, rootG
export async function loadSourceSets ({ dispatch, commit, rootGetters }) { export async function loadSourceSets ({ dispatch, commit, rootGetters }) {
dispatch('wait/start', 'csc-cf-sourcesets', { root: true }) dispatch('wait/start', 'csc-cf-sourcesets', { root: true })
const sourceSets = await cfLoadSourceSets(rootGetters['user/getSubscriberId']) const sourceSets = await cfLoadSourceSets()
commit('dataSucceeded', { commit('dataSucceeded', {
sourceSets: sourceSets.items sourceSets: sourceSets.items
}) })
@ -238,7 +244,7 @@ export async function createSourceSet ({ dispatch, commit, rootGetters, state },
fieldPath: payload.mapping.type, fieldPath: payload.mapping.type,
value: updatedMapping value: updatedMapping
}) })
const sourceSets = await cfLoadSourceSets(rootGetters['user/getSubscriberId']) const sourceSets = await cfLoadSourceSets()
commit('dataSucceeded', { commit('dataSucceeded', {
mappings: updatedMappings, mappings: updatedMappings,
sourceSets: sourceSets.items sourceSets: sourceSets.items
@ -252,7 +258,7 @@ export async function updateSourceSet ({ dispatch, commit, rootGetters, state },
try { try {
dispatch('wait/start', 'csc-cf-source-set-create', { root: true }) dispatch('wait/start', 'csc-cf-source-set-create', { root: true })
await cfUpdateSourceSet(rootGetters['user/getSubscriberId'], payload) await cfUpdateSourceSet(rootGetters['user/getSubscriberId'], payload)
const sourceSets = await cfLoadSourceSets(rootGetters['user/getSubscriberId']) const sourceSets = await cfLoadSourceSets()
commit('dataSucceeded', { commit('dataSucceeded', {
sourceSets: sourceSets.items sourceSets: sourceSets.items
}) })
@ -274,7 +280,7 @@ export async function deleteSourceSet ({ dispatch, commit, rootGetters, state },
value: updatedMapping value: updatedMapping
}) })
await cfDeleteSourceSet(payload.id) await cfDeleteSourceSet(payload.id)
const sourceSets = await cfLoadSourceSets(rootGetters['user/getSubscriberId']) const sourceSets = await cfLoadSourceSets()
commit('dataSucceeded', { commit('dataSucceeded', {
mappings: updatedMappings, mappings: updatedMappings,
sourceSets: sourceSets.items sourceSets: sourceSets.items
@ -334,7 +340,7 @@ export async function createTimeSetDate ({ dispatch, commit, rootGetters, state
fieldPath: payload.mapping.type, fieldPath: payload.mapping.type,
value: updatedMapping value: updatedMapping
}) })
const timeSets = await cfLoadTimeSets(rootGetters['user/getSubscriberId']) const timeSets = await cfLoadTimeSets()
commit('dataSucceeded', { commit('dataSucceeded', {
mappings: updatedMappings, mappings: updatedMappings,
timeSets: timeSets.items timeSets: timeSets.items
@ -345,7 +351,7 @@ export async function createTimeSetDate ({ dispatch, commit, rootGetters, state
export async function updateTimeSetDate ({ dispatch, commit, rootGetters, state }, payload) { export async function updateTimeSetDate ({ dispatch, commit, rootGetters, state }, payload) {
dispatch('wait/start', 'csc-cf-time-set-create', { root: true }) dispatch('wait/start', 'csc-cf-time-set-create', { root: true })
await cfUpdateTimeSetDate(payload.id, payload.date) await cfUpdateTimeSetDate(payload.id, payload.date)
const timeSets = await cfLoadTimeSets(rootGetters['user/getSubscriberId']) const timeSets = await cfLoadTimeSets()
commit('dataSucceeded', { commit('dataSucceeded', {
timeSets: timeSets.items timeSets: timeSets.items
}) })
@ -364,7 +370,7 @@ export async function deleteTimeSet ({ dispatch, commit, rootGetters, state }, p
value: updatedMapping value: updatedMapping
}) })
await cfDeleteTimeSet(payload.id) await cfDeleteTimeSet(payload.id)
const timeSets = await cfLoadTimeSets(rootGetters['user/getSubscriberId']) const timeSets = await cfLoadTimeSets()
commit('dataSucceeded', { commit('dataSucceeded', {
mappings: updatedMappings, mappings: updatedMappings,
timeSets: timeSets.items timeSets: timeSets.items
@ -425,7 +431,7 @@ export async function createTimeSetDateRange ({ dispatch, commit, rootGetters, s
fieldPath: payload.mapping.type, fieldPath: payload.mapping.type,
value: updatedMapping value: updatedMapping
}) })
const timeSets = await cfLoadTimeSets(rootGetters['user/getSubscriberId']) const timeSets = await cfLoadTimeSets()
commit('dataSucceeded', { commit('dataSucceeded', {
mappings: updatedMappings, mappings: updatedMappings,
timeSets: timeSets.items timeSets: timeSets.items
@ -436,7 +442,7 @@ export async function createTimeSetDateRange ({ dispatch, commit, rootGetters, s
export async function updateTimeSetDateRange ({ dispatch, commit, rootGetters, state }, payload) { export async function updateTimeSetDateRange ({ dispatch, commit, rootGetters, state }, payload) {
dispatch('wait/start', 'csc-cf-time-set-create', { root: true }) dispatch('wait/start', 'csc-cf-time-set-create', { root: true })
await cfUpdateTimeSetDateRange(payload.id, payload.date) await cfUpdateTimeSetDateRange(payload.id, payload.date)
const timeSets = await cfLoadTimeSets(rootGetters['user/getSubscriberId']) const timeSets = await cfLoadTimeSets()
commit('dataSucceeded', { commit('dataSucceeded', {
timeSets: timeSets.items timeSets: timeSets.items
}) })
@ -454,7 +460,7 @@ export async function createTimeSetWeekdays ({ dispatch, commit, rootGetters, st
fieldPath: payload.mapping.type, fieldPath: payload.mapping.type,
value: updatedMapping value: updatedMapping
}) })
const timeSets = await cfLoadTimeSets(rootGetters['user/getSubscriberId']) const timeSets = await cfLoadTimeSets()
commit('dataSucceeded', { commit('dataSucceeded', {
mappings: updatedMappings, mappings: updatedMappings,
timeSets: timeSets.items timeSets: timeSets.items
@ -465,7 +471,7 @@ export async function createTimeSetWeekdays ({ dispatch, commit, rootGetters, st
export async function updateTimeSetWeekdays ({ dispatch, commit, rootGetters, state }, payload) { export async function updateTimeSetWeekdays ({ dispatch, commit, rootGetters, state }, payload) {
dispatch('wait/start', 'csc-cf-time-set-create', { root: true }) dispatch('wait/start', 'csc-cf-time-set-create', { root: true })
await cfUpdateTimeSetWeekdays(payload.id, payload.weekdays) await cfUpdateTimeSetWeekdays(payload.id, payload.weekdays)
const timeSets = await cfLoadTimeSets(rootGetters['user/getSubscriberId']) const timeSets = await cfLoadTimeSets()
commit('dataSucceeded', { commit('dataSucceeded', {
timeSets: timeSets.items timeSets: timeSets.items
}) })
@ -486,7 +492,7 @@ export async function createOfficeHours ({ dispatch, commit, rootGetters, state
if (payload.id) { if (payload.id) {
await cfDeleteTimeSet(payload.id) await cfDeleteTimeSet(payload.id)
} }
const timeSets = await cfLoadTimeSets(rootGetters['user/getSubscriberId']) const timeSets = await cfLoadTimeSets()
commit('dataSucceeded', { commit('dataSucceeded', {
mappings: updatedMappings, mappings: updatedMappings,
timeSets: timeSets.items timeSets: timeSets.items
@ -497,7 +503,7 @@ export async function createOfficeHours ({ dispatch, commit, rootGetters, state
export async function updateOfficeHours ({ dispatch, commit, rootGetters, state }, payload) { export async function updateOfficeHours ({ dispatch, commit, rootGetters, state }, payload) {
dispatch('wait/start', 'csc-cf-time-set-create', { root: true }) dispatch('wait/start', 'csc-cf-time-set-create', { root: true })
await cfUpdateOfficeHours(payload.id, payload.times) await cfUpdateOfficeHours(payload.id, payload.times)
const timeSets = await cfLoadTimeSets(rootGetters['user/getSubscriberId']) const timeSets = await cfLoadTimeSets()
commit('dataSucceeded', { commit('dataSucceeded', {
timeSets: timeSets.items timeSets: timeSets.items
}) })
@ -539,7 +545,7 @@ export async function updateAnnouncement ({ dispatch, commit, rootGetters, state
fieldPath: 'destinations', fieldPath: 'destinations',
value: destinations value: destinations
}) })
const destinationSets = await cfLoadDestinationSets(rootGetters['user/getSubscriberId']) const destinationSets = await cfLoadDestinationSets()
commit('dataSucceeded', { commit('dataSucceeded', {
destinationSets: destinationSets.items destinationSets: destinationSets.items
}) })

Loading…
Cancel
Save