Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
25856a47
Commit
25856a47
authored
Apr 04, 2013
by
Dmitriy Zaporozhets
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
save each notification setting with ajax on change
parent
3c3baf8f
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
148 additions
and
76 deletions
+148
-76
app/assets/stylesheets/sections/profile.scss
app/assets/stylesheets/sections/profile.scss
+13
-0
app/controllers/notifications_controller.rb
app/controllers/notifications_controller.rb
+11
-3
app/models/notification.rb
app/models/notification.rb
+15
-6
app/models/project.rb
app/models/project.rb
+1
-0
app/models/users_project.rb
app/models/users_project.rb
+12
-6
app/services/notification_service.rb
app/services/notification_service.rb
+31
-9
app/views/notifications/show.html.haml
app/views/notifications/show.html.haml
+46
-37
app/views/notifications/update.js.haml
app/views/notifications/update.js.haml
+2
-3
db/schema.rb
db/schema.rb
+9
-6
spec/models/project_spec.rb
spec/models/project_spec.rb
+1
-0
spec/models/users_project_spec.rb
spec/models/users_project_spec.rb
+7
-6
No files found.
app/assets/stylesheets/sections/profile.scss
View file @
25856a47
...
@@ -20,3 +20,16 @@
...
@@ -20,3 +20,16 @@
border
:
1px
solid
#ddd
;
border
:
1px
solid
#ddd
;
}
}
}
}
.save-status-fixed
{
position
:
fixed
;
left
:
20px
;
bottom
:
50px
;
}
.update-notifications
{
margin-bottom
:
0
;
label
{
margin-bottom
:
0
;
}
}
app/controllers/notifications_controller.rb
View file @
25856a47
...
@@ -3,11 +3,19 @@ class NotificationsController < ApplicationController
...
@@ -3,11 +3,19 @@ class NotificationsController < ApplicationController
def
show
def
show
@notification
=
current_user
.
notification
@notification
=
current_user
.
notification
@
projects
=
current_user
.
authorized
_projects
@
users_projects
=
current_user
.
users
_projects
end
end
def
update
def
update
current_user
.
notification_level
=
params
[
:notification_level
]
type
=
params
[
:notification_type
]
@saved
=
current_user
.
save
@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
end
end
app/models/notification.rb
View file @
25856a47
...
@@ -5,26 +5,35 @@ class Notification
...
@@ -5,26 +5,35 @@ class Notification
N_DISABLED
=
0
N_DISABLED
=
0
N_PARTICIPATING
=
1
N_PARTICIPATING
=
1
N_WATCH
=
2
N_WATCH
=
2
N_GLOBAL
=
3
attr_accessor
:
user
attr_accessor
:
target
def
self
.
notification_levels
def
self
.
notification_levels
[
N_DISABLED
,
N_PARTICIPATING
,
N_WATCH
]
[
N_DISABLED
,
N_PARTICIPATING
,
N_WATCH
]
end
end
def
initialize
(
user
)
def
self
.
project_notification_levels
@user
=
user
[
N_DISABLED
,
N_PARTICIPATING
,
N_WATCH
,
N_GLOBAL
]
end
def
initialize
(
target
)
@target
=
target
end
end
def
disabled?
def
disabled?
user
.
notification_level
==
N_DISABLED
target
.
notification_level
==
N_DISABLED
end
end
def
participating?
def
participating?
user
.
notification_level
==
N_PARTICIPATING
target
.
notification_level
==
N_PARTICIPATING
end
end
def
watch?
def
watch?
user
.
notification_level
==
N_WATCH
target
.
notification_level
==
N_WATCH
end
def
global?
target
.
notification_level
==
N_GLOBAL
end
end
end
end
app/models/project.rb
View file @
25856a47
...
@@ -19,6 +19,7 @@
...
@@ -19,6 +19,7 @@
# issues_tracker :string(255) default("gitlab"), not null
# issues_tracker :string(255) default("gitlab"), not null
# issues_tracker_id :string(255)
# issues_tracker_id :string(255)
# snippets_enabled :boolean default(TRUE), not null
# snippets_enabled :boolean default(TRUE), not null
# last_activity_at :datetime
#
#
require
"grit"
require
"grit"
...
...
app/models/users_project.rb
View file @
25856a47
...
@@ -2,12 +2,13 @@
...
@@ -2,12 +2,13 @@
#
#
# Table name: users_projects
# Table name: users_projects
#
#
# id :integer not null, primary key
# id :integer not null, primary key
# user_id :integer not null
# user_id :integer not null
# project_id :integer not null
# project_id :integer not null
# created_at :datetime not null
# created_at :datetime not null
# updated_at :datetime not null
# updated_at :datetime not null
# project_access :integer default(0), not null
# project_access :integer default(0), not null
# notification_level :integer default(3), not null
#
#
class
UsersProject
<
ActiveRecord
::
Base
class
UsersProject
<
ActiveRecord
::
Base
...
@@ -29,6 +30,7 @@ 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
:user_id
,
uniqueness:
{
scope:
[
:project_id
],
message:
"already exists in project"
}
validates
:project_access
,
inclusion:
{
in:
[
GUEST
,
REPORTER
,
DEVELOPER
,
MASTER
]
},
presence:
true
validates
:project_access
,
inclusion:
{
in:
[
GUEST
,
REPORTER
,
DEVELOPER
,
MASTER
]
},
presence:
true
validates
:project
,
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
delegate
:name
,
:username
,
:email
,
to: :user
,
prefix:
true
...
@@ -134,4 +136,8 @@ class UsersProject < ActiveRecord::Base
...
@@ -134,4 +136,8 @@ class UsersProject < ActiveRecord::Base
def
skip_git?
def
skip_git?
!!
@skip_git
!!
@skip_git
end
end
def
notification
@notification
||=
Notification
.
new
(
self
)
end
end
end
app/services/notification_service.rb
View file @
25856a47
...
@@ -80,7 +80,7 @@ class NotificationService
...
@@ -80,7 +80,7 @@ class NotificationService
# * project team members with notification level higher then Participating
# * project team members with notification level higher then Participating
#
#
def
merge_mr
(
merge_request
)
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
=
recipients
.
concat
(
project_watchers
(
merge_request
.
project
)).
uniq
recipients
.
each
do
|
recipient
|
recipients
.
each
do
|
recipient
|
...
@@ -122,7 +122,7 @@ class NotificationService
...
@@ -122,7 +122,7 @@ class NotificationService
recipients
=
recipients
.
concat
(
project_watchers
(
note
.
project
)).
compact
.
uniq
recipients
=
recipients
.
concat
(
project_watchers
(
note
.
project
)).
compact
.
uniq
# Reject mutes users
# Reject mutes users
recipients
=
reject_muted_users
(
recipients
)
recipients
=
reject_muted_users
(
recipients
,
note
.
project
)
# Reject author
# Reject author
recipients
.
delete
(
note
.
author
)
recipients
.
delete
(
note
.
author
)
...
@@ -147,19 +147,41 @@ class NotificationService
...
@@ -147,19 +147,41 @@ class NotificationService
# Get project users with WATCH notification level
# Get project users with WATCH notification level
def
project_watchers
(
project
)
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
end
# Remove users with disabled notifications from array
# Remove users with disabled notifications from array
# Also remove duplications and nil recipients
# Also remove duplications and nil recipients
def
reject_muted_users
(
users
)
def
reject_muted_users
(
users
,
project
=
nil
)
users
.
compact
.
uniq
.
reject
do
|
user
|
users
=
users
.
compact
.
uniq
user
.
notification
.
disabled?
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
end
end
def
new_resource_email
(
target
,
method
)
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
=
recipients
.
concat
(
project_watchers
(
target
.
project
)).
uniq
recipients
.
delete
(
target
.
author
)
recipients
.
delete
(
target
.
author
)
...
@@ -169,7 +191,7 @@ class NotificationService
...
@@ -169,7 +191,7 @@ class NotificationService
end
end
def
close_resource_email
(
target
,
current_user
,
method
)
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
=
recipients
.
concat
(
project_watchers
(
target
.
project
)).
uniq
recipients
.
delete
(
current_user
)
recipients
.
delete
(
current_user
)
...
@@ -185,7 +207,7 @@ class NotificationService
...
@@ -185,7 +207,7 @@ class NotificationService
recipients
=
recipients
.
concat
(
project_watchers
(
target
.
project
))
recipients
=
recipients
.
concat
(
project_watchers
(
target
.
project
))
# reject users with disabled notifications
# 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
# Reject me from recipients if I reassign an item
recipients
.
delete
(
current_user
)
recipients
.
delete
(
current_user
)
...
...
app/views/notifications/show.html.haml
View file @
25856a47
...
@@ -13,56 +13,65 @@
...
@@ -13,56 +13,65 @@
–
You will receive all notifications from projects in which you participate
–
You will receive all notifications from projects in which you participate
%hr
%hr
=
form_tag
profile_notifications_path
,
method: :put
,
remote:
true
,
class:
'update-notifications'
do
.row
%ul
.well-list
.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
%li
.row
.row
.span4
.span4
%h5
Global
%span
=
link_to_project
(
users_project
.
project
)
.span7
.span7
=
label_tag
do
=
form_tag
profile_notifications_path
,
method: :put
,
remote:
true
,
class:
'update-notifications'
do
=
radio_button_tag
:notification_level
,
Notification
::
N_DISABLED
,
@notification
.
disabled?
=
hidden_field_tag
:notification_type
,
'project'
,
id:
dom_id
(
users_project
,
'notification_type'
)
%span
Disabled
=
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
=
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
=
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
%span
Disabled
=
label_tag
do
=
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
%span
Participating
=
label_tag
do
=
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
%span
Watch
.form-actions
.save-status-fixed
=
submit_tag
'Save'
,
class:
'btn btn-save'
%span
.update-success.cgreen.hide
%span
.update-success.cgreen.hide
%i
.icon-ok
%i
.icon-ok
Saved
Saved
%span
.update-failed.cred.hide
%span
.update-failed.cred.hide
%i
.icon-remove
%i
.icon-remove
Failed
Failed
app/views/notifications/update.js.haml
View file @
25856a47
-
if
@saved
-
if
@saved
:plain
:plain
$('.
update-notifications
.update-success').showAndHide();
$('.
save-status-fixed
.update-success').showAndHide();
-
else
-
else
:plain
:plain
$('.update-notifications .update-failed').showAndHide();
$('.save-status-fixed .update-failed').showAndHide();
db/schema.rb
View file @
25856a47
...
@@ -11,7 +11,7 @@
...
@@ -11,7 +11,7 @@
#
#
# It's strongly recommended to check this file into your version control system.
# It's strongly recommended to check this file into your version control system.
ActiveRecord
::
Schema
.
define
(
:version
=>
20130
325173941
)
do
ActiveRecord
::
Schema
.
define
(
:version
=>
20130
404164628
)
do
create_table
"events"
,
:force
=>
true
do
|
t
|
create_table
"events"
,
:force
=>
true
do
|
t
|
t
.
string
"target_type"
t
.
string
"target_type"
...
@@ -156,9 +156,11 @@ ActiveRecord::Schema.define(:version => 20130325173941) do
...
@@ -156,9 +156,11 @@ ActiveRecord::Schema.define(:version => 20130325173941) do
t
.
string
"issues_tracker"
,
:default
=>
"gitlab"
,
:null
=>
false
t
.
string
"issues_tracker"
,
:default
=>
"gitlab"
,
:null
=>
false
t
.
string
"issues_tracker_id"
t
.
string
"issues_tracker_id"
t
.
boolean
"snippets_enabled"
,
:default
=>
true
,
:null
=>
false
t
.
boolean
"snippets_enabled"
,
:default
=>
true
,
:null
=>
false
t
.
datetime
"last_activity_at"
end
end
add_index
"projects"
,
[
"creator_id"
],
:name
=>
"index_projects_on_owner_id"
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"
add_index
"projects"
,
[
"namespace_id"
],
:name
=>
"index_projects_on_namespace_id"
create_table
"protected_branches"
,
:force
=>
true
do
|
t
|
create_table
"protected_branches"
,
:force
=>
true
do
|
t
|
...
@@ -281,11 +283,12 @@ ActiveRecord::Schema.define(:version => 20130325173941) do
...
@@ -281,11 +283,12 @@ ActiveRecord::Schema.define(:version => 20130325173941) do
add_index
"users"
,
[
"username"
],
:name
=>
"index_users_on_username"
add_index
"users"
,
[
"username"
],
:name
=>
"index_users_on_username"
create_table
"users_projects"
,
:force
=>
true
do
|
t
|
create_table
"users_projects"
,
:force
=>
true
do
|
t
|
t
.
integer
"user_id"
,
:null
=>
false
t
.
integer
"user_id"
,
:null
=>
false
t
.
integer
"project_id"
,
:null
=>
false
t
.
integer
"project_id"
,
:null
=>
false
t
.
datetime
"created_at"
,
:null
=>
false
t
.
datetime
"created_at"
,
:null
=>
false
t
.
datetime
"updated_at"
,
:null
=>
false
t
.
datetime
"updated_at"
,
:null
=>
false
t
.
integer
"project_access"
,
:default
=>
0
,
:null
=>
false
t
.
integer
"project_access"
,
:default
=>
0
,
:null
=>
false
t
.
integer
"notification_level"
,
:default
=>
3
,
:null
=>
false
end
end
add_index
"users_projects"
,
[
"project_access"
],
:name
=>
"index_users_projects_on_project_access"
add_index
"users_projects"
,
[
"project_access"
],
:name
=>
"index_users_projects_on_project_access"
...
...
spec/models/project_spec.rb
View file @
25856a47
...
@@ -19,6 +19,7 @@
...
@@ -19,6 +19,7 @@
# issues_tracker :string(255) default("gitlab"), not null
# issues_tracker :string(255) default("gitlab"), not null
# issues_tracker_id :string(255)
# issues_tracker_id :string(255)
# snippets_enabled :boolean default(TRUE), not null
# snippets_enabled :boolean default(TRUE), not null
# last_activity_at :datetime
#
#
require
'spec_helper'
require
'spec_helper'
...
...
spec/models/users_project_spec.rb
View file @
25856a47
...
@@ -2,12 +2,13 @@
...
@@ -2,12 +2,13 @@
#
#
# Table name: users_projects
# Table name: users_projects
#
#
# id :integer not null, primary key
# id :integer not null, primary key
# user_id :integer not null
# user_id :integer not null
# project_id :integer not null
# project_id :integer not null
# created_at :datetime not null
# created_at :datetime not null
# updated_at :datetime not null
# updated_at :datetime not null
# project_access :integer default(0), not null
# project_access :integer default(0), not null
# notification_level :integer default(3), not null
#
#
require
'spec_helper'
require
'spec_helper'
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment