Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-10-13 00:08:56 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-10-13 00:08:56 +0300
commitf5dcc7ae73d1744b7737c16411af6281d78bc455 (patch)
tree5747413442c4cfdc2bbd668d4bc11851a6a2c288 /app/assets
parent884a65481f9e5365329f4ba371ac5b813c45a2f9 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets')
-rw-r--r--app/assets/javascripts/api.js9
-rw-r--r--app/assets/javascripts/design_management/components/design_sidebar.vue11
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue11
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js1
-rw-r--r--app/assets/javascripts/vue_shared/components/members/action_buttons/access_request_action_buttons.vue7
-rw-r--r--app/assets/javascripts/vue_shared/components/members/action_buttons/approve_access_request_button.vue42
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue107
-rw-r--r--app/assets/stylesheets/_page_specific_files.scss1
-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.scss14
-rw-r--r--app/assets/stylesheets/pages/pipelines.scss14
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;
}