diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-05-17 00:09:09 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-05-17 00:09:09 +0300 |
commit | cffe2c2c348d86d67298fa6516d49c36d696ab2d (patch) | |
tree | 9511c62edd677012325946d19e4d2df4a9733aa1 /app | |
parent | 7ff36fc6e9f0f5dffb41bfc79b4f07b2ce93e1c7 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
31 files changed, 272 insertions, 154 deletions
diff --git a/app/assets/javascripts/flash.js b/app/assets/javascripts/flash.js index c9b6a4f9913..5a47e76d597 100644 --- a/app/assets/javascripts/flash.js +++ b/app/assets/javascripts/flash.js @@ -86,48 +86,43 @@ const addDismissFlashClickListener = (flashEl, fadeTransition) => { /** * Render an alert at the top of the page, or, optionally an - * arbitrary existing container. - * - * This alert is always dismissible. - * - * Usage: - * - * 1. Render a new alert + * arbitrary existing container. This alert is always dismissible. * + * @example + * // Render a new alert * import { createAlert, VARIANT_WARNING } from '~/flash'; * * createAlert({ message: 'My error message' }); * createAlert({ message: 'My warning message', variant: VARIANT_WARNING }); * - * 2. Dismiss this alert programmatically - * + * @example + * // Dismiss this alert programmatically * const alert = createAlert({ message: 'Message' }); * * // ... * * alert.dismiss(); * - * 3. Respond to the alert being dismissed - * - * createAlert({ message: 'Message', onDismiss: () => { ... }}); + * @example + * // Respond to the alert being dismissed + * createAlert({ message: 'Message', onDismiss: () => {} }); * - * @param {Object} options Options to control the flash message - * @param {String} options.message Alert message text - * @param {String?} options.variant Which GlAlert variant to use, should be VARIANT_SUCCESS, VARIANT_WARNING, VARIANT_DANGER, VARIANT_INFO or VARIANT_TIP. Defaults to VARIANT_DANGER. - * @param {Object?} options.parent Reference to parent element under which alert needs to appear. Defaults to `document`. - * @param {Function?} options.onDismiss Handler to call when this alert is dismissed. - * @param {Object?} options.containerSelector Selector for the container of the alert - * @param {Object?} options.primaryButton Object describing primary button of alert - * @param {String?} link Href of primary button - * @param {String?} text Text of primary button - * @param {Function?} clickHandler Handler to call when primary button is clicked on. The click event is sent as an argument. - * @param {Object?} options.secondaryButton Object describing secondary button of alert - * @param {String?} link Href of secondary button - * @param {String?} text Text of secondary button - * @param {Function?} clickHandler Handler to call when secondary button is clicked on. The click event is sent as an argument. - * @param {Boolean?} options.captureError Whether to send error to Sentry - * @param {Object} options.error Error to be captured in Sentry - * @returns + * @param {object} options - Options to control the flash message + * @param {string} options.message - Alert message text + * @param {VARIANT_SUCCESS|VARIANT_WARNING|VARIANT_DANGER|VARIANT_INFO|VARIANT_TIP} [options.variant] - Which GlAlert variant to use; it defaults to VARIANT_DANGER. + * @param {object} [options.parent] - Reference to parent element under which alert needs to appear. Defaults to `document`. + * @param {Function} [options.onDismiss] - Handler to call when this alert is dismissed. + * @param {string} [options.containerSelector] - Selector for the container of the alert + * @param {object} [options.primaryButton] - Object describing primary button of alert + * @param {string} [options.primaryButton.link] - Href of primary button + * @param {string} [options.primaryButton.text] - Text of primary button + * @param {Function} [options.primaryButton.clickHandler] - Handler to call when primary button is clicked on. The click event is sent as an argument. + * @param {object} [options.secondaryButton] - Object describing secondary button of alert + * @param {string} [options.secondaryButton.link] - Href of secondary button + * @param {string} [options.secondaryButton.text] - Text of secondary button + * @param {Function} [options.secondaryButton.clickHandler] - Handler to call when secondary button is clicked on. The click event is sent as an argument. + * @param {boolean} [options.captureError] - Whether to send error to Sentry + * @param {object} [options.error] - Error to be captured in Sentry */ const createAlert = function createAlert({ message, @@ -208,22 +203,24 @@ const createAlert = function createAlert({ }; /** - * Flash banner supports different types of Flash configurations - * along with ability to provide actionConfig which can be used to show - * additional action or link on banner next to message + * @deprecated use `createAlert` instead + * + * Flash banner supports different types of Flash configurations + * along with ability to provide actionConfig which can be used to show + * additional action or link on banner next to message * - * @param {Object} options Options to control the flash message - * @param {String} options.message Flash message text - * @param {String} options.type Type of Flash, it can be `notice`, `success`, `warning` or `alert` (default) - * @param {Object} options.parent Reference to parent element under which Flash needs to appear - * @param {Object} options.actionConfig Map of config to show action on banner - * @param {String} href URL to which action config should point to (default: '#') - * @param {String} title Title of action - * @param {Function} clickHandler Method to call when action is clicked on - * @param {Boolean} options.fadeTransition Boolean to determine whether to fade the alert out - * @param {Boolean} options.captureError Boolean to determine whether to send error to Sentry - * @param {Object} options.error Error to be captured in Sentry - * @deprecated Use `createAlert` instead. See https://gitlab.com/gitlab-org/gitlab/-/issues/362334. + * @param {object} options - Options to control the flash message + * @param {string} options.message - Flash message text + * @param {'alert'|'notice'|'success'|'warning'} [options.type] - Type of Flash; it defaults to 'alert' + * @param {Element|Document} [options.parent] - Reference to parent element under which Flash needs to appear + * @param {object} [options.actionConfig] - Map of config to show action on banner + * @param {string} [options.actionConfig.href] - URL to which action config should point to (default: '#') + * @param {string} [options.actionConfig.title] - Title of action + * @param {Function} [options.actionConfig.clickHandler] - Method to call when action is clicked on + * @param {boolean} [options.fadeTransition] - Boolean to determine whether to fade the alert out + * @param {boolean} [options.addBodyClass] - Adds `flash-shown` class to the `body` element + * @param {boolean} [options.captureError] - Boolean to determine whether to send error to Sentry + * @param {object} [options.error] - Error to be captured in Sentry */ const createFlash = function createFlash({ message, diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js index 4101b520e80..2f3cdc525a7 100644 --- a/app/assets/javascripts/main.js +++ b/app/assets/javascripts/main.js @@ -195,7 +195,11 @@ $body.on('click', 'a[href^="#"]', function clickHashLinkCallback() { * Quick fix: Get rid of jQuery for this implementation */ const isBoardsPage = /(projects|groups):boards:show/.test(document.body.dataset.page); -if (!isBoardsPage && (bootstrapBreakpoint === 'sm' || bootstrapBreakpoint === 'xs')) { +if ( + !isBoardsPage && + !window.gon?.features?.movedMrSidebar && + (bootstrapBreakpoint === 'sm' || bootstrapBreakpoint === 'xs') +) { const $rightSidebar = $('aside.right-sidebar'); const $layoutPage = $('.layout-page'); diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js index 61f7a079d77..e02109d1fd1 100644 --- a/app/assets/javascripts/merge_request_tabs.js +++ b/app/assets/javascripts/merge_request_tabs.js @@ -1,5 +1,4 @@ /* eslint-disable no-new, class-methods-use-this */ -import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils'; import $ from 'jquery'; import Vue from 'vue'; import { getCookie, isMetaClick, parseBoolean, scrollToElement } from '~/lib/utils/common_utils'; @@ -176,6 +175,8 @@ export default class MergeRequestTabs { : null; this.navbar = document.querySelector('.navbar-gitlab'); this.peek = document.getElementById('js-peek'); + this.sidebar = document.querySelector('.js-right-sidebar'); + this.pageLayout = document.querySelector('.layout-page'); this.paddingTop = 16; this.scrollPositions = {}; @@ -282,7 +283,7 @@ export default class MergeRequestTabs { if (action === 'commits') { this.loadCommits(href); - this.expandView(); + // this.hideSidebar(); this.resetViewContainer(); this.commitPipelinesTable = destroyPipelines(this.commitPipelinesTable); } else if (action === 'new') { @@ -301,13 +302,12 @@ export default class MergeRequestTabs { */ this.loadDiff(href); } - if (bp.getBreakpointSize() !== 'xl') { - this.shrinkView(); - } + // this.hideSidebar(); this.expandViewContainer(); this.commitPipelinesTable = destroyPipelines(this.commitPipelinesTable); this.commitsTab.classList.remove('active'); } else if (action === 'pipelines') { + // this.hideSidebar(); this.resetViewContainer(); this.mountPipelinesView(); } else { @@ -320,9 +320,7 @@ export default class MergeRequestTabs { notesTab.classList.add('active'); } - if (bp.getBreakpointSize() !== 'xs') { - this.expandView(); - } + // this.showSidebar(); this.resetViewContainer(); this.commitPipelinesTable = destroyPipelines(this.commitPipelinesTable); } @@ -509,19 +507,6 @@ export default class MergeRequestTabs { } } - shrinkView() { - const $gutterBtn = $('.js-sidebar-toggle:visible'); - const $expandSvg = $gutterBtn.find('.js-sidebar-expand'); - - // Wait until listeners are set - setTimeout(() => { - // Only when sidebar is expanded - if ($expandSvg.length && $expandSvg.hasClass('hidden')) { - $gutterBtn.trigger('click', [true]); - } - }, 0); - } - // Expand the issuable sidebar unless the user explicitly collapsed it expandView() { if (parseBoolean(getCookie('collapsed_gutter'))) { @@ -538,4 +523,24 @@ export default class MergeRequestTabs { } }, 0); } + + hideSidebar() { + if (!isInVueNoteablePage() || this.cachedPageLayoutClasses) return; + + this.cachedPageLayoutClasses = this.pageLayout.className; + this.pageLayout.classList.remove( + 'right-sidebar-collapsed', + 'right-sidebar-expanded', + 'page-with-icon-sidebar', + ); + this.sidebar.style.width = '0px'; + } + + showSidebar() { + if (!isInVueNoteablePage() || !this.cachedPageLayoutClasses) return; + + this.pageLayout.className = this.cachedPageLayoutClasses; + this.sidebar.style.width = ''; + delete this.cachedPageLayoutClasses; + } } diff --git a/app/assets/javascripts/right_sidebar.js b/app/assets/javascripts/right_sidebar.js index 009afe03ea6..a3abc8b8e90 100644 --- a/app/assets/javascripts/right_sidebar.js +++ b/app/assets/javascripts/right_sidebar.js @@ -7,6 +7,18 @@ import createFlash from './flash'; import axios from './lib/utils/axios_utils'; import { sprintf, s__, __ } from './locale'; +const updateSidebarClasses = (layoutPage, rightSidebar) => { + if (window.innerWidth >= 768) { + layoutPage.classList.remove('right-sidebar-expanded', 'right-sidebar-collapsed'); + rightSidebar.classList.remove('right-sidebar-collapsed'); + rightSidebar.classList.add('right-sidebar-expanded'); + } else { + layoutPage.classList.add('right-sidebar-collapsed', 'is-merge-request'); + rightSidebar.classList.add('right-sidebar-collapsed'); + rightSidebar.classList.remove('right-sidebar-expanded'); + } +}; + function Sidebar() { this.toggleTodo = this.toggleTodo.bind(this); this.sidebar = $('aside'); @@ -42,13 +54,22 @@ Sidebar.prototype.addEventListeners = function () { this.sidebar.on('hiddenGlDropdown', this, this.onSidebarDropdownHidden); $document.on('click', '.js-sidebar-toggle', this.sidebarToggleClicked); - return $(document) - .off('click', '.js-issuable-todo') - .on('click', '.js-issuable-todo', this.toggleTodo); + $(document).off('click', '.js-issuable-todo').on('click', '.js-issuable-todo', this.toggleTodo); + + if (window.gon?.features?.movedMrSidebar) { + const layoutPage = document.querySelector('.layout-page'); + const rightSidebar = document.querySelector('.js-right-sidebar'); + + updateSidebarClasses(layoutPage, rightSidebar); + window.addEventListener('resize', () => updateSidebarClasses(layoutPage, rightSidebar)); + } }; Sidebar.prototype.sidebarToggleClicked = function (e, triggered) { const $this = $(this); + + if ($this.hasClass('right-sidebar-merge-requests')) return; + const $collapseIcon = $('.js-sidebar-collapse'); const $expandIcon = $('.js-sidebar-expand'); const $toggleContainer = $('.js-sidebar-toggle-container'); diff --git a/app/assets/javascripts/sidebar/components/assignees/assignee_title.vue b/app/assets/javascripts/sidebar/components/assignees/assignee_title.vue index 68deb3761a3..6e18cf36690 100644 --- a/app/assets/javascripts/sidebar/components/assignees/assignee_title.vue +++ b/app/assets/javascripts/sidebar/components/assignees/assignee_title.vue @@ -1,6 +1,7 @@ <script> import { GlLoadingIcon, GlIcon } from '@gitlab/ui'; import { n__, __ } from '~/locale'; +import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; export default { name: 'AssigneeTitle', @@ -8,6 +9,7 @@ export default { GlLoadingIcon, GlIcon, }, + mixins: [glFeatureFlagMixin()], props: { loading: { type: Boolean, @@ -63,6 +65,7 @@ export default { v-if="showToggle" :aria-label="__('Toggle sidebar')" class="gutter-toggle float-right js-sidebar-toggle" + :class="{ 'gl-display-block gl-md-display-none!': glFeatures.movedMrSidebar }" href="#" role="button" > diff --git a/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue b/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue index 63ba5c31809..b0502202b0e 100644 --- a/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue +++ b/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue @@ -111,12 +111,6 @@ export default { /> <div data-testid="lock-status" class="sidebar-item-value" :class="lockStatus.class"> - <gl-icon - :size="16" - :name="lockStatus.icon" - class="sidebar-item-icon" - :class="lockStatus.iconClass" - /> {{ lockStatus.displayText }} </div> </div> diff --git a/app/assets/javascripts/sidebar/components/participants/participants.vue b/app/assets/javascripts/sidebar/components/participants/participants.vue index fbecb21ecbd..77e41648e9b 100644 --- a/app/assets/javascripts/sidebar/components/participants/participants.vue +++ b/app/assets/javascripts/sidebar/components/participants/participants.vue @@ -103,7 +103,7 @@ export default { </div> <div v-if="showParticipantLabel" - class="title hide-collapsed gl-mb-2 gl-line-height-20 gl-font-weight-bold" + class="title hide-collapsed gl-mb-2! gl-line-height-20 gl-font-weight-bold" > <gl-loading-icon v-if="loading" size="sm" :inline="true" /> {{ participantLabel }} diff --git a/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue b/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue index ee3972ab3d5..2f58e11c00f 100644 --- a/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue +++ b/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue @@ -98,7 +98,7 @@ export default { 'gl-mb-3': index !== users.length - 1, 'attention-requests': glFeatures.mrAttentionRequests, }" - class="gl-display-grid gl-align-items-center reviewer-grid" + class="gl-display-grid gl-align-items-center reviewer-grid gl-mr-2" data-testid="reviewer" > <reviewer-avatar-link diff --git a/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue b/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue index 7a10a9f3a4c..1bafa845665 100644 --- a/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue +++ b/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue @@ -5,6 +5,7 @@ import { IssuableType } from '~/issues/constants'; import { isLoggedIn } from '~/lib/utils/common_utils'; import { __, sprintf } from '~/locale'; import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue'; +import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { subscribedQueries, Tracking } from '~/sidebar/constants'; const ICON_ON = 'notifications'; @@ -25,6 +26,7 @@ export default { GlToggle, SidebarEditableItem, }, + mixins: [glFeatureFlagMixin()], props: { iid: { type: String, @@ -82,6 +84,9 @@ export default { }, }, computed: { + isMergeRequest() { + return this.issuableType === IssuableType.MergeRequest && this.glFeatures.movedMrSidebar; + }, isLoading() { return this.$apollo.queries?.subscribed?.loading || this.loading; }, @@ -171,7 +176,20 @@ export default { </script> <template> + <li v-if="isMergeRequest" class="gl-new-dropdown-item"> + <button type="button" class="dropdown-item" @click="toggleSubscribed"> + <span class="gl-new-dropdown-item-text-wrapper"> + <template v-if="subscribed"> + {{ __('Turn off notifications') }} + </template> + <template v-else> + {{ __('Turn on notifications') }} + </template> + </span> + </button> + </li> <sidebar-editable-item + v-else ref="editable" :title="$options.i18n.notifications" :tracking="$options.tracking" diff --git a/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue b/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue index e7d47634af2..057bb9f0100 100644 --- a/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue +++ b/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue @@ -204,7 +204,7 @@ export default { :time-estimate-human-readable="humanTimeEstimate" /> <div - class="hide-collapsed gl-line-height-20 gl-text-gray-900 gl-display-flex gl-align-items-center gl-font-weight-bold" + class="hide-collapsed gl-line-height-20 gl-text-gray-900 gl-display-flex gl-align-items-center gl-font-weight-bold gl-mr-3" > {{ __('Time tracking') }} <gl-loading-icon v-if="isTimeTrackingInfoLoading" size="sm" class="gl-ml-2" inline /> diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss index 87dac85d4cd..7c5ccd07913 100644 --- a/app/assets/stylesheets/framework/sidebar.scss +++ b/app/assets/stylesheets/framework/sidebar.scss @@ -19,13 +19,23 @@ .right-sidebar-collapsed { padding-right: 0; - @include media-breakpoint-up(sm) { - &:not(.wiki-sidebar):not(.build-sidebar):not(.issuable-bulk-update-sidebar) .content-wrapper { - padding-right: $gutter-collapsed-width; + &:not(.is-merge-request) { + @include media-breakpoint-up(sm) { + &:not(.wiki-sidebar):not(.build-sidebar):not(.issuable-bulk-update-sidebar) .content-wrapper { + padding-right: $gutter-collapsed-width; + } + + .merge-request-tabs-holder.affix { + right: $gutter-collapsed-width; + } } + } - .merge-request-tabs-holder.affix { - right: $gutter-collapsed-width; + &.is-merge-request { + @include media-breakpoint-up(md) { + .content-wrapper { + padding-right: $gutter-collapsed-width; + } } } @@ -49,6 +59,18 @@ padding-right: 0; z-index: $zindex-dropdown-menu; + &.right-sidebar-merge-requests { + width: 270px; + + @include media-breakpoint-up(md) { + z-index: auto; + } + + .shortcut-sidebar-dropdown-toggle { + margin-right: 0 !important; + } + } + @include media-breakpoint-only(sm) { &:not(.wiki-sidebar):not(.build-sidebar):not(.issuable-bulk-update-sidebar) .content-wrapper { padding-right: $gutter-collapsed-width; @@ -73,10 +95,18 @@ .right-sidebar { border-left: 1px solid $gray-50; - .sidebar-container, - .issuable-sidebar { - // Add 100px so that potentially visible vertical scroll bar is hidden - width: calc(100% + 100px); + &.right-sidebar-merge-requests { + @include media-breakpoint-up(md) { + border-left: 0; + } + } + + &:not(.right-sidebar-merge-requests) { + .sidebar-container, + .issuable-sidebar { + // Add 100px so that potentially visible vertical scroll bar is hidden + width: calc(100% + 100px); + } } } @@ -231,6 +261,10 @@ margin-right: -$gl-spacing-scale-2; } +.issuable-sidebar.is-merge-request .edit-link { + margin-right: 0; +} + .assignee-grid { grid-template-areas: ' attention user'; grid-template-columns: min-content 1fr; diff --git a/app/assets/stylesheets/page_bundles/merge_requests.scss b/app/assets/stylesheets/page_bundles/merge_requests.scss index 269ce4042fc..f04cdfba0e4 100644 --- a/app/assets/stylesheets/page_bundles/merge_requests.scss +++ b/app/assets/stylesheets/page_bundles/merge_requests.scss @@ -735,3 +735,11 @@ $tabs-holder-z-index: 250; .attention-request-sidebar-popover { z-index: 999; } + +.merge-request-overview { + @include media-breakpoint-up(md) { + display: grid; + grid-template-columns: 1fr 270px; + grid-gap: 5%; + } +} diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index a0088e5ab56..5b8366e91bf 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -114,7 +114,7 @@ } } -.right-sidebar { +@mixin right-sidebar { position: fixed; top: $header-height; // Default value for CSS var must contain a unit @@ -125,6 +125,18 @@ background-color: $white; z-index: 200; overflow: hidden; +} + +.right-sidebar { + &:not(.right-sidebar-merge-requests) { + @include right-sidebar; + } + + &.right-sidebar-merge-requests { + @include media-breakpoint-down(sm) { + @include right-sidebar; + } + } @include media-breakpoint-down(sm) { z-index: 251; @@ -135,10 +147,6 @@ &:hover { color: $blue-800; - - .avatar { - border-color: rgba($gray-normal, 0.2); - } } } @@ -168,6 +176,21 @@ } } + &.right-sidebar-merge-requests { + .block, + .sidebar-contained-width, + .issuable-sidebar-header { + width: 100%; + border-bottom: 0; + } + + .block { + @include media-breakpoint-up(md) { + padding: $gl-spacing-scale-5 0; + } + } + } + .block, .sidebar-contained-width, .issuable-sidebar-header { @@ -224,9 +247,20 @@ .issuable-sidebar { height: 100%; - overflow-y: scroll; - overflow-x: hidden; - -webkit-overflow-scrolling: touch; + + &:not(.is-merge-request) { + overflow-y: scroll; + overflow-x: hidden; + -webkit-overflow-scrolling: touch; + } + + &.is-merge-request { + @include media-breakpoint-down(sm) { + overflow-y: scroll; + overflow-x: hidden; + -webkit-overflow-scrolling: touch; + } + } } &.affix-top .issuable-sidebar { @@ -234,7 +268,9 @@ } &.right-sidebar-expanded { - width: $gutter-width; + &:not(.right-sidebar-merge-requests) { + width: $gutter-width; + } .value { line-height: 1; @@ -242,6 +278,12 @@ .issuable-sidebar { padding: 0 20px; + + &.is-merge-request { + @include media-breakpoint-up(md) { + padding: 0; + } + } } &:not(.boards-sidebar):not([data-signed-in]):not([data-always-show-toggle]) { @@ -284,8 +326,17 @@ /* Extra small devices (phones, less than 768px) */ display: none; /* Small devices (tablets, 768px and up) */ - @include media-breakpoint-up(sm) { - display: block; + + &:not(.right-sidebar-merge-requests) { + @include media-breakpoint-up(sm) { + display: block; + } + } + + &.right-sidebar-merge-requests { + @include media-breakpoint-up(md) { + display: block; + } } width: $gutter-collapsed-width; diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index c40871c858f..0d3ed0e7c71 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -233,8 +233,7 @@ $tabs-holder-z-index: 250; top: calc(#{$header-height} + #{$system-header-height} + #{$performance-bar-height}); } - @include media-breakpoint-up(sm) { - position: -webkit-sticky; + @include media-breakpoint-up(md) { position: sticky; } diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index be61232eace..458df40ece1 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -47,6 +47,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo push_frontend_feature_flag(:mr_attention_requests, current_user) push_frontend_feature_flag(:updated_mr_header, project) push_frontend_feature_flag(:remove_diff_header_icons, project) + push_frontend_feature_flag(:moved_mr_sidebar, project) end before_action do diff --git a/app/finders/alert_management/alerts_finder.rb b/app/finders/alert_management/alerts_finder.rb index 1fbc1a4a258..11c0f37a79c 100644 --- a/app/finders/alert_management/alerts_finder.rb +++ b/app/finders/alert_management/alerts_finder.rb @@ -66,5 +66,3 @@ module AlertManagement end end end - -AlertManagement::AlertsFinder.prepend_mod_with('AlertManagement::AlertsFinder') diff --git a/app/graphql/types/ci/runner_type.rb b/app/graphql/types/ci/runner_type.rb index 9c604209409..6f957d2511f 100644 --- a/app/graphql/types/ci/runner_type.rb +++ b/app/graphql/types/ci/runner_type.rb @@ -41,6 +41,8 @@ module Types field :architecture_name, GraphQL::Types::String, null: true, description: 'Architecture provided by the the runner.', method: :architecture + field :maintenance_note, GraphQL::Types::String, null: true, + description: 'Runner\'s maintenance notes.' field :groups, ::Types::GroupType.connection_type, null: true, description: 'Groups the runner is associated with. For group runners only.' field :id, ::Types::GlobalIDType[::Ci::Runner], null: false, diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb index 6ecc41151af..1bd27158be4 100644 --- a/app/helpers/issuables_helper.rb +++ b/app/helpers/issuables_helper.rb @@ -13,6 +13,8 @@ module IssuablesHelper end def sidebar_gutter_collapsed_class + return "right-sidebar-expanded" if moved_mr_sidebar_enabled? + "right-sidebar-#{sidebar_gutter_collapsed? ? 'collapsed' : 'expanded'}" end diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb index 821ea403dc9..a2730c53ea2 100644 --- a/app/helpers/merge_requests_helper.rb +++ b/app/helpers/merge_requests_helper.rb @@ -256,6 +256,10 @@ module MergeRequestsHelper _('%{author} requested to merge %{source_branch} %{copy_button} into %{target_branch} %{created_at}').html_safe % { author: link_to_author.html_safe, source_branch: merge_request_source_branch(merge_request).html_safe, copy_button: copy_button.html_safe, target_branch: target_branch.html_safe, created_at: time_ago_with_tooltip(merge_request.created_at, html_class: 'gl-display-inline-block').html_safe } end + + def moved_mr_sidebar_enabled? + Feature.enabled?(:moved_mr_sidebar, @project) && defined?(@merge_request) + end end MergeRequestsHelper.prepend_mod_with('MergeRequestsHelper') diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb index d4d3fddb2cd..37cd491e19f 100644 --- a/app/helpers/nav_helper.rb +++ b/app/helpers/nav_helper.rb @@ -19,11 +19,13 @@ module NavHelper end def page_gutter_class + moved_sidebar_enabled = current_controller?('merge_requests') && moved_mr_sidebar_enabled? + if page_has_markdown? if cookies[:collapsed_gutter] == 'true' - %w[page-gutter right-sidebar-collapsed] + ["page-gutter", "#{'right-sidebar-collapsed' unless moved_sidebar_enabled}"] else - %w[page-gutter right-sidebar-expanded] + ["page-gutter", "#{'right-sidebar-expanded' unless moved_sidebar_enabled}"] end elsif current_path?('jobs#show') %w[page-gutter build-sidebar right-sidebar-expanded] diff --git a/app/models/alert_management/alert.rb b/app/models/alert_management/alert.rb index 047a4d510f9..9f05c87018d 100644 --- a/app/models/alert_management/alert.rb +++ b/app/models/alert_management/alert.rb @@ -81,7 +81,6 @@ module AlertManagement scope :search, -> (query) { fuzzy_search(query, [:title, :description, :monitoring_tool, :service]) } scope :not_resolved, -> { without_status(:resolved) } scope :with_prometheus_alert, -> { includes(:prometheus_alert) } - scope :with_threat_monitoring_alerts, -> { where(domain: :threat_monitoring ) } scope :with_operations_alerts, -> { where(domain: :operations) } scope :order_start_time, -> (sort_order) { order(started_at: sort_order) } diff --git a/app/models/clusters/applications/prometheus.rb b/app/models/clusters/applications/prometheus.rb index 21f7e410843..d1e169a1f78 100644 --- a/app/models/clusters/applications/prometheus.rb +++ b/app/models/clusters/applications/prometheus.rb @@ -18,7 +18,6 @@ module Clusters default_value_for :version, VERSION scope :preload_cluster_platform, -> { preload(cluster: [:platform_kubernetes]) } - scope :with_clusters_with_cilium, -> { joins(:cluster).merge(Clusters::Cluster.with_available_cilium) } attr_encrypted :alert_manager_token, mode: :per_attribute_iv, diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index 87afa9f9491..014f7530357 100644 --- a/app/models/clusters/cluster.rb +++ b/app/models/clusters/cluster.rb @@ -137,7 +137,6 @@ module Clusters scope :aws_installed, -> { aws_provided.joins(:provider_aws).merge(Clusters::Providers::Aws.with_status(:created)) } scope :with_available_elasticstack, -> { joins(:application_elastic_stack).merge(::Clusters::Applications::ElasticStack.available) } - scope :with_available_cilium, -> { joins(:application_cilium).merge(::Clusters::Applications::Cilium.available) } scope :distinct_with_deployed_environments, -> { joins(:environments).merge(::Deployment.success).distinct } scope :managed, -> { where(managed: true) } diff --git a/app/models/deploy_token.rb b/app/models/deploy_token.rb index 1dc8451dc09..3c0f7d91a03 100644 --- a/app/models/deploy_token.rb +++ b/app/models/deploy_token.rb @@ -5,7 +5,11 @@ class DeployToken < ApplicationRecord include TokenAuthenticatable include PolicyActor include Gitlab::Utils::StrongMemoize - add_authentication_token_field :token, encrypted: :optional + include IgnorableColumns + + ignore_column :token, remove_with: '15.2', remove_after: '2022-07-22' + + add_authentication_token_field :token, encrypted: :required AVAILABLE_SCOPES = %i(read_repository read_registry write_registry read_package_registry write_package_registry).freeze diff --git a/app/models/integrations/prometheus.rb b/app/models/integrations/prometheus.rb index d6aafe45ae9..5a30f55595b 100644 --- a/app/models/integrations/prometheus.rb +++ b/app/models/integrations/prometheus.rb @@ -30,7 +30,6 @@ module Integrations after_create_commit :create_default_alerts scope :preload_project, -> { preload(:project) } - scope :with_clusters_with_cilium, -> { joins(project: [:clusters]).merge(Clusters::Cluster.with_available_cilium) } def show_active_box? false diff --git a/app/services/clusters/kubernetes.rb b/app/services/clusters/kubernetes.rb index ef549b56946..819ac4c8464 100644 --- a/app/services/clusters/kubernetes.rb +++ b/app/services/clusters/kubernetes.rb @@ -14,7 +14,5 @@ module Clusters GITLAB_CROSSPLANE_DATABASE_ROLE_BINDING_NAME = 'gitlab-crossplane-database-rolebinding' KNATIVE_SERVING_NAMESPACE = 'knative-serving' ISTIO_SYSTEM_NAMESPACE = 'istio-system' - GITLAB_CILIUM_ROLE_NAME = 'gitlab-cilium-role' - GITLAB_CILIUM_ROLE_BINDING_NAME = 'gitlab-cilium-rolebinding' end end diff --git a/app/services/clusters/kubernetes/create_or_update_service_account_service.rb b/app/services/clusters/kubernetes/create_or_update_service_account_service.rb index ecad33fc7c0..eabc428d0d2 100644 --- a/app/services/clusters/kubernetes/create_or_update_service_account_service.rb +++ b/app/services/clusters/kubernetes/create_or_update_service_account_service.rb @@ -53,8 +53,6 @@ module Clusters create_or_update_knative_serving_role_binding create_or_update_crossplane_database_role create_or_update_crossplane_database_role_binding - create_or_update_cilium_role - create_or_update_cilium_role_binding end private @@ -99,14 +97,6 @@ module Clusters kubeclient.update_role_binding(crossplane_database_role_binding_resource) end - def create_or_update_cilium_role - kubeclient.update_role(cilium_role_resource) - end - - def create_or_update_cilium_role_binding - kubeclient.update_role_binding(cilium_role_binding_resource) - end - def service_account_resource Gitlab::Kubernetes::ServiceAccount.new( service_account_name, @@ -185,28 +175,6 @@ module Clusters service_account_name: service_account_name ).generate end - - def cilium_role_resource - Gitlab::Kubernetes::Role.new( - name: Clusters::Kubernetes::GITLAB_CILIUM_ROLE_NAME, - namespace: service_account_namespace, - rules: [{ - apiGroups: %w(cilium.io), - resources: %w(ciliumnetworkpolicies), - verbs: %w(get list create update patch) - }] - ).generate - end - - def cilium_role_binding_resource - Gitlab::Kubernetes::RoleBinding.new( - name: Clusters::Kubernetes::GITLAB_CILIUM_ROLE_BINDING_NAME, - role_name: Clusters::Kubernetes::GITLAB_CILIUM_ROLE_NAME, - role_kind: :Role, - namespace: service_account_namespace, - service_account_name: service_account_name - ).generate - end end end end diff --git a/app/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml b/app/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml index df9ef28726a..d4e8893407c 100644 --- a/app/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml +++ b/app/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml @@ -38,3 +38,7 @@ = link_to new_abuse_report_path(user_id: @merge_request.author.id, ref_url: merge_request_url(@merge_request)), class: 'dropdown-item' do .gl-new-dropdown-item-text-wrapper = _('Report abuse') + - if current_user && moved_mr_sidebar_enabled? + %li.gl-new-dropdown-divider + %hr.dropdown-divider + %li.gl-new-dropdown-item.js-sidebar-subscriptions-entry-point diff --git a/app/views/projects/merge_requests/_mr_title.html.haml b/app/views/projects/merge_requests/_mr_title.html.haml index 70b0a7dc650..638c520e210 100644 --- a/app/views/projects/merge_requests/_mr_title.html.haml +++ b/app/views/projects/merge_requests/_mr_title.html.haml @@ -27,7 +27,7 @@ = issuable_meta(@merge_request, @project) %div - %button.gl-button.btn.btn-default.btn-icon.float-right.d-block.d-sm-none.gutter-toggle.issuable-gutter-toggle.js-sidebar-toggle{ type: 'button' } + %button.gl-button.btn.btn-default.btn-icon.float-right.gl-display-block.gutter-toggle.issuable-gutter-toggle.js-sidebar-toggle{ type: 'button', class: "#{'gl-md-display-none!' if moved_mr_sidebar_enabled? } #{'gl-sm-display-none!' unless moved_mr_sidebar_enabled?}" } = sprite_icon('chevron-double-lg-left') .detail-page-header-actions.js-issuable-actions{ class: "#{'gl-align-self-start is-merge-request' if updated_mr_header_enabled}" } diff --git a/app/views/projects/merge_requests/show.html.haml b/app/views/projects/merge_requests/show.html.haml index 91f999eda36..13e5451df98 100644 --- a/app/views/projects/merge_requests/show.html.haml +++ b/app/views/projects/merge_requests/show.html.haml @@ -1,5 +1,6 @@ - @gfm_form = true -- @content_class = "merge-request-container#{' limit-container-width' unless fluid_layout}" +- unless moved_mr_sidebar_enabled? + - @content_class = "merge-request-container#{' limit-container-width' unless fluid_layout}" - add_to_breadcrumbs _("Merge requests"), project_merge_requests_path(@project) - breadcrumb_title @merge_request.to_reference - page_title "#{@merge_request.title} (#{@merge_request.to_reference})", _("Merge requests") @@ -47,8 +48,8 @@ #js-diff-file-finder #js-code-navigation = render "projects/merge_requests/tabs/pane", id: "notes", class: "notes voting_notes" do - .row - %section.col-md-12 + %div{ class: "#{'merge-request-overview' if moved_mr_sidebar_enabled?}" } + %section .issuable-discussion.js-vue-notes-event - if @merge_request.description.present? .detail-page-description @@ -70,6 +71,8 @@ help_page_path: suggest_changes_help_path, current_user_data: @current_user_data, is_locked: @merge_request.discussion_locked.to_s } } + - if moved_mr_sidebar_enabled? + = render 'shared/issuable/sidebar', issuable_sidebar: @issuable_sidebar, assignees: @merge_request.assignees, reviewers: @merge_request.reviewers, source_branch: @merge_request.source_branch = render "projects/merge_requests/tabs/pane", name: "commits", id: "commits", class: "commits" do -# This tab is always loaded via AJAX @@ -83,7 +86,8 @@ .loading.hide = gl_loading_icon(size: 'lg') -= render 'shared/issuable/sidebar', issuable_sidebar: @issuable_sidebar, assignees: @merge_request.assignees, reviewers: @merge_request.reviewers, source_branch: @merge_request.source_branch +- unless moved_mr_sidebar_enabled? + = render 'shared/issuable/sidebar', issuable_sidebar: @issuable_sidebar, assignees: @merge_request.assignees, reviewers: @merge_request.reviewers, source_branch: @merge_request.source_branch - if @merge_request.can_be_reverted?(current_user) = render "projects/commit/change", type: 'revert', commit: @merge_request.merge_commit diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml index 0af9b1cf2e3..4317c77eb89 100644 --- a/app/views/shared/issuable/_sidebar.html.haml +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -8,11 +8,12 @@ - add_page_startup_api_call "#{issuable_sidebar[:issuable_json_path]}?serializer=sidebar_extras" - reviewers = local_assigns.fetch(:reviewers, nil) - in_group_context_with_iterations = @project.group.present? && issuable_sidebar[:supports_iterations] +- moved_sidebar_enabled = moved_mr_sidebar_enabled? && issuable_type === 'merge_request' -%aside.right-sidebar.js-right-sidebar.js-issuable-sidebar{ data: { signed: { in: signed_in }, issuable_type: issuable_type }, class: sidebar_gutter_collapsed_class, 'aria-live' => 'polite', 'aria-label': issuable_type } - .issuable-sidebar - .issuable-sidebar-header.gl-py-3 - %a.gutter-toggle.float-right.js-sidebar-toggle.has-tooltip{ role: "button", href: "#", "aria-label" => _('Toggle sidebar'), title: sidebar_gutter_tooltip_text, data: { container: 'body', placement: 'left', boundary: 'viewport' } } +%aside.right-sidebar.js-right-sidebar.js-issuable-sidebar{ data: { signed: { in: signed_in }, issuable_type: issuable_type }, class: "#{sidebar_gutter_collapsed_class} #{'right-sidebar-merge-requests' if moved_sidebar_enabled}", 'aria-live' => 'polite', 'aria-label': issuable_type } + .issuable-sidebar{ class: "#{'is-merge-request' if moved_sidebar_enabled}" } + .issuable-sidebar-header{ class: "#{'gl-pb-2! gl-md-display-flex gl-justify-content-end' if moved_sidebar_enabled}" } + %a.gutter-toggle.float-right.js-sidebar-toggle.has-tooltip{ role: "button", class: "#{'gl-display-block gl-md-display-none!' if moved_sidebar_enabled}", href: "#", "aria-label" => _('Toggle sidebar'), title: sidebar_gutter_tooltip_text, data: { container: 'body', placement: 'left', boundary: 'viewport' } } = sidebar_gutter_toggle_icon - if signed_in .js-issuable-todo{ data: { project_path: issuable_sidebar[:project_full_path], iid: issuable_sidebar[:iid], id: issuable_sidebar[:id] } } @@ -76,14 +77,14 @@ %script#js-lock-issue-data{ type: "application/json" }= { is_locked: !!issuable_sidebar[:discussion_locked], is_editable: can_edit_issuable }.to_json.html_safe #js-lock-entry-point - - if signed_in + - if signed_in && !moved_sidebar_enabled .js-sidebar-subscriptions-entry-point .js-sidebar-participants-entry-point .block.with-sub-blocks #js-reference-entry-point - - if issuable_type == 'merge_request' + - if issuable_type == 'merge_request' && !moved_sidebar_enabled .sub-block.js-sidebar-source-branch .sidebar-collapsed-icon.js-dont-change-state = clipboard_button(text: source_branch, title: _('Copy branch name'), placement: "left", boundary: 'viewport', class: 'btn-clipboard gl-button btn-default-tertiary btn-icon btn-sm js-source-branch-copy') |