diff --git a/src/components/CscMoreMenu.vue b/src/components/CscMoreMenu.vue index 01351075..7641831f 100644 --- a/src/components/CscMoreMenu.vue +++ b/src/components/CscMoreMenu.vue @@ -6,8 +6,24 @@ dense @click.stop.prevent > - + + + @@ -17,6 +33,12 @@ export default { name: 'CscMoreMenu', components: { CscPopupMenu + }, + props: { + gridView: { + type: Boolean, + default: false + } } } diff --git a/src/components/CscPopupMenu.vue b/src/components/CscPopupMenu.vue index ebffd79d..fce689ef 100644 --- a/src/components/CscPopupMenu.vue +++ b/src/components/CscPopupMenu.vue @@ -3,16 +3,52 @@ @before-show="$store.commit('callForwarding/popupShow', null)" > +
+
+ + + +
+
+ + + +
+
diff --git a/src/components/call-forwarding/CscCfDestination.vue b/src/components/call-forwarding/CscCfDestination.vue new file mode 100644 index 00000000..45081415 --- /dev/null +++ b/src/components/call-forwarding/CscCfDestination.vue @@ -0,0 +1,69 @@ + + + diff --git a/src/components/call-forwarding/CscCfDestinationCustomAnnouncement.vue b/src/components/call-forwarding/CscCfDestinationCustomAnnouncement.vue new file mode 100644 index 00000000..4627a54c --- /dev/null +++ b/src/components/call-forwarding/CscCfDestinationCustomAnnouncement.vue @@ -0,0 +1,61 @@ + + diff --git a/src/components/call-forwarding/CscCfDestinationNumber.vue b/src/components/call-forwarding/CscCfDestinationNumber.vue new file mode 100644 index 00000000..5a662c39 --- /dev/null +++ b/src/components/call-forwarding/CscCfDestinationNumber.vue @@ -0,0 +1,52 @@ + + + diff --git a/src/components/call-forwarding/CscCfGroupItem.vue b/src/components/call-forwarding/CscCfGroupItem.vue index d1f64768..aa433467 100644 --- a/src/components/call-forwarding/CscCfGroupItem.vue +++ b/src/components/call-forwarding/CscCfGroupItem.vue @@ -92,118 +92,29 @@ {{ $t('forwarded to') }} - - - {{ $t('Voicebox') }} - - - - {{ $t('Fax2Mail') }} - - - - {{ $t('ManagerSecretary') }} - - - - {{ $t('Conference') }} - - - - {{ announcement ? announcement.label : '' }} - - - - - - - {{ $t('Application') }} - - + + - - {{ destination.simple_destination }} - - - - - - + :value="destination" + /> - - - - - - - - - - - + + + @@ -278,6 +335,7 @@ import CscCfConditionPopupCallNotFrom from 'components/call-forwarding/CscCfCond import CscCfConditionPopupDateRange from 'components/call-forwarding/CscCfConditionPopupDateRange' import CscCfConditionPopupWeekdays from 'components/call-forwarding/CscCfConditionPopupWeekdays' import CscCfConditionPopupOfficeHours from 'components/call-forwarding/CscCfConditionPopupOfficeHours' +import destination from 'src/mixins/destination' export default { name: 'CscCfGroupTitle', components: { @@ -292,6 +350,7 @@ export default { CscPopupMenuItemDelete, CscMoreMenu }, + mixins: [destination], props: { mapping: { type: Object, @@ -316,7 +375,8 @@ export default { }, computed: { ...mapGetters('user', [ - 'hasSubscriberProfileAttribute' + 'hasSubscriberProfileAttribute', + 'isPbxAttendant' ]), clickableClasses () { return ['cursor-pointer', 'text-weight-bold', 'text-primary'] diff --git a/src/i18n/en.json b/src/i18n/en.json index 46f28bc9..7d44518f 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -98,6 +98,7 @@ "Audio + Video": "Audio + Video", "Audio Call": "Audio Call", "Audio Only": "Audio Only", + "Auto Attendant": "Auto Attendant", "Auto-attendant": "Auto-attendant", "Blacklist": "Blacklist", "Block Incoming": "Block Incoming", @@ -120,6 +121,7 @@ "Call Queue": "Call Queue", "Call Queues": "Call Queues", "Call Settings": "Call Settings", + "Call Through": "Call Through", "Call back": "Call back", "Call ended": "Call ended", "Call forwarded": "Call forwarded", @@ -128,6 +130,7 @@ "Callee": "Callee", "Caller": "Caller", "Calling": "Calling", + "Calling Card": "Calling Card", "Calling {number}...": "Calling {number}...", "Calls": "Calls", "Calls, Faxes, VoiceMails": "Calls, Faxes, VoiceMails", @@ -255,10 +258,17 @@ "Fine": "Fine", "Forgot password?": "Forgot password?", "Format": "Format", + "Forward to Auto Attendant": "Forward to Auto Attendant", + "Forward to Call Through": "Forward to Call Through", + "Forward to Calling Card": "Forward to Calling Card", "Forward to Conference": "Forward to Conference", + "Forward to Custom Announcement": "Forward to Custom Announcement", "Forward to Fax2Mail": "Forward to Fax2Mail", + "Forward to Local Subscriber": "Forward to Local Subscriber", + "Forward to Manager Secretary": "Forward to Manager Secretary", "Forward to ManagerSecretary": "Forward to ManagerSecretary", "Forward to Number": "Forward to Number", + "Forward to Office Hours Announcement": "Forward to Office Hours Announcement", "Forward to Voicebox": "Forward to Voicebox", "Forwarded to": "Forwarded to", "Forwarding": "Forwarding", @@ -322,6 +332,7 @@ "List of registered devices for the subscriber": "List of registered devices for the subscriber", "Load Files": "Load Files", "Logged in as": "Logged in as", + "Local Subscriber": "Local Subscriber", "Login": "Login", "Logout": "Logout", "M,T,W,T,F,S,S": "M,T,W,T,F,S,S", @@ -379,6 +390,7 @@ "Number {type} successfully": "Number {type} successfully", "Numbers": "Numbers", "Office hours": "Office hours", + "Office Hours Announcement": "Office Hours Announcement", "On weekdays": "On weekdays", "Only incoming calls from listed numbers are allowed": "Only incoming calls from listed numbers are allowed", "Only once": "Only once", diff --git a/src/mixins/destination.js b/src/mixins/destination.js new file mode 100644 index 00000000..5b3c07df --- /dev/null +++ b/src/mixins/destination.js @@ -0,0 +1,160 @@ +import sipUriParse from 'src/sip-uri-parse' +import _ from 'lodash' + +const DestinationType = { + VoiceBox: 'VoiceBox', + Conference: 'Conference', + Fax2Mail: 'Fax2Mail', + CallingCard: 'CallingCard', + CallThrough: 'CallThrough', + AutoAttendant: 'AutoAttendant', + OfficeHoursAnnouncement: 'OfficeHoursAnnouncement', + CustomAnnouncement: 'CustomAnnouncement', + LocalSubscriber: 'LocalSubscriber', + ManagerSecretary: 'ManagerSecretary', + Application: 'Application', + Number: 'Number' +} + +function parseSipUri (sipUri) { + const parsedUri = sipUriParse(sipUri) + const host = parsedUri.host + const username = parsedUri.username + let destinationType + if (host.endsWith('voicebox.local')) { + destinationType = DestinationType.VoiceBox + } else if (host.endsWith('conference.local')) { + destinationType = DestinationType.Conference + } else if (host.endsWith('fax2mail.local')) { + destinationType = DestinationType.Fax2Mail + } else if (username === 'callingcard' && host.endsWith('app.local')) { + destinationType = DestinationType.CallingCard + } else if (username === 'callthrough' && host.endsWith('app.local')) { + destinationType = DestinationType.CallThrough + } else if (username === 'auto-attendant' && host.endsWith('app.local')) { + destinationType = DestinationType.AutoAttendant + } else if (username === 'office-hours' && host.endsWith('app.local')) { + destinationType = DestinationType.OfficeHoursAnnouncement + } else if (username === 'custom-hours' && host.endsWith('app.local')) { + destinationType = DestinationType.CustomAnnouncement + } else if (username === 'localuser' && host.endsWith('local')) { + destinationType = DestinationType.LocalSubscriber + } else if (host.endsWith('managersecretary.local')) { + destinationType = DestinationType.ManagerSecretary + } else if (host.endsWith('app.local')) { + destinationType = DestinationType.Application + } else { + destinationType = DestinationType.Number + } + return { + destinationType, + parsedUri + } +} + +export default { + methods: { + isDestinationType (sipUri, destinationType) { + const parsedSipUri = parseSipUri(sipUri) + return parsedSipUri.destinationType === destinationType + }, + isDestinationTypeVoiceBox (sipUri) { + return this.isDestinationType(sipUri, DestinationType.VoiceBox) + }, + isDestinationTypeConference (sipUri) { + return this.isDestinationType(sipUri, DestinationType.Conference) + }, + isDestinationTypeFax2Mail (sipUri) { + return this.isDestinationType(sipUri, DestinationType.Fax2Mail) + }, + isDestinationTypeCallingCard (sipUri) { + return this.isDestinationType(sipUri, DestinationType.CallingCard) + }, + isDestinationTypeCallThrough (sipUri) { + return this.isDestinationType(sipUri, DestinationType.CallThrough) + }, + isDestinationTypeAutoAttendant (sipUri) { + return this.isDestinationType(sipUri, DestinationType.AutoAttendant) + }, + isDestinationTypeOfficeHoursAnnouncement (sipUri) { + return this.isDestinationType(sipUri, DestinationType.OfficeHoursAnnouncement) + }, + isDestinationTypeCustomAnnouncement (sipUri) { + return this.isDestinationType(sipUri, DestinationType.CustomAnnouncement) + }, + isDestinationTypeLocalSubscriber (sipUri) { + return this.isDestinationType(sipUri, DestinationType.LocalSubscriber) + }, + isDestinationTypeManagerSecretary (sipUri) { + return this.isDestinationType(sipUri, DestinationType.ManagerSecretary) + }, + isDestinationTypeApplication (sipUri) { + return this.isDestinationType(sipUri, DestinationType.Application) + }, + isDestinationTypeNumber (sipUri) { + return this.isDestinationType(sipUri, DestinationType.Number) + }, + destinationIconBySipUri (sipUri) { + const parsedSipUri = parseSipUri(sipUri) + return this.destinationIconByType(parsedSipUri.destinationType) + }, + destinationIconByType (destinationType) { + switch (destinationType) { + case DestinationType.VoiceBox: + return 'voicemail' + case DestinationType.Conference: + return 'groups' + case DestinationType.Fax2Mail: + return 'email' + case DestinationType.CallingCard: + return 'credit_card' + case DestinationType.CallThrough: + return 'double_arrow' + case DestinationType.AutoAttendant: + return 'dialpad' + case DestinationType.OfficeHoursAnnouncement: + return 'schedule' + case DestinationType.CustomAnnouncement: + return 'music_note' + case DestinationType.LocalSubscriber: + return 'person_pin' + case DestinationType.ManagerSecretary: + return 'support_agent' + case DestinationType.Application: + return 'apps' + case DestinationType.Number: + return 'phone_forwarded' + } + }, + destinationFormattedBySipUri (sipUri) { + const parsedSipUri = parseSipUri(sipUri) + switch (parsedSipUri.destinationType) { + case DestinationType.VoiceBox: + return this.$t('Voicebox') + case DestinationType.Conference: + return this.$t('Conference') + case DestinationType.Fax2Mail: + return this.$t('Fax2Mail') + case DestinationType.CallingCard: + return this.$t('Calling Card') + case DestinationType.CallThrough: + return this.$t('Call Through') + case DestinationType.AutoAttendant: + return this.$t('Auto Attendant') + case DestinationType.OfficeHoursAnnouncement: + return this.$t('Office Hours Announcement') + case DestinationType.CustomAnnouncement: + return this.$t('Custom Announcement') + case DestinationType.LocalSubscriber: + return this.$t('Local Subscriber') + case DestinationType.ManagerSecretary: + return this.$t('Manager Secretary') + case DestinationType.Application: + return _.words(parsedSipUri.parsedUri.username).map(word => _.upperFirst(word)).join(' ') + default: + case DestinationType.Number: + return parsedSipUri.parsedUri.username + } + } + } +} diff --git a/src/store/call-forwarding/actions.js b/src/store/call-forwarding/actions.js index bf4db844..385395cb 100644 --- a/src/store/call-forwarding/actions.js +++ b/src/store/call-forwarding/actions.js @@ -33,7 +33,7 @@ const DEFAULT_CUSTOM_ANNOUNCEMENT_ID = 255 // TODO get from endpoint function createDefaultDestination (destination) { const payload = { - destination: destination || 'Number', + destination: destination || ' ', priority: DEFAULT_PRIORITY, timeout: DEFAULT_RING_TIMEOUT } diff --git a/src/store/user.js b/src/store/user.js index b197d9dd..6b9a800d 100644 --- a/src/store/user.js +++ b/src/store/user.js @@ -206,6 +206,18 @@ export default { }, isOldCSCProxyingAllowed (state, getters) { return getters.isAdmin && state.platformInfo?.csc_v2_mode === 'mixed' && !!getters.getCustomerId + }, + isPbxPilot (state) { + return !!state.subscriber?.is_pbx_pilot + }, + isPbxGroup (state) { + return !!state.subscriber?.is_pbx_group + }, + isPbxSeat (state, getters) { + return !getters.isPbxPilot && !getters.isPbxGroup && !!state.subscriber?.pbx_extension + }, + isPbxAttendant (state, getters) { + return getters.isPbxPilot || getters.isPbxGroup || getters.isPbxSeat } }, mutations: {