diff --git a/app/assets/images/twemoji/face-sunglasses.svg b/app/assets/images/twemoji/face-sunglasses.svg new file mode 100644 index 000000000..ffc0708cf --- /dev/null +++ b/app/assets/images/twemoji/face-sunglasses.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/app/assets/stylesheets/article-form-needed-legacy.scss b/app/assets/stylesheets/article-form-needed-legacy.scss index 42514b7c1..ab8e2365d 100644 --- a/app/assets/stylesheets/article-form-needed-legacy.scss +++ b/app/assets/stylesheets/article-form-needed-legacy.scss @@ -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; diff --git a/app/assets/stylesheets/crayons.scss b/app/assets/stylesheets/crayons.scss index 3d98fcccc..43749bf05 100644 --- a/app/assets/stylesheets/crayons.scss +++ b/app/assets/stylesheets/crayons.scss @@ -32,4 +32,5 @@ @import 'views/article-form'; @import 'views/listings'; @import 'views/dashboard'; +@import 'views/signin'; @import 'views/sponsors'; diff --git a/app/assets/stylesheets/minimal.scss b/app/assets/stylesheets/minimal.scss index 906f45d1d..c8e73800f 100644 --- a/app/assets/stylesheets/minimal.scss +++ b/app/assets/stylesheets/minimal.scss @@ -9,7 +9,6 @@ @import 'shared'; @import 'dashboard'; @import 'settings'; -@import 'signin'; @import 'podcast-episodes-show'; @import 'podcast-form'; @import 'more-articles'; diff --git a/app/assets/stylesheets/signin.scss b/app/assets/stylesheets/signin.scss deleted file mode 100644 index 357c50559..000000000 --- a/app/assets/stylesheets/signin.scss +++ /dev/null @@ -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); - } - } - } -} diff --git a/app/assets/stylesheets/views/signin.scss b/app/assets/stylesheets/views/signin.scss new file mode 100644 index 000000000..07f6f4f75 --- /dev/null +++ b/app/assets/stylesheets/views/signin.scss @@ -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; + } + } +} diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index a0c680589..92c55fcff 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -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 diff --git a/app/views/devise/registrations/_registration_form.html.erb b/app/views/devise/registrations/_registration_form.html.erb index 2a8a5687d..fe791eadd 100644 --- a/app/views/devise/registrations/_registration_form.html.erb +++ b/app/views/devise/registrations/_registration_form.html.erb @@ -1,60 +1,71 @@ -
- <% if @new_article_not_logged_in %> -
-
- +
+
+
+

+ Welcome to <%= community_name %> +

+

+ <%= community_name %> is a community of + <%= number_with_delimiter(@registered_users_count) %> + amazing <%= community_members_label %>. +

+
+ +
+ <%= render partial: "shared/authentication/providers_registration_form" %> + +
+ <%# if there are no SSO auths enabled, we don't ask the user if they have a password %> + <% if authentication_enabled_providers.any? %> +
+ + Have a password? Continue with your email address + +
+ <% end %> + + <%= form_for(User.new, as: :user, url: session_path(:user)) do |f| %> +
+ <%= f.label :email, class: "crayons-field__label" %> + <%= f.email_field :email, autocomplete: "email", class: "crayons-textfield" %> +
+ +
+ <%= f.label :password, class: "crayons-field__label" %> + <%= f.password_field :password, autocomplete: "current-password", class: "crayons-textfield" %> +
+ +
+ <%= f.check_box :remember_me, class: "crayons-checkbox" %> + <%= f.label :remember_me, class: "crayons-field__label fw-normal" %> +
+ +
+ <%= f.submit "Continue", class: "crayons-btn crayons-btn--l w-100" %> +
+ <% end %> +

+ + I forgot my password + +

-

- Welcome to <%= community_name %> -

-

- Sign in below to compose your post and share it with the community. -

-
- <% else %> -
- -
- <% if any_selfserve_auth? %> -

Great to have you

- <% else %> -

Registration is by invitation only

- <% end %> - <% end %> - -

Open Source 😇

-

Free Forever ❤️

-
-
+
+ +

+ We strive for transparency and don't collect excess data. +

+
+
diff --git a/app/views/devise/shared/_authorization_error.html.erb b/app/views/devise/shared/_authorization_error.html.erb index 62f0c0841..55deaaa98 100644 --- a/app/views/devise/shared/_authorization_error.html.erb +++ b/app/views/devise/shared/_authorization_error.html.erb @@ -1,19 +1,7 @@ - <% unless flash[:alert].blank? %> -
- Something went wrong: +
<% if flash[:alert].is_a?(Array) %> + Something went wrong:
    <% flash[:alert].each do |error| %>
  • @@ -22,9 +10,14 @@ <% end %>
<% else %> - <%= flash[:alert] %> + + <%= flash[:alert] %> +
<% 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.
<% end %> diff --git a/app/views/shared/authentication/_providers_registration_form.html.erb b/app/views/shared/authentication/_providers_registration_form.html.erb index 541eddd02..ea1d38d94 100644 --- a/app/views/shared/authentication/_providers_registration_form.html.erb +++ b/app/views/shared/authentication/_providers_registration_form.html.erb @@ -1,15 +1,11 @@ -
+ - -<% if authentication_enabled_providers.any? %> -

We require social registration to prevent abuse.

-<% end %> diff --git a/spec/requests/editor_spec.rb b/spec/requests/editor_spec.rb index 84b9f4bf4..f80e795f3 100644 --- a/spec/requests/editor_spec.rb +++ b/spec/requests/editor_spec.rb @@ -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 diff --git a/spec/requests/notifications_spec.rb b/spec/requests/notifications_spec.rb index 2df9545b6..6934a2692 100644 --- a/spec/requests/notifications_spec.rb +++ b/spec/requests/notifications_spec.rb @@ -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 diff --git a/spec/requests/registrations_spec.rb b/spec/requests/registrations_spec.rb index 41a38a3c7..e57d359d6 100644 --- a/spec/requests/registrations_spec.rb +++ b/spec/requests/registrations_spec.rb @@ -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 diff --git a/spec/requests/stories_index_spec.rb b/spec/requests/stories_index_spec.rb index 11a155601..b184cf9a6 100644 --- a/spec/requests/stories_index_spec.rb +++ b/spec/requests/stories_index_spec.rb @@ -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 diff --git a/spec/system/link_for_tags_in_posts_in_notifications_spec.rb b/spec/system/link_for_tags_in_posts_in_notifications_spec.rb index 3e0e390e2..6c82c5479 100644 --- a/spec/system/link_for_tags_in_posts_in_notifications_spec.rb +++ b/spec/system/link_for_tags_in_posts_in_notifications_spec.rb @@ -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 diff --git a/spec/system/user_logs_in_with_password_spec.rb b/spec/system/user_logs_in_with_password_spec.rb index c1d95ede5..73afbe652 100644 --- a/spec/system/user_logs_in_with_password_spec.rb +++ b/spec/system/user_logs_in_with_password_spec.rb @@ -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