Commit e005d419 authored by Marin Jankovski's avatar Marin Jankovski

Merge branch 'master' into developer_can_push_to_protected_branches_option

parents 43c2d5a2 75043a9e
...@@ -4,7 +4,7 @@ v 7.7.0 ...@@ -4,7 +4,7 @@ v 7.7.0
- Add Jetbrains Teamcity CI service (Jason Lippert) - Add Jetbrains Teamcity CI service (Jason Lippert)
- -
- -
- - Mention notification level
- -
- -
- OAuth applications feature - OAuth applications feature
...@@ -14,8 +14,12 @@ v 7.7.0 ...@@ -14,8 +14,12 @@ v 7.7.0
- -
- -
- New side navigation - New side navigation
-
-
-
- Add alert message in case of outdated browser (IE < 10)
-
-
v 7.6.0 v 7.6.0
- Fork repository to groups - Fork repository to groups
...@@ -62,7 +66,7 @@ v 7.5.0 ...@@ -62,7 +66,7 @@ v 7.5.0
- Performance improvements - Performance improvements
- Fix post-receive issue for projects with deleted forks - Fix post-receive issue for projects with deleted forks
- New gitlab-shell version with custom hooks support - New gitlab-shell version with custom hooks support
- Improve code - Improve code
- GitLab CI 5.2+ support (does not support older versions) - GitLab CI 5.2+ support (does not support older versions)
- Fixed bug when you can not push commits starting with 000000 to protected branches - Fixed bug when you can not push commits starting with 000000 to protected branches
- Added a password strength indicator - Added a password strength indicator
......
...@@ -32,6 +32,9 @@ gem 'omniauth-kerberos' ...@@ -32,6 +32,9 @@ gem 'omniauth-kerberos'
gem 'doorkeeper', '2.0.1' gem 'doorkeeper', '2.0.1'
gem "rack-oauth2", "~> 1.0.5" gem "rack-oauth2", "~> 1.0.5"
# Browser detection
gem "browser"
# Extracting information from a git repository # Extracting information from a git repository
# Provide access to Gitlab::Git library # Provide access to Gitlab::Git library
gem "gitlab_git", '7.0.0.rc12' gem "gitlab_git", '7.0.0.rc12'
......
...@@ -50,6 +50,7 @@ GEM ...@@ -50,6 +50,7 @@ GEM
debug_inspector (>= 0.0.1) debug_inspector (>= 0.0.1)
bootstrap-sass (3.0.3.0) bootstrap-sass (3.0.3.0)
sass (~> 3.2) sass (~> 3.2)
browser (0.7.2)
builder (3.2.2) builder (3.2.2)
capybara (2.2.1) capybara (2.2.1)
mime-types (>= 1.16) mime-types (>= 1.16)
...@@ -614,6 +615,7 @@ DEPENDENCIES ...@@ -614,6 +615,7 @@ DEPENDENCIES
better_errors better_errors
binding_of_caller binding_of_caller
bootstrap-sass (~> 3.0) bootstrap-sass (~> 3.0)
browser
capybara (~> 2.2.1) capybara (~> 2.2.1)
carrierwave carrierwave
coffee-rails coffee-rails
......
7.6.0.pre 7.7.0.pre
...@@ -207,6 +207,18 @@ li.note { ...@@ -207,6 +207,18 @@ li.note {
} }
} }
.browser-alert {
padding: 10px;
text-align: center;
background: #C67;
color: #fff;
font-weight: bold;
a {
color: #fff;
text-decoration: underline;
}
}
.warning_message { .warning_message {
border-left: 4px solid #ed9; border-left: 4px solid #ed9;
color: #b90; color: #b90;
......
...@@ -293,4 +293,8 @@ module ApplicationHelper ...@@ -293,4 +293,8 @@ module ApplicationHelper
path << "?#{options.to_param}" path << "?#{options.to_param}"
path path
end end
def outdated_browser?
browser.ie? && browser.version.to_i < 10
end
end end
...@@ -6,12 +6,13 @@ class Notification ...@@ -6,12 +6,13 @@ class Notification
N_PARTICIPATING = 1 N_PARTICIPATING = 1
N_WATCH = 2 N_WATCH = 2
N_GLOBAL = 3 N_GLOBAL = 3
N_MENTION = 4
attr_accessor :target attr_accessor :target
class << self class << self
def notification_levels def notification_levels
[N_DISABLED, N_PARTICIPATING, N_WATCH] [N_DISABLED, N_PARTICIPATING, N_WATCH, N_MENTION]
end end
def options_with_labels def options_with_labels
...@@ -19,12 +20,13 @@ class Notification ...@@ -19,12 +20,13 @@ class Notification
disabled: N_DISABLED, disabled: N_DISABLED,
participating: N_PARTICIPATING, participating: N_PARTICIPATING,
watch: N_WATCH, watch: N_WATCH,
mention: N_MENTION,
global: N_GLOBAL global: N_GLOBAL
} }
end end
def project_notification_levels def project_notification_levels
[N_DISABLED, N_PARTICIPATING, N_WATCH, N_GLOBAL] [N_DISABLED, N_PARTICIPATING, N_WATCH, N_GLOBAL, N_MENTION]
end end
end end
...@@ -48,6 +50,10 @@ class Notification ...@@ -48,6 +50,10 @@ class Notification
target.notification_level == N_GLOBAL target.notification_level == N_GLOBAL
end end
def mention?
target.notification_level == N_MENTION
end
def level def level
target.notification_level target.notification_level
end end
......
...@@ -144,6 +144,10 @@ class NotificationService ...@@ -144,6 +144,10 @@ class NotificationService
# Merge project watchers # Merge project watchers
recipients = recipients.concat(project_watchers(note.project)).compact.uniq recipients = recipients.concat(project_watchers(note.project)).compact.uniq
# Reject mention users unless mentioned in comment
recipients = reject_mention_users(recipients - note.mentioned_users, note.project)
recipients = recipients + note.mentioned_users
# Reject mutes users # Reject mutes users
recipients = reject_muted_users(recipients, note.project) recipients = reject_muted_users(recipients, note.project)
...@@ -285,13 +289,39 @@ class NotificationService ...@@ -285,13 +289,39 @@ class NotificationService
end end
end end
# Remove users with notification level 'Mentioned'
def reject_mention_users(users, project = nil)
users = users.to_a.compact.uniq
users.reject do |user|
next user.notification.mention? unless project
tm = project.project_members.find_by(user_id: user.id)
if !tm && project.group
tm = project.group.group_members.find_by(user_id: user.id)
end
# reject users who globally set mention notification and has no membership
next user.notification.mention? unless tm
# reject users who set mention notification in project
next true if tm.notification.mention?
# reject users who have N_MENTION in project and disabled in global settings
tm.notification.global? && user.notification.mention?
end
end
def new_resource_email(target, project, method) def new_resource_email(target, project, method)
if target.respond_to?(:participants) if target.respond_to?(:participants)
recipients = target.participants recipients = target.participants
else else
recipients = [] recipients = []
end end
recipients = reject_muted_users(recipients, project) recipients = reject_muted_users(recipients, project)
recipients = reject_mention_users(recipients, project)
recipients = recipients.concat(project_watchers(project)).uniq recipients = recipients.concat(project_watchers(project)).uniq
recipients.delete(target.author) recipients.delete(target.author)
...@@ -302,6 +332,7 @@ class NotificationService ...@@ -302,6 +332,7 @@ class NotificationService
def close_resource_email(target, project, current_user, method) def close_resource_email(target, project, current_user, method)
recipients = reject_muted_users([target.author, target.assignee], project) recipients = reject_muted_users([target.author, target.assignee], project)
recipients = reject_mention_users(recipients, project)
recipients = recipients.concat(project_watchers(project)).uniq recipients = recipients.concat(project_watchers(project)).uniq
recipients.delete(current_user) recipients.delete(current_user)
...@@ -320,6 +351,7 @@ class NotificationService ...@@ -320,6 +351,7 @@ class NotificationService
# reject users with disabled notifications # reject users with disabled notifications
recipients = reject_muted_users(recipients, project) recipients = reject_muted_users(recipients, project)
recipients = reject_mention_users(recipients, 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)
...@@ -331,6 +363,7 @@ class NotificationService ...@@ -331,6 +363,7 @@ class NotificationService
def reopen_resource_email(target, project, current_user, method, status) def reopen_resource_email(target, project, current_user, method, status)
recipients = reject_muted_users([target.author, target.assignee], project) recipients = reject_muted_users([target.author, target.assignee], project)
recipients = reject_mention_users(recipients, project)
recipients = recipients.concat(project_watchers(project)).uniq recipients = recipients.concat(project_watchers(project)).uniq
recipients.delete(current_user) recipients.delete(current_user)
......
...@@ -2,9 +2,10 @@ ...@@ -2,9 +2,10 @@
= nav_link(path: 'groups#edit') do = nav_link(path: 'groups#edit') do
= link_to edit_group_path(@group) do = link_to edit_group_path(@group) do
%i.fa.fa-pencil-square-o %i.fa.fa-pencil-square-o
Group %span
Group
= nav_link(path: 'groups#projects') do = nav_link(path: 'groups#projects') do
= link_to projects_group_path(@group) do = link_to projects_group_path(@group) do
%i.fa.fa-folder %i.fa.fa-folder
Projects %span
Projects
...@@ -44,3 +44,5 @@ ...@@ -44,3 +44,5 @@
%li.hidden-xs %li.hidden-xs
= link_to current_user, class: "profile-pic", id: 'profile-pic' do = link_to current_user, class: "profile-pic", id: 'profile-pic' do
= image_tag avatar_icon(current_user.email, 26), alt: 'User activity' = image_tag avatar_icon(current_user.email, 26), alt: 'User activity'
= render 'shared/outdated_browser'
...@@ -20,3 +20,4 @@ ...@@ -20,3 +20,4 @@
%li.visible-xs %li.visible-xs
= link_to "Sign in", new_session_path(:user, redirect_to_referer: 'yes') = link_to "Sign in", new_session_path(:user, redirect_to_referer: 'yes')
= render 'shared/outdated_browser'
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
.content .content
.login-title .login-title
%h1= brand_title %h1= brand_title
= render 'shared/outdated_browser'
%hr %hr
.container .container
.content .content
......
...@@ -7,7 +7,8 @@ ...@@ -7,7 +7,8 @@
= nav_link(controller: :accounts) do = nav_link(controller: :accounts) do
= link_to profile_account_path do = link_to profile_account_path do
%i.fa.fa-gear %i.fa.fa-gear
Account %span
Account
= nav_link(path: ['profiles#applications', 'applications#edit', 'applications#show', 'applications#new']) do = nav_link(path: ['profiles#applications', 'applications#edit', 'applications#show', 'applications#new']) do
= link_to applications_profile_path do = link_to applications_profile_path do
%i.fa.fa-cloud %i.fa.fa-cloud
......
...@@ -15,6 +15,13 @@ ...@@ -15,6 +15,13 @@
Disabled Disabled
%p You will not get any notifications via email %p You will not get any notifications via email
.radio
= label_tag nil, class: '' do
= radio_button_tag :notification_level, Notification::N_MENTION, @notification.mention?, class: 'trigger-submit'
.level-title
Mention
%p You will receive notifications only for comments where you was @mentioned
.radio .radio
= label_tag nil, class: '' do = label_tag nil, class: '' do
= radio_button_tag :notification_level, Notification::N_PARTICIPATING, @notification.participating?, class: 'trigger-submit' = radio_button_tag :notification_level, Notification::N_PARTICIPATING, @notification.participating?, class: 'trigger-submit'
......
...@@ -11,8 +11,6 @@ ...@@ -11,8 +11,6 @@
%ul.breadcrumb.repo-breadcrumb %ul.breadcrumb.repo-breadcrumb
= commits_breadcrumbs = commits_breadcrumbs
%li.active
commits
%div{id: dom_id(@project)} %div{id: dom_id(@project)}
#commits-list= render "commits" #commits-list= render "commits"
......
- if outdated_browser?
- link = "https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/requirements.md#supported-web-browsers"
.browser-alert
GitLab may not work properly because you are using an outdated web browser.
%br
Please install a
= link_to 'supported web browser', link
for a better experience.
...@@ -8,7 +8,6 @@ If a user is a GitLab administrator they receive all permissions. ...@@ -8,7 +8,6 @@ If a user is a GitLab administrator they receive all permissions.
## Project ## Project
| Action | Guest | Reporter | Developer | Master | Owner | | Action | Guest | Reporter | Developer | Master | Owner |
|---------------------------------------|---------|------------|-------------|----------|--------| |---------------------------------------|---------|------------|-------------|----------|--------|
| Create new issue | ✓ | ✓ | ✓ | ✓ | ✓ | | Create new issue | ✓ | ✓ | ✓ | ✓ | ✓ |
...@@ -38,7 +37,7 @@ If a user is a GitLab administrator they receive all permissions. ...@@ -38,7 +37,7 @@ If a user is a GitLab administrator they receive all permissions.
| Transfer project to another namespace | | | | | ✓ | | Transfer project to another namespace | | | | | ✓ |
| Remove project | | | | | ✓ | | Remove project | | | | | ✓ |
| Force push to protected branches | | | | | | | Force push to protected branches | | | | | |
| Remove protected branches | | | | | | | Remove protected branches | | | | | |
## Group ## Group
......
...@@ -265,7 +265,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps ...@@ -265,7 +265,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
end end
step 'I click Side-by-side Diff tab' do step 'I click Side-by-side Diff tab' do
click_link 'Side-by-side' find('a', text: 'Side-by-side').trigger('click')
end end
step 'I should see comments on the side-by-side diff page' do step 'I should see comments on the side-by-side diff page' do
......
...@@ -116,6 +116,7 @@ describe NotificationService do ...@@ -116,6 +116,7 @@ describe NotificationService do
should_email(note.noteable.assignee_id) should_email(note.noteable.assignee_id)
should_not_email(note.author_id) should_not_email(note.author_id)
should_not_email(@u_mentioned.id)
should_not_email(@u_disabled.id) should_not_email(@u_disabled.id)
should_not_email(@u_not_mentioned.id) should_not_email(@u_not_mentioned.id)
notification.new_note(note) notification.new_note(note)
...@@ -168,6 +169,12 @@ describe NotificationService do ...@@ -168,6 +169,12 @@ describe NotificationService do
notification.new_note(note) notification.new_note(note)
end end
it do
@u_committer.update_attributes(notification_level: Notification::N_MENTION)
should_not_email(@u_committer.id, note)
notification.new_note(note)
end
def should_email(user_id, n) def should_email(user_id, n)
Notify.should_receive(:note_commit_email).with(user_id, n.id) Notify.should_receive(:note_commit_email).with(user_id, n.id)
end end
...@@ -190,11 +197,18 @@ describe NotificationService do ...@@ -190,11 +197,18 @@ describe NotificationService do
it do it do
should_email(issue.assignee_id) should_email(issue.assignee_id)
should_email(@u_watcher.id) should_email(@u_watcher.id)
should_not_email(@u_mentioned.id)
should_not_email(@u_participating.id) should_not_email(@u_participating.id)
should_not_email(@u_disabled.id) should_not_email(@u_disabled.id)
notification.new_issue(issue, @u_disabled) notification.new_issue(issue, @u_disabled)
end end
it do
issue.assignee.update_attributes(notification_level: Notification::N_MENTION)
should_not_email(issue.assignee_id)
notification.new_issue(issue, @u_disabled)
end
def should_email(user_id) def should_email(user_id)
Notify.should_receive(:new_issue_email).with(user_id, issue.id) Notify.should_receive(:new_issue_email).with(user_id, issue.id)
end end
...@@ -391,7 +405,7 @@ describe NotificationService do ...@@ -391,7 +405,7 @@ describe NotificationService do
@u_watcher = create(:user, notification_level: Notification::N_WATCH) @u_watcher = create(:user, notification_level: Notification::N_WATCH)
@u_participating = create(:user, notification_level: Notification::N_PARTICIPATING) @u_participating = create(:user, notification_level: Notification::N_PARTICIPATING)
@u_disabled = create(:user, notification_level: Notification::N_DISABLED) @u_disabled = create(:user, notification_level: Notification::N_DISABLED)
@u_mentioned = create(:user, username: 'mention', notification_level: Notification::N_PARTICIPATING) @u_mentioned = create(:user, username: 'mention', notification_level: Notification::N_MENTION)
@u_committer = create(:user, username: 'committer') @u_committer = create(:user, username: 'committer')
@u_not_mentioned = create(:user, username: 'regular', notification_level: Notification::N_PARTICIPATING) @u_not_mentioned = create(:user, username: 'regular', notification_level: Notification::N_PARTICIPATING)
......
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