Support Users Directly Uploading Profile Pictures.

* Adds a `picture` attribute to `User`.
* Preserves Gravatar as a fallback option.
* Now, you should use `user.profile_picturer` instead of `gravatar_url`
* TODO: Ensure `profile_picture` handles sizing right for uploaded images.
This commit is contained in:
Michael Ball 2020-07-14 21:06:15 -07:00
parent b66f69599a
commit 3883188dcd
13 changed files with 43 additions and 18 deletions

View file

@ -24,8 +24,8 @@ class UsersController < ApplicationController
private
# Only allow a trusted parameter "white list" through.
def user_params
params.require(:user).permit(:name, :biography, :nickname, :affiliation)
params.require(:user).permit(:name, :biography, :nickname, :affiliation,
:picture, :picture_cache)
end
end

View file

@ -23,9 +23,13 @@ class User < ApplicationRecord
has_paper_trail on: [:create, :update], ignore: [:sign_in_count, :remember_created_at, :current_sign_in_at, :last_sign_in_at, :current_sign_in_ip, :last_sign_in_ip, :unconfirmed_email,
:avatar_content_type, :avatar_file_size, :avatar_updated_at, :updated_at, :confirmation_sent_at, :confirmation_token, :reset_password_token]
# A user may have an uploaded avatar or use gravatar.
# The uploaded picture takes precedence.
include Gravtastic
gravtastic size: 32
mount_uploader :picture, PictureUploader, mount_on: :picture
before_create :setup_role
after_save :touch_events
@ -151,6 +155,14 @@ class User < ApplicationRecord
ticket_purchases.find_by(conference_id: conference.id).present?
end
##
# Returns a user's profile picture URL.
# Partials should *not* directly call `gravatar_url`
def profile_picture(opts)
# TODO: Figure out how to align sizes?
picture.thumb.url || gravatar_url(opts)
end
def self.for_ichain_username(username, attributes)
user = find_by(username: username)

View file

@ -6,7 +6,7 @@
- @top_submitter.each do |key, value|
.row.top-submitter
.col-md-2
= image_tag(key.gravatar_url(size: '25'), title: "Yo #{key.name}!", alt: '', 'class' => 'img-circle img-responsive text-center')
= image_tag(key.profile_picture(size: '25'), title: "Yo #{key.name}!", alt: '', 'class' => 'img-circle img-responsive text-center')
.col-md-10
%h4
= link_to key.name, admin_user_path(key)

View file

@ -145,7 +145,7 @@
Registered
= word_pluralize(@conference.participants.count, 'Attendee')
- @conference.participants.each do |participant|
= link_to image_tag(participant.gravatar_url(size: '25'), title: "#{participant.name}!", class: 'img-circle'), user_path(participant)
= link_to image_tag(participant.profile_picture(size: '25'), title: "#{participant.name}!", class: 'img-circle'), user_path(participant)
.col-md-4.col-md-offset-2
- if @conference.program.speakers.confirmed.any?
%h4
@ -156,4 +156,4 @@
Confirmed
= word_pluralize(@conference.program.speakers.confirmed.count, 'Speaker')
- @conference.program.speakers.confirmed.each do |speaker|
= link_to image_tag(speaker.gravatar_url(size: '25'), title: "#{speaker.name}!", class: 'img-circle'), user_path(speaker)
= link_to image_tag(speaker.profile_picture(size: '25'), title: "#{speaker.name}!", class: 'img-circle'), user_path(speaker)

View file

@ -11,7 +11,7 @@
= link_to(conference_program_proposal_path(conference_id,
event),
class: 'thumbnail') do
= image_tag speaker.gravatar_url(size: 300),
= image_tag speaker.profile_picture(size: 300),
class: ['img-responsive', 'img-circle'],
title: speaker.name
.caption

View file

