From 78cfc7cf4afe0c7ffb72b8a9522b07873cd36820 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Tue, 15 Feb 2022 15:15:04 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- .../boards/components/boards_selector.vue | 54 ++--- .../graphql/group_recent_boards.query.graphql | 14 ++ .../project_recent_boards.query.graphql | 14 ++ app/assets/javascripts/boards/index.js | 1 - .../boards/mount_multiple_boards_switcher.js | 1 - .../javascripts/diffs/components/app.vue | 55 ++--- .../diffs/components/diff_file_header.vue | 2 +- app/assets/javascripts/diffs/constants.js | 2 - app/assets/javascripts/diffs/index.js | 8 +- app/assets/javascripts/diffs/store/actions.js | 16 +- app/assets/javascripts/diffs/store/getters.js | 17 +- app/assets/javascripts/diffs/store/utils.js | 18 +- .../add_extra_tokens_for_merge_requests.js | 15 ++ .../available_dropdown_mappings.js | 5 + .../javascripts/filtered_search/constants.js | 2 +- .../notes/mixins/discussion_navigation.js | 12 +- .../deployment/deployment_actions.vue | 20 +- app/assets/stylesheets/utilities.scss | 30 +++ app/controllers/dashboard_controller.rb | 4 + .../projects/merge_requests_controller.rb | 10 +- app/finders/merge_requests_finder.rb | 10 +- app/finders/merge_requests_finder/params.rb | 6 + .../members/effective_access_level_finder.rb | 12 +- app/helpers/boards_helper.rb | 5 - .../select_for_project_authorization.rb | 10 +- app/models/container_repository.rb | 10 +- app/models/merge_request.rb | 11 + .../namespaces/traversal/linear_scopes.rb | 11 + .../namespaces/traversal/recursive_scopes.rb | 5 + app/models/project.rb | 2 +- app/models/project_team.rb | 8 +- .../members/projects/creator_service.rb | 2 +- .../builder/project_maintainers.rb | 1 - app/services/projects/create_service.rb | 6 +- app/views/layouts/header/_default.html.haml | 2 +- .../layouts/header/_help_dropdown.html.haml | 1 + .../shared/issuable/_search_bar.html.haml | 10 + .../migration/guard_worker.rb | 56 ++++- .../development/diffs_virtual_scrolling.yml | 8 - .../permit_all_shared_groups_for_approval.yml | 8 + ...sal_ids_for_self_and_hierarchy_scopes.yml} | 6 +- ..._index_to_merge_request_assignees_state.rb | 15 ++ ..._index_to_merge_request_reviewers_state.rb | 15 ++ db/schema_migrations/20220127112243 | 1 + db/schema_migrations/20220127112412 | 1 + db/structure.sql | 4 + doc/topics/gitlab_flow.md | 6 +- doc/update/index.md | 8 +- doc/user/clusters/agent/troubleshooting.md | 2 +- doc/user/permissions.md | 17 +- doc/user/search/index.md | 27 ++- lib/container_registry/gitlab_api_client.rb | 4 + lib/container_registry/migration.rb | 5 + lib/gitlab/access.rb | 8 +- lib/gitlab/project_authorizations.rb | 2 +- locale/gitlab.pot | 33 +++ .../project_members_controller_spec.rb | 6 +- .../merge_request/batch_comments_spec.rb | 12 +- .../user_comments_on_diff_spec.rb | 45 ++-- .../merge_request/user_expands_diff_spec.rb | 4 +- ...er_interacts_with_batched_mr_diffs_spec.rb | 43 ++-- .../user_posts_diff_notes_spec.rb | 58 +++--- .../user_sees_avatar_on_diff_notes_spec.rb | 5 +- .../user_sees_deployment_widget_spec.rb | 6 +- .../merge_request/user_sees_diff_spec.rb | 21 +- .../merge_request/user_sees_versions_spec.rb | 10 +- .../user_suggests_changes_on_diff_spec.rb | 12 +- .../merge_requests_finder/params_spec.rb | 23 +++ spec/finders/merge_requests_finder_spec.rb | 16 ++ .../effective_access_level_finder_spec.rb | 70 ++----- .../boards/components/boards_selector_spec.js | 195 +++++++++--------- spec/frontend/boards/mock_data.js | 79 +++++++ spec/frontend/diffs/components/app_spec.js | 6 + spec/frontend/diffs/store/actions_spec.js | 2 +- .../mixins/discussion_navigation_spec.js | 29 +-- .../deployment/deployment_actions_spec.js | 64 ++++-- .../deployment/deployment_mock_data.js | 3 + .../lib/gitlab/project_authorizations_spec.rb | 26 +-- spec/models/container_repository_spec.rb | 10 + spec/models/merge_request_spec.rb | 14 ++ spec/models/project_team_spec.rb | 2 +- spec/models/user_spec.rb | 2 +- spec/requests/api/members_spec.rb | 29 +-- ...nd_records_due_for_refresh_service_spec.rb | 24 +-- .../members/projects/creator_service_spec.rb | 4 +- spec/services/notification_service_spec.rb | 4 +- spec/services/projects/create_service_spec.rb | 36 +--- ...efresh_authorized_projects_service_spec.rb | 12 +- spec/spec_helper.rb | 2 - .../helpers/merge_request_diff_helpers.rb | 54 +++++ .../helpers/note_interaction_helpers.rb | 4 +- ..._on_merge_request_files_shared_examples.rb | 2 +- .../namespaces/traversal_scope_examples.rb | 47 +++++ .../migration/guard_worker_spec.rb | 59 +++++- 94 files changed, 1060 insertions(+), 618 deletions(-) create mode 100644 app/assets/javascripts/boards/graphql/group_recent_boards.query.graphql create mode 100644 app/assets/javascripts/boards/graphql/project_recent_boards.query.graphql delete mode 100644 config/feature_flags/development/diffs_virtual_scrolling.yml create mode 100644 config/feature_flags/development/permit_all_shared_groups_for_approval.yml rename config/feature_flags/development/{personal_project_owner_with_owner_access.yml => use_traversal_ids_for_self_and_hierarchy_scopes.yml} (73%) create mode 100644 db/post_migrate/20220127112243_add_index_to_merge_request_assignees_state.rb create mode 100644 db/post_migrate/20220127112412_add_index_to_merge_request_reviewers_state.rb create mode 100644 db/schema_migrations/20220127112243 create mode 100644 db/schema_migrations/20220127112412 create mode 100644 spec/finders/merge_requests_finder/params_spec.rb diff --git a/app/assets/javascripts/boards/components/boards_selector.vue b/app/assets/javascripts/boards/components/boards_selector.vue index 69343cd78d8..6dbb1ea0050 100644 --- a/app/assets/javascripts/boards/components/boards_selector.vue +++ b/app/assets/javascripts/boards/components/boards_selector.vue @@ -14,8 +14,6 @@ import { mapActions, mapGetters, mapState } from 'vuex'; import BoardForm from 'ee_else_ce/boards/components/board_form.vue'; import { getIdFromGraphQLId } from '~/graphql_shared/utils'; -import axios from '~/lib/utils/axios_utils'; -import httpStatusCodes from '~/lib/utils/http_status'; import { s__ } from '~/locale'; import eventHub from '../eventhub'; @@ -23,6 +21,8 @@ import groupBoardsQuery from '../graphql/group_boards.query.graphql'; import projectBoardsQuery from '../graphql/project_boards.query.graphql'; import groupBoardQuery from '../graphql/group_board.query.graphql'; import projectBoardQuery from '../graphql/project_board.query.graphql'; +import groupRecentBoardsQuery from '../graphql/group_recent_boards.query.graphql'; +import projectRecentBoardsQuery from '../graphql/project_recent_boards.query.graphql'; const MIN_BOARDS_TO_VIEW_RECENT = 10; @@ -40,7 +40,7 @@ export default { directives: { GlModalDirective, }, - inject: ['fullPath', 'recentBoardsEndpoint'], + inject: ['fullPath'], props: { throttleDuration: { type: Number, @@ -158,6 +158,10 @@ export default { this.scrollFadeInitialized = false; this.$nextTick(this.setScrollFade); }, + recentBoards() { + this.scrollFadeInitialized = false; + this.$nextTick(this.setScrollFade); + }, }, created() { eventHub.$on('showBoardModal', this.showPage); @@ -173,11 +177,11 @@ export default { cancel() { this.showPage(''); }, - boardUpdate(data) { + boardUpdate(data, boardType) { if (!data?.[this.parentType]) { return []; } - return data[this.parentType].boards.edges.map(({ node }) => ({ + return data[this.parentType][boardType].edges.map(({ node }) => ({ id: getIdFromGraphQLId(node.id), name: node.name, })); @@ -185,6 +189,9 @@ export default { boardQuery() { return this.isGroupBoard ? groupBoardsQuery : projectBoardsQuery; }, + recentBoardsQuery() { + return this.isGroupBoard ? groupRecentBoardsQuery : projectRecentBoardsQuery; + }, loadBoards(toggleDropdown = true) { if (toggleDropdown && this.boards.length > 0) { return; @@ -196,39 +203,20 @@ export default { }, query: this.boardQuery, loadingKey: 'loadingBoards', - update: this.boardUpdate, + update: (data) => this.boardUpdate(data, 'boards'), }); this.loadRecentBoards(); }, loadRecentBoards() { - this.loadingRecentBoards = true; - // Follow up to fetch recent boards using GraphQL - // https://gitlab.com/gitlab-org/gitlab/-/issues/300985 - axios - .get(this.recentBoardsEndpoint) - .then((res) => { - this.recentBoards = res.data; - }) - .catch((err) => { - /** - * If user is unauthorized we'd still want to resolve the - * request to display all boards. - */ - if (err?.response?.status === httpStatusCodes.UNAUTHORIZED) { - this.recentBoards = []; // recent boards are empty - return; - } - throw err; - }) - .then(() => this.$nextTick()) // Wait for boards list in DOM - .then(() => { - this.setScrollFade(); - }) - .catch(() => {}) - .finally(() => { - this.loadingRecentBoards = false; - }); + this.$apollo.addSmartQuery('recentBoards', { + variables() { + return { fullPath: this.fullPath }; + }, + query: this.recentBoardsQuery, + loadingKey: 'loadingRecentBoards', + update: (data) => this.boardUpdate(data, 'recentIssueBoards'), + }); }, isScrolledUp() { const { content } = this.$refs; diff --git a/app/assets/javascripts/boards/graphql/group_recent_boards.query.graphql b/app/assets/javascripts/boards/graphql/group_recent_boards.query.graphql new file mode 100644 index 00000000000..827c08486b1 --- /dev/null +++ b/app/assets/javascripts/boards/graphql/group_recent_boards.query.graphql @@ -0,0 +1,14 @@ +#import "ee_else_ce/boards/graphql/board.fragment.graphql" + +query group_recent_boards($fullPath: ID!) { + group(fullPath: $fullPath) { + id + recentIssueBoards { + edges { + node { + ...BoardFragment + } + } + } + } +} diff --git a/app/assets/javascripts/boards/graphql/project_recent_boards.query.graphql b/app/assets/javascripts/boards/graphql/project_recent_boards.query.graphql new file mode 100644 index 00000000000..4d38e9b0498 --- /dev/null +++ b/app/assets/javascripts/boards/graphql/project_recent_boards.query.graphql @@ -0,0 +1,14 @@ +#import "ee_else_ce/boards/graphql/board.fragment.graphql" + +query project_recent_boards($fullPath: ID!) { + project(fullPath: $fullPath) { + id + recentIssueBoards { + edges { + node { + ...BoardFragment + } + } + } + } +} diff --git a/app/assets/javascripts/boards/index.js b/app/assets/javascripts/boards/index.js index ded3bfded86..9f44380781e 100644 --- a/app/assets/javascripts/boards/index.js +++ b/app/assets/javascripts/boards/index.js @@ -144,7 +144,6 @@ export default () => { mountMultipleBoardsSwitcher({ fullPath: $boardApp.dataset.fullPath, rootPath: $boardApp.dataset.boardsEndpoint, - recentBoardsEndpoint: $boardApp.dataset.recentBoardsEndpoint, allowScopedLabels: $boardApp.dataset.scopedLabels, labelsManagePath: $boardApp.dataset.labelsManagePath, }); diff --git a/app/assets/javascripts/boards/mount_multiple_boards_switcher.js b/app/assets/javascripts/boards/mount_multiple_boards_switcher.js index 26dd8b99f98..3838b4f2a83 100644 --- a/app/assets/javascripts/boards/mount_multiple_boards_switcher.js +++ b/app/assets/javascripts/boards/mount_multiple_boards_switcher.js @@ -24,7 +24,6 @@ export default (params = {}) => { provide: { fullPath: params.fullPath, rootPath: params.rootPath, - recentBoardsEndpoint: params.recentBoardsEndpoint, allowScopedLabels: params.allowScopedLabels, labelsManagePath: params.labelsManagePath, allowLabelCreate: parseBoolean(dataset.canAdminBoard), diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue index a8ca17ab4dd..5707e4d67f9 100644 --- a/app/assets/javascripts/diffs/components/app.vue +++ b/app/assets/javascripts/diffs/components/app.vue @@ -53,6 +53,7 @@ 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'; +import VirtualScrollerScrollSync from './virtual_scroller_scroll_sync'; export default { name: 'DiffsApp', @@ -62,8 +63,7 @@ export default { DynamicScrollerItem: () => import('vendor/vue-virtual-scroller').then(({ DynamicScrollerItem }) => DynamicScrollerItem), PreRenderer: () => import('./pre_renderer.vue').then((PreRenderer) => PreRenderer), - VirtualScrollerScrollSync: () => - import('./virtual_scroller_scroll_sync').then((VSSSync) => VSSSync), + VirtualScrollerScrollSync, CompareVersions, DiffFile, NoChanges, @@ -406,10 +406,8 @@ export default { this.unsubscribeFromEvents(); this.removeEventListeners(); - if (window.gon?.features?.diffsVirtualScrolling) { - diffsEventHub.$off('scrollToFileHash', this.scrollVirtualScrollerToFileHash); - diffsEventHub.$off('scrollToIndex', this.scrollVirtualScrollerToIndex); - } + diffsEventHub.$off('scrollToFileHash', this.scrollVirtualScrollerToFileHash); + diffsEventHub.$off('scrollToIndex', this.scrollVirtualScrollerToIndex); }, methods: { ...mapActions(['startTaskList']), @@ -522,32 +520,27 @@ export default { ); } - if ( - window.gon?.features?.diffsVirtualScrolling || - window.gon?.features?.usageDataDiffSearches - ) { - let keydownTime; - Mousetrap.bind(['mod+f', 'mod+g'], () => { - keydownTime = new Date().getTime(); - }); + let keydownTime; + Mousetrap.bind(['mod+f', 'mod+g'], () => { + keydownTime = new Date().getTime(); + }); - window.addEventListener('blur', () => { - if (keydownTime) { - const delta = new Date().getTime() - keydownTime; + 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(); + // 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?.usageDataDiffSearches) { - api.trackRedisHllUserEvent('i_code_review_user_searches_diff'); - api.trackRedisCounterEvent('diff_searches'); - } + if (window.gon?.features?.usageDataDiffSearches) { + api.trackRedisHllUserEvent('i_code_review_user_searches_diff'); + api.trackRedisCounterEvent('diff_searches'); } } - }); - } + } + }); }, removeEventListeners() { Mousetrap.unbind(keysFor(MR_PREVIOUS_FILE_IN_DIFF)); @@ -589,8 +582,6 @@ export default { this.virtualScrollCurrentIndex = -1; }, scrollVirtualScrollerToDiffNote() { - if (!window.gon?.features?.diffsVirtualScrolling) return; - const id = window?.location?.hash; if (id.startsWith('#note_')) { @@ -605,11 +596,7 @@ export default { } }, subscribeToVirtualScrollingEvents() { - if ( - window.gon?.features?.diffsVirtualScrolling && - this.shouldShow && - !this.subscribedToVirtualScrollingEvents - ) { + if (this.shouldShow && !this.subscribedToVirtualScrollingEvents) { diffsEventHub.$on('scrollToFileHash', this.scrollVirtualScrollerToFileHash); diffsEventHub.$on('scrollToIndex', this.scrollVirtualScrollerToIndex); diff --git a/app/assets/javascripts/diffs/components/diff_file_header.vue b/app/assets/javascripts/diffs/components/diff_file_header.vue index 0e8506cd896..3cf1f69b08c 100644 --- a/app/assets/javascripts/diffs/components/diff_file_header.vue +++ b/app/assets/javascripts/diffs/components/diff_file_header.vue @@ -209,7 +209,7 @@ export default { handler(val) { const el = this.$el.closest('.vue-recycle-scroller__item-view'); - if (this.glFeatures.diffsVirtualScrolling && el) { + if (el) { // We can't add a style with Vue because of the way the virtual // scroller library renders the diff files el.style.zIndex = val ? '1' : null; diff --git a/app/assets/javascripts/diffs/constants.js b/app/assets/javascripts/diffs/constants.js index c2eefad8f40..bbe27c0dbd6 100644 --- a/app/assets/javascripts/diffs/constants.js +++ b/app/assets/javascripts/diffs/constants.js @@ -29,8 +29,6 @@ export const UNFOLD_COUNT = 20; export const COUNT_OF_AVATARS_IN_GUTTER = 3; export const LENGTH_OF_AVATAR_TOOLTIP = 17; -export const LINES_TO_BE_RENDERED_DIRECTLY = 100; - export const DIFF_FILE_SYMLINK_MODE = '120000'; export const DIFF_FILE_DELETED_MODE = '0'; diff --git a/app/assets/javascripts/diffs/index.js b/app/assets/javascripts/diffs/index.js index dfe29e767c9..1691da34c6d 100644 --- a/app/assets/javascripts/diffs/index.js +++ b/app/assets/javascripts/diffs/index.js @@ -1,8 +1,7 @@ import Vue from 'vue'; import { mapActions, mapState, mapGetters } from 'vuex'; -import { getCookie, setCookie, parseBoolean, removeCookie } from '~/lib/utils/common_utils'; +import { getCookie, parseBoolean, removeCookie } from '~/lib/utils/common_utils'; -import { getParameterValues } from '~/lib/utils/url_utility'; import eventHub from '../notes/event_hub'; import diffsApp from './components/app.vue'; @@ -74,11 +73,6 @@ export default function initDiffsApp(store) { trackClick: false, }); } - - const vScrollingParam = getParameterValues('virtual_scrolling')[0]; - if (vScrollingParam === 'false' || vScrollingParam === 'true') { - setCookie('diffs_virtual_scrolling', vScrollingParam); - } }, methods: { ...mapActions('diffs', ['setRenderTreeList', 'setShowWhitespace']), diff --git a/app/assets/javascripts/diffs/store/actions.js b/app/assets/javascripts/diffs/store/actions.js index 572949e585a..e967be23f42 100644 --- a/app/assets/javascripts/diffs/store/actions.js +++ b/app/assets/javascripts/diffs/store/actions.js @@ -125,7 +125,7 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => { commit(types.SET_DIFF_DATA_BATCH, { diff_files }); commit(types.SET_BATCH_LOADING_STATE, 'loaded'); - if (window.gon?.features?.diffsVirtualScrolling && !scrolledVirtualScroller) { + if (!scrolledVirtualScroller) { const index = state.diffFiles.findIndex( (f) => f.file_hash === hash || f[INLINE_DIFF_LINES_KEY].find((l) => l.line_code === hash), @@ -195,9 +195,7 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => { commit(types.SET_BATCH_LOADING_STATE, 'error'); }); - return getBatch().then( - () => !window.gon?.features?.diffsVirtualScrolling && handleLocationHash(), - ); + return getBatch(); }; export const fetchDiffFilesMeta = ({ commit, state }) => { @@ -529,7 +527,7 @@ export const setCurrentFileHash = ({ commit }, hash) => { commit(types.SET_CURRENT_DIFF_FILE, hash); }; -export const scrollToFile = ({ state, commit, getters }, { path, setHash = true }) => { +export const scrollToFile = ({ state, commit, getters }, { path }) => { if (!state.treeEntries[path]) return; const { fileHash } = state.treeEntries[path]; @@ -539,11 +537,9 @@ export const scrollToFile = ({ state, commit, getters }, { path, setHash = true if (getters.isVirtualScrollingEnabled) { eventHub.$emit('scrollToFileHash', fileHash); - if (setHash) { - setTimeout(() => { - window.history.replaceState(null, null, `#${fileHash}`); - }); - } + setTimeout(() => { + window.history.replaceState(null, null, `#${fileHash}`); + }); } else { document.location.hash = fileHash; diff --git a/app/assets/javascripts/diffs/store/getters.js b/app/assets/javascripts/diffs/store/getters.js index 83c7f8c814b..3a85c1a9fe1 100644 --- a/app/assets/javascripts/diffs/store/getters.js +++ b/app/assets/javascripts/diffs/store/getters.js @@ -1,6 +1,5 @@ -import { getCookie } from '~/lib/utils/common_utils'; -import { getParameterValues } from '~/lib/utils/url_utility'; import { __, n__ } from '~/locale'; +import { getParameterValues } from '~/lib/utils/url_utility'; import { PARALLEL_DIFF_VIEW_TYPE, INLINE_DIFF_VIEW_TYPE, @@ -175,21 +174,11 @@ export function suggestionCommitMessage(state, _, rootState) { } export const isVirtualScrollingEnabled = (state) => { - const vSrollerCookie = getCookie('diffs_virtual_scrolling'); - - if (state.disableVirtualScroller) { + if (state.disableVirtualScroller || getParameterValues('virtual_scrolling')[0] === 'false') { return false; } - if (vSrollerCookie) { - return vSrollerCookie === 'true'; - } - - return ( - !state.viewDiffsFileByFile && - (window.gon?.features?.diffsVirtualScrolling || - getParameterValues('virtual_scrolling')[0] === 'true') - ); + return !state.viewDiffsFileByFile; }; export const isBatchLoading = (state) => state.batchLoadingState === 'loading'; diff --git a/app/assets/javascripts/diffs/store/utils.js b/app/assets/javascripts/diffs/store/utils.js index 3f1af68e37a..f2028892a5f 100644 --- a/app/assets/javascripts/diffs/store/utils.js +++ b/app/assets/javascripts/diffs/store/utils.js @@ -9,7 +9,6 @@ import { NEW_LINE_TYPE, OLD_LINE_TYPE, MATCH_LINE_TYPE, - LINES_TO_BE_RENDERED_DIRECTLY, INLINE_DIFF_LINES_KEY, CONFLICT_OUR, CONFLICT_THEIR, @@ -380,16 +379,9 @@ function prepareDiffFileLines(file) { return file; } -function finalizeDiffFile(file, index) { - let renderIt = Boolean(window.gon?.features?.diffsVirtualScrolling); - - if (!window.gon?.features?.diffsVirtualScrolling) { - renderIt = - index < 3 ? file[INLINE_DIFF_LINES_KEY].length < LINES_TO_BE_RENDERED_DIRECTLY : false; - } - +function finalizeDiffFile(file) { Object.assign(file, { - renderIt, + renderIt: true, isShowingFullFile: false, isLoadingFullFile: false, discussions: [], @@ -417,15 +409,13 @@ export function prepareDiffData({ diff, priorFiles = [], meta = false }) { .map((file, index, allFiles) => prepareRawDiffFile({ file, allFiles, meta })) .map(ensureBasicDiffFileLines) .map(prepareDiffFileLines) - .map((file, index) => finalizeDiffFile(file, priorFiles.length + index)); + .map((file) => finalizeDiffFile(file)); return deduplicateFilesList([...priorFiles, ...cleanedFiles]); } export function getDiffPositionByLineCode(diffFiles) { - let lines = []; - - lines = diffFiles.reduce((acc, diffFile) => { + const lines = diffFiles.reduce((acc, diffFile) => { diffFile[INLINE_DIFF_LINES_KEY].forEach((line) => { acc.push({ file: diffFile, line }); }); diff --git a/app/assets/javascripts/filtered_search/add_extra_tokens_for_merge_requests.js b/app/assets/javascripts/filtered_search/add_extra_tokens_for_merge_requests.js index d00e6e59cf5..28a3c54cc8f 100644 --- a/app/assets/javascripts/filtered_search/add_extra_tokens_for_merge_requests.js +++ b/app/assets/javascripts/filtered_search/add_extra_tokens_for_merge_requests.js @@ -13,6 +13,21 @@ export default (IssuableTokenKeys, disableTargetBranchFilter = false) => { IssuableTokenKeys.tokenKeys.splice(2, 0, reviewerToken); IssuableTokenKeys.tokenKeysWithAlternative.splice(2, 0, reviewerToken); + if (window.gon?.features?.mrAttentionRequests) { + const attentionRequestedToken = { + formattedKey: __('Attention'), + key: 'attention', + type: 'string', + param: '', + symbol: '@', + icon: 'user', + tag: '@attention', + hideNotEqual: true, + }; + IssuableTokenKeys.tokenKeys.splice(2, 0, attentionRequestedToken); + IssuableTokenKeys.tokenKeysWithAlternative.splice(2, 0, attentionRequestedToken); + } + const draftToken = { token: { formattedKey: __('Draft'), diff --git a/app/assets/javascripts/filtered_search/available_dropdown_mappings.js b/app/assets/javascripts/filtered_search/available_dropdown_mappings.js index 3cd4d48a4a3..09cef74477c 100644 --- a/app/assets/javascripts/filtered_search/available_dropdown_mappings.js +++ b/app/assets/javascripts/filtered_search/available_dropdown_mappings.js @@ -77,6 +77,11 @@ export default class AvailableDropdownMappings { gl: DropdownUser, element: this.container.querySelector('#js-dropdown-reviewer'), }, + attention: { + reference: null, + gl: DropdownUser, + element: this.container.getElementById('js-dropdown-attention-requested'), + }, 'approved-by': { reference: null, gl: DropdownUser, diff --git a/app/assets/javascripts/filtered_search/constants.js b/app/assets/javascripts/filtered_search/constants.js index e2d6936acbd..f8b5910de9e 100644 --- a/app/assets/javascripts/filtered_search/constants.js +++ b/app/assets/javascripts/filtered_search/constants.js @@ -1,4 +1,4 @@ -export const USER_TOKEN_TYPES = ['author', 'assignee', 'approved-by', 'reviewer']; +export const USER_TOKEN_TYPES = ['author', 'assignee', 'approved-by', 'reviewer', 'attention']; export const DROPDOWN_TYPE = { hint: 'hint', diff --git a/app/assets/javascripts/notes/mixins/discussion_navigation.js b/app/assets/javascripts/notes/mixins/discussion_navigation.js index ad529eb99b6..93236b05100 100644 --- a/app/assets/javascripts/notes/mixins/discussion_navigation.js +++ b/app/assets/javascripts/notes/mixins/discussion_navigation.js @@ -3,8 +3,6 @@ import { scrollToElementWithContext, scrollToElement } from '~/lib/utils/common_ import { updateHistory } from '../../lib/utils/url_utility'; import eventHub from '../event_hub'; -const isDiffsVirtualScrollingEnabled = () => window.gon?.features?.diffsVirtualScrolling; - /** * @param {string} selector * @returns {boolean} @@ -15,7 +13,7 @@ function scrollTo(selector, { withoutContext = false } = {}) { if (el) { scrollFunction(el, { - behavior: isDiffsVirtualScrollingEnabled() ? 'auto' : 'smooth', + behavior: 'auto', }); return true; } @@ -31,7 +29,7 @@ function updateUrlWithNoteId(noteId) { replace: true, }; - if (noteId && isDiffsVirtualScrollingEnabled()) { + if (noteId) { // Temporarily mask the ID to avoid the browser default // scrolling taking over which is broken with virtual // scrolling enabled. @@ -115,17 +113,13 @@ function handleDiscussionJump(self, fn, discussionId = self.currentDiscussionId) const isDiffView = window.mrTabs.currentAction === 'diffs'; const targetId = fn(discussionId, isDiffView); const discussion = self.getDiscussion(targetId); - const setHash = !isDiffView && !isDiffsVirtualScrollingEnabled(); const discussionFilePath = discussion?.diff_file?.file_path; - if (isDiffsVirtualScrollingEnabled()) { - window.location.hash = ''; - } + window.location.hash = ''; if (discussionFilePath) { self.scrollToFile({ path: discussionFilePath, - setHash, }); } diff --git a/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_actions.vue b/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_actions.vue index 5ef7c2f72e0..7ba387c79b1 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_actions.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_actions.vue @@ -1,5 +1,6 @@