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.vue69
-rw-r--r--app/assets/javascripts/diffs/components/commit_item.vue51
-rw-r--r--app/assets/javascripts/diffs/components/commit_widget.vue9
-rw-r--r--app/assets/javascripts/diffs/components/compare_versions.vue9
-rw-r--r--app/assets/javascripts/diffs/components/diff_content.vue2
-rw-r--r--app/assets/javascripts/diffs/components/diff_expansion_cell.vue2
-rw-r--r--app/assets/javascripts/diffs/components/diff_file.vue24
-rw-r--r--app/assets/javascripts/diffs/components/diff_line_note_form.vue4
-rw-r--r--app/assets/javascripts/diffs/components/diff_stats.vue13
-rw-r--r--app/assets/javascripts/diffs/components/diff_table_cell.vue51
-rw-r--r--app/assets/javascripts/diffs/components/hidden_files_warning.vue2
11 files changed, 190 insertions, 46 deletions
diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue
index 1e524882d5f..5062006424e 100644
--- a/app/assets/javascripts/diffs/components/app.vue
+++ b/app/assets/javascripts/diffs/components/app.vue
@@ -1,9 +1,10 @@
<script>
import { mapState, mapGetters, mapActions } from 'vuex';
-import { GlLoadingIcon, GlButtonGroup, GlButton } from '@gitlab/ui';
+import { GlLoadingIcon, GlButtonGroup, GlButton, GlAlert } from '@gitlab/ui';
import Mousetrap from 'mousetrap';
import { __ } from '~/locale';
-import createFlash from '~/flash';
+import { getParameterByName, parseBoolean } from '~/lib/utils/common_utils';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
import PanelResizer from '~/vue_shared/components/panel_resizer.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { isSingleViewStyle } from '~/helpers/diffs_helper';
@@ -38,6 +39,7 @@ export default {
PanelResizer,
GlButtonGroup,
GlButton,
+ GlAlert,
},
mixins: [glFeatureFlagsMixin()],
props: {
@@ -127,7 +129,16 @@ export default {
emailPatchPath: state => state.diffs.emailPatchPath,
retrievingBatches: state => state.diffs.retrievingBatches,
}),
- ...mapState('diffs', ['showTreeList', 'isLoading', 'startVersion', 'currentDiffFileId']),
+ ...mapState('diffs', [
+ 'showTreeList',
+ 'isLoading',
+ 'startVersion',
+ 'currentDiffFileId',
+ 'isTreeLoaded',
+ 'conflictResolutionPath',
+ 'canMerge',
+ 'hasConflicts',
+ ]),
...mapGetters('diffs', ['isParallelView', 'currentDiffIndex']),
...mapGetters(['isNotesFetched', 'getNoteableData']),
diffs() {
@@ -155,6 +166,9 @@ export default {
isLimitedContainer() {
return !this.showTreeList && !this.isParallelView && !this.isFluidLayout;
},
+ isDiffHead() {
+ return parseBoolean(getParameterByName('diff_head'));
+ },
},
watch: {
commit(newCommit, oldCommit) {
@@ -400,12 +414,12 @@ export default {
<template>
<div v-show="shouldShow">
- <div v-if="isLoading" class="loading"><gl-loading-icon size="lg" /></div>
+ <div v-if="isLoading || !isTreeLoaded" class="loading"><gl-loading-icon size="lg" /></div>
<div v-else id="diffs" :class="{ active: shouldShow }" class="diffs tab-pane">
<compare-versions
:merge-request-diffs="mergeRequestDiffs"
:is-limited-container="isLimitedContainer"
- :diff-files-length="diffFilesLength"
+ :diff-files-count-text="numTotalFiles"
/>
<hidden-files-warning
@@ -417,6 +431,49 @@ export default {
/>
<div
+ v-if="isDiffHead && hasConflicts"
+ :class="{
+ [CENTERED_LIMITED_CONTAINER_CLASSES]: isLimitedContainer,
+ }"
+ >
+ <gl-alert
+ :dismissible="false"
+ :title="__('There are merge conflicts')"
+ variant="warning"
+ class="w-100 mb-3"
+ >
+ <p class="mb-1">
+ {{ __('The comparison view may be inaccurate due to merge conflicts.') }}
+ </p>
+ <p class="mb-0">
+ {{
+ __(
+ 'Resolve these conflicts or ask someone with write access to this repository to merge it locally.',
+ )
+ }}
+ </p>
+ <template #actions>
+ <gl-button
+ v-if="conflictResolutionPath"
+ :href="conflictResolutionPath"
+ variant="info"
+ class="mr-3 gl-alert-action"
+ >
+ {{ __('Resolve conflicts') }}
+ </gl-button>
+ <gl-button
+ v-if="canMerge"
+ class="gl-alert-action"
+ data-toggle="modal"
+ data-target="#modal_merge_info"
+ >
+ {{ __('Merge locally') }}
+ </gl-button>
+ </template>
+ </gl-alert>
+ </div>
+
+ <div
:data-can-create-note="getNoteableData.current_user.can_create_note"
class="files d-flex"
>
@@ -441,7 +498,7 @@ export default {
[CENTERED_LIMITED_CONTAINER_CLASSES]: isLimitedContainer,
}"
>
- <commit-widget v-if="commit" :commit="commit" />
+ <commit-widget v-if="commit" :commit="commit" :collapsible="false" />
<div v-if="isBatchLoading" class="loading"><gl-loading-icon size="lg" /></div>
<template v-else-if="renderDiffFiles">
<diff-file
diff --git a/app/assets/javascripts/diffs/components/commit_item.vue b/app/assets/javascripts/diffs/components/commit_item.vue
index 99bc1b5c040..274a4027e62 100644
--- a/app/assets/javascripts/diffs/components/commit_item.vue
+++ b/app/assets/javascripts/diffs/components/commit_item.vue
@@ -52,10 +52,25 @@ export default {
},
mixins: [glFeatureFlagsMixin()],
props: {
+ isSelectable: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
commit: {
type: Object,
required: true,
},
+ checked: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ collapsible: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
},
computed: {
author() {
@@ -78,6 +93,10 @@ export default {
authorAvatar() {
return this.author.avatar_url || this.commit.author_gravatar_url;
},
+ commitDescription() {
+ // Strip the newline at the beginning
+ return this.commit.description_html.replace(/^&#x000A;/, '');
+ },
nextCommitUrl() {
return this.commit.next_commit_id
? setUrlParams({ commit_id: this.commit.next_commit_id })
@@ -104,14 +123,23 @@ export default {
</script>
<template>
- <li class="commit flex-row js-toggle-container">
- <user-avatar-link
- :link-href="authorUrl"
- :img-src="authorAvatar"
- :img-alt="authorName"
- :img-size="40"
- class="avatar-cell d-none d-sm-block"
- />
+ <li :class="{ 'js-toggle-container': collapsible }" class="commit flex-row">
+ <div class="d-flex align-items-center align-self-start">
+ <input
+ v-if="isSelectable"
+ class="mr-2"
+ type="checkbox"
+ :checked="checked"
+ @change="$emit('handleCheckboxChange', $event.target.checked)"
+ />
+ <user-avatar-link
+ :link-href="authorUrl"
+ :img-src="authorAvatar"
+ :img-alt="authorName"
+ :img-size="40"
+ class="avatar-cell d-none d-sm-block"
+ />
+ </div>
<div class="commit-detail flex-list">
<div class="commit-content qa-commit-content">
<a
@@ -123,7 +151,7 @@ export default {
<span class="commit-row-message d-block d-sm-none">&middot; {{ commit.short_id }}</span>
<button
- v-if="commit.description_html"
+ v-if="commit.description_html && collapsible"
class="text-expander js-toggle-button"
type="button"
:aria-label="__('Toggle commit description')"
@@ -144,8 +172,9 @@ export default {
<pre
v-if="commit.description_html"
- class="commit-row-description js-toggle-content gl-mb-3"
- v-html="commit.description_html"
+ :class="{ 'js-toggle-content': collapsible, 'd-block': !collapsible }"
+ class="commit-row-description gl-mb-3 text-dark"
+ v-html="commitDescription"
></pre>
</div>
<div class="commit-actions flex-row d-none d-sm-flex">
diff --git a/app/assets/javascripts/diffs/components/commit_widget.vue b/app/assets/javascripts/diffs/components/commit_widget.vue
index 31ed003cc0f..5c7e84bd87c 100644
--- a/app/assets/javascripts/diffs/components/commit_widget.vue
+++ b/app/assets/javascripts/diffs/components/commit_widget.vue
@@ -23,15 +23,20 @@ export default {
type: Object,
required: true,
},
+ collapsible: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
},
};
</script>
<template>
- <div class="info-well w-100">
+ <div class="info-well mw-100 mx-0">
<div class="well-segment">
<ul class="blob-commit-info">
- <commit-item :commit="commit" />
+ <commit-item :commit="commit" :collapsible="collapsible" />
</ul>
</div>
</div>
diff --git a/app/assets/javascripts/diffs/components/compare_versions.vue b/app/assets/javascripts/diffs/components/compare_versions.vue
index 6f6fa312865..35e4527af69 100644
--- a/app/assets/javascripts/diffs/components/compare_versions.vue
+++ b/app/assets/javascripts/diffs/components/compare_versions.vue
@@ -32,9 +32,10 @@ export default {
required: false,
default: false,
},
- diffFilesLength: {
- type: Number,
- required: true,
+ diffFilesCountText: {
+ type: String,
+ required: false,
+ default: null,
},
},
computed: {
@@ -119,7 +120,7 @@ export default {
</div>
<div class="inline-parallel-buttons d-none d-md-flex ml-auto">
<diff-stats
- :diff-files-length="diffFilesLength"
+ :diff-files-count-text="diffFilesCountText"
:added-lines="addedLines"
:removed-lines="removedLines"
/>
diff --git a/app/assets/javascripts/diffs/components/diff_content.vue b/app/assets/javascripts/diffs/components/diff_content.vue
index 741462a849c..087a558efdc 100644
--- a/app/assets/javascripts/diffs/components/diff_content.vue
+++ b/app/assets/javascripts/diffs/components/diff_content.vue
@@ -147,7 +147,7 @@ export default {
slot="image-overlay"
:discussions="imageDiscussions"
:file-hash="diffFileHash"
- :can-comment="getNoteableData.current_user.can_create_note"
+ :can-comment="getNoteableData.current_user.can_create_note && !diffFile.brokenSymlink"
/>
<div v-if="showNotesContainer" class="note-container">
<user-avatar-link
diff --git a/app/assets/javascripts/diffs/components/diff_expansion_cell.vue b/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
index 46ed76450c4..e5e63bdcb43 100644
--- a/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
+++ b/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
@@ -1,6 +1,6 @@
<script>
import { mapState, mapActions } from 'vuex';
-import createFlash from '~/flash';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
import { s__ } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
import { UNFOLD_COUNT, INLINE_DIFF_VIEW_TYPE, PARALLEL_DIFF_VIEW_TYPE } from '../constants';
diff --git a/app/assets/javascripts/diffs/components/diff_file.vue b/app/assets/javascripts/diffs/components/diff_file.vue
index 00d36c0b978..eace673c2d7 100644
--- a/app/assets/javascripts/diffs/components/diff_file.vue
+++ b/app/assets/javascripts/diffs/components/diff_file.vue
@@ -2,8 +2,9 @@
import { mapActions, mapGetters, mapState } from 'vuex';
import { escape } from 'lodash';
import { GlLoadingIcon } from '@gitlab/ui';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { __, sprintf } from '~/locale';
-import createFlash from '~/flash';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
import { hasDiff } from '~/helpers/diffs_helper';
import eventHub from '../../notes/event_hub';
import DiffFileHeader from './diff_file_header.vue';
@@ -16,6 +17,7 @@ export default {
DiffContent,
GlLoadingIcon,
},
+ mixins: [glFeatureFlagsMixin()],
props: {
file: {
type: Object,
@@ -89,8 +91,25 @@ export default {
this.setFileCollapsed({ filePath: this.file.file_path, collapsed: newVal });
},
+ 'file.file_hash': {
+ handler: function watchFileHash() {
+ if (
+ this.glFeatures.autoExpandCollapsedDiffs &&
+ this.viewDiffsFileByFile &&
+ this.file.viewer.collapsed
+ ) {
+ this.isCollapsed = false;
+ this.handleLoadCollapsedDiff();
+ } else {
+ this.isCollapsed = this.file.viewer.collapsed || false;
+ }
+ },
+ immediate: true,
+ },
'file.viewer.collapsed': function setIsCollapsed(newVal) {
- this.isCollapsed = newVal;
+ if (!this.viewDiffsFileByFile && !this.glFeatures.autoExpandCollapsedDiffs) {
+ this.isCollapsed = newVal;
+ }
},
},
created() {
@@ -148,6 +167,7 @@ export default {
:id="file.file_hash"
:class="{
'is-active': currentDiffFileId === file.file_hash,
+ 'comments-disabled': Boolean(file.brokenSymlink),
}"
:data-path="file.new_path"
class="diff-file file-holder"
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 d2f49bd0020..700e6302102 100644
--- a/app/assets/javascripts/diffs/components/diff_line_note_form.vue
+++ b/app/assets/javascripts/diffs/components/diff_line_note_form.vue
@@ -148,7 +148,7 @@ export default {
<template>
<div class="content discussion-form discussion-form-container discussion-notes">
- <div v-if="glFeatures.multilineComments" class="gl-mb-3 gl-text-gray-700 gl-pb-3">
+ <div v-if="glFeatures.multilineComments" class="gl-mb-3 gl-text-gray-500 gl-pb-3">
<multiline-comment-form
v-model="commentLineStart"
:line="line"
@@ -172,7 +172,7 @@ export default {
:diff-file="diffFile"
:show-suggest-popover="showSuggestPopover"
save-button-title="Comment"
- class="diff-comment-form prepend-top-10"
+ class="diff-comment-form gl-mt-3"
@handleFormUpdateAddToReview="addToReview"
@cancelForm="handleCancelCommentForm"
@handleFormUpdate="handleSaveNote"
diff --git a/app/assets/javascripts/diffs/components/diff_stats.vue b/app/assets/javascripts/diffs/components/diff_stats.vue
index 0234fc4f40e..439d8097e56 100644
--- a/app/assets/javascripts/diffs/components/diff_stats.vue
+++ b/app/assets/javascripts/diffs/components/diff_stats.vue
@@ -1,7 +1,7 @@
<script>
+import { isNumber } from 'lodash';
import Icon from '~/vue_shared/components/icon.vue';
import { n__ } from '~/locale';
-import { isNumber } from 'lodash';
export default {
components: { Icon },
@@ -14,18 +14,21 @@ export default {
type: Number,
required: true,
},
- diffFilesLength: {
- type: Number,
+ diffFilesCountText: {
+ type: String,
required: false,
default: null,
},
},
computed: {
+ diffFilesLength() {
+ return parseInt(this.diffFilesCountText, 10);
+ },
filesText() {
return n__('file', 'files', this.diffFilesLength);
},
isCompareVersionsHeader() {
- return Boolean(this.diffFilesLength);
+ return Boolean(this.diffFilesCountText);
},
hasDiffFiles() {
return isNumber(this.diffFilesLength) && this.diffFilesLength >= 0;
@@ -44,7 +47,7 @@ export default {
>
<div v-if="hasDiffFiles" class="diff-stats-group">
<icon name="doc-code" class="diff-stats-icon text-secondary" />
- <span class="text-secondary bold">{{ diffFilesLength }} {{ filesText }}</span>
+ <span class="text-secondary bold">{{ diffFilesCountText }} {{ filesText }}</span>
</div>
<div
class="diff-stats-group cgreen d-flex align-items-center"
diff --git a/app/assets/javascripts/diffs/components/diff_table_cell.vue b/app/assets/javascripts/diffs/components/diff_table_cell.vue
index 198113e330a..49982a81372 100644
--- a/app/assets/javascripts/diffs/components/diff_table_cell.vue
+++ b/app/assets/javascripts/diffs/components/diff_table_cell.vue
@@ -1,8 +1,9 @@
<script>
import { mapGetters, mapActions } from 'vuex';
-import { GlIcon } from '@gitlab/ui';
+import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
import { getParameterByName, parseBoolean } from '~/lib/utils/common_utils';
import DiffGutterAvatars from './diff_gutter_avatars.vue';
+import { __ } from '~/locale';
import {
CONTEXT_LINE_TYPE,
LINE_POSITION_RIGHT,
@@ -18,6 +19,9 @@ export default {
DiffGutterAvatars,
GlIcon,
},
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
props: {
line: {
type: Object,
@@ -123,6 +127,24 @@ export default {
lineNumber() {
return this.lineType === OLD_LINE_TYPE ? this.line.old_line : this.line.new_line;
},
+ addCommentTooltip() {
+ const brokenSymlinks = this.line.commentsDisabled;
+ let tooltip = __('Add a comment to this line');
+
+ if (brokenSymlinks) {
+ if (brokenSymlinks.wasSymbolic || brokenSymlinks.isSymbolic) {
+ tooltip = __(
+ 'Commenting on symbolic links that replace or are replaced by files is currently not supported.',
+ );
+ } else if (brokenSymlinks.wasReal || brokenSymlinks.isReal) {
+ tooltip = __(
+ 'Commenting on files that replace or are replaced by symbolic links is currently not supported.',
+ );
+ }
+ }
+
+ return tooltip;
+ },
},
mounted() {
this.unwatchShouldShowCommentButton = this.$watch('shouldShowCommentButton', newVal => {
@@ -146,17 +168,24 @@ export default {
<template>
<td ref="td" :class="classNameMap">
- <button
- v-if="shouldRenderCommentButton"
- v-show="shouldShowCommentButton"
- ref="addDiffNoteButton"
- type="button"
- class="add-diff-note js-add-diff-note-button qa-diff-comment"
- title="Add a comment to this line"
- @click="handleCommentButton"
+ <span
+ ref="addNoteTooltip"
+ v-gl-tooltip
+ class="add-diff-note tooltip-wrapper"
+ :title="addCommentTooltip"
>
- <gl-icon :size="12" name="comment" />
- </button>
+ <button
+ v-if="shouldRenderCommentButton"
+ v-show="shouldShowCommentButton"
+ ref="addDiffNoteButton"
+ type="button"
+ class="add-diff-note note-button js-add-diff-note-button qa-diff-comment"
+ :disabled="line.commentsDisabled"
+ @click="handleCommentButton"
+ >
+ <gl-icon :size="12" name="comment" />
+ </button>
+ </span>
<a
v-if="lineNumber"
ref="lineNumberRef"
diff --git a/app/assets/javascripts/diffs/components/hidden_files_warning.vue b/app/assets/javascripts/diffs/components/hidden_files_warning.vue
index ad0ca4fa402..baf7471582a 100644
--- a/app/assets/javascripts/diffs/components/hidden_files_warning.vue
+++ b/app/assets/javascripts/diffs/components/hidden_files_warning.vue
@@ -26,7 +26,7 @@ export default {
<div class="alert alert-warning">
<h4>
{{ __('Too many changes to show.') }}
- <div class="pull-right">
+ <div class="float-right">
<a :href="plainDiffPath" class="btn btn-sm"> {{ __('Plain diff') }} </a>
<a :href="emailPatchPath" class="btn btn-sm"> {{ __('Email patch') }} </a>
</div>