Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
heptapod
heptapod
Commits
577da3a453fa
Commit
577da3a4
authored
Apr 04, 2013
by
Dmitriy Zaporozhets
Browse files
save each notification setting with ajax on change
parent
06f362320ca2
Changes
11
Hide whitespace changes
Inline
Side-by-side
app/assets/stylesheets/sections/profile.scss
View file @
577da3a4
...
...
@@ -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
;
}
}
app/controllers/notifications_controller.rb
View file @
577da3a4
...
...
@@ -3,7 +3,7 @@
def
show
@notification
=
current_user
.
notification
@projects
=
current_user
.
authorized
_projects
@
users_
projects
=
current_user
.
users
_projects
end
def
update
...
...
@@ -7,7 +7,15 @@
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
app/models/notification.rb
View file @
577da3a4
...
...
@@ -5,4 +5,5 @@
N_DISABLED
=
0
N_PARTICIPATING
=
1
N_WATCH
=
2
N_GLOBAL
=
3
...
...
@@ -8,7 +9,7 @@
attr_accessor
:
user
attr_accessor
:
target
def
self
.
notification_levels
[
N_DISABLED
,
N_PARTICIPATING
,
N_WATCH
]
end
...
...
@@ -10,10 +11,14 @@
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?
...
...
@@ -17,7 +22,7 @@
end
def
disabled?
user
.
notification_level
==
N_DISABLED
target
.
notification_level
==
N_DISABLED
end
def
participating?
...
...
@@ -21,7 +26,7 @@
end
def
participating?
user
.
notification_level
==
N_PARTICIPATING
target
.
notification_level
==
N_PARTICIPATING
end
def
watch?
...
...
@@ -25,6 +30,10 @@
end
def
watch?
user
.
notification_level
==
N_WATCH
target
.
notification_level
==
N_WATCH
end
def
global?
target
.
notification_level
==
N_GLOBAL
end
end
app/models/project.rb
View file @
577da3a4
...
...
@@ -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"
...
...
app/models/users_project.rb
View file @
577da3a4
...
...
@@ -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 @@
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 @@
def
skip_git?
!!
@skip_git
end
def
notification
@notification
||=
Notification
.
new
(
self
)
end
end
app/services/notification_service.rb
View file @
577da3a4
...
...
@@ -80,7 +80,7 @@
# * 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 @@
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,8 +147,17 @@
# 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
...
...
@@ -151,11 +160,24 @@
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
)
...
...
@@ -158,8 +180,8 @@
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 @@
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 @@
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
)
...
...
app/views/notifications/show.html.haml
View file @
577da3a4
...
...
@@ -13,8 +13,34 @@
–
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
...
...
@@ -18,5 +44,6 @@
%li
.row
.span4
%h5
Global
%span
=
link_to_project
(
users_project
.
project
)
.span7
...
...
@@ -22,14 +49,5 @@
.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'
)
...
...
@@ -35,14 +53,2 @@
=
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
...
...
@@ -48,5 +54,9 @@
=
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
...
...
@@ -50,7 +60,7 @@
%span
Disabled
=
label_tag
do
=
radio_button_tag
:
"
notification_level
[
#{
project
.
id
}
]"
,
Notification
::
N_PARTICIPATING
,
@
notification
.
participating?
,
disabled
:
tr
ue
=
radio_button_tag
:notification_level
,
Notification
::
N_PARTICIPATING
,
notification
.
participating?
,
id:
dom_id
(
users_project
,
'notification_level'
),
class
:
'
tr
igger-submit'
%span
Participating
=
label_tag
do
...
...
@@ -54,7 +64,7 @@
%span
Participating
=
label_tag
do
=
radio_button_tag
:
"
notification_level
[
#{
project
.
id
}
]"
,
Notification
::
N_WATCH
,
@
notification
.
watch?
,
disabled
:
tr
ue
=
radio_button_tag
:notification_level
,
Notification
::
N_WATCH
,
notification
.
watch?
,
id:
dom_id
(
users_project
,
'notification_level'
),
class
:
'
tr
igger-submit'
%span
Watch
...
...
@@ -58,11 +68,10 @@
%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
app/views/notifications/update.js.haml
View file @
577da3a4
-
if
@saved
:plain
$('.
update-notifications
.update-success').showAndHide();
$('.
save-status-fixed
.update-success').showAndHide();
-
else
:plain
...
...
@@ -4,4 +4,3 @@
-
else
:plain
$('.update-notifications .update-failed').showAndHide();
$('.save-status-fixed .update-failed').showAndHide();
db/schema.rb
View file @
577da3a4
...
...
@@ -11,7 +11,7 @@
#
# 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
|
t
.
string
"target_type"
...
...
@@ -156,6 +156,7 @@
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"
...
...
@@ -159,6 +160,7 @@
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 @@
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"
...
...
spec/models/project_spec.rb
View file @
577da3a4
...
...
@@ -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'
...
...
spec/models/users_project_spec.rb
View file @
577da3a4
...
...
@@ -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'
...
...
Write
Preview
Supports
Markdown
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