web/satellite: refreshing billing history on entering billing page implemented

Change-Id: I986d6bc5ca1277c78ead7cf6323d59cb73045e25
This commit is contained in:
VitaliiShpital 2020-03-19 14:54:31 +02:00 committed by Vitalii Shpital
parent f61b77ea39
commit fe39845a8c
18 changed files with 75 additions and 54 deletions

View File

@ -5,7 +5,7 @@
<div class="account-billing-area">
<div class="account-billing-area__title-area">
<h1 class="account-billing-area__title-area__title">Billing</h1>
<div class="account-billing-area__title-area__options-area" v-if="areBillingPeriodsVisible">
<div class="account-billing-area__title-area__options-area" v-if="userHasOwnProject">
<div class="account-billing-area__title-area__options-area__option active" @click.prevent="onCurrentPeriodClick">
<span class="account-billing-area__title-area__options-area__option__label">Current Billing Period</span>
</div>
@ -60,6 +60,7 @@ import DatePickerIcon from '@/../static/images/project/datePicker.svg';
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
import { PROJECTS_ACTIONS } from '@/store/modules/projects';
import { DateRange } from '@/types/usage';
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
import { SegmentEvent } from '@/utils/constants/analyticsEventNames';
import { ProjectOwning } from '@/utils/projectOwning';
@ -88,12 +89,16 @@ declare interface ShowCheck {
})
export default class BillingArea extends Vue {
/**
* Mounted lifecycle hook after initial render.
* Fetches project limits and current usage rollup.
* Mounted lifecycle hook before initial render.
* Fetches billing history and project limits.
*/
public async mounted(): Promise<void> {
public async beforeMount(): Promise<void> {
try {
await this.$store.dispatch(PAYMENTS_ACTIONS.GET_PROJECT_CHARGES_CURRENT_ROLLUP);
await this.$store.dispatch(PAYMENTS_ACTIONS.GET_BILLING_HISTORY);
if (this.$store.getters.canUserCreateFirstProject && !this.userHasOwnProject) {
await this.$store.dispatch(APP_STATE_ACTIONS.SHOW_CREATE_PROJECT_BUTTON);
await this.$store.dispatch(APP_STATE_ACTIONS.SHOW_CONTENT_BLUR);
}
} catch (error) {
await this.$notify.error(error.message);
}
@ -171,7 +176,7 @@ export default class BillingArea extends Vue {
public get isSummaryVisible(): boolean {
const isBalancePositive: boolean = this.$store.state.paymentsModule.balance > 0;
return isBalancePositive || new ProjectOwning(this.$store).userHasOwnProject();
return isBalancePositive || this.userHasOwnProject;
}
/**
@ -196,9 +201,9 @@ export default class BillingArea extends Vue {
}
/**
* Indicates if billing periods logic is visible.
* Indicates if user has own project.
*/
public get areBillingPeriodsVisible(): boolean {
public get userHasOwnProject(): boolean {
return new ProjectOwning(this.$store).userHasOwnProject();
}

View File

@ -23,7 +23,6 @@ import BillingItem from '@/components/account/billing/billingHistory/BillingItem
import SortingHeader from '@/components/account/billing/billingHistory/SortingHeader.vue';
import { RouteConfig } from '@/router';
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
import { BillingHistoryItem } from '@/types/payments';
@Component({
@ -33,17 +32,6 @@ import { BillingHistoryItem } from '@/types/payments';
},
})
export default class DepositAndBilling extends Vue {
/**
* Lifecycle hook after initial render where billing history is fetched.
*/
public mounted(): void {
try {
this.$store.dispatch(PAYMENTS_ACTIONS.GET_BILLING_HISTORY);
} catch (error) {
this.$notify.error(error.message);
}
}
/**
* Changes location to billing history route.
*/

View File

@ -55,8 +55,6 @@ import ArrowDownIcon from '@/../static/images/common/BlueExpand.svg';
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
import { ProjectCharge } from '@/types/payments';
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
import { ProjectOwning } from '@/utils/projectOwning';
@Component({
components: {
@ -78,10 +76,6 @@ export default class EstimatedCostsAndCredits extends Vue {
} catch (error) {
await this.$notify.error(error.message);
}
if (this.balance > 0 && !new ProjectOwning(this.$store).userHasOwnProject()) {
await this.$store.dispatch(APP_STATE_ACTIONS.SHOW_CREATE_PROJECT_BUTTON);
}
}
/**

View File

@ -230,7 +230,7 @@ export default class PaymentMethods extends Vue {
* Indicates if free credits or percentage bonus banner is shown.
*/
public get isDefaultBonusBannerShown(): boolean {
return this.isDefaultState && !this.$store.getters.isBonusCouponApplied;
return this.isDefaultState && !this.$store.getters.canUserCreateFirstProject;
}
/**
@ -294,7 +294,7 @@ export default class PaymentMethods extends Vue {
this.isLoading = true;
if ((this.tokenDepositValue < 50 || this.tokenDepositValue >= this.MAX_TOKEN_AMOUNT) && !new ProjectOwning(this.$store).userHasOwnProject()) {
if ((this.tokenDepositValue < 50 || this.tokenDepositValue >= this.MAX_TOKEN_AMOUNT) && !this.userHasOwnProject) {
await this.$notify.error('First deposit amount must be more than 50 and less than 1000000');
this.tokenDepositValue = this.DEFAULT_TOKEN_DEPOSIT_VALUE;
this.areaState = PaymentMethodsBlockState.DEFAULT;
@ -379,7 +379,7 @@ export default class PaymentMethods extends Vue {
this.isLoading = false;
this.isLoaded = true;
if (!new ProjectOwning(this.$store).userHasOwnProject()) {
if (!this.userHasOwnProject) {
await this.$store.dispatch(APP_STATE_ACTIONS.SHOW_CREATE_PROJECT_BUTTON);
}
@ -388,7 +388,9 @@ export default class PaymentMethods extends Vue {
this.isLoaded = false;
setTimeout(() => {
this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_CONTENT_BLUR);
if (!this.userHasOwnProject) {
this.$store.dispatch(APP_STATE_ACTIONS.SHOW_CONTENT_BLUR);
}
}, 500);
}, 2000);
}
@ -400,6 +402,13 @@ export default class PaymentMethods extends Vue {
return this.areaState === PaymentMethodsBlockState.DEFAULT;
}
/**
* Indicates if user has own project.
*/
private get userHasOwnProject(): boolean {
return new ProjectOwning(this.$store).userHasOwnProject();
}
/**
* Provides card information to Stripe.
*/

View File

@ -28,7 +28,7 @@
import { Component, Prop, Vue } from 'vue-property-decorator';
import CardIcon from '@/../static/images/account/billing/card.svg';
import LogoIcon from '@/../static/images/navigation/logo.svg';
import LogoIcon from '@/../static/images/account/billing/logo.svg';
@Component({
components: {

View File

@ -45,7 +45,7 @@ export default class NewProjectArea extends Vue {
* Toggles new project button visibility depending on user having his own project or payment method.
*/
public beforeMount(): void {
if (new ProjectOwning(this.$store).userHasOwnProject() || !this.$store.getters.isBonusCouponApplied) {
if (this.userHasOwnProject || !this.$store.getters.canUserCreateFirstProject) {
this.$store.dispatch(APP_STATE_ACTIONS.HIDE_CREATE_PROJECT_BUTTON);
return;
@ -79,7 +79,14 @@ export default class NewProjectArea extends Vue {
* Indicates if new project creation mock button is shown.
*/
public get isMockButtonShown(): boolean {
return !new ProjectOwning(this.$store).userHasOwnProject() && !this.$store.getters.isBonusCouponApplied;
return !(this.userHasOwnProject || this.$store.getters.canUserCreateFirstProject);
}
/**
* Indicates if user has own project.
*/
private get userHasOwnProject(): boolean {
return new ProjectOwning(this.$store).userHasOwnProject();
}
}
</script>

View File

@ -20,7 +20,7 @@
<p v-if="isResourcesDisplayingButtonShown" @click="toggleResourceItemsVisibility" class="navigation-area__resources-title__button">Show</p>
<p v-if="isResourcesHidingButtonShown" @click="toggleResourceItemsVisibility" class="navigation-area__resources-title__button">Hide</p>
</div>
<a v-if="areResourceItemsShown" class="navigation-area__item-container" href="https://documentation.tardigrade.io/setup/buckets-objects" target="_blank">
<a v-if="areResourceItemsShown" class="navigation-area__item-container" href="https://documentation.tardigrade.io" target="_blank">
<div class="navigation-area__item-container__link-container">
<DocsIcon class="svg"/>
<h1 class="navigation-area__item-container__link-container__title docs-title">Docs</h1>

View File

@ -21,7 +21,7 @@
is-white="true"
/>
<VButton
label="Create API Key"
label="Create an API Key"
width="214px"
height="50px"
:on-press="onCreateAPIKeyClick"

View File

@ -75,9 +75,6 @@ export const appStateModule = {
[APP_STATE_MUTATIONS.TOGGLE_EDIT_PROFILE_POPUP](state: any): void {
state.appState.isEditProfilePopupShown = !state.appState.isEditProfilePopupShown;
},
[APP_STATE_MUTATIONS.TOGGLE_CONTENT_BLUR](state: any): void {
state.appState.isContentBlurShown = !state.appState.isContentBlurShown;
},
[APP_STATE_MUTATIONS.SHOW_SET_DEFAULT_PAYMENT_METHOD_POPUP](state: any, id: string): void {
state.appState.setDefaultPaymentMethodID = id;
},
@ -90,6 +87,12 @@ export const appStateModule = {
[APP_STATE_MUTATIONS.HIDE_CREATE_PROJECT_BUTTON](state: any): void {
state.appState.isCreateProjectButtonShown = false;
},
[APP_STATE_MUTATIONS.SHOW_CONTENT_BLUR](state: any): void {
state.appState.isContentBlurShown = true;
},
[APP_STATE_MUTATIONS.HIDE_CONTENT_BLUR](state: any): void {
state.appState.isContentBlurShown = false;
},
// Mutation that closes each popup/dropdown
[APP_STATE_MUTATIONS.CLOSE_ALL](state: any): void {
state.appState.isAccountDropdownShown = false;
@ -180,9 +183,6 @@ export const appStateModule = {
[APP_STATE_ACTIONS.TOGGLE_EDIT_PROFILE_POPUP]: function ({commit}: any): void {
commit(APP_STATE_MUTATIONS.TOGGLE_EDIT_PROFILE_POPUP);
},
[APP_STATE_ACTIONS.TOGGLE_CONTENT_BLUR]: function ({commit}: any): void {
commit(APP_STATE_MUTATIONS.TOGGLE_CONTENT_BLUR);
},
[APP_STATE_ACTIONS.SHOW_SET_DEFAULT_PAYMENT_METHOD_POPUP]: function ({commit, state}: any, methodID: string): void {
if (!state.appState.setDefaultPaymentMethodID) {
commit(APP_STATE_MUTATIONS.CLOSE_ALL);
@ -203,6 +203,12 @@ export const appStateModule = {
[APP_STATE_ACTIONS.HIDE_CREATE_PROJECT_BUTTON]: function ({commit}: any): void {
commit(APP_STATE_MUTATIONS.HIDE_CREATE_PROJECT_BUTTON);
},
[APP_STATE_ACTIONS.SHOW_CONTENT_BLUR]: function ({commit}: any): void {
commit(APP_STATE_MUTATIONS.SHOW_CONTENT_BLUR);
},
[APP_STATE_ACTIONS.HIDE_CONTENT_BLUR]: function ({commit}: any): void {
commit(APP_STATE_MUTATIONS.HIDE_CONTENT_BLUR);
},
[APP_STATE_ACTIONS.CLOSE_POPUPS]: function ({commit}: any): void {
commit(APP_STATE_MUTATIONS.CLOSE_ALL);
},

View File

@ -224,7 +224,7 @@ export function makePaymentsModule(api: PaymentsApi): StoreModule<PaymentsState>
},
},
getters: {
isBonusCouponApplied: (state: PaymentsState): boolean => {
canUserCreateFirstProject: (state: PaymentsState): boolean => {
return state.billingHistory.some((billingItem: BillingHistoryItem) => {
return billingItem.amount >= 50 && billingItem.type === BillingHistoryItemType.Transaction
&& billingItem.status === BillingHistoryItemStatus.Completed;

View File

@ -29,7 +29,8 @@ export const APP_STATE_MUTATIONS = {
SET_NAME: 'SET_NAME',
SHOW_CREATE_PROJECT_BUTTON: 'SHOW_CREATE_PROJECT_BUTTON',
HIDE_CREATE_PROJECT_BUTTON: 'HIDE_CREATE_PROJECT_BUTTON',
TOGGLE_CONTENT_BLUR: 'TOGGLE_CONTENT_BLUR',
SHOW_CONTENT_BLUR: 'SHOW_CONTENT_BLUR',
HIDE_CONTENT_BLUR: 'HIDE_CONTENT_BLUR',
};
export const PROJECT_PAYMENT_METHODS_MUTATIONS = {

View File

@ -23,7 +23,8 @@ export const APP_STATE_ACTIONS = {
SET_SATELLITE_NAME: 'SET_SATELLITE_NAME',
SHOW_CREATE_PROJECT_BUTTON: 'SHOW_CREATE_PROJECT_BUTTON',
HIDE_CREATE_PROJECT_BUTTON: 'HIDE_CREATE_PROJECT_BUTTON',
TOGGLE_CONTENT_BLUR: 'TOGGLE_CONTENT_BLUR',
SHOW_CONTENT_BLUR: 'SHOW_CONTENT_BLUR',
HIDE_CONTENT_BLUR: 'HIDE_CONTENT_BLUR',
};
export const NOTIFICATION_ACTIONS = {

View File

@ -157,8 +157,8 @@ export default class DashboardArea extends Vue {
if (!projects.length) {
await this.$store.dispatch(APP_STATE_ACTIONS.CHANGE_STATE, AppState.LOADED_EMPTY);
if (this.$store.getters.isBonusCouponApplied) {
await this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_CONTENT_BLUR);
if (this.$store.getters.canUserCreateFirstProject) {
await this.$store.dispatch(APP_STATE_ACTIONS.SHOW_CONTENT_BLUR);
}
if (!this.isRouteAccessibleWithoutProject()) {
@ -205,8 +205,8 @@ export default class DashboardArea extends Vue {
await this.$notify.error(`Unable to fetch buckets. ${error.message}`);
}
if (this.$store.getters.isBonusCouponApplied && !new ProjectOwning(this.$store).userHasOwnProject()) {
await this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_CONTENT_BLUR);
if (this.$store.getters.canUserCreateFirstProject && !new ProjectOwning(this.$store).userHasOwnProject()) {
await this.$store.dispatch(APP_STATE_ACTIONS.SHOW_CONTENT_BLUR);
}
await this.$store.dispatch(APP_STATE_ACTIONS.CHANGE_STATE, AppState.LOADED);
@ -281,7 +281,7 @@ export default class DashboardArea extends Vue {
* Hides blur.
*/
public onCloseClick(): void {
this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_CONTENT_BLUR);
this.$store.dispatch(APP_STATE_ACTIONS.HIDE_CONTENT_BLUR);
}
/**

View File

@ -51,7 +51,7 @@
</div>
</div>
<div class="login-area__info-area">
<p class="login-area__info-area__signature">Storj Labs Inc 2019.</p>
<p class="login-area__info-area__signature">Storj Labs Inc 2020.</p>
<a class="login-area__info-area__terms" href="https://tardigrade.io/terms-of-use/" target="_blank">Terms & Conditions</a>
<a class="login-area__info-area__help" href="mailto:support@storj.io" target="_blank">Support</a>
</div>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -49,7 +49,7 @@ exports[`NavigationArea snapshot not changed with project 1`] = `
<p class="navigation-area__resources-title__title">RESOURCES</p>
<!---->
<!---->
</div> <a href="https://documentation.tardigrade.io/setup/buckets-objects" target="_blank" class="navigation-area__item-container">
</div> <a href="https://documentation.tardigrade.io" target="_blank" class="navigation-area__item-container">
<div class="navigation-area__item-container__link-container">
<docsicon-stub class="svg"></docsicon-stub>
<h1 class="navigation-area__item-container__link-container__title docs-title">Docs</h1>
@ -131,7 +131,7 @@ exports[`NavigationArea snapshot not changed without project 1`] = `
<p class="navigation-area__resources-title__title">RESOURCES</p>
<!---->
<!---->
</div> <a href="https://documentation.tardigrade.io/setup/buckets-objects" target="_blank" class="navigation-area__item-container">
</div> <a href="https://documentation.tardigrade.io" target="_blank" class="navigation-area__item-container">
<div class="navigation-area__item-container__link-container">
<docsicon-stub class="svg"></docsicon-stub>
<h1 class="navigation-area__item-container__link-container__title docs-title">Docs</h1>

View File

@ -15,7 +15,7 @@ exports[`ProjectCreationSuccessPopup.vue renders correctly 1`] = `
<a href="https://documentation.tardigrade.io/api-reference/uplink-cli" target="_blank" class="project-creation-success-popup__form-container__confirmation-text__link">Uplink CLI.</a></p>
<div class="project-creation-success-popup__form-container__button-container">
<vbutton-stub label="I will do it later" width="214px" height="50px" iswhite="true" onpress="function () { [native code] }"></vbutton-stub>
<vbutton-stub label="Create API Key" width="214px" height="50px" onpress="function () { [native code] }"></vbutton-stub>
<vbutton-stub label="Create an API Key" width="214px" height="50px" onpress="function () { [native code] }"></vbutton-stub>
</div>
</div>
<div class="project-creation-success-popup__close-cross-container">

View File

@ -84,7 +84,7 @@ describe('Dashboard', () => {
});
it('renders correctly without project and with payment method', async () => {
store.commit(APP_STATE_MUTATIONS.TOGGLE_CONTENT_BLUR);
store.commit(APP_STATE_MUTATIONS.SHOW_CONTENT_BLUR);
const wrapper = shallowMount(DashboardArea, {
store,