gitlab-org--gitlab-foss/app/assets/javascripts/diffs/components/parallel_diff_view.vue

225 lines
7.6 KiB
Vue

<script>
import diffContentMixin from '../mixins/diff_content';
import {
EMPTY_CELL_TYPE,
MATCH_LINE_TYPE,
CONTEXT_LINE_TYPE,
OLD_NO_NEW_LINE_TYPE,
NEW_NO_NEW_LINE_TYPE,
LINE_HOVER_CLASS_NAME,
LINE_UNFOLD_CLASS_NAME,
LINE_POSITION_RIGHT,
} from '../constants';
export default {
mixins: [diffContentMixin],
computed: {
parallelDiffLines() {
return this.normalizedDiffLines.map(line => {
if (!line.left) {
Object.assign(line, { left: { type: EMPTY_CELL_TYPE } });
} else if (!line.right) {
Object.assign(line, { right: { type: EMPTY_CELL_TYPE } });
}
return line;
});
},
},
methods: {
hasDiscussion(line) {
const discussions = this.discussionsByLineCode;
const hasDiscussion = discussions[line.left.lineCode] || discussions[line.right.lineCode];
return hasDiscussion;
},
getClassName(line, position) {
const { type, lineCode } = line[position];
const isMatchLine = type === MATCH_LINE_TYPE;
const isContextLine = !isMatchLine && type !== EMPTY_CELL_TYPE && type !== CONTEXT_LINE_TYPE;
const isMetaLine = type === OLD_NO_NEW_LINE_TYPE || type === NEW_NO_NEW_LINE_TYPE;
const isSameLine = this.hoveredLineCode && this.hoveredLineCode === lineCode;
const isSameSection = position === this.hoveredSection;
return {
[type]: type,
[LINE_UNFOLD_CLASS_NAME]: isMatchLine,
[LINE_HOVER_CLASS_NAME]:
this.isLoggedIn && isContextLine && isSameLine && isSameSection && !isMetaLine,
};
},
handleMouse(e, line, isHover) {
if (isHover) {
const cell = e.target.closest('td');
if (this.$refs.leftLines.indexOf(cell) > -1) {
this.hoveredLineCode = line.left.lineCode;
this.hoveredSection = 'left';
} else if (this.$refs.rightLines.indexOf(cell) > -1) {
this.hoveredLineCode = line.right.lineCode;
this.hoveredSection = 'right';
}
} else {
this.hoveredLineCode = null;
this.hoveredSection = null;
}
},
shouldRenderDiscussionsRow(line) {
const hasDiscussion = this.hasDiscussion(line) && this.hasAnyExpandedDiscussion(line);
const hasCommentFormOnLeft = this.diffLineCommentForms[line.left.lineCode];
const hasCommentFormOnRight = this.diffLineCommentForms[line.right.lineCode];
return hasDiscussion || hasCommentFormOnLeft || hasCommentFormOnRight;
},
shouldRenderDiscussions(line, position) {
const { lineCode } = line[position];
let render = this.discussionsByLineCode[lineCode] && this.isDiscussionExpanded(lineCode);
// Avoid rendering context line discussions on the right side in parallel view
if (position === LINE_POSITION_RIGHT) {
render = render && line.right.type;
}
return render;
},
hasAnyExpandedDiscussion(line) {
const isLeftExpanded = this.isDiscussionExpanded(line.left.lineCode);
const isRightExpanded = this.isDiscussionExpanded(line.right.lineCode);
return isLeftExpanded || isRightExpanded;
},
getLineCode(line, side) {
const lineCode = side.lineCode;
if (lineCode) {
return lineCode;
}
return `${this.fileHash}_${line.left.oldLine}_${line.right.newLine}`;
},
},
};
</script>
<template>
<div
:class="userColorScheme"
:data-commit-id="commitId"
class="code diff-wrap-lines js-syntax-highlight text-file">
<table>
<tbody>
<template
v-for="(line, index) in parallelDiffLines"
>
<tr
:key="index"
:class="getRowClass(line)"
class="line_holder parallel"
@mouseover="handleMouse($event, line, true)"
@mouseout="handleMouse($event, line, false)"
>
<td
ref="leftLines"
:class="getClassName(line, 'left')"
class="diff-line-num old_line"
>
<diff-line-gutter-content
:file-hash="fileHash"
:line-type="line.left.type"
:line-code="line.left.lineCode"
:line-number="line.left.oldLine"
:meta-data="line.left.metaData"
:show-comment-button="true"
:context-lines-path="diffFile.contextLinesPath"
:is-bottom="index + 1 === diffLinesLength"
line-position="left"
@showCommentForm="handleShowCommentForm"
/>
</td>
<td
ref="leftLines"
:class="getClassName(line, 'left')"
:id="getLineCode(line, line.left)"
class="line_content parallel left-side"
v-html="line.left.richText"
>
</td>
<td
ref="rightLines"
:class="getClassName(line, 'right')"
class="diff-line-num new_line"
>
<diff-line-gutter-content
:file-hash="fileHash"
:line-type="line.right.type"
:line-code="line.right.lineCode"
:line-number="line.right.newLine"
:meta-data="line.right.metaData"
:show-comment-button="true"
:context-lines-path="diffFile.contextLinesPath"
:is-bottom="index + 1 === diffLinesLength"
line-position="right"
@showCommentForm="handleShowCommentForm"
/>
</td>
<td
ref="rightLines"
:class="getClassName(line, 'right')"
:id="getLineCode(line, line.right)"
class="line_content parallel right-side"
v-html="line.right.richText"
>
</td>
</tr>
<tr
v-if="shouldRenderDiscussionsRow(line)"
:key="line.left.lineCode || line.right.lineCode"
:class="hasDiscussion(line) ? '' : 'js-temp-notes-holder'"
class="notes_holder"
>
<td class="notes_line old"></td>
<td class="notes_content parallel old">
<div
v-if="shouldRenderDiscussions(line, 'left')"
class="content"
>
<diff-discussions
:discussions="discussionsByLineCode[line.left.lineCode]"
/>
</div>
<diff-line-note-form
v-if="diffLineCommentForms[line.left.lineCode] &&
diffLineCommentForms[line.left.lineCode]"
:diff-file="diffFile"
:diff-lines="diffLines"
:line="line.left"
:note-target-line="diffLines[index].left"
position="left"
/>
</td>
<td class="notes_line new"></td>
<td class="notes_content parallel new">
<div
v-if="shouldRenderDiscussions(line, 'right')"
class="content"
>
<diff-discussions
:discussions="discussionsByLineCode[line.right.lineCode]"
/>
</div>
<diff-line-note-form
v-if="diffLineCommentForms[line.right.lineCode] &&
diffLineCommentForms[line.right.lineCode] && line.right.type"
:diff-file="diffFile"
:diff-lines="diffLines"
:line="line.right"
:note-target-line="diffLines[index].right"
position="right"
/>
</td>
</tr>
</template>
</tbody>
</table>
</div>
</template>