diff options
Diffstat (limited to 'app/assets/javascripts/reports')
10 files changed, 22 insertions, 333 deletions
diff --git a/app/assets/javascripts/reports/accessibility_report/components/accessibility_issue_body.vue b/app/assets/javascripts/reports/accessibility_report/components/accessibility_issue_body.vue deleted file mode 100644 index 05ab5c2cc90..00000000000 --- a/app/assets/javascripts/reports/accessibility_report/components/accessibility_issue_body.vue +++ /dev/null @@ -1,61 +0,0 @@ -<script> -import { GlBadge, GlLink } from '@gitlab/ui'; - -export default { - name: 'AccessibilityIssueBody', - components: { - GlBadge, - GlLink, - }, - props: { - issue: { - type: Object, - required: true, - }, - isNew: { - type: Boolean, - required: false, - default: false, - }, - }, - computed: { - parsedTECHSCode() { - /* - * In issue code looks like "WCAG2AA.Principle1.Guideline1_4.1_4_3.G18.Fail" - * or "WCAG2AA.Principle4.Guideline4_1.4_1_2.H91.A.NoContent" - * - * The TECHS code is the "G18", "G168", "H91", etc. from the code which is used for the documentation. - * Here we simply split the string on `.` and get the code in the 5th position - */ - return this.issue.code?.split('.')[4]; - }, - learnMoreUrl() { - // eslint-disable-next-line @gitlab/require-i18n-strings - return `https://www.w3.org/TR/WCAG20-TECHS/${this.parsedTECHSCode || 'Overview'}.html`; - }, - }, -}; -</script> -<template> - <div class="report-block-list-issue-description gl-mt-2 gl-mb-2"> - <div ref="accessibility-issue-description" class="report-block-list-issue-description-text"> - <gl-badge v-if="isNew" class="gl-mr-2" variant="danger">{{ - s__('AccessibilityReport|New') - }}</gl-badge> - <div> - {{ - sprintf( - s__( - 'AccessibilityReport|The accessibility scanning found an error of the following type: %{code}', - ), - { code: issue.code }, - ) - }} - <gl-link ref="accessibility-issue-learn-more" :href="learnMoreUrl" target="_blank">{{ - s__('AccessibilityReport|Learn more') - }}</gl-link> - </div> - {{ sprintf(s__('AccessibilityReport|Message: %{message}'), { message: issue.message }) }} - </div> - </div> -</template> diff --git a/app/assets/javascripts/reports/accessibility_report/grouped_accessibility_reports_app.vue b/app/assets/javascripts/reports/accessibility_report/grouped_accessibility_reports_app.vue deleted file mode 100644 index 99cdeae545e..00000000000 --- a/app/assets/javascripts/reports/accessibility_report/grouped_accessibility_reports_app.vue +++ /dev/null @@ -1,65 +0,0 @@ -<script> -import { mapActions, mapGetters } from 'vuex'; -import { componentNames } from '~/reports/components/issue_body'; -import IssuesList from '~/reports/components/issues_list.vue'; -import ReportSection from '~/reports/components/report_section.vue'; -import createStore from './store'; - -export default { - name: 'GroupedAccessibilityReportsApp', - store: createStore(), - components: { - ReportSection, - IssuesList, - }, - props: { - endpoint: { - type: String, - required: true, - }, - }, - componentNames, - computed: { - ...mapGetters([ - 'summaryStatus', - 'groupedSummaryText', - 'shouldRenderIssuesList', - 'unresolvedIssues', - 'resolvedIssues', - 'newIssues', - ]), - }, - created() { - this.setEndpoint(this.endpoint); - - this.fetchReport(); - }, - methods: { - ...mapActions(['fetchReport', 'setEndpoint']), - }, -}; -</script> -<template> - <report-section - :status="summaryStatus" - :success-text="groupedSummaryText" - :loading-text="groupedSummaryText" - :error-text="groupedSummaryText" - :has-issues="shouldRenderIssuesList" - track-action="users_expanding_testing_accessibility_report" - class="mr-widget-section grouped-security-reports mr-report" - > - <template #body> - <div class="mr-widget-grouped-section report-block"> - <issues-list - v-if="shouldRenderIssuesList" - :unresolved-issues="unresolvedIssues" - :new-issues="newIssues" - :resolved-issues="resolvedIssues" - :component="$options.componentNames.AccessibilityIssueBody" - class="report-block-group-list" - /> - </div> - </template> - </report-section> -</template> diff --git a/app/assets/javascripts/reports/accessibility_report/store/actions.js b/app/assets/javascripts/reports/accessibility_report/store/actions.js deleted file mode 100644 index e0142a35291..00000000000 --- a/app/assets/javascripts/reports/accessibility_report/store/actions.js +++ /dev/null @@ -1,76 +0,0 @@ -import Visibility from 'visibilityjs'; -import axios from '~/lib/utils/axios_utils'; -import httpStatusCodes from '~/lib/utils/http_status'; -import Poll from '~/lib/utils/poll'; -import * as types from './mutation_types'; - -let eTagPoll; - -export const clearEtagPoll = () => { - eTagPoll = null; -}; - -export const stopPolling = () => { - if (eTagPoll) eTagPoll.stop(); -}; - -export const restartPolling = () => { - if (eTagPoll) eTagPoll.restart(); -}; - -export const setEndpoint = ({ commit }, endpoint) => commit(types.SET_ENDPOINT, endpoint); - -/** - * We need to poll the report endpoint while they are being parsed in the Backend. - * This can take up to one minute. - * - * Poll.js will handle etag response. - * While http status code is 204, it means it's parsing, and we'll keep polling - * When http status code is 200, it means parsing is done, we can show the results & stop polling - * When http status code is 500, it means parsing went wrong and we stop polling - */ -export const fetchReport = ({ state, dispatch, commit }) => { - commit(types.REQUEST_REPORT); - - eTagPoll = new Poll({ - resource: { - getReport(endpoint) { - return axios.get(endpoint); - }, - }, - data: state.endpoint, - method: 'getReport', - successCallback: ({ status, data }) => dispatch('receiveReportSuccess', { status, data }), - errorCallback: () => dispatch('receiveReportError'), - }); - - if (!Visibility.hidden()) { - eTagPoll.makeRequest(); - } else { - axios - .get(state.endpoint) - .then(({ status, data }) => dispatch('receiveReportSuccess', { status, data })) - .catch(() => dispatch('receiveReportError')); - } - - Visibility.change(() => { - if (!Visibility.hidden() && state.isLoading) { - dispatch('restartPolling'); - } else { - dispatch('stopPolling'); - } - }); -}; - -export const receiveReportSuccess = ({ commit, dispatch }, { status, data }) => { - if (status === httpStatusCodes.OK) { - commit(types.RECEIVE_REPORT_SUCCESS, data); - // Stop polling since we have the information already parsed and it won't be changing - dispatch('stopPolling'); - } -}; - -export const receiveReportError = ({ commit, dispatch }) => { - commit(types.RECEIVE_REPORT_ERROR); - dispatch('stopPolling'); -}; diff --git a/app/assets/javascripts/reports/accessibility_report/store/getters.js b/app/assets/javascripts/reports/accessibility_report/store/getters.js deleted file mode 100644 index 20506b1bfd1..00000000000 --- a/app/assets/javascripts/reports/accessibility_report/store/getters.js +++ /dev/null @@ -1,45 +0,0 @@ -import { s__, n__ } from '~/locale'; -import { LOADING, ERROR, SUCCESS, STATUS_FAILED } from '../../constants'; - -export const groupedSummaryText = (state) => { - if (state.isLoading) { - return s__('Reports|Accessibility scanning results are being parsed'); - } - - if (state.hasError) { - return s__('Reports|Accessibility scanning failed loading results'); - } - - const numberOfResults = state.report?.summary?.errored || 0; - if (numberOfResults === 0) { - return s__('Reports|Accessibility scanning detected no issues for the source branch only'); - } - - return n__( - 'Reports|Accessibility scanning detected %d issue for the source branch only', - 'Reports|Accessibility scanning detected %d issues for the source branch only', - numberOfResults, - ); -}; - -export const summaryStatus = (state) => { - if (state.isLoading) { - return LOADING; - } - - if (state.hasError || state.status === STATUS_FAILED) { - return ERROR; - } - - return SUCCESS; -}; - -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; diff --git a/app/assets/javascripts/reports/accessibility_report/store/index.js b/app/assets/javascripts/reports/accessibility_report/store/index.js deleted file mode 100644 index 5bfcd69edec..00000000000 --- a/app/assets/javascripts/reports/accessibility_report/store/index.js +++ /dev/null @@ -1,17 +0,0 @@ -import Vue from 'vue'; -import Vuex from 'vuex'; -import * as actions from './actions'; -import * as getters from './getters'; -import mutations from './mutations'; -import state from './state'; - -Vue.use(Vuex); - -export const getStoreConfig = (initialState) => ({ - actions, - getters, - mutations, - state: state(initialState), -}); - -export default (initialState) => new Vuex.Store(getStoreConfig(initialState)); diff --git a/app/assets/javascripts/reports/accessibility_report/store/mutation_types.js b/app/assets/javascripts/reports/accessibility_report/store/mutation_types.js deleted file mode 100644 index 22e2330e1ea..00000000000 --- a/app/assets/javascripts/reports/accessibility_report/store/mutation_types.js +++ /dev/null @@ -1,5 +0,0 @@ -export const SET_ENDPOINT = 'SET_ENDPOINT'; - -export const REQUEST_REPORT = 'REQUEST_REPORT'; -export const RECEIVE_REPORT_SUCCESS = 'RECEIVE_REPORT_SUCCESS'; -export const RECEIVE_REPORT_ERROR = 'RECEIVE_REPORT_ERROR'; diff --git a/app/assets/javascripts/reports/accessibility_report/store/mutations.js b/app/assets/javascripts/reports/accessibility_report/store/mutations.js deleted file mode 100644 index 20d3e5be9a3..00000000000 --- a/app/assets/javascripts/reports/accessibility_report/store/mutations.js +++ /dev/null @@ -1,20 +0,0 @@ -import * as types from './mutation_types'; - -export default { - [types.SET_ENDPOINT](state, endpoint) { - state.endpoint = endpoint; - }, - [types.REQUEST_REPORT](state) { - state.isLoading = true; - }, - [types.RECEIVE_REPORT_SUCCESS](state, report) { - state.hasError = false; - state.isLoading = false; - state.report = report; - }, - [types.RECEIVE_REPORT_ERROR](state) { - state.isLoading = false; - state.hasError = true; - state.report = {}; - }, -}; diff --git a/app/assets/javascripts/reports/accessibility_report/store/state.js b/app/assets/javascripts/reports/accessibility_report/store/state.js deleted file mode 100644 index 2a4cefea5e6..00000000000 --- a/app/assets/javascripts/reports/accessibility_report/store/state.js +++ /dev/null @@ -1,28 +0,0 @@ -export default (initialState = {}) => ({ - endpoint: initialState.endpoint || '', - - isLoading: initialState.isLoading || false, - hasError: initialState.hasError || false, - - /** - * Report will have the following format: - * { - * status: {String}, - * summary: { - * total: {Number}, - * resolved: {Number}, - * errored: {Number}, - * }, - * existing_errors: {Array.<Object>}, - * existing_notes: {Array.<Object>}, - * existing_warnings: {Array.<Object>}, - * new_errors: {Array.<Object>}, - * new_notes: {Array.<Object>}, - * new_warnings: {Array.<Object>}, - * resolved_errors: {Array.<Object>}, - * resolved_notes: {Array.<Object>}, - * resolved_warnings: {Array.<Object>}, - * } - */ - report: initialState.report || {}, -}); diff --git a/app/assets/javascripts/reports/components/issue_body.js b/app/assets/javascripts/reports/components/issue_body.js index 04e72809e62..a76a6f45c07 100644 --- a/app/assets/javascripts/reports/components/issue_body.js +++ b/app/assets/javascripts/reports/components/issue_body.js @@ -1,14 +1,11 @@ import IssueStatusIcon from '~/reports/components/issue_status_icon.vue'; export const components = { - AccessibilityIssueBody: () => - import('../accessibility_report/components/accessibility_issue_body.vue'), CodequalityIssueBody: () => import('../codequality_report/components/codequality_issue_body.vue'), TestIssueBody: () => import('../grouped_test_report/components/test_issue_body.vue'), }; export const componentNames = { - AccessibilityIssueBody: 'AccessibilityIssueBody', CodequalityIssueBody: 'CodequalityIssueBody', TestIssueBody: 'TestIssueBody', }; diff --git a/app/assets/javascripts/reports/components/report_section.vue b/app/assets/javascripts/reports/components/report_section.vue index 6061be465ca..bb86695b9a3 100644 --- a/app/assets/javascripts/reports/components/report_section.vue +++ b/app/assets/javascripts/reports/components/report_section.vue @@ -1,7 +1,6 @@ <script> import { GlButton } from '@gitlab/ui'; import api from '~/api'; -import { __ } from '~/locale'; 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'; @@ -115,9 +114,6 @@ export default { }, computed: { - collapseText() { - return this.isCollapsed ? __('Expand') : __('Collapse'); - }, isLoading() { return this.status === status.LOADING; }, @@ -172,6 +168,11 @@ export default { }, methods: { toggleCollapsed() { + // Because the top-level div is always clickable, we need to check if we can collapse. + if (!this.isCollapsible) { + return; + } + if (this.trackAction) { api.trackRedisHllUserEvent(this.trackAction); } @@ -186,10 +187,13 @@ export default { </script> <template> <section class="media-section"> - <div class="media"> + <div class="media" :class="{ 'gl-cursor-pointer': isCollapsible }" @click="toggleCollapsed"> <status-icon :status="statusIconName" :size="24" class="align-self-center" /> - <div class="media-body d-flex flex-align-self-center align-items-center"> - <div data-testid="report-section-code-text" class="js-code-text code-text"> + <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> @@ -204,14 +208,19 @@ export default { <slot name="action-buttons" :is-collapsible="isCollapsible"></slot> - <gl-button + <div v-if="isCollapsible" - data-testid="report-section-expand-button" - data-qa-selector="expand_report_button" - @click="toggleCollapsed" + class="gl-border-l-1 gl-border-l-solid gl-border-gray-100 gl-ml-3 gl-pl-3" > - {{ collapseText }} - </gl-button> + <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.stop="toggleCollapsed" + /> + </div> </div> </div> |