summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/diffs/components
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/diffs/components')
-rw-r--r--app/assets/javascripts/diffs/components/app.vue2
-rw-r--r--app/assets/javascripts/diffs/components/commit_item.vue2
-rw-r--r--app/assets/javascripts/diffs/components/compare_versions.vue1
-rw-r--r--app/assets/javascripts/diffs/components/diff_discussion_reply.vue1
-rw-r--r--app/assets/javascripts/diffs/components/diff_expansion_cell.vue244
-rw-r--r--app/assets/javascripts/diffs/components/diff_file.vue19
-rw-r--r--app/assets/javascripts/diffs/components/diff_file_header.vue3
-rw-r--r--app/assets/javascripts/diffs/components/diff_gutter_avatars.vue5
-rw-r--r--app/assets/javascripts/diffs/components/diff_line_gutter_content.vue106
-rw-r--r--app/assets/javascripts/diffs/components/hidden_files_warning.vue1
-rw-r--r--app/assets/javascripts/diffs/components/inline_diff_expansion_row.vue53
-rw-r--r--app/assets/javascripts/diffs/components/inline_diff_table_row.vue5
-rw-r--r--app/assets/javascripts/diffs/components/inline_diff_view.vue18
-rw-r--r--app/assets/javascripts/diffs/components/parallel_diff_expansion_row.vue56
-rw-r--r--app/assets/javascripts/diffs/components/parallel_diff_table_row.vue11
-rw-r--r--app/assets/javascripts/diffs/components/parallel_diff_view.vue17
16 files changed, 448 insertions, 96 deletions
diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue
index 81da0754752..19b85710710 100644
--- a/app/assets/javascripts/diffs/components/app.vue
+++ b/app/assets/javascripts/diffs/components/app.vue
@@ -305,7 +305,7 @@ export default {
<div
v-show="showTreeList"
:style="{ width: `${treeWidth}px` }"
- class="diff-tree-list js-diff-tree-list"
+ class="diff-tree-list js-diff-tree-list mr-3"
>
<panel-resizer
:size.sync="treeWidth"
diff --git a/app/assets/javascripts/diffs/components/commit_item.vue b/app/assets/javascripts/diffs/components/commit_item.vue
index 58d5b658b17..c82b4a7abc6 100644
--- a/app/assets/javascripts/diffs/components/commit_item.vue
+++ b/app/assets/javascripts/diffs/components/commit_item.vue
@@ -49,8 +49,8 @@ export default {
return this.author.id ? this.author.id : '';
},
authorUrl() {
- // TODO: when the vue i18n rules are merged need to disable @gitlab/i18n/no-non-i18n-strings
// name: 'mailto:' is a false positive: https://gitlab.com/gitlab-org/frontend/eslint-plugin-i18n/issues/26#possible-false-positives
+ // eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings
return this.author.web_url || `mailto:${this.commit.author_email}`;
},
authorAvatar() {
diff --git a/app/assets/javascripts/diffs/components/compare_versions.vue b/app/assets/javascripts/diffs/components/compare_versions.vue
index 363ebad1594..2e57a47f2f7 100644
--- a/app/assets/javascripts/diffs/components/compare_versions.vue
+++ b/app/assets/javascripts/diffs/components/compare_versions.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable @gitlab/vue-i18n/no-bare-strings */
import { mapActions, mapGetters, mapState } from 'vuex';
import { GlTooltipDirective, GlLink, GlButton } from '@gitlab/ui';
import { __ } from '~/locale';
diff --git a/app/assets/javascripts/diffs/components/diff_discussion_reply.vue b/app/assets/javascripts/diffs/components/diff_discussion_reply.vue
index 2aa5e9b3339..531ebaddacd 100644
--- a/app/assets/javascripts/diffs/components/diff_discussion_reply.vue
+++ b/app/assets/javascripts/diffs/components/diff_discussion_reply.vue
@@ -44,7 +44,6 @@ export default {
class="d-none d-sm-block"
/>
<reply-placeholder
- class="qa-discussion-reply"
:button-text="__('Start a new discussion...')"
@onClick="$emit('showNewDiscussionForm')"
/>
diff --git a/app/assets/javascripts/diffs/components/diff_expansion_cell.vue b/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
new file mode 100644
index 00000000000..839ab542377
--- /dev/null
+++ b/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
@@ -0,0 +1,244 @@
+<script>
+import createFlash from '~/flash';
+import { s__ } from '~/locale';
+import { mapState, mapActions } from 'vuex';
+import Icon from '~/vue_shared/components/icon.vue';
+import { UNFOLD_COUNT } from '../constants';
+import * as utils from '../store/utils';
+import tooltip from '../../vue_shared/directives/tooltip';
+
+const EXPAND_ALL = 0;
+const EXPAND_UP = 1;
+const EXPAND_DOWN = 2;
+
+export default {
+ directives: {
+ tooltip,
+ },
+ components: {
+ Icon,
+ },
+ props: {
+ fileHash: {
+ type: String,
+ required: true,
+ },
+ contextLinesPath: {
+ type: String,
+ required: true,
+ },
+ line: {
+ type: Object,
+ required: true,
+ },
+ isTop: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ isBottom: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ colspan: {
+ type: Number,
+ required: false,
+ default: 3,
+ },
+ },
+ computed: {
+ ...mapState({
+ diffViewType: state => state.diffs.diffViewType,
+ diffFiles: state => state.diffs.diffFiles,
+ }),
+ canExpandUp() {
+ return !this.isBottom;
+ },
+ canExpandDown() {
+ return this.isBottom || !this.isTop;
+ },
+ },
+ created() {
+ this.EXPAND_DOWN = EXPAND_DOWN;
+ this.EXPAND_UP = EXPAND_UP;
+ },
+ methods: {
+ ...mapActions('diffs', ['loadMoreLines']),
+ getPrevLineNumber(oldLineNumber, newLineNumber) {
+ const diffFile = utils.findDiffFile(this.diffFiles, this.fileHash);
+ const indexForInline = utils.findIndexInInlineLines(diffFile.highlighted_diff_lines, {
+ oldLineNumber,
+ newLineNumber,
+ });
+ const prevLine = diffFile.highlighted_diff_lines[indexForInline - 2];
+ return (prevLine && prevLine.new_line) || 0;
+ },
+ callLoadMoreLines(
+ endpoint,
+ params,
+ lineNumbers,
+ fileHash,
+ isExpandDown = false,
+ nextLineNumbers = {},
+ ) {
+ this.loadMoreLines({ endpoint, params, lineNumbers, fileHash, isExpandDown, nextLineNumbers })
+ .then(() => {
+ this.isRequesting = false;
+ })
+ .catch(() => {
+ createFlash(s__('Diffs|Something went wrong while fetching diff lines.'));
+ this.isRequesting = false;
+ });
+ },
+ handleExpandLines(type = EXPAND_ALL) {
+ if (this.isRequesting) {
+ return;
+ }
+
+ this.isRequesting = true;
+ const endpoint = this.contextLinesPath;
+ const { fileHash } = this;
+ const view = this.diffViewType;
+ const oldLineNumber = this.line.meta_data.old_pos || 0;
+ const newLineNumber = this.line.meta_data.new_pos || 0;
+ const offset = newLineNumber - oldLineNumber;
+
+ const expandOptions = { endpoint, fileHash, view, oldLineNumber, newLineNumber, offset };
+
+ if (type === EXPAND_UP) {
+ this.handleExpandUpLines(expandOptions);
+ } else if (type === EXPAND_DOWN) {
+ this.handleExpandDownLines(expandOptions);
+ } else {
+ this.handleExpandAllLines(expandOptions);
+ }
+ },
+ handleExpandUpLines(expandOptions = EXPAND_ALL) {
+ const { endpoint, fileHash, view, oldLineNumber, newLineNumber, offset } = expandOptions;
+
+ const bottom = this.isBottom;
+ const lineNumber = newLineNumber - 1;
+ const to = lineNumber;
+ let since = lineNumber - UNFOLD_COUNT;
+ let unfold = true;
+
+ const prevLineNumber = this.getPrevLineNumber(oldLineNumber, newLineNumber);
+ if (since <= prevLineNumber + 1) {
+ since = prevLineNumber + 1;
+ unfold = false;
+ }
+
+ const params = { since, to, bottom, offset, unfold, view };
+ const lineNumbers = { oldLineNumber, newLineNumber };
+ this.callLoadMoreLines(endpoint, params, lineNumbers, fileHash);
+ },
+ handleExpandDownLines(expandOptions) {
+ const {
+ endpoint,
+ fileHash,
+ view,
+ oldLineNumber: metaOldPos,
+ newLineNumber: metaNewPos,
+ offset,
+ } = expandOptions;
+
+ const bottom = true;
+ const nextLineNumbers = {
+ old_line: metaOldPos,
+ new_line: metaNewPos,
+ };
+
+ let unfold = true;
+ let isExpandDown = false;
+ let oldLineNumber = metaOldPos;
+ let newLineNumber = metaNewPos;
+ let lineNumber = metaNewPos + 1;
+ let since = lineNumber;
+ let to = lineNumber + UNFOLD_COUNT;
+
+ if (!this.isBottom) {
+ const prevLineNumber = this.getPrevLineNumber(oldLineNumber, newLineNumber);
+
+ isExpandDown = true;
+ oldLineNumber = prevLineNumber - offset;
+ newLineNumber = prevLineNumber;
+ lineNumber = prevLineNumber + 1;
+ since = lineNumber;
+ to = lineNumber + UNFOLD_COUNT;
+
+ if (to >= metaNewPos) {
+ to = metaNewPos - 1;
+ unfold = false;
+ }
+ }
+
+ const params = { since, to, bottom, offset, unfold, view };
+ const lineNumbers = { oldLineNumber, newLineNumber };
+ this.callLoadMoreLines(
+ endpoint,
+ params,
+ lineNumbers,
+ fileHash,
+ isExpandDown,
+ nextLineNumbers,
+ );
+ },
+ handleExpandAllLines(expandOptions) {
+ const { endpoint, fileHash, view, oldLineNumber, newLineNumber, offset } = expandOptions;
+ const bottom = this.isBottom;
+ const unfold = false;
+ let since;
+ let to;
+
+ if (this.isTop) {
+ since = 1;
+ to = newLineNumber - 1;
+ } else if (bottom) {
+ since = newLineNumber + 1;
+ to = -1;
+ } else {
+ const prevLineNumber = this.getPrevLineNumber(oldLineNumber, newLineNumber);
+ since = prevLineNumber + 1;
+ to = newLineNumber - 1;
+ }
+
+ const params = { since, to, bottom, offset, unfold, view };
+ const lineNumbers = { oldLineNumber, newLineNumber };
+ this.callLoadMoreLines(endpoint, params, lineNumbers, fileHash);
+ },
+ },
+};
+</script>
+
+<template>
+ <td :colspan="colspan" class="text-center">
+ <div class="content js-line-expansion-content">
+ <a
+ v-if="canExpandUp"
+ v-tooltip
+ class="cursor-pointer js-unfold unfold-icon d-inline-block pt-2 pb-2"
+ data-placement="top"
+ data-container="body"
+ :title="__('Expand up')"
+ @click="handleExpandLines(EXPAND_UP)"
+ >
+ <icon :size="12" name="expand-up" aria-hidden="true" />
+ </a>
+ <a class="mx-2 cursor-pointer js-unfold-all" @click="handleExpandLines()">
+ <span>{{ s__('Diffs|Show all lines') }}</span>
+ </a>
+ <a
+ v-if="canExpandDown"
+ v-tooltip
+ class="cursor-pointer js-unfold-down has-tooltip unfold-icon d-inline-block pt-2 pb-2"
+ data-placement="top"
+ data-container="body"
+ :title="__('Expand down')"
+ @click="handleExpandLines(EXPAND_DOWN)"
+ >
+ <icon :size="12" name="expand-down" aria-hidden="true" />
+ </a>
+ </div>
+ </td>
+</template>
diff --git a/app/assets/javascripts/diffs/components/diff_file.vue b/app/assets/javascripts/diffs/components/diff_file.vue
index 63350fafefa..2514274224d 100644
--- a/app/assets/javascripts/diffs/components/diff_file.vue
+++ b/app/assets/javascripts/diffs/components/diff_file.vue
@@ -67,6 +67,18 @@ export default {
errorMessage() {
return this.file.viewer.error_message;
},
+ forkMessage() {
+ return sprintf(
+ __(
+ "You're not allowed to %{tag_start}edit%{tag_end} files in this project directly. Please fork this project, make your changes there, and submit a merge request.",
+ ),
+ {
+ tag_start: '<span class="js-file-fork-suggestion-section-action">',
+ tag_end: '</span>',
+ },
+ false,
+ );
+ },
},
watch: {
isCollapsed: function fileCollapsedWatch(newVal, oldVal) {
@@ -150,12 +162,7 @@ export default {
/>
<div v-if="forkMessageVisible" class="js-file-fork-suggestion-section file-fork-suggestion">
- <span class="file-fork-suggestion-note">
- {{ sprintf(__("You're not allowed to %{tag_start}edit%{tag_end} files in this project
- directly. Please fork this project, make your changes there, and submit a merge request."),
- { tag_start: '<span class="js-file-fork-suggestion-section-action">', tag_end: '</span>' })
- }}
- </span>
+ <span class="file-fork-suggestion-note" v-html="forkMessage"></span>
<a
:href="file.fork_path"
class="js-fork-suggestion-button btn btn-grouped btn-inverted btn-success"
diff --git a/app/assets/javascripts/diffs/components/diff_file_header.vue b/app/assets/javascripts/diffs/components/diff_file_header.vue
index 4b226e30699..69ec6ab8600 100644
--- a/app/assets/javascripts/diffs/components/diff_file_header.vue
+++ b/app/assets/javascripts/diffs/components/diff_file_header.vue
@@ -130,7 +130,7 @@ export default {
return `\`${this.diffFile.file_path}\``;
},
isFileRenamed() {
- return this.diffFile.viewer.name === diffViewerModes.renamed;
+ return this.diffFile.renamed_file;
},
isModeChanged() {
return this.diffFile.viewer.name === diffViewerModes.mode_changed;
@@ -263,6 +263,7 @@ export default {
:disabled="!diffHasDiscussions(diffFile)"
:class="{ active: hasExpandedDiscussions }"
class="js-btn-vue-toggle-comments btn"
+ data-qa-selector="toggle_comments_button"
type="button"
@click="handleToggleDiscussions"
>
diff --git a/app/assets/javascripts/diffs/components/diff_gutter_avatars.vue b/app/assets/javascripts/diffs/components/diff_gutter_avatars.vue
index af5550aec3b..7ede7a4f430 100644
--- a/app/assets/javascripts/diffs/components/diff_gutter_avatars.vue
+++ b/app/assets/javascripts/diffs/components/diff_gutter_avatars.vue
@@ -1,6 +1,7 @@
<script>
+import { n__ } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
-import { pluralize, truncate } from '~/lib/utils/text_utility';
+import { truncate } from '~/lib/utils/text_utility';
import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
import { GlTooltipDirective } from '@gitlab/ui';
import { COUNT_OF_AVATARS_IN_GUTTER, LENGTH_OF_AVATAR_TOOLTIP } from '../constants';
@@ -42,7 +43,7 @@ export default {
return '';
}
- return pluralize(`${this.moreCount} more comment`, this.moreCount);
+ return n__('%d more comment', '%d more comments', this.moreCount);
},
},
methods: {
diff --git a/app/assets/javascripts/diffs/components/diff_line_gutter_content.vue b/app/assets/javascripts/diffs/components/diff_line_gutter_content.vue
index 351110f0a87..434d554d148 100644
--- a/app/assets/javascripts/diffs/components/diff_line_gutter_content.vue
+++ b/app/assets/javascripts/diffs/components/diff_line_gutter_content.vue
@@ -1,11 +1,8 @@
<script>
-import createFlash from '~/flash';
-import { s__ } from '~/locale';
import { mapState, mapGetters, mapActions } from 'vuex';
import Icon from '~/vue_shared/components/icon.vue';
import DiffGutterAvatars from './diff_gutter_avatars.vue';
-import { LINE_POSITION_RIGHT, UNFOLD_COUNT } from '../constants';
-import * as utils from '../store/utils';
+import { LINE_POSITION_RIGHT } from '../constants';
export default {
components: {
@@ -115,89 +112,36 @@ export default {
handleCommentButton() {
this.showCommentForm({ lineCode: this.line.line_code, fileHash: this.fileHash });
},
- handleLoadMoreLines() {
- if (this.isRequesting) {
- return;
- }
-
- this.isRequesting = true;
- const endpoint = this.contextLinesPath;
- const oldLineNumber = this.line.meta_data.old_pos || 0;
- const newLineNumber = this.line.meta_data.new_pos || 0;
- const offset = newLineNumber - oldLineNumber;
- const bottom = this.isBottom;
- const { fileHash } = this;
- const view = this.diffViewType;
- let unfold = true;
- let lineNumber = newLineNumber - 1;
- let since = lineNumber - UNFOLD_COUNT;
- let to = lineNumber;
-
- if (bottom) {
- lineNumber = newLineNumber + 1;
- since = lineNumber;
- to = lineNumber + UNFOLD_COUNT;
- } else {
- const diffFile = utils.findDiffFile(this.diffFiles, this.fileHash);
- const indexForInline = utils.findIndexInInlineLines(diffFile.highlighted_diff_lines, {
- oldLineNumber,
- newLineNumber,
- });
- const prevLine = diffFile.highlighted_diff_lines[indexForInline - 2];
- const prevLineNumber = (prevLine && prevLine.new_line) || 0;
-
- if (since <= prevLineNumber + 1) {
- since = prevLineNumber + 1;
- unfold = false;
- }
- }
-
- const params = { since, to, bottom, offset, unfold, view };
- const lineNumbers = { oldLineNumber, newLineNumber };
- this.loadMoreLines({ endpoint, params, lineNumbers, fileHash })
- .then(() => {
- this.isRequesting = false;
- })
- .catch(() => {
- createFlash(s__('Diffs|Something went wrong while fetching diff lines.'));
- this.isRequesting = false;
- });
- },
},
};
</script>
<template>
<div>
- <span v-if="isMatchLine" class="context-cell" role="button" @click="handleLoadMoreLines"
- >...</span
+ <button
+ v-if="shouldRenderCommentButton"
+ v-show="shouldShowCommentButton"
+ type="button"
+ class="add-diff-note js-add-diff-note-button qa-diff-comment"
+ title="Add a comment to this line"
+ @click="handleCommentButton"
+ >
+ <icon :size="12" name="comment" />
+ </button>
+ <a
+ v-if="lineNumber"
+ :data-linenumber="lineNumber"
+ :href="lineHref"
+ @click="setHighlightedRow(lineCode)"
>
- <template v-else>
- <button
- v-if="shouldRenderCommentButton"
- v-show="shouldShowCommentButton"
- type="button"
- class="add-diff-note js-add-diff-note-button qa-diff-comment"
- title="Add a comment to this line"
- @click="handleCommentButton"
- >
- <icon :size="12" name="comment" />
- </button>
- <a
- v-if="lineNumber"
- :data-linenumber="lineNumber"
- :href="lineHref"
- @click="setHighlightedRow(lineCode)"
- >
- </a>
- <diff-gutter-avatars
- v-if="shouldShowAvatarsOnGutter"
- :discussions="line.discussions"
- :discussions-expanded="line.discussionsExpanded"
- @toggleLineDiscussions="
- toggleLineDiscussions({ lineCode, fileHash, expanded: !line.discussionsExpanded })
- "
- />
- </template>
+ </a>
+ <diff-gutter-avatars
+ v-if="shouldShowAvatarsOnGutter"
+ :discussions="line.discussions"
+ :discussions-expanded="line.discussionsExpanded"
+ @toggleLineDiscussions="
+ toggleLineDiscussions({ lineCode, fileHash, expanded: !line.discussionsExpanded })
+ "
+ />
</div>
</template>
diff --git a/app/assets/javascripts/diffs/components/hidden_files_warning.vue b/app/assets/javascripts/diffs/components/hidden_files_warning.vue
index 119e139de21..035c2b3b11e 100644
--- a/app/assets/javascripts/diffs/components/hidden_files_warning.vue
+++ b/app/assets/javascripts/diffs/components/hidden_files_warning.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable @gitlab/vue-i18n/no-bare-strings */
export default {
props: {
total: {
diff --git a/app/assets/javascripts/diffs/components/inline_diff_expansion_row.vue b/app/assets/javascripts/diffs/components/inline_diff_expansion_row.vue
new file mode 100644
index 00000000000..6e732727f42
--- /dev/null
+++ b/app/assets/javascripts/diffs/components/inline_diff_expansion_row.vue
@@ -0,0 +1,53 @@
+<script>
+import Icon from '~/vue_shared/components/icon.vue';
+import DiffExpansionCell from './diff_expansion_cell.vue';
+import { MATCH_LINE_TYPE } from '../constants';
+
+export default {
+ components: {
+ Icon,
+ DiffExpansionCell,
+ },
+ props: {
+ fileHash: {
+ type: String,
+ required: true,
+ },
+ contextLinesPath: {
+ type: String,
+ required: true,
+ },
+ line: {
+ type: Object,
+ required: true,
+ },
+ isTop: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ isBottom: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ computed: {
+ isMatchLine() {
+ return this.line.type === MATCH_LINE_TYPE;
+ },
+ },
+};
+</script>
+
+<template>
+ <tr v-if="isMatchLine" class="line_expansion match">
+ <diff-expansion-cell
+ :file-hash="fileHash"
+ :context-lines-path="contextLinesPath"
+ :line="line"
+ :is-top="isTop"
+ :is-bottom="isBottom"
+ />
+ </tr>
+</template>
diff --git a/app/assets/javascripts/diffs/components/inline_diff_table_row.vue b/app/assets/javascripts/diffs/components/inline_diff_table_row.vue
index 2d5262baeec..55a8df43c62 100644
--- a/app/assets/javascripts/diffs/components/inline_diff_table_row.vue
+++ b/app/assets/javascripts/diffs/components/inline_diff_table_row.vue
@@ -2,6 +2,7 @@
import { mapActions, mapState } from 'vuex';
import DiffTableCell from './diff_table_cell.vue';
import {
+ MATCH_LINE_TYPE,
NEW_LINE_TYPE,
OLD_LINE_TYPE,
CONTEXT_LINE_TYPE,
@@ -58,6 +59,9 @@ export default {
inlineRowId() {
return this.line.line_code || `${this.fileHash}_${this.line.old_line}_${this.line.new_line}`;
},
+ isMatchLine() {
+ return this.line.type === MATCH_LINE_TYPE;
+ },
},
created() {
this.newLineType = NEW_LINE_TYPE;
@@ -81,6 +85,7 @@ export default {
<template>
<tr
+ v-if="!isMatchLine"
:id="inlineRowId"
:class="classNameMap"
class="line_holder"
diff --git a/app/assets/javascripts/diffs/components/inline_diff_view.vue b/app/assets/javascripts/diffs/components/inline_diff_view.vue
index b2bc3d9914f..aee01409db7 100644
--- a/app/assets/javascripts/diffs/components/inline_diff_view.vue
+++ b/app/assets/javascripts/diffs/components/inline_diff_view.vue
@@ -3,6 +3,7 @@ import { mapGetters } from 'vuex';
import draftCommentsMixin from 'ee_else_ce/diffs/mixins/draft_comments';
import inlineDiffTableRow from './inline_diff_table_row.vue';
import inlineDiffCommentRow from './inline_diff_comment_row.vue';
+import inlineDiffExpansionRow from './inline_diff_expansion_row.vue';
export default {
components: {
@@ -10,6 +11,7 @@ export default {
inlineDiffTableRow,
InlineDraftCommentRow: () =>
import('ee_component/batch_comments/components/inline_draft_comment_row.vue'),
+ inlineDiffExpansionRow,
},
mixins: [draftCommentsMixin],
props: {
@@ -43,10 +45,24 @@ export default {
:data-commit-id="commitId"
class="code diff-wrap-lines js-syntax-highlight text-file js-diff-inline-view"
>
+ <!-- Need to insert an empty row to solve "table-layout:fixed" equal width when expansion row is the first line -->
+ <tr>
+ <td style="width: 50px;"></td>
+ <td style="width: 50px;"></td>
+ <td></td>
+ </tr>
<tbody>
<template v-for="(line, index) in diffLines">
+ <inline-diff-expansion-row
+ :key="`expand-${index}`"
+ :file-hash="diffFile.file_hash"
+ :context-lines-path="diffFile.context_lines_path"
+ :line="line"
+ :is-top="index === 0"
+ :is-bottom="index + 1 === diffLinesLength"
+ />
<inline-diff-table-row
- :key="line.line_code"
+ :key="`${line.line_code || index}`"
:file-hash="diffFile.file_hash"
:context-lines-path="diffFile.context_lines_path"
:line="line"
diff --git a/app/assets/javascripts/diffs/components/parallel_diff_expansion_row.vue b/app/assets/javascripts/diffs/components/parallel_diff_expansion_row.vue
new file mode 100644
index 00000000000..c1b30eab199
--- /dev/null
+++ b/app/assets/javascripts/diffs/components/parallel_diff_expansion_row.vue
@@ -0,0 +1,56 @@
+<script>
+import { MATCH_LINE_TYPE } from '../constants';
+import DiffExpansionCell from './diff_expansion_cell.vue';
+
+export default {
+ components: {
+ DiffExpansionCell,
+ },
+ props: {
+ fileHash: {
+ type: String,
+ required: true,
+ },
+ contextLinesPath: {
+ type: String,
+ required: true,
+ },
+ line: {
+ type: Object,
+ required: true,
+ },
+ isTop: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ isBottom: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ computed: {
+ isMatchLineLeft() {
+ return this.line.left && this.line.left.type === MATCH_LINE_TYPE;
+ },
+ isMatchLineRight() {
+ return this.line.right && this.line.right.type === MATCH_LINE_TYPE;
+ },
+ },
+};
+</script>
+<template>
+ <tr class="line_expansion match">
+ <template v-if="isMatchLineLeft || isMatchLineRight">
+ <diff-expansion-cell
+ :file-hash="fileHash"
+ :context-lines-path="contextLinesPath"
+ :line="line.left"
+ :is-top="isTop"
+ :is-bottom="isBottom"
+ :colspan="4"
+ />
+ </template>
+ </tr>
+</template>
diff --git a/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue b/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue
index c60246bf8ef..4c95d618b0f 100644
--- a/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue
+++ b/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue
@@ -3,6 +3,7 @@ import { mapActions, mapState } from 'vuex';
import $ from 'jquery';
import DiffTableCell from './diff_table_cell.vue';
import {
+ MATCH_LINE_TYPE,
NEW_LINE_TYPE,
OLD_LINE_TYPE,
CONTEXT_LINE_TYPE,
@@ -75,6 +76,12 @@ export default {
},
];
},
+ isMatchLineLeft() {
+ return this.line.left && this.line.left.type === MATCH_LINE_TYPE;
+ },
+ isMatchLineRight() {
+ return this.line.right && this.line.right.type === MATCH_LINE_TYPE;
+ },
},
created() {
this.newLineType = NEW_LINE_TYPE;
@@ -122,7 +129,7 @@ export default {
@mouseover="handleMouseMove"
@mouseout="handleMouseMove"
>
- <template v-if="line.left">
+ <template v-if="line.left && !isMatchLineLeft">
<diff-table-cell
:file-hash="fileHash"
:context-lines-path="contextLinesPath"
@@ -148,7 +155,7 @@ export default {
<td class="diff-line-num old_line empty-cell"></td>
<td class="line_content parallel left-side empty-cell"></td>
</template>
- <template v-if="line.right">
+ <template v-if="line.right && !isMatchLineRight">
<diff-table-cell
:file-hash="fileHash"
:context-lines-path="contextLinesPath"
diff --git a/app/assets/javascripts/diffs/components/parallel_diff_view.vue b/app/assets/javascripts/diffs/components/parallel_diff_view.vue
index c477e68c33c..d400eb2c586 100644
--- a/app/assets/javascripts/diffs/components/parallel_diff_view.vue
+++ b/app/assets/javascripts/diffs/components/parallel_diff_view.vue
@@ -3,9 +3,11 @@ import { mapGetters } from 'vuex';
import draftCommentsMixin from 'ee_else_ce/diffs/mixins/draft_comments';
import parallelDiffTableRow from './parallel_diff_table_row.vue';
import parallelDiffCommentRow from './parallel_diff_comment_row.vue';
+import parallelDiffExpansionRow from './parallel_diff_expansion_row.vue';
export default {
components: {
+ parallelDiffExpansionRow,
parallelDiffTableRow,
parallelDiffCommentRow,
ParallelDraftCommentRow: () =>
@@ -43,8 +45,23 @@ export default {
:data-commit-id="commitId"
class="code diff-wrap-lines js-syntax-highlight text-file"
>
+ <!-- Need to insert an empty row to solve "table-layout:fixed" equal width when expansion row is the first line -->
+ <tr>
+ <td style="width: 50px;"></td>
+ <td></td>
+ <td style="width: 50px;"></td>
+ <td></td>
+ </tr>
<tbody>
<template v-for="(line, index) in diffLines">
+ <parallel-diff-expansion-row
+ :key="`expand-${index}`"
+ :file-hash="diffFile.file_hash"
+ :context-lines-path="diffFile.context_lines_path"
+ :line="line"
+ :is-top="index === 0"
+ :is-bottom="index + 1 === diffLinesLength"
+ />
<parallel-diff-table-row
:key="line.line_code"
:file-hash="diffFile.file_hash"