Security Dashboard as default view for groups
Add a supporting code to separate groups#show and groups#details which is required for the proper implementation of the Group Overview content and Security Dashboard option for it
This commit is contained in:
parent
b5bf179e69
commit
6ab102a2f8
12 changed files with 116 additions and 41 deletions
5
app/assets/javascripts/pages/groups/details/index.js
Normal file
5
app/assets/javascripts/pages/groups/details/index.js
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import initGroupDetails from '../shared/group_details';
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
initGroupDetails('details');
|
||||||
|
});
|
31
app/assets/javascripts/pages/groups/shared/group_details.js
Normal file
31
app/assets/javascripts/pages/groups/shared/group_details.js
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
/* eslint-disable no-new */
|
||||||
|
|
||||||
|
import { getPagePath } from '~/lib/utils/common_utils';
|
||||||
|
import { ACTIVE_TAB_SHARED, ACTIVE_TAB_ARCHIVED } from '~/groups/constants';
|
||||||
|
import NewGroupChild from '~/groups/new_group_child';
|
||||||
|
import notificationsDropdown from '~/notifications_dropdown';
|
||||||
|
import NotificationsForm from '~/notifications_form';
|
||||||
|
import ProjectsList from '~/projects_list';
|
||||||
|
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
|
||||||
|
import GroupTabs from './group_tabs';
|
||||||
|
|
||||||
|
export default function initGroupDetails(actionName = 'show') {
|
||||||
|
const newGroupChildWrapper = document.querySelector('.js-new-project-subgroup');
|
||||||
|
const loadableActions = [ACTIVE_TAB_SHARED, ACTIVE_TAB_ARCHIVED];
|
||||||
|
const paths = window.location.pathname.split('/');
|
||||||
|
const subpath = paths[paths.length - 1];
|
||||||
|
let action = loadableActions.includes(subpath) ? subpath : getPagePath(1);
|
||||||
|
if (actionName && action === actionName) {
|
||||||
|
action = 'show'; // 'show' resets GroupTabs to default action through base class
|
||||||
|
}
|
||||||
|
|
||||||
|
new GroupTabs({ parentEl: '.groups-listing', action });
|
||||||
|
new ShortcutsNavigation();
|
||||||
|
new NotificationsForm();
|
||||||
|
notificationsDropdown();
|
||||||
|
new ProjectsList();
|
||||||
|
|
||||||
|
if (newGroupChildWrapper) {
|
||||||
|
new NewGroupChild(newGroupChildWrapper);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,28 +1,5 @@
|
||||||
/* eslint-disable no-new */
|
import initGroupDetails from '../shared/group_details';
|
||||||
|
|
||||||
import { getPagePath } from '~/lib/utils/common_utils';
|
|
||||||
import { ACTIVE_TAB_SHARED, ACTIVE_TAB_ARCHIVED } from '~/groups/constants';
|
|
||||||
import NewGroupChild from '~/groups/new_group_child';
|
|
||||||
import notificationsDropdown from '~/notifications_dropdown';
|
|
||||||
import NotificationsForm from '~/notifications_form';
|
|
||||||
import ProjectsList from '~/projects_list';
|
|
||||||
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
|
|
||||||
import GroupTabs from './group_tabs';
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
const newGroupChildWrapper = document.querySelector('.js-new-project-subgroup');
|
initGroupDetails();
|
||||||
const loadableActions = [ACTIVE_TAB_SHARED, ACTIVE_TAB_ARCHIVED];
|
|
||||||
const paths = window.location.pathname.split('/');
|
|
||||||
const subpath = paths[paths.length - 1];
|
|
||||||
const action = loadableActions.includes(subpath) ? subpath : getPagePath(1);
|
|
||||||
|
|
||||||
new GroupTabs({ parentEl: '.groups-listing', action });
|
|
||||||
new ShortcutsNavigation();
|
|
||||||
new NotificationsForm();
|
|
||||||
notificationsDropdown();
|
|
||||||
new ProjectsList();
|
|
||||||
|
|
||||||
if (newGroupChildWrapper) {
|
|
||||||
new NewGroupChild(newGroupChildWrapper);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -91,6 +91,7 @@ export default class UserTabs {
|
||||||
this.actions = Object.keys(this.loaded);
|
this.actions = Object.keys(this.loaded);
|
||||||
this.bindEvents();
|
this.bindEvents();
|
||||||
|
|
||||||
|
// TODO: refactor to make this configurable via constructor params with a default value of 'show'
|
||||||
if (this.action === 'show') {
|
if (this.action === 'show') {
|
||||||
this.action = this.defaultAction;
|
this.action = this.defaultAction;
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,11 +58,24 @@ class GroupsController < Groups::ApplicationController
|
||||||
|
|
||||||
def show
|
def show
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html
|
format.html do
|
||||||
|
render_show_html
|
||||||
|
end
|
||||||
|
|
||||||
format.atom do
|
format.atom do
|
||||||
load_events
|
render_details_view_atom
|
||||||
render layout: 'xml.atom'
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def details
|
||||||
|
respond_to do |format|
|
||||||
|
format.html do
|
||||||
|
render_details_html
|
||||||
|
end
|
||||||
|
|
||||||
|
format.atom do
|
||||||
|
render_details_view_atom
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -119,6 +132,19 @@ class GroupsController < Groups::ApplicationController
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
|
def render_show_html
|
||||||
|
render 'groups/show'
|
||||||
|
end
|
||||||
|
|
||||||
|
def render_details_html
|
||||||
|
render 'groups/show'
|
||||||
|
end
|
||||||
|
|
||||||
|
def render_details_view_atom
|
||||||
|
load_events
|
||||||
|
render layout: 'xml.atom', template: 'groups/show'
|
||||||
|
end
|
||||||
|
|
||||||
# rubocop: disable CodeReuse/ActiveRecord
|
# rubocop: disable CodeReuse/ActiveRecord
|
||||||
def authorize_create_group!
|
def authorize_create_group!
|
||||||
allowed = if params[:parent_id].present?
|
allowed = if params[:parent_id].present?
|
||||||
|
@ -178,8 +204,8 @@ class GroupsController < Groups::ApplicationController
|
||||||
.includes(:namespace)
|
.includes(:namespace)
|
||||||
|
|
||||||
@events = EventCollection
|
@events = EventCollection
|
||||||
.new(@projects, offset: params[:offset].to_i, filter: event_filter)
|
.new(@projects, offset: params[:offset].to_i, filter: event_filter)
|
||||||
.to_a
|
.to_a
|
||||||
|
|
||||||
Events::RenderService
|
Events::RenderService
|
||||||
.new(current_user)
|
.new(current_user)
|
||||||
|
|
|
@ -4,6 +4,7 @@ module GroupsHelper
|
||||||
def group_overview_nav_link_paths
|
def group_overview_nav_link_paths
|
||||||
%w[
|
%w[
|
||||||
groups#show
|
groups#show
|
||||||
|
groups#details
|
||||||
groups#activity
|
groups#activity
|
||||||
groups#subgroups
|
groups#subgroups
|
||||||
analytics#show
|
analytics#show
|
||||||
|
|
|
@ -20,13 +20,14 @@
|
||||||
= _('Overview')
|
= _('Overview')
|
||||||
|
|
||||||
%ul.sidebar-sub-level-items
|
%ul.sidebar-sub-level-items
|
||||||
= nav_link(path: ['groups#show', 'groups#activity', 'groups#subgroups'], html_options: { class: "fly-out-top-item" } ) do
|
= nav_link(path: ['groups#show', 'groups#details', 'groups#activity', 'groups#subgroups'], html_options: { class: "fly-out-top-item" } ) do
|
||||||
= link_to group_path(@group) do
|
= link_to group_path(@group) do
|
||||||
%strong.fly-out-top-item-name
|
%strong.fly-out-top-item-name
|
||||||
= _('Overview')
|
= _('Overview')
|
||||||
%li.divider.fly-out-top-item
|
%li.divider.fly-out-top-item
|
||||||
= nav_link(path: ['groups#show', 'groups#subgroups'], html_options: { class: 'home' }) do
|
|
||||||
= link_to group_path(@group), title: _('Group details') do
|
= nav_link(path: ['groups#show', 'groups#details', 'groups#subgroups'], html_options: { class: 'home' }) do
|
||||||
|
= link_to details_group_path(@group), title: _('Group details') do
|
||||||
%span
|
%span
|
||||||
= _('Details')
|
= _('Details')
|
||||||
|
|
||||||
|
@ -40,9 +41,9 @@
|
||||||
|
|
||||||
- if group_sidebar_link?(:contribution_analytics)
|
- if group_sidebar_link?(:contribution_analytics)
|
||||||
= nav_link(path: 'analytics#show') do
|
= nav_link(path: 'analytics#show') do
|
||||||
= link_to group_analytics_path(@group), title: 'Contribution Analytics', data: {placement: 'right'} do
|
= link_to group_analytics_path(@group), title: _('Contribution Analytics'), data: { placement: 'right' } do
|
||||||
%span
|
%span
|
||||||
Contribution Analytics
|
= _('Contribution Analytics')
|
||||||
|
|
||||||
= render_if_exists "layouts/nav/ee/epic_link", group: @group
|
= render_if_exists "layouts/nav/ee/epic_link", group: @group
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ constraints(::Constraints::GroupUrlConstrainer.new) do
|
||||||
get :issues, as: :issues_group
|
get :issues, as: :issues_group
|
||||||
get :merge_requests, as: :merge_requests_group
|
get :merge_requests, as: :merge_requests_group
|
||||||
get :projects, as: :projects_group
|
get :projects, as: :projects_group
|
||||||
|
get :details, as: :details_group
|
||||||
get :activity, as: :activity_group
|
get :activity, as: :activity_group
|
||||||
put :transfer, as: :transfer_group
|
put :transfer, as: :transfer_group
|
||||||
# TODO: Remove as part of refactor in https://gitlab.com/gitlab-org/gitlab-ce/issues/49693
|
# TODO: Remove as part of refactor in https://gitlab.com/gitlab-org/gitlab-ce/issues/49693
|
||||||
|
|
|
@ -2315,6 +2315,9 @@ msgstr ""
|
||||||
msgid "Contribution"
|
msgid "Contribution"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Contribution Analytics"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Contribution Charts"
|
msgid "Contribution Charts"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -32,21 +32,46 @@ describe GroupsController do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
shared_examples 'details view' do
|
||||||
|
it { is_expected.to render_template('groups/show') }
|
||||||
|
|
||||||
|
context 'as atom' do
|
||||||
|
let!(:event) { create(:event, project: project) }
|
||||||
|
let(:format) { :atom }
|
||||||
|
|
||||||
|
it { is_expected.to render_template('groups/show') }
|
||||||
|
|
||||||
|
it 'assigns events for all the projects in the group' do
|
||||||
|
subject
|
||||||
|
expect(assigns(:events)).to contain_exactly(event)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe 'GET #show' do
|
describe 'GET #show' do
|
||||||
before do
|
before do
|
||||||
sign_in(user)
|
sign_in(user)
|
||||||
project
|
project
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'as atom' do
|
let(:format) { :html }
|
||||||
it 'assigns events for all the projects in the group' do
|
|
||||||
create(:event, project: project)
|
|
||||||
|
|
||||||
get :show, params: { id: group.to_param }, format: :atom
|
subject { get :show, params: { id: group.to_param }, format: format }
|
||||||
|
|
||||||
expect(assigns(:events)).not_to be_empty
|
it_behaves_like 'details view'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'GET #details' do
|
||||||
|
before do
|
||||||
|
sign_in(user)
|
||||||
|
project
|
||||||
end
|
end
|
||||||
|
|
||||||
|
let(:format) { :html }
|
||||||
|
|
||||||
|
subject { get :details, params: { id: group.to_param }, format: format }
|
||||||
|
|
||||||
|
it_behaves_like 'details view'
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'GET edit' do
|
describe 'GET edit' do
|
||||||
|
|
|
@ -17,6 +17,10 @@ describe "Groups", "routing" do
|
||||||
expect(get("/#{group_path}")).to route_to('groups#show', id: group_path)
|
expect(get("/#{group_path}")).to route_to('groups#show', id: group_path)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "to #details" do
|
||||||
|
expect(get("/groups/#{group_path}/-/details")).to route_to('groups#details', id: group_path)
|
||||||
|
end
|
||||||
|
|
||||||
it "to #activity" do
|
it "to #activity" do
|
||||||
expect(get("/groups/#{group_path}/-/activity")).to route_to('groups#activity', id: group_path)
|
expect(get("/groups/#{group_path}/-/activity")).to route_to('groups#activity', id: group_path)
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue