Commit f82ab42d authored by Felipe Artur's avatar Felipe Artur

Re-use notifications dropdown on user profile

parent 5c45d593
...@@ -126,6 +126,8 @@ class Dispatcher ...@@ -126,6 +126,8 @@ class Dispatcher
shortcut_handler = new ShortcutsDashboardNavigation() shortcut_handler = new ShortcutsDashboardNavigation()
when 'profiles' when 'profiles'
new Profile() new Profile()
new NotificationsForm()
new NotificationsDropdown()
when 'projects' when 'projects'
new Project() new Project()
new ProjectAvatar() new ProjectAvatar()
...@@ -139,6 +141,7 @@ class Dispatcher ...@@ -139,6 +141,7 @@ class Dispatcher
new ProjectNew() new ProjectNew()
when 'show' when 'show'
new ProjectShow() new ProjectShow()
new NotificationsDropdown()
when 'wikis' when 'wikis'
new Wikis() new Wikis()
shortcut_handler = new ShortcutsNavigation() shortcut_handler = new ShortcutsNavigation()
......
class @NotificationsDropdown
$ ->
$(document)
.off 'click', '.update-notification'
.on 'click', '.update-notification', (e) ->
e.preventDefault()
notificationLevel = $(@).data 'notification-level'
label = $(@).data 'notification-title'
form = $(this).parents('form:first')
form.find('.js-notification-loading').toggleClass 'fa-bell fa-spin fa-spinner'
form.find('#notification_setting_level').val(notificationLevel)
form.submit();
$(document)
.off 'ajax:success', '#notification-form'
.on 'ajax:success', '#notification-form', (e, data) ->
if data.saved
new Flash('Notification settings saved', 'notice')
$(e.currentTarget).closest('.notification-dropdown').replaceWith(data.html)
else
new Flash('Failed to save new settings', 'alert')
class @NotificationsForm class @NotificationsForm
constructor: -> constructor: ->
@form = $('.custom-notifications-form')
@removeEventListeners() @removeEventListeners()
@initEventListeners() @initEventListeners()
...@@ -14,7 +12,7 @@ class @NotificationsForm ...@@ -14,7 +12,7 @@ class @NotificationsForm
toggleCheckbox: (e) => toggleCheckbox: (e) =>
$checkbox = $(e.currentTarget) $checkbox = $(e.currentTarget)
$parent = $checkbox.closest('.checkbox') $parent = $checkbox.closest('.checkbox')
console.log($parent)
@saveEvent($checkbox, $parent) @saveEvent($checkbox, $parent)
showCheckboxLoadingSpinner: ($parent) -> showCheckboxLoadingSpinner: ($parent) ->
...@@ -26,11 +24,14 @@ class @NotificationsForm ...@@ -26,11 +24,14 @@ class @NotificationsForm
.removeClass 'is-done' .removeClass 'is-done'
saveEvent: ($checkbox, $parent) -> saveEvent: ($checkbox, $parent) ->
form = $parent.parents('form:first')
console.log(form)
$.ajax( $.ajax(
url: @form.attr('action') url: form.attr('action')
method: 'patch' method: form.attr('method')
dataType: 'json' dataType: 'json'
data: @form.serialize() data: form.serialize()
beforeSend: => beforeSend: =>
@showCheckboxLoadingSpinner($parent) @showCheckboxLoadingSpinner($parent)
).done (data) -> ).done (data) ->
......
...@@ -8,6 +8,10 @@ class @Profile ...@@ -8,6 +8,10 @@ class @Profile
$('.js-preferences-form').on 'change.preference', 'input[type=radio]', -> $('.js-preferences-form').on 'change.preference', 'input[type=radio]', ->
$(this).parents('form').submit() $(this).parents('form').submit()
# Automatically submit email form when it changes
$('#user_notification_email').on 'change', ->
$(this).parents('form').submit()
$('.update-username').on 'ajax:before', -> $('.update-username').on 'ajax:before', ->
$('.loading-username').show() $('.loading-username').show()
$(this).find('.update-success').hide() $(this).find('.update-success').hide()
......
...@@ -34,27 +34,6 @@ class @Project ...@@ -34,27 +34,6 @@ class @Project
$(@).parents('.no-password-message').remove() $(@).parents('.no-password-message').remove()
e.preventDefault() e.preventDefault()
$(document)
.off 'click', '.update-notification'
.on 'click', '.update-notification', (e) ->
e.preventDefault()
notificationLevel = $(@).data 'notification-level'
label = $(@).data 'notification-title'
$('.js-notification-loading').toggleClass 'fa-bell fa-spin fa-spinner'
$('#notification_setting_level').val(notificationLevel)
$('#notification-form').submit()
$(document)
.off 'ajax:success', '#notification-form'
.on 'ajax:success', '#notification-form', (e, data) ->
if data.saved
new Flash('Notification settings saved', 'notice')
$('.js-notification-toggle-btns')
.closest('.notification-dropdown')
.replaceWith(data.html)
else
new Flash('Failed to save new settings', 'alert')
@projectSelectDropdown() @projectSelectDropdown()
......
class Groups::NotificationSettingsController < Groups::ApplicationController
before_action :authenticate_user!
def update
notification_setting = current_user.notification_settings_for(group)
saved = notification_setting.update_attributes(notification_setting_params)
render json: { saved: saved }
end
private
def notification_setting_params
params.require(:notification_setting).permit(:level)
end
end
class Projects::NotificationSettingsController < Projects::ApplicationController class NotificationSettingsController < ApplicationController
before_action :authenticate_user! before_action :authenticate_user!
def update def create
project = current_user.projects.find(params[:project][:id])
@notification_setting = current_user.notification_settings_for(project) @notification_setting = current_user.notification_settings_for(project)
saved = @notification_setting.update_attributes(notification_setting_params) @saved = @notification_setting.update_attributes(notification_setting_params)
render json: { render_response
html: view_to_html_string("projects/buttons/_notifications", locals: { project: @project, notification_setting: @notification_setting }), end
saved: saved
} def update
@notification_setting = current_user.notification_settings.find(params[:id])
@saved = @notification_setting.update_attributes(notification_setting_params)
render_response
end end
private private
def render_response
render json: {
html: view_to_html_string("notifications/buttons/_notifications", notification_setting: @notification_setting),
saved: @saved
}
end
def notification_setting_params def notification_setting_params
allowed_fields = NotificationSetting::EMAIL_EVENTS.dup allowed_fields = NotificationSetting::EMAIL_EVENTS.dup
allowed_fields << :level allowed_fields << :level
......
class Profiles::NotificationsController < Profiles::ApplicationController class Profiles::NotificationsController < Profiles::ApplicationController
def show def show
@user = current_user @user = current_user
@group_notifications = current_user.notification_settings.for_groups @group_notifications = current_user.notification_settings.for_groups.order(:id)
@project_notifications = current_user.notification_settings.for_projects @project_notifications = current_user.notification_settings.for_projects.order(:id)
@global_notification_setting = current_user.global_notification_setting @global_notification_setting = current_user.global_notification_setting
end end
def update def update
if current_user.update_attributes(user_params) && update_notification_settings if current_user.update_attributes(user_params)
flash[:notice] = "Notification settings saved" flash[:notice] = "Notification settings saved"
else else
flash[:alert] = "Failed to save new settings" flash[:alert] = "Failed to save new settings"
...@@ -19,16 +19,4 @@ class Profiles::NotificationsController < Profiles::ApplicationController ...@@ -19,16 +19,4 @@ class Profiles::NotificationsController < Profiles::ApplicationController
def user_params def user_params
params.require(:user).permit(:notification_email) params.require(:user).permit(:notification_email)
end end
def global_notification_setting_params
params.require(:global_notification_setting).permit(:level)
end
private
def update_notification_settings
return true unless global_notification_setting_params
current_user.global_notification_setting.update_attributes(global_notification_setting_params)
end
end end
...@@ -62,22 +62,14 @@ module NotificationsHelper ...@@ -62,22 +62,14 @@ module NotificationsHelper
end end
end end
def notification_level_radio_buttons # Identifier to trigger individually dropdowns and custom settings modals in the same view
html = "" def notifications_menu_identifier(type, notification_setting)
"#{type}-#{notification_setting.user_id}-#{notification_setting.source_id}-#{notification_setting.source_type}"
NotificationSetting.levels.each_key do |level|
level = level.to_sym
next if level == :global
html << content_tag(:div, class: "radio") do
content_tag(:label, { value: level }) do
radio_button_tag(:"global_notification_setting[level]", level, @global_notification_setting.level.to_sym == level) +
content_tag(:div, level.to_s.capitalize, class: "level-title") +
content_tag(:p, notification_description(level))
end
end
end end
html.html_safe # Create hidden field to send notification setting source to controller
def hidden_setting_source_input(notification_setting)
return unless notification_setting.source_type
hidden_field_tag "#{notification_setting.source_type.downcase}[id]", notification_setting.source_id
end end
end end
...@@ -159,7 +159,7 @@ class NotificationService ...@@ -159,7 +159,7 @@ class NotificationService
recipients = add_project_watchers(recipients, note.project) recipients = add_project_watchers(recipients, note.project)
# Merge project with custom notification # Merge project with custom notification
recipients = add_project_custom_notifications(recipients, note.project, :new_note) recipients = add_custom_notifications(recipients, note.project, :new_note)
# Reject users with Mention notification level, except those mentioned in _this_ note. # Reject users with Mention notification level, except those mentioned in _this_ note.
recipients = reject_mention_users(recipients - mentioned_users, note.project) recipients = reject_mention_users(recipients - mentioned_users, note.project)
...@@ -257,12 +257,20 @@ class NotificationService ...@@ -257,12 +257,20 @@ class NotificationService
protected protected
# Get project/group users with CUSTOM notification level # Get project/group users with CUSTOM notification level
def add_project_custom_notifications(recipients, project, action) def add_custom_notifications(recipients, project, action)
user_ids = [] user_ids = []
# Users with a notification setting on group or project
user_ids += notification_settings_for(project, :custom, action) user_ids += notification_settings_for(project, :custom, action)
user_ids += notification_settings_for(project.group, :custom, action) user_ids += notification_settings_for(project.group, :custom, action)
# Users with global level custom
users_with_project_level_global = notification_settings_for(project, :global)
users_with_group_level_global = notification_settings_for(project.group, :global)
global_users_ids = users_with_project_level_global.concat(users_with_group_level_global)
user_ids += users_with_global_level_custom(global_users_ids, action)
recipients.concat(User.find(user_ids)) recipients.concat(User.find(user_ids))
end end
...@@ -271,7 +279,7 @@ class NotificationService ...@@ -271,7 +279,7 @@ class NotificationService
project_members = notification_settings_for(project) project_members = notification_settings_for(project)
users_with_project_level_global = notification_settings_for(project, :global) users_with_project_level_global = notification_settings_for(project, :global)
users_with_group_level_global = notification_settings_for(project, :global) users_with_group_level_global = notification_settings_for(project.group, :global)
users = users_with_global_level_watch([users_with_project_level_global, users_with_group_level_global].flatten.uniq) users = users_with_global_level_watch([users_with_project_level_global, users_with_group_level_global].flatten.uniq)
users_with_project_setting = select_project_member_setting(project, users_with_project_level_global, users) users_with_project_setting = select_project_member_setting(project, users_with_project_level_global, users)
...@@ -293,11 +301,21 @@ class NotificationService ...@@ -293,11 +301,21 @@ class NotificationService
end end
def users_with_global_level_watch(ids) def users_with_global_level_watch(ids)
settings_with_global_level_of(:watch, ids).pluck(:user_id)
end
def users_with_global_level_custom(ids, action)
settings = settings_with_global_level_of(:custom, ids)
settings = settings.select { |setting| setting.events[action] }
settings.map(&:user_id)
end
def settings_with_global_level_of(level, ids)
NotificationSetting.where( NotificationSetting.where(
user_id: ids, user_id: ids,
source_type: nil, source_type: nil,
level: NotificationSetting.levels[:watch] level: NotificationSetting.levels[level]
).pluck(:user_id) )
end end
# Build a list of users based on project notifcation settings # Build a list of users based on project notifcation settings
...@@ -477,7 +495,7 @@ class NotificationService ...@@ -477,7 +495,7 @@ class NotificationService
recipients = target.participants(current_user) recipients = target.participants(current_user)
recipients = add_project_watchers(recipients, project) recipients = add_project_watchers(recipients, project)
recipients = add_project_custom_notifications(recipients, project, custom_action) recipients = add_custom_notifications(recipients, project, custom_action)
recipients = reject_mention_users(recipients, project) recipients = reject_mention_users(recipients, project)
recipients = recipients.uniq recipients = recipients.uniq
......
- if notification_setting
.dropdown.notification-dropdown.pull-right
- url = notification_setting.persisted? ? notification_setting_path(notification_setting) : notification_settings_path(notification_setting)
= form_for notification_setting, remote: true, html: { class: "inline", id: "notification-form" } do |f|
= hidden_setting_source_input(notification_setting)
= f.hidden_field :level, class: "notification_setting_level"
.js-notification-toggle-btns
.btn-group
- if notification_setting.level != "custom"
%button.dropdown-new.btn.btn-default.notifications-btn#notifications-button{ type: "button", data: { toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting) } }
= icon("bell", class: "js-notification-loading")
= notification_title(notification_setting.level)
= icon("caret-down")
- else
%button.dropdown-new.btn.btn-default.notifications-btn#notifications-button{ type: "button", data: { toggle: "modal", target: "#" + notifications_menu_identifier("modal", notification_setting) } }
= icon("bell", class: "js-notification-loading")
= notification_title(notification_setting.level)
%button.btn.btn-danger.dropdown-toggle{ data: { toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting) } }
%span.caret
.sr-only Toggle dropdown
= render "shared/notifications/notification_dropdown", notification_setting: notification_setting
= content_for :scripts_body do
= render "shared/notifications/custom_notifications", notification_setting: notification_setting
...@@ -9,5 +9,4 @@ ...@@ -9,5 +9,4 @@
= link_to group.name, group_path(group) = link_to group.name, group_path(group)
.pull-right .pull-right
= form_for [group, setting], remote: true, html: { class: 'update-notifications' } do |f| = render 'notifications/buttons/notifications', notification_setting: setting
= f.select :level, NotificationSetting.levels.keys, {}, class: 'form-control trigger-submit'
...@@ -9,5 +9,4 @@ ...@@ -9,5 +9,4 @@
= link_to_project(project) = link_to_project(project)
.pull-right .pull-right
= form_for [project.namespace.becomes(Namespace), project, setting], remote: true, html: { class: 'update-notifications' } do |f| = render 'notifications/buttons/notifications', notification_setting: setting
= f.select :level, NotificationSetting.levels.keys, {}, class: 'form-control trigger-submit'
...@@ -24,12 +24,12 @@ ...@@ -24,12 +24,12 @@
.form-group .form-group
= f.label :notification_email, class: "label-light" = f.label :notification_email, class: "label-light"
= f.select :notification_email, @user.all_emails, { include_blank: false }, class: "select2" = f.select :notification_email, @user.all_emails, { include_blank: false }, class: "select2"
.form-group
= f.label :notification_level, class: 'label-light'
= notification_level_radio_buttons
.prepend-top-default .form-group.pull-left
= f.submit 'Update settings', class: "btn btn-create" = render 'notifications/buttons/notifications', notification_setting: @global_notification_setting
.clearfix
%hr %hr
%h5 %h5
Groups (#{@group_notifications.count}) Groups (#{@group_notifications.count})
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
.project-repo-buttons.btn-group.project-right-buttons .project-repo-buttons.btn-group.project-right-buttons
= render "projects/buttons/download" = render "projects/buttons/download"
= render 'projects/buttons/dropdown' = render 'projects/buttons/dropdown'
= render 'projects/buttons/notifications' = render 'notifications/buttons/notifications', notification_setting: @notification_setting
:javascript :javascript
new Star(); new Star();
- if @notification_setting
.dropdown.notification-dropdown.pull-right
= form_for @notification_setting, url: namespace_project_notification_setting_path(@project.namespace.becomes(Namespace), @project), method: :patch, remote: true, html: { class: "inline", id: "notification-form" } do |f|
= f.hidden_field :level
.js-notification-toggle-btns
- if @notification_setting.level != "custom"
%button.dropdown-new.btn.btn-default.notifications-btn#notifications-button{ type: "button", data: { toggle: "dropdown", target: ".notification-dropdown" } }
= icon("bell", class: "js-notification-loading")
= notification_title(@notification_setting.level)
= icon("caret-down")
- else
.btn-group
%button.dropdown-new.btn.btn-default.notifications-btn#notifications-button{ type: "button", data: { toggle: "modal", target: "#custom-notifications-modal" } }
= icon("bell", class: "js-notification-loading")
= notification_title(@notification_setting.level)
%button.btn.btn-danger.dropdown-toggle{ data: { toggle: "dropdown", target: ".notification-dropdown" } }
%span.caret
.sr-only Toggle dropdown
= render "shared/projects/notification_dropdown"
= content_for :scripts_body do
= render "shared/projects/custom_notifications"
#custom-notifications-modal.modal.fade{ tabindex: "-1", role: "dialog", aria: { labelledby: "custom-notifications-title" } } .modal.fade{ tabindex: "-1", role: "dialog", id: notifications_menu_identifier("modal", notification_setting), aria: { labelledby: "custom-notifications-title" } }
.modal-dialog .modal-dialog
.modal-content .modal-content
.modal-header .modal-header
...@@ -6,10 +6,11 @@ ...@@ -6,10 +6,11 @@
%span{ aria: { hidden: "true" } } × %span{ aria: { hidden: "true" } } ×
%h4#custom-notifications-title.modal-title %h4#custom-notifications-title.modal-title
Custom notification events Custom notification events
.modal-body .modal-body
.container-fluid .container-fluid
= form_for @notification_setting, url: namespace_project_notification_setting_path(@project.namespace.becomes(Namespace), @project), method: :patch, html: { class: "custom-notifications-form" } do |f| = form_for notification_setting, html: { class: "custom-notifications-form" } do |f|
= f.hidden_field :level = hidden_setting_source_input(notification_setting)
.row .row
.col-lg-3 .col-lg-3
%h4.prepend-top-0 %h4.prepend-top-0
...@@ -20,7 +21,7 @@ ...@@ -20,7 +21,7 @@
.form-group .form-group
.checkbox{ class: ("prepend-top-0" if index == 0) } .checkbox{ class: ("prepend-top-0" if index == 0) }
%label{ for: "events_#{event}" } %label{ for: "events_#{event}" }
= check_box("notification_setting", event, {id: "events_#{event}", class: "js-custom-notification-event"}) = check_box("", event, { name: "notification_setting[#{event}]", class: "js-custom-notification-event", checked: notification_setting.events[event] })
%strong %strong
= event.to_s.humanize = event.to_s.humanize
......
%ul.dropdown-menu.dropdown-menu-no-wrap.dropdown-menu-align-right.dropdown-menu-selectable.dropdown-menu-large{ role: "menu", class: notifications_menu_identifier("dropdown", notification_setting) }
- NotificationSetting.levels.each_key do |level|
- next if level == "custom"
- next if level == "global" && notification_setting.source.nil?
= notification_list_item(level, notification_setting)
- unless notification_setting.custom?
%li.divider
%li
%a.update-notification{ href: "#", role: "button", data: { toggle: "modal", target: "#" + notifications_menu_identifier("modal", notification_setting), notification_level: "custom", notification_title: "Custom" } }
Custom
%ul.dropdown-menu.dropdown-menu-no-wrap.dropdown-menu-align-right.dropdown-menu-selectable.dropdown-menu-large{ role: "menu" }
- NotificationSetting.levels.each do |level|
- if level.first != "custom"
= notification_list_item(level.first, @notification_setting)
- if @notification_setting.level != "custom"
%li.divider
%li
%a.update-notification{ href: "#", role: "button", data: { toggle: "modal", target: "#custom-notifications-modal", notification_level: "custom", notification_title: "Custom" } }
Custom
...@@ -118,9 +118,17 @@ Rails.application.routes.draw do ...@@ -118,9 +118,17 @@ Rails.application.routes.draw do
end end
end end
#
# Spam reports # Spam reports
#
resources :abuse_reports, only: [:new, :create] resources :abuse_reports, only: [:new, :create]
#
# Notification settings
#
resources :notification_settings, only: [:create, :update]
# #
# Import # Import
# #
...@@ -416,7 +424,6 @@ Rails.application.routes.draw do ...@@ -416,7 +424,6 @@ Rails.application.routes.draw do
resource :avatar, only: [:destroy] resource :avatar, only: [:destroy]
resources :milestones, constraints: { id: /[^\/]+/ }, only: [:index, :show, :update, :new, :create] resources :milestones, constraints: { id: /[^\/]+/ }, only: [:index, :show, :update, :new, :create]
resource :notification_setting, only: [:update]
end end
end end
...@@ -648,7 +655,6 @@ Rails.application.routes.draw do ...@@ -648,7 +655,6 @@ Rails.application.routes.draw do
resources :forks, only: [:index, :new, :create] resources :forks, only: [:index, :new, :create]
resource :import, only: [:new, :create, :show] resource :import, only: [:new, :create, :show]
resource :notification_setting, only: [:update]
resources :refs, only: [] do resources :refs, only: [] do
collection do collection do
......
require 'spec_helper'
describe Groups::NotificationSettingsController do
let(:group) { create(:group) }
let(:user) { create(:user) }
describe '#update' do
context 'when not authorized' do
it 'redirects to sign in page' do
put :update,
group_id: group.to_param,
notification_setting: { level: :participating }
expect(response).to redirect_to(new_user_session_path)
end
end
context 'when authorized' do
before do
sign_in(user)
end
it 'returns success' do
put :update,
group_id: group.to_param,
notification_setting: { level: :participating }
expect(response.status).to eq 200
end
end
end
end
require 'spec_helper' require 'spec_helper'
describe Projects::NotificationSettingsController do describe NotificationSettingsController do
let(:project) { create(:empty_project) } let(:project) { create(:empty_project) }
let(:user) { create(:user) } let(:user) { create(:user) }
...@@ -8,12 +8,11 @@ describe Projects::NotificationSettingsController do ...@@ -8,12 +8,11 @@ describe Projects::NotificationSettingsController do
project.team << [user, :developer] project.team << [user, :developer]
end end
describe '#update' do describe '#create' do
context 'when not authorized' do context 'when not authorized' do
it 'redirects to sign in page' do it 'redirects to sign in page' do
put :update, post :create,
namespace_id: project.namespace.to_param, project: { id: project.id },
project_id: project.to_param,
notification_setting: { level: :participating } notification_setting: { level: :participating }
expect(response).to redirect_to(new_user_session_path) expect(response).to redirect_to(new_user_session_path)
...@@ -26,9 +25,8 @@ describe Projects::NotificationSettingsController do ...@@ -26,9 +25,8 @@ describe Projects::NotificationSettingsController do
end end
it 'returns success' do it 'returns success' do
put :update, post :create,
namespace_id: project.namespace.to_param, project: { id: project.id },
project_id: project.to_param,
notification_setting: { level: :participating } notification_setting: { level: :participating }
expect(response.status).to eq 200 expect(response.status).to eq 200
...@@ -44,9 +42,8 @@ describe Projects::NotificationSettingsController do ...@@ -44,9 +42,8 @@ describe Projects::NotificationSettingsController do
end end
it 'returns success' do it 'returns success' do
put :update, post :create,
namespace_id: project.namespace.to_param, project: { id: project.id },
project_id: project.to_param,
notification_setting: { level: :participating, events: custom_events } notification_setting: { level: :participating, events: custom_events }
expect(response.status).to eq 200 expect(response.status).to eq 200
...@@ -58,10 +55,67 @@ describe Projects::NotificationSettingsController do ...@@ -58,10 +55,67 @@ describe Projects::NotificationSettingsController do
let(:private_project) { create(:project, :private) } let(:private_project) { create(:project, :private) }
before { sign_in(user) } before { sign_in(user) }
it 'returns 404' do
post :create,
project: { id: private_project.id },
notification_setting: { level: :participating }
expect(response.status).to eq(404)
end
end
end
describe '#update' do
let(:notification_setting) { user.global_notification_setting }
context 'when not authorized' do
it 'redirects to sign in page' do
put :update,
id: notification_setting,
notification_setting: { level: :participating }
expect(response).to redirect_to(new_user_session_path)
end
end
context 'when authorized' do
before{ sign_in(user) }
it 'returns success' do
put :update,
id: notification_setting,
notification_setting: { level: :participating }
expect(response.status).to eq 200
end
context 'and setting custom notification setting' do
let(:custom_events) do
events = {}
NotificationSetting::EMAIL_EVENTS.each do |event|
events[event] = "true"
end
end
it 'returns success' do
put :update,
id: notification_setting,
notification_setting: { level: :participating, events: custom_events }
expect(response.status).to eq 200
end
end
end
context 'not authorized' do
let(:other_user) { create(:user) }
before { sign_in(other_user) }
it 'returns 404' do it 'returns 404' do
put :update, put :update,
namespace_id: private_project.namespace.to_param, id: notification_setting,
project_id: private_project.to_param,
notification_setting: { level: :participating } notification_setting: { level: :participating }
expect(response.status).to eq(404) expect(response.status).to eq(404)
......
...@@ -46,7 +46,8 @@ describe NotificationService, services: true do ...@@ -46,7 +46,8 @@ describe NotificationService, services: true do
project.team << [issue.assignee, :master] project.team << [issue.assignee, :master]
project.team << [note.author, :master] project.team << [note.author, :master]
create(:note_on_issue, noteable: issue, project_id: issue.project_id, note: '@subscribed_participant cc this guy') create(:note_on_issue, noteable: issue, project_id: issue.project_id, note: '@subscribed_participant cc this guy')
update_custom_notification(:new_note) update_custom_notification(:new_note, @u_guest_custom, project)
update_custom_notification(:new_note, @u_custom_global)
end end
describe :new_note do describe :new_note do
...@@ -54,7 +55,7 @@ describe NotificationService, services: true do ...@@ -54,7 +55,7 @@ describe NotificationService, services: true do
add_users_with_subscription(note.project, issue) add_users_with_subscription(note.project, issue)
# Ensure create SentNotification by noteable = issue 6 times, not noteable = note # Ensure create SentNotification by noteable = issue 6 times, not noteable = note
expect(SentNotification).to receive(:record).with(issue, any_args).exactly(7).times expect(SentNotification).to receive(:record).with(issue, any_args).exactly(8).times
ActionMailer::Base.deliveries.clear ActionMailer::Base.deliveries.clear
...@@ -63,6 +64,7 @@ describe NotificationService, services: true do ...@@ -63,6 +64,7 @@ describe NotificationService, services: true do
should_email(@u_watcher) should_email(@u_watcher)
should_email(note.noteable.author) should_email(note.noteable.author)
should_email(note.noteable.assignee) should_email(note.noteable.assignee)
should_email(@u_custom_global)
should_email(@u_mentioned) should_email(@u_mentioned)
should_email(@subscriber) should_email(@subscriber)
should_email(@watcher_and_subscriber) should_email(@watcher_and_subscriber)
...@@ -105,10 +107,12 @@ describe NotificationService, services: true do ...@@ -105,10 +107,12 @@ describe NotificationService, services: true do
before do before do
note.project.namespace_id = group.id note.project.namespace_id = group.id
note.project.group.add_user(@u_watcher, GroupMember::MASTER) note.project.group.add_user(@u_watcher, GroupMember::MASTER)
note.project.group.add_user(@u_custom_global, GroupMember::MASTER)
note.project.save note.project.save
@u_watcher.notification_settings_for(note.project).participating! @u_watcher.notification_settings_for(note.project).participating!
@u_watcher.notification_settings_for(note.project.group).global! @u_watcher.notification_settings_for(note.project.group).global!
update_custom_notification(:new_note, @u_custom_global)
ActionMailer::Base.deliveries.clear ActionMailer::Base.deliveries.clear
end end
...@@ -118,6 +122,7 @@ describe NotificationService, services: true do ...@@ -118,6 +122,7 @@ describe NotificationService, services: true do
should_email(note.noteable.author) should_email(note.noteable.author)
should_email(note.noteable.assignee) should_email(note.noteable.assignee)
should_email(@u_mentioned) should_email(@u_mentioned)
should_email(@u_custom_global)
should_not_email(@u_guest_custom) should_not_email(@u_guest_custom)
should_not_email(@u_guest_watcher) should_not_email(@u_guest_watcher)
should_not_email(@u_watcher) should_not_email(@u_watcher)
...@@ -138,6 +143,10 @@ describe NotificationService, services: true do ...@@ -138,6 +143,10 @@ describe NotificationService, services: true do
let(:admin) { create(:admin) } let(:admin) { create(:admin) }
let(:confidential_issue) { create(:issue, :confidential, project: project, author: author, assignee: assignee) } let(:confidential_issue) { create(:issue, :confidential, project: project, author: author, assignee: assignee) }
let(:note) { create(:note_on_issue, noteable: confidential_issue, project: project, note: "#{author.to_reference} #{assignee.to_reference} #{non_member.to_reference} #{member.to_reference} #{admin.to_reference}") } let(:note) { create(:note_on_issue, noteable: confidential_issue, project: project, note: "#{author.to_reference} #{assignee.to_reference} #{non_member.to_reference} #{member.to_reference} #{admin.to_reference}") }
let(:guest_watcher) { create_user_with_notification(:watch, "guest-watcher-confidential") }
before do
end
it 'filters out users that can not read the issue' do it 'filters out users that can not read the issue' do
project.team << [member, :developer] project.team << [member, :developer]
...@@ -149,6 +158,7 @@ describe NotificationService, services: true do ...@@ -149,6 +158,7 @@ describe NotificationService, services: true do
notification.new_note(note) notification.new_note(note)
should_not_email(non_member) should_not_email(non_member)
should_not_email(guest_watcher)
should_email(author) should_email(author)
should_email(assignee) should_email(assignee)
should_email(member) should_email(member)
...@@ -223,6 +233,9 @@ describe NotificationService, services: true do ...@@ -223,6 +233,9 @@ describe NotificationService, services: true do
should_email(member) should_email(member)
end end
# it emails custom global users on mention
should_email(@u_custom_global)
should_email(@u_guest_watcher) should_email(@u_guest_watcher)
should_email(note.noteable.author) should_email(note.noteable.author)
should_not_email(note.author) should_not_email(note.author)
...@@ -241,13 +254,15 @@ describe NotificationService, services: true do ...@@ -241,13 +254,15 @@ describe NotificationService, services: true do
build_team(note.project) build_team(note.project)
ActionMailer::Base.deliveries.clear ActionMailer::Base.deliveries.clear
allow_any_instance_of(Commit).to receive(:author).and_return(@u_committer) allow_any_instance_of(Commit).to receive(:author).and_return(@u_committer)
update_custom_notification(:new_note) update_custom_notification(:new_note, @u_guest_custom, project)
update_custom_notification(:new_note, @u_custom_global)
end end
describe '#new_note, #perform_enqueued_jobs' do describe '#new_note, #perform_enqueued_jobs' do
it do it do
notification.new_note(note) notification.new_note(note)
should_email(@u_guest_watcher) should_email(@u_guest_watcher)
should_email(@u_custom_global)
should_email(@u_guest_custom) should_email(@u_guest_custom)
should_email(@u_committer) should_email(@u_committer)
should_email(@u_watcher) should_email(@u_watcher)
...@@ -289,7 +304,8 @@ describe NotificationService, services: true do ...@@ -289,7 +304,8 @@ describe NotificationService, services: true do
build_team(issue.project) build_team(issue.project)
add_users_with_subscription(issue.project, issue) add_users_with_subscription(issue.project, issue)
ActionMailer::Base.deliveries.clear ActionMailer::Base.deliveries.clear
update_custom_notification(:new_issue) update_custom_notification(:new_issue, @u_guest_custom, project)
update_custom_notification(:new_issue, @u_custom_global)
end end
describe '#new_issue' do describe '#new_issue' do
...@@ -300,6 +316,7 @@ describe NotificationService, services: true do ...@@ -300,6 +316,7 @@ describe NotificationService, services: true do
should_email(@u_watcher) should_email(@u_watcher)
should_email(@u_guest_watcher) should_email(@u_guest_watcher)
should_email(@u_guest_custom) should_email(@u_guest_custom)
should_email(@u_custom_global)
should_email(@u_participant_mentioned) should_email(@u_participant_mentioned)
should_not_email(@u_mentioned) should_not_email(@u_mentioned)
should_not_email(@u_participating) should_not_email(@u_participating)
...@@ -345,6 +362,7 @@ describe NotificationService, services: true do ...@@ -345,6 +362,7 @@ describe NotificationService, services: true do
notification.new_issue(confidential_issue, @u_disabled) notification.new_issue(confidential_issue, @u_disabled)
should_not_email(@u_guest_watcher)
should_not_email(non_member) should_not_email(non_member)
should_not_email(author) should_not_email(author)
should_email(assignee) should_email(assignee)
...@@ -355,7 +373,10 @@ describe NotificationService, services: true do ...@@ -355,7 +373,10 @@ describe NotificationService, services: true do
end end
describe '#reassigned_issue' do describe '#reassigned_issue' do
before { update_custom_notification(:reassign_issue) } before do
update_custom_notification(:reassign_issue, @u_guest_custom, project)
update_custom_notification(:reassign_issue, @u_custom_global)
end
it 'emails new assignee' do it 'emails new assignee' do
notification.reassigned_issue(issue, @u_disabled) notification.reassigned_issue(issue, @u_disabled)
...@@ -364,6 +385,7 @@ describe NotificationService, services: true do ...@@ -364,6 +385,7 @@ describe NotificationService, services: true do
should_email(@u_watcher) should_email(@u_watcher)
should_email(@u_guest_watcher) should_email(@u_guest_watcher)
should_email(@u_guest_custom) should_email(@u_guest_custom)
should_email(@u_custom_global)
should_email(@u_participant_mentioned) should_email(@u_participant_mentioned)
should_email(@subscriber) should_email(@subscriber)
should_not_email(@unsubscriber) should_not_email(@unsubscriber)
...@@ -383,6 +405,7 @@ describe NotificationService, services: true do ...@@ -383,6 +405,7 @@ describe NotificationService, services: true do
should_email(@u_guest_custom) should_email(@u_guest_custom)
should_email(@u_participant_mentioned) should_email(@u_participant_mentioned)
should_email(@subscriber) should_email(@subscriber)
should_email(@u_custom_global)
should_not_email(@unsubscriber) should_not_email(@unsubscriber)
should_not_email(@u_participating) should_not_email(@u_participating)
should_not_email(@u_disabled) should_not_email(@u_disabled)
...@@ -400,6 +423,7 @@ describe NotificationService, services: true do ...@@ -400,6 +423,7 @@ describe NotificationService, services: true do
should_email(@u_guest_custom) should_email(@u_guest_custom)
should_email(@u_participant_mentioned) should_email(@u_participant_mentioned)
should_email(@subscriber) should_email(@subscriber)
should_email(@u_custom_global)
should_not_email(@unsubscriber) should_not_email(@unsubscriber)
should_not_email(@u_participating) should_not_email(@u_participating)
should_not_email(@u_disabled) should_not_email(@u_disabled)
...@@ -417,6 +441,7 @@ describe NotificationService, services: true do ...@@ -417,6 +441,7 @@ describe NotificationService, services: true do
should_email(@u_guest_custom) should_email(@u_guest_custom)
should_email(@u_participant_mentioned) should_email(@u_participant_mentioned)
should_email(@subscriber) should_email(@subscriber)
should_email(@u_custom_global)
should_not_email(@unsubscriber) should_not_email(@unsubscriber)
should_not_email(@u_participating) should_not_email(@u_participating)
should_not_email(@u_disabled) should_not_email(@u_disabled)
...@@ -433,6 +458,7 @@ describe NotificationService, services: true do ...@@ -433,6 +458,7 @@ describe NotificationService, services: true do
should_email(@u_guest_custom) should_email(@u_guest_custom)
should_email(@u_participant_mentioned) should_email(@u_participant_mentioned)
should_email(@subscriber) should_email(@subscriber)
should_email(@u_custom_global)
should_not_email(issue.assignee) should_not_email(issue.assignee)
should_not_email(@unsubscriber) should_not_email(@unsubscriber)
should_not_email(@u_participating) should_not_email(@u_participating)
...@@ -531,7 +557,10 @@ describe NotificationService, services: true do ...@@ -531,7 +557,10 @@ describe NotificationService, services: true do
end end
describe '#close_issue' do describe '#close_issue' do
before { update_custom_notification(:close_issue) } before do
update_custom_notification(:close_issue, @u_guest_custom, project)
update_custom_notification(:close_issue, @u_custom_global)
end
it 'should sent email to issue assignee and issue author' do it 'should sent email to issue assignee and issue author' do
notification.close_issue(issue, @u_disabled) notification.close_issue(issue, @u_disabled)
...@@ -541,6 +570,7 @@ describe NotificationService, services: true do ...@@ -541,6 +570,7 @@ describe NotificationService, services: true do
should_email(@u_watcher) should_email(@u_watcher)
should_email(@u_guest_watcher) should_email(@u_guest_watcher)
should_email(@u_guest_custom) should_email(@u_guest_custom)
should_email(@u_custom_global)
should_email(@u_participant_mentioned) should_email(@u_participant_mentioned)
should_email(@subscriber) should_email(@subscriber)
should_email(@watcher_and_subscriber) should_email(@watcher_and_subscriber)
...@@ -580,7 +610,10 @@ describe NotificationService, services: true do ...@@ -580,7 +610,10 @@ describe NotificationService, services: true do
end end
describe '#reopen_issue' do describe '#reopen_issue' do
before { update_custom_notification(:reopen_issue) } before do
update_custom_notification(:reopen_issue, @u_guest_custom, project)
update_custom_notification(:reopen_issue, @u_custom_global)
end
it 'should send email to issue assignee and issue author' do it 'should send email to issue assignee and issue author' do
notification.reopen_issue(issue, @u_disabled) notification.reopen_issue(issue, @u_disabled)
...@@ -590,6 +623,7 @@ describe NotificationService, services: true do ...@@ -590,6 +623,7 @@ describe NotificationService, services: true do
should_email(@u_watcher) should_email(@u_watcher)
should_email(@u_guest_watcher) should_email(@u_guest_watcher)
should_email(@u_guest_custom) should_email(@u_guest_custom)
should_email(@u_custom_global)
should_email(@u_participant_mentioned) should_email(@u_participant_mentioned)
should_email(@subscriber) should_email(@subscriber)
should_email(@watcher_and_subscriber) should_email(@watcher_and_subscriber)
...@@ -639,7 +673,11 @@ describe NotificationService, services: true do ...@@ -639,7 +673,11 @@ describe NotificationService, services: true do
end end
describe '#new_merge_request' do describe '#new_merge_request' do
before { update_custom_notification(:new_merge_request) } before do
update_custom_notification(:new_merge_request, @u_guest_custom, project)
update_custom_notification(:new_merge_request, @u_custom_global)
end
it do it do
notification.new_merge_request(merge_request, @u_disabled) notification.new_merge_request(merge_request, @u_disabled)
...@@ -650,6 +688,7 @@ describe NotificationService, services: true do ...@@ -650,6 +688,7 @@ describe NotificationService, services: true do
should_email(@u_participant_mentioned) should_email(@u_participant_mentioned)
should_email(@u_guest_watcher) should_email(@u_guest_watcher)
should_email(@u_guest_custom) should_email(@u_guest_custom)
should_email(@u_custom_global)
should_not_email(@u_participating) should_not_email(@u_participating)
should_not_email(@u_disabled) should_not_email(@u_disabled)
should_not_email(@u_lazy_participant) should_not_email(@u_lazy_participant)
...@@ -696,7 +735,10 @@ describe NotificationService, services: true do ...@@ -696,7 +735,10 @@ describe NotificationService, services: true do
end end
describe '#reassigned_merge_request' do describe '#reassigned_merge_request' do
before { update_custom_notification(:reassign_merge_request) } before do
update_custom_notification(:reassign_merge_request, @u_guest_custom, project)
update_custom_notification(:reassign_merge_request, @u_custom_global)
end
it do it do
notification.reassigned_merge_request(merge_request, merge_request.author) notification.reassigned_merge_request(merge_request, merge_request.author)
...@@ -708,6 +750,7 @@ describe NotificationService, services: true do ...@@ -708,6 +750,7 @@ describe NotificationService, services: true do
should_email(@watcher_and_subscriber) should_email(@watcher_and_subscriber)
should_email(@u_guest_watcher) should_email(@u_guest_watcher)
should_email(@u_guest_custom) should_email(@u_guest_custom)
should_email(@u_custom_global)
should_not_email(@unsubscriber) should_not_email(@unsubscriber)
should_not_email(@u_participating) should_not_email(@u_participating)
should_not_email(@u_disabled) should_not_email(@u_disabled)
...@@ -775,7 +818,10 @@ describe NotificationService, services: true do ...@@ -775,7 +818,10 @@ describe NotificationService, services: true do
end end
describe '#closed_merge_request' do describe '#closed_merge_request' do
before { update_custom_notification(:close_merge_request) } before do
update_custom_notification(:close_merge_request, @u_guest_custom, project)
update_custom_notification(:close_merge_request, @u_custom_global)
end
it do it do
notification.close_mr(merge_request, @u_disabled) notification.close_mr(merge_request, @u_disabled)
...@@ -784,6 +830,7 @@ describe NotificationService, services: true do ...@@ -784,6 +830,7 @@ describe NotificationService, services: true do
should_email(@u_watcher) should_email(@u_watcher)
should_email(@u_guest_watcher) should_email(@u_guest_watcher)
should_email(@u_guest_custom) should_email(@u_guest_custom)
should_email(@u_custom_global)
should_email(@u_participant_mentioned) should_email(@u_participant_mentioned)
should_email(@subscriber) should_email(@subscriber)
should_email(@watcher_and_subscriber) should_email(@watcher_and_subscriber)
...@@ -824,7 +871,10 @@ describe NotificationService, services: true do ...@@ -824,7 +871,10 @@ describe NotificationService, services: true do
end end
describe '#merged_merge_request' do describe '#merged_merge_request' do
before { update_custom_notification(:merge_merge_request) } before do
update_custom_notification(:merge_merge_request, @u_guest_custom, project)
update_custom_notification(:merge_merge_request, @u_custom_global)
end
it do it do
notification.merge_mr(merge_request, @u_disabled) notification.merge_mr(merge_request, @u_disabled)
...@@ -835,6 +885,7 @@ describe NotificationService, services: true do ...@@ -835,6 +885,7 @@ describe NotificationService, services: true do
should_email(@subscriber) should_email(@subscriber)
should_email(@watcher_and_subscriber) should_email(@watcher_and_subscriber)
should_email(@u_guest_watcher) should_email(@u_guest_watcher)
should_email(@u_custom_global)
should_email(@u_guest_custom) should_email(@u_guest_custom)
should_not_email(@unsubscriber) should_not_email(@unsubscriber)
should_not_email(@u_participating) should_not_email(@u_participating)
...@@ -873,7 +924,10 @@ describe NotificationService, services: true do ...@@ -873,7 +924,10 @@ describe NotificationService, services: true do
end end
describe '#reopen_merge_request' do describe '#reopen_merge_request' do
before { update_custom_notification(:reopen_merge_request) } before do
update_custom_notification(:reopen_merge_request, @u_guest_custom, project)
update_custom_notification(:reopen_merge_request, @u_custom_global)
end
it do it do
notification.reopen_mr(merge_request, @u_disabled) notification.reopen_mr(merge_request, @u_disabled)
...@@ -885,6 +939,7 @@ describe NotificationService, services: true do ...@@ -885,6 +939,7 @@ describe NotificationService, services: true do
should_email(@watcher_and_subscriber) should_email(@watcher_and_subscriber)
should_email(@u_guest_watcher) should_email(@u_guest_watcher)
should_email(@u_guest_custom) should_email(@u_guest_custom)
should_email(@u_custom_global)
should_not_email(@unsubscriber) should_not_email(@unsubscriber)
should_not_email(@u_participating) should_not_email(@u_participating)
should_not_email(@u_disabled) should_not_email(@u_disabled)
...@@ -937,6 +992,7 @@ describe NotificationService, services: true do ...@@ -937,6 +992,7 @@ describe NotificationService, services: true do
should_email(@u_watcher) should_email(@u_watcher)
should_email(@u_participating) should_email(@u_participating)
should_email(@u_lazy_participant) should_email(@u_lazy_participant)
should_email(@u_custom_global)
should_not_email(@u_guest_watcher) should_not_email(@u_guest_watcher)
should_not_email(@u_guest_custom) should_not_email(@u_guest_custom)
should_not_email(@u_disabled) should_not_email(@u_disabled)
...@@ -953,6 +1009,7 @@ describe NotificationService, services: true do ...@@ -953,6 +1009,7 @@ describe NotificationService, services: true do
@u_committer = create(:user, username: 'committer') @u_committer = create(:user, username: 'committer')
@u_not_mentioned = create_global_setting_for(create(:user, username: 'regular'), :participating) @u_not_mentioned = create_global_setting_for(create(:user, username: 'regular'), :participating)
@u_outsider_mentioned = create(:user, username: 'outsider') @u_outsider_mentioned = create(:user, username: 'outsider')
@u_custom_global = create_global_setting_for(create(:user, username: 'custom_global'), :custom)
# User to be participant by default # User to be participant by default
# This user does not contain any record in notification settings table # This user does not contain any record in notification settings table
...@@ -970,6 +1027,7 @@ describe NotificationService, services: true do ...@@ -970,6 +1027,7 @@ describe NotificationService, services: true do
project.team << [@u_committer, :master] project.team << [@u_committer, :master]
project.team << [@u_not_mentioned, :master] project.team << [@u_not_mentioned, :master]
project.team << [@u_lazy_participant, :master] project.team << [@u_lazy_participant, :master]
project.team << [@u_custom_global, :master]
end end
def create_global_setting_for(user, level) def create_global_setting_for(user, level)
...@@ -989,8 +1047,10 @@ describe NotificationService, services: true do ...@@ -989,8 +1047,10 @@ describe NotificationService, services: true do
user user
end end
def update_custom_notification(event) # Create custom notifications
setting = @u_guest_custom.notification_settings_for(project) # When resource is nil it means global notification
def update_custom_notification(event, user, resource = nil)
setting = user.notification_settings_for(resource)
setting.events[event] = true setting.events[event] = true
setting.save setting.save
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment