MT#62916 Pbx Devices Bugfix

Listed here the changes:
- change properties accessed directly
  from state with computed properties
  that handles null cases
- Fix typos for subcriberListState
  and subcriberListError
- Improve route watcher in
  CscPagePbxDeviceDetails
- add a method to load only thumbnails
  instead of full set of data for
  the device profiles to improve
  performance.
- removed 1000 rows for loadProfiles()
  as it was too slow. We expect max 150
  devices so it was set to 300 rows.
Note, more refactoring will be needed.

Change-Id: Iefe0328052174f0bb93f8cdbae59f77257592592
mr13.4
Debora Crescenzo 4 months ago committed by Crescenzo Debora
parent 38c2f37c1a
commit d8c1f097cc

@ -87,8 +87,8 @@ export async function getList (options) {
const requestConfig = _.merge({ const requestConfig = _.merge({
all: false, all: false,
params: { params: {
page: LIST_DEFAULT_PAGE, page: options.page || LIST_DEFAULT_PAGE,
rows: LIST_DEFAULT_ROWS rows: options.rows || LIST_DEFAULT_ROWS
}, },
headers: GET_HEADERS headers: GET_HEADERS
}, options) }, options)

@ -48,8 +48,10 @@ export function getProfiles (options) {
} }
export function getAllProfiles () { export function getAllProfiles () {
// Replace 1000 rows with 300 as we expect to have max 150 profiles.
return getProfiles({ return getProfiles({
all: true page: 1,
rows: 300
}) })
} }

@ -9,10 +9,21 @@
center center
no-wrap no-wrap
> >
<img <q-icon
class="csc-list-item-head-image" v-if="!imageUrl"
:src="imageUrl" name="fas fa-fax"
size="24px"
/>
<q-avatar
v-else
square
> >
<q-img
class="csc-list-item-head-image"
:src="imageUrl"
/>
</q-avatar>
</q-item-section> </q-item-section>
<q-item-section> <q-item-section>
<csc-list-item-title> <csc-list-item-title>

@ -119,8 +119,8 @@ export default {
'deviceProfileMap', 'deviceProfileMap',
'deviceProfileList', 'deviceProfileList',
'subscriberList', 'subscriberList',
'subcriberListState', 'subscriberListState',
'subcriberListError' 'subscriberListError'
]), ]),
subscribersOptions () { subscribersOptions () {
const options = [] const options = []
@ -196,9 +196,9 @@ export default {
filterTypeModel () { filterTypeModel () {
this.typedFilter = null this.typedFilter = null
}, },
subcriberListState (state) { subscriberListState (state) {
if (state === RequestState.failed) { if (state === RequestState.failed) {
showGlobalError(this.subcriberListError) showGlobalError(this.subscriberListError)
} }
} }
}, },

@ -49,10 +49,11 @@
> >
<q-avatar <q-avatar
square square
size="32px"
> >
<img <q-img
:src="deviceModelImageSmallMap[scope.opt.model].url" :src="deviceModelImageSmallMap[scope.opt.model].url"
> />
</q-avatar> </q-avatar>
</q-item-section> </q-item-section>
<q-item-section> <q-item-section>
@ -118,15 +119,11 @@ export default {
return _.get(this.deviceModelImageSmallMap, `${deviceModelId}.url`, null) return _.get(this.deviceModelImageSmallMap, `${deviceModelId}.url`, null)
}, },
options () { options () {
const options = [] return this.profiles.map((profile) => ({
this.profiles.forEach((profile) => { label: profile.name,
options.push({ value: profile.id,
label: profile.name, model: profile.device_id
value: profile.id, }))
model: profile.device_id
})
})
return options
} }
}, },
watch: { watch: {

@ -154,8 +154,8 @@ export default {
'getCallQueueRemovalToastMessage' 'getCallQueueRemovalToastMessage'
]), ]),
...mapState('pbx', [ ...mapState('pbx', [
'subcriberListState', 'subscriberListState',
'subcriberListError' 'subscriberListError'
]) ])
}, },
watch: { watch: {
@ -187,9 +187,9 @@ export default {
showGlobalError(this.callQueueListError) showGlobalError(this.callQueueListError)
} }
}, },
subcriberListState (state) { subscriberListState (state) {
if (state === RequestState.failed) { if (state === RequestState.failed) {
showGlobalError(this.subcriberListError) showGlobalError(this.subscriberListError)
} }
} }
}, },

