Merge branch 'dz-create-nested-groups-via-ui' into 'master'
Allow creating nested group via UI See merge request !8786
This commit is contained in:
commit
059d1ae4c8
11 changed files with 115 additions and 54 deletions
|
@ -13,9 +13,11 @@ class GroupsController < Groups::ApplicationController
|
|||
before_action :authorize_create_group!, only: [:new, :create]
|
||||
|
||||
# Load group projects
|
||||
before_action :group_projects, only: [:show, :projects, :activity, :issues, :merge_requests]
|
||||
before_action :group_projects, only: [:projects, :activity, :issues, :merge_requests]
|
||||
before_action :event_filter, only: [:activity]
|
||||
|
||||
before_action :user_actions, only: [:show, :subgroups]
|
||||
|
||||
layout :determine_layout
|
||||
|
||||
def index
|
||||
|
@ -37,13 +39,6 @@ class GroupsController < Groups::ApplicationController
|
|||
end
|
||||
|
||||
def show
|
||||
if current_user
|
||||
@last_push = current_user.recent_push
|
||||
@notification_setting = current_user.notification_settings_for(group)
|
||||
end
|
||||
|
||||
@nested_groups = group.children
|
||||
|
||||
setup_projects
|
||||
|
||||
respond_to do |format|
|
||||
|
@ -62,6 +57,11 @@ class GroupsController < Groups::ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def subgroups
|
||||
@nested_groups = group.children
|
||||
@nested_groups = @nested_groups.search(params[:filter_groups]) if params[:filter_groups].present?
|
||||
end
|
||||
|
||||
def activity
|
||||
respond_to do |format|
|
||||
format.html
|
||||
|
@ -99,13 +99,16 @@ class GroupsController < Groups::ApplicationController
|
|||
protected
|
||||
|
||||
def setup_projects
|
||||
options = {}
|
||||
options[:only_owned] = true if params[:shared] == '0'
|
||||
options[:only_shared] = true if params[:shared] == '1'
|
||||
|
||||
@projects = GroupProjectsFinder.new(group, options).execute(current_user)
|
||||
@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!
|
||||
|
@ -138,7 +141,8 @@ class GroupsController < Groups::ApplicationController
|
|||
:public,
|
||||
:request_access_enabled,
|
||||
:share_with_group_lock,
|
||||
:visibility_level
|
||||
:visibility_level,
|
||||
:parent_id
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -147,4 +151,11 @@ class GroupsController < Groups::ApplicationController
|
|||
@events = event_filter.apply_filter(@events).with_associations
|
||||
@events = @events.limit(20).offset(params[:offset] || 0)
|
||||
end
|
||||
|
||||
def user_actions
|
||||
if current_user
|
||||
@last_push = current_user.recent_push
|
||||
@notification_setting = current_user.notification_settings_for(group)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
17
app/views/groups/_home_panel.html.haml
Normal file
17
app/views/groups/_home_panel.html.haml
Normal file
|
@ -0,0 +1,17 @@
|
|||
.group-home-panel.text-center
|
||||
%div{ class: container_class }
|
||||
.avatar-container.s70.group-avatar
|
||||
= image_tag group_icon(@group), class: "avatar s70 avatar-tile"
|
||||
%h1.group-title
|
||||
@#{@group.path}
|
||||
%span.visibility-icon.has-tooltip{ data: { container: 'body' }, title: visibility_icon_description(@group) }
|
||||
= visibility_level_icon(@group.visibility_level, fw: false)
|
||||
|
||||
- if @group.description.present?
|
||||
.group-home-desc
|
||||
= markdown_field(@group, :description)
|
||||
|
||||
- if current_user
|
||||
.group-buttons
|
||||
= render 'shared/members/access_request_buttons', source: @group
|
||||
= render 'shared/notifications/button', notification_setting: @notification_setting
|
7
app/views/groups/_show_nav.html.haml
Normal file
7
app/views/groups/_show_nav.html.haml
Normal file
|
@ -0,0 +1,7 @@
|
|||
%ul.nav-links
|
||||
= nav_link(page: group_path(@group)) do
|
||||
= link_to group_path(@group) do
|
||||
Projects
|
||||
= nav_link(page: subgroups_group_path(@group)) do
|
||||
= link_to subgroups_group_path(@group) do
|
||||
Subgroups
|
|
@ -4,38 +4,12 @@
|
|||
- if current_user
|
||||
= auto_discovery_link_tag(:atom, group_url(@group, format: :atom, private_token: current_user.private_token), title: "#{@group.name} activity")
|
||||
|
||||
.group-home-panel.text-center
|
||||
%div{ class: container_class }
|
||||
.avatar-container.s70.group-avatar
|
||||
= image_tag group_icon(@group), class: "avatar s70 avatar-tile"
|
||||
%h1.group-title
|
||||
@#{@group.path}
|
||||
%span.visibility-icon.has-tooltip{ data: { container: 'body' }, title: visibility_icon_description(@group) }
|
||||
= visibility_level_icon(@group.visibility_level, fw: false)
|
||||
= render 'groups/home_panel'
|
||||
|
||||
- if @group.description.present?
|
||||
.group-home-desc
|
||||
= markdown_field(@group, :description)
|
||||
|
||||
- if current_user
|
||||
.group-buttons
|
||||
= render 'shared/members/access_request_buttons', source: @group
|
||||
= render 'shared/notifications/button', notification_setting: @notification_setting
|
||||
|
||||
.groups-header{ class: container_class }
|
||||
.top-area
|
||||
%ul.nav-links
|
||||
%li.active
|
||||
= link_to "#projects", 'data-toggle' => 'tab' do
|
||||
All Projects
|
||||
- if @shared_projects.present?
|
||||
%li
|
||||
= link_to "#shared", 'data-toggle' => 'tab' do
|
||||
Shared Projects
|
||||
- if @nested_groups.present?
|
||||
%li
|
||||
= link_to "#groups", 'data-toggle' => 'tab' do
|
||||
Subgroups
|
||||
= render 'groups/show_nav'
|
||||
.nav-controls
|
||||
= form_tag request.path, method: :get, class: 'project-filter-form', id: 'project-filter-form' do |f|
|
||||
= search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control', spellcheck: false
|
||||
|
@ -44,15 +18,4 @@
|
|||
= link_to new_project_path(namespace_id: @group.id), class: 'btn btn-new pull-right' do
|
||||
New Project
|
||||
|
||||
.tab-content
|
||||
.tab-pane.active#projects
|
||||
= render "projects", projects: @projects
|
||||
|
||||
- if @shared_projects.present?
|
||||
.tab-pane#shared
|
||||
= render "shared_projects", projects: @shared_projects
|
||||
|
||||
- if @nested_groups.present?
|
||||
.tab-pane#groups
|
||||
%ul.content-list
|
||||
= render partial: 'shared/groups/group', collection: @nested_groups
|
||||
= render "projects", projects: @projects
|
||||
|
|
20
app/views/groups/subgroups.html.haml
Normal file
20
app/views/groups/subgroups.html.haml
Normal file
|
@ -0,0 +1,20 @@
|
|||
- @no_container = true
|
||||
|
||||
= render 'groups/home_panel'
|
||||
|
||||
.groups-header{ class: container_class }
|
||||
.top-area
|
||||
= render 'groups/show_nav'
|
||||
.nav-controls
|
||||
= form_tag request.path, method: :get do |f|
|
||||
= search_field_tag :filter_groups, params[:filter_groups], placeholder: 'Filter by name', class: 'form-control', spellcheck: false
|
||||
- if can? current_user, :admin_group, @group
|
||||
= link_to new_group_path(parent_id: @group.id), class: 'btn btn-new pull-right' do
|
||||
New Subgroup
|
||||
|
||||
- if @nested_groups.present?
|
||||
%ul.content-list
|
||||
= render partial: 'shared/groups/group', collection: @nested_groups, locals: { full_name: false }
|
||||
- else
|
||||
.nothing-here-block
|
||||
There are no subgroups to show.
|
|
@ -1,3 +1,4 @@
|
|||
- parent = Group.find_by(id: params[:parent_id] || @group.parent_id)
|
||||
- if @group.persisted?
|
||||
.form-group
|
||||
= f.label :name, class: 'control-label' do
|
||||
|
@ -11,11 +12,15 @@
|
|||
.col-sm-10
|
||||
.input-group.gl-field-error-anchor
|
||||
.input-group-addon
|
||||
= root_url
|
||||
%span>= root_url
|
||||
- if parent
|
||||
%strong= parent.full_path + '/'
|
||||
= f.text_field :path, placeholder: 'open-source', class: 'form-control',
|
||||
autofocus: local_assigns[:autofocus] || false, required: true,
|
||||
pattern: Gitlab::Regex::NAMESPACE_REGEX_STR_SIMPLE,
|
||||
title: 'Please choose a group name with no special characters.'
|
||||
- if parent
|
||||
= f.hidden_field :parent_id, value: parent.id
|
||||
|
||||
- if @group.persisted?
|
||||
.alert.alert-warning.prepend-top-10
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
- group_member = local_assigns[:group_member]
|
||||
- full_name = true unless local_assigns[:full_name] == false
|
||||
- css_class = '' unless local_assigns[:css_class]
|
||||
- css_class += " no-description" if group.description.blank?
|
||||
|
||||
|
@ -28,7 +29,10 @@
|
|||
= image_tag group_icon(group), class: "avatar s40 hidden-xs"
|
||||
.title
|
||||
= link_to group, class: 'group-name' do
|
||||
= group.full_name
|
||||
- if full_name
|
||||
= group.full_name
|
||||
- else
|
||||
= group.name
|
||||
|
||||
- if group_member
|
||||
as
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
- @sort ||= sort_value_recently_updated
|
||||
- personal = params[:personal]
|
||||
- archived = params[:archived]
|
||||
- shared = params[:shared]
|
||||
- namespace_id = params[:namespace_id]
|
||||
.dropdown
|
||||
- toggle_text = projects_sort_options_hash[@sort]
|
||||
|
@ -28,3 +29,14 @@
|
|||
%li
|
||||
= link_to filter_projects_path(namespace_id: namespace_id, sort: @sort, personal: true), class: ("is-active" if personal.present?) do
|
||||
Owned by me
|
||||
- if @group && @group.shared_projects.present?
|
||||
%li.divider
|
||||
%li
|
||||
= link_to filter_projects_path(namespace_id: namespace_id, sort: @sort, shared: nil), class: ("is-active" unless shared.present?) do
|
||||
All projects
|
||||
%li
|
||||
= link_to filter_projects_path(namespace_id: namespace_id, sort: @sort, shared: 0), class: ("is-active" if shared == '0') do
|
||||
Hide shared projects
|
||||
%li
|
||||
= link_to filter_projects_path(namespace_id: namespace_id, sort: @sort, shared: 1), class: ("is-active" if shared == '1') do
|
||||
Hide group projects
|
||||
|
|
4
changelogs/unreleased/dz-create-nested-groups-via-ui.yml
Normal file
4
changelogs/unreleased/dz-create-nested-groups-via-ui.yml
Normal file
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Allow creating nested groups via UI
|
||||
merge_request: 8786
|
||||
author:
|
|
@ -25,5 +25,6 @@ scope(path: 'groups/*id',
|
|||
get :merge_requests, as: :merge_requests_group
|
||||
get :projects, as: :projects_group
|
||||
get :activity, as: :activity_group
|
||||
get :subgroups, as: :subgroups_group
|
||||
get '/', action: :show, as: :group_canonical
|
||||
end
|
||||
|
|
|
@ -45,6 +45,23 @@ feature 'Group', feature: true do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'create a nested group' do
|
||||
let(:group) { create(:group, path: 'foo') }
|
||||
|
||||
before do
|
||||
visit subgroups_group_path(group)
|
||||
click_link 'New Subgroup'
|
||||
end
|
||||
|
||||
it 'creates a nested group' do
|
||||
fill_in 'Group path', with: 'bar'
|
||||
click_button 'Create group'
|
||||
|
||||
expect(current_path).to eq(group_path('foo/bar'))
|
||||
expect(page).to have_content("Group 'bar' was successfully created.")
|
||||
end
|
||||
end
|
||||
|
||||
describe 'group edit' do
|
||||
let(:group) { create(:group) }
|
||||
let(:path) { edit_group_path(group) }
|
||||
|
@ -117,7 +134,7 @@ feature 'Group', feature: true do
|
|||
visit path
|
||||
click_link 'Subgroups'
|
||||
|
||||
expect(page).to have_content(nested_group.full_name)
|
||||
expect(page).to have_content(nested_group.name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue