web/satellite: onboarding tour: adding payment methods step
Change-Id: I40c6680de4778700611f2f6978a02688d50d792f
@ -57,9 +57,11 @@ import VDatepicker from '@/components/common/VDatePicker.vue';
|
||||
|
||||
import DatePickerIcon from '@/../static/images/account/billing/datePicker.svg';
|
||||
|
||||
import { RouteConfig } from '@/router';
|
||||
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
|
||||
import { PROJECTS_ACTIONS } from '@/store/modules/projects';
|
||||
import { DateRange } from '@/types/payments';
|
||||
import { Project } from '@/types/projects';
|
||||
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
|
||||
import { SegmentEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { ProjectOwning } from '@/utils/projectOwning';
|
||||
@ -93,6 +95,12 @@ export default class BillingArea extends Vue {
|
||||
* Fetches billing history and project limits.
|
||||
*/
|
||||
public async beforeMount(): Promise<void> {
|
||||
if (!this.$store.getters.selectedProject.id) {
|
||||
await this.$router.push(RouteConfig.OnboardingTour.path);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await this.$store.dispatch(PAYMENTS_ACTIONS.GET_BILLING_HISTORY);
|
||||
if (this.$store.getters.canUserCreateFirstProject && !this.userHasOwnProject) {
|
||||
@ -103,10 +111,6 @@ export default class BillingArea extends Vue {
|
||||
await this.$notify.error(error.message);
|
||||
}
|
||||
|
||||
if (!this.$store.getters.selectedProject.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await this.$store.dispatch(PROJECTS_ACTIONS.GET_LIMITS, this.$store.getters.selectedProject.id);
|
||||
} catch (error) {
|
||||
|
@ -5,9 +5,7 @@
|
||||
<div class="billing-history-area">
|
||||
<div class="billing-history-area__title-area" @click="onBackToAccountClick">
|
||||
<div class="billing-history-area__title-area__back-button">
|
||||
<svg width="13" height="13" viewBox="0 0 13 13" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path class="billing-history-svg-path" fill-rule="evenodd" clip-rule="evenodd" d="M7.22572 0.300601C7.62652 0.701402 7.62652 1.35123 7.22572 1.75203L3.50406 5.47368H11.9737C12.5405 5.47368 13 5.93318 13 6.5C13 7.06682 12.5405 7.52632 11.9737 7.52632H3.50406L7.22572 11.248C7.62652 11.6488 7.62652 12.2986 7.22572 12.6994C6.82491 13.1002 6.17509 13.1002 5.77429 12.6994L0.300601 7.22571C-0.1002 6.82491 -0.1002 6.17509 0.300601 5.77428L5.77429 0.300601C6.17509 -0.1002 6.82491 -0.1002 7.22572 0.300601Z" fill="#384B65"/>
|
||||
</svg>
|
||||
<BackImage/>
|
||||
</div>
|
||||
<p class="billing-history-area__title-area__title">Back to Account</p>
|
||||
</div>
|
||||
@ -36,6 +34,8 @@ import BillingItem from '@/components/account/billing/billingHistory/BillingItem
|
||||
import SortingHeader from '@/components/account/billing/billingHistory/SortingHeader.vue';
|
||||
import VPagination from '@/components/common/VPagination.vue';
|
||||
|
||||
import BackImage from '@/../static/images/account/billing/back.svg';
|
||||
|
||||
import { RouteConfig } from '@/router';
|
||||
import { BillingHistoryItem } from '@/types/payments';
|
||||
import { SegmentEvent } from '@/utils/constants/analyticsEventNames';
|
||||
@ -45,6 +45,7 @@ import { SegmentEvent } from '@/utils/constants/analyticsEventNames';
|
||||
BillingItem,
|
||||
SortingHeader,
|
||||
VPagination,
|
||||
BackImage,
|
||||
},
|
||||
})
|
||||
export default class BillingHistory extends Vue {
|
||||
@ -118,7 +119,7 @@ export default class BillingHistory extends Vue {
|
||||
.billing-history-area__title-area__back-button {
|
||||
background-color: #2683ff;
|
||||
|
||||
.billing-history-svg-path {
|
||||
.back-button-svg-path {
|
||||
fill: #fff;
|
||||
}
|
||||
}
|
||||
|
@ -54,8 +54,6 @@ export default class AddCardForm extends Vue {
|
||||
|
||||
try {
|
||||
await this.$store.dispatch(ADD_CREDIT_CARD, token);
|
||||
await this.$store.dispatch(GET_BILLING_HISTORY);
|
||||
await this.$store.dispatch(GET_BALANCE);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
|
||||
|
@ -114,13 +114,13 @@ export default class AddStorjForm extends Vue {
|
||||
*/
|
||||
private get isDepositValueValid(): boolean {
|
||||
switch (true) {
|
||||
case (this.tokenDepositValue < 50 || this.tokenDepositValue >= this.MAX_TOKEN_AMOUNT) && !this.userHasOwnProject:
|
||||
this.$notify.error('First deposit amount must be more than 50 and less than 1000000');
|
||||
case (this.tokenDepositValue < this.DEFAULT_TOKEN_DEPOSIT_VALUE || this.tokenDepositValue >= this.MAX_TOKEN_AMOUNT) && !this.userHasOwnProject:
|
||||
this.$notify.error('First deposit amount must be more than $50 and less than $1000000');
|
||||
this.setDefault();
|
||||
|
||||
return false;
|
||||
case this.tokenDepositValue >= this.MAX_TOKEN_AMOUNT || this.tokenDepositValue === 0:
|
||||
this.$notify.error('Deposit amount must be more than 0 and less than 1000000');
|
||||
this.$notify.error('Deposit amount must be more than $0 and less than $1000000');
|
||||
this.setDefault();
|
||||
|
||||
return false;
|
||||
|
@ -65,7 +65,6 @@
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
import { PaymentAmountOption } from '@/types/payments';
|
||||
import { Project } from '@/types/projects';
|
||||
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
|
||||
import { ProjectOwning } from '@/utils/projectOwning';
|
||||
|
||||
@ -276,6 +275,7 @@ export default class TokenDepositSelection extends Vue {
|
||||
|
||||
&__svg {
|
||||
cursor: pointer;
|
||||
min-height: 25px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -113,6 +113,10 @@ export default class VButton extends Vue {
|
||||
}
|
||||
}
|
||||
|
||||
&.blue-white {
|
||||
border: 2px solid #2683ff !important;
|
||||
}
|
||||
|
||||
&.red {
|
||||
box-shadow: none !important;
|
||||
background-color: transparent !important;
|
||||
|
@ -4,7 +4,7 @@
|
||||
<template>
|
||||
<div class="account-dropdown-choice-container" id="accountDropdown">
|
||||
<div class="account-dropdown-overflow-container">
|
||||
<div class="account-dropdown-item-container settings" @click="onAccountSettingsClick">
|
||||
<div class="account-dropdown-item-container settings" v-if="!isOnboardingTour" @click="onAccountSettingsClick">
|
||||
<div class="account-dropdown-item-container__image-container">
|
||||
<AccountSettingsIcon class="account-dropdown-item-container__image-container__image"/>
|
||||
</div>
|
||||
@ -48,6 +48,13 @@ import { LocalData } from '@/utils/localData';
|
||||
export default class AccountDropdown extends Vue {
|
||||
private readonly auth: AuthHttpApi = new AuthHttpApi();
|
||||
|
||||
/**
|
||||
* Indicates if current route is onboarding tour.
|
||||
*/
|
||||
public get isOnboardingTour(): boolean {
|
||||
return this.$route.name === RouteConfig.OnboardingTour.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes account dropdown.
|
||||
*/
|
||||
|
@ -3,14 +3,6 @@
|
||||
|
||||
<template>
|
||||
<div class="new-project-container">
|
||||
<VInfo
|
||||
v-if="isMockButtonShown"
|
||||
text="Please add a payment method"
|
||||
>
|
||||
<div class="new-project-button-mock">
|
||||
<h1 class="new-project-button-mock__label">+ Create Project</h1>
|
||||
</div>
|
||||
</VInfo>
|
||||
<div
|
||||
v-if="isButtonShown"
|
||||
class="new-project-button-container"
|
||||
@ -75,13 +67,6 @@ export default class NewProjectArea extends Vue {
|
||||
return this.$store.state.appStateModule.appState.isCreateProjectButtonShown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if new project creation mock button is shown.
|
||||
*/
|
||||
public get isMockButtonShown(): boolean {
|
||||
return !(this.userHasOwnProject || this.$store.getters.canUserCreateFirstProject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if user has own project.
|
||||
*/
|
||||
@ -124,39 +109,4 @@ export default class NewProjectArea extends Vue {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.new-project-button-mock {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 156px;
|
||||
height: 40px;
|
||||
border-radius: 6px;
|
||||
background-color: #dadde5;
|
||||
border: 1px solid #dadde5;
|
||||
|
||||
&__label {
|
||||
font-family: 'font_medium', sans-serif;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
color: #acb0bc;
|
||||
}
|
||||
}
|
||||
|
||||
/deep/ .info__message-box {
|
||||
background-image: url('../../../static/images/header/info.png');
|
||||
background-repeat: no-repeat;
|
||||
height: auto;
|
||||
width: auto;
|
||||
top: 41px;
|
||||
left: 157px;
|
||||
padding: 30px 20px 25px 20px;
|
||||
white-space: nowrap;
|
||||
|
||||
&__text {
|
||||
text-align: left;
|
||||
font-size: 13px;
|
||||
line-height: 17px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -31,29 +31,44 @@ export default class NavigationArea extends Vue {
|
||||
*/
|
||||
public areResourceItemsShown: boolean = true;
|
||||
public isResourceButtonShown: boolean = false;
|
||||
|
||||
/**
|
||||
* Indicates if account related navigation links appears.
|
||||
*/
|
||||
public areAccountItemsShown: boolean = true;
|
||||
public isAccountButtonShown: boolean = false;
|
||||
public homePath: string = RouteConfig.Account.with(RouteConfig.Billing).path;
|
||||
|
||||
/**
|
||||
* Toggles resource items visibility.
|
||||
*/
|
||||
public toggleResourceItemsVisibility(): void {
|
||||
this.areResourceItemsShown = !this.areResourceItemsShown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles resource button visibility.
|
||||
*/
|
||||
public toggleResourceButtonVisibility(): void {
|
||||
this.isResourceButtonShown = !this.isResourceButtonShown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles account items visibility.
|
||||
*/
|
||||
public toggleAccountItemsVisibility(): void {
|
||||
this.areAccountItemsShown = !this.areAccountItemsShown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles account button visibility.
|
||||
*/
|
||||
public toggleAccountButtonVisibility(): void {
|
||||
this.isAccountButtonShown = !this.isAccountButtonShown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Array of navigation links with icons.
|
||||
*/
|
||||
// TODO: Use SvgLoaderComponent to reduce markup lines
|
||||
public readonly navigation: NavigationLink[] = [
|
||||
RouteConfig.ProjectDashboard.withIcon(
|
||||
@ -73,6 +88,9 @@ export default class NavigationArea extends Vue {
|
||||
`),
|
||||
];
|
||||
|
||||
/**
|
||||
* Array of account related navigation links.
|
||||
*/
|
||||
public readonly accountNavigation: NavigationLink[] = [
|
||||
RouteConfig.Account.with(RouteConfig.Settings),
|
||||
RouteConfig.Account.with(RouteConfig.Billing),
|
||||
@ -80,25 +98,65 @@ export default class NavigationArea extends Vue {
|
||||
// RouteConfig.Account.with(RouteConfig.Referral),
|
||||
];
|
||||
|
||||
public get isLinkDisabled(): boolean {
|
||||
return this.$store.state.projectsModule.selectedProject.id === '';
|
||||
/**
|
||||
* Returns home path depending on app's state.
|
||||
*/
|
||||
public get homePath(): string {
|
||||
if (this.isOnboardingTour) {
|
||||
return RouteConfig.OnboardingTour.path;
|
||||
}
|
||||
|
||||
return RouteConfig.ProjectDashboard.path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if resources displaying button is shown.
|
||||
*/
|
||||
public get isResourcesDisplayingButtonShown(): boolean {
|
||||
return !this.areResourceItemsShown && this.isResourceButtonShown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if resources items hiding button is shown.
|
||||
*/
|
||||
public get isResourcesHidingButtonShown(): boolean {
|
||||
return this.areResourceItemsShown && this.isResourceButtonShown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if account items displaying button is shown.
|
||||
*/
|
||||
public get isAccountItemsDisplayingButtonShown(): boolean {
|
||||
return !this.areAccountItemsShown && this.isAccountButtonShown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if account items hiding button is shown.
|
||||
*/
|
||||
public get isAccountItemsHidingButtonShown(): boolean {
|
||||
return this.areAccountItemsShown && this.isAccountButtonShown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if roter link is disabled.
|
||||
*/
|
||||
public get isLinkDisabled(): boolean {
|
||||
return this.isOnboardingTour || this.isNoProject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if current route is onboarding tour.
|
||||
*/
|
||||
private get isOnboardingTour(): boolean {
|
||||
return this.$route.name === RouteConfig.OnboardingTour.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if there is no projects.
|
||||
*/
|
||||
private get isNoProject(): boolean {
|
||||
return this.$store.state.projectsModule.projects.length === 0;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -9,41 +9,100 @@
|
||||
</router-link>
|
||||
<ProjectSelectionArea class="project-selection-area"/>
|
||||
<p class="navigation-area__project-title">PROJECT</p>
|
||||
<router-link :aria-label="navItem.name" class="navigation-area__item-container" :class="{ disabled: isLinkDisabled }" v-for="navItem in navigation" :key="navItem.name" :to="navItem.path">
|
||||
<router-link
|
||||
:aria-label="navItem.name"
|
||||
class="navigation-area__item-container"
|
||||
:class="{ disabled: isLinkDisabled }"
|
||||
v-for="navItem in navigation"
|
||||
:key="navItem.name"
|
||||
:to="navItem.path"
|
||||
>
|
||||
<div class="navigation-area__item-container__link-container">
|
||||
<div v-html="navItem.icon"></div>
|
||||
<h1 class="navigation-area__item-container__link-container__title">{{navItem.name}}</h1>
|
||||
</div>
|
||||
</router-link>
|
||||
<div class="navigation-area__resources-title" :class="{ custom: areResourceItemsShown }" @mouseenter="toggleResourceButtonVisibility" @mouseleave="toggleResourceButtonVisibility">
|
||||
<div
|
||||
class="navigation-area__resources-title"
|
||||
:class="{ custom: areResourceItemsShown }"
|
||||
@mouseenter="toggleResourceButtonVisibility"
|
||||
@mouseleave="toggleResourceButtonVisibility"
|
||||
>
|
||||
<p class="navigation-area__resources-title__title">RESOURCES</p>
|
||||
<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>
|
||||
<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" target="_blank">
|
||||
<a
|
||||
v-if="areResourceItemsShown"
|
||||
class="navigation-area__item-container"
|
||||
:class="{ disabled: isLinkDisabled }"
|
||||
href="https://documentation.storj.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>
|
||||
</div>
|
||||
</a>
|
||||
<a v-if="areResourceItemsShown" class="navigation-area__item-container support-item" href="mailto:support@storj.io" target="_blank">
|
||||
<a
|
||||
v-if="areResourceItemsShown"
|
||||
class="navigation-area__item-container support-item"
|
||||
:class="{ disabled: isLinkDisabled }"
|
||||
href="mailto:support@storj.io"
|
||||
target="_blank"
|
||||
>
|
||||
<div class="navigation-area__item-container__link-container">
|
||||
<SupportIcon class="svg"/>
|
||||
<h1 class="navigation-area__item-container__link-container__title">Support</h1>
|
||||
</div>
|
||||
</a>
|
||||
<div class="navigation-area__account-title" :class="{custom: areAccountItemsShown}" @mouseenter="toggleAccountButtonVisibility" @mouseleave="toggleAccountButtonVisibility">
|
||||
<div
|
||||
class="navigation-area__account-title"
|
||||
:class="{ custom: areAccountItemsShown }"
|
||||
@mouseenter="toggleAccountButtonVisibility"
|
||||
@mouseleave="toggleAccountButtonVisibility"
|
||||
>
|
||||
<p class="navigation-area__account-title__title">ACCOUNT</p>
|
||||
<p v-if="isAccountItemsDisplayingButtonShown" @click="toggleAccountItemsVisibility" class="navigation-area__account-title__button">Show</p>
|
||||
<p v-if="isAccountItemsHidingButtonShown" @click="toggleAccountItemsVisibility" class="navigation-area__account-title__button">Hide</p>
|
||||
<p
|
||||
v-if="isAccountItemsDisplayingButtonShown"
|
||||
@click="toggleAccountItemsVisibility"
|
||||
class="navigation-area__account-title__button"
|
||||
>
|
||||
Show
|
||||
</p>
|
||||
<p
|
||||
v-if="isAccountItemsHidingButtonShown"
|
||||
@click="toggleAccountItemsVisibility"
|
||||
class="navigation-area__account-title__button"
|
||||
>
|
||||
Hide
|
||||
</p>
|
||||
</div>
|
||||
<div v-if="areAccountItemsShown" class="navigation-area__account-area">
|
||||
<router-link class="navigation-area__item-container account-item" v-for="navItem in accountNavigation" :key="navItem.name" :to="navItem.path">
|
||||
<router-link
|
||||
class="navigation-area__item-container account-item"
|
||||
:class="{ disabled: isLinkDisabled }"
|
||||
v-for="navItem in accountNavigation"
|
||||
:key="navItem.name"
|
||||
:to="navItem.path"
|
||||
>
|
||||
<div class="navigation-area__item-container__link-container" >
|
||||
<h1 class="navigation-area__item-container__link-container__title account-item">{{navItem.name}}</h1>
|
||||
</div>
|
||||
</router-link>
|
||||
</div>
|
||||
<div class="divider" :class="{'custom-divider': areAccountItemsShown}"></div>
|
||||
<div class="divider" :class="{ 'custom-divider': areAccountItemsShown }"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -152,6 +152,7 @@ a {
|
||||
}
|
||||
|
||||
.disabled {
|
||||
cursor: not-allowed;
|
||||
pointer-events: none;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
@ -0,0 +1,102 @@
|
||||
// Copyright (C) 2020 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
<template>
|
||||
<div class="tour-area">
|
||||
<ProgressBar/>
|
||||
<OverviewStep
|
||||
v-if="isDefaultState"
|
||||
@setAddPaymentState="setAddPaymentState"
|
||||
/>
|
||||
<AddPaymentStep
|
||||
v-if="isAddPaymentState"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
import ProgressBar from '@/components/onboardingTour/ProgressBar.vue';
|
||||
import AddPaymentStep from '@/components/onboardingTour/steps/AddPaymentStep.vue';
|
||||
import OverviewStep from '@/components/onboardingTour/steps/OverviewStep.vue';
|
||||
|
||||
import CheckedImage from '@/../static/images/common/checked.svg';
|
||||
|
||||
import { RouteConfig } from '@/router';
|
||||
import { TourState } from '@/utils/constants/onboardingTourEnums';
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
AddPaymentStep,
|
||||
ProgressBar,
|
||||
OverviewStep,
|
||||
CheckedImage,
|
||||
},
|
||||
})
|
||||
|
||||
export default class OnboardingTourArea extends Vue {
|
||||
public areaState: number = TourState.DEFAULT;
|
||||
|
||||
/**
|
||||
* Lifecycle hook after initial render.
|
||||
* Sets area to needed state.
|
||||
*/
|
||||
public mounted(): void {
|
||||
if (this.$store.state.projectsModule.projects.length > 0) {
|
||||
try {
|
||||
this.$router.push(RouteConfig.ProjectDashboard.path);
|
||||
} catch (error) {
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.$store.getters.isTransactionProcessing || this.$store.getters.isTransactionCompleted) {
|
||||
this.setAddPaymentState();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if area is in default state.
|
||||
*/
|
||||
public get isDefaultState(): boolean {
|
||||
return this.areaState === TourState.DEFAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if area is adding payment method state.
|
||||
*/
|
||||
public get isAddPaymentState(): boolean {
|
||||
return this.areaState === TourState.ADDING_PAYMENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets area's state to adding payment method state.
|
||||
*/
|
||||
public setAddPaymentState(): void {
|
||||
this.areaState = TourState.ADDING_PAYMENT;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.tour-area {
|
||||
padding: 0 100px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1380px) {
|
||||
|
||||
.tour-area {
|
||||
padding: 0 50px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1000px) {
|
||||
|
||||
.tour-area {
|
||||
padding: 0 25px;
|
||||
}
|
||||
}
|
||||
</style>
|
102
web/satellite/src/components/onboardingTour/ProgressBar.vue
Normal file
@ -0,0 +1,102 @@
|
||||
// Copyright (C) 2020 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
<template>
|
||||
<div class="progress-bar-container">
|
||||
<div class="progress-bar-container__progress-area">
|
||||
<div class="progress-bar-container__progress-area__circle">
|
||||
<CheckedImage/>
|
||||
</div>
|
||||
<div class="progress-bar-container__progress-area__bar"/>
|
||||
<div class="progress-bar-container__progress-area__circle">
|
||||
<CheckedImage/>
|
||||
</div>
|
||||
<div class="progress-bar-container__progress-area__bar"/>
|
||||
<div class="progress-bar-container__progress-area__circle">
|
||||
<CheckedImage/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-bar-container__titles-area">
|
||||
<span class="progress-bar-container__titles-area__title">Name Your Project</span>
|
||||
<span class="progress-bar-container__titles-area__title api-key-title">Create an API Key</span>
|
||||
<span class="progress-bar-container__titles-area__title">Upload Data</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
import CheckedImage from '@/../static/images/common/checked.svg';
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
CheckedImage,
|
||||
},
|
||||
})
|
||||
|
||||
export default class ProgressBar extends Vue {}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.progress-bar-container {
|
||||
width: 100%;
|
||||
|
||||
&__progress-area {
|
||||
width: calc(100% - 420px);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 25px 210px 6px 210px;
|
||||
|
||||
&__circle {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-width: 20px;
|
||||
height: 20px;
|
||||
background-color: #c5cbdb;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
&__bar {
|
||||
width: 100%;
|
||||
height: 4px;
|
||||
background-color: #c5cbdb;
|
||||
}
|
||||
}
|
||||
|
||||
&__titles-area {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 188px 0 178px;
|
||||
|
||||
&__title {
|
||||
font-family: 'font_regular', sans-serif;
|
||||
font-size: 10px;
|
||||
line-height: 15px;
|
||||
color: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.api-key-title {
|
||||
padding: 0 15px 0 0;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 800px) {
|
||||
|
||||
.progress-bar-container {
|
||||
|
||||
&__progress-area {
|
||||
width: calc(100% - 300px);
|
||||
padding: 25px 150px 6px 150px;
|
||||
}
|
||||
|
||||
&__titles-area {
|
||||
padding: 0 128px 0 118px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,217 @@
|
||||
// Copyright (C) 2020 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
<template>
|
||||
<div class="payment-step">
|
||||
<h1 class="payment-step__title">Get Started with 5 GB Free</h1>
|
||||
<p class="payment-step__sub-title">
|
||||
Adding a payment method ensures your project won’t be interrupted after your <b>free</b> credit is used.
|
||||
</p>
|
||||
<div class="payment-step__methods-container">
|
||||
<div class="payment-step__methods-container__title-area">
|
||||
<h2 class="payment-step__methods-container__title-area__title">Payment Method</h2>
|
||||
<div class="payment-step__methods-container__title-area__options-area">
|
||||
<span
|
||||
class="payment-step__methods-container__title-area__options-area__token"
|
||||
@click="setAddStorjState"
|
||||
:class="{ selected: isAddStorjState }"
|
||||
>
|
||||
STORJ Token
|
||||
</span>
|
||||
<span
|
||||
class="payment-step__methods-container__title-area__options-area__card"
|
||||
@click="setAddCardState"
|
||||
:class="{ selected: isAddCardState }"
|
||||
>
|
||||
Card
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="payment-step__methods-container__blur" v-if="isLoading"/>
|
||||
</div>
|
||||
<AddCardState
|
||||
v-if="isAddCardState"
|
||||
@toggleIsLoading="toggleIsLoading"
|
||||
/>
|
||||
<AddStorjState
|
||||
v-if="isAddStorjState"
|
||||
@toggleIsLoading="toggleIsLoading"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
import AddCardState from '@/components/onboardingTour/steps/paymentStates/AddCardState.vue';
|
||||
import AddStorjState from '@/components/onboardingTour/steps/paymentStates/AddStorjState.vue';
|
||||
|
||||
import { AddingPaymentState } from '@/utils/constants/onboardingTourEnums';
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
AddStorjState,
|
||||
AddCardState,
|
||||
},
|
||||
})
|
||||
|
||||
export default class AddPaymentStep extends Vue {
|
||||
public areaState: number = AddingPaymentState.ADD_CARD;
|
||||
public isLoading: boolean = false;
|
||||
|
||||
/**
|
||||
* Lifecycle hook after initial render.
|
||||
* Sets area to needed state.
|
||||
*/
|
||||
public mounted(): void {
|
||||
if (this.$store.getters.isTransactionProcessing || this.$store.getters.isTransactionCompleted) {
|
||||
this.setAddStorjState();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if area is in adding card state.
|
||||
*/
|
||||
public get isAddCardState(): boolean {
|
||||
return this.areaState === AddingPaymentState.ADD_CARD;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if area is in adding tokens state.
|
||||
*/
|
||||
public get isAddStorjState(): boolean {
|
||||
return this.areaState === AddingPaymentState.ADD_STORJ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets area to adding card state.
|
||||
*/
|
||||
public setAddCardState(): void {
|
||||
this.areaState = AddingPaymentState.ADD_CARD;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets area to adding tokens state.
|
||||
*/
|
||||
public setAddStorjState(): void {
|
||||
this.areaState = AddingPaymentState.ADD_STORJ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles area's loading state.
|
||||
*/
|
||||
public toggleIsLoading(): void {
|
||||
this.isLoading = !this.isLoading;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
h1,
|
||||
h2,
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.payment-step {
|
||||
font-family: 'font_regular', sans-serif;
|
||||
margin-top: 75px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 140px;
|
||||
|
||||
&__title {
|
||||
font-size: 32px;
|
||||
line-height: 39px;
|
||||
color: #1b2533;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
&__sub-title {
|
||||
font-size: 16px;
|
||||
line-height: 19px;
|
||||
color: #354049;
|
||||
margin-bottom: 35px;
|
||||
text-align: center;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
&__methods-container {
|
||||
padding: 30px 45px 10px 45px;
|
||||
width: calc(100% - 90px);
|
||||
border-radius: 8px 8px 0 0;
|
||||
background-color: #fff;
|
||||
position: relative;
|
||||
|
||||
&__title-area {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
&__title {
|
||||
font-family: 'font_medium', sans-serif;
|
||||
font-size: 22px;
|
||||
line-height: 27px;
|
||||
color: #354049;
|
||||
}
|
||||
|
||||
&__options-area {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
min-height: 21px;
|
||||
|
||||
&__token,
|
||||
&__card {
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
color: #a9b5c1;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&__token {
|
||||
min-width: 110px;
|
||||
}
|
||||
|
||||
&__card {
|
||||
margin-left: 10px;
|
||||
min-width: 65px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__blur {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
border-radius: 8px;
|
||||
background-color: rgba(229, 229, 229, 0.2);
|
||||
z-index: 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.selected {
|
||||
color: #2582ff;
|
||||
border-bottom: 3px solid #2582ff;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1550px) {
|
||||
|
||||
.payment-step {
|
||||
padding: 0 70px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 800px) {
|
||||
|
||||
.payment-step {
|
||||
padding: 0 25px;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,7 +1,7 @@
|
||||
// Copyright (C) 2019 Storj Labs, Inc.
|
||||
// Copyright (C) 2020 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
<template src="./OverviewArea.html"></template>
|
||||
<template src="./overviewStep.html"></template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
@ -12,8 +12,6 @@ import FirstStepIcon from '@/../static/images/common/one.svg';
|
||||
import ThirdStepIcon from '@/../static/images/common/three.svg';
|
||||
import SecondStepIcon from '@/../static/images/common/two.svg';
|
||||
|
||||
import { RouteConfig } from '@/router';
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
VButton,
|
||||
@ -22,9 +20,15 @@ import { RouteConfig } from '@/router';
|
||||
SecondStepIcon,
|
||||
},
|
||||
})
|
||||
export default class OverviewArea extends Vue {
|
||||
public readonly billingPath: string = RouteConfig.Account.with(RouteConfig.Billing).path;
|
||||
export default class OverviewStep extends Vue {
|
||||
/**
|
||||
* Holds button click logic.
|
||||
* Sets tour state to adding payment method state.
|
||||
*/
|
||||
public onClick(): void {
|
||||
this.$emit('setAddPaymentState');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss" src="./OverviewArea.scss"></style>
|
||||
<style scoped lang="scss" src="./overviewStep.scss"></style>
|
@ -0,0 +1,43 @@
|
||||
<!--Copyright (C) 2020 Storj Labs, Inc.-->
|
||||
<!--See LICENSE for copying information.-->
|
||||
|
||||
<div class="overview-area">
|
||||
<h1 class="overview-area__title">Welcome to Storj</h1>
|
||||
<p class="overview-area__sub-title">
|
||||
You’re just a few steps away from uploading your first object to the 100% secure, decentralized cloud. After
|
||||
adding payment, you’ll create a project, API key, get set up with Storj, and start uploading objects.
|
||||
</p>
|
||||
<div class="overview-area__steps-area">
|
||||
<div class="overview-area__steps-area__step">
|
||||
<FirstStepIcon class="overview-area__steps-area__step__icon"/>
|
||||
<img class="overview-step-image" src="@/../static/images/onboardingTour/project.jpg" alt="project image">
|
||||
<h2 class="overview-area__steps-area__step__title">Name Your Project</h2>
|
||||
<span class="overview-area__steps-area__step__subtitle">
|
||||
Projects are where buckets are created for storing data.
|
||||
</span>
|
||||
</div>
|
||||
<div class="overview-area__steps-area__step second-step">
|
||||
<SecondStepIcon class="overview-area__steps-area__step__icon"/>
|
||||
<img class="overview-step-image" src="@/../static/images/onboardingTour/api-key.jpg" alt="api keys image">
|
||||
<h2 class="overview-area__steps-area__step__title">Create an API Key</h2>
|
||||
<span class="overview-area__steps-area__step__subtitle">
|
||||
Generate access to your project to upload data.
|
||||
</span>
|
||||
</div>
|
||||
<div class="overview-area__steps-area__step">
|
||||
<ThirdStepIcon class="overview-area__steps-area__step__icon"/>
|
||||
<img class="overview-step-image" src="@/../static/images/onboardingTour/uplink.jpg" alt="uplink image">
|
||||
<h2 class="overview-area__steps-area__step__title">Upload Data</h2>
|
||||
<span class="overview-area__steps-area__step__subtitle">
|
||||
Store your data on the secure, decentralized cloud.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<VButton
|
||||
class="get-started-button"
|
||||
label="Get Started"
|
||||
width="251px"
|
||||
height="56px"
|
||||
:on-press="onClick"
|
||||
/>
|
||||
</div>
|
@ -0,0 +1,89 @@
|
||||
// Copyright (C) 2020 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
p,
|
||||
h1,
|
||||
h2 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.overview-area {
|
||||
width: auto;
|
||||
padding: 75px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-family: 'font_regular', sans-serif;
|
||||
background-color: #fff;
|
||||
border-radius: 6px;
|
||||
margin-top: 25px;
|
||||
|
||||
&__title {
|
||||
font-family: 'font_bold', sans-serif;
|
||||
font-size: 32px;
|
||||
line-height: 39px;
|
||||
color: #1b2533;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
&__sub-title {
|
||||
font-size: 16px;
|
||||
line-height: 26px;
|
||||
color: #354049;
|
||||
margin-bottom: 60px;
|
||||
text-align: center;
|
||||
max-width: 815px;
|
||||
}
|
||||
|
||||
&__steps-area {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 50px;
|
||||
|
||||
&__step {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
max-width: 190px;
|
||||
width: 190px;
|
||||
|
||||
&__icon {
|
||||
position: absolute;
|
||||
top: -15px;
|
||||
left: 80px;
|
||||
}
|
||||
|
||||
&__title {
|
||||
font-size: 16px;
|
||||
line-height: 26px;
|
||||
text-align: center;
|
||||
color: #354049;
|
||||
margin: 15px 0 5px 0;
|
||||
}
|
||||
|
||||
&__subtitle {
|
||||
font-family: 'font_regular', sans-serif;
|
||||
font-size: 14px;
|
||||
line-height: 17px;
|
||||
text-align: center;
|
||||
color: #61666b;
|
||||
word-break: break-word;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.second-step {
|
||||
margin: 0 50px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 800px) {
|
||||
|
||||
.second-step {
|
||||
margin: 0 10px;
|
||||
}
|
||||
}
|
@ -0,0 +1,200 @@
|
||||
// Copyright (C) 2020 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
<template>
|
||||
<div class="add-card-state">
|
||||
<div class="add-card-state__input-container">
|
||||
<StripeCardInput
|
||||
ref="stripeCardInput"
|
||||
:on-stripe-response-callback="addCard"
|
||||
/>
|
||||
<div class="add-card-state__input-container__blur" v-if="isLoading"/>
|
||||
</div>
|
||||
<div class="add-card-state__security-info">
|
||||
<LockImage/>
|
||||
<span class="add-card-state__security-info__text">
|
||||
Your card is secured by 128-bit SSL and AES-256 encryption. Your information is secure.
|
||||
</span>
|
||||
</div>
|
||||
<div class="add-card-state__button" :class="{ loading: isLoading }" @click="onConfirmAddStripe">
|
||||
<img
|
||||
v-if="isLoading"
|
||||
class="add-card-state__button__loading-image"
|
||||
src="@/../static/images/account/billing/loading.gif"
|
||||
alt="loading gif"
|
||||
>
|
||||
<span class="add-card-state__button__label">{{ isLoading ? 'Adding' : 'Add Payment' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
import StripeCardInput from '@/components/account/billing/paymentMethods/StripeCardInput.vue';
|
||||
|
||||
import LockImage from '@/../static/images/account/billing/lock.svg';
|
||||
|
||||
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
|
||||
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
|
||||
import { SegmentEvent } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
const {
|
||||
ADD_CREDIT_CARD,
|
||||
GET_CREDIT_CARDS,
|
||||
GET_BILLING_HISTORY,
|
||||
GET_BALANCE,
|
||||
} = PAYMENTS_ACTIONS;
|
||||
|
||||
interface StripeForm {
|
||||
onSubmit(): Promise<void>;
|
||||
}
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
StripeCardInput,
|
||||
LockImage,
|
||||
},
|
||||
})
|
||||
|
||||
export default class AddCardState extends Vue {
|
||||
public isLoading: boolean = false;
|
||||
|
||||
public $refs!: {
|
||||
stripeCardInput: StripeCardInput & StripeForm;
|
||||
};
|
||||
|
||||
/**
|
||||
* Provides card information to Stripe.
|
||||
*/
|
||||
public async onConfirmAddStripe(): Promise<void> {
|
||||
await this.$refs.stripeCardInput.onSubmit();
|
||||
|
||||
this.$segment.track(SegmentEvent.PAYMENT_METHOD_ADDED, {
|
||||
project_id: this.$store.getters.selectedProject.id,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds card after Stripe confirmation.
|
||||
*
|
||||
* @param token from Stripe
|
||||
*/
|
||||
public async addCard(token: string) {
|
||||
if (this.isLoading) return;
|
||||
|
||||
this.isLoading = true;
|
||||
this.$emit('toggleIsLoading');
|
||||
|
||||
try {
|
||||
await this.$store.dispatch(ADD_CREDIT_CARD, token);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
this.setDefaultState();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
await this.$notify.success('Card successfully added');
|
||||
try {
|
||||
await this.$store.dispatch(GET_CREDIT_CARDS);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
}
|
||||
|
||||
this.setDefaultState();
|
||||
|
||||
// TODO: rework after adding next step
|
||||
await this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_NEW_PROJ);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets area to default state.
|
||||
*/
|
||||
private setDefaultState(): void {
|
||||
this.isLoading = false;
|
||||
this.$emit('toggleIsLoading');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.add-card-state {
|
||||
font-family: 'font_regular', sans-serif;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
&__input-container {
|
||||
position: relative;
|
||||
width: calc(100% - 90px);
|
||||
padding: 25px 45px 35px 45px;
|
||||
background-color: #fff;
|
||||
|
||||
&__blur {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: rgba(229, 229, 229, 0.2);
|
||||
z-index: 100;
|
||||
}
|
||||
}
|
||||
|
||||
&__security-info {
|
||||
width: calc(100% - 70px);
|
||||
padding: 15px 35px;
|
||||
background-color: #cef0e3;
|
||||
border-radius: 0 0 8px 8px;
|
||||
margin-bottom: 45px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
&__text {
|
||||
margin-left: 5px;
|
||||
font-size: 15px;
|
||||
line-height: 18px;
|
||||
color: #1a9666;
|
||||
}
|
||||
}
|
||||
|
||||
&__button {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 156px;
|
||||
height: 48px;
|
||||
cursor: pointer;
|
||||
border-radius: 6px;
|
||||
background-color: #2683ff;
|
||||
|
||||
&__loading-image {
|
||||
margin-right: 5px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
&__label {
|
||||
font-family: 'font_medium', sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 23px;
|
||||
color: #fff;
|
||||
word-break: keep-all;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: #0059d0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.loading {
|
||||
opacity: 0.6;
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,221 @@
|
||||
// Copyright (C) 2020 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
<template>
|
||||
<div class="add-storj-state">
|
||||
<div class="add-storj-state__container">
|
||||
<p class="add-storj-state__container__bonus-info">
|
||||
Deposit STORJ Token to your account and receive a 10% bonus, or $10 for every $100.
|
||||
</p>
|
||||
<div class="add-storj-state__container__deposit-area">
|
||||
<p class="add-storj-state__container__deposit-area__info">
|
||||
<b>Please Note:</b> Your first deposit of $50 or more in STORJ Token is applied to your account
|
||||
after Coin Payments verifies payment<br/><br/>5GB are your starting project limits. Increased
|
||||
amounts are available
|
||||
<a
|
||||
class="add-storj-state__container__deposit-area__info__request-link"
|
||||
href="https://support.tardigrade.io/hc/en-us/requests/new?ticket_form_id=360000683212"
|
||||
target="_blank"
|
||||
>
|
||||
per request.
|
||||
</a>
|
||||
</p>
|
||||
<PayingStep
|
||||
v-if="isDefaultState"
|
||||
@toggleIsLoading="toggleIsLoading"
|
||||
@setVerifyingState="setVerifyingState"
|
||||
/>
|
||||
<VerifyingStep
|
||||
v-if="isVerifyingState"
|
||||
@setDefaultState="setDefaultState"
|
||||
/>
|
||||
<VerifiedStep v-if="isVerifiedState"/>
|
||||
</div>
|
||||
<div class="add-storj-state__container__blur" v-if="isLoading"/>
|
||||
</div>
|
||||
<VButton
|
||||
width="222px"
|
||||
height="48px"
|
||||
label="Name Your Project"
|
||||
:on-press="createProject"
|
||||
:is-disabled="isButtonDisabled"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
import PayingStep from '@/components/onboardingTour/steps/paymentStates/tokenSubSteps/PayingStep.vue';
|
||||
import VerifiedStep from '@/components/onboardingTour/steps/paymentStates/tokenSubSteps/VerifiedStep.vue';
|
||||
import VerifyingStep from '@/components/onboardingTour/steps/paymentStates/tokenSubSteps/VerifyingStep.vue';
|
||||
|
||||
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
|
||||
import { AddingStorjState } from '@/utils/constants/onboardingTourEnums';
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
VerifiedStep,
|
||||
VerifyingStep,
|
||||
PayingStep,
|
||||
VButton,
|
||||
},
|
||||
})
|
||||
|
||||
export default class AddStorjState extends Vue {
|
||||
public isLoading: boolean = false;
|
||||
public addingTokenState: number = AddingStorjState.DEFAULT;
|
||||
|
||||
/**
|
||||
* Lifecycle hook after initial render.
|
||||
* Sets area to needed state.
|
||||
*/
|
||||
public beforeMount(): void {
|
||||
switch (true) {
|
||||
case this.$store.getters.isTransactionCompleted:
|
||||
this.setVerifiedState();
|
||||
|
||||
return;
|
||||
case this.$store.getters.isTransactionProcessing:
|
||||
this.setVerifyingState();
|
||||
|
||||
return;
|
||||
default:
|
||||
this.setDefaultState();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if area is in default state.
|
||||
*/
|
||||
public get isDefaultState(): boolean {
|
||||
return this.addingTokenState === AddingStorjState.DEFAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if area is in verifying state.
|
||||
*/
|
||||
public get isVerifyingState(): boolean {
|
||||
return this.addingTokenState === AddingStorjState.VERIFYING;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if area is in verified state.
|
||||
*/
|
||||
public get isVerifiedState(): boolean {
|
||||
return this.addingTokenState === AddingStorjState.VERIFIED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if button is disabled.
|
||||
*/
|
||||
public get isButtonDisabled(): boolean {
|
||||
return !this.$store.getters.canUserCreateFirstProject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets area to default state.
|
||||
*/
|
||||
public setDefaultState(): void {
|
||||
this.addingTokenState = AddingStorjState.DEFAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets area to verifying state.
|
||||
*/
|
||||
public setVerifyingState(): void {
|
||||
this.addingTokenState = AddingStorjState.VERIFYING;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets area to verified state.
|
||||
*/
|
||||
public setVerifiedState(): void {
|
||||
this.addingTokenState = AddingStorjState.VERIFIED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles area's loading state.
|
||||
*/
|
||||
public toggleIsLoading(): void {
|
||||
this.isLoading = !this.isLoading;
|
||||
this.$emit('toggleIsLoading');
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts creating project process.
|
||||
*/
|
||||
public createProject(): void {
|
||||
this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_NEW_PROJ);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
p,
|
||||
h2 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.add-storj-state {
|
||||
font-family: 'font_regular', sans-serif;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
&__container {
|
||||
width: calc(100% - 90px);
|
||||
padding: 20px 45px 45px 45px;
|
||||
background-color: #fff;
|
||||
border-radius: 0 0 8px 8px;
|
||||
margin-bottom: 35px;
|
||||
position: relative;
|
||||
|
||||
&__bonus-info {
|
||||
padding: 20px 30px;
|
||||
width: calc(100% - 60px);
|
||||
background-color: #edf4fe;
|
||||
border-radius: 6px;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
color: #7b8eab;
|
||||
}
|
||||
|
||||
&__deposit-area {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
margin-top: 30px;
|
||||
|
||||
&__info {
|
||||
background-color: rgba(245, 246, 250, 0.65);
|
||||
padding: 35px;
|
||||
border-radius: 6px;
|
||||
font-size: 12px;
|
||||
line-height: 17px;
|
||||
color: #7b8eab;
|
||||
width: calc(40% - 70px);
|
||||
margin-right: 40px;
|
||||
|
||||
&__request-link {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__blur {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: rgba(229, 229, 229, 0.2);
|
||||
z-index: 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,168 @@
|
||||
// Copyright (C) 2020 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
<template>
|
||||
<div class="paying-step">
|
||||
<div class="paying-step__title-area">
|
||||
<img src="@/../static/images/onboardingTour/coins.png" alt="coins image">
|
||||
<h2 class="paying-step__title-area__title">
|
||||
Select Your Deposit Amount
|
||||
</h2>
|
||||
<img
|
||||
v-if="isLoading"
|
||||
class="loading-image"
|
||||
src="@/../static/images/account/billing/loading.gif"
|
||||
alt="loading gif"
|
||||
>
|
||||
</div>
|
||||
<TokenDepositSelection
|
||||
class="paying-step__form"
|
||||
@onChangeTokenValue="onChangeTokenValue"
|
||||
/>
|
||||
<VButton
|
||||
width="100%"
|
||||
height="48px"
|
||||
label="Continue to Coin Payments"
|
||||
:on-press="onConfirmAddSTORJ"
|
||||
:is-blue-white="true"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
import TokenDepositSelection from '@/components/account/billing/paymentMethods/TokenDepositSelection.vue';
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
|
||||
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
|
||||
import { SegmentEvent } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
const {
|
||||
MAKE_TOKEN_DEPOSIT,
|
||||
GET_BILLING_HISTORY,
|
||||
} = PAYMENTS_ACTIONS;
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
VButton,
|
||||
TokenDepositSelection,
|
||||
},
|
||||
})
|
||||
|
||||
export default class PayingStep extends Vue {
|
||||
private readonly DEFAULT_TOKEN_DEPOSIT_VALUE = 50; // in dollars.
|
||||
private readonly MAX_TOKEN_AMOUNT = 1000000; // in dollars.
|
||||
private tokenDepositValue: number = this.DEFAULT_TOKEN_DEPOSIT_VALUE;
|
||||
|
||||
public isLoading: boolean = false;
|
||||
|
||||
/**
|
||||
* Event for changing token deposit value.
|
||||
*/
|
||||
public onChangeTokenValue(value: number): void {
|
||||
this.tokenDepositValue = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* onConfirmAddSTORJ checks if amount is valid and if so process token.
|
||||
* payment and return state to default
|
||||
*/
|
||||
public async onConfirmAddSTORJ(): Promise<void> {
|
||||
if (this.isLoading) return;
|
||||
|
||||
this.isLoading = true;
|
||||
this.$emit('toggleIsLoading');
|
||||
|
||||
if (this.tokenDepositValue < this.DEFAULT_TOKEN_DEPOSIT_VALUE || this.tokenDepositValue >= this.MAX_TOKEN_AMOUNT) {
|
||||
await this.$notify.error('First deposit amount must be more than $50 and less than $1000000');
|
||||
this.setDefaultState();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const tokenResponse = await this.$store.dispatch(MAKE_TOKEN_DEPOSIT, this.tokenDepositValue * 100);
|
||||
await this.$notify.success(`Successfully created new deposit transaction! \nAddress:${tokenResponse.address} \nAmount:${tokenResponse.amount}`);
|
||||
const depositWindow = window.open(tokenResponse.link, '_blank');
|
||||
if (depositWindow) {
|
||||
depositWindow.focus();
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
this.setDefaultState();
|
||||
}
|
||||
|
||||
this.$segment.track(SegmentEvent.PAYMENT_METHOD_ADDED, {
|
||||
project_id: this.$store.getters.selectedProject.id,
|
||||
});
|
||||
|
||||
this.tokenDepositValue = this.DEFAULT_TOKEN_DEPOSIT_VALUE;
|
||||
try {
|
||||
await this.$store.dispatch(GET_BILLING_HISTORY);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
}
|
||||
|
||||
this.setDefaultState();
|
||||
this.$emit('setVerifyingState');
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets area to default state.
|
||||
*/
|
||||
private setDefaultState(): void {
|
||||
this.isLoading = false;
|
||||
this.$emit('toggleIsLoading');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
p,
|
||||
h2 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.paying-step {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 60%;
|
||||
|
||||
&__title-area {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
margin-bottom: 25px;
|
||||
|
||||
&__title {
|
||||
font-size: 20px;
|
||||
line-height: 26px;
|
||||
color: #384b65;
|
||||
margin-left: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
&__form {
|
||||
width: 100%;
|
||||
margin-bottom: 20px;
|
||||
|
||||
/deep/ .selected-container,
|
||||
/deep/ .options-container,
|
||||
/deep/ .payment-selection-blur {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/deep/ .custom-input {
|
||||
width: calc(100% - 61px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.loading-image {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,50 @@
|
||||
// Copyright (C) 2020 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
<template>
|
||||
<div class="verified-step">
|
||||
<VerifiedImage/>
|
||||
<h2 class="verified-step__title">Payment Verified</h2>
|
||||
<span class="verified-step__sub-title">
|
||||
Your payment has been successfully verified. Click the button below to name your project and start uploading data.
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
import VerifiedImage from '@/../static/images/onboardingTour/verified.svg';
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
VerifiedImage,
|
||||
},
|
||||
})
|
||||
|
||||
export default class VerifiedStep extends Vue {}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.verified-step {
|
||||
width: 60%;
|
||||
padding-top: 30px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
font-family: 'font_regular', sans-serif;
|
||||
|
||||
&__title {
|
||||
font-size: 18px;
|
||||
line-height: 22px;
|
||||
color: #354049;
|
||||
}
|
||||
|
||||
&__sub-title {
|
||||
font-size: 12px;
|
||||
line-height: 17px;
|
||||
text-align: center;
|
||||
color: #354049;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,30 @@
|
||||
// Copyright (C) 2020 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
<template src="./verifyingStep.html"></template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
import BackImage from '@/../static/images/account/billing/back.svg';
|
||||
import VerifyingImage from '@/../static/images/onboardingTour/verifying.svg';
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
VerifyingImage,
|
||||
BackImage,
|
||||
},
|
||||
})
|
||||
|
||||
export default class VerifyingStep extends Vue {
|
||||
/**
|
||||
* Holds logic for button click.
|
||||
* Sets area to default state.
|
||||
*/
|
||||
public onBackClick(): void {
|
||||
this.$emit('setDefaultState');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss" src="./verifyingStep.scss"></style>
|
@ -0,0 +1,22 @@
|
||||
<!--Copyright (C) 2020 Storj Labs, Inc.-->
|
||||
<!--See LICENSE for copying information.-->
|
||||
|
||||
<div class="verifying-step">
|
||||
<VerifyingImage/>
|
||||
<h2 class="verifying-step__title">Verifying Payment</h2>
|
||||
<span class="verifying-step__sub-title">
|
||||
Refresh this page in 10-15 minutes to continue after your purchase is verified. In the meantime, see how
|
||||
easy it is to get started visiting documentation page, or join the community to get involved.
|
||||
</span>
|
||||
<div class="verifying-step__buttons-area">
|
||||
<a class="verifying-step__buttons-area__how-to-button" href="https://documentation.storj.io" target="_blank">
|
||||
Documentation
|
||||
</a>
|
||||
<a class="verifying-step__buttons-area__community-button" href="https://storj.io/community/" target="_blank">
|
||||
Community
|
||||
</a>
|
||||
</div>
|
||||
<div class="verifying-step__back-button" @click="onBackClick">
|
||||
<BackImage/>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,89 @@
|
||||
// Copyright (C) 2020 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
.verifying-step {
|
||||
width: 60%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
font-family: 'font_regular', sans-serif;
|
||||
position: relative;
|
||||
|
||||
&__title {
|
||||
font-size: 18px;
|
||||
line-height: 22px;
|
||||
color: #354049;
|
||||
}
|
||||
|
||||
&__sub-title {
|
||||
font-size: 12px;
|
||||
line-height: 17px;
|
||||
text-align: center;
|
||||
color: #354049;
|
||||
}
|
||||
|
||||
&__buttons-area {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
margin-top: 25px;
|
||||
|
||||
&__how-to-button,
|
||||
&__community-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 50%;
|
||||
height: 44px;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
border-radius: 8px;
|
||||
border: 2px solid #2683ff;
|
||||
}
|
||||
|
||||
&__how-to-button {
|
||||
color: #2683ff;
|
||||
background-color: #fff;
|
||||
margin-right: 10px;
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
background-color: #2683ff;
|
||||
}
|
||||
}
|
||||
|
||||
&__community-button {
|
||||
color: #fff;
|
||||
background-color: #2683ff;
|
||||
|
||||
&:hover {
|
||||
background-color: #0059d0;
|
||||
border: 2px solid #0059d0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__back-button {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #fff;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 15px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background-color: #2683ff;
|
||||
|
||||
.back-button-svg-path {
|
||||
fill: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
<!--Copyright (C) 2019 Storj Labs, Inc.-->
|
||||
<!--See LICENSE for copying information.-->
|
||||
|
||||
<div class="overview-area">
|
||||
<div class="overview-area__welcome-container">
|
||||
<h1 class="overview-area__welcome-container__title">Welcome to Storj</h1>
|
||||
<p class="overview-area__welcome-container__sub-title">
|
||||
To create a project, get started by adding a payment method - <br/>your first 5GB are free for your first project.
|
||||
</p>
|
||||
<router-link class="overview-area__welcome-container__button" :to="billingPath" >Add Payment</router-link>
|
||||
</div>
|
||||
<div class="overview-area__steps-area">
|
||||
<div class="overview-area__steps-area__numbers">
|
||||
<FirstStepIcon class="overview-area__steps-area__numbers__icon"/>
|
||||
<div class="overview-area-divider"></div>
|
||||
<SecondStepIcon class="overview-area__steps-area__numbers__icon"/>
|
||||
<div class="overview-area-divider"></div>
|
||||
<ThirdStepIcon class="overview-area__steps-area__numbers__icon"/>
|
||||
</div>
|
||||
<div class="overview-area__steps-area__items">
|
||||
<div class="overview-area__steps-area__items__add-payment-info">
|
||||
<h2 class="overview-area__steps-area__items__add-payment-info__title">Add Payment Info</h2>
|
||||
<img class="overview-area-image" src="@/../static/images/overview/payment.jpg" alt="payment image">
|
||||
</div>
|
||||
<div class="overview-area__steps-area__items__create-project">
|
||||
<h2 class="overview-area__steps-area__items__create-project__title">Create a Project</h2>
|
||||
<img class="overview-area-image" src="@/../static/images/overview/project.jpg" alt="project image">
|
||||
</div>
|
||||
<div class="overview-area__steps-area__items__create-api-key">
|
||||
<h2 class="overview-area__steps-area__items__create-api-key__title">Create an API Key</h2>
|
||||
<img class="overview-area-image" src="@/../static/images/overview/apikey.jpg" alt="api key image">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,152 +0,0 @@
|
||||
// Copyright (C) 2019 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
p,
|
||||
h1 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.overview-area {
|
||||
width: auto;
|
||||
height: calc(100% - 150px);
|
||||
padding: 75px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-family: 'font_regular', sans-serif;
|
||||
|
||||
&__welcome-container {
|
||||
width: auto;
|
||||
background-color: #fff;
|
||||
border-radius: 6px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 73px 261px;
|
||||
margin-bottom: 32px;
|
||||
|
||||
&__title {
|
||||
font-family: 'font_bold', sans-serif;
|
||||
font-size: 32px;
|
||||
line-height: 39px;
|
||||
color: #1b2533;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
&__sub-title {
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
color: #354049;
|
||||
margin-bottom: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&__button {
|
||||
font-size: 16px;
|
||||
line-height: 23px;
|
||||
padding: 10px 15px;
|
||||
color: #fff;
|
||||
background-color: #2683ff;
|
||||
border-radius: 8px;
|
||||
|
||||
&:hover {
|
||||
background-color: #0059d0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__steps-area {
|
||||
padding: 55px;
|
||||
width: auto;
|
||||
background-color: #fff;
|
||||
border-radius: 12px;
|
||||
|
||||
&__numbers {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 125px;
|
||||
margin-bottom: 15px;
|
||||
|
||||
&__icon {
|
||||
min-width: 30px;
|
||||
min-height: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
&__items {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
&__add-payment-info,
|
||||
&__create-project,
|
||||
&__create-api-key {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
&__title {
|
||||
font-family: 'font_bold', sans-serif;
|
||||
font-size: 24px;
|
||||
line-height: 16px;
|
||||
text-align: center;
|
||||
color: #354049;
|
||||
}
|
||||
}
|
||||
|
||||
&__add-payment-info,
|
||||
&__create-project {
|
||||
margin-right: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.overview-area-divider {
|
||||
width: calc(46% + 2px);
|
||||
border: 1px solid #cfd5da;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1450px) {
|
||||
|
||||
.overview-area {
|
||||
|
||||
&__welcome-container {
|
||||
width: 626px;
|
||||
padding: 73px 55px;
|
||||
}
|
||||
|
||||
&__steps-area {
|
||||
|
||||
&__numbers {
|
||||
padding: 0 80px;
|
||||
}
|
||||
|
||||
&__items {
|
||||
|
||||
&__add-payment-info,
|
||||
&__create-project,
|
||||
&__create-api-key {
|
||||
|
||||
&__title {
|
||||
font-family: 'font_bold', sans-serif;
|
||||
font-size: 19px;
|
||||
line-height: 16px;
|
||||
text-align: center;
|
||||
color: #354049;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.overview-area-image {
|
||||
max-width: 210px;
|
||||
max-height: 150px;
|
||||
}
|
||||
}
|
@ -63,6 +63,7 @@ import VButton from '@/components/common/VButton.vue';
|
||||
import CloseCrossIcon from '@/../static/images/common/closeCross.svg';
|
||||
import SuccessIcon from '@/../static/images/project/success.svg';
|
||||
|
||||
import { RouteConfig } from '@/router';
|
||||
import { BUCKET_ACTIONS } from '@/store/modules/buckets';
|
||||
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
|
||||
import { PROJECTS_ACTIONS } from '@/store/modules/projects';
|
||||
@ -174,6 +175,9 @@ export default class NewProjectPopup extends Vue {
|
||||
this.checkIfUsersFirstProject();
|
||||
|
||||
this.isLoading = false;
|
||||
|
||||
// TODO: remove after adding second step of onboarding tour
|
||||
await this.$router.push(RouteConfig.ProjectDashboard.path);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -19,6 +19,7 @@ import BucketArea from '@/components/project/buckets/BucketArea.vue';
|
||||
import ProjectDetails from '@/components/project/ProjectDetails.vue';
|
||||
import ProjectUsage from '@/components/project/usage/ProjectUsage.vue';
|
||||
|
||||
import { RouteConfig } from '@/router';
|
||||
import { SegmentEvent } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
@Component({
|
||||
@ -34,6 +35,12 @@ export default class ProjectDashboard extends Vue {
|
||||
* Segment tracking is processed.
|
||||
*/
|
||||
public mounted(): void {
|
||||
if (!this.$store.getters.selectedProject.id) {
|
||||
this.$router.push(RouteConfig.OnboardingTour.path);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.$segment.track(SegmentEvent.PROJECT_VIEWED, {
|
||||
project_id: this.$store.getters.selectedProject.id,
|
||||
});
|
||||
|
@ -68,7 +68,15 @@ export default class BucketArea extends Vue {
|
||||
* Lifecycle hook after initial render where buckets list is fetched.
|
||||
*/
|
||||
public async mounted(): Promise<void> {
|
||||
if (!this.$store.getters.selectedProject.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await this.$store.dispatch(FETCH, 1);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -48,6 +48,10 @@ export default class ProjectUsage extends Vue {
|
||||
* Fetches project limits.
|
||||
*/
|
||||
public async mounted(): Promise<void> {
|
||||
if (!this.$store.getters.selectedProject.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await this.$store.dispatch(PROJECTS_ACTIONS.GET_LIMITS, this.$store.getters.selectedProject.id);
|
||||
} catch (error) {
|
||||
|
@ -206,7 +206,7 @@ export default class HeaderArea extends Vue {
|
||||
const projects = await this.$store.dispatch(PROJECTS_ACTIONS.FETCH);
|
||||
if (!projects.length) {
|
||||
await this.$store.dispatch(APP_STATE_ACTIONS.CHANGE_STATE, AppState.LOADED_EMPTY);
|
||||
await this.$router.push(RouteConfig.Account.with(RouteConfig.Billing).path);
|
||||
await this.$router.push(RouteConfig.OnboardingTour.path);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import BillingHistory from '@/components/account/billing/billingHistory/BillingH
|
||||
import SettingsArea from '@/components/account/SettingsArea.vue';
|
||||
import ApiKeysArea from '@/components/apiKeys/ApiKeysArea.vue';
|
||||
import Page404 from '@/components/errors/Page404.vue';
|
||||
import OverviewArea from '@/components/overview/OverviewArea.vue';
|
||||
import OnboardingTourArea from '@/components/onboardingTour/OnboardingTourArea.vue';
|
||||
import ProjectDashboard from '@/components/project/ProjectDashboard.vue';
|
||||
import ProjectMembersArea from '@/components/team/ProjectMembersArea.vue';
|
||||
|
||||
@ -36,7 +36,7 @@ export abstract class RouteConfig {
|
||||
public static ProjectDashboard = new NavigationLink('/project-dashboard', 'Dashboard');
|
||||
public static Team = new NavigationLink('/project-members', 'Team');
|
||||
public static ApiKeys = new NavigationLink('/api-keys', 'API Keys');
|
||||
public static Overview = new NavigationLink('/overview', 'Initial Overview');
|
||||
public static OnboardingTour = new NavigationLink('/onboarding-tour', 'Onboarding Tour');
|
||||
|
||||
// child paths
|
||||
public static Settings = new NavigationLink('settings', 'Settings');
|
||||
@ -132,9 +132,9 @@ export const router = new Router({
|
||||
component: ApiKeysArea,
|
||||
},
|
||||
{
|
||||
path: RouteConfig.Overview.path,
|
||||
name: RouteConfig.Overview.name,
|
||||
component: OverviewArea,
|
||||
path: RouteConfig.OnboardingTour.path,
|
||||
name: RouteConfig.OnboardingTour.name,
|
||||
component: OnboardingTourArea,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -267,6 +267,20 @@ export function makePaymentsModule(api: PaymentsApi): StoreModule<PaymentsState>
|
||||
&& billingItem.status === BillingHistoryItemStatus.Completed;
|
||||
}) && state.balance > 0) || state.creditCards.length > 0;
|
||||
},
|
||||
isTransactionProcessing: (state: PaymentsState): boolean => {
|
||||
return state.billingHistory.some((billingItem: BillingHistoryItem) => {
|
||||
return billingItem.amount >= 50 && billingItem.type === BillingHistoryItemType.Transaction
|
||||
&& (billingItem.status === BillingHistoryItemStatus.Pending
|
||||
|| billingItem.status === BillingHistoryItemStatus.Paid
|
||||
|| billingItem.status === BillingHistoryItemStatus.Completed);
|
||||
}) && state.balance === 0;
|
||||
},
|
||||
isTransactionCompleted: (state: PaymentsState): boolean => {
|
||||
return (state.billingHistory.some((billingItem: BillingHistoryItem) => {
|
||||
return billingItem.amount >= 50 && billingItem.type === BillingHistoryItemType.Transaction
|
||||
&& billingItem.status === BillingHistoryItemStatus.Completed;
|
||||
}) && state.balance > 0);
|
||||
},
|
||||
isInvoiceForPreviousRollup: (state: PaymentsState): boolean => {
|
||||
const now = new Date();
|
||||
|
||||
|
@ -152,6 +152,16 @@ export enum BillingHistoryItemStatus {
|
||||
* Status showed if transaction successfully completed.
|
||||
*/
|
||||
Completed = 'completed',
|
||||
|
||||
/**
|
||||
* Status showed if transaction successfully paid.
|
||||
*/
|
||||
Paid = 'paid',
|
||||
|
||||
/**
|
||||
* Status showed if transaction is pending.
|
||||
*/
|
||||
Pending = 'pending',
|
||||
}
|
||||
|
||||
/**
|
||||
|
21
web/satellite/src/utils/constants/onboardingTourEnums.ts
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright (C) 2020 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
export enum TourState {
|
||||
DEFAULT = 1,
|
||||
ADDING_PAYMENT,
|
||||
PROJECT,
|
||||
API_KEY,
|
||||
UPLOAD,
|
||||
}
|
||||
|
||||
export enum AddingPaymentState {
|
||||
ADD_CARD = 1,
|
||||
ADD_STORJ,
|
||||
}
|
||||
|
||||
export enum AddingStorjState {
|
||||
DEFAULT = 1,
|
||||
VERIFYING,
|
||||
VERIFIED,
|
||||
}
|
@ -6,7 +6,7 @@
|
||||
<div v-if="isLoading" class="loading-overlay active">
|
||||
<img class="loading-image" src="@/../static/images/register/Loading.gif" alt="Company logo loading gif">
|
||||
</div>
|
||||
<div v-if="!isLoading" class="dashboard-container__wrap">
|
||||
<div v-else class="dashboard-container__wrap">
|
||||
<NavigationArea class="regular-navigation"/>
|
||||
<div class="dashboard-container__wrap__column">
|
||||
<DashboardHeader/>
|
||||
@ -45,7 +45,6 @@ import { BUCKET_ACTIONS } from '@/store/modules/buckets';
|
||||
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
|
||||
import { PROJECTS_ACTIONS } from '@/store/modules/projects';
|
||||
import { USER_ACTIONS } from '@/store/modules/users';
|
||||
import { CreditCard } from '@/types/payments';
|
||||
import { Project } from '@/types/projects';
|
||||
import { Size } from '@/utils/bytesSize';
|
||||
import {
|
||||
@ -97,18 +96,40 @@ export default class DashboardArea extends Vue {
|
||||
return;
|
||||
}
|
||||
|
||||
let balance: number = 0;
|
||||
let creditCards: CreditCard[] = [];
|
||||
|
||||
try {
|
||||
await this.$store.dispatch(SETUP_ACCOUNT);
|
||||
balance = await this.$store.dispatch(GET_BALANCE);
|
||||
creditCards = await this.$store.dispatch(GET_CREDIT_CARDS);
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to setup account. ${error.message}`);
|
||||
}
|
||||
|
||||
try {
|
||||
await this.$store.dispatch(GET_BALANCE);
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to get account balance. ${error.message}`);
|
||||
}
|
||||
|
||||
try {
|
||||
await this.$store.dispatch(GET_CREDIT_CARDS);
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to get credit cards. ${error.message}`);
|
||||
}
|
||||
|
||||
try {
|
||||
await this.$store.dispatch(GET_BILLING_HISTORY);
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to get account billing history. ${error.message}`);
|
||||
}
|
||||
|
||||
try {
|
||||
await this.$store.dispatch(GET_PROJECT_USAGE_AND_CHARGES_PREVIOUS_ROLLUP);
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to get usage and charges for previous billing period. ${error.message}`);
|
||||
}
|
||||
|
||||
try {
|
||||
await this.$store.dispatch(GET_PROJECT_USAGE_AND_CHARGES_CURRENT_ROLLUP);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(`Unable to get usage and charges for current billing period. ${error.message}`);
|
||||
}
|
||||
|
||||
let projects: Project[] = [];
|
||||
@ -121,28 +142,14 @@ export default class DashboardArea extends Vue {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!projects.length && !creditCards.length && balance === 0) {
|
||||
await this.$store.dispatch(APP_STATE_ACTIONS.CHANGE_STATE, AppState.LOADED_EMPTY);
|
||||
|
||||
try {
|
||||
await this.$router.push(RouteConfig.Overview.path);
|
||||
} catch (error) {
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!projects.length) {
|
||||
await this.$store.dispatch(APP_STATE_ACTIONS.CHANGE_STATE, AppState.LOADED_EMPTY);
|
||||
|
||||
if (!this.isRouteAccessibleWithoutProject()) {
|
||||
try {
|
||||
await this.$router.push(RouteConfig.Account.with(RouteConfig.Billing).path);
|
||||
await this.$router.push(RouteConfig.OnboardingTour.path);
|
||||
} catch (error) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@ -226,19 +233,6 @@ export default class DashboardArea extends Vue {
|
||||
public get isLoading(): boolean {
|
||||
return this.$store.state.appStateModule.appState.fetchState === AppState.LOADING;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method checks if current route is available when user has no created projects.
|
||||
*/
|
||||
private isRouteAccessibleWithoutProject(): boolean {
|
||||
const availableRoutes = [
|
||||
RouteConfig.Account.with(RouteConfig.Billing).path,
|
||||
RouteConfig.Account.with(RouteConfig.Settings).path,
|
||||
RouteConfig.Overview.path,
|
||||
];
|
||||
|
||||
return availableRoutes.includes(this.$router.currentRoute.path.toLowerCase());
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -288,16 +282,6 @@ export default class DashboardArea extends Vue {
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 720px) {
|
||||
|
||||
.dashboard-container {
|
||||
|
||||
&__main-area {
|
||||
left: 60px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.loading-overlay {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
@ -77,7 +77,7 @@ export default class Login extends Vue {
|
||||
|
||||
/**
|
||||
* Performs login action.
|
||||
* Than change location to project overview.
|
||||
* Then changes location to billing page.
|
||||
*/
|
||||
public async onLogin(): Promise<void> {
|
||||
if (this.isLoading) {
|
||||
|
3
web/satellite/static/images/account/billing/back.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="13" height="13" viewBox="0 0 13 13" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path class="back-button-svg-path" fill-rule="evenodd" clip-rule="evenodd" d="M7.22572 0.300601C7.62652 0.701402 7.62652 1.35123 7.22572 1.75203L3.50406 5.47368H11.9737C12.5405 5.47368 13 5.93318 13 6.5C13 7.06682 12.5405 7.52632 11.9737 7.52632H3.50406L7.22572 11.248C7.62652 11.6488 7.62652 12.2986 7.22572 12.6994C6.82491 13.1002 6.17509 13.1002 5.77429 12.6994L0.300601 7.22571C-0.1002 6.82491 -0.1002 6.17509 0.300601 5.77428L5.77429 0.300601C6.17509 -0.1002 6.82491 -0.1002 7.22572 0.300601Z" fill="#384B65"/>
|
||||
</svg>
|
After Width: | Height: | Size: 623 B |
3
web/satellite/static/images/common/checked.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="10" height="7" viewBox="0 0 10 7" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7.61854 0.302314C8.02258 -0.100771 8.67764 -0.100771 9.08163 0.302314C9.48569 0.705397 9.48569 1.35893 9.08163 1.76202L4.20463 6.62768C3.8006 7.03077 3.14555 7.03077 2.74152 6.62768L0.303018 4.19485C-0.101006 3.79177 -0.101006 3.13823 0.303018 2.73515C0.707044 2.33206 1.3621 2.33206 1.76612 2.73515L3.47307 4.43813L7.61854 0.302314Z" fill="white"/>
|
||||
</svg>
|
After Width: | Height: | Size: 465 B |
Before Width: | Height: | Size: 3.6 KiB |
BIN
web/satellite/static/images/onboardingTour/api-key.jpg
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
web/satellite/static/images/onboardingTour/coins.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
web/satellite/static/images/onboardingTour/project.jpg
Normal file
After Width: | Height: | Size: 5.7 KiB |
BIN
web/satellite/static/images/onboardingTour/uplink.jpg
Normal file
After Width: | Height: | Size: 5.9 KiB |
3
web/satellite/static/images/onboardingTour/verified.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="34" height="34" viewBox="0 0 34 34" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M17 34C26.3888 34 34 26.3888 34 17C34 7.61116 26.3888 0 17 0C7.61116 0 0 7.61116 0 17C0 26.3888 7.61116 34 17 34ZM24.4639 12.1445C23.7686 11.4507 22.6412 11.4507 21.9459 12.1445L14.8113 19.2624L11.8735 16.3315C11.1782 15.6378 10.0508 15.6378 9.35544 16.3315C8.66009 17.0252 8.66009 18.15 9.35544 18.8437L13.5522 23.0308C14.2476 23.7245 15.375 23.7245 16.0703 23.0308L24.4639 14.6567C25.1593 13.963 25.1593 12.8382 24.4639 12.1445Z" fill="#00BD8F"/>
|
||||
</svg>
|
After Width: | Height: | Size: 605 B |
3
web/satellite/static/images/onboardingTour/verifying.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="34" height="34" viewBox="0 0 34 34" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M17 34C26.3889 34 34 26.3889 34 17C34 7.61115 26.3889 0 17 0C7.61115 0 0 7.61115 0 17C0 26.3889 7.61115 34 17 34ZM8 19C9.10455 19 10 18.1046 10 17C10 15.8954 9.10455 15 8 15C6.89545 15 6 15.8954 6 17C6 18.1046 6.89545 19 8 19ZM17 19C18.1046 19 19 18.1046 19 17C19 15.8954 18.1046 15 17 15C15.8954 15 15 15.8954 15 17C15 18.1046 15.8954 19 17 19ZM28 17C28 18.1046 27.1046 19 26 19C24.8954 19 24 18.1046 24 17C24 15.8954 24.8954 15 26 15C27.1046 15 28 15.8954 28 17Z" fill="#C7CDD2"/>
|
||||
</svg>
|
After Width: | Height: | Size: 639 B |
Before Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 5.0 KiB |
@ -66,12 +66,12 @@ describe('AddStorjForm', () => {
|
||||
wrapper.vm.$data.tokenDepositValue = 30;
|
||||
await wrapper.vm.onConfirmAddSTORJ();
|
||||
|
||||
expect((store.state as any).notificationsModule.notificationQueue[0].message).toMatch('First deposit amount must be more than 50 and less than 1000000');
|
||||
expect((store.state as any).notificationsModule.notificationQueue[0].message).toMatch('First deposit amount must be more than $50 and less than $1000000');
|
||||
|
||||
wrapper.vm.$data.tokenDepositValue = 1000000;
|
||||
await wrapper.vm.onConfirmAddSTORJ();
|
||||
|
||||
expect((store.state as any).notificationsModule.notificationQueue[1].message).toMatch('First deposit amount must be more than 50 and less than 1000000');
|
||||
expect((store.state as any).notificationsModule.notificationQueue[1].message).toMatch('First deposit amount must be more than $50 and less than $1000000');
|
||||
});
|
||||
|
||||
it('user is able to add less than 50$ after coupon is applied', async () => {
|
||||
|
@ -42,17 +42,6 @@ describe('NewProjectArea', () => {
|
||||
expect(wrapper.findAll('.new-project-button-container').length).toBe(0); // user is unable to create project.
|
||||
});
|
||||
|
||||
it('renders correctly without projects and without payment methods with info tooltip', async () => {
|
||||
const wrapper = mount(NewProjectArea, {
|
||||
store,
|
||||
localVue,
|
||||
});
|
||||
|
||||
await wrapper.find('.info').trigger('mouseenter');
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders correctly without projects and with credit card', async () => {
|
||||
const creditCard = new CreditCard('id', 1, 2000, 'test', '0000', true);
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
exports[`NewProjectArea renders correctly without projects and with credit card 1`] = `
|
||||
<div class="new-project-container">
|
||||
<!---->
|
||||
<div id="newProjectButton" class="new-project-button-container">
|
||||
<h1 class="new-project-button-container__label">+ Create Project</h1>
|
||||
</div>
|
||||
@ -12,7 +11,6 @@ exports[`NewProjectArea renders correctly without projects and with credit card
|
||||
|
||||
exports[`NewProjectArea renders correctly without projects and with credit card 2`] = `
|
||||
<div class="new-project-container">
|
||||
<!---->
|
||||
<div id="newProjectButton" class="new-project-button-container">
|
||||
<h1 class="new-project-button-container__label">+ Create Project</h1>
|
||||
</div>
|
||||
@ -61,30 +59,6 @@ exports[`NewProjectArea renders correctly without projects and with credit card
|
||||
|
||||
exports[`NewProjectArea renders correctly without projects and without payment methods 1`] = `
|
||||
<div class="new-project-container">
|
||||
<div class="info">
|
||||
<div class="new-project-button-mock">
|
||||
<h1 class="new-project-button-mock__label">+ Create Project</h1>
|
||||
</div>
|
||||
<!---->
|
||||
</div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`NewProjectArea renders correctly without projects and without payment methods with info tooltip 1`] = `
|
||||
<div class="new-project-container">
|
||||
<div class="info">
|
||||
<div class="new-project-button-mock">
|
||||
<h1 class="new-project-button-mock__label">+ Create Project</h1>
|
||||
</div>
|
||||
<div class="info__message-box">
|
||||
<div class="info__message-box__text">
|
||||
<p class="info__message-box__text__regular-text">Please add a payment method</p>
|
||||
<p class="info__message-box__text__bold-text"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
|
@ -3,7 +3,7 @@
|
||||
exports[`NavigationArea snapshot not changed with project 1`] = `
|
||||
<div class="navigation-area">
|
||||
<div class="navigation-area__wrap">
|
||||
<router-link-stub to="/account/billing" tag="a" event="click" class="navigation-area__logo">
|
||||
<router-link-stub to="/project-dashboard" tag="a" event="click" class="navigation-area__logo">
|
||||
<logoicon-stub class="navigation-area__logo__img"></logoicon-stub>
|
||||
<logotexticon-stub class="navigation-area__logo__text"></logotexticon-stub>
|
||||
</router-link-stub>
|
||||
@ -40,7 +40,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" target="_blank" class="navigation-area__item-container">
|
||||
</div> <a href="https://documentation.storj.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>
|
||||
@ -76,7 +76,7 @@ exports[`NavigationArea snapshot not changed with project 1`] = `
|
||||
exports[`NavigationArea snapshot not changed without project 1`] = `
|
||||
<div class="navigation-area">
|
||||
<div class="navigation-area__wrap">
|
||||
<router-link-stub to="/account/billing" tag="a" event="click" class="navigation-area__logo">
|
||||
<router-link-stub to="/onboarding-tour" tag="a" event="click" class="navigation-area__logo">
|
||||
<logoicon-stub class="navigation-area__logo__img"></logoicon-stub>
|
||||
<logotexticon-stub class="navigation-area__logo__text"></logotexticon-stub>
|
||||
</router-link-stub>
|
||||
@ -113,12 +113,12 @@ exports[`NavigationArea snapshot not changed without project 1`] = `
|
||||
<p class="navigation-area__resources-title__title">RESOURCES</p>
|
||||
<!---->
|
||||
<!---->
|
||||
</div> <a href="https://documentation.tardigrade.io" target="_blank" class="navigation-area__item-container">
|
||||
</div> <a href="https://documentation.storj.io" target="_blank" class="navigation-area__item-container disabled">
|
||||
<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>
|
||||
</div>
|
||||
</a> <a href="mailto:support@storj.io" target="_blank" class="navigation-area__item-container support-item">
|
||||
</a> <a href="mailto:support@storj.io" target="_blank" class="navigation-area__item-container support-item disabled">
|
||||
<div class="navigation-area__item-container__link-container">
|
||||
<supporticon-stub class="svg"></supporticon-stub>
|
||||
<h1 class="navigation-area__item-container__link-container__title">Support</h1>
|
||||
@ -130,12 +130,12 @@ exports[`NavigationArea snapshot not changed without project 1`] = `
|
||||
<!---->
|
||||
</div>
|
||||
<div class="navigation-area__account-area">
|
||||
<router-link-stub to="/account/settings" tag="a" event="click" class="navigation-area__item-container account-item">
|
||||
<router-link-stub to="/account/settings" tag="a" event="click" class="navigation-area__item-container account-item disabled">
|
||||
<div class="navigation-area__item-container__link-container">
|
||||
<h1 class="navigation-area__item-container__link-container__title account-item">Settings</h1>
|
||||
</div>
|
||||
</router-link-stub>
|
||||
<router-link-stub to="/account/billing" tag="a" event="click" class="navigation-area__item-container account-item">
|
||||
<router-link-stub to="/account/billing" tag="a" event="click" class="navigation-area__item-container account-item disabled">
|
||||
<div class="navigation-area__item-container__link-container">
|
||||
<h1 class="navigation-area__item-container__link-container__title account-item">Billing</h1>
|
||||
</div>
|
||||
|
@ -1,9 +1,12 @@
|
||||
// Copyright (C) 2019 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import Router from 'vue-router';
|
||||
import Vuex from 'vuex';
|
||||
|
||||
import NavigationArea from '@/components/navigation/NavigationArea.vue';
|
||||
import OnboardingTourArea from '@/components/onboardingTour/OnboardingTourArea.vue';
|
||||
import ProjectDashboard from '@/components/project/ProjectDashboard.vue';
|
||||
|
||||
import { RouteConfig } from '@/router';
|
||||
import { makeProjectsModule, PROJECTS_MUTATIONS } from '@/store/modules/projects';
|
||||
@ -19,6 +22,7 @@ const projectsModule = makeProjectsModule(api);
|
||||
const localVue = createLocalVue();
|
||||
|
||||
localVue.use(Vuex);
|
||||
localVue.use(Router);
|
||||
|
||||
const store = new Vuex.Store({ modules: { projectsModule } });
|
||||
|
||||
@ -29,10 +33,19 @@ const expectedLinks: NavigationLink[] = [
|
||||
];
|
||||
|
||||
describe('NavigationArea', () => {
|
||||
it('snapshot not changed without project', () => {
|
||||
it('snapshot not changed without project', (): void => {
|
||||
const router = new Router({
|
||||
mode: 'history',
|
||||
routes: [{
|
||||
path: '/',
|
||||
name: RouteConfig.OnboardingTour.name,
|
||||
component: OnboardingTourArea,
|
||||
}],
|
||||
});
|
||||
const wrapper = shallowMount(NavigationArea, {
|
||||
store,
|
||||
localVue,
|
||||
router,
|
||||
});
|
||||
|
||||
const navigationElements = wrapper.findAll('.navigation-area__item-container');
|
||||
@ -41,13 +54,22 @@ describe('NavigationArea', () => {
|
||||
const accountButton = wrapper.findAll('.navigation-area__account-title__button');
|
||||
|
||||
expect(navigationElements.length).toBe(7);
|
||||
expect(disabledElements.length).toBe(3);
|
||||
expect(disabledElements.length).toBe(7);
|
||||
expect(resourcesButton.length).toBe(0);
|
||||
expect(accountButton.length).toBe(0);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
const router = new Router({
|
||||
mode: 'history',
|
||||
routes: [{
|
||||
path: '/',
|
||||
name: RouteConfig.ProjectDashboard.name,
|
||||
component: ProjectDashboard,
|
||||
}],
|
||||
});
|
||||
|
||||
it('snapshot not changed with project', async () => {
|
||||
const projects = await store.dispatch('fetchProjects');
|
||||
store.commit(PROJECTS_MUTATIONS.SELECT_PROJECT, projects[0].id);
|
||||
@ -55,6 +77,7 @@ describe('NavigationArea', () => {
|
||||
const wrapper = shallowMount(NavigationArea, {
|
||||
store,
|
||||
localVue,
|
||||
router,
|
||||
});
|
||||
|
||||
const navigationElements = wrapper.findAll('.navigation-area__item-container');
|
||||
@ -74,6 +97,7 @@ describe('NavigationArea', () => {
|
||||
const wrapper = shallowMount(NavigationArea, {
|
||||
store,
|
||||
localVue,
|
||||
router,
|
||||
});
|
||||
|
||||
const navigationLinks = (wrapper.vm as any).navigation;
|
||||
@ -90,6 +114,7 @@ describe('NavigationArea', () => {
|
||||
const wrapper = shallowMount(NavigationArea, {
|
||||
store,
|
||||
localVue,
|
||||
router,
|
||||
});
|
||||
|
||||
await wrapper.find('.navigation-area__resources-title').trigger('mouseenter');
|
||||
|
14
web/satellite/tests/unit/onboardingTour/ProgressBar.spec.ts
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright (C) 2020 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import ProgressBar from '@/components/onboardingTour/ProgressBar.vue';
|
||||
|
||||
import { mount } from '@vue/test-utils';
|
||||
|
||||
describe('ProgressBar.vue', () => {
|
||||
it('renders correctly', (): void => {
|
||||
const wrapper = mount(ProgressBar);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
@ -0,0 +1,20 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ProgressBar.vue renders correctly 1`] = `
|
||||
<div class="progress-bar-container">
|
||||
<div class="progress-bar-container__progress-area">
|
||||
<div class="progress-bar-container__progress-area__circle"><svg width="10" height="7" viewBox="0 0 10 7" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7.61854 0.302314C8.02258 -0.100771 8.67764 -0.100771 9.08163 0.302314C9.48569 0.705397 9.48569 1.35893 9.08163 1.76202L4.20463 6.62768C3.8006 7.03077 3.14555 7.03077 2.74152 6.62768L0.303018 4.19485C-0.101006 3.79177 -0.101006 3.13823 0.303018 2.73515C0.707044 2.33206 1.3621 2.33206 1.76612 2.73515L3.47307 4.43813L7.61854 0.302314Z" fill="white"></path>
|
||||
</svg></div>
|
||||
<div class="progress-bar-container__progress-area__bar"></div>
|
||||
<div class="progress-bar-container__progress-area__circle"><svg width="10" height="7" viewBox="0 0 10 7" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7.61854 0.302314C8.02258 -0.100771 8.67764 -0.100771 9.08163 0.302314C9.48569 0.705397 9.48569 1.35893 9.08163 1.76202L4.20463 6.62768C3.8006 7.03077 3.14555 7.03077 2.74152 6.62768L0.303018 4.19485C-0.101006 3.79177 -0.101006 3.13823 0.303018 2.73515C0.707044 2.33206 1.3621 2.33206 1.76612 2.73515L3.47307 4.43813L7.61854 0.302314Z" fill="white"></path>
|
||||
</svg></div>
|
||||
<div class="progress-bar-container__progress-area__bar"></div>
|
||||
<div class="progress-bar-container__progress-area__circle"><svg width="10" height="7" viewBox="0 0 10 7" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7.61854 0.302314C8.02258 -0.100771 8.67764 -0.100771 9.08163 0.302314C9.48569 0.705397 9.48569 1.35893 9.08163 1.76202L4.20463 6.62768C3.8006 7.03077 3.14555 7.03077 2.74152 6.62768L0.303018 4.19485C-0.101006 3.79177 -0.101006 3.13823 0.303018 2.73515C0.707044 2.33206 1.3621 2.33206 1.76612 2.73515L3.47307 4.43813L7.61854 0.302314Z" fill="white"></path>
|
||||
</svg></div>
|
||||
</div>
|
||||
<div class="progress-bar-container__titles-area"><span class="progress-bar-container__titles-area__title">Name Your Project</span> <span class="progress-bar-container__titles-area__title api-key-title">Create an API Key</span> <span class="progress-bar-container__titles-area__title">Upload Data</span></div>
|
||||
</div>
|
||||
`;
|
@ -0,0 +1,9 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`OnboardingTourArea.vue renders correctly 1`] = `
|
||||
<div class="tour-area">
|
||||
<progressbar-stub></progressbar-stub>
|
||||
<overviewstep-stub></overviewstep-stub>
|
||||
<!---->
|
||||
</div>
|
||||
`;
|
@ -0,0 +1,34 @@
|
||||
// Copyright (C) 2020 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import Vuex from 'vuex';
|
||||
|
||||
import OnboardingTourArea from '@/components/onboardingTour/OnboardingTourArea.vue';
|
||||
|
||||
import { PaymentsHttpApi } from '@/api/payments';
|
||||
import { makePaymentsModule } from '@/store/modules/payments';
|
||||
import { makeProjectsModule } from '@/store/modules/projects';
|
||||
import { createLocalVue, shallowMount } from '@vue/test-utils';
|
||||
|
||||
import { ProjectsApiMock } from '../mock/api/projects';
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(Vuex);
|
||||
|
||||
const projectsApi = new ProjectsApiMock();
|
||||
const projectsModule = makeProjectsModule(projectsApi);
|
||||
const paymentsApi = new PaymentsHttpApi();
|
||||
const paymentsModule = makePaymentsModule(paymentsApi);
|
||||
|
||||
const store = new Vuex.Store({ modules: { projectsModule, paymentsModule }});
|
||||
|
||||
describe('OnboardingTourArea.vue', () => {
|
||||
it('renders correctly', (): void => {
|
||||
const wrapper = shallowMount(OnboardingTourArea, {
|
||||
store,
|
||||
localVue,
|
||||
});
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
@ -0,0 +1,32 @@
|
||||
// Copyright (C) 2020 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import Vuex from 'vuex';
|
||||
|
||||
import AddPaymentStep from '@/components/onboardingTour/steps/AddPaymentStep.vue';
|
||||
|
||||
import { PaymentsHttpApi } from '@/api/payments';
|
||||
import { makePaymentsModule } from '@/store/modules/payments';
|
||||
import { createLocalVue, shallowMount } from '@vue/test-utils';
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(Vuex);
|
||||
const paymentsApi = new PaymentsHttpApi();
|
||||
const paymentsModule = makePaymentsModule(paymentsApi);
|
||||
|
||||
const store = new Vuex.Store({ modules: { paymentsModule }});
|
||||
|
||||
describe('AddPaymentStep.vue', () => {
|
||||
it('renders correctly', async (): Promise<void> => {
|
||||
const wrapper = shallowMount(AddPaymentStep, {
|
||||
store,
|
||||
localVue,
|
||||
});
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
|
||||
await wrapper.find('.payment-step__methods-container__title-area__options-area__token').trigger('click');
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
@ -0,0 +1,18 @@
|
||||
// Copyright (C) 2020 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import OverviewStep from '@/components/onboardingTour/steps/OverviewStep.vue';
|
||||
|
||||
import { mount } from '@vue/test-utils';
|
||||
|
||||
describe('OverviewStep.vue', () => {
|
||||
it('renders correctly', async (): Promise<void> => {
|
||||
const wrapper = mount(OverviewStep);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
|
||||
await wrapper.find('.get-started-button').trigger('click');
|
||||
|
||||
expect(wrapper.emitted()).toHaveProperty('setAddPaymentState');
|
||||
});
|
||||
});
|
@ -0,0 +1,45 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`AddPaymentStep.vue renders correctly 1`] = `
|
||||
<div class="payment-step">
|
||||
<h1 class="payment-step__title">Get Started with 5 GB Free</h1>
|
||||
<p class="payment-step__sub-title">
|
||||
Adding a payment method ensures your project won’t be interrupted after your <b>free</b> credit is used.
|
||||
</p>
|
||||
<div class="payment-step__methods-container">
|
||||
<div class="payment-step__methods-container__title-area">
|
||||
<h2 class="payment-step__methods-container__title-area__title">Payment Method</h2>
|
||||
<div class="payment-step__methods-container__title-area__options-area"><span class="payment-step__methods-container__title-area__options-area__token">
|
||||
STORJ Token
|
||||
</span> <span class="payment-step__methods-container__title-area__options-area__card selected">
|
||||
Card
|
||||
</span></div>
|
||||
</div>
|
||||
<!---->
|
||||
</div>
|
||||
<addcardstate-stub></addcardstate-stub>
|
||||
<!---->
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`AddPaymentStep.vue renders correctly 2`] = `
|
||||
<div class="payment-step">
|
||||
<h1 class="payment-step__title">Get Started with 5 GB Free</h1>
|
||||
<p class="payment-step__sub-title">
|
||||
Adding a payment method ensures your project won’t be interrupted after your <b>free</b> credit is used.
|
||||
</p>
|
||||
<div class="payment-step__methods-container">
|
||||
<div class="payment-step__methods-container__title-area">
|
||||
<h2 class="payment-step__methods-container__title-area__title">Payment Method</h2>
|
||||
<div class="payment-step__methods-container__title-area__options-area"><span class="payment-step__methods-container__title-area__options-area__token selected">
|
||||
STORJ Token
|
||||
</span> <span class="payment-step__methods-container__title-area__options-area__card">
|
||||
Card
|
||||
</span></div>
|
||||
</div>
|
||||
<!---->
|
||||
</div>
|
||||
<!---->
|
||||
<addstorjstate-stub></addstorjstate-stub>
|
||||
</div>
|
||||
`;
|
@ -0,0 +1,38 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`OverviewStep.vue renders correctly 1`] = `
|
||||
<div class="overview-area">
|
||||
<h1 class="overview-area__title">Welcome to Storj</h1>
|
||||
<p class="overview-area__sub-title">
|
||||
You’re just a few steps away from uploading your first object to the 100% secure, decentralized cloud. After
|
||||
adding payment, you’ll create a project, API key, get set up with Storj, and start uploading objects.
|
||||
</p>
|
||||
<div class="overview-area__steps-area">
|
||||
<div class="overview-area__steps-area__step"><svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg" class="overview-area__steps-area__step__icon">
|
||||
<circle cx="15" cy="15" r="15" fill="#519CFF"></circle>
|
||||
<path d="M17.0916 9.36364H14.7791L11.8984 11.1875V13.3693L14.5632 11.6989H14.6314V21H17.0916V9.36364Z" fill="white"></path>
|
||||
</svg> <img src="@/../static/images/onboardingTour/project.jpg" alt="project image" class="overview-step-image">
|
||||
<h2 class="overview-area__steps-area__step__title">Name Your Project</h2> <span class="overview-area__steps-area__step__subtitle">
|
||||
Projects are where buckets are created for storing data.
|
||||
</span>
|
||||
</div>
|
||||
<div class="overview-area__steps-area__step second-step"><svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg" class="overview-area__steps-area__step__icon">
|
||||
<circle cx="15" cy="15" r="15" fill="#519CFF"></circle>
|
||||
<path d="M11.4041 21H19.6996V18.9886H14.8132V18.9091L16.5121 17.2443C18.9041 15.0625 19.5462 13.9716 19.5462 12.6477C19.5462 10.6307 17.8984 9.20455 15.4041 9.20455C12.9609 9.20455 11.2848 10.6648 11.2905 12.9489H13.6257C13.62 11.8352 14.3246 11.1534 15.3871 11.1534C16.4098 11.1534 17.1712 11.7898 17.1712 12.8125C17.1712 13.7386 16.603 14.375 15.5462 15.392L11.4041 19.2273V21Z" fill="white"></path>
|
||||
</svg> <img src="@/../static/images/onboardingTour/api-key.jpg" alt="api keys image" class="overview-step-image">
|
||||
<h2 class="overview-area__steps-area__step__title">Create an API Key</h2> <span class="overview-area__steps-area__step__subtitle">
|
||||
Generate access to your project to upload data.
|
||||
</span>
|
||||
</div>
|
||||
<div class="overview-area__steps-area__step"><svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg" class="overview-area__steps-area__step__icon">
|
||||
<circle cx="15" cy="15" r="15" fill="#519CFF"></circle>
|
||||
<path d="M15.4709 21.1591C18.0845 21.1591 19.9538 19.7216 19.9482 17.733C19.9538 16.2841 19.0334 15.25 17.3232 15.0341V14.9432C18.6243 14.7102 19.522 13.7898 19.5163 12.483C19.522 10.6477 17.9141 9.20455 15.505 9.20455C13.1186 9.20455 11.3232 10.6023 11.2891 12.6136H13.647C13.6754 11.7273 14.4879 11.1534 15.4936 11.1534C16.4879 11.1534 17.1527 11.7557 17.147 12.6307C17.1527 13.5455 16.3743 14.1648 15.255 14.1648H14.1697V15.9716H15.255C16.5732 15.9716 17.397 16.6307 17.3913 17.5682C17.397 18.4943 16.6016 19.1307 15.4766 19.1307C14.3913 19.1307 13.5788 18.5625 13.5334 17.7102H11.0561C11.0959 19.7443 12.9141 21.1591 15.4709 21.1591Z" fill="white"></path>
|
||||
</svg> <img src="@/../static/images/onboardingTour/uplink.jpg" alt="uplink image" class="overview-step-image">
|
||||
<h2 class="overview-area__steps-area__step__title">Upload Data</h2> <span class="overview-area__steps-area__step__subtitle">
|
||||
Store your data on the secure, decentralized cloud.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="get-started-button container" style="width: 251px; height: 56px;"><span class="label">Get Started</span></div>
|
||||
</div>
|
||||
`;
|
@ -0,0 +1,14 @@
|
||||
// Copyright (C) 2020 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import AddCardState from '@/components/onboardingTour/steps/paymentStates/AddCardState.vue';
|
||||
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
|
||||
describe('AddCardState.vue', () => {
|
||||
it('renders correctly', (): void => {
|
||||
const wrapper = shallowMount(AddCardState);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
@ -0,0 +1,55 @@
|
||||
// Copyright (C) 2020 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import Vuex from 'vuex';
|
||||
|
||||
import AddStorjState from '@/components/onboardingTour/steps/paymentStates/AddStorjState.vue';
|
||||
|
||||
import { makePaymentsModule, PAYMENTS_MUTATIONS } from '@/store/modules/payments';
|
||||
import { BillingHistoryItem, BillingHistoryItemStatus, BillingHistoryItemType } from '@/types/payments';
|
||||
import { createLocalVue, shallowMount } from '@vue/test-utils';
|
||||
|
||||
import { PaymentsMock } from '../../../mock/api/payments';
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(Vuex);
|
||||
|
||||
const paymentsApi = new PaymentsMock();
|
||||
const paymentsModule = makePaymentsModule(paymentsApi);
|
||||
const store = new Vuex.Store({ modules: { paymentsModule }});
|
||||
|
||||
describe('AddStorjState.vue', () => {
|
||||
it('renders correctly', (): void => {
|
||||
const wrapper = shallowMount(AddStorjState, {
|
||||
store,
|
||||
localVue,
|
||||
});
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders correctly with pending transaction', (): void => {
|
||||
const billingTransactionItem = new BillingHistoryItem('itemId', 'test', 50, 50,
|
||||
BillingHistoryItemStatus.Pending, 'test', new Date(), new Date(), BillingHistoryItemType.Transaction);
|
||||
store.commit(PAYMENTS_MUTATIONS.SET_BILLING_HISTORY, [billingTransactionItem]);
|
||||
const wrapper = shallowMount(AddStorjState, {
|
||||
store,
|
||||
localVue,
|
||||
});
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders correctly with completed transaction', (): void => {
|
||||
const billingTransactionItem = new BillingHistoryItem('itemId', 'test', 50, 50,
|
||||
BillingHistoryItemStatus.Completed, 'test', new Date(), new Date(), BillingHistoryItemType.Transaction);
|
||||
store.commit(PAYMENTS_MUTATIONS.SET_BILLING_HISTORY, [billingTransactionItem]);
|
||||
store.commit(PAYMENTS_MUTATIONS.SET_BALANCE, 5000);
|
||||
const wrapper = shallowMount(AddStorjState, {
|
||||
store,
|
||||
localVue,
|
||||
});
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
@ -0,0 +1,17 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`AddCardState.vue renders correctly 1`] = `
|
||||
<div class="add-card-state">
|
||||
<div class="add-card-state__input-container">
|
||||
<stripecardinput-stub onstriperesponsecallback="function () { [native code] }"></stripecardinput-stub>
|
||||
<!---->
|
||||
</div>
|
||||
<div class="add-card-state__security-info">
|
||||
<lockimage-stub></lockimage-stub> <span class="add-card-state__security-info__text">
|
||||
Your card is secured by 128-bit SSL and AES-256 encryption. Your information is secure.
|
||||
</span>
|
||||
</div>
|
||||
<div class="add-card-state__button">
|
||||
<!----> <span class="add-card-state__button__label">Add Payment</span></div>
|
||||
</div>
|
||||
`;
|
@ -0,0 +1,70 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`AddStorjState.vue renders correctly 1`] = `
|
||||
<div class="add-storj-state">
|
||||
<div class="add-storj-state__container">
|
||||
<p class="add-storj-state__container__bonus-info">
|
||||
Deposit STORJ Token to your account and receive a 10% bonus, or $10 for every $100.
|
||||
</p>
|
||||
<div class="add-storj-state__container__deposit-area">
|
||||
<p class="add-storj-state__container__deposit-area__info"><b>Please Note:</b> Your first deposit of $50 or more in STORJ Token is applied to your account
|
||||
after Coin Payments verifies payment<br><br>5GB are your starting project limits. Increased
|
||||
amounts are available
|
||||
<a href="https://support.tardigrade.io/hc/en-us/requests/new?ticket_form_id=360000683212" target="_blank" class="add-storj-state__container__deposit-area__info__request-link">
|
||||
per request.
|
||||
</a></p>
|
||||
<payingstep-stub></payingstep-stub>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
<!---->
|
||||
</div>
|
||||
<vbutton-stub label="Name Your Project" width="222px" height="48px" isdisabled="true" onpress="function () { [native code] }"></vbutton-stub>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`AddStorjState.vue renders correctly with completed transaction 1`] = `
|
||||
<div class="add-storj-state">
|
||||
<div class="add-storj-state__container">
|
||||
<p class="add-storj-state__container__bonus-info">
|
||||
Deposit STORJ Token to your account and receive a 10% bonus, or $10 for every $100.
|
||||
</p>
|
||||
<div class="add-storj-state__container__deposit-area">
|
||||
<p class="add-storj-state__container__deposit-area__info"><b>Please Note:</b> Your first deposit of $50 or more in STORJ Token is applied to your account
|
||||
after Coin Payments verifies payment<br><br>5GB are your starting project limits. Increased
|
||||
amounts are available
|
||||
<a href="https://support.tardigrade.io/hc/en-us/requests/new?ticket_form_id=360000683212" target="_blank" class="add-storj-state__container__deposit-area__info__request-link">
|
||||
per request.
|
||||
</a></p>
|
||||
<!---->
|
||||
<!---->
|
||||
<verifiedstep-stub></verifiedstep-stub>
|
||||
</div>
|
||||
<!---->
|
||||
</div>
|
||||
<vbutton-stub label="Name Your Project" width="222px" height="48px" onpress="function () { [native code] }"></vbutton-stub>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`AddStorjState.vue renders correctly with pending transaction 1`] = `
|
||||
<div class="add-storj-state">
|
||||
<div class="add-storj-state__container">
|
||||
<p class="add-storj-state__container__bonus-info">
|
||||
Deposit STORJ Token to your account and receive a 10% bonus, or $10 for every $100.
|
||||
</p>
|
||||
<div class="add-storj-state__container__deposit-area">
|
||||
<p class="add-storj-state__container__deposit-area__info"><b>Please Note:</b> Your first deposit of $50 or more in STORJ Token is applied to your account
|
||||
after Coin Payments verifies payment<br><br>5GB are your starting project limits. Increased
|
||||
amounts are available
|
||||
<a href="https://support.tardigrade.io/hc/en-us/requests/new?ticket_form_id=360000683212" target="_blank" class="add-storj-state__container__deposit-area__info__request-link">
|
||||
per request.
|
||||
</a></p>
|
||||
<!---->
|
||||
<verifyingstep-stub></verifyingstep-stub>
|
||||
<!---->
|
||||
</div>
|
||||
<!---->
|
||||
</div>
|
||||
<vbutton-stub label="Name Your Project" width="222px" height="48px" isdisabled="true" onpress="function () { [native code] }"></vbutton-stub>
|
||||
</div>
|
||||
`;
|
@ -0,0 +1,82 @@
|
||||
// Copyright (C) 2020 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import Vuex from 'vuex';
|
||||
|
||||
import PayingStep from '@/components/onboardingTour/steps/paymentStates/tokenSubSteps/PayingStep.vue';
|
||||
|
||||
import { appStateModule } from '@/store/modules/appState';
|
||||
import { makeNotificationsModule } from '@/store/modules/notifications';
|
||||
import { makePaymentsModule } from '@/store/modules/payments';
|
||||
import { makeProjectsModule, PROJECTS_MUTATIONS } from '@/store/modules/projects';
|
||||
import { Project } from '@/types/projects';
|
||||
import { Notificator } from '@/utils/plugins/notificator';
|
||||
import { SegmentioPlugin } from '@/utils/plugins/segment';
|
||||
import { createLocalVue, mount, shallowMount } from '@vue/test-utils';
|
||||
|
||||
import { PaymentsMock } from '../../../../mock/api/payments';
|
||||
import { ProjectsApiMock } from '../../../../mock/api/projects';
|
||||
|
||||
const localVue = createLocalVue();
|
||||
const segmentioPlugin = new SegmentioPlugin();
|
||||
localVue.use(Vuex);
|
||||
localVue.use(segmentioPlugin);
|
||||
|
||||
const paymentsApi = new PaymentsMock();
|
||||
const paymentsModule = makePaymentsModule(paymentsApi);
|
||||
const projectsApi = new ProjectsApiMock();
|
||||
const projectsModule = makeProjectsModule(projectsApi);
|
||||
const notificationsModule = makeNotificationsModule();
|
||||
const store = new Vuex.Store({ modules: { paymentsModule, notificationsModule, appStateModule, projectsModule }});
|
||||
|
||||
class NotificatorPlugin {
|
||||
public install() {
|
||||
localVue.prototype.$notify = new Notificator(store);
|
||||
}
|
||||
}
|
||||
|
||||
const notificationsPlugin = new NotificatorPlugin();
|
||||
localVue.use(notificationsPlugin);
|
||||
|
||||
describe('PayingStep.vue', () => {
|
||||
it('renders correctly', (): void => {
|
||||
const wrapper = shallowMount(PayingStep, {
|
||||
store,
|
||||
localVue,
|
||||
});
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('user is unable to add less than 50$ or more than 999999$', async (): Promise<void> => {
|
||||
const wrapper = mount(PayingStep, {
|
||||
store,
|
||||
localVue,
|
||||
});
|
||||
|
||||
wrapper.vm.$data.tokenDepositValue = 30;
|
||||
await wrapper.vm.onConfirmAddSTORJ();
|
||||
|
||||
expect((store.state as any).notificationsModule.notificationQueue[0].message).toMatch('First deposit amount must be more than $50 and less than $1000000');
|
||||
|
||||
wrapper.vm.$data.tokenDepositValue = 1000000;
|
||||
await wrapper.vm.onConfirmAddSTORJ();
|
||||
|
||||
expect((store.state as any).notificationsModule.notificationQueue[1].message).toMatch('First deposit amount must be more than $50 and less than $1000000');
|
||||
});
|
||||
|
||||
it('continue to coin payments works correctly', async (): Promise<void> => {
|
||||
const project = new Project('testId', 'test', 'test', 'test', 'id', true);
|
||||
store.commit(PROJECTS_MUTATIONS.ADD, project);
|
||||
window.open = jest.fn();
|
||||
const wrapper = mount(PayingStep, {
|
||||
store,
|
||||
localVue,
|
||||
});
|
||||
|
||||
wrapper.vm.$data.tokenDepositValue = 70;
|
||||
await wrapper.vm.onConfirmAddSTORJ();
|
||||
|
||||
expect(wrapper.vm.$data.tokenDepositValue).toEqual(50);
|
||||
});
|
||||
});
|
@ -0,0 +1,14 @@
|
||||
// Copyright (C) 2020 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import VerifiedStep from '@/components/onboardingTour/steps/paymentStates/tokenSubSteps/VerifiedStep.vue';
|
||||
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
|
||||
describe('VerifiedStep.vue', () => {
|
||||
it('renders correctly', (): void => {
|
||||
const wrapper = shallowMount(VerifiedStep);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
@ -0,0 +1,18 @@
|
||||
// Copyright (C) 2020 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import VerifyingStep from '@/components/onboardingTour/steps/paymentStates/tokenSubSteps/VerifyingStep.vue';
|
||||
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
|
||||
describe('VerifyingStep.vue', () => {
|
||||
it('renders correctly', async (): Promise<void> => {
|
||||
const wrapper = shallowMount(VerifyingStep);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
|
||||
await wrapper.find('.verifying-step__back-button').trigger('click');
|
||||
|
||||
expect(wrapper.emitted()).toEqual({ 'setDefaultState': [[]] });
|
||||
});
|
||||
});
|
@ -0,0 +1,14 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`PayingStep.vue renders correctly 1`] = `
|
||||
<div class="paying-step">
|
||||
<div class="paying-step__title-area"><img src="@/../static/images/onboardingTour/coins.png" alt="coins image">
|
||||
<h2 class="paying-step__title-area__title">
|
||||
Select Your Deposit Amount
|
||||
</h2>
|
||||
<!---->
|
||||
</div>
|
||||
<tokendepositselection-stub class="paying-step__form"></tokendepositselection-stub>
|
||||
<vbutton-stub label="Continue to Coin Payments" width="100%" height="48px" isbluewhite="true" onpress="function () { [native code] }"></vbutton-stub>
|
||||
</div>
|
||||
`;
|
@ -0,0 +1,10 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`VerifiedStep.vue renders correctly 1`] = `
|
||||
<div class="verified-step">
|
||||
<verifiedimage-stub></verifiedimage-stub>
|
||||
<h2 class="verified-step__title">Payment Verified</h2> <span class="verified-step__sub-title">
|
||||
Your payment has been successfully verified. Click the button below to name your project and start uploading data.
|
||||
</span>
|
||||
</div>
|
||||
`;
|
@ -0,0 +1,19 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`VerifyingStep.vue renders correctly 1`] = `
|
||||
<div class="verifying-step">
|
||||
<verifyingimage-stub></verifyingimage-stub>
|
||||
<h2 class="verifying-step__title">Verifying Payment</h2> <span class="verifying-step__sub-title">
|
||||
Refresh this page in 10-15 minutes to continue after your purchase is verified. In the meantime, see how
|
||||
easy it is to get started visiting documentation page, or join the community to get involved.
|
||||
</span>
|
||||
<div class="verifying-step__buttons-area"><a href="https://documentation.storj.io" target="_blank" class="verifying-step__buttons-area__how-to-button">
|
||||
Documentation
|
||||
</a> <a href="https://storj.io/community/" target="_blank" class="verifying-step__buttons-area__community-button">
|
||||
Community
|
||||
</a></div>
|
||||
<div class="verifying-step__back-button">
|
||||
<backimage-stub></backimage-stub>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
@ -1,17 +0,0 @@
|
||||
// Copyright (C) 2019 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import OverviewArea from '@/components/overview/OverviewArea.vue';
|
||||
|
||||
import { router } from '@/router';
|
||||
import { mount } from '@vue/test-utils';
|
||||
|
||||
describe('OverviewArea.vue', () => {
|
||||
it('renders correctly', (): void => {
|
||||
const wrapper = mount(OverviewArea, {
|
||||
router,
|
||||
});
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
@ -1,38 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`OverviewArea.vue renders correctly 1`] = `
|
||||
<div class="overview-area">
|
||||
<div class="overview-area__welcome-container">
|
||||
<h1 class="overview-area__welcome-container__title">Welcome to Storj</h1>
|
||||
<p class="overview-area__welcome-container__sub-title">
|
||||
To create a project, get started by adding a payment method - <br>your first 5GB are free for your first project.
|
||||
</p> <a href="/account/billing" class="overview-area__welcome-container__button">Add Payment</a>
|
||||
</div>
|
||||
<div class="overview-area__steps-area">
|
||||
<div class="overview-area__steps-area__numbers"><svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg" class="overview-area__steps-area__numbers__icon">
|
||||
<circle cx="15" cy="15" r="15" fill="#519CFF"></circle>
|
||||
<path d="M17.0916 9.36364H14.7791L11.8984 11.1875V13.3693L14.5632 11.6989H14.6314V21H17.0916V9.36364Z" fill="white"></path>
|
||||
</svg>
|
||||
<div class="overview-area-divider"></div> <svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg" class="overview-area__steps-area__numbers__icon">
|
||||
<circle cx="15" cy="15" r="15" fill="#519CFF"></circle>
|
||||
<path d="M11.4041 21H19.6996V18.9886H14.8132V18.9091L16.5121 17.2443C18.9041 15.0625 19.5462 13.9716 19.5462 12.6477C19.5462 10.6307 17.8984 9.20455 15.4041 9.20455C12.9609 9.20455 11.2848 10.6648 11.2905 12.9489H13.6257C13.62 11.8352 14.3246 11.1534 15.3871 11.1534C16.4098 11.1534 17.1712 11.7898 17.1712 12.8125C17.1712 13.7386 16.603 14.375 15.5462 15.392L11.4041 19.2273V21Z" fill="white"></path>
|
||||
</svg>
|
||||
<div class="overview-area-divider"></div> <svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg" class="overview-area__steps-area__numbers__icon">
|
||||
<circle cx="15" cy="15" r="15" fill="#519CFF"></circle>
|
||||
<path d="M15.4709 21.1591C18.0845 21.1591 19.9538 19.7216 19.9482 17.733C19.9538 16.2841 19.0334 15.25 17.3232 15.0341V14.9432C18.6243 14.7102 19.522 13.7898 19.5163 12.483C19.522 10.6477 17.9141 9.20455 15.505 9.20455C13.1186 9.20455 11.3232 10.6023 11.2891 12.6136H13.647C13.6754 11.7273 14.4879 11.1534 15.4936 11.1534C16.4879 11.1534 17.1527 11.7557 17.147 12.6307C17.1527 13.5455 16.3743 14.1648 15.255 14.1648H14.1697V15.9716H15.255C16.5732 15.9716 17.397 16.6307 17.3913 17.5682C17.397 18.4943 16.6016 19.1307 15.4766 19.1307C14.3913 19.1307 13.5788 18.5625 13.5334 17.7102H11.0561C11.0959 19.7443 12.9141 21.1591 15.4709 21.1591Z" fill="white"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="overview-area__steps-area__items">
|
||||
<div class="overview-area__steps-area__items__add-payment-info">
|
||||
<h2 class="overview-area__steps-area__items__add-payment-info__title">Add Payment Info</h2> <img src="@/../static/images/overview/payment.jpg" alt="payment image" class="overview-area-image">
|
||||
</div>
|
||||
<div class="overview-area__steps-area__items__create-project">
|
||||
<h2 class="overview-area__steps-area__items__create-project__title">Create a Project</h2> <img src="@/../static/images/overview/project.jpg" alt="project image" class="overview-area-image">
|
||||
</div>
|
||||
<div class="overview-area__steps-area__items__create-api-key">
|
||||
<h2 class="overview-area__steps-area__items__create-api-key__title">Create an API Key</h2> <img src="@/../static/images/overview/apikey.jpg" alt="api key image" class="overview-area-image">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
@ -2,7 +2,6 @@
|
||||
|
||||
exports[`Dashboard renders correctly when data is loaded 1`] = `
|
||||
<div class="dashboard-container">
|
||||
<!---->
|
||||
<div class="dashboard-container__wrap">
|
||||
<navigationarea-stub class="regular-navigation"></navigationarea-stub>
|
||||
<div class="dashboard-container__wrap__column">
|
||||
@ -23,6 +22,5 @@ exports[`Dashboard renders correctly when data is loaded 1`] = `
|
||||
exports[`Dashboard renders correctly when data is loading 1`] = `
|
||||
<div class="dashboard-container">
|
||||
<div class="loading-overlay active"><img src="@/../static/images/register/Loading.gif" alt="Company logo loading gif" class="loading-image"></div>
|
||||
<!---->
|
||||
</div>
|
||||
`;
|
||||
|