web/satellite: Update registration files

Allows us to remove the following files from satellite branding
repo, with an up-to-date single source of truth now in storj/storj:
* web/satellite/src/common/registrationSuccess.html
* web/satellite/src/common/registrationSuccess.scss
* web/satellite/src/views/register/registerArea.html
* web/satellite/src/views/register/registerArea.scss

The registrationSuccess files have been removed from all satellites in
the branding repository. The registerArea files have been removed only
from production satellites in the branding repository.

Importantly, this change enables the "resend email" functionality on
production satellites - previously, this functionality was available in
storj/storj, but not our branding repository.

Removes the config for VerificationPageURL, which redirected users away
from the satellite app to storj.io after creating an account. In order
for the email resend button to work, we cannot leave the app.

Adds a new config value for partner satellites, which replaces the
partner satellite names config. The new config includes name and
address. It is validated on setup/run to ensure it can be parsed.

Change-Id: I67db0702d9b9641f1a37b599f2929d56f3c33aca
This commit is contained in:
Moby von Briesen 2021-04-23 10:22:20 -04:00 committed by Maximillian von Briesen
parent bc95455135
commit b317f28fdb
17 changed files with 730 additions and 527 deletions

View File

@ -69,34 +69,66 @@ type Config struct {
AuthToken string `help:"auth token needed for access to registration token creation endpoint" default:""`
AuthTokenSecret string `help:"secret used to sign auth tokens" releaseDefault:"" devDefault:"my-suppa-secret-key"`
ContactInfoURL string `help:"url link to contacts page" default:"https://forum.storj.io"`
FrameAncestors string `help:"allow domains to embed the satellite in a frame, space separated" default:"tardigrade.io storj.io"`
LetUsKnowURL string `help:"url link to let us know page" default:"https://storjlabs.atlassian.net/servicedesk/customer/portals"`
SEO string `help:"used to communicate with web crawlers and other web robots" default:"User-agent: *\nDisallow: \nDisallow: /cgi-bin/"`
SatelliteName string `help:"used to display at web satellite console" default:"Storj"`
SatelliteOperator string `help:"name of organization which set up satellite" default:"Storj Labs" `
TermsAndConditionsURL string `help:"url link to terms and conditions page" default:"https://storj.io/storage-sla/"`
AccountActivationRedirectURL string `help:"url link for account activation redirect" default:""`
VerificationPageURL string `help:"url link to sign up verification page" devDefault:"" releaseDefault:"https://tardigrade.io/verify"`
PartneredSatelliteNames string `help:"names of partnered satellites" default:"US1,EU1,AP1"`
GeneralRequestURL string `help:"url link to general request page" default:"https://supportdcs.storj.io/hc/en-us/requests/new?ticket_form_id=360000379291"`
ProjectLimitsIncreaseRequestURL string `help:"url link to project limit increase request page" default:"https://supportdcs.storj.io/hc/en-us/requests/new?ticket_form_id=360000683212"`
GatewayCredentialsRequestURL string `help:"url link for gateway credentials requests" default:"https://auth.us1.storjshare.io"`
IsBetaSatellite bool `help:"indicates if satellite is in beta" default:"false"`
BetaSatelliteFeedbackURL string `help:"url link for for beta satellite feedback" default:""`
BetaSatelliteSupportURL string `help:"url link for for beta satellite support" default:""`
DocumentationURL string `help:"url link to documentation" default:"https://docs.storj.io/"`
CouponCodeUIEnabled bool `help:"indicates if user is allowed to add coupon codes to account" default:"false"`
FileBrowserFlowDisabled bool `help:"indicates if file browser flow is disabled" default:"false"`
CSPEnabled bool `help:"indicates if Content Security Policy is enabled" devDefault:"false" releaseDefault:"true"`
LinksharingURL string `help:"url link for linksharing requests" default:"https://link.us1.storjshare.io"`
PathwayOverviewEnabled bool `help:"indicates if the overview onboarding step should render with pathways" default:"true"`
ContactInfoURL string `help:"url link to contacts page" default:"https://forum.storj.io"`
FrameAncestors string `help:"allow domains to embed the satellite in a frame, space separated" default:"tardigrade.io storj.io"`
LetUsKnowURL string `help:"url link to let us know page" default:"https://storjlabs.atlassian.net/servicedesk/customer/portals"`
SEO string `help:"used to communicate with web crawlers and other web robots" default:"User-agent: *\nDisallow: \nDisallow: /cgi-bin/"`
SatelliteName string `help:"used to display at web satellite console" default:"Storj"`
SatelliteOperator string `help:"name of organization which set up satellite" default:"Storj Labs" `
TermsAndConditionsURL string `help:"url link to terms and conditions page" default:"https://storj.io/storage-sla/"`
AccountActivationRedirectURL string `help:"url link for account activation redirect" default:""`
PartneredSatellites SatList `help:"names and addresses of partnered satellites in JSON list format" default:"[[\"US1\",\"https://us1.storj.io\"],[\"EU1\",\"https://eu1.storj.io\"],[\"AP1\",\"https://ap1.storj.io\"]]"`
GeneralRequestURL string `help:"url link to general request page" default:"https://supportdcs.storj.io/hc/en-us/requests/new?ticket_form_id=360000379291"`
ProjectLimitsIncreaseRequestURL string `help:"url link to project limit increase request page" default:"https://supportdcs.storj.io/hc/en-us/requests/new?ticket_form_id=360000683212"`
GatewayCredentialsRequestURL string `help:"url link for gateway credentials requests" default:"https://auth.us1.storjshare.io"`
IsBetaSatellite bool `help:"indicates if satellite is in beta" default:"false"`
BetaSatelliteFeedbackURL string `help:"url link for for beta satellite feedback" default:""`
BetaSatelliteSupportURL string `help:"url link for for beta satellite support" default:""`
DocumentationURL string `help:"url link to documentation" default:"https://docs.storj.io/"`
CouponCodeUIEnabled bool `help:"indicates if user is allowed to add coupon codes to account" default:"false"`
FileBrowserFlowDisabled bool `help:"indicates if file browser flow is disabled" default:"false"`
CSPEnabled bool `help:"indicates if Content Security Policy is enabled" devDefault:"false" releaseDefault:"true"`
LinksharingURL string `help:"url link for linksharing requests" default:"https://link.us1.storjshare.io"`
PathwayOverviewEnabled bool `help:"indicates if the overview onboarding step should render with pathways" default:"true"`
RateLimit web.IPRateLimiterConfig
console.Config
}
// SatList is a configuration value that contains a list of satellite names and addresses.
// Format should be [[name,address],[name,address],...] in valid JSON format.
//
// Can be used as a flag.
type SatList string
// Type implements pflag.Value.
func (SatList) Type() string { return "consoleweb.SatList" }
// String is required for pflag.Value.
func (sl *SatList) String() string {
return string(*sl)
}
// Set does validation on the configured JSON, but does not actually transform it - it will be passed to the client as-is.
func (sl *SatList) Set(s string) error {
satellites := make([][]string, 3)
err := json.Unmarshal([]byte(s), &satellites)
if err != nil {
return err
}
for _, sat := range satellites {
if len(sat) != 2 {
return errs.New("Could not parse satellite list config. Each satellite in the config must have two values: [name, address]")
}
}
*sl = SatList(s)
return nil
}
// Server represents console web server.
//
// architecture: Endpoint
@ -308,8 +340,7 @@ func (server *Server) appHandler(w http.ResponseWriter, r *http.Request) {
SatelliteName string
SatelliteNodeURL string
StripePublicKey string
VerificationPageURL string
PartneredSatelliteNames string
PartneredSatellites string
DefaultProjectLimit int
GeneralRequestURL string
ProjectLimitsIncreaseRequestURL string
@ -331,8 +362,7 @@ func (server *Server) appHandler(w http.ResponseWriter, r *http.Request) {
data.SatelliteName = server.config.SatelliteName
data.SatelliteNodeURL = server.nodeURL.String()
data.StripePublicKey = server.stripePublicKey
data.VerificationPageURL = server.config.VerificationPageURL
data.PartneredSatelliteNames = server.config.PartneredSatelliteNames
data.PartneredSatellites = string(server.config.PartneredSatellites)
data.DefaultProjectLimit = server.config.DefaultProjectLimit
data.GeneralRequestURL = server.config.GeneralRequestURL
data.ProjectLimitsIncreaseRequestURL = server.config.ProjectLimitsIncreaseRequestURL

View File

@ -130,8 +130,8 @@ compensation.withheld-percents: 75,75,75,50,50,50,25,25,25,0,0,0,0,0,0
# enable open registration
# console.open-registration-enabled: false
# names of partnered satellites
# console.partnered-satellite-names: US1,EU1,AP1
# names and addresses of partnered satellites in JSON list format
# console.partnered-satellites: '[["US1","https://us1.storj.io"],["EU1","https://eu1.storj.io"],["AP1","https://ap1.storj.io"]]'
# indicates if the overview onboarding step should render with pathways
# console.pathway-overview-enabled: true
@ -169,9 +169,6 @@ compensation.withheld-percents: 75,75,75,50,50,50,25,25,25,0,0,0,0,0,0
# the default storage usage limit
# console.usage-limits.default-storage-limit: 50.00 GB
# url link to sign up verification page
# console.verification-page-url: https://tardigrade.io/verify
# the public address of the node, useful for nodes behind NAT
contact.external-address: ""

View File

@ -7,8 +7,7 @@
<meta name="satellite-name" content="{{ .SatelliteName }}">
<meta name="satellite-nodeurl" content="{{ .SatelliteNodeURL }}">
<meta name="stripe-public-key" content="{{ .StripePublicKey }}">
<meta name="verification-page-url" content="{{ .VerificationPageURL }}">
<meta name="partnered-satellite-names" content="{{ .PartneredSatelliteNames }}">
<meta name="partnered-satellites" content="{{ .PartneredSatellites }}">
<meta name="default-project-limit" content="{{ .DefaultProjectLimit }}">
<meta name="general-request-url" content="{{ .GeneralRequestURL }}">
<meta name="project-limits-increase-request-url" content="{{ .ProjectLimitsIncreaseRequestURL }}">

View File

@ -14,6 +14,7 @@ import { Component, Vue } from 'vue-property-decorator';
import NotificationArea from '@/components/notifications/NotificationArea.vue';
import { PartneredSatellite } from '@/types/common.ts';
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
import { MetaUtils } from '@/utils/meta';
@ -29,11 +30,25 @@ export default class App extends Vue {
*/
public mounted(): void {
const satelliteName = MetaUtils.getMetaContent('satellite-name');
const partneredSatellitesJson = JSON.parse(MetaUtils.getMetaContent('partnered-satellites'));
const isBetaSatellite = MetaUtils.getMetaContent('is-beta-satellite');
const couponCodeUIEnabled = MetaUtils.getMetaContent('coupon-code-ui-enabled');
if (satelliteName) {
this.$store.dispatch(APP_STATE_ACTIONS.SET_SATELLITE_NAME, satelliteName);
if (partneredSatellitesJson) {
const partneredSatellites: PartneredSatellite[] = [];
partneredSatellitesJson.forEach((partner) => {
const name = partner[0];
const address = partner[1];
// skip current satellite
if (name !== satelliteName) {
partneredSatellites.push(new PartneredSatellite(name, address));
}
});
this.$store.dispatch(APP_STATE_ACTIONS.SET_PARTNERED_SATELLITES, partneredSatellites);
}
}
if (isBetaSatellite) {

View File

@ -1,19 +1,59 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
<template src="./registrationSuccess.html"></template>
<template>
<div class="register-success-area">
<div class="register-success-area__form-container">
<MailIcon/>
<h2 class="register-success-area__form-container__title">You're almost there!</h2>
<p class="register-success-area__form-container__sub-title">
Check your email to confirm your account and get started.
</p>
<p class="register-success-area__form-container__text">
Didn't receive a verification email?
<b class="register-success-area__form-container__verification-cooldown__bold-text">
{{timeToEnableResendEmailButton}}
</b>
</p>
<div class="register-success-area__form-container__button-container">
<VButton
label="Resend Email"
width="450px"
height="50px"
:on-press="onResendEmailButtonClick"
:is-disabled="isResendEmailButtonDisabled"
/>
</div>
<p class="register-success-area__form-container__contact">
or
<a
class="register-success-area__form-container__contact__link"
href="https://support.storj.io/hc/en-us"
target="_blank"
rel="noopener noreferrer"
>
Contact our support team
</a>
</p>
</div>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import VButton from '@/components/common/VButton.vue';
import MailIcon from '@/../static/images/register/mail.svg';
import { AuthHttpApi } from '@/api/auth';
import { LocalData } from '@/utils/localData';
@Component({
components: {
VButton,
MailIcon,
},
})
export default class RegistrationSuccess extends Vue {
@ -93,4 +133,103 @@ export default class RegistrationSuccess extends Vue {
}
</script>
<style scoped lang="scss" src="./registrationSuccess.scss"></style>
<style scoped lang="scss">
.register-success-area {
display: flex;
align-items: center;
justify-content: center;
font-family: 'font_regular', sans-serif;
&__form-container {
padding: 100px;
max-width: 395px;
text-align: center;
border-radius: 20px;
background-color: #fff;
box-shadow: 0 0 19px 9px #ddd;
display: flex;
flex-direction: column;
align-items: center;
&__title {
font-family: 'font_bold', sans-serif;
font-size: 40px;
line-height: 1.2;
color: #252525;
margin: 25px 0;
}
&__sub-title {
font-size: 16px;
line-height: 21px;
color: #252525;
margin: 0;
max-width: 350px;
}
&__text {
font-family: 'font_medium', sans-serif;
font-size: 16px;
line-height: 21px;
color: #252525;
margin: 27px 0 0 0;
}
&__verification-cooldown {
font-family: 'font_medium', sans-serif;
font-size: 12px;
line-height: 16px;
padding: 27px 0 0 0;
margin: 0;
&__bold-text {
color: #252525;
}
}
&__button-container {
width: 100%;
display: flex;
justify-content: center;
align-items: center;
margin-top: 15px;
}
&__contact {
margin-top: 20px;
&__link {
color: #376fff;
&:visited {
color: #376fff;
}
}
}
}
}
@media screen and (max-width: 650px) {
.register-success-area {
&__form-container {
padding: 50px;
}
}
/deep/ .container {
width: 100% !important;
}
}
@media screen and (max-width: 500px) {
.register-success-area {
&__form-container {
padding: 50px 20px;
}
}
}
</style>

View File

@ -1,19 +0,0 @@
<!--Copyright (C) 2019 Storj Labs, Inc.-->
<!--See LICENSE for copying information.-->
<div class="register-success-area" >
<div class="register-success-area__form-container">
<h2 class="register-success-area__form-container__title">Account Created!</h2>
<span class="register-success-area__form-container__sub-title">Check your email to complete registration.</span>
<p class="register-success-area__form-container__text">Didnt receive a verification email?<b class="register-success-area__form-container__verification-cooldown__bold-text"> {{timeToEnableResendEmailButton}}</b></p>
<div class="register-success-area__form-container__button-container">
<VButton
label="Resend Email"
width="450px"
height="50px"
:on-press="onResendEmailButtonClick"
:is-disabled="isResendEmailButtonDisabled"
/>
</div>
</div>
</div>

View File

@ -1,70 +0,0 @@
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
.register-success-area {
width: calc(100% - 150px);
display: flex;
align-items: center;
justify-content: center;
padding: 80px 100px 80px 50px;
font-family: 'font_regular', sans-serif;
&__form-container {
max-width: 440px;
&__title {
font-family: 'font_bold', sans-serif;
font-size: 32px;
line-height: 39px;
color: #384b65;
margin: 0 0 25px 0;
}
&__sub-title {
font-size: 16px;
line-height: 21px;
color: #354049;
}
&__text {
font-family: 'font_medium', sans-serif;
font-size: 16px;
line-height: 21px;
color: #354049;
margin: 27px 0 0 0;
}
&__verification-cooldown {
font-family: 'font_medium', sans-serif;
font-size: 12px;
line-height: 16px;
color: #354049;
padding: 27px 0 0 0;
margin: 0;
&__bold-text {
color: #2683ff;
}
}
&__button-container {
width: 100%;
display: flex;
justify-content: center;
align-items: center;
margin-top: 15px;
}
}
}
@media screen and (max-width: 650px) {
.register-success-area {
width: 100%;
padding: 100px 0 50px 0;
}
/deep/ .container {
width: 100% !important;
}
}

View File

@ -1,6 +1,7 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
import { PartneredSatellite } from '@/types/common.ts';
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
import { AppState } from '@/utils/constants/appStateEnum';
@ -30,6 +31,7 @@ export const appStateModule = {
isCreateProjectButtonShown: false,
},
satelliteName: '',
partneredSatellites: new Array<PartneredSatellite>(),
isBetaSatellite: false,
couponCodeUIEnabled: false,
},
@ -127,6 +129,9 @@ export const appStateModule = {
[APP_STATE_MUTATIONS.SET_SATELLITE_NAME](state: any, satelliteName: string): void {
state.satelliteName = satelliteName;
},
[APP_STATE_MUTATIONS.SET_PARTNERED_SATELLITES](state: any, partneredSatellites: PartneredSatellite[]): void {
state.partneredSatellites = partneredSatellites;
},
[APP_STATE_MUTATIONS.SET_SATELLITE_STATUS](state: any, isBetaSatellite: boolean): void {
state.isBetaSatellite = isBetaSatellite;
},
@ -269,6 +274,9 @@ export const appStateModule = {
[APP_STATE_ACTIONS.SET_SATELLITE_NAME]: function ({commit}: any, satelliteName: string): void {
commit(APP_STATE_MUTATIONS.SET_SATELLITE_NAME, satelliteName);
},
[APP_STATE_ACTIONS.SET_PARTNERED_SATELLITES]: function ({commit}: any, partneredSatellites: PartneredSatellite[]): void {
commit(APP_STATE_MUTATIONS.SET_PARTNERED_SATELLITES, partneredSatellites);
},
[APP_STATE_ACTIONS.SET_SATELLITE_STATUS]: function ({commit}: any, isBetaSatellite: boolean): void {
commit(APP_STATE_MUTATIONS.SET_SATELLITE_STATUS, isBetaSatellite);
},

View File

@ -32,6 +32,7 @@ export const APP_STATE_MUTATIONS = {
CHANGE_STATE: 'CHANGE_STATE',
TOGGLE_PAYMENT_SELECTION: 'TOGGLE_PAYMENT_SELECTION',
SET_SATELLITE_NAME: 'SET_SATELLITE_NAME',
SET_PARTNERED_SATELLITES: 'SET_PARTNERED_SATELLITES',
SET_SATELLITE_STATUS: 'SET_SATELLITE_STATUS',
SHOW_CREATE_PROJECT_BUTTON: 'SHOW_CREATE_PROJECT_BUTTON',
HIDE_CREATE_PROJECT_BUTTON: 'HIDE_CREATE_PROJECT_BUTTON',

View File

@ -5,3 +5,10 @@ export enum SortDirection {
ASCENDING = 1,
DESCENDING,
}
export class PartneredSatellite {
constructor(
public name: string = '',
public address: string = '',
) {}
}

View File

@ -26,6 +26,7 @@ export const APP_STATE_ACTIONS = {
CHANGE_STATE: 'changeFetchState',
TOGGLE_PAYMENT_SELECTION: 'TOGGLE_PAYMENT_SELECTION',
SET_SATELLITE_NAME: 'SET_SATELLITE_NAME',
SET_PARTNERED_SATELLITES: 'SET_PARTNERED_SATELLITES',
SET_SATELLITE_STATUS: 'SET_SATELLITE_STATUS',
SHOW_CREATE_PROJECT_BUTTON: 'SHOW_CREATE_PROJECT_BUTTON',
HIDE_CREATE_PROJECT_BUTTON: 'HIDE_CREATE_PROJECT_BUTTON',

View File

@ -12,15 +12,17 @@ import PasswordStrength from '@/components/common/PasswordStrength.vue';
import RegistrationSuccess from '@/components/common/RegistrationSuccess.vue';
import AuthIcon from '@/../static/images/AuthImage.svg';
import BottomArrowIcon from '@/../static/images/common/lightBottomArrow.svg';
import SelectedCheckIcon from '@/../static/images/common/selectedCheck.svg';
import LogoIcon from '@/../static/images/dcs-logo.svg';
import InfoIcon from '@/../static/images/info.svg';
import { AuthHttpApi } from '@/api/auth';
import { RouteConfig } from '@/router';
import { PartneredSatellite } from '@/types/common';
import { User } from '@/types/users';
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
import { LocalData } from '@/utils/localData';
import { MetaUtils } from '@/utils/meta';
import { Validator } from '@/utils/validation';
@Component({
@ -28,6 +30,8 @@ import { Validator } from '@/utils/validation';
HeaderlessInput,
RegistrationSuccess,
AuthIcon,
BottomArrowIcon,
SelectedCheckIcon,
LogoIcon,
InfoIcon,
PasswordStrength,
@ -199,6 +203,20 @@ export default class RegisterArea extends Vue {
this.repeatedPasswordError = '';
}
/**
* Name of the current satellite.
*/
public get satelliteName(): string {
return this.$store.state.appStateModule.satelliteName;
}
/**
* Information about partnered satellites, including name and signup link.
*/
public get partneredSatellites(): PartneredSatellite[] {
return this.$store.state.appStateModule.partneredSatellites;
}
/**
* Indicates if satellite is in beta.
*/
@ -312,17 +330,6 @@ export default class RegisterArea extends Vue {
this.userId = await this.auth.register(this.user, this.secret);
LocalData.setUserId(this.userId);
const verificationPageURL: string = MetaUtils.getMetaContent('verification-page-url');
if (verificationPageURL) {
const externalAddress: string = MetaUtils.getMetaContent('external-address');
const url = new URL(verificationPageURL);
url.searchParams.append('redirect', externalAddress);
window.top.location.href = url.href;
return;
}
await this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_SUCCESSFUL_REGISTRATION);
} catch (error) {
await this.$notify.error(error.message);

View File

@ -1,53 +1,120 @@
<!--Copyright (C) 2019 Storj Labs, Inc.-->
<!--Copyright (C) 2021 Storj Labs, Inc.-->
<!--See LICENSE for copying information.-->
<div class="register-container" @keyup.enter="onCreateClick">
<AuthIcon
class="image"
alt="Authentication illustration"
/>
<div class="register-container__wrapper">
<div class="register-container__header">
<LogoIcon
class="register-container__logo"
alt="Company logo"
@click="onLogoClick"
/>
<div class="register-container__register-button" @click.prevent="onLoginClick">
<p class="register-container__register-button__label">Login</p>
</div>
</div>
<div class="register-area-wrapper">
<div class="register-area" v-if="!isRegistrationSuccessful">
<div class="register-area__title-container">
<h1 class="register-area__title-container__title">Sign Up to Storj</h1>
<div class="register-area" @keyup.enter="onCreateClick">
<div class="register-area__logo-wrapper">
<LogoIcon class="logo" @click="onLogoClick"/>
</div>
<div class="register-area__content-area">
<div
class="register-area__content-area__container"
:class="{ 'professional-container': isProfessional }"
v-if="!isRegistrationSuccessful"
>
<div class="register-area__content-area__container__title-area">
<div class="register-area__content-area__container__title-container">
<h1 class="register-area__content-area__container__title-area__title">Start for Free</h1>
<p class="register-area__content-area__container__title-area__sub-title">What are you using Storj DCS for?</p>
</div>
<div class="register-area__content-area__expand" @click.stop="toggleDropdown">
<span class="register-area__content-area__expand__value">{{ satelliteName }}</span>
<BottomArrowIcon />
<div class="register-area__content-area__expand__dropdown" v-if="isDropdownShown" v-click-outside="closeDropdown">
<div class="register-area__content-area__expand__dropdown__item" @click.stop="closeDropdown">
<SelectedCheckIcon />
<span class="register-area__content-area__expand__dropdown__item__name">{{ satelliteName }}</span>
</div>
<a v-for="sat in partneredSatellites" class="register-area__content-area__expand__dropdown__item" :href="sat.address + '/signup'">
{{ sat.name }}
</a>
</div>
</div>
</div>
<div class="register-area__content-area__toggle__conatainer">
<ul class="register-area__content-area__toggle__wrapper">
<li
class="register-area__content-area__toggle__personal"
:class="{ 'active': !isProfessional }"
@click.prevent="toggleAccountType(false)"
>
Personal
</li>
<li
class="register-area__content-area__toggle__professional"
:class="{ 'active': isProfessional }"
@click.prevent="toggleAccountType(true)"
>
Business
</li>
</ul>
</div>
<div class="register-area__input-wrapper first-input">
<HeaderlessInput
class="full-input"
label="Full Name"
placeholder="Enter Full Name"
:error="fullNameError"
@setData="setFullName"
width="100%"
width="calc(100% - 2px)"
height="46px"
/>
</div>
<div class="register-area__input-wrapper">
<HeaderlessInput
class="full-input"
label="Email"
placeholder="Enter Email"
label="Email Address"
placeholder="example@email.com"
:error="emailError"
@setData="setEmail"
width="100%"
width="calc(100% - 2px)"
height="46px"
/>
<div class="register-input">
</div>
<div v-if="isProfessional">
<div class="register-area__input-wrapper">
<HeaderlessInput
class="full-input"
label="Company Name"
placeholder="Acme Corp."
:error="companyNameError"
@setData="setCompanyName"
width="calc(100% - 2px)"
height="46px"
/>
</div>
<div class="register-area__input-wrapper">
<HeaderlessInput
class="full-input"
label="Position"
placeholder="Position Title"
:error="positionError"
@setData="setPosition"
width="calc(100% - 2px)"
height="46px"
/>
</div>
<div class="register-area__input-wrapper">
<HeaderlessInput
class="full-input"
label="Employees"
placeholder="Employees"
:error="employeeCountError"
@setData="setEmployeeCount"
width="calc(100% - 2px)"
height="46px"
:optionsList="employeeCountOptions"
/>
</div>
</div>
<div class="register-input">
<div class="register-area__input-wrapper">
<HeaderlessInput
class="full-input"
label="Password"
placeholder="Enter Password"
:error="passwordError"
@setData="setPassword"
width="100%"
width="calc(100% - 2px)"
height="46px"
is-password="true"
@showPasswordStrength="showPasswordStrength"
@ -58,32 +125,43 @@
:is-shown="isPasswordStrengthShown"
/>
</div>
<div class="register-input">
<HeaderlessInput
class="full-input"
label="Confirm Password"
placeholder="Confirm Password"
:error="repeatedPasswordError"
@setData="setRepeatedPassword"
width="100%"
height="46px"
is-password="true"
/>
</div>
<div class="register-area__submit-container">
<div class="register-area__submit-container__terms-area">
<label class="container">
<input type="checkbox" id="terms" v-model="isTermsAccepted">
<span class="checkmark" :class="{'error': isTermsAcceptedError}"/>
</label>
<h2 class="register-area__submit-container__terms-area__terms-confirmation"><label for="terms">I agree to the </label><a class="register-area__submit-container__terms-area__link" href="https://tardigrade.io/terms-of-use/" target="_blank">Terms & Conditions</a></h2>
</div>
<div id="createAccountButton" class="register-area__submit-container__create-button" @click.prevent="onCreateClick">
<p class="register-area__submit-container__create-button__label">Create Account</p>
</div>
</div>
</div>
<RegistrationSuccess v-if="isRegistrationSuccessful"/>
<div class="register-area__input-wrapper">
<HeaderlessInput
class="full-input"
label="Retype Password"
placeholder="Retype Password"
:error="repeatedPasswordError"
@setData="setRepeatedPassword"
width="calc(100% - 2px)"
height="46px"
is-password="true"
/>
</div>
<AddCouponCodeInput v-if="couponCodeUIEnabled" />
<div class="register-area__content-area__container__terms-area">
<label class="container">
<input id="terms" type="checkbox" v-model="isTermsAccepted">
<span class="checkmark" :class="{'error': isTermsAcceptedError}"></span>
</label>
<label class="register-area__content-area__container__terms-area__msg-box" for="terms">
<p class="register-area__content-area__container__terms-area__msg-box__msg">
I agree to the
<a class="register-area__content-area__container__terms-area__msg-box__msg__link" href="https://storj.io/terms-of-service/" target="_blank" rel="noopener">Terms of Service</a>
and
<a class="register-area__content-area__container__terms-area__msg-box__msg__link" href="https://storj.io/privacy-policy/" target="_blank" rel="noopener">Privacy Policy</a>
</p>
</label>
</div>
<p class="register-area__content-area__container__button" @click.prevent="onCreateClick">Sign Up</p>
</div>
<RegistrationSuccess v-if="isRegistrationSuccessful"/>
<div class="register-area__content-area__login-container">
<router-link :to="loginPath" class="register-area__content-area__login-container__link">
Already have an account? Login.
</router-link>
</div>
</div>
</div>

View File

@ -1,4 +1,4 @@
// Copyright (C) 2019 Storj Labs, Inc.
// Copyright (C) 2021 Storj Labs, Inc.
// See LICENSE for copying information.
body {
@ -6,408 +6,396 @@ body {
margin: 0 !important;
}
.register-container {
position: fixed;
width: 100%;
height: 100%;
left: 0;
top: 0;
z-index: 10;
background-size: contain;
display: flex;
justify-content: flex-start;
flex-direction: column;
align-items: flex-start;
padding: 60px 0 0 104px;
background-color: #f5f6fa;
font-family: 'font_regular', sans-serif;
.register-input {
position: relative;
width: 100%;
&__info-button {
position: absolute;
top: 58px;
right: 53px;
}
}
&__wrapper {
min-width: 50%;
height: 86vh;
}
&__header {
display: flex;
align-items: center;
justify-content: space-between;
flex-direction: row;
width: 100%;
}
&__logo {
cursor: pointer;
width: 207px;
height: 62px;
}
&__register-button {
display: flex;
align-items: center;
justify-content: center;
background-color: transparent;
border-radius: 6px;
border: 1px solid #afb7c1;
cursor: pointer;
width: 160px;
height: 48px;
&__label {
font-family: 'font_bold', sans-serif;
font-size: 14px;
line-height: 19px;
margin-block-start: 0;
margin-block-end: 0;
color: #354049;
}
&:hover {
background-color: #2683ff;
border: 1px solid #2683ff;
.register-container__register-button__label {
color: white;
}
}
}
}
.register-area-wrapper {
width: 100%;
height: 100%;
display: flex;
align-items: flex-start;
justify-content: flex-end;
margin-top: 50px;
p,
h1 {
margin: 0;
}
.register-area {
background-color: transparent;
width: 620px;
border-radius: 6px;
display: flex;
justify-content: center;
flex-direction: column;
align-items: flex-start;
align-items: center;
font-family: 'font_regular', sans-serif;
background-color: #f5f6fa;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
min-height: 100%;
overflow-y: scroll;
&__title-container {
height: 48px;
display: flex;
justify-content: space-between;
align-items: flex-end;
flex-direction: row;
margin-bottom: 20px;
width: 100%;
&__title {
font-family: 'font_bold', sans-serif;
font-size: 22px;
color: #384b65;
line-height: 27px;
margin-block-start: 0;
margin-block-end: 0;
}
&__logo-wrapper {
text-align: center;
margin-top: 60px;
}
&__submit-container {
&__input-wrapper {
margin-top: 20px;
}
&__input-wrapper.first-input {
margin-top: 10px;
}
&__content-area {
background-color: #f5f6fa;
padding: 55px 20px 0 20px;
display: flex;
flex-direction: row;
flex-direction: column;
align-items: center;
justify-content: space-between;
width: 100%;
&__terms-area {
&__expand {
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
position: relative;
bottom: 10px;
&__checkbox {
align-self: center;
&__value {
font-family: 'font_normal', sans-serif;
font-weight: 700;
font-size: 16px;
line-height: 21px;
color: #afb7c1;
margin-right: 10px;
}
&__terms-confirmation {
font-size: 14px;
line-height: 20px;
margin: 4px 0 0 10px;
&__dropdown {
position: absolute;
top: 35px;
left: 0;
background-color: #fff;
z-index: 1000;
border: 1px solid #c5cbdb;
box-shadow: 0 8px 34px rgba(161, 173, 185, 0.41);
border-radius: 6px;
min-width: 250px;
&__item {
display: flex;
align-items: center;
justify-content: flex-start;
padding: 12px 25px;
font-size: 14px;
line-height: 20px;
color: #7e8b9c;
cursor: pointer;
text-decoration: none;
&__name {
font-family: 'font_bold', sans-serif;
margin-left: 15px;
font-size: 14px;
line-height: 20px;
color: #7e8b9c;
}
&:hover {
background-color: #f2f2f6;
}
}
}
}
&__toggle {
&__wrapper {
display: flex;
justify-content: space-between;
margin: 20px 0 15px 0;
list-style: none;
padding: 0;
}
&__personal {
border-top-left-radius: 20px;
border-bottom-left-radius: 20px;
border-right: none;
}
&__professional {
border-top-right-radius: 20px;
border-bottom-right-radius: 20px;
border-left: none;
}
&__personal,
&__professional {
color: #376fff;
display: block;
width: 100%;
text-align: center;
padding: 8px;
border: 1px solid #376fff;
cursor: pointer;
}
&__personal.active,
&__professional.active {
color: #fff;
background: #376fff;
font-weight: bold;
}
}
&__container {
display: flex;
flex-direction: column;
padding: 60px 80px;
background-color: #fff;
border-radius: 6px;
min-height: 675px;
&__title-area {
display: flex;
justify-content: space-between;
align-items: center;
&__title {
font-size: 24px;
line-height: 49px;
letter-spacing: -0.100741px;
color: #252525;
font-family: 'font_normal', sans-serif;
font-weight: 800;
white-space: nowrap;
}
&__satellite {
font-size: 16px;
line-height: 21px;
color: #848484;
}
}
&__terms-area {
display: flex;
align-items: center;
width: 100%;
margin-top: 30px;
&__msg-box {
font-size: 14px;
line-height: 20px;
color: #354049;
&__msg {
&__link {
margin: 0 4px;
font-family: 'font_bold', sans-serif;
&:hover {
text-decoration: underline !important;
}
&:visited {
color: inherit;
}
}
}
}
}
&__button {
font-family: 'font_normal', sans-serif;
font-weight: 700;
margin-top: 30px;
display: flex;
justify-content: center;
align-items: center;
background-color: #376fff;
border-radius: 50px;
color: #fff;
cursor: pointer;
width: 100%;
min-height: 48px;
&:hover {
background-color: #0059d0;
}
}
}
&__container.professional-container {
min-height: 901px;
}
&__footer {
display: flex;
justify-content: center;
align-items: flex-start;
margin-top: 40px;
width: 100%;
&__copyright {
font-size: 12px;
line-height: 18px;
color: #384b65;
padding-bottom: 20px;
}
&__link {
color: #2683ff;
font-family: 'font_bold', sans-serif;
&:hover {
text-decoration: underline;
}
}
.container {
display: block;
position: relative;
padding-left: 20px;
height: 23px;
width: 23px;
cursor: pointer;
font-size: 22px;
outline: none;
}
.container input {
position: absolute;
opacity: 0;
cursor: pointer;
height: 0;
width: 0;
}
.checkmark {
position: absolute;
top: 0;
left: 0;
height: 25px;
width: 25px;
border: 2px solid #384b65;
border-radius: 4px;
}
.container:hover input ~ .checkmark {
background-color: white;
}
.container input:checked ~ .checkmark {
border: 2px solid #384b65;
background-color: transparent;
}
.checkmark:after {
content: '';
position: absolute;
display: none;
}
.checkmark.error {
border-color: red;
}
.container .checkmark:after {
left: 9px;
top: 5px;
width: 5px;
height: 10px;
border: solid #384b65;
border-width: 0 3px 3px 0;
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
.container input:checked ~ .checkmark:after {
display: block;
font-size: 12px;
line-height: 18px;
margin-left: 30px;
color: #376fff;
text-decoration: none;
}
}
&__create-button {
&__login-container {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
background-color: #2683ff;
border-radius: 6px;
cursor: pointer;
width: 160px;
height: 48px;
box-shadow: none;
margin-top: 50px;
padding-bottom: 20px;
text-align: center;
&__label {
font-family: 'font_bold', sans-serif;
&__link {
font-family: 'font_medium', sans-serif;
text-decoration: none;
font-size: 14px;
line-height: 19px;
margin-block-start: 0;
margin-block-end: 0;
color: white;
}
&:hover {
background-color: #0059d0;
line-height: 18px;
color: #376fff;
}
}
}
}
.logo {
cursor: pointer;
}
.register-input {
position: relative;
width: 100%;
}
.input-wrap.full-input {
width: 100%;
margin-bottom: 15px;
width: calc(100% - 2px);
}
.image {
position: fixed;
right: 0;
.container {
display: block;
position: relative;
padding-left: 20px;
height: 21px;
width: 21px;
cursor: pointer;
font-size: 22px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
outline: none;
}
.container input {
position: absolute;
opacity: 0;
cursor: pointer;
height: 0;
width: 0;
}
.checkmark {
position: absolute;
top: 0;
bottom: 0;
height: 100vh;
.st1 { fill: #2683ff; }
.st2 { fill: #007aff; }
.st3 { fill: #0062ff; }
.st4 { fill: #fff; }
.st5 { fill: #6cb9ff; }
.st6 { fill: #499ffc; }
.st7 { fill: #f7f9f9; }
.st8 { fill: #0f002d; }
.st9 { fill: #dedefc; }
left: 0;
height: 21px;
width: 21px;
border: 2px solid #afb7c1;
border-radius: 4px;
}
@media screen and (max-width: 1500px) {
.register-container {
&__wrapper {
min-width: 45%;
}
}
.container:hover input ~ .checkmark {
background-color: white;
}
@media screen and (max-width: 1300px) {
.register-container {
&__wrapper {
min-width: 75%;
}
}
.image {
display: none;
}
.container input:checked ~ .checkmark {
border: 2px solid #afb7c1;
background-color: transparent;
}
@media screen and (max-height: 840px) {
.register-container {
overflow: hidden;
&__wrapper {
height: 770px;
overflow-y: scroll;
overflow-x: hidden;
-ms-overflow-style: none;
overflow: -moz-scrollbars-none;
&::-webkit-scrollbar {
width: 0 !important;
display: none;
}
}
}
.checkmark:after {
content: '';
position: absolute;
display: none;
}
@media screen and (max-height: 810px) {
.register-container {
&__wrapper {
height: 700px;
}
}
.register-area__submit-container {
margin-bottom: 25px;
}
.checkmark.error {
border-color: red;
}
@media screen and (max-width: 800px) {
.register-container {
padding: 0;
align-items: center;
justify-content: center;
}
.container .checkmark:after {
left: 7px;
top: 3px;
width: 5px;
height: 10px;
border: solid #354049;
border-width: 0 3px 3px 0;
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
@media screen and (max-width: 650px) {
.register-container {
&__wrapper {
width: 500px;
}
}
.container input:checked ~ .checkmark:after {
display: block;
}
@media screen and (max-width: 520px) {
.register-container {
&__wrapper {
width: 400px;
}
}
}
@media screen and (max-width: 420px) {
.register-container {
&__wrapper {
width: 350px;
}
}
}
@media screen and (max-width: 320px) {
.register-container {
&__wrapper {
width: 300px;
}
&__header {
margin-top: 20px;
}
&__register-button {
width: 120px;
height: 42px;
}
}
@media screen and (max-width: 700px) {
.register-area {
&__title-container {
&__content-area {
width: 100%;
padding: 55px 0 0 0;
&__title {
font-size: 20px;
line-height: 22px;
&__container {
padding: 40px;
width: calc(100% - 80px);
}
}
&__submit-container {
&__toggle {
&__terms-area {
&__terms-confirmation {
font-size: 12px;
&__professional {
right: 1px;
position: relative;
}
}
&__create-button {
height: 40px;
&__expand {
&__label {
font-size: 12px;
&__dropdown {
left: -200px;
}
}
}
}
}
@media screen and (max-width: 414px) {
.register-area {
&__logo-wrapper {
margin-top: 30px;
}
&__content-area {
padding: 30px 0 0 0;
&__container {
padding: 40px 20px;
width: calc(100% - 40px);
}
&__login-container {
margin-top: 25px;
}
}
}
}

View File

@ -0,0 +1,3 @@
<svg class="register-area__content-area__expand__icon" width="10" height="5" viewBox="0 0 10 5" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5 5L0.669873 0.499999L9.33013 0.5L5 5Z" fill="#ACBACE"/>
</svg>

After

Width:  |  Height:  |  Size: 222 B

View File

@ -0,0 +1,3 @@
<svg width="15" height="13" viewBox="0 0 15 13" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14.0928 3.02746C14.6603 2.4239 14.631 1.4746 14.0275 0.907152C13.4239 0.339699 12.4746 0.368972 11.9072 0.972536L14.0928 3.02746ZM4.53846 11L3.44613 12.028C3.72968 12.3293 4.12509 12.5001 4.53884 12.5C4.95258 12.4999 5.34791 12.3289 5.63131 12.0275L4.53846 11ZM3.09234 7.27469C2.52458 6.67141 1.57527 6.64261 0.971991 7.21036C0.36871 7.77812 0.339911 8.72743 0.907664 9.33071L3.09234 7.27469ZM11.9072 0.972536L3.44561 9.97254L5.63131 12.0275L14.0928 3.02746L11.9072 0.972536ZM5.6308 9.97199L3.09234 7.27469L0.907664 9.33071L3.44613 12.028L5.6308 9.97199Z" fill="#2683FF"/>
</svg>

After

Width:  |  Height:  |  Size: 690 B

View File

@ -0,0 +1,16 @@
<svg width="207" height="89" viewBox="0 0 207 89" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="56" y="18" width="81" height="56">
<rect x="56" y="18" width="81" height="56" rx="10" fill="#ABABAB"/>
</mask>
<g mask="url(#mask0)">
<rect x="56" y="18" width="81" height="56" rx="10" fill="#D3DCE6"/>
<path d="M97 207.706L-7.85281 122.853L97 37.9999L201.853 122.853L97 207.706Z" fill="#EAF0F7" fill-opacity="0.3"/>
<path d="M97 -114L201.853 -29.1472L97 55.7056L-7.85283 -29.1472L97 -114Z" fill="#EAF0F7"/>
</g>
<path d="M39 16C34.5817 16 31 12.4183 31 8C31 3.58172 34.5817 0 39 0C43.4183 0 47 3.58172 47 8C47 12.4183 43.4183 16 39 16Z" fill="#FF69A1"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.10494 20L4.95911e-05 25.8885L3.09584 35.4164H13.114L16.2098 25.8885L8.10494 20Z" fill="#276CFF"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M198.105 28L190 33.8885L193.096 43.4164H203.114L206.21 33.8885L198.105 28Z" fill="#276CFF"/>
<path d="M172 78.1127L182.113 68L192.225 78.1127L182.113 88.2254L172 78.1127Z" fill="#00E567"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M161.889 43L152 57.3548H171.778L161.889 43Z" fill="#FFC600"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.8889 50L11 64.3548H30.7778L20.8889 50Z" fill="#FFC600"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB