flex around devise, also reconfirmable

This commit is contained in:
Torsten 2022-12-20 21:02:36 +02:00
parent 13682fb58b
commit 0ccfab790b
15 changed files with 298 additions and 133 deletions

View File

@ -14,6 +14,7 @@ gem "sassc-rails"
gem 'haml-rails'
gem 'html2haml'
gem 'devise'
gem "ruby2js" , path: "../ruby2js"
# Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images]

View File

@ -117,6 +117,9 @@ GEM
railties (>= 4.1.0)
responders
warden (~> 1.2.3)
devise-tailwindcssed (0.1.5)
rails (>= 5.2.3.4, < 7.1)
railties (> 4.0, < 7.1)
diff-lcs (1.5.0)
erubi (1.11.0)
erubis (2.7.0)
@ -330,6 +333,7 @@ DEPENDENCIES
capybara
debug
devise
devise-tailwindcssed
guard-rspec
haml-rails
html2haml

View File

@ -0,0 +1,55 @@
# frozen_string_literal: true
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
# devise helper
module DeviseHelper
def devise_error_messages!
return if resource.errors.empty?
messages = resource.errors.full_messages.map { |msg| content_tag(:p, "- #{msg}.") }
.join
sentence = I18n.t(
"errors.messages.not_saved",
count: resource.errors.count,
resource: resource.class.model_name.human.downcase
)
html = <<-HTML
<div class="bg-red-100 border-l-4 border-red-500 mb-4 p-4 text-red-700" role="alert">
<p class="font-bold">Oops!</p>
<p>#{sentence}</p>#{messages}
</div>
HTML
html.html_safe
end
def devise_simple_error_messages!
return if resource.errors.empty?
sentence = "Ooops!"
if resource.errors.count == 1
message = resource.errors.full_messages[0]
html = <<-HTML
<div class="bg-red-lightest border-l-4 border-red text-orange-dark p-4" role="alert">
<p class="font-bold">#{sentence}</p>
<p> #{message}.</p>
</div>
HTML
else
messages = resource.errors.full_messages.map { |msg| content_tag(:li, "#{msg}.") }
.join
html = <<-HTML
<div class="bg-red-100 border-l-4 border-red-500 mb-4 p-4 text-red-700" role="alert">
<p class="font-bold">#{sentence}</p>
<ul class="list-disc">
#{messages}
</ul>
</div>
HTML
end
html.html_safe
end
end
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength

View File

@ -1,10 +1,23 @@
%h2 Resend confirmation instructions
= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f|
= render "devise/shared/error_messages", resource: resource
.field
= f.label :email
%br/
= f.email_field :email, autofocus: true, autocomplete: "email", value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email)
.actions
= f.submit "Resend confirmation instructions"
= render "devise/shared/links"
.flex.justify-center
.w-full.max-w-xs
%h1.font-hairline.mb-6.text-center Resend Confirmation Instructions
= form_for(resource, |
as: resource_name, |
url: confirmation_path(resource_name), |
html: { |
method: :post, |
class: "bg-white mb-4 px-8 pt-6 pb-8 rounded shadow-md" |
}) do |f| |
= devise_error_messages!
.mb-4
= f.label :email, class: "block font-bold mb-2 text-gray-700 text-sm"
= f.email_field :email, |
autofocus: true, |
autocomplete: "email", |
value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email), |
class: "appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none shadow focus:shadow-outline" |
.mb-4
= f.submit "Resend Confirmation Info", |
class: "button bg-blue-500 hover:bg-blue-700 font-bold text-white focus:outline-none py-2 px-4 rounded focus:shadow-outline w-full" |
= render "devise/shared/links"
= render "devise/shared/form_footer"

View File

