diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss
index 965fcc06518a350e0ee4a6836911757e5ce16274..dfdfe4a3c8978f4f56c57b8c1ecd9cdddc10c9e9 100644
--- a/app/assets/stylesheets/framework/lists.scss
+++ b/app/assets/stylesheets/framework/lists.scss
@@ -164,6 +164,14 @@ ul.content-list {
       }
     }
 
+    .member-controls {
+      float: none;
+      
+      @media (min-width: $screen-md-min) {
+        float: right;
+      }
+    }
+
     // When dragging a list item
     &.ui-sortable-helper {
       border-bottom: none;
diff --git a/app/assets/stylesheets/pages/groups.scss b/app/assets/stylesheets/pages/groups.scss
index b657ca47d38637753b44b19f31b97eea54a3c1cf..a27f7a2fd77deabd4288c5b40a27d79f9b21b587 100644
--- a/app/assets/stylesheets/pages/groups.scss
+++ b/app/assets/stylesheets/pages/groups.scss
@@ -1,6 +1,4 @@
 .member-search-form {
-  float: left;
-
   input[type='search'] {
     width: 225px;
     vertical-align: bottom;
diff --git a/app/assets/stylesheets/pages/members.scss b/app/assets/stylesheets/pages/members.scss
index 9583d7c61613d0bee646a10acfad64d382ef8133..4bc34ac15dfd7b75f01800082f33bec9a70a1d0c 100644
--- a/app/assets/stylesheets/pages/members.scss
+++ b/app/assets/stylesheets/pages/members.scss
@@ -5,6 +5,15 @@
 }
 
 .member {
+  .list-item-name {
+    float: none;
+
+    @media (min-width: $screen-md-min) {
+      float: left;
+      width: 50%;
+    }
+  }
+
   .controls {
     display: flex;
     width: 400px;
diff --git a/app/controllers/projects/group_links_controller.rb b/app/controllers/projects/group_links_controller.rb
index d0c4550733c6ddae4629ab0804e40e0f98897809..57c54bf625a55ab758bf52f26aceeb40926f28cc 100644
--- a/app/controllers/projects/group_links_controller.rb
+++ b/app/controllers/projects/group_links_controller.rb
@@ -19,9 +19,21 @@ class Projects::GroupLinksController < Projects::ApplicationController
     redirect_to namespace_project_group_links_path(project.namespace, project)
   end
 
+  def update
+    @group_link = @project.project_group_links.find(params[:id])
+
+    @group_link.update_attributes(group_link_params)
+  end
+
   def destroy
     project.project_group_links.find(params[:id]).destroy
 
     redirect_to namespace_project_group_links_path(project.namespace, project)
   end
+
+  protected
+
+  def group_link_params
+    params.require(:group_link).permit(:group_access, :expires_at)
+  end
 end
diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb
index 42a7e5a2c30d6fe3e0bfa9ef8a16738cf59f3ca2..d83e95cf097603cb9d160c6358da6d0c0bde2550 100644
--- a/app/controllers/projects/project_members_controller.rb
+++ b/app/controllers/projects/project_members_controller.rb
@@ -5,6 +5,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController
   before_action :authorize_admin_project_member!, except: [:index, :leave, :request_access]
 
   def index
+    @groups = @project.project_group_links.all
     @project_members = @project.project_members
     @project_members = @project_members.non_invite unless can?(current_user, :admin_project, @project)
 
diff --git a/app/views/projects/group_links/update.js.haml b/app/views/projects/group_links/update.js.haml
new file mode 100644
index 0000000000000000000000000000000000000000..d3a37847f5804643156b793ed4d355e38f6fea5a
--- /dev/null
+++ b/app/views/projects/group_links/update.js.haml
@@ -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'));
diff --git a/app/views/projects/project_members/_group_members.html.haml b/app/views/projects/project_members/_group_members.html.haml
index e783d8c72c52dd82190f1b21c48844555e7910fb..9738f369a35368d50cbb842893b7b4698066df3b 100644
--- a/app/views/projects/project_members/_group_members.html.haml
+++ b/app/views/projects/project_members/_group_members.html.haml
@@ -1,7 +1,7 @@
 .panel.panel-default
   .panel-heading
+    Group members with access to
     %strong #{@group.name}
-    group members
     %span.badge= members.size
     - if can?(current_user, :admin_group_member, @group)
       .controls
diff --git a/app/views/projects/project_members/_groups.html.haml b/app/views/projects/project_members/_groups.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..79791af7963a6c0827360c1fcb004e9c5c8bf6c4
--- /dev/null
+++ b/app/views/projects/project_members/_groups.html.haml
@@ -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
diff --git a/app/views/projects/project_members/_team.html.haml b/app/views/projects/project_members/_team.html.haml
index db6c1194da72e8e5f1b2e0c0ae1bfd71212432b6..6a8b28d38869f591ea6fd70e861d746f1af9a14a 100644
--- a/app/views/projects/project_members/_team.html.haml
+++ b/app/views/projects/project_members/_team.html.haml
@@ -3,17 +3,5 @@
     Users with access to
     %strong #{@project.name}
     %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
     = 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());
-  });
diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml
index 9d47e7d725c104bf9f81aaf0bda00a736cf32751..db8a060d170c490958d03c1b3909a8a5c02aa087 100644
--- a/app/views/projects/project_members/index.html.haml
+++ b/app/views/projects/project_members/index.html.haml
@@ -14,12 +14,16 @@
 
       = render 'shared/members/requests', membership_source: @project, requesters: @requesters
 
-  %h5.append-bottom-default
-    Existing users and groups
+  .append-bottom-default.clearfix
+    %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
 
   - if @group
     = render "group_members", members: @group_members
-
-  - if @project_group_links.any? && @project.allowed_to_share_with_group?
-    = render "shared_group_members"
diff --git a/app/views/shared/members/_group.html.haml b/app/views/shared/members/_group.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..0502de5210b5ad6dac6991c225b07bee4e6a7ff0
--- /dev/null
+++ b/app/views/shared/members/_group.html.haml
@@ -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'
diff --git a/app/views/shared/members/_member.html.haml b/app/views/shared/members/_member.html.haml
index fd9b688dc2040f757c09dcf432bf663ebf2e8b99..800badc051a588062c895874a6448612a102674c 100644
--- a/app/views/shared/members/_member.html.haml
+++ b/app/views/shared/members/_member.html.haml
@@ -3,43 +3,6 @@
 - user = member.user
 
 %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) }
     - if user
       = image_tag avatar_icon(user, 40), class: "avatar s40", alt: ''
@@ -74,3 +37,35 @@
           by
           = link_to member.created_by.name, user_path(member.created_by)
         = 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)
diff --git a/config/routes.rb b/config/routes.rb
index 068c92d1400e1fb7e5000f799949ea01c7c2196a..441f7249aa86b6d00ac601280f97fab34228a733 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -867,7 +867,7 @@ Rails.application.routes.draw do
           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
           member do