diff options
author | Clement Ho <clemmakesapps@gmail.com> | 2019-06-07 14:16:29 +0000 |
---|---|---|
committer | Clement Ho <clemmakesapps@gmail.com> | 2019-06-07 14:16:29 +0000 |
commit | 53da0237fae80c3e2b1b7d55d150a87d83f1c6e7 (patch) | |
tree | 871e6b45c5c42565bff8e47f7e946a7f676de472 | |
parent | 5e05ec3b8b7e8f693e3ca74fe73aca64655356a0 (diff) | |
parent | c763d98ed76a2a23c05b9816dee3245779313ecf (diff) | |
download | gitlab-ce-53da0237fae80c3e2b1b7d55d150a87d83f1c6e7.tar.gz |
Merge branch 'ee-9688-fe-mr-merge-order' into 'master'
Backport of EE Displaying Blocking MRs
See merge request gitlab-org/gitlab-ce!29095
6 files changed, 115 insertions, 15 deletions
diff --git a/app/assets/javascripts/reports/components/issues_list.vue b/app/assets/javascripts/reports/components/issues_list.vue index 50f2910e02d..ee07efea3b0 100644 --- a/app/assets/javascripts/reports/components/issues_list.vue +++ b/app/assets/javascripts/reports/components/issues_list.vue @@ -52,11 +52,21 @@ export default { required: false, default: '', }, - showReportSectionStatus: { + showReportSectionStatusIcon: { type: Boolean, required: false, default: true, }, + issuesUlElementClass: { + type: String, + required: false, + default: '', + }, + issueItemClass: { + type: String, + required: false, + default: null, + }, }, computed: { issuesWithState() { @@ -67,6 +77,9 @@ export default { ...this.resolvedIssues.map(wrapIssueWithState(STATUS_SUCCESS)), ]; }, + wclass() { + return `report-block-list ${this.issuesUlElementClass}`; + }, }, }; </script> @@ -77,7 +90,7 @@ export default { :size="$options.typicalReportItemHeight" class="report-block-container" wtag="ul" - wclass="report-block-list" + :wclass="wclass" > <report-item v-for="(wrapped, index) in issuesWithState" @@ -86,7 +99,8 @@ export default { :status="wrapped.status" :component="component" :is-new="wrapped.isNew" - :show-report-section-status="showReportSectionStatus" + :show-report-section-status-icon="showReportSectionStatusIcon" + :class="issueItemClass" /> </smart-virtual-list> </template> diff --git a/app/assets/javascripts/reports/components/report_section.vue b/app/assets/javascripts/reports/components/report_section.vue index 241185e3126..3d576caaf8f 100644 --- a/app/assets/javascripts/reports/components/report_section.vue +++ b/app/assets/javascripts/reports/components/report_section.vue @@ -3,10 +3,7 @@ import { __ } from '~/locale'; import StatusIcon from '~/vue_merge_request_widget/components/mr_widget_status_icon.vue'; import Popover from '~/vue_shared/components/help_popover.vue'; import IssuesList from './issues_list.vue'; - -const LOADING = 'LOADING'; -const ERROR = 'ERROR'; -const SUCCESS = 'SUCCESS'; +import { status } from '../constants'; export default { name: 'ReportSection', @@ -42,7 +39,8 @@ export default { }, successText: { type: String, - required: true, + required: false, + default: '', }, unresolvedIssues: { type: Array, @@ -78,6 +76,21 @@ export default { 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, + }, }, data() { @@ -91,13 +104,13 @@ export default { return this.isCollapsed ? __('Expand') : __('Collapse'); }, isLoading() { - return this.status === LOADING; + return this.status === status.LOADING; }, loadingFailed() { - return this.status === ERROR; + return this.status === status.ERROR; }, isSuccess() { - return this.status === SUCCESS; + return this.status === status.SUCCESS; }, isCollapsible() { return !this.alwaysOpen && this.hasIssues; @@ -132,6 +145,15 @@ export default { hasPopover() { return Object.keys(this.popoverOptions).length > 0; }, + slotName() { + if (this.isSuccess) { + return 'success'; + } else if (this.isLoading) { + return 'loading'; + } + + return 'error'; + }, }, methods: { toggleCollapsed() { @@ -147,6 +169,7 @@ export default { <div class="media-body d-flex flex-align-self-center"> <span class="js-code-text code-text"> {{ headerText }} + <slot :name="slotName"></slot> <popover v-if="hasPopover" :options="popoverOptions" class="prepend-left-5" /> </span> @@ -172,6 +195,9 @@ export default { :neutral-issues="neutralIssues" :component="component" :show-report-section-status-icon="showReportSectionStatusIcon" + :issues-ul-element-class="issuesUlElementClass" + :class="issuesListContainerClass" + :issue-item-class="issueItemClass" /> </slot> </div> diff --git a/app/assets/javascripts/reports/constants.js b/app/assets/javascripts/reports/constants.js index c323dc543f3..66ac1af062b 100644 --- a/app/assets/javascripts/reports/constants.js +++ b/app/assets/javascripts/reports/constants.js @@ -16,3 +16,9 @@ export const STATUS_NEUTRAL = 'neutral'; export const ICON_WARNING = 'warning'; export const ICON_SUCCESS = 'success'; export const ICON_NOTFOUND = 'notfound'; + +export const status = { + LOADING: 'LOADING', + ERROR: 'ERROR', + SUCCESS: 'SUCCESS', +}; diff --git a/app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue b/app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue index b807a35b421..05ad7710a62 100644 --- a/app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue +++ b/app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue @@ -24,6 +24,11 @@ export default { required: false, default: false, }, + greyLinkWhenMerged: { + type: Boolean, + required: false, + default: false, + }, }, computed: { stateTitle() { @@ -36,6 +41,11 @@ export default { }, ); }, + issueableLinkClass() { + return this.greyLinkWhenMerged + ? `sortable-link ${this.state === 'merged' ? ' text-secondary' : ''}` + : 'sortable-link'; + }, }, }; </script> @@ -69,7 +79,7 @@ export default { class="confidential-icon append-right-4 align-self-baseline align-self-md-auto mt-xl-0" :aria-label="__('Confidential')" /> - <a :href="computedPath" class="sortable-link">{{ title }}</a> + <a :href="computedPath" :class="issueableLinkClass">{{ title }}</a> </div> <div class="item-meta d-flex flex-wrap mt-xl-0 justify-content-xl-end flex-xl-nowrap"> <div diff --git a/app/controllers/projects/merge_requests/application_controller.rb b/app/controllers/projects/merge_requests/application_controller.rb index eb469d2d714..f2a6268b3e9 100644 --- a/app/controllers/projects/merge_requests/application_controller.rb +++ b/app/controllers/projects/merge_requests/application_controller.rb @@ -7,11 +7,15 @@ class Projects::MergeRequests::ApplicationController < Projects::ApplicationCont private - # rubocop: disable CodeReuse/ActiveRecord def merge_request - @issuable = @merge_request ||= @project.merge_requests.includes(author: :status).find_by!(iid: params[:id]) + @issuable = + @merge_request ||= + merge_request_includes(@project.merge_requests).find_by_iid!(params[:id]) + end + + def merge_request_includes(association) + association.includes(:metrics, :assignees, author: :status) # rubocop:disable CodeReuse/ActiveRecord end - # rubocop: enable CodeReuse/ActiveRecord def merge_request_params params.require(:merge_request).permit(merge_request_params_attributes) diff --git a/spec/frontend/reports/components/report_section_spec.js b/spec/frontend/reports/components/report_section_spec.js index 3b609484b9e..d4a3073374a 100644 --- a/spec/frontend/reports/components/report_section_spec.js +++ b/spec/frontend/reports/components/report_section_spec.js @@ -197,4 +197,44 @@ describe('Report section', () => { expect(vm.$el.querySelector('.js-collapse-btn').textContent.trim()).toEqual('Expand'); }); }); + + describe('Success and Error slots', () => { + const createComponent = status => { + vm = mountComponentWithSlots(ReportSection, { + props: { + status, + hasIssues: true, + }, + slots: { + success: ['This is a success'], + loading: ['This is loading'], + error: ['This is an error'], + }, + }); + }; + + it('only renders success slot when status is "SUCCESS"', () => { + createComponent('SUCCESS'); + + expect(vm.$el.textContent.trim()).toContain('This is a success'); + expect(vm.$el.textContent.trim()).not.toContain('This is an error'); + expect(vm.$el.textContent.trim()).not.toContain('This is loading'); + }); + + it('only renders error slot when status is "ERROR"', () => { + createComponent('ERROR'); + + expect(vm.$el.textContent.trim()).toContain('This is an error'); + expect(vm.$el.textContent.trim()).not.toContain('This is a success'); + expect(vm.$el.textContent.trim()).not.toContain('This is loading'); + }); + + it('only renders loading slot when status is "LOADING"', () => { + createComponent('LOADING'); + + expect(vm.$el.textContent.trim()).toContain('This is loading'); + expect(vm.$el.textContent.trim()).not.toContain('This is an error'); + expect(vm.$el.textContent.trim()).not.toContain('This is a success'); + }); + }); }); |