diff --git a/src/components/form/CscInputPassword.vue b/src/components/form/CscInputPassword.vue index 0c90aefc..e1975056 100644 --- a/src/components/form/CscInputPassword.vue +++ b/src/components/form/CscInputPassword.vue @@ -1,36 +1,38 @@ <template> <csc-input ref="input" - v-bind="$attrs" + :value="$attrs.value" :type="inputType" - :value="value" - @input="$emit('input', $event)" + v-bind="$attrs" v-on="$listeners" > <template slot="prepend" > + <slot + name="prepend" + /> <q-icon - name="lock" + :name="$attrs.icon || 'lock'" /> </template> <template v-slot:append > <q-btn - v-if="value !== ''" - :icon="icon" - :disable="$attrs.disable" + v-if="$attrs.value !== ''" + :icon="visibilityIcon" + :disable="$attrs.disable || $attrs.loading" tabindex="-1" color="primary" flat dense - @click.stop="visible=!visible" + @click.stop="toggleVisibility" /> <q-btn v-if="generate" icon="casino" - :disable="$attrs.disable" + :disable="$attrs.disable || $attrs.loading" tabindex="-1" color="primary" flat @@ -50,13 +52,41 @@ export default { name: 'CscInputPassword', components: { CscInput }, props: { - value: { - type: String, - default: undefined - }, generate: { type: Boolean, default: false + }, + generateLength: { + type: Number, + default: 10 + }, + generateNumbers: { + type: Boolean, + default: true + }, + generateLowercase: { + type: Boolean, + default: true + }, + generateUppercase: { + type: Boolean, + default: true + }, + generateSymbols: { + type: Boolean, + default: false + }, + generateExcludeSimilarCharacters: { + type: Boolean, + default: false + }, + generateExclude: { + type: String, + default: '' + }, + generateStrict: { + type: Boolean, + default: true } }, data () { @@ -72,7 +102,7 @@ export default { return 'password' } }, - icon () { + visibilityIcon () { if (!this.visible) { return 'visibility_off' } else { @@ -83,12 +113,21 @@ export default { methods: { generatePassword () { const pass = PasswordGenerator.generate({ - length: 10, - numbers: true + length: this.generateLength, + numbers: this.generateNumbers, + lowercase: this.generateLowercase, + uppercase: this.generateUppercase, + symbols: this.generateSymbols, + excludeSimilarCharacters: this.generateExcludeSimilarCharacters, + exclude: this.generateExclude, + strict: this.generateStrict }) this.$emit('input', pass) this.$emit('generated', pass) }, + toggleVisibility () { + this.visible = !this.visible + }, clear () { this.$refs.input.clear() } diff --git a/src/components/pages/UserSettings/CscChangePasswordEmbeded.vue b/src/components/pages/UserSettings/CscChangePasswordEmbeded.vue index 2cd8c788..bda461fd 100644 --- a/src/components/pages/UserSettings/CscChangePasswordEmbeded.vue +++ b/src/components/pages/UserSettings/CscChangePasswordEmbeded.vue @@ -42,16 +42,15 @@ :disable="!isValid" @click="openConfirmDialog" > - {{ $t('Save new password') }} + {{ saveButtonLabel }} </q-btn> </div> </div> </q-slide-transition> - <q-inner-loading :showing="loading"> - <q-spinner-dots - size="32px" - color="primary" - /> + <q-inner-loading + :showing="loading" + > + <csc-spinner /> </q-inner-loading> </div> </template> @@ -59,18 +58,25 @@ <script> import CscInputPasswordRetype from 'components/form/CscInputPasswordRetype' +import CscSpinner from 'components/CscSpinner' export default { name: 'CscChangePasswordEmbedded', - components: { CscInputPasswordRetype }, + components: { CscSpinner, CscInputPasswordRetype }, props: { loading: { type: Boolean, default: false }, + saveButtonLabel: { + type: String, + default () { + return this.$t('Save') + } + }, btnLabel: { type: String, default () { - return this.$t('Change Password') + return this.$t('Change password') } }, passwordLabel: { diff --git a/src/i18n/en.json b/src/i18n/en.json index b141da00..f205fa3c 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -76,6 +76,7 @@ "Change PIN": "Change PIN", "Change Password": "Change Password", "Change SIP Password": "Change SIP Password", + "Change Web Password": "Change Web Password", "Change login password": "Change login password", "Change password": "Change password", "Changed PIN successfully.": "Changed PIN successfully.", @@ -241,6 +242,8 @@ "New Messages": "New Messages", "New SIP Password": "New SIP Password", "New SIP Password confirm": "New SIP Password confirm", + "New Web Password": "New Web Password", + "New Web Password confirm": "New Web Password confirm", "New features": "New features", "New password": "New password", "New password retyped": "New password retyped", @@ -483,11 +486,13 @@ "You have blocked incoming call notifications.": "You have blocked incoming call notifications.", "You have invalid form input. Please check and try again.": "You have invalid form input. Please check and try again.", "Your SIP password has been changed successfully": "Your SIP password has been changed successfully", + "Your Web password has been changed successfully": "Your Web password has been changed successfully", "Your number is hidden to the callee": "Your number is hidden to the callee", "Your number is hidden to the callee within own PBX": "Your number is hidden to the callee within own PBX", "Your number is visible to the callee": "Your number is visible to the callee", "Your number is visible to the callee within own PBX": "Your number is visible to the callee within own PBX", "Your password has been changed successfully": "Your password has been changed successfully", + "Your web password has been changed successfully": "Your web password has been changed successfully", "ago": "ago", "and": "and", "and call from": "and call from", diff --git a/src/pages/CscPageUserSettings.vue b/src/pages/CscPageUserSettings.vue index 19b5e9ee..a16abddd 100644 --- a/src/pages/CscPageUserSettings.vue +++ b/src/pages/CscPageUserSettings.vue @@ -6,12 +6,15 @@ <div class="col col-xs-12 col-md-6" > - <csc-change-password + <csc-change-password-embedded + ref="changeWebPasswordSection" class="q-mb-md" - :loading="isPasswordChanging" - :error="changePasswordError" - :subscriber="getSubscriber" - @change="changePassword" + :btn-label="$t('Change Web Password')" + :password-label="$t('New Web Password')" + :password-confirm-label="$t('New Web Password confirm')" + :save-conformation-text="$t('You are about to change your login password. After the password was changed successfully, you get automatically logged out to authenticate with the new password. ')" + :loading="processingChangeWebPassword" + @change="requestWebPasswordChange" /> <csc-change-password-embedded ref="changeSipPasswordSection" @@ -62,26 +65,22 @@ import { showToast } from 'src/helpers/ui' import { - RequestState -} from 'src/store/common' -import { - mapState, - mapGetters, - mapActions + mapGetters } from 'vuex' import CscPage from 'components/CscPage' -import CscChangePassword from 'components/pages/UserSettings/CscChangePassword' import CscChangePasswordEmbedded from 'components/pages/UserSettings/CscChangePasswordEmbeded' import { mapWaitingActions, mapWaitingGetters } from 'vue-wait' import { copyToClipboard } from 'quasar' import CscInputPassword from 'components/form/CscInputPassword' +const WAIT_CHANGE_WEB_PASSWORD = 'processing-changeWebPassword' +const WAIT_CHANGE_SIP_PASSWORD = 'processing-changeSIPPassword' + export default { name: 'CscPageUserSettings', components: { CscInputPassword, CscChangePasswordEmbedded, - CscChangePassword, CscPage }, data () { @@ -89,16 +88,12 @@ export default { } }, computed: { - ...mapState('user', [ - 'changePasswordState', - 'changePasswordError' - ]), ...mapGetters('user', [ - 'getSubscriber', - 'isPasswordChanging' + 'getSubscriber' ]), ...mapWaitingGetters({ - processingChangeSIPPassword: 'processing-changeSIPPassword' + processingChangeSIPPassword: WAIT_CHANGE_SIP_PASSWORD, + processingChangeWebPassword: WAIT_CHANGE_WEB_PASSWORD }), currentSIPPassword () { return this.getSubscriber?.password || '' @@ -108,22 +103,20 @@ export default { return subscriberData?.username + '@' + subscriberData?.domain } }, - watch: { - changePasswordState (state) { - if (state === RequestState.succeeded) { - showToast(this.$t('Your password has been changed successfully')) - } else if (state === RequestState.failed) { - showGlobalError(this.changePasswordError) - } - } - }, methods: { - ...mapActions('user', [ - 'changePassword' - ]), ...mapWaitingActions('user', { - changeSIPPassword: 'processing-changeSIPPassword' + changeSIPPassword: WAIT_CHANGE_SIP_PASSWORD, + changePassword: WAIT_CHANGE_WEB_PASSWORD }), + async requestWebPasswordChange (newPassword) { + try { + await this.changePassword(newPassword) + showToast(this.$t('Your Web password has been changed successfully')) + this.$refs.changeWebPasswordSection.cancel() + } catch (error) { + showGlobalError(error?.message) + } + }, async requestSIPPasswordChange (newPassword) { try { await this.changeSIPPassword(newPassword) diff --git a/src/store/user.js b/src/store/user.js index 1895c4aa..78f02b64 100644 --- a/src/store/user.js +++ b/src/store/user.js @@ -351,15 +351,10 @@ export default { await context.dispatch('forwardHome') } }, - changePassword (context, newPassword) { + async changePassword (context, newPassword) { const subscriberId = getSubscriberId() - context.commit('userPasswordRequesting') - changePassword(subscriberId, newPassword).then(() => { - context.commit('userPasswordSucceeded') - context.dispatch('logout') - }).catch((err) => { - context.commit('userPasswordFailed', err.message) - }) + await changePassword(subscriberId, newPassword) + await context.dispatch('logout') }, async changeSIPPassword (context, newPassword) { const subscriberId = getSubscriberId()