diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-01-14 21:10:59 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-01-14 21:10:59 +0300 |
commit | ea3306a15e945e694afba62dc93b17500ffaec7f (patch) | |
tree | aa444f7fe503e5650bfdb6500ed428b4619ff37b /app/assets/javascripts/diffs | |
parent | 8106ac487c3b52471e2ca894c65c13162c2fb1a8 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/diffs')
7 files changed, 148 insertions, 27 deletions
diff --git a/app/assets/javascripts/diffs/components/diff_line_note_form.vue b/app/assets/javascripts/diffs/components/diff_line_note_form.vue index 6e22e181c02..463b7f5cff4 100644 --- a/app/assets/javascripts/diffs/components/diff_line_note_form.vue +++ b/app/assets/javascripts/diffs/components/diff_line_note_form.vue @@ -56,10 +56,11 @@ export default { }, computed: { ...mapState({ - noteableData: (state) => state.notes.noteableData, - diffViewType: (state) => state.diffs.diffViewType, + diffViewType: ({ diffs }) => diffs.diffViewType, + showSuggestPopover: ({ diffs }) => diffs.showSuggestPopover, + noteableData: ({ notes }) => notes.noteableData, + selectedCommentPosition: ({ notes }) => notes.selectedCommentPosition, }), - ...mapState('diffs', ['showSuggestPopover']), ...mapGetters('diffs', ['getDiffFileByHash', 'diffLines']), ...mapGetters([ 'isLoggedIn', @@ -126,6 +127,10 @@ export default { this.initAutoSave(this.noteableData, keys); } + + if (this.selectedCommentPosition) { + this.commentLineStart = this.selectedCommentPosition.start; + } }, methods: { ...mapActions('diffs', [ diff --git a/app/assets/javascripts/diffs/components/diff_row.vue b/app/assets/javascripts/diffs/components/diff_row.vue index 9e1385853b6..9054a8aec04 100644 --- a/app/assets/javascripts/diffs/components/diff_row.vue +++ b/app/assets/javascripts/diffs/components/diff_row.vue @@ -10,6 +10,7 @@ import { CONFLICT_THEIR, CONFLICT_MARKER, } from '../constants'; +import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import DiffGutterAvatars from './diff_gutter_avatars.vue'; import * as utils from './diff_row_utils'; @@ -22,6 +23,7 @@ export default { GlTooltip: GlTooltipDirective, SafeHtml, }, + mixins: [glFeatureFlagsMixin()], props: { fileHash: { type: String, @@ -45,6 +47,15 @@ export default { required: false, default: false, }, + index: { + type: Number, + required: true, + }, + }, + data() { + return { + dragging: false, + }; }, computed: { ...mapGetters('diffs', ['fileLineCoverage']), @@ -52,26 +63,35 @@ export default { ...mapState({ isHighlighted(state) { const line = this.line.left?.line_code ? this.line.left : this.line.right; - return utils.isHighlighted(state, line, this.isCommented); + return utils.isHighlighted(state, line, false); }, }), classNameMap() { return { [CONTEXT_LINE_CLASS_NAME]: this.line.isContextLineLeft, [PARALLEL_DIFF_VIEW_TYPE]: !this.inline, + commented: this.isCommented, }; }, parallelViewLeftLineType() { - return utils.parallelViewLeftLineType(this.line, this.isHighlighted); + return utils.parallelViewLeftLineType(this.line, this.isHighlighted || this.isCommented); }, coverageState() { return this.fileLineCoverage(this.filePath, this.line.right.new_line); }, classNameMapCellLeft() { - return utils.classNameMapCell(this.line.left, this.isHighlighted, this.isLoggedIn); + return utils.classNameMapCell({ + line: this.line.left, + hll: this.isHighlighted || this.isCommented, + isLoggedIn: this.isLoggedIn, + }); }, classNameMapCellRight() { - return utils.classNameMapCell(this.line.right, this.isHighlighted, this.isLoggedIn); + return utils.classNameMapCell({ + line: this.line.right, + hll: this.isHighlighted || this.isCommented, + isLoggedIn: this.isLoggedIn, + }); }, addCommentTooltipLeft() { return utils.addCommentTooltip(this.line.left); @@ -131,6 +151,22 @@ export default { ? this.$options.THEIR_CHANGES : this.$options.OUR_CHANGES; }, + onDragEnd() { + this.dragging = false; + if (!this.glFeatures.dragCommentSelection) return; + + this.$emit('stopdragging'); + }, + onDragEnter(line, index) { + if (!this.glFeatures.dragCommentSelection) return; + + this.$emit('enterdragging', { ...line, index }); + }, + onDragStart(line) { + this.$root.$emit('bv::hide::tooltip'); + this.dragging = true; + this.$emit('startdragging', line); + }, }, OUR_CHANGES: 'HEAD//our changes', THEIR_CHANGES: 'origin//their changes', @@ -143,7 +179,13 @@ export default { <template> <div :class="classNameMap" class="diff-grid-row diff-tr line_holder"> - <div class="diff-grid-left left-side"> + <div + data-testid="left-side" + class="diff-grid-left left-side" + @dragover.prevent + @dragenter="onDragEnter(line.left, index)" + @dragend="onDragEnd" + > <template v-if="line.left && line.left.type !== $options.CONFLICT_MARKER"> <div :class="classNameMapCellLeft" @@ -159,10 +201,13 @@ export default { :title="addCommentTooltipLeft" > <button + :draggable="glFeatures.dragCommentSelection" type="button" class="add-diff-note note-button js-add-diff-note-button qa-diff-comment" + :class="{ 'gl-cursor-grab': dragging }" :disabled="line.left.commentsDisabled" @click="handleCommentButton(line.left)" + @dragstart="onDragStart({ ...line.left, index })" > <gl-icon :size="12" name="comment" /> </button> @@ -234,7 +279,14 @@ export default { ></div> </template> </div> - <div v-if="!inline" class="diff-grid-right right-side"> + <div + v-if="!inline" + data-testid="right-side" + class="diff-grid-right right-side" + @dragover.prevent + @dragenter="onDragEnter(line.right, index)" + @dragend="onDragEnd" + > <template v-if="line.right"> <div :class="classNameMapCellRight" class="diff-td diff-line-num new_line"> <template v-if="line.right.type !== $options.CONFLICT_MARKER_THEIR"> @@ -246,10 +298,13 @@ export default { :title="addCommentTooltipRight" > <button + :draggable="glFeatures.dragCommentSelection" type="button" class="add-diff-note note-button js-add-diff-note-button qa-diff-comment" + :class="{ 'gl-cursor-grab': dragging }" :disabled="line.right.commentsDisabled" @click="handleCommentButton(line.right)" + @dragstart="onDragStart({ ...line.right, index })" > <gl-icon :size="12" name="comment" /> </button> @@ -279,13 +334,21 @@ export default { <div v-gl-tooltip.hover :title="coverageState.text" - :class="[line.right.type, coverageState.class, { hll: isHighlighted }]" + :class="[line.right.type, coverageState.class, { hll: isHighlighted, hll: isCommented }]" class="diff-td line-coverage right-side" ></div> <div :id="line.right.line_code" :key="line.right.rich_text" - :class="[line.right.type, { hll: isHighlighted, parallel: !inline }]" + v-safe-html="line.right.rich_text" + :class="[ + line.right.type, + { + hll: isHighlighted, + hll: isCommented, + parallel: !inline, + }, + ]" class="diff-td line_content with-coverage right-side" @mousedown="handleParallelLineMouseDown" > diff --git a/app/assets/javascripts/diffs/components/diff_row_utils.js b/app/assets/javascripts/diffs/components/diff_row_utils.js index 3ef271ddb8f..7606c39ad37 100644 --- a/app/assets/javascripts/diffs/components/diff_row_utils.js +++ b/app/assets/javascripts/diffs/components/diff_row_utils.js @@ -35,7 +35,7 @@ export const lineCode = (line) => { return line.line_code || line.left?.line_code || line.right?.line_code; }; -export const classNameMapCell = (line, hll, isLoggedIn, isHover) => { +export const classNameMapCell = ({ line, hll, isLoggedIn, isHover }) => { if (!line) return []; const { type } = line; @@ -54,7 +54,9 @@ export const addCommentTooltip = (line) => { let tooltip; if (!line) return tooltip; - tooltip = __('Add a comment to this line'); + tooltip = gon.drag_comment_selection + ? __('Add a comment to this line or drag for multiple lines') + : __('Add a comment to this line'); const brokenSymlinks = line.commentsDisabled; if (brokenSymlinks) { diff --git a/app/assets/javascripts/diffs/components/diff_view.vue b/app/assets/javascripts/diffs/components/diff_view.vue index 84429f62a1c..79800f835f4 100644 --- a/app/assets/javascripts/diffs/components/diff_view.vue +++ b/app/assets/javascripts/diffs/components/diff_view.vue @@ -1,5 +1,5 @@ <script> -import { mapGetters, mapState } from 'vuex'; +import { mapGetters, mapState, mapActions } from 'vuex'; import draftCommentsMixin from '~/diffs/mixins/draft_comments'; import DraftNote from '~/batch_comments/components/draft_note.vue'; import DiffRow from './diff_row.vue'; @@ -35,6 +35,12 @@ export default { default: false, }, }, + data() { + return { + dragStart: null, + updatedLineRange: null, + }; + }, computed: { ...mapGetters('diffs', ['commitId']), ...mapState({ @@ -52,12 +58,39 @@ export default { }, }, methods: { + ...mapActions(['setSelectedCommentPosition']), + ...mapActions('diffs', ['showCommentForm']), showCommentLeft(line) { return !this.inline || line.left; }, showCommentRight(line) { return !this.inline || (line.right && !line.left); }, + onStartDragging(line) { + this.dragStart = line; + }, + onDragOver(line) { + if (line.chunk !== this.dragStart.chunk) return; + + let start = this.dragStart; + let end = line; + + if (this.dragStart.index >= line.index) { + start = line; + end = this.dragStart; + } + + this.updatedLineRange = { start, end }; + + this.setSelectedCommentPosition(this.updatedLineRange); + }, + onStopDragging() { + this.showCommentForm({ + lineCode: this.updatedLineRange?.end?.line_code, + fileHash: this.diffFile.file_hash, + }); + this.dragStart = null; + }, }, userColorScheme: window.gon.user_color_scheme, }; @@ -94,6 +127,10 @@ export default { :is-bottom="index + 1 === diffLinesLength" :is-commented="index >= commentedLines.startLine && index <= commentedLines.endLine" :inline="inline" + :index="index" + @enterdragging="onDragOver" + @startdragging="onStartDragging" + @stopdragging="onStopDragging" /> <div v-if="line.renderCommentRow" 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 2d8ffb047ca..014b1ebe54b 100644 --- a/app/assets/javascripts/diffs/components/inline_diff_table_row.vue +++ b/app/assets/javascripts/diffs/components/inline_diff_table_row.vue @@ -72,7 +72,12 @@ export default { return this.fileLineCoverage(this.filePath, this.line.new_line); }, classNameMapCell() { - return classNameMapCell(this.line, this.isHighlighted, this.isLoggedIn, this.isHover); + return classNameMapCell({ + line: this.line, + hll: this.isHighlighted, + isLoggedIn: this.isLoggedIn, + isHover: this.isHover, + }); }, addCommentTooltip() { return addCommentTooltip(this.line); 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 b1618fb0688..47eecef2385 100644 --- a/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue +++ b/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue @@ -68,20 +68,20 @@ export default { return this.fileLineCoverage(this.filePath, this.line.right.new_line); }, classNameMapCellLeft() { - return utils.classNameMapCell( - this.line.left, - this.isHighlighted, - this.isLoggedIn, - this.isLeftHover, - ); + return utils.classNameMapCell({ + line: this.line.left, + hll: this.isHighlighted, + isLoggedIn: this.isLoggedIn, + isHover: this.isLeftHover, + }); }, classNameMapCellRight() { - return utils.classNameMapCell( - this.line.right, - this.isHighlighted, - this.isLoggedIn, - this.isRightHover, - ); + return utils.classNameMapCell({ + line: this.line.right, + hll: this.isHighlighted, + isLoggedIn: this.isLoggedIn, + isHover: this.isRightHover, + }); }, addCommentTooltipLeft() { return utils.addCommentTooltip(this.line.left); diff --git a/app/assets/javascripts/diffs/store/utils.js b/app/assets/javascripts/diffs/store/utils.js index 8712220b25e..c52da558be2 100644 --- a/app/assets/javascripts/diffs/store/utils.js +++ b/app/assets/javascripts/diffs/store/utils.js @@ -55,8 +55,17 @@ export const parallelizeDiffLines = (diffLines, inline) => { let conflictStartIndex = -1; const lines = []; + // `chunk` is used for dragging to select diff lines + // we are restricting commenting to only lines that appear between + // "expansion rows". Here equal chunks are lines grouped together + // inbetween expansion rows. + let chunk = 0; + for (let i = 0, diffLinesLength = diffLines.length, index = 0; i < diffLinesLength; i += 1) { const line = diffLines[i]; + line.chunk = chunk; + + if (isMeta(line)) chunk += 1; if (isRemoved(line) || isConflictOur(line) || inline) { lines.push({ |