TT#124272 AutoAttendant - As PBX-Attendant (Pilot, Seat, Group), I can change my AutoAttendant configuration
Change-Id: If6238f053f44e4b880dfbbe03d8b44e5e65ce8d9mr10.0
parent
a282cd29ae
commit
17f2345b30
@ -0,0 +1,162 @@
|
|||||||
|
<template>
|
||||||
|
<csc-list-item
|
||||||
|
ref="listItem"
|
||||||
|
icon="dialpad"
|
||||||
|
:expanded="expanded"
|
||||||
|
@toggle="toggle"
|
||||||
|
>
|
||||||
|
<template
|
||||||
|
slot="title"
|
||||||
|
>
|
||||||
|
<csc-list-item-title>
|
||||||
|
{{ $t('Slot') }}: {{ personalSlot.slot }}
|
||||||
|
</csc-list-item-title>
|
||||||
|
<q-slide-transition>
|
||||||
|
<csc-list-item-subtitle
|
||||||
|
v-if="!expanded"
|
||||||
|
>
|
||||||
|
{{ $t('Destination') }}: {{ personalSlot.destination }}
|
||||||
|
</csc-list-item-subtitle>
|
||||||
|
</q-slide-transition>
|
||||||
|
</template>
|
||||||
|
<template slot="menu">
|
||||||
|
<csc-list-menu-item
|
||||||
|
icon="delete"
|
||||||
|
icon-color="negative"
|
||||||
|
@click="confirmRowDeletion"
|
||||||
|
>
|
||||||
|
{{ $t('Remove') }}
|
||||||
|
</csc-list-menu-item>
|
||||||
|
</template>
|
||||||
|
<template
|
||||||
|
slot="body"
|
||||||
|
>
|
||||||
|
<q-input
|
||||||
|
v-model="newDestination"
|
||||||
|
:label="$t('Destination')"
|
||||||
|
:error="$v.newDestination.$error"
|
||||||
|
:error-message="errorMessage"
|
||||||
|
@keyup.enter="save"
|
||||||
|
@input="valueChanged"
|
||||||
|
>
|
||||||
|
<template
|
||||||
|
v-if="hasDestinationChanged"
|
||||||
|
v-slot:append
|
||||||
|
>
|
||||||
|
<csc-input-button-save
|
||||||
|
v-if="newDestination !== '' && newDestination !== null"
|
||||||
|
@click.stop="save"
|
||||||
|
/>
|
||||||
|
<csc-input-button-reset
|
||||||
|
v-if="!addNewSlot"
|
||||||
|
@click.stop="resetSlotDestination"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</q-input>
|
||||||
|
</template>
|
||||||
|
</csc-list-item>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import CscListItem from '../../CscListItem'
|
||||||
|
import CscListItemTitle from '../../CscListItemTitle'
|
||||||
|
import CscListItemSubtitle from '../../CscListItemSubtitle'
|
||||||
|
import CscListMenuItem from '../../CscListMenuItem'
|
||||||
|
import CscInputButtonSave from 'components/form/CscInputButtonSave'
|
||||||
|
import CscInputButtonReset from 'components/form/CscInputButtonReset'
|
||||||
|
import CscRemoveDialog from 'components/CscRemoveDialog'
|
||||||
|
import {
|
||||||
|
required
|
||||||
|
} from 'vuelidate/lib/validators'
|
||||||
|
export default {
|
||||||
|
name: 'CscPbxSettingsAutoAttendant',
|
||||||
|
components: {
|
||||||
|
CscInputButtonSave,
|
||||||
|
CscInputButtonReset,
|
||||||
|
CscListItem,
|
||||||
|
CscListItemTitle,
|
||||||
|
CscListItemSubtitle,
|
||||||
|
CscListMenuItem
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
personalSlot: {
|
||||||
|
type: Object,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
addNewSlot: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
expanded: this.addNewSlot,
|
||||||
|
hasDestinationChanged: false,
|
||||||
|
newDestination: this.personalSlot.destination,
|
||||||
|
currentDestination: this.personalSlot.destination
|
||||||
|
}
|
||||||
|
},
|
||||||
|
validations: {
|
||||||
|
newDestination: {
|
||||||
|
required
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
errorMessage () {
|
||||||
|
if (!this.$v.newDestination.required) {
|
||||||
|
return this.$t('Destination must not be empty')
|
||||||
|
} else {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
this.$root.$on('all-slots-saved', () => {
|
||||||
|
if (this.expanded) {
|
||||||
|
this.toggle()
|
||||||
|
}
|
||||||
|
this.newDestination = this.personalSlot.destination
|
||||||
|
this.currentDestination = this.personalSlot.destination
|
||||||
|
this.hasDestinationChanged = this.newDestination !== this.currentDestination
|
||||||
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
confirmRowDeletion () {
|
||||||
|
if (!this.addNewSlot) {
|
||||||
|
this.$q.dialog({
|
||||||
|
component: CscRemoveDialog,
|
||||||
|
parent: this,
|
||||||
|
title: this.$t('Delete slot?'),
|
||||||
|
message: this.$t('You are about to delete slot {slot}', { slot: this.personalSlot.slot })
|
||||||
|
}).onOk(() => {
|
||||||
|
this.remove()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.remove()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
remove () {
|
||||||
|
this.$emit('remove', this.personalSlot.slot)
|
||||||
|
},
|
||||||
|
save () {
|
||||||
|
if (this.personalSlot.destination !== '') {
|
||||||
|
this.$emit('save')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
toggle () {
|
||||||
|
this.expanded = !this.expanded
|
||||||
|
this.newDestination = this.personalSlot.destination
|
||||||
|
},
|
||||||
|
valueChanged () {
|
||||||
|
this.$v.newDestination.$touch()
|
||||||
|
this.hasDestinationChanged = this.newDestination !== this.currentDestination
|
||||||
|
this.$emit('edit', this.newDestination, this.personalSlot.slot)
|
||||||
|
},
|
||||||
|
resetSlotDestination () {
|
||||||
|
this.$emit('reset', this.personalSlot.slot)
|
||||||
|
this.newDestination = this.personalSlot.destination
|
||||||
|
this.hasDestinationChanged = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
@ -0,0 +1,215 @@
|
|||||||
|
<template>
|
||||||
|
<csc-page-sticky
|
||||||
|
id="csc-page-call-forwarding"
|
||||||
|
class="q-pa-lg"
|
||||||
|
>
|
||||||
|
<template
|
||||||
|
v-slot:header
|
||||||
|
>
|
||||||
|
<q-btn-dropdown
|
||||||
|
size="md"
|
||||||
|
color="primary"
|
||||||
|
:label="$t('Add slot')"
|
||||||
|
:disabled="getAvailableSlots().length === 0"
|
||||||
|
icon="add"
|
||||||
|
dropdown-icon=" "
|
||||||
|
flat
|
||||||
|
>
|
||||||
|
<q-list
|
||||||
|
v-for="availableSlot in getAvailableSlots()"
|
||||||
|
:key="availableSlot"
|
||||||
|
>
|
||||||
|
<csc-popup-menu-item
|
||||||
|
:label="availableSlot"
|
||||||
|
@click="addSlot(availableSlot)"
|
||||||
|
/>
|
||||||
|
</q-list>
|
||||||
|
</q-btn-dropdown>
|
||||||
|
</template>
|
||||||
|
<div
|
||||||
|
class="text-center"
|
||||||
|
>
|
||||||
|
<csc-spinner
|
||||||
|
v-if="$wait.is('csc-pbx-auto-attendant') || $wait.is('csc-pbx-autoattendant-slots-table')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<csc-list
|
||||||
|
v-if="newPersonalSlots && newPersonalSlots.length > 0 && !$wait.is('csc-pbx-auto-attendant')
|
||||||
|
&& !$wait.is('csc-pbx-autoattendant-slots-table')"
|
||||||
|
>
|
||||||
|
<csc-fade
|
||||||
|
v-for="newSlot in newPersonalSlots"
|
||||||
|
:key="'csc-pbx-settings-fade-'+ newSlot.slot "
|
||||||
|
>
|
||||||
|
<csc-pbx-settings-auto-attendant
|
||||||
|
:add-new-slot="true"
|
||||||
|
:personal-slot="newSlot"
|
||||||
|
@save="saveSlot"
|
||||||
|
@remove="removeSlot"
|
||||||
|
@edit="editNewSlotDestination"
|
||||||
|
/>
|
||||||
|
</csc-fade>
|
||||||
|
</csc-list>
|
||||||
|
<csc-list
|
||||||
|
v-if="personalSlots.length > 0 && !$wait.is('csc-pbx-auto-attendant') && !$wait.is('csc-pbx-autoattendant-slots-table')"
|
||||||
|
>
|
||||||
|
<csc-fade
|
||||||
|
v-for="(personalSlot, index) in personalSlots"
|
||||||
|
:key="'csc-pbx-settings-fade-'+ personalSlot.slot "
|
||||||
|
>
|
||||||
|
<csc-pbx-settings-auto-attendant
|
||||||
|
v-model="personalSlots[index].destination"
|
||||||
|
:personal-slot="personalSlot"
|
||||||
|
@save="saveSlot"
|
||||||
|
@remove="removeSlot"
|
||||||
|
@edit="editNewSlotDestination"
|
||||||
|
@reset="resetPersonalSlot"
|
||||||
|
/>
|
||||||
|
</csc-fade>
|
||||||
|
</csc-list>
|
||||||
|
</csc-page-sticky>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import _ from 'lodash'
|
||||||
|
import CscPopupMenuItem from 'components/CscPopupMenuItem'
|
||||||
|
import CscPageSticky from 'components/CscPageSticky'
|
||||||
|
import CscPbxSettingsAutoAttendant from 'components/pages/PbxSettings/CscPbxSettingsAutoAttendant'
|
||||||
|
import CscList from 'components/CscList'
|
||||||
|
import CscFade from 'components/transitions/CscFade'
|
||||||
|
import CscSpinner from 'components/CscSpinner'
|
||||||
|
import { mapGetters } from 'vuex'
|
||||||
|
import { mapWaitingActions } from 'vue-wait'
|
||||||
|
import { getSubscriberId } from 'src/auth'
|
||||||
|
import { showGlobalError, showToast } from 'src/helpers/ui'
|
||||||
|
export default {
|
||||||
|
name: 'CscPagePbxSettingsAutoAttendant',
|
||||||
|
components: {
|
||||||
|
CscPageSticky,
|
||||||
|
CscPopupMenuItem,
|
||||||
|
CscPbxSettingsAutoAttendant,
|
||||||
|
CscList,
|
||||||
|
CscFade,
|
||||||
|
CscSpinner
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
data: [],
|
||||||
|
subscriberId: parseInt(getSubscriberId()),
|
||||||
|
personalSlots: [],
|
||||||
|
newPersonalSlots: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters('pbxAutoAttendants', [
|
||||||
|
'slots',
|
||||||
|
'slotsNumbers',
|
||||||
|
'newSlots'
|
||||||
|
])
|
||||||
|
},
|
||||||
|
async mounted () {
|
||||||
|
await this.fetchAutoAttendants()
|
||||||
|
this.personalSlots = _.cloneDeep(this.slots.filter(slot => slot.subscriber_id === this.subscriberId)[0]?.slots)
|
||||||
|
this.newPersonalSlots = _.cloneDeep(this.newSlots.filter(slot => slot.subscriber_id === this.subscriberId)[0].slots)
|
||||||
|
this.sortArrays()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapWaitingActions('pbxAutoAttendants', {
|
||||||
|
updateSubscriberSlots: 'csc-pbx-autoattendant-slots-table',
|
||||||
|
resetAllNewSlots: 'csc-pbx-autoattendant-slots-table',
|
||||||
|
fetchAutoAttendants: 'csc-pbx-auto-attendant',
|
||||||
|
createNewSlot: 'csc-pbx-auto-attendant',
|
||||||
|
deleteNewSlot: 'csc-pbx-autoattendant-slots-table'
|
||||||
|
}),
|
||||||
|
getAvailableSlots () {
|
||||||
|
let subscriberSlots = this.slots.filter(slot => slot.subscriber_id === this.subscriberId)[0]?.slots
|
||||||
|
const subscriberSavedSlots = subscriberSlots?.map(item => item.slot)
|
||||||
|
const subscriberNewSlots = this.newSlots.filter(item => item.subscriber_id === this.subscriberId)
|
||||||
|
subscriberSlots = subscriberNewSlots.length > 0
|
||||||
|
? [...subscriberSavedSlots, ...subscriberNewSlots[0].slots.map(item => item.slot)]
|
||||||
|
: subscriberSavedSlots
|
||||||
|
const availableSlots = this.slotsNumbers.filter(slot => !subscriberSlots?.includes(slot))
|
||||||
|
return availableSlots
|
||||||
|
},
|
||||||
|
async saveSlot (isARemoval = false) {
|
||||||
|
for (const newSlot of this.newPersonalSlots) {
|
||||||
|
if (!newSlot.destination && !isARemoval) {
|
||||||
|
showGlobalError(this.$t('Please fill or remove the empty slots'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isARemoval) {
|
||||||
|
for (const newSlot of this.newPersonalSlots) {
|
||||||
|
this.updateLocalDestination(newSlot.slot, newSlot.destination)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await this.updateSubscriberSlots({
|
||||||
|
subscriberId: this.subscriberId,
|
||||||
|
slots: [...this.newPersonalSlots, ...this.personalSlots]
|
||||||
|
})
|
||||||
|
this.resetAllNewSlots(this.subscriberId)
|
||||||
|
this.personalSlots = _.cloneDeep(this.slots.filter(slot => slot.subscriber_id === this.subscriberId)[0]?.slots)
|
||||||
|
this.newPersonalSlots = _.cloneDeep(this.newSlots.filter(slot => slot.subscriber_id === this.subscriberId)[0].slots)
|
||||||
|
this.sortArrays()
|
||||||
|
showToast(this.$t('Slots saved successfully'))
|
||||||
|
this.$root.$emit('all-slots-saved')
|
||||||
|
},
|
||||||
|
removeSlot (slotToRemove) {
|
||||||
|
const foundIndex = this.newPersonalSlots.findIndex(item => item.slot === slotToRemove)
|
||||||
|
if (foundIndex === -1) {
|
||||||
|
this.personalSlots = this.personalSlots.filter((item) => item.slot !== slotToRemove)
|
||||||
|
this.saveSlot(true)
|
||||||
|
} else {
|
||||||
|
this.deleteNewSlot({
|
||||||
|
subscriberId: this.subscriberId,
|
||||||
|
index: foundIndex
|
||||||
|
})
|
||||||
|
this.newPersonalSlots.splice(foundIndex, 1)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
addSlot (availableSlot) {
|
||||||
|
this.createNewSlot({
|
||||||
|
subscriberId: this.subscriberId,
|
||||||
|
slot: availableSlot
|
||||||
|
})
|
||||||
|
this.newPersonalSlots = _.cloneDeep(this.newSlots.filter(slot => slot.subscriber_id === this.subscriberId)[0].slots)
|
||||||
|
this.sortArrays()
|
||||||
|
},
|
||||||
|
updateLocalDestination (newPersonalSlot, newDestination) {
|
||||||
|
this.personalSlots.forEach((item) => {
|
||||||
|
if (item.slot === newPersonalSlot) {
|
||||||
|
item.destination = newDestination
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (this.newPersonalSlots) {
|
||||||
|
this.newPersonalSlots.forEach((item) => {
|
||||||
|
if (item.slot === newPersonalSlot) {
|
||||||
|
item.destination = newDestination
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
editNewSlotDestination (newDestination, newPersonalSlot) {
|
||||||
|
const foundIndexNewSlots = this.newPersonalSlots.findIndex(item => item.slot === newPersonalSlot)
|
||||||
|
if (foundIndexNewSlots !== -1) {
|
||||||
|
this.newPersonalSlots[foundIndexNewSlots].destination = newDestination
|
||||||
|
} else {
|
||||||
|
const foundIndexExistingSlots = this.personalSlots.findIndex(item => item.slot === newPersonalSlot)
|
||||||
|
this.personalSlots[foundIndexExistingSlots].destination = newDestination
|
||||||
|
if (foundIndexNewSlots !== -1) {
|
||||||
|
this.personalSlots[foundIndexExistingSlots].destination = newDestination
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
resetPersonalSlot (personalSlot) {
|
||||||
|
const slotsFiltered = this.slots.filter(slot => slot.subscriber_id === this.subscriberId)[0]?.slots
|
||||||
|
const foundIndex = slotsFiltered.findIndex(item => item.slot === personalSlot)
|
||||||
|
this.personalSlots[foundIndex].destination = slotsFiltered[foundIndex].destination
|
||||||
|
},
|
||||||
|
sortArrays () {
|
||||||
|
this.personalSlots.sort((a, b) => (a.slot > b.slot) ? 1 : ((b.slot > a.slot) ? -1 : 0))
|
||||||
|
this.newPersonalSlots.sort((a, b) => (a.slot > b.slot) ? 1 : ((b.slot > a.slot) ? -1 : 0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
Loading…
Reference in new issue