save each notification setting with ajax on change
This commit is contained in:
parent
3c3baf8f6d
commit
25856a47e5
|
@ -20,3 +20,16 @@
|
|||
border: 1px solid #ddd;
|
||||
}
|
||||
}
|
||||
|
||||
.save-status-fixed {
|
||||
position: fixed;
|
||||
left: 20px;
|
||||
bottom: 50px;
|
||||
}
|
||||
|
||||
.update-notifications {
|
||||
margin-bottom: 0;
|
||||
label {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,11 +3,19 @@ class NotificationsController < ApplicationController
|
|||
|
||||
def show
|
||||
@notification = current_user.notification
|
||||
@projects = current_user.authorized_projects
|
||||
@users_projects = current_user.users_projects
|
||||
end
|
||||
|
||||
def update
|
||||
current_user.notification_level = params[:notification_level]
|
||||
@saved = current_user.save
|
||||
type = params[:notification_type]
|
||||
|
||||
@saved = if type == 'global'
|
||||
current_user.notification_level = params[:notification_level]
|
||||
current_user.save
|
||||
else
|
||||
users_project = current_user.users_projects.find(params[:notification_id])
|
||||
users_project.notification_level = params[:notification_level]
|
||||
users_project.save
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,26 +5,35 @@ class Notification
|
|||
N_DISABLED = 0
|
||||
N_PARTICIPATING = 1
|
||||
N_WATCH = 2
|
||||
N_GLOBAL = 3
|
||||
|
||||
attr_accessor :user
|
||||
attr_accessor :target
|
||||
|
||||
def self.notification_levels
|
||||
[N_DISABLED, N_PARTICIPATING, N_WATCH]
|
||||
end
|
||||
|
||||
def initialize(user)
|
||||
@user = user
|
||||
def self.project_notification_levels
|
||||
[N_DISABLED, N_PARTICIPATING, N_WATCH, N_GLOBAL]
|
||||
end
|
||||
|
||||
def initialize(target)
|
||||
@target = target
|
||||
end
|
||||
|
||||
def disabled?
|
||||
user.notification_level == N_DISABLED
|
||||
target.notification_level == N_DISABLED
|
||||
end
|
||||
|
||||
def participating?
|
||||
user.notification_level == N_PARTICIPATING
|
||||
target.notification_level == N_PARTICIPATING
|
||||
end
|
||||
|
||||
def watch?
|
||||
user.notification_level == N_WATCH
|
||||
target.notification_level == N_WATCH
|
||||
end
|
||||
|
||||
def global?
|
||||
target.notification_level == N_GLOBAL
|
||||
end
|
||||
end
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
# issues_tracker :string(255) default("gitlab"), not null
|
||||
# issues_tracker_id :string(255)
|
||||
# snippets_enabled :boolean default(TRUE), not null
|
||||
# last_activity_at :datetime
|
||||
#
|
||||
|
||||
require "grit"
|
||||
|
|
|
@ -2,12 +2,13 @@
|
|||
#
|
||||
# Table name: users_projects
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# user_id :integer not null
|
||||
# project_id :integer not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# project_access :integer default(0), not null
|
||||
# id :integer not null, primary key
|
||||
# user_id :integer not null
|
||||
# project_id :integer not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# project_access :integer default(0), not null
|
||||
# notification_level :integer default(3), not null
|
||||
#
|
||||
|
||||
class UsersProject < ActiveRecord::Base
|
||||
|
@ -29,6 +30,7 @@ class UsersProject < ActiveRecord::Base
|
|||
validates :user_id, uniqueness: { scope: [:project_id], message: "already exists in project" }
|
||||
validates :project_access, inclusion: { in: [GUEST, REPORTER, DEVELOPER, MASTER] }, presence: true
|
||||
validates :project, presence: true
|
||||
validates :notification_level, inclusion: { in: Notification.project_notification_levels }, presence: true
|
||||
|
||||
delegate :name, :username, :email, to: :user, prefix: true
|
||||
|
||||
|
@ -134,4 +136,8 @@ class UsersProject < ActiveRecord::Base
|
|||
def skip_git?
|
||||
!!@skip_git
|
||||
end
|
||||
|
||||
def notification
|
||||
@notification ||= Notification.new(self)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -80,7 +80,7 @@ class NotificationService
|
|||
# * project team members with notification level higher then Participating
|
||||
#
|
||||
def merge_mr(merge_request)
|
||||
recipients = reject_muted_users([merge_request.author, merge_request.assignee])
|
||||
recipients = reject_muted_users([merge_request.author, merge_request.assignee], merge_request.project)
|
||||
recipients = recipients.concat(project_watchers(merge_request.project)).uniq
|
||||
|
||||
recipients.each do |recipient|
|
||||
|
@ -122,7 +122,7 @@ class NotificationService
|
|||
recipients = recipients.concat(project_watchers(note.project)).compact.uniq
|
||||
|
||||
# Reject mutes users
|
||||
recipients = reject_muted_users(recipients)
|
||||
recipients = reject_muted_users(recipients, note.project)
|
||||
|
||||
# Reject author
|
||||
recipients.delete(note.author)
|
||||
|
@ -147,19 +147,41 @@ class NotificationService
|
|||
|
||||
# Get project users with WATCH notification level
|
||||
def project_watchers(project)
|
||||
project.users.where(notification_level: Notification::N_WATCH)
|
||||
|
||||
# Get project notification settings since it has higher priority
|
||||
user_ids = project.users_projects.where(notification_level: Notification::N_WATCH).pluck(:user_id)
|
||||
project_watchers = User.where(id: user_ids)
|
||||
|
||||
# next collect users who use global settings with watch state
|
||||
user_ids = project.users_projects.where(notification_level: Notification::N_GLOBAL).pluck(:user_id)
|
||||
project_watchers += User.where(id: user_ids, notification_level: Notification::N_WATCH)
|
||||
|
||||
project_watchers.uniq
|
||||
end
|
||||
|
||||
# Remove users with disabled notifications from array
|
||||
# Also remove duplications and nil recipients
|
||||
def reject_muted_users(users)
|
||||
users.compact.uniq.reject do |user|
|
||||
user.notification.disabled?
|
||||
def reject_muted_users(users, project = nil)
|
||||
users = users.compact.uniq
|
||||
|
||||
users.reject do |user|
|
||||
next user.notification.disabled? unless project
|
||||
|
||||
tm = project.users_projects.find_by_user_id(user.id)
|
||||
|
||||
# reject users who globally disabled notification and has no membership
|
||||
next user.notification.disabled? unless tm
|
||||
|
||||
# reject users who disabled notification in project
|
||||
next true if tm.notification.disabled?
|
||||
|
||||
# reject users who have N_GLOBAL in project and disabled in global settings
|
||||
tm.notification.global? && user.notification.disabled?
|
||||
end
|
||||
end
|
||||
|
||||
def new_resource_email(target, method)
|
||||
recipients = reject_muted_users([target.assignee])
|
||||
recipients = reject_muted_users([target.assignee], target.project)
|
||||
recipients = recipients.concat(project_watchers(target.project)).uniq
|
||||
recipients.delete(target.author)
|
||||
|
||||
|
@ -169,7 +191,7 @@ class NotificationService
|
|||
end
|
||||
|
||||
def close_resource_email(target, current_user, method)
|
||||
recipients = reject_muted_users([target.author, target.assignee])
|
||||
recipients = reject_muted_users([target.author, target.assignee], target.project)
|
||||
recipients = recipients.concat(project_watchers(target.project)).uniq
|
||||
recipients.delete(current_user)
|
||||
|
||||
|
@ -185,7 +207,7 @@ class NotificationService
|
|||
recipients = recipients.concat(project_watchers(target.project))
|
||||
|
||||
# reject users with disabled notifications
|
||||
recipients = reject_muted_users(recipients)
|
||||
recipients = reject_muted_users(recipients, target.project)
|
||||
|
||||
# Reject me from recipients if I reassign an item
|
||||
recipients.delete(current_user)
|
||||
|
|
|
@ -13,56 +13,65 @@
|
|||
– You will receive all notifications from projects in which you participate
|
||||
%hr
|
||||
|
||||
= form_tag profile_notifications_path, method: :put, remote: true, class: 'update-notifications' do
|
||||
%ul.well-list
|
||||
.row
|
||||
.span4
|
||||
%h5 Global
|
||||
.span7
|
||||
= form_tag profile_notifications_path, method: :put, remote: true, class: 'update-notifications' do
|
||||
= hidden_field_tag :notification_type, 'global'
|
||||
|
||||
= label_tag do
|
||||
= radio_button_tag :notification_level, Notification::N_DISABLED, @notification.disabled?, class: 'trigger-submit'
|
||||
%span Disabled
|
||||
|
||||
= label_tag do
|
||||
= radio_button_tag :notification_level, Notification::N_PARTICIPATING, @notification.participating?, class: 'trigger-submit'
|
||||
%span Participating
|
||||
|
||||
= label_tag do
|
||||
= radio_button_tag :notification_level, Notification::N_WATCH, @notification.watch?, class: 'trigger-submit'
|
||||
%span Watch
|
||||
|
||||
%hr
|
||||
= link_to '#', class: 'js-toggle-visibility-link' do
|
||||
%h6.btn.btn-tiny
|
||||
%i.icon-chevron-down
|
||||
%span Per project notifications settings
|
||||
|
||||
%ul.well-list.js-toggle-visibility-container.hide
|
||||
- @users_projects.each do |users_project|
|
||||
- notification = Notification.new(users_project)
|
||||
%li
|
||||
.row
|
||||
.span4
|
||||
%h5 Global
|
||||
%span
|
||||
= link_to_project(users_project.project)
|
||||
.span7
|
||||
= label_tag do
|
||||
= radio_button_tag :notification_level, Notification::N_DISABLED, @notification.disabled?
|
||||
%span Disabled
|
||||
= form_tag profile_notifications_path, method: :put, remote: true, class: 'update-notifications' do
|
||||
= hidden_field_tag :notification_type, 'project', id: dom_id(users_project, 'notification_type')
|
||||
= hidden_field_tag :notification_id, users_project.id, id: dom_id(users_project, 'notification_id')
|
||||
|
||||
= label_tag do
|
||||
= radio_button_tag :notification_level, Notification::N_PARTICIPATING, @notification.participating?
|
||||
%span Participating
|
||||
|
||||
= label_tag do
|
||||
= radio_button_tag :notification_level, Notification::N_WATCH, @notification.watch?
|
||||
%span Watch
|
||||
|
||||
|
||||
= link_to '#', class: 'js-toggle-visibility-link' do
|
||||
%h6.btn.btn-tiny
|
||||
%i.icon-chevron-down
|
||||
%span Per project notifications settings
|
||||
%ul.well-list.js-toggle-visibility-container.hide
|
||||
- @projects.each do |project|
|
||||
%li
|
||||
.row
|
||||
.span4
|
||||
%span
|
||||
= project.name_with_namespace
|
||||
.span7
|
||||
= label_tag do
|
||||
= radio_button_tag :"notification_level[#{project.id}]", Notification::N_DISABLED, @notification.disabled?, disabled: true
|
||||
= radio_button_tag :notification_level, Notification::N_GLOBAL, notification.global?, id: dom_id(users_project, 'notification_level'), class: 'trigger-submit'
|
||||
%span Use global settings
|
||||
|
||||
= label_tag do
|
||||
= radio_button_tag :notification_level, Notification::N_DISABLED, notification.disabled?, id: dom_id(users_project, 'notification_level'), class: 'trigger-submit'
|
||||
%span Disabled
|
||||
|
||||
= label_tag do
|
||||
= radio_button_tag :"notification_level[#{project.id}]", Notification::N_PARTICIPATING, @notification.participating?, disabled: true
|
||||
= radio_button_tag :notification_level, Notification::N_PARTICIPATING, notification.participating?, id: dom_id(users_project, 'notification_level'), class: 'trigger-submit'
|
||||
%span Participating
|
||||
|
||||
= label_tag do
|
||||
= radio_button_tag :"notification_level[#{project.id}]", Notification::N_WATCH, @notification.watch?, disabled: true
|
||||
= radio_button_tag :notification_level, Notification::N_WATCH, notification.watch?, id: dom_id(users_project, 'notification_level'), class: 'trigger-submit'
|
||||
%span Watch
|
||||
|
||||
|
||||
.form-actions
|
||||
= submit_tag 'Save', class: 'btn btn-save'
|
||||
%span.update-success.cgreen.hide
|
||||
%i.icon-ok
|
||||
Saved
|
||||
%span.update-failed.cred.hide
|
||||
%i.icon-remove
|
||||
Failed
|
||||
.save-status-fixed
|
||||
%span.update-success.cgreen.hide
|
||||
%i.icon-ok
|
||||
Saved
|
||||
%span.update-failed.cred.hide
|
||||
%i.icon-remove
|
||||
Failed
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
- if @saved
|
||||
:plain
|
||||
$('.update-notifications .update-success').showAndHide();
|
||||
$('.save-status-fixed .update-success').showAndHide();
|
||||
- else
|
||||
:plain
|
||||
$('.update-notifications .update-failed').showAndHide();
|
||||
|
||||
$('.save-status-fixed .update-failed').showAndHide();
|
||||
|
|
15
db/schema.rb
15
db/schema.rb
|
@ -11,7 +11,7 @@
|
|||
#
|
||||
# It's strongly recommended to check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(:version => 20130325173941) do
|
||||
ActiveRecord::Schema.define(:version => 20130404164628) do
|
||||
|
||||
create_table "events", :force => true do |t|
|
||||
t.string "target_type"
|
||||
|
@ -156,9 +156,11 @@ ActiveRecord::Schema.define(:version => 20130325173941) do
|
|||
t.string "issues_tracker", :default => "gitlab", :null => false
|
||||
t.string "issues_tracker_id"
|
||||
t.boolean "snippets_enabled", :default => true, :null => false
|
||||
t.datetime "last_activity_at"
|
||||
end
|
||||
|
||||
add_index "projects", ["creator_id"], :name => "index_projects_on_owner_id"
|
||||
add_index "projects", ["last_activity_at"], :name => "index_projects_on_last_activity_at"
|
||||
add_index "projects", ["namespace_id"], :name => "index_projects_on_namespace_id"
|
||||
|
||||
create_table "protected_branches", :force => true do |t|
|
||||
|
@ -281,11 +283,12 @@ ActiveRecord::Schema.define(:version => 20130325173941) do
|
|||
add_index "users", ["username"], :name => "index_users_on_username"
|
||||
|
||||
create_table "users_projects", :force => true do |t|
|
||||
t.integer "user_id", :null => false
|
||||
t.integer "project_id", :null => false
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
t.integer "project_access", :default => 0, :null => false
|
||||
t.integer "user_id", :null => false
|
||||
t.integer "project_id", :null => false
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
t.integer "project_access", :default => 0, :null => false
|
||||
t.integer "notification_level", :default => 3, :null => false
|
||||
end
|
||||
|
||||
add_index "users_projects", ["project_access"], :name => "index_users_projects_on_project_access"
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
# issues_tracker :string(255) default("gitlab"), not null
|
||||
# issues_tracker_id :string(255)
|
||||
# snippets_enabled :boolean default(TRUE), not null
|
||||
# last_activity_at :datetime
|
||||
#
|
||||
|
||||
require 'spec_helper'
|
||||
|
|
|
@ -2,12 +2,13 @@
|
|||
#
|
||||
# Table name: users_projects
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# user_id :integer not null
|
||||
# project_id :integer not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# project_access :integer default(0), not null
|
||||
# id :integer not null, primary key
|
||||
# user_id :integer not null
|
||||
# project_id :integer not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# project_access :integer default(0), not null
|
||||
# notification_level :integer default(3), not null
|
||||
#
|
||||
|
||||
require 'spec_helper'
|
||||
|
|
Loading…
Reference in New Issue