From fb4ba3093bf887e35045af030da3f70e56e6fb02 Mon Sep 17 00:00:00 2001 From: raxelsen Date: Wed, 23 Jan 2019 15:23:26 +0100 Subject: [PATCH] TT#47510 Extra page section for managing SoundSets What has been done: - TT#47510, SoundManagement: As a SubscriberAdmin, I want to have an extra page section for managing SoundSets - TT#47511, SoundManagement: As a SubscriberAdmin, I want to see a list of all owned SoundSets Change-Id: I1e1d6d49d90d1b8b5deef5689c686b921eb6f7d8 --- src/api/pbx-config.js | 112 ++++++++++- src/components/layouts/MainMenu.vue | 11 ++ .../PbxConfiguration/CscPbxSoundGroup.vue | 82 ++++++++ .../PbxConfiguration/CscPbxSoundItem.vue | 129 ++++++++++++ .../pages/PbxConfiguration/CscPbxSoundSet.vue | 187 ++++++++++++++++++ .../PbxConfiguration/CscPbxSoundSets.vue | 70 +++++++ src/locales/en.json | 7 +- src/routes.js | 9 + src/store/pbx-config/actions.js | 34 +++- src/store/pbx-config/getters.js | 11 ++ src/store/pbx-config/mutations.js | 32 +++ src/store/pbx-config/state.js | 8 +- t/store/pbx-config.js | 27 +++ 13 files changed, 714 insertions(+), 5 deletions(-) create mode 100644 src/components/pages/PbxConfiguration/CscPbxSoundGroup.vue create mode 100644 src/components/pages/PbxConfiguration/CscPbxSoundItem.vue create mode 100644 src/components/pages/PbxConfiguration/CscPbxSoundSet.vue create mode 100644 src/components/pages/PbxConfiguration/CscPbxSoundSets.vue diff --git a/src/api/pbx-config.js b/src/api/pbx-config.js index 802054dc..0b85908c 100644 --- a/src/api/pbx-config.js +++ b/src/api/pbx-config.js @@ -24,7 +24,7 @@ import { removeCallQueueConfig } from './subscriber'; import uuid from 'uuid'; -import { getList, get, patchReplace } from './common' +import { getList, get, patchReplace} from './common' var createId = uuid.v4; @@ -602,3 +602,113 @@ export function setWrapUpTimeConfig(id, wrapUpTime) { export function getPrefs(id) { return getPreferences(id); } + +export function getAllSoundSets(options) { + return new Promise((resolve, reject)=>{ + options = options || {}; + options = _.merge(options, { + path: 'api/soundsets/', + root: '_embedded.ngcp:soundsets', + all: true + }); + getList(options).then((list)=>{ + list.items.map((set) => { + delete set._links; + }); + resolve(list); + }).catch((err)=>{ + reject(err); + }); + }); +} + +export function getSoundHandles(options) { + return new Promise((resolve, reject)=>{ + options = options || {}; + options = _.merge(options, { + path: 'api/soundhandles/', + root: '_embedded.ngcp:soundhandles', + all: true + }); + getList(options).then((list) => { + // Ngcp-panel only lists three groups ('digits', 'music_on_hold' + // and 'pbx'). Filtering out the rest for that reason, as the + // enpoint has 11 groups total + let soundHandles = list.items.filter((handle) => { + return ['digits', 'music_on_hold', 'pbx'].indexOf(handle.group) > -1; + }); + resolve(soundHandles); + }).catch((err)=>{ + reject(err); + }); + }); +} + +export function getSoundFilesBySet(options) { + return new Promise((resolve, reject)=>{ + options = options || {}; + options = _.merge(options, { + path: 'api/soundfiles/', + root: '_embedded.ngcp:soundfiles', + all: true + }); + getList(options).then((result)=>{ + let list = result.items.map((file) => { + return { + filename: file.filename, + handle: file.handle, + loopplay: file.loopplay, + id: file.id + }; + }); + resolve(list); + }).catch((err)=>{ + reject(err); + }); + }); +} + +export function getSoundFilesGrouped(options) { + let handles = []; + return new Promise((resolve, reject) => { + Promise.resolve().then(() => { + return getSoundHandles(); + }).then((soundHandles) => { + handles = soundHandles.map((handle) => { + return { + group: handle.group, + handle: handle.handle, + filename: '', + id: null, + loopplay: null + }; + }); + return getSoundFilesBySet(options); + }).then((files) => { + files.forEach((file) => { + handles.forEach((handle) => { + if (file.handle === handle.handle) { + handle.filename = file.filename; + handle.id = file.id; + handle.loopplay = file.loopplay + } + }); + }); + return handles; + }).then((merged) => { + let groupedFiles = { + groups: _(merged) + .groupBy('group') + .map((items, group) => { + return { + name: group, + handles: items + }; + }).value() + }; + resolve(groupedFiles); + }).catch((err)=>{ + reject(err); + }); + }); +} diff --git a/src/components/layouts/MainMenu.vue b/src/components/layouts/MainMenu.vue index 00a2de4e..67ee1ab9 100644 --- a/src/components/layouts/MainMenu.vue +++ b/src/components/layouts/MainMenu.vue @@ -191,6 +191,17 @@ :label="$t('navigation.pbxConfiguration.callQueues')" /> + + + + diff --git a/src/components/pages/PbxConfiguration/CscPbxSoundGroup.vue b/src/components/pages/PbxConfiguration/CscPbxSoundGroup.vue new file mode 100644 index 00000000..e0cc721f --- /dev/null +++ b/src/components/pages/PbxConfiguration/CscPbxSoundGroup.vue @@ -0,0 +1,82 @@ + + + + + diff --git a/src/components/pages/PbxConfiguration/CscPbxSoundItem.vue b/src/components/pages/PbxConfiguration/CscPbxSoundItem.vue new file mode 100644 index 00000000..78077af3 --- /dev/null +++ b/src/components/pages/PbxConfiguration/CscPbxSoundItem.vue @@ -0,0 +1,129 @@ + + + + + diff --git a/src/components/pages/PbxConfiguration/CscPbxSoundSet.vue b/src/components/pages/PbxConfiguration/CscPbxSoundSet.vue new file mode 100644 index 00000000..5e48e545 --- /dev/null +++ b/src/components/pages/PbxConfiguration/CscPbxSoundSet.vue @@ -0,0 +1,187 @@ + + + + + diff --git a/src/components/pages/PbxConfiguration/CscPbxSoundSets.vue b/src/components/pages/PbxConfiguration/CscPbxSoundSets.vue new file mode 100644 index 00000000..7052ef63 --- /dev/null +++ b/src/components/pages/PbxConfiguration/CscPbxSoundSets.vue @@ -0,0 +1,70 @@ + + + + + diff --git a/src/locales/en.json b/src/locales/en.json index 1049d388..85568c18 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -87,7 +87,8 @@ "groups": "Groups", "seats": "Seats", "devices": "Devices", - "callQueues": "Call Queues" + "callQueues": "Call Queues", + "soundSets": "Sound Sets" }, "voicebox": { "title": "Voicebox", @@ -360,6 +361,7 @@ "noGroups": "No groups created yet", "noSeats": "No seats created yet", "noCallQueues": "No call queues created yet", + "noSoundSets": "No sound sets created yet", "toasts": { "changedFieldToast": "Changed {type} to {name}", "updatedAliasNumbersToast": "Alias numbers field updated!", @@ -410,7 +412,8 @@ "removeConfigTitle": "Remove call queue", "removeConfigText": "You are about to remove call queue for {subscriber}", "seconds": "seconds", - "callers": "callers" + "callers": "callers", + "description": "Description" }, "callBlocking": { "privacyEnabledToast": "Your number is hidden to the callee", diff --git a/src/routes.js b/src/routes.js index 11492647..64f7f392 100644 --- a/src/routes.js +++ b/src/routes.js @@ -15,6 +15,7 @@ import PbxConfigurationGroups from './components/pages/PbxConfiguration/CscPbxGr import PbxConfigurationSeats from './components/pages/PbxConfiguration/CscPbxSeats' import PbxConfigurationDevices from './components/pages/PbxConfiguration/CscPbxDevices' import PbxConfigurationCallQueues from './components/pages/PbxConfiguration/CscPbxCallQueues' +import PbxConfigurationSoundSets from './components/pages/PbxConfiguration/CscPbxSoundSets' import Voicebox from './components/pages/Voicebox/Voicebox'; import Login from './components/Login' import Error404 from './components/Error404' @@ -135,6 +136,14 @@ export default [ subtitle: i18n.t('navigation.pbxConfiguration.callQueues') } }, + { + path: 'pbx-configuration/sound-sets', + component: PbxConfigurationSoundSets, + meta: { + title: i18n.t('navigation.pbxConfiguration.title'), + subtitle: i18n.t('navigation.pbxConfiguration.soundSets') + } + }, { path: 'voicebox', component: Voicebox, diff --git a/src/store/pbx-config/actions.js b/src/store/pbx-config/actions.js index b3b69991..8865282b 100644 --- a/src/store/pbx-config/actions.js +++ b/src/store/pbx-config/actions.js @@ -37,7 +37,9 @@ import { setWrapUpTimeConfig, getConfig, getPrefs, - removeCallQueue + removeCallQueue, + getAllSoundSets, + getSoundFilesGrouped } from '../../api/pbx-config' export default { @@ -550,5 +552,35 @@ export default { }).catch((err)=>{ context.commit('removeItemFailed', err.message); }); + }, + listSoundSets(context) { + context.commit('listSoundSetsRequesting'); + getAllSoundSets().then((data) => { + context.commit('listSoundSetsSucceeded', data); + return data; + }).then((sets) => { + sets.items.forEach((set) => { + context.dispatch('loadFilesForSoundSet', set.id); + }); + }).catch((err) => { + context.commit('listSoundSetsFailed', err.message) + }); + }, + loadFilesForSoundSet(context, id) { + let options = { + params: { + set_id: id + '' + } + } + context.commit('filesForSoundSetRequesting', id); + getSoundFilesGrouped(options).then((files) => { + let id = options.params.set_id; + context.commit('filesForSoundSetSucceeded', { + files: files, + id: id + }); + }).catch((err) => { + context.commit('filesForSoundSetFailed', id, err); + }) } } diff --git a/src/store/pbx-config/getters.js b/src/store/pbx-config/getters.js index a97509b6..97e7b0a2 100644 --- a/src/store/pbx-config/getters.js +++ b/src/store/pbx-config/getters.js @@ -324,5 +324,16 @@ export default { return item.id === id; }) } + }, + soundSets(state) { + return state.soundSetsOrdered; + }, + soundSetFilesLoading(state) { + return (id) => { + return state.soundSetFilesStates[id] !== 'succeeded'; + } + }, + isSoundSetsRequesting(state) { + return state.listSoundSetsState === RequestState.requesting; } } diff --git a/src/store/pbx-config/mutations.js b/src/store/pbx-config/mutations.js index 4a67bec7..13d0d0b7 100644 --- a/src/store/pbx-config/mutations.js +++ b/src/store/pbx-config/mutations.js @@ -471,5 +471,37 @@ export default { id = id + ""; reactiveSet(state[type + 'States'], id, RequestState.failed); reactiveSet(state[type + 'Errors'], id, error); + }, + listSoundSetsRequesting(state) { + state.listSoundSetsState = RequestState.requesting; + state.listSoundSetsError = null; + }, + listSoundSetsSucceeded(state, sets) { + state.listSoundSetsState = RequestState.succeeded; + state.listSoundSetsError = null; + state.soundSets = {}; + state.soundSetsOrdered = []; + sets.items.forEach((set) => { + state.soundSets[set.id] = set; + state.soundSetsOrdered.push(set); + }); + }, + listSoundSetsFailed(state, error) { + state.listSoundSetsState = RequestState.failed; + state.listSoundSetsError = error; + }, + filesForSoundSetRequesting(state, id) { + reactiveSet(state.soundSetFilesStates, id, RequestState.requesting); + }, + filesForSoundSetSucceeded(state, options) { + let id = options.id; + reactiveSet(state.soundSetFilesStates, id, RequestState.succeeded); + reactiveSet(state.soundSetFilesErrors, id, null); + Vue.set(state.soundSets, id, Object.assign(state.soundSets[id], options.files)); + }, + filesForSoundSetFailed(state, id, error) { + id = id + ""; + reactiveSet(state.soundSetFilesStates, id, RequestState.failed); + reactiveSet(state.soundSetFilesErrors, id, error); } } diff --git a/src/store/pbx-config/state.js b/src/store/pbx-config/state.js index d79c2f06..2e9f223d 100644 --- a/src/store/pbx-config/state.js +++ b/src/store/pbx-config/state.js @@ -78,5 +78,11 @@ export default { groupStates: {}, groupErrors: {}, seatStates: {}, - seatErrors: {} + seatErrors: {}, + listSoundSetsState: RequestState.initiated, + listSoundSetsError: null, + soundSets: {}, + soundSetsOrdered: [], + soundSetFilesStates: {}, + soundSetFilesErrors: {} } diff --git a/t/store/pbx-config.js b/t/store/pbx-config.js index 2690a9cf..d5ffa693 100644 --- a/t/store/pbx-config.js +++ b/t/store/pbx-config.js @@ -50,4 +50,31 @@ describe('PBX Configuration Store', () => { assert.deepEqual(state.numbers, data.numbers); }); + it('should list all Sound Sets', () => { + let state = {}; + let data = { + items: [ + { + contract_defaults: true, + customer_id: null, + description: 'Set description 1', + groups: [], + id: 15, + name: 'Set 1' + }, + { + contract_defaults: false, + customer_id: null, + description: 'Set description 2', + groups: [], + id: 17, + name: 'Set 2' + } + ] + }; + PbxConfig.mutations.listSoundSetsSucceeded(state, data); + assert.equal(state.soundSets[15], data.items[0]); + assert.equal(state.soundSets[17], data.items[1]); + }); + });