diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-10-13 00:08:56 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-10-13 00:08:56 +0300 |
commit | f5dcc7ae73d1744b7737c16411af6281d78bc455 (patch) | |
tree | 5747413442c4cfdc2bbd668d4bc11851a6a2c288 /app/assets | |
parent | 884a65481f9e5365329f4ba371ac5b813c45a2f9 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets')
-rw-r--r-- | app/assets/javascripts/api.js | 9 | ||||
-rw-r--r-- | app/assets/javascripts/design_management/components/design_sidebar.vue | 11 | ||||
-rw-r--r-- | app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue | 11 | ||||
-rw-r--r-- | app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js | 1 | ||||
-rw-r--r-- | app/assets/javascripts/vue_shared/components/members/action_buttons/access_request_action_buttons.vue | 7 | ||||
-rw-r--r-- | app/assets/javascripts/vue_shared/components/members/action_buttons/approve_access_request_button.vue | 42 | ||||
-rw-r--r-- | app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue | 107 | ||||
-rw-r--r-- | app/assets/stylesheets/_page_specific_files.scss | 1 | ||||
-rw-r--r-- | app/assets/stylesheets/page_bundles/dev_ops_report.scss (renamed from app/assets/stylesheets/pages/dev_ops_report.scss) | 60 | ||||
-rw-r--r-- | app/assets/stylesheets/page_bundles/pipeline.scss | 14 | ||||
-rw-r--r-- | app/assets/stylesheets/pages/pipelines.scss | 14 |
11 files changed, 221 insertions, 56 deletions
diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js index a87f89efd70..996ca4e8b73 100644 --- a/app/assets/javascripts/api.js +++ b/app/assets/javascripts/api.js @@ -54,6 +54,7 @@ const Api = { releaseLinkPath: '/api/:version/projects/:id/releases/:tag_name/assets/links/:link_id', mergeRequestsPipeline: '/api/:version/projects/:id/merge_requests/:merge_request_iid/pipelines', adminStatisticsPath: '/api/:version/application/statistics', + pipelineJobsPath: '/api/:version/projects/:id/pipelines/:pipeline_id/jobs', pipelineSinglePath: '/api/:version/projects/:id/pipelines/:pipeline_id', pipelinesPath: '/api/:version/projects/:id/pipelines/', createPipelinePath: '/api/:version/projects/:id/pipeline', @@ -599,6 +600,14 @@ const Api = { return axios.get(url); }, + pipelineJobs(projectId, pipelineId) { + const url = Api.buildUrl(this.pipelineJobsPath) + .replace(':id', encodeURIComponent(projectId)) + .replace(':pipeline_id', encodeURIComponent(pipelineId)); + + return axios.get(url); + }, + // Return all pipelines for a project or filter by query params pipelines(id, options = {}) { const url = Api.buildUrl(this.pipelinesPath).replace(':id', encodeURIComponent(id)); diff --git a/app/assets/javascripts/design_management/components/design_sidebar.vue b/app/assets/javascripts/design_management/components/design_sidebar.vue index fecedceef32..fb8e74c8c4c 100644 --- a/app/assets/javascripts/design_management/components/design_sidebar.vue +++ b/app/assets/javascripts/design_management/components/design_sidebar.vue @@ -71,14 +71,6 @@ export default { resolvedCommentsToggleIcon() { return this.resolvedDiscussionsExpanded ? 'chevron-down' : 'chevron-right'; }, - showTodoButton() { - return this.glFeatures.designManagementTodoButton; - }, - sidebarWrapperClass() { - return { - 'gl-pt-0': this.showTodoButton, - }; - }, }, watch: { isResolvedCommentsPopoverHidden(newVal) { @@ -121,9 +113,8 @@ export default { </script> <template> - <div class="image-notes" :class="sidebarWrapperClass" @click="handleSidebarClick"> + <div class="image-notes gl-pt-0" @click="handleSidebarClick"> <div - v-if="showTodoButton" class="gl-py-4 gl-mb-4 gl-display-flex gl-justify-content-space-between gl-align-items-center gl-border-b-1 gl-border-b-solid gl-border-b-gray-100" > <span>{{ __('To Do') }}</span> diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue index 78ac9b6ac76..acf6f65b1a0 100644 --- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue +++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue @@ -86,6 +86,7 @@ export default { TerraformPlan, GroupedAccessibilityReportsApp, MrWidgetApprovals, + SecurityReportsApp: () => import('~/vue_shared/security_reports/security_reports_app.vue'), }, apollo: { state: { @@ -179,6 +180,9 @@ export default { this.mr.mergePipelinesEnabled && this.mr.sourceProjectId !== this.mr.targetProjectId, ); }, + shouldRenderSecurityReport() { + return Boolean(window.gon?.features?.coreSecurityMrWidget && this.mr.pipeline.id); + }, mergeError() { let { mergeError } = this.mr; @@ -456,6 +460,13 @@ export default { :codequality-help-path="mr.codequalityHelpPath" /> + <security-reports-app + v-if="shouldRenderSecurityReport" + :pipeline-id="mr.pipeline.id" + :project-id="mr.targetProjectId" + :security-reports-docs-path="mr.securityReportsDocsPath" + /> + <grouped-test-reports-app v-if="mr.testResultsPath" class="js-reports-container" diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js index 846b1c453a1..8b235b20ad4 100644 --- a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js +++ b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js @@ -232,6 +232,7 @@ export default class MergeRequestStore { this.userCalloutsPath = data.user_callouts_path; this.suggestPipelineFeatureId = data.suggest_pipeline_feature_id; this.isDismissedSuggestPipeline = data.is_dismissed_suggest_pipeline; + this.securityReportsDocsPath = data.security_reports_docs_path; // codeclimate const blobPath = data.blob_path || {}; diff --git a/app/assets/javascripts/vue_shared/components/members/action_buttons/access_request_action_buttons.vue b/app/assets/javascripts/vue_shared/components/members/action_buttons/access_request_action_buttons.vue index 0d1ac0196ec..10078d5cd64 100644 --- a/app/assets/javascripts/vue_shared/components/members/action_buttons/access_request_action_buttons.vue +++ b/app/assets/javascripts/vue_shared/components/members/action_buttons/access_request_action_buttons.vue @@ -1,11 +1,12 @@ <script> import ActionButtonGroup from './action_button_group.vue'; import RemoveMemberButton from './remove_member_button.vue'; +import ApproveAccessRequestButton from './approve_access_request_button.vue'; import { s__, sprintf } from '~/locale'; export default { name: 'AccessRequestActionButtons', - components: { ActionButtonGroup, RemoveMemberButton }, + components: { ActionButtonGroup, RemoveMemberButton, ApproveAccessRequestButton }, props: { member: { type: Object, @@ -42,7 +43,9 @@ export default { <template> <action-button-group> - <!-- Approve button will go here --> + <div v-if="permissions.canUpdate" class="gl-px-1"> + <approve-access-request-button :member-id="member.id" /> + </div> <div v-if="permissions.canRemove" class="gl-px-1"> <remove-member-button :member-id="member.id" diff --git a/app/assets/javascripts/vue_shared/components/members/action_buttons/approve_access_request_button.vue b/app/assets/javascripts/vue_shared/components/members/action_buttons/approve_access_request_button.vue new file mode 100644 index 00000000000..e8a53ff173d --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/members/action_buttons/approve_access_request_button.vue @@ -0,0 +1,42 @@ +<script> +import { mapState } from 'vuex'; +import { GlButton, GlForm, GlTooltipDirective } from '@gitlab/ui'; +import csrf from '~/lib/utils/csrf'; +import { __ } from '~/locale'; + +export default { + name: 'ApproveAccessRequestButton', + csrf, + title: __('Grant access'), + components: { GlButton, GlForm }, + directives: { + GlTooltip: GlTooltipDirective, + }, + props: { + memberId: { + type: Number, + required: true, + }, + }, + computed: { + ...mapState(['memberPath']), + approvePath() { + return this.memberPath.replace(/:id$/, `${this.memberId}/approve_access_request`); + }, + }, +}; +</script> + +<template> + <gl-form :action="approvePath" method="post"> + <input :value="$options.csrf.token" type="hidden" name="authenticity_token" /> + <gl-button + v-gl-tooltip.hover + :title="$options.title" + :aria-label="$options.title" + icon="check" + variant="success" + type="submit" + /> + </gl-form> +</template> diff --git a/app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue b/app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue new file mode 100644 index 00000000000..d5696e3c8cf --- /dev/null +++ b/app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue @@ -0,0 +1,107 @@ +<script> +import { GlIcon, GlLink, GlSprintf } from '@gitlab/ui'; +import ReportSection from '~/reports/components/report_section.vue'; +import { status } from '~/reports/constants'; +import { s__ } from '~/locale'; +import Flash from '~/flash'; +import Api from '~/api'; + +export default { + components: { + GlIcon, + GlLink, + GlSprintf, + ReportSection, + }, + props: { + pipelineId: { + type: Number, + required: true, + }, + projectId: { + type: Number, + required: true, + }, + securityReportsDocsPath: { + type: String, + required: true, + }, + }, + data() { + return { + hasSecurityReports: false, + + // Error state is shown even when successfully loaded, since success + // state suggests that the security scans detected no security problems, + // which is not necessarily the case. A future iteration will actually + // check whether problems were found and display the appropriate status. + status: status.ERROR, + }; + }, + created() { + this.checkHasSecurityReports(this.$options.reportTypes) + .then(hasSecurityReports => { + this.hasSecurityReports = hasSecurityReports; + }) + .catch(error => { + Flash({ + message: this.$options.i18n.apiError, + captureError: true, + error, + }); + }); + }, + methods: { + checkHasSecurityReports(reportTypes) { + return Api.pipelineJobs(this.projectId, this.pipelineId).then(({ data: jobs }) => + jobs.some(({ artifacts = [] }) => + artifacts.some(({ file_type }) => reportTypes.includes(file_type)), + ), + ); + }, + activatePipelinesTab() { + if (window.mrTabs) { + window.mrTabs.tabShown('pipelines'); + } + }, + }, + reportTypes: ['sast', 'secret_detection'], + i18n: { + apiError: s__( + 'SecurityReports|Failed to get security report information. Please reload the page or try again later.', + ), + scansHaveRun: s__( + 'SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports', + ), + securityReportsHelp: s__('SecurityReports|Security reports help page link'), + }, +}; +</script> +<template> + <report-section + v-if="hasSecurityReports" + :status="status" + :has-issues="false" + class="mr-widget-border-top mr-report" + data-testid="security-mr-widget" + > + <template #error> + <gl-sprintf :message="$options.i18n.scansHaveRun"> + <template #link="{ content }"> + <gl-link data-testid="show-pipelines" @click="activatePipelinesTab">{{ + content + }}</gl-link> + </template> + </gl-sprintf> + + <gl-link + target="_blank" + data-testid="help" + :href="securityReportsDocsPath" + :aria-label="$options.i18n.securityReportsHelp" + > + <gl-icon name="question" /> + </gl-link> + </template> + </report-section> +</template> diff --git a/app/assets/stylesheets/_page_specific_files.scss b/app/assets/stylesheets/_page_specific_files.scss index 620a8654d4e..eb602651d43 100644 --- a/app/assets/stylesheets/_page_specific_files.scss +++ b/app/assets/stylesheets/_page_specific_files.scss @@ -8,7 +8,6 @@ @import './pages/commits'; @import './pages/deploy_keys'; @import './pages/detail_page'; -@import './pages/dev_ops_report'; @import './pages/diff'; @import './pages/editor'; @import './pages/environment_logs'; diff --git a/app/assets/stylesheets/pages/dev_ops_report.scss b/app/assets/stylesheets/page_bundles/dev_ops_report.scss index 871cd9c4f02..5c6019efce6 100644 --- a/app/assets/stylesheets/pages/dev_ops_report.scss +++ b/app/assets/stylesheets/page_bundles/dev_ops_report.scss @@ -1,3 +1,5 @@ +@import 'mixins_and_variables_and_functions'; + $space-between-cards: 8px; .devops-empty svg { @@ -21,7 +23,7 @@ $space-between-cards: 8px; .devops-header-subtitle { font-size: 22px; line-height: 1; - color: $gl-text-color-secondary; + color: var(--gl-text-color-secondary, $gl-text-color-secondary); margin-left: 8px; font-weight: $gl-font-weight-normal; @@ -31,10 +33,10 @@ $space-between-cards: 8px; a { font-size: 18px; - color: $gl-text-color-secondary; + color: var(--gl-text-color-secondary, $gl-text-color-secondary); &:hover { - color: $blue-500; + color: var(--blue-500, $blue-500); } } } @@ -52,7 +54,7 @@ $space-between-cards: 8px; align-items: stretch; text-align: center; width: 50%; - border-color: $border-color; + border-color: var(--border-color, $border-color); margin: 0 0 32px; padding: $space-between-cards / 2; position: relative; @@ -75,7 +77,7 @@ $space-between-cards: 8px; } .devops-card { - border: solid 1px $border-color; + border: solid 1px var(--border-color, $border-color); border-radius: 3px; border-top-width: 3px; display: flex; @@ -84,26 +86,26 @@ $space-between-cards: 8px; } .devops-card-low { - border-top-color: $red-400; + border-top-color: var(--red-400, $red-400); .board-card-score-big { - background-color: $red-50; + background-color: var(--red-50, $red-50); } } .devops-card-average { - border-top-color: $orange-200; + border-top-color: var(--orange-200, $orange-200); .board-card-score-big { - background-color: $orange-50; + background-color: var(--orange-50, $orange-50); } } .devops-card-high { - border-top-color: $green-400; + border-top-color: var(--green-400, $green-400); .board-card-score-big { - background-color: $green-50; + background-color: var(--green-50, $green-50); } } @@ -119,7 +121,7 @@ $space-between-cards: 8px; .light-text { font-size: 13px; line-height: 1.25; - color: $gl-text-color-secondary; + color: var(--gl-text-color-secondary, $gl-text-color-secondary); } } @@ -132,7 +134,7 @@ $space-between-cards: 8px; } .board-card-score { - color: $gl-text-color-secondary; + color: var(--gl-text-color-secondary, $gl-text-color-secondary); .board-card-score-name { font-size: 13px; @@ -142,13 +144,13 @@ $space-between-cards: 8px; .board-card-score-value { font-size: 16px; - color: $gl-text-color; + color: var(--gl-text-color, $gl-text-color); font-weight: $gl-font-weight-normal; } .board-card-score-big { - border-top: 2px solid $border-color; - border-bottom: 1px solid $border-color; + border-top: 2px solid var(--border-color, $border-color); + border-bottom: 1px solid var(--border-color, $border-color); font-size: 22px; padding: 10px 0; font-weight: $gl-font-weight-normal; @@ -159,17 +161,17 @@ $space-between-cards: 8px; > * { font-size: 16px; - color: $gl-text-color-secondary; + color: var(--gl-text-color-secondary, $gl-text-color-secondary); padding: 10px; flex-grow: 1; &:hover { - background-color: $border-color; - color: $gl-text-color; + background-color: var(--border-color, $border-color); + color: var(--border-color, $border-color); } + * { - border-left: solid 1px $border-color; + border-left: solid 1px var(--border-color, $border-color); } } } @@ -180,7 +182,7 @@ $space-between-cards: 8px; min-width: 100%; justify-content: space-around; position: relative; - background: $border-color; + background: var(--border-color, $border-color); } .devops-step { @@ -202,12 +204,12 @@ $space-between-cards: 8px; display: flex; flex-direction: column; align-items: center; - border: solid 1px $border-color; - background: $white; + border: solid 1px var(--border-color, $border-color); + background: var(--white, $white); transform: translate(-50%, -50%); - color: $gl-text-color-secondary; - fill: $gl-text-color-secondary; - box-shadow: 0 2px 4px $dropdown-shadow-color; + color: var(--gl-text-color-secondary, $gl-text-color-secondary); + fill: var(--gl-text-color-secondary, $gl-text-color-secondary); + box-shadow: 0 2px 4px var(--dropdown-shadow-color, $dropdown-shadow-color); &:hover { padding: 8px 10px; @@ -247,13 +249,13 @@ $space-between-cards: 8px; } .devops-high-score { - color: $green-400; + color: var(--green-400, $green-400); } .devops-average-score { - color: $orange-500; + color: var(--orange-500, $orange-500); } .devops-low-score { - color: $red-400; + color: var(--red-400, $red-400); } diff --git a/app/assets/stylesheets/page_bundles/pipeline.scss b/app/assets/stylesheets/page_bundles/pipeline.scss index bebb915bce6..5ba9668ca19 100644 --- a/app/assets/stylesheets/page_bundles/pipeline.scss +++ b/app/assets/stylesheets/page_bundles/pipeline.scss @@ -426,3 +426,17 @@ flex: 1; } } + +.codequality-report { + .media { + padding: $gl-padding; + } + + .media-body { + flex-direction: row; + } + + .report-block-container { + height: auto !important; + } +} diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 0f68c393187..b758e2c588c 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -506,20 +506,6 @@ button.mini-pipeline-graph-dropdown-toggle { } } -.codequality-report { - .media { - padding: $gl-padding; - } - - .media-body { - flex-direction: row; - } - - .report-block-container { - height: auto !important; - } -} - .progress-bar.bg-primary { background-color: $blue-500 !important; } |