web/satellite: overview page implemented

Change-Id: I66a8e17635040730906bd6f9c20924abd0db0744
This commit is contained in:
VitaliiShpital 2020-02-18 17:48:19 +02:00 committed by Vitalii Shpital
parent 29452d82a5
commit b387c6b90c
20 changed files with 338 additions and 14 deletions

View File

@ -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: {

View File

@ -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 {

View File

@ -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>

View 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, lets add a payment method.<br/>Well 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>

View 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;
}
}

View 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>

View File

@ -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,
},
],
},
{

View File

@ -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();

View File

@ -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());

View File

Before

Width:  |  Height:  |  Size: 277 B

After

Width:  |  Height:  |  Size: 277 B

View File

Before

Width:  |  Height:  |  Size: 813 B

After

Width:  |  Height:  |  Size: 813 B

View File

Before

Width:  |  Height:  |  Size: 555 B

After

Width:  |  Height:  |  Size: 555 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@ -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>

View File

@ -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);

View 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();
});
});

View File

@ -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, lets add a payment method.<br>Well 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 &amp; 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>
`;

View File

@ -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="Weve 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>