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:
Diffstat (limited to 'app/assets/javascripts/ci/reports/components/report_section.vue')
-rw-r--r--app/assets/javascripts/ci/reports/components/report_section.vue237
1 files changed, 237 insertions, 0 deletions
diff --git a/app/assets/javascripts/ci/reports/components/report_section.vue b/app/assets/javascripts/ci/reports/components/report_section.vue
new file mode 100644
index 00000000000..468c8916b8d
--- /dev/null
+++ b/app/assets/javascripts/ci/reports/components/report_section.vue
@@ -0,0 +1,237 @@
+<script>
+import { GlButton } from '@gitlab/ui';
+import api from '~/api';
+import StatusIcon from '~/vue_merge_request_widget/components/mr_widget_status_icon.vue';
+import HelpPopover from '~/vue_shared/components/help_popover.vue';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import { status, SLOT_SUCCESS, SLOT_LOADING, SLOT_ERROR } from '../constants';
+import IssuesList from './issues_list.vue';
+
+export default {
+ name: 'ReportSection',
+ components: {
+ GlButton,
+ IssuesList,
+ HelpPopover,
+ StatusIcon,
+ },
+ mixins: [glFeatureFlagsMixin()],
+ props: {
+ alwaysOpen: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ component: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ status: {
+ type: String,
+ required: true,
+ },
+ loadingText: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ errorText: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ successText: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ unresolvedIssues: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ resolvedIssues: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ neutralIssues: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ infoText: {
+ type: [String, Boolean],
+ required: false,
+ default: false,
+ },
+ hasIssues: {
+ type: Boolean,
+ required: true,
+ },
+ popoverOptions: {
+ type: Object,
+ default: () => ({}),
+ required: false,
+ },
+ showReportSectionStatusIcon: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ issuesUlElementClass: {
+ type: String,
+ required: false,
+ default: undefined,
+ },
+ issuesListContainerClass: {
+ type: String,
+ required: false,
+ default: undefined,
+ },
+ issueItemClass: {
+ type: String,
+ required: false,
+ default: undefined,
+ },
+ shouldEmitToggleEvent: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ trackAction: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ },
+
+ data() {
+ return {
+ isCollapsed: true,
+ };
+ },
+
+ computed: {
+ isLoading() {
+ return this.status === status.LOADING;
+ },
+ loadingFailed() {
+ return this.status === status.ERROR;
+ },
+ isSuccess() {
+ return this.status === status.SUCCESS;
+ },
+ isCollapsible() {
+ return !this.alwaysOpen && this.hasIssues;
+ },
+ isExpanded() {
+ return this.alwaysOpen || !this.isCollapsed;
+ },
+ statusIconName() {
+ if (this.isLoading) {
+ return 'loading';
+ }
+ if (this.loadingFailed || this.unresolvedIssues.length || this.neutralIssues.length) {
+ return 'warning';
+ }
+ return 'success';
+ },
+ headerText() {
+ if (this.isLoading) {
+ return this.loadingText;
+ }
+
+ if (this.isSuccess) {
+ return this.successText;
+ }
+
+ if (this.loadingFailed) {
+ return this.errorText;
+ }
+
+ return '';
+ },
+ hasPopover() {
+ return Object.keys(this.popoverOptions).length > 0;
+ },
+ slotName() {
+ if (this.isSuccess) {
+ return SLOT_SUCCESS;
+ } else if (this.isLoading) {
+ return SLOT_LOADING;
+ }
+
+ return SLOT_ERROR;
+ },
+ },
+ methods: {
+ toggleCollapsed() {
+ if (this.trackAction) {
+ api.trackRedisHllUserEvent(this.trackAction);
+ }
+
+ if (this.shouldEmitToggleEvent) {
+ this.$emit('toggleEvent');
+ }
+ this.isCollapsed = !this.isCollapsed;
+ },
+ },
+};
+</script>
+<template>
+ <section class="media-section">
+ <div class="media">
+ <status-icon :status="statusIconName" :size="24" class="align-self-center" />
+ <div class="media-body gl-display-flex gl-align-items-flex-start gl-flex-direction-row!">
+ <div
+ data-testid="report-section-code-text"
+ class="js-code-text code-text gl-align-self-center gl-flex-grow-1"
+ >
+ <div class="gl-display-flex gl-align-items-center">
+ <p class="gl-line-height-normal gl-m-0">{{ headerText }}</p>
+ <slot :name="slotName"></slot>
+ <help-popover
+ v-if="hasPopover"
+ :options="popoverOptions"
+ class="gl-ml-2 gl-display-inline-flex"
+ />
+ </div>
+ <slot name="sub-heading"></slot>
+ </div>
+
+ <slot name="action-buttons" :is-collapsible="isCollapsible"></slot>
+
+ <div
+ v-if="isCollapsible"
+ class="gl-border-l-1 gl-border-l-solid gl-border-gray-100 gl-ml-3 gl-pl-3"
+ >
+ <gl-button
+ data-testid="report-section-expand-button"
+ data-qa-selector="expand_report_button"
+ category="tertiary"
+ size="small"
+ :icon="isExpanded ? 'chevron-lg-up' : 'chevron-lg-down'"
+ @click="toggleCollapsed"
+ />
+ </div>
+ </div>
+ </div>
+
+ <div v-if="hasIssues" v-show="isExpanded" class="js-report-section-container">
+ <slot name="body">
+ <issues-list
+ :unresolved-issues="unresolvedIssues"
+ :resolved-issues="resolvedIssues"
+ :neutral-issues="neutralIssues"
+ :component="component"
+ :show-report-section-status-icon="showReportSectionStatusIcon"
+ :issues-ul-element-class="issuesUlElementClass"
+ :class="issuesListContainerClass"
+ :issue-item-class="issueItemClass"
+ />
+ </slot>
+ </div>
+ </section>
+</template>