web/satellite/vuetify: added change password dialog

Added change password dialog for vuetify app and wired it up with backend.

Issue:
https://github.com/storj/storj/issues/6089

Change-Id: Ib1dffa947b65c299b278a48ed1491a623895a0bd
This commit is contained in:
Vitalii 2023-07-31 14:38:56 +03:00
parent 6f002f4220
commit ceef4b8362
3 changed files with 203 additions and 1 deletions

View File

@ -0,0 +1,8 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.4423 0H23.3462C28.8834 0 31.0803 0.613723 33.2352 1.76617C35.39 2.91861 37.0812 4.60977 38.2336 6.76466L38.3212 6.93055C39.4027 9.00672 39.9844 11.2 39.9998 16.4423V23.3463C39.9998 28.8835 39.3861 31.0805 38.2336 33.2353C37.0812 35.3902 35.39 37.0814 33.2352 38.2338L33.0693 38.3214C30.9931 39.4029 28.7999 39.9846 23.5575 40H16.6536C11.1164 40 8.91949 39.3863 6.76462 38.2338C4.60975 37.0814 2.9186 35.3902 1.76616 33.2353L1.67857 33.0694C0.597071 30.9933 0.0154218 28.8 0 23.5577V16.6537C0 11.1165 0.61372 8.91954 1.76616 6.76466C2.9186 4.60977 4.60975 2.91861 6.76462 1.76617L6.93052 1.67858C9.00667 0.597074 11.1999 0.0154219 16.4423 0Z" fill="#0218A7"/>
<path d="M20.165 24.4628C24.3642 24.4628 27.7683 21.0587 27.7683 16.8595C27.7683 12.6604 24.3642 9.25635 20.165 9.25635C15.9659 9.25635 12.5618 12.6604 12.5618 16.8595C12.5618 21.0587 15.9659 24.4628 20.165 24.4628Z" fill="#FFC600"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.9998 7.27271C25.5682 7.27271 30.0824 11.7128 30.0824 17.1899C30.0824 22.667 25.5682 27.107 19.9998 27.107C14.7669 27.107 10.4651 23.186 9.96558 18.1681C10.0421 16.4121 10.2088 15.0761 10.4611 13.9688C11.8204 10.0728 15.5776 7.27271 19.9998 7.27271ZM19.9998 10.2479C16.0635 10.2479 12.8923 13.367 12.8923 17.1899C12.8923 21.0127 16.0635 24.1319 19.9998 24.1319C23.936 24.1319 27.1072 21.0127 27.1072 17.1899C27.1072 13.367 23.936 10.2479 19.9998 10.2479Z" fill="#FF458B"/>
<path d="M30.0826 17.1902H9.91748V32.3965H30.0826V17.1902Z" fill="#0149FF"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.1653 21.1567C21.2608 21.1567 22.1488 21.9859 22.1488 23.0087C22.1488 23.7829 21.64 24.4462 20.9176 24.7229L20.9177 26.7766H19.413L19.413 24.7229C18.6906 24.4462 18.1819 23.7829 18.1819 23.0087C18.1819 21.9859 19.0699 21.1567 20.1653 21.1567Z" fill="#0218A7"/>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,183 @@
// Copyright (C) 2023 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<v-dialog
v-model="model"
width="auto"
min-width="320px"
max-width="410px"
transition="fade-transition"
>
<v-card rounded="xlg">
<v-card-item class="pl-7 pr-0 pb-5 pt-0">
<v-row align="start" justify="space-between" class="ma-0">
<v-row align="center" class="ma-0 pt-5">
<img class="flex-shrink-0" src="@poc/assets/icon-change-password.svg" alt="Change password">
<v-card-title class="font-weight-bold ml-4">Change password</v-card-title>
</v-row>
<v-btn
icon="$close"
variant="text"
size="small"
color="default"
:disabled="isLoading"
@click="model = false"
/>
</v-row>
</v-card-item>
<v-divider />
<v-card-item class="px-7 py-5">
<p>You will receive a verification link in your email to confirm the password change.</p>
</v-card-item>
<v-divider />
<v-card-item class="px-7 py-5">
<v-form v-model="formValid">
<v-col cols="12" class="px-0">
<v-text-field
v-model="oldPassword"
variant="outlined"
type="password"
:rules="oldRules"
label="Current password"
required
autofocus
/>
</v-col>
<v-col cols="12" class="px-0">
<v-text-field
v-model="newPassword"
variant="outlined"
type="password"
:rules="newRules"
label="New password"
required
/>
</v-col>
<v-col cols="12" class="px-0">
<v-text-field
variant="outlined"
type="password"
:rules="repeatRules"
label="Repeat password"
required
/>
</v-col>
</v-form>
</v-card-item>
<v-divider />
<v-card-actions class="px-7 py-5">
<v-row class="ma-0">
<v-col>
<v-btn
variant="outlined"
color="default"
block
:disabled="isLoading"
:loading="isLoading"
@click="model = false"
>
Cancel
</v-btn>
</v-col>
<v-col>
<v-btn
color="primary"
variant="flat"
block
:disabled="isLoading || !formValid"
:loading="isLoading"
@click="onChangePassword"
>
Save
</v-btn>
</v-col>
</v-row>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script setup lang="ts">
import { computed, ref } from 'vue';
import {
VDialog,
VCard,
VCardItem,
VCardTitle,
VDivider,
VCardActions,
VRow,
VCol,
VBtn,
VForm,
VTextField,
} from 'vuetify/components';
import { useRouter } from 'vue-router';
import { useLoading } from '@/composables/useLoading';
import { useConfigStore } from '@/store/modules/configStore';
import { AuthHttpApi } from '@/api/auth';
import { RouteConfig } from '@/types/router';
const DELAY_BEFORE_REDIRECT = 2000; // 2 sec
const auth: AuthHttpApi = new AuthHttpApi();
const oldRules = [
(value: string) => (value && value.length >= config.passwordMinimumLength || `Invalid old password. Must be ${config.passwordMinimumLength} or more characters`),
];
const newRules = [
(value: string) => (value && value.length >= config.passwordMinimumLength || `Invalid password. Use ${config.passwordMinimumLength} or more characters`),
(value: string) => (value && value.length <= config.passwordMaximumLength || `Invalid password. Use ${config.passwordMaximumLength} or fewer characters`),
];
const repeatRules = [
...newRules,
(value: string) => (value && value === newPassword.value || 'Passwords are not the same.'),
];
const { config } = useConfigStore().state;
const { isLoading, withLoading } = useLoading();
const router = useRouter();
const props = defineProps<{
modelValue: boolean,
}>();
const emit = defineEmits<{
(event: 'update:modelValue', value: boolean): void,
}>();
const model = computed<boolean>({
get: () => props.modelValue,
set: value => emit('update:modelValue', value),
});
const formValid = ref<boolean>(false);
const oldPassword = ref<string>('');
const newPassword = ref<string>('');
/**
* Handles change password request.
*/
async function onChangePassword(): Promise<void> {
if (!formValid.value) return;
await withLoading(async () => {
try {
await auth.changePassword(oldPassword.value, newPassword.value);
} catch (error) {
return;
}
try {
await auth.logout();
setTimeout(() => {
router.push(RouteConfig.Login.path);
// TODO: this reload will be unnecessary once vuetify poc has its own login and/or becomes the primary app
location.reload();
}, DELAY_BEFORE_REDIRECT);
} catch (error) { /* empty */ }
emit('update:modelValue', false);
});
}
</script>

View File

@ -67,7 +67,9 @@
<template #append>
<v-list-item-action>
<v-btn variant="outlined" color="default" size="small">Change Password</v-btn>
<v-btn variant="outlined" color="default" size="small" @click="isChangePasswordDialogShown = true">
Change Password
</v-btn>
</v-list-item-action>
</template>
</v-list-item>
@ -132,9 +134,14 @@
</v-list>
</v-card>
</v-container>
<ChangePasswordDialog
v-model="isChangePasswordDialogShown"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import {
VContainer,
VCard,
@ -148,4 +155,8 @@ import {
VBtn,
VCheckboxBtn,
} from 'vuetify/components';
import ChangePasswordDialog from '@poc/components/dialogs/ChangePasswordDialog.vue';
const isChangePasswordDialogShown = ref<boolean>(false);
</script>