@ -29,7 +29,7 @@
%li.dropdown
%a.dropdown-toggle{"data-toggle" => "dropdown", href: '#', id: "current-user-detail"}
= current_user.name
= image_tag(current_user.gravatar_url(size: '18'), title: "Yo #{current_user.name}!", alt: '')
= image_tag(current_user.profile_picture(size: '18'), title: "Yo #{current_user.name}!", alt: '')
%b.caret
%ul.dropdown-menu
= render 'layouts/user_menu'

View file

@ -4,8 +4,8 @@
%meta{ property: "og:description", content: @event.abstract }
%meta{ property: "og:site_name", content: (ENV['OSEM_NAME'] || 'OSEM') }
- if @speakers_ordered.any?
%meta{ property: "og:image", content: @speakers_ordered.first.gravatar_url }
%meta{ property: "og:image:secure_url", content: @speakers_ordered.first.gravatar_url }
%meta{ property: "og:image", content: @speakers_ordered.first.profile_picture }
%meta{ property: "og:image:secure_url", content: @speakers_ordered.first.profile_picture }
.container
.row.page-header
@ -37,7 +37,7 @@
.speakerinfo
.row
.col-md-4
= image_tag speaker.gravatar_url(:size => 120), class: 'img-responsive img-rounded'
= image_tag speaker.profile_picture(:size => 120), class: 'img-responsive img-rounded'
.col-md-8
%h4
= link_to speaker.name, user_path(speaker.id)

View file

@ -1,7 +1,7 @@
.panel.panel-default.event-panel{ onClick: 'eventClicked(event, this);', "data-url" => "#{url_for(conference_program_proposal_path(@conference.short_title, event.id))}" }
.panel-body
- event.speakers_ordered.each do |speaker|
= image_tag speaker.gravatar_url, :class => "img-circle pull-right all-speaker-pic", |
= image_tag speaker.profile_picture, :class => "img-circle pull-right all-speaker-pic", |
:alt => speaker.name, |
:title => speaker.name |

View file

@ -10,8 +10,7 @@
= event.title
- event.speakers_ordered.each do |speaker|
= image_tag speaker.gravatar_url, :class => "img-circle pull-right speaker-pic", |
= image_tag speaker.profile_picture, :class => "img-circle pull-right speaker-pic", |
:alt => speaker.name, |
:title => speaker.name, |
:style => "height: #{ speaker_height(@rooms) }px; width: #{ speaker_width(@rooms) }px;"

View file

@ -10,8 +10,16 @@
= f.input :nickname, as: :string, hint: 'This is how the other users see you, not your real name'
.control-label
= "Avatar"
= image_tag(@user.gravatar_url(size: '48'), title: "Yo #{@user.name}!", alt: '')
= image_tag(@user.profile_picture(size: '48'), title: "Yo #{@user.name}!", alt: '')
= link_to 'Change your avatar here', 'https://gravatar.com'
%br
%p
Or upload a picture.
= image_tag f.object.picture.thumb.url if f.object.picture?
- if @user.picture?
= image_tag(@user.picture.thumb.url, width: '20%')
= f.input :picture, hint: 'If you upload a picture, it will be used in place of Gravatar.'
= f.input :affiliation, as: :string,
hint: 'This could be a company, a user group, or nothing at all.'
= f.input :biography, input_html: { rows: 5, data: { provide: 'markdown' } },

View file

@ -3,7 +3,7 @@
.col-md-12
.page-header
%h1
= image_tag(@user.gravatar_url(size: '48'), title: "Yo #{@user.name}!", alt: '')
= image_tag(@user.profile_picture(size: '48'), title: "Yo #{@user.name}!", alt: '')
= @user.name
%small
= @user.nickname

View file

@ -0,0 +1,5 @@
class AddPictureToUsers < ActiveRecord::Migration[5.2]
def change
add_column :users, :picture, :string
end
end

View file

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2020_07_15_001812) do
ActiveRecord::Schema.define(version: 2020_07_15_034647) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -591,6 +591,7 @@ ActiveRecord::Schema.define(version: 2020_07_15_001812) do
t.boolean "is_admin", default: false
t.string "username"
t.boolean "is_disabled", default: false
t.string "picture"
t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true