Commit 2de53683 authored by Filipa Lacerda's avatar Filipa Lacerda

Merge branch '7120-add-a-manage-licenses-button-in-the-report' into 'master'

Add Manage licenses to MR widget and pipelines

Closes #7120

See merge request gitlab-org/gitlab-ee!7411
parents 9afa4a5f 309c4d1b
...@@ -139,7 +139,7 @@ export default { ...@@ -139,7 +139,7 @@ export default {
<section class="media-section"> <section class="media-section">
<div class="media"> <div class="media">
<status-icon :status="statusIconName" /> <status-icon :status="statusIconName" />
<div class="media-body space-children d-flex flex-align-self-center"> <div class="media-body d-flex flex-align-self-center">
<span class="js-code-text code-text"> <span class="js-code-text code-text">
{{ headerText }} {{ headerText }}
......
...@@ -10,7 +10,12 @@ export default () => { ...@@ -10,7 +10,12 @@ export default () => {
const licensesTab = document.getElementById('js-licenses-app'); const licensesTab = document.getElementById('js-licenses-app');
if (licensesTab) { if (licensesTab) {
const { licenseHeadPath, canManageLicenses, apiUrl } = licensesTab.dataset; const {
licenseHeadPath,
canManageLicenses,
apiUrl,
licenseManagementSettingsPath,
} = licensesTab.dataset;
// eslint-disable-next-line no-new // eslint-disable-next-line no-new
new Vue({ new Vue({
...@@ -22,13 +27,14 @@ export default () => { ...@@ -22,13 +27,14 @@ export default () => {
return createElement('license-report-app', { return createElement('license-report-app', {
props: { props: {
apiUrl, apiUrl,
licenseManagementSettingsPath,
headPath: licenseHeadPath, headPath: licenseHeadPath,
canManageLicenses: convertPermissionToBoolean(canManageLicenses), canManageLicenses: convertPermissionToBoolean(canManageLicenses),
alwaysOpen: true, alwaysOpen: true,
reportSectionClass: 'split-report-section', reportSectionClass: 'split-report-section',
}, },
on: { on: {
updateBadgeCount: (count) => { updateBadgeCount: count => {
updateBadgeCount('.js-licenses-counter', count); updateBadgeCount('.js-licenses-counter', count);
}, },
}, },
......
...@@ -261,6 +261,8 @@ export default { ...@@ -261,6 +261,8 @@ export default {
:api-url="mr.licenseManagement.managed_licenses_path" :api-url="mr.licenseManagement.managed_licenses_path"
:pipeline-path="mr.pipeline.path" :pipeline-path="mr.pipeline.path"
:can-manage-licenses="mr.licenseManagement.can_manage_licenses" :can-manage-licenses="mr.licenseManagement.can_manage_licenses"
:full-report-path="mr.licenseManagement.license_management_full_report_path"
:license-management-settings-path="mr.licenseManagement.license_management_settings_path"
:base-path="mr.licenseManagement.base_path" :base-path="mr.licenseManagement.base_path"
:head-path="mr.licenseManagement.head_path" :head-path="mr.licenseManagement.head_path"
report-section-class="mr-widget-border-top" report-section-class="mr-widget-border-top"
......
...@@ -30,7 +30,12 @@ export default { ...@@ -30,7 +30,12 @@ export default {
required: false, required: false,
default: null, default: null,
}, },
pipelinePath: { fullReportPath: {
type: String,
required: false,
default: null,
},
licenseManagementSettingsPath: {
type: String, type: String,
required: false, required: false,
default: null, default: null,
...@@ -64,8 +69,8 @@ export default { ...@@ -64,8 +69,8 @@ export default {
licenseReportStatus() { licenseReportStatus() {
return this.checkReportStatus(this.isLoading, this.loadLicenseReportError); return this.checkReportStatus(this.isLoading, this.loadLicenseReportError);
}, },
licensesTab() { showActionButtons() {
return this.pipelinePath ? `${this.pipelinePath}/licenses` : null; return this.licenseManagementSettingsPath !== null || this.fullReportPath !== null;
}, },
}, },
watch: { watch: {
...@@ -107,15 +112,25 @@ export default { ...@@ -107,15 +112,25 @@ export default {
class="license-report-widget mr-report" class="license-report-widget mr-report"
> >
<div <div
v-if="licensesTab" v-if="showActionButtons"
slot="actionButtons" slot="actionButtons"
class="append-right-default"
> >
<a <a
:href="licensesTab" v-if="licenseManagementSettingsPath"
:class="{'append-right-8': fullReportPath}"
:href="licenseManagementSettingsPath"
class="btn btn-default btn-sm js-manage-licenses"
>
{{ s__("ciReport|Manage licenses") }}
</a>
<a
v-if="fullReportPath"
:href="fullReportPath"
target="_blank" target="_blank"
class="btn btn-default btn-sm float-right" class="btn btn-default btn-sm js-full-report"
> >
<span>{{ s__("ciReport|View full report") }}</span> {{ s__("ciReport|View full report") }}
<icon <icon
:size="16" :size="16"
name="external-link" name="external-link"
......
...@@ -227,7 +227,7 @@ export default { ...@@ -227,7 +227,7 @@ export default {
<a <a
:href="securityTab" :href="securityTab"
target="_blank" target="_blank"
class="btn btn-default btn-sm float-right" class="btn btn-default btn-sm float-right append-right-default"
> >
<span>{{ s__("ciReport|View full report") }}</span> <span>{{ s__("ciReport|View full report") }}</span>
<icon <icon
......
...@@ -69,5 +69,9 @@ module EE ...@@ -69,5 +69,9 @@ module EE
def license_management_api_url(project) def license_management_api_url(project)
api_v4_projects_managed_licenses_path(id: project.id) api_v4_projects_managed_licenses_path(id: project.id)
end end
def license_management_settings_path(project)
project_settings_ci_cd_path(project, anchor: 'js-license-management')
end
end end
end end
...@@ -108,6 +108,14 @@ module EE ...@@ -108,6 +108,14 @@ module EE
expose :can_manage_licenses do |merge_request| expose :can_manage_licenses do |merge_request|
can?(current_user, :admin_software_license_policy, merge_request) can?(current_user, :admin_software_license_policy, merge_request)
end end
expose :license_management_settings_path, if: -> (mr, _) {can?(current_user, :admin_software_license_policy, mr.target_project)} do |merge_request|
license_management_settings_path(merge_request.target_project)
end
expose :license_management_full_report_path, if: -> (mr, _) { mr.head_pipeline } do |merge_request|
licenses_project_pipeline_path(merge_request.target_project, merge_request.head_pipeline)
end
end end
# expose_sast_container_data? is deprecated and replaced with expose_container_scanning_data? (#5778) # expose_sast_container_data? is deprecated and replaced with expose_container_scanning_data? (#5778)
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
- dast_endpoint = pipeline.expose_dast_data? ? dast_artifact_url(pipeline) : nil - dast_endpoint = pipeline.expose_dast_data? ? dast_artifact_url(pipeline) : nil
- sast_container_endpoint = pipeline.expose_sast_container_data? ? sast_container_artifact_url(pipeline) : pipeline.expose_container_scanning_data? ? container_scanning_artifact_url(pipeline) : nil - sast_container_endpoint = pipeline.expose_sast_container_data? ? sast_container_artifact_url(pipeline) : pipeline.expose_container_scanning_data? ? container_scanning_artifact_url(pipeline) : nil
- blob_path = project_blob_path(project, pipeline.sha) - blob_path = project_blob_path(project, pipeline.sha)
- license_management_settings_path = can?(current_user, :admin_software_license_policy, project) ? license_management_settings_path(project) : nil
- if pipeline.expose_security_dashboard? - if pipeline.expose_security_dashboard?
#js-tab-security.build-security.tab-pane #js-tab-security.build-security.tab-pane
...@@ -28,4 +29,5 @@ ...@@ -28,4 +29,5 @@
#js-tab-licenses.tab-pane #js-tab-licenses.tab-pane
#js-licenses-app{ data: { license_head_path: pipeline.expose_license_management_data? ? license_management_artifact_url(pipeline) : nil, #js-licenses-app{ data: { license_head_path: pipeline.expose_license_management_data? ? license_management_artifact_url(pipeline) : nil,
api_url: license_management_api_url(project), api_url: license_management_api_url(project),
license_management_settings_path: license_management_settings_path,
can_manage_licenses: can?(current_user, :admin_software_license_policy, project).to_s } } can_manage_licenses: can?(current_user, :admin_software_license_policy, project).to_s } }
- return unless @project.feature_available?(:license_management) - return unless @project.feature_available?(:license_management)
- expanded = Rails.env.test? - expanded = Rails.env.test?
%section.settings.no-animate{ class: ('expanded' if expanded) } %section.settings.no-animate#js-license-management{ class: ('expanded' if expanded) }
.settings-header .settings-header
%h4 %h4
= s_('LicenseManagement|License Management') = s_('LicenseManagement|License Management')
......
---
title: Add `Manage licenses` button to MR widget and pipelines view
merge_request: 7411
author:
type: added
...@@ -102,22 +102,46 @@ describe MergeRequestWidgetEntity do ...@@ -102,22 +102,46 @@ describe MergeRequestWidgetEntity do
expect(subject.as_json[:dependency_scanning]).to include(:base_path) expect(subject.as_json[:dependency_scanning]).to include(:base_path)
end end
it 'has license_management data' do describe '#license_management' do
build = create(:ci_build, name: 'license_management', pipeline: pipeline) before do
build = create(:ci_build, name: 'license_management', pipeline: pipeline)
allow(merge_request).to receive_messages(
expose_license_management_data?: true, allow(merge_request).to receive_messages(
expose_security_dashboard?: false, expose_license_management_data?: true,
base_has_license_management_data?: true, expose_security_dashboard?: false,
base_license_management_artifact: build, base_has_license_management_data?: true,
head_license_management_artifact: build base_license_management_artifact: build,
) head_license_management_artifact: build,
head_pipeline: pipeline,
expect(subject.as_json).to include(:license_management) target_project: project
expect(subject.as_json[:license_management]).to include(:head_path) )
expect(subject.as_json[:license_management]).to include(:base_path) end
expect(subject.as_json[:license_management]).to include(:managed_licenses_path)
expect(subject.as_json[:license_management]).to include(:can_manage_licenses) it 'should not be included, if license management features are off' do
allow(merge_request).to receive_messages(expose_license_management_data?: false)
expect(subject.as_json).not_to include(:license_management)
end
it 'should be included, if license manage management features are on' do
expect(subject.as_json).to include(:license_management)
expect(subject.as_json[:license_management]).to include(:head_path)
expect(subject.as_json[:license_management]).to include(:base_path)
expect(subject.as_json[:license_management]).to include(:managed_licenses_path)
expect(subject.as_json[:license_management]).to include(:can_manage_licenses)
expect(subject.as_json[:license_management]).to include(:license_management_full_report_path)
end
it '#license_management_settings_path should not be included for developers' do
expect(subject.as_json[:license_management]).not_to include(:license_management_settings_path)
end
it '#license_management_settings_path should be included for maintainers' do
stub_licensed_features(license_management: true)
project.add_maintainer(user)
expect(subject.as_json[:license_management]).to include(:license_management_settings_path)
end
end end
# methods for old artifact are deprecated and replaced with ones for the new name (#5779) # methods for old artifact are deprecated and replaced with ones for the new name (#5779)
......
...@@ -8745,6 +8745,9 @@ msgstr "" ...@@ -8745,6 +8745,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report" msgid "ciReport|Loading %{reportName} report"
msgstr "" msgstr ""
msgid "ciReport|Manage licenses"
msgstr ""
msgid "ciReport|Method" msgid "ciReport|Method"
msgstr "" 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