Update main authentication view to improve visual design (#9856) [deploy]

* Update mobile version of /new registration view

* Optimize styles for desktop view

* Fix typo

* Fix typo

* Add twemojis in footer area

* Update messaging to fulfill all intents

* cache

* cache

* hr-label fix on mobile

* hr-label fix on mobile

* crayons for checkbox

* crayons for checkbox

* remove old styles

* move signin to appropriate folder

* Remove schema changes

* Fix registraction specs and hide password hint for no SSO enabled

* Disable email hint for password reset page

* Fix specs

* Revert "Disable email hint for password reset page"

This reverts commit b33a6dda4c13534541294281f83f7ad5a4864c0d.

* Transfer User.registered.estimated_count to the controller

* Fix import path

Co-authored-by: ludwiczakpawel <ludwiczakpawel@gmail.com>
Co-authored-by: rhymes <rhymes@hey.com>
This commit is contained in:
Lisa Sy 2020-08-31 09:55:27 -07:00 committed by GitHub
parent dba151915b
commit 5ff2ad7437
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 312 additions and 316 deletions

View file

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 44 44" width="24" height="24">
<path fill="#FFCC4D" d="M36 18c0 9.941-8.059 18-18 18S0 27.941 0 18 8.059 0 18 0s18 8.059 18 18"/>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#292F33" d="M1.24 11.018c.24.239 1.438.957 1.677 1.675.24.717.72 4.784 2.158 5.981 1.483 1.232 7.077.774 8.148.24 2.397-1.195 2.691-4.531 3.115-6.221.239-.957 1.677-.957 1.677-.957s1.438 0 1.678.956c.424 1.691.72 5.027 3.115 6.221 1.072.535 6.666.994 8.151-.238 1.436-1.197 1.915-5.264 2.155-5.982.238-.717 1.438-1.435 1.677-1.674.241-.239.241-1.196 0-1.436-.479-.478-6.134-.904-12.223-.239-1.215.133-1.677.478-4.554.478-2.875 0-3.339-.346-4.553-.478-6.085-.666-11.741-.24-12.221.238-.239.239-.239 1.197 0 1.436z"/>
<path fill="#664500" d="M27.335 23.629a.501.501 0 00-.635-.029c-.039.029-3.922 2.9-8.7 2.9-4.766 0-8.662-2.871-8.7-2.9a.5.5 0 00-.729.657C8.7 24.472 11.788 29.5 18 29.5s9.301-5.028 9.429-5.243a.499.499 0 00-.094-.628z"/>
</svg>

After

Width:  |  Height:  |  Size: 991 B

View file

@ -475,101 +475,6 @@
margin-bottom: 70px;
}
.new-article-pitch {
padding-top: calc(3% + 25px);
width: 900px;
max-width: 94%;
margin: auto;
text-align: center;
.registration__logo-container {
.logo {
height: calc(170px + 1vw);
width: calc(170px + 1vw);
transform: rotate(6deg);
border-radius: 18px;
margin-top: 26px;
}
}
.prefill-non-logged-in-message {
background: lighten($yellow, 12%);
border-radius: 8px;
padding: 10px 0px;
border: 3px solid $yellow;
.logo {
height: calc(100px + 1vw);
width: calc(100px + 1vw);
margin-top: 26px;
}
p {
font-size: 1.1em;
padding: 15px;
}
}
h1 {
font-size: calc(30px + 1vw);
font-weight: 800;
}
h2 {
font-weight: 300;
font-size: 40px;
margin: 70px auto 40px;
}
hr {
width: 40%;
margin-top: 40px;
opacity: 0.4;
}
h3 {
font-weight: 300;
font-size: 30px;
}
p {
font-size: 16px;
line-height: 25px;
font-family: var(--ff-monospace);
}
img.gif {
width: 500px;
max-width: 100%;
}
.links {
margin: 50px auto;
.sign-up-link {
padding: 22px 0px;
margin: 2%;
border: 3px solid $bold-blue;
background: $bold-blue;
font-family: $helvetica-condensed;
display: inline-block;
text-align: center;
width: 290px;
border-radius: 100px;
color: white;
font-size: 1.1em;
.icon-img {
vertical-align: -7px;
fill: white;
height: 30px;
width: 30px;
margin-right: 4px;
}
}
}
}
.sign-in-message {
background: rgb(219, 29, 57);
color: white;

View file

@ -32,4 +32,5 @@
@import 'views/article-form';
@import 'views/listings';
@import 'views/dashboard';
@import 'views/signin';
@import 'views/sponsors';

View file

@ -9,7 +9,6 @@
@import 'shared';
@import 'dashboard';
@import 'settings';
@import 'signin';
@import 'podcast-episodes-show';
@import 'podcast-form';
@import 'more-articles';

View file

@ -1,115 +0,0 @@
@import 'variables';
@import 'config/import';
.authentication-feed {
&__card {
display: grid;
grid-gap: var(--su-6);
padding: var(--su-6);
margin: var(--su-3);
@include generate-box(
$level: 1,
$bg: #f5f6fe,
$border: var(--accent-brand),
$color: var(--card-color)
);
@media (min-width: $breakpoint-s) {
padding: var(--su-7);
margin: 0 0 var(--su-3) 0;
}
}
&__container {
@media (min-width: $breakpoint-s) {
display: flex;
grid-gap: var(--su-7);
flex-direction: row;
align-items: center;
}
}
&__image-container {
width: var(--su-8);
height: var(--su-8);
margin-bottom: var(--su-2);
@media (min-width: $breakpoint-s) {
height: 80px;
width: 80px;
}
}
&__image {
border-radius: var(--radius);
transform: rotate(-10deg);
height: auto;
width: 100%;
}
&__title {
color: var(--card-color);
font-size: var(--fs-2xl);
line-height: var(--lh-tight);
@media (min-width: $breakpoint-s) {
font-size: var(--fs-3xl);
}
}
&__description {
color: var(--card-color-secondary);
}
&__actions {
display: grid;
grid-gap: var(--su-1);
@media (min-width: $breakpoint-s) {
display: flex;
flex-direction: column;
width: max-content;
justify-self: center;
}
}
}
#page-content.registrations {
.devise-container {
min-height: 480px;
padding-top: calc(10vw + 35px);
h1 {
font-weight: 300;
text-align: center;
font-family: var(--ff-sans-serif);
font-size: 30px;
@media screen and (min-width: 520px) {
font-size: 50px;
}
}
a.sign-up-link {
display: block;
margin: 50px auto;
width: 280px;
max-width: 92%;
text-align: center;
padding: 20px 0px;
border: 1px solid rgb(245, 245, 245);
font-family: var(--ff-sans-serif);
color: rgb(86, 98, 103);
border-radius: 3px;
font-size: 22px;
img {
opacity: 0.7;
width: 24px;
height: 24px;
margin-right: 3px;
vertical-align: -3px;
}
&:hover {
border: 1px solid rgb(0, 231, 255);
}
}
}
}

