Included groups on project_members page
This commit is contained in:
parent
87a0501ded
commit
4afd17b278
13 changed files with 108 additions and 58 deletions
|
@ -164,6 +164,14 @@ ul.content-list {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.member-controls {
|
||||||
|
float: none;
|
||||||
|
|
||||||
|
@media (min-width: $screen-md-min) {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// When dragging a list item
|
// When dragging a list item
|
||||||
&.ui-sortable-helper {
|
&.ui-sortable-helper {
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
.member-search-form {
|
.member-search-form {
|
||||||
float: left;
|
|
||||||
|
|
||||||
input[type='search'] {
|
input[type='search'] {
|
||||||
width: 225px;
|
width: 225px;
|
||||||
vertical-align: bottom;
|
vertical-align: bottom;
|
||||||
|
|
|
@ -5,6 +5,15 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.member {
|
.member {
|
||||||
|
.list-item-name {
|
||||||
|
float: none;
|
||||||
|
|
||||||
|
@media (min-width: $screen-md-min) {
|
||||||
|
float: left;
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.controls {
|
.controls {
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 400px;
|
width: 400px;
|
||||||
|
|
|
@ -19,9 +19,21 @@ class Projects::GroupLinksController < Projects::ApplicationController
|
||||||
redirect_to namespace_project_group_links_path(project.namespace, project)
|
redirect_to namespace_project_group_links_path(project.namespace, project)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
@group_link = @project.project_group_links.find(params[:id])
|
||||||
|
|
||||||
|
@group_link.update_attributes(group_link_params)
|
||||||
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
project.project_group_links.find(params[:id]).destroy
|
project.project_group_links.find(params[:id]).destroy
|
||||||
|
|
||||||
redirect_to namespace_project_group_links_path(project.namespace, project)
|
redirect_to namespace_project_group_links_path(project.namespace, project)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def group_link_params
|
||||||
|
params.require(:group_link).permit(:group_access, :expires_at)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,6 +5,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController
|
||||||
before_action :authorize_admin_project_member!, except: [:index, :leave, :request_access]
|
before_action :authorize_admin_project_member!, except: [:index, :leave, :request_access]
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
@groups = @project.project_group_links.all
|
||||||
@project_members = @project.project_members
|
@project_members = @project.project_members
|
||||||
@project_members = @project_members.non_invite unless can?(current_user, :admin_project, @project)
|
@project_members = @project_members.non_invite unless can?(current_user, :admin_project, @project)
|
||||||
|
|
||||||
|
|
3
app/views/projects/group_links/update.js.haml
Normal file
3
app/views/projects/group_links/update.js.haml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
:plain
|
||||||
|
var $listItem = $('#{escape_javascript(render('shared/members/group', group_link: @group_link, group: @group_link.group))}');
|
||||||
|
$("##{dom_id(@group_link.group)} .list-item-name").replaceWith($listItem.find('.list-item-name'));
|
|
@ -1,7 +1,7 @@
|
||||||
.panel.panel-default
|
.panel.panel-default
|
||||||
.panel-heading
|
.panel-heading
|
||||||
|
Group members with access to
|
||||||
%strong #{@group.name}
|
%strong #{@group.name}
|
||||||
group members
|
|
||||||
%span.badge= members.size
|
%span.badge= members.size
|
||||||
- if can?(current_user, :admin_group_member, @group)
|
- if can?(current_user, :admin_group_member, @group)
|
||||||
.controls
|
.controls
|
||||||
|
|
9
app/views/projects/project_members/_groups.html.haml
Normal file
9
app/views/projects/project_members/_groups.html.haml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
.panel.panel-default
|
||||||
|
.panel-heading
|
||||||
|
Groups with access to
|
||||||
|
%strong #{@project.name}
|
||||||
|
%span.badge= groups.size
|
||||||
|
%ul.content-list
|
||||||
|
- @groups.each do |group_link|
|
||||||
|
- group = group_link.group
|
||||||
|
= render 'shared/members/group', group_link: group_link, group: group
|
|
@ -3,17 +3,5 @@
|
||||||
Users with access to
|
Users with access to
|
||||||
%strong #{@project.name}
|
%strong #{@project.name}
|
||||||
%span.badge= members.size
|
%span.badge= members.size
|
||||||
.controls
|
|
||||||
= form_tag namespace_project_project_members_path(@project.namespace, @project), method: :get, class: 'form-inline member-search-form' do
|
|
||||||
.form-group
|
|
||||||
= search_field_tag :search, params[:search], { placeholder: 'Find existing member by name', class: 'form-control', spellcheck: false }
|
|
||||||
= button_tag class: 'btn', title: 'Search' do
|
|
||||||
= icon("search")
|
|
||||||
%ul.content-list
|
%ul.content-list
|
||||||
= render partial: 'shared/members/member', collection: members, as: :member
|
= render partial: 'shared/members/member', collection: members, as: :member
|
||||||
|
|
||||||
:javascript
|
|
||||||
$('form.member-search-form').on('submit', function (event) {
|
|
||||||
event.preventDefault();
|
|
||||||
Turbolinks.visit(this.action + '?' + $(this).serialize());
|
|
||||||
});
|
|
||||||
|
|
|
@ -14,12 +14,16 @@
|
||||||
|
|
||||||
= render 'shared/members/requests', membership_source: @project, requesters: @requesters
|
= render 'shared/members/requests', membership_source: @project, requesters: @requesters
|
||||||
|
|
||||||
%h5.append-bottom-default
|
.append-bottom-default.clearfix
|
||||||
Existing users and groups
|
%h5.pull-left
|
||||||
|
Existing users and groups
|
||||||
|
= form_tag namespace_project_project_members_path(@project.namespace, @project), method: :get, class: 'form-inline member-search-form pull-right hidden-xs hidden-sm' do
|
||||||
|
.form-group
|
||||||
|
= search_field_tag :search, params[:search], { placeholder: 'Find existing members by name', class: 'form-control', spellcheck: false }
|
||||||
|
= icon("search")
|
||||||
|
- if @grups
|
||||||
|
= render 'groups', groups: @groups
|
||||||
= render 'team', members: @project_members
|
= render 'team', members: @project_members
|
||||||
|
|
||||||
- if @group
|
- if @group
|
||||||
= render "group_members", members: @group_members
|
= render "group_members", members: @group_members
|
||||||
|
|
||||||
- if @project_group_links.any? && @project.allowed_to_share_with_group?
|
|
||||||
= render "shared_group_members"
|
|
||||||
|
|
23
app/views/shared/members/_group.html.haml
Normal file
23
app/views/shared/members/_group.html.haml
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
- group = local_assigns[:group]
|
||||||
|
- group_link = local_assigns[:group_link]
|
||||||
|
%li.member{ class: dom_class(group), id: dom_id(group) }
|
||||||
|
%span{ class: "list-item-name" }
|
||||||
|
= image_tag group_icon(group), class: "avatar s40", alt: ''
|
||||||
|
%strong
|
||||||
|
= link_to group.name, group_path(group)
|
||||||
|
.cgray
|
||||||
|
Joined #{time_ago_with_tooltip(group.created_at)}
|
||||||
|
- if group_link.expires?
|
||||||
|
·
|
||||||
|
%span{ class: ('text-warning' if group_link.expires_soon?) }
|
||||||
|
Expires in #{distance_of_time_in_words_to_now(group_link.expires_at)}
|
||||||
|
.controls.member-controls
|
||||||
|
= form_tag namespace_project_group_link_path(@project.namespace, @project, group_link), method: :put, remote: true, class: 'form-horizontal' do
|
||||||
|
= select_tag 'group_link[group_access]', options_for_select(ProjectGroupLink.access_options, group_link.group_access), class: 'form-control member-form-control append-right-5 js-member-update-control', id: "member_access_level_#{group.id}"
|
||||||
|
.prepend-left-5.append-right-10.clearable-input.member-form-control
|
||||||
|
= text_field_tag 'group_link[expires_at]', group_link.expires_at, class: 'form-control js-access-expiration-date js-member-update-control', placeholder: 'Expiration date', id: "member_expires_at_#{group.id}"
|
||||||
|
%i.clear-icon.js-clear-input
|
||||||
|
= link_to icon('trash'), namespace_project_group_link_path(@project.namespace, @project, group_link),
|
||||||
|
remote: true,
|
||||||
|
method: :delete,
|
||||||
|
class: 'btn btn-remove'
|
|
@ -3,43 +3,6 @@
|
||||||
- user = member.user
|
- user = member.user
|
||||||
|
|
||||||
%li.member{ class: dom_class(member), id: dom_id(member) }
|
%li.member{ class: dom_class(member), id: dom_id(member) }
|
||||||
- if show_roles
|
|
||||||
.controls
|
|
||||||
- if show_controls
|
|
||||||
- if @project.owner != user
|
|
||||||
= form_for member, remote: true, html: { class: 'form-horizontal' } do |f|
|
|
||||||
= f.select :access_level, options_for_select(member.class.access_level_roles, member.access_level), {}, class: 'form-control member-form-control append-right-5 js-member-update-control', id: "member_access_level_#{member.id}", disabled: !can?(current_user, action_member_permission(:update, member), member)
|
|
||||||
.prepend-left-5.append-right-10.clearable-input.member-form-control
|
|
||||||
= f.text_field :expires_at, class: 'form-control js-access-expiration-date js-member-update-control', placeholder: 'Expiration date', id: "member_expires_at_#{member.id}", disabled: !can?(current_user, action_member_permission(:update, member), member)
|
|
||||||
%i.clear-icon.js-clear-input
|
|
||||||
- if !user && can?(current_user, action_member_permission(:admin, member), member.source)
|
|
||||||
= link_to 'Resend invite', polymorphic_path([:resend_invite, member]),
|
|
||||||
method: :post,
|
|
||||||
class: 'btn'
|
|
||||||
- else
|
|
||||||
Owner
|
|
||||||
|
|
||||||
- if member.request? && can?(current_user, action_member_permission(:update, member), member)
|
|
||||||
= link_to icon('check inverse'), polymorphic_path([:approve_access_request, member]),
|
|
||||||
method: :post,
|
|
||||||
class: 'btn btn-success',
|
|
||||||
title: 'Grant access'
|
|
||||||
|
|
||||||
- if can?(current_user, action_member_permission(:destroy, member), member)
|
|
||||||
- if current_user == user
|
|
||||||
= link_to icon('sign-out', text: 'Leave'), polymorphic_path([:leave, member.source, :members]),
|
|
||||||
method: :delete,
|
|
||||||
data: { confirm: leave_confirmation_message(member.source) },
|
|
||||||
class: 'btn btn-remove'
|
|
||||||
- else
|
|
||||||
= link_to icon('trash'), member,
|
|
||||||
remote: true,
|
|
||||||
method: :delete,
|
|
||||||
data: { confirm: remove_member_message(member) },
|
|
||||||
class: 'btn btn-remove',
|
|
||||||
title: remove_member_title(member)
|
|
||||||
|
|
||||||
|
|
||||||
%span{ class: ("list-item-name" if show_controls) }
|
%span{ class: ("list-item-name" if show_controls) }
|
||||||
- if user
|
- if user
|
||||||
= image_tag avatar_icon(user, 40), class: "avatar s40", alt: ''
|
= image_tag avatar_icon(user, 40), class: "avatar s40", alt: ''
|
||||||
|
@ -74,3 +37,35 @@
|
||||||
by
|
by
|
||||||
= link_to member.created_by.name, user_path(member.created_by)
|
= link_to member.created_by.name, user_path(member.created_by)
|
||||||
= time_ago_with_tooltip(member.created_at)
|
= time_ago_with_tooltip(member.created_at)
|
||||||
|
- if show_roles
|
||||||
|
.controls.member-controls
|
||||||
|
- if show_controls
|
||||||
|
= form_for member, remote: true, html: { class: 'form-horizontal' } do |f|
|
||||||
|
= f.select :access_level, options_for_select(member.class.access_level_roles, member.access_level), {}, class: 'form-control member-form-control append-right-5 js-member-update-control', id: "member_access_level_#{member.id}", disabled: !can?(current_user, action_member_permission(:update, member), member)
|
||||||
|
.prepend-left-5.append-right-10.clearable-input.member-form-control
|
||||||
|
= f.text_field :expires_at, class: 'form-control js-access-expiration-date js-member-update-control', placeholder: 'Expiration date', id: "member_expires_at_#{member.id}", disabled: !can?(current_user, action_member_permission(:update, member), member)
|
||||||
|
%i.clear-icon.js-clear-input
|
||||||
|
- if !user && can?(current_user, action_member_permission(:admin, member), member.source)
|
||||||
|
= link_to 'Resend invite', polymorphic_path([:resend_invite, member]),
|
||||||
|
method: :post,
|
||||||
|
class: 'btn'
|
||||||
|
|
||||||
|
- if member.request? && can?(current_user, action_member_permission(:update, member), member)
|
||||||
|
= link_to icon('check inverse'), polymorphic_path([:approve_access_request, member]),
|
||||||
|
method: :post,
|
||||||
|
class: 'btn btn-success',
|
||||||
|
title: 'Grant access'
|
||||||
|
|
||||||
|
- if can?(current_user, action_member_permission(:destroy, member), member)
|
||||||
|
- if current_user == user
|
||||||
|
= link_to icon('sign-out', text: 'Leave'), polymorphic_path([:leave, member.source, :members]),
|
||||||
|
method: :delete,
|
||||||
|
data: { confirm: leave_confirmation_message(member.source) },
|
||||||
|
class: 'btn btn-remove'
|
||||||
|
- else
|
||||||
|
= link_to icon('trash'), member,
|
||||||
|
remote: true,
|
||||||
|
method: :delete,
|
||||||
|
data: { confirm: remove_member_message(member) },
|
||||||
|
class: 'btn btn-remove',
|
||||||
|
title: remove_member_title(member)
|
||||||
|
|
|
@ -867,7 +867,7 @@ Rails.application.routes.draw do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
resources :group_links, only: [:index, :create, :destroy], constraints: { id: /\d+/ }
|
resources :group_links, only: [:index, :create, :update, :destroy], constraints: { id: /\d+/ }
|
||||||
|
|
||||||
resources :notes, only: [:index, :create, :destroy, :update], constraints: { id: /\d+/ } do
|
resources :notes, only: [:index, :create, :destroy, :update], constraints: { id: /\d+/ } do
|
||||||
member do
|
member do
|
||||||
|
|
Loading…
Reference in a new issue