Commit 4f01a32f authored by Kushal Pandya's avatar Kushal Pandya

Merge branch '223076-disable-commenting-on-symlinks-in-an-mr' into 'master'

Disable commenting on symlinks in symlink-related files

See merge request gitlab-org/gitlab!35371
parents eb96a9cc 5749cc9c
...@@ -147,7 +147,7 @@ export default { ...@@ -147,7 +147,7 @@ export default {
slot="image-overlay" slot="image-overlay"
:discussions="imageDiscussions" :discussions="imageDiscussions"
:file-hash="diffFileHash" :file-hash="diffFileHash"
:can-comment="getNoteableData.current_user.can_create_note" :can-comment="getNoteableData.current_user.can_create_note && !diffFile.brokenSymlink"
/> />
<div v-if="showNotesContainer" class="note-container"> <div v-if="showNotesContainer" class="note-container">
<user-avatar-link <user-avatar-link
......
...@@ -167,6 +167,7 @@ export default { ...@@ -167,6 +167,7 @@ export default {
:id="file.file_hash" :id="file.file_hash"
:class="{ :class="{
'is-active': currentDiffFileId === file.file_hash, 'is-active': currentDiffFileId === file.file_hash,
'comments-disabled': Boolean(file.brokenSymlink),
}" }"
:data-path="file.new_path" :data-path="file.new_path"
class="diff-file file-holder" class="diff-file file-holder"
......
<script> <script>
import { mapGetters, mapActions } from 'vuex'; import { mapGetters, mapActions } from 'vuex';
import { GlIcon } from '@gitlab/ui'; import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
import { getParameterByName, parseBoolean } from '~/lib/utils/common_utils'; import { getParameterByName, parseBoolean } from '~/lib/utils/common_utils';
import DiffGutterAvatars from './diff_gutter_avatars.vue'; import DiffGutterAvatars from './diff_gutter_avatars.vue';
import { __ } from '~/locale';
import { import {
CONTEXT_LINE_TYPE, CONTEXT_LINE_TYPE,
LINE_POSITION_RIGHT, LINE_POSITION_RIGHT,
...@@ -18,6 +19,9 @@ export default { ...@@ -18,6 +19,9 @@ export default {
DiffGutterAvatars, DiffGutterAvatars,
GlIcon, GlIcon,
}, },
directives: {
GlTooltip: GlTooltipDirective,
},
props: { props: {
line: { line: {
type: Object, type: Object,
...@@ -123,6 +127,24 @@ export default { ...@@ -123,6 +127,24 @@ export default {
lineNumber() { lineNumber() {
return this.lineType === OLD_LINE_TYPE ? this.line.old_line : this.line.new_line; return this.lineType === OLD_LINE_TYPE ? this.line.old_line : this.line.new_line;
}, },
addCommentTooltip() {
const brokenSymlinks = this.line.commentsDisabled;
let tooltip = __('Add a comment to this line');
if (brokenSymlinks) {
if (brokenSymlinks.wasSymbolic || brokenSymlinks.isSymbolic) {
tooltip = __(
'Commenting on symbolic links that replace or are replaced by files is currently not supported.',
);
} else if (brokenSymlinks.wasReal || brokenSymlinks.isReal) {
tooltip = __(
'Commenting on files that replace or are replaced by symbolic links is currently not supported.',
);
}
}
return tooltip;
},
}, },
mounted() { mounted() {
this.unwatchShouldShowCommentButton = this.$watch('shouldShowCommentButton', newVal => { this.unwatchShouldShowCommentButton = this.$watch('shouldShowCommentButton', newVal => {
...@@ -146,17 +168,24 @@ export default { ...@@ -146,17 +168,24 @@ export default {
<template> <template>
<td ref="td" :class="classNameMap"> <td ref="td" :class="classNameMap">
<button <span
v-if="shouldRenderCommentButton" ref="addNoteTooltip"
v-show="shouldShowCommentButton" v-gl-tooltip
ref="addDiffNoteButton" class="add-diff-note tooltip-wrapper"
type="button" :title="addCommentTooltip"
class="add-diff-note js-add-diff-note-button qa-diff-comment"
title="Add a comment to this line"
@click="handleCommentButton"
> >
<gl-icon :size="12" name="comment" /> <button
</button> v-if="shouldRenderCommentButton"
v-show="shouldShowCommentButton"
ref="addDiffNoteButton"
type="button"
class="add-diff-note note-button js-add-diff-note-button qa-diff-comment"
:disabled="line.commentsDisabled"
@click="handleCommentButton"
>
<gl-icon :size="12" name="comment" />
</button>
</span>
<a <a
v-if="lineNumber" v-if="lineNumber"
ref="lineNumberRef" ref="lineNumberRef"
......
...@@ -480,6 +480,10 @@ export function getDiffPositionByLineCode(diffFiles, useSingleDiffStyle) { ...@@ -480,6 +480,10 @@ export function getDiffPositionByLineCode(diffFiles, useSingleDiffStyle) {
// This method will check whether the discussion is still applicable // This method will check whether the discussion is still applicable
// to the diff line in question regarding different versions of the MR // to the diff line in question regarding different versions of the MR
export function isDiscussionApplicableToLine({ discussion, diffPosition, latestDiff }) { export function isDiscussionApplicableToLine({ discussion, diffPosition, latestDiff }) {
if (!diffPosition) {
return false;
}
const { line_code, ...dp } = diffPosition; const { line_code, ...dp } = diffPosition;
// Removing `line_range` from diffPosition because the backend does not // Removing `line_range` from diffPosition because the backend does not
// yet consistently return this property. This check can be removed, // yet consistently return this property. This check can be removed,
......
...@@ -820,9 +820,7 @@ $note-form-margin-left: 72px; ...@@ -820,9 +820,7 @@ $note-form-margin-left: 72px;
} }
} }
.add-diff-note { .tooltip-wrapper.add-diff-note {
@include btn-comment-icon;
opacity: 0;
margin-left: -52px; margin-left: -52px;
position: absolute; position: absolute;
top: 50%; top: 50%;
...@@ -830,6 +828,18 @@ $note-form-margin-left: 72px; ...@@ -830,6 +828,18 @@ $note-form-margin-left: 72px;
z-index: 10; z-index: 10;
} }
.note-button.add-diff-note {
@include btn-comment-icon;
opacity: 0;
&[disabled] {
background: $white;
border-color: $gray-200;
color: $gl-gray-400;
cursor: not-allowed;
}
}
.disabled-comment { .disabled-comment {
background-color: $gray-light; background-color: $gray-light;
border-radius: $border-radius-base; border-radius: $border-radius-base;
......
---
title: Disable commenting on lines in files that were or are symlinks or replace or
are replaced by symlinks
merge_request: 35371
author:
type: fixed
...@@ -6161,6 +6161,12 @@ msgstr "" ...@@ -6161,6 +6161,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)" msgid "Comment/Reply (quoting selected text)"
msgstr "" msgstr ""
msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
msgstr ""
msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
msgstr ""
msgid "Comments" msgid "Comments"
msgstr "" msgstr ""
......
...@@ -18,6 +18,12 @@ const TEST_LINE_CODE = 'LC_42'; ...@@ -18,6 +18,12 @@ const TEST_LINE_CODE = 'LC_42';
const TEST_FILE_HASH = diffFileMockData.file_hash; const TEST_FILE_HASH = diffFileMockData.file_hash;
describe('DiffTableCell', () => { describe('DiffTableCell', () => {
const symlinkishFileTooltip =
'Commenting on symbolic links that replace or are replaced by files is currently not supported.';
const realishFileTooltip =
'Commenting on files that replace or are replaced by symbolic links is currently not supported.';
const otherFileTooltip = 'Add a comment to this line';
let wrapper; let wrapper;
let line; let line;
let store; let store;
...@@ -67,6 +73,7 @@ describe('DiffTableCell', () => { ...@@ -67,6 +73,7 @@ describe('DiffTableCell', () => {
const findTd = () => wrapper.find({ ref: 'td' }); const findTd = () => wrapper.find({ ref: 'td' });
const findNoteButton = () => wrapper.find({ ref: 'addDiffNoteButton' }); const findNoteButton = () => wrapper.find({ ref: 'addDiffNoteButton' });
const findLineNumber = () => wrapper.find({ ref: 'lineNumberRef' }); const findLineNumber = () => wrapper.find({ ref: 'lineNumberRef' });
const findTooltip = () => wrapper.find({ ref: 'addNoteTooltip' });
const findAvatars = () => wrapper.find(DiffGutterAvatars); const findAvatars = () => wrapper.find(DiffGutterAvatars);
describe('td', () => { describe('td', () => {
...@@ -134,6 +141,53 @@ describe('DiffTableCell', () => { ...@@ -134,6 +141,53 @@ describe('DiffTableCell', () => {
}); });
}, },
); );
it.each`
disabled | commentsDisabled
${'disabled'} | ${true}
${undefined} | ${false}
`(
'has attribute disabled=$disabled when the outer component has prop commentsDisabled=$commentsDisabled',
({ disabled, commentsDisabled }) => {
line.commentsDisabled = commentsDisabled;
createComponent({
showCommentButton: true,
isHover: true,
});
wrapper.setData({ isCommentButtonRendered: true });
return wrapper.vm.$nextTick().then(() => {
expect(findNoteButton().attributes('disabled')).toBe(disabled);
});
},
);
it.each`
tooltip | commentsDisabled
${symlinkishFileTooltip} | ${{ wasSymbolic: true }}
${symlinkishFileTooltip} | ${{ isSymbolic: true }}
${realishFileTooltip} | ${{ wasReal: true }}
${realishFileTooltip} | ${{ isReal: true }}
${otherFileTooltip} | ${false}
`(
'has the correct tooltip when commentsDisabled=$commentsDisabled',
({ tooltip, commentsDisabled }) => {
line.commentsDisabled = commentsDisabled;
createComponent({
showCommentButton: true,
isHover: true,
});
wrapper.setData({ isCommentButtonRendered: true });
return wrapper.vm.$nextTick().then(() => {
expect(findTooltip().attributes('title')).toBe(tooltip);
});
},
);
}); });
describe('line number', () => { describe('line number', () => {
......
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