diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-06-22 15:10:55 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-06-22 15:10:55 +0300 |
commit | a27c21b5af4f60ff11706f85289065272c616a0c (patch) | |
tree | 73ac1a10bfe1bd6a4c486f58fb663b262580627b /app/assets/javascripts/vue_merge_request_widget | |
parent | 0b54de365bc766260093c9584c7470aff96d14fd (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/vue_merge_request_widget')
-rw-r--r-- | app/assets/javascripts/vue_merge_request_widget/components/widget/action_buttons.vue | 2 | ||||
-rw-r--r-- | app/assets/javascripts/vue_merge_request_widget/components/widget/app.vue | 10 | ||||
-rw-r--r-- | app/assets/javascripts/vue_merge_request_widget/components/widget/dynamic_content.vue | 32 | ||||
-rw-r--r-- | app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue | 37 | ||||
-rw-r--r-- | app/assets/javascripts/vue_merge_request_widget/extensions/security_reports/mr_widget_security_reports.vue | 5 | ||||
-rw-r--r-- | app/assets/javascripts/vue_merge_request_widget/extensions/terraform/index.vue (renamed from app/assets/javascripts/vue_merge_request_widget/extensions/terraform/index.js) | 77 | ||||
-rw-r--r-- | app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue | 14 |
7 files changed, 113 insertions, 64 deletions
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/widget/action_buttons.vue b/app/assets/javascripts/vue_merge_request_widget/components/widget/action_buttons.vue index 6655af92a55..c38c253564a 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/widget/action_buttons.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/widget/action_buttons.vue @@ -23,7 +23,7 @@ export default { default: () => [], }, }, - data: () => { + data() { return { timeout: null, updatingTooltip: false, diff --git a/app/assets/javascripts/vue_merge_request_widget/components/widget/app.vue b/app/assets/javascripts/vue_merge_request_widget/components/widget/app.vue index 334fc01c9f7..258fa4edcda 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/widget/app.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/widget/app.vue @@ -5,16 +5,24 @@ export default { import( '~/vue_merge_request_widget/extensions/security_reports/mr_widget_security_reports.vue' ), + + MrTerraformWidget: () => import('~/vue_merge_request_widget/extensions/terraform/index.vue'), }, + props: { mr: { type: Object, required: true, }, }, + computed: { + terraformPlansWidget() { + return this.mr.terraformReportsPath && 'MrTerraformWidget'; + }, + widgets() { - return ['MrSecurityWidget']; + return [this.terraformPlansWidget, 'MrSecurityWidget'].filter((w) => w); }, }, }; diff --git a/app/assets/javascripts/vue_merge_request_widget/components/widget/dynamic_content.vue b/app/assets/javascripts/vue_merge_request_widget/components/widget/dynamic_content.vue index cdce7c6625a..ec979861283 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/widget/dynamic_content.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/widget/dynamic_content.vue @@ -30,6 +30,11 @@ export default { required: false, default: 2, }, + rowIndex: { + type: Number, + required: false, + default: -1, + }, }, computed: { statusIcon() { @@ -44,6 +49,9 @@ export default { generatedSupportingText() { return generateText(this.data.supportingText); }, + shouldShowThirdLevel() { + return this.data.children?.length > 0 && this.level === 2; + }, }, methods: { onClickedAction(action) { @@ -60,16 +68,19 @@ export default { :widget-name="widgetName" :header="data.header" :help-popover="data.helpPopover" + :class="{ 'gl-border-top-0': rowIndex === 0 }" > <template #body> - <div class="gl-display-flex gl-flex-direction-column"> - <div> - <p v-safe-html="generatedText" class="gl-mb-0"></p> - <gl-link v-if="data.link" :href="data.link.href">{{ data.link.text }}</gl-link> - <p v-if="data.supportingText" v-safe-html="generatedSupportingText" class="gl-mb-0"></p> - <gl-badge v-if="data.badge" :variant="data.badge.variant || 'info'"> - {{ data.badge.text }} - </gl-badge> + <div class="gl-w-full gl-display-flex" :class="{ 'gl-flex-direction-column': level === 1 }"> + <div class="gl-display-flex gl-flex-grow-1"> + <div class="gl-display-flex gl-flex-grow-1 gl-flex-direction-column"> + <p v-safe-html="generatedText" class="gl-mb-0 gl-mr-1"></p> + <gl-link v-if="data.link" :href="data.link.href">{{ data.link.text }}</gl-link> + <p v-if="data.supportingText" v-safe-html="generatedSupportingText" class="gl-mb-0"></p> + <gl-badge v-if="data.badge" :variant="data.badge.variant || 'info'"> + {{ data.badge.text }} + </gl-badge> + </div> <actions :widget="widgetName" :tertiary-buttons="data.actions" @@ -78,10 +89,7 @@ export default { /> <p v-if="data.subtext" v-safe-html="generatedSubtext" class="gl-m-0 gl-font-sm"></p> </div> - <ul - v-if="data.children && data.children.length > 0 && level === 2" - class="gl-m-0 gl-p-0 gl-list-style-none" - > + <ul v-if="shouldShowThirdLevel" class="gl-m-0 gl-p-0 gl-list-style-none"> <li v-for="(childData, index) in data.children" :key="childData.id || index"> <dynamic-content :data="childData" diff --git a/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue b/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue index 54eb15c8ac8..e327d848d8f 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue @@ -10,6 +10,7 @@ import HelpPopover from '~/vue_shared/components/help_popover.vue'; import { DynamicScroller, DynamicScrollerItem } from 'vendor/vue-virtual-scroller'; import { EXTENSION_ICONS } from '../../constants'; import { createTelemetryHub } from '../extensions/telemetry'; +import { generateText } from '../extensions/utils'; import ContentRow from './widget_content_row.vue'; import DynamicContent from './dynamic_content.vue'; import StatusIcon from './status_icon.vue'; @@ -72,9 +73,12 @@ export default { }, // If the summary slot is not used, this value will be used as a fallback. summary: { - type: String, + type: Object, required: false, default: undefined, + validator: (s) => { + return Boolean(s.title); + }, }, // If the content slot is not used, this value will be used as a fallback. content: { @@ -154,7 +158,7 @@ export default { return { isExpandedForTheFirstTime: true, isCollapsed: true, - isLoading: false, + isLoading: true, isLoadingExpandedContent: false, summaryError: null, contentError: null, @@ -162,6 +166,12 @@ export default { }; }, computed: { + generatedSummary() { + return generateText(this.summary?.title || ''); + }, + generatedSubSummary() { + return generateText(this.summary?.subtitle || ''); + }, collapseButtonLabel() { return sprintf(this.isCollapsed ? __('Show details') : __('Hide details')); }, @@ -171,6 +181,9 @@ export default { hasActionButtons() { return this.actionButtons.length > 0 || Boolean(this.$scopedSlots['action-buttons']); }, + contentWithKeyField() { + return this.content?.map((item, index) => ({ ...item, id: item.id || index })); + }, }, watch: { hasError: { @@ -289,7 +302,7 @@ export default { <template> <section class="media-section" data-testid="widget-extension"> - <div class="gl-px-5 gl-pr-4 gl-py-4 gl-align-items-center gl-display-flex"> + <div class="gl-px-5 gl-pr-4 gl-py-4 gl-display-flex"> <status-icon :level="1" :name="widgetName" @@ -302,7 +315,14 @@ export default { > <div class="gl-flex-grow-1" data-testid="widget-extension-top-level-summary"> <span v-if="summaryError">{{ summaryError }}</span> - <slot v-else name="summary">{{ isLoading ? loadingText : summary }}</slot> + <slot v-else name="summary" + ><div v-safe-html="isLoading ? loadingText : generatedSummary"></div> + <div + v-if="!isLoading && generatedSubSummary" + v-safe-html="generatedSubSummary" + class="gl-font-sm gl-text-gray-700" + ></div + ></slot> </div> <div class="gl-display-flex"> <help-popover @@ -336,7 +356,7 @@ export default { </slot> </div> <div - v-if="isCollapsible" + v-if="isCollapsible && !isLoading" class="gl-border-l-1 gl-border-l-solid gl-border-gray-100 gl-ml-3 gl-pl-3 gl-h-6" > <gl-button @@ -376,8 +396,8 @@ export default { <div v-else class="gl-w-full"> <slot name="content"> <dynamic-scroller - v-if="content" - :items="content" + v-if="contentWithKeyField" + :items="contentWithKeyField" :min-item-size="32" :style="{ maxHeight: '170px' }" data-testid="dynamic-content-scroller" @@ -390,6 +410,9 @@ export default { :data="item" :widget-name="widgetName" :level="2" + :row-index="index" + data-testid="extension-list-item" + @clickedAction="onActionClick" /> </dynamic-scroller-item> </template> diff --git a/app/assets/javascripts/vue_merge_request_widget/extensions/security_reports/mr_widget_security_reports.vue b/app/assets/javascripts/vue_merge_request_widget/extensions/security_reports/mr_widget_security_reports.vue index 6155a912683..e7d8de97f20 100644 --- a/app/assets/javascripts/vue_merge_request_widget/extensions/security_reports/mr_widget_security_reports.vue +++ b/app/assets/javascripts/vue_merge_request_widget/extensions/security_reports/mr_widget_security_reports.vue @@ -73,6 +73,9 @@ export default { hasSecurityReports() { return this.artifacts.length > 0; }, + summary() { + return { title: this.$options.i18n.scansHaveRun }; + }, }, methods: { handleIsLoading(value) { @@ -109,7 +112,7 @@ export default { :widget-name="$options.name" :is-collapsible="false" :help-popover="$options.widgetHelpPopover" - :summary="$options.i18n.scansHaveRun" + :summary="summary" @is-loading="handleIsLoading" > <template #action-buttons> diff --git a/app/assets/javascripts/vue_merge_request_widget/extensions/terraform/index.js b/app/assets/javascripts/vue_merge_request_widget/extensions/terraform/index.vue index c5cbed4a280..a6d12ed7aec 100644 --- a/app/assets/javascripts/vue_merge_request_widget/extensions/terraform/index.js +++ b/app/assets/javascripts/vue_merge_request_widget/extensions/terraform/index.vue @@ -1,12 +1,29 @@ +<script> import { __, n__, s__, sprintf } from '~/locale'; import axios from '~/lib/utils/axios_utils'; +import MrWidget from '~/vue_merge_request_widget/components/widget/widget.vue'; import { EXTENSION_ICONS } from '../../constants'; export default { name: 'WidgetTerraform', - enablePolling: true, + components: { + MrWidget, + }, + props: { + mr: { + type: Object, + required: true, + }, + }, + data() { + return { + terraformData: { + collapsed: null, + expanded: null, + }, + }; + }, i18n: { - label: s__('Terraform|Terraform reports'), loading: s__('Terraform|Loading Terraform reports...'), error: s__('Terraform|Failed to load Terraform reports'), reportGenerated: s__('Terraform|A Terraform report was generated in your pipelines.'), @@ -23,18 +40,13 @@ export default { reportErrored: s__('Terraform|Generating the report caused an error.'), fullLog: __('Full log'), }, - props: ['terraformReportsPath'], computed: { - // Extension computed props - statusIcon() { - return EXTENSION_ICONS.warning; + terraformReportsPath() { + return this.mr.terraformReportsPath; }, - }, - methods: { - // Extension methods - summary({ valid = [], invalid = [] }) { - let title; - let subtitle = ''; + + summary() { + const { valid = [], invalid = [] } = this.terraformData.collapsed || {}; const validText = sprintf( n__( @@ -60,20 +72,13 @@ export default { false, ); - if (valid.length) { - title = validText; - if (invalid.length) { - subtitle = invalidText; - } - } else { - title = invalidText; - } - return { - subject: title, - meta: subtitle, + title: valid.length ? validText : invalidText, + subtitle: valid.length && invalid.length ? invalidText : undefined, }; }, + }, + methods: { fetchCollapsedData() { return axios .get(this.terraformReportsPath) @@ -84,6 +89,10 @@ export default { const formattedData = this.prepareReports(reports); + const { valid, invalid } = formattedData; + this.terraformData.collapsed = formattedData; + this.terraformData.expanded = [...valid, ...invalid]; + return { ...res, data: formattedData, @@ -91,14 +100,10 @@ export default { }) .catch(() => { const formattedData = this.prepareReports([{ tf_report_error: 'api_error' }]); - + this.terraformData.collapsed = formattedData; return { data: formattedData }; }); }, - fetchFullData() { - const { valid, invalid } = this.collapsedData; - return Promise.resolve([...valid, ...invalid]); - }, createReportRow(report, iconName) { const addNum = Number(report.create); const changeNum = Number(report.update); @@ -176,4 +181,20 @@ export default { return { valid, invalid }; }, }, + + WARNING_ICON: EXTENSION_ICONS.warning, }; +</script> + +<template> + <mr-widget + :error-text="$options.i18n.error" + :status-icon-name="$options.WARNING_ICON" + :loading-text="$options.i18n.loading" + :widget-name="$options.name" + :is-collapsible="Boolean(terraformData.collapsed)" + :summary="summary" + :content="terraformData.expanded" + :fetch-collapsed-data="fetchCollapsedData" + /> +</template> 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 af9e303594a..9baa2ed15d6 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 @@ -55,7 +55,6 @@ import eventHub from './event_hub'; import mergeRequestQueryVariablesMixin from './mixins/merge_request_query_variables'; import getStateQuery from './queries/get_state.query.graphql'; import getStateSubscription from './queries/get_state.subscription.graphql'; -import terraformExtension from './extensions/terraform'; import accessibilityExtension from './extensions/accessibility'; import codeQualityExtension from './extensions/code_quality'; import testReportExtension from './extensions/test_report'; @@ -238,9 +237,6 @@ export default { this.mr.mergePipelinesEnabled && this.mr.sourceProjectId !== this.mr.targetProjectId, ); }, - shouldRenderTerraformPlans() { - return Boolean(this.mr?.terraformReportsPath); - }, shouldRenderTestReport() { return Boolean(this.mr?.testResultsPath); }, @@ -292,11 +288,6 @@ export default { this.initPostMergeDeploymentsPolling(); } }, - shouldRenderTerraformPlans(newVal) { - if (newVal) { - this.registerTerraformPlans(); - } - }, shouldRenderCodeQuality(newVal) { if (newVal) { this.registerCodeQualityExtension(); @@ -546,11 +537,6 @@ export default { dismissSuggestPipelines() { this.mr.isDismissedSuggestPipeline = true; }, - registerTerraformPlans() { - if (this.shouldRenderTerraformPlans) { - registerExtension(terraformExtension); - } - }, registerAccessibilityExtension() { if (this.shouldShowAccessibilityReport) { registerExtension(accessibilityExtension); |