diff --git a/src/api/pbx-config.js b/src/api/pbx-config.js index 218689a8..015881c1 100644 --- a/src/api/pbx-config.js +++ b/src/api/pbx-config.js @@ -57,17 +57,15 @@ export function getAllProfiles () { }) } +export function getProfile (id) { + return get({ + path: `api/pbxdeviceprofiles/${id}` + }) +} + export function getModel (id) { - return new Promise((resolve, reject) => { - Promise.resolve().then(() => { - return get({ - path: 'api/pbxdevicemodels/' + id - }) - }).then((model) => { - resolve(model) - }).catch((err) => { - reject(err) - }) + return get({ + path: `api/pbxdevicemodels/${id}` }) } diff --git a/src/api/pbx-devices.js b/src/api/pbx-devices.js index 81170083..ed93b8d4 100644 --- a/src/api/pbx-devices.js +++ b/src/api/pbx-devices.js @@ -1,18 +1,14 @@ -import { - getModel, - getModelFrontImage, - PBX_CONFIG_ORDER_BY, - PBX_CONFIG_ORDER_DIRECTION -} from './pbx-config' +import { PBX_CONFIG_ORDER_BY, PBX_CONFIG_ORDER_DIRECTION } from './pbx-config' import _ from 'lodash' import { + get, getList, httpApi, patchAdd, patchRemove, patchReplace, patchReplaceFull -} from './common' +} from 'src/api/common' export function getDevices (options) { return new Promise((resolve, reject) => { @@ -28,6 +24,12 @@ export function getDevices (options) { }) }) } + +export function getDevice (id) { + return get({ + path: `api/pbxdevices/${id}` + }) +} export function getDevicesPreferences (options) { return new Promise((resolve, reject) => { let requestOptions = options || {} @@ -183,22 +185,6 @@ export function setDeviceKeys (deviceId, keys) { }) } -export async function loadDeviceModel (modelId) { - return new Promise((resolve, reject) => { - Promise.all([ - getModel(modelId), - getModelFrontImage(modelId) - ]).then((res) => { - resolve({ - model: res[0], - modelImage: res[1] - }) - }).catch((err) => { - reject(err) - }) - }) -} - export function setPreferenceDevice (deviceId, deviceValue, fieldName) { return new Promise((resolve, reject) => { Promise.resolve().then(() => { diff --git a/src/components/pages/PbxConfiguration/CscPbxDeviceConfig.vue b/src/components/pages/PbxConfiguration/CscPbxDeviceConfig.vue index 1d651688..0f48874b 100644 --- a/src/components/pages/PbxConfiguration/CscPbxDeviceConfig.vue +++ b/src/components/pages/PbxConfiguration/CscPbxDeviceConfig.vue @@ -36,7 +36,7 @@
+ import useValidate from '@vuelidate/core' +import CscListSpinner from 'components/CscListSpinner' import CscInputButtonReset from 'components/form/CscInputButtonReset' import CscInputButtonSave from 'components/form/CscInputButtonSave' import CscPageStickyTabs from 'components/CscPageStickyTabs' @@ -209,7 +213,9 @@ export default { CscInputButtonSave, CscInputButtonReset, CscPbxModelSelect, - CscPbxDeviceConfig + CscPbxDeviceConfig, + CscListSpinner + }, props: { initialTab: { @@ -248,13 +254,16 @@ export default { ]), ...mapGetters('pbx', [ 'getSubscriberOptions', - 'isSubscribersRequesting' + 'isSubscribersRequesting', + 'isDeviceInModelMap' ]), ...mapGetters('pbxDevices', [ 'getDeviceUpdateToastMessage', 'getDevicePreferencesUpdateToastMessage', 'isDeviceLoading', - 'isDevicePreferencesLoading' + 'isDevicePreferencesLoading', + 'isDeviceInMapBy', + 'isDeviceInPreferencesMap' ]), tabs () { return [ @@ -280,6 +289,18 @@ export default { hasProfileChanged () { return this.changes.profile_id !== this.deviceSelected?.profile_id }, + hasDeviceModelImage () { + if (!this.deviceSelected || !this.deviceSelected.profile_id) { + return false + } + + const profileMap = this.deviceProfileMap[this.deviceSelected.profile_id] + if (!profileMap || !profileMap.device_id) { + return false + } + + return !!this.deviceModelImageMap[profileMap.device_id] + }, imageUrl () { if (this.modelImage && this.modelImage.url) { return this.modelImage.url @@ -295,10 +316,8 @@ export default { }, watch: { async $route (to) { - if (this.id !== to.params.id) { - this.id = to.params.id - this.expandDevice(this.id) - } + this.id = to.params.id + await this.getData(this.id) }, deviceSelected () { this.changes = this.getDeviceData() @@ -319,13 +338,8 @@ export default { } }, async created () { - await this.loadDeviceListItems() - if (this.isDeviceMapByIdEmpty) { - await this.loadDeviceListItems() - } - this.expandDevice(this.id) - this.expandDevicePreferences(this.id) - await this.loadSubscribers() + const deviceId = this.deviceSelected?.id || this.id + await this.getData(deviceId) }, methods: { ...mapMutations('pbxDevices', [ @@ -333,7 +347,6 @@ export default { 'expandDevicePreferences' ]), ...mapActions('pbxDevices', [ - 'loadDeviceListItems', 'setDeviceKeys', 'setDeviceStationName', 'setDeviceIdentifier', @@ -342,11 +355,35 @@ export default { 'setAdminPassword', 'setGui', 'setUserConfig', - 'setFW' + 'setFW', + 'loadDevicePreferencesList', + 'loadDevice' ]), ...mapActions('pbx', [ - 'loadSubscribers' + 'loadSubscribers', + 'loadDeviceModel' + ]), + async getData (deviceId) { + if (!this.isDeviceInMapBy(deviceId)) { + await this.loadDevice(deviceId) + } + + if (!this.isDeviceInModelMap(deviceId)) { + await this.loadDeviceModel({ + type: 'all', + deviceId + }) + } + + if (!this.isDeviceInPreferencesMap(deviceId)) { + await this.loadDevicePreferencesList() + } + + this.expandDevice(deviceId) + this.expandDevicePreferences(deviceId) + this.loadSubscribers() + }, getDeviceData () { return (this.deviceSelected && this.devicePreferencesSelected) ? { diff --git a/src/pages/CscPagePbxDevices.vue b/src/pages/CscPagePbxDevices.vue index 2a044430..a6aa72b8 100644 --- a/src/pages/CscPagePbxDevices.vue +++ b/src/pages/CscPagePbxDevices.vue @@ -73,7 +73,7 @@
{ + return state.deviceMapById[deviceId] !== undefined + } + }, + isDeviceInPreferencesMap (state) { + return (deviceId) => { + return state.devicePreferencesMap[deviceId] !== undefined + } }, isDeviceListPaginationActive (state, getters) { const requesting = !getters.isDeviceListRequesting || getters.isDeviceCreating || @@ -153,41 +161,49 @@ export default { } }, mutations: { - deviceListItemsRequesting (state, options) { + deviceListRequesting (state, options) { const clearList = _.get(options, 'clearList', true) state.deviceListState = RequestState.requesting state.deviceListLastPage = null if (clearList) { state.deviceListVisibility = 'hidden' - state.deviceListItems = [] + state.deviceList = [] state.deviceMapById = {} } else { state.deviceListVisibility = 'visible' } }, - deviceListItemsSucceeded (state, options) { + deviceListSucceeded (state, options) { state.deviceListState = RequestState.succeeded state.deviceListCurrentPage = _.get(options, 'page', 1) - state.deviceListItems = _.get(options, 'devices.items', []) + state.deviceList = _.get(options, 'devices.items', []) state.deviceListLastPage = _.get(options, 'devices.lastPage', 1) state.deviceMapById = {} - state.deviceListItems.forEach((device) => { + state.deviceList.forEach((device) => { state.deviceMapById[device.id] = device }) state.deviceListVisibility = 'visible' }, - devicePreferencesListItemsSucceeded (state, options) { + deviceSucceeded (state, device) { + state.deviceListState = RequestState.succeeded + state.deviceList = [...state.deviceList, device] + state.deviceMapById[device.id] = device + }, + devicePreferencesListRequesting (state) { + state.devicePreferencesListState = RequestState.requesting + }, + devicePreferencesListSucceeded (state, options) { state.devicePreferencesListState = RequestState.succeeded - state.devicePreferencesListItems = _.get(options, 'devicesPreferences', []) + state.devicePreferencesList = _.get(options, 'devicesPreferences', []) state.devicePreferencesMap = {} - state.devicePreferencesListItems.forEach((devicePreferences) => { + state.devicePreferencesList.forEach((devicePreferences) => { state.devicePreferencesMap[devicePreferences.id] = devicePreferences }) }, - deviceListItemsFailed (state) { + deviceListFailed (state) { state.deviceListState = RequestState.failed }, - devicePreferencesListItemsFailed (state) { + devicePreferencesListFailed (state) { state.devicePreferencesListState = RequestState.failed }, deviceCreationRequesting (state, device) { @@ -215,11 +231,11 @@ export default { state.deviceUpdateState = RequestState.succeeded delete state.deviceMapById[device.id] state.deviceMapById[device.id] = device - for (let i = 0; i < state.deviceListItems.length; i++) { - if (state.deviceListItems[i].id === device.id) { - state.deviceListItems[i] = device + state.deviceList.forEach((item, index) => { + if (item.id === device.id) { + state.deviceList[index] = device } - } + }) if (state.deviceSelected !== null && state.deviceSelected.id === device.id) { state.deviceSelected = device } @@ -228,11 +244,11 @@ export default { 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 + state.devicePreferencesList.forEach((item, index) => { + if (item.id === device.id) { + state.devicePreferencesList[index] = device } - } + }) if (state.devicePreferencesSelected !== null && state.devicePreferencesSelected.id === device.id) { state.devicePreferencesSelected = device } @@ -280,56 +296,54 @@ export default { } }, actions: { - loadDeviceListItems (context, options) { - return new Promise((resolve, reject) => { - const page = _.get(options, 'page', context.state.deviceListCurrentPage) - const clearList = _.get(options, 'clearList', true) - const filters = _.get(options, 'filters', {}) - context.commit('deviceListItemsRequesting', { - clearList: clearList - }) - Promise.resolve().then(() => { - return context.dispatch('pbx/loadProfiles', null, { root: true }) - }).then(() => { - return getDeviceList({ - page: page, - filters - }) - }).then((devices) => { - context.commit('deviceListItemsSucceeded', { - devices: devices, - page: page - }) - resolve() - }).catch((err) => { - context.commit('deviceListItemsFailed', err.message) - reject(err) - }) - }) + async loadDeviceList (context, options) { + const page = _.get(options, 'page', context.state.deviceListCurrentPage) + const clearList = _.get(options, 'clearList', true) + const filters = _.get(options, 'filters', {}) + + context.commit('deviceListRequesting', { clearList }) + + try { + // Ensure profiles are loaded before fetching devices + await context.dispatch('pbx/loadProfiles', null, { root: true }) + const devices = await getDeviceList({ page, filters }) + context.commit('deviceListSucceeded', { devices, page }) + } catch (err) { + context.commit('deviceListFailed', err.message) + throw err + } + }, + async loadDevice (context, deviceId) { + context.commit('deviceListRequesting', { clearList: false }) + try { + // Ensure profiles are loaded before fetching devices + await context.dispatch('pbx/loadProfileById', deviceId, { root: true }) + const device = await getDevice(deviceId) + context.commit('deviceSucceeded', device) + } catch (err) { + context.commit('deviceListFailed', err.message) + throw err + } }, - 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) + async loadDevicePreferencesList (context) { + context.commit('devicePreferencesListRequesting') + try { + const devicesPreferences = await getDevicesPreferences() + context.commit('devicePreferencesListSucceeded', { + devicesPreferences: devicesPreferences.items }) - }) + } catch (err) { + context.commit('devicePreferencesListFailed', err.message) + } }, createDevice (context, deviceData) { context.commit('deviceCreationRequesting', deviceData) createDevice(deviceData).then(() => { - context.dispatch('loadDeviceListItems', { + context.dispatch('loadDeviceList', { page: 1, clearList: false }) - context.dispatch('loadDevicePreferencesListItems') + context.dispatch('loadDevicePreferencesList') }).then(() => { context.commit('deviceCreationSucceeded') }).catch((err) => { @@ -339,7 +353,7 @@ export default { removeDevice (context, deviceId) { context.commit('deviceRemovalRequesting', deviceId) removeDevice(deviceId).then(() => { - return context.dispatch('loadDeviceListItems', { + return context.dispatch('loadDeviceList', { page: context.state.deviceListCurrentPage, clearList: false }) diff --git a/src/store/pbx.js b/src/store/pbx.js index 649239f7..dc4148a8 100644 --- a/src/store/pbx.js +++ b/src/store/pbx.js @@ -2,18 +2,16 @@ import numberFilter from '../filters/number' import _ from 'lodash' import { - getAllProfiles, getModel, getModelFrontImage, getModelFrontThumbnailImage -} from '../api/pbx-config' -import { - getSubscribers -} from '../api/subscriber' -import { - RequestState -} from './common' -import { getNumbers } from '../api/user' -import { - i18n -} from 'src/boot/i18n' + getAllProfiles, + getModel, + getModelFrontImage, + getModelFrontThumbnailImage, + getProfile +} from 'src/api/pbx-config' +import { getSubscribers } from 'src/api/subscriber' +import { getNumbers } from 'src/api/user' +import { RequestState } from 'src/store/common' +import { i18n } from 'src/boot/i18n' export default { namespaced: true, @@ -28,6 +26,7 @@ export default { seatMapById: {}, soundSetList: [], soundSetMapByName: {}, + deviceProfilesListState: RequestState.initiated, deviceProfileList: [], deviceProfileMap: {}, deviceModelList: [], @@ -152,6 +151,11 @@ export default { }) return options }, + isDeviceInModelMap (state) { + return (deviceId) => { + return state.deviceModelMap[deviceId] !== undefined + } + }, isSubscribersRequesting (state) { return state.subscriberListState === RequestState.requesting }, @@ -223,16 +227,30 @@ export default { state.soundSetMapByName[soundSet.name] = soundSet }) }, - deviceProfilesSucceeded (state, deviceProfileList) { + deviceProfilesListStateRequesting (state) { + state.deviceProfilesListState = RequestState.requesting + }, + deviceProfilesListSucceeded (state, deviceProfileList) { + state.deviceProfilesListState = RequestState.succeeded state.deviceProfileList = _.get(deviceProfileList, 'items', []) state.deviceProfileMap = {} state.deviceProfileList.forEach((deviceProfile) => { state.deviceProfileMap[deviceProfile.id] = deviceProfile }) }, - deviceProfilesFailed (state) { - state.deviceProfileList = [] - state.deviceProfileMap = {} + deviceProfilesListFailed (state) { + state.deviceProfilesListState = RequestState.failed + }, + deviceProfileRequesting (state) { + state.deviceProfilesListState = RequestState.requesting + }, + deviceProfileSucceeded (state, deviceProfile) { + state.deviceProfilesListState = RequestState.succeeded + state.deviceProfileList = [...state.deviceProfileList, deviceProfile] + state.deviceProfileMap[deviceProfile.id] = deviceProfile + }, + deviceProfileFailed (state) { + state.deviceProfilesListState = RequestState.failed }, deviceModelSucceeded (state, deviceModel) { const model = _.get(deviceModel, 'model', null) @@ -268,12 +286,13 @@ export default { actions: { loadProfiles (context) { return new Promise((resolve, reject) => { + context.commit('deviceProfilesListStateRequesting') if (context.state.deviceProfileList.length === 0) { getAllProfiles().then((profiles) => { - context.commit('deviceProfilesSucceeded', profiles) + context.commit('deviceProfilesListSucceeded', profiles) resolve(profiles) }).catch((err) => { - context.commit('deviceProfilesFailed') + context.commit('deviceProfilesListFailed') reject(err) }) } else { @@ -281,6 +300,15 @@ export default { } }) }, + async loadProfileById (context, deviceId) { + context.commit('deviceProfileRequesting') + try { + const profile = await getProfile(deviceId) + context.commit('deviceProfileSucceeded', profile) + } catch (err) { + context.commit('deviceProfileFailed') + } + }, async loadDeviceModel (context, payload) { try { const isFrontCached = context.state.deviceModelImageMap[payload.deviceId] !== undefined @@ -336,13 +364,13 @@ export default { } }, async loadDeviceModels (context, imageType) { - const requests = [] - for (let i = 0; i < context.state.deviceProfileList.length; i++) { - requests.push(context.dispatch('loadDeviceModel', { - deviceId: context.state.deviceProfileList[i].device_id, + const requests = context.state.deviceProfileList.map((deviceProfile) => { + return context.dispatch('loadDeviceModel', { + deviceId: deviceProfile.device_id, type: imageType - })) - } + }) + }) + await Promise.all(requests) }, loadSubscribers (context) {