TT#100551 CSC: As Customer, I want to search PBXDevices by Username using a selection with autocompletion

AC:
Can input PBXSeats, PBXGroups or PBXPilots name in the search input
Can see a list of possible PBXSeat, PBXGroup or PBXPilot according to the search input
Can select PBXSeat, PBXGroup or PBXPilot from the list to apply the search

Change-Id: Id97cf90b0a5fb62bc2049f73daf98d811fb4583e
pull/4/head
Sergii Leonenko 5 years ago
parent 7c0c1f412a
commit 63347a0b7d

@ -0,0 +1,64 @@
<template>
<q-select
:label="selectedKeyLabel"
v-bind="$attrs"
v-on="$listeners"
>
<template
v-if="showSelectedItemIcon"
v-slot:prepend
>
<q-icon
:name="selectedKeyIcon"
/>
</template>
<template v-slot:option="scope">
<q-item
v-bind="scope.itemProps"
v-on="scope.itemEvents"
>
<q-item-section
side
>
<q-icon
:name="scope.opt.icon"
/>
</q-item-section>
<q-item-section>
<q-item-label>
{{ scope.opt.label }}
</q-item-label>
</q-item-section>
</q-item>
</template>
</q-select>
</template>
<script>
export default {
name: 'CscPbxAttendantSelection',
props: {
showSelectedItemIcon: {
type: Boolean,
default: true
}
},
computed: {
selectedKeyLabel () {
const selectedValue = this.$attrs.value || { type: null }
let label = this.$t('pbxConfig.keyBothLabel')
if (selectedValue.type !== null) {
label = ({
pilot: this.$t('pbxConfig.keyPilotLabel'),
seat: this.$t('pbxConfig.keySeatLabel'),
group: this.$t('pbxConfig.keyGroupLabel')
})[selectedValue.type]
}
return label
},
selectedKeyIcon () {
return this.$attrs.value?.icon
}
}
}
</script>

@ -51,44 +51,13 @@
</div> </div>
</div> </div>
</div> </div>
<q-select <csc-pbx-attendant-selection
ref="selectSubscriber"
emit-value
map-options
:label="selectedKeyLabel"
:value="selectedKeySubscriber" :value="selectedKeySubscriber"
:options="subscriberOptions" :options="subscriberOptions"
@input="keySubscriberChanged" @input="keySubscriberChanged"
> />
<template
v-slot:prepend
>
<q-icon
:name="selectedKeyIcon"
/>
</template>
<template v-slot:option="scope">
<q-item
v-bind="scope.itemProps"
v-on="scope.itemEvents"
>
<q-item-section
side
>
<q-icon
:name="scope.opt.icon"
/>
</q-item-section>
<q-item-section>
<q-item-label>
{{ scope.opt.label }}
</q-item-label>
</q-item-section>
</q-item>
</template>
</q-select>
<q-select <q-select
v-show="selectedKeySubscriber !== null" v-show="selectedKeySubscriber !== null && selectedKeySubscriber.value !== null"
ref="selectType" ref="selectType"
v-model="selectedKeyType" v-model="selectedKeyType"
emit-value emit-value
@ -137,9 +106,13 @@ import {
import { import {
BoundingBox2D BoundingBox2D
} from 'src/helpers/graphics' } from 'src/helpers/graphics'
import CscPbxAttendantSelection from './CscPbxAttendantSelection'
export default { export default {
name: 'CscPbxDeviceConfig', name: 'CscPbxDeviceConfig',
components: {
CscPbxAttendantSelection
},
props: { props: {
device: { device: {
type: Object, type: Object,
@ -199,26 +172,13 @@ export default {
} }
return '' return ''
}, },
selectedKeyLabel () {
if (this.selectedLine !== null) {
const subscriber = this.subscriberMap[this.selectedLine.subscriber_id]
if (subscriber !== null && subscriber.is_pbx_pilot === true) {
return this.$t('pbxConfig.keyPilotLabel')
} else if (subscriber !== null && subscriber.is_pbx_group === true) {
return this.$t('pbxConfig.keyGroupLabel')
} else if (subscriber !== null) {
return this.$t('pbxConfig.keySeatLabel')
} else {
return this.$t('pbxConfig.keyBothLabel')
}
}
return this.$t('pbxConfig.keyBothLabel')
},
selectedKeySubscriber () { selectedKeySubscriber () {
const unassignedItem = this.subscriberOptions[0]
if (this.selectedLine !== null) { if (this.selectedLine !== null) {
return this.selectedLine.subscriber_id const selectedOption = this.subscriberOptions.find(opt => opt.value === this.selectedLine.subscriber_id)
return selectedOption || unassignedItem
} }
return null return unassignedItem
}, },
selectedKeyType: { selectedKeyType: {
get () { get () {
@ -432,7 +392,7 @@ export default {
loadGroupsAndSeats () { loadGroupsAndSeats () {
this.$emit('loadGroupsAndSeats') this.$emit('loadGroupsAndSeats')
}, },
keySubscriberChanged (subscriberId) { keySubscriberChanged ({ value: subscriberId }) {
const newLines = [] const newLines = []
const lines = _.clone(this.lines) const lines = _.clone(this.lines)
const line = this.getLineByKey(this.selectedKey) const line = this.getLineByKey(this.selectedKey)

@ -18,7 +18,7 @@
class="col-xs-12 col-md-2" class="col-xs-12 col-md-2"
> >
<q-input <q-input
v-if="filterType !== 'profile_id'" v-if="!filterTypeModel || filterTypeModel.control === 'input'"
v-model="typedFilter" v-model="typedFilter"
type="text" type="text"
dense dense
@ -49,6 +49,17 @@
@opened="$emit('model-select-opened')" @opened="$emit('model-select-opened')"
@input="triggerFilter" @input="triggerFilter"
/> />
<csc-pbx-attendant-selection
v-if="filterType === 'display_name'"
use-input
dense
:show-selected-item-icon="false"
:value="typedFilter"
:options="subscribersOptionsFiltered"
:disable="loading"
@filter="filterSubscriberOptions"
@input="triggerFilter"
/>
</div> </div>
</div> </div>
<div <div
@ -77,12 +88,14 @@
<script> <script>
import _ from 'lodash' import _ from 'lodash'
import CscPbxModelSelect from '../PbxConfiguration/CscPbxModelSelect' import CscPbxModelSelect from '../PbxConfiguration/CscPbxModelSelect'
import { mapState } from 'vuex' import CscPbxAttendantSelection from '../PbxConfiguration/CscPbxAttendantSelection'
import { mapActions, mapState } from 'vuex'
export default { export default {
name: 'CscPbxDeviceFilters', name: 'CscPbxDeviceFilters',
components: { components: {
CscPbxModelSelect CscPbxModelSelect,
CscPbxAttendantSelection
}, },
props: { props: {
loading: { loading: {
@ -94,14 +107,41 @@ export default {
return { return {
filterTypeModel: null, filterTypeModel: null,
typedFilter: null, typedFilter: null,
filters: [] filters: [],
subscribersFilter: ''
} }
}, },
computed: { computed: {
...mapState('pbx', [ ...mapState('pbx', [
'deviceProfileMap', 'deviceProfileMap',
'deviceProfileList' 'deviceProfileList',
'subscriberList'
]), ]),
subscribersOptions () {
const options = []
this.subscriberList.forEach((subscriber) => {
let icon = 'person'
let subscriberTypeTitle = this.$t('pbxConfig.keySeatLabel')
if (subscriber.is_pbx_group) {
icon = 'group'
subscriberTypeTitle = this.$t('pbxConfig.keyGroupLabel')
} else if (subscriber.is_pbx_pilot) {
icon = 'person_outline'
subscriberTypeTitle = this.$t('pbxConfig.keyPilotLabel')
}
options.push({
label: subscriber.display_name || subscriber.webusername,
icon: icon,
value: subscriber.display_name,
disable: !subscriber.display_name,
subscriberTypeTitle
})
})
return options
},
subscribersOptionsFiltered () {
return this.subscribersOptions.filter(option => option.label.toLowerCase().indexOf(this.subscribersFilter) > -1)
},
filterType () { filterType () {
return this.filterTypeModel && this.filterTypeModel.value return this.filterTypeModel && this.filterTypeModel.value
}, },
@ -109,35 +149,40 @@ export default {
return [ return [
{ {
label: this.$t('pbxConfig.deviceStationName'), label: this.$t('pbxConfig.deviceStationName'),
value: 'station_name' value: 'station_name',
control: 'input'
}, },
{ {
label: this.$t('pbxConfig.deviceIdentifier'), label: this.$t('pbxConfig.deviceIdentifier'),
value: 'identifier' value: 'identifier',
control: 'input'
}, },
{ {
label: this.$t('pbxConfig.deviceModel'), label: this.$t('pbxConfig.deviceModel'),
value: 'profile_id' value: 'profile_id',
control: 'select'
}, },
{ {
label: this.$t('pbxConfig.extension'), label: this.$t('pbxConfig.extension'),
value: 'pbx_extension' value: 'pbx_extension',
control: 'input'
}, },
{ {
label: this.$t('pbxConfig.queueExtensionName'), label: this.$t('pbxConfig.queueExtensionName'),
value: 'display_name' value: 'display_name',
control: 'select'
} }
] ]
}, },
filtersList () { filtersList () {
return this.filters.map((filterItem) => { return this.filters.map((filterItem) => {
let filterDisplayValue = filterItem.value let filterDisplayValue = filterItem.value
if (filterItem.name === 'profile_id') { if (filterItem.id === 'profile_id') {
filterDisplayValue = this.deviceProfileMap[filterItem.value].name filterDisplayValue = this.deviceProfileMap[filterItem.value].name
} }
return { return {
id: filterItem.name, id: filterItem.id,
filterInfo: this.filterTypeOptions.find(option => option.value === filterItem.name).label + ': ' + filterDisplayValue filterInfo: filterItem.title + ': ' + filterDisplayValue
} }
}) })
} }
@ -147,12 +192,31 @@ export default {
this.typedFilter = null this.typedFilter = null
} }
}, },
mounted () {
this.loadSubscribers()
},
methods: { methods: {
...mapActions('pbx', [
'loadSubscribers'
]),
filterSubscriberOptions (val, update, abort) {
update(() => {
this.subscribersFilter = val.toLowerCase()
})
},
triggerFilter (data) { triggerFilter (data) {
this.addFilter(this.filterTypeModel?.value, this.typedFilter) const filterId = this.filterTypeModel?.value
let filterTitle = this.filterTypeOptions.find(option => option.value === filterId).label
let filterValue = this.typedFilter
if (this.filterType === 'display_name') {
filterTitle = data.subscriberTypeTitle
filterValue = data.value
}
this.addFilter(filterId, filterTitle, filterValue)
}, },
removeFilter (name) { removeFilter (id) {
this.filters = this.filters.filter(item => item.name !== name) this.filters = this.filters.filter(item => item.id !== id)
this.filter() this.filter()
}, },
removeFilters () { removeFilters () {
@ -161,13 +225,14 @@ export default {
this.filter() this.filter()
} }
}, },
addFilter (name, value) { addFilter (id, title, value) {
const valueTrimmed = _.trim(value) const valueTrimmed = _.trim(value)
if (valueTrimmed) { if (valueTrimmed) {
this.typedFilter = null this.typedFilter = null
this.filters = this.filters.filter(item => item.name !== name) this.filters = this.filters.filter(item => item.id !== id)
const filter = { const filter = {
name: name, id,
title,
value: valueTrimmed value: valueTrimmed
} }
this.filters.push(filter) this.filters.push(filter)
@ -177,7 +242,7 @@ export default {
filter () { filter () {
const params = {} const params = {}
this.filters.forEach(filter => { this.filters.forEach(filter => {
params[filter.name] = filter.value params[filter.id] = filter.value
}) })
// a special fix because of q-select behaviour. it stores 0 for empty selection // a special fix because of q-select behaviour. it stores 0 for empty selection

@ -120,19 +120,24 @@ export default {
options.push({ options.push({
label: i18n.t('pbxConfig.keyEmptyLabel'), label: i18n.t('pbxConfig.keyEmptyLabel'),
icon: 'clear', icon: 'clear',
value: null value: null,
type: null
}) })
state.subscriberList.forEach((subscriber) => { state.subscriberList.forEach((subscriber) => {
let icon = 'person' let icon = 'person'
let type = 'seat'
if (subscriber.is_pbx_group) { if (subscriber.is_pbx_group) {
icon = 'group' icon = 'group'
type = 'group'
} else if (subscriber.is_pbx_pilot) { } else if (subscriber.is_pbx_pilot) {
icon = 'person_outline' icon = 'person_outline'
type = 'pilot'
} }
options.push({ options.push({
label: subscriber.display_name || subscriber.webusername, label: subscriber.display_name || subscriber.webusername,
icon: icon, icon: icon,
value: subscriber.id value: subscriber.id,
type
}) })
}) })
return options return options

Loading…
Cancel
Save