diff options
Diffstat (limited to 'app/assets/javascripts/diffs/components')
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" |