@ -1,19 +1,36 @@
%h2 Change your password
= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f|
= render "devise/shared/error_messages", resource: resource
= f.hidden_field :reset_password_token
.field
= f.label :password, "New password"
%br/
- if @minimum_password_length
%em
(#{@minimum_password_length} characters minimum)
%br/
= f.password_field :password, autofocus: true, autocomplete: "new-password"
.field
= f.label :password_confirmation, "Confirm new password"
%br/
= f.password_field :password_confirmation, autocomplete: "new-password"
.actions
= f.submit "Change my password"
= render "devise/shared/links"
.flex.justify-center
.w-full.max-w-xs
%h2.font-hairline.mb-6.text-center Change Your Password
= form_for(resource, |
as: resource_name, |
url: member_password_path(resource_name), |
html: { |
method: :put, |
class: "bg-white mb-4 px-8 pt-6 pb-8 rounded shadow-md" |
} |
) do |f| |
= devise_error_messages!
= f.hidden_field :reset_password_token
.mb-4
= f.label :password, "New Password", |
class: "block font-bold mb-2 text-gray-700 text-sm" |
- if @minimum_password_length
%small
%em.text-gray-600
(#{@minimum_password_length} characters minimum)
= f.password_field :password, |
autofocus: true, |
autocomplete: "new-password", |
class: "appearance-none border leading-tight focus:outline-none px-3 py-2 rounded shadow focus:shadow-outline text-gray-700 w-full" |
.mb-4
= f.label :password_confirmation, |
"Confirm New Password", |
class: "block font-bold mb-2 text-gray-700 text-sm" |
= f.password_field :password_confirmation, |
autocomplete: "off", |
class: "shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 mb-3 leading-tight focus:outline-none focus:shadow-outline" |
.mb-4
= f.submit "Change My Password", |
class: "button bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline w-full" |
= render "devise/shared/links"
= render "devise/shared/form_footer"

View File

@ -1,10 +1,20 @@
%h2 Forgot your password?
= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f|
= render "devise/shared/error_messages", resource: resource
.field
= f.label :email
%br/
= f.email_field :email, autofocus: true, autocomplete: "email"
.actions
= f.submit "Send me reset password instructions"
= render "devise/shared/links"
.flex.justify-center
.w-full.max-w-xs
%h1.font-hairline.mb-6.text-center Forgot your password?
= form_for(resource, |
as: resource_name, |
url: password_path(resource_name), |
html: { |
method: :post, |
class: "bg-white mb-4 px-8 pt-6 pb-8 rounded shadow-md" |
}) do |f| |
= devise_error_messages!
.mb-4
= f.label :email, class: "block font-bold mb-2 text-gray-700 text-sm"
= f.email_field :email, autofocus: true, autocomplete: "email", |
class: "appearance-none border leading-tight focus:outline-none px-3 py-2 rounded shadow focus:shadow-outline text-gray-700 w-full" |
.mb-4
= f.submit "Send Password Reset Info", |
class: "button bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline w-full" |
= render "devise/shared/links"
= render "devise/shared/form_footer"

View File

@ -1,36 +1,44 @@
%h2
Edit #{resource_name.to_s.humanize}
= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f|
= render "devise/shared/error_messages", resource: resource
.field
= f.label :email
%br/
= f.email_field :email, autofocus: true, autocomplete: "email"
- if devise_mapping.confirmable? && resource.pending_reconfirmation?
%div
Currently waiting confirmation for: #{resource.unconfirmed_email}
.field
= f.label :password
%i (leave blank if you don't want to change it)
%br/
= f.password_field :password, autocomplete: "new-password"
- if @minimum_password_length
%br/
%em
= @minimum_password_length
characters minimum
.field
= f.label :password_confirmation
%br/
= f.password_field :password_confirmation, autocomplete: "new-password"
.field
= f.label :current_password
%i (we need your current password to confirm your changes)
%br/
= f.password_field :current_password, autocomplete: "current-password"
.actions
= f.submit "Update"
%h3 Cancel my account
%p
Unhappy? #{button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete}
= link_to "Back", :back
.flex.justify-center
.w-full.max-w-xs
%h1.font-hairline.mb-6.text-center
Edit #{resource_name.to_s.humanize}
= form_for(resource, |
as: resource_name, |
url: registration_path(resource_name), |
html: { |
method: :put, |
class: "bg-white mb-4 px-8 pt-6 pb-8 rounded shadow-md" |
} |
) do |f| |
= devise_error_messages!
.mb-4
= f.label :email, class: "block font-bold mb-2 text-gray-700 text-sm"
%br/
= f.email_field :email, |
autofocus: true, |
autocomplete: "email", |
class: "appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none shadow focus:shadow-outline" |
- if devise_mapping.confirmable? && resource.pending_reconfirmation?
%div
Currently waiting confirmation for: #{resource.unconfirmed_email}
.mb-4
= f.label :password, class: "block font-bold mb-2 text-gray-700 text-sm"
%i (leave blank if you don't want to change it)
%br/
= f.password_field :password, autocomplete: "new-password", class: "shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 mb-3 leading-tight focus:outline-none focus:shadow-outline"
.mb-4
= f.label :password_confirmation, class: "block font-bold mb-2 text-gray-700 text-sm"
= f.password_field :password_confirmation, |
autocomplete: "new-password", |
class: "shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 mb-3 leading-tight focus:outline-none focus:shadow-outline" |
.mb-4
= f.label :current_password, class: "block font-bold mb-2 text-gray-700 text-sm"
= f.password_field :current_password, |
autocomplete: "current-password", |
class: "shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 mb-3 leading-tight focus:outline-none focus:shadow-outline" |
.actions
= f.submit "Update", class: "button bg-blue-500 hover:bg-blue-700 font-bold text-white focus:outline-none py-2 px-4 rounded focus:shadow-outline w-full"
%p
Unhappy?
%span= button_to "Delete my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete
= link_to "Back", :back

View File

@ -1,21 +1,36 @@
%h2 Sign up
= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f|
= render "devise/shared/error_messages", resource: resource
.field
= f.label :email
%br/
= f.email_field :email, autofocus: true, autocomplete: "email"
.field
= f.label :password
- if @minimum_password_length
%em
(#{@minimum_password_length} characters minimum)
%br/
= f.password_field :password, autocomplete: "new-password"
.field
= f.label :password_confirmation
%br/
= f.password_field :password_confirmation, autocomplete: "new-password"
.actions
= f.submit "Sign up"
= render "devise/shared/links"
.flex.justify-center
.w-full.max-w-xs
%h1.font-hairline.mb-6.text-center Sign Up
= form_for(resource, |
as: resource_name, |
url: registration_path(resource_name), |
html: { |
class: "bg-white mb-4 px-8 pt-6 pb-8 rounded shadow-md" |
} |
) do |f| |
= devise_error_messages!
.mb-4
= f.label :email, class: "block font-bold mb-2 text-gray-700 text-sm"
= f.email_field :email, |
autocomplete: "email", |
placeholder: "user@example.com", |
class: "appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none shadow focus:shadow-outline" |
.mb-4
= f.label :password, class: "block font-bold mb-2 text-gray-700 text-sm"
- if @minimum_password_length
%small
%em.text-gray-600
(#{@minimum_password_length} characters minimum)
= f.password_field :password, |
autocomplete: "new-password", |
class: "shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 mb-3 leading-tight focus:outline-none focus:shadow-outline" |
.mb-4
= f.label :password_confirmation, class: "block font-bold mb-2 text-gray-700 text-sm"
= f.password_field :password_confirmation, |
autocomplete: "new-password", |
class: "appearance-none border leading-tight focus:outline-none px-3 py-2 rounded shadow focus:shadow-outline text-gray-700 w-full" |
.mb-4
= f.submit "Sign Up", |
class: "button bg-blue-500 hover:bg-blue-700 font-bold text-white focus:outline-none py-2 px-4 rounded focus:shadow-outline w-full" |
= render "devise/shared/links"
= render "devise/shared/form_footer"

View File

@ -1,17 +1,37 @@
%h2 Log in
= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f|
.field
= f.label :email
%br/
= f.email_field :email, autofocus: true, autocomplete: "email"
.field
= f.label :password
%br/
= f.password_field :password, autocomplete: "current-password"
- if devise_mapping.rememberable?
.field
= f.check_box :remember_me
= f.label :remember_me
.actions
= f.submit "Log in"
= render "devise/shared/links"
.flex.justify-center
.w-full.max-w-xs
%h1.font-hairline.mb-6.text-center Log In
= form_for(resource, |
as: resource_name, |
url: session_path(resource_name), |
html: { |
class: "bg-white mb-4 px-8 pt-6 pb-8 rounded shadow-md" |
} |
) do |f| |
= devise_simple_error_messages!
- if flash.present?
.bg-red-100.border-l-4.border-red-500.text-red-700.p-4.mb-4{:role => "alert"}
%p.font-bold Oops!
- flash.each do |name, msg|
= content_tag :p, |
msg.humanize, |
id: "flash_#{name}" if msg.is_a?(String) |
.mb-4
= f.label :email, class: "block text-gray-700 text-sm font-bold mb-2"
= f.email_field :email, autofocus: true, autocomplete: "email", |
class: "shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight foucs:outline-none focus:shadow-outline" |
.mb-4
= f.label :password, class: "block text-gray-700 text-sm font-bold mb-2"
= f.password_field :password, |
autocomplete: "current-password", |
class: "shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" |
- if devise_mapping.rememberable?
.mb-4
= f.check_box :remember_me, class: "mr-2 leading-tight"
= f.label :remember_me, |
class: "align-baseline inline-block text-gray-700 text-sm" |
.mb-4
= f.submit "Log in", |
class: "button bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline w-full" |
= render "devise/shared/links"
= render "devise/shared/form_footer"

View File

@ -0,0 +1,2 @@
%p.text-center.text-gray-500.text-xs
Be a member of Hub Feenix

View File

@ -1,19 +1,25 @@
- if controller_name != 'sessions'
= link_to "Log in", new_session_path(resource_name)
%br/
- if devise_mapping.registerable? && controller_name != 'registrations'
= link_to "Sign up", new_registration_path(resource_name)
= link_to "Log in", new_session_path(resource_name), |
class: "inline-block align-baseline font-bold text-sm text-blue-500 hover:text-blue-800" |
%br/
- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations'
= link_to "Forgot your password?", new_password_path(resource_name)
= link_to "Forgot Password?", new_member_password_path(resource_name), |
class: "inline-block align-baseline font-bold text-sm text-blue-500 hover:text-blue-800" |
%br/
- if devise_mapping.registerable? && controller_name != 'registrations'
= link_to "Sign up", new_registration_path(resource_name), |
class: "inline-block align-baseline font-bold text-sm text-blue-500 hover:text-blue-800" |
%br/
- if devise_mapping.confirmable? && controller_name != 'confirmations'
= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name)
= link_to "Didn't receive confirmation info?", new_member_confirmation_path(resource_name), |
class: "inline-block align-baseline font-bold text-sm text-blue-500 hover:text-blue-800" |
%br/
- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks'
= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name)
= link_to "Didn't receive unlock info?", new_member_unlock_path(resource_name), |
class: "inline-block align-baseline font-bold text-sm text-blue-500 hover:text-blue-800" |
%br/
- if devise_mapping.omniauthable?
- resource_class.omniauth_providers.each do |provider|
= link_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider), method: :post
= link_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider), |
class: "inline-block align-baseline font-bold text-sm text-blue-500 hover:text-blue-800" |
%br/

View File

@ -1,10 +1,23 @@
%h2 Resend unlock instructions
= form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f|
= render "devise/shared/error_messages", resource: resource
.field
= f.label :email
%br/
= f.email_field :email, autofocus: true, autocomplete: "email"
.actions
= f.submit "Resend unlock instructions"
= render "devise/shared/links"
.flex.justify-center
.w-full.max-w-xs
%h1.font-hairline.mb-6.text-center Resend Unlock Info
= form_for(resource, |
as: resource_name, |
url: unlock_path(resource_name), |
html: { |
method: :post, |
class: "bg-white mb-4 px-8 pt-6 pb-8 rounded shadow-md" |
} |
) do |f| |
= devise_error_messages!
.mb-4
= f.label :email, class: "block font-bold mb-2 text-gray-700 text-sm"
= f.email_field :email, |
autofocus: true, |
autocomplete: "email", |
class: "appearance-none border leading-tight focus:outline-none px-3 py-2 rounded shadow focus:shadow-outline text-gray-700 w-full" |
.mb-4
= f.submit "Resend unlock instructions", |
class: "button bg-blue-500 hover:bg-blue-700 font-bold text-white focus:outline-none py-2 px-4 rounded focus:shadow-outline w-full" |
= render "devise/shared/links"
= render "devise/shared/form_footer"

View File

@ -157,7 +157,7 @@ Devise.setup do |config|
# initial account confirmation) to be applied. Requires additional unconfirmed_email
# db field (see migrations). Until confirmed, new email is stored in
# unconfirmed_email column, and copied to email column on successful confirmation.
# config.reconfirmable = true
config.reconfirmable = true
# Defines which key will be used when confirming an account
# config.confirmation_keys = [:email]

View File

@ -25,7 +25,7 @@ class AddDeviseToMembers < ActiveRecord::Migration[7.0]
t.string :confirmation_token
t.datetime :confirmed_at
t.datetime :confirmation_sent_at
#t.string :unconfirmed_email # Only if using reconfirmable
t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
# t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts

1
db/schema.rb generated
View File

@ -27,6 +27,7 @@ ActiveRecord::Schema[7.0].define(version: 2022_12_20_150958) do
t.string "confirmation_token"
t.datetime "confirmed_at"
t.datetime "confirmation_sent_at"
t.string "unconfirmed_email"
t.index ["email"], name: "index_members_on_email", unique: true
t.index ["reset_password_token"], name: "index_members_on_reset_password_token", unique: true
end