@ -175,10 +175,11 @@
v-if="!deviceSelected" v-if="!deviceSelected"
/> />
<csc-pbx-device-config <csc-pbx-device-config
v-if="deviceSelected && hasDeviceModelImage" v-else
:id="deviceSelected?.id"
:device="deviceSelected" :device="deviceSelected"
:model="deviceModelMap[deviceProfileMap[deviceSelected.profile_id].device_id]" :model="deviceModel"
:model-image="deviceModelImageMap[deviceProfileMap[deviceSelected.profile_id].device_id]" :model-image="deviceModelImage"
:loading="isSubscribersRequesting" :loading="isSubscribersRequesting"
:subscribers="subscriberList" :subscribers="subscriberList"
:subscriber-map="subscriberMap" :subscriber-map="subscriberMap"
@ -244,22 +245,23 @@ export default {
'devicePreferencesUpdateState', 'devicePreferencesUpdateState',
'devicePreferencesSelected', 'devicePreferencesSelected',
'devicePreferencesListState', 'devicePreferencesListState',
'devicePreferencesError' 'devicePreferencesError',
'deviceMapById'
]), ]),
...mapState('pbx', [ ...mapState('pbx', [
'deviceProfileList', 'deviceProfileList',
'deviceProfileMap', 'deviceProfileMap',
'deviceProfileListState',
'deviceModelImageMap', 'deviceModelImageMap',
'deviceModelMap', 'deviceModelMap',
'subscriberList', 'subscriberList',
'subscriberMap', 'subscriberMap',
'subcriberListState', 'subscriberListState',
'subcriberListError' 'subscriberListError'
]), ]),
...mapGetters('pbx', [ ...mapGetters('pbx', [
'getSubscriberOptions', 'getSubscriberOptions',
'isSubscribersRequesting', 'isSubscribersRequesting'
'isDeviceInModelMap'
]), ]),
...mapGetters('pbxDevices', [ ...mapGetters('pbxDevices', [
'getDeviceUpdateToastMessage', 'getDeviceUpdateToastMessage',
@ -269,6 +271,55 @@ export default {
'isDeviceInMapBy', 'isDeviceInMapBy',
'isDeviceInPreferencesMap' 'isDeviceInPreferencesMap'
]), ]),
deviceModel () {
if (!this.deviceSelected?.profile_id) {
return {}
}
const profileId = this.deviceSelected.profile_id
const deviceProfile = this.deviceProfileMap[profileId]
if (!deviceProfile) {
return {}
}
if (!deviceProfile.device_id) {
return {}
}
const deviceId = deviceProfile.device_id
const deviceModel = this.deviceModelMap[deviceId]
if (!deviceModel) {
return {}
}
return deviceModel
},
deviceModelImage () {
if (!this.deviceSelected?.profile_id) {
return null
}
const profileId = this.deviceSelected.profile_id
const deviceProfile = this.deviceProfileMap[profileId]
if (!deviceProfile) {
return null
}
if (!deviceProfile.device_id) {
return null
}
const deviceId = deviceProfile.device_id
const deviceModelImage = this.deviceModelImageMap[deviceId]
if (!deviceModelImage) {
return null
}
return deviceModelImage
},
tabs () { tabs () {
return [ return [
{ {
@ -279,7 +330,7 @@ export default {
] ]
}, },
isLoading () { isLoading () {
return this.isDeviceLoading(this.deviceSelected?.id) return this.isDeviceLoading(this.id)
}, },
isLoadingPreferences () { isLoadingPreferences () {
return this.isDevicePreferencesLoading(this.devicePreferencesSelected?.id) return this.isDevicePreferencesLoading(this.devicePreferencesSelected?.id)
@ -319,9 +370,11 @@ export default {
} }
}, },
watch: { watch: {
async $route (to) { $route: {
this.id = to.params.id async handler (to) {
await this.getData(this.id) this.id = to.params.id
await this.getData(this.id)
}
}, },
deviceSelected () { deviceSelected () {
this.changes = this.getDeviceData() this.changes = this.getDeviceData()
@ -345,15 +398,19 @@ export default {
showGlobalError(this.devicePreferencesError) showGlobalError(this.devicePreferencesError)
} }
}, },
subcriberListState (state) { subscriberListState (state) {
if (state === RequestState.failed) { if (state === RequestState.failed) {
showGlobalError(this.subcriberListError) showGlobalError(this.subscriberListError)
} }
} }
}, },
async created () { async created () {
const deviceId = this.deviceSelected?.id || this.id if (this.deviceProfileList.length === 0) {
await this.getData(deviceId) await this.loadProfiles()
await this.loadProfileThumbnails()
}
await this.getData(this.id)
}, },
methods: { methods: {
...mapMutations('pbxDevices', [ ...mapMutations('pbxDevices', [
@ -375,7 +432,9 @@ export default {
]), ]),
...mapActions('pbx', [ ...mapActions('pbx', [
'loadSubscribers', 'loadSubscribers',
'loadDeviceModel' 'loadDeviceModel',
'loadProfiles',
'loadProfileThumbnails'
]), ]),
async getData (deviceId) { async getData (deviceId) {
@ -383,10 +442,13 @@ export default {
await this.loadDevice(deviceId) await this.loadDevice(deviceId)
} }
if (!this.isDeviceInModelMap(deviceId)) { const deviceProfileId = this.deviceMapById[deviceId].profile_id
const deviceProfile = this.deviceProfileMap[deviceProfileId]
if (deviceProfile.device_id) {
await this.loadDeviceModel({ await this.loadDeviceModel({
type: 'all', type: 'all',
deviceId deviceId: deviceProfile.device_id
}) })
} }
@ -461,6 +523,14 @@ export default {
this.setDeviceProfile({ this.setDeviceProfile({
deviceId: this.deviceSelected?.id, deviceId: this.deviceSelected?.id,
profileId: this.changes.profile_id profileId: this.changes.profile_id
}).then(() => {
const newProfile = this.deviceProfileMap[this.changes.profile_id]
if (newProfile && newProfile.device_id) {
this.loadDeviceModel({
type: 'all',
deviceId: newProfile.device_id
})
}
}) })
} }
if (this.hasAdminNameChanged) { if (this.hasAdminNameChanged) {

@ -3,9 +3,7 @@
id="csc-page-pbx-devices" id="csc-page-pbx-devices"
class="q-pa-lg" class="q-pa-lg"
> >
<csc-list-actions <csc-list-actions class="row justify-center q-mb-xs">
class="row justify-center q-mb-xs"
>
<template <template
v-if="isDeviceAddFormDisabled" v-if="isDeviceAddFormDisabled"
#slot1 #slot1
@ -18,9 +16,7 @@
@click="enableAddForm" @click="enableAddForm"
/> />
</template> </template>
<template <template #slot2>
#slot2
>
<csc-list-action-button <csc-list-action-button
v-if="!filtersEnabled" v-if="!filtersEnabled"
icon="filter_alt" icon="filter_alt"
@ -53,7 +49,7 @@
:model-image-map="deviceModelImageMap" :model-image-map="deviceModelImageMap"
@cancel="disableDeviceAddForm" @cancel="disableDeviceAddForm"
@submit="createDevice" @submit="createDevice"
@model-select-opened="loadDeviceModels('front_thumb')" @model-select-opened="loadProfileThumbnails()"
/> />
</div> </div>
</q-slide-transition> </q-slide-transition>
@ -63,7 +59,7 @@
:loading="isDeviceListRequesting" :loading="isDeviceListRequesting"
class="q-pb-md" class="q-pb-md"
@filter="applyFilter" @filter="applyFilter"
@model-select-opened="loadDeviceModels('front_thumb')" @model-select-opened="loadProfileThumbnails()"
/> />
</q-slide-transition> </q-slide-transition>
<div <div
@ -76,11 +72,9 @@
@update:model-value="loadDeviceListFiltered" @update:model-value="loadDeviceListFiltered"
/> />
</div> </div>
<csc-list-spinner <csc-list-spinner v-if="showSpinner" />
v-if="isDeviceListRequesting && !(isDeviceCreating || isDeviceRemoving || isDeviceUpdating)"
/>
<q-list <q-list
v-if="!isDeviceListEmpty && deviceListVisibility === 'visible'" v-if="!showSpinner && !isDeviceListEmpty && deviceListVisibility === 'visible'"
class="row justify-start items-start" class="row justify-start items-start"
> >
<csc-fade <csc-fade
@ -89,15 +83,15 @@
> >
<csc-pbx-device <csc-pbx-device
:key="device.id" :key="device.id"
:loading="isDeviceLoading(device.id) || isDeviceListRequesting" :loading="isItemLoading(device.id)"
:device="device" :device="device"
:class="'col-xs-12 col-md-6 col-lg-4 csc-item-' + ((index % 2 === 0)?'odd':'even')" :class="'col-xs-12 col-md-6 col-lg-4 csc-item-' + ((index % 2 === 0)?'odd':'even')"
:profile="deviceProfileMap[device.profile_id]" :profile="getDeviceProfile(device.profile_id)"
:model="deviceModelMap[deviceProfileMap[device.profile_id].device_id]" :model="getDeviceModel(device.profile_id)"
:model-image="deviceModelImageMap[deviceProfileMap[device.profile_id].device_id]" :model-image="getDeviceModelImage(device.profile_id)"
@load-model="loadDeviceModel({ @load-model="loadDeviceModel({
type: 'all', type: 'all',
deviceId: deviceProfileMap[device.profile_id].device_id deviceId: device.profile_id ? getDeviceProfile(device.profile_id).device_id : null
})" })"
@remove="openDeviceRemovalDialog(device.id)" @remove="openDeviceRemovalDialog(device.id)"
/> />
@ -169,17 +163,12 @@ export default {
'deviceModelList', 'deviceModelList',
'deviceModelMap', 'deviceModelMap',
'deviceModelImageMap', 'deviceModelImageMap',
'subscriberList',
'subscriberMap',
'deviceModelListState', 'deviceModelListState',
'isDeviceModelListStateRequesting',
'deviceModelError', 'deviceModelError',
'deviceProfileListState', 'deviceProfileListState',
'deviceProfileListError' 'deviceProfileListError'
]), ]),
...mapGetters('pbx', [
'getSubscriberOptions',
'isSubscribersRequesting'
]),
...mapState('pbxDevices', [ ...mapState('pbxDevices', [
'deviceRemoving', 'deviceRemoving',
'deviceList', 'deviceList',
@ -189,12 +178,12 @@ export default {
'deviceCreationState', 'deviceCreationState',
'deviceRemovalState', 'deviceRemovalState',
'deviceListState', 'deviceListState',
'deviceListError' 'deviceListError',
'deviceCreationError'
]), ]),
...mapGetters('pbxDevices', [ ...mapGetters('pbxDevices', [
'isDeviceListEmpty', 'isDeviceListEmpty',
'isDeviceListRequesting', 'isDeviceListRequesting',
'isDeviceExpanded',
'isDeviceListPaginationActive', 'isDeviceListPaginationActive',
'isDeviceAddFormDisabled', 'isDeviceAddFormDisabled',
'isDeviceCreating', 'isDeviceCreating',
@ -208,6 +197,75 @@ export default {
]), ]),
hasFilters () { hasFilters () {
return Object.keys(this.filters).length > 0 return Object.keys(this.filters).length > 0
},
getDeviceIdFromProfile () {
return (profileId) => {
const profile = this.getDeviceProfile(profileId)
return profile && profile.device_id ? profile.device_id : null
}
},
getDeviceProfile () {
return (profileId) => {
if (!profileId) {
return {}
}
return this.deviceProfileMap[profileId] || {}
}
},
getDeviceModel () {
return (profileId) => {
if (!profileId) {
return {}
}
const deviceProfile = this.deviceProfileMap[profileId]
if (!deviceProfile) {
return {}
}
if (!deviceProfile.device_id) {
return {}
}
const deviceModel = this.deviceModelMap[deviceProfile.device_id]
if (!deviceModel) {
return {}
}
return deviceModel
}
},
getDeviceModelImage () {
return (profileId) => {
if (!profileId) {
return null
}
const deviceProfile = this.deviceProfileMap[profileId]
if (!deviceProfile) {
return null
}
if (!deviceProfile.device_id) {
return null
}
const deviceModelImage = this.deviceModelImageMap[deviceProfile.device_id]
if (!deviceModelImage) {
return null
}
return deviceModelImage
}
},
isItemLoading () {
return (deviceId) => this.isDeviceLoading(deviceId) ||
this.isDeviceListRequesting ||
this.isDeviceModelListStateRequesting
},
showSpinner () {
const deviceListDataIsNotReady = this.isDeviceListRequesting && !(this.isDeviceCreating || this.isDeviceRemoving || this.isDeviceUpdating)
return this.deviceProfileListState === RequestState.requesting || deviceListDataIsNotReady
} }
}, },
watch: { watch: {
@ -243,6 +301,9 @@ export default {
} }
} }
}, },
async created () {
await this.loadProfiles()
},
mounted () { mounted () {
this.$scrollTo(this.$parent.$el) this.$scrollTo(this.$parent.$el)
this.loadDeviceListFiltered() this.loadDeviceListFiltered()
@ -251,11 +312,10 @@ export default {
methods: { methods: {
...mapActions('pbx', [ ...mapActions('pbx', [
'loadDeviceModel', 'loadDeviceModel',
'loadDeviceModels' 'loadProfileThumbnails',
'loadProfiles'
]), ]),
...mapMutations('pbxDevices', [ ...mapMutations('pbxDevices', [
'expandDevice',
'collapseDevice',
'enableDeviceAddForm', 'enableDeviceAddForm',
'disableDeviceAddForm', 'disableDeviceAddForm',
'deviceRemovalRequesting', 'deviceRemovalRequesting',
@ -265,11 +325,7 @@ export default {
'loadDeviceList', 'loadDeviceList',
'loadDevicePreferencesList', 'loadDevicePreferencesList',
'createDevice', 'createDevice',
'removeDevice', 'removeDevice'
'setDeviceStationName',
'setDeviceIdentifier',
'setDeviceProfile',
'setDeviceKeys'
]), ]),
loadDeviceListFiltered (page) { loadDeviceListFiltered (page) {
this.loadDeviceList({ this.loadDeviceList({

@ -142,8 +142,8 @@ export default {
...mapState('pbx', [ ...mapState('pbx', [
'numberListState', 'numberListState',
'numberListError', 'numberListError',
'subcriberListState', 'subscriberListState',
'subcriberListError' 'subscriberListError'
]), ]),
...mapGetters('pbxMsConfigs', [ ...mapGetters('pbxMsConfigs', [
@ -193,9 +193,9 @@ export default {
showGlobalError(this.numberListError) showGlobalError(this.numberListError)
} }
}, },
subcriberListState (state) { subscriberListState (state) {
if (state === RequestState.failed) { if (state === RequestState.failed) {
showGlobalError(this.subcriberListError) showGlobalError(this.subscriberListError)
} }
} }
}, },

@ -22,13 +22,12 @@ export default {
deviceCreationState: CreationState.initiated, deviceCreationState: CreationState.initiated,
deviceListCurrentPage: 1, deviceListCurrentPage: 1,
deviceList: [], deviceList: [],
deviceListError: null,
deviceListLastPage: null, deviceListLastPage: null,
deviceListState: RequestState.initiated, deviceListState: RequestState.initiated,
deviceListVisibility: 'visible', deviceListVisibility: 'visible',
deviceMapById: {}, deviceMapById: {},
devicePreferencesList: [], devicePreferencesList: [],
deviceListError: null,
deviceMap: {},
devicePreferencesListState: RequestState.initiated, devicePreferencesListState: RequestState.initiated,
devicePreferencesMap: {}, devicePreferencesMap: {},
devicePreferencesRemovalState: RequestState.initiated, devicePreferencesRemovalState: RequestState.initiated,
@ -303,8 +302,6 @@ export default {
context.commit('deviceListRequesting', { clearList }) context.commit('deviceListRequesting', { clearList })
try { try {
// Ensure profiles are loaded before fetching devices
await context.dispatch('pbx/loadProfiles', null, { root: true })
const devices = await getDeviceList({ page, filters }) const devices = await getDeviceList({ page, filters })
context.commit('deviceListSucceeded', { devices, page }) context.commit('deviceListSucceeded', { devices, page })
} catch (err) { } catch (err) {
@ -315,7 +312,6 @@ export default {
async loadDevice (context, deviceId) { async loadDevice (context, deviceId) {
context.commit('deviceListRequesting', { clearList: false }) context.commit('deviceListRequesting', { clearList: false })
try { try {
// Ensure profiles are loaded before fetching devices
await context.dispatch('pbx/loadProfileById', deviceId, { root: true }) await context.dispatch('pbx/loadProfileById', deviceId, { root: true })
const device = await getDevice(deviceId) const device = await getDevice(deviceId)
context.commit('deviceSucceeded', device) context.commit('deviceSucceeded', device)

@ -10,6 +10,7 @@ import {
import { getSubscribers } from 'src/api/subscriber' import { getSubscribers } from 'src/api/subscriber'
import { getNumbers } from 'src/api/user' import { getNumbers } from 'src/api/user'
import numberFilter from 'src/filters/number' import numberFilter from 'src/filters/number'
import { showGlobalError } from 'src/helpers/ui'
import { RequestState } from 'src/store/common' import { RequestState } from 'src/store/common'
export default { export default {
@ -26,7 +27,8 @@ export default {
seatMapById: {}, seatMapById: {},
soundSetList: [], soundSetList: [],
soundSetMapByName: {}, soundSetMapByName: {},
deviceProfilesListState: RequestState.initiated, deviceProfileListState: RequestState.initiated,
deviceProfileListError: null,
deviceProfileList: [], deviceProfileList: [],
deviceProfileMap: {}, deviceProfileMap: {},
deviceModelList: [], deviceModelList: [],
@ -36,11 +38,9 @@ export default {
deviceModelImageSmallMap: {}, deviceModelImageSmallMap: {},
subscriberList: [], subscriberList: [],
subscriberListState: RequestState.initiated, subscriberListState: RequestState.initiated,
subcriberListError: null, subscriberListError: null,
subscriberMap: {}, subscriberMap: {},
ncosMapByName: {}, ncosMapByName: {}
deviceProfileListState: RequestState.initiated,
deviceProfileListError: null
}, },
getters: { getters: {
pilot (state) { pilot (state) {
@ -160,6 +160,9 @@ export default {
return state.deviceModelMap[deviceId] !== undefined return state.deviceModelMap[deviceId] !== undefined
} }
}, },
isDeviceModelListStateRequesting (state) {
return state.deviceModelListState === RequestState.requesting
},
isSubscribersRequesting (state) { isSubscribersRequesting (state) {
return state.subscriberListState === RequestState.requesting return state.subscriberListState === RequestState.requesting
}, },
@ -234,30 +237,39 @@ export default {
state.soundSetMapByName[soundSet.name] = soundSet state.soundSetMapByName[soundSet.name] = soundSet
}) })
}, },
deviceProfilesListStateRequesting (state) { deviceProfileListStateRequesting (state) {
state.deviceProfilesListState = RequestState.requesting state.deviceProfileListState = RequestState.requesting
}, },
deviceProfilesListSucceeded (state, deviceProfileList) { deviceProfileListSucceeded (state, deviceProfileList) {
state.deviceProfilesListState = RequestState.succeeded const newList = _.get(deviceProfileList, 'items', [])
state.deviceProfileList = _.get(deviceProfileList, 'items', [])
// First remove existing items that we're about to replace with newer versions
// and keep only items whoseIds are not in the updated list
const existingIds = newList.map((item) => item.id)
const filteredExistingList = state.deviceProfileList.filter(
(existingItem) => !existingIds.includes(existingItem.id)
)
state.deviceProfileList = [...filteredExistingList, ...newList]
state.deviceProfileListState = RequestState.succeeded
state.deviceProfileMap = {} state.deviceProfileMap = {}
state.deviceProfileList.forEach((deviceProfile) => { state.deviceProfileList.forEach((deviceProfile) => {
state.deviceProfileMap[deviceProfile.id] = deviceProfile state.deviceProfileMap[deviceProfile.id] = deviceProfile
}) })
}, },
deviceProfilesListFailed (state) { deviceProfileListFailed (state) {
state.deviceProfilesListState = RequestState.failed state.deviceProfileListState = RequestState.failed
}, },
deviceProfileRequesting (state) { deviceProfileRequesting (state) {
state.deviceProfilesListState = RequestState.requesting state.deviceProfileListState = RequestState.requesting
}, },
deviceProfileSucceeded (state, deviceProfile) { deviceProfileSucceeded (state, deviceProfile) {
state.deviceProfilesListState = RequestState.succeeded state.deviceProfileListState = RequestState.succeeded
state.deviceProfileList = [...state.deviceProfileList, deviceProfile] state.deviceProfileList = [...state.deviceProfileList, deviceProfile]
state.deviceProfileMap[deviceProfile.id] = deviceProfile state.deviceProfileMap[deviceProfile.id] = deviceProfile
}, },
deviceProfileFailed (state) { deviceProfileFailed (state) {
state.deviceProfilesListState = RequestState.failed state.deviceProfileListState = RequestState.failed
}, },
deviceModelSucceeded (state, deviceModel) { deviceModelSucceeded (state, deviceModel) {
state.deviceModelListState = RequestState.succeeded state.deviceModelListState = RequestState.succeeded
@ -285,7 +297,7 @@ export default {
state.deviceModelError = options.error state.deviceModelError = options.error
}, },
subscribersRequesting (state) { subscribersRequesting (state) {
state.subcriberListState = RequestState.requesting state.subscriberListState = RequestState.requesting
state.subscriberList = [] state.subscriberList = []
}, },
subscribersSucceeded (state, subscribers) { subscribersSucceeded (state, subscribers) {
@ -296,20 +308,18 @@ export default {
}) })
}, },
subscribersFailed (state, err) { subscribersFailed (state, err) {
state.subcriberListState = RequestState.failed state.subscriberListState = RequestState.failed
state.subcriberListError = err state.subscriberListError = err
} }
}, },
actions: { actions: {
async loadProfiles (context) { async loadProfiles (context) {
if (context.state.deviceProfileList.length === 0) { context.commit('deviceProfileListStateRequesting')
context.commit('deviceProfilesListStateRequesting') try {
try { const profiles = await getAllProfiles()
const profiles = await getAllProfiles() context.commit('deviceProfileListSucceeded', profiles)
context.commit('deviceProfilesListSucceeded', profiles) } catch (err) {
} catch (err) { context.commit('deviceProfileListFailed', err.message)
context.commit('deviceProfilesListFailed', err.message)
}
} }
}, },
async loadProfileById (context, deviceId) { async loadProfileById (context, deviceId) {
@ -321,6 +331,47 @@ export default {
context.commit('deviceProfileFailed') context.commit('deviceProfileFailed')
} }
}, },
async loadProfileThumbnails (context) {
const requests = []
context.state.deviceProfileList.forEach((deviceProfile) => {
const isFrontThumbnailCached = context.state.deviceModelImageSmallMap[deviceProfile.device_id] !== undefined
if (!isFrontThumbnailCached) {
requests.push(
getModelFrontThumbnailImage(deviceProfile.device_id)
.then((thumbnail) => ({
deviceId: deviceProfile.device_id,
thumbnail
}))
.catch((error) => ({
deviceId: deviceProfile.device_id,
error
}))
)
}
})
if (requests.length > 0) {
try {
const results = await Promise.all(requests)
results.forEach((result) => {
if (result.thumbnail) {
context.commit('deviceModelSucceeded', {
modelImageThumbnail: result.thumbnail
})
} else if (result.error) {
// Silent warning as it's not a critical error
// and we can still use the device profile without the thumbnail
// eslint-disable-next-line no-console
console.warn(`Failed to load thumbnail for device ${result.deviceId}:`, result.error)
}
})
} catch (error) {
showGlobalError('Failed to load profile thumbnails:', error)
}
}
},
async loadDeviceModel (context, payload) { async loadDeviceModel (context, payload) {
try { try {
const isFrontCached = context.state.deviceModelImageMap[payload.deviceId] !== undefined const isFrontCached = context.state.deviceModelImageMap[payload.deviceId] !== undefined
@ -373,6 +424,10 @@ export default {
} }
context.commit('deviceModelSucceeded', deviceModel) context.commit('deviceModelSucceeded', deviceModel)
} catch (err) { } catch (err) {
// Note: the way it is implemented at the moment
// if any of the promises fails, the whole action fails
// and only the first error is reported. This needs refactoring
// to handle each request separately and report errors accordingly.
context.commit('deviceModelFailed', { context.commit('deviceModelFailed', {
deviceModelId: payload.deviceId, deviceModelId: payload.deviceId,
error: err.message error: err.message

@ -3,10 +3,7 @@ import { i18n } from 'boot/i18n'
import _ from 'lodash' import _ from 'lodash'
import QRCode from 'qrcode' import QRCode from 'qrcode'
import { date } from 'quasar' import { date } from 'quasar'
import { import { apiDownloadFile, httpApi } from 'src/api/common'
apiDownloadFile,
httpApi
} from 'src/api/common'
import { callInitialize } from 'src/api/ngcp-call' import { callInitialize } from 'src/api/ngcp-call'
import { import {
changePassword, changePassword,

Loading…
Cancel
Save