Skip to content

Commit

Permalink
Users can now edit their profile and account settings
Browse files Browse the repository at this point in the history
  • Loading branch information
remomueller committed Oct 5, 2018
1 parent 66fd893 commit d4adcae
Show file tree
Hide file tree
Showing 27 changed files with 543 additions and 46 deletions.
3 changes: 3 additions & 0 deletions .ebextensions/imagemagick.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
packages:
yum:
ImageMagick: []
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
- Internal pages and file links now friendly forward after sign in
- **Admin Changes**
- Simplify folder archiving and management for admins
- **Profile Changes**
- Users can now edit their profile and account settings
- **Search Changes**
- Search now returns more specific results as more search terms are added

Expand Down
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ gem "haml", "~> 5.0.4"
gem "jquery-rails", "~> 4.3.3"
gem "jquery-ui-rails", "~> 6.0.1"
gem "kaminari", "~> 1.1.1"
gem "mini_magick", "~> 4.8.0"
gem "pg_search", "~> 2.1.2"

# Rails defaults
Expand Down
2 changes: 2 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ GEM
mime-types-data (~> 3.2015)
mime-types-data (3.2018.0812)
mimemagic (0.3.2)
mini_magick (4.8.0)
mini_mime (1.0.1)
mini_portile2 (2.3.0)
minitest (5.11.3)
Expand Down Expand Up @@ -302,6 +303,7 @@ DEPENDENCIES
jquery-ui-rails (~> 6.0.1)
kaminari (~> 1.1.1)
listen (>= 3.0.5, < 3.2)
mini_magick (~> 4.8.0)
pg (>= 0.18, < 2.0)
pg_search (~> 2.1.2)
puma (~> 3.11)
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/internal_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def dashboard

# GET /directory
def directory
@users = User.current.where(approved: true).order(id: :desc).limit(5)
@users = User.current.where(approved: true).order(id: :desc).limit(20)
@key_contacts = User.current.where(key_contact: true)
end

Expand Down
30 changes: 30 additions & 0 deletions app/controllers/profiles_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# frozen_string_literal: true

# Displays user profile pictures.
class ProfilesController < ApplicationController
before_action :find_user, only: [:picture]

def picture
profile_picture = if params[:thumb] == "1"
@user&.profile_picture&.thumb
else
@user&.profile_picture
end

if Rails.env.production?
if profile_picture&.url.present?
redirect_to profile_picture.url(query: { "response-content-disposition" => "inline" })
else
head :ok
end
else
send_file_if_present profile_picture, disposition: "inline"
end
end

private

def find_user
@user = User.current.find_by("LOWER(username) = ?", params[:id].to_s.downcase)
end
end
101 changes: 101 additions & 0 deletions app/controllers/settings_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# frozen_string_literal: true

class SettingsController < ApplicationController
before_action :authenticate_user!

layout "layouts/full_page_sidebar"

# # GET /settings/profile
# def profile
# end

# PATCH /settings/profile
def update_profile
if current_user.update(profile_params)
redirect_to settings_profile_path, notice: "Profile successfully updated."
else
render :profile
end
end

# PATCH /settings/complete-profile
def complete_profile
if current_user.update(complete_profile_params)
redirect_to dashboard_path, notice: "Profile successfully updated."
else
redirect_to dashboard_path
end
end

# PATCH /settings/profile/picture
def update_profile_picture
if current_user.update(profile_picture_params)
redirect_to settings_profile_path, notice: "Profile picture successfully updated."
else
render :profile
end
end

# # GET /settings/account
# def account
# end

# PATCH /settings/account
def update_account
if current_user.update(account_params)
redirect_to settings_account_path, notice: "Account successfully updated."
else
render :account
end
end

# PATCH /settings/password
def update_password
if current_user.valid_password?(params[:user][:current_password])
if current_user.reset_password(params[:user][:password], params[:user][:password_confirmation])
bypass_sign_in current_user
redirect_to settings_account_path, notice: "Your password has been changed."
else
render :account
end
else
current_user.errors.add(:current_password, "is invalid")
render :account
end
end

# # GET /settings/email
# def email
# end

# PATCH /settings/email
def update_email
if current_user.update(email_params)
redirect_to settings_email_path, notice: I18n.t("devise.confirmations.send_instructions")
else
render :email
end
end

private

def complete_profile_params
params.require(:user).permit(:phone, :role, :profile_picture)
end

def profile_params
params.require(:user).permit(:username, :phone, :role)
end

def profile_picture_params
params.require(:user).permit(:profile_picture, :remove_profile_picture)
end

def account_params
params.require(:user).permit(:full_name)
end

def email_params
params.require(:user).permit(:email, :emails_enabled)
end
end
13 changes: 13 additions & 0 deletions app/helpers/profiles_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

# Helps generate URLs for user profile pictures.
module ProfilesHelper
def profile_picture_tag(user, size: 128, style: nil)
image_tag(
picture_profile_path(user.username, thumb: size <= 64 ? "1" : nil),
alt: "",
class: "rounded img-ignore-selection",
style: "max-height: #{size}px; max-width: #{size}px;"
)
end
end
6 changes: 6 additions & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ class User < ApplicationRecord
# Callbacks
after_commit :new_registration!, on: :create

# Uploaders
mount_uploader :profile_picture, ResizableImageUploader

