debian-mirror-gitlab/app/assets/javascripts/diffs/components/app.vue

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

777 lines
23 KiB
Vue
Raw Normal View History

2018-11-08 19:23:39 +05:30
<script>
2021-11-11 11:23:49 +05:30
import { GlLoadingIcon, GlPagination, GlSprintf, GlAlert } from '@gitlab/ui';
2021-02-22 17:27:13 +05:30
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
2020-01-01 13:55:28 +05:30
import Mousetrap from 'mousetrap';
2021-03-11 19:13:27 +05:30
import { mapState, mapGetters, mapActions } from 'vuex';
2021-06-08 01:23:25 +05:30
import api from '~/api';
2021-04-29 21:17:54 +05:30
import {
keysFor,
MR_PREVIOUS_FILE_IN_DIFF,
MR_NEXT_FILE_IN_DIFF,
MR_COMMITS_NEXT_COMMIT,
MR_COMMITS_PREVIOUS_COMMIT,
} from '~/behaviors/shortcuts/keybindings';
2022-11-25 23:54:43 +05:30
import { createAlert } from '~/flash';
2020-03-13 15:44:24 +05:30
import { isSingleViewStyle } from '~/helpers/diffs_helper';
2021-10-27 15:23:28 +05:30
import { helpPagePath } from '~/helpers/help_page_helper';
2021-09-30 23:02:18 +05:30
import { parseBoolean } from '~/lib/utils/common_utils';
2020-05-24 23:13:21 +05:30
import { updateHistory } from '~/lib/utils/url_utility';
2021-03-11 19:13:27 +05:30
import { __ } from '~/locale';
import PanelResizer from '~/vue_shared/components/panel_resizer.vue';
2021-11-18 22:05:49 +05:30
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
2021-02-22 17:27:13 +05:30
2022-06-21 17:19:12 +05:30
import notesEventHub from '~/notes/event_hub';
2019-07-07 11:18:12 +05:30
import {
TREE_LIST_WIDTH_STORAGE_KEY,
INITIAL_TREE_WIDTH,
MIN_TREE_WIDTH,
TREE_HIDE_STATS_WIDTH,
MR_TREE_SHOW_KEY,
2020-11-24 15:15:51 +05:30
ALERT_OVERFLOW_HIDDEN,
ALERT_MERGE_CONFLICT,
ALERT_COLLAPSED_FILES,
2021-06-08 01:23:25 +05:30
INLINE_DIFF_VIEW_TYPE,
TRACKING_DIFF_VIEW_INLINE,
TRACKING_DIFF_VIEW_PARALLEL,
TRACKING_FILE_BROWSER_TREE,
TRACKING_FILE_BROWSER_LIST,
TRACKING_WHITESPACE_SHOW,
TRACKING_WHITESPACE_HIDE,
TRACKING_SINGLE_FILE_MODE,
TRACKING_MULTIPLE_FILES_MODE,
2019-07-07 11:18:12 +05:30
} from '../constants';
2021-03-11 19:13:27 +05:30
2021-09-30 23:02:18 +05:30
import diffsEventHub from '../event_hub';
2021-03-11 19:13:27 +05:30
import { reviewStatuses } from '../utils/file_reviews';
import { diffsApp } from '../utils/performance';
2021-10-27 15:23:28 +05:30
import { queueRedisHllEvents } from '../utils/queue_events';
2021-03-11 19:13:27 +05:30
import CollapsedFilesWarning from './collapsed_files_warning.vue';
import CommitWidget from './commit_widget.vue';
import CompareVersions from './compare_versions.vue';
import DiffFile from './diff_file.vue';
import HiddenFilesWarning from './hidden_files_warning.vue';
import NoChanges from './no_changes.vue';
import TreeList from './tree_list.vue';
2022-04-04 11:22:00 +05:30
import VirtualScrollerScrollSync from './virtual_scroller_scroll_sync';
2018-11-08 19:23:39 +05:30
export default {
name: 'DiffsApp',
components: {
2021-11-11 11:23:49 +05:30
DynamicScroller: () =>
import('vendor/vue-virtual-scroller').then(({ DynamicScroller }) => DynamicScroller),
DynamicScrollerItem: () =>
import('vendor/vue-virtual-scroller').then(({ DynamicScrollerItem }) => DynamicScrollerItem),
PreRenderer: () => import('./pre_renderer.vue').then((PreRenderer) => PreRenderer),
2022-04-04 11:22:00 +05:30
VirtualScrollerScrollSync,
2018-11-08 19:23:39 +05:30
CompareVersions,
DiffFile,
NoChanges,
HiddenFilesWarning,
2020-11-24 15:15:51 +05:30
CollapsedFilesWarning,
2018-12-05 23:21:45 +05:30
CommitWidget,
TreeList,
2018-12-13 13:39:08 +05:30
GlLoadingIcon,
2019-07-07 11:18:12 +05:30
PanelResizer,
2020-11-24 15:15:51 +05:30
GlPagination,
GlSprintf,
2021-11-11 11:23:49 +05:30
GlAlert,
2018-11-08 19:23:39 +05:30
},
2021-11-18 22:05:49 +05:30
mixins: [glFeatureFlagsMixin()],
2020-11-24 15:15:51 +05:30
alerts: {
ALERT_OVERFLOW_HIDDEN,
ALERT_MERGE_CONFLICT,
ALERT_COLLAPSED_FILES,
},
2018-11-08 19:23:39 +05:30
props: {
endpoint: {
type: String,
required: true,
},
2020-01-01 13:55:28 +05:30
endpointMetadata: {
type: String,
required: true,
},
endpointBatch: {
type: String,
required: true,
},
2020-04-08 14:13:33 +05:30
endpointCoverage: {
type: String,
required: false,
default: '',
},
2021-04-29 21:17:54 +05:30
endpointCodequality: {
type: String,
required: false,
default: '',
},
endpointUpdateUser: {
type: String,
required: false,
default: '',
},
2018-11-08 19:23:39 +05:30
projectPath: {
type: String,
required: true,
},
shouldShow: {
type: Boolean,
required: false,
default: false,
},
currentUser: {
type: Object,
required: true,
},
2019-02-15 15:39:39 +05:30
helpPagePath: {
type: String,
required: false,
default: '',
},
changesEmptyStateIllustration: {
type: String,
required: false,
default: '',
},
2019-07-07 11:18:12 +05:30
isFluidLayout: {
type: Boolean,
required: false,
default: false,
},
2019-09-04 21:01:54 +05:30
dismissEndpoint: {
type: String,
required: false,
default: '',
},
showSuggestPopover: {
type: Boolean,
required: false,
default: false,
},
2021-02-22 17:27:13 +05:30
fileByFileUserPreference: {
2020-07-28 23:09:34 +05:30
type: Boolean,
required: false,
default: false,
},
2021-03-08 18:12:59 +05:30
defaultSuggestionCommitMessage: {
type: String,
required: false,
default: '',
},
2021-04-17 20:07:23 +05:30
rehydratedMrReviews: {
2021-03-08 18:12:59 +05:30
type: Object,
required: false,
default: () => ({}),
},
2021-10-27 15:23:28 +05:30
sourceProjectDefaultUrl: {
type: String,
required: false,
default: '',
},
sourceProjectFullPath: {
type: String,
required: false,
default: '',
},
isForked: {
type: Boolean,
required: false,
default: false,
},
2018-11-08 19:23:39 +05:30
},
2018-12-13 13:39:08 +05:30
data() {
2019-07-07 11:18:12 +05:30
const treeWidth =
parseInt(localStorage.getItem(TREE_LIST_WIDTH_STORAGE_KEY), 10) || INITIAL_TREE_WIDTH;
2018-12-13 13:39:08 +05:30
return {
2019-07-07 11:18:12 +05:30
treeWidth,
2020-03-13 15:44:24 +05:30
diffFilesLength: 0,
2021-09-30 23:02:18 +05:30
virtualScrollCurrentIndex: -1,
2021-11-11 11:23:49 +05:30
subscribedToVirtualScrollingEvents: false,
2018-12-13 13:39:08 +05:30
};
},
2018-11-08 19:23:39 +05:30
computed: {
2021-11-11 11:23:49 +05:30
...mapState('diffs', {
numTotalFiles: 'realSize',
numVisibleFiles: 'size',
2018-11-08 19:23:39 +05:30
}),
2020-10-24 23:57:45 +05:30
...mapState('diffs', [
'showTreeList',
'isLoading',
2021-11-11 11:23:49 +05:30
'diffFiles',
'diffViewType',
'commit',
'renderOverflowWarning',
'plainDiffPath',
'emailPatchPath',
'retrievingBatches',
2020-10-24 23:57:45 +05:30
'startVersion',
2021-09-30 23:02:18 +05:30
'latestDiff',
2020-10-24 23:57:45 +05:30
'currentDiffFileId',
'isTreeLoaded',
'conflictResolutionPath',
'canMerge',
'hasConflicts',
2021-02-22 17:27:13 +05:30
'viewDiffsFileByFile',
2021-04-17 20:07:23 +05:30
'mrReviews',
2021-06-08 01:23:25 +05:30
'renderTreeList',
'showWhitespace',
2021-10-27 15:23:28 +05:30
'targetBranchName',
'branchName',
2021-06-08 01:23:25 +05:30
]),
...mapGetters('diffs', [
'whichCollapsedTypes',
'isParallelView',
'currentDiffIndex',
'isVirtualScrollingEnabled',
2021-11-11 11:23:49 +05:30
'isBatchLoading',
'isBatchLoadingError',
2020-10-24 23:57:45 +05:30
]),
2018-12-13 13:39:08 +05:30
...mapGetters(['isNotesFetched', 'getNoteableData']),
2020-07-28 23:09:34 +05:30
diffs() {
if (!this.viewDiffsFileByFile) {
return this.diffFiles;
}
return this.diffFiles.filter((file, i) => {
return file.file_hash === this.currentDiffFileId || (i === 0 && !this.currentDiffFileId);
});
},
2018-11-08 19:23:39 +05:30
canCurrentUserFork() {
2019-02-15 15:39:39 +05:30
return this.currentUser.can_fork === true && this.currentUser.can_create_merge_request;
2018-11-08 19:23:39 +05:30
},
2019-02-15 15:39:39 +05:30
renderDiffFiles() {
2021-03-08 18:12:59 +05:30
return this.diffFiles.length > 0;
},
renderFileTree() {
return this.renderDiffFiles && this.showTreeList;
2019-02-15 15:39:39 +05:30
},
2019-07-07 11:18:12 +05:30
hideFileStats() {
return this.treeWidth <= TREE_HIDE_STATS_WIDTH;
},
2021-09-30 23:02:18 +05:30
isFullChangeset() {
return this.startVersion === null && this.latestDiff;
2020-10-24 23:57:45 +05:30
},
2020-11-24 15:15:51 +05:30
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;
},
visibleWarning() {
let visible = false;
if (this.renderOverflowWarning) {
visible = this.$options.alerts.ALERT_OVERFLOW_HIDDEN;
2021-09-30 23:02:18 +05:30
} else if (this.isFullChangeset && this.hasConflicts) {
2020-11-24 15:15:51 +05:30
visible = this.$options.alerts.ALERT_MERGE_CONFLICT;
2021-01-29 00:20:46 +05:30
} else if (this.whichCollapsedTypes.automatic && !this.viewDiffsFileByFile) {
2020-11-24 15:15:51 +05:30
visible = this.$options.alerts.ALERT_COLLAPSED_FILES;
}
return visible;
},
2021-03-11 19:13:27 +05:30
fileReviews() {
return reviewStatuses(this.diffFiles, this.mrReviews);
},
2018-11-08 19:23:39 +05:30
},
watch: {
2020-05-24 23:13:21 +05:30
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-11-08 19:23:39 +05:30
diffViewType() {
this.adjustView();
},
shouldShow() {
// 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();
}
this.adjustView();
2021-11-11 11:23:49 +05:30
this.subscribeToVirtualScrollingEvents();
2018-11-08 19:23:39 +05:30
},
2018-12-05 23:21:45 +05:30
isLoading: 'adjustView',
2021-03-08 18:12:59 +05:30
renderFileTree: 'adjustView',
2018-11-08 19:23:39 +05:30
},
mounted() {
2019-09-04 21:01:54 +05:30
this.setBaseConfig({
endpoint: this.endpoint,
2020-01-01 13:55:28 +05:30
endpointMetadata: this.endpointMetadata,
endpointBatch: this.endpointBatch,
2020-04-08 14:13:33 +05:30
endpointCoverage: this.endpointCoverage,
2021-04-29 21:17:54 +05:30
endpointUpdateUser: this.endpointUpdateUser,
2019-09-04 21:01:54 +05:30
projectPath: this.projectPath,
dismissEndpoint: this.dismissEndpoint,
showSuggestPopover: this.showSuggestPopover,
2021-11-11 11:23:49 +05:30
viewDiffsFileByFile: this.fileByFileUserPreference || false,
2021-03-08 18:12:59 +05:30
defaultSuggestionCommitMessage: this.defaultSuggestionCommitMessage,
2021-04-17 20:07:23 +05:30
mrReviews: this.rehydratedMrReviews,
2019-09-04 21:01:54 +05:30
});
2018-11-08 19:23:39 +05:30
2022-10-11 01:57:18 +05:30
this.interfaceWithDOM();
2021-04-29 21:17:54 +05:30
if (this.endpointCodequality) {
this.setCodequalityEndpoint(this.endpointCodequality);
}
2018-11-08 19:23:39 +05:30
if (this.shouldShow) {
this.fetchData();
}
2019-02-15 15:39:39 +05:30
2020-07-28 23:09:34 +05:30
const id = window?.location?.hash;
2019-02-15 15:39:39 +05:30
2020-07-28 23:09:34 +05:30
if (id && id.indexOf('#note') !== 0) {
2021-03-08 18:12:59 +05:30
this.setHighlightedRow(id.split('diff-content').pop().slice(1));
2019-02-15 15:39:39 +05:30
}
2021-06-08 01:23:25 +05:30
2022-06-21 17:19:12 +05:30
const events = [];
2021-10-27 15:23:28 +05:30
2022-06-21 17:19:12 +05:30
if (this.renderTreeList) {
events.push(TRACKING_FILE_BROWSER_TREE);
} else {
events.push(TRACKING_FILE_BROWSER_LIST);
}
2021-06-08 01:23:25 +05:30
2022-06-21 17:19:12 +05:30
if (this.diffViewType === INLINE_DIFF_VIEW_TYPE) {
events.push(TRACKING_DIFF_VIEW_INLINE);
} else {
events.push(TRACKING_DIFF_VIEW_PARALLEL);
}
2021-06-08 01:23:25 +05:30
2022-06-21 17:19:12 +05:30
if (this.showWhitespace) {
events.push(TRACKING_WHITESPACE_SHOW);
} else {
events.push(TRACKING_WHITESPACE_HIDE);
}
2021-10-27 15:23:28 +05:30
2022-06-21 17:19:12 +05:30
if (this.viewDiffsFileByFile) {
events.push(TRACKING_SINGLE_FILE_MODE);
} else {
events.push(TRACKING_MULTIPLE_FILES_MODE);
2021-06-08 01:23:25 +05:30
}
2021-11-11 11:23:49 +05:30
2022-07-16 23:28:13 +05:30
queueRedisHllEvents(events, { verifyCap: true });
2022-06-21 17:19:12 +05:30
2021-11-11 11:23:49 +05:30
this.subscribeToVirtualScrollingEvents();
2018-11-08 19:23:39 +05:30
},
2021-01-29 00:20:46 +05:30
beforeCreate() {
diffsApp.instrument();
},
2018-11-08 19:23:39 +05:30
created() {
this.adjustView();
2021-02-22 17:27:13 +05:30
this.subscribeToEvents();
2021-01-29 00:20:46 +05:30
2020-03-13 15:44:24 +05:30
this.unwatchDiscussions = this.$watch(
() => `${this.diffFiles.length}:${this.$store.state.notes.discussions.length}`,
2022-07-23 23:45:48 +05:30
() => {
this.setDiscussions();
if (
this.$store.state.notes.doneFetchingBatchDiscussions &&
window.gon?.features?.paginatedMrDiscussions
) {
this.unwatchDiscussions();
}
},
2020-03-13 15:44:24 +05:30
);
this.unwatchRetrievingBatches = this.$watch(
() => `${this.retrievingBatches}:${this.$store.state.notes.discussions.length}`,
() => {
if (!this.retrievingBatches && this.$store.state.notes.discussions.length) {
2022-07-23 23:45:48 +05:30
if (!window.gon?.features?.paginatedMrDiscussions) {
this.unwatchDiscussions();
}
2020-03-13 15:44:24 +05:30
this.unwatchRetrievingBatches();
}
},
);
2019-03-02 22:35:43 +05:30
},
beforeDestroy() {
2021-01-29 00:20:46 +05:30
diffsApp.deinstrument();
2021-02-22 17:27:13 +05:30
this.unsubscribeFromEvents();
2019-07-07 11:18:12 +05:30
this.removeEventListeners();
2021-09-30 23:02:18 +05:30
2022-04-04 11:22:00 +05:30
diffsEventHub.$off('scrollToFileHash', this.scrollVirtualScrollerToFileHash);
diffsEventHub.$off('scrollToIndex', this.scrollVirtualScrollerToIndex);
2018-11-08 19:23:39 +05:30
},
methods: {
2019-02-15 15:39:39 +05:30
...mapActions(['startTaskList']),
2018-11-20 20:47:30 +05:30
...mapActions('diffs', [
2020-05-24 23:13:21 +05:30
'moveToNeighboringCommit',
2018-11-20 20:47:30 +05:30
'setBaseConfig',
2021-04-29 21:17:54 +05:30
'setCodequalityEndpoint',
2020-01-01 13:55:28 +05:30
'fetchDiffFilesMeta',
'fetchDiffFilesBatch',
2020-04-08 14:13:33 +05:30
'fetchCoverageFiles',
2021-04-29 21:17:54 +05:30
'fetchCodequality',
2018-11-20 20:47:30 +05:30
'startRenderDiffsQueue',
'assignDiscussionsToDiff',
2019-02-15 15:39:39 +05:30
'setHighlightedRow',
2019-07-07 11:18:12 +05:30
'cacheTreeListWidth',
'scrollToFile',
2021-02-22 17:27:13 +05:30
'setShowTreeList',
2020-07-28 23:09:34 +05:30
'navigateToDiffFileIndex',
2021-02-22 17:27:13 +05:30
'setFileByFile',
2021-10-27 15:23:28 +05:30
'disableVirtualScroller',
2018-11-20 20:47:30 +05:30
]),
2021-02-22 17:27:13 +05:30
subscribeToEvents() {
notesEventHub.$once('fetchDiffData', this.fetchData);
notesEventHub.$on('refetchDiffData', this.refetchDiffData);
},
unsubscribeFromEvents() {
notesEventHub.$off('refetchDiffData', this.refetchDiffData);
notesEventHub.$off('fetchDiffData', this.fetchData);
},
2022-10-11 01:57:18 +05:30
interfaceWithDOM() {
this.diffsTab = document.querySelector('.js-diffs-tab');
},
updateChangesTabCount() {
const badge = this.diffsTab.querySelector('.gl-badge');
if (this.diffsTab && badge) {
badge.textContent = this.diffFilesLength;
}
},
2020-11-24 15:15:51 +05:30
navigateToDiffFileNumber(number) {
this.navigateToDiffFileIndex(number - 1);
},
2019-09-04 21:01:54 +05:30
refetchDiffData() {
this.fetchData(false);
},
2020-03-13 15:44:24 +05:30
needsReload() {
2020-11-24 15:15:51 +05:30
return this.diffFiles.length && isSingleViewStyle(this.diffFiles[0]);
2020-03-13 15:44:24 +05:30
},
needsFirstLoad() {
2020-11-24 15:15:51 +05:30
return !this.diffFiles.length;
2020-03-13 15:44:24 +05:30
},
2019-09-04 21:01:54 +05:30
fetchData(toggleTree = true) {
2020-11-24 15:15:51 +05:30
this.fetchDiffFilesMeta()
2023-01-13 00:05:48 +05:30
.then((data) => {
let realSize = 0;
if (data) {
realSize = data.real_size;
}
this.diffFilesLength = parseInt(realSize, 10) || 0;
2022-10-11 01:57:18 +05:30
if (toggleTree) {
this.setTreeDisplay();
}
this.updateChangesTabCount();
2020-11-24 15:15:51 +05:30
})
.catch(() => {
2022-11-25 23:54:43 +05:30
createAlert({
2021-09-04 01:27:46 +05:30
message: __('Something went wrong on our end. Please try again!'),
});
2020-11-24 15:15:51 +05:30
});
2020-01-01 13:55:28 +05:30
2020-11-24 15:15:51 +05:30
this.fetchDiffFilesBatch()
.then(() => {
2021-02-22 17:27:13 +05:30
if (toggleTree) this.setTreeDisplay();
2020-11-24 15:15:51 +05:30
// 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();
})
.catch(() => {
2022-11-25 23:54:43 +05:30
createAlert({
2021-09-04 01:27:46 +05:30
message: __('Something went wrong on our end. Please try again!'),
});
2020-11-24 15:15:51 +05:30
});
2018-11-08 19:23:39 +05:30
2020-04-08 14:13:33 +05:30
if (this.endpointCoverage) {
this.fetchCoverageFiles();
}
2021-04-29 21:17:54 +05:30
if (this.endpointCodequality) {
this.fetchCodequality();
}
2018-11-08 19:23:39 +05:30
if (!this.isNotesFetched) {
2021-02-22 17:27:13 +05:30
notesEventHub.$emit('fetchNotesData');
2018-11-08 19:23:39 +05:30
}
},
2018-11-20 20:47:30 +05:30
setDiscussions() {
2020-03-13 15:44:24 +05:30
requestIdleCallback(
2021-09-30 23:02:18 +05:30
() =>
this.assignDiscussionsToDiff()
.then(this.$nextTick)
.then(this.startTaskList)
.then(this.scrollVirtualScrollerToDiffNote),
2020-03-13 15:44:24 +05:30
{ timeout: 1000 },
);
2018-11-20 20:47:30 +05:30
},
2018-11-08 19:23:39 +05:30
adjustView() {
2018-12-05 23:21:45 +05:30
if (this.shouldShow) {
this.$nextTick(() => {
2019-07-07 11:18:12 +05:30
this.setEventListeners();
2018-12-05 23:21:45 +05:30
});
2019-07-07 11:18:12 +05:30
} else {
this.removeEventListeners();
}
},
setEventListeners() {
2021-04-29 21:17:54 +05:30
Mousetrap.bind(keysFor(MR_PREVIOUS_FILE_IN_DIFF), () => this.jumpToFile(-1));
Mousetrap.bind(keysFor(MR_NEXT_FILE_IN_DIFF), () => this.jumpToFile(+1));
2020-05-24 23:13:21 +05:30
2021-03-08 18:12:59 +05:30
if (this.commit) {
2021-04-29 21:17:54 +05:30
Mousetrap.bind(keysFor(MR_COMMITS_NEXT_COMMIT), () =>
this.moveToNeighboringCommit({ direction: 'next' }),
);
Mousetrap.bind(keysFor(MR_COMMITS_PREVIOUS_COMMIT), () =>
this.moveToNeighboringCommit({ direction: 'previous' }),
);
2020-05-24 23:13:21 +05:30
}
2021-09-30 23:02:18 +05:30
2022-04-04 11:22:00 +05:30
let keydownTime;
Mousetrap.bind(['mod+f', 'mod+g'], () => {
keydownTime = new Date().getTime();
});
2021-10-27 15:23:28 +05:30
2022-04-04 11:22:00 +05:30
window.addEventListener('blur', () => {
if (keydownTime) {
const delta = new Date().getTime() - keydownTime;
2021-10-27 15:23:28 +05:30
2022-04-04 11:22:00 +05:30
// To make sure the user is using the find function we need to wait for blur
// and max 1000ms to be sure it the search box is filtered
if (delta >= 0 && delta < 1000) {
this.disableVirtualScroller();
2021-10-27 15:23:28 +05:30
2022-06-21 17:19:12 +05:30
api.trackRedisHllUserEvent('i_code_review_user_searches_diff');
api.trackRedisCounterEvent('diff_searches');
2021-10-27 15:23:28 +05:30
}
2022-04-04 11:22:00 +05:30
}
});
2019-07-07 11:18:12 +05:30
},
removeEventListeners() {
2021-04-29 21:17:54 +05:30
Mousetrap.unbind(keysFor(MR_PREVIOUS_FILE_IN_DIFF));
Mousetrap.unbind(keysFor(MR_NEXT_FILE_IN_DIFF));
Mousetrap.unbind(keysFor(MR_COMMITS_NEXT_COMMIT));
Mousetrap.unbind(keysFor(MR_COMMITS_PREVIOUS_COMMIT));
2021-09-30 23:02:18 +05:30
Mousetrap.unbind(['ctrl+f', 'command+f']);
2019-07-07 11:18:12 +05:30
},
jumpToFile(step) {
const targetIndex = this.currentDiffIndex + step;
if (targetIndex >= 0 && targetIndex < this.diffFiles.length) {
2021-12-11 22:18:48 +05:30
this.scrollToFile({ path: this.diffFiles[targetIndex].file_path });
2019-07-07 11:18:12 +05:30
}
},
2021-02-22 17:27:13 +05:30
setTreeDisplay() {
2019-07-07 11:18:12 +05:30
const storedTreeShow = localStorage.getItem(MR_TREE_SHOW_KEY);
2021-02-22 17:27:13 +05:30
let showTreeList = true;
2019-07-07 11:18:12 +05:30
2021-02-22 17:27:13 +05:30
if (storedTreeShow !== null) {
showTreeList = parseBoolean(storedTreeShow);
} else if (!bp.isDesktop() || (!this.isBatchLoading && this.diffFiles.length <= 1)) {
showTreeList = false;
2018-11-08 19:23:39 +05:30
}
2021-02-22 17:27:13 +05:30
return this.setShowTreeList({ showTreeList, saving: false });
2018-11-08 19:23:39 +05:30
},
2021-09-30 23:02:18 +05:30
async scrollVirtualScrollerToFileHash(hash) {
const index = this.diffFiles.findIndex((f) => f.file_hash === hash);
if (index !== -1) {
this.scrollVirtualScrollerToIndex(index);
}
},
2022-06-21 17:19:12 +05:30
scrollVirtualScrollerToIndex(index) {
2021-09-30 23:02:18 +05:30
this.virtualScrollCurrentIndex = index;
},
scrollVirtualScrollerToDiffNote() {
const id = window?.location?.hash;
if (id.startsWith('#note_')) {
const noteId = id.replace('#note_', '');
const discussion = this.$store.state.notes.discussions.find(
(d) => d.diff_file && d.notes.find((n) => n.id === noteId),
);
if (discussion) {
this.scrollVirtualScrollerToFileHash(discussion.diff_file.file_hash);
}
}
},
2021-11-11 11:23:49 +05:30
subscribeToVirtualScrollingEvents() {
2022-04-04 11:22:00 +05:30
if (this.shouldShow && !this.subscribedToVirtualScrollingEvents) {
2021-11-11 11:23:49 +05:30
diffsEventHub.$on('scrollToFileHash', this.scrollVirtualScrollerToFileHash);
diffsEventHub.$on('scrollToIndex', this.scrollVirtualScrollerToIndex);
this.subscribedToVirtualScrollingEvents = true;
}
},
reloadPage() {
window.location.reload();
},
2018-11-08 19:23:39 +05:30
},
2019-07-07 11:18:12 +05:30
minTreeWidth: MIN_TREE_WIDTH,
2022-04-04 11:22:00 +05:30
maxTreeWidth: window.innerWidth / 2,
2021-10-27 15:23:28 +05:30
howToMergeDocsPath: helpPagePath('user/project/merge_requests/reviews/index.md', {
anchor: 'checkout-merge-requests-locally-through-the-head-ref',
}),
2018-11-08 19:23:39 +05:30
};
</script>
<template>
<div v-show="shouldShow">
2020-10-24 23:57:45 +05:30
<div v-if="isLoading || !isTreeLoaded" class="loading"><gl-loading-icon size="lg" /></div>
2019-02-15 15:39:39 +05:30
<div v-else id="diffs" :class="{ active: shouldShow }" class="diffs tab-pane">
2022-04-04 11:22:00 +05:30
<compare-versions :diff-files-count-text="numTotalFiles" />
2018-11-08 19:23:39 +05:30
2021-11-11 11:23:49 +05:30
<template v-if="!isBatchLoadingError">
<hidden-files-warning
v-if="visibleWarning == $options.alerts.ALERT_OVERFLOW_HIDDEN"
:visible="numVisibleFiles"
:total="numTotalFiles"
:plain-diff-path="plainDiffPath"
:email-patch-path="emailPatchPath"
/>
2022-04-04 11:22:00 +05:30
<collapsed-files-warning v-if="visibleWarning == $options.alerts.ALERT_COLLAPSED_FILES" />
2021-11-11 11:23:49 +05:30
</template>
2020-10-24 23:57:45 +05:30
2018-12-13 13:39:08 +05:30
<div
:data-can-create-note="getNoteableData.current_user.can_create_note"
2020-11-24 15:15:51 +05:30
class="files d-flex gl-mt-2"
2018-12-13 13:39:08 +05:30
>
2019-07-07 11:18:12 +05:30
<div
2021-03-08 18:12:59 +05:30
v-if="renderFileTree"
2019-07-07 11:18:12 +05:30
:style="{ width: `${treeWidth}px` }"
2022-10-11 01:57:18 +05:30
:class="{ 'is-sidebar-moved': glFeatures.movedMrSidebar }"
2022-04-04 11:22:00 +05:30
class="diff-tree-list js-diff-tree-list gl-px-5"
2019-07-07 11:18:12 +05:30
>
<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>
2022-04-04 11:22:00 +05:30
<div class="col-12 col-md-auto diff-files-holder">
2020-10-24 23:57:45 +05:30
<commit-widget v-if="commit" :commit="commit" :collapsible="false" />
2021-11-11 11:23:49 +05:30
<gl-alert
v-if="isBatchLoadingError"
variant="danger"
:dismissible="false"
:primary-button-text="__('Reload page')"
@primaryAction="reloadPage"
>
{{ __("Error: Couldn't load some or all of the changes.") }}
</gl-alert>
<div v-if="isBatchLoading && !isBatchLoadingError" class="loading">
<gl-loading-icon size="lg" />
</div>
2020-01-01 13:55:28 +05:30
<template v-else-if="renderDiffFiles">
2021-06-08 01:23:25 +05:30
<dynamic-scroller
2021-10-27 15:23:28 +05:30
v-if="isVirtualScrollingEnabled"
2021-06-08 01:23:25 +05:30
:items="diffs"
:min-item-size="70"
:buffer="1000"
:use-transform="false"
page-mode
>
<template #default="{ item, index, active }">
2021-09-30 23:02:18 +05:30
<dynamic-scroller-item :item="item" :active="active" :class="{ active }">
2021-06-08 01:23:25 +05:30
<diff-file
:file="item"
:reviewed="fileReviews[item.id]"
:is-first-file="index === 0"
:is-last-file="index === diffFilesLength - 1"
:help-page-path="helpPagePath"
:can-current-user-fork="canCurrentUserFork"
:view-diffs-file-by-file="viewDiffsFileByFile"
2021-09-30 23:02:18 +05:30
:active="active"
2021-06-08 01:23:25 +05:30
/>
</dynamic-scroller-item>
</template>
2021-09-30 23:02:18 +05:30
<template #before>
<pre-renderer :max-length="diffFilesLength">
<template #default="{ item, index, active }">
<dynamic-scroller-item :item="item" :active="active">
<diff-file
:file="item"
:reviewed="fileReviews[item.id]"
:is-first-file="index === 0"
:is-last-file="index === diffFilesLength - 1"
:help-page-path="helpPagePath"
:can-current-user-fork="canCurrentUserFork"
:view-diffs-file-by-file="viewDiffsFileByFile"
pre-render
/>
</dynamic-scroller-item>
</template>
</pre-renderer>
2022-06-21 17:19:12 +05:30
<virtual-scroller-scroll-sync v-model="virtualScrollCurrentIndex" />
2021-09-30 23:02:18 +05:30
</template>
2021-06-08 01:23:25 +05:30
</dynamic-scroller>
<template v-else>
<diff-file
v-for="(file, index) in diffs"
:key="file.new_path"
:file="file"
:reviewed="fileReviews[file.id]"
:is-first-file="index === 0"
:is-last-file="index === diffFilesLength - 1"
:help-page-path="helpPagePath"
:can-current-user-fork="canCurrentUserFork"
:view-diffs-file-by-file="viewDiffsFileByFile"
/>
</template>
2020-11-24 15:15:51 +05:30
<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-28 23:09:34 +05:30
</div>
2021-02-22 17:27:13 +05:30
<gl-loading-icon v-else-if="retrievingBatches" size="lg" />
2019-02-15 15:39:39 +05:30
</template>
2021-11-11 11:23:49 +05:30
<no-changes
v-else-if="!isBatchLoadingError"
:changes-empty-state-illustration="changesEmptyStateIllustration"
/>
2018-12-05 23:21:45 +05:30
</div>
2018-11-08 19:23:39 +05:30
</div>
</div>
</div>
</template>