View file

@ -0,0 +1,175 @@
@import '../variables';
@import '../config/import';
// Authentication Card in Feed
.authentication-feed {
&__card {
display: grid;
grid-gap: var(--su-6);
padding: var(--su-6);
margin: var(--su-3);
@include generate-box(
$level: 1,
$bg: #f5f6fe,
$border: var(--accent-brand),
$color: var(--card-color)
);
@media (min-width: $breakpoint-s) {
padding: var(--su-7);
margin: 0 0 var(--su-3) 0;
}
}
&__container {
@media (min-width: $breakpoint-s) {
display: flex;
grid-gap: var(--su-7);
flex-direction: row;
align-items: center;
}
}
&__image-container {
width: var(--su-8);
height: var(--su-8);
margin-bottom: var(--su-2);
@media (min-width: $breakpoint-s) {
height: 80px;
width: 80px;
}
}
&__image {
border-radius: var(--radius);
transform: rotate(-10deg);
height: auto;
width: 100%;
}
&__title {
color: var(--card-color);
font-size: var(--fs-2xl);
line-height: var(--lh-tight);
@media (min-width: $breakpoint-s) {
font-size: var(--fs-3xl);
}
}
&__description {
color: var(--card-color-secondary);
}
&__actions {
display: grid;
grid-gap: var(--su-1);
@media (min-width: $breakpoint-s) {
display: flex;
flex-direction: column;
width: max-content;
justify-self: center;
}
}
}
// Registration View
.registration {
border-radius: unset;
padding: var(--su-6);
@media (min-width: $breakpoint-s) {
border-radius: var(--radius);
padding: var(--su-8);
margin: 0 auto;
width: $breakpoint-s;
}
&__content {
margin-bottom: var(--su-6);
text-align: center;
}
&__title {
color: var(--card-color);
font-size: var(--fs-2xl);
line-height: var(--lh-tight);
@media (min-width: $breakpoint-s) {
font-size: var(--fs-3xl);
}
}
&__description {
color: var(--card-color-secondary);
font-size: var(--fs-base);
}
&__hr {
margin-bottom: var(--su-4);
position: relative;
text-align: center;
&:after {
border: 1px solid var(--base-20);
content: '';
display: block;
position: absolute;
top: 50%;
width: 100%;
z-index: 0;
border-radius: var(--radius);
}
}
&__hr-label {
position: relative;
font-size: var(--fs-s);
color: var(--card-color-secondary);
background: var(--card-bg);
padding: 0 var(--su-2);
z-index: 1;
display: inline-block;
max-width: 75%;
}
&__actions-providers {
margin-bottom: var(--su-4);
display: grid;
grid-gap: var(--su-2);
width: 100%;
}
&__footer {
font-size: var(--fs-s);
font-family: var(--ff-monospace);
padding-top: var(--su-4);
padding-bottom: var(--su-4);
text-align: center;
color: var(--base-60);
}
&__footer-content {
display: flex;
justify-content: center;
svg {
margin-left: var(--su-2);
}
}
&__error-notice {
color: var(--accent-danger-darker);
font-size: var(--fs-base);
padding: var(--su-2);
margin: var(--su-2);
@media (min-width: $breakpoint-s) {
margin: var(--su-4) auto 0;
width: $breakpoint-s;
}
}
}

