From f3456833579d654f316f84b2da63c67b568fc1c2 Mon Sep 17 00:00:00 2001 From: raxelsen Date: Fri, 2 Feb 2018 11:45:54 +0100 Subject: [PATCH] TT#31801 List Company Hours Times What has been done: - TT#31810, CallForwarding: Implement api requests - TT#32002, CallForwarding: Implement store - TT#32001, CallForwarding: Implement UI component - TT#32003, CallForwarding: Create test Change-Id: I2c858ea73bde7ec8a71127dd48d3e8de6121fd37 --- src/api/call-forward.js | 127 +++++++- .../pages/CallForward/AfterHours.vue | 14 +- src/components/pages/CallForward/Always.vue | 14 +- .../pages/CallForward/CompanyHours.vue | 65 ++++- ...ard.vue => CscCallForwardDestinations.vue} | 2 +- .../pages/CallForward/CscCallForwardTime.vue | 64 +++++ .../pages/CallForward/CscCallForwardTimes.vue | 83 ++++++ src/locales/en.json | 20 +- src/store/call-forward.js | 108 +++---- t/api/call-forward.js | 271 +++++++++++++++++- t/store/call-forward.js | 100 ++----- 11 files changed, 711 insertions(+), 157 deletions(-) rename src/components/pages/CallForward/{CscCallForward.vue => CscCallForwardDestinations.vue} (98%) create mode 100644 src/components/pages/CallForward/CscCallForwardTime.vue create mode 100644 src/components/pages/CallForward/CscCallForwardTimes.vue diff --git a/src/api/call-forward.js b/src/api/call-forward.js index 1fbe93d1..150205d3 100644 --- a/src/api/call-forward.js +++ b/src/api/call-forward.js @@ -1,6 +1,7 @@ import _ from 'lodash'; import Vue from 'vue'; +import { i18n } from '../i18n'; import { getJsonBody } from './utils'; let rowCountAssumption = 1000; @@ -54,8 +55,10 @@ export function getTimesets(id) { } else { return Promise.resolve(result); } - }).then(result => { - resolve(getJsonBody(result.body)._embedded['ngcp:cftimesets']); + }).then((result) => { + let response = getJsonBody(result.body)._embedded || []; + let timesets = response['ngcp:cftimesets'] || []; + resolve(timesets); }).catch(err => { reject(err); }); @@ -375,3 +378,123 @@ export function moveDestinationDown(options) { }); }); } + +export function getDaysFromRange(options) { + let fromDay = options.from; + let toDay = options.to; + let wdayMap = { + 1: i18n.t('pages.callForward.times.sunday'), + 2: i18n.t('pages.callForward.times.monday'), + 3: i18n.t('pages.callForward.times.tuesday'), + 4: i18n.t('pages.callForward.times.wednesday'), + 5: i18n.t('pages.callForward.times.thursday'), + 6: i18n.t('pages.callForward.times.friday'), + 7: i18n.t('pages.callForward.times.saturday') + }; + let days = []; + while (fromDay < toDay) { + days.push({ name: wdayMap[fromDay], number: fromDay }); + fromDay++; + }; + return days; +} + +export function getHoursFromRange(options) { + let fromMinute = options.hasMinute ? options.fromMinute : '00'; + let toMinute = options.hasMinute ? options.toMinute + 1 : '00'; + toMinute = !toMinute ? fromMinute + 1 : toMinute; + let hours = []; + if (options.hasMinute) { + while (options.fromHour < options.toHour) { + hours.push({ + from: `${options.fromHour}:${fromMinute}`, + to: `${options.fromHour}:${toMinute}` + }); + options.fromHour++; + }; + } else { + hours.push({ + from: `${options.fromHour}:${fromMinute}`, + to: `${options.toHour}:${toMinute}` + }); + } + return hours; +} + +export function convertTimesetToWeekdays(options) { + let times = []; + let counter = 0; + let timesetIsCompatible = false; + let timesetHasDuplicate = false; + let timesetExists = false; + let timesetHasReverse = false; + options.timesets.forEach((timeset) => { + let timesetNameMatches = timeset.name === options.timesetName; + if (counter === 0 && timesetNameMatches) { + timeset.times.forEach((time) => { + let days = []; + let hours = []; + let fromDay = parseInt(time.wday.split('-')[0]); + let toDay = time.wday.split('-')[1] ? parseInt(time.wday.split('-')[1]) + 1 : fromDay + 1; + let fromHour = parseInt(time.hour.split('-')[0]); + let toHour = time.hour.split('-')[1] ? parseInt(time.hour.split('-')[1]) + 1 : fromHour + 1; + let fromMinute = time.minute ? parseInt(time.minute.split('-')[0]) : undefined; + let toMinute = (time.minute && time.minute.split('-')[1]) ? parseInt(time.minute.split('-')[1]) : undefined; + let isCompatible = time.mday || time.month || time.year || !time.wday || !time.hour; + let isReverse = fromDay > toDay || fromHour > toHour || fromMinute > toMinute; + if (isCompatible) { + timesetIsCompatible = false; + return; + } else if (isReverse) { + timesetHasReverse = true; + return; + } else { + hours = getHoursFromRange({ hasMinute: !!time.minute, + fromHour: fromHour, toHour: toHour, + fromMinute: fromMinute, toMinute: toMinute }); + days = getDaysFromRange({ from: fromDay, to: toDay }); + days.forEach(day => { + hours.forEach(hour => { + times.push({ + weekday: day.name, + from: hour.from, + to: hour.to, + wday: time.wday, + hour: time.hour, + minute: time.minute + }); + }); + }); + timesetIsCompatible = true; + } + }); + timesetExists = true; + counter++; + } else if (timesetNameMatches) { + timesetHasDuplicate = true; + return; + } + }); + return { + times: times, + timesetIsCompatible: timesetIsCompatible, + timesetExists: timesetExists, + timesetHasReverse: timesetHasReverse, + timesetHasDuplicate: timesetHasDuplicate + }; +} + +export function loadTimesetTimes(options) { + return new Promise((resolve, reject)=> { + Promise.resolve().then(() => { + return getTimesets(options.subscriberId); + }).then((timesets) => { + let times = convertTimesetToWeekdays({ timesets: timesets, timesetName: options.timeset}); + return times; + }).then((times) => { + resolve(times); + }).catch((err) => { + reject(err); + }); + }); +} diff --git a/src/components/pages/CallForward/AfterHours.vue b/src/components/pages/CallForward/AfterHours.vue index b7705738..f98ab721 100644 --- a/src/components/pages/CallForward/AfterHours.vue +++ b/src/components/pages/CallForward/AfterHours.vue @@ -1,29 +1,29 @@ diff --git a/src/components/pages/CallForward/Always.vue b/src/components/pages/CallForward/Always.vue index e2f446ad..12cdafa4 100644 --- a/src/components/pages/CallForward/Always.vue +++ b/src/components/pages/CallForward/Always.vue @@ -1,29 +1,29 @@ diff --git a/src/components/pages/CallForward/CompanyHours.vue b/src/components/pages/CallForward/CompanyHours.vue index 85d8bdea..7038c27b 100644 --- a/src/components/pages/CallForward/CompanyHours.vue +++ b/src/components/pages/CallForward/CompanyHours.vue @@ -1,29 +1,80 @@ diff --git a/src/components/pages/CallForward/CscCallForward.vue b/src/components/pages/CallForward/CscCallForwardDestinations.vue similarity index 98% rename from src/components/pages/CallForward/CscCallForward.vue rename to src/components/pages/CallForward/CscCallForwardDestinations.vue index 7009bca4..6256791e 100644 --- a/src/components/pages/CallForward/CscCallForward.vue +++ b/src/components/pages/CallForward/CscCallForwardDestinations.vue @@ -29,7 +29,7 @@ import CscDestinations from './CscDestinations' import { QCard } from 'quasar-framework' export default { - name: 'csc-call-forward', + name: 'csc-call-forward-destinations', props: [ 'timeset', 'destinations' diff --git a/src/components/pages/CallForward/CscCallForwardTime.vue b/src/components/pages/CallForward/CscCallForwardTime.vue new file mode 100644 index 00000000..f5551b0e --- /dev/null +++ b/src/components/pages/CallForward/CscCallForwardTime.vue @@ -0,0 +1,64 @@ + + + + + diff --git a/src/components/pages/CallForward/CscCallForwardTimes.vue b/src/components/pages/CallForward/CscCallForwardTimes.vue new file mode 100644 index 00000000..76c2723c --- /dev/null +++ b/src/components/pages/CallForward/CscCallForwardTimes.vue @@ -0,0 +1,83 @@ + + + + + diff --git a/src/locales/en.json b/src/locales/en.json index eb8e1fa9..049d40ef 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -149,7 +149,25 @@ "addErrorMessage": "An error occured while trying to add the destination. Please try again.", "addInputError": "Input a valid number or subscriber name", "timeout": "Timeout", - "destination": "Destination" + "destination": "Destination", + "times": { + "noTimeSet": "no time set", + "addTimeButton": "Add Time", + "companyHoursIncompatible": "The Company Hours timeset contains incompatible values.", + "companyHoursNotDefined": "The Company Hours timeset is not defined.", + "companyHoursDuplicate": "More than one Company Hours timeset exists.", + "companyHoursReverse": "The Company Hours timeset contain reverse order of values.", + "weekday": "Weekday", + "from": "From", + "to": "To", + "monday": "Monday", + "tuesday": "Tuesday", + "wednesday": "Wednesday", + "thursday": "Thursday", + "friday": "Friday", + "saturday": "Saturday", + "sunday": "Sunday" + } }, "home": { "title": "Home", diff --git a/src/store/call-forward.js b/src/store/call-forward.js index 79951dbf..1334d9be 100644 --- a/src/store/call-forward.js +++ b/src/store/call-forward.js @@ -1,6 +1,9 @@ 'use strict'; -import _ from 'lodash'; import { getSourcesets, getDestinationsets, + +import _ from 'lodash'; +import { getSourcesets, + getDestinationsets, getTimesets, getMappings, loadEverybodyDestinations, @@ -10,7 +13,8 @@ import _ from 'lodash'; import { getSourcesets, getDestinationsets, addDestinationToExistingGroup, changePositionOfDestination, moveDestinationUp, - moveDestinationDown } from '../api/call-forward'; + moveDestinationDown, + loadTimesetTimes } from '../api/call-forward'; const DestinationState = { button: 'button', @@ -26,17 +30,7 @@ export default { sourcesets: null, timesets: null, destinationsets: null, - alwaysEverybodyDestinations: { - online: [], - busy: [], - offline: [] - }, - companyHoursEverybodyDestinations: { - online: [], - busy: [], - offline: [] - }, - afterHoursEverybodyDestinations: { + destinations: { online: [], busy: [], offline: [] @@ -58,7 +52,12 @@ export default { destination: '', priority: 1, timeout: '' - } + }, + timesetTimes: [], + timesetIsCompatible: false, + timesetExists: true, + timesetHasReverse: false, + timesetHasDuplicate: false }, getters: { hasFaxCapability(state, getters, rootState, rootGetters) { @@ -79,21 +78,11 @@ export default { getDestinationsetId(state) { return state.destinationsetId; }, - getCompanyHoursId(state) { + getTimesetId(state) { let timeset; - for (let group in state.companyHoursEverybodyDestinations) { + for (let group in state.destinations) { if (!timeset) { - timeset = _.find(state.companyHoursEverybodyDestinations[group], (o) => { - return o.timesetId > 0; - }); - }; - }; - return timeset ? timeset.timesetId : null; - }, - getAfterHoursId(state) { - let timeset; - for (let group in state.afterHoursEverybodyDestinations) { if (!timeset) { - timeset = _.find(state.afterHoursEverybodyDestinations[group], (o) => { + timeset = _.find(state.destinations[group], (o) => { return o.timesetId > 0; }); }; @@ -111,17 +100,8 @@ export default { loadTimesets(state, result) { state.timesets = result; }, - loadDestinationsets(state, result) { - state.destinationsets = result; - }, - loadAlwaysEverybodyDestinations(state, result) { - state.alwaysEverybodyDestinations = result; - }, - loadCompanyHoursEverybodyDestinations(state, result) { - state.companyHoursEverybodyDestinations = result; - }, - loadAfterHoursEverybodyDestinations(state, result) { - state.afterHoursEverybodyDestinations = result; + loadDestinations(state, result) { + state.destinations = result; }, setActiveForm(state, value) { state.activeForm = value; @@ -196,6 +176,21 @@ export default { removeDestinationFailed(state, error) { state.removeDestinationState = DestinationState.failed; state.removeDestinationError = error; + }, + loadTimesetTimes(state, result) { + state.timesetTimes = result; + }, + setTimesetIsCompatible(state, value) { + state.timesetIsCompatible = value; + }, + setTimesetExists(state, value) { + state.timesetExists = value; + }, + setTimesetHasReverse(state, value) { + state.timesetHasReverse = value; + }, + setTimesetHasDuplicate(state, value) { + state.timesetHasDuplicate = value; } }, actions: { @@ -244,9 +239,9 @@ export default { loadEverybodyDestinations({ subscriberId: localStorage.getItem('subscriberId'), timeset: null - }).then((result)=>{ - context.commit('loadAlwaysEverybodyDestinations', result); - }) + }).then((result)=>{ + context.commit('loadDestinations', result); + }); }); }, loadCompanyHoursEverybodyDestinations(context) { @@ -254,9 +249,9 @@ export default { loadEverybodyDestinations({ subscriberId: localStorage.getItem('subscriberId'), timeset: 'Company Hours' - }).then((result)=>{ - context.commit('loadCompanyHoursEverybodyDestinations', result); - }) + }).then((result)=>{ + context.commit('loadDestinations', result); + }); }); }, loadAfterHoursEverybodyDestinations(context) { @@ -264,9 +259,9 @@ export default { loadEverybodyDestinations({ subscriberId: localStorage.getItem('subscriberId'), timeset: 'After Hours' - }).then((result)=>{ - context.commit('loadAfterHoursEverybodyDestinations', result); - }) + }).then((result)=>{ + context.commit('loadDestinations', result); + }); }); }, deleteDestinationFromDestinationset(context, options) { @@ -297,10 +292,9 @@ export default { let updatedOptions; let type = context.getters.getFormType; let timeset = null; - if (options.timeset === 'Company Hours') { - timeset = context.getters.getCompanyHoursId; - } else if (options.timeset === 'After Hours') { - timeset = context.getters.getAfterHoursId; + if (options.timeset === 'Company Hours' || + options.timeset === 'After Hours') { + timeset = context.getters.getTimesetId; }; context.commit('addDestinationRequesting'); if (type !== 'number') { @@ -412,6 +406,18 @@ export default { }, resetDestinationState(context) { context.commit('resetDestinationState'); + }, + loadTimesetTimes(context, options) { + loadTimesetTimes({ + timeset: options.timeset, + subscriberId: context.getters.getSubscriberId + }).then((result) => { + context.commit('loadTimesetTimes', result.times); + context.commit('setTimesetIsCompatible', result.timesetIsCompatible); + context.commit('setTimesetExists', result.timesetExists); + context.commit('setTimesetHasReverse', result.timesetHasReverse); + context.commit('setTimesetHasDuplicate', result.timesetHasDuplicate); + }); } } }; diff --git a/t/api/call-forward.js b/t/api/call-forward.js index 54800cf1..94fbf8ff 100644 --- a/t/api/call-forward.js +++ b/t/api/call-forward.js @@ -6,7 +6,10 @@ import VueResource from 'vue-resource'; import { getMappings, getSourcesets, getTimesets, getDestinationsets, getDestinationsetById, deleteDestinationFromDestinationset, - addDestinationToDestinationset } from '../../src/api/call-forward'; + addDestinationToDestinationset, + convertTimesetToWeekdays, + getHoursFromRange, + getDaysFromRange } from '../../src/api/call-forward'; import { assert } from 'chai'; Vue.use(VueResource); @@ -386,4 +389,270 @@ describe('CallForward', function(){ }); }); + it('should convert timeset with days and hours, and no minutes, to weekdays', function(){ + + let options = { + timesetName: "Company Hours", + timesets: [{ + id: 1, + name: "Company Hours", + subscriber_id: 309, + times: [{ + hour: "6-8", + mday: null, + minute: null, + month: null, + wday: "1-2", + year: null + }] + }] + }; + let convertedData = { + times: [ + { + from: "6:00", + hour: "6-8", + minute: null, + to: "9:00", + wday: "1-2", + weekday: "Sunday" + }, + { + from: "6:00", + hour: "6-8", + minute: null, + to: "9:00", + wday: "1-2", + weekday: "Monday" + } + ], + timesetExists: true, + timesetHasDuplicate: false, + timesetHasReverse: false, + timesetIsCompatible: true + }; + + assert.deepEqual(convertTimesetToWeekdays(options), convertedData); + + }); + + it('should convert timeset with days, hours and minutes to weekdays', function(){ + + let options = { + timesetName: "Company Hours", + timesets: [{ + id: 1, + name: "Company Hours", + subscriber_id: 309, + times: [{ + hour: "6-8", + mday: null, + minute: "0-30", + month: null, + wday: "1-2", + year: null + }] + }] + }; + let convertedData = { + times: [ + { + from: "6:0", + hour: "6-8", + minute: "0-30", + to: "6:31", + wday: "1-2", + weekday: "Sunday" + }, + { + from: "7:0", + hour: "6-8", + minute: "0-30", + to: "7:31", + wday: "1-2", + weekday: "Sunday" + }, + { + from: "8:0", + hour: "6-8", + minute: "0-30", + to: "8:31", + wday: "1-2", + weekday: "Sunday" + }, + { + from: "6:0", + hour: "6-8", + minute: "0-30", + to: "6:31", + wday: "1-2", + weekday: "Monday" + }, + { + from: "7:0", + hour: "6-8", + minute: "0-30", + to: "7:31", + wday: "1-2", + weekday: "Monday" + }, + { + from: "8:0", + hour: "6-8", + minute: "0-30", + to: "8:31", + wday: "1-2", + weekday: "Monday" + } + ], + timesetExists: true, + timesetHasDuplicate: false, + timesetHasReverse: false, + timesetIsCompatible: true + }; + + assert.deepEqual(convertTimesetToWeekdays(options), convertedData); + + }); + + it('should correctly convert timeset with single day, hour and minute', function(){ + + let options = { + timesetName: "Company Hours", + timesets: [{ + id: 1, + name: "Company Hours", + subscriber_id: 309, + times: [{ + hour: "6", + mday: null, + minute: "0", + month: null, + wday: "1", + year: null + }] + }] + }; + let convertedData = { + times: [ + { + from: "6:0", + hour: "6", + minute: "0", + to: "6:1", + wday: "1", + weekday: "Sunday" + } + ], + timesetExists: true, + timesetHasDuplicate: false, + timesetHasReverse: false, + timesetIsCompatible: true + }; + + assert.deepEqual(convertTimesetToWeekdays(options), convertedData); + + }); + + it('should attempt to convert timeset with year, returning compatibility error', function(){ + + let options = { + timesetName: "Company Hours", + timesets: [{ + id: 1, + name: "Company Hours", + subscriber_id: 309, + times: [{ + hour: "6-8", + mday: null, + minute: null, + month: null, + wday: "1-2", + year: "2018" + }] + }] + }; + let timesetIsCompatible = false; + + assert.equal(convertTimesetToWeekdays(options).timesetIsCompatible, timesetIsCompatible); + + }); + + it('should attempt to convert timeset with reverse range, returning compatibility error', function(){ + + let options = { + timesetName: "Company Hours", + timesets: [ + { + id: 1, + name: "Company Hours", + subscriber_id: 309, + times: [{ + hour: "8-6", + mday: null, + minute: null, + month: null, + wday: "1-2", + year: null + }] + } + ] + }; + let timesetHasReverse = true; + + assert.equal(convertTimesetToWeekdays(options).timesetHasReverse, timesetHasReverse); + + }); + + it('should attempt to convert duplicate timesets, returning compatibility error', function(){ + + let options = { + timesetName: "Company Hours", + timesets: [ + { + id: 1, + name: "Company Hours", + subscriber_id: 309, + times: [{ + hour: "8-6", + mday: null, + minute: null, + month: null, + wday: "1-2", + year: null + }] + }, + { + id: 3, + name: "Company Hours", + subscriber_id: 309, + times: [{ + hour: "8-14", + mday: null, + minute: null, + month: null, + wday: "1-4", + year: null + }] + } + ] + }; + let timesetHasDuplicate = true; + + assert.equal(convertTimesetToWeekdays(options).timesetHasDuplicate, timesetHasDuplicate); + + }); + + it('should attempt to convert empty timesets, returning error declaring that timeset is undefined', function(){ + + let options = { + timesetName: "Company Hours", + timesets: [] + }; + let timesetExists = false; + + assert.equal(convertTimesetToWeekdays(options).timesetExists, timesetExists); + + }); + }); diff --git a/t/store/call-forward.js b/t/store/call-forward.js index c8f1e6c3..266a26d9 100644 --- a/t/store/call-forward.js +++ b/t/store/call-forward.js @@ -6,12 +6,16 @@ import { assert } from 'chai'; describe('CallForward', function(){ - it('should load always everybody destinations', function(){ + it('should load always type destinations', function(){ let state = { - alwaysEverybodyDestinations: [ - ] + destinations: { + online: [], + busy: [], + offline: [] + } }; let data = { + online: [], busy: [], offline: [{ destinations: [{ @@ -30,87 +34,23 @@ describe('CallForward', function(){ }], id: 3, name: "csc_destinationset_1" - }], - online: [] + }] }; - CallForwardModule.mutations.loadAlwaysEverybodyDestinations(state, data); - assert.deepEqual(state.alwaysEverybodyDestinations, data); + CallForwardModule.mutations.loadDestinations(state, data); + assert.deepEqual(state.destinations, data); }); - it(' should reset destination form', function() { + it('should load timeset times', function(){ let state = { - conversations: [ - ] - }; - let data = { - announcement_id: null, - destination: '', - priority: 1, - timeout: '' - }; - CallForwardModule.mutations.resetFormState(state); - assert.deepEqual(state.form, data); - - it('should load company hours everybody destinations', function(){ - let state = { - companyHoursEverybodyDestinations: [ - ] - }; - let data = { - busy: [], - offline: [{ - destinations: [{ - "announcement_id": null, - "destination": "sip:3333@192.168.178.23", - "priority": 1, - "simple_destination": "3333", - "timeout": 60 - }, - { - "announcement_id": null, - "destination": "sip:2222@192.168.178.23", - "priority": 1, - "simple_destination": "2222", - "timeout": 300 - }], - id: 3, - name: "csc_destinationset_1" - }], - online: [] - }; - CallForwardModule.mutations.loadCompanyHoursEverybodyDestinations(state, data); - assert.deepEqual(state.companyHoursEverybodyDestinations, data); - }); - - it('should load after hours everybody destinations', function(){ - let state = { - afterHoursEverybodyDestinations: [ - ] - }; - let data = { - busy: [], - offline: [{ - destinations: [{ - "announcement_id": null, - "destination": "sip:3333@192.168.178.23", - "priority": 1, - "simple_destination": "3333", - "timeout": 60 - }, - { - "announcement_id": null, - "destination": "sip:2222@192.168.178.23", - "priority": 1, - "simple_destination": "2222", - "timeout": 300 - }], - id: 3, - name: "csc_destinationset_1" - }], - online: [] - }; - CallForwardModule.mutations.loadAfterHoursEverybodyDestinations(state, data); - assert.deepEqual(state.afterHoursEverybodyDestinations, data); + timesetTimes: [] + }; + let data = [ + { weekday: "Monday", from: "8", to: "16" }, + { weekday: "Tuesday", from: "8", to: "16" }, + { weekday: "Wednesday", from: "8", to: "16" } + ] + CallForwardModule.mutations.loadTimesetTimes(state, data); + assert.equal(state.timesetTimes, data); }); });