diff --git a/app/assets/stylesheets/osem.scss b/app/assets/stylesheets/osem.scss index bcf37d4f..7b913fe6 100644 --- a/app/assets/stylesheets/osem.scss +++ b/app/assets/stylesheets/osem.scss @@ -51,6 +51,11 @@ body { margin: 0 auto; } +nav #current-user-detail .profile-thumnail { + max-height: 20px; + max-width: 20px; +} + /* centered columns styles */ .row-centered { text-align:center; diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index 4d7925dd..e49c02f5 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -43,7 +43,8 @@ module Admin # Variable @show_attributes holds the attributes that are visible for the 'show' action # If you want to change the attributes that are shown in the 'show' action of users # add/remove the attributes in the following string array - @show_attributes = %w(name email username nickname affiliation biography registered attended roles created_at + @show_attributes = %w(name email username nickname affiliation biography + profile_picture registered attended roles created_at updated_at sign_in_count current_sign_in_at last_sign_in_at current_sign_in_ip last_sign_in_ip) end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 3db62d11..678c1901 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -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) - end + def user_params + params.require(:user).permit(:name, :biography, :nickname, :affiliation, + :picture, :picture_cache) + end end diff --git a/app/models/conference.rb b/app/models/conference.rb index b4b19e2c..c91939ae 100644 --- a/app/models/conference.rb +++ b/app/models/conference.rb @@ -127,7 +127,7 @@ class Conference < ApplicationRecord event_schedules = program.event_schedules.select do |event_schedule| event_schedule.start_time.hour < start_hour || event_schedule.end_time.hour > end_hour || - (event_schedule.end_time.hour == end_hour && event_schedule.end_time.minute > 0) + (event_schedule.end_time.hour == end_hour && event_schedule.end_time.min > 0) end event_schedules.each(&:destroy) end diff --git a/app/models/user.rb b/app/models/user.rb index f6d62de3..1a2b19b1 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -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,21 @@ 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 = {}) + return gravatar_url(opts) unless picture.present? + size = (opts[:size] || 0).to_i + if size < 50 + picture.tiny.url + elsif size <= 100 + picture.thumb.url + else + picture.large.url + end + end + def self.for_ichain_username(username, attributes) user = find_by(username: username) diff --git a/app/uploaders/picture_uploader.rb b/app/uploaders/picture_uploader.rb index 4cad1594..47e86f8b 100644 --- a/app/uploaders/picture_uploader.rb +++ b/app/uploaders/picture_uploader.rb @@ -62,6 +62,10 @@ class PictureUploader < CarrierWave::Uploader::Base process resize_to_fit: [100, 100] end + version :tiny do + process resize_to_fit: [32, 32] + end + version :first, if: :sponsor? version :first do process resize_and_pad: [320, 180, 'white'] diff --git a/app/views/admin/conferences/_top_submitter.html.haml b/app/views/admin/conferences/_top_submitter.html.haml index 9f220249..b4f714fd 100644 --- a/app/views/admin/conferences/_top_submitter.html.haml +++ b/app/views/admin/conferences/_top_submitter.html.haml @@ -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) diff --git a/app/views/admin/users/_form.html.haml b/app/views/admin/users/_form.html.haml index 7604f0d3..845065dc 100644 --- a/app/views/admin/users/_form.html.haml +++ b/app/views/admin/users/_form.html.haml @@ -19,6 +19,18 @@ = f.input :username, :as => :string if @user.new_record? = f.input :email = f.input :password if @user.new_record? + .control-label + Gravatar + = image_tag(@user.profile_picture(size: '48'), alt: '') + %p + Or upload a picture. + = f.input :picture, hint: 'If you upload a picture, it will be used in place of Gravatar.' + - if @user.picture? + %p + Current Picture + %br + = image_tag(@user.picture.url, width: '20%') + = f.input :affiliation, as: :string = f.input :biography, input_html: { rows: 10, data: { provide: 'markdown' } }, hint: markdown_hint diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml index c9048be4..b90e72d9 100644 --- a/app/views/admin/users/show.html.haml +++ b/app/views/admin/users/show.html.haml @@ -26,6 +26,9 @@ - elsif attr == 'biography' %td = markdown(@user.biography) + - elsif attr == 'profile_picture' + %td + = image_tag @user.profile_picture(size: '100'), alt: '' - elsif attr == 'email' %td = @user.send(attr) diff --git a/app/views/conference_registrations/show.html.haml b/app/views/conference_registrations/show.html.haml index a5663ef1..49cca609 100644 --- a/app/views/conference_registrations/show.html.haml +++ b/app/views/conference_registrations/show.html.haml @@ -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) diff --git a/app/views/conferences/_highlights.haml b/app/views/conferences/_highlights.haml index b44a24b1..4b2f601c 100644 --- a/app/views/conferences/_highlights.haml +++ b/app/views/conferences/_highlights.haml @@ -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 diff --git a/app/views/layouts/_navigation.html.haml b/app/views/layouts/_navigation.html.haml index 794caa96..239c053f 100644 --- a/app/views/layouts/_navigation.html.haml +++ b/app/views/layouts/_navigation.html.haml @@ -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'), class: 'profile-thumbnail', alt: '') %b.caret %ul.dropdown-menu = render 'layouts/user_menu' diff --git a/app/views/proposals/show.html.haml b/app/views/proposals/show.html.haml index 217a76b3..0de85205 100644 --- a/app/views/proposals/show.html.haml +++ b/app/views/proposals/show.html.haml @@ -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) diff --git a/app/views/schedules/_event.html.haml b/app/views/schedules/_event.html.haml index 601afdf5..7ec7122f 100644 --- a/app/views/schedules/_event.html.haml +++ b/app/views/schedules/_event.html.haml @@ -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 | diff --git a/app/views/schedules/_schedule_item.html.haml b/app/views/schedules/_schedule_item.html.haml index b6d8708e..e00d9a38 100644 --- a/app/views/schedules/_schedule_item.html.haml +++ b/app/views/schedules/_schedule_item.html.haml @@ -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;" - diff --git a/app/views/users/edit.html.haml b/app/views/users/edit.html.haml index 52c0d57f..e5235099 100644 --- a/app/views/users/edit.html.haml +++ b/app/views/users/edit.html.haml @@ -10,8 +10,17 @@ = 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' + %p + Or upload a picture. + = f.input :picture, hint: 'If you upload a picture, it will be used in place of Gravatar.' + - if @user.picture? + %p + Current Picture + %br + = image_tag(@user.picture.thumb.url, width: '20%') + = 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' } }, diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index b20891f8..65f8e853 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -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 diff --git a/db/migrate/20200715034647_add_picture_to_users.rb b/db/migrate/20200715034647_add_picture_to_users.rb new file mode 100644 index 00000000..ec529882 --- /dev/null +++ b/db/migrate/20200715034647_add_picture_to_users.rb @@ -0,0 +1,5 @@ +class AddPictureToUsers < ActiveRecord::Migration[5.2] + def change + add_column :users, :picture, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index 07effdca..a29ab329 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -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