debian-mirror-gitlab/app/assets/javascripts/diffs/components/diff_row.vue

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

425 lines
15 KiB
Vue
Raw Normal View History

2021-01-29 00:20:46 +05:30
<script>
2021-11-18 22:05:49 +05:30
/* eslint-disable vue/no-v-html */
/**
NOTE: This file uses v-html over v-safe-html for performance reasons, see:
https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57842
* */
2021-09-30 23:02:18 +05:30
import { memoize } from 'lodash';
import { isLoggedIn } from '~/lib/utils/common_utils';
2021-03-08 18:12:59 +05:30
import {
PARALLEL_DIFF_VIEW_TYPE,
CONFLICT_MARKER_THEIR,
CONFLICT_OUR,
CONFLICT_THEIR,
CONFLICT_MARKER,
} from '../constants';
2021-04-29 21:17:54 +05:30
import {
getInteropInlineAttributes,
getInteropOldSideAttributes,
getInteropNewSideAttributes,
} from '../utils/interoperability';
2021-01-29 00:20:46 +05:30
import DiffGutterAvatars from './diff_gutter_avatars.vue';
import * as utils from './diff_row_utils';
export default {
2021-09-30 23:02:18 +05:30
DiffGutterAvatars,
CodeQualityGutterIcon: () => import('ee_component/diffs/components/code_quality_gutter_icon.vue'),
2021-01-29 00:20:46 +05:30
props: {
fileHash: {
type: String,
required: true,
},
filePath: {
type: String,
required: true,
},
line: {
type: Object,
required: true,
},
isCommented: {
type: Boolean,
required: false,
default: false,
},
2022-01-26 12:08:38 +05:30
coverageLoaded: {
type: Boolean,
required: false,
default: false,
},
2021-01-29 00:20:46 +05:30
inline: {
type: Boolean,
required: false,
default: false,
},
2021-03-08 18:12:59 +05:30
index: {
type: Number,
required: true,
},
2021-09-30 23:02:18 +05:30
isHighlighted: {
type: Boolean,
required: true,
},
fileLineCoverage: {
type: Function,
required: true,
},
2021-03-08 18:12:59 +05:30
},
2021-09-30 23:02:18 +05:30
classNameMap: memoize(
(props) => {
2021-01-29 00:20:46 +05:30
return {
2021-09-30 23:02:18 +05:30
[PARALLEL_DIFF_VIEW_TYPE]: !props.inline,
commented: props.isCommented,
2021-01-29 00:20:46 +05:30
};
},
2021-09-30 23:02:18 +05:30
(props) => [!props.inline, props.isCommented].join(':'),
),
parallelViewLeftLineType: memoize(
(props) => {
return utils.parallelViewLeftLineType(props.line, props.isHighlighted || props.isCommented);
2021-01-29 00:20:46 +05:30
},
2021-09-30 23:02:18 +05:30
(props) =>
[props.line.left?.type, props.line.right?.type, props.isHighlighted, props.isCommented].join(
':',
),
),
coverageStateLeft: memoize(
(props) => {
if (!props.inline || !props.line.left) return {};
return props.fileLineCoverage(props.filePath, props.line.left.new_line);
2021-03-08 18:12:59 +05:30
},
2022-01-26 12:08:38 +05:30
(props) =>
[props.inline, props.filePath, props.line.left?.new_line, props.coverageLoaded].join(':'),
2021-09-30 23:02:18 +05:30
),
coverageStateRight: memoize(
(props) => {
if (!props.line.right) return {};
return props.fileLineCoverage(props.filePath, props.line.right.new_line);
2021-01-29 00:20:46 +05:30
},
2022-01-26 12:08:38 +05:30
(props) => [props.line.right?.new_line, props.filePath, props.coverageLoaded].join(':'),
2021-09-30 23:02:18 +05:30
),
showCodequalityLeft: memoize(
(props) => {
return props.inline && props.line.left?.codequality?.length > 0;
2021-09-04 01:27:46 +05:30
},
2021-09-30 23:02:18 +05:30
(props) => [props.inline, props.line.left?.codequality?.length].join(':'),
),
showCodequalityRight: memoize(
(props) => {
return !props.inline && props.line.right?.codequality?.length > 0;
2021-09-04 01:27:46 +05:30
},
2021-09-30 23:02:18 +05:30
(props) => [props.inline, props.line.right?.codequality?.length].join(':'),
),
classNameMapCellLeft: memoize(
(props) => {
2021-03-08 18:12:59 +05:30
return utils.classNameMapCell({
2021-09-30 23:02:18 +05:30
line: props.line.left,
hll: props.isHighlighted || props.isCommented,
2021-03-08 18:12:59 +05:30
});
2021-01-29 00:20:46 +05:30
},
2021-09-30 23:02:18 +05:30
(props) => [props.line.left.type, props.isHighlighted, props.isCommented].join(':'),
),
classNameMapCellRight: memoize(
(props) => {
2021-03-08 18:12:59 +05:30
return utils.classNameMapCell({
2021-09-30 23:02:18 +05:30
line: props.line.right,
hll: props.isHighlighted || props.isCommented,
2021-03-08 18:12:59 +05:30
});
2021-01-29 00:20:46 +05:30
},
2021-09-30 23:02:18 +05:30
(props) => [props.line.right.type, props.isHighlighted, props.isCommented].join(':'),
),
shouldRenderCommentButton: memoize(
(props) => {
return isLoggedIn() && !props.line.isContextLineLeft && !props.line.isMetaLineLeft;
2021-01-29 00:20:46 +05:30
},
2021-09-30 23:02:18 +05:30
(props) => [props.line.isContextLineLeft, props.line.isMetaLineLeft].join(':'),
),
interopLeftAttributes(props) {
if (props.inline) {
return getInteropInlineAttributes(props.line.left);
}
2021-04-29 21:17:54 +05:30
2021-09-30 23:02:18 +05:30
return getInteropOldSideAttributes(props.line.left);
2021-01-29 00:20:46 +05:30
},
2021-09-30 23:02:18 +05:30
interopRightAttributes(props) {
return getInteropNewSideAttributes(props.line.right);
2021-01-29 00:20:46 +05:30
},
2021-10-27 15:23:28 +05:30
lineContent: (line) => {
if (line.isConflictMarker) {
2021-09-30 23:02:18 +05:30
return line.type === CONFLICT_MARKER_THEIR ? 'HEAD//our changes' : 'origin//their changes';
2021-10-27 15:23:28 +05:30
}
2021-03-08 18:12:59 +05:30
2021-10-27 15:23:28 +05:30
return line.rich_text;
},
2021-03-08 18:12:59 +05:30
CONFLICT_MARKER,
CONFLICT_MARKER_THEIR,
CONFLICT_OUR,
CONFLICT_THEIR,
2021-01-29 00:20:46 +05:30
};
</script>
2021-09-30 23:02:18 +05:30
<!-- eslint-disable-next-line vue/no-deprecated-functional-template -->
<template functional>
2022-07-16 23:28:13 +05:30
<div
:class="[
$options.classNameMap(props),
{ expansion: props.line.left && props.line.left.type === 'expanded' },
]"
class="diff-grid-row diff-tr line_holder"
>
2021-03-08 18:12:59 +05:30
<div
2021-09-30 23:02:18 +05:30
:id="props.line.left && props.line.left.line_code"
2021-03-08 18:12:59 +05:30
data-testid="left-side"
class="diff-grid-left left-side"
2021-09-30 23:02:18 +05:30
v-bind="$options.interopLeftAttributes(props)"
2021-03-08 18:12:59 +05:30
@dragover.prevent
2021-09-30 23:02:18 +05:30
@dragenter="listeners.enterdragging({ ...props.line.left, index: props.index })"
@dragend="listeners.stopdragging"
2021-03-08 18:12:59 +05:30
>
2021-09-30 23:02:18 +05:30
<template v-if="props.line.left && props.line.left.type !== $options.CONFLICT_MARKER">
2021-01-29 00:20:46 +05:30
<div
2021-09-30 23:02:18 +05:30
:class="$options.classNameMapCellLeft(props)"
2021-06-08 01:23:25 +05:30
data-testid="left-line-number"
2021-03-08 18:12:59 +05:30
class="diff-td diff-line-num"
2021-06-08 01:23:25 +05:30
data-qa-selector="new_diff_line_link"
2021-01-29 00:20:46 +05:30
>
2021-09-30 23:02:18 +05:30
<span
v-if="
!props.line.left.isConflictMarker &&
$options.shouldRenderCommentButton(props) &&
!props.line.hasDiscussionsLeft
"
class="add-diff-note tooltip-wrapper has-tooltip"
:title="props.line.left.addCommentTooltip"
>
<div
data-testid="left-comment-button"
role="button"
tabindex="0"
:draggable="!props.line.left.commentsDisabled"
type="button"
class="add-diff-note unified-diff-components-diff-note-button note-button js-add-diff-note-button"
data-qa-selector="diff_comment_button"
:disabled="props.line.left.commentsDisabled"
:aria-disabled="props.line.left.commentsDisabled"
@click="
!props.line.left.commentsDisabled &&
listeners.showCommentForm(props.line.left.line_code)
"
@keydown.enter="
!props.line.left.commentsDisabled &&
listeners.showCommentForm(props.line.left.line_code)
"
@keydown.space="
!props.line.left.commentsDisabled &&
listeners.showCommentForm(props.line.left.line_code)
"
@dragstart="
!props.line.left.commentsDisabled &&
listeners.startdragging({
event: $event,
line: { ...props.line.left, index: props.index },
})
"
></div>
</span>
2021-01-29 00:20:46 +05:30
<a
2021-09-30 23:02:18 +05:30
v-if="props.line.left.old_line && props.line.left.type !== $options.CONFLICT_THEIR"
:data-linenumber="props.line.left.old_line"
:href="props.line.lineHrefOld"
@click="listeners.setHighlightedRow(props.line.lineCode)"
2021-01-29 00:20:46 +05:30
>
</a>
2021-09-30 23:02:18 +05:30
<component
:is="$options.DiffGutterAvatars"
v-if="props.line.hasDiscussionsLeft"
:discussions="props.line.left.discussions"
:discussions-expanded="props.line.left.discussionsExpanded"
2021-06-08 01:23:25 +05:30
data-testid="left-discussions"
2021-01-29 00:20:46 +05:30
@toggleLineDiscussions="
2021-09-30 23:02:18 +05:30
listeners.toggleLineDiscussions({
lineCode: props.line.left.line_code,
expanded: !props.line.left.discussionsExpanded,
2021-01-29 00:20:46 +05:30
})
"
/>
</div>
2021-09-30 23:02:18 +05:30
<div
v-if="props.inline"
:class="$options.classNameMapCellLeft(props)"
class="diff-td diff-line-num"
>
2021-01-29 00:20:46 +05:30
<a
2021-09-30 23:02:18 +05:30
v-if="props.line.left.new_line && props.line.left.type !== $options.CONFLICT_OUR"
:data-linenumber="props.line.left.new_line"
:href="props.line.lineHrefOld"
@click="listeners.setHighlightedRow(props.line.lineCode)"
2021-01-29 00:20:46 +05:30
>
</a>
</div>
2021-03-08 18:12:59 +05:30
<div
2021-09-30 23:02:18 +05:30
:title="$options.coverageStateLeft(props).text"
:class="[
$options.parallelViewLeftLineType(props),
$options.coverageStateLeft(props).class,
]"
class="diff-td line-coverage left-side has-tooltip"
2021-03-08 18:12:59 +05:30
></div>
2021-09-30 23:02:18 +05:30
<div
class="diff-td line-codequality left-side"
:class="$options.parallelViewLeftLineType(props)"
>
<component
:is="$options.CodeQualityGutterIcon"
v-if="$options.showCodequalityLeft(props)"
:codequality="props.line.left.codequality"
:file-path="props.filePath"
2021-09-04 01:27:46 +05:30
/>
</div>
2021-01-29 00:20:46 +05:30
<div
2021-09-30 23:02:18 +05:30
:key="props.line.left.line_code"
:class="[
$options.parallelViewLeftLineType(props),
{ parallel: !props.inline, 'gl-font-weight-bold': props.line.left.isConflictMarker },
]"
2021-03-08 18:12:59 +05:30
class="diff-td line_content with-coverage left-side"
2021-06-08 01:23:25 +05:30
data-testid="left-content"
2021-11-18 22:05:49 +05:30
v-html="
$options.lineContent(props.line.left) /* v-html for performance, see top of file */
"
2021-09-30 23:02:18 +05:30
></div>
2021-01-29 00:20:46 +05:30
</template>
2021-09-30 23:02:18 +05:30
<template
v-else-if="
!props.inline || (props.line.left && props.line.left.type === $options.CONFLICT_MARKER)
"
>
<div data-testid="left-empty-cell" class="diff-td diff-line-num old_line empty-cell">
2021-03-08 18:12:59 +05:30
&nbsp;
</div>
2021-09-30 23:02:18 +05:30
<div v-if="props.inline" class="diff-td diff-line-num old_line empty-cell"></div>
<div class="diff-td line-coverage left-side empty-cell"></div>
<div v-if="props.inline" class="diff-td line-codequality left-side empty-cell"></div>
2021-03-08 18:12:59 +05:30
<div
class="diff-td line_content with-coverage left-side empty-cell"
2021-09-30 23:02:18 +05:30
:class="[{ parallel: !props.inline }]"
2021-03-08 18:12:59 +05:30
></div>
2021-01-29 00:20:46 +05:30
</template>
</div>
2021-03-08 18:12:59 +05:30
<div
2021-09-30 23:02:18 +05:30
v-if="!props.inline"
:id="props.line.right && props.line.right.line_code"
2021-03-08 18:12:59 +05:30
data-testid="right-side"
class="diff-grid-right right-side"
2021-09-30 23:02:18 +05:30
v-bind="$options.interopRightAttributes(props)"
2021-03-08 18:12:59 +05:30
@dragover.prevent
2021-09-30 23:02:18 +05:30
@dragenter="listeners.enterdragging({ ...props.line.right, index: props.index })"
@dragend="listeners.stopdragging"
2021-03-08 18:12:59 +05:30
>
2021-09-30 23:02:18 +05:30
<template v-if="props.line.right">
<div :class="$options.classNameMapCellRight(props)" class="diff-td diff-line-num new_line">
<template v-if="props.line.right.type !== $options.CONFLICT_MARKER_THEIR">
2021-03-08 18:12:59 +05:30
<span
2021-09-30 23:02:18 +05:30
v-if="$options.shouldRenderCommentButton(props) && !props.line.hasDiscussionsRight"
class="add-diff-note tooltip-wrapper has-tooltip"
:title="props.line.right.addCommentTooltip"
2021-01-29 00:20:46 +05:30
>
2021-06-08 01:23:25 +05:30
<div
data-testid="right-comment-button"
role="button"
tabindex="0"
2021-09-30 23:02:18 +05:30
:draggable="!props.line.right.commentsDisabled"
2021-03-08 18:12:59 +05:30
type="button"
2021-06-08 01:23:25 +05:30
class="add-diff-note unified-diff-components-diff-note-button note-button js-add-diff-note-button"
2021-09-30 23:02:18 +05:30
:disabled="props.line.right.commentsDisabled"
:aria-disabled="props.line.right.commentsDisabled"
@click="
!props.line.right.commentsDisabled &&
listeners.showCommentForm(props.line.right.line_code)
"
@keydown.enter="
!props.line.right.commentsDisabled &&
listeners.showCommentForm(props.line.right.line_code)
"
@keydown.space="
!props.line.right.commentsDisabled &&
listeners.showCommentForm(props.line.right.line_code)
"
@dragstart="
!props.line.right.commentsDisabled &&
listeners.startdragging({
event: $event,
line: { ...props.line.right, index: props.index },
})
"
2021-06-08 01:23:25 +05:30
></div>
2021-03-08 18:12:59 +05:30
</span>
</template>
2021-01-29 00:20:46 +05:30
<a
2021-09-30 23:02:18 +05:30
v-if="props.line.right.new_line"
:data-linenumber="props.line.right.new_line"
:href="props.line.lineHrefNew"
@click="listeners.setHighlightedRow(props.line.lineCode)"
2021-01-29 00:20:46 +05:30
>
</a>
2021-09-30 23:02:18 +05:30
<component
:is="$options.DiffGutterAvatars"
v-if="props.line.hasDiscussionsRight"
:discussions="props.line.right.discussions"
:discussions-expanded="props.line.right.discussionsExpanded"
2021-06-08 01:23:25 +05:30
data-testid="right-discussions"
2021-01-29 00:20:46 +05:30
@toggleLineDiscussions="
2021-09-30 23:02:18 +05:30
listeners.toggleLineDiscussions({
lineCode: props.line.right.line_code,
expanded: !props.line.right.discussionsExpanded,
2021-01-29 00:20:46 +05:30
})
"
/>
</div>
<div
2021-09-30 23:02:18 +05:30
:title="$options.coverageStateRight(props).text"
2021-03-08 18:12:59 +05:30
:class="[
2021-09-30 23:02:18 +05:30
props.line.right.type,
$options.coverageStateRight(props).class,
{ hll: props.isHighlighted, hll: props.isCommented },
2021-03-08 18:12:59 +05:30
]"
2021-09-30 23:02:18 +05:30
class="diff-td line-coverage right-side has-tooltip"
2021-01-29 00:20:46 +05:30
></div>
2021-09-04 01:27:46 +05:30
<div
class="diff-td line-codequality right-side"
2021-09-30 23:02:18 +05:30
:class="[props.line.right.type, { hll: props.isHighlighted, hll: props.isCommented }]"
2021-09-04 01:27:46 +05:30
>
2021-09-30 23:02:18 +05:30
<component
:is="$options.CodeQualityGutterIcon"
v-if="$options.showCodequalityRight(props)"
:codequality="props.line.right.codequality"
:file-path="props.filePath"
data-testid="codeQualityIcon"
2021-09-04 01:27:46 +05:30
/>
</div>
2021-01-29 00:20:46 +05:30
<div
2021-09-30 23:02:18 +05:30
:key="props.line.right.rich_text"
2021-01-29 00:20:46 +05:30
:class="[
2021-09-30 23:02:18 +05:30
props.line.right.type,
2021-01-29 00:20:46 +05:30
{
2021-09-30 23:02:18 +05:30
hll: props.isHighlighted,
hll: props.isCommented,
'gl-font-weight-bold': props.line.right.type === $options.CONFLICT_MARKER_THEIR,
2021-01-29 00:20:46 +05:30
},
]"
2021-09-30 23:02:18 +05:30
class="diff-td line_content with-coverage right-side parallel"
2021-11-18 22:05:49 +05:30
v-html="
$options.lineContent(props.line.right) /* v-html for performance, see top of file */
"
2021-09-30 23:02:18 +05:30
></div>
2021-01-29 00:20:46 +05:30
</template>
<template v-else>
2021-09-30 23:02:18 +05:30
<div data-testid="right-empty-cell" class="diff-td diff-line-num old_line empty-cell"></div>
<div class="diff-td line-coverage right-side empty-cell"></div>
<div class="diff-td line-codequality right-side empty-cell"></div>
<div class="diff-td line_content with-coverage right-side empty-cell parallel"></div>
2021-01-29 00:20:46 +05:30
</template>
</div>
</div>
</template>