TT#20517 PBXConfig: As a Customer, I want to edit PBX Seats

Change-Id: I48808fdb6931a4bf2737d9f3a2a23503b24353fd
changes/29/20329/7
Hans-Peter Herzog 7 years ago
parent 7842fa27b4
commit 46aad5d561

@ -76,6 +76,16 @@ You need a pbx subscriber to be able to access the pbx config specific modules i
`enable: yes` `enable: yes`
1. Enable write access for subscriberadmins by adding "write" to subscriber privileges as in the following example
```
www_admin
privileges:
subscriberadmin:
subscribers:
- write
```
1. Run ngcpcfg apply 1. Run ngcpcfg apply
`ngcpcfg apply 'Enable pbx'` `ngcpcfg apply 'Enable pbx'`

@ -5,7 +5,7 @@ import { getJsonBody } from './utils';
import { getNumbers, assignNumbers } from './user'; import { getNumbers, assignNumbers } from './user';
import { createSubscriber, deleteSubscriber, setDisplayName, import { createSubscriber, deleteSubscriber, setDisplayName,
setPbxExtension, setPbxHuntPolicy, setPbxHuntTimeout, setPbxExtension, setPbxHuntPolicy, setPbxHuntTimeout,
setPbxGroupMemberIds } from './subscriber'; setPbxGroupMemberIds, setPbxGroupIds } from './subscriber';
import uuid from 'uuid'; import uuid from 'uuid';
var createId = uuid.v4; var createId = uuid.v4;
@ -154,3 +154,15 @@ export function setGroupHuntTimeout(id, huntTimeout) {
export function updateGroupSeats(id, seatIds) { export function updateGroupSeats(id, seatIds) {
return setPbxGroupMemberIds(id, seatIds); return setPbxGroupMemberIds(id, seatIds);
} }
export function setSeatName(id, seatName) {
return setDisplayName(id, seatName);
}
export function setSeatExtension(id, seatExtension) {
return setPbxExtension(id, seatExtension);
}
export function updateSeatGroups(id, seatIds) {
return setPbxGroupIds(id, seatIds);
}

@ -260,3 +260,6 @@ export function setPbxGroupMemberIds(id, ids) {
return setField(id, 'pbx_groupmember_ids', ids); return setField(id, 'pbx_groupmember_ids', ids);
} }
export function setPbxGroupIds(id, ids) {
return setField(id, 'pbx_group_ids', ids);
}

