Improve tenant signup page (#302)

This commit is contained in:
Riccardo Graziosi
2024-03-02 18:36:22 +01:00
committed by GitHub
parent 4969bbc261
commit 719f1ad4e9
17 changed files with 101 additions and 43 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
app/assets/images/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -152,6 +152,9 @@
.postEditFormButtons { .postEditFormButtons {
@extend .d-flex, .justify-content-end; @extend .d-flex, .justify-content-end;
} }
#selectPickerBoard { margin-right: 4px !important; }
#selectPickerStatus { margin-left: 4px !important; }
} }
} }
} }

View File

@@ -1,3 +1,41 @@
.astutoLogo {
display: block;
margin: 12px auto;
}
.tenantSignUpContainer { .tenantSignUpContainer {
@extend .smallContainer; @extend .smallContainer;
}
h1, h2, h3 {
text-align: center;
margin-bottom: 16px;
}
.userConfirm, .tenantConfirm {
display: block;
margin: 0 auto;
margin-top: 16px;
}
.userPasswordDiv, .userPasswordConfirmationDiv {
@extend .col-6;
padding-left: 0;
padding-right: 0;
}
.userPasswordDiv { padding-right: 4px; }
.userPasswordConfirmationDiv { padding-left: 4px; }
.userRecap {
text-align: center;
margin-bottom: 0;
.editUser {
display: block;
width: fit-content;
margin-top: 4px;
margin-left: auto;
margin-right: auto;
}
}
}

View File

@@ -4,7 +4,7 @@ class TenantsController < ApplicationController
before_action :authenticate_admin, only: [:show, :update] before_action :authenticate_admin, only: [:show, :update]
def new def new
@page_title = t('signup.page_title') @page_title = "Create your feedback space"
@o_auths = OAuth.unscoped.where(tenant_id: nil) @o_auths = OAuth.unscoped.where(tenant_id: nil)
end end

View File

@@ -1,20 +1,25 @@
import * as React from 'react'; import * as React from 'react';
import I18n from 'i18n-js';
import Box from '../common/Box'; import Box from '../common/Box';
interface Props { interface Props {
subdomain: string; subdomain: string;
userEmail: string; userEmail: string;
pendingTenantImage: string;
} }
const ConfirmSignUpPage = ({ const ConfirmSignUpPage = ({
subdomain, subdomain,
userEmail, userEmail,
pendingTenantImage,
}: Props) => ( }: Props) => (
<Box> <Box>
<h3>{ I18n.t('signup.step3.title') }</h3> <h3>You're almost done!</h3>
<p>{ I18n.t('signup.step3.message', { email: userEmail, subdomain: `${subdomain}.astuto.io` }) }</p> <img src={pendingTenantImage} width={64} height={64} style={{margin: '12px auto'}} />
<p style={{textAlign: 'center'}}>
Check your email <b>{userEmail}</b> to activate your new feedback space {subdomain}.astuto.io!
</p>
</Box> </Box>
); );

View File

