web/satellite: Setting.vue migrated to use composition api
added useLoading composable to get rid or repetative same code usage; Change-Id: I3524efdb1919759046bbf11fe3510f8044adc828
This commit is contained in:
parent
a7fc884a2c
commit
86fb188be6
@ -7,16 +7,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
/**
|
||||
* AccountArea is a container for all account related routes.
|
||||
*/
|
||||
// @vue/component
|
||||
@Component
|
||||
export default class AccountArea extends Vue {}
|
||||
</script>
|
||||
<script setup lang="ts"></script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
::-webkit-scrollbar,
|
||||
|
@ -82,13 +82,15 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted } from 'vue';
|
||||
|
||||
import { USER_ACTIONS } from '@/store/modules/users';
|
||||
import { User } from '@/types/users';
|
||||
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
import { useNotify, useStore } from '@/utils/hooks';
|
||||
import { useLoading } from '@/composables/useLoading';
|
||||
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
|
||||
@ -96,110 +98,93 @@ import ChangePasswordIcon from '@/../static/images/account/profile/changePasswor
|
||||
import EmailIcon from '@/../static/images/account/profile/email.svg';
|
||||
import EditIcon from '@/../static/images/common/edit.svg';
|
||||
|
||||
// @vue/component
|
||||
@Component({
|
||||
components: {
|
||||
EditIcon,
|
||||
ChangePasswordIcon,
|
||||
EmailIcon,
|
||||
VButton,
|
||||
},
|
||||
})
|
||||
export default class SettingsArea extends Vue {
|
||||
public isLoading = false;
|
||||
const store = useStore();
|
||||
const notify = useNotify();
|
||||
const { isLoading, withLoading } = useLoading();
|
||||
|
||||
/**
|
||||
* Lifecycle hook after initial render where user info is fetching.
|
||||
*/
|
||||
public mounted(): void {
|
||||
this.$store.dispatch(USER_ACTIONS.GET);
|
||||
}
|
||||
/**
|
||||
* Returns user info from store.
|
||||
*/
|
||||
const user = computed((): User => {
|
||||
return store.getters.user;
|
||||
});
|
||||
|
||||
/**
|
||||
* Generates user's MFA secret and opens popup.
|
||||
*/
|
||||
public async enableMFA(): Promise<void> {
|
||||
if (this.isLoading) return;
|
||||
/**
|
||||
* Returns first letter of user name.
|
||||
*/
|
||||
const avatarLetter = computed((): string => {
|
||||
return store.getters.userName.slice(0, 1).toUpperCase();
|
||||
});
|
||||
|
||||
this.isLoading = true;
|
||||
|
||||
try {
|
||||
await this.$store.dispatch(USER_ACTIONS.GENERATE_USER_MFA_SECRET);
|
||||
this.toggleEnableMFAModal();
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.ACCOUNT_SETTINGS_AREA);
|
||||
}
|
||||
|
||||
this.isLoading = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles generate new MFA recovery codes popup visibility.
|
||||
*/
|
||||
public async generateNewMFARecoveryCodes(): Promise<void> {
|
||||
if (this.isLoading) return;
|
||||
|
||||
this.isLoading = true;
|
||||
|
||||
try {
|
||||
await this.$store.dispatch(USER_ACTIONS.GENERATE_USER_MFA_RECOVERY_CODES);
|
||||
this.toggleMFACodesModal();
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.ACCOUNT_SETTINGS_AREA);
|
||||
}
|
||||
|
||||
this.isLoading = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles enable MFA modal visibility.
|
||||
*/
|
||||
public toggleEnableMFAModal(): void {
|
||||
this.$store.commit(APP_STATE_MUTATIONS.TOGGLE_ENABLE_MFA_MODAL_SHOWN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles disable MFA modal visibility.
|
||||
*/
|
||||
public toggleDisableMFAModal(): void {
|
||||
this.$store.commit(APP_STATE_MUTATIONS.TOGGLE_DISABLE_MFA_MODAL_SHOWN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles MFA recovery codes modal visibility.
|
||||
*/
|
||||
public toggleMFACodesModal(): void {
|
||||
this.$store.commit(APP_STATE_MUTATIONS.TOGGLE_MFA_RECOVERY_MODAL_SHOWN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens change password popup.
|
||||
*/
|
||||
public toggleChangePasswordModal(): void {
|
||||
this.$store.commit(APP_STATE_MUTATIONS.TOGGLE_CHANGE_PASSWORD_MODAL_SHOWN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens edit account info modal.
|
||||
*/
|
||||
public toggleEditProfileModal(): void {
|
||||
this.$store.commit(APP_STATE_MUTATIONS.TOGGLE_EDIT_PROFILE_MODAL_SHOWN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns user info from store.
|
||||
*/
|
||||
public get user(): User {
|
||||
return this.$store.getters.user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns first letter of user name.
|
||||
*/
|
||||
public get avatarLetter(): string {
|
||||
return this.$store.getters.userName.slice(0, 1).toUpperCase();
|
||||
}
|
||||
/**
|
||||
* Toggles enable MFA modal visibility.
|
||||
*/
|
||||
function toggleEnableMFAModal(): void {
|
||||
store.commit(APP_STATE_MUTATIONS.TOGGLE_ENABLE_MFA_MODAL_SHOWN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles disable MFA modal visibility.
|
||||
*/
|
||||
function toggleDisableMFAModal(): void {
|
||||
store.commit(APP_STATE_MUTATIONS.TOGGLE_DISABLE_MFA_MODAL_SHOWN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles MFA recovery codes modal visibility.
|
||||
*/
|
||||
function toggleMFACodesModal(): void {
|
||||
store.commit(APP_STATE_MUTATIONS.TOGGLE_MFA_RECOVERY_MODAL_SHOWN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens change password popup.
|
||||
*/
|
||||
function toggleChangePasswordModal(): void {
|
||||
store.commit(APP_STATE_MUTATIONS.TOGGLE_CHANGE_PASSWORD_MODAL_SHOWN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens edit account info modal.
|
||||
*/
|
||||
function toggleEditProfileModal(): void {
|
||||
store.commit(APP_STATE_MUTATIONS.TOGGLE_EDIT_PROFILE_MODAL_SHOWN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates user's MFA secret and opens popup.
|
||||
*/
|
||||
async function enableMFA(): Promise<void> {
|
||||
await withLoading(async () => {
|
||||
try {
|
||||
await store.dispatch(USER_ACTIONS.GENERATE_USER_MFA_SECRET);
|
||||
toggleEnableMFAModal();
|
||||
} catch (error) {
|
||||
await notify.error(error.message, AnalyticsErrorEventSource.ACCOUNT_SETTINGS_AREA);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles generate new MFA recovery codes popup visibility.
|
||||
*/
|
||||
async function generateNewMFARecoveryCodes(): Promise<void> {
|
||||
await withLoading(async () => {
|
||||
try {
|
||||
await store.dispatch(USER_ACTIONS.GENERATE_USER_MFA_RECOVERY_CODES);
|
||||
toggleMFACodesModal();
|
||||
} catch (error) {
|
||||
await notify.error(error.message, AnalyticsErrorEventSource.ACCOUNT_SETTINGS_AREA);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Lifecycle hook after initial render where user info is fetching.
|
||||
*/
|
||||
onMounted(() => {
|
||||
store.dispatch(USER_ACTIONS.GET);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
@ -35,6 +35,7 @@ import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
import { useNotify, useStore } from '@/utils/hooks';
|
||||
import { useLoading } from '@/composables/useLoading';
|
||||
|
||||
import VInput from '@/components/common/VInput.vue';
|
||||
import ValidationMessage from '@/components/common/ValidationMessage.vue';
|
||||
@ -42,6 +43,7 @@ import VButton from '@/components/common/VButton.vue';
|
||||
|
||||
const store = useStore();
|
||||
const notify = useNotify();
|
||||
const { isLoading, withLoading } = useLoading();
|
||||
|
||||
const emit = defineEmits(['close']);
|
||||
|
||||
@ -49,7 +51,6 @@ const showValidationMessage = ref<boolean>(false);
|
||||
const isCodeValid = ref<boolean>(false);
|
||||
const errorMessage = ref<string>('');
|
||||
const couponCode = ref<string>('');
|
||||
const isLoading = ref<boolean>(false);
|
||||
|
||||
const analytics = new AnalyticsHttpApi();
|
||||
|
||||
@ -61,22 +62,20 @@ function setCouponCode(value: string): void {
|
||||
* Check if coupon code is valid
|
||||
*/
|
||||
async function applyCouponCode(): Promise<void> {
|
||||
if (isLoading.value) return;
|
||||
|
||||
isLoading.value = true;
|
||||
|
||||
try {
|
||||
await store.dispatch(PAYMENTS_ACTIONS.APPLY_COUPON_CODE, couponCode.value);
|
||||
await notify.success('Coupon Added!');
|
||||
emit('close');
|
||||
} catch (error) {
|
||||
errorMessage.value = error.message;
|
||||
isCodeValid.value = false;
|
||||
showValidationMessage.value = true;
|
||||
await analytics.errorEventTriggered(AnalyticsErrorEventSource.BILLING_APPLY_COUPON_CODE_INPUT);
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
await withLoading(async () => {
|
||||
try {
|
||||
await store.dispatch(PAYMENTS_ACTIONS.APPLY_COUPON_CODE, couponCode.value);
|
||||
await notify.success('Coupon Added!');
|
||||
emit('close');
|
||||
} catch (error) {
|
||||
errorMessage.value = error.message;
|
||||
isCodeValid.value = false;
|
||||
showValidationMessage.value = true;
|
||||
await analytics.errorEventTriggered(AnalyticsErrorEventSource.BILLING_APPLY_COUPON_CODE_INPUT);
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -19,9 +19,12 @@
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import { OnPageClickCallback } from '@/types/pagination';
|
||||
import { useLoading } from '@/composables/useLoading';
|
||||
|
||||
import PaginationRightIcon from '@/../static/images/common/tablePaginationArrowRight.svg';
|
||||
|
||||
const { withLoading } = useLoading();
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
totalPageCount?: number;
|
||||
limit?: number;
|
||||
@ -35,7 +38,6 @@ const props = withDefaults(defineProps<{
|
||||
});
|
||||
|
||||
const currentPageNumber = ref<number>(1);
|
||||
const isLoading = ref<boolean>(false);
|
||||
|
||||
const label = computed((): string => {
|
||||
const currentMaxPage = currentPageNumber.value * props.limit > props.totalItemsCount ?
|
||||
@ -56,28 +58,28 @@ const isLastPage = computed((): boolean => {
|
||||
* nextPage fires after 'next' arrow click.
|
||||
*/
|
||||
async function nextPage(): Promise<void> {
|
||||
if (isLastPage.value || isLoading.value) {
|
||||
return;
|
||||
}
|
||||
await withLoading(async () => {
|
||||
if (isLastPage.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
isLoading.value = true;
|
||||
await props.onPageClickCallback(currentPageNumber.value + 1);
|
||||
incrementCurrentPage();
|
||||
isLoading.value = false;
|
||||
await props.onPageClickCallback(currentPageNumber.value + 1);
|
||||
incrementCurrentPage();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* prevPage fires after 'previous' arrow click.
|
||||
*/
|
||||
async function prevPage(): Promise<void> {
|
||||
if (isFirstPage.value || isLoading.value) {
|
||||
return;
|
||||
}
|
||||
await withLoading(async () => {
|
||||
if (isFirstPage.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
isLoading.value = true;
|
||||
await props.onPageClickCallback(currentPageNumber.value - 1);
|
||||
decrementCurrentPage();
|
||||
isLoading.value = false;
|
||||
await props.onPageClickCallback(currentPageNumber.value - 1);
|
||||
decrementCurrentPage();
|
||||
});
|
||||
}
|
||||
|
||||
function incrementCurrentPage(): void {
|
||||
|
@ -34,6 +34,7 @@
|
||||
import { computed, onMounted, ref, watch } from 'vue';
|
||||
|
||||
import { OnPageClickCallback, Page } from '@/types/pagination';
|
||||
import { useLoading } from '@/composables/useLoading';
|
||||
|
||||
import PagesBlock from '@/components/common/PagesBlock.vue';
|
||||
|
||||
@ -44,14 +45,16 @@ const MAX_PAGES_PER_BLOCK = 3;
|
||||
const MAX_PAGES_OFF_BLOCKS = 6;
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
onPageClickCallback: OnPageClickCallback;
|
||||
onPageClickCallback?: OnPageClickCallback;
|
||||
totalPageCount?: number;
|
||||
}>(), {
|
||||
totalPageCount: 0,
|
||||
onPageClickCallback: () => () => {},
|
||||
});
|
||||
|
||||
const { withLoading } = useLoading();
|
||||
|
||||
const currentPageNumber = ref<number>(1);
|
||||
const isLoading = ref<boolean>(false);
|
||||
const pagesArray = ref<Page[]>([]);
|
||||
const firstBlockPages = ref<Page[]>([]);
|
||||
const middleBlockPages = ref<Page[]>([]);
|
||||
@ -169,45 +172,41 @@ function setCurrentPage(pageNumber: number): void {
|
||||
* onPageClick fires after concrete page click.
|
||||
*/
|
||||
async function onPageClick(page: number): Promise<void> {
|
||||
if (isLoading.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
isLoading.value = true;
|
||||
await props.onPageClickCallback(page);
|
||||
setCurrentPage(page);
|
||||
reorganizePageBlocks();
|
||||
isLoading.value = false;
|
||||
await withLoading(async () => {
|
||||
await props.onPageClickCallback(page);
|
||||
setCurrentPage(page);
|
||||
reorganizePageBlocks();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* nextPage fires after 'next' arrow click.
|
||||
*/
|
||||
async function nextPage(): Promise<void> {
|
||||
if (isLastPage || isLoading.value) {
|
||||
return;
|
||||
}
|
||||
await withLoading(async () => {
|
||||
if (isLastPage) {
|
||||
return;
|
||||
}
|
||||
|
||||
isLoading.value = true;
|
||||
await props.onPageClickCallback(currentPageNumber.value + 1);
|
||||
incrementCurrentPage();
|
||||
reorganizePageBlocks();
|
||||
isLoading.value = false;
|
||||
await props.onPageClickCallback(currentPageNumber.value + 1);
|
||||
incrementCurrentPage();
|
||||
reorganizePageBlocks();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* prevPage fires after 'previous' arrow click.
|
||||
*/
|
||||
async function prevPage(): Promise<void> {
|
||||
if (isFirstPage || isLoading.value) {
|
||||
return;
|
||||
}
|
||||
await withLoading(async () => {
|
||||
if (isFirstPage) {
|
||||
return;
|
||||
}
|
||||
|
||||
isLoading.value = true;
|
||||
await props.onPageClickCallback(currentPageNumber.value - 1);
|
||||
decrementCurrentPage();
|
||||
reorganizePageBlocks();
|
||||
isLoading.value = false;
|
||||
await props.onPageClickCallback(currentPageNumber.value - 1);
|
||||
decrementCurrentPage();
|
||||
reorganizePageBlocks();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
23
web/satellite/src/composables/useLoading.ts
Normal file
23
web/satellite/src/composables/useLoading.ts
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright (C) 2023 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import { ref } from 'vue';
|
||||
|
||||
export function useLoading() {
|
||||
const isLoading = ref<boolean>(false);
|
||||
|
||||
async function withLoading(callback): Promise<void> {
|
||||
if (isLoading.value) return;
|
||||
|
||||
isLoading.value = true;
|
||||
|
||||
await callback();
|
||||
|
||||
isLoading.value = false;
|
||||
}
|
||||
|
||||
return {
|
||||
isLoading,
|
||||
withLoading,
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user