View file

@ -2,6 +2,8 @@ class RegistrationsController < Devise::RegistrationsController
prepend_before_action :require_no_authentication, only: []
def new
@registered_users_count = User.registered.estimated_count
if user_signed_in?
redirect_to dashboard_path
else

View file

@ -1,60 +1,71 @@
<div class="new-article-pitch">
<% if @new_article_not_logged_in %>
<div class="prefill-non-logged-in-message">
<div class="registration__logo-container">
<img class="secondary-logo" src="<%= optimized_image_url(safe_logo_url(SiteConfig.secondary_logo_url), width: 190) %>"
alt="Secondary <%= community_name %> logo" />
<section class="crayons-layout">
<div class="registration crayons-card">
<div class="registration__content">
<h1 class="registration__title">
Welcome to <%= community_name %>
</h1>
<p class="registration__description">
<a href="/"><%= community_name %></a> is a community of
<%= number_with_delimiter(@registered_users_count) %>
amazing <%= community_members_label %>.
</p>
</div>
<div class="registration__actions">
<%= render partial: "shared/authentication/providers_registration_form" %>
<div class="registration__actions-email" id="sign-in-password-form">
<%# if there are no SSO auths enabled, we don't ask the user if they have a password %>
<% if authentication_enabled_providers.any? %>
<div class="registration__hr">
<span class="registration__hr-label">
Have a password? Continue with your email address
</span>
</div>
<% end %>
<%= form_for(User.new, as: :user, url: session_path(:user)) do |f| %>
<div class="crayons-field mb-3">
<%= f.label :email, class: "crayons-field__label" %>
<%= f.email_field :email, autocomplete: "email", class: "crayons-textfield" %>
</div>
<div class="crayons-field mb-3">
<%= f.label :password, class: "crayons-field__label" %>
<%= f.password_field :password, autocomplete: "current-password", class: "crayons-textfield" %>
</div>
<div class="crayons-field crayons-field--checkbox inline-flex flex-row items-center">
<%= f.check_box :remember_me, class: "crayons-checkbox" %>
<%= f.label :remember_me, class: "crayons-field__label fw-normal" %>
</div>
<div class="actions pt-3">
<%= f.submit "Continue", class: "crayons-btn crayons-btn--l w-100" %>
</div>
<% end %>
<p class="pt-6 fs-s align-center">
<a href="<%= new_password_path(:user) %>">
I forgot my password
</a>
</p>
</div>
<p>
<b>Welcome to <%= community_name %></b>
</p>
<p>
Sign in below to compose your post and share it with the community.
</p>
</div>
<% else %>
<div class="registration__logo-container">
<img class="secondary-logo" src="<%= optimized_image_url(safe_logo_url(SiteConfig.secondary_logo_url), width: 190) %>"
alt="Secondary <%= community_name %> logo" />
</div>
<% if any_selfserve_auth? %>
<h1>Great to have you</h1>
<% else %>
<h1>Registration is by invitation only</h1>
<% end %>
<% end %>
<div class="links">
<%= render partial: "shared/authentication/providers_registration_form" %>
<div id="sign-in-password-form" class="mt-1 crayons-card p-7 align-left mx-auto" style="max-width:490px;">
<p class="pb-4 fw-bold">If you have a password...</p>
<%= form_for(User.new, as: :user, url: session_path(:user)) do |f| %>
<div class="crayons-field">
<%= f.label :email, class: "crayons-field__label" %>
<%= f.email_field :email, autocomplete: "email", required: true, class: "crayons-textfield" %>
</div>
<div class="field">
<%= f.label :password, class: "crayons-field__label" %>
<%= f.password_field :password, autocomplete: "current-password", required: true, class: "crayons-textfield" %>
</div>
<div class="field">
<%= f.check_box :remember_me %>
<%= f.label :remember_me %>
</div>
<div class="actions pt-3">
<%= f.submit "Log in", class: "crayons-btn" %>
</div>
<% end %>
<% if any_selfserve_auth? %>
<p class="pt-6 fs-s"><em>Sign in by social auth if you don't have a password set.</em></p>
<% end %>
<p class="pt-6 fs-s"><em><a href="<%= new_password_path(:user) %>">Forgot password?</a></em></p>
</div>
</div>
<p>Open Source 😇</p>
<p>Free Forever ❤️</p>
<div style="height:300px"></div>
</div>
<footer class="registration__footer">
<p class="registration__footer-content">
Open Source
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 44 44" width="24" height="24">
<path fill="#FFCC4D" d="M36 18c0 9.941-8.059 18-18 18S0 27.941 0 18 8.059 0 18 0s18 8.059 18 18" /><path fill-rule="evenodd" clip-rule="evenodd" fill="#292F33" d="M1.24 11.018c.24.239 1.438.957 1.677 1.675.24.717.72 4.784 2.158 5.981 1.483 1.232 7.077.774 8.148.24 2.397-1.195 2.691-4.531 3.115-6.221.239-.957 1.677-.957 1.677-.957s1.438 0 1.678.956c.424 1.691.72 5.027 3.115 6.221 1.072.535 6.666.994 8.151-.238 1.436-1.197 1.915-5.264 2.155-5.982.238-.717 1.438-1.435 1.677-1.674.241-.239.241-1.196 0-1.436-.479-.478-6.134-.904-12.223-.239-1.215.133-1.677.478-4.554.478-2.875 0-3.339-.346-4.553-.478-6.085-.666-11.741-.24-12.221.238-.239.239-.239 1.197 0 1.436z" /><path fill="#664500" d="M27.335 23.629c-.178-.161-.444-.171-.635-.029-.039.029-3.922 2.9-8.7 2.9-4.766 0-8.662-2.871-8.7-2.9-.191-.142-.457-.13-.635.029-.177.16-.217.424-.094.628C8.7 24.472 11.788 29.5 18 29.5s9.301-5.028 9.429-5.243c.123-.205.084-.468-.094-.628z" />
</svg>
· Free Forever
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 44 44" width="24" height="24">
<path fill="#DD2E44" d="M39.885 15.833c0-5.45-4.418-9.868-9.867-9.868-3.308 0-6.227 1.633-8.018 4.129-1.791-2.496-4.71-4.129-8.017-4.129-5.45 0-9.868 4.417-9.868 9.868 0 .772.098 1.52.266 2.241C5.751 26.587 15.216 35.568 22 38.034c6.783-2.466 16.249-11.447 17.617-19.959.17-.721.268-1.469.268-2.242z" />
</svg>
</p>
<p>
We strive for transparency and don't collect excess data.
</p>
</footer>
</section>

View file

@ -1,19 +1,7 @@
<style>
.error-notice {
background: rgba(255, 80, 80, 0.7);
color: white;
padding: 40px 0px 40px;
text-align: center;
position: relative;
top: 0px;
left: 0px;
right: 0px;
}
</style>
<% unless flash[:alert].blank? %>
<div class="error-notice">
Something went wrong:
<div class="crayons-notice--danger registration__error-notice">
<% if flash[:alert].is_a?(Array) %>
Something went wrong:
<ul>
<% flash[:alert].each do |error| %>
<li>
@ -22,9 +10,14 @@
<% end %>
</ul>
<% else %>
<%= flash[:alert] %>
<strong>
<%= flash[:alert] %>
</strong>
<br>
<% end %>
Please try again below, or contact <%= email_link %> if this persists.
<% if any_selfserve_auth? %>
If you haven't created an account, we recommend signing up with social authentication below.
<% end %>
Contact <%= email_link %> if you continue having trouble.
</div>
<% end %>

View file

@ -1,15 +1,11 @@
<div class="flex flex-col m:flex-row justify-center">
<div class="registration__actions-providers">
<% authentication_enabled_providers.each do |provider| %>
<a
href="<%= provider.sign_in_path(state: "navbar_basic") %>"
class="crayons-btn crayons-btn--xl crayons-btn--brand-<%= provider.provider_name %> crayons-btn--icon-left m-1 whitespace-nowrap"
class="crayons-btn crayons-btn--l crayons-btn--brand-<%= provider.provider_name %> crayons-btn--icon-left whitespace-nowrap"
data-no-instant>
<%= inline_svg_tag("#{provider.provider_name}.svg", aria: true, class: "crayons-icon", title: provider.provider_name) %>
Sign In with <%= provider.official_name %>
Continue with <%= provider.official_name %>
</a>
<% end %>
</div>
<% if authentication_enabled_providers.any? %>
<p class="pt-6 pb-8"><em>We require social registration to prevent abuse.</em></p>
<% end %>

