Commit 97b9241a authored by Kerri Miller's avatar Kerri Miller Committed by Alex Kalderimis

Remove multiline_comments feature flag

Removes from backend and frontend code. Flag initially added in 13.3
parent c65265b4
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
import { mapActions, mapGetters, mapState } from 'vuex'; import { mapActions, mapGetters, mapState } from 'vuex';
import { GlButton } from '@gitlab/ui'; import { GlButton } from '@gitlab/ui';
import NoteableNote from '~/notes/components/noteable_note.vue'; import NoteableNote from '~/notes/components/noteable_note.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import PublishButton from './publish_button.vue'; import PublishButton from './publish_button.vue';
export default { export default {
...@@ -12,7 +11,6 @@ export default { ...@@ -12,7 +11,6 @@ export default {
PublishButton, PublishButton,
GlButton, GlButton,
}, },
mixins: [glFeatureFlagsMixin()],
props: { props: {
draft: { draft: {
type: Object, type: Object,
...@@ -63,14 +61,14 @@ export default { ...@@ -63,14 +61,14 @@ export default {
this.isEditingDraft = false; this.isEditingDraft = false;
}, },
handleMouseEnter(draft) { handleMouseEnter(draft) {
if (this.glFeatures.multilineComments && draft.position) { if (draft.position) {
this.setSelectedCommentPositionHover(draft.position.line_range); this.setSelectedCommentPositionHover(draft.position.line_range);
} }
}, },
handleMouseLeave(draft) { handleMouseLeave(draft) {
// Even though position isn't used here we still don't want to unecessarily call a mutation // Even though position isn't used here we still don't want to unnecessarily call a mutation
// The lack of position tells us that highlighting is irrelevant in this context // The lack of position tells us that highlighting is irrelevant in this context
if (this.glFeatures.multilineComments && draft.position) { if (draft.position) {
this.setSelectedCommentPositionHover(); this.setSelectedCommentPositionHover();
} }
}, },
......
...@@ -3,7 +3,6 @@ import { mapGetters } from 'vuex'; ...@@ -3,7 +3,6 @@ import { mapGetters } from 'vuex';
import { GlSprintf, GlIcon } from '@gitlab/ui'; import { GlSprintf, GlIcon } from '@gitlab/ui';
import { IMAGE_DIFF_POSITION_TYPE } from '~/diffs/constants'; import { IMAGE_DIFF_POSITION_TYPE } from '~/diffs/constants';
import { sprintf, __ } from '~/locale'; import { sprintf, __ } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { import {
getStartLineNumber, getStartLineNumber,
getEndLineNumber, getEndLineNumber,
...@@ -16,7 +15,7 @@ export default { ...@@ -16,7 +15,7 @@ export default {
GlIcon, GlIcon,
GlSprintf, GlSprintf,
}, },
mixins: [resolvedStatusMixin, glFeatureFlagsMixin()], mixins: [resolvedStatusMixin],
props: { props: {
draft: { draft: {
type: Object, type: Object,
...@@ -71,6 +70,10 @@ export default { ...@@ -71,6 +70,10 @@ export default {
return this.draft.position || this.discussion.position; return this.draft.position || this.discussion.position;
}, },
startLineNumber() { startLineNumber() {
if (this.position?.position_type === IMAGE_DIFF_POSITION_TYPE) {
// eslint-disable-next-line @gitlab/require-i18n-strings
return `${this.position.x}x ${this.position.y}y`;
}
return getStartLineNumber(this.position?.line_range); return getStartLineNumber(this.position?.line_range);
}, },
endLineNumber() { endLineNumber() {
...@@ -90,16 +93,12 @@ export default { ...@@ -90,16 +93,12 @@ export default {
<span> <span>
<span class="review-preview-item-header"> <span class="review-preview-item-header">
<gl-icon class="flex-shrink-0" :name="iconName" /> <gl-icon class="flex-shrink-0" :name="iconName" />
<span <span class="bold text-nowrap gl-align-items-center">
class="bold text-nowrap"
:class="{ 'gl-align-items-center': glFeatures.multilineComments }"
>
<span class="review-preview-item-header-text block-truncated"> <span class="review-preview-item-header-text block-truncated">
{{ titleText }} {{ titleText }}
</span> </span>
<template v-if="showLinePosition"> <template v-if="showLinePosition">
<template v-if="!glFeatures.multilineComments">:{{ linePosition }}</template> <template v-if="startLineNumber === endLineNumber">
<template v-else-if="startLineNumber === endLineNumber">
:<span :class="getLineClasses(startLineNumber)">{{ startLineNumber }}</span> :<span :class="getLineClasses(startLineNumber)">{{ startLineNumber }}</span>
</template> </template>
<gl-sprintf v-else :message="__(':%{startLine} to %{endLine}')"> <gl-sprintf v-else :message="__(':%{startLine} to %{endLine}')">
......
...@@ -165,7 +165,7 @@ export default { ...@@ -165,7 +165,7 @@ export default {
<template> <template>
<div class="content discussion-form discussion-form-container discussion-notes"> <div class="content discussion-form discussion-form-container discussion-notes">
<div v-if="glFeatures.multilineComments" class="gl-mb-3 gl-text-gray-500 gl-pb-3"> <div class="gl-mb-3 gl-text-gray-500 gl-pb-3">
<multiline-comment-form <multiline-comment-form
v-model="commentLineStart" v-model="commentLineStart"
:line="line" :line="line"
......
...@@ -4,7 +4,6 @@ import { __ } from '~/locale'; ...@@ -4,7 +4,6 @@ import { __ } from '~/locale';
import PlaceholderNote from '~/vue_shared/components/notes/placeholder_note.vue'; import PlaceholderNote from '~/vue_shared/components/notes/placeholder_note.vue';
import PlaceholderSystemNote from '~/vue_shared/components/notes/placeholder_system_note.vue'; import PlaceholderSystemNote from '~/vue_shared/components/notes/placeholder_system_note.vue';
import SystemNote from '~/vue_shared/components/notes/system_note.vue'; import SystemNote from '~/vue_shared/components/notes/system_note.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { SYSTEM_NOTE } from '../constants'; import { SYSTEM_NOTE } from '../constants';
import NoteableNote from './noteable_note.vue'; import NoteableNote from './noteable_note.vue';
import ToggleRepliesWidget from './toggle_replies_widget.vue'; import ToggleRepliesWidget from './toggle_replies_widget.vue';
...@@ -18,7 +17,6 @@ export default { ...@@ -18,7 +17,6 @@ export default {
NoteEditedText, NoteEditedText,
DiscussionNotesRepliesWrapper, DiscussionNotesRepliesWrapper,
}, },
mixins: [glFeatureFlagsMixin()],
props: { props: {
discussion: { discussion: {
type: Object, type: Object,
...@@ -96,14 +94,14 @@ export default { ...@@ -96,14 +94,14 @@ export default {
return note.isPlaceholderNote ? note.notes[0] : note; return note.isPlaceholderNote ? note.notes[0] : note;
}, },
handleMouseEnter(discussion) { handleMouseEnter(discussion) {
if (this.glFeatures.multilineComments && discussion.position) { if (discussion.position) {
this.setSelectedCommentPositionHover(discussion.position.line_range); this.setSelectedCommentPositionHover(discussion.position.line_range);
} }
}, },
handleMouseLeave(discussion) { handleMouseLeave(discussion) {
// Even though position isn't used here we still don't want to unecessarily call a mutation // Even though position isn't used here we still don't want to unnecessarily call a mutation
// The lack of position tells us that highlighting is irrelevant in this context // The lack of position tells us that highlighting is irrelevant in this context
if (this.glFeatures.multilineComments && discussion.position) { if (discussion.position) {
this.setSelectedCommentPositionHover(); this.setSelectedCommentPositionHover();
} }
}, },
......
...@@ -3,7 +3,6 @@ import $ from 'jquery'; ...@@ -3,7 +3,6 @@ import $ from 'jquery';
import { mapGetters, mapActions } from 'vuex'; import { mapGetters, mapActions } from 'vuex';
import { escape } from 'lodash'; import { escape } from 'lodash';
import { GlSprintf, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui'; import { GlSprintf, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { truncateSha } from '~/lib/utils/text_utility'; import { truncateSha } from '~/lib/utils/text_utility';
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue'; import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
import httpStatusCodes from '~/lib/utils/http_status'; import httpStatusCodes from '~/lib/utils/http_status';
...@@ -38,7 +37,7 @@ export default { ...@@ -38,7 +37,7 @@ export default {
directives: { directives: {
SafeHtml, SafeHtml,
}, },
mixins: [noteable, resolvable, glFeatureFlagsMixin()], mixins: [noteable, resolvable],
props: { props: {
note: { note: {
type: Object, type: Object,
...@@ -160,7 +159,6 @@ export default { ...@@ -160,7 +159,6 @@ export default {
}, },
showMultiLineComment() { showMultiLineComment() {
if ( if (
!this.glFeatures.multilineComments ||
!this.discussionRoot || !this.discussionRoot ||
this.startLineNumber.length === 0 || this.startLineNumber.length === 0 ||
this.endLineNumber.length === 0 this.endLineNumber.length === 0
......
...@@ -30,7 +30,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo ...@@ -30,7 +30,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
before_action :authenticate_user!, only: [:assign_related_issues] before_action :authenticate_user!, only: [:assign_related_issues]
before_action :check_user_can_push_to_source_branch!, only: [:rebase] before_action :check_user_can_push_to_source_branch!, only: [:rebase]
before_action only: [:show] do before_action only: [:show] do
push_frontend_feature_flag(:multiline_comments, @project, default_enabled: true)
push_frontend_feature_flag(:file_identifier_hash) push_frontend_feature_flag(:file_identifier_hash)
push_frontend_feature_flag(:batch_suggestions, @project, default_enabled: true) push_frontend_feature_flag(:batch_suggestions, @project, default_enabled: true)
push_frontend_feature_flag(:approvals_commented_by, @project, default_enabled: true) push_frontend_feature_flag(:approvals_commented_by, @project, default_enabled: true)
......
---
name: multiline_comments
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37114
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/211255
milestone: '13.2'
type: development
group: group::code review
default_enabled: true
...@@ -195,12 +195,7 @@ to expand the diff lines and leave a comment, just as you would for a changed li ...@@ -195,12 +195,7 @@ to expand the diff lines and leave a comment, just as you would for a changed li
### Commenting on multiple lines ### Commenting on multiple lines
> - [Introduced](https://gitlab.com/gitlab-org/ux-research/-/issues/870) in GitLab 13.2. > - [Introduced](https://gitlab.com/gitlab-org/ux-research/-/issues/870) in GitLab 13.2.
> - It's deployed behind a feature flag, enabled by default. > - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/299121) in GitLab 13.9.
> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/221268) on GitLab 13.3.
> - It's enabled on GitLab.com.
> - It can be disabled or enabled per-project.
> - It's recommended for production use.
> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-multiline-comments). **(FREE SELF)**
GitLab provides a way to select which lines of code a comment refers to. After starting a comment GitLab provides a way to select which lines of code a comment refers to. After starting a comment
a dropdown selector is shown to select the first line that this comment refers to. a dropdown selector is shown to select the first line that this comment refers to.
...@@ -216,25 +211,6 @@ above it. ...@@ -216,25 +211,6 @@ above it.
![Multiline comment selection displayed above comment](img/multiline-comment-saved.png) ![Multiline comment selection displayed above comment](img/multiline-comment-saved.png)
### Enable or disable multiline comments **(FREE SELF)**
The multiline comments feature is under development but ready for production use.
It is deployed behind a feature flag that is **disabled by default**.
[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
can opt to enable it for your instance.
To disable it:
```ruby
Feature.disable(:multiline_comments)
```
To enable it:
```ruby
Feature.enable(:multiline_comments)
```
## Pipeline status in merge requests widgets ## Pipeline status in merge requests widgets
If you've set up [GitLab CI/CD](../../../ci/README.md) in your project, If you've set up [GitLab CI/CD](../../../ci/README.md) in your project,
......
...@@ -38,6 +38,7 @@ describe('EE DiffLineNoteForm', () => { ...@@ -38,6 +38,7 @@ describe('EE DiffLineNoteForm', () => {
diff_refs: { diff_refs: {
head_sha: headSha || null, head_sha: headSha || null,
}, },
highlighted_diff_lines: [],
})), })),
}, },
}, },
......
...@@ -21,14 +21,11 @@ describe('Batch comments draft note component', () => { ...@@ -21,14 +21,11 @@ describe('Batch comments draft note component', () => {
const getList = () => getByRole(wrapper.element, 'list'); const getList = () => getByRole(wrapper.element, 'list');
const createComponent = (propsData = { draft }, features = {}) => { const createComponent = (propsData = { draft }) => {
wrapper = shallowMount(localVue.extend(DraftNote), { wrapper = shallowMount(localVue.extend(DraftNote), {
store, store,
propsData, propsData,
localVue, localVue,
provide: {
glFeatures: { multilineComments: true, ...features },
},
}); });
jest.spyOn(wrapper.vm.$store, 'dispatch').mockImplementation(); jest.spyOn(wrapper.vm.$store, 'dispatch').mockImplementation();
...@@ -145,16 +142,14 @@ describe('Batch comments draft note component', () => { ...@@ -145,16 +142,14 @@ describe('Batch comments draft note component', () => {
describe('multiline comments', () => { describe('multiline comments', () => {
describe.each` describe.each`
desc | props | features | event | expectedCalls desc | props | event | expectedCalls
${'with `draft.position`'} | ${draftWithLineRange} | ${{}} | ${'mouseenter'} | ${[['setSelectedCommentPositionHover', LINE_RANGE]]} ${'with `draft.position`'} | ${draftWithLineRange} | ${'mouseenter'} | ${[['setSelectedCommentPositionHover', LINE_RANGE]]}
${'with `draft.position`'} | ${draftWithLineRange} | ${{}} | ${'mouseleave'} | ${[['setSelectedCommentPositionHover']]} ${'with `draft.position`'} | ${draftWithLineRange} | ${'mouseleave'} | ${[['setSelectedCommentPositionHover']]}
${'with `draft.position`'} | ${draftWithLineRange} | ${{ multilineComments: false }} | ${'mouseenter'} | ${[]} ${'without `draft.position`'} | ${{}} | ${'mouseenter'} | ${[]}
${'with `draft.position`'} | ${draftWithLineRange} | ${{ multilineComments: false }} | ${'mouseleave'} | ${[]} ${'without `draft.position`'} | ${{}} | ${'mouseleave'} | ${[]}
${'without `draft.position`'} | ${{}} | ${{}} | ${'mouseenter'} | ${[]} `('$desc', ({ props, event, expectedCalls }) => {
${'without `draft.position`'} | ${{}} | ${{}} | ${'mouseleave'} | ${[]}
`('$desc and features $features', ({ props, event, features, expectedCalls }) => {
beforeEach(() => { beforeEach(() => {
createComponent({ draft: { ...draft, ...props } }, features); createComponent({ draft: { ...draft, ...props } });
jest.spyOn(store, 'dispatch'); jest.spyOn(store, 'dispatch');
}); });
......
...@@ -56,17 +56,30 @@ describe('Batch comments draft preview item component', () => { ...@@ -56,17 +56,30 @@ describe('Batch comments draft preview item component', () => {
createComponent(false, { createComponent(false, {
file_path: 'index.js', file_path: 'index.js',
file_hash: 'abc', file_hash: 'abc',
position: { new_line: 1 }, position: {
line_range: {
start: {
new_line: 1,
type: 'new',
},
},
},
}); });
expect(vm.$el.querySelector('.bold').textContent).toContain(':1'); expect(vm.$el.querySelector('.bold').textContent).toContain(':+1');
}); });
it('renders old line position', () => { it('renders old line position', () => {
createComponent(false, { createComponent(false, {
file_path: 'index.js', file_path: 'index.js',
file_hash: 'abc', file_hash: 'abc',
position: { old_line: 2 }, position: {
line_range: {
start: {
old_line: 2,
},
},
},
}); });
expect(vm.$el.querySelector('.bold').textContent).toContain(':2'); expect(vm.$el.querySelector('.bold').textContent).toContain(':2');
......
...@@ -17,6 +17,7 @@ describe('DiffLineNoteForm', () => { ...@@ -17,6 +17,7 @@ describe('DiffLineNoteForm', () => {
const store = createStore(); const store = createStore();
store.state.notes.userData.id = 1; store.state.notes.userData.id = 1;
store.state.notes.noteableData = noteableDataMock; store.state.notes.noteableData = noteableDataMock;
store.state.diffs.diffFiles = [diffFile];
store.replaceState({ ...store.state, ...args.state }); store.replaceState({ ...store.state, ...args.state });
......
...@@ -23,7 +23,7 @@ describe('DiscussionNotes', () => { ...@@ -23,7 +23,7 @@ describe('DiscussionNotes', () => {
let wrapper; let wrapper;
const getList = () => getByRole(wrapper.element, 'list'); const getList = () => getByRole(wrapper.element, 'list');
const createComponent = (props, features = {}) => { const createComponent = (props) => {
wrapper = shallowMount(DiscussionNotes, { wrapper = shallowMount(DiscussionNotes, {
store, store,
propsData: { propsData: {
...@@ -38,9 +38,6 @@ describe('DiscussionNotes', () => { ...@@ -38,9 +38,6 @@ describe('DiscussionNotes', () => {
slots: { slots: {
'avatar-badge': '<span class="avatar-badge-slot-content" />', 'avatar-badge': '<span class="avatar-badge-slot-content" />',
}, },
provide: {
glFeatures: { multilineComments: true, ...features },
},
}); });
}; };
...@@ -177,16 +174,14 @@ describe('DiscussionNotes', () => { ...@@ -177,16 +174,14 @@ describe('DiscussionNotes', () => {
}); });
describe.each` describe.each`
desc | props | features | event | expectedCalls desc | props | event | expectedCalls
${'with `discussion.position`'} | ${{ discussion: DISCUSSION_WITH_LINE_RANGE }} | ${{}} | ${'mouseenter'} | ${[['setSelectedCommentPositionHover', LINE_RANGE]]} ${'with `discussion.position`'} | ${{ discussion: DISCUSSION_WITH_LINE_RANGE }} | ${'mouseenter'} | ${[['setSelectedCommentPositionHover', LINE_RANGE]]}
${'with `discussion.position`'} | ${{ discussion: DISCUSSION_WITH_LINE_RANGE }} | ${{}} | ${'mouseleave'} | ${[['setSelectedCommentPositionHover']]} ${'with `discussion.position`'} | ${{ discussion: DISCUSSION_WITH_LINE_RANGE }} | ${'mouseleave'} | ${[['setSelectedCommentPositionHover']]}
${'with `discussion.position`'} | ${{ discussion: DISCUSSION_WITH_LINE_RANGE }} | ${{ multilineComments: false }} | ${'mouseenter'} | ${[]} ${'without `discussion.position`'} | ${{}} | ${'mouseenter'} | ${[]}
${'with `discussion.position`'} | ${{ discussion: DISCUSSION_WITH_LINE_RANGE }} | ${{ multilineComments: false }} | ${'mouseleave'} | ${[]} ${'without `discussion.position`'} | ${{}} | ${'mouseleave'} | ${[]}
${'without `discussion.position`'} | ${{}} | ${{}} | ${'mouseenter'} | ${[]} `('$desc', ({ props, event, expectedCalls }) => {
${'without `discussion.position`'} | ${{}} | ${{}} | ${'mouseleave'} | ${[]}
`('$desc and features $features', ({ props, event, features, expectedCalls }) => {
beforeEach(() => { beforeEach(() => {
createComponent(props, features); createComponent(props);
jest.spyOn(store, 'dispatch'); jest.spyOn(store, 'dispatch');
}); });
......
...@@ -8,15 +8,6 @@ import NoteActions from '~/notes/components/note_actions.vue'; ...@@ -8,15 +8,6 @@ import NoteActions from '~/notes/components/note_actions.vue';
import NoteBody from '~/notes/components/note_body.vue'; import NoteBody from '~/notes/components/note_body.vue';
import { noteableDataMock, notesDataMock, note } from '../mock_data'; import { noteableDataMock, notesDataMock, note } from '../mock_data';
jest.mock('~/vue_shared/mixins/gl_feature_flags_mixin', () => () => ({
inject: {
glFeatures: {
from: 'glFeatures',
default: () => ({ multilineComments: true }),
},
},
}));
describe('issue_note', () => { describe('issue_note', () => {
let store; let store;
let wrapper; let wrapper;
......
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