Commit b06b17c3 authored by Kushal Pandya's avatar Kushal Pandya

Merge branch '230413-remove-edit-dashboard-button' into 'master'

Remove project selector logic from dashboard

See merge request gitlab-org/gitlab!39631
parents cf00a6bc 92fc5fc3
......@@ -131,14 +131,14 @@ bar at the top of the page. Under **More**, select **Security**.
To add projects to the dashboard:
1. Click the **Edit dashboard** button on the Instance Security Dashboard page.
1. Click **Settings** in the left navigation bar.
1. Search for and add one or more projects using the **Search your projects** field.
1. Click the **Add projects** button.
Once added, the Security Dashboard displays the vulnerabilities found in your chosen projects'
After you add projects, the Security Dashboard displays the vulnerabilities found in those projects'
default branches.
![Instance Security Dashboard with projects](img/instance_security_dashboard_with_projects_v13_2_sm.png)
![Uninitialized Instance Security Dashboard](img/instance_security_dashboard_empty_v13_3.png)
## Export vulnerabilities
......
......@@ -7,12 +7,7 @@ export default {
GlButton,
GlLink,
},
inject: ['dashboardDocumentation', 'emptyStateSvgPath'],
methods: {
handleAddProjectsClick() {
this.$emit('handleAddProjectsClick');
},
},
inject: ['dashboardDocumentation', 'emptyStateSvgPath', 'instanceDashboardSettingsPath'],
};
</script>
......@@ -32,7 +27,7 @@ export default {
}}</gl-link>
</template>
<template #actions>
<gl-button variant="success" @click="handleAddProjectsClick">
<gl-button variant="success" :href="instanceDashboardSettingsPath">
{{ s__('SecurityReports|Add projects') }}
</gl-button>
</template>
......
<script>
import { GlLoadingIcon, GlButton } from '@gitlab/ui';
import SecurityDashboardLayout from 'ee/security_dashboard/components/security_dashboard_layout.vue';
import VulnerabilitySeverities from 'ee/security_dashboard/components/first_class_vulnerability_severities.vue';
import VulnerabilityChart from 'ee/security_dashboard/components/first_class_vulnerability_chart.vue';
import Filters from 'ee/security_dashboard/components/first_class_vulnerability_filters.vue';
import projectsQuery from 'ee/security_dashboard/graphql/get_instance_security_dashboard_projects.query.graphql';
import InstanceSecurityVulnerabilities from './first_class_instance_security_dashboard_vulnerabilities.vue';
import { __, s__ } from '~/locale';
import { __ } from '~/locale';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import ProjectManager from './first_class_project_manager/project_manager.vue';
import CsvExportButton from './csv_export_button.vue';
import vulnerabilityHistoryQuery from '../graphql/instance_vulnerability_history.query.graphql';
import vulnerabilityGradesQuery from '../graphql/instance_vulnerability_grades.query.graphql';
......@@ -16,15 +14,12 @@ import DashboardNotConfigured from './empty_states/instance_dashboard_not_config
export default {
components: {
ProjectManager,
CsvExportButton,
SecurityDashboardLayout,
InstanceSecurityVulnerabilities,
VulnerabilitySeverities,
VulnerabilityChart,
Filters,
GlLoadingIcon,
GlButton,
DashboardNotConfigured,
},
props: {
......@@ -47,49 +42,29 @@ export default {
data() {
return {
filters: {},
showProjectSelector: false,
vulnerabilityHistoryQuery,
vulnerabilityGradesQuery,
projects: [],
isManipulatingProjects: false,
};
},
computed: {
isLoadingProjects() {
return this.$apollo.queries.projects.loading;
},
isUpdatingProjects() {
return this.isLoadingProjects || this.isManipulatingProjects;
},
hasProjectsData() {
return !this.isUpdatingProjects && this.projects.length > 0;
return !this.isLoadingProjects && this.projects.length > 0;
},
shouldShowDashboard() {
return this.hasProjectsData && !this.showProjectSelector;
return this.hasProjectsData;
},
shouldShowEmptyState() {
return !this.hasProjectsData && !this.showProjectSelector && !this.isUpdatingProjects;
},
toggleButtonProps() {
return this.showProjectSelector
? {
text: s__('SecurityReports|Return to dashboard'),
}
: {
text: s__('SecurityReports|Edit dashboard'),
};
return !this.isLoadingProjects && this.projects.length === 0;
},
},
methods: {
handleFilterChange(filters) {
this.filters = filters;
},
toggleProjectSelector() {
this.showProjectSelector = !this.showProjectSelector;
},
handleProjectManipulation(value) {
this.isManipulatingProjects = value;
},
},
};
</script>
......@@ -103,12 +78,6 @@ export default {
v-if="shouldShowDashboard"
:vulnerabilities-export-endpoint="vulnerabilitiesExportEndpoint"
/>
<gl-button
class="page-title-controls ml-2"
:variant="toggleButtonProps.variant"
@click="toggleProjectSelector"
>{{ toggleButtonProps.text }}</gl-button
>
</header>
</template>
<template #sticky>
......@@ -119,19 +88,7 @@ export default {
:projects="projects"
:filters="filters"
/>
<dashboard-not-configured
v-else-if="shouldShowEmptyState"
@handleAddProjectsClick="toggleProjectSelector"
/>
<div v-else class="d-flex justify-content-center">
<project-manager
v-if="showProjectSelector"
:projects="projects"
:is-manipulating-projects="isManipulatingProjects"
@handle-project-manipulation="handleProjectManipulation"
/>
<gl-loading-icon v-else size="lg" class="mt-4" />
</div>
<dashboard-not-configured v-else-if="shouldShowEmptyState" />
<template #aside>
<template v-if="shouldShowDashboard">
<vulnerability-chart :query="vulnerabilityHistoryQuery" class="mb-4" />
......
......@@ -27,6 +27,7 @@ export default (el, dashboardType) => {
});
}
const provide = {};
const props = {
hasVulnerabilities: Boolean(el.dataset.hasVulnerabilities),
securityDashboardHelpPath: el.dataset.securityDashboardHelpPath,
......@@ -45,6 +46,7 @@ export default (el, dashboardType) => {
component = FirstClassGroupSecurityDashboard;
props.groupFullPath = el.dataset.groupFullPath;
} else if (dashboardType === DASHBOARD_TYPES.INSTANCE) {
provide.instanceDashboardSettingsPath = el.dataset.instanceDashboardSettingsPath;
component = FirstClassInstanceSecurityDashboard;
}
......@@ -62,6 +64,7 @@ export default (el, dashboardType) => {
emptyStateSvgPath: el.dataset.emptyStateSvgPath,
notEnabledScannersHelpPath: el.dataset.notEnabledScannersHelpPath,
noPipelineRunScannersHelpPath: el.dataset.noPipelineRunScannersHelpPath,
...provide,
}),
render(createElement) {
return createElement(component, { props });
......
......@@ -10,6 +10,7 @@ module SecurityHelper
project_add_endpoint: security_projects_path,
project_list_endpoint: security_projects_path,
vulnerable_projects_endpoint: security_vulnerable_projects_path,
instance_dashboard_settings_path: security_settings_dashboard_path,
vulnerability_feedback_help_path: help_page_path('user/application_security/index', anchor: 'interacting-with-the-vulnerabilities'),
vulnerabilities_export_endpoint: expose_path(api_v4_security_vulnerability_exports_path)
}
......
---
title: Remove project selector logic from instance security dashboard
merge_request: 39631
author:
type: changed
......@@ -4,6 +4,7 @@ import DashboardNotConfigured from 'ee/security_dashboard/components/empty_state
describe('first class instance security dashboard empty state', () => {
let wrapper;
const instanceDashboardSettingsPath = '/path/to/dashboard/settings';
const dashboardDocumentation = '/path/to/dashboard/documentation';
const emptyStateSvgPath = '/placeholder.svg';
......@@ -12,6 +13,7 @@ describe('first class instance security dashboard empty state', () => {
provide: {
dashboardDocumentation,
emptyStateSvgPath,
instanceDashboardSettingsPath,
},
});
......@@ -36,16 +38,7 @@ describe('first class instance security dashboard empty state', () => {
expect(findLink().attributes('href')).toBe(dashboardDocumentation);
});
it('contains a GlButton', () => {
expect(findButton().exists()).toBe(true);
});
it('emits `handleAddProjectsClick` on button click', async () => {
const eventName = 'handleAddProjectsClick';
findButton().trigger('click');
await wrapper.vm.$nextTick();
expect(wrapper.emitted()).toHaveProperty(eventName);
it('contains a GlButton with a link to settings page', () => {
expect(findButton().attributes('href')).toBe(instanceDashboardSettingsPath);
});
});
import { shallowMount } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
import SecurityDashboardLayout from 'ee/security_dashboard/components/security_dashboard_layout.vue';
import FirstClassInstanceDashboard from 'ee/security_dashboard/components/first_class_instance_security_dashboard.vue';
import FirstClassInstanceVulnerabilities from 'ee/security_dashboard/components/first_class_instance_security_dashboard_vulnerabilities.vue';
......@@ -7,7 +6,6 @@ import VulnerabilitySeverity from 'ee/security_dashboard/components/first_class_
import VulnerabilityChart from 'ee/security_dashboard/components/first_class_vulnerability_chart.vue';
import CsvExportButton from 'ee/security_dashboard/components/csv_export_button.vue';
import Filters from 'ee/security_dashboard/components/first_class_vulnerability_filters.vue';
import ProjectManager from 'ee/security_dashboard/components/first_class_project_manager/project_manager.vue';
import DashboardNotConfigured from 'ee/security_dashboard/components/empty_states/instance_dashboard_not_configured.vue';
describe('First Class Instance Dashboard Component', () => {
......@@ -23,7 +21,6 @@ describe('First Class Instance Dashboard Component', () => {
const findVulnerabilitySeverity = () => wrapper.find(VulnerabilitySeverity);
const findVulnerabilityChart = () => wrapper.find(VulnerabilityChart);
const findCsvExportButton = () => wrapper.find(CsvExportButton);
const findProjectManager = () => wrapper.find(ProjectManager);
const findEmptyState = () => wrapper.find(DashboardNotConfigured);
const findFilters = () => wrapper.find(Filters);
......@@ -134,14 +131,6 @@ describe('First Class Instance Dashboard Component', () => {
it('does not display the vulnerability severity in an aside', () => {
expect(findVulnerabilitySeverity().exists()).toBe(false);
});
it('displays the project manager when the button in empty state is clicked', () => {
expect(findProjectManager().exists()).toBe(false);
wrapper.find(GlButton).vm.$emit('click');
return wrapper.vm.$nextTick(() => {
expect(findProjectManager().exists()).toBe(true);
});
});
});
describe('always', () => {
......@@ -152,13 +141,5 @@ describe('First Class Instance Dashboard Component', () => {
it('has the security dashboard title', () => {
expect(wrapper.find('.page-title').text()).toBe('Security Dashboard');
});
it('displays the project manager when the edit dashboard button is clicked', () => {
expect(findProjectManager().exists()).toBe(false);
wrapper.find(GlButton).vm.$emit('click');
return wrapper.vm.$nextTick(() => {
expect(findProjectManager().exists()).toBe(true);
});
});
});
});
......@@ -15,6 +15,7 @@ RSpec.describe SecurityHelper do
project_add_endpoint: security_projects_path,
project_list_endpoint: security_projects_path,
vulnerable_projects_endpoint: security_vulnerable_projects_path,
instance_dashboard_settings_path: security_settings_dashboard_path,
vulnerability_feedback_help_path: help_page_path('user/application_security/index', anchor: 'interacting-with-the-vulnerabilities'),
vulnerabilities_export_endpoint: api_v4_security_vulnerability_exports_path
})
......
......@@ -21777,9 +21777,6 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
msgid "SecurityReports|Edit dashboard"
msgstr ""
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
......@@ -21837,9 +21834,6 @@ msgstr ""
msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Return to dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
msgstr ""
......
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