diff --git a/CHANGELOG b/CHANGELOG index f379bc427bd0e2156f3d0b074c13231d2ed57d37..ea390eef2007421ada776f8c9958bd98682da919 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -4,7 +4,7 @@ v 7.7.0 - Add Jetbrains Teamcity CI service (Jason Lippert) - - - - + - Mention notification level - - - OAuth applications feature @@ -14,8 +14,12 @@ v 7.7.0 - - - New side navigation - - + - + - + - + - Add alert message in case of outdated browser (IE < 10) + - + - v 7.6.0 - Fork repository to groups @@ -62,7 +66,7 @@ v 7.5.0 - Performance improvements - Fix post-receive issue for projects with deleted forks - New gitlab-shell version with custom hooks support - - Improve code + - Improve code - GitLab CI 5.2+ support (does not support older versions) - Fixed bug when you can not push commits starting with 000000 to protected branches - Added a password strength indicator diff --git a/Gemfile b/Gemfile index 85e7bba444a33c76f0df7b3c5651b122e30b5bb1..29f3df0ea9ef9b46615ae94ad9eb18a59836fe62 100644 --- a/Gemfile +++ b/Gemfile @@ -32,6 +32,9 @@ gem 'omniauth-kerberos' gem 'doorkeeper', '2.0.1' gem "rack-oauth2", "~> 1.0.5" +# Browser detection +gem "browser" + # Extracting information from a git repository # Provide access to Gitlab::Git library gem "gitlab_git", '7.0.0.rc12' diff --git a/Gemfile.lock b/Gemfile.lock index 0d089305fe5f4f046344d376afa0200aedc56961..554223b83c9c324fe15eca88bd0136b805349658 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -50,6 +50,7 @@ GEM debug_inspector (>= 0.0.1) bootstrap-sass (3.0.3.0) sass (~> 3.2) + browser (0.7.2) builder (3.2.2) capybara (2.2.1) mime-types (>= 1.16) @@ -614,6 +615,7 @@ DEPENDENCIES better_errors binding_of_caller bootstrap-sass (~> 3.0) + browser capybara (~> 2.2.1) carrierwave coffee-rails diff --git a/VERSION b/VERSION index a28398aef42a01991b2de52be85daa5685fc6d89..550b62480c3ff6b92aab024526509f1c32b88505 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -7.6.0.pre +7.7.0.pre diff --git a/app/assets/stylesheets/generic/common.scss b/app/assets/stylesheets/generic/common.scss index 19c8f103535eedc9119adb25dd478f15ce426c9d..24f7a9ad686a777b99eb14fff97851c9d67f8337 100644 --- a/app/assets/stylesheets/generic/common.scss +++ b/app/assets/stylesheets/generic/common.scss @@ -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 { border-left: 4px solid #ed9; color: #b90; diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 90cc58f44b7de9f463dabbc3f74f8b08ee49bc20..54caaa0f7e54e03a46fc79bb5d76278501ef1a50 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -293,4 +293,8 @@ module ApplicationHelper path << "?#{options.to_param}" path end + + def outdated_browser? + browser.ie? && browser.version.to_i < 10 + end end diff --git a/app/models/notification.rb b/app/models/notification.rb index b0f8ed6a4ecdaa2856a12d2c67d964c4c7a8568f..1395274173d4d18609167b6b9f6ed12abc133076 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -6,12 +6,13 @@ class Notification N_PARTICIPATING = 1 N_WATCH = 2 N_GLOBAL = 3 + N_MENTION = 4 attr_accessor :target class << self def notification_levels - [N_DISABLED, N_PARTICIPATING, N_WATCH] + [N_DISABLED, N_PARTICIPATING, N_WATCH, N_MENTION] end def options_with_labels @@ -19,12 +20,13 @@ class Notification disabled: N_DISABLED, participating: N_PARTICIPATING, watch: N_WATCH, + mention: N_MENTION, global: N_GLOBAL } end def project_notification_levels - [N_DISABLED, N_PARTICIPATING, N_WATCH, N_GLOBAL] + [N_DISABLED, N_PARTICIPATING, N_WATCH, N_GLOBAL, N_MENTION] end end @@ -48,6 +50,10 @@ class Notification target.notification_level == N_GLOBAL end + def mention? + target.notification_level == N_MENTION + end + def level target.notification_level end diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index d1aadd741e1fa7052e69b64aa6bc8172456bed87..fb8f812dad84133d6cb1ed4d572145f180670311 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -144,6 +144,10 @@ class NotificationService # Merge project watchers 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 recipients = reject_muted_users(recipients, note.project) @@ -285,13 +289,39 @@ class NotificationService 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) if target.respond_to?(:participants) recipients = target.participants else recipients = [] end + recipients = reject_muted_users(recipients, project) + recipients = reject_mention_users(recipients, project) recipients = recipients.concat(project_watchers(project)).uniq recipients.delete(target.author) @@ -302,6 +332,7 @@ class NotificationService def close_resource_email(target, project, current_user, method) recipients = reject_muted_users([target.author, target.assignee], project) + recipients = reject_mention_users(recipients, project) recipients = recipients.concat(project_watchers(project)).uniq recipients.delete(current_user) @@ -320,6 +351,7 @@ class NotificationService # reject users with disabled notifications recipients = reject_muted_users(recipients, project) + recipients = reject_mention_users(recipients, project) # Reject me from recipients if I reassign an item recipients.delete(current_user) @@ -331,6 +363,7 @@ class NotificationService def reopen_resource_email(target, project, current_user, method, status) recipients = reject_muted_users([target.author, target.assignee], project) + recipients = reject_mention_users(recipients, project) recipients = recipients.concat(project_watchers(project)).uniq recipients.delete(current_user) diff --git a/app/views/groups/_settings_nav.html.haml b/app/views/groups/_settings_nav.html.haml index 82d760f7c4120a5d07c4daea89c2d740d10a47cc..35180792a0daff4a8e8c1ee9353f3607d81ecd61 100644 --- a/app/views/groups/_settings_nav.html.haml +++ b/app/views/groups/_settings_nav.html.haml @@ -2,9 +2,10 @@ = nav_link(path: 'groups#edit') do = link_to edit_group_path(@group) do %i.fa.fa-pencil-square-o - Group + %span + Group = nav_link(path: 'groups#projects') do = link_to projects_group_path(@group) do %i.fa.fa-folder - Projects - + %span + Projects diff --git a/app/views/layouts/_head_panel.html.haml b/app/views/layouts/_head_panel.html.haml index eda37f8237a07b59960a834d07601941649980fe..e98b8ec631d203fff39c3b5b7259fd4181c1c9ba 100644 --- a/app/views/layouts/_head_panel.html.haml +++ b/app/views/layouts/_head_panel.html.haml @@ -44,3 +44,5 @@ %li.hidden-xs = link_to current_user, class: "profile-pic", id: 'profile-pic' do = image_tag avatar_icon(current_user.email, 26), alt: 'User activity' + += render 'shared/outdated_browser' diff --git a/app/views/layouts/_public_head_panel.html.haml b/app/views/layouts/_public_head_panel.html.haml index 9bfc14d16c1b6ff6dc3546ba89fe729ec5c477dc..02a5e4868d1c462cbaf8607f861f602d70326f7a 100644 --- a/app/views/layouts/_public_head_panel.html.haml +++ b/app/views/layouts/_public_head_panel.html.haml @@ -20,3 +20,4 @@ %li.visible-xs = link_to "Sign in", new_session_path(:user, redirect_to_referer: 'yes') += render 'shared/outdated_browser' diff --git a/app/views/layouts/devise.html.haml b/app/views/layouts/devise.html.haml index 06de03eadad967ba3e8047ae12fb58cfdc2a5718..6539a24119c5eb34ccabfff95eb37656bbebcf4b 100644 --- a/app/views/layouts/devise.html.haml +++ b/app/views/layouts/devise.html.haml @@ -6,6 +6,7 @@ .content .login-title %h1= brand_title + = render 'shared/outdated_browser' %hr .container .content diff --git a/app/views/layouts/nav/_profile.html.haml b/app/views/layouts/nav/_profile.html.haml index 36b48a5d02d24ad7b54d7cc2530fd40c80ef3313..cc50b9b570a8a8c36ce0bbfe9c8b07af6223bd9f 100644 --- a/app/views/layouts/nav/_profile.html.haml +++ b/app/views/layouts/nav/_profile.html.haml @@ -7,7 +7,8 @@ = nav_link(controller: :accounts) do = link_to profile_account_path do %i.fa.fa-gear - Account + %span + Account = nav_link(path: ['profiles#applications', 'applications#edit', 'applications#show', 'applications#new']) do = link_to applications_profile_path do %i.fa.fa-cloud diff --git a/app/views/profiles/notifications/show.html.haml b/app/views/profiles/notifications/show.html.haml index a044fad8fa3cd879519707ed485502a1ac571891..96fe91b9b2018781916ae5bf5b52c4976e194f7f 100644 --- a/app/views/profiles/notifications/show.html.haml +++ b/app/views/profiles/notifications/show.html.haml @@ -15,6 +15,13 @@ Disabled %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 = label_tag nil, class: '' do = radio_button_tag :notification_level, Notification::N_PARTICIPATING, @notification.participating?, class: 'trigger-submit' diff --git a/app/views/projects/commits/show.html.haml b/app/views/projects/commits/show.html.haml index 5717c24c27442f16aefe6e84bcaf7ff088cf929e..56956625e0ba740a1b4b3cfefd4a5deef4183360 100644 --- a/app/views/projects/commits/show.html.haml +++ b/app/views/projects/commits/show.html.haml @@ -11,8 +11,6 @@ %ul.breadcrumb.repo-breadcrumb = commits_breadcrumbs - %li.active - commits %div{id: dom_id(@project)} #commits-list= render "commits" diff --git a/app/views/shared/_outdated_browser.html.haml b/app/views/shared/_outdated_browser.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..0eba1fe075f35762dbe37f0bae29c77dbfe02db7 --- /dev/null +++ b/app/views/shared/_outdated_browser.html.haml @@ -0,0 +1,8 @@ +- 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. diff --git a/doc/permissions/permissions.md b/doc/permissions/permissions.md index 8e64b43929a4c4e6160223e00ad05931e579ea47..d70cbb280749911928f5a9301174a2c7aee07dab 100644 --- a/doc/permissions/permissions.md +++ b/doc/permissions/permissions.md @@ -8,7 +8,6 @@ If a user is a GitLab administrator they receive all permissions. ## Project - | Action | Guest | Reporter | Developer | Master | Owner | |---------------------------------------|---------|------------|-------------|----------|--------| | Create new issue | 鉁� | 鉁� | 鉁� | 鉁� | 鉁� | @@ -38,7 +37,7 @@ If a user is a GitLab administrator they receive all permissions. | Transfer project to another namespace | | | | | 鉁� | | Remove project | | | | | 鉁� | | Force push to protected branches | | | | | | -| Remove protected branches | | | | | | +| Remove protected branches | | | | | | ## Group diff --git a/features/steps/project/merge_requests.rb b/features/steps/project/merge_requests.rb index 28928d602d6602dbfc658d04d2d58c7dabf8a05c..bd84abae06e19849aaf68c2b0a6360d0dea6ebdd 100644 --- a/features/steps/project/merge_requests.rb +++ b/features/steps/project/merge_requests.rb @@ -265,7 +265,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps end step 'I click Side-by-side Diff tab' do - click_link 'Side-by-side' + find('a', text: 'Side-by-side').trigger('click') end step 'I should see comments on the side-by-side diff page' do diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index f8377650e0a6193a2200f93868e4850d55bbf248..e305536f7ee6f17957c6e0d43b90b5c343258b04 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -116,6 +116,7 @@ describe NotificationService do should_email(note.noteable.assignee_id) should_not_email(note.author_id) + should_not_email(@u_mentioned.id) should_not_email(@u_disabled.id) should_not_email(@u_not_mentioned.id) notification.new_note(note) @@ -168,6 +169,12 @@ describe NotificationService do notification.new_note(note) 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) Notify.should_receive(:note_commit_email).with(user_id, n.id) end @@ -190,11 +197,18 @@ describe NotificationService do it do should_email(issue.assignee_id) should_email(@u_watcher.id) + should_not_email(@u_mentioned.id) should_not_email(@u_participating.id) should_not_email(@u_disabled.id) notification.new_issue(issue, @u_disabled) 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) Notify.should_receive(:new_issue_email).with(user_id, issue.id) end @@ -391,7 +405,7 @@ describe NotificationService do @u_watcher = create(:user, notification_level: Notification::N_WATCH) @u_participating = create(:user, notification_level: Notification::N_PARTICIPATING) @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_not_mentioned = create(:user, username: 'regular', notification_level: Notification::N_PARTICIPATING)