TT#40250 PBXConfig: As a Customer, I want to get notified about invalid input before creating a PBXGroup

Change-Id: Iaf18363545097ffe733034a94daa1e42fb228242
changes/61/22761/4
Hans-Peter Herzog 7 years ago
parent 40e15adff0
commit f867c69d26

@ -157,6 +157,7 @@
separator
sparse
multiline
:highlight="!isMobile"
>
<csc-pbx-device
v-for="device in devices"

@ -1,114 +1,158 @@
<template>
<q-card
class="csc-entity csc-pbx-group shadow-1"
>
<q-card-title class="csc-entity-title">
<q-item class="csc-list-item csc-pbx-group">
<q-item-side
v-if="!expanded"
>
<q-icon
size="32px"
name="group"
color="secondary"
size="24px"
/>
<span class="csc-entity-title-text">
{{ entityTitle }}
</span>
<q-chip
</q-item-side>
<q-item-main>
<q-item-tile
v-if="!expanded"
pointing="left"
color="primary"
class="gt-md cursor-pointer"
class="csc-item-title"
label
>
{{ $t('pbxConfig.extension') }}: <span class="csc-important">{{ group.pbx_extension }}</span>
</q-chip>
<q-btn
:icon="titleIcon"
:small="isMobile"
color="primary"
slot="right"
flat
@click="toggleMain()"
/>
<q-btn
icon="delete"
:small="isMobile"
color="negative"
slot="right"
flat
@click="remove()"
/>
</q-card-title>
<q-card-main
v-if="expanded"
class="transition-generic"
{{ group.display_name }}
</q-item-tile>
<q-item-tile
v-if="!expanded"
class="csc-item-subtitle"
sublabel
>
<div>
<span class="csc-item-label">{{ $t('pbxConfig.extension') }}:</span>
<span class="csc-item-value">{{ group.pbx_extension }}</span>
</div>
</q-item-tile>
<q-item-tile
v-if="!expanded"
class="csc-item-subtitle"
sublabel
>
<div
v-if="!hasSeats"
class="csc-form-info"
>
<q-icon name="info" color="info" size="24px"/>
<span class="csc-info-text">{{ $t('pbxConfig.noSeatAssigned') }}</span>
</div>
<div
class="csc-item-field"
v-if="hasSeats"
>
<span
class="csc-item-label"
>{{ $t('pbxConfig.seats') }}:
</span>
<span
class="csc-item-value"
v-for="seat in group.seats"
>{{ seat.display_name }}
</span>
</div>
</q-item-tile>
<q-item-tile
class="csc-list-item-main"
v-if="expanded"
>
<q-field :label="$t('pbxConfig.groupName')">
<q-input
v-model="changes.name"
:after="nameButtons"
@keyup.enter="saveName"
/>
</q-field>
<q-field :label="$t('pbxConfig.extension')">
<q-input
v-model="changes.extension"
type="number"
:after="extensionButtons"
@keyup.enter="saveExtension"
/>
</q-field>
<q-field :label="$t('pbxConfig.huntPolicy')">
<q-select
v-model="changes.huntPolicy"
:options="huntPolicyOptions"
radio
@change="huntPolicyChanged"
/>
</q-field>
<q-field :label="$t('pbxConfig.huntTimeout')">
<q-input
v-model="changes.huntTimeout"
type="number"
suffix="seconds"
:after="huntTimeoutButtons"
:min="0"
@keyup.enter="saveHuntTimeout"
/>
</q-field>
<q-field :label="$t('pbxConfig.primaryNumber')">
<q-input
v-model="primaryNumber"
readonly
disable
/>
</q-field>
<q-field :label="$t('pbxConfig.aliasNumbers')">
<q-select
ref="aliasNumbers"
v-model="changes.aliasNumbers"
:options="aliasNumberOptions"
multiple
chips
clearable
:after="aliasNumberButtons"
/>
</q-field>
<q-field :label="$t('pbxConfig.seats')">
<q-select
v-model="changes.seats"
:options="seatOptions"
multiple
chips
clearable
:after="seatButtons"
/>
</q-field>
</q-item-tile>
</q-item-main>
<q-item-side
right
class="csc-item-buttons"
>
<q-field :label="$t('pbxConfig.groupName')">
<q-input
v-model="changes.name"
:after="nameButtons"
@keyup.enter="saveName"
/>
</q-field>
<q-field :label="$t('pbxConfig.extension')">
<q-input
v-model="changes.extension"
type="number"
:after="extensionButtons"
@keyup.enter="saveExtension"
/>
</q-field>
<q-field :label="$t('pbxConfig.huntPolicy')">
<q-select
v-model="changes.huntPolicy"
:options="huntPolicyOptions"
radio
@change="huntPolicyChanged"
/>
</q-field>
<q-field :label="$t('pbxConfig.huntTimeout')">
<q-input
v-model="changes.huntTimeout"
type="number"
suffix="seconds"
:after="huntTimeoutButtons"
:min="0"
@keyup.enter="saveHuntTimeout"
/>
</q-field>
<q-field :label="$t('pbxConfig.primaryNumber')">
<q-input
v-model="primaryNumber"
readonly
disable
/>
</q-field>
<q-field :label="$t('pbxConfig.aliasNumbers')">
<q-select
ref="aliasNumbers"
v-model="changes.aliasNumbers"
:options="aliasNumberOptions"
multiple
chips
clearable
:after="aliasNumberButtons"
/>
</q-field>
<q-field :label="$t('pbxConfig.seats')">
<q-select
v-model="changes.seats"
:options="seatOptions"
multiple
chips
clearable
:after="seatButtons"
/>
</q-field>
</q-card-main>
<q-item-tile>
<div class="csc-item-button">
<q-icon
size="26px"
:name="titleIcon"
color="primary"
slot="right"
@click="toggleMain()"
/>
</div>
<div class="csc-item-button">
<q-icon
size="26px"
name="delete"
color="negative"
slot="right"
@click="remove()"
/>
</div>
</q-item-tile>
</q-item-side>
<q-inner-loading :visible="isLoading">
<q-spinner-mat
size="60px"
color="primary"
/>
</q-inner-loading>
</q-card>
</q-item>
</template>
<script>
@ -128,7 +172,12 @@
QInnerLoading,
QSpinnerMat,
QTransition,
Platform
Platform,
QItem,
QItemSide,
QItemMain,
QItemTile,
QAlert
} from 'quasar-framework'
export default {
name: 'csc-pbx-group',
@ -158,7 +207,12 @@
QBtn,
QInnerLoading,
QSpinnerMat,
QTransition
QTransition,
QItem,
QItemSide,
QItemMain,
QItemTile,
QAlert
},
computed: {
entityTitle() {
@ -366,6 +420,9 @@
);
}
return buttons;
},
hasSeats() {
return _.isArray(_.get(this.group, 'seats')) && this.group.seats.length > 0;
}
},
methods: {

@ -1,52 +1,127 @@
<template>
<q-card class="csc-pbx-group-add-form shadow-1">
<q-card-title>
<q-icon name="add" color="primary" size="22px"/>
<span>{{ $t('pbxConfig.addGroup') }}</span>
</q-card-title>
<q-card-main>
<q-field>
<q-input :disabled="loading" :readonly="loading" v-model="data.name" autofocus
:float-label="$t('pbxConfig.groupName')" clearable />
</q-field>
<q-field>
<q-input :disabled="loading" :readonly="loading" type="number" v-model="data.extension"
clearable :min="1" :max="1000000" :float-label="$t('pbxConfig.extension')" />
</q-field>
<q-field>
<q-select :disabled="loading" :readonly="loading" v-model="data.huntPolicy"
:float-label="$t('pbxConfig.huntPolicy')" :options="huntPolicyOptions" radio />
</q-field>
<q-field>
<q-input :disabled="loading" :readonly="loading" type="number" v-model="data.huntTimeout" clearable
:float-label="$t('pbxConfig.huntTimeout')" suffix="seconds" :min="1" :max="3600" />
</q-field>
<q-field>
<q-select :disabled="loading" :readonly="loading" v-model="data.aliasNumbers" multiple chips clearable
:float-label="$t('pbxConfig.aliasNumbers')" :options="aliasNumberOptions" />
</q-field>
<q-field>
<q-select :disabled="loading" :readonly="loading" v-model="data.seats" multiple chips clearable
:float-label="$t('pbxConfig.seats')" :options="seatOptions" />
</q-field>
</q-card-main>
<q-card-separator/>
<q-card-actions align="center">
<q-btn v-if="!loading" flat color="secondary" icon="clear"
@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>
<div class="csc-form csc-pbx-seat-add-form">
<q-field :error-label="groupNameErrorMessage">
<q-input
@input="$v.data.name.$touch"
:error="$v.data.name.$error"
:disabled="loading"
:readonly="loading"
v-model="data.name"
autofocus
:float-label="$t('pbxConfig.groupName')"
clearable
/>
</q-field>
<q-field :error-label="extensionErrorMessage">
<q-input
@input="$v.data.extension.$touch"
:error="$v.data.extension.$error"
:disabled="loading"
:readonly="loading"
v-model="data.extension"
:float-label="$t('pbxConfig.extension')"
clearable
/>
</q-field>
<q-field>
<q-select
:disabled="loading"
:readonly="loading"
v-model="data.huntPolicy"
:float-label="$t('pbxConfig.huntPolicy')"
:options="huntPolicyOptions"
radio
/>
</q-field>
<q-field :error-label="huntTimeoutErrorMessage">
<q-input
@input="$v.data.huntTimeout.$touch"
:error="$v.data.huntTimeout.$error"
:disabled="loading"
:readonly="loading"
type="number"
v-model="data.huntTimeout"
clearable
:float-label="$t('pbxConfig.huntTimeout')"
suffix="seconds"
:min="1"
:max="3600"
/>
</q-field>
<q-field>
<q-select
:disabled="loading"
:readonly="loading"
v-model="data.aliasNumbers"
multiple
chips
clearable
:float-label="$t('pbxConfig.aliasNumbers')"
:options="aliasNumberOptions"
/>
</q-field>
<q-field>
<q-select
:disabled="loading"
:readonly="loading"
v-model="data.seats"
multiple
chips
clearable
:float-label="$t('pbxConfig.seats')"
:options="seatOptions"
/>
</q-field>
<div class="csc-form-actions row justify-center">
<q-btn
v-if="!loading"
flat
color="secondary"
icon="clear"
@click="cancel()"
>
{{ $t('buttons.cancel') }}
</q-btn>
<q-btn
v-if="!loading"
:disabled="$v.data.$invalid"
flat
color="primary"
icon="group"
@click="save()"
>
{{ $t('pbxConfig.createGroup') }}
</q-btn>
</div>
<q-inner-loading :visible="loading">
<q-spinner-mat size="60px" color="primary"></q-spinner-mat>
<q-spinner-mat size="60px" color="primary" />
</q-inner-loading>
</q-card>
</div>
</template>
<script>
import { QCard, QCardTitle, QCardMain, QCardActions, QCardSeparator, QBtn,
QInnerLoading, QSpinnerMat, QField, QInput, QSelect, QIcon } from 'quasar-framework'
import {
required,
minValue,
maxValue,
maxLength,
numeric
} from 'vuelidate/lib/validators'
import {
QCard,
QCardTitle,
QCardMain,
QCardActions,
QCardSeparator,
QBtn,
QInnerLoading,
QSpinnerMat,
QField,
QInput,
QSelect,
QIcon
} from 'quasar-framework'
export default {
name: 'csc-pbx-group-add-form',
@ -57,14 +132,82 @@
'loading',
],
components: {
QCard, QCardTitle, QCardMain, QCardActions, QCardSeparator, QBtn,
QInnerLoading, QSpinnerMat, QField, QInput, QSelect, QIcon
QCard,
QCardTitle,
QCardMain,
QCardActions,
QCardSeparator,
QBtn,
QInnerLoading,
QSpinnerMat,
QField,
QInput,
QSelect,
QIcon
},
validations: {
data: {
name: {
required,
maxLength: maxLength(64)
},
extension: {
required,
maxLength: maxLength(64),
numeric
},
huntTimeout: {
required,
minValue: minValue(1),
maxValue: maxValue(3600)
}
}
},
data () {
return {
data: this.getDefaults()
}
},
computed: {
groupNameErrorMessage() {
if (!this.$v.data.name.required) {
return this.$t('pbxConfig.requiredGroupName');
}
else if (!this.$v.data.name.maxLength) {
return this.$t('pbxConfig.groupNameMaxLength', {
maxLength: this.$v.data.name.$params.maxLength.max
});
}
},
extensionErrorMessage() {
if (!this.$v.data.extension.required) {
return this.$t('pbxConfig.requiredExtension');
}
else if (!this.$v.data.name.maxLength) {
return this.$t('pbxConfig.extensionMaxLength', {
maxLength: this.$v.data.extension.$params.maxLength.max
});
}
else if (!this.$v.data.name.numeric) {
return this.$t('pbxConfig.extensionAlphaNum');
}
},
huntTimeoutErrorMessage() {
if (!this.$v.data.huntTimeout.required) {
return this.$t('pbxConfig.requiredHuntTimeout');
}
else if (!this.$v.data.huntTimeout.minValue) {
return this.$t('pbxConfig.huntTimeoutMinValue', {
minValue: this.$v.data.huntTimeout.$params.minValue.min
});
}
else if (!this.$v.data.huntTimeout.maxValue) {
return this.$t('pbxConfig.huntTimeoutMaxValue', {
maxValue: this.$v.data.huntTimeout.$params.maxValue.max
});
}
}
},
methods: {
getDefaults() {
return {
@ -84,6 +227,7 @@
},
reset() {
this.data = this.getDefaults();
this.$v.$reset();
}
}
}

@ -1,15 +1,22 @@
<template>
<csc-page :title="$t('pbxConfig.groupsTitle')">
<csc-pbx-group-add-form
<csc-page
class="csc-list-page"
>
<div
v-show="addFormEnabled"
ref="addForm"
@save="addGroup"
@cancel="disableAddForm"
:loading="isAdding"
:alias-number-options="aliasNumberOptions"
:seat-options="seatOptions"
:hunt-policy-options="huntPolicyOptions"
/>
class="row justify-center margin-sm"
>
<csc-pbx-group-add-form
class="col-xs-12 col-md-6"
ref="addForm"
@save="addGroup"
@cancel="disableAddForm"
:loading="isAdding"
:alias-number-options="aliasNumberOptions"
:seat-options="seatOptions"
:hunt-policy-options="huntPolicyOptions"
/>
</div>
<div
v-show="!addFormEnabled"
class="row justify-center"
@ -42,22 +49,31 @@
@change="changePage"
/>
</div>
<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"
:loading="isItemLoading(group.id)"
@save-name="setGroupName"
@save-extension="setGroupExtension"
@save-hunt-policy="setGroupHuntPolicy"
@save-hunt-timeout="setGroupHuntTimeout"
@save-alias-numbers="updateAliasNumbers"
@save-seats="updateSeats"
/>
<q-list
class=""
no-border
separator
sparse
multiline
:highlight="!isMobile"
>
<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"
:loading="isItemLoading(group.id)"
@save-name="setGroupName"
@save-extension="setGroupExtension"
@save-hunt-policy="setGroupHuntPolicy"
@save-hunt-timeout="setGroupHuntTimeout"
@save-alias-numbers="updateAliasNumbers"
@save-seats="updateSeats"
/>
</q-list>
<div
v-if="groups.length === 0 && !isListRequesting"
class="row justify-center csc-no-entities"
@ -95,7 +111,8 @@
QSpinnerDots,
QSpinnerMat,
Dialog,
QPagination
QPagination,
Platform
} from 'quasar-framework'
export default {
@ -194,7 +211,10 @@
'lastUpdatedField',
'updateAliasNumbersState',
'updateGroupsAndSeatsState'
])
]),
isMobile() {
return Platform.is.mobile;
},
},
watch: {
addState(state) {

@ -1,5 +1,4 @@
<template>
<q-item class="csc-list-item csc-pbx-seat">
<q-item-side
v-if="!expanded"
@ -41,6 +40,7 @@
<span class="csc-info-text">{{ $t('pbxConfig.noGroupAssigned') }}</span>
</div>
<div
class="csc-item-field"
v-if="hasGroups">
<span
class="csc-item-label">
@ -134,97 +134,6 @@
/>
</q-inner-loading>
</q-item>
<!--<q-card class="csc-entity csc-pbx-seat shadow-1">-->
<!--<q-card-title class="csc-entity-title">-->
<!--<q-icon-->
<!--name="person"-->
<!--color="secondary"-->
<!--size="24px"-->
<!--/>-->
<!--<span class="csc-entity-title-text">-->
<!--{{ entityTitle }}-->
<!--</span>-->
<!--<q-chip-->
<!--v-if="!expanded"-->
<!--pointing="left"-->
<!--color="primary"-->
<!--class="gt-md"-->
<!--&gt;-->
<!--{{ $t('pbxConfig.extension') }}: <span class="csc-important">{{ seat.pbx_extension }}</span>-->
<!--</q-chip>-->
<!--<q-btn-->
<!--:icon="titleIcon"-->
<!--:small="isMobile"-->
<!--color="primary"-->
<!--slot="right"-->
<!--flat-->
<!--@click="toggleMain()"-->
<!--/>-->
<!--<q-btn-->
<!--icon="delete"-->
<!--:small="isMobile"-->
<!--color="negative"-->
<!--slot="right"-->
<!--flat-->
<!--@click="remove()"-->
<!--/>-->
<!--</q-card-title>-->
<!--<q-card-main-->
<!--v-if="expanded"-->
<!--class="transition-generic"-->
<!--&gt;-->
<!--<q-field :label="$t('pbxConfig.seatName')">-->
<!--<q-input-->
<!--v-model="changes.name"-->
<!--:after="nameButtons"-->
<!--@keyup.enter="saveName"-->
<!--/>-->
<!--</q-field>-->
<!--<q-field :label="$t('pbxConfig.extension')">-->
<!--<q-input-->
<!--v-model="changes.extension"-->
<!--type="number"-->
<!--:after="extensionButtons"-->
<!--@keyup.enter="saveExtension"-->
<!--/>-->
<!--</q-field>-->
<!--<q-field :label="$t('pbxConfig.primaryNumber')">-->
<!--<q-input-->
<!--v-model="primaryNumber"-->
<!--readonly-->
<!--disable-->
<!--/>-->
<!--</q-field>-->
<!--<q-field :label="$t('pbxConfig.aliasNumbers')">-->
<!--<q-select-->
<!--ref="aliasNumbers"-->
<!--v-model="changes.aliasNumbers"-->
<!--:options="aliasNumberOptions"-->
<!--multiple-->
<!--chips-->
<!--clearable-->
<!--:after="aliasNumberButtons"-->
<!--/>-->
<!--</q-field>-->
<!--<q-field :label="$t('pbxConfig.groups')">-->
<!--<q-select-->
<!--v-model="changes.groups"-->
<!--:options="groupOptions"-->
<!--multiple-->
<!--chips-->
<!--clearable-->
<!--:after="groupButtons"-->
<!--/>-->
<!--</q-field>-->
<!--</q-card-main>-->
<!--<q-inner-loading :visible="isLoading">-->
<!--<q-spinner-mat-->
<!--size="60px"-->
<!--color="primary"-->
<!--/>-->
<!--</q-inner-loading>-->
<!--</q-card>-->
</template>
<script>

@ -16,11 +16,11 @@
</q-btn>
</div>
<div
class="row justify-center"
class="row justify-center margin-sm"
v-show="addFormEnabled"
>
<csc-pbx-seat-add-form
class="col-xs-12 col-md-6"
v-show="addFormEnabled"
ref="addForm"
:alias-number-options="aliasNumberOptions"
:group-options="groupOptions"

@ -314,9 +314,16 @@
"noStationName": "Could not find any device with station name matching the filter criteria",
"noGroups": "No groups created yet",
"noSeats": "No seats created yet",
"requiredGroupName": "Group name is required",
"groupNameMaxLength": "Group name must have at most {maxLength} letters",
"requiredExtension": "Extension is required",
"extensionMinValue": "Extension must be at least {minValue}",
"extensionMaxValue": "Extension must be maximum {maxValue}",
"requiredHuntTimeout": "Hunt timeout is required",
"huntTimeoutMinValue": "Hunt timeout must be at least {minValue} second",
"huntTimeoutMaxValue": "Hunt timeout must be maximum {maxValue} seconds",
"requiredSeatName": "Seat name is required",
"seatNameMaxLength": "Seat name must have at most {maxLength} letters",
"requiredExtension": "Extension is required",
"extensionMaxLength": "Extension must have at most {maxLength} letters",
"extensionAlphaNum": "Only numeric characters are allowed",
"toasts": {
@ -357,7 +364,9 @@
"resetFilters": "Reset filters",
"closeFilters": "Close filters",
"createSeat": "Create seat",
"noGroupAssigned": "Not assigned to any group"
"noGroupAssigned": "Not assigned to any group",
"noSeatAssigned": "No seats assigned",
"createGroup": "Create group"
},
"callBlocking": {
"privacyEnabledToast": "Your number is hidden to the callee",

@ -1,6 +1,15 @@
@import 'quasar.variables'
.csc-item-field
.csc-item-value
display inline-block
margin-right 4px
.csc-item-value::after
content ','
.csc-item-value:last-child:after
content ''
.csc-list-item
position relative
.csc-list-item-main

Loading…
Cancel
Save