diff options
Diffstat (limited to 'app/assets/javascripts/reports')
21 files changed, 106 insertions, 144 deletions
diff --git a/app/assets/javascripts/reports/accessibility_report/store/getters.js b/app/assets/javascripts/reports/accessibility_report/store/getters.js index 312b333a771..8f8eec11c7f 100644 --- a/app/assets/javascripts/reports/accessibility_report/store/getters.js +++ b/app/assets/javascripts/reports/accessibility_report/store/getters.js @@ -1,7 +1,7 @@ import { LOADING, ERROR, SUCCESS, STATUS_FAILED } from '../../constants'; import { s__, n__ } from '~/locale'; -export const groupedSummaryText = state => { +export const groupedSummaryText = (state) => { if (state.isLoading) { return s__('Reports|Accessibility scanning results are being parsed'); } @@ -22,7 +22,7 @@ export const groupedSummaryText = state => { ); }; -export const summaryStatus = state => { +export const summaryStatus = (state) => { if (state.isLoading) { return LOADING; } @@ -34,12 +34,12 @@ export const summaryStatus = state => { return SUCCESS; }; -export const shouldRenderIssuesList = state => - Object.values(state.report).some(x => Array.isArray(x) && x.length > 0); +export const shouldRenderIssuesList = (state) => + Object.values(state.report).some((x) => Array.isArray(x) && x.length > 0); // We could just map state, but we're going to iterate in the future // to add notes and warnings to these issue lists, so I'm going to // keep these as getters -export const unresolvedIssues = state => state.report.existing_errors; -export const resolvedIssues = state => state.report.resolved_errors; -export const newIssues = state => state.report.new_errors; +export const unresolvedIssues = (state) => state.report.existing_errors; +export const resolvedIssues = (state) => state.report.resolved_errors; +export const newIssues = (state) => state.report.new_errors; diff --git a/app/assets/javascripts/reports/accessibility_report/store/index.js b/app/assets/javascripts/reports/accessibility_report/store/index.js index 9fa2c589324..5bfcd69edec 100644 --- a/app/assets/javascripts/reports/accessibility_report/store/index.js +++ b/app/assets/javascripts/reports/accessibility_report/store/index.js @@ -7,11 +7,11 @@ import state from './state'; Vue.use(Vuex); -export const getStoreConfig = initialState => ({ +export const getStoreConfig = (initialState) => ({ actions, getters, mutations, state: state(initialState), }); -export default initialState => new Vuex.Store(getStoreConfig(initialState)); +export default (initialState) => new Vuex.Store(getStoreConfig(initialState)); diff --git a/app/assets/javascripts/reports/codequality_report/store/actions.js b/app/assets/javascripts/reports/codequality_report/store/actions.js index bf84d27b5ea..e5fb5caca2e 100644 --- a/app/assets/javascripts/reports/codequality_report/store/actions.js +++ b/app/assets/javascripts/reports/codequality_report/store/actions.js @@ -11,13 +11,13 @@ export const fetchReports = ({ state, dispatch, commit }) => { return dispatch('receiveReportsError'); } return Promise.all([axios.get(state.headPath), axios.get(state.basePath)]) - .then(results => + .then((results) => doCodeClimateComparison( parseCodeclimateMetrics(results[0].data, state.headBlobPath), parseCodeclimateMetrics(results[1].data, state.baseBlobPath), ), ) - .then(data => dispatch('receiveReportsSuccess', data)) + .then((data) => dispatch('receiveReportsSuccess', data)) .catch(() => dispatch('receiveReportsError')); }; diff --git a/app/assets/javascripts/reports/codequality_report/store/getters.js b/app/assets/javascripts/reports/codequality_report/store/getters.js index d7c31bcf459..e017bab976c 100644 --- a/app/assets/javascripts/reports/codequality_report/store/getters.js +++ b/app/assets/javascripts/reports/codequality_report/store/getters.js @@ -2,10 +2,10 @@ import { LOADING, ERROR, SUCCESS } from '../../constants'; import { sprintf, __, s__, n__ } from '~/locale'; import { spriteIcon } from '~/lib/utils/common_utils'; -export const hasCodequalityIssues = state => +export const hasCodequalityIssues = (state) => Boolean(state.newIssues?.length || state.resolvedIssues?.length); -export const codequalityStatus = state => { +export const codequalityStatus = (state) => { if (state.isLoading) { return LOADING; } @@ -16,7 +16,7 @@ export const codequalityStatus = state => { return SUCCESS; }; -export const codequalityText = state => { +export const codequalityText = (state) => { const { newIssues, resolvedIssues } = state; const text = []; @@ -41,7 +41,7 @@ export const codequalityText = state => { return text.join(''); }; -export const codequalityPopover = state => { +export const codequalityPopover = (state) => { if (state.headPath && !state.basePath) { return { title: s__('ciReport|Base pipeline codequality artifact not found'), diff --git a/app/assets/javascripts/reports/codequality_report/store/index.js b/app/assets/javascripts/reports/codequality_report/store/index.js index 9fa2c589324..5bfcd69edec 100644 --- a/app/assets/javascripts/reports/codequality_report/store/index.js +++ b/app/assets/javascripts/reports/codequality_report/store/index.js @@ -7,11 +7,11 @@ import state from './state'; Vue.use(Vuex); -export const getStoreConfig = initialState => ({ +export const getStoreConfig = (initialState) => ({ actions, getters, mutations, state: state(initialState), }); -export default initialState => new Vuex.Store(getStoreConfig(initialState)); +export default (initialState) => new Vuex.Store(getStoreConfig(initialState)); diff --git a/app/assets/javascripts/reports/codequality_report/store/utils/codequality_comparison.js b/app/assets/javascripts/reports/codequality_report/store/utils/codequality_comparison.js index eba9e340c4e..fd775f52f7d 100644 --- a/app/assets/javascripts/reports/codequality_report/store/utils/codequality_comparison.js +++ b/app/assets/javascripts/reports/codequality_report/store/utils/codequality_comparison.js @@ -1,7 +1,7 @@ import CodeQualityComparisonWorker from '../../workers/codequality_comparison_worker'; export const parseCodeclimateMetrics = (issues = [], path = '') => { - return issues.map(issue => { + return issues.map((issue) => { const parsedIssue = { ...issue, name: issue.description, diff --git a/app/assets/javascripts/reports/codequality_report/workers/codequality_comparison_worker.js b/app/assets/javascripts/reports/codequality_report/workers/codequality_comparison_worker.js index fc55602f95c..ae389d266f8 100644 --- a/app/assets/javascripts/reports/codequality_report/workers/codequality_comparison_worker.js +++ b/app/assets/javascripts/reports/codequality_report/workers/codequality_comparison_worker.js @@ -3,7 +3,7 @@ import { differenceBy } from 'lodash'; const KEY_TO_FILTER_BY = 'fingerprint'; // eslint-disable-next-line no-restricted-globals -self.addEventListener('message', e => { +self.addEventListener('message', (e) => { const { data } = e; if (data === undefined) { diff --git a/app/assets/javascripts/reports/components/grouped_issues_list.vue b/app/assets/javascripts/reports/components/grouped_issues_list.vue index 97587636644..1826fbaddac 100644 --- a/app/assets/javascripts/reports/components/grouped_issues_list.vue +++ b/app/assets/javascripts/reports/components/grouped_issues_list.vue @@ -41,7 +41,7 @@ export default { computed: { groups() { return this.$options.groups - .map(group => ({ + .map((group) => ({ name: group, issues: this[`${group}Issues`], heading: this[`${group}Heading`], diff --git a/app/assets/javascripts/reports/components/grouped_test_reports_app.vue b/app/assets/javascripts/reports/components/grouped_test_reports_app.vue index c13df60198b..bf1868d427e 100644 --- a/app/assets/javascripts/reports/components/grouped_test_reports_app.vue +++ b/app/assets/javascripts/reports/components/grouped_test_reports_app.vue @@ -10,7 +10,6 @@ import IssuesList from './issues_list.vue'; import Modal from './modal.vue'; import createStore from '../store'; import Tracking from '~/tracking'; -import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { summaryTextBuilder, reportTextBuilder, @@ -28,7 +27,7 @@ export default { Modal, GlButton, }, - mixins: [glFeatureFlagsMixin(), Tracking.mixin()], + mixins: [Tracking.mixin()], props: { endpoint: { type: String, @@ -44,8 +43,9 @@ export default { computed: { ...mapState(['reports', 'isLoading', 'hasError', 'summary']), ...mapState({ - modalTitle: state => state.modal.title || '', - modalData: state => state.modal.data || {}, + modalTitle: (state) => state.modal.title || '', + modalData: (state) => state.modal.data || {}, + modalOpen: (state) => state.modal.open || false, }), ...mapGetters(['summaryStatus']), groupedSummaryText() { @@ -77,7 +77,7 @@ export default { this.fetchReports(); }, methods: { - ...mapActions(['setEndpoint', 'fetchReports']), + ...mapActions(['setEndpoint', 'fetchReports', 'closeModal']), reportText(report) { const { name, summary } = report || {}; @@ -92,7 +92,7 @@ export default { return reportTextBuilder(name, summary); }, hasRecentFailures(summary) { - return this.glFeatures.testFailureHistory && summary?.recentlyFailed > 0; + return summary?.recentlyFailed > 0; }, recentFailuresText(summary) { return recentFailuresTextBuilder(summary); @@ -171,8 +171,12 @@ export default { class="report-block-group-list" /> </template> - - <modal :title="modalTitle" :modal-data="modalData" /> + <modal + :visible="modalOpen" + :title="modalTitle" + :modal-data="modalData" + @hide="closeModal" + /> </div> </template> </report-section> diff --git a/app/assets/javascripts/reports/components/issues_list.vue b/app/assets/javascripts/reports/components/issues_list.vue index ee07efea3b0..16d5b14d3e9 100644 --- a/app/assets/javascripts/reports/components/issues_list.vue +++ b/app/assets/javascripts/reports/components/issues_list.vue @@ -3,7 +3,7 @@ import ReportItem from '~/reports/components/report_item.vue'; import { STATUS_FAILED, STATUS_NEUTRAL, STATUS_SUCCESS } from '~/reports/constants'; import SmartVirtualList from '~/vue_shared/components/smart_virtual_list.vue'; -const wrapIssueWithState = (status, isNew = false) => issue => ({ +const wrapIssueWithState = (status, isNew = false) => (issue) => ({ status: issue.status || status, isNew, issue, diff --git a/app/assets/javascripts/reports/components/modal.vue b/app/assets/javascripts/reports/components/modal.vue index ca95db6c826..6243bddf941 100644 --- a/app/assets/javascripts/reports/components/modal.vue +++ b/app/assets/javascripts/reports/components/modal.vue @@ -1,15 +1,21 @@ <script> -// import { sprintf, __ } from '~/locale'; -import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue'; +import { GlModal, GlLink, GlSprintf } from '@gitlab/ui'; + import CodeBlock from '~/vue_shared/components/code_block.vue'; import { fieldTypes } from '../constants'; export default { components: { - Modal: DeprecatedModal2, CodeBlock, + GlModal, + GlLink, + GlSprintf, }, props: { + visible: { + type: Boolean, + required: true, + }, title: { type: String, required: true, @@ -23,39 +29,43 @@ export default { }; </script> <template> - <modal - id="modal-mrwidget-reports" - :header-title-text="title" - class="modal-security-report-dast modal-hide-footer" + <gl-modal + :visible="visible" + modal-id="modal-mrwidget-reports" + :title="title" + :hide-footer="true" + @hide="$emit('hide')" > - <slot> - <div - v-for="(field, key, index) in modalData" - v-if="field.value" - :key="index" - class="row gl-mt-3 gl-mb-3" - > - <strong class="col-sm-3 text-right"> {{ field.text }}: </strong> + <div + v-for="(field, key, index) in modalData" + v-if="field.value" + :key="index" + class="row gl-mt-3 gl-mb-3" + > + <strong class="col-sm-3 text-right"> {{ field.text }}: </strong> - <div class="col-sm-9 text-secondary"> - <code-block v-if="field.type === $options.fieldTypes.codeBock" :code="field.value" /> + <div class="col-sm-9 text-secondary"> + <code-block v-if="field.type === $options.fieldTypes.codeBock" :code="field.value" /> - <template v-else-if="field.type === $options.fieldTypes.link"> - <a :href="field.value" target="_blank" rel="noopener noreferrer" class="js-modal-link"> - {{ field.value }} - </a> - </template> + <gl-link + v-else-if="field.type === $options.fieldTypes.link" + :href="field.value" + target="_blank" + > + {{ field.value }} + </gl-link> - <template v-else-if="field.type === $options.fieldTypes.seconds">{{ - sprintf(__('%{value} s'), { value: field.value }) - }}</template> + <gl-sprintf + v-else-if="field.type === $options.fieldTypes.seconds" + :message="__('%{value} s')" + > + <template #value>{{ field.value }}</template> + </gl-sprintf> - <template v-else-if="field.type === $options.fieldTypes.text"> - {{ field.value }} - </template> - </div> + <template v-else-if="field.type === $options.fieldTypes.text"> + {{ field.value }} + </template> </div> - </slot> - <div slot="footer"></div> - </modal> + </div> + </gl-modal> </template> diff --git a/app/assets/javascripts/reports/components/modal_open_name.vue b/app/assets/javascripts/reports/components/modal_open_name.vue deleted file mode 100644 index 78e1fcb205b..00000000000 --- a/app/assets/javascripts/reports/components/modal_open_name.vue +++ /dev/null @@ -1,51 +0,0 @@ -<script> -import { GlTooltipDirective, GlResizeObserverDirective } from '@gitlab/ui'; -import { mapActions } from 'vuex'; - -export default { - directives: { - GlTooltip: GlTooltipDirective, - GlResizeObserverDirective, - }, - props: { - issue: { - type: Object, - required: true, - }, - // failed || success - status: { - type: String, - required: true, - }, - }, - data: () => ({ - tooltipTitle: '', - }), - mounted() { - this.updateTooltipTitle(); - }, - methods: { - ...mapActions(['openModal']), - handleIssueClick() { - const { issue, status, openModal } = this; - openModal({ issue, status }); - }, - updateTooltipTitle() { - // Only show the tooltip if the text is truncated with an ellipsis. - this.tooltipTitle = this.$el.offsetWidth < this.$el.scrollWidth ? this.issue.title : ''; - }, - }, -}; -</script> -<template> - <button - v-gl-tooltip="{ boundary: 'viewport' }" - v-gl-resize-observer-directive="updateTooltipTitle" - class="btn-link gl-text-truncate" - :aria-label="s__('Reports|Vulnerability Name')" - :title="tooltipTitle" - @click="handleIssueClick()" - > - {{ issue.title }} - </button> -</template> diff --git a/app/assets/javascripts/reports/components/report_item.vue b/app/assets/javascripts/reports/components/report_item.vue index 1b47d03aa01..df20d5c19ba 100644 --- a/app/assets/javascripts/reports/components/report_item.vue +++ b/app/assets/javascripts/reports/components/report_item.vue @@ -17,7 +17,7 @@ export default { type: String, required: false, default: '', - validator: value => value === '' || Object.values(componentNames).includes(value), + validator: (value) => value === '' || Object.values(componentNames).includes(value), }, // failed || success status: { diff --git a/app/assets/javascripts/reports/components/report_link.vue b/app/assets/javascripts/reports/components/report_link.vue index f285b526a54..1f68f79e487 100644 --- a/app/assets/javascripts/reports/components/report_link.vue +++ b/app/assets/javascripts/reports/components/report_link.vue @@ -21,16 +21,10 @@ export default { rel="noopener noreferrer nofollow" class="break-link" > - {{ issue.path - }}<template v-if="issue.line" - >:{{ issue.line }}</template - > + {{ issue.path }}<template v-if="issue.line">:{{ issue.line }}</template> </a> <template v-else> - {{ issue.path - }}<template v-if="issue.line" - >:{{ issue.line }}</template - > + {{ issue.path }}<template v-if="issue.line">:{{ issue.line }}</template> </template> </div> </template> diff --git a/app/assets/javascripts/reports/components/test_issue_body.vue b/app/assets/javascripts/reports/components/test_issue_body.vue index 69b0dcf881d..ad980b334bb 100644 --- a/app/assets/javascripts/reports/components/test_issue_body.vue +++ b/app/assets/javascripts/reports/components/test_issue_body.vue @@ -1,7 +1,6 @@ <script> import { mapActions } from 'vuex'; import { GlBadge, GlSprintf } from '@gitlab/ui'; -import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; export default { name: 'TestIssueBody', @@ -9,7 +8,6 @@ export default { GlBadge, GlSprintf, }, - mixins: [glFeatureFlagsMixin()], props: { issue: { type: Object, @@ -28,11 +26,7 @@ export default { }, computed: { showRecentFailures() { - return ( - this.glFeatures.testFailureHistory && - this.issue.recent_failures?.count && - this.issue.recent_failures?.base_branch - ); + return this.issue.recent_failures?.count && this.issue.recent_failures?.base_branch; }, }, methods: { diff --git a/app/assets/javascripts/reports/store/actions.js b/app/assets/javascripts/reports/store/actions.js index c5860db6601..301fdce7989 100644 --- a/app/assets/javascripts/reports/store/actions.js +++ b/app/assets/javascripts/reports/store/actions.js @@ -1,5 +1,4 @@ import Visibility from 'visibilityjs'; -import $ from 'jquery'; import axios from '../../lib/utils/axios_utils'; import Poll from '../../lib/utils/poll'; import * as types from './mutation_types'; @@ -78,10 +77,6 @@ export const receiveReportsSuccess = ({ commit }, response) => { export const receiveReportsError = ({ commit }) => commit(types.RECEIVE_REPORTS_ERROR); -export const openModal = ({ dispatch }, payload) => { - dispatch('setModalData', payload); +export const openModal = ({ commit }, payload) => commit(types.SET_ISSUE_MODAL_DATA, payload); - $('#modal-mrwidget-reports').modal('show'); -}; - -export const setModalData = ({ commit }, payload) => commit(types.SET_ISSUE_MODAL_DATA, payload); +export const closeModal = ({ commit }, payload) => commit(types.RESET_ISSUE_MODAL_DATA, payload); diff --git a/app/assets/javascripts/reports/store/getters.js b/app/assets/javascripts/reports/store/getters.js index d49e5760b3f..cc8c4cc446c 100644 --- a/app/assets/javascripts/reports/store/getters.js +++ b/app/assets/javascripts/reports/store/getters.js @@ -1,6 +1,6 @@ import { LOADING, ERROR, SUCCESS, STATUS_FAILED } from '../constants'; -export const summaryStatus = state => { +export const summaryStatus = (state) => { if (state.isLoading) { return LOADING; } diff --git a/app/assets/javascripts/reports/store/mutation_types.js b/app/assets/javascripts/reports/store/mutation_types.js index 599d4862dfe..337085f9bf0 100644 --- a/app/assets/javascripts/reports/store/mutation_types.js +++ b/app/assets/javascripts/reports/store/mutation_types.js @@ -4,3 +4,4 @@ export const REQUEST_REPORTS = 'REQUEST_REPORTS'; export const RECEIVE_REPORTS_SUCCESS = 'RECEIVE_REPORTS_SUCCESS'; export const RECEIVE_REPORTS_ERROR = 'RECEIVE_REPORTS_ERROR'; export const SET_ISSUE_MODAL_DATA = 'SET_ISSUE_MODAL_DATA'; +export const RESET_ISSUE_MODAL_DATA = 'RESET_ISSUE_MODAL_DATA'; diff --git a/app/assets/javascripts/reports/store/mutations.js b/app/assets/javascripts/reports/store/mutations.js index acaa98754b0..3bb31d71d8f 100644 --- a/app/assets/javascripts/reports/store/mutations.js +++ b/app/assets/javascripts/reports/store/mutations.js @@ -9,7 +9,7 @@ export default { state.isLoading = true; }, [types.RECEIVE_REPORTS_SUCCESS](state, response) { - state.hasError = response.suites.some(suite => suite.status === 'error'); + state.hasError = response.suites.some((suite) => suite.status === 'error'); state.isLoading = false; @@ -44,7 +44,7 @@ export default { [types.SET_ISSUE_MODAL_DATA](state, payload) { state.modal.title = payload.issue.name; - Object.keys(payload.issue).forEach(key => { + Object.keys(payload.issue).forEach((key) => { if (Object.prototype.hasOwnProperty.call(state.modal.data, key)) { state.modal.data[key] = { ...state.modal.data[key], @@ -52,5 +52,19 @@ export default { }; } }); + + state.modal.open = true; + }, + [types.RESET_ISSUE_MODAL_DATA](state) { + state.modal.open = false; + + // Resetting modal data + state.modal.title = null; + Object.keys(state.modal.data).forEach((key) => { + state.modal.data[key] = { + ...state.modal.data[key], + value: null, + }; + }); }, }; diff --git a/app/assets/javascripts/reports/store/state.js b/app/assets/javascripts/reports/store/state.js index 4f9eb53e787..e8a0db2e1a8 100644 --- a/app/assets/javascripts/reports/store/state.js +++ b/app/assets/javascripts/reports/store/state.js @@ -38,6 +38,7 @@ export default () => ({ modal: { title: null, + open: false, data: { class: { diff --git a/app/assets/javascripts/reports/store/utils.js b/app/assets/javascripts/reports/store/utils.js index 2d32daee9d0..d89833032a0 100644 --- a/app/assets/javascripts/reports/store/utils.js +++ b/app/assets/javascripts/reports/store/utils.js @@ -7,7 +7,7 @@ import { ICON_NOTFOUND, } from '../constants'; -const textBuilder = results => { +const textBuilder = (results) => { const { failed, errored, resolved, total } = results; const failedOrErrored = (failed || 0) + (errored || 0); @@ -70,18 +70,18 @@ export const recentFailuresTextBuilder = (summary = {}) => { ); }; -export const countRecentlyFailedTests = subject => { +export const countRecentlyFailedTests = (subject) => { // handle either a single report or an array of reports const reports = !subject.length ? [subject] : subject; return reports - .map(report => { + .map((report) => { return ( [report.new_failures, report.existing_failures, report.resolved_failures] // only count tests which have failed more than once .map( - failureArray => - failureArray.filter(failure => failure.recent_failures?.count > 1).length, + (failureArray) => + failureArray.filter((failure) => failure.recent_failures?.count > 1).length, ) .reduce((total, count) => total + count, 0) ); @@ -89,7 +89,7 @@ export const countRecentlyFailedTests = subject => { .reduce((total, count) => total + count, 0); }; -export const statusIcon = status => { +export const statusIcon = (status) => { if (status === STATUS_FAILED) { return ICON_WARNING; } |