Add ActionText and user profile text

This commit is contained in:
Trevor Vallender 2024-05-30 09:07:54 +01:00
parent b58c0a7c1a
commit 46d8a4bbca
12 changed files with 120 additions and 20 deletions

View File

@ -12,4 +12,5 @@
--notice-text-color: #fff;
--invalid-alert: #d00;
--input-background: #fff;
}

View File

@ -1,4 +1,4 @@
form {
form, fieldset {
display: grid;
gap: 1rem;
grid-template-columns: 1fr 2fr;
@ -31,4 +31,12 @@ form {
color: var(--invalid-alert);
font-size: .8em;
}
fieldset, p, trix-editor {
grid-column: 1/3;
}
trix-editor {
background-color: var(--input-background);
}
}

View File

@ -2,14 +2,15 @@
class UsersController < ApplicationController
skip_before_action :authenticate, only: [ :new, :create ]
before_action :set_user, only: [ :show ]
before_action :set_user, only: [ :show, :edit, :update ]
before_action :ensure_self, only: [ :edit, :update ]
def new
@user = User.new
end
def create
@user = User.new(user_params)
@user = User.new(new_user_params)
if @user.save
token = @user.generate_token_for(:email_verification)
UserMailer.with(user: @user, token: token).email_verification.deliver_later
@ -27,9 +28,21 @@ class UsersController < ApplicationController
end
end
def edit
end
def update
if @user.update(existing_user_params)
redirect_to @user, notice: t(".success")
else
flash.now[:alert] = t(".error")
render :edit, status: :unprocessable_entity
end
end
private
def user_params
def new_user_params
params.require(:user).permit(
:username,
:password,
@ -40,7 +53,22 @@ class UsersController < ApplicationController
)
end
def existing_user_params
params.require(:user).permit(
:password,
:password_confirmation,
:password_challenge,
:first_name,
:last_name,
:profile,
)
end
def set_user
@user = User.find_by(username: params[:id])
end
def ensure_self
head :forbidden unless @user == Current.user || Current.user.admin?
end
end

View File

@ -5,6 +5,7 @@ class User < ApplicationRecord
has_many :owned_tables, foreign_key: :owner_id, class_name: "Table"
has_many :players, dependent: :destroy
has_many :tables, through: :players
has_rich_text :profile
has_secure_password
generates_token_for :password_reset, expires_in: 4.hours do

View File

@ -19,6 +19,7 @@
<ul>
<% if logged_in? %>
<li><%= link_to t(".tables"), tables_path %></li>
<li><%= link_to t(".profile"), user_path(Current.user) %></li>
<li><%= link_to t("log_out"), logout_path, data: {turbo_method: :delete} %></li>
<% if Current.user.admin? %>
<li><%= link_to t("administration"), admin_index_path %></li>

View File

@ -3,7 +3,7 @@
<section class="inset">
<%= form_with model: user do |f| %>
<%= f.label :username %>
<%= f.text_field :username, required: true %>
<%= f.text_field :username, required: true, disabled: user.persisted? %>
<%= display_form_errors(user, :username) %>
<%= f.label :first_name %>
@ -15,16 +15,34 @@
<%= display_form_errors(user, :last_name) %>
<%= f.label :email %>
<%= f.text_field :email, required: true %>
<%= f.text_field :email, required: true, disabled: user.persisted? %>
<%= display_form_errors(user, :email) %>
<fieldset>
<legend><%= t(".password") %></legend>
<% if user.persisted? %>
<%= f.label :password_challenge, t(".current_password") %>
<%= f.password_field :password_challenge, required: user.new_record? %>
<%= display_form_errors(user, :password_challenge) %>
<p><%= t(".password_hint") %></p>
<% end %>
<%= f.label :password %>
<%= f.password_field :password, required: true %>
<%= f.password_field :password, required: user.new_record? %>
<%= display_form_errors(user, :password) %>
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation, required: true %>
<%= f.password_field :password_confirmation, required: user.new_record? %>
<%= display_form_errors(user, :password_confirmation) %>
</fieldset>
<% if user.persisted? %>
<%= f.label :profile %>
<%= f.rich_text_area :profile %>
<%= display_form_errors(user, :profile) %>
<% end %>
<%= f.submit button_text %>
<% end %>

View File

@ -0,0 +1,6 @@
<% content_for :title, t(".edit_profile") %>
<h2><%= t(".edit_profile") %></h2>
<%= render partial: "users/form",
locals: { user: @user, button_text: t(".update_profile") } %>

View File

@ -2,6 +2,13 @@
<h2><%= @user.username %></h2>
<% if @user == Current.user && @table_invites.any? %>
<aside>
<% if @user == Current.user %>
<%= link_to t(".edit_profile"), edit_user_path(@user) %>
<% if @table_invites.any? %>
<%= link_to t(".your_invites"), table_invites_path %>
<% end %>
<% end %>
</aside>
<%= @user.profile %>

View File

@ -15,6 +15,7 @@ en:
game_systems: Game Systems
jobs: Jobs
application:
profile: Profile
tables: Tables
mailer:
greeting: "Hi %{name},"
@ -130,6 +131,17 @@ en:
success: "Thanks for joining Tabletop Companion, %{name}! Please check your email to verify your address."
show:
your_invites: Your invites
edit_profile: Edit profile
edit:
edit_profile: Edit profile
update_profile: Update profile
form:
password: Password
password_hint: To keep your existing password, leave the below fields blank
current_password: Current password
update:
success: Your profile has been updated
error: Failed to update profile
user_mailer:
email_verified:
content: |-

View File

@ -8,7 +8,7 @@ Rails.application.routes.draw do
get "login" => "sessions#new", as: :login
delete "logout" => "sessions#destroy", as: :logout
resources :users, only: [ :new, :create, :show ]
resources :users, only: [ :new, :create, :show, :edit, :update ]
resources :account_verifications, only: [ :show ]
resources :sessions, only: [ :new, :create, :destroy ]

View File

@ -34,6 +34,24 @@ class UsersControllerTest < ActionDispatch::IntegrationTest
assert_response :unprocessable_entity
end
test "should get edit" do
sign_in users(:trevor)
get edit_user_url(users(:trevor))
assert_response :success
end
test "can only edit own user" do
sign_in users(:trevor)
get edit_user_url(users(:gimli))
assert_response :forbidden
end
test "should update user" do
sign_in users(:trevor)
patch user_url(users(:trevor)), params: { user: { profile: "All about me" } }
assert_redirected_to user_path(users(:trevor))
end
private
def user_params

View File

@ -1,4 +1,4 @@
# one:
# record: name_of_fixture (ClassOfFixture)
# name: content
# body: <p>In a <i>million</i> stars!</p>
one:
record: trevor (User)
name: profile
body: <p>I am just <strong>so awesome</strong></p>