web/satellite: overview page implemented
Change-Id: I66a8e17635040730906bd6f9c20924abd0db0744
@ -54,9 +54,9 @@ import { Component, Vue } from 'vue-property-decorator';
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
|
||||
import DotsIcon from '@/../static/images/buckets/noBucketState/dots.svg';
|
||||
import FirstStepIcon from '@/../static/images/buckets/noBucketState/one.svg';
|
||||
import ThirdStepIcon from '@/../static/images/buckets/noBucketState/three.svg';
|
||||
import SecondStepIcon from '@/../static/images/buckets/noBucketState/two.svg';
|
||||
import FirstStepIcon from '@/../static/images/common/one.svg';
|
||||
import ThirdStepIcon from '@/../static/images/common/three.svg';
|
||||
import SecondStepIcon from '@/../static/images/common/two.svg';
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
|
@ -88,8 +88,9 @@ export default class NavigationArea extends Vue {
|
||||
// RouteConfig.Account.with(RouteConfig.Referral),
|
||||
];
|
||||
|
||||
public get isProjectNotSelected(): boolean {
|
||||
return this.$store.state.projectsModule.selectedProject.id === '';
|
||||
|
||||
public isLinkDisabled(navItem: NavigationLink): boolean {
|
||||
return this.$store.state.projectsModule.selectedProject.id === '' && navItem.path !== this.homePath;
|
||||
}
|
||||
|
||||
public get isResourcesDisplayingButtonShown(): boolean {
|
||||
|
@ -9,7 +9,7 @@
|
||||
</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: isProjectNotSelected && navItem.path !== '/project-details'}" 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(navItem) }" 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>
|
||||
|
34
web/satellite/src/components/overview/OverviewArea.html
Normal file
@ -0,0 +1,34 @@
|
||||
<!--Copyright (C) 2019 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">
|
||||
To get started, let’s add a payment method.<br/>We’ll provide you with a $55 credit right away!
|
||||
</p>
|
||||
<router-link class="overview-area__button" :to="billingPath" >Add Payment Info & Get $55</router-link>
|
||||
<span class="overview-area__charge-info">You will not be charged unless $55 is used</span>
|
||||
<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>
|
185
web/satellite/src/components/overview/OverviewArea.scss
Normal file
@ -0,0 +1,185 @@
|
||||
// Copyright (C) 2019 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
p,
|
||||
h1 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.overview-area {
|
||||
width: auto;
|
||||
height: calc(100% - 170px);
|
||||
padding: 85px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-family: 'font_regular', sans-serif;
|
||||
|
||||
&__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;
|
||||
margin-bottom: 10px;
|
||||
|
||||
&:hover {
|
||||
background-color: #0059d0;
|
||||
}
|
||||
}
|
||||
|
||||
&__charge-info {
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
color: #898989;
|
||||
margin-bottom: 90px;
|
||||
}
|
||||
|
||||
&__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 {
|
||||
|
||||
&__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;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1200px) {
|
||||
|
||||
.overview-area {
|
||||
|
||||
&__steps-area {
|
||||
|
||||
&__numbers {
|
||||
padding: 0 70px;
|
||||
}
|
||||
|
||||
&__items {
|
||||
|
||||
&__add-payment-info,
|
||||
&__create-project,
|
||||
&__create-api-key {
|
||||
|
||||
&__title {
|
||||
font-family: 'font_bold', sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 16px;
|
||||
text-align: center;
|
||||
color: #354049;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.overview-area-image {
|
||||
max-width: 190px;
|
||||
max-height: 130px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1110px) {
|
||||
|
||||
.overview-area {
|
||||
width: calc(100% - 80px);
|
||||
padding: 85px 40px;
|
||||
}
|
||||
}
|
30
web/satellite/src/components/overview/OverviewArea.vue
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright (C) 2019 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
<template src="./OverviewArea.html"></template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
|
||||
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,
|
||||
FirstStepIcon,
|
||||
ThirdStepIcon,
|
||||
SecondStepIcon,
|
||||
},
|
||||
})
|
||||
export default class OverviewArea extends Vue {
|
||||
public readonly billingPath: string = RouteConfig.Account.with(RouteConfig.Billing).path;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss" src="./OverviewArea.scss"></style>
|
@ -12,6 +12,7 @@ import ReferralArea from '@/components/account/referral/ReferralArea.vue';
|
||||
import ApiKeysArea from '@/components/apiKeys/ApiKeysArea.vue';
|
||||
import BucketArea from '@/components/buckets/BucketArea.vue';
|
||||
import Page404 from '@/components/errors/Page404.vue';
|
||||
import OverviewArea from '@/components/overview/OverviewArea.vue';
|
||||
import ProjectDetails from '@/components/project/ProjectDetails.vue';
|
||||
import ProjectOverviewArea from '@/components/project/ProjectOverviewArea.vue';
|
||||
import UsageReport from '@/components/project/UsageReport.vue';
|
||||
@ -40,6 +41,7 @@ export abstract class RouteConfig {
|
||||
public static Team = new NavigationLink('/project-members', 'Team');
|
||||
public static ApiKeys = new NavigationLink('/api-keys', 'API Keys');
|
||||
public static Buckets = new NavigationLink('/buckets', 'Buckets');
|
||||
public static Overview = new NavigationLink('/overview', 'Initial Overview');
|
||||
|
||||
// child paths
|
||||
public static ProjectDetails = new NavigationLink('details', 'Project Details');
|
||||
@ -152,6 +154,11 @@ export const router = new Router({
|
||||
name: RouteConfig.Buckets.name,
|
||||
component: BucketArea,
|
||||
},
|
||||
{
|
||||
path: RouteConfig.Overview.path,
|
||||
name: RouteConfig.Overview.name,
|
||||
component: OverviewArea,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
@ -117,10 +117,12 @@ export function makePaymentsModule(api: PaymentsApi): StoreModule<PaymentsState>
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
[GET_BALANCE]: async function({commit}: any): Promise<void> {
|
||||
[GET_BALANCE]: async function({commit}: any): Promise<number> {
|
||||
const balance = await api.getBalance();
|
||||
|
||||
commit(SET_BALANCE, balance);
|
||||
|
||||
return balance;
|
||||
},
|
||||
[SETUP_ACCOUNT]: async function(): Promise<void> {
|
||||
await api.setupAccount();
|
||||
|
@ -42,6 +42,7 @@ import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
|
||||
import { PROJECTS_ACTIONS } from '@/store/modules/projects';
|
||||
import { PROJECT_USAGE_ACTIONS } from '@/store/modules/usage';
|
||||
import { USER_ACTIONS } from '@/store/modules/users';
|
||||
import { CreditCard } from '@/types/payments';
|
||||
import { Project } from '@/types/projects';
|
||||
import {
|
||||
API_KEYS_ACTIONS,
|
||||
@ -87,10 +88,13 @@ export default class DashboardArea extends Vue {
|
||||
return;
|
||||
}
|
||||
|
||||
let balance: number = 0;
|
||||
let creditCards: CreditCard[] = [];
|
||||
|
||||
try {
|
||||
await this.$store.dispatch(SETUP_ACCOUNT);
|
||||
await this.$store.dispatch(GET_BALANCE);
|
||||
await this.$store.dispatch(GET_CREDIT_CARDS);
|
||||
balance = await this.$store.dispatch(GET_BALANCE);
|
||||
creditCards = await this.$store.dispatch(GET_CREDIT_CARDS);
|
||||
await this.$store.dispatch(GET_BILLING_HISTORY);
|
||||
await this.$store.dispatch(GET_PROJECT_CHARGES);
|
||||
} catch (error) {
|
||||
@ -107,13 +111,25 @@ 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.ProjectOverview.with(RouteConfig.ProjectDetails).path);
|
||||
} catch (err) {
|
||||
} catch (error) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -161,7 +177,10 @@ export default class DashboardArea extends Vue {
|
||||
* Indicates if bonus banner should be rendered.
|
||||
*/
|
||||
public get isBannerShown(): boolean {
|
||||
return this.$store.state.paymentsModule.creditCards.length === 0;
|
||||
const isNotOverviewPage = this.$route.name === RouteConfig.Overview.name;
|
||||
const hasCreditCards = this.$store.state.paymentsModule.creditCards.length > 0;
|
||||
|
||||
return !(isNotOverviewPage || hasCreditCards);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -179,6 +198,7 @@ export default class DashboardArea extends Vue {
|
||||
RouteConfig.Account.with(RouteConfig.Billing).path,
|
||||
RouteConfig.Account.with(RouteConfig.Profile).path,
|
||||
RouteConfig.ProjectOverview.with(RouteConfig.ProjectDetails).path,
|
||||
RouteConfig.Overview.path,
|
||||
];
|
||||
|
||||
return availableRoutes.includes(this.$router.currentRoute.path.toLowerCase());
|
||||
|
Before Width: | Height: | Size: 277 B After Width: | Height: | Size: 277 B |
Before Width: | Height: | Size: 813 B After Width: | Height: | Size: 813 B |
Before Width: | Height: | Size: 555 B After Width: | Height: | Size: 555 B |
BIN
web/satellite/static/images/overview/apikey.jpg
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
web/satellite/static/images/overview/payment.jpg
Normal file
After Width: | Height: | Size: 5.6 KiB |
BIN
web/satellite/static/images/overview/project.jpg
Normal file
After Width: | Height: | Size: 5.0 KiB |
@ -94,7 +94,7 @@ exports[`NavigationArea snapshot not changed without project 1`] = `
|
||||
</router-link-stub>
|
||||
<projectselectionarea-stub class="project-selection-area"></projectselectionarea-stub>
|
||||
<p class="navigation-area__project-title">PROJECT</p>
|
||||
<router-link-stub to="/project-overview" tag="a" event="click" aria-label="Overview" class="navigation-area__item-container disabled">
|
||||
<router-link-stub to="/project-overview" tag="a" event="click" aria-label="Overview" class="navigation-area__item-container">
|
||||
<div class="navigation-area__item-container__link-container">
|
||||
<div><svg class="svg" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path class="navigation-svg-path" d="M22.073 5.3913C21.8382 5.15652 21.5252 5 21.2121 5H6.89038C6.26429 5 5.71647 5.54783 5.79473 6.09565L2.19473 6.01739C1.80342 6.09565 1.49038 6.17391 1.2556 6.48696C1.09908 6.72174 0.942555 7.03478 1.02082 7.42609L3.13386 18.4609C3.21212 19.0087 3.68169 19.4 4.22951 19.4H19.0991C19.6469 19.4 20.1165 19.0087 20.1947 18.4609L22.3078 6.33043C22.386 6.01739 22.3078 5.62609 22.073 5.3913ZM19.6469 14.7826L18.7078 9.38261C18.6295 8.75652 18.0034 8.28696 17.3773 8.28696H8.4556C8.37734 8.28696 8.29908 8.2087 8.29908 8.13043L8.14256 7.34783C8.14256 6.8 7.75125 6.33043 7.28169 6.17391L21.2121 6.09565L19.6469 14.7826Z" fill="#363840"></path>
|
||||
|
@ -42,7 +42,7 @@ describe('NavigationArea', () => {
|
||||
const accountButton = wrapper.findAll('.navigation-area__account-title__button');
|
||||
|
||||
expect(navigationElements.length).toBe(8);
|
||||
expect(disabledElements.length).toBe(4);
|
||||
expect(disabledElements.length).toBe(3);
|
||||
expect(resourcesButton.length).toBe(0);
|
||||
expect(accountButton.length).toBe(0);
|
||||
|
||||
|
14
web/satellite/tests/unit/overview/OverviewArea.spec.ts
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright (C) 2019 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import OverviewArea from '@/components/overview/OverviewArea.vue';
|
||||
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
|
||||
describe('OverviewArea.vue', () => {
|
||||
it('renders correctly', (): void => {
|
||||
const wrapper = shallowMount(OverviewArea);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
@ -0,0 +1,31 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`OverviewArea.vue renders correctly 1`] = `
|
||||
<div class="overview-area">
|
||||
<h1 class="overview-area__title">Welcome to Storj</h1>
|
||||
<p class="overview-area__sub-title">
|
||||
To get started, let’s add a payment method.<br>We’ll provide you with a $55 credit right away!
|
||||
</p>
|
||||
<router-link-stub to="/account/billing" tag="a" event="click" class="overview-area__button">Add Payment Info & Get $55</router-link-stub> <span class="overview-area__charge-info">You will not be charged unless $55 is used</span>
|
||||
<div class="overview-area__steps-area">
|
||||
<div class="overview-area__steps-area__numbers">
|
||||
<firststepicon-stub class="overview-area__steps-area__numbers__icon"></firststepicon-stub>
|
||||
<div class="overview-area-divider"></div>
|
||||
<secondstepicon-stub class="overview-area__steps-area__numbers__icon"></secondstepicon-stub>
|
||||
<div class="overview-area-divider"></div>
|
||||
<thirdstepicon-stub class="overview-area__steps-area__numbers__icon"></thirdstepicon-stub>
|
||||
</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>
|
||||
`;
|
@ -9,7 +9,7 @@ exports[`Dashboard renders correctly when data is loaded 1`] = `
|
||||
<dashboardheader-stub></dashboardheader-stub>
|
||||
<div class="dashboard-container__main-area">
|
||||
<div class="dashboard-container__main-area__banner-area">
|
||||
<vbanner-stub text="We’ve Now Added Billing!" additionaltext="Your attention is required. Add a credit card to set up your account." path="/account/billing"></vbanner-stub>
|
||||
<!---->
|
||||
</div>
|
||||
<div class="dashboard-container__main-area__content">
|
||||
<router-view-stub name="default"></router-view-stub>
|
||||
|