diff --git a/Changelog.md b/Changelog.md index 002066b6d..c91cc6508 100644 --- a/Changelog.md +++ b/Changelog.md @@ -8,12 +8,12 @@ # 0.7.2.0 -## Refactor - ## Bug fixes * Ignore invalid `diaspora://` links [#7652](https://github.com/diaspora/diaspora/pull/7652) +* Fix deformed avatar in hovercards [#7656](https://github.com/diaspora/diaspora/pull/7656) ## Features +* Add birthday notifications [#7624](https://github.com/diaspora/diaspora/pull/7624) # 0.7.1.1 diff --git a/app/assets/stylesheets/hovercard.scss b/app/assets/stylesheets/hovercard.scss index c664ee467..89e3b4cde 100644 --- a/app/assets/stylesheets/hovercard.scss +++ b/app/assets/stylesheets/hovercard.scss @@ -12,16 +12,10 @@ font-size: small; .avatar { - position: relative; float: left; - height: 70px !important; - width: 70px !important; - top: 0 !important; - - margin: { - right: 10px; - left: 0; - } + height: 70px; + object-fit: cover; + width: 70px; } $image_width: 80px; /* including margin */ diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb index 736389a64..31fb8aa38 100644 --- a/app/controllers/notifications_controller.rb +++ b/app/controllers/notifications_controller.rb @@ -104,7 +104,8 @@ class NotificationsController < ApplicationController "mentioned" => "Notifications::MentionedInPost", "mentioned_in_comment" => "Notifications::MentionedInComment", "reshared" => "Notifications::Reshared", - "started_sharing" => "Notifications::StartedSharing" + "started_sharing" => "Notifications::StartedSharing", + "contacts_birthday" => "Notifications::ContactsBirthday" } end helper_method :types diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb index 15f04a327..dd1a4cf9a 100644 --- a/app/helpers/notifications_helper.rb +++ b/app/helpers/notifications_helper.rb @@ -16,6 +16,8 @@ module NotificationsHelper elsif %w(Notifications::CommentOnPost Notifications::AlsoCommented Notifications::Reshared Notifications::Liked) .include?(note.type) opts.merge!(opts_for_post(note.linked_object)) + elsif note.is_a?(Notifications::ContactsBirthday) + opts.merge!(opts_for_birthday(note.linked_object)) end end translation(target_type, opts) @@ -44,6 +46,10 @@ module NotificationsHelper } end + def opts_for_birthday(person) + {date: locale_date(person.birthday.to_s)} + end + def notification_people_link(note, people=nil) actors =people || note.actors number_of_actors = actors.size diff --git a/app/mailers/notification_mailers/contacts_birthday.rb b/app/mailers/notification_mailers/contacts_birthday.rb new file mode 100644 index 000000000..c032e39c4 --- /dev/null +++ b/app/mailers/notification_mailers/contacts_birthday.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +module NotificationMailers + class ContactsBirthday < NotificationMailers::Base + attr_accessor :person + + def set_headers(person_id) + @person = Person.find(person_id) + @headers[:subject] = I18n.t("notifier.contacts_birthday.subject", name: @person.name) + end + end +end diff --git a/app/models/notifications/contacts_birthday.rb b/app/models/notifications/contacts_birthday.rb new file mode 100644 index 000000000..ec8c3c0fe --- /dev/null +++ b/app/models/notifications/contacts_birthday.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module Notifications + class ContactsBirthday < Notification + def mail_job + Workers::Mail::ContactsBirthday + end + + def popup_translation_key + "notifications.contacts_birthday" + end + + def self.notify(contact, _recipient_user_ids) + recipient = contact.user + actor = contact.person + create_notification(recipient, actor, actor).try(:email_the_user, actor, actor) + end + end +end diff --git a/app/models/user_preference.rb b/app/models/user_preference.rb index ef29de6a1..4f6b5f9aa 100644 --- a/app/models/user_preference.rb +++ b/app/models/user_preference.rb @@ -14,7 +14,8 @@ class UserPreference < ApplicationRecord "started_sharing", "also_commented", "liked", - "reshared"] + "reshared", + "contacts_birthday"] def must_be_valid_email_type unless VALID_EMAIL_TYPES.include?(self.email_type) diff --git a/app/views/notifications/index.html.haml b/app/views/notifications/index.html.haml index 61a70fe14..283eca5a3 100644 --- a/app/views/notifications/index.html.haml +++ b/app/views/notifications/index.html.haml @@ -30,6 +30,8 @@ %i.entypo-reshare - when "started_sharing" %i.entypo-add-user + - when "contacts_birthday" + %i.entypo-calendar = t("." + key) .col-md-9.stream.notifications diff --git a/app/views/notifier/contacts_birthday.markerb b/app/views/notifier/contacts_birthday.markerb new file mode 100644 index 000000000..7c3dcfe57 --- /dev/null +++ b/app/views/notifier/contacts_birthday.markerb @@ -0,0 +1,6 @@ + +<%= t(".birthday", name: @notification.person.name) %> + +[<%= t(".view_profile", name: @notification.person.name) %>][1] + +[1] <%= local_or_remote_person_path(@notification.person, absolute: true) %> diff --git a/app/views/users/_edit.haml b/app/views/users/_edit.haml index 060778b95..5b6ad6172 100644 --- a/app/views/users/_edit.haml +++ b/app/views/users/_edit.haml @@ -127,51 +127,55 @@ #email_prefs - if current_user.admin? = type.label :someone_reported, class: "checkbox-inline" do - = type.check_box :someone_reported, {checked: @email_prefs["someone_reported"]}, false, true + = type.check_box :someone_reported, {checked: email_prefs["someone_reported"]}, false, true = t(".someone_reported") .small-horizontal-spacer = type.label :started_sharing, class: "checkbox-inline" do - = type.check_box :started_sharing, {checked: @email_prefs["started_sharing"]}, false, true + = type.check_box :started_sharing, {checked: email_prefs["started_sharing"]}, false, true = t(".started_sharing") .small-horizontal-spacer = type.label :mentioned, class: "checkbox-inline" do - = type.check_box :mentioned, {checked: @email_prefs["mentioned"]}, false, true + = type.check_box :mentioned, {checked: email_prefs["mentioned"]}, false, true = t(".mentioned") .small-horizontal-spacer = type.label :mentioned_in_comment, class: "checkbox-inline" do - = type.check_box :mentioned_in_comment, {checked: @email_prefs["mentioned_in_comment"]}, false, true + = type.check_box :mentioned_in_comment, {checked: email_prefs["mentioned_in_comment"]}, false, true = t(".mentioned_in_comment") .small-horizontal-spacer = type.label :liked, class: "checkbox-inline" do - = type.check_box :liked, {checked: @email_prefs["liked"]}, false, true + = type.check_box :liked, {checked: email_prefs["liked"]}, false, true = t(".liked") .small-horizontal-spacer = type.label :reshared, class: "checkbox-inline" do - = type.check_box :reshared, {checked: @email_prefs["reshared"]}, false, true + = type.check_box :reshared, {checked: email_prefs["reshared"]}, false, true = t(".reshared") .small-horizontal-spacer = type.label :comment_on_post, class: "checkbox-inline" do - = type.check_box :comment_on_post, {checked: @email_prefs["comment_on_post"]}, false, true + = type.check_box :comment_on_post, {checked: email_prefs["comment_on_post"]}, false, true = t(".comment_on_post") .small-horizontal-spacer = type.label :also_commented, class: "checkbox-inline" do - = type.check_box :also_commented, {checked: @email_prefs["also_commented"]}, false, true + = type.check_box :also_commented, {checked: email_prefs["also_commented"]}, false, true = t(".also_commented") .small-horizontal-spacer = type.label :private_message, class: "checkbox-inline" do - = type.check_box :private_message, {checked: @email_prefs["private_message"]}, false, true + = type.check_box :private_message, {checked: email_prefs["private_message"]}, false, true = t(".private_message") + .small-horizontal-spacer - .small-horizontal-spacer + = type.label :contacts_birthday, class: "checkbox-inline" do + = type.check_box :contacts_birthday, {checked: email_prefs["contacts_birthday"]}, false, true + = t(".birthday") + .small-horizontal-spacer .clearfix= f.submit t(".change"), class: "btn btn-primary pull-right", id: "change_email_preferences" %hr diff --git a/app/views/users/edit.html.haml b/app/views/users/edit.html.haml index 0f883935f..53ec409ce 100644 --- a/app/views/users/edit.html.haml +++ b/app/views/users/edit.html.haml @@ -5,4 +5,4 @@ = render "shared/settings_nav" .col-md-9 .framed-content - = render "edit" + = render "edit", email_prefs: @email_prefs diff --git a/app/views/users/edit.mobile.haml b/app/views/users/edit.mobile.haml index 7a7b4a3ce..74617455e 100644 --- a/app/views/users/edit.mobile.haml +++ b/app/views/users/edit.mobile.haml @@ -5,4 +5,4 @@ .row .col-md-12 - = render "edit" + = render "edit", email_prefs: @email_prefs diff --git a/app/workers/check_birthday.rb b/app/workers/check_birthday.rb new file mode 100644 index 000000000..2ed919f42 --- /dev/null +++ b/app/workers/check_birthday.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +module Workers + class CheckBirthday < Base + sidekiq_options queue: :low + + def perform + profiles = Profile + .where("EXTRACT(MONTH FROM birthday) = ?", Time.zone.today.month) + .where("EXTRACT(DAY FROM birthday) = ?", Time.zone.today.day) + profiles.each do |profile| + profile.person.contacts.where(sharing: true, receiving: true).each do |contact| + Notifications::ContactsBirthday.notify(contact, []) + end + end + end + end +end diff --git a/app/workers/mail/contacts_birthday.rb b/app/workers/mail/contacts_birthday.rb new file mode 100644 index 000000000..0a3072897 --- /dev/null +++ b/app/workers/mail/contacts_birthday.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +module Workers + module Mail + class ContactsBirthday < NotifierBase + end + end +end diff --git a/config/locales/diaspora/en.yml b/config/locales/diaspora/en.yml index bc7dd9a2e..d00a64d11 100644 --- a/config/locales/diaspora/en.yml +++ b/config/locales/diaspora/en.yml @@ -642,6 +642,10 @@ en: zero: "%{actors} have reshared your post %{post_link}." one: "%{actors} has reshared your post %{post_link}." other: "%{actors} have reshared your post %{post_link}." + contacts_birthday: + zero: "%{actors} have their birthday on %{date}." + one: "%{actors} has their birthday on %{date}." + other: "%{actors} have their birthday on %{date}." also_commented_deleted: zero: "%{actors} commented on a deleted post." one: "%{actors} commented on a deleted post." @@ -676,6 +680,7 @@ en: mentioned_in_comment: "Mentioned in comment" reshared: "Reshared" started_sharing: "Started sharing" + contacts_birthday: "Birthday" no_notifications: "You don't have any notifications yet." and_others: zero: "and nobody else" @@ -720,6 +725,10 @@ en: reshared: reshared: "%{name} reshared your post" view_post: "View post >" + contacts_birthday: + subject: "%{name} has their birthday today" + birthday: "%{name} has their birthday today. Wish them 'Happy Birthday'!" + view_profile: "View %{name}’s profile" confirm_email: subject: "Please activate your new email address %{unconfirmed_email}" click_link: "To activate your new email address %{unconfirmed_email}, please follow this link:" @@ -1213,6 +1222,7 @@ en: comment_on_post: "someone comments on your post" also_commented: "someone comments on a post you’ve commented on" private_message: "you receive a private message" + birthday: "someone has their birthday" download_export: "Download my profile" request_export: "Request my profile data" request_export_update: "Refresh my profile data" diff --git a/config/schedule.yml b/config/schedule.yml index 0d179a75b..88292df2a 100644 --- a/config/schedule.yml +++ b/config/schedule.yml @@ -13,3 +13,7 @@ recurring_pod_check: recheck_scheduled_pods: cron: "*/30 * * * *" class: "Workers::RecheckScheduledPods" + +check_birthday: + cron: "0 0 * * *" + class: "Workers::CheckBirthday" diff --git a/spec/controllers/notifications_controller_spec.rb b/spec/controllers/notifications_controller_spec.rb index 1788182a3..21b812885 100644 --- a/spec/controllers/notifications_controller_spec.rb +++ b/spec/controllers/notifications_controller_spec.rb @@ -81,6 +81,7 @@ describe NotificationsController, :type => :controller do expect(response_json["unread_count_by_type"]).to eq( "also_commented" => 1, "comment_on_post" => 0, + "contacts_birthday" => 0, "liked" => 0, "mentioned" => 0, "mentioned_in_comment" => 0, diff --git a/spec/mailers/notifier_spec.rb b/spec/mailers/notifier_spec.rb index ea8ad573e..002014b05 100644 --- a/spec/mailers/notifier_spec.rb +++ b/spec/mailers/notifier_spec.rb @@ -79,6 +79,23 @@ describe Notifier, type: :mailer do end end + describe ".contacts_birthday" do + let(:contact) { alice.contact_for(bob.person) } + let(:mail) { Notifier.send_notification("contacts_birthday", alice.id, nil, bob.person.id) } + + it "TO: goes to the right person" do + expect(mail.to).to eq([alice.email]) + end + + it "SUBJECT: has the name of birthday person in the subject" do + expect(mail.subject).to include(bob.person.name) + end + + it "has a link to the birthday profile in the body" do + expect(mail.body.encoded).to include(user_profile_url(bob.person.username)) + end + end + describe ".mentioned" do before do @user = alice diff --git a/spec/models/notifications/contacts_birthday_spec.rb b/spec/models/notifications/contacts_birthday_spec.rb new file mode 100644 index 000000000..8ca85266c --- /dev/null +++ b/spec/models/notifications/contacts_birthday_spec.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +describe Notifications::ContactsBirthday, type: :model do + let(:contact) { alice.contact_for(bob.person) } + let(:recipient) { alice } + let(:actor) { bob.person } + let(:birthday_notification) { Notifications::ContactsBirthday.new(recipient: alice) } + + describe ".notify" do + it "calls create_notification with contact owner as a recipient" do + expect(Notifications::ContactsBirthday).to receive(:create_notification).with(recipient, actor, actor) + + Notifications::ContactsBirthday.notify(contact, []) + end + + it "sends an email to the contacts owner person" do + allow(Notifications::ContactsBirthday).to receive(:create_notification).and_return(birthday_notification) + expect(alice).to receive(:mail).with(Workers::Mail::ContactsBirthday, recipient.id, actor.id, actor.id) + + Notifications::ContactsBirthday.notify(contact, []) + end + end +end diff --git a/spec/workers/check_birthday_spec.rb b/spec/workers/check_birthday_spec.rb new file mode 100644 index 000000000..594be68f0 --- /dev/null +++ b/spec/workers/check_birthday_spec.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +describe Workers::CheckBirthday do + let(:birthday_profile) { bob.profile } + let(:contact1) { alice.contact_for(bob.person) } + let(:contact2) { eve.contact_for(bob.person) } + + before do + Timecop.freeze(Time.zone.local(1999, 9, 9)) + birthday_profile.update_attributes(birthday: "1990-09-09") + allow(Notifications::ContactsBirthday).to receive(:notify) + end + + after do + Timecop.return + end + + it "calls notify method for the birthday person's contacts" do + Workers::CheckBirthday.new.perform + expect(Notifications::ContactsBirthday).to have_received(:notify).with(contact1, []) + expect(Notifications::ContactsBirthday).to have_received(:notify).with(contact2, []) + end + + it "does nothing if the birthday does not exist" do + birthday_profile.update_attributes(birthday: nil) + Workers::CheckBirthday.new.perform + expect(Notifications::ContactsBirthday).not_to have_received(:notify) + end + + it "does nothing if the person's birthday is not today" do + birthday_profile.update_attributes(birthday: "1988-04-15") + Workers::CheckBirthday.new.perform + expect(Notifications::ContactsBirthday).not_to have_received(:notify) + end + + it "does not call notify method if a person is not a contact of the birthday person" do + contact2.destroy + Workers::CheckBirthday.new.perform + expect(Notifications::ContactsBirthday).to have_received(:notify).with(contact1, []) + expect(Notifications::ContactsBirthday).not_to have_received(:notify).with(contact2, []) + end + + it "does not call notify method if a contact user is not :receiving from the birthday person" do + contact2.update_attributes(receiving: false) + Workers::CheckBirthday.new.perform + expect(Notifications::ContactsBirthday).to have_received(:notify).with(contact1, []) + expect(Notifications::ContactsBirthday).not_to have_received(:notify).with(contact2, []) + end + + it "does not call notify method if a birthday person is not :sharing with the contact user" do + contact2.update_attributes(sharing: false) + Workers::CheckBirthday.new.perform + expect(Notifications::ContactsBirthday).to have_received(:notify).with(contact1, []) + expect(Notifications::ContactsBirthday).not_to have_received(:notify).with(contact2, []) + end +end diff --git a/spec/workers/mail/contacts_birthday_spec.rb b/spec/workers/mail/contacts_birthday_spec.rb new file mode 100644 index 000000000..83867eb42 --- /dev/null +++ b/spec/workers/mail/contacts_birthday_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +describe Workers::Mail::ContactsBirthday do + describe "#perform" do + it "should call .deliver on the notifier object" do + mail_double = double + expect(mail_double).to receive(:deliver_now) + expect(Notifier).to receive(:send_notification) + .with("contacts_birthday", alice.id).and_return(mail_double) + Workers::Mail::ContactsBirthday.new.perform(alice.id) + end + end +end