MT#54861 Configure sip username, display-names and web username independently in CSC

Change-Id: I7f0b8543a610c930f55b18a4ce3c96d136c3f49a
pull/27/merge
Georges Francisco 3 years ago committed by Hugo Zigha
parent 9311936377
commit 3f298e008e

@ -5,6 +5,7 @@ import {
getSubscriberAndPreferences, getSubscriberAndPreferences,
getSubscribers, getSubscribers,
setDisplayName, setDisplayName,
setWebUsername,
setPbxExtension, setPbxExtension,
setPbxWebPassword, setPbxWebPassword,
setPbxGroupIds, setPbxGroupIds,
@ -134,9 +135,10 @@ export function createSeat (seat) {
let subscriberId let subscriberId
Promise.resolve().then(() => { Promise.resolve().then(() => {
return createSubscriber({ return createSubscriber({
username: seat.name.trim().toLowerCase().replace(/\s+/g, '-'), username: seat.sipUsername.trim(),
display_name: seat.displayName.trim(),
webusername: seat.webUsername.trim(),
password: seat.sipPassword ? seat.sipPassword : createId(), password: seat.sipPassword ? seat.sipPassword : createId(),
display_name: seat.name,
webpassword: seat.webPassword.length > 0 ? seat.webPassword : null, webpassword: seat.webPassword.length > 0 ? seat.webPassword : null,
is_pbx_group: false, is_pbx_group: false,
pbx_extension: seat.extension, pbx_extension: seat.extension,
@ -173,12 +175,34 @@ export function removeSeat (id) {
/** /**
* @param options * @param options
* @param options.seatId * @param options.seatId
* @param options.seatName * @param options.displayName
*/ */
export function setSeatName (options) { export function setSeatDisplayName (options) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
Promise.resolve().then(() => { Promise.resolve().then(() => {
return setDisplayName(options.seatId, options.seatName) return setDisplayName(options.seatId, options.displayName)
}).then(() => {
return getSubscriberAndPreferences(options.seatId)
}).then((result) => {
resolve({
seat: result.subscriber,
preferences: result.preferences
})
}).catch((err) => {
reject(err)
})
})
}
/**
* @param options
* @param options.seatId
* @param options.webUsername
*/
export function setSeatWebUsername (options) {
return new Promise((resolve, reject) => {
Promise.resolve().then(() => {
return setWebUsername(options.seatId, options.webUsername)
}).then(() => { }).then(() => {
return getSubscriberAndPreferences(options.seatId) return getSubscriberAndPreferences(options.seatId)
}).then((result) => { }).then((result) => {

@ -297,6 +297,10 @@ export function setDisplayName (id, displayName) {
return setField(id, 'display_name', displayName) return setField(id, 'display_name', displayName)
} }
export function setWebUsername (id, webUsername) {
return setField(id, 'webusername', webUsername)
}
export function setPbxExtension (id, pbxExtension) { export function setPbxExtension (id, pbxExtension) {
return setField(id, 'pbx_extension', pbxExtension) return setField(id, 'pbx_extension', pbxExtension)
} }

@ -7,17 +7,17 @@
class="col-xs-12 col-lg-3" class="col-xs-12 col-lg-3"
> >
<csc-input <csc-input
v-model="data.name" v-model="data.displayName"
clearable clearable
autofocus autofocus
dense dense
hide-bottom-space hide-bottom-space
:error="$v.data.name.$error" :error="$v.data.displayName.$error"
:error-message="seatNameErrorMessage" :error-message="seatDisplayNameErrorMessage"
:disable="loading" :disable="loading"
:readonly="loading" :readonly="loading"
:label="$t('Name')" :label="$t('Display Name')"
@input="$v.data.name.$touch" @input="$v.data.displayName.$touch"
> >
<template <template
v-slot:prepend v-slot:prepend
@ -49,25 +49,6 @@
/> />
</template> </template>
</csc-input> </csc-input>
<csc-input-password-retype
v-model="data.password"
:password-label="$t('Web Password')"
:password-confirm-label="$t('Web Password confirm')"
:disable="loading"
hide-bottom-space
dense
/>
<csc-input-password-retype
v-model="data.sipPassword"
:password-label="$t('SIP Password')"
:password-confirm-label="$t('SIP Password confirm')"
:disable="loading"
dense
/>
</div>
<div
class="col-xs-12 col-lg-3"
>
<q-select <q-select
v-model="data.aliasNumbers" v-model="data.aliasNumbers"
clearable clearable
@ -129,6 +110,65 @@
dense dense
/> />
</div> </div>
<div
class="col-xs-12 col-lg-3"
>
<csc-input
v-model="data.webUsername"
clearable
dense
hide-bottom-space
:error="$v.data.webUsername.$error"
:error-message="seatWebUsernameErrorMessage"
:disable="loading"
:readonly="loading"
:label="$t('Web Username')"
@input="$v.data.webUsername.$touch"
>
<template
v-slot:prepend
>
<q-icon
name="person"
/>
</template>
</csc-input>
<csc-input-password-retype
v-model="data.password"
:password-label="$t('Web Password')"
:password-confirm-label="$t('Web Password confirm')"
:disable="loading"
hide-bottom-space
dense
/>
<csc-input
v-model="data.sipUsername"
clearable
dense
hide-bottom-space
:error="$v.data.sipUsername.$error"
:error-message="seatSipUsernameErrorMessage"
:disable="loading"
:readonly="loading"
:label="$t('SIP Username')"
@input="$v.data.sipUsername.$touch"
>
<template
v-slot:prepend
>
<q-icon
name="person"
/>
</template>
</csc-input>
<csc-input-password-retype
v-model="data.sipPassword"
:password-label="$t('SIP Password')"
:password-confirm-label="$t('SIP Password confirm')"
:disable="loading"
dense
/>
</div>
</div> </div>
<div <div
class="row justify-center" class="row justify-center"
@ -193,7 +233,18 @@ export default {
}, },
validations: { validations: {
data: { data: {
name: { displayName: {
required,
maxLength: maxLength(64)
},
sipUsername: {
required,
maxLength: maxLength(64),
noWhiteSpace: (value) => {
return new RegExp(/\s/).test(value) === false
}
},
webUsername: {
required, required,
maxLength: maxLength(64) maxLength: maxLength(64)
}, },
@ -234,15 +285,48 @@ export default {
'getMinAllowedExtension', 'getMinAllowedExtension',
'getMaxAllowedExtension' 'getMaxAllowedExtension'
]), ]),
seatNameErrorMessage () { seatDisplayNameErrorMessage () {
if (!this.$v.data.name.required) { if (!this.$v.data.displayName.required) {
return this.$t('{field} is required', {
field: this.$t('Seat Display Name')
})
} else if (!this.$v.data.displayName.maxLength) {
return this.$t('{field} must have at most {maxLength} letters', {
field: this.$t('Seat Display Name'),
maxLength: this.$v.data.displayName.$params.maxLength.max
})
} else {
return ''
}
},
seatWebUsernameErrorMessage () {
if (!this.$v.data.webUsername.required) {
return this.$t('{field} is required', { return this.$t('{field} is required', {
field: this.$t('Seat name') field: this.$t('Seat Web Username')
}) })
} else if (!this.$v.data.name.maxLength) { } else if (!this.$v.data.webUsername.maxLength) {
return this.$t('{field} must have at most {maxLength} letters', { return this.$t('{field} must have at most {maxLength} letters', {
field: this.$t('Seat name'), field: this.$t('Seat Web Username'),
maxLength: this.$v.data.name.$params.maxLength.max maxLength: this.$v.data.webUsername.$params.maxLength.max
})
} else {
return ''
}
},
seatSipUsernameErrorMessage () {
if (!this.$v.data.sipUsername.required) {
return this.$t('SIP Username is required', {
field: this.$t('Seat SIP Username')
})
} else if (!this.$v.data.sipUsername.maxLength) {
return this.$t('SIP Username must have at most {maxLength} letters', {
field: this.$t('Seat SIP Username'),
maxLength: this.$v.data.sipUsername.$params.maxLength.max
})
} else if (!this.$v.data.sipUsername.noWhiteSpace) {
return this.$t('SIP Username must not contain any space character', {
field: this.$t('Seat SIP Username'),
maxLength: this.$v.data.sipUsername.$params.maxLength.max
}) })
} else { } else {
return '' return ''
@ -291,7 +375,9 @@ export default {
methods: { methods: {
getDefaults () { getDefaults () {
return { return {
name: '', displayName: '',
sipUsername: '',
webUsername: '',
extension: '', extension: '',
password: { password: {
password: '', password: '',
@ -312,7 +398,9 @@ export default {
}, },
save () { save () {
this.$emit('save', { this.$emit('save', {
name: this.data.name, displayName: this.data.displayName,
sipUsername: this.data.sipUsername,
webUsername: this.data.webUsername,
extension: this.data.extension, extension: this.data.extension,
webPassword: this.data.password.password, webPassword: this.data.password.password,
sipPassword: this.data.sipPassword.password, sipPassword: this.data.sipPassword.password,

@ -53,6 +53,7 @@
"Block outgoing": "Block outgoing", "Block outgoing": "Block outgoing",
"Busy Greeting": "Busy Greeting", "Busy Greeting": "Busy Greeting",
"Busy Lamp Field": "Busy Lamp Field", "Busy Lamp Field": "Busy Lamp Field",
"CLI": "CLI",
"Call": "Call", "Call": "Call",
"Call Blocking": "Call Blocking", "Call Blocking": "Call Blocking",
"Call Forwarding": "Call Forwarding", "Call Forwarding": "Call Forwarding",
@ -138,6 +139,7 @@
"Destinations": "Destinations", "Destinations": "Destinations",
"Devices": "Devices", "Devices": "Devices",
"Disable": "Disable", "Disable": "Disable",
"Display Name": "Display Name",
"Do not ring primary number": "Do not ring primary number", "Do not ring primary number": "Do not ring primary number",
"Download fax": "Download fax", "Download fax": "Download fax",
"Download voicemail": "Download voicemail", "Download voicemail": "Download voicemail",
@ -362,6 +364,10 @@
"SIP Password": "SIP Password", "SIP Password": "SIP Password",
"SIP Password confirm": "SIP Password confirm", "SIP Password confirm": "SIP Password confirm",
"SIP URI": "SIP URI", "SIP URI": "SIP URI",
"SIP Username": "SIP Username",
"SIP Username is required": "SIP Username is required",
"SIP Username must have at most {maxLength} letters": "SIP Username must have at most {maxLength} letters",
"SIP Username must not contain any space character": "SIP Username must not contain any space character",
"Sa": "Sa", "Sa": "Sa",
"Same time for selected days": "Same time for selected days", "Same time for selected days": "Same time for selected days",
"Saturday": "Saturday", "Saturday": "Saturday",
@ -369,6 +375,10 @@
"Save new password": "Save new password", "Save new password": "Save new password",
"Scan to login sip:phone": "Scan to login sip:phone", "Scan to login sip:phone": "Scan to login sip:phone",
"Seat": "Seat", "Seat": "Seat",
"Seat Display Name": "Seat Display Name",
"Seat SIP Username": "Seat SIP Username",
"Seat Web Username": "Seat Web Username",
"Seat displayName": "Seat displayName",
"Seat name": "Seat name", "Seat name": "Seat name",
"Seats": "Seats", "Seats": "Seats",
"Secret Key (empty=disabled)": "Secret Key (empty=disabled)", "Secret Key (empty=disabled)": "Secret Key (empty=disabled)",
@ -463,6 +473,7 @@
"We": "We", "We": "We",
"Web Password": "Web Password", "Web Password": "Web Password",
"Web Password confirm": "Web Password confirm", "Web Password confirm": "Web Password confirm",
"Web Username": "Web Username",
"WebSocket connection to kamailio lb failed with code {code}": "WebSocket connection to kamailio lb failed with code {code}", "WebSocket connection to kamailio lb failed with code {code}": "WebSocket connection to kamailio lb failed with code {code}",
"Wednesday": "Wednesday", "Wednesday": "Wednesday",
"Weekly": "Weekly", "Weekly": "Weekly",
@ -506,6 +517,7 @@
"busy": "busy", "busy": "busy",
"call from ...": "call from ...", "call from ...": "call from ...",
"call not from ...": "call not from ...", "call not from ...": "call not from ...",
"cli of the seat": "cli of the seat",
"condition": "condition", "condition": "condition",
"data error": "data error", "data error": "data error",
"date is": "date is", "date is": "date is",

@ -42,21 +42,52 @@
@change-password="changeWebPassword({ password: $event.password })" @change-password="changeWebPassword({ password: $event.password })"
/> />
<q-input <q-input
v-model="changes.name" v-model="changes.displayName"
:label="$t('Name')" :label="$t('Display Name')"
:disable="isLoading" :disable="isLoading"
:error="$v.changes.displayName.$error"
:error-message="seatDisplayNameErrorMessage"
@input="$v.changes.displayName.$touch"
@keyup.enter="save" @keyup.enter="save"
> >
<template <template
v-if="hasDisplayNameChanged"
v-slot:append v-slot:append
> >
<csc-input-button-save <csc-input-button-save
v-if="hasNameChanged" v-if="!$v.changes.displayName.$error"
@click.stop="save" @click.stop="save"
/> />
<csc-input-button-reset <csc-input-button-reset
v-if="hasNameChanged" @click.stop="resetDisplayName"
@click.stop="resetName" />
</template>
</q-input>
<q-input
readonly
disable
:label="$t('SIP Username')"
:value="changes.sipUsername"
/>
<q-input
v-model="changes.webUsername"
:label="$t('Web Username')"
:disable="isLoading"
:error="$v.changes.webUsername.$error"
:error-message="seatWebUsernameErrorMessage"
@input="$v.changes.webUsername.$touch"
@keyup.enter="save"
>
<template
v-if="hasWebUsernameChanged"
v-slot:append
>
<csc-input-button-save
v-if="!$v.changes.webUsername.$error"
@click.stop="save"
/>
<csc-input-button-reset
@click.stop="resetWebUsername"
/> />
</template> </template>
</q-input> </q-input>
@ -72,14 +103,14 @@
@input="$v.changes.extension.$touch" @input="$v.changes.extension.$touch"
> >
<template <template
v-if="hasExtensionChanged"
v-slot:append v-slot:append
> >
<csc-input-button-save <csc-input-button-save
v-if="hasExtensionChanged" v-if="!$v.changes.webUsername.$error"
@click.stop="save" @click.stop="save"
/> />
<csc-input-button-reset <csc-input-button-reset
v-if="hasExtensionChanged"
@click.stop="resetExtension" @click.stop="resetExtension"
/> />
</template> </template>
@ -227,9 +258,13 @@ import CscInputButtonSave from 'components/form/CscInputButtonSave'
import CscInputButtonReset from 'components/form/CscInputButtonReset' import CscInputButtonReset from 'components/form/CscInputButtonReset'
import CscChangePasswordDialog from 'src/components/CscChangePasswordDialog' import CscChangePasswordDialog from 'src/components/CscChangePasswordDialog'
import CscPageSticky from 'src/components/CscPageSticky' import CscPageSticky from 'src/components/CscPageSticky'
import { between } from 'vuelidate/lib/validators'
import { inRange } from 'src/helpers/validation' import { inRange } from 'src/helpers/validation'
import numberFilter from '../filters/number' import numberFilter from '../filters/number'
import {
required,
maxLength,
between
} from 'vuelidate/lib/validators'
export default { export default {
name: 'CscPagePbxSeatDetails', name: 'CscPagePbxSeatDetails',
components: { components: {
@ -254,6 +289,14 @@ export default {
isInRange: function (value) { isInRange: function (value) {
return inRange(value, this.getMinAllowedExtension, this.getMaxAllowedExtension, between) return inRange(value, this.getMinAllowedExtension, this.getMaxAllowedExtension, between)
} }
},
displayName: {
required,
maxLength: maxLength(64)
},
webUsername: {
required,
maxLength: maxLength(64)
} }
} }
}, },
@ -283,8 +326,11 @@ export default {
getPrimaryNumber () { getPrimaryNumber () {
return numberFilter(this.seatSelected.primary_number) return numberFilter(this.seatSelected.primary_number)
}, },
hasNameChanged () { hasDisplayNameChanged () {
return this.changes.name !== this.seatSelected.display_name return this.changes.displayName !== this.seatSelected.display_name
},
hasWebUsernameChanged () {
return this.changes.webUsername !== this.seatSelected.webusername
}, },
hasExtensionChanged () { hasExtensionChanged () {
return this.changes.extension !== this.seatSelected.pbx_extension return this.changes.extension !== this.seatSelected.pbx_extension
@ -308,6 +354,34 @@ export default {
return '' return ''
} }
}, },
seatDisplayNameErrorMessage () {
if (!this.$v.changes.displayName.required) {
return this.$t('{field} is required', {
field: this.$t('Seat Display Name')
})
} else if (!this.$v.changes.displayName.maxLength) {
return this.$t('{field} must have at most {maxLength} letters', {
field: this.$t('Seat Display Name'),
maxLength: this.$v.changes.displayName.$params.maxLength.max
})
} else {
return ''
}
},
seatWebUsernameErrorMessage () {
if (!this.$v.changes.webUsername.required) {
return this.$t('{field} is required', {
field: this.$t('Seat Web Username')
})
} else if (!this.$v.changes.webUsername.maxLength) {
return this.$t('{field} must have at most {maxLength} letters', {
field: this.$t('Seat Web Username'),
maxLength: this.$v.changes.webUsername.$params.maxLength.max
})
} else {
return ''
}
},
internalSoundSetOptions () { internalSoundSetOptions () {
const items = [] const items = []
if (this.soundSet) { if (this.soundSet) {
@ -375,7 +449,8 @@ export default {
}, },
methods: { methods: {
...mapActions('pbxSeats', [ ...mapActions('pbxSeats', [
'setSeatName', 'setSeatDisplayName',
'setSeatWebUsername',
'setSeatExtension', 'setSeatExtension',
'setSeatNumbers', 'setSeatNumbers',
'setSeatGroups', 'setSeatGroups',
@ -418,7 +493,9 @@ export default {
}, },
getSeatData () { getSeatData () {
return (this.seatSelected) ? { return (this.seatSelected) ? {
name: this.seatSelected.display_name, displayName: this.seatSelected.display_name,
sipUsername: this.seatSelected.username,
webUsername: this.seatSelected.webusername,
extension: this.seatSelected.pbx_extension, extension: this.seatSelected.pbx_extension,
aliasNumbers: this.getAliasNumberIds(), aliasNumbers: this.getAliasNumberIds(),
webPassword: this.seatSelected.webpassword, webPassword: this.seatSelected.webpassword,
@ -429,8 +506,11 @@ export default {
cliNumber: this.getCliNumberId() cliNumber: this.getCliNumberId()
} : null } : null
}, },
resetName () { resetDisplayName () {
this.changes.name = this.seatSelected.display_name this.changes.displayName = this.seatSelected.display_name
},
resetWebUsername () {
this.changes.webUsername = this.seatSelected.webusername
}, },
resetExtension () { resetExtension () {
this.changes.extension = this.seatSelected.pbx_extension this.changes.extension = this.seatSelected.pbx_extension
@ -448,10 +528,16 @@ export default {
this.changes.soundSet = this.getSoundSetId() this.changes.soundSet = this.getSoundSetId()
}, },
save () { save () {
if (this.hasNameChanged) { if (this.hasDisplayNameChanged) {
this.setSeatName({ this.setSeatDisplayName({
seatId: this.seatSelected.id,
displayName: this.changes.displayName
})
}
if (this.hasWebUsernameChanged) {
this.setSeatWebUsername({
seatId: this.seatSelected.id, seatId: this.seatSelected.id,
seatName: this.changes.name webUsername: this.changes.webUsername
}) })
} }
if (this.hasExtensionChanged) { if (this.hasExtensionChanged) {

@ -13,7 +13,8 @@ import {
getSeatList, getSeatList,
createSeat, createSeat,
removeSeat, removeSeat,
setSeatName, setSeatDisplayName,
setSeatWebUsername,
setSeatExtension, setSeatExtension,
setSeatGroups, setSeatGroups,
setSeatNumbers, setSeatNumbers,
@ -319,14 +320,28 @@ export default {
context.commit('seatRemovalFailed', err.message) context.commit('seatRemovalFailed', err.message)
}) })
}, },
setSeatName (context, options) { setSeatDisplayName (context, options) {
context.commit('seatUpdateRequesting', { context.commit('seatUpdateRequesting', {
seatId: options.seatId, seatId: options.seatId,
seatField: i18n.t('Seat name') seatField: i18n.t('Seat displayName')
}) })
setSeatName({ setSeatDisplayName({
seatId: options.seatId, seatId: options.seatId,
seatName: options.seatName displayName: options.displayName
}).then((result) => {
context.commit('seatUpdateSucceeded', result)
}).catch((err) => {
context.commit('seatUpdateFailed', err.message)
})
},
setSeatWebUsername (context, options) {
context.commit('seatUpdateRequesting', {
seatId: options.seatId,
seatField: i18n.t('Seat Web Username')
})
setSeatWebUsername({
seatId: options.seatId,
webUsername: options.webUsername
}).then((result) => { }).then((result) => {
context.commit('seatUpdateSucceeded', result) context.commit('seatUpdateSucceeded', result)
}).catch((err) => { }).catch((err) => {

Loading…
Cancel
Save