Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>2013-04-04 23:11:51 +0400
committerDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>2013-04-04 23:11:51 +0400
commit25856a47e5a757e88a33218cc51367f6171db1c4 (patch)
treebe29c3ec4d3cdfcc0ce7913834f434b9dda8ed4a
parent3c3baf8f6d7799039cf16db044c9873f79137a49 (diff)
save each notification setting with ajax on change
-rw-r--r--app/assets/stylesheets/sections/profile.scss13
-rw-r--r--app/controllers/notifications_controller.rb14
-rw-r--r--app/models/notification.rb21
-rw-r--r--app/models/project.rb1
-rw-r--r--app/models/users_project.rb18
-rw-r--r--app/services/notification_service.rb40
-rw-r--r--app/views/notifications/show.html.haml83
-rw-r--r--app/views/notifications/update.js.haml5
-rw-r--r--db/schema.rb15
-rw-r--r--spec/models/project_spec.rb1
-rw-r--r--spec/models/users_project_spec.rb13
11 files changed, 148 insertions, 76 deletions
diff --git a/app/assets/stylesheets/sections/profile.scss b/app/assets/stylesheets/sections/profile.scss
index 607daf7a97e..c34cd23a9c9 100644
--- a/app/assets/stylesheets/sections/profile.scss
+++ b/app/assets/stylesheets/sections/profile.scss
@@ -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;
+ }
+}
diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb
index e44e0aa845e..4aa3172912f 100644
--- a/app/controllers/notifications_controller.rb
+++ b/app/controllers/notifications_controller.rb
@@ -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
diff --git a/app/models/notification.rb b/app/models/notification.rb
index bfd1e2cff56..ff6a18d6a51 100644
--- a/app/models/notification.rb
+++ b/app/models/notification.rb
@@ -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
diff --git a/app/models/project.rb b/app/models/project.rb
index 0263ffefdf0..53b318da66f 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -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"
diff --git a/app/models/users_project.rb b/app/models/users_project.rb
index c32edf38025..935ecede42c 100644
--- a/app/models/users_project.rb
+++ b/app/models/users_project.rb
@@ -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
diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb
index f8779fd5c2d..4b3c982c189 100644
--- a/app/services/notification_service.rb
+++ b/app/services/notification_service.rb
@@ -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)
diff --git a/app/views/notifications/show.html.haml b/app/views/notifications/show.html.haml
index d8ab93b8d1f..38e492f2d1b 100644
--- a/app/views/notifications/show.html.haml
+++ b/app/views/notifications/show.html.haml
@@ -13,56 +13,65 @@
&ndash; 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
-
- = 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
+ = 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_GLOBAL, notification.global?, id: dom_id(users_project, 'notification_level'), class: 'trigger-submit'
+ %span Use global settings
- = 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_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
diff --git a/app/views/notifications/update.js.haml b/app/views/notifications/update.js.haml
index 4468004a5c2..88e74d50671 100644
--- a/app/views/notifications/update.js.haml
+++ b/app/views/notifications/update.js.haml
@@ -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();
diff --git a/db/schema.rb b/db/schema.rb
index 3c8b9eaee43..0f7827a736e 100644
--- a/db/schema.rb
+++ b/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"
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index cbc7f278c2a..3ecf69795e3 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -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'
diff --git a/spec/models/users_project_spec.rb b/spec/models/users_project_spec.rb
index e8f5b647ce0..e289a592b03 100644
--- a/spec/models/users_project_spec.rb
+++ b/spec/models/users_project_spec.rb
@@ -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'