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