diff options
Diffstat (limited to 'app/assets/javascripts/diffs/components/diff_row.vue')
-rw-r--r-- | app/assets/javascripts/diffs/components/diff_row.vue | 268 |
1 files changed, 205 insertions, 63 deletions
diff --git a/app/assets/javascripts/diffs/components/diff_row.vue b/app/assets/javascripts/diffs/components/diff_row.vue index c0719e2a7d9..db03da966c3 100644 --- a/app/assets/javascripts/diffs/components/diff_row.vue +++ b/app/assets/javascripts/diffs/components/diff_row.vue @@ -1,7 +1,16 @@ <script> import { mapActions, mapGetters, mapState } from 'vuex'; import { GlTooltipDirective, GlIcon, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui'; -import { CONTEXT_LINE_CLASS_NAME, PARALLEL_DIFF_VIEW_TYPE } from '../constants'; +import { + CONTEXT_LINE_CLASS_NAME, + PARALLEL_DIFF_VIEW_TYPE, + CONFLICT_MARKER_OUR, + CONFLICT_MARKER_THEIR, + CONFLICT_OUR, + 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'; @@ -14,6 +23,7 @@ export default { GlTooltip: GlTooltipDirective, SafeHtml, }, + mixins: [glFeatureFlagsMixin()], props: { fileHash: { type: String, @@ -37,6 +47,15 @@ export default { required: false, default: false, }, + index: { + type: Number, + required: true, + }, + }, + data() { + return { + dragging: false, + }; }, computed: { ...mapGetters('diffs', ['fileLineCoverage']), @@ -44,26 +63,40 @@ 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]: true, + [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() { + coverageStateLeft() { + if (!this.inline || !this.line.left) return {}; + return this.fileLineCoverage(this.filePath, this.line.left.new_line); + }, + coverageStateRight() { + if (!this.line.right) return {}; 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); @@ -71,6 +104,12 @@ export default { addCommentTooltipRight() { return utils.addCommentTooltip(this.line.right); }, + emptyCellRightClassMap() { + return { conflict_their: this.line.left?.type === CONFLICT_OUR }; + }, + emptyCellLeftClassMap() { + return { conflict_our: this.line.right?.type === CONFLICT_THEIR }; + }, shouldRenderCommentButton() { return ( this.isLoggedIn && @@ -80,6 +119,9 @@ export default { !this.line.hasDiscussionsRight ); }, + isLeftConflictMarker() { + return [CONFLICT_MARKER_OUR, CONFLICT_MARKER_THEIR].includes(this.line.left?.type); + }, }, mounted() { this.scrollToLineIfNeededParallel(this.line); @@ -98,7 +140,9 @@ export default { const table = line.closest('.diff-table'); table.classList.remove('left-side-selected', 'right-side-selected'); - const [lineClass] = ['left-side', 'right-side'].filter(name => line.classList.contains(name)); + const [lineClass] = ['left-side', 'right-side'].filter((name) => + line.classList.contains(name), + ); if (lineClass) { table.classList.add(`${lineClass}-selected`); @@ -107,37 +151,75 @@ export default { handleCommentButton(line) { this.showCommentForm({ lineCode: line.line_code, fileHash: this.fileHash }); }, + conflictText(line) { + return line.type === CONFLICT_MARKER_THEIR + ? 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', + CONFLICT_MARKER, + CONFLICT_MARKER_THEIR, + CONFLICT_OUR, + CONFLICT_THEIR, }; </script> <template> <div :class="classNameMap" class="diff-grid-row diff-tr line_holder"> - <div class="diff-grid-left left-side"> - <template v-if="line.left"> + <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" data-testid="leftLineNumber" - class="diff-td diff-line-num old_line" + class="diff-td diff-line-num" > - <span - v-if="shouldRenderCommentButton" - v-gl-tooltip - data-testid="leftCommentButton" - class="add-diff-note tooltip-wrapper" - :title="addCommentTooltipLeft" - > - <button - type="button" - class="add-diff-note note-button js-add-diff-note-button qa-diff-comment" - :disabled="line.left.commentsDisabled" - @click="handleCommentButton(line.left)" + <template v-if="!isLeftConflictMarker"> + <span + v-if="shouldRenderCommentButton" + v-gl-tooltip + data-testid="leftCommentButton" + class="add-diff-note tooltip-wrapper" + :title="addCommentTooltipLeft" > - <gl-icon :size="12" name="comment" /> - </button> - </span> + <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> + </span> + </template> <a - v-if="line.left.old_line" + v-if="line.left.old_line && line.left.type !== $options.CONFLICT_THEIR" :data-linenumber="line.left.old_line" :href="line.lineHrefOld" @click="setHighlightedRow(line.lineCode)" @@ -157,52 +239,87 @@ export default { " /> </div> - <div v-if="inline" :class="classNameMapCellLeft" class="diff-td diff-line-num old_line"> + <div v-if="inline" :class="classNameMapCellLeft" class="diff-td diff-line-num"> <a - v-if="line.left.new_line" + v-if="line.left.new_line && line.left.type !== $options.CONFLICT_OUR" :data-linenumber="line.left.new_line" :href="line.lineHrefOld" @click="setHighlightedRow(line.lineCode)" > </a> </div> - <div :class="parallelViewLeftLineType" class="diff-td line-coverage left-side"></div> + <div + v-gl-tooltip.hover + :title="coverageStateLeft.text" + :class="[...parallelViewLeftLineType, coverageStateLeft.class]" + class="diff-td line-coverage left-side" + ></div> <div :id="line.left.line_code" :key="line.left.line_code" - v-safe-html="line.left.rich_text" - :class="parallelViewLeftLineType" - class="diff-td line_content with-coverage parallel left-side" + :class="[parallelViewLeftLineType, { parallel: !inline }]" + class="diff-td line_content with-coverage left-side" data-testid="leftContent" @mousedown="handleParallelLineMouseDown" - ></div> + > + <strong v-if="isLeftConflictMarker">{{ conflictText(line.left) }}</strong> + <span v-else v-safe-html="line.left.rich_text"></span> + </div> </template> - <template v-else> - <div data-testid="leftEmptyCell" class="diff-td diff-line-num old_line empty-cell"></div> - <div v-if="inline" class="diff-td diff-line-num old_line empty-cell"></div> - <div class="diff-td line-coverage left-side empty-cell"></div> - <div class="diff-td line_content with-coverage parallel left-side empty-cell"></div> + <template v-else-if="!inline || (line.left && line.left.type === $options.CONFLICT_MARKER)"> + <div + data-testid="leftEmptyCell" + class="diff-td diff-line-num old_line empty-cell" + :class="emptyCellLeftClassMap" + > + + </div> + <div + v-if="inline" + class="diff-td diff-line-num old_line empty-cell" + :class="emptyCellLeftClassMap" + ></div> + <div + class="diff-td line-coverage left-side empty-cell" + :class="emptyCellLeftClassMap" + ></div> + <div + class="diff-td line_content with-coverage left-side empty-cell" + :class="[emptyCellLeftClassMap, { parallel: !inline }]" + ></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"> - <span - v-if="shouldRenderCommentButton" - v-gl-tooltip - data-testid="rightCommentButton" - class="add-diff-note tooltip-wrapper" - :title="addCommentTooltipRight" - > - <button - type="button" - class="add-diff-note note-button js-add-diff-note-button qa-diff-comment" - :disabled="line.right.commentsDisabled" - @click="handleCommentButton(line.right)" + <template v-if="line.right.type !== $options.CONFLICT_MARKER_THEIR"> + <span + v-if="shouldRenderCommentButton" + v-gl-tooltip + data-testid="rightCommentButton" + class="add-diff-note tooltip-wrapper" + :title="addCommentTooltipRight" > - <gl-icon :size="12" name="comment" /> - </button> - </span> + <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> + </span> + </template> <a v-if="line.right.new_line" :data-linenumber="line.right.new_line" @@ -226,8 +343,12 @@ export default { </div> <div v-gl-tooltip.hover - :title="coverageState.text" - :class="[line.right.type, coverageState.class, { hll: isHighlighted }]" + :title="coverageStateRight.text" + :class="[ + line.right.type, + coverageStateRight.class, + { hll: isHighlighted, hll: isCommented }, + ]" class="diff-td line-coverage right-side" ></div> <div @@ -238,17 +359,38 @@ export default { line.right.type, { hll: isHighlighted, + hll: isCommented, + parallel: !inline, }, ]" - class="diff-td line_content with-coverage parallel right-side" + class="diff-td line_content with-coverage right-side" @mousedown="handleParallelLineMouseDown" - ></div> + > + <strong v-if="line.right.type === $options.CONFLICT_MARKER_THEIR">{{ + conflictText(line.right) + }}</strong> + <span v-else v-safe-html="line.right.rich_text"></span> + </div> </template> <template v-else> - <div data-testid="rightEmptyCell" class="diff-td diff-line-num old_line empty-cell"></div> - <div 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_content with-coverage parallel right-side empty-cell"></div> + <div + data-testid="rightEmptyCell" + class="diff-td diff-line-num old_line empty-cell" + :class="emptyCellRightClassMap" + ></div> + <div + v-if="inline" + class="diff-td diff-line-num old_line empty-cell" + :class="emptyCellRightClassMap" + ></div> + <div + class="diff-td line-coverage right-side empty-cell" + :class="emptyCellRightClassMap" + ></div> + <div + class="diff-td line_content with-coverage right-side empty-cell" + :class="[emptyCellRightClassMap, { parallel: !inline }]" + ></div> </template> </div> </div> |