web/satellite/vuetify: added update session timeout dialog

Added update session timeout dialog for vuetify app and wired it up with the backend

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

Change-Id: Icfd981c8d24a87b199e5e1eeb599f6369e6ee5c4
This commit is contained in:
Vitalii 2023-08-02 17:35:27 +03:00 committed by Storj Robot
parent 6e46a926bb
commit d8d3bb5033
5 changed files with 194 additions and 6 deletions

View File

@ -0,0 +1,7 @@
<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.3463C28.8835 0 31.0805 0.613723 33.2353 1.76617C35.3902 2.91861 37.0814 4.60977 38.2338 6.76465L38.3214 6.93055C39.4029 9.00671 39.9846 11.2 40 16.4423V23.3463C40 28.8835 39.3863 31.0804 38.2338 33.2353C37.0814 35.3902 35.3902 37.0814 33.2353 38.2338L33.0694 38.3214C30.9933 39.4029 28.8 39.9845 23.5577 40H16.6537C11.1165 40 8.91954 39.3862 6.76466 38.2338C4.60977 37.0814 2.91861 35.3902 1.76617 33.2353L1.67858 33.0694C0.597074 30.9933 0.0154219 28.8 0 23.5576V16.6536C0 11.1165 0.613723 8.91953 1.76617 6.76465C2.91861 4.60977 4.60977 2.91861 6.76466 1.76617L6.93055 1.67858C9.00672 0.597073 11.2 0.0154218 16.4423 0Z" fill="#0218A7"/>
<path d="M20.1654 34.3801C28.1986 34.3801 34.7108 27.8678 34.7108 19.8346C34.7108 11.8013 28.1986 5.28906 20.1654 5.28906C12.1321 5.28906 5.61987 11.8013 5.61987 19.8346C5.61987 27.8678 12.1321 34.3801 20.1654 34.3801Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.1652 32.409C27.1098 32.409 32.7396 26.7793 32.7396 19.8346C32.7396 16.1716 22.6985 21.4552 20.1992 19.157C17.9601 17.0981 23.4468 7.26025 20.1652 7.26025C13.2206 7.26025 7.59082 12.89 7.59082 19.8346C7.59082 26.7793 13.2206 32.409 20.1652 32.409Z" fill="#FF458B"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.1654 7.26025C21.0663 7.26025 21.7966 7.9906 21.7966 8.89152V19.8346C21.7966 20.7355 21.0663 21.4658 20.1654 21.4658C19.2645 21.4658 18.5342 20.7355 18.5342 19.8346V8.89152C18.5342 7.9906 19.2645 7.26025 20.1654 7.26025Z" fill="#0149FF"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M32.7056 19.8007C32.7056 20.7016 31.9752 21.432 31.0743 21.432L20.1312 21.432C19.2303 21.432 18.4999 20.7016 18.4999 19.8007C18.4999 18.8998 19.2303 18.1694 20.1312 18.1694L31.0743 18.1694C31.9752 18.1694 32.7056 18.8998 32.7056 19.8007Z" fill="#0149FF"/>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -44,7 +44,7 @@
<v-divider /> <v-divider />
<v-card-actions class="px-7 py-5"> <v-card-actions class="px-7 py-5">
<v-row class="ma-0"> <v-row class="ma-0">
<v-col> <v-col class="pl-0">
<v-btn <v-btn
variant="outlined" variant="outlined"
color="default" color="default"
@ -56,7 +56,7 @@
Cancel Cancel
</v-btn> </v-btn>
</v-col> </v-col>
<v-col> <v-col class="pr-0">
<v-btn <v-btn
color="primary" color="primary"
variant="flat" variant="flat"

View File

@ -0,0 +1,147 @@
// 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-session-timeout.svg" alt="Change name">
<v-card-title class="font-weight-bold ml-4">Session Timeout</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>Select your session timeout duration.</p>
</v-card-item>
<v-divider />
<v-card-item class="px-7 py-5">
<v-select
v-model="duration"
class="pt-2"
:items="options"
variant="outlined"
item-title="shortString"
item-value="nanoseconds"
label="Session timeout duration"
return-object
hide-details
/>
</v-card-item>
<v-divider />
<v-card-actions class="px-7 py-5">
<v-row class="ma-0">
<v-col class="pl-0">
<v-btn
variant="outlined"
color="default"
block
:disabled="isLoading"
:loading="isLoading"
@click="model = false"
>
Cancel
</v-btn>
</v-col>
<v-col class="pr-0">
<v-btn
color="primary"
variant="flat"
block
:disabled="isLoading"
:loading="isLoading"
@click="onChangeTimeout"
>
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,
VSelect,
} from 'vuetify/components';
import { useLoading } from '@/composables/useLoading';
import { useUsersStore } from '@/store/modules/usersStore';
import { Duration } from '@/utils/time';
const usersStore = useUsersStore();
const { isLoading, withLoading } = useLoading();
const props = defineProps<{
modelValue: boolean,
}>();
const emit = defineEmits<{
(event: 'update:modelValue', value: boolean): void,
}>();
const options = [
Duration.MINUTES_15,
Duration.MINUTES_30,
Duration.HOUR_1,
Duration.DAY_1,
Duration.WEEK_1,
Duration.DAY_30,
];
/**
* Returns user's session duration from store.
*/
const storedDuration = computed((): Duration | null => {
return usersStore.state.settings.sessionDuration;
});
const model = computed<boolean>({
get: () => props.modelValue,
set: value => emit('update:modelValue', value),
});
const duration = ref<Duration>(storedDuration.value || Duration.MINUTES_15);
/**
* Handles change session timeout request.
*/
async function onChangeTimeout(): Promise<void> {
await withLoading(async () => {
try {
await usersStore.updateSettings({ sessionDuration: duration.value.nanoseconds });
} catch (error) {
return;
}
emit('update:modelValue', false);
});
}
</script>

View File

@ -10,7 +10,22 @@
<script setup lang="ts"> <script setup lang="ts">
import { VApp } from 'vuetify/components'; import { VApp } from 'vuetify/components';
import { onBeforeMount } from 'vue';
import DefaultBar from './AppBar.vue'; import DefaultBar from './AppBar.vue';
import DefaultView from './View.vue'; import DefaultView from './View.vue';
import { useUsersStore } from '@/store/modules/usersStore';
const usersStore = useUsersStore();
/**
* Lifecycle hook after initial render.
* Pre-fetches user`s and project information.
*/
onBeforeMount(async () => {
try {
await usersStore.getSettings();
} catch (error) { /* empty */ }
});
</script> </script>

View File

@ -99,12 +99,14 @@
<v-list-item-title>Session Timeout</v-list-item-title> <v-list-item-title>Session Timeout</v-list-item-title>
<v-list-item-subtitle> <v-list-item-subtitle>
Set timeout to log you out for inactivity. {{ userSettings.sessionDuration?.shortString ?? Duration.MINUTES_15.shortString }}
</v-list-item-subtitle> </v-list-item-subtitle>
<template #append> <template #append>
<v-list-item-action> <v-list-item-action>
<v-btn variant="outlined" color="default" size="small">Set Timeout</v-btn> <v-btn variant="outlined" color="default" size="small" @click="isSetSessionTimeoutDialogShown = true">
Set Timeout
</v-btn>
</v-list-item-action> </v-list-item-action>
</template> </template>
</v-list-item> </v-list-item>
@ -149,6 +151,10 @@
<EnableMFADialog <EnableMFADialog
v-model="isEnableMFADialogShown" v-model="isEnableMFADialogShown"
/> />
<SetSessionTimeoutDialog
v-model="isSetSessionTimeoutDialogShown"
/>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@ -167,18 +173,21 @@ import {
VCheckboxBtn, VCheckboxBtn,
} from 'vuetify/components'; } from 'vuetify/components';
import { User } from '@/types/users'; import { User, UserSettings } from '@/types/users';
import { useUsersStore } from '@/store/modules/usersStore'; import { useUsersStore } from '@/store/modules/usersStore';
import { Duration } from '@/utils/time';
import ChangePasswordDialog from '@poc/components/dialogs/ChangePasswordDialog.vue'; import ChangePasswordDialog from '@poc/components/dialogs/ChangePasswordDialog.vue';
import ChangeNameDialog from '@poc/components/dialogs/ChangeNameDialog.vue'; import ChangeNameDialog from '@poc/components/dialogs/ChangeNameDialog.vue';
import EnableMFADialog from '@poc/components/dialogs/EnableMFADialog.vue'; import EnableMFADialog from '@poc/components/dialogs/EnableMFADialog.vue';
import SetSessionTimeoutDialog from '@poc/components/dialogs/SetSessionTimeoutDialog.vue';
const usersStore = useUsersStore(); const usersStore = useUsersStore();
const isChangePasswordDialogShown = ref<boolean>(false); const isChangePasswordDialogShown = ref<boolean>(false);
const isChangeNameDialogShown = ref<boolean>(false); const isChangeNameDialogShown = ref<boolean>(false);
const isEnableMFADialogShown = ref<boolean>(false); const isEnableMFADialogShown = ref<boolean>(false);
const isSetSessionTimeoutDialogShown = ref<boolean>(false);
/** /**
* Returns user entity from store. * Returns user entity from store.
@ -187,6 +196,13 @@ const user = computed((): User => {
return usersStore.state.user; return usersStore.state.user;
}); });
/**
* Returns user settings from store.
*/
const userSettings = computed((): UserSettings => {
return usersStore.state.settings as UserSettings;
});
async function toggleEnableMFADialog() { async function toggleEnableMFADialog() {
try { try {
await usersStore.generateUserMFASecret(); await usersStore.generateUserMFASecret();
@ -197,6 +213,9 @@ async function toggleEnableMFADialog() {
} }
onMounted(() => { onMounted(() => {
usersStore.getUser(); Promise.all([
usersStore.getUser(),
usersStore.getSettings(),
]);
}); });
</script> </script>