Commit 56cf2dce authored by Tim Zallmann's avatar Tim Zallmann

Merge branch '2035-frontend-remove-feature-flag-code' into 'master'

Remove blocking issues FE feature flag code

See merge request gitlab-org/gitlab!24460
parents 755d1cbf aaff6347
......@@ -44,7 +44,6 @@ class Projects::IssuesController < Projects::ApplicationController
before_action do
push_frontend_feature_flag(:vue_issuable_sidebar, project.group)
push_frontend_feature_flag(:issue_link_types, project)
end
around_action :allow_gitaly_ref_name_caching, only: [:discussions]
......
---
title: Add blocking issues feature
merge_request: 24460
author:
type: added
<script>
import { GlFormGroup, GlFormRadioGroup, GlLoadingIcon } from '@gitlab/ui';
import { __ } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import RelatedIssuableInput from './related_issuable_input.vue';
import {
issuableTypesMap,
......@@ -19,7 +18,6 @@ export default {
GlLoadingIcon,
RelatedIssuableInput,
},
mixins: [glFeatureFlagsMixin()],
props: {
inputValue: {
type: String,
......@@ -125,24 +123,22 @@ export default {
<template>
<form @submit.prevent="onFormSubmit">
<template v-if="glFeatures.issueLinkTypes">
<gl-form-group
:label="__('The current issue')"
label-for="linked-issue-type-radio"
label-class="label-bold"
class="mb-2"
>
<gl-form-radio-group
id="linked-issue-type-radio"
v-model="linkedIssueType"
:options="linkedIssueTypes"
:checked="linkedIssueType"
/>
</gl-form-group>
<p class="bold">
{{ __('the following issue(s)') }}
</p>
</template>
<gl-form-group
:label="__('The current issue')"
label-for="linked-issue-type-radio"
label-class="label-bold"
class="mb-2"
>
<gl-form-radio-group
id="linked-issue-type-radio"
v-model="linkedIssueType"
:options="linkedIssueTypes"
:checked="linkedIssueType"
/>
</gl-form-group>
<p class="bold">
{{ __('the following issue(s)') }}
</p>
<related-issuable-input
ref="relatedIssuableInput"
:focus-on-mount="true"
......
<script>
import { __ } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import AddIssuableForm from './add_issuable_form.vue';
import RelatedIssuesList from './related_issues_list.vue';
import {
......@@ -18,7 +16,6 @@ export default {
AddIssuableForm,
RelatedIssuesList,
},
mixins: [glFeatureFlagsMixin()],
props: {
isFetching: {
type: Boolean,
......@@ -84,20 +81,12 @@ export default {
return this.relatedIssues.length > 0;
},
categorisedIssues() {
if (this.glFeatures.issueLinkTypes) {
return Object.values(linkedIssueTypesMap)
.map(linkType => ({
linkType,
issues: this.relatedIssues.filter(issue => issue.linkType === linkType),
}))
.filter(obj => obj.issues.length > 0);
}
return [
{
linkType: linkedIssueTypesMap.RELATES_TO,
issues: this.relatedIssues,
},
];
return Object.values(linkedIssueTypesMap)
.map(linkType => ({
linkType,
issues: this.relatedIssues.filter(issue => issue.linkType === linkType),
}))
.filter(obj => obj.issues.length > 0);
},
shouldShowTokenBody() {
return this.hasRelatedIssues || this.isFetching;
......@@ -117,32 +106,9 @@ export default {
qaClass() {
return issuableQaClassMap[this.issuableType];
},
cardBodyCssClass() {
return this.glFeatures.issueLinkTypes
? {
'linked-issues-card-body': true,
'bg-gray-light': true,
'gl-p-3': this.isFormVisible || this.shouldShowTokenBody,
}
: {};
},
formCssClass() {
if (this.glFeatures.issueLinkTypes) {
return ['bordered-box', 'bg-white'];
}
if (this.hasRelatedIssues) {
return [
'border-bottom-width-1px',
'border-bottom-style-solid',
'border-bottom-color-default',
];
}
return [];
},
},
created() {
this.linkedIssueTypesTextMap = linkedIssueTypesTextMap;
this.title = this.glFeatures.issueLinkTypes ? __('Linked issues') : __('Related issues');
},
};
</script>
......@@ -152,7 +118,7 @@ export default {
<div class="card card-slim">
<div :class="{ 'panel-empty-heading border-bottom-0': !hasBody }" class="card-header">
<h3 class="card-title mt-0 mb-0 h5">
{{ title }}
{{ __('Linked issues') }}
<a v-if="hasHelpPath" :href="helpPath">
<i
class="related-issues-header-help-icon fa fa-question-circle"
......@@ -184,11 +150,13 @@ export default {
</div>
</h3>
</div>
<div :class="cardBodyCssClass">
<div
class="linked-issues-card-body bg-gray-light"
:class="{ 'gl-p-3': isFormVisible || shouldShowTokenBody }"
>
<div
v-if="isFormVisible"
class="js-add-related-issues-form-area card-body"
:class="formCssClass"
class="js-add-related-issues-form-area card-body bordered-box bg-white"
>
<add-issuable-form
:is-submitting="isSubmitting"
......
......@@ -6,7 +6,6 @@ import sortableConfig from 'ee/sortable/sortable_config';
import IssueDueDate from '~/boards/components/issue_due_date.vue';
import RelatedIssuableItem from '~/vue_shared/components/issue/related_issuable_item.vue';
import tooltip from '~/vue_shared/directives/tooltip';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
name: 'RelatedIssuesList',
......@@ -19,7 +18,6 @@ export default {
IssueWeight,
RelatedIssuableItem,
},
mixins: [glFeatureFlagsMixin()],
props: {
canAdmin: {
type: Boolean,
......@@ -59,9 +57,6 @@ export default {
validIssueWeight() {
return this.issue && this.issue.weight >= 0;
},
shouldRenderHeading() {
return this.glFeatures.issueLinkTypes && this.heading;
},
},
mounted() {
if (this.canReorder) {
......@@ -112,14 +107,10 @@ export default {
<template>
<div>
<h4 v-if="shouldRenderHeading" class="gl-font-size-14 mt-0">{{ heading }}</h4>
<h4 v-if="heading" class="gl-font-size-14 mt-0">{{ heading }}</h4>
<div
class="related-issues-token-body"
:class="{
'sortable-container': canReorder,
'bordered-box': glFeatures.issueLinkTypes,
'bg-white': glFeatures.issueLinkTypes,
}"
class="related-issues-token-body bordered-box bg-white"
:class="{ 'sortable-container': canReorder }"
>
<div v-if="isFetching" class="related-issues-loading-icon qa-related-issues-loading-icon">
<gl-loading-icon ref="loadingIcon" label="Fetching linked issues" class="prepend-top-5" />
......
......@@ -6,4 +6,4 @@
.card.card-slim
.card-header.panel-empty-heading.border-bottom-0
%h3.card-title.mt-0.mb-0.h5
Related issues
= _('Linked issues')
......@@ -421,7 +421,7 @@ describe 'Related issues', :js do
end
end
describe 'issue link types' do
context 'with "Relates to", "Blocks", "Is blocked by" groupings' do
def add_linked_issue(issue, radio_input_value)
find('.js-issue-count-badge-add-button').click
find('.js-add-issuable-form-input').set "#{issue.to_reference(project)} "
......
......@@ -95,52 +95,7 @@ describe('AddIssuableForm', () => {
});
});
it('should emit the `addIssuableFormSubmit` event when submitting pending issues', () => {
wrapper = mount(AddIssuableForm, {
propsData: {
inputValue: 'foo #123',
pendingReferences: [issuable1.reference, issuable2.reference],
pathIdSeparator,
},
});
spyOn(wrapper.vm, '$emit');
const newInputValue = 'filling in things';
const inputEl = findFormInput(wrapper);
inputEl.value = newInputValue;
wrapper.vm.onFormSubmit();
expect(wrapper.vm.$emit).toHaveBeenCalledWith('addIssuableFormSubmit', {
pendingReferences: newInputValue,
linkedIssueType: linkedIssueTypesMap.RELATES_TO,
});
});
it('should emit the `addIssuableFormCancel` event when canceling form to collapse', () => {
spyOn(wrapper.vm, '$emit');
wrapper.vm.onFormCancel();
expect(wrapper.vm.$emit).toHaveBeenCalledWith('addIssuableFormCancel');
});
});
describe('with :issue_link_types feature flag on', () => {
beforeEach(() => {
wrapper = mount(AddIssuableForm, {
propsData: {
inputValue: '',
pendingReferences: [],
pathIdSeparator,
},
provide: {
glFeatures: {
issueLinkTypes: true,
},
},
});
});
describe('radio buttons', () => {
describe('form radio buttons', () => {
let radioInputs;
beforeEach(() => {
......@@ -165,6 +120,16 @@ describe('AddIssuableForm', () => {
});
describe('when the form is submitted', () => {
beforeEach(() => {
wrapper = mount(AddIssuableForm, {
propsData: {
inputValue: '',
pendingReferences: [],
pathIdSeparator,
},
});
});
it('emits an event with a "relates_to" link type when the "relates to" radio input selected', done => {
spyOn(wrapper.vm, '$emit');
......
......@@ -28,6 +28,10 @@ describe('RelatedIssuesBlock', () => {
});
});
it('displays "Linked issues" in the header', () => {
expect(wrapper.find('h3').text()).toContain('Linked issues');
});
it('unable to add new related issues', () => {
expect(wrapper.vm.$refs.issueCountBadgeAddButton).toBeUndefined();
});
......@@ -86,18 +90,40 @@ describe('RelatedIssuesBlock', () => {
});
describe('with relatedIssues', () => {
let categorizedHeadings;
beforeEach(() => {
wrapper = mount(RelatedIssuesBlock, {
propsData: {
pathIdSeparator: PathIdSeparator.Issue,
relatedIssues: [issuable1, issuable2],
relatedIssues: [issuable1, issuable2, issuable3],
issuableType: 'issue',
},
});
categorizedHeadings = wrapper.findAll('h4');
});
it('should render issue tokens items', () => {
expect(wrapper.findAll('.js-related-issues-token-list-item').length).toEqual(2);
expect(wrapper.findAll('.js-related-issues-token-list-item').length).toEqual(3);
});
it('shows "Blocks" heading', () => {
const blocks = linkedIssueTypesTextMap[linkedIssueTypesMap.BLOCKS];
expect(categorizedHeadings.at(0).text()).toBe(blocks);
});
it('shows "Is blocked by" heading', () => {
const isBlockedBy = linkedIssueTypesTextMap[linkedIssueTypesMap.IS_BLOCKED_BY];
expect(categorizedHeadings.at(1).text()).toBe(isBlockedBy);
});
it('shows "Relates to" heading', () => {
const relatesTo = linkedIssueTypesTextMap[linkedIssueTypesMap.RELATES_TO];
expect(categorizedHeadings.at(2).text()).toBe(relatesTo);
});
});
......@@ -124,51 +150,4 @@ describe('RelatedIssuesBlock', () => {
});
});
});
describe('with :issue_link_types feature flag on', () => {
beforeEach(() => {
wrapper = mount(RelatedIssuesBlock, {
propsData: {
pathIdSeparator: PathIdSeparator.Issue,
relatedIssues: [issuable1, issuable2, issuable3],
issuableType: 'issue',
},
provide: {
glFeatures: {
issueLinkTypes: true,
},
},
});
});
it('displays "Linked issues" in the header', () => {
expect(wrapper.find('h3').text()).toContain('Linked issues');
});
describe('categorized headings', () => {
let categorizedHeadings;
beforeEach(() => {
categorizedHeadings = wrapper.findAll('h4');
});
it('shows "Blocks" heading', () => {
const blocks = linkedIssueTypesTextMap[linkedIssueTypesMap.BLOCKS];
expect(categorizedHeadings.at(0).text()).toBe(blocks);
});
it('shows "Is blocked by" heading', () => {
const isBlockedBy = linkedIssueTypesTextMap[linkedIssueTypesMap.IS_BLOCKED_BY];
expect(categorizedHeadings.at(1).text()).toBe(isBlockedBy);
});
it('shows "Relates to" heading', () => {
const relatesTo = linkedIssueTypesTextMap[linkedIssueTypesMap.RELATES_TO];
expect(categorizedHeadings.at(2).text()).toBe(relatesTo);
});
});
});
});
......@@ -17,15 +17,22 @@ describe('RelatedIssuesList', () => {
});
describe('with defaults', () => {
const heading = 'Related to';
beforeEach(() => {
wrapper = mount(RelatedIssuesList, {
propsData: {
pathIdSeparator: PathIdSeparator.Issue,
issuableType: 'issue',
heading,
},
});
});
it('shows a heading', () => {
expect(wrapper.find('h4').text()).toContain(heading);
});
it('should not show loading icon', () => {
expect(wrapper.vm.$refs.loadingIcon).toBeUndefined();
});
......@@ -158,25 +165,4 @@ describe('RelatedIssuesList', () => {
});
});
});
describe('with :issue_link_types feature flag on', () => {
it('shows a heading', () => {
const heading = 'Related';
wrapper = mount(RelatedIssuesList, {
propsData: {
pathIdSeparator: PathIdSeparator.Issue,
issuableType: 'issue',
heading,
},
provide: {
glFeatures: {
issueLinkTypes: true,
},
},
});
expect(wrapper.find('h4').text()).toContain(heading);
});
});
});
......@@ -15795,9 +15795,6 @@ msgstr ""
msgid "Related Merged Requests"
msgstr ""
msgid "Related issues"
msgstr ""
msgid "Related merge requests"
msgstr ""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment