From f11e89813e44009f4a34c1e65a5cc5cad8b394c0 Mon Sep 17 00:00:00 2001 From: Nouhaila Idrissi Zouggari Date: Thu, 23 May 2024 16:01:37 +0200 Subject: [PATCH] MT#58736 Improve Cloud PBX Device configuration adding some preferences - Changing list view to 8 rows with 3 columns. - Preferences/Edit are now open in a separate page. - Adding the new 4 preferences ( - Admin Name/ Disable web GUI/ User config priority over-provisioning/FW upgrade disable) together with the existing parameters. Change-Id: Iae92c3313c592f7662587f52d0d4c9293ba41a97 --- src/api/pbx-devices.js | 53 ++- .../pages/PbxConfiguration/CscPbxDevice.vue | 274 ++---------- src/i18n/en.json | 25 ++ src/pages/CscPagePbxDeviceDetails.vue | 415 ++++++++++++++++++ src/pages/CscPagePbxDevices.vue | 41 +- src/router/routes.js | 75 ++-- src/store/pbx-devices.js | 261 ++++++++--- 7 files changed, 781 insertions(+), 363 deletions(-) create mode 100644 src/pages/CscPagePbxDeviceDetails.vue diff --git a/src/api/pbx-devices.js b/src/api/pbx-devices.js index d6ffbf44..81170083 100644 --- a/src/api/pbx-devices.js +++ b/src/api/pbx-devices.js @@ -7,9 +7,11 @@ import { import _ from 'lodash' import { getList, + httpApi, + patchAdd, + patchRemove, patchReplace, - patchReplaceFull, - httpApi + patchReplaceFull } from './common' export function getDevices (options) { @@ -26,6 +28,20 @@ export function getDevices (options) { }) }) } +export function getDevicesPreferences (options) { + return new Promise((resolve, reject) => { + let requestOptions = options || {} + requestOptions = _.merge(requestOptions, { + path: 'api/pbxfielddevicepreferences/', + root: '_embedded.ngcp:pbxfielddevicepreferences' + }) + getList(requestOptions).then((list) => { + resolve(list) + }).catch((err) => { + reject(err) + }) + }) +} export function getDeviceList (options) { return new Promise((resolve, reject) => { @@ -182,3 +198,36 @@ export async function loadDeviceModel (modelId) { }) }) } + +export function setPreferenceDevice (deviceId, deviceValue, fieldName) { + return new Promise((resolve, reject) => { + Promise.resolve().then(() => { + if (deviceValue === undefined || deviceValue === null || deviceValue === '' || (Array.isArray(deviceValue) && !deviceValue.length)) { + return patchRemove({ + path: 'api/pbxfielddevicepreferences/' + deviceId, + fieldPath: fieldName + }) + } + return patchReplaceFull({ + path: 'api/pbxfielddevicepreferences/' + deviceId, + fieldPath: fieldName, + value: deviceValue + }) + }).then((device) => { + resolve(device) + }).catch((err) => { + const errCode = err.status + '' + if (errCode === '422') { + return patchAdd({ + path: 'api/pbxfielddevicepreferences/' + deviceId, + fieldPath: fieldName, + value: deviceValue + }) + } + }).then((device) => { + resolve(device.data) + }).catch((err) => { + reject(err) + }) + }) +} diff --git a/src/components/pages/PbxConfiguration/CscPbxDevice.vue b/src/components/pages/PbxConfiguration/CscPbxDevice.vue index dec3acdd..c5416d9f 100644 --- a/src/components/pages/PbxConfiguration/CscPbxDevice.vue +++ b/src/components/pages/PbxConfiguration/CscPbxDevice.vue @@ -1,159 +1,64 @@ diff --git a/src/i18n/en.json b/src/i18n/en.json index d51771a0..9df4e107 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -24,6 +24,7 @@ "Add time range": "Add time range", "Added group {group}": "Added group {group}", "Added seat {seat}": "Added seat {seat}", + "Admin name": "Admin name", "After": "After", "Alias Number": "Alias Number", "Alias Numbers": "Alias Numbers", @@ -57,6 +58,8 @@ "Busy Lamp Field": "Busy Lamp Field", "CDR": "CDR", "CLI": "CLI", + "CSTA Client": "CSTA Client", + "CSTA Controller": "CSTA Controller", "Call": "Call", "Call Blocking": "Call Blocking", "Call Forwarding": "Call Forwarding", @@ -70,6 +73,7 @@ "Call back": "Call back", "Call ended": "Call ended", "Call forwarded": "Call forwarded", + "Call holded": "Call holded", "Call recordings": "Call recordings", "CallID": "CallID", "Callee": "Callee", @@ -121,6 +125,7 @@ "Custom Announcements": "Custom Announcements", "Custom sound": "Custom sound", "Customer Details": "Customer Details", + "Customer Phonebook": "Customer Phonebook", "Daily": "Daily", "Dashboard": "Dashboard", "Data is in the clipboard": "Data is in the clipboard", @@ -129,6 +134,7 @@ "Default sound": "Default sound", "Default sound set for all seats and groups": "Default sound set for all seats and groups", "Delete": "Delete", + "Delete customer phonebook": "Delete customer phonebook", "Delete destination": "Delete destination", "Delete forwarding": "Delete forwarding", "Delete recording": "Delete recording", @@ -148,8 +154,10 @@ "Devices": "Devices", "Direction": "Direction", "Disable": "Disable", + "Disable phone web interface": "Disable phone web interface", "Display Name": "Display Name", "Do not ring primary number": "Do not ring primary number", + "Download CSV": "Download CSV", "Download fax": "Download fax", "Download voicemail": "Download voicemail", "Duration": "Duration", @@ -168,6 +176,7 @@ "Expires": "Expires", "Extension": "Extension", "Extension Settings": "Extension Settings", + "FW Upgrade disable": "FW Upgrade disable", "Fax": "Fax", "Fax Settings": "Fax Settings", "Fax to Mail and Sendfax": "Fax to Mail and Sendfax", @@ -220,6 +229,7 @@ "If available": "If available", "If busy": "If busy", "If not available": "If not available", + "Ignore Members Call Forwards when Hunting": "Ignore Members Call Forwards when Hunting", "In": "In", "In call with": "In call with", "In call with {number}": "In call with {number}", @@ -330,12 +340,17 @@ "Phone number": "Phone number", "Pilot": "Pilot", "Play all files in loop": "Play all files in loop", + "Play announcement before call setup": "Play announcement before call setup", + "Play announcement before routing to CFU/CFNA": "Play announcement before routing to CFU/CFNA", + "Play announcement to callee after answer": "Play announcement to callee after answer", "Please fill or remove the empty slots": "Please fill or remove the empty slots", "Please select an option": "Please select an option", + "Powered by": "Powered by", "Preferences": "Preferences", "Primary Number": "Primary Number", "Privacy": "Privacy", "Private": "Private", + "Purge existing": "Purge existing", "Q-Value": "Q-Value", "QR code unavailable. Please retry later": "QR code unavailable. Please retry later", "Quality": "Quality", @@ -461,6 +476,7 @@ "There are no ACLs yet": "There are no ACLs yet", "There are no Key Renew Notify Emails yet": "There are no Key Renew Notify Emails yet", "There was an error, please retry later": "There was an error, please retry later", + "This number is already in use.": "This number is already in use.", "Thursday": "Thursday", "Time": "Time", "Time is invalid": "Time is invalid", @@ -486,13 +502,16 @@ "Updated {field} for device {device} successfully": "Updated {field} for device {device} successfully", "Updated {field} for manager secretary config {msConfig} successfully": "Updated {field} for manager secretary config {msConfig} successfully", "Updated {field} for sound set {soundSet} successfully": "Updated {field} for sound set {soundSet} successfully", + "Updated {field} successfully": "Updated {field} successfully", "Upload": "Upload", + "Upload CSV": "Upload CSV", "Use Parent": "Use Parent", "Use RegExp": "Use RegExp", "Use as default for all seats and groups": "Use as default for all seats and groups", "Use custom number": "Use custom number", "Use language specific preset": "Use language specific preset", "User Agent": "User Agent", + "User config priority over provisioning": "User config priority over provisioning", "User settings": "User settings", "Username": "Username", "Using Bye": "Using Bye", @@ -579,6 +598,12 @@ "ring": "ring", "second": "second", "seconds": "seconds", + "the behavior of the members call forwards from a Cloud PBX subscriber when it is called within a huntgroup": "the behavior of the members call forwards from a Cloud PBX subscriber when it is called within a huntgroup", + "the playback announcement as early media before Call Forward Unconditional or Unavailable": "the playback announcement as early media before Call Forward Unconditional or Unavailable", + "the playback announcement as early media before send the call to callee": "the playback announcement as early media before send the call to callee", + "the playback announcement to callee after he answered the call": "the playback announcement to callee after he answered the call", + "the right of this subscriber to be controlled by a CTI subscriber within the same customer using uaCSTA via SIP": "the right of this subscriber to be controlled by a CTI subscriber within the same customer using uaCSTA via SIP", + "the right this subscriber to initiate CTI sessions to other subscribers within the same customer using uaCSTA via SIP": "the right this subscriber to initiate CTI sessions to other subscribers within the same customer using uaCSTA via SIP", "the visibility of the number within own PBX": "the visibility of the number within own PBX", "to": "to", "unavailable": "unavailable", diff --git a/src/pages/CscPagePbxDeviceDetails.vue b/src/pages/CscPagePbxDeviceDetails.vue new file mode 100644 index 00000000..87162d90 --- /dev/null +++ b/src/pages/CscPagePbxDeviceDetails.vue @@ -0,0 +1,415 @@ + + + + diff --git a/src/pages/CscPagePbxDevices.vue b/src/pages/CscPagePbxDevices.vue index ab53b6b7..2a044430 100644 --- a/src/pages/CscPagePbxDevices.vue +++ b/src/pages/CscPagePbxDevices.vue @@ -79,8 +79,9 @@ - - +
{ @@ -106,7 +107,7 @@ const routes = [ component: CscPageSubscriberPhonebookAdd, meta: { get title () { - return i18n.global.tc('Add Phoneboossdsk') + return i18n.global.tc('Add Phonebook') } } }, @@ -294,6 +295,18 @@ const routes = [ } } }, + { + path: 'pbx-configuration/device/:id', + component: CscPagePbxDeviceDetails, + meta: { + get title () { + return i18n.global.tc('PBX Configuration') + }, + get subtitle () { + return i18n.global.tc('Devices') + } + } + }, { path: 'pbx-configuration/seat/:id', component: CscPagePbxSeatDetails, diff --git a/src/store/pbx-devices.js b/src/store/pbx-devices.js index ec725003..2507e0a6 100644 --- a/src/store/pbx-devices.js +++ b/src/store/pbx-devices.js @@ -5,13 +5,15 @@ import { } from './common' import _ from 'lodash' import { - getDeviceList, createDevice, + getDeviceList, + getDevicesPreferences, removeDevice, - setDeviceStationName, setDeviceIdentifier, + setDeviceKeys, setDeviceProfile, - setDeviceKeys + setDeviceStationName, + setPreferenceDevice } from '../api/pbx-devices' import { i18n @@ -20,40 +22,81 @@ import { export default { namespaced: true, state: { - deviceListState: RequestState.initiated, - deviceListVisibility: 'visible', - deviceListItems: [], + deviceCreating: null, + deviceCreationError: null, + deviceCreationState: CreationState.initiated, deviceListCurrentPage: 1, + deviceListItems: [], deviceListLastPage: null, + deviceListState: RequestState.initiated, + deviceListVisibility: 'visible', + deviceMap: {}, + devicePreferencesListItems: [], + devicePreferencesListState: RequestState.initiated, + devicePreferencesMap: {}, + devicePreferencesRemovalState: RequestState.initiated, + devicePreferencesRemoving: null, + devicePreferencesSelected: null, + devicePreferencesUpdateError: null, + devicePreferencesUpdateState: RequestState.initiated, + devicePreferencesUpdating: null, + devicePreferencesUpdatingField: null, + deviceRemovalError: null, + deviceRemovalState: RequestState.initiated, + deviceRemoving: null, deviceSelected: null, - deviceCreating: null, - deviceCreationState: CreationState.initiated, - deviceCreationError: null, - deviceUpdating: null, - deviceUpdatingField: null, - deviceUpdateState: RequestState.initiated, deviceUpdateError: null, - deviceRemoving: null, - deviceRemovalState: RequestState.initiated, - deviceRemovalError: null, - deviceMapById: {} + deviceUpdateState: RequestState.initiated, + deviceUpdating: null, + deviceUpdatingField: null }, getters: { - isDeviceListEmpty (state) { - return Array.isArray(state.deviceListItems) && state.deviceListItems.length === 0 + getDeviceCreatingName (state) { + return _.get(state, 'deviceCreating.stationName', '') }, - isDeviceListRequesting (state) { - return state.deviceListState === RequestState.requesting + getDeviceCreationToastMessage (state, getters) { + return i18n.global.tc('Created device {device} successfully', { + device: getters.getDeviceCreatingName + }) }, - isDeviceExpanded (state) { - return (id) => { - return state.deviceSelected !== null && state.deviceSelected.id === id + getDevicePreferencesUpdateToastMessage (state, getters) { + return i18n.global.tc('Updated {field} successfully', { + field: getters.getDevicePreferencesUpdatingField + }) + }, + getDevicePreferencesUpdatingField (state) { + return state.devicePreferencesUpdatingField + }, + getDevicePreferencesUpdatingName (state) { + return _.get(state, 'devicePreferencesUpdating.admin_name', '') + }, + getDeviceRemoveDialogMessage (state, getters) { + if (getters.isDeviceRemoving) { + return i18n.global.tc('You are about to remove device {device}', { + device: getters.getDeviceRemovingName + }) } + return '' }, - isDeviceListPaginationActive (state, getters) { - const requesting = !getters.isDeviceListRequesting || getters.isDeviceCreating || - getters.isDeviceRemoving || getters.isDeviceUpdating - return !getters.isDeviceListEmpty && requesting && state.deviceListLastPage > 1 + getDeviceRemovingName (state) { + return _.get(state, 'deviceRemoving.station_name', '') + }, + getDeviceRemovalToastMessage (state, getters) { + return i18n.global.tc('Removed device {device} successfully', { + device: getters.getDeviceRemovingName + }) + }, + getDeviceUpdateToastMessage (state, getters) { + return i18n.global.tc('Updated {field} for device {device} successfully', { + device: getters.getDeviceUpdatingName, + field: getters.getDeviceUpdatingField + }) + }, + getDeviceUpdatingField (state) { + return state.deviceUpdatingField + }, + getDeviceUpdatingName (state) { + return _.get(state, 'deviceUpdating.station_name', '') }, isDeviceAddFormDisabled (state) { return state.deviceCreationState === CreationState.initiated || @@ -62,11 +105,21 @@ export default { isDeviceCreating (state) { return state.deviceCreationState === CreationState.creating }, - isDeviceRemoving (state) { - return state.deviceRemovalState === RequestState.requesting + isDeviceExpanded (state) { + return (id) => { + return state.deviceSelected !== null && state.deviceSelected.id === id + } }, - isDeviceUpdating (state) { - return state.deviceUpdateState === RequestState.requesting + isDeviceListEmpty (state) { + return Array.isArray(state.deviceListItems) && state.deviceListItems.length === 0 + }, + isDeviceListPaginationActive (state, getters) { + const requesting = !getters.isDeviceListRequesting || getters.isDeviceCreating || + getters.isDeviceRemoving || getters.isDeviceUpdating + return !getters.isDeviceListEmpty && requesting && state.deviceListLastPage > 1 + }, + isDeviceListRequesting (state) { + return state.deviceListState === RequestState.requesting }, isDeviceLoading (state, getters) { return (deviceId) => { @@ -74,41 +127,23 @@ export default { (getters.isDeviceRemoving && state.deviceRemoving.id === deviceId) } }, - getDeviceRemovingName (state) { - return _.get(state, 'deviceRemoving.station_name', '') - }, - getDeviceCreatingName (state) { - return _.get(state, 'deviceCreating.stationName', '') - }, - getDeviceUpdatingName (state) { - return _.get(state, 'deviceUpdating.station_name', '') - }, - getDeviceUpdatingField (state) { - return state.deviceUpdatingField - }, - getDeviceRemoveDialogMessage (state, getters) { - if (getters.isDeviceRemoving) { - return i18n.global.tc('You are about to remove device {device}', { - device: getters.getDeviceRemovingName - }) + isDevicePreferencesLoading (state, getters) { + return (devicePreferencesId) => { + return (getters.isDevicePreferencesUpdating && state.devicePreferencesUpdating.id === devicePreferencesId) || + (getters.isDevicePreferencesRemoving && state.devicePreferencesRemoving.id === devicePreferencesId) } - return '' }, - getDeviceCreationToastMessage (state, getters) { - return i18n.global.tc('Created device {device} successfully', { - device: getters.getDeviceCreatingName - }) + isDevicePreferencesRemoving (state) { + return state.devicePreferencesRemovalState === RequestState.requesting }, - getDeviceUpdateToastMessage (state, getters) { - return i18n.global.tc('Updated {field} for device {device} successfully', { - device: getters.getDeviceUpdatingName, - field: getters.getDeviceUpdatingField - }) + isDevicePreferencesUpdating (state) { + return state.devicePreferencesUpdateState === RequestState.requesting }, - getDeviceRemovalToastMessage (state, getters) { - return i18n.global.tc('Removed device {device} successfully', { - device: getters.getDeviceRemovingName - }) + isDeviceRemoving (state) { + return state.deviceRemovalState === RequestState.requesting + }, + isDeviceUpdating (state) { + return state.deviceUpdateState === RequestState.requesting } }, mutations: { @@ -135,9 +170,20 @@ export default { }) state.deviceListVisibility = 'visible' }, + devicePreferencesListItemsSucceeded (state, options) { + state.devicePreferencesListState = RequestState.succeeded + state.devicePreferencesListItems = _.get(options, 'devicesPreferences', []) + state.devicePreferencesMap = {} + state.devicePreferencesListItems.forEach((devicePreferences) => { + state.devicePreferencesMap[devicePreferences.id] = devicePreferences + }) + }, deviceListItemsFailed (state) { state.deviceListState = RequestState.failed }, + devicePreferencesListItemsFailed (state) { + state.devicePreferencesListState = RequestState.failed + }, deviceCreationRequesting (state, device) { state.deviceCreationState = CreationState.creating state.deviceCreating = device @@ -154,6 +200,11 @@ export default { state.deviceUpdatingField = options.deviceField state.deviceUpdateState = RequestState.requesting }, + devicePreferencesUpdateRequesting (state, options) { + state.devicePreferencesUpdating = state.devicePreferencesMap[options.deviceId] + state.devicePreferencesUpdatingField = options.devicePreferencesField + state.devicePreferencesUpdateState = RequestState.requesting + }, deviceUpdateSucceeded (state, device) { state.deviceUpdateState = RequestState.succeeded delete state.deviceMap[device.id] @@ -163,12 +214,33 @@ export default { state.deviceListItems[i] = device } } + if (state.deviceSelected !== null && state.deviceSelected.id === device.id) { + state.deviceSelected = device + } + }, + devicePreferencesUpdateSucceeded (state, device) { + state.devicePreferencesUpdateState = RequestState.succeeded + delete state.devicePreferencesMap[device.id] + state.devicePreferencesMap[device.id] = device + for (let i = 0; i < state.devicePreferencesListItems.length; i++) { + if (state.devicePreferencesListItems[i].id === device.id) { + state.devicePreferencesListItems[i] = device + } + } + if (state.devicePreferencesSelected !== null && state.devicePreferencesSelected.id === device.id) { + state.devicePreferencesSelected = device + } }, deviceUpdateFailed (state, err) { state.deviceUpdating = null state.deviceUpdateState = RequestState.failed state.deviceUpdateError = err }, + devicePreferencesUpdateFailed (state, err) { + state.devicePreferencesUpdating = null + state.devicePreferencesUpdateState = RequestState.failed + state.devicePreferencesUpdateError = err + }, deviceRemovalRequesting (state, id) { state.deviceRemovalState = RequestState.requesting state.deviceRemoving = state.deviceMap[id] @@ -187,6 +259,9 @@ export default { expandDevice (state, deviceId) { state.deviceSelected = state.deviceMap[deviceId] }, + expandDevicePreferences (state, devicePreferencesId) { + state.devicePreferencesSelected = state.devicePreferencesMap[devicePreferencesId] + }, collapseDevice (state) { state.deviceSelected = null }, @@ -226,13 +301,29 @@ export default { }) }) }, + loadDevicePreferencesListItems (context) { + return new Promise((resolve, reject) => { + Promise.resolve().then(() => { + return getDevicesPreferences() + }).then((devicesPreferences) => { + context.commit('devicePreferencesListItemsSucceeded', { + devicesPreferences: devicesPreferences.items + }) + resolve() + }).catch((err) => { + context.commit('devicePreferencesListItemsFailed', err.message) + reject(err) + }) + }) + }, createDevice (context, deviceData) { context.commit('deviceCreationRequesting', deviceData) createDevice(deviceData).then(() => { - return context.dispatch('loadDeviceListItems', { + context.dispatch('loadDeviceListItems', { page: 1, clearList: false }) + context.dispatch('loadDevicePreferencesListItems') }).then(() => { context.commit('deviceCreationSucceeded') }).catch((err) => { @@ -295,6 +386,50 @@ export default { }).catch((err) => { context.commit('deviceUpdateFailed', err.message) }) + }, + setAdminName (context, options) { + context.commit('devicePreferencesUpdateRequesting', { + deviceId: options.deviceId, + devicePreferencesField: i18n.global.tc('Admin name') + }) + setPreferenceDevice(options.deviceId, options.adminName, 'admin_name').then((device) => { + context.commit('devicePreferencesUpdateSucceeded', device) + }).catch((err) => { + context.commit('devicePreferencesUpdateFailed', err.message) + }) + }, + setFW (context, options) { + context.commit('devicePreferencesUpdateRequesting', { + deviceId: options.deviceId, + devicePreferencesField: i18n.global.tc('FW Upgrade disable') + }) + setPreferenceDevice(options.deviceId, options.FWupg, 'FW_upg_dis').then((device) => { + context.commit('devicePreferencesUpdateSucceeded', device) + }).catch((err) => { + context.commit('devicePreferencesUpdateFailed', err.message) + }) + }, + setGui (context, options) { + context.commit('devicePreferencesUpdateRequesting', { + deviceId: options.deviceId, + devicePreferencesField: i18n.global.tc('Disable phone web interface') + }) + setPreferenceDevice(options.deviceId, options.webGui, 'web_gui_dis').then((device) => { + context.commit('devicePreferencesUpdateSucceeded', device) + }).catch((err) => { + context.commit('devicePreferencesUpdateFailed', err.message) + }) + }, + setUserConfig (context, options) { + context.commit('devicePreferencesUpdateRequesting', { + deviceId: options.deviceId, + devicePreferencesField: i18n.global.tc('User config priority over provisioning') + }) + setPreferenceDevice(options.deviceId, options.userConf, 'user_conf_priority').then((device) => { + context.commit('devicePreferencesUpdateSucceeded', device) + }).catch((err) => { + context.commit('devicePreferencesUpdateFailed', err.message) + }) } } }