# Constants
ORDERS = {
"activity desc" => "(CASE WHEN (users.current_sign_in_at IS NULL) THEN users.created_at ELSE users.current_sign_in_at END) desc",
Expand Down Expand Up @@ -54,6 +57,9 @@ def self.searchable_attributes
belongs_to :site, optional: true

# Methods
def incomplete_profile?
role.blank? || phone.blank? || self[:profile_picture].blank?
end

def email=(email)
super(email.try(:downcase))
Expand Down
42 changes: 42 additions & 0 deletions app/uploaders/resizable_image_uploader.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# frozen_string_literal: true

# Resizes uploaded images to preset dimensions
class ResizableImageUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick

# Choose what kind of storage to use for this uploader:
storage Rails.env.production? ? :fog : :file

# Override the directory where uploaded files will be stored.
# This is a sensible default for uploaders that are meant to be mounted:
def store_dir
File.join(model.class.to_s.underscore.pluralize, model.id.to_s, mounted_as.to_s)
end

# Provide a default URL as a default if there hasn't been a file uploaded:
# def default_url
# # For Rails 3.1+ asset pipeline compatibility:
# # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
#
# "/images/fallback/" + [version_name, "default.png"].compact.join('_')
# end

# Process files as they are uploaded:
process resize_to_limit: [256, 256]

# Create different versions of your uploaded files:
version :thumb do
process resize_to_fill: [64, 64]
end

# Add a white list of extensions which are allowed to be uploaded.
def extension_whitelist
%w(jpg jpeg gif png)
end

# Override the filename of the uploaded files:
# Avoid using model.id or version_name here, see uploader/store.rb for details.
def filename
"image#{File.extname(original_filename)}" if original_filename
end
end
12 changes: 12 additions & 0 deletions app/views/directory/_contact.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.key-contact
.key-contact-icon
- if user[:profile_picture]
= profile_picture_tag(user, size: 64)
- else
.px-2= icon("far", "user", class: "fa-3x")
.key-contact-info
.key-contact-name
= user.full_name
.key-contact-role= user.role
.key-contact-email= user.email
.key-contact-phone= user.phone
5 changes: 5 additions & 0 deletions app/views/directory/_profile_form.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
= form_with model: user, url: settings_complete_profile_path, method: :patch, local: true do |form|
= render "forms/vertical/text_field", form: form, object: user, key: :role, key_name: "Project role", help_text: "Ex: Project Manager, DSMB Member, Co-Investigator, Study Coordinator, etc." if user.role.blank?
= render "forms/vertical/text_field", form: form, object: user, key: :phone, help_text: "Format: 555-555-5555" if user.phone.blank?
= render "forms/vertical/file_field", form: form, object: user, key: :profile_picture, help_text: "Square pictures work best. Supported file formats JPG, PNG, and GIF."
= render "forms/vertical/submit", form: form, object: user, submit_text: "Update profile", cancel: false
8 changes: 8 additions & 0 deletions app/views/internal/_tabs.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@
- else
.d-none.d-sm-inline Docs

- current_page = params[:controller].in?(%w(settings))
= link_to settings_path, class: "header-tab #{"header-tab-active" if current_page}", data: { object: "#{"suppress-click" if current_page?(settings_path)}" } do
= icon("fas", "cog")
- if current_page
Settings
- else
.d-none.d-sm-inline Settings

- if false
- current_page = params[:controller].in?(%w(internal)) && params[:action].in?(%w(reports))
= link_to reports_path, class: "header-tab #{"header-tab-active" if current_page}", data: { object: "#{"suppress-click" if current_page?(reports_path)}" } do
Expand Down
7 changes: 7 additions & 0 deletions app/views/internal/dashboard.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@
= render "internal/tabs"
- content_for :sidebar, render("internal/sidebar")

.d-flex.flex-column.flex-sm-row.justify-content-around
- if current_user.incomplete_profile?
.dashboard-container.dashboard-container-border-accent{ style: "border-top: 1px solid #ccc;border-right: 1px solid #ccc;border-bottom: 1px solid #ccc;background-color: #f7eaed;width: 600px;max-width: 100%;" }
.mb-3
%strong Complete your profile
= render "directory/profile_form", user: current_user

.d-flex.flex-column.flex-sm-row.justify-content-between
.dashboard-container.flex-fill
.mb-3
Expand Down
35 changes: 8 additions & 27 deletions app/views/internal/directory.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -11,40 +11,21 @@

.key-contacts
- @key_contacts.each do |user|
.key-contact
.key-contact-icon= icon("far", "user", class: "fa-3x")
.key-contact-info
.key-contact-name
= user.full_name
.key-contact-role= user.role
.key-contact-email= user.email
.key-contact-phone= user.phone
= render "directory/contact", user: user

- if @users.present?
.subheading
Joined Recently

.dashboard-container.dashboard-table
%table.table.table-striped.table-borderless.table-hover.table-sticky
%col
%col
%col.d-none.d-md-table-column
%thead
%tr
%th Name
%th Email
%th.d-none.d-md-table-cell Role

- @users.each do |user|
%tr
%td= user.full_name
%td= user.email
%td.d-none.d-md-table-cell= user.role
.key-contacts
- @users.each do |user|
= render "directory/contact", user: user

.jumbotron.jumbotron-custom-text.jumbotron-shadow
= icon("far", "comments")
= mail_to ActionMailer::Base.smtp_settings[:email], "Contact us"
if your listed information is incorrect.
= icon("fas", "info-circle")
Update your profile in
= succeed "." do
= link_to "settings", settings_path

- elsif false
.jumbotron.jumbotron-custom-text
Expand Down
9 changes: 1 addition & 8 deletions app/views/internal/search.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,7 @@
- case document.searchable.class.to_s
- when "User"
- user = document.searchable
.key-contact
.key-contact-icon= icon("far", "user", class: "fa-3x")
.key-contact-info
.key-contact-name
= user.full_name
.key-contact-role= user.role
.key-contact-email= user.email
.key-contact-phone= user.phone
= render "directory/contact", user: user
- when "Document"
- document = document.searchable
.dashboard-container.dashboard-container-border-accent.mb-3
Expand Down
Loading

0 comments on commit d4adcae

Please sign in to comment.