2018-06-21 08:22:40 -04:00
|
|
|
<script>
|
|
|
|
import { mapState, mapGetters, mapActions } from 'vuex';
|
2020-08-20 11:10:18 -04:00
|
|
|
import { GlLoadingIcon, GlButton, GlAlert, GlPagination, GlSprintf } from '@gitlab/ui';
|
2019-12-09 07:07:58 -05:00
|
|
|
import Mousetrap from 'mousetrap';
|
2018-06-21 08:22:40 -04:00
|
|
|
import { __ } from '~/locale';
|
2020-08-17 08:10:12 -04:00
|
|
|
import { getParameterByName, parseBoolean } from '~/lib/utils/common_utils';
|
2020-08-20 05:09:55 -04:00
|
|
|
import { deprecatedCreateFlash as createFlash } from '~/flash';
|
2019-02-15 05:25:33 -05:00
|
|
|
import PanelResizer from '~/vue_shared/components/panel_resizer.vue';
|
2019-12-09 07:07:58 -05:00
|
|
|
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
2020-01-14 07:07:41 -05:00
|
|
|
import { isSingleViewStyle } from '~/helpers/diffs_helper';
|
2020-04-27 17:10:10 -04:00
|
|
|
import { updateHistory } from '~/lib/utils/url_utility';
|
2018-06-29 03:22:07 -04:00
|
|
|
import eventHub from '../../notes/event_hub';
|
2018-06-21 08:22:40 -04:00
|
|
|
import CompareVersions from './compare_versions.vue';
|
|
|
|
import DiffFile from './diff_file.vue';
|
|
|
|
import NoChanges from './no_changes.vue';
|
|
|
|
import HiddenFilesWarning from './hidden_files_warning.vue';
|
2018-09-26 04:28:50 -04:00
|
|
|
import CommitWidget from './commit_widget.vue';
|
2018-10-03 05:05:43 -04:00
|
|
|
import TreeList from './tree_list.vue';
|
2019-02-15 05:25:33 -05:00
|
|
|
import {
|
|
|
|
TREE_LIST_WIDTH_STORAGE_KEY,
|
|
|
|
INITIAL_TREE_WIDTH,
|
|
|
|
MIN_TREE_WIDTH,
|
|
|
|
MAX_TREE_WIDTH,
|
|
|
|
TREE_HIDE_STATS_WIDTH,
|
2019-03-19 07:34:21 -04:00
|
|
|
MR_TREE_SHOW_KEY,
|
2019-03-28 17:37:06 -04:00
|
|
|
CENTERED_LIMITED_CONTAINER_CLASSES,
|
2019-02-15 05:25:33 -05:00
|
|
|
} from '../constants';
|
2018-06-21 08:22:40 -04:00
|
|
|
|
|
|
|
export default {
|
|
|
|
name: 'DiffsApp',
|
|
|
|
components: {
|
|
|
|
CompareVersions,
|
|
|
|
DiffFile,
|
|
|
|
NoChanges,
|
|
|
|
HiddenFilesWarning,
|
2018-09-26 04:28:50 -04:00
|
|
|
CommitWidget,
|
2018-10-03 05:05:43 -04:00
|
|
|
TreeList,
|
2018-11-07 05:06:15 -05:00
|
|
|
GlLoadingIcon,
|
2019-02-15 05:25:33 -05:00
|
|
|
PanelResizer,
|
2020-08-20 11:10:18 -04:00
|
|
|
GlPagination,
|
2020-07-15 02:09:35 -04:00
|
|
|
GlButton,
|
2020-08-17 08:10:12 -04:00
|
|
|
GlAlert,
|
2020-08-20 11:10:18 -04:00
|
|
|
GlSprintf,
|
2018-06-21 08:22:40 -04:00
|
|
|
},
|
2019-11-26 04:08:36 -05:00
|
|
|
mixins: [glFeatureFlagsMixin()],
|
2018-06-21 08:22:40 -04:00
|
|
|
props: {
|
|
|
|
endpoint: {
|
|
|
|
type: String,
|
|
|
|
required: true,
|
|
|
|
},
|
2019-11-26 04:08:36 -05:00
|
|
|
endpointMetadata: {
|
|
|
|
type: String,
|
|
|
|
required: true,
|
|
|
|
},
|
|
|
|
endpointBatch: {
|
|
|
|
type: String,
|
|
|
|
required: true,
|
|
|
|
},
|
2020-03-17 14:09:44 -04:00
|
|
|
endpointCoverage: {
|
|
|
|
type: String,
|
|
|
|
required: false,
|
|
|
|
default: '',
|
|
|
|
},
|
2018-06-26 14:49:22 -04:00
|
|
|
projectPath: {
|
|
|
|
type: String,
|
|
|
|
required: true,
|
|
|
|
},
|
2018-06-21 08:22:40 -04:00
|
|
|
shouldShow: {
|
|
|
|
type: Boolean,
|
|
|
|
required: false,
|
|
|
|
default: false,
|
|
|
|
},
|
|
|
|
currentUser: {
|
|
|
|
type: Object,
|
|
|
|
required: true,
|
|
|
|
},
|
2018-12-13 14:17:19 -05:00
|
|
|
helpPagePath: {
|
|
|
|
type: String,
|
|
|
|
required: false,
|
|
|
|
default: '',
|
|
|
|
},
|
2018-12-13 05:57:45 -05:00
|
|
|
changesEmptyStateIllustration: {
|
|
|
|
type: String,
|
|
|
|
required: false,
|
|
|
|
default: '',
|
|
|
|
},
|
2019-04-12 04:32:05 -04:00
|
|
|
isFluidLayout: {
|
|
|
|
type: Boolean,
|
|
|
|
required: false,
|
|
|
|
default: false,
|
|
|
|
},
|
2019-06-14 09:01:24 -04:00
|
|
|
dismissEndpoint: {
|
|
|
|
type: String,
|
|
|
|
required: false,
|
|
|
|
default: '',
|
|
|
|
},
|
|
|
|
showSuggestPopover: {
|
|
|
|
type: Boolean,
|
|
|
|
required: false,
|
|
|
|
default: false,
|
|
|
|
},
|
2020-07-15 02:09:35 -04:00
|
|
|
viewDiffsFileByFile: {
|
|
|
|
type: Boolean,
|
|
|
|
required: false,
|
|
|
|
default: false,
|
|
|
|
},
|
2018-06-21 08:22:40 -04:00
|
|
|
},
|
2018-10-19 09:09:16 -04:00
|
|
|
data() {
|
2019-02-15 05:25:33 -05:00
|
|
|
const treeWidth =
|
|
|
|
parseInt(localStorage.getItem(TREE_LIST_WIDTH_STORAGE_KEY), 10) || INITIAL_TREE_WIDTH;
|
|
|
|
|
2018-10-19 09:09:16 -04:00
|
|
|
return {
|
2019-02-15 05:25:33 -05:00
|
|
|
treeWidth,
|
2020-01-14 16:07:45 -05:00
|
|
|
diffFilesLength: 0,
|
2018-10-19 09:09:16 -04:00
|
|
|
};
|
|
|
|
},
|
2018-06-21 08:22:40 -04:00
|
|
|
computed: {
|
|
|
|
...mapState({
|
|
|
|
isLoading: state => state.diffs.isLoading,
|
2019-11-26 04:08:36 -05:00
|
|
|
isBatchLoading: state => state.diffs.isBatchLoading,
|
2018-06-21 08:22:40 -04:00
|
|
|
diffFiles: state => state.diffs.diffFiles,
|
|
|
|
diffViewType: state => state.diffs.diffViewType,
|
|
|
|
mergeRequestDiffs: state => state.diffs.mergeRequestDiffs,
|
|
|
|
mergeRequestDiff: state => state.diffs.mergeRequestDiff,
|
|
|
|
commit: state => state.diffs.commit,
|
|
|
|
renderOverflowWarning: state => state.diffs.renderOverflowWarning,
|
|
|
|
numTotalFiles: state => state.diffs.realSize,
|
|
|
|
numVisibleFiles: state => state.diffs.size,
|
|
|
|
plainDiffPath: state => state.diffs.plainDiffPath,
|
|
|
|
emailPatchPath: state => state.diffs.emailPatchPath,
|
2019-12-19 07:07:35 -05:00
|
|
|
retrievingBatches: state => state.diffs.retrievingBatches,
|
2018-06-21 08:22:40 -04:00
|
|
|
}),
|
2020-07-30 11:09:40 -04:00
|
|
|
...mapState('diffs', [
|
|
|
|
'showTreeList',
|
|
|
|
'isLoading',
|
|
|
|
'startVersion',
|
|
|
|
'currentDiffFileId',
|
|
|
|
'isTreeLoaded',
|
2020-08-17 08:10:12 -04:00
|
|
|
'conflictResolutionPath',
|
|
|
|
'canMerge',
|
|
|
|
'hasConflicts',
|
2020-07-30 11:09:40 -04:00
|
|
|
]),
|
2019-02-27 04:12:13 -05:00
|
|
|
...mapGetters('diffs', ['isParallelView', 'currentDiffIndex']),
|
2018-10-19 09:09:16 -04:00
|
|
|
...mapGetters(['isNotesFetched', 'getNoteableData']),
|
2020-07-15 02:09:35 -04:00
|
|
|
diffs() {
|
|
|
|
if (!this.viewDiffsFileByFile) {
|
|
|
|
return this.diffFiles;
|
|
|
|
}
|
|
|
|
|
|
|
|
return this.diffFiles.filter((file, i) => {
|
|
|
|
return file.file_hash === this.currentDiffFileId || (i === 0 && !this.currentDiffFileId);
|
|
|
|
});
|
|
|
|
},
|
2018-07-17 11:47:02 -04:00
|
|
|
canCurrentUserFork() {
|
2018-11-09 14:48:41 -05:00
|
|
|
return this.currentUser.can_fork === true && this.currentUser.can_create_merge_request;
|
2018-07-17 11:47:02 -04:00
|
|
|
},
|
2018-12-13 05:57:45 -05:00
|
|
|
renderDiffFiles() {
|
|
|
|
return (
|
|
|
|
this.diffFiles.length > 0 ||
|
|
|
|
(this.startVersion &&
|
|
|
|
this.startVersion.version_index === this.mergeRequestDiff.version_index)
|
|
|
|
);
|
|
|
|
},
|
2019-02-15 05:25:33 -05:00
|
|
|
hideFileStats() {
|
|
|
|
return this.treeWidth <= TREE_HIDE_STATS_WIDTH;
|
|
|
|
},
|
2019-03-28 17:37:06 -04:00
|
|
|
isLimitedContainer() {
|
2019-04-12 04:32:05 -04:00
|
|
|
return !this.showTreeList && !this.isParallelView && !this.isFluidLayout;
|
2019-03-28 17:37:06 -04:00
|
|
|
},
|
2020-08-17 08:10:12 -04:00
|
|
|
isDiffHead() {
|
|
|
|
return parseBoolean(getParameterByName('diff_head'));
|
|
|
|
},
|
2020-08-20 11:10:18 -04:00
|
|
|
showFileByFileNavigation() {
|
|
|
|
return this.diffFiles.length > 1 && this.viewDiffsFileByFile;
|
|
|
|
},
|
|
|
|
currentFileNumber() {
|
|
|
|
return this.currentDiffIndex + 1;
|
|
|
|
},
|
|
|
|
previousFileNumber() {
|
|
|
|
const { currentDiffIndex } = this;
|
|
|
|
|
|
|
|
return currentDiffIndex >= 1 ? currentDiffIndex : null;
|
|
|
|
},
|
|
|
|
nextFileNumber() {
|
|
|
|
const { currentFileNumber, diffFiles } = this;
|
|
|
|
|
|
|
|
return currentFileNumber < diffFiles.length ? currentFileNumber + 1 : null;
|
|
|
|
},
|
2018-06-21 08:22:40 -04:00
|
|
|
},
|
|
|
|
watch: {
|
2020-04-27 17:10:10 -04:00
|
|
|
commit(newCommit, oldCommit) {
|
|
|
|
const commitChangedAfterRender = newCommit && !this.isLoading;
|
|
|
|
const commitIsDifferent = oldCommit && newCommit.id !== oldCommit.id;
|
|
|
|
const url = window?.location ? String(window.location) : '';
|
|
|
|
|
|
|
|
if (commitChangedAfterRender && commitIsDifferent) {
|
|
|
|
updateHistory({
|
|
|
|
title: document.title,
|
|
|
|
url: url.replace(oldCommit.id, newCommit.id),
|
|
|
|
});
|
|
|
|
this.refetchDiffData();
|
|
|
|
this.adjustView();
|
|
|
|
}
|
|
|
|
},
|
2018-06-21 08:22:40 -04:00
|
|
|
diffViewType() {
|
2020-08-26 08:10:53 -04:00
|
|
|
if (!this.glFeatures.unifiedDiffLines && (this.needsReload() || this.needsFirstLoad())) {
|
2020-01-14 07:07:41 -05:00
|
|
|
this.refetchDiffData();
|
|
|
|
}
|
2018-06-21 08:22:40 -04:00
|
|
|
this.adjustView();
|
|
|
|
},
|
|
|
|
shouldShow() {
|
2018-06-29 03:22:07 -04:00
|
|
|
// When the shouldShow property changed to true, the route is rendered for the first time
|
|
|
|
// and if we have the isLoading as true this means we didn't fetch the data
|
|
|
|
if (this.isLoading) {
|
|
|
|
this.fetchData();
|
|
|
|
}
|
|
|
|
|
2018-06-21 08:22:40 -04:00
|
|
|
this.adjustView();
|
|
|
|
},
|
2018-10-03 05:05:43 -04:00
|
|
|
isLoading: 'adjustView',
|
|
|
|
showTreeList: 'adjustView',
|
2018-06-21 08:22:40 -04:00
|
|
|
},
|
|
|
|
mounted() {
|
2019-06-14 09:01:24 -04:00
|
|
|
this.setBaseConfig({
|
|
|
|
endpoint: this.endpoint,
|
2019-11-26 04:08:36 -05:00
|
|
|
endpointMetadata: this.endpointMetadata,
|
|
|
|
endpointBatch: this.endpointBatch,
|
2020-03-17 14:09:44 -04:00
|
|
|
endpointCoverage: this.endpointCoverage,
|
2019-06-14 09:01:24 -04:00
|
|
|
projectPath: this.projectPath,
|
|
|
|
dismissEndpoint: this.dismissEndpoint,
|
|
|
|
showSuggestPopover: this.showSuggestPopover,
|
2020-07-15 02:09:35 -04:00
|
|
|
viewDiffsFileByFile: this.viewDiffsFileByFile,
|
2019-06-14 09:01:24 -04:00
|
|
|
});
|
2018-06-29 03:22:07 -04:00
|
|
|
|
|
|
|
if (this.shouldShow) {
|
|
|
|
this.fetchData();
|
|
|
|
}
|
2018-11-30 03:48:47 -05:00
|
|
|
|
2020-07-15 02:09:35 -04:00
|
|
|
const id = window?.location?.hash;
|
2018-11-30 03:48:47 -05:00
|
|
|
|
2020-07-15 02:09:35 -04:00
|
|
|
if (id && id.indexOf('#note') !== 0) {
|
|
|
|
this.setHighlightedRow(
|
|
|
|
id
|
|
|
|
.split('diff-content')
|
|
|
|
.pop()
|
|
|
|
.slice(1),
|
|
|
|
);
|
2018-11-30 03:48:47 -05:00
|
|
|
}
|
2018-06-21 08:22:40 -04:00
|
|
|
},
|
|
|
|
created() {
|
|
|
|
this.adjustView();
|
2019-01-16 10:17:10 -05:00
|
|
|
eventHub.$once('fetchDiffData', this.fetchData);
|
2019-05-10 14:06:37 -04:00
|
|
|
eventHub.$on('refetchDiffData', this.refetchDiffData);
|
2019-03-28 17:37:06 -04:00
|
|
|
this.CENTERED_LIMITED_CONTAINER_CLASSES = CENTERED_LIMITED_CONTAINER_CLASSES;
|
2019-12-19 07:07:35 -05:00
|
|
|
|
|
|
|
this.unwatchDiscussions = this.$watch(
|
|
|
|
() => `${this.diffFiles.length}:${this.$store.state.notes.discussions.length}`,
|
|
|
|
() => this.setDiscussions(),
|
|
|
|
);
|
2020-01-14 22:08:55 -05:00
|
|
|
|
|
|
|
this.unwatchRetrievingBatches = this.$watch(
|
|
|
|
() => `${this.retrievingBatches}:${this.$store.state.notes.discussions.length}`,
|
|
|
|
() => {
|
|
|
|
if (!this.retrievingBatches && this.$store.state.notes.discussions.length) {
|
|
|
|
this.unwatchDiscussions();
|
|
|
|
this.unwatchRetrievingBatches();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
);
|
2019-01-16 10:17:10 -05:00
|
|
|
},
|
|
|
|
beforeDestroy() {
|
|
|
|
eventHub.$off('fetchDiffData', this.fetchData);
|
2019-05-10 14:06:37 -04:00
|
|
|
eventHub.$off('refetchDiffData', this.refetchDiffData);
|
2019-02-27 04:12:13 -05:00
|
|
|
this.removeEventListeners();
|
2018-06-21 08:22:40 -04:00
|
|
|
},
|
|
|
|
methods: {
|
2018-10-25 11:51:00 -04:00
|
|
|
...mapActions(['startTaskList']),
|
2018-08-13 04:47:54 -04:00
|
|
|
...mapActions('diffs', [
|
2020-05-13 14:08:47 -04:00
|
|
|
'moveToNeighboringCommit',
|
2018-08-13 04:47:54 -04:00
|
|
|
'setBaseConfig',
|
|
|
|
'fetchDiffFiles',
|
2019-11-26 04:08:36 -05:00
|
|
|
'fetchDiffFilesMeta',
|
|
|
|
'fetchDiffFilesBatch',
|
2020-03-17 14:09:44 -04:00
|
|
|
'fetchCoverageFiles',
|
2018-08-13 04:47:54 -04:00
|
|
|
'startRenderDiffsQueue',
|
|
|
|
'assignDiscussionsToDiff',
|
2018-11-30 03:48:47 -05:00
|
|
|
'setHighlightedRow',
|
2019-02-15 05:25:33 -05:00
|
|
|
'cacheTreeListWidth',
|
2019-02-27 04:12:13 -05:00
|
|
|
'scrollToFile',
|
2019-03-19 07:34:21 -04:00
|
|
|
'toggleShowTreeList',
|
2020-07-15 02:09:35 -04:00
|
|
|
'navigateToDiffFileIndex',
|
2018-08-13 04:47:54 -04:00
|
|
|
]),
|
2020-08-20 11:10:18 -04:00
|
|
|
navigateToDiffFileNumber(number) {
|
|
|
|
this.navigateToDiffFileIndex(number - 1);
|
|
|
|
},
|
2019-05-10 14:06:37 -04:00
|
|
|
refetchDiffData() {
|
|
|
|
this.fetchData(false);
|
|
|
|
},
|
2019-12-04 13:08:46 -05:00
|
|
|
startDiffRendering() {
|
|
|
|
requestIdleCallback(
|
|
|
|
() => {
|
|
|
|
this.startRenderDiffsQueue();
|
|
|
|
},
|
|
|
|
{ timeout: 1000 },
|
|
|
|
);
|
|
|
|
},
|
2020-01-14 07:07:41 -05:00
|
|
|
needsReload() {
|
2020-08-28 08:10:37 -04:00
|
|
|
return this.diffFiles.length && isSingleViewStyle(this.diffFiles[0]);
|
2020-01-14 07:07:41 -05:00
|
|
|
},
|
|
|
|
needsFirstLoad() {
|
2020-08-28 08:10:37 -04:00
|
|
|
return !this.diffFiles.length;
|
2020-01-14 07:07:41 -05:00
|
|
|
},
|
2019-05-10 14:06:37 -04:00
|
|
|
fetchData(toggleTree = true) {
|
2019-12-17 13:07:48 -05:00
|
|
|
if (this.glFeatures.diffsBatchLoad) {
|
2019-11-26 04:08:36 -05:00
|
|
|
this.fetchDiffFilesMeta()
|
2020-01-14 16:07:45 -05:00
|
|
|
.then(({ real_size }) => {
|
|
|
|
this.diffFilesLength = parseInt(real_size, 10);
|
2019-11-26 04:08:36 -05:00
|
|
|
if (toggleTree) this.hideTreeListIfJustOneFile();
|
2019-12-04 13:08:46 -05:00
|
|
|
|
|
|
|
this.startDiffRendering();
|
2019-11-26 04:08:36 -05:00
|
|
|
})
|
|
|
|
.catch(() => {
|
|
|
|
createFlash(__('Something went wrong on our end. Please try again!'));
|
|
|
|
});
|
2019-03-19 07:34:21 -04:00
|
|
|
|
2019-11-26 04:08:36 -05:00
|
|
|
this.fetchDiffFilesBatch()
|
2020-01-14 07:07:41 -05:00
|
|
|
.then(() => {
|
|
|
|
// Guarantee the discussions are assigned after the batch finishes.
|
|
|
|
// Just watching the length of the discussions or the diff files
|
|
|
|
// isn't enough, because with split diff loading, neither will
|
|
|
|
// change when loading the other half of the diff files.
|
|
|
|
this.setDiscussions();
|
|
|
|
})
|
2019-12-04 13:08:46 -05:00
|
|
|
.then(() => this.startDiffRendering())
|
2019-11-26 04:08:36 -05:00
|
|
|
.catch(() => {
|
|
|
|
createFlash(__('Something went wrong on our end. Please try again!'));
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
this.fetchDiffFiles()
|
2020-01-14 16:07:45 -05:00
|
|
|
.then(({ real_size }) => {
|
|
|
|
this.diffFilesLength = parseInt(real_size, 10);
|
2019-11-26 04:08:36 -05:00
|
|
|
if (toggleTree) {
|
|
|
|
this.hideTreeListIfJustOneFile();
|
|
|
|
}
|
|
|
|
|
|
|
|
requestIdleCallback(
|
|
|
|
() => {
|
2020-01-14 07:07:41 -05:00
|
|
|
this.setDiscussions();
|
2019-11-26 04:08:36 -05:00
|
|
|
this.startRenderDiffsQueue();
|
|
|
|
},
|
|
|
|
{ timeout: 1000 },
|
|
|
|
);
|
|
|
|
})
|
|
|
|
.catch(() => {
|
|
|
|
createFlash(__('Something went wrong on our end. Please try again!'));
|
|
|
|
});
|
|
|
|
}
|
2018-06-29 03:22:07 -04:00
|
|
|
|
2020-03-17 14:09:44 -04:00
|
|
|
if (this.endpointCoverage) {
|
|
|
|
this.fetchCoverageFiles();
|
|
|
|
}
|
|
|
|
|
2018-06-29 03:22:07 -04:00
|
|
|
if (!this.isNotesFetched) {
|
|
|
|
eventHub.$emit('fetchNotesData');
|
|
|
|
}
|
|
|
|
},
|
2018-09-05 04:28:49 -04:00
|
|
|
setDiscussions() {
|
2019-12-19 07:07:35 -05:00
|
|
|
requestIdleCallback(
|
|
|
|
() =>
|
|
|
|
this.assignDiscussionsToDiff()
|
|
|
|
.then(this.$nextTick)
|
|
|
|
.then(this.startTaskList),
|
|
|
|
{ timeout: 1000 },
|
|
|
|
);
|
2018-09-05 04:28:49 -04:00
|
|
|
},
|
2018-06-21 08:22:40 -04:00
|
|
|
adjustView() {
|
2018-10-03 05:05:43 -04:00
|
|
|
if (this.shouldShow) {
|
|
|
|
this.$nextTick(() => {
|
2019-02-27 04:12:13 -05:00
|
|
|
this.setEventListeners();
|
2018-10-03 05:05:43 -04:00
|
|
|
});
|
2019-02-27 04:12:13 -05:00
|
|
|
} else {
|
|
|
|
this.removeEventListeners();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
setEventListeners() {
|
|
|
|
Mousetrap.bind(['[', 'k', ']', 'j'], (e, combo) => {
|
|
|
|
switch (combo) {
|
|
|
|
case '[':
|
|
|
|
case 'k':
|
|
|
|
this.jumpToFile(-1);
|
|
|
|
break;
|
|
|
|
case ']':
|
|
|
|
case 'j':
|
|
|
|
this.jumpToFile(+1);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
});
|
2020-05-13 14:08:47 -04:00
|
|
|
|
|
|
|
if (this.commit && this.glFeatures.mrCommitNeighborNav) {
|
|
|
|
Mousetrap.bind('c', () => this.moveToNeighboringCommit({ direction: 'next' }));
|
|
|
|
Mousetrap.bind('x', () => this.moveToNeighboringCommit({ direction: 'previous' }));
|
|
|
|
}
|
2019-02-27 04:12:13 -05:00
|
|
|
},
|
|
|
|
removeEventListeners() {
|
|
|
|
Mousetrap.unbind(['[', 'k', ']', 'j']);
|
2020-05-13 14:08:47 -04:00
|
|
|
Mousetrap.unbind('c');
|
|
|
|
Mousetrap.unbind('x');
|
2019-02-27 04:12:13 -05:00
|
|
|
},
|
|
|
|
jumpToFile(step) {
|
|
|
|
const targetIndex = this.currentDiffIndex + step;
|
|
|
|
if (targetIndex >= 0 && targetIndex < this.diffFiles.length) {
|
|
|
|
this.scrollToFile(this.diffFiles[targetIndex].file_path);
|
2018-06-21 08:22:40 -04:00
|
|
|
}
|
|
|
|
},
|
2019-03-19 07:34:21 -04:00
|
|
|
hideTreeListIfJustOneFile() {
|
|
|
|
const storedTreeShow = localStorage.getItem(MR_TREE_SHOW_KEY);
|
|
|
|
|
|
|
|
if ((storedTreeShow === null && this.diffFiles.length <= 1) || storedTreeShow === 'false') {
|
|
|
|
this.toggleShowTreeList(false);
|
|
|
|
}
|
|
|
|
},
|
2018-06-21 08:22:40 -04:00
|
|
|
},
|
2019-02-15 05:25:33 -05:00
|
|
|
minTreeWidth: MIN_TREE_WIDTH,
|
|
|
|
maxTreeWidth: MAX_TREE_WIDTH,
|
2018-06-21 08:22:40 -04:00
|
|
|
};
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<template>
|
2018-06-30 09:17:46 -04:00
|
|
|
<div v-show="shouldShow">
|
2020-07-30 11:09:40 -04:00
|
|
|
<div v-if="isLoading || !isTreeLoaded" class="loading"><gl-loading-icon size="lg" /></div>
|
2018-11-16 15:07:38 -05:00
|
|
|
<div v-else id="diffs" :class="{ active: shouldShow }" class="diffs tab-pane">
|
2018-06-21 08:22:40 -04:00
|
|
|
<compare-versions
|
|
|
|
:merge-request-diffs="mergeRequestDiffs"
|
2019-03-28 17:37:06 -04:00
|
|
|
:is-limited-container="isLimitedContainer"
|
2020-07-28 02:09:53 -04:00
|
|
|
:diff-files-count-text="numTotalFiles"
|
2018-06-21 08:22:40 -04:00
|
|
|
/>
|
|
|
|
|
|
|
|
<hidden-files-warning
|
|
|
|
v-if="renderOverflowWarning"
|
|
|
|
:visible="numVisibleFiles"
|
|
|
|
:total="numTotalFiles"
|
|
|
|
:plain-diff-path="plainDiffPath"
|
|
|
|
:email-patch-path="emailPatchPath"
|
|
|
|
/>
|
|
|
|
|
2020-08-17 08:10:12 -04:00
|
|
|
<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>
|
|
|
|
|
2018-10-18 03:50:38 -04:00
|
|
|
<div
|
|
|
|
:data-can-create-note="getNoteableData.current_user.can_create_note"
|
2020-02-05 04:08:43 -05:00
|
|
|
class="files d-flex"
|
2018-10-18 03:50:38 -04:00
|
|
|
>
|
2019-02-15 05:25:33 -05:00
|
|
|
<div
|
2020-06-22 11:09:27 -04:00
|
|
|
v-if="showTreeList"
|
2019-02-15 05:25:33 -05:00
|
|
|
:style="{ width: `${treeWidth}px` }"
|
2019-08-12 21:20:15 -04:00
|
|
|
class="diff-tree-list js-diff-tree-list mr-3"
|
2019-02-15 05:25:33 -05:00
|
|
|
>
|
|
|
|
<panel-resizer
|
|
|
|
:size.sync="treeWidth"
|
|
|
|
:start-size="treeWidth"
|
|
|
|
:min-size="$options.minTreeWidth"
|
|
|
|
:max-size="$options.maxTreeWidth"
|
|
|
|
side="right"
|
|
|
|
@resize-end="cacheTreeListWidth"
|
|
|
|
/>
|
|
|
|
<tree-list :hide-file-stats="hideFileStats" />
|
|
|
|
</div>
|
2019-03-28 17:37:06 -04:00
|
|
|
<div
|
|
|
|
class="diff-files-holder"
|
|
|
|
:class="{
|
|
|
|
[CENTERED_LIMITED_CONTAINER_CLASSES]: isLimitedContainer,
|
|
|
|
}"
|
|
|
|
>
|
2020-07-20 05:09:22 -04:00
|
|
|
<commit-widget v-if="commit" :commit="commit" :collapsible="false" />
|
2020-03-06 10:08:05 -05:00
|
|
|
<div v-if="isBatchLoading" class="loading"><gl-loading-icon size="lg" /></div>
|
2019-11-26 04:08:36 -05:00
|
|
|
<template v-else-if="renderDiffFiles">
|
2018-11-20 07:37:57 -05:00
|
|
|
<diff-file
|
2020-07-15 02:09:35 -04:00
|
|
|
v-for="file in diffs"
|
2018-11-20 07:37:57 -05:00
|
|
|
:key="file.newPath"
|
|
|
|
:file="file"
|
2018-12-13 14:17:19 -05:00
|
|
|
:help-page-path="helpPagePath"
|
2018-11-20 07:37:57 -05:00
|
|
|
:can-current-user-fork="canCurrentUserFork"
|
2020-07-15 02:09:35 -04:00
|
|
|
:view-diffs-file-by-file="viewDiffsFileByFile"
|
2018-11-20 07:37:57 -05:00
|
|
|
/>
|
2020-08-20 11:10:18 -04:00
|
|
|
<div
|
|
|
|
v-if="showFileByFileNavigation"
|
|
|
|
data-testid="file-by-file-navigation"
|
|
|
|
class="gl-display-grid gl-text-center"
|
|
|
|
>
|
|
|
|
<gl-pagination
|
|
|
|
class="gl-mx-auto"
|
|
|
|
:value="currentFileNumber"
|
|
|
|
:prev-page="previousFileNumber"
|
|
|
|
:next-page="nextFileNumber"
|
|
|
|
@input="navigateToDiffFileNumber"
|
|
|
|
/>
|
|
|
|
<gl-sprintf :message="__('File %{current} of %{total}')">
|
|
|
|
<template #current>{{ currentFileNumber }}</template>
|
|
|
|
<template #total>{{ diffFiles.length }}</template>
|
|
|
|
</gl-sprintf>
|
2020-07-15 02:09:35 -04:00
|
|
|
</div>
|
2018-11-20 07:37:57 -05:00
|
|
|
</template>
|
2018-12-13 05:57:45 -05:00
|
|
|
<no-changes v-else :changes-empty-state-illustration="changesEmptyStateIllustration" />
|
2018-10-03 05:05:43 -04:00
|
|
|
</div>
|
2018-06-21 08:22:40 -04:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|