@@ -1,6 +1,5 @@
import * as React from 'react'; import * as React from 'react';
import { SubmitHandler, useForm } from 'react-hook-form'; import { SubmitHandler, useForm } from 'react-hook-form';
import I18n from 'i18n-js';
import Box from '../common/Box'; import Box from '../common/Box';
import Button from '../common/Button'; import Button from '../common/Button';
@@ -28,7 +27,7 @@ const TenantSignUpForm = ({
return ( return (
<Box customClass="tenantSignUpStep2"> <Box customClass="tenantSignUpStep2">
<h3>{ I18n.t('signup.step2.title') }</h3> <h3>Create feedback space</h3>
<form onSubmit={handleSubmit(onSubmit)}> <form onSubmit={handleSubmit(onSubmit)}>
<div className="formRow"> <div className="formRow">
@@ -68,10 +67,10 @@ const TenantSignUpForm = ({
{errors.subdomain?.type === 'required' && getValidationMessage('required', 'tenant', 'subdomain')} {errors.subdomain?.type === 'required' && getValidationMessage('required', 'tenant', 'subdomain')}
</DangerText> </DangerText>
<DangerText> <DangerText>
{errors.subdomain?.type === 'pattern' && I18n.t('signup.step2.validations.subdomain_only_letters_and_numbers')} {errors.subdomain?.type === 'pattern' && 'Subdomain can only contain alphanumeric characters and hyphens'}
</DangerText> </DangerText>
<DangerText> <DangerText>
{errors.subdomain?.type === 'notAlreadyTaken' && I18n.t('signup.step2.validations.subdomain_already_taken')} {errors.subdomain?.type === 'notAlreadyTaken' && 'Sorry, this subdomain is not available'}
</DangerText> </DangerText>
</div> </div>
@@ -79,7 +78,7 @@ const TenantSignUpForm = ({
onClick={() => null} onClick={() => null}
className="tenantConfirm" className="tenantConfirm"
> >
{ isSubmitting ? <Spinner /> : I18n.t('signup.step2.create_button') } { isSubmitting ? <Spinner /> : 'Create feedback space' }
</Button> </Button>
{ error !== '' && <DangerText>{ error }</DangerText> } { error !== '' && <DangerText>{ error }</DangerText> }

View File

@@ -26,6 +26,9 @@ interface Props {
authenticityToken: string, authenticityToken: string,
): Promise<any>; ): Promise<any>;
astutoLogoImage: string;
pendingTenantImage: string;
baseUrl: string; baseUrl: string;
authenticityToken: string; authenticityToken: string;
} }
@@ -50,6 +53,8 @@ const TenantSignUpP = ({
isSubmitting, isSubmitting,
error, error,
handleSubmit, handleSubmit,
astutoLogoImage,
pendingTenantImage,
baseUrl, baseUrl,
authenticityToken authenticityToken
}: Props) => { }: Props) => {
@@ -93,6 +98,9 @@ const TenantSignUpP = ({
} }
return ( return (
<>
<img src={astutoLogoImage} width={64} height={64} className="astutoLogo" />
<div className="tenantSignUpContainer"> <div className="tenantSignUpContainer">
{ {
(currentStep === 1 || currentStep === 2) && (currentStep === 1 || currentStep === 2) &&
@@ -124,9 +132,11 @@ const TenantSignUpP = ({
<ConfirmSignUpPage <ConfirmSignUpPage
subdomain={tenantData.subdomain} subdomain={tenantData.subdomain}
userEmail={userData.email} userEmail={userData.email}
pendingTenantImage={pendingTenantImage}
/> />
} }
</div> </div>
</>
); );
} }

View File

@@ -11,7 +11,7 @@ import { getLabel, getValidationMessage } from '../../helpers/formUtils';
import { EMAIL_REGEX } from '../../constants/regex'; import { EMAIL_REGEX } from '../../constants/regex';
import { IOAuth } from '../../interfaces/IOAuth'; import { IOAuth } from '../../interfaces/IOAuth';
import ActionLink from '../common/ActionLink'; import ActionLink from '../common/ActionLink';
import { BackIcon } from '../common/Icons'; import { BackIcon, EditIcon } from '../common/Icons';
interface Props { interface Props {
currentStep: number; currentStep: number;
@@ -47,7 +47,7 @@ const UserSignUpForm = ({
} = useForm<ITenantSignUpUserForm>(); } = useForm<ITenantSignUpUserForm>();
const onSubmit: SubmitHandler<ITenantSignUpUserForm> = data => { const onSubmit: SubmitHandler<ITenantSignUpUserForm> = data => {
if (data.password !== data.passwordConfirmation) { if (data.password !== data.passwordConfirmation) {
setError('passwordConfirmation', I18n.t('signup.step1.validations.password_mismatch')); setError('passwordConfirmation', I18n.t('common.validations.password_mismatch'));
return; return;
} }
@@ -57,13 +57,13 @@ const UserSignUpForm = ({
return ( return (
<Box customClass="tenantSignUpStep1"> <Box customClass="tenantSignUpStep1">
<h3>{ I18n.t('signup.step1.title') }</h3> <h3>Create user account</h3>
{ {
currentStep === 1 && !emailAuth && currentStep === 1 && !emailAuth &&
<> <>
<Button className="emailAuth" onClick={() => setEmailAuth(true)}> <Button className="emailAuth" onClick={() => setEmailAuth(true)}>
{ I18n.t('signup.step1.email_auth') } Sign up with email
</Button> </Button>
{ {
@@ -118,7 +118,7 @@ const UserSignUpForm = ({
</div> </div>
<div className="formRow"> <div className="formRow">
<div className="formGroup col-6"> <div className="userPasswordDiv">
<input <input
{...register('password', { required: true, minLength: 6, maxLength: 128 })} {...register('password', { required: true, minLength: 6, maxLength: 128 })}
type="password" type="password"
@@ -129,7 +129,7 @@ const UserSignUpForm = ({
<DangerText>{ errors.password && I18n.t('common.validations.password', { n: 6 }) }</DangerText> <DangerText>{ errors.password && I18n.t('common.validations.password', { n: 6 }) }</DangerText>
</div> </div>
<div className="formGroup col-6"> <div className="userPasswordConfirmationDiv">
<input <input
{...register('passwordConfirmation')} {...register('passwordConfirmation')}
type="password" type="password"
@@ -152,12 +152,10 @@ const UserSignUpForm = ({
{ {
currentStep === 2 && !oAuthLoginCompleted && currentStep === 2 && !oAuthLoginCompleted &&
<p><b>{userData.fullName}</b> ({userData.email})</p> <p className="userRecap">
} <b>{oAuthLoginCompleted ? oauthUserName : userData.fullName}</b> ({oAuthLoginCompleted ? oauthUserEmail : userData.email})
<ActionLink onClick={() => setCurrentStep(currentStep-1)} icon={<EditIcon />} customClass="editUser">Edit</ActionLink>
{ </p>
currentStep === 2 && oAuthLoginCompleted &&
<p><b>{oauthUserName}</b> ({oauthUserEmail})</p>
} }
</Box> </Box>
); );

View File

@@ -13,6 +13,8 @@ interface Props {
oauthUserEmail?: string; oauthUserEmail?: string;
oauthUserName?: string; oauthUserName?: string;
baseUrl: string; baseUrl: string;
astutoLogoImage: string;
pendingTenantImage: string;
authenticityToken: string; authenticityToken: string;
} }
@@ -31,6 +33,8 @@ class TenantSignUpRoot extends React.Component<Props> {
oAuthLoginCompleted, oAuthLoginCompleted,
oauthUserEmail, oauthUserEmail,
oauthUserName, oauthUserName,
astutoLogoImage,
pendingTenantImage,
baseUrl, baseUrl,
authenticityToken, authenticityToken,
} = this.props; } = this.props;
@@ -42,6 +46,8 @@ class TenantSignUpRoot extends React.Component<Props> {
oauthUserEmail={oauthUserEmail} oauthUserEmail={oauthUserEmail}
oauthUserName={oauthUserName} oauthUserName={oauthUserName}
oAuths={oAuths.map(oAuth => oAuthJSON2JS(oAuth))} oAuths={oAuths.map(oAuth => oAuthJSON2JS(oAuth))}
astutoLogoImage={astutoLogoImage}
pendingTenantImage={pendingTenantImage}
baseUrl={baseUrl} baseUrl={baseUrl}
authenticityToken={authenticityToken} authenticityToken={authenticityToken}
/> />

View File

@@ -13,6 +13,8 @@
<%= javascript_include_tag "application", "data-turbo-track": "reload" %> <%= javascript_include_tag "application", "data-turbo-track": "reload" %>
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %> <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
<%= favicon_link_tag asset_path('favicon.png') %>
</head> </head>
<body> <body>

View File

@@ -1,5 +1,7 @@
<div class="smallContainer"> <div class="smallContainer">
<div class="box"> <div class="box" style="text-align: center">
<h3><%= t('blocked_tenant.title') %></h3> <h3><%= t('blocked_tenant.title') %></h3>
<%= image_tag("blocked-tenant.png", size: 64, style: "margin: 0 auto") %>
</div> </div>
</div> </div>

View File

@@ -1,6 +1,16 @@
<div class="smallContainer"> <div class="smallContainer">
<div class="box"> <div class="box" style="text-align: center">
<h3><%= t('pending_tenant.title') %></h3> <h3>Verify your email address</h3>
<p><%= t('pending_tenant.message') %></p>
<%= image_tag("pending-tenant.png", size: 64, style: "margin: 0 auto") %>
<p>Please check your email inbox (and your spam folder!) and click on the activation link.</p>
<p>
Need help?
<a href=<%= "mailto:info@astuto.io?subject=[SUPPORT]%20Unable%20to%20activate%20my%20feedback%20space&body=I%20need%20help%20activating%20my%20feedback%20space%20'#{request.subdomain}'" %>>
Contact us.
</a>
</p>
</div> </div>
</div> </div>

View File

@@ -7,6 +7,8 @@
oauthUserEmail: @user_email, oauthUserEmail: @user_email,
oauthUserName: @user_name, oauthUserName: @user_name,
baseUrl: Rails.application.base_url, baseUrl: Rails.application.base_url,
astutoLogoImage: image_url("logo.png"),
pendingTenantImage: image_url("pending-tenant.png"),
authenticityToken: form_authenticity_token authenticityToken: form_authenticity_token
} }
) )

View File

@@ -68,20 +68,6 @@ en:
days: days:
one: '1 day ago' one: '1 day ago'
other: '%{count} days ago' other: '%{count} days ago'
signup:
page_title: 'Create your feedback space'
step1:
title: '1. Create user account'
email_auth: 'Sign up with email'
step2:
title: '2. Create feedback space'
create_button: 'Create feedback space'
validations:
subdomain_already_taken: 'Sorry, this subdomain is not available'
subdomain_only_letters_and_numbers: 'Subdomain can only contain alphanumeric characters and hyphen'
step3:
title: "You're almost done!"
message: "Check your email %{email} to activate your new feedback space %{subdomain}!"
header: header:
menu: menu:
site_settings: 'Site settings' site_settings: 'Site settings'
@@ -90,9 +76,6 @@ en:
log_in: 'Log in / Sign up' log_in: 'Log in / Sign up'
roadmap: roadmap:
title: 'Roadmap' title: 'Roadmap'
pending_tenant:
title: 'Verify your email address'
message: 'We''ve sent an email with an activation link to the email you provided during registration. Click on that link to activate this feedback space!'
blocked_tenant: blocked_tenant:
title: 'This feedback space has been blocked' title: 'This feedback space has been blocked'
board: board: