TT#37655 Customer wants to filter by mac address

Change-Id: I147c4e52e35f5fc8540320badacaebc7b2eb1708
changes/69/22669/6
Tijana Maksimovic 7 years ago committed by raxelsen
parent 72ad4e4381
commit 7b6b3c0f32

@ -200,12 +200,16 @@ export function getDeviceList(options) {
let params = { let params = {
page: options.page, page: options.page,
profile_id: options.profile_id, profile_id: options.profile_id,
identifier: options.identifier,
order_by: PBX_CONFIG_ORDER_BY, order_by: PBX_CONFIG_ORDER_BY,
order_by_direction: PBX_CONFIG_ORDER_DIRECTION order_by_direction: PBX_CONFIG_ORDER_DIRECTION
}; };
if(params.profile_id === null) { if(params.profile_id === null) {
delete params['profile_id']; delete params['profile_id'];
} }
if(params.identifier === null) {
delete params['identifier'];
}
return getDevices({ return getDevices({
params: params params: params
}).then((devices)=>{ }).then((devices)=>{

@ -1,6 +1,6 @@
<template> <template>
<div class="row justify-center"> <div class="col">
<div v-if="formEnabled" class="col col-md-6 col-sm-12"> <div class="col">
<q-field> <q-field>
<q-input <q-input
v-model="data.station_name" v-model="data.station_name"
@ -40,23 +40,13 @@
>{{ $t('buttons.cancel') }}</q-btn> >{{ $t('buttons.cancel') }}</q-btn>
<q-btn <q-btn
v-if="!loading" v-if="!loading"
flat color="primary" flat
color="primary"
icon="done" icon="done"
@click="save()" @click="save()"
>{{ $t('buttons.save') }}</q-btn> >{{ $t('buttons.save') }}</q-btn>
</div> </div>
</div> </div>
<div
v-else
class="row justify-center"
>
<q-btn
color="primary"
icon="add"
flat
@click="enableForm()"
>Add device</q-btn>
</div>
<q-inner-loading <q-inner-loading
v-show="loading" v-show="loading"
:visible="loading" :visible="loading"
@ -96,8 +86,21 @@
'loading' 'loading'
], ],
components: { components: {
CscPbxModelSelect, QCard, QCardTitle, QCardMain, QCardActions, QCardSeparator, QBtn, CscPbxModelSelect,
QInnerLoading, QSpinnerMat, QField, QInput, QSelect, QIcon, QItem, QItemMain QCard,
QCardTitle,
QCardMain,
QCardActions,
QCardSeparator,
QBtn,
QInnerLoading,
QSpinnerMat,
QField,
QInput,
QSelect,
QIcon,
QItem,
QItemMain
}, },
data () { data () {
return { return {
@ -115,11 +118,11 @@
} }
}, },
enableForm(){ enableForm(){
this.reset();
this.formEnabled = true; this.formEnabled = true;
}, },
disableForm(){ disableForm(){
this.formEnabled = false; this.reset();
this.$emit('cancelForm');
}, },
cancel() { cancel() {
this.disableForm(); this.disableForm();

@ -16,7 +16,7 @@
ref="image" ref="image"
:src="imageUrl" :src="imageUrl"
:style="imageStyles" :style="imageStyles"
@load="imageLoaded"s @load="imageLoaded"
/> />
</div> </div>
<div <div

@ -2,6 +2,11 @@
<csc-page <csc-page
class="csc-list-page" class="csc-list-page"
> >
<csc-pbx-devices-toolbar
@showForm="showForm"
@toggleFilterOptions="toggleFilterOptions"
@resetAll="resetAllFilters"
/>
<q-list <q-list
no-border no-border
separator separator
@ -10,27 +15,22 @@
> >
<q-item> <q-item>
<q-item-main> <q-item-main>
<csc-pbx-device-add-form <div class="row justify-center">
ref="deviceAddForm" <csc-pbx-device-add-form
:profiles="profiles"
:modelImages="modelImages"
:loading="createDeviceRequesting"
@remove="removeDevice"
@modelSelectOpened="modelSelectOpened()"
@save="saveDevice"
/>
<div
class="row justify-center"
>
<csc-pbx-model-select
class="col col-md-6 col-sm-12" class="col col-md-6 col-sm-12"
:erasable="true" v-if="formEnabled"
ref="deviceAddForm"
:profiles="profiles" :profiles="profiles"
:modelImages="modelImages" :modelImages="modelImages"
:label="$t('pbxConfig.filterPhoneModel')" :loading="createDeviceRequesting"
@opened="modelSelectOpened()" @remove="removeDevice"
@select="filterByProfile" @modelSelectOpened="modelSelectOpened()"
@reseted="resetProfileFilter" @save="saveDevice"
@cancelForm="cancelForm"
/>
<csc-pbx-devices-filter
class="col col-md-6 col-sm-12"
v-if="filterOptionsPanelOpened"
/> />
</div> </div>
<div <div
@ -85,7 +85,9 @@
import CscPage from '../../CscPage' import CscPage from '../../CscPage'
import CscPbxDevice from './CscPbxDevice' import CscPbxDevice from './CscPbxDevice'
import CscPbxDeviceAddForm from './CscPbxDeviceAddForm' import CscPbxDeviceAddForm from './CscPbxDeviceAddForm'
import CscPbxDevicesFilter from './CscPbxDevicesFilter'
import CscPbxModelSelect from './CscPbxModelSelect' import CscPbxModelSelect from './CscPbxModelSelect'
import CscPbxDevicesToolbar from './CscPbxDevicesToolbar'
import { showToast, showGlobalError } from '../../../helpers/ui' import { showToast, showGlobalError } from '../../../helpers/ui'
import { import {
QSpinnerDots, QSpinnerDots,
@ -101,7 +103,8 @@
export default { export default {
data () { data () {
return { return {
profile: null, formEnabled: false,
filterOptionsPanelOpened: false,
platform: this.$q.platform.is platform: this.$q.platform.is
} }
}, },
@ -113,7 +116,9 @@
CscPage, CscPage,
CscPbxDevice, CscPbxDevice,
CscPbxDeviceAddForm, CscPbxDeviceAddForm,
CscPbxDevicesFilter,
CscPbxModelSelect, CscPbxModelSelect,
CscPbxDevicesToolbar,
QSpinnerDots, QSpinnerDots,
QPagination, QPagination,
QList, QList,
@ -148,24 +153,38 @@
'updatedDevice', 'updatedDevice',
'updatedDeviceSucceeded', 'updatedDeviceSucceeded',
'updatedDeviceError', 'updatedDeviceError',
'updatedDeviceProperty' 'updatedDeviceProperty',
'listProfileFilter',
'listMacAddressFilter'
]), ]),
noDeviceMessage() { noDeviceMessage() {
if (this.profile) { if (this.listProfileFilter && !this.listMacAddressFilter) {
return this.$t('pbxConfig.noModel'); return this.$t('pbxConfig.noModel');
} }
else { else if (this.listMacAddressFilter && !this.listProfileFilter) {
return this.$t('pbxConfig.noDevices'); return this.$t('pbxConfig.noMacAddress')
}
if (this.listMacAddressFilter && this.listProfileFilter) {
return this.$t('pbxConfig.noDevicesFound');
}
else if (this.devices.length === 0) {
return this.$t('pbxConfig.noDevicesCreated');
} }
} }
}, },
methods: { methods: {
filterByProfile(profile) { resetAllFilters() {
this.$store.dispatch('pbxConfig/filterByProfile', profile); this.filterOptionsPanelOpened = false;
this.$emit('resetAllFilters');
this.resetProfileFilter();
this.resetMacAddressFilter();
}, },
resetProfileFilter() { resetProfileFilter() {
this.$store.dispatch('pbxConfig/resetProfileFilter'); this.$store.dispatch('pbxConfig/resetProfileFilter');
}, },
resetMacAddressFilter() {
this.$store.dispatch('pbxConfig/resetMacAddressFilter');
},
changePage(page) { changePage(page) {
this.$store.dispatch('pbxConfig/goToPage', page); this.$store.dispatch('pbxConfig/goToPage', page);
}, },
@ -216,6 +235,21 @@
updateProfile(data) { updateProfile(data) {
this.$store.dispatch('pbxConfig/setProfile', data); this.$store.dispatch('pbxConfig/setProfile', data);
}, },
showForm() {
if(this.filterOptionsPanelOpened) {
this.toggleFilterOptions();
}
this.formEnabled = true;
},
cancelForm() {
this.formEnabled = false;
},
toggleFilterOptions() {
if(this.formEnabled) {
this.cancelForm();
}
this.filterOptionsPanelOpened = !this.filterOptionsPanelOpened;
}
}, },
watch: { watch: {
deviceRemoved(device) { deviceRemoved(device) {

@ -0,0 +1,66 @@
<template>
<div class="col">
<div class="filterOptionsPanel">
<csc-pbx-mac-input
@filter="filterByMacAddress"
@reset="resetMacAddressFilter"
/>
<csc-pbx-model-select
:erasable="true"
:profiles="profiles"
:modelImages="modelImages"
:label="$t('pbxConfig.filterPhoneModel')"
@opened="modelSelectOpened()"
@select="filterByProfile"
@reseted="resetProfileFilter"
/>
</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import CscPbxModelSelect from './CscPbxModelSelect'
import CscPbxMacInput from './CscPbxMacInput'
export default {
name: 'csc-pbx-devices-filter',
components: {
CscPbxModelSelect,
CscPbxMacInput
},
computed: {
...mapGetters('pbxConfig', [
'profiles',
'modelImages'
])
},
methods: {
filterByProfile(profile) {
this.$store.dispatch('pbxConfig/filterByProfile', profile);
},
filterByMacAddress(identifier) {
this.$store.dispatch('pbxConfig/filterByMacAddress', identifier);
},
resetProfileFilter() {
this.$store.dispatch('pbxConfig/resetProfileFilter');
},
resetMacAddressFilter() {
this.$store.dispatch('pbxConfig/resetMacAddressFilter');
},
modelSelectOpened() {
this.$store.dispatch('pbxConfig/loadProfiles');
}
}
}
</script>
<style lang="stylus" rel="stylesheet/stylus">
.filter-model-select
margin 16px 16px 8px 16px
.filter-icon
padding 10px
</style>

@ -0,0 +1,163 @@
<template>
<div>
<q-toolbar
color="primary"
inverted
class="row justify-center"
>
<div>
<q-btn
color="primary"
icon="add"
flat
@click="enableForm()"
:class="{ cscLabelMobile: isSmallLabelBreakpoint }"
>
{{ $t('pbxConfig.addDevice') }}
</q-btn>
</div>
<q-btn
v-if="isMobile"
:disabled="checkDevicesCreated"
color="primary"
icon="fa-filter"
flat
@click="toggleFilterOptions()"
:class="{ cscIconMobile: isSmallIconBreakpoint }"
>
{{ showFilterLabel }}
</q-btn>
<div
v-if="!isMobile"
@click="toggleFilterOptions()"
>
<q-btn
:disabled="checkDevicesCreated"
icon="fa-filter"
flat
:class="{ cscIconMobile: isSmallIconBreakpoint }"
>
{{ $t('pbxConfig.filterDevices') }}
</q-btn>
<q-chip
small
tag
square
color="primary"
v-if="chipMacAddressFilter"
>
{{ chipMacAddressFilter | removeTrailingWildcard }}
</q-chip>
<q-chip
small
tag
square
color="primary"
v-if="chipModelFilter"
>
{{ chipModelFilter }}
</q-chip>
</div>
<div class="resetAllBtn">
<q-btn
color="primary"
icon="highlight_off"
flat
:disabled="checkFiltersApplied"
@click="resetAllFilters"
:class="{ cscIconMobile: isSmallIconBreakpoint }"
>
{{ $t('pbxConfig.resetFilters') }}
</q-btn>
</div>
</q-toolbar>
</div>
</template>
<script>
import {
QChip,
QIcon,
QBtn,
QToolbar,
Platform,
dom
} from 'quasar-framework'
import { mapGetters } from 'vuex'
const { viewport } = dom
let { width } = viewport()
export default {
name: 'csc-pbx-devices-toolbar',
data () {
return {
formEnabled: false
}
},
components: {
QChip,
QIcon,
QBtn,
QToolbar,
Platform
},
computed: {
...mapGetters('pbxConfig', [
'devices',
'chipModelFilter',
'chipMacAddressFilter'
]),
isSmallLabelBreakpoint() {
return (width <= 390 && width > 352);
},
isSmallIconBreakpoint() {
return (width <= 500);
},
isMobile() {
return (Platform.is.mobile || width < 1270);
},
filtersApplied() {
return (this.chipModelFilter || this.chipMacAddressFilter);
},
showFilterLabel() {
return this.filtersApplied ? this.$t('pbxConfig.showFilters') : this.$t('pbxConfig.filterDevices');
},
checkFiltersApplied() {
return !(this.chipModelFilter || this.chipMacAddressFilter);
},
checkDevicesCreated() {
return (this.devices.length === 0 && !this.chipModelFilter && !this.chipMacAddressFilter);
}
},
methods: {
enableForm() {
if(this.chipModelFilter || this.chipMacAddressFilter) {
this.resetAllFilters();
}
this.$emit('showForm');
},
toggleFilterOptions() {
if(this.devices.length !== 0 || this.chipModelFilter || this.chipMacAddressFilter) {
this.$emit('toggleFilterOptions');
}
},
resetAllFilters() {
this.$emit('resetAll');
}
},
filters: {
removeTrailingWildcard: function(value) {
return value.slice(0, -1);
}
}
}
</script>
<style lang="stylus" rel="stylesheet/stylus">
.cscIconMobile
.on-left
margin-right 0
.cscLabelMobile
padding-bottom 20px
</style>

@ -0,0 +1,93 @@
<template>
<div class="col">
<q-field class="row">
<q-input
v-model="macAddress"
:float-label="$t('pbxConfig.filterMacAddress')"
:after="clearButton"
@keyup="filterByMacAddress"
/>
</q-field>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import {
QInnerLoading,
QSpinnerMat,
QField,
QInput,
debounce } from 'quasar-framework'
export default {
name: 'csc-pbx-mac-input',
data () {
return {
macAddress: ''
}
},
components: {
QInnerLoading,
QSpinnerMat,
QField,
QInput
},
created() {
if (this.listMacAddressFilter) {
this.macAddress = this.listMacAddressFilter.slice(0, -1);
}
},
computed: {
...mapGetters('pbxConfig', [
'listMacAddressFilter'
]),
clearButton() {
let self = this;
let buttons = [];
if (this.macAddress) {
buttons = [{
icon: 'clear',
error: false,
handler (event) {
event.stopPropagation();
self.reset();
}
}];
}
return buttons;
}
},
mounted() {
this.debouncedFilterByMacAddress = debounce(() => {
if(this.macAddress === '') {
this.reset();
}
else {
this.$emit('filter', this.macAddress + '*');
}
}, 500)
},
methods: {
reset() {
this.macAddress = '';
this.$emit('reset');
},
filterByMacAddress() {
this.debouncedFilterByMacAddress();
}
},
watch: {
listMacAddressFilter() {
if (this.listMacAddressFilter === null) {
this.macAddress = '';
}
}
}
}
</script>
<style lang="stylus" rel="stylesheet/stylus">
@import '../../../themes/quasar.variables.styl';
</style>

@ -8,10 +8,23 @@
:float-label="label" :float-label="label"
:after="clearButton" :after="clearButton"
/> />
<q-popover ref="popover" fit @open="opened()"> <q-popover
<q-list no-borders class="csc-pbx-model-list" highlight inset-separator> ref="popover"
<q-item v-for="(profile, index) in profiles" :key="profile.id" fit
@click="selectProfile(profile)" class="cursor-pointer"> @open="opened()"
>
<q-list
no-borders
class="csc-pbx-model-list"
highlight
inset-separator
>
<q-item
v-for="(profile, index) in profiles"
:key="profile.id"
@click="selectProfile(profile)"
class="cursor-pointer"
>
<q-item-side> <q-item-side>
<q-item-tile avatar> <q-item-tile avatar>
<img :src="frontImageUrl(profile.device_id)" /> <img :src="frontImageUrl(profile.device_id)" />
@ -24,16 +37,31 @@
</q-list> </q-list>
</q-popover> </q-popover>
</div> </div>
<div v-if="selectedProfile.device_id != null && preview" class="csc-pbx-model-image"> <div
<img :src="frontImageUrl(selectedProfile.device_id)" class="csc-pbx-model-select-preview" /> v-if="selectedProfile.device_id != null && preview"
class="csc-pbx-model-image"
>
<img
:src="frontImageUrl(selectedProfile.device_id)"
class="csc-pbx-model-select-preview"
/>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import { QInput, QPopover, QList, QItem, QItemMain, QItemTile, QItemSide } from 'quasar-framework'
import _ from 'lodash'; import _ from 'lodash';
import {
QInput,
QPopover,
QList,
QItem,
QItemMain,
QItemTile,
QItemSide } from 'quasar-framework'
import { mapGetters } from 'vuex';
export default { export default {
name: 'csc-pbx-model-select', name: 'csc-pbx-model-select',
@ -73,7 +101,13 @@
} }
}, },
components: { components: {
QInput, QPopover, QList, QItem, QItemMain, QItemTile, QItemSide QInput,
QPopover,
QList,
QItem,
QItemMain,
QItemTile,
QItemSide
}, },
data () { data () {
return { return {
@ -81,6 +115,9 @@
} }
}, },
computed: { computed: {
...mapGetters('pbxConfig', [
'listProfileFilter'
]),
clearButton() { clearButton() {
let self = this; let self = this;
let buttons = []; let buttons = [];
@ -129,12 +166,22 @@
}); });
} }
}, },
mounted(){ mounted() {
this.selectById(this.selectedId); if (this.listProfileFilter) {
this.selectById(this.listProfileFilter);
}
else {
this.selectById(this.selectedId);
}
}, },
watch: { watch: {
selectedId(id) { selectedId(id) {
this.selectById(id); this.selectById(id);
},
listProfileFilter() {
if(this.listProfileFilter === null) {
this.selectedProfile = this.getDefaults();
}
} }
} }
} }

@ -307,8 +307,10 @@
"deviceModel": "Model", "deviceModel": "Model",
"groupsTitle": "Groups", "groupsTitle": "Groups",
"seatsTitle": "Seats", "seatsTitle": "Seats",
"noDevices": "No devices created yet", "noDevicesCreated": "No devices created yet",
"noDevicesFound": "Could not find any device matching any of the filter criteria",
"noModel": "Could not find any device with model matching the filter criteria", "noModel": "Could not find any device with model matching the filter criteria",
"noMacAddress": "Could not find any device with MAC address matching the filter criteria",
"noGroups": "No groups created yet", "noGroups": "No groups created yet",
"noSeats": "No seats created yet", "noSeats": "No seats created yet",
"toasts": { "toasts": {
@ -327,6 +329,7 @@
"updatedIdentifier": "Updated identifier to {identifier}", "updatedIdentifier": "Updated identifier to {identifier}",
"createdDevice": "Created device {name} successfully" "createdDevice": "Created device {name} successfully"
}, },
"addDevice": "Add device",
"removeDevice": "Remove device", "removeDevice": "Remove device",
"removeDeviceTitle": "Remove device", "removeDeviceTitle": "Remove device",
"removeDeviceText": "You are about to remove device {device}", "removeDeviceText": "You are about to remove device {device}",
@ -338,7 +341,11 @@
"keyTypeShared": "Shared", "keyTypeShared": "Shared",
"keyTypeBLF": "Busy Lamp Field", "keyTypeBLF": "Busy Lamp Field",
"keyTypePrivate": "Private", "keyTypePrivate": "Private",
"filterPhoneModel": "Filter by phone model" "filterPhoneModel": "Filter by phone model",
"filterMacAddress": "Filter by MAC address",
"showFilters": "Show filters",
"filterDevices": "Filter devices",
"resetFilters": "Reset filters"
}, },
"callBlocking": { "callBlocking": {
"privacyEnabledToast": "Your number is hidden to the callee", "privacyEnabledToast": "Your number is hidden to the callee",

@ -261,7 +261,8 @@ export default {
context.commit('deviceListRequesting', silent); context.commit('deviceListRequesting', silent);
getDeviceList({ getDeviceList({
page: _.get(context, 'getters.listCurrentPage', 1), page: _.get(context, 'getters.listCurrentPage', 1),
profile_id: _.get(context, 'getters.listProfileFilter', null) profile_id: _.get(context, 'getters.listProfileFilter', null),
identifier: _.get(context, 'getters.listMacAddressFilter', null)
}).then((devices)=>{ }).then((devices)=>{
context.commit('deviceListSucceeded', devices); context.commit('deviceListSucceeded', devices);
devices.items.forEach((device)=>{ devices.items.forEach((device)=>{
@ -385,10 +386,18 @@ export default {
context.commit('filterByProfile', profileId); context.commit('filterByProfile', profileId);
context.dispatch('listDevices'); context.dispatch('listDevices');
}, },
filterByMacAddress(context, macAddress) {
context.commit('filterByMacAddress', macAddress);
context.dispatch('listDevices');
},
resetProfileFilter(context) { resetProfileFilter(context) {
context.commit('resetProfileFilter'); context.commit('resetProfileFilter');
context.dispatch('listDevices'); context.dispatch('listDevices');
}, },
resetMacAddressFilter(context) {
context.commit('resetMacAddressFilter');
context.dispatch('listDevices');
},
goToPage(context, page) { goToPage(context, page) {
context.commit('goToPage', page); context.commit('goToPage', page);
context.dispatch('listDevices'); context.dispatch('listDevices');

@ -270,5 +270,14 @@ export default {
}, },
listProfileFilter(state) { listProfileFilter(state) {
return state.listProfileFilter; return state.listProfileFilter;
},
listMacAddressFilter(state) {
return state.listMacAddressFilter;
},
chipModelFilter(state) {
return state.chipModelFilter;
},
chipMacAddressFilter(state) {
return state.chipMacAddressFilter;
} }
} }

@ -161,7 +161,6 @@ export default {
}, },
deviceListRequesting(state, options) { deviceListRequesting(state, options) {
options = options || {}; options = options || {};
// state.listCurrentPage = _.get(options, 'page', 1);
state.listLastPage = null; state.listLastPage = null;
state.listLoadingSilently = _.get(options, 'silent', false); state.listLoadingSilently = _.get(options, 'silent', false);
state.listState = RequestState.requesting; state.listState = RequestState.requesting;
@ -176,6 +175,10 @@ export default {
state.devicesOrdered.forEach((device)=>{ state.devicesOrdered.forEach((device)=>{
state.devices[device.id + ""] = device; state.devices[device.id + ""] = device;
}); });
if (data.length === 0) {
state.filterByMacAddress = null;
state.filterByProfile = null;
}
}, },
deviceListFailed(state, error) { deviceListFailed(state, error) {
state.listState = RequestState.failed; state.listState = RequestState.failed;
@ -333,9 +336,20 @@ export default {
filterByProfile(state, profile) { filterByProfile(state, profile) {
state.listProfileFilter = profile.id; state.listProfileFilter = profile.id;
state.listCurrentPage = 1; state.listCurrentPage = 1;
state.chipModelFilter = profile.name;
},
filterByMacAddress(state, macAddress) {
state.listMacAddressFilter = macAddress;
state.listCurrentPage = 1;
state.chipMacAddressFilter = macAddress;
}, },
resetProfileFilter(state) { resetProfileFilter(state) {
state.listProfileFilter = null; state.listProfileFilter = null;
state.chipModelFilter = null;
},
resetMacAddressFilter(state) {
state.listMacAddressFilter = null;
state.chipMacAddressFilter = null;
}, },
goToPage(state, page) { goToPage(state, page) {
state.listCurrentPage = page; state.listCurrentPage = page;

@ -22,6 +22,7 @@ export default {
listCurrentPage: 1, listCurrentPage: 1,
listLastPage: null, listLastPage: null,
listProfileFilter: null, listProfileFilter: null,
listMacAddressFilter: null,
addState: RequestState.initiated, addState: RequestState.initiated,
addError: null, addError: null,
addItem: null, addItem: null,
@ -64,5 +65,7 @@ export default {
groupReloadingError: null, groupReloadingError: null,
seatReloading: null, seatReloading: null,
seatReloadingState: RequestState.initiated, seatReloadingState: RequestState.initiated,
seatReloadingError: null seatReloadingError: null,
chipModelFilter: null,
chipMacAddressFilter: null
} }

@ -29,7 +29,7 @@
.q-btn .q-btn
.on-left .on-left
margin 0 margin-right 0
.csc-entity-title .q-chip-main { .csc-entity-title .q-chip-main {
color white color white

Loading…
Cancel
Save