Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-08-19 12:08:42 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-08-19 12:08:42 +0300
commitb76ae638462ab0f673e5915986070518dd3f9ad3 (patch)
treebdab0533383b52873be0ec0eb4d3c66598ff8b91 /app/assets/javascripts/diffs
parent434373eabe7b4be9593d18a585fb763f1e5f1a6f (diff)
Add latest changes from gitlab-org/gitlab@14-2-stable-eev14.2.0-rc42
Diffstat (limited to 'app/assets/javascripts/diffs')
-rw-r--r--app/assets/javascripts/diffs/components/app.vue94
-rw-r--r--app/assets/javascripts/diffs/components/diff_file.vue99
-rw-r--r--app/assets/javascripts/diffs/components/diff_gutter_avatars.vue1
-rw-r--r--app/assets/javascripts/diffs/components/diff_row.vue19
-rw-r--r--app/assets/javascripts/diffs/components/diff_stats.vue4
-rw-r--r--app/assets/javascripts/diffs/components/settings_dropdown.vue4
-rw-r--r--app/assets/javascripts/diffs/constants.js2
-rw-r--r--app/assets/javascripts/diffs/i18n.js22
-rw-r--r--app/assets/javascripts/diffs/index.js16
-rw-r--r--app/assets/javascripts/diffs/store/actions.js50
-rw-r--r--app/assets/javascripts/diffs/store/getters.js22
-rw-r--r--app/assets/javascripts/diffs/store/modules/diff_state.js1
-rw-r--r--app/assets/javascripts/diffs/store/mutation_types.js1
-rw-r--r--app/assets/javascripts/diffs/store/mutations.js3
-rw-r--r--app/assets/javascripts/diffs/utils/queue_events.js13
15 files changed, 278 insertions, 73 deletions
diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue
index e33b60f8ab5..d03b5cbc26b 100644
--- a/app/assets/javascripts/diffs/components/app.vue
+++ b/app/assets/javascripts/diffs/components/app.vue
@@ -14,9 +14,11 @@ import {
} from '~/behaviors/shortcuts/keybindings';
import createFlash from '~/flash';
import { isSingleViewStyle } from '~/helpers/diffs_helper';
+import { helpPagePath } from '~/helpers/help_page_helper';
import { parseBoolean } from '~/lib/utils/common_utils';
import { updateHistory } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
+import MrWidgetHowToMergeModal from '~/vue_merge_request_widget/components/mr_widget_how_to_merge_modal.vue';
import PanelResizer from '~/vue_shared/components/panel_resizer.vue';
import notesEventHub from '../../notes/event_hub';
@@ -46,12 +48,12 @@ import diffsEventHub from '../event_hub';
import { reviewStatuses } from '../utils/file_reviews';
import { diffsApp } from '../utils/performance';
import { fileByFile } from '../utils/preferences';
+import { queueRedisHllEvents } from '../utils/queue_events';
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 MergeConflictWarning from './merge_conflict_warning.vue';
import NoChanges from './no_changes.vue';
import PreRenderer from './pre_renderer.vue';
import TreeList from './tree_list.vue';
@@ -64,7 +66,6 @@ export default {
DiffFile,
NoChanges,
HiddenFilesWarning,
- MergeConflictWarning,
CollapsedFilesWarning,
CommitWidget,
TreeList,
@@ -76,6 +77,7 @@ export default {
DynamicScrollerItem,
PreRenderer,
VirtualScrollerScrollSync,
+ MrWidgetHowToMergeModal,
},
alerts: {
ALERT_OVERFLOW_HIDDEN,
@@ -163,6 +165,21 @@ export default {
required: false,
default: () => ({}),
},
+ sourceProjectDefaultUrl: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ sourceProjectFullPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ isForked: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
const treeWidth =
@@ -172,7 +189,6 @@ export default {
treeWidth,
diffFilesLength: 0,
virtualScrollCurrentIndex: -1,
- disableVirtualScroller: false,
};
},
computed: {
@@ -203,6 +219,8 @@ export default {
'mrReviews',
'renderTreeList',
'showWhitespace',
+ 'targetBranchName',
+ 'branchName',
]),
...mapGetters('diffs', [
'whichCollapsedTypes',
@@ -337,29 +355,33 @@ export default {
}
if (window.gon?.features?.diffSettingsUsageData) {
+ const events = [];
+
if (this.renderTreeList) {
- api.trackRedisHllUserEvent(TRACKING_FILE_BROWSER_TREE);
+ events.push(TRACKING_FILE_BROWSER_TREE);
} else {
- api.trackRedisHllUserEvent(TRACKING_FILE_BROWSER_LIST);
+ events.push(TRACKING_FILE_BROWSER_LIST);
}
if (this.diffViewType === INLINE_DIFF_VIEW_TYPE) {
- api.trackRedisHllUserEvent(TRACKING_DIFF_VIEW_INLINE);
+ events.push(TRACKING_DIFF_VIEW_INLINE);
} else {
- api.trackRedisHllUserEvent(TRACKING_DIFF_VIEW_PARALLEL);
+ events.push(TRACKING_DIFF_VIEW_PARALLEL);
}
if (this.showWhitespace) {
- api.trackRedisHllUserEvent(TRACKING_WHITESPACE_SHOW);
+ events.push(TRACKING_WHITESPACE_SHOW);
} else {
- api.trackRedisHllUserEvent(TRACKING_WHITESPACE_HIDE);
+ events.push(TRACKING_WHITESPACE_HIDE);
}
if (this.viewDiffsFileByFile) {
- api.trackRedisHllUserEvent(TRACKING_SINGLE_FILE_MODE);
+ events.push(TRACKING_SINGLE_FILE_MODE);
} else {
- api.trackRedisHllUserEvent(TRACKING_MULTIPLE_FILES_MODE);
+ events.push(TRACKING_MULTIPLE_FILES_MODE);
}
+
+ queueRedisHllEvents(events);
}
},
beforeCreate() {
@@ -414,6 +436,7 @@ export default {
'setShowTreeList',
'navigateToDiffFileIndex',
'setFileByFile',
+ 'disableVirtualScroller',
]),
subscribeToEvents() {
notesEventHub.$once('fetchDiffData', this.fetchData);
@@ -506,9 +529,32 @@ export default {
);
}
- Mousetrap.bind(['ctrl+f', 'command+f'], () => {
- this.disableVirtualScroller = true;
- });
+ if (
+ window.gon?.features?.diffsVirtualScrolling ||
+ window.gon?.features?.diffSearchingUsageData
+ ) {
+ let keydownTime;
+ Mousetrap.bind(['mod+f', 'mod+g'], () => {
+ keydownTime = new Date().getTime();
+ });
+
+ window.addEventListener('blur', () => {
+ if (keydownTime) {
+ const delta = new Date().getTime() - keydownTime;
+
+ // 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();
+
+ if (window.gon?.features?.diffSearchingUsageData) {
+ api.trackRedisHllUserEvent('i_code_review_user_searches_diff');
+ api.trackRedisCounterEvent('diff_searches');
+ }
+ }
+ }
+ });
+ }
},
removeEventListeners() {
Mousetrap.unbind(keysFor(MR_PREVIOUS_FILE_IN_DIFF));
@@ -568,6 +614,9 @@ export default {
},
minTreeWidth: MIN_TREE_WIDTH,
maxTreeWidth: MAX_TREE_WIDTH,
+ howToMergeDocsPath: helpPagePath('user/project/merge_requests/reviews/index.md', {
+ anchor: 'checkout-merge-requests-locally-through-the-head-ref',
+ }),
};
</script>
@@ -587,12 +636,6 @@ export default {
:plain-diff-path="plainDiffPath"
:email-patch-path="emailPatchPath"
/>
- <merge-conflict-warning
- v-if="visibleWarning == $options.alerts.ALERT_MERGE_CONFLICT"
- :limited="isLimitedContainer"
- :resolution-path="conflictResolutionPath"
- :mergeable="canMerge"
- />
<collapsed-files-warning
v-if="visibleWarning == $options.alerts.ALERT_COLLAPSED_FILES"
:limited="isLimitedContainer"
@@ -628,7 +671,7 @@ export default {
<div v-if="isBatchLoading" class="loading"><gl-loading-icon size="lg" /></div>
<template v-else-if="renderDiffFiles">
<dynamic-scroller
- v-if="!disableVirtualScroller && isVirtualScrollingEnabled"
+ v-if="isVirtualScrollingEnabled"
ref="virtualScroller"
:items="diffs"
:min-item-size="70"
@@ -705,6 +748,15 @@ export default {
<no-changes v-else :changes-empty-state-illustration="changesEmptyStateIllustration" />
</div>
</div>
+ <mr-widget-how-to-merge-modal
+ :is-fork="isForked"
+ :can-merge="canMerge"
+ :source-branch="branchName"
+ :source-project-path="sourceProjectFullPath"
+ :target-branch="targetBranchName"
+ :source-project-default-url="sourceProjectDefaultUrl"
+ :reviewing-docs-path="$options.howToMergeDocsPath"
+ />
</div>
</div>
</template>
diff --git a/app/assets/javascripts/diffs/components/diff_file.vue b/app/assets/javascripts/diffs/components/diff_file.vue
index dde5ea81e9a..933891d698c 100644
--- a/app/assets/javascripts/diffs/components/diff_file.vue
+++ b/app/assets/javascripts/diffs/components/diff_file.vue
@@ -1,5 +1,12 @@
<script>
-import { GlButton, GlLoadingIcon, GlSafeHtmlDirective as SafeHtml, GlSprintf } from '@gitlab/ui';
+import {
+ GlButton,
+ GlLoadingIcon,
+ GlSafeHtmlDirective as SafeHtml,
+ GlSprintf,
+ GlAlert,
+ GlModalDirective,
+} from '@gitlab/ui';
import { escape } from 'lodash';
import { mapActions, mapGetters, mapState } from 'vuex';
import { IdState } from 'vendor/vue-virtual-scroller';
@@ -19,7 +26,7 @@ import {
EVT_PERF_MARK_FIRST_DIFF_FILE_SHOWN,
} from '../constants';
import eventHub from '../event_hub';
-import { DIFF_FILE, GENERIC_ERROR } from '../i18n';
+import { DIFF_FILE, GENERIC_ERROR, CONFLICT_TEXT } from '../i18n';
import { collapsedType, getShortShaFromFile } from '../utils/diff_file';
import DiffContent from './diff_content.vue';
import DiffFileHeader from './diff_file_header.vue';
@@ -31,9 +38,11 @@ export default {
GlButton,
GlLoadingIcon,
GlSprintf,
+ GlAlert,
},
directives: {
SafeHtml,
+ GlModalDirective,
},
mixins: [glFeatureFlagsMixin(), IdState({ idProp: (vm) => vm.file.file_hash })],
props: {
@@ -83,6 +92,7 @@ export default {
idState() {
return {
isLoadingCollapsedDiff: false,
+ hasLoadedCollapsedDiff: false,
forkMessageVisible: false,
hasToggled: false,
};
@@ -92,7 +102,12 @@ export default {
genericError: GENERIC_ERROR,
},
computed: {
- ...mapState('diffs', ['currentDiffFileId', 'codequalityDiff']),
+ ...mapState('diffs', [
+ 'currentDiffFileId',
+ 'codequalityDiff',
+ 'conflictResolutionPath',
+ 'canMerge',
+ ]),
...mapGetters(['isNotesFetched']),
...mapGetters('diffs', ['getDiffFileDiscussions', 'isVirtualScrollingEnabled']),
viewBlobHref() {
@@ -181,7 +196,13 @@ export default {
},
'file.file_hash': {
handler: function hashChangeWatch(newHash, oldHash) {
- if (newHash && oldHash && !this.hasDiff && !this.preRender) {
+ if (
+ newHash &&
+ oldHash &&
+ !this.hasDiff &&
+ !this.preRender &&
+ !this.idState.hasLoadedCollapsedDiff
+ ) {
this.requestDiff();
}
},
@@ -198,6 +219,8 @@ export default {
if (this.hasDiff) {
this.postRender();
+ } else if (this.viewDiffsFileByFile && !this.isCollapsed) {
+ this.requestDiff();
}
this.manageViewedEffects();
@@ -265,14 +288,22 @@ export default {
}
},
requestDiff() {
- this.idState.isLoadingCollapsedDiff = true;
+ const { idState, file } = this;
- this.loadCollapsedDiff(this.file)
+ idState.isLoadingCollapsedDiff = true;
+
+ this.loadCollapsedDiff(file)
.then(() => {
- this.idState.isLoadingCollapsedDiff = false;
- this.setRenderIt(this.file);
+ idState.isLoadingCollapsedDiff = false;
+ idState.hasLoadedCollapsedDiff = true;
+
+ if (this.file.file_hash === file.file_hash) {
+ this.setRenderIt(this.file);
+ }
})
.then(() => {
+ if (this.file.file_hash !== file.file_hash) return;
+
requestIdleCallback(
() => {
this.postRender();
@@ -282,7 +313,7 @@ export default {
);
})
.catch(() => {
- this.idState.isLoadingCollapsedDiff = false;
+ idState.isLoadingCollapsedDiff = false;
createFlash({
message: this.$options.i18n.genericError,
});
@@ -295,6 +326,7 @@ export default {
this.idState.forkMessageVisible = false;
},
},
+ CONFLICT_TEXT,
};
</script>
@@ -373,6 +405,55 @@ export default {
<div v-else v-safe-html="errorMessage" class="nothing-here-block"></div>
</div>
<template v-else>
+ <gl-alert
+ v-if="file.conflict_type"
+ variant="danger"
+ :dismissible="false"
+ data-testid="conflictsAlert"
+ >
+ {{ $options.CONFLICT_TEXT[file.conflict_type] }}
+ <template v-if="!canMerge">
+ {{ __('Ask someone with write access to resolve it.') }}
+ </template>
+ <gl-sprintf
+ v-else-if="conflictResolutionPath"
+ :message="
+ __(
+ 'You can %{gitlabLinkStart}resolve conflicts on GitLab%{gitlabLinkEnd} or %{resolveLocallyStart}resolve it locally%{resolveLocallyEnd}.',
+ )
+ "
+ >
+ <template #gitlabLink="{ content }">
+ <gl-button
+ :href="conflictResolutionPath"
+ variant="link"
+ class="gl-vertical-align-text-bottom"
+ >{{ content }}</gl-button
+ >
+ </template>
+ <template #resolveLocally="{ content }">
+ <gl-button
+ v-gl-modal-directive="'modal-merge-info'"
+ variant="link"
+ class="gl-vertical-align-text-bottom"
+ >{{ content }}</gl-button
+ >
+ </template>
+ </gl-sprintf>
+ <gl-sprintf
+ v-else
+ :message="__('You can %{resolveLocallyStart}resolve it locally%{resolveLocallyEnd}.')"
+ >
+ <template #resolveLocally="{ content }">
+ <gl-button
+ v-gl-modal-directive="'modal-merge-info'"
+ variant="link"
+ class="gl-vertical-align-text-bottom"
+ >{{ content }}</gl-button
+ >
+ </template>
+ </gl-sprintf>
+ </gl-alert>
<div
v-if="showWarning"
class="collapsed-file-warning gl-p-7 gl-bg-orange-50 gl-text-center gl-rounded-bottom-left-base gl-rounded-bottom-right-base"
diff --git a/app/assets/javascripts/diffs/components/diff_gutter_avatars.vue b/app/assets/javascripts/diffs/components/diff_gutter_avatars.vue
index 1f3ec7092bc..e2f3f9cad7b 100644
--- a/app/assets/javascripts/diffs/components/diff_gutter_avatars.vue
+++ b/app/assets/javascripts/diffs/components/diff_gutter_avatars.vue
@@ -75,6 +75,7 @@ export default {
:key="note.id"
:img-src="note.author.avatar_url"
:tooltip-text="getTooltipText(note)"
+ lazy
class="diff-comment-avatar js-diff-comment-avatar"
@click.native="$emit('toggleLineDiscussions')"
/>
diff --git a/app/assets/javascripts/diffs/components/diff_row.vue b/app/assets/javascripts/diffs/components/diff_row.vue
index c310bd9f31a..db3ad074d2f 100644
--- a/app/assets/javascripts/diffs/components/diff_row.vue
+++ b/app/assets/javascripts/diffs/components/diff_row.vue
@@ -134,22 +134,13 @@ export default {
interopRightAttributes(props) {
return getInteropNewSideAttributes(props.line.right);
},
- conflictText: memoize(
- (line) => {
+ lineContent: (line) => {
+ if (line.isConflictMarker) {
return line.type === CONFLICT_MARKER_THEIR ? 'HEAD//our changes' : 'origin//their changes';
- },
- (line) => line.type,
- ),
- lineContent: memoize(
- (line) => {
- if (line.isConflictMarker) {
- return line.type === CONFLICT_MARKER_THEIR ? 'HEAD//our changes' : 'origin//their changes';
- }
+ }
- return line.rich_text;
- },
- (line) => line.line_code,
- ),
+ return line.rich_text;
+ },
CONFLICT_MARKER,
CONFLICT_MARKER_THEIR,
CONFLICT_OUR,
diff --git a/app/assets/javascripts/diffs/components/diff_stats.vue b/app/assets/javascripts/diffs/components/diff_stats.vue
index 05d4fbe7c20..e8b4ff16aec 100644
--- a/app/assets/javascripts/diffs/components/diff_stats.vue
+++ b/app/assets/javascripts/diffs/components/diff_stats.vue
@@ -62,8 +62,8 @@ export default {
</div>
<div v-else class="diff-stats-contents">
<div v-if="hasDiffFiles" class="diff-stats-group">
- <gl-icon name="doc-code" class="diff-stats-icon text-secondary" />
- <span class="text-secondary bold">{{ diffFilesCountText }} {{ filesText }}</span>
+ <gl-icon name="doc-code" class="diff-stats-icon gl-text-gray-500" />
+ <span class="gl-text-gray-500 bold">{{ diffFilesCountText }} {{ filesText }}</span>
</div>
<div
class="diff-stats-group gl-text-green-600 gl-display-flex gl-align-items-center"
diff --git a/app/assets/javascripts/diffs/components/settings_dropdown.vue b/app/assets/javascripts/diffs/components/settings_dropdown.vue
index 178f93b651e..2d9ac76b3e4 100644
--- a/app/assets/javascripts/diffs/components/settings_dropdown.vue
+++ b/app/assets/javascripts/diffs/components/settings_dropdown.vue
@@ -60,14 +60,14 @@ export default {
<gl-button
:class="{ selected: !renderTreeList }"
class="gl-w-half js-list-view"
- @click="setRenderTreeList(false)"
+ @click="setRenderTreeList({ renderTreeList: false })"
>
{{ __('List view') }}
</gl-button>
<gl-button
:class="{ selected: renderTreeList }"
class="gl-w-half js-tree-view"
- @click="setRenderTreeList(true)"
+ @click="setRenderTreeList({ renderTreeList: true })"
>
{{ __('Tree view') }}
</gl-button>
diff --git a/app/assets/javascripts/diffs/constants.js b/app/assets/javascripts/diffs/constants.js
index f1cf556fde0..8dda5eadb16 100644
--- a/app/assets/javascripts/diffs/constants.js
+++ b/app/assets/javascripts/diffs/constants.js
@@ -111,6 +111,8 @@ export const CONFLICT_MARKER_OUR = 'conflict_marker_our';
export const CONFLICT_MARKER_THEIR = 'conflict_marker_their';
// Tracking events
+export const DEFER_DURATION = 750;
+
export const TRACKING_CLICK_DIFF_VIEW_SETTING = 'i_code_review_click_diff_view_setting';
export const TRACKING_DIFF_VIEW_INLINE = 'i_code_review_diff_view_inline';
export const TRACKING_DIFF_VIEW_PARALLEL = 'i_code_review_diff_view_parallel';
diff --git a/app/assets/javascripts/diffs/i18n.js b/app/assets/javascripts/diffs/i18n.js
index a45fd92d0a9..e617890af2e 100644
--- a/app/assets/javascripts/diffs/i18n.js
+++ b/app/assets/javascripts/diffs/i18n.js
@@ -25,3 +25,25 @@ export const SETTINGS_DROPDOWN = {
fileByFile: __('Show one file at a time'),
preferences: __('Preferences'),
};
+
+export const CONFLICT_TEXT = {
+ both_modified: __('Conflict: This file was modified in both the source and target branches.'),
+ modified_source_removed_target: __(
+ 'Conflict: This file was modified in the source branch, but removed in the target branch.',
+ ),
+ modified_target_removed_source: __(
+ 'Conflict: This file was removed in the source branch, but modified in the target branch.',
+ ),
+ renamed_same_file: __(
+ 'Conflict: This file was renamed differently in the source and target branches.',
+ ),
+ removed_source_renamed_target: __(
+ 'Conflict: This file was removed in the source branch, but renamed in the target branch.',
+ ),
+ removed_target_renamed_source: __(
+ 'Conflict: This file was renamed in the source branch, but removed in the target branch.',
+ ),
+ both_added: __(
+ 'Conflict: This file was added both in the source and target branches, but with different contents.',
+ ),
+};
diff --git a/app/assets/javascripts/diffs/index.js b/app/assets/javascripts/diffs/index.js
index ea83523008c..bddc28c4758 100644
--- a/app/assets/javascripts/diffs/index.js
+++ b/app/assets/javascripts/diffs/index.js
@@ -2,6 +2,7 @@ import Cookies from 'js-cookie';
import Vue from 'vue';
import { mapActions, mapState, mapGetters } from 'vuex';
import { parseBoolean } from '~/lib/utils/common_utils';
+import { getParameterValues } from '~/lib/utils/url_utility';
import FindFile from '~/vue_shared/components/file_finder/index.vue';
import eventHub from '../notes/event_hub';
import diffsApp from './components/app.vue';
@@ -82,6 +83,9 @@ export default function initDiffsApp(store) {
showWhitespaceDefault: parseBoolean(dataset.showWhitespaceDefault),
viewDiffsFileByFile: parseBoolean(dataset.fileByFileDefault),
defaultSuggestionCommitMessage: dataset.defaultSuggestionCommitMessage,
+ sourceProjectDefaultUrl: dataset.sourceProjectDefaultUrl,
+ sourceProjectFullPath: dataset.sourceProjectFullPath,
+ isForked: parseBoolean(dataset.isForked),
};
},
computed: {
@@ -93,7 +97,7 @@ export default function initDiffsApp(store) {
const treeListStored = localStorage.getItem(TREE_LIST_STORAGE_KEY);
const renderTreeList = treeListStored !== null ? parseBoolean(treeListStored) : true;
- this.setRenderTreeList(renderTreeList);
+ this.setRenderTreeList({ renderTreeList, trackClick: false });
// NOTE: A "true" or "checked" value for `showWhitespace` is '0' not '1'.
// Check for cookie and save that setting for future use.
@@ -104,6 +108,7 @@ export default function initDiffsApp(store) {
this.setShowWhitespace({
url: this.endpointUpdateUser,
showWhitespace: hideWhitespace !== '1',
+ trackClick: false,
});
Cookies.remove(DIFF_WHITESPACE_COOKIE_NAME);
} else {
@@ -111,8 +116,14 @@ export default function initDiffsApp(store) {
this.setShowWhitespace({
showWhitespace: this.showWhitespaceDefault,
updateDatabase: false,
+ trackClick: false,
});
}
+
+ const vScrollingParam = getParameterValues('virtual_scrolling')[0];
+ if (vScrollingParam === 'false' || vScrollingParam === 'true') {
+ Cookies.set('diffs_virtual_scrolling', vScrollingParam);
+ }
},
methods: {
...mapActions('diffs', ['setRenderTreeList', 'setShowWhitespace']),
@@ -139,6 +150,9 @@ export default function initDiffsApp(store) {
fileByFileUserPreference: this.viewDiffsFileByFile,
defaultSuggestionCommitMessage: this.defaultSuggestionCommitMessage,
rehydratedMrReviews: getReviewsForMergeRequest(mrPath),
+ sourceProjectDefaultUrl: this.sourceProjectDefaultUrl,
+ sourceProjectFullPath: this.sourceProjectFullPath,
+ isForked: this.isForked,
},
});
},
diff --git a/app/assets/javascripts/diffs/store/actions.js b/app/assets/javascripts/diffs/store/actions.js
index 66510edf3db..f7bdbe94bac 100644
--- a/app/assets/javascripts/diffs/store/actions.js
+++ b/app/assets/javascripts/diffs/store/actions.js
@@ -1,6 +1,5 @@
import Cookies from 'js-cookie';
import Vue from 'vue';
-import api from '~/api';
import createFlash from '~/flash';
import { diffViewerModes } from '~/ide/constants';
import axios from '~/lib/utils/axios_utils';
@@ -50,6 +49,7 @@ import eventHub from '../event_hub';
import { isCollapsed } from '../utils/diff_file';
import { markFileReview, setReviewsForMergeRequest } from '../utils/file_reviews';
import { getDerivedMergeRequestInformation } from '../utils/merge_request';
+import { queueRedisHllEvents } from '../utils/queue_events';
import TreeWorker from '../workers/tree_worker';
import * as types from './mutation_types';
import {
@@ -368,8 +368,7 @@ export const setInlineDiffViewType = ({ commit }) => {
historyPushState(url);
if (window.gon?.features?.diffSettingsUsageData) {
- api.trackRedisHllUserEvent(TRACKING_CLICK_DIFF_VIEW_SETTING);
- api.trackRedisHllUserEvent(TRACKING_DIFF_VIEW_INLINE);
+ queueRedisHllEvents([TRACKING_CLICK_DIFF_VIEW_SETTING, TRACKING_DIFF_VIEW_INLINE]);
}
};
@@ -381,8 +380,7 @@ export const setParallelDiffViewType = ({ commit }) => {
historyPushState(url);
if (window.gon?.features?.diffSettingsUsageData) {
- api.trackRedisHllUserEvent(TRACKING_CLICK_DIFF_VIEW_SETTING);
- api.trackRedisHllUserEvent(TRACKING_DIFF_VIEW_PARALLEL);
+ queueRedisHllEvents([TRACKING_CLICK_DIFF_VIEW_SETTING, TRACKING_DIFF_VIEW_PARALLEL]);
}
};
@@ -520,14 +518,14 @@ export const toggleActiveFileByHash = ({ commit }, hash) => {
commit(types.VIEW_DIFF_FILE, hash);
};
-export const scrollToFile = ({ state, commit }, path) => {
+export const scrollToFile = ({ state, commit, getters }, path) => {
if (!state.treeEntries[path]) return;
const { fileHash } = state.treeEntries[path];
commit(types.VIEW_DIFF_FILE, fileHash);
- if (window.gon?.features?.diffsVirtualScrolling) {
+ if (getters.isVirtualScrollingEnabled) {
eventHub.$emit('scrollToFileHash', fileHash);
setTimeout(() => {
@@ -535,6 +533,10 @@ export const scrollToFile = ({ state, commit }, path) => {
});
} else {
document.location.hash = fileHash;
+
+ setTimeout(() => {
+ handleLocationHash();
+ });
}
};
@@ -560,25 +562,27 @@ export const closeDiffFileCommentForm = ({ commit }, fileHash) => {
commit(types.CLOSE_DIFF_FILE_COMMENT_FORM, fileHash);
};
-export const setRenderTreeList = ({ commit }, renderTreeList) => {
+export const setRenderTreeList = ({ commit }, { renderTreeList, trackClick = true }) => {
commit(types.SET_RENDER_TREE_LIST, renderTreeList);
localStorage.setItem(TREE_LIST_STORAGE_KEY, renderTreeList);
- if (window.gon?.features?.diffSettingsUsageData) {
- api.trackRedisHllUserEvent(TRACKING_CLICK_FILE_BROWSER_SETTING);
+ if (window.gon?.features?.diffSettingsUsageData && trackClick) {
+ const events = [TRACKING_CLICK_FILE_BROWSER_SETTING];
if (renderTreeList) {
- api.trackRedisHllUserEvent(TRACKING_FILE_BROWSER_TREE);
+ events.push(TRACKING_FILE_BROWSER_TREE);
} else {
- api.trackRedisHllUserEvent(TRACKING_FILE_BROWSER_LIST);
+ events.push(TRACKING_FILE_BROWSER_LIST);
}
+
+ queueRedisHllEvents(events);
}
};
export const setShowWhitespace = async (
{ state, commit },
- { url, showWhitespace, updateDatabase = true },
+ { url, showWhitespace, updateDatabase = true, trackClick = true },
) => {
if (updateDatabase && Boolean(window.gon?.current_user_id)) {
await axios.put(url || state.endpointUpdateUser, { show_whitespace_in_diffs: showWhitespace });
@@ -587,14 +591,16 @@ export const setShowWhitespace = async (
commit(types.SET_SHOW_WHITESPACE, showWhitespace);
notesEventHub.$emit('refetchDiffData');
- if (window.gon?.features?.diffSettingsUsageData) {
- api.trackRedisHllUserEvent(TRACKING_CLICK_WHITESPACE_SETTING);
+ if (window.gon?.features?.diffSettingsUsageData && trackClick) {
+ const events = [TRACKING_CLICK_WHITESPACE_SETTING];
if (showWhitespace) {
- api.trackRedisHllUserEvent(TRACKING_WHITESPACE_SHOW);
+ events.push(TRACKING_WHITESPACE_SHOW);
} else {
- api.trackRedisHllUserEvent(TRACKING_WHITESPACE_HIDE);
+ events.push(TRACKING_WHITESPACE_HIDE);
}
+
+ queueRedisHllEvents(events);
}
};
@@ -815,13 +821,15 @@ export const setFileByFile = ({ state, commit }, { fileByFile }) => {
Cookies.set(DIFF_FILE_BY_FILE_COOKIE_NAME, fileViewMode);
if (window.gon?.features?.diffSettingsUsageData) {
- api.trackRedisHllUserEvent(TRACKING_CLICK_SINGLE_FILE_SETTING);
+ const events = [TRACKING_CLICK_SINGLE_FILE_SETTING];
if (fileByFile) {
- api.trackRedisHllUserEvent(TRACKING_SINGLE_FILE_MODE);
+ events.push(TRACKING_SINGLE_FILE_MODE);
} else {
- api.trackRedisHllUserEvent(TRACKING_MULTIPLE_FILES_MODE);
+ events.push(TRACKING_MULTIPLE_FILES_MODE);
}
+
+ queueRedisHllEvents(events);
}
return axios
@@ -844,3 +852,5 @@ export function reviewFile({ commit, state }, { file, reviewed = true }) {
setReviewsForMergeRequest(mrPath, reviews);
commit(types.SET_MR_FILE_REVIEWS, reviews);
}
+
+export const disableVirtualScroller = ({ commit }) => commit(types.DISABLE_VIRTUAL_SCROLLING);
diff --git a/app/assets/javascripts/diffs/store/getters.js b/app/assets/javascripts/diffs/store/getters.js
index 1b6a673925f..18bd8e5f1d8 100644
--- a/app/assets/javascripts/diffs/store/getters.js
+++ b/app/assets/javascripts/diffs/store/getters.js
@@ -1,3 +1,4 @@
+import Cookies from 'js-cookie';
import { getParameterValues } from '~/lib/utils/url_utility';
import { __, n__ } from '~/locale';
import {
@@ -173,7 +174,20 @@ export function suggestionCommitMessage(state, _, rootState) {
});
}
-export const isVirtualScrollingEnabled = (state) =>
- !state.viewDiffsFileByFile &&
- (window.gon?.features?.diffsVirtualScrolling ||
- getParameterValues('virtual_scrolling')[0] === 'true');
+export const isVirtualScrollingEnabled = (state) => {
+ const vSrollerCookie = Cookies.get('diffs_virtual_scrolling');
+
+ if (state.disableVirtualScroller) {
+ return false;
+ }
+
+ if (vSrollerCookie) {
+ return vSrollerCookie === 'true';
+ }
+
+ return (
+ !state.viewDiffsFileByFile &&
+ (window.gon?.features?.diffsVirtualScrolling ||
+ getParameterValues('virtual_scrolling')[0] === 'true')
+ );
+};
diff --git a/app/assets/javascripts/diffs/store/modules/diff_state.js b/app/assets/javascripts/diffs/store/modules/diff_state.js
index 348dd452698..d76361513d4 100644
--- a/app/assets/javascripts/diffs/store/modules/diff_state.js
+++ b/app/assets/javascripts/diffs/store/modules/diff_state.js
@@ -43,4 +43,5 @@ export default () => ({
defaultSuggestionCommitMessage: '',
mrReviews: {},
latestDiff: true,
+ disableVirtualScroller: false,
});
diff --git a/app/assets/javascripts/diffs/store/mutation_types.js b/app/assets/javascripts/diffs/store/mutation_types.js
index 4641731c4b6..2c370221f40 100644
--- a/app/assets/javascripts/diffs/store/mutation_types.js
+++ b/app/assets/javascripts/diffs/store/mutation_types.js
@@ -47,3 +47,4 @@ export const SET_DIFF_FILE_VIEWER = 'SET_DIFF_FILE_VIEWER';
export const SET_SHOW_SUGGEST_POPOVER = 'SET_SHOW_SUGGEST_POPOVER';
export const TOGGLE_LINE_DISCUSSIONS = 'TOGGLE_LINE_DISCUSSIONS';
+export const DISABLE_VIRTUAL_SCROLLING = 'DISABLE_VIRTUAL_SCROLLING';
diff --git a/app/assets/javascripts/diffs/store/mutations.js b/app/assets/javascripts/diffs/store/mutations.js
index 9ff9a02d444..1aa83453bf7 100644
--- a/app/assets/javascripts/diffs/store/mutations.js
+++ b/app/assets/javascripts/diffs/store/mutations.js
@@ -362,4 +362,7 @@ export default {
[types.SET_MR_FILE_REVIEWS](state, newReviews) {
state.mrReviews = newReviews;
},
+ [types.DISABLE_VIRTUAL_SCROLLING](state) {
+ state.disableVirtualScroller = true;
+ },
};
diff --git a/app/assets/javascripts/diffs/utils/queue_events.js b/app/assets/javascripts/diffs/utils/queue_events.js
new file mode 100644
index 00000000000..08fcc98d45f
--- /dev/null
+++ b/app/assets/javascripts/diffs/utils/queue_events.js
@@ -0,0 +1,13 @@
+import { delay } from 'lodash';
+import api from '~/api';
+import { DEFER_DURATION } from '../constants';
+
+function trackRedisHllUserEvent(event, deferDuration = 0) {
+ delay(() => api.trackRedisHllUserEvent(event), deferDuration);
+}
+
+export function queueRedisHllEvents(events) {
+ events.forEach((event, index) => {
+ trackRedisHllUserEvent(event, DEFER_DURATION * (index + 1));
+ });
+}