Commit 1d34ce13 authored by Douwe Maan's avatar Douwe Maan

Merge branch 'issue_3359_3' into 'master'

Insert notification settings dropdown into groups

## Display notification settings dropdown for groups

part of #3359   

![groups](/uploads/d61648236b81b0cca55fa2d73758f0df/groups.png)
![Screenshot_from_2016-06-29_10-58-37](/uploads/7be05ea6002932c094a81b25a308fd62/Screenshot_from_2016-06-29_10-58-37.png)  
![small](/uploads/6f2b556d734c870e358f6f56618a0bab/small.png)

See merge request !4857
parents c051630a d2971315
...@@ -13,6 +13,7 @@ v 8.10.0 (unreleased) ...@@ -13,6 +13,7 @@ v 8.10.0 (unreleased)
- Fix pagination when sorting by columns with lots of ties (like priority) - Fix pagination when sorting by columns with lots of ties (like priority)
- Exclude email check from the standard health check - Exclude email check from the standard health check
- Fix changing issue state columns in milestone view - Fix changing issue state columns in milestone view
- Add notification settings dropdown for groups
- Fix user creation with stronger minimum password requirements !4054 (nathan-pmt) - Fix user creation with stronger minimum password requirements !4054 (nathan-pmt)
- PipelinesFinder uses git cache data - PipelinesFinder uses git cache data
- Check for conflicts with existing Project's wiki path when creating a new project. - Check for conflicts with existing Project's wiki path when creating a new project.
......
...@@ -84,6 +84,8 @@ class Dispatcher ...@@ -84,6 +84,8 @@ class Dispatcher
new Activities() new Activities()
when 'groups:show' when 'groups:show'
shortcut_handler = new ShortcutsNavigation() shortcut_handler = new ShortcutsNavigation()
new NotificationsForm()
new NotificationsDropdown()
when 'groups:group_members:index' when 'groups:group_members:index'
new GroupMembers() new GroupMembers()
new UsersSelect() new UsersSelect()
......
...@@ -137,7 +137,7 @@ ...@@ -137,7 +137,7 @@
margin: 0; margin: 0;
font-size: 24px; font-size: 24px;
font-weight: normal; font-weight: normal;
margin-bottom: 5px; margin-bottom: 10px;
color: #4c4e54; color: #4c4e54;
font-size: 23px; font-size: 23px;
line-height: 1.1; line-height: 1.1;
......
...@@ -48,11 +48,7 @@ ...@@ -48,11 +48,7 @@
.access-request-button { .access-request-button {
@include btn-gray; @include btn-gray;
position: absolute; margin-right: 10px;
right: 16px;
bottom: 32px;
padding: 3px 10px;
text-transform: none; text-transform: none;
background-color: $background-color;
} }
} }
...@@ -37,15 +37,12 @@ class GroupsController < Groups::ApplicationController ...@@ -37,15 +37,12 @@ class GroupsController < Groups::ApplicationController
end end
def show def show
@last_push = current_user.recent_push if current_user if current_user
@last_push = current_user.recent_push
@projects = @projects.includes(:namespace) @notification_setting = current_user.notification_settings_for(group)
@projects = @projects.sorted_by_activity end
@projects = filter_projects(@projects)
@projects = @projects.sort(@sort = params[:sort])
@projects = @projects.page(params[:page]) if params[:filter_projects].blank?
@shared_projects = GroupProjectsFinder.new(group, only_shared: true).execute(current_user) setup_projects
respond_to do |format| respond_to do |format|
format.html format.html
...@@ -97,6 +94,16 @@ class GroupsController < Groups::ApplicationController ...@@ -97,6 +94,16 @@ class GroupsController < Groups::ApplicationController
protected protected
def setup_projects
@projects = @projects.includes(:namespace)
@projects = @projects.sorted_by_activity
@projects = filter_projects(@projects)
@projects = @projects.sort(@sort = params[:sort])
@projects = @projects.page(params[:page]) if params[:filter_projects].blank?
@shared_projects = GroupProjectsFinder.new(group, only_shared: true).execute(current_user)
end
def authorize_create_group! def authorize_create_group!
unless can?(current_user, :create_group, nil) unless can?(current_user, :create_group, nil)
return render_404 return render_404
......
...@@ -2,11 +2,9 @@ class NotificationSettingsController < ApplicationController ...@@ -2,11 +2,9 @@ class NotificationSettingsController < ApplicationController
before_action :authenticate_user! before_action :authenticate_user!
def create def create
project = Project.find(params[:project][:id]) return render_404 unless can_read?(resource)
return render_404 unless can?(current_user, :read_project, project) @notification_setting = current_user.notification_settings_for(resource)
@notification_setting = current_user.notification_settings_for(project)
@saved = @notification_setting.update_attributes(notification_setting_params) @saved = @notification_setting.update_attributes(notification_setting_params)
render_response render_response
...@@ -21,6 +19,22 @@ class NotificationSettingsController < ApplicationController ...@@ -21,6 +19,22 @@ class NotificationSettingsController < ApplicationController
private private
def resource
@resource ||=
if params[:project_id].present?
Project.find(params[:project_id])
elsif params[:namespace_id].present?
Group.find(params[:namespace_id])
end
end
def can_read?(resource)
ability_name = resource.class.name.downcase
ability_name = "read_#{ability_name}".to_sym
can?(current_user, ability_name, resource)
end
def render_response def render_response
render json: { render json: {
html: view_to_html_string("shared/notifications/_button", notification_setting: @notification_setting), html: view_to_html_string("shared/notifications/_button", notification_setting: @notification_setting),
......
...@@ -72,6 +72,6 @@ module NotificationsHelper ...@@ -72,6 +72,6 @@ module NotificationsHelper
# Create hidden field to send notification setting source to controller # Create hidden field to send notification setting source to controller
def hidden_setting_source_input(notification_setting) def hidden_setting_source_input(notification_setting)
return unless notification_setting.source_type return unless notification_setting.source_type
hidden_field_tag "#{notification_setting.source_type.downcase}[id]", notification_setting.source_id hidden_field_tag "#{notification_setting.source_type.downcase}_id", notification_setting.source_id
end end
end end
...@@ -15,12 +15,17 @@ ...@@ -15,12 +15,17 @@
%span.visibility-icon.has-tooltip{ data: { container: 'body' }, title: visibility_icon_description(@group) } %span.visibility-icon.has-tooltip{ data: { container: 'body' }, title: visibility_icon_description(@group) }
= visibility_level_icon(@group.visibility_level, fw: false) = visibility_level_icon(@group.visibility_level, fw: false)
%span.hidden-xs
= render 'shared/notifications/button', notification_setting: @notification_setting
- if current_user
.pull-right
= render 'shared/members/access_request_buttons', source: @group
- if @group.description.present? - if @group.description.present?
.cover-desc.description .cover-desc.description
= markdown(@group.description, pipeline: :description) = markdown(@group.description, pipeline: :description)
- if current_user
= render 'shared/members/access_request_buttons', source: @group
%div{ class: container_class } %div{ class: container_class }
.top-area .top-area
......
...@@ -37,12 +37,14 @@ This means that you can set a different level of notifications per group while s ...@@ -37,12 +37,14 @@ This means that you can set a different level of notifications per group while s
to have a finer level setting per project. to have a finer level setting per project.
Organization like this is suitable for users that belong to different groups but don't have the Organization like this is suitable for users that belong to different groups but don't have the
same need for being notified for every group they are member of. same need for being notified for every group they are member of.
These settings can be configured on group page or user profile notifications dropdown.
#### Project Settings #### Project Settings
Project Settings are at the top level and any setting placed at this level will take precedence of any Project Settings are at the top level and any setting placed at this level will take precedence of any
other setting. other setting.
This is suitable for users that have different needs for notifications per project basis. This is suitable for users that have different needs for notifications per project basis.
These settings can be configured on project page or user profile notifications dropdown.
## Notification events ## Notification events
......
...@@ -2,6 +2,7 @@ require 'spec_helper' ...@@ -2,6 +2,7 @@ require 'spec_helper'
describe NotificationSettingsController do describe NotificationSettingsController do
let(:project) { create(:empty_project) } let(:project) { create(:empty_project) }
let(:group) { create(:group, :internal) }
let(:user) { create(:user) } let(:user) { create(:user) }
before do before do
...@@ -12,7 +13,7 @@ describe NotificationSettingsController do ...@@ -12,7 +13,7 @@ describe NotificationSettingsController do
context 'when not authorized' do context 'when not authorized' do
it 'redirects to sign in page' do it 'redirects to sign in page' do
post :create, post :create,
project: { id: project.id }, project_id: project.id,
notification_setting: { level: :participating } notification_setting: { level: :participating }
expect(response).to redirect_to(new_user_session_path) expect(response).to redirect_to(new_user_session_path)
...@@ -20,33 +21,73 @@ describe NotificationSettingsController do ...@@ -20,33 +21,73 @@ describe NotificationSettingsController do
end end
context 'when authorized' do context 'when authorized' do
let(:custom_events) do
events = {}
NotificationSetting::EMAIL_EVENTS.each do |event|
events[event.to_s] = true
end
events
end
before do before do
sign_in(user) sign_in(user)
end end
it 'returns success' do context 'for projects' do
let(:notification_setting) { user.notification_settings_for(project) }
it 'creates notification setting' do
post :create, post :create,
project: { id: project.id }, project_id: project.id,
notification_setting: { level: :participating } notification_setting: { level: :participating }
expect(response.status).to eq 200 expect(response.status).to eq 200
expect(notification_setting.level).to eq("participating")
expect(notification_setting.user_id).to eq(user.id)
expect(notification_setting.source_id).to eq(project.id)
expect(notification_setting.source_type).to eq("Project")
end end
context 'and setting custom notification setting' do context 'with custom settings' do
let(:custom_events) do it 'creates notification setting' do
events = {} post :create,
project_id: project.id,
notification_setting: { level: :custom }.merge(custom_events)
NotificationSetting::EMAIL_EVENTS.each do |event| expect(response.status).to eq 200
events[event] = "true" expect(notification_setting.level).to eq("custom")
expect(notification_setting.events).to eq(custom_events)
end
end end
end end
it 'returns success' do context 'for groups' do
let(:notification_setting) { user.notification_settings_for(group) }
it 'creates notification setting' do
post :create, post :create,
project: { id: project.id }, namespace_id: group.id,
notification_setting: { level: :participating, events: custom_events } notification_setting: { level: :watch }
expect(response.status).to eq 200 expect(response.status).to eq 200
expect(notification_setting.level).to eq("watch")
expect(notification_setting.user_id).to eq(user.id)
expect(notification_setting.source_id).to eq(group.id)
expect(notification_setting.source_type).to eq("Namespace")
end
context 'with custom settings' do
it 'creates notification setting' do
post :create,
namespace_id: group.id,
notification_setting: { level: :custom }.merge(custom_events)
expect(response.status).to eq 200
expect(notification_setting.level).to eq("custom")
expect(notification_setting.events).to eq(custom_events)
end
end end
end end
end end
...@@ -57,7 +98,7 @@ describe NotificationSettingsController do ...@@ -57,7 +98,7 @@ describe NotificationSettingsController do
it 'returns 404' do it 'returns 404' do
post :create, post :create,
project: { id: private_project.id }, project_id: private_project.id,
notification_setting: { level: :participating } notification_setting: { level: :participating }
expect(response).to have_http_status(404) expect(response).to have_http_status(404)
......
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