web/satellite: referral links and registration (#3678)

This commit is contained in:
Nikolay Yurchenko 2019-12-02 21:27:56 +02:00 committed by GitHub
parent 526a126a5a
commit 90b631c8bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 112 additions and 76 deletions

View File

@ -12,6 +12,7 @@ import { HttpClient } from '@/utils/httpClient';
export class AuthHttpApi {
private readonly http: HttpClient = new HttpClient();
private readonly ROOT_PATH: string = '/api/v0/auth';
private readonly REFERRAL_PATH: string = '/api/v0/referrals';
/**
* Used to resend an registration confirmation email
@ -189,4 +190,34 @@ export class AuthHttpApi {
return await response.json();
}
/**
* Used to register account by referral link
*
* @param user - stores user information
* @param referralToken - referral registration token
* @returns id of created user
* @throws Error
*/
public async referralRegister(user: {fullName: string; shortName: string; email: string; password: string}, referralToken: string): Promise<string> {
const path = `${this.REFERRAL_PATH}/register`;
const body = {
referralToken,
password: user.password,
fullName: user.fullName,
shortName: user.shortName,
email: user.email,
};
const response = await this.http.post(path, JSON.stringify(body), false);
if (!response.ok) {
if (response.status === 400) {
throw new Error('we are unable to create your account. This is an invite-only alpha, please join our waitlist to receive an invitation');
}
throw new Error('can not register user');
}
return await response.json();
}
}

View File

@ -13,19 +13,15 @@ export class ReferralHttpApi {
private readonly ROOT_PATH: string = '/api/v0/referrals';
/**
* Used to get referral links
* Used to get referral tokens
*
* @throws Error
*/
public async getLinks(): Promise<any> {
const path = `${this.ROOT_PATH}`;
public async getTokens(): Promise<string[]> {
const path = `${this.ROOT_PATH}/tokens`;
const response = await this.http.get(path, true);
// TODO: remove mock and add types after final referral manager implementation
return [];
if (response.ok) {
return await response.json();
}
@ -33,6 +29,6 @@ export class ReferralHttpApi {
throw new ErrorUnauthorized();
}
throw new Error('can not get referral links');
throw new Error('can not get referral tokens');
}
}

View File

@ -34,6 +34,7 @@ export default class AccountArea extends Vue {}
.account-area-container {
padding: 0 39px 0 65px;
margin-right: 16px;
height: 100%;
&__navigation {
position: absolute;

View File

@ -117,6 +117,7 @@ export default class ProfileArea extends Vue {
.profile-container {
position: relative;
font-family: 'font_regular', sans-serif;
padding-bottom: 100px;
user-select: none;
&__title {

View File

@ -8,29 +8,17 @@
<p class="referral-container__title-container__text">Decentralized Future</p>
</div>
<div class="referral-container__available" v-if="isAvailableLinks">
<p class="referral-container__available__title">You Have {{ 5 }} Invitations To Share!</p>
<div class="referral-container__copy-and-share-container__link-holder">
<p class="referral-container__copy-and-share-container__link-holder__link">https://us-central-1.tardigrade.io/ref/?uuid=96a33796-2c9b-47</p>
<div class="copy-button" v-clipboard="'test'" @click="copyLink">Copy</div>
</div>
<div class="referral-container__copy-and-share-container__link-holder">
<p class="referral-container__copy-and-share-container__link-holder__link">https://us-central-1.tardigrade.io/ref/?uuid=96a33796-2c9b-47</p>
<div class="copy-button" v-clipboard="'test'" @click="copyLink">Copy</div>
</div>
<div class="referral-container__copy-and-share-container__link-holder">
<p class="referral-container__copy-and-share-container__link-holder__link">https://us-central-1.tardigrade.io/ref/?uuid=96a33796-2c9b-47</p>
<div class="copy-button" v-clipboard="'test'" @click="copyLink">Copy</div>
</div>
<div class="referral-container__copy-and-share-container__link-holder">
<p class="referral-container__copy-and-share-container__link-holder__link">https://us-central-1.tardigrade.io/ref/?uuid=96a33796-2c9b-47</p>
<div class="copy-button" v-clipboard="'test'" @click="copyLink">Copy</div>
</div>
<div class="referral-container__copy-and-share-container__link-holder">
<p class="referral-container__copy-and-share-container__link-holder__link">https://us-central-1.tardigrade.io/ref/?uuid=96a33796-2c9b-47</p>
<div class="copy-button" v-clipboard="'test'" @click="copyLink">Copy</div>
<p class="referral-container__available__title">You Have {{ referralLinks.length }} Invitations To Share!</p>
<div
class="referral-container__copy-and-share-container__link-holder"
v-for="link in referralLinks"
:key="link.url"
>
<p class="referral-container__copy-and-share-container__link-holder__link">{{ link.url }}</p>
<div class="copy-button" v-clipboard="link.url" @click="copyLink">Copy</div>
</div>
</div>
<div class="referral-container__not-available" v-if="!isAvailableLinks">
<div class="referral-container__not-available" v-else>
<p class="referral-container__not-available__text">No available referral links. Try again later.</p>
<NoLinksIcon />
</div>
@ -44,6 +32,7 @@ import { Component, Vue } from 'vue-property-decorator';
import NoLinksIcon from '@/../static/images/referral/NoLinks.svg';
import { REFERRAL_ACTIONS } from '@/store/modules/referral';
import { ReferralLink } from '@/types/referral';
Vue.use(VueClipboards);
@ -58,11 +47,15 @@ export default class ReferralArea extends Vue {
}
public get isAvailableLinks(): boolean {
return this.$store.state.referralModule.referralLinks.length !== 0;
return this.$store.state.referralModule.referralTokens.length !== 0;
}
public get referralLinks(): ReferralLink[] {
return this.$store.getters.referralLinks;
}
public async beforeMount() {
await this.$store.dispatch(REFERRAL_ACTIONS.GET_LINKS);
await this.$store.dispatch(REFERRAL_ACTIONS.GET_TOKENS);
}
}
</script>
@ -79,6 +72,7 @@ export default class ReferralArea extends Vue {
justify-content: center;
align-items: center;
height: 100%;
padding: 50px 0 100px 0;
&__title-container {
display: flex;

View File

@ -346,7 +346,6 @@ export default class ApiKeysArea extends Vue {
.api-keys-area {
position: relative;
padding: 40px 65px 55px 65px;
height: 85vh;
font-family: 'font_regular', sans-serif;
&__title {

View File

@ -40,7 +40,7 @@ export default class VBanner extends Vue {
padding: 20px 20px 20px 20px;
border-radius: 12px;
background-color: #d0e3fe;
margin: 32px 65px 32px 55px;
margin: 32px 65px 15px 55px;
&__text {
font-family: 'font_medium', sans-serif;

View File

@ -155,7 +155,6 @@ export default class ProjectDetailsArea extends Vue {
.project-details {
position: relative;
overflow: hidden;
height: 85vh;
font-family: 'font_regular', sans-serif;
&__title {

View File

@ -54,7 +54,6 @@ export default class ProjectOverviewArea extends Vue {
.project-overview {
padding: 40px 65px 55px 65px;
position: relative;
height: 85vh;
&__navigation {
position: absolute;

View File

@ -2,26 +2,26 @@
// See LICENSE for copying information.
import { StoreModule } from '@/store';
import { ReferralApi } from '@/types/referral';
import { ReferralApi, ReferralLink } from '@/types/referral';
export const REFERRAL_ACTIONS = {
GET_LINKS: 'getReferralLinks',
GET_TOKENS: 'getReferralTokens',
};
export const REFERRAL_MUTATIONS = {
SET_LINKS: 'setReferralLinks',
SET_TOKENS: 'setReferralTokens',
};
const {
GET_LINKS,
GET_TOKENS,
} = REFERRAL_ACTIONS;
const {
SET_LINKS,
SET_TOKENS,
} = REFERRAL_MUTATIONS;
export class ReferralState {
public referralLinks = [];
public referralTokens: string[] = [];
}
/**
@ -33,17 +33,24 @@ export function makeReferralModule(api: ReferralApi): StoreModule<ReferralState>
return {
state: new ReferralState(),
mutations: {
[SET_LINKS](state: ReferralState, referralLinks): void {
state.referralLinks = referralLinks;
[SET_TOKENS](state: ReferralState, referralTokens: string[]): void {
state.referralTokens = referralTokens;
},
},
actions: {
[GET_LINKS]: async function ({commit}: any): Promise<any> {
const referralLinks = await api.getLinks();
[GET_TOKENS]: async function ({commit}: any): Promise<string[]> {
const referralTokens = await api.getTokens();
commit(GET_LINKS, referralLinks);
commit(SET_TOKENS, referralTokens);
return referralLinks;
return referralTokens;
},
},
getters: {
referralLinks: (state: ReferralState): ReferralLink[] => {
return state.referralTokens.map(token => {
return new ReferralLink(token);
});
},
},
};

View File

@ -11,5 +11,16 @@ export interface ReferralApi {
* @returns links
* @throws Error
*/
getLinks(): Promise<any>;
getTokens(): Promise<string[]>;
}
/**
* ReferralLink creates url from token
*/
export class ReferralLink {
public url: string = '';
constructor(token: string = '') {
this.url = `${location.host}/register?referralToken=${token}`;
}
}

View File

@ -11,11 +11,13 @@
<div class="dashboard-container__wrap__column">
<DashboardHeader/>
<div class="dashboard-container__main-area">
<VBanner
v-if="isBannerShown"
text="You have no payment method added."
additional-text="To start work with your account please add Credit Card or add $50.00 or more worth of STORJ tokens to your balance."
/>
<div class="dashboard-container__main-area__banner-area">
<VBanner
v-if="isBannerShown"
text="You have no payment method added."
additional-text="To start work with your account please add Credit Card or add $50.00 or more worth of STORJ tokens to your balance."
/>
</div>
<div class="dashboard-container__main-area__content">
<router-view/>
</div>
@ -33,7 +35,6 @@ import DashboardHeader from '@/components/header/HeaderArea.vue';
import NavigationArea from '@/components/navigation/NavigationArea.vue';
import { ErrorUnauthorized } from '@/api/errors/ErrorUnauthorized';
import { PaymentsHttpApi } from '@/api/payments';
import { RouteConfig } from '@/router';
import { BUCKET_ACTIONS } from '@/store/modules/buckets';
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
@ -49,7 +50,6 @@ import {
} from '@/utils/constants/actionNames';
import { AppState } from '@/utils/constants/appStateEnum';
import { LocalData } from '@/utils/localData';
import { MetaUtils } from '@/utils/meta';
const {
SETUP_ACCOUNT,
@ -207,27 +207,16 @@ export default class DashboardArea extends Vue {
width: 100%;
height: calc(100vh - 50px);
overflow-y: auto;
}
}
display: flex;
flex-direction: column;
@media screen and (max-height: 900px) {
&__banner-area {
flex: 0 1 auto;
}
.dashboard-container__main-area__content {
height: 600px;
}
}
@media screen and (max-height: 700px) {
.dashboard-container__main-area__content {
height: 400px;
}
}
@media screen and (max-height: 500px) {
.dashboard-container__main-area__content {
height: 300px;
&__content {
flex: 1 1 auto;
}
}
}

View File

@ -37,6 +37,7 @@ export default class RegisterArea extends Vue {
// tardigrade logic
private secret: string = '';
private referralToken: string = '';
private refUserId: string = '';
private userId: string = '';
@ -62,6 +63,10 @@ export default class RegisterArea extends Vue {
this.secret = this.$route.query.token.toString();
}
if (this.$route.query.referralToken) {
this.referralToken = this.$route.query.referralToken.toString();
}
const { ids = '' } = this.$route.params;
let decoded = '';
try {
@ -165,7 +170,9 @@ export default class RegisterArea extends Vue {
private async createUser(): Promise<void> {
try {
this.userId = await this.auth.register(this.user, this.secret, this.refUserId);
this.userId = this.referralToken ?
await this.auth.referralRegister(this.user, this.referralToken) :
await this.auth.register(this.user, this.secret, this.refUserId);
LocalData.setUserId(this.userId);

View File

@ -8,7 +8,9 @@ exports[`Dashboard renders correctly when data is loaded 1`] = `
<div class="dashboard-container__wrap__column">
<dashboardheader-stub></dashboardheader-stub>
<div class="dashboard-container__main-area">
<vbanner-stub text="You have no payment method added." additionaltext="To start work with your account please add Credit Card or add $50.00 or more worth of STORJ tokens to your balance."></vbanner-stub>
<div class="dashboard-container__main-area__banner-area">
<vbanner-stub text="You have no payment method added." additionaltext="To start work with your account please add Credit Card or add $50.00 or more worth of STORJ tokens to your balance."></vbanner-stub>
</div>
<div class="dashboard-container__main-area__content">
<router-view-stub name="default"></router-view-stub>
</div>