From 91e33e25166632282d972397549cf350b4b81484 Mon Sep 17 00:00:00 2001 From: raxelsen Date: Mon, 13 Aug 2018 15:22:56 +0200 Subject: [PATCH] TT#37304 CallForwarding: As a Customer, I want to enable/disable calls to my own number What has been done: - TT#42759, Implement API method for toggling of enable/disable own number - TT#42763, Implement state handling for toggle button and timeout - TT#42766, Extend unit tests to also account for cft destinations - TT#42755, Extend API method to also render cft destinations - TT#42761, Implement UI for toggle button - TT#42760, Implement API methods for fetching, updating and resetting cft_timeout - TT#43163, Implement UI for timeout input field with reset/save - TT#42764, Implement success toast and error handling for toggle action - TT#42765, Implement success toast and error handling for timeout input Change-Id: I0ce37bbe14caacadb822f14d01782009633c4354 --- .gitreview | 1 + src/api/call-forward.js | 119 +++++- .../CallForward/CscAddDestinationForm.vue | 2 - .../CscCallForwardDestinations.vue | 70 ++-- .../pages/CallForward/CscDestination.vue | 97 +++-- .../pages/CallForward/CscDestinations.vue | 379 +++++++++++++++++- .../pages/CallForward/CscSourcesets.vue | 3 - src/locales/en.json | 15 +- src/store/call-forward.js | 106 ++++- t/api/call-forward.js | 10 +- 10 files changed, 716 insertions(+), 86 deletions(-) diff --git a/.gitreview b/.gitreview index 91d50972..b41a4e6b 100644 --- a/.gitreview +++ b/.gitreview @@ -2,3 +2,4 @@ host=gerrit.mgm.sipwise.com port=29418 project=ngcp-csc-ui + diff --git a/src/api/call-forward.js b/src/api/call-forward.js index 4884c86b..4e9c5f2e 100644 --- a/src/api/call-forward.js +++ b/src/api/call-forward.js @@ -12,6 +12,7 @@ export function getMappings(id) { let jsonBody = getJsonBody(result.body); delete jsonBody._links; delete jsonBody.cfs; + delete jsonBody.cfr; resolve(getJsonBody(result.body)); }).catch((err) => { reject(err); @@ -131,15 +132,25 @@ export function loadDestinations(options) { export function getDestinationsBySourcesetId(options) { return new Promise((resolve, reject) => { + let cftTimeset = null; let cfuTimeset = null; let cfnaTimeset = null; let cfbTimeset = null; Promise.resolve().then(() => { return getMappings(options.subscriberId); }).then((mappings) => { + let cftPromises = []; let cfuPromises = []; let cfnaPromises = []; let cfbPromises = []; + if(_.has(mappings, 'cft') && _.isArray(mappings.cft) && mappings.cft.length > 0) { + mappings.cft.forEach((cftMapping) => { + if (cftMapping.timeset === options.timeset && cftMapping.sourceset_id === options.sourceset_id) { + cftTimeset = cftMapping.timeset_id; + cftPromises.push(getDestinationsetById(cftMapping.destinationset_id)); + } + }); + } if(_.has(mappings, 'cfu') && _.isArray(mappings.cfu) && mappings.cfu.length > 0) { mappings.cfu.forEach((cfuMapping) => { if (cfuMapping.timeset === options.timeset && cfuMapping.sourceset_id === options.sourceset_id) { @@ -165,22 +176,27 @@ export function getDestinationsBySourcesetId(options) { }); } return Promise.all([ + Promise.all(cftPromises), Promise.all(cfuPromises), Promise.all(cfnaPromises), Promise.all(cfbPromises) ]); }).then((result) => { - addNameIdAndTerminating({ group: result[0], groupName: 'cfu', timesetId: cfuTimeset }); - addNameIdAndTerminating({ group: result[1], groupName: 'cfna', timesetId: cfnaTimeset }); - addNameIdAndTerminating({ group: result[2], groupName: 'cfb', timesetId: cfbTimeset }); + let ownPhone = result[0].length > 0 && result[1].length === 0; + let cftDestinations = addNameIdOwnPhoneAndTerminating({ group: _.cloneDeep(result[0]), groupName: 'cft', timesetId: cftTimeset, ownPhone: ownPhone }); + let cfuDestinations = addNameIdOwnPhoneAndTerminating({ group: _.cloneDeep(result[1]), groupName: 'cfu', timesetId: cfuTimeset, ownPhone: ownPhone }); + let offlineDestinations = addNameIdOwnPhoneAndTerminating({ group: _.cloneDeep(result[2]), groupName: 'cfna', timesetId: cfnaTimeset, ownPhone: ownPhone }); + let busyDestinations = addNameIdOwnPhoneAndTerminating({ group: _.cloneDeep(result[3]), groupName: 'cfb', timesetId: cfbTimeset, ownPhone: ownPhone }); + let onlineDestinations = getOnlineDestinations({ cftDestinations: cftDestinations, cfuDestinations: cfuDestinations }); resolve({ sourcesetId: options.sourceset_id, sourcesetName: options.sourceset_name, sourcesetMode: options.sourceset_mode, + ownPhone: ownPhone, destinationGroups: { - online: result[0], - offline: result[1], - busy: result[2] + online: onlineDestinations, + offline: offlineDestinations, + busy: busyDestinations } }) }).catch((err)=>{ @@ -189,13 +205,24 @@ export function getDestinationsBySourcesetId(options) { }); } -export function addNameIdAndTerminating(options) { +export function getOnlineDestinations(options) { + if (options.cftDestinations.length > 0 && options.cfuDestinations.length === 0) { + return options.cftDestinations; + } + else { + return options.cfuDestinations; + } +} + +export function addNameIdOwnPhoneAndTerminating(options) { let terminatingFlag = false; options.group.forEach(destinationset => { destinationset.groupName = options.groupName; destinationset.timesetId = options.timesetId; + destinationset.ownPhone = options.ownPhone; destinationset.destinations.forEach(destination => { let normalized = normalizeDestination(destination.destination); + if (!terminatingFlag && _.includes(['Voicebox', 'Fax2Mail', 'Manager Secretary', 'Custom Announcement', 'Conference'], normalized)) { terminatingFlag = true; @@ -841,3 +868,81 @@ export function deleteSourceFromSourcesetByIndex(options) { }); }); } + +export function flipCfuAndCft(options) { + return new Promise((resolve, reject) => { + Promise.resolve().then(() => { + return getMappings(options.subscriberId); + }).then((mappings) => { + let flipValues = mappings[options.fromType].filter((destinationset) => { + return destinationset.sourceset_id === options.sourcesetId && destinationset.timeset_id === options.timesetId; + }); + let fromValues = mappings[options.fromType].filter((destinationset) => { + return !(destinationset.sourceset_id === options.sourcesetId && destinationset.timeset_id === options.timesetId); + }) + let toValues = mappings[options.toType].concat(flipValues); + let patchOptions = [ + { + op: 'replace', + path: '/' + options.fromType, + value: fromValues + }, { + op: 'replace', + path: '/' + options.toType, + value: toValues + } + ]; + let timeoutOption = { + op: 'replace', + path: '/cft_ringtimeout', + value: 15 + }; + if (!mappings.cft_ringtimeout) { + patchOptions.push(timeoutOption); + } + return new Promise((resolve, reject) => { + let headers = { + 'Content-Type': 'application/json-patch+json' + }; + Vue.http.patch('api/cfmappings/' + options.subscriberId, + patchOptions, { headers: headers }).then((result) => { + resolve(result); + }).catch((err) => { + reject(err); + }); + }); + }).then(() => { + resolve(); + }).catch((err) => { + reject(err); + }); + }); +} + +export function getOwnPhoneTimeout(id) { + return new Promise((resolve, reject)=>{ + Vue.http.get('api/cfmappings/' + id).then((res) => { + let timeout = getJsonBody(res.body).cft_ringtimeout; + resolve(timeout); + }).catch((err) => { + reject(err); + }); + }); +} + +export function updateOwnPhoneTimeout(options) { + return new Promise((resolve, reject)=>{ + let headers = { + 'Content-Type': 'application/json-patch+json' + }; + Vue.http.patch('api/cfmappings/' + options.subscriberId, [{ + op: 'replace', + path: '/cft_ringtimeout', + value: options.timeout + }], { headers: headers }).then(() => { + resolve(); + }).catch((err) => { + reject(err); + }); + }); +} diff --git a/src/components/pages/CallForward/CscAddDestinationForm.vue b/src/components/pages/CallForward/CscAddDestinationForm.vue index 2ced684e..ccc61392 100644 --- a/src/components/pages/CallForward/CscAddDestinationForm.vue +++ b/src/components/pages/CallForward/CscAddDestinationForm.vue @@ -53,8 +53,6 @@ :float-label="$t('pages.callForward.timeout')" type="number" v-model="destinationForm.timeout" - :min="0" - :max="600" suffix="seconds" /> diff --git a/src/components/pages/CallForward/CscCallForwardDestinations.vue b/src/components/pages/CallForward/CscCallForwardDestinations.vue index 787e8eca..2433316a 100644 --- a/src/components/pages/CallForward/CscCallForwardDestinations.vue +++ b/src/components/pages/CallForward/CscCallForwardDestinations.vue @@ -1,26 +1,33 @@ @@ -36,13 +43,12 @@ 'sourceset', 'destinations' ], - data () { - return { - } - }, components: { CscDestinations }, + created() { + this.$store.dispatch('callForward/loadOwnPhoneTimeout'); + }, computed: { ...mapState('callForward', { removeDestinationState: 'removeDestinationState', @@ -62,7 +68,15 @@ } }), ...mapGetters('callForward', { - timesLength: 'getTimesetTimesLength' + timesLength: 'getTimesetTimesLength', + isUpdating: 'isUpdating', + updateOwnPhoneToggleState: 'updateOwnPhoneToggleState', + updateOwnPhoneToggleError: 'updateOwnPhoneToggleError', + ownPhoneTimeout: 'ownPhoneTimeout', + lastOwnPhoneToggle: 'lastOwnPhoneToggle', + updateOwnPhoneTimeoutState: 'updateOwnPhoneTimeoutState', + updateOwnPhoneTimeoutError: 'updateOwnPhoneTimeoutError', + lastOwnPhoneTimeout: 'lastOwnPhoneTimeout' }) }, methods: { @@ -124,25 +138,35 @@ } }, removeTimeState(state) { - if (state === 'requesting') { - startLoading(); - } - else if (state === 'failed') { - stopLoading(); - showGlobalError(this.removeTimeError); + if (state === 'failed') { + showGlobalError(this.changeDestinationError); } else if (state === 'succeeded') { - stopLoading(); - if (this.timesLength <= 1) { - showToast(this.$t('pages.callForward.times.removeTimesetSuccessMessage')); - } - else { - showToast(this.$t('pages.callForward.times.removeSuccessMessage', { - day: this.lastRemovedDay - })); - } this.reloadTimes(this.timeset); } + }, + updateOwnPhoneToggleState(state) { + if (state === 'failed') { + showGlobalError(this.updateOwnPhoneToggleError); + } + else if (state === 'succeeded') { + this.reloadDestinations(this.timeset); + showToast(this.$t('pages.callForward.updateOwnPhoneToggleSuccessMessage', { + toggle: this.lastOwnPhoneToggle + })); + } + }, + updateOwnPhoneTimeoutState(state) { + if (state === 'failed') { + showGlobalError(this.updateOwnPhoneToggleError); + } + else if (state === 'succeeded') { + this.$refs.online.hideModal(); + this.reloadDestinations(this.timeset); + showToast(this.$t('pages.callForward.updateOwnPhoneTimeoutSuccessMessage', { + timeout: this.lastOwnPhoneTimeout + })); + } } } } diff --git a/src/components/pages/CallForward/CscDestination.vue b/src/components/pages/CallForward/CscDestination.vue index f0654396..5f46f476 100644 --- a/src/components/pages/CallForward/CscDestination.vue +++ b/src/components/pages/CallForward/CscDestination.vue @@ -1,12 +1,22 @@