View file

@ -3,11 +3,11 @@ require "rails_helper"
RSpec.describe "Editor", type: :request do
describe "GET /new" do
context "when not logged-in" do
it "asks the stray-user to 'Sign In or Create Your Account'" do
get "/new"
it "asks the non logged in user to sign in" do
get new_path
expect(response).to have_http_status(:ok)
expect(response.body).to include("Sign in below to compose your post and share")
# should actually be looking for textarea tag
expect(response.body).to include("Password")
end
end
end

View file

@ -25,17 +25,19 @@ RSpec.describe "NotificationsIndex", type: :request do
end
context "when signed out" do
it "renders the signup cue" do
it "renders the signup page" do
get "/notifications"
expect(response.body).to include "Great to have you"
expect(response.body).to include("Continue with")
end
end
context "when signed in" do
it "does not render the signup cue" do
sign_in user
get "/notifications"
expect(response.body).not_to include "Create your account"
expect(response.body).not_to include("Continue with")
end
end

View file

@ -3,23 +3,39 @@ require "rails_helper"
RSpec.describe "Registrations", type: :request do
let(:user) { create(:user) }
describe "GET /enter" do
describe "Sign up" do
context "when not logged in" do
it "shows the sign in page (with self-serve auth)" do
get "/enter"
expect(response.body).to include "Great to have you"
it "shows the sign in page with single sign on options" do
get sign_up_path
Authentication::Providers.enabled.each do |provider_name|
provider = Authentication::Providers.get!(provider_name)
expect(response.body).to include("Continue with #{provider.official_name}")
end
end
it "shows the sign in text" do
get "/enter"
expect(response.body).to include "If you have a password"
it "shows the sign in text for password based authentication" do
get sign_up_path
expect(response.body).to include("Have a password? Continue with your email address")
end
it "shows invite-only text if no self-serve" do
SiteConfig.authentication_providers = []
get "/enter"
expect(response.body).to include "If you have a password"
expect(response.body).not_to include "Sign in by social auth"
it "does not show the password based authentication hint if there are no single sign in options enabled" do
allow(Authentication::Providers).to receive(:enabled).and_return([])
get sign_up_path
expect(response.body).not_to include("Have a password? Continue with your email address")
end
it "only shows the single sign on options if they are present" do
allow(Authentication::Providers).to receive(:enabled).and_return([])
get sign_up_path
expect(response.body).to include("Password")
expect(response.body).not_to include("Continue with")
end
end
@ -27,8 +43,8 @@ RSpec.describe "Registrations", type: :request do
it "redirects to /dashboard" do
sign_in user
get "/enter"
expect(response).to redirect_to("/dashboard")
get sign_up_path
expect(response).to redirect_to(dashboard_path)
end
end
end

View file

@ -21,8 +21,9 @@ RSpec.describe "StoriesIndex", type: :request do
it "renders registration page if site config is private" do
SiteConfig.public = false
get "/"
expect(response.body).to include("Great to have you")
get root_path
expect(response.body).to include("Continue with")
end
it "renders proper description" do

View file

@ -14,7 +14,11 @@ RSpec.describe "Link on tags for post in notifications", type: :system do
end
it "shows the sign-with page", js: true do
expect(page).to have_content(/Sign In With/i, count: Authentication::Providers.available.size)
Authentication::Providers.enabled.each do |provider_name|
provider = Authentication::Providers.get!(provider_name)
expect(page).to have_content("Continue with #{provider.official_name}")
end
end
end

View file

@ -4,7 +4,7 @@ RSpec.describe "Authenticating with a password" do
def submit_login_form(email, password)
fill_in "Email", with: email
fill_in "Password", with: password
click_button "Log in"
click_button "Continue"
end
let(:password) { "p4assw0rd" }
@ -17,6 +17,7 @@ RSpec.describe "Authenticating with a password" do
context "when logging in with incorrect credentials" do
it "displays an error when the email address is wrong" do
submit_login_form("wrong@example.com", password)
expect(page).to have_text("Invalid Email or password.")
end