@ -10,16 +10,19 @@
</q-card-title> </q-card-title>
<q-card-main v-if="expanded" class="transition-generic"> <q-card-main v-if="expanded" class="transition-generic">
<q-field :label="$t('pbxConfig.groupName')"> <q-field :label="$t('pbxConfig.groupName')">
<q-input v-model="changes.name" :after="nameButtons" /> <q-input v-model="changes.name" :after="nameButtons" @keyup.enter="saveName" />
</q-field> </q-field>
<q-field :label="$t('pbxConfig.extension')"> <q-field :label="$t('pbxConfig.extension')">
<q-input v-model="changes.extension" type="number" :after="extensionButtons" /> <q-input v-model="changes.extension" type="number" :after="extensionButtons"
@keyup.enter="saveExtension" />
</q-field> </q-field>
<q-field :label="$t('pbxConfig.huntPolicy')"> <q-field :label="$t('pbxConfig.huntPolicy')">
<q-select v-model="changes.huntPolicy" :options="huntPolicyOptions" radio @change="huntPolicyChanged"/> <q-select v-model="changes.huntPolicy" :options="huntPolicyOptions"
radio @change="huntPolicyChanged"/>
</q-field> </q-field>
<q-field :label="$t('pbxConfig.huntTimeout')"> <q-field :label="$t('pbxConfig.huntTimeout')">
<q-input v-model="changes.huntTimeout" type="number" suffix="seconds" :after="huntTimeoutButtons" min="0" /> <q-input v-model="changes.huntTimeout" type="number" suffix="seconds"
:after="huntTimeoutButtons" min="0" @keyup.enter="saveHuntTimeout" />
</q-field> </q-field>
<q-field :label="$t('pbxConfig.primaryNumber')"> <q-field :label="$t('pbxConfig.primaryNumber')">
<q-input v-model="primaryNumber" readonly disabled /> <q-input v-model="primaryNumber" readonly disabled />
@ -126,13 +129,6 @@
isLoading() { isLoading() {
return this.loading; return this.loading;
}, },
cardClasses() {
var cardClasses = ['csc-pbx-group'];
if(this.isLoading) {
cardClasses.push('light-dimmed');
}
return cardClasses;
},
titleIcon() { titleIcon() {
if(this.expanded) { if(this.expanded) {
return 'keyboard arrow down'; return 'keyboard arrow down';
@ -277,7 +273,7 @@
}, },
seatChanges() { seatChanges() {
return !_.isEqual(this.changes.seats.sort(), return !_.isEqual(this.changes.seats.sort(),
this.numbersToIds(this.group.seats).sort()); this.seatsToIds(this.group.seats).sort());
}, },
seatButtons() { seatButtons() {
let buttons = []; let buttons = [];
@ -359,7 +355,7 @@
var numbersToAdd = _.difference(this.changes.aliasNumbers, oldNumbers); var numbersToAdd = _.difference(this.changes.aliasNumbers, oldNumbers);
var numbersToRemove = _.difference(oldNumbers, this.changes.aliasNumbers); var numbersToRemove = _.difference(oldNumbers, this.changes.aliasNumbers);
this.$emit('save-alias-numbers', { this.$emit('save-alias-numbers', {
group: this.groupModel, item: this.groupModel,
add: numbersToAdd, add: numbersToAdd,
remove: numbersToRemove remove: numbersToRemove
}); });

@ -2,40 +2,42 @@
<q-card class="csc-pbx-group-add-form"> <q-card class="csc-pbx-group-add-form">
<q-card-title> <q-card-title>
<q-icon name="add" color="primary" size="22px"/> <q-icon name="add" color="primary" size="22px"/>
<span>Add Group</span> <span>{{ $t('pbxConfig.addGroup') }}</span>
</q-card-title> </q-card-title>
<q-card-main> <q-card-main>
<q-field> <q-field>
<q-input :disabled="addGroupIsRequesting" ref="groupName" v-model="groupForm.name" autofocus <q-input :disabled="loading" :readonly="loading" v-model="data.name" autofocus
:float-label="$t('pbxConfig.groupName')" clearable /> :float-label="$t('pbxConfig.groupName')" clearable />
</q-field> </q-field>
<q-field> <q-field>
<q-input :disabled="addGroupIsRequesting" type="number" v-model="groupForm.extension" clearable min="1" max="1000000" <q-input :disabled="loading" :readonly="loading" type="number" v-model="data.extension"
:float-label="$t('pbxConfig.extension')" /> clearable min="1" max="1000000" :float-label="$t('pbxConfig.extension')" />
</q-field> </q-field>
<q-field> <q-field>
<q-select :disabled="addGroupIsRequesting" v-model="groupForm.huntPolicy" :float-label="$t('pbxConfig.huntPolicy')" <q-select :disabled="loading" :readonly="loading" v-model="data.huntPolicy"
:options="huntPolicyOptions" radio /> :float-label="$t('pbxConfig.huntPolicy')" :options="huntPolicyOptions" radio />
</q-field> </q-field>
<q-field > <q-field>
<q-input :disabled="addGroupIsRequesting" type="number" v-model="groupForm.huntTimeout" :float-label="$t('pbxConfig.huntTimeout')" <q-input :disabled="loading" :readonly="loading" type="number" v-model="data.huntTimeout" clearable
suffix="seconds" min="1" max="3600" clearable /> :float-label="$t('pbxConfig.huntTimeout')" suffix="seconds" min="1" max="3600" />
</q-field> </q-field>
<q-field> <q-field>
<q-select :disabled="addGroupIsRequesting" v-model="groupForm.aliasNumbers" :float-label="$t('pbxConfig.aliasNumbers')" <q-select :disabled="loading" :readonly="loading" v-model="data.aliasNumbers" multiple chips clearable
:options="aliasNumberOptions" multiple chips readonly clearable /> :float-label="$t('pbxConfig.aliasNumbers')" :options="aliasNumberOptions" />
</q-field> </q-field>
<q-field> <q-field>
<q-select :disabled="addGroupIsRequesting" v-model="groupForm.seats" :float-label="$t('pbxConfig.seats')" <q-select :disabled="loading" :readonly="loading" v-model="data.seats" multiple chips clearable
:options="seatOptions" multiple chips readonly clearable /> :float-label="$t('pbxConfig.seats')" :options="seatOptions" />
</q-field> </q-field>
</q-card-main> </q-card-main>
<q-card-separator/> <q-card-separator/>
<q-card-actions align="center"> <q-card-actions align="center">
<q-btn v-if="!addGroupIsRequesting" flat color="secondary" icon="clear" @click="disableGroupForm()">{{ $t('buttons.cancel') }}</q-btn> <q-btn v-if="!loading" flat color="secondary" icon="clear"
<q-btn loader v-model="addGroupIsRequesting" flat color="primary" icon="done" @click="addGroup()">{{ $t('buttons.save') }}</q-btn> @click="cancel()">{{ $t('buttons.cancel') }}</q-btn>
<q-btn v-if="!loading" flat color="primary" icon="done"
@click="save()">{{ $t('buttons.save') }}</q-btn>
</q-card-actions> </q-card-actions>
<q-inner-loading :visible="addGroupIsRequesting"> <q-inner-loading :visible="loading">
<q-spinner-mat size="60px" color="primary"></q-spinner-mat> <q-spinner-mat size="60px" color="primary"></q-spinner-mat>
</q-inner-loading> </q-inner-loading>
</q-card> </q-card>
@ -43,78 +45,45 @@
<script> <script>
import { startLoading, stopLoading, showGlobalError, showToast } from '../../../helpers/ui' import { QCard, QCardTitle, QCardMain, QCardActions, QCardSeparator, QBtn,
import CscPage from '../../CscPage' QInnerLoading, QSpinnerMat, QField, QInput, QSelect, QIcon } from 'quasar-framework'
import CscPbxGroup from './CscPbxGroup'
import {
QChip,
QCard,
QCardSeparator,
QCardTitle,
QCardMain,
QCardActions,
QIcon,
QPopover,
QList,
QItem,
QItemMain,
QField,
QInput,
QBtn,
QSelect,
QInnerLoading,
QSpinnerDots,
QSpinnerMat,
Dialog
} from 'quasar-framework'
import { mapState } from 'vuex'
import numberFilter from '../../../filters/number'
export default { export default {
name: 'csc-pbx-group-add-form',
props: [
'huntPolicyOptions',
'aliasNumberOptions',
'seatOptions',
'loading',
],
components: { components: {
CscPage, QCard, QCardTitle, QCardMain, QCardActions, QCardSeparator, QBtn,
QChip, QInnerLoading, QSpinnerMat, QField, QInput, QSelect, QIcon
QCard,
QCardSeparator,
QCardTitle,
QCardMain,
QCardActions,
QIcon,
QPopover,
QList,
QItem,
QItemMain,
QField,
QInput,
CscPbxGroup,
QBtn,
QSelect,
QInnerLoading,
QSpinnerDots,
QSpinnerMat,
Dialog
}, },
data () { data () {
return { return {
group: { data: this.getDefaults()
}
},
methods: {
getDefaults() {
return {
name: '', name: '',
extension: '', extension: '',
huntPolicy: 'serial', huntPolicy: 'serial',
huntTimeout: 10, huntTimeout: 10,
aliasNumbers: [], aliasNumbers: [],
seats: [] seats: []
}, }
}
},
computed: {
},
methods: {
save() {
}, },
cancel() { cancel() {
this.$emit('cancel');
},
save() {
this.$emit('save', this.data);
},
reset() {
this.data = this.getDefaults();
} }
} }
} }
@ -122,10 +91,9 @@
<style lang="stylus" rel="stylesheet/stylus"> <style lang="stylus" rel="stylesheet/stylus">
@import '../../../themes/quasar.variables.styl'; @import '../../../themes/quasar.variables.styl';
.add-form { .csc-pbx-group-add-form
position: relative; position: relative
} .csc-pbx-group-add-form
.add-form .q-field:last-child { .q-field:last-child
margin-bottom: 36px; margin-bottom: 36px
}
</style> </style>

@ -2,32 +2,35 @@
<q-card class="csc-pbx-seat"> <q-card class="csc-pbx-seat">
<q-card-title class="cursor-pointer" @click="toggleMain()"> <q-card-title class="cursor-pointer" @click="toggleMain()">
<q-icon name="person" color="primary" size="24px"/> <q-icon name="person" color="primary" size="24px"/>
<span v-if="!expanded" class="csc-pbx-seat-title">{{ name }}</span> <span v-if="!expanded" class="csc-pbx-seat-title">{{ seat.display_name }}</span>
<q-chip v-if="!expanded" pointing="left" color="primary"> <q-chip v-if="!expanded" pointing="left" color="primary" class="gt-md">
{{ $t('pbxConfig.extension') }}: <span class="csc-important">{{ extension }}</span> {{ $t('pbxConfig.extension') }}: <span class="csc-important">{{ seat.pbx_extension }}</span>
</q-chip> </q-chip>
<q-icon :name="titleIcon" color="primary" size="22px" slot="right"/> <q-icon :name="titleIcon" color="primary" size="22px" slot="right"/>
</q-card-title> </q-card-title>
<q-card-main v-if="expanded"> <q-card-main v-if="expanded" class="transition-generic">
<q-field :label="$t('pbxConfig.seatName')"> <q-field :label="$t('pbxConfig.seatName')">
<q-input v-model="name" readonly /> <q-input v-model="changes.name" :after="nameButtons" @keyup.enter="saveName" />
</q-field> </q-field>
<q-field :label="$t('pbxConfig.extension')"> <q-field :label="$t('pbxConfig.extension')">
<q-input v-model="extension" readonly /> <q-input v-model="changes.extension" type="number"
:after="extensionButtons" @keyup.enter="saveExtension" />
</q-field> </q-field>
<q-field :label="$t('pbxConfig.primaryNumber')"> <q-field :label="$t('pbxConfig.primaryNumber')">
<q-input v-model="primaryNumber" readonly disabled /> <q-input v-model="primaryNumber" readonly disabled />
</q-field> </q-field>
<q-field :label="$t('pbxConfig.aliasNumbers')"> <q-field :label="$t('pbxConfig.aliasNumbers')">
<q-select v-model="aliasNumbers" :options="aliasNumberOptions" multiple chips readonly clearable /> <q-select ref="aliasNumbers" v-model="changes.aliasNumbers" :options="aliasNumberOptions"
multiple chips clearable :after="aliasNumberButtons" @change="aliasNumberChange"/>
</q-field> </q-field>
<q-field :label="$t('pbxConfig.groups')"> <q-field :label="$t('pbxConfig.groups')">
<q-select v-model="groups" :options="groupOptions" multiple chips readonly clearable /> <q-select v-model="changes.groups" :options="groupOptions" multiple chips clearable
:after="groupButtons" @change="groupChange" />
</q-field> </q-field>
</q-card-main> </q-card-main>
<q-card-actions align="center"> <q-card-actions align="center">
<q-btn flat :small="isMobile" :round="isMobile" color="negative" <q-btn flat :small="isMobile" :round="isMobile"
icon="delete" @click="remove()">Delete</q-btn> color="negative" icon="delete" @click="remove()">Delete</q-btn>
</q-card-actions> </q-card-actions>
<q-inner-loading :visible="isLoading"> <q-inner-loading :visible="isLoading">
<q-spinner-mat size="60px" color="primary"></q-spinner-mat> <q-spinner-mat size="60px" color="primary"></q-spinner-mat>
@ -52,8 +55,7 @@
QInnerLoading, QInnerLoading,
QSpinnerMat, QSpinnerMat,
QTransition, QTransition,
Platform, Platform
Dialog
} from 'quasar-framework' } from 'quasar-framework'
export default { export default {
name: 'csc-pbx-seat', name: 'csc-pbx-seat',
@ -61,11 +63,12 @@
'seat', 'seat',
'aliasNumberOptions', 'aliasNumberOptions',
'groupOptions', 'groupOptions',
'deleting' 'loading'
], ],
data () { data () {
return { return {
expanded: false expanded: false,
changes: this.getSeat()
} }
}, },
components: { components: {
@ -96,43 +99,18 @@
primaryNumber() { primaryNumber() {
return numberFilter(this.seat.primary_number); return numberFilter(this.seat.primary_number);
}, },
aliasNumbers() {
let numbers = [];
if(_.isArray(this.seat.alias_numbers)) {
this.seat.alias_numbers.forEach((number)=>{
numbers.push(number.number_id);
});
}
return numbers;
},
groups() {
let groups = [];
if(_.isArray(this.seat.groups)) {
this.seat.groups.forEach((group)=>{
groups.push(group.id);
});
}
return groups;
},
seatModel() { seatModel() {
return { return {
id: this.id, id: this.id,
name: this.name, name: this.changes.name,
extension: this.extension, extension: this.changes.extension,
primaryNumber: this.primaryNumber, primaryNumber: this.primaryNumber,
aliasNumbers: this.aliasNumbers, aliasNumbers: this.changes.aliasNumbers,
groups: this.groups groups: this.changes.groups
} }
}, },
isLoading() { isLoading() {
return this.deleting; return this.loading;
},
cardClasses() {
var cardClasses = ['csc-pbx-seat'];
if(this.isLoading) {
cardClasses.push('light-dimmed');
}
return cardClasses;
}, },
titleIcon() { titleIcon() {
if(this.expanded) { if(this.expanded) {
@ -144,30 +122,187 @@
}, },
isMobile() { isMobile() {
return Platform.is.mobile; return Platform.is.mobile;
},
nameHasChanges() {
return this.name !== this.changes.name;
},
nameButtons() {
let buttons = [];
let self = this;
if(this.nameHasChanges) {
buttons.push({
icon: 'check',
error: false,
handler (event) {
event.stopPropagation();
self.saveName();
}
}, {
icon: 'clear',
error: false,
handler (event) {
event.stopPropagation();
self.resetName();
}
}
);
}
return buttons;
},
extensionHasChanges() {
return this.extension + "" !== this.changes.extension + "";
},
extensionButtons() {
let buttons = [];
let self = this;
if(this.extensionHasChanges) {
buttons.push({
icon: 'check',
error: false,
handler (event) {
event.stopPropagation();
self.saveExtension();
}
}, {
icon: 'clear',
error: false,
handler (event) {
event.stopPropagation();
self.resetExtension();
}
}
);
}
return buttons;
},
aliasNumbersChanges() {
return !_.isEqual(this.changes.aliasNumbers.sort(),
this.numbersToIds(this.seat.alias_numbers).sort());
},
aliasNumberButtons() {
let buttons = [];
let self = this;
if(this.aliasNumbersChanges) {
buttons.push({
icon: 'check',
error: false,
handler (event) {
event.stopPropagation();
self.saveAliasNumbers();
}
}, {
icon: 'clear',
error: false,
handler (event) {
event.stopPropagation();
self.resetAliasNumbers();
}
}
);
}
return buttons;
},
groupChanges() {
return !_.isEqual(this.changes.groups.sort(),
this.groupsToIds(this.seat.groups).sort());
},
groupButtons() {
let buttons = [];
let self = this;
if(this.groupChanges) {
buttons.push({
icon: 'check',
error: false,
handler (event) {
event.stopPropagation();
self.saveGroups();
}
}, {
icon: 'clear',
error: false,
handler (event) {
event.stopPropagation();
self.resetGroups();
}
}
);
}
return buttons;
} }
}, },
methods: { methods: {
toggleMain() { toggleMain() {
this.expanded = !this.expanded if(this.expanded) {
this.expanded = false;
}
else {
this.expanded = true;
}
}, },
remove() { remove() {
var state = this; this.$emit('remove', this.seatModel);
var i18n = this.$i18n; },
Dialog.create({ resetName() {
title: i18n.t('pbxConfig.removeSeatTitle'), this.changes.name = this.seat.display_name;
message: i18n.t('pbxConfig.removeSeatText', { seat: this.name }), },
buttons: [ saveName() {
'Cancel', this.$emit('save-name', this.seatModel);
{ },
label: i18n.t('pbxConfig.removeSeat'), resetExtension() {
color: 'negative', this.changes.extension = this.seat.pbx_extension;
handler () { },
state.loading = true; saveExtension() {
state.$emit('remove', state.seatModel); this.$emit('save-extension', this.seatModel);
} },
} numbersToIds(aliasNumbers) {
] let numbers = [];
if(_.isArray(aliasNumbers)) {
aliasNumbers.forEach((number) => {
numbers.push(number.number_id);
});
}
return numbers;
},
resetAliasNumbers() {
this.changes.aliasNumbers = this.numbersToIds(this.seat.alias_numbers);
},
saveAliasNumbers() {
var oldNumbers = this.numbersToIds(this.seat.alias_numbers);
var numbersToAdd = _.difference(this.changes.aliasNumbers, oldNumbers);
var numbersToRemove = _.difference(oldNumbers, this.changes.aliasNumbers);
this.$emit('save-alias-numbers', {
item: this.seatModel,
add: numbersToAdd,
remove: numbersToRemove
}); });
},
getSeat() {
return {
name: this.seat.display_name,
extension: this.seat.pbx_extension,
aliasNumbers: this.numbersToIds(this.seat.alias_numbers),
groups: this.groupsToIds(this.seat.groups)
}
},
groupsToIds(groups) {
let groupIds = [];
if(_.isArray(groups)) {
groups.forEach((group) => {
groupIds.push(group.id);
});
}
return groupIds;
},
resetGroups() {
this.changes.groups = this.groupsToIds(this.seat.groups);
},
saveGroups() {
this.$emit('save-groups', this.seatModel);
},
},
watch: {
seat() {
this.changes = this.getSeat()
} }
} }
} }

@ -1,111 +1,63 @@
<template> <template>
<div class="csc-add-form csc-pbx-seat-add-form"> <q-card class="csc-pbx-seat-add-form">
<q-card v-if="enabled"> <q-card-title>
<q-card-title> <q-icon name="add" color="primary" size="22px"/>
<q-icon name="add" color="primary" size="24px"/> <span>{{ $t('pbxConfig.addSeat') }}</span>
<span>{{ $t('pbxConfig.addSeat') }}</span> </q-card-title>
</q-card-title> <q-card-main>
<q-card-main> <q-field>
<q-field> <q-input :disabled="loading" :readonly="loading" v-model="data.name" autofocus
<q-input :disabled="isRequesting" ref="name" v-model="form.name" autofocus :float-label="$t('pbxConfig.seatName')" clearable />
:float-label="$t('pbxConfig.seatName')" clearable /> </q-field>
</q-field> <q-field>
<q-field> <q-input :disabled="loading" :readonly="loading" type="number" v-model="data.extension"
<q-input :disabled="isRequesting" type="number" v-model="form.extension" clearable clearable min="1" max="1000000" :float-label="$t('pbxConfig.extension')" />
min="1" max="1000000" :float-label="$t('pbxConfig.extension')" /> </q-field>
</q-field> <q-field>
<q-field> <q-select :disabled="loading" :readonly="loading" v-model="data.aliasNumbers" multiple chips clearable
<q-select :disabled="isRequesting" v-model="form.aliasNumbers" multiple chips readonly clearable :float-label="$t('pbxConfig.aliasNumbers')" :options="aliasNumberOptions" />
:float-label="$t('pbxConfig.aliasNumbers')" :options="aliasNumberOptions" /> </q-field>
</q-field> <q-field>
<q-field> <q-select :disabled="loading" :readonly="loading" v-model="data.groups" multiple chips clearable
<q-select :disabled="isRequesting" v-model="form.groups" multiple chips readonly clearable :float-label="$t('pbxConfig.groups')" :options="groupOptions" />
:float-label="$t('pbxConfig.groups')" :options="groupOptions" /> </q-field>
</q-field> </q-card-main>
</q-card-main> <q-card-separator/>
<q-card-separator/> <q-card-actions align="center">
<q-card-actions align="center"> <q-btn v-if="!loading" flat color="secondary" icon="clear"
<q-btn v-if="!isRequesting" flat color="secondary" icon="clear" @click="cancel()">{{ $t('buttons.cancel') }}</q-btn>
@click="cancel()">{{ $t('buttons.cancel') }}</q-btn> <q-btn v-if="!loading" flat color="primary" icon="done"
<q-btn loader v-model="isRequesting" flat color="primary" icon="done" @click="save()">{{ $t('buttons.save') }}</q-btn>
@click="save()">{{ $t('buttons.save') }}</q-btn> </q-card-actions>
</q-card-actions> <q-inner-loading :visible="loading">
<q-inner-loading :visible="isRequesting"> <q-spinner-mat size="60px" color="primary"></q-spinner-mat>
<q-spinner-mat size="60px" color="primary"></q-spinner-mat> </q-inner-loading>
</q-inner-loading> </q-card>
</q-card>
<q-card v-else flat>
<q-card-actions align="center">
<q-btn color="primary" icon="add" flat @click="add()">{{ $t('pbxConfig.addSeat') }}</q-btn>
</q-card-actions>
</q-card>
</div>
</template> </template>
<script> <script>
import {
QChip, import { QCard, QCardTitle, QCardMain, QCardActions, QCardSeparator, QBtn,
QCard, QInnerLoading, QSpinnerMat, QField, QInput, QSelect, QIcon } from 'quasar-framework'
QCardSeparator,
QCardTitle,
QCardMain,
QCardActions,
QIcon,
QPopover,
QList,
QItem,
QItemMain,
QField,
QInput,
QBtn,
QSelect,
QInnerLoading,
QSpinnerDots,
QSpinnerMat,
Dialog
} from 'quasar-framework'
export default { export default {
name: 'csc-pbx-seat-add-form', name: 'csc-pbx-seat-add-form',
props: [ props: [
'aliasNumberOptions', 'aliasNumberOptions',
'groupOptions' 'groupOptions',
'loading'
], ],
components: { components: {
QChip, QCard, QCardTitle, QCardMain, QCardActions, QCardSeparator, QBtn,
QCard, QInnerLoading, QSpinnerMat, QField, QInput, QSelect, QIcon
QCardSeparator,
QCardTitle,
QCardMain,
QCardActions,
QIcon,
QPopover,
QList,
QItem,
QItemMain,
QField,
QInput,
QBtn,
QSelect,
QInnerLoading,
QSpinnerDots,
QSpinnerMat,
Dialog
}, },
data () { data () {
return { return {
form: this.getDefaultData(), data: this.getDefaults()
enabled: false,
loading: false
}
},
computed: {
isRequesting() {
return this.loading;
} }
}, },
methods: { methods: {
getDefaultData() { getDefaults() {
return { return {
name: '', name: '',
extension: '', extension: '',
@ -114,28 +66,13 @@
} }
}, },
cancel() { cancel() {
this.enabled = false; this.$emit('cancel');
},
add() {
this.enabled = true;
this.form = this.getDefaultData();
}, },
save() { save() {
this.loading = true; this.$emit('save', this.data);
this.$emit('save', {
name: this.form.name,
extension: this.form.extension,
aliasNumbers: this.form.aliasNumbers,
groups: this.form.groups
});
}, },
succeeded() { reset() {
this.loading = false; this.data = this.getDefaults();
this.enabled = false;
},
failed() {
this.loading = false;
this.enabled = true;
} }
} }
} }
@ -143,11 +80,9 @@
<style lang="stylus" rel="stylesheet/stylus"> <style lang="stylus" rel="stylesheet/stylus">
@import '../../../themes/quasar.variables.styl'; @import '../../../themes/quasar.variables.styl';
.csc-pbx-seat-add-form
.csc-pbx-seat-add-form .q-card { position: relative
position: relative; .csc-pbx-seat-add-form
} .q-field:last-child
.csc-pbx-seat-add-form .q-card .q-field:last-child { margin-bottom: 36px
margin-bottom: 36px;
}
</style> </style>

@ -1,53 +0,0 @@
<template>
<div class="csc-pbx-seat-list">
<q-card v-if="loading" flat>
<q-card-actions align="center">
<q-spinner-dots color="primary" :size="40"/>
</q-card-actions>
</q-card>
<csc-pbx-seat v-for="seat in seats" :seat="seat" @remove="remove" :deleting="isDeleting(seat)"
:alias-number-options="aliasNumberOptions" :group-options="groupOptions" />
</div>
</template>
<script>
import {
QCard,
QCardActions,
QSpinnerDots
} from 'quasar-framework'
import CscPbxSeat from './CscPbxSeat'
export default {
name: 'csc-pbx-seat-list',
components: {
QCard,
QCardActions,
QSpinnerDots,
CscPbxSeat
},
props: [
'seats',
'loading',
'aliasNumberOptions',
'groupOptions',
'deletingSeat'
],
data () {
return {
}
},
methods: {
remove(seat) {
this.$emit('remove', seat);
},
isDeleting(seat) {
return this.deletingSeat !== null && seat.id === this.deletingSeat.id;
}
}
}
</script>
<style lang="stylus" rel="stylesheet/stylus">
</style>

@ -1,58 +1,23 @@
<template> <template>
<csc-page id="csc-page-pbx-groups" title="Groups"> <csc-page id="csc-page-pbx-groups" title="Groups">
<q-card v-if="groupFormEnabled" class="add-form"> <csc-pbx-group-add-form v-show="addFormEnabled" ref="addForm" @save="addGroup" @cancel="disableAddForm"
<q-card-title> :loading="isAdding" :alias-number-options="aliasNumberOptions"
<q-icon name="add" color="primary" size="22px"/> :seat-options="seatOptions" :hunt-policy-options="huntPolicyOptions"/>
<span>Add Group</span> <q-card v-show="!addFormEnabled" flat>
</q-card-title>
<q-card-main>
<q-field>
<q-input :disabled="addGroupIsRequesting" ref="groupName" v-model="groupForm.name" autofocus
:float-label="$t('pbxConfig.groupName')" clearable />
</q-field>
<q-field>
<q-input :disabled="addGroupIsRequesting" type="number" v-model="groupForm.extension" clearable min="1" max="1000000"
:float-label="$t('pbxConfig.extension')" />
</q-field>
<q-field>
<q-select :disabled="addGroupIsRequesting" v-model="groupForm.huntPolicy" :float-label="$t('pbxConfig.huntPolicy')"
:options="huntPolicyOptions" radio />
</q-field>
<q-field >
<q-input :disabled="addGroupIsRequesting" type="number" v-model="groupForm.huntTimeout" :float-label="$t('pbxConfig.huntTimeout')"
suffix="seconds" min="1" max="3600" clearable />
</q-field>
<q-field>
<q-select :disabled="addGroupIsRequesting" v-model="groupForm.aliasNumbers" :float-label="$t('pbxConfig.aliasNumbers')"
:options="aliasNumberOptions" multiple chips readonly clearable />
</q-field>
<q-field>
<q-select :disabled="addGroupIsRequesting" v-model="groupForm.seats" :float-label="$t('pbxConfig.seats')"
:options="seatOptions" multiple chips readonly clearable />
</q-field>
</q-card-main>
<q-card-separator/>
<q-card-actions align="center"> <q-card-actions align="center">
<q-btn v-if="!addGroupIsRequesting" flat color="secondary" icon="clear" @click="disableGroupForm()">{{ $t('buttons.cancel') }}</q-btn> <q-btn color="primary" icon="add" flat @click="enableAddForm">
<q-btn loader v-model="addGroupIsRequesting" flat color="primary" icon="done" @click="addGroup()">{{ $t('buttons.save') }}</q-btn> {{ $t('pbxConfig.addGroup') }}
</q-btn>
</q-card-actions> </q-card-actions>
<q-inner-loading :visible="addGroupIsRequesting">
<q-spinner-mat size="60px" color="primary"></q-spinner-mat>
</q-inner-loading>
</q-card> </q-card>
<q-card v-else flat> <q-card v-if="isListRequesting && !listLoadingSilently" flat>
<q-card-actions align="center">
<q-btn color="primary" icon="add" flat @click="enableGroupForm">{{ $t('pbxConfig.addGroup') }}</q-btn>
</q-card-actions>
</q-card>
<q-card v-if="listIsRequesting && !listLoadingSilently" flat>
<q-card-actions align="center"> <q-card-actions align="center">
<q-spinner-dots color="primary" :size="40"/> <q-spinner-dots color="primary" :size="40"/>
</q-card-actions> </q-card-actions>
</q-card> </q-card>
<csc-pbx-group v-for="group in groups" :key="group.id" :group="group" :alias-number-options="aliasNumberOptions" <csc-pbx-group v-for="group in groups" :key="group.id" :group="group" :alias-number-options="aliasNumberOptions"
:seat-options="seatOptions" :hunt-policy-options="huntPolicyOptions" @remove="removeGroup" :seat-options="seatOptions" :hunt-policy-options="huntPolicyOptions" @remove="removeGroup"
:loading="isGroupUpdating(group.id)" @save-name="setGroupName" @save-extension="setGroupExtension" :loading="isItemLoading(group.id)" @save-name="setGroupName" @save-extension="setGroupExtension"
@save-hunt-policy="setGroupHuntPolicy" @save-hunt-timeout="setGroupHuntTimeout" @save-hunt-policy="setGroupHuntPolicy" @save-hunt-timeout="setGroupHuntTimeout"
@save-alias-numbers="updateAliasNumbers" @save-seats="updateSeats" /> @save-alias-numbers="updateAliasNumbers" @save-seats="updateSeats" />
</csc-page> </csc-page>
@ -60,82 +25,35 @@
<script> <script>
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import { showGlobalError } from '../../../helpers/ui'
import CscPage from '../../CscPage' import CscPage from '../../CscPage'
import CscPbxGroup from './CscPbxGroup' import CscPbxGroup from './CscPbxGroup'
import { import CscPbxGroupAddForm from './CscPbxGroupAddForm'
QChip, import { QChip, QCard, QCardSeparator, QCardTitle, QCardMain,
QCard, QCardActions, QIcon, QPopover, QList, QItem, QItemMain,
QCardSeparator, QField, QInput, QBtn, QSelect, QInnerLoading, QSpinnerDots,
QCardTitle, QSpinnerMat, Dialog
QCardMain,
QCardActions,
QIcon,
QPopover,
QList,
QItem,
QItemMain,
QField,
QInput,
QBtn,
QSelect,
QInnerLoading,
QSpinnerDots,
QSpinnerMat,
Dialog
} from 'quasar-framework' } from 'quasar-framework'
import numberFilter from '../../../filters/number' import aliasNumberOptions from '../../../mixins/alias-number-options'
import itemError from '../../../mixins/item-error'
export default { export default {
mixins: [aliasNumberOptions, itemError],
components: { components: {
CscPage, CscPage, CscPbxGroup, CscPbxGroupAddForm,
QChip, QChip, QCard, QCardSeparator, QCardTitle, QCardMain,
QCard, QCardActions, QIcon, QPopover, QList, QItem, QItemMain,
QCardSeparator, QField, QInput, QBtn, QSelect, QInnerLoading, QSpinnerDots,
QCardTitle, QSpinnerMat, Dialog
QCardMain,
QCardActions,
QIcon,
QPopover,
QList,
QItem,
QItemMain,
QField,
QInput,
CscPbxGroup,
QBtn,
QSelect,
QInnerLoading,
QSpinnerDots,
QSpinnerMat,
Dialog
}, },
mounted() { mounted() {
this.$store.dispatch('pbxConfig/listGroups'); this.$store.dispatch('pbxConfig/listGroups');
}, },
data () { data () {
return { return {
groupForm: { addFormEnabled: false
name: '',
extension: '',
huntPolicy: 'serial',
huntTimeout: 10,
aliasNumbers: [],
seats: []
},
groupFormEnabled: false,
} }
}, },
computed: { computed: {
groups() {
return this.$store.getters['pbxConfig/groups'];
},
seats() {
return this.$store.getters['pbxConfig/seats'];
},
aliasNumbers() {
return this.$store.getters['pbxConfig/aliasNumbers'];
},
huntPolicyOptions() { huntPolicyOptions() {
return [ return [
{ {
@ -156,31 +74,6 @@
} }
]; ];
}, },
aliasNumberOptions() {
let aliasNumber = [];
this.aliasNumbers.forEach((number)=>{
let owner = this.$t('pbxConfig.allocatedByNobody');
if(number.subscriber !== null && number.subscriber.display_name !== null &&
number.subscriber.is_pbx_group) {
owner = this.$t('pbxConfig.allocatedBy', {
type: this.$t('pbxConfig.group'),
name: number.subscriber.display_name
});
}
else if (number.subscriber !== null && number.subscriber.display_name !== null) {
owner = this.$t('pbxConfig.allocatedBy', {
type: this.$t('pbxConfig.seat'),
name: number.subscriber.display_name
});
}
aliasNumber.push({
label: numberFilter(number),
sublabel: owner,
value: number.id
});
});
return aliasNumber;
},
seatOptions() { seatOptions() {
let seats = []; let seats = [];
this.seats.forEach((seat)=>{ this.seats.forEach((seat)=>{
@ -192,87 +85,47 @@
}); });
return seats; return seats;
}, },
listIsRequesting() {
return this.listState === 'requesting';
},
listState() {
return this.$store.state.pbxConfig.listAllState;
},
listError() {
return this.$store.state.pbxConfig.listAllError;
},
addGroupIsRequesting() {
return this.addGroupState === 'requesting';
},
addGroupState() {
return this.$store.state.pbxConfig.addGroupState;
},
addGroupError() {
return this.$store.state.pbxConfig.addGroupError;
},
removeGroupState() {
return this.$store.state.pbxConfig.removeGroupState;
},
removeGroupIsRequesting() {
return this.removeGroupState === 'requesting' ||
this.removeGroupState === 'succeeded';
},
removeGroupId() {
return this.$store.state.pbxConfig.removeGroupItem.id;
},
...mapGetters('pbxConfig', [ ...mapGetters('pbxConfig', [
'listItemUpdating', 'groups',
'listItemUpdateState', 'seats',
'listItemUpdateError', 'aliasNumbers',
'addState',
'isAdding',
'isUpdating',
'updateItemId',
'isRemoving',
'removeItemId',
'isListRequesting',
'listState',
'listError',
'listLoadingSilently' 'listLoadingSilently'
]) ])
}, },
watch: { watch: {
addGroupState(state) { addState(state) {
if(state === 'failed') {
showGlobalError(this.addGroupError);
}
if(state === 'succeeded') { if(state === 'succeeded') {
this.disableGroupForm(); this.disableAddForm();
}
},
removeGroupState(state) {
if(state === 'failed') {
showGlobalError(this.removeGroupError);
}
},
listItemUpdateState(state) {
if(state === 'failed') {
showGlobalError(this.listItemUpdateError);
} }
} }
}, },
methods: { methods: {
isGroupUpdating(groupId) { isItemLoading(groupId) {
return this.listItemUpdateState === 'requesting' && return (this.isUpdating && this.updateItemId + "" === groupId + "") ||
this.listItemUpdating !== null && (this.isRemoving && this.removeItemId + "" === groupId + "");
this.listItemUpdating.id === groupId;
}, },
resetGroupForm() { resetAddForm() {
this.groupForm = { this.$refs.addForm.reset();
name: '',
extension: '',
huntPolicy: 'serial',
huntTimeout: 10,
aliasNumbers: [],
seats: []
}
}, },
enableGroupForm() { enableAddForm() {
this.resetGroupForm(); this.resetAddForm();
this.groupFormEnabled = true; this.addFormEnabled = true;
}, },
disableGroupForm() { disableAddForm() {
this.resetGroupForm(); this.resetAddForm();
this.groupFormEnabled = false; this.addFormEnabled = false;
}, },
addGroup() { addGroup(group) {
this.$store.dispatch('pbxConfig/addGroup', this.groupForm); this.$store.dispatch('pbxConfig/addGroup', group);
}, },
removeGroup(group) { removeGroup(group) {
var store = this.$store; var store = this.$store;

@ -1,60 +1,72 @@
<template> <template>
<csc-page title="Seats"> <csc-page title="Seats">
<csc-pbx-seat-add-form ref="addForm" :alias-number-options="aliasNumberOptions" <csc-pbx-seat-add-form v-show="addFormEnabled" ref="addForm" :alias-number-options="aliasNumberOptions"
:group-options="groupOptions" @save="save" /> :group-options="groupOptions" :loading="isAdding" @save="addSeat"
<csc-pbx-seat-list :alias-number-options="aliasNumberOptions" :group-options="groupOptions" @cancel="disableAddForm" />
:seats="seats" :loading="isListLoading" @remove="remove" :deleting-seat="deletingSeat" /> <q-card v-show="!addFormEnabled" flat>
<q-card-actions align="center">
<q-btn color="primary" icon="add" flat @click="enableAddForm">
{{ $t('pbxConfig.addSeat') }}
</q-btn>
</q-card-actions>
</q-card>
<q-card v-if="isListRequesting && !listLoadingSilently" flat>
<q-card-actions align="center">
<q-spinner-dots color="primary" :size="40"/>
</q-card-actions>
</q-card>
<csc-pbx-seat v-for="seat in seats" :key="seat.id" :seat="seat" :alias-number-options="aliasNumberOptions"
:group-options="groupOptions" @remove="removeSeat" :loading="isItemLoading(seat.id)"
@save-name="setSeatName" @save-extension="setSeatExtension"
@save-alias-numbers="updateAliasNumbers" @save-groups="updateGroups" />
</csc-page> </csc-page>
</template> </template>
<script> <script>
import CscPage from '../../CscPage' import CscPage from '../../CscPage'
import CscPbxSeatAddForm from './CscPbxSeatAddForm' import CscPbxSeatAddForm from './CscPbxSeatAddForm'
import CscPbxSeatList from './CscPbxSeatList' import CscPbxSeat from './CscPbxSeat'
import { QChip, QCard, QCardSeparator, QCardTitle, QCardMain, import { QChip, QCard, QCardSeparator, QCardTitle, QCardMain,
QIcon, QPopover, QList, QItem, QItemMain } from 'quasar-framework' QCardActions, QIcon, QPopover, QList, QItem, QItemMain,
QField, QInput, QBtn, QSelect, QInnerLoading, QSpinnerDots,
QSpinnerMat, Dialog } from 'quasar-framework'
import aliasNumberOptions from '../../../mixins/alias-number-options' import aliasNumberOptions from '../../../mixins/alias-number-options'
import { showGlobalError } from '../../../helpers/ui' import itemError from '../../../mixins/item-error'
// import { showGlobalError } from '../../../helpers/ui'
import { mapGetters } from 'vuex'
export default { export default {
mixins: [aliasNumberOptions], mixins: [aliasNumberOptions, itemError],
mounted() { mounted() {
this.$store.dispatch('pbxConfig/listSeats'); this.$store.dispatch('pbxConfig/listSeats');
}, },
data () { data () {
return {} return {
addFormEnabled: false
}
}, },
components: { components: {
CscPage, CscPage, CscPbxSeat, CscPbxSeatAddForm,
QChip, QChip, QCard, QCardSeparator, QCardTitle, QCardMain,
QCard, QCardActions, QIcon, QPopover, QList, QItem, QItemMain,
QCardSeparator, QField, QInput, QBtn, QSelect, QInnerLoading, QSpinnerDots,
QCardTitle, QSpinnerMat, Dialog
QCardMain,
QIcon,
QPopover,
QList,
QItem,
QItemMain,
CscPbxSeatAddForm,
CscPbxSeatList
}, },
computed: { computed: {
addFormSucceeded() { ...mapGetters('pbxConfig', [
return this.$store.state.pbxConfig.addSeatState === 'succeeded'; 'seats',
}, 'groups',
addFormFailed() { 'addState',
return this.$store.state.pbxConfig.addSeatState === 'failed'; 'isAdding',
}, 'isUpdating',
addFormError() { 'updateItemId',
return this.$store.state.pbxConfig.addSeatError; 'isRemoving',
}, 'removeItemId',
isListLoading() { 'isListRequesting',
return this.$store.state.pbxConfig.listAllState === 'requesting'; 'listState',
}, 'listError',
removeError() { 'listLoadingSilently'
return this.$store.state.pbxConfig.removeSeatError; ]),
},
groupOptions() { groupOptions() {
let groups = []; let groups = [];
this.groups.forEach((group)=>{ this.groups.forEach((group)=>{
@ -65,39 +77,63 @@
}); });
}); });
return groups; return groups;
}, }
seats() { },
return this.$store.getters['pbxConfig/seats']; watch: {
}, addState(state) {
groups() { if(state === 'succeeded') {
return this.$store.getters['pbxConfig/groups']; this.disableAddForm();
}, }
deletingSeat() {
return this.$store.state.pbxConfig.removeSeatItem;
} }
}, },
methods: { methods: {
save(seat) { isItemLoading(seatId) {
return (this.isUpdating && this.updateItemId + "" === seatId + "") ||
(this.isRemoving && this.removeItemId + "" === seatId + "");
},
resetAddForm() {
this.$refs.addForm.reset();
},
enableAddForm() {
this.resetAddForm();
this.addFormEnabled = true;
},
disableAddForm() {
this.resetAddForm();
this.addFormEnabled = false;
},
addSeat(seat) {
this.$store.dispatch('pbxConfig/addSeat', seat); this.$store.dispatch('pbxConfig/addSeat', seat);
}, },
remove(seat) { removeSeat(seat) {
this.$store.dispatch('pbxConfig/removeSeat', seat); var store = this.$store;
} var i18n = this.$i18n;
}, Dialog.create({
watch: { title: i18n.t('pbxConfig.removeSeatTitle'),
addFormSucceeded() { message: i18n.t('pbxConfig.removeSeatText', { seat: seat.name }),
this.$refs.addForm.succeeded(); buttons: [
'Cancel',
{
label: i18n.t('pbxConfig.removeSeat'),
color: 'negative',
handler () {
store.dispatch('pbxConfig/removeSeat', seat);
}
}
]
});
}, },
addFormFailed() { setSeatName(seat) {
if(this.addFormError !== null) { this.$store.dispatch('pbxConfig/setSeatName', seat);
this.$refs.addForm.failed();
showGlobalError(this.addFormError);
}
}, },
removeError() { setSeatExtension(seat) {
if(this.removeError !== null) { this.$store.dispatch('pbxConfig/setSeatExtension', seat);
showGlobalError(this.removeError); },
} updateAliasNumbers(data) {
this.$store.dispatch('pbxConfig/updateAliasNumbers', data);
},
updateGroups(data) {
this.$store.dispatch('pbxConfig/updateGroups', data);
} }
} }
} }

@ -0,0 +1,34 @@
'use strict';
import { showGlobalError } from '../helpers/ui';
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters('pbxConfig', [
'addState',
'updateState',
'removeState',
'addError',
'updateError',
'removeError'
]),
},
watch: {
addState(state) {
if(state === 'failed') {
showGlobalError(this.addError);
}
},
updateState(state) {
if(state === 'failed') {
showGlobalError(this.updateError);
}
},
removeState(state) {
if(state === 'failed') {
showGlobalError(this.removeError);
}
}
}
};

@ -1,24 +1,8 @@
'use strict'; 'use strict';
export const RequestState = { export const RequestState = {
requesting: 'requesting',
succeeded: 'succeeded',
failed: 'failed'
};
export const ListState = {
initiated: 'initiated', initiated: 'initiated',
requesting: 'requesting', requesting: 'requesting',
succeeded: 'succeeded', succeeded: 'succeeded',
failed: 'failed' failed: 'failed'
}; };
export const AddState = {
button: 'button',
input: 'input',
requesting: 'requesting',
succeeded: 'succeeded',
failed: 'failed'
};
export const RemoveState = ListState;

@ -3,128 +3,161 @@
import { assignNumbers } from '../../api/user'; import { assignNumbers } from '../../api/user';
import { getPbxConfiguration, addGroup, import { getPbxConfiguration, addGroup,
removeGroup, addSeat, removeSeat, setGroupName, removeGroup, addSeat, removeSeat, setGroupName,
setGroupExtension, setGroupHuntPolicy, setGroupHuntTimeout, updateGroupSeats } from '../../api/pbx-config' setGroupExtension, setGroupHuntPolicy, setGroupHuntTimeout,
updateGroupSeats, setSeatName, setSeatExtension, updateSeatGroups } from '../../api/pbx-config'
export default { export default {
listSeats(context, silent) {
return context.dispatch('listGroups', silent);
},
listGroups(context, silent) { listGroups(context, silent) {
return new Promise((resolve, reject)=>{ return new Promise((resolve, reject)=>{
context.commit('listAllRequesting', silent); context.commit('listRequesting', silent);
getPbxConfiguration().then((config)=>{ getPbxConfiguration().then((config)=>{
context.commit('listAllSucceeded', config); context.commit('listSucceeded', config);
resolve(); resolve();
}).catch((err)=>{ }).catch((err)=>{
context.commit('listAllFailed', err.message); context.commit('listFailed', err.message);
reject(err); reject(err);
}); });
}); });
}, },
addGroup(context, group) { addGroup(context, group) {
context.commit('addGroupRequesting');
group.customerId = context.state.pilot.customer_id; group.customerId = context.state.pilot.customer_id;
group.domainId = context.state.pilot.domain_id; group.domainId = context.state.pilot.domain_id;
context.commit('addItemRequesting', group);
addGroup(group).then(()=>{ addGroup(group).then(()=>{
return context.dispatch('listGroups', true); return context.dispatch('listGroups', true);
}).then(()=>{ }).then(()=>{
context.commit('addGroupSucceeded'); context.commit('addItemSucceeded');
}).catch((err)=>{ }).catch((err)=>{
context.commit('addGroupFailed', err.message); context.commit('addItemFailed', err.message);
});
},
removeGroup(context, group) {
context.commit('updateListItemStarted', group);
removeGroup(group.id).then(()=>{
return context.dispatch('listGroups', true);
}).then(()=>{
context.commit('removeGroup', group);
context.commit('updateListItemSucceeded');
}).catch((err)=>{
context.commit('updateListItemFailed', err.message);
});
},
addSeat(context, seat) {
seat.customerId = context.state.pilot.customer_id;
seat.domainId = context.state.pilot.domain_id;
context.commit('addSeatRequesting', seat);
addSeat(seat).then(()=>{
context.commit('addSeatSucceeded', seat);
context.dispatch('listSeats', true);
}).catch((err)=>{
context.commit('addSeatFailed', err.message);
});
},
removeSeat(context, seat) {
context.commit('removeSeatRequesting', seat);
removeSeat(seat.id).then(()=>{
context.commit('removeSeatSucceeded');
context.dispatch('listSeats', true);
}).catch((err)=>{
context.commit('removeSeatFailed', err.message);
}); });
}, },
setGroupName(context, group) { setGroupName(context, group) {
context.commit('updateListItemStarted', group); context.commit('updateItemRequesting', group);
setGroupName(group.id, group.name).then(() => { setGroupName(group.id, group.name).then(() => {
return context.dispatch('listGroups', true); return context.dispatch('listGroups', true);
}).then(()=>{ }).then(()=>{
context.commit('updateListItemSucceeded'); context.commit('updateItemSucceeded');
}).catch((err) => { }).catch((err) => {
context.commit('updateListItemFailed', err.message); context.commit('updateItemFailed', err.message);
}); });
}, },
setGroupExtension(context, group) { setGroupExtension(context, group) {
context.commit('updateListItemStarted', group); context.commit('updateItemRequesting', group);
setGroupExtension(group.id, group.extension).then(()=>{ setGroupExtension(group.id, group.extension).then(()=>{
return context.dispatch('listGroups', true); return context.dispatch('listGroups', true);
}).then(() => { }).then(() => {
context.commit('updateListItemSucceeded'); context.commit('updateItemSucceeded');
}).catch((err) => { }).catch((err) => {
context.commit('updateListItemFailed', err.message); context.commit('updateItemFailed', err.message);
}); });
}, },
setGroupHuntPolicy(context, group) { setGroupHuntPolicy(context, group) {
context.commit('updateListItemStarted', group); context.commit('updateItemRequesting', group);
setGroupHuntPolicy(group.id, group.huntPolicy).then(() => { setGroupHuntPolicy(group.id, group.huntPolicy).then(() => {
return context.dispatch('listGroups', true); return context.dispatch('listGroups', true);
}).then(()=>{ }).then(()=>{
context.commit('updateListItemSucceeded'); context.commit('updateItemSucceeded');
}).catch((err) => { }).catch((err) => {
context.commit('updateListItemFailed', err.message); context.commit('updateItemFailed', err.message);
}); });
}, },
setGroupHuntTimeout(context, group) { setGroupHuntTimeout(context, group) {
context.commit('updateListItemStarted', group); context.commit('updateItemRequesting', group);
setGroupHuntTimeout(group.id, group.huntTimeout).then(()=>{ setGroupHuntTimeout(group.id, group.huntTimeout).then(()=>{
return context.dispatch('listGroups', true); return context.dispatch('listGroups', true);
}).then(() => { }).then(() => {
context.commit('updateListItemSucceeded'); context.commit('updateItemSucceeded');
}).catch((err) => { }).catch((err) => {
context.commit('updateListItemFailed', err.message); context.commit('updateItemFailed', err.message);
}); });
}, },
updateAliasNumbers(context, data) { updateAliasNumbers(context, data) {
context.commit('updateListItemStarted', data.group); context.commit('updateItemRequesting', data.item);
Promise.all([ Promise.all([
assignNumbers(data.add, data.group.id), assignNumbers(data.add, data.item.id),
assignNumbers(data.remove, context.getters.pilotId) assignNumbers(data.remove, context.getters.pilotId)
]).then(()=>{ ]).then(()=>{
return context.dispatch('listGroups', true); return context.dispatch('listGroups', true);
}).then(()=>{ }).then(()=>{
context.commit('updateListItemSucceeded'); context.commit('updateItemSucceeded');
}).catch((err)=>{ }).catch((err)=>{
context.commit('updateListItemFailed', err.message); context.commit('updateItemFailed', err.message);
}); });
}, },
updateSeats(context, group) { updateSeats(context, group) {
context.commit('updateListItemStarted', group); context.commit('updateItemRequesting', group);
updateGroupSeats(group.id, group.seats).then(()=>{ updateGroupSeats(group.id, group.seats).then(()=>{
return context.dispatch('listGroups', true); return context.dispatch('listGroups', true);
}).then(() => { }).then(() => {
context.commit('updateListItemSucceeded'); context.commit('updateItemSucceeded');
}).catch((err) => { }).catch((err) => {
context.commit('updateListItemFailed', err.message); context.commit('updateItemFailed', err.message);
});
},
removeGroup(context, group) {
context.commit('removeItemRequesting', group);
removeGroup(group.id).then(()=>{
return context.dispatch('listGroups', true);
}).then(()=>{
context.commit('removeGroup', group);
context.commit('removeItemSucceeded');
}).catch((err)=>{
context.commit('removeItemFailed', err.message);
});
},
listSeats(context, silent) {
return context.dispatch('listGroups', silent);
},
addSeat(context, seat) {
seat.customerId = context.state.pilot.customer_id;
seat.domainId = context.state.pilot.domain_id;
context.commit('addItemRequesting', seat);
addSeat(seat).then(()=>{
return context.dispatch('listGroups', true);
}).then(()=>{
context.commit('addItemSucceeded');
}).catch((err)=>{
context.commit('addItemFailed', err.message);
});
},
setSeatName(context, seat) {
context.commit('updateItemRequesting', seat);
setSeatName(seat.id, seat.name).then(() => {
return context.dispatch('listGroups', true);
}).then(()=>{
context.commit('updateItemSucceeded');
}).catch((err) => {
context.commit('updateItemFailed', err.message);
});
},
setSeatExtension(context, seat) {
context.commit('updateItemRequesting', seat);
setSeatExtension(seat.id, seat.extension).then(()=>{
return context.dispatch('listGroups', true);
}).then(() => {
context.commit('updateItemSucceeded');
}).catch((err) => {
context.commit('updateItemFailed', err.message);
});
},
updateGroups(context, seat) {
context.commit('updateItemRequesting', seat);
updateSeatGroups(seat.id, seat.groups).then(()=>{
return context.dispatch('listGroups', true);
}).then(() => {
context.commit('updateItemSucceeded');
}).catch((err) => {
context.commit('updateItemFailed', err.message);
});
},
removeSeat(context, seat) {
context.commit('removeItemRequesting', seat);
removeSeat(seat.id).then(()=>{
return context.dispatch('listGroups', true);
}).then(()=>{
context.commit('removeItemSucceeded');
}).catch((err)=>{
context.commit('removeItemFailed', err.message);
}); });
} }
} }

@ -1,6 +1,7 @@
'use strict'; 'use strict';
import _ from 'lodash' import _ from 'lodash'
import { RequestState } from '../common'
export default { export default {
groups(state) { groups(state) {
@ -36,19 +37,67 @@ export default {
} }
return aliasNumbers; return aliasNumbers;
}, },
listItemUpdating(state) { isListRequesting(state) {
return state.listItemUpdating; return state.listState === RequestState.requesting;
}, },
listItemUpdateState(state) { listState(state) {
return state.listItemUpdateState; return state.listState;
}, },
listItemUpdateError(state) { listError(state) {
return state.listItemUpdateError; return state.listError;
}, },
listLoadingSilently(state) { listLoadingSilently(state) {
return (state.listLoadingSilently === true); return (state.listLoadingSilently === true);
}, },
pilotId(state) { pilotId(state) {
return state.pilot.id; return state.pilot.id;
},
isAdding(state) {
return state.addState === RequestState.requesting;
},
addState(state) {
return state.addState;
},
addItem(state) {
return state.addItem;
},
addError(state) {
return state.addError;
},
isUpdating(state) {
return state.updateState === RequestState.requesting;
},
updateState(state) {
return state.updateState;
},
updateItem(state) {
return state.updateItem;
},
updateItemId(state, getters) {
if(_.isObject(getters.updateItem)) {
return getters.updateItem.id;
}
return null;
},
updateError(state) {
return state.updateError;
},
isRemoving(state) {
return state.removeState === RequestState.requesting;
},
removeState(state) {
return state.removeState;
},
removeItem(state) {
return state.removeItem;
},
removeItemId(state, getters) {
if(_.isObject(getters.removeItem)) {
return getters.removeItem.id;
}
return null;
},
removeError(state) {
return state.removeError;
} }
} }

@ -1,16 +1,17 @@
'use strict'; 'use strict';
import _ from 'lodash' import _ from 'lodash'
import { ListState, AddState, RemoveState } from '../common' import { RequestState } from '../common'
export default { export default {
listAllRequesting(state, silent) { listRequesting(state, silent) {
state.listAllState = ListState.requesting; state.listState = RequestState.requesting;
state.listError = null;
state.listLoadingSilently = silent; state.listLoadingSilently = silent;
}, },
listAllSucceeded(state, all) { listSucceeded(state, all) {
state.listAllState = ListState.succeeded; state.listState = RequestState.succeeded;
state.listAllError = null; state.listError = null;
state.pilot = all.pilot; state.pilot = all.pilot;
state.groups = {}; state.groups = {};
state.groupsOrdered = []; state.groupsOrdered = [];
@ -55,21 +56,48 @@ export default {
_.reverse(state.groupsOrdered); _.reverse(state.groupsOrdered);
_.reverse(state.seatsOrdered); _.reverse(state.seatsOrdered);
}, },
listAllFailed(state, error) { listFailed(state, error) {
state.listAllState = ListState.failed; state.listState = RequestState.failed;
state.listAllError = error; state.listError = error;
}, },
addGroupRequesting(state){ addItemRequesting(state, item) {
state.addGroupState = AddState.requesting; state.addState = RequestState.requesting;
state.addGroupError = null; state.addError = null;
state.addItem = item;
}, },
addGroupSucceeded(state){ addItemSucceeded(state) {
state.addGroupState = AddState.succeeded; state.addState = RequestState.succeeded;
state.addGroupError = null; state.addError = null;
}, },
addGroupFailed(state, error) { addItemFailed(state, error) {
state.addGroupState = AddState.failed; state.addState = RequestState.failed;
state.addGroupError = error; state.addError = error;
},
updateItemRequesting(state, item) {
state.updateState = RequestState.requesting;
state.updateError = null;
state.updateItem = item;
},
updateItemSucceeded(state) {
state.updateState = RequestState.succeeded;
state.updateError = null;
},
updateItemFailed(state, error) {
state.updateState = RequestState.failed;
state.updateError = error;
},
removeItemRequesting(state, item) {
state.removeState = RequestState.requesting;
state.removeError = null;
state.removeItem = item;
},
removeItemSucceeded(state) {
state.removeState = RequestState.succeeded;
state.removeError = null;
},
removeItemFailed(state, error) {
state.removeState = RequestState.failed;
state.removeError = error;
}, },
removeGroup(state, group) { removeGroup(state, group) {
delete state.groups[group.id]; delete state.groups[group.id];
@ -78,44 +106,5 @@ export default {
delete state.groupsOrdered[index]; delete state.groupsOrdered[index];
} }
}); });
},
addSeatRequesting(state){
state.addSeatState = AddState.requesting;
state.addSeatError = null;
},
addSeatSucceeded(state){
state.addSeatState = AddState.succeeded;
state.addSeatError = null;
},
addSeatFailed(state, error) {
state.addSeatState = AddState.failed;
state.addSeatError = error;
},
removeSeatRequesting(state, seat) {
state.removeSeatState = RemoveState.requesting;
state.removeSeatError = null;
state.removeSeatItem = seat;
},
removeSeatSucceeded(state) {
state.removeSeatState = RemoveState.succeeded;
state.removeSeatError = null;
},
removeSeatFailed(state, message) {
state.removeSeatState = RemoveState.failed;
state.removeSeatError = message;
state.removeSeatItem = null;
},
updateListItemStarted(state, item) {
state.listItemUpdateState = 'requesting';
state.listItemUpdating = item;
},
updateListItemSucceeded(state) {
state.listItemUpdateState = 'succeeded';
state.listItemUpdating = null;
},
updateListItemFailed(state, error) {
state.listItemUpdateState = 'failed';
state.listItemUpdating = null;
state.listItemUpdateError = error;
} }
} }

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import { ListState, AddState, RemoveState } from '../common' import { RequestState } from '../common'
export default { export default {
pilot: null, pilot: null,
@ -10,17 +10,16 @@ export default {
seatsOrdered: [], seatsOrdered: [],
numbers: [], numbers: [],
numbersMap : {}, numbersMap : {},
listAllState: ListState.initiated, listState: RequestState.initiated,
listAllError: null, listError: null,
listLoadingSilently: false, listLoadingSilently: false,
addGroupState: AddState.button, addState: RequestState.initiated,
addGroupError: null, addError: null,
addSeatState: AddState.button, addItem: null,
addSeatError: null, updateState: RequestState.initiated,
removeSeatState: RemoveState.initiated, updateError: null,
removeSeatError: null, updateItem: null,
removeSeatItem: null, removeState: RequestState.initiated,
listItemUpdating: null, removeError: null,
listItemUpdateState: null, removeItem: null
listItemUpdateError: null
} }

Loading…
Cancel
Save