diff options
34 files changed, 318 insertions, 96 deletions
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 45f6226a5e1..bee87e17ed9 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -c7695bd902060be80b3499ffd2bd9e86d89c4f4f +e6c3f8fa60ab4b5af91b5f893876c130d97fe37c diff --git a/app/assets/javascripts/boards/components/board_list.vue b/app/assets/javascripts/boards/components/board_list.vue index 64b94fcefcf..a47db661445 100644 --- a/app/assets/javascripts/boards/components/board_list.vue +++ b/app/assets/javascripts/boards/components/board_list.vue @@ -129,7 +129,7 @@ export default { }; }, listItemsCount() { - return this.isEpicBoard ? this.list.epicsCount : this.boardList?.issuesCount; + return this.isEpicBoard ? this.list.metadata.epicsCount : this.boardList?.issuesCount; }, paginatedIssueText() { return sprintf(__('Showing %{pageSize} of %{total} %{issuableType}'), { diff --git a/app/assets/javascripts/boards/components/board_list_header.vue b/app/assets/javascripts/boards/components/board_list_header.vue index 165941ff938..93096777d64 100644 --- a/app/assets/javascripts/boards/components/board_list_header.vue +++ b/app/assets/javascripts/boards/components/board_list_header.vue @@ -90,6 +90,9 @@ export default { listType() { return this.list.listType; }, + itemsCount() { + return this.isEpicBoard ? this.list.metadata.epicsCount : this.boardList?.issuesCount; + }, listAssignee() { return this.list?.assignee?.username || ''; }, @@ -452,7 +455,7 @@ export default { <gl-icon class="gl-mr-2" :name="countIcon" :size="14" /> <item-count v-if="!isLoading" - :items-size="isEpicBoard ? list.epicsCount : boardList.issuesCount" + :items-size="itemsCount" :max-issue-count="list.maxIssueCount" /> </span> diff --git a/app/assets/javascripts/boards/stores/mutations.js b/app/assets/javascripts/boards/stores/mutations.js index 91669bf3562..047a14508f3 100644 --- a/app/assets/javascripts/boards/stores/mutations.js +++ b/app/assets/javascripts/boards/stores/mutations.js @@ -9,10 +9,9 @@ import * as mutationTypes from './mutation_types'; const updateListItemsCount = ({ state, listId, value }) => { const list = state.boardLists[listId]; if (state.issuableType === TYPE_EPIC) { - Vue.set(state.boardLists, listId, { ...list, epicsCount: list.epicsCount + value }); - } else { - Vue.set(state.boardLists, listId, { ...list }); + list.metadata.epicsCount += value; } + Vue.set(state.boardLists, listId, { ...list }); }; export const removeItemFromList = ({ state, listId, itemId, reordering = false }) => { diff --git a/app/assets/javascripts/ci/pipeline_schedules/components/pipeline_schedules_empty_state.vue b/app/assets/javascripts/ci/pipeline_schedules/components/pipeline_schedules_empty_state.vue index f633ba053ee..39ac55bb9c5 100644 --- a/app/assets/javascripts/ci/pipeline_schedules/components/pipeline_schedules_empty_state.vue +++ b/app/assets/javascripts/ci/pipeline_schedules/components/pipeline_schedules_empty_state.vue @@ -1,5 +1,5 @@ <script> -import scheduleSvg from '@gitlab/svgs/dist/illustrations/schedule-md.svg'; +import scheduleSvg from '@gitlab/svgs/dist/illustrations/schedule-md.svg?raw'; import { GlEmptyState, GlLink, GlSprintf } from '@gitlab/ui'; import { helpPagePath } from '~/helpers/help_page_helper'; import { s__ } from '~/locale'; diff --git a/app/assets/javascripts/ensure_data.js b/app/assets/javascripts/ensure_data.js index 69c81c35bd4..4566ab20258 100644 --- a/app/assets/javascripts/ensure_data.js +++ b/app/assets/javascripts/ensure_data.js @@ -1,4 +1,4 @@ -import emptySvg from '@gitlab/svgs/dist/illustrations/security-dashboard-empty-state.svg'; +import emptySvg from '@gitlab/svgs/dist/illustrations/security-dashboard-empty-state.svg?raw'; import { GlEmptyState } from '@gitlab/ui'; import * as Sentry from '@sentry/browser'; import { __ } from '~/locale'; diff --git a/app/assets/javascripts/environments/components/deploy_board.vue b/app/assets/javascripts/environments/components/deploy_board.vue index 31bc462f0b9..caf375a16cf 100644 --- a/app/assets/javascripts/environments/components/deploy_board.vue +++ b/app/assets/javascripts/environments/components/deploy_board.vue @@ -8,7 +8,7 @@ * - Button Actions. * [Mockup](https://gitlab.com/gitlab-org/gitlab-foss/uploads/2f655655c0eadf655d0ae7467b53002a/environments__deploy-graphic.png) */ -import deployBoardSvg from '@gitlab/svgs/dist/illustrations/deploy-boards.svg'; +import deployBoardSvg from '@gitlab/svgs/dist/illustrations/deploy-boards.svg?raw'; import { GlIcon, GlLoadingIcon, diff --git a/app/assets/javascripts/feature_highlight/feature_highlight_popover.vue b/app/assets/javascripts/feature_highlight/feature_highlight_popover.vue index 1c6e6380e76..24f7d567ea7 100644 --- a/app/assets/javascripts/feature_highlight/feature_highlight_popover.vue +++ b/app/assets/javascripts/feature_highlight/feature_highlight_popover.vue @@ -1,5 +1,5 @@ <script> -import clusterPopover from '@gitlab/svgs/dist/illustrations/cluster_popover.svg'; +import clusterPopover from '@gitlab/svgs/dist/illustrations/cluster_popover.svg?raw'; import { GlPopover, GlSprintf, GlLink, GlButton } from '@gitlab/ui'; import SafeHtml from '~/vue_shared/directives/safe_html'; import { __ } from '~/locale'; diff --git a/app/assets/javascripts/monitoring/components/charts/empty_chart.vue b/app/assets/javascripts/monitoring/components/charts/empty_chart.vue index da4c92df711..6419c45c20c 100644 --- a/app/assets/javascripts/monitoring/components/charts/empty_chart.vue +++ b/app/assets/javascripts/monitoring/components/charts/empty_chart.vue @@ -1,5 +1,5 @@ <script> -import chartEmptyStateIllustration from '@gitlab/svgs/dist/illustrations/chart-empty-state.svg'; +import chartEmptyStateIllustration from '@gitlab/svgs/dist/illustrations/chart-empty-state.svg?raw'; import SafeHtml from '~/vue_shared/directives/safe_html'; import { chartHeight } from '../../constants'; diff --git a/app/assets/javascripts/pages/groups/new/components/app.vue b/app/assets/javascripts/pages/groups/new/components/app.vue index 68ddcf3d868..68f813d9375 100644 --- a/app/assets/javascripts/pages/groups/new/components/app.vue +++ b/app/assets/javascripts/pages/groups/new/components/app.vue @@ -1,6 +1,6 @@ <script> -import importGroupIllustration from '@gitlab/svgs/dist/illustrations/group-import.svg'; -import newGroupIllustration from '@gitlab/svgs/dist/illustrations/group-new.svg'; +import importGroupIllustration from '@gitlab/svgs/dist/illustrations/group-import.svg?raw'; +import newGroupIllustration from '@gitlab/svgs/dist/illustrations/group-new.svg?raw'; import { s__ } from '~/locale'; import NewNamespacePage from '~/vue_shared/new_namespace/new_namespace_page.vue'; diff --git a/app/assets/javascripts/projects/new/components/app.vue b/app/assets/javascripts/projects/new/components/app.vue index 4f3924b04bf..8d883e7126c 100644 --- a/app/assets/javascripts/projects/new/components/app.vue +++ b/app/assets/javascripts/projects/new/components/app.vue @@ -1,8 +1,8 @@ <script> -import createFromTemplateIllustration from '@gitlab/svgs/dist/illustrations/project-create-from-template-sm.svg'; -import blankProjectIllustration from '@gitlab/svgs/dist/illustrations/project-create-new-sm.svg'; -import importProjectIllustration from '@gitlab/svgs/dist/illustrations/project-import-sm.svg'; -import ciCdProjectIllustration from '@gitlab/svgs/dist/illustrations/project-run-CICD-pipelines-sm.svg'; +import createFromTemplateIllustration from '@gitlab/svgs/dist/illustrations/project-create-from-template-sm.svg?raw'; +import blankProjectIllustration from '@gitlab/svgs/dist/illustrations/project-create-new-sm.svg?raw'; +import importProjectIllustration from '@gitlab/svgs/dist/illustrations/project-import-sm.svg?raw'; +import ciCdProjectIllustration from '@gitlab/svgs/dist/illustrations/project-run-CICD-pipelines-sm.svg?raw'; import SafeHtml from '~/vue_shared/directives/safe_html'; import { s__ } from '~/locale'; import NewNamespacePage from '~/vue_shared/new_namespace/new_namespace_page.vue'; diff --git a/app/assets/javascripts/security_configuration/components/constants.js b/app/assets/javascripts/security_configuration/components/constants.js index 6beb6cd4d34..1321624fe7d 100644 --- a/app/assets/javascripts/security_configuration/components/constants.js +++ b/app/assets/javascripts/security_configuration/components/constants.js @@ -15,8 +15,8 @@ import { REPORT_TYPE_LICENSE_COMPLIANCE, } from '~/vue_shared/security_reports/constants'; -import kontraLogo from 'images/vulnerability/kontra-logo.svg'; -import scwLogo from 'images/vulnerability/scw-logo.svg'; +import kontraLogo from 'images/vulnerability/kontra-logo.svg?raw'; +import scwLogo from 'images/vulnerability/scw-logo.svg?raw'; import configureSastMutation from '../graphql/configure_sast.mutation.graphql'; import configureSastIacMutation from '../graphql/configure_iac.mutation.graphql'; import configureSecretDetectionMutation from '../graphql/configure_secret_detection.mutation.graphql'; diff --git a/app/assets/javascripts/super_sidebar/components/super_sidebar.vue b/app/assets/javascripts/super_sidebar/components/super_sidebar.vue index 2da71c029fd..630537f0323 100644 --- a/app/assets/javascripts/super_sidebar/components/super_sidebar.vue +++ b/app/assets/javascripts/super_sidebar/components/super_sidebar.vue @@ -1,5 +1,6 @@ <script> import { GlCollapse } from '@gitlab/ui'; +import { isCollapsed, toggleSuperSidebarCollapsed } from '../super_sidebar_collapsed_state_manager'; import UserBar from './user_bar.vue'; import SidebarPortalTarget from './sidebar_portal_target.vue'; import ContextSwitcherToggle from './context_switcher_toggle.vue'; @@ -26,6 +27,7 @@ export default { data() { return { contextSwitcherOpened: false, + isCollapased: isCollapsed(), }; }, computed: { @@ -33,34 +35,45 @@ export default { return this.sidebarData.current_menu_items || []; }, }, + methods: { + collapseSidebar() { + toggleSuperSidebarCollapsed(true, false); + }, + }, }; </script> <template> - <aside - id="super-sidebar" - class="super-sidebar gl-display-flex gl-flex-direction-column" - data-testid="super-sidebar" - data-qa-selector="navbar" - > - <user-bar :sidebar-data="sidebarData" /> - <div class="gl-display-flex gl-flex-direction-column gl-flex-grow-1 gl-overflow-hidden"> - <div class="gl-flex-grow-1 gl-overflow-auto"> - <context-switcher-toggle - :context="sidebarData.current_context_header" - :expanded="contextSwitcherOpened" - /> - <gl-collapse id="context-switcher" v-model="contextSwitcherOpened"> - <context-switcher /> - </gl-collapse> - <gl-collapse :visible="!contextSwitcherOpened"> - <sidebar-menu :items="menuItems" /> - <sidebar-portal-target /> - </gl-collapse> - </div> - <div class="gl-p-3"> - <help-center :sidebar-data="sidebarData" /> + <div> + <div class="super-sidebar-overlay" @click="collapseSidebar"></div> + <aside + id="super-sidebar" + :aria-hidden="String(isCollapased)" + class="super-sidebar" + data-testid="super-sidebar" + data-qa-selector="navbar" + :inert="isCollapased" + tabindex="-1" + > + <user-bar :sidebar-data="sidebarData" /> + <div class="gl-display-flex gl-flex-direction-column gl-flex-grow-1 gl-overflow-hidden"> + <div class="gl-flex-grow-1 gl-overflow-auto"> + <context-switcher-toggle + :context="sidebarData.current_context_header" + :expanded="contextSwitcherOpened" + /> + <gl-collapse id="context-switcher" v-model="contextSwitcherOpened"> + <context-switcher /> + </gl-collapse> + <gl-collapse :visible="!contextSwitcherOpened"> + <sidebar-menu :items="menuItems" /> + <sidebar-portal-target /> + </gl-collapse> + </div> + <div class="gl-p-3"> + <help-center :sidebar-data="sidebarData" /> + </div> </div> - </div> - </aside> + </aside> + </div> </template> diff --git a/app/assets/javascripts/super_sidebar/components/user_bar.vue b/app/assets/javascripts/super_sidebar/components/user_bar.vue index 82db6a2e351..32ce4abd646 100644 --- a/app/assets/javascripts/super_sidebar/components/user_bar.vue +++ b/app/assets/javascripts/super_sidebar/components/user_bar.vue @@ -2,7 +2,7 @@ import { GlBadge, GlButton, GlTooltipDirective } from '@gitlab/ui'; import { __ } from '~/locale'; import SafeHtml from '~/vue_shared/directives/safe_html'; -import logo from '../../../../views/shared/_logo.svg'; +import logo from '../../../../views/shared/_logo.svg?raw'; import { toggleSuperSidebarCollapsed } from '../super_sidebar_collapsed_state_manager'; import CreateMenu from './create_menu.vue'; import Counter from './counter.vue'; @@ -93,7 +93,6 @@ export default { <counter v-gl-tooltip:super-sidebar.hover.bottom="$options.i18n.mergeRequests" class="gl-w-full" - tabindex="-1" icon="merge-request-open" :count="sidebarData.total_merge_requests_count" :label="$options.i18n.mergeRequests" diff --git a/app/assets/javascripts/super_sidebar/super_sidebar_collapsed_state_manager.js b/app/assets/javascripts/super_sidebar/super_sidebar_collapsed_state_manager.js index 1dfd132d522..a4eb65dc08c 100644 --- a/app/assets/javascripts/super_sidebar/super_sidebar_collapsed_state_manager.js +++ b/app/assets/javascripts/super_sidebar/super_sidebar_collapsed_state_manager.js @@ -7,9 +7,10 @@ export const SIDEBAR_COLLAPSED_COOKIE = 'super_sidebar_collapsed'; export const SIDEBAR_COLLAPSED_COOKIE_EXPIRATION = 365 * 10; export const findPage = () => document.querySelector('.page-with-super-sidebar'); -export const findToggle = () => document.querySelector('.js-super-sidebar-toggle'); +export const findSidebar = () => document.querySelector('.super-sidebar'); +export const findToggles = () => document.querySelectorAll('.js-super-sidebar-toggle'); -const isCollapsed = () => findPage().classList.contains(SIDEBAR_COLLAPSED_CLASS); +export const isCollapsed = () => findPage().classList.contains(SIDEBAR_COLLAPSED_CLASS); // See documentation: https://design.gitlab.com/patterns/navigation#left-sidebar // NOTE: at 1200px nav sidebar should not overlap the content @@ -19,6 +20,12 @@ export const isDesktopBreakpoint = () => bp.windowWidth() >= breakpoints.xl; export const getCollapsedCookie = () => getCookie(SIDEBAR_COLLAPSED_COOKIE) === 'true'; export const toggleSuperSidebarCollapsed = (collapsed, saveCookie) => { + const sidebar = findSidebar(); + sidebar.ariaHidden = collapsed; + sidebar.inert = collapsed; + + if (!collapsed) sidebar.focus(); + findPage().classList.toggle(SIDEBAR_COLLAPSED_CLASS, collapsed); if (saveCookie && isDesktopBreakpoint()) { @@ -34,12 +41,11 @@ export const initSuperSidebarCollapsedState = () => { }; export const bindSuperSidebarCollapsedEvents = () => { - if (findToggle()) { - findToggle().addEventListener('click', () => { - const value = !isCollapsed(); - toggleSuperSidebarCollapsed(value, true); + findToggles().forEach((elem) => { + elem.addEventListener('click', () => { + toggleSuperSidebarCollapsed(!isCollapsed(), true); }); - } + }); window.addEventListener('resize', debounce(initSuperSidebarCollapsedState, 100)); }; diff --git a/app/assets/javascripts/surveys/merge_request_experience/app.vue b/app/assets/javascripts/surveys/merge_request_experience/app.vue index 6e90ad2e0fd..333059b5340 100644 --- a/app/assets/javascripts/surveys/merge_request_experience/app.vue +++ b/app/assets/javascripts/surveys/merge_request_experience/app.vue @@ -1,6 +1,6 @@ <script> import { GlButton, GlSprintf, GlTooltipDirective } from '@gitlab/ui'; -import gitlabLogo from '@gitlab/svgs/dist/illustrations/gitlab_logo.svg'; +import gitlabLogo from '@gitlab/svgs/dist/illustrations/gitlab_logo.svg?raw'; import SafeHtml from '~/vue_shared/directives/safe_html'; import { s__, __ } from '~/locale'; import UserCalloutDismisser from '~/vue_shared/components/user_callout_dismisser.vue'; diff --git a/app/assets/javascripts/work_items/components/work_item_detail.vue b/app/assets/javascripts/work_items/components/work_item_detail.vue index d4ee84f0255..eb715518451 100644 --- a/app/assets/javascripts/work_items/components/work_item_detail.vue +++ b/app/assets/javascripts/work_items/components/work_item_detail.vue @@ -11,7 +11,7 @@ import { GlTooltipDirective, GlEmptyState, } from '@gitlab/ui'; -import noAccessSvg from '@gitlab/svgs/dist/illustrations/analytics/no-access.svg'; +import noAccessSvg from '@gitlab/svgs/dist/illustrations/analytics/no-access.svg?raw'; import * as Sentry from '@sentry/browser'; import { s__ } from '~/locale'; import { parseBoolean } from '~/lib/utils/common_utils'; diff --git a/app/assets/stylesheets/framework/super_sidebar.scss b/app/assets/stylesheets/framework/super_sidebar.scss index dd723d9f4f4..659e8c5b37d 100644 --- a/app/assets/stylesheets/framework/super_sidebar.scss +++ b/app/assets/stylesheets/framework/super_sidebar.scss @@ -24,16 +24,17 @@ } .super-sidebar { - @include gl-fixed; - @include gl-top-0; - @include gl-bottom-0; - @include gl-left-0; - @include gl-bg-gray-10; - @include gl-border-r; - @include gl-border-gray-a-08; + display: flex; + flex-direction: column; + position: fixed; + top: 0; + bottom: 0; + left: 0; + background-color: var(--gray-10, $gray-10); + border-right: 1px solid $t-gray-a-08; transform: translate3d(0, 0, 0); width: $super-sidebar-width; - z-index: 600; + z-index: $super-sidebar-z-index; &.super-sidebar-loading { transform: translate3d(-100%, 0, 0); @@ -139,12 +140,33 @@ } } +.super-sidebar-overlay { + display: none; +} + .page-with-super-sidebar { padding-left: 0; transition: padding-left $gl-transition-duration-medium; + &:not(.page-with-super-sidebar-collapsed) { + .super-sidebar-overlay { + display: block; + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + background-color: $black-transparent; + z-index: $super-sidebar-z-index - 1; + + @include media-breakpoint-up(md) { + display: none; + } + } + } + @include media-breakpoint-up(xl) { - padding-left: $contextual-sidebar-width; + padding-left: $super-sidebar-width; .super-sidebar-toggle { display: none; diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index e032961a253..dff0ca9a819 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -12,6 +12,8 @@ $contextual-sidebar-collapsed-width: 56px; $toggle-sidebar-height: 48px; $super-sidebar-width: 256px; $super-sidebar-toggle-position-breakpoint: 1360px; +$super-sidebar-z-index: 600; +$super-sidebar-overlay-z-index: 599; /** 🚨 Do not use this spacing scale — it is deprecated and being removed. 🚨 diff --git a/app/assets/stylesheets/startup/startup-dark.scss b/app/assets/stylesheets/startup/startup-dark.scss index accc50697c5..ac74096e97c 100644 --- a/app/assets/stylesheets/startup/startup-dark.scss +++ b/app/assets/stylesheets/startup/startup-dark.scss @@ -1494,13 +1494,14 @@ kbd { } } .super-sidebar { + display: flex; + flex-direction: column; position: fixed; top: 0; bottom: 0; left: 0; - background-color: #1f1e24; - border-right: solid 1px #434248; - border-color: rgba(251, 250, 253, 0.08); + background-color: var(--gray-10, #1f1e24); + border-right: 1px solid rgba(251, 250, 253, 0.08); transform: translate3d(0, 0, 0); width: 256px; z-index: 600; diff --git a/app/assets/stylesheets/startup/startup-general.scss b/app/assets/stylesheets/startup/startup-general.scss index 511c270d556..fc3da60d3b8 100644 --- a/app/assets/stylesheets/startup/startup-general.scss +++ b/app/assets/stylesheets/startup/startup-general.scss @@ -1494,13 +1494,14 @@ kbd { } } .super-sidebar { + display: flex; + flex-direction: column; position: fixed; top: 0; bottom: 0; left: 0; - background-color: #fbfafd; - border-right: solid 1px #dcdcde; - border-color: rgba(31, 30, 36, 0.08); + background-color: var(--gray-10, #fbfafd); + border-right: 1px solid rgba(31, 30, 36, 0.08); transform: translate3d(0, 0, 0); width: 256px; z-index: 600; diff --git a/app/services/jira_connect_installations/proxy_lifecycle_event_service.rb b/app/services/jira_connect_installations/proxy_lifecycle_event_service.rb index d94d9e1324e..9f3b4a37672 100644 --- a/app/services/jira_connect_installations/proxy_lifecycle_event_service.rb +++ b/app/services/jira_connect_installations/proxy_lifecycle_event_service.rb @@ -82,9 +82,9 @@ module JiraConnectInstallations Gitlab::IntegrationsLogger.info( integration: 'JiraConnect', message: 'Proxy lifecycle event received error response', - event_type: event, - status_code: status_code, - body: body + jira_event_type: event, + jira_status_code: status_code, + jira_body: body ) end end diff --git a/app/views/devise/confirmations/almost_there.haml b/app/views/devise/confirmations/almost_there.haml index 01f9595f35c..c22eeba2f01 100644 --- a/app/views/devise/confirmations/almost_there.haml +++ b/app/views/devise/confirmations/almost_there.haml @@ -1,6 +1,7 @@ - user_email = "(#{params[:email]})" if Devise.email_regexp.match?(params[:email]) - request_link_start = '<a href="%{new_user_confirmation_path}">'.html_safe % { new_user_confirmation_path: new_user_confirmation_path } -- request_link_end = '</a>'.html_safe +- registration_link_start = '<a href="%{new_user_registration_path}">'.html_safe % { new_user_registration_path: new_user_registration_path } +- link_end = '</a>'.html_safe - content_for :page_specific_javascripts do = render "layouts/google_tag_manager_head" = render "layouts/one_trust" @@ -12,9 +13,11 @@ = _("Almost there...") %p{ class: 'gl-mb-6 gl-font-lg!' } = _('Please check your email %{email} to confirm your account') % { email: user_email } + %br + = _('If the email address is incorrect, you can %{registration_link_start}register again with a different email%{registration_link_end}.').html_safe % { registration_link_start: registration_link_start, registration_link_end: link_end } %hr - if Gitlab::CurrentSettings.after_sign_up_text.present? .well-confirmation.gl-text-center = markdown_field(Gitlab::CurrentSettings, :after_sign_up_text) %p.gl-text-center - = _("No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}.").html_safe % { request_link_start: request_link_start, request_link_end: request_link_end } + = _("No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}.").html_safe % { request_link_start: request_link_start, request_link_end: link_end } diff --git a/app/views/projects/pages_domains/_certificate.html.haml b/app/views/projects/pages_domains/_certificate.html.haml index 4ba3e084dc4..3433958a397 100644 --- a/app/views/projects/pages_domains/_certificate.html.haml +++ b/app/views/projects/pages_domains/_certificate.html.haml @@ -30,10 +30,10 @@ - if has_user_defined_certificate .row .col-sm-10.offset-sm-2 - .card - .card-header - = _('Certificate') - .d-flex.justify-content-between.align-items-center.p-3 + = render Pajamas::CardComponent.new(body_options: { class: 'gl-display-flex gl-align-items-center gl-justify-content-space-between gl-p-5' }) do |c| + - c.header do + = s_('Certificate') + - c.body do %span = domain_presenter.pages_domain.subject || _('missing') = link_to _('Remove'), diff --git a/config/webpack.config.js b/config/webpack.config.js index 550a3a62e24..ba7a1f70acc 100644 --- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -393,6 +393,7 @@ module.exports = { }, }, { + resourceQuery: /raw/, loader: 'raw-loader', }, ], diff --git a/jest.config.base.js b/jest.config.base.js index 34134d6983b..cc275c3ed0f 100644 --- a/jest.config.base.js +++ b/jest.config.base.js @@ -47,6 +47,9 @@ module.exports = (path, options = {}) => { // temporary alias until we replace all `flash` imports for `alert` // https://gitlab.com/gitlab-org/gitlab/-/merge_requests/109449 '^~/flash$': '<rootDir>/app/assets/javascripts/alert', + [TEST_FIXTURES_PATTERN]: '<rootDir>/tmp/tests/frontend/fixtures$1', + '^test_fixtures_static(/.*)$': '<rootDir>/spec/frontend/fixtures/static$1', + '\\.(jpg|jpeg|png|svg|css)(\\?\\w+)?$': '<rootDir>/spec/frontend/__mocks__/file_mock.js', '^~(/.*)\\?(worker|raw)$': '<rootDir>/app/assets/javascripts$1', '^(.*)\\?(worker|raw)$': '$1', '^~(/.*)$': '<rootDir>/app/assets/javascripts$1', @@ -60,10 +63,6 @@ module.exports = (path, options = {}) => { '^any_else_ce(/.*)$': '<rootDir>/app/assets/javascripts$1', '^helpers(/.*)$': '<rootDir>/spec/frontend/__helpers__$1', '^vendor(/.*)$': '<rootDir>/vendor/assets/javascripts$1', - [TEST_FIXTURES_PATTERN]: '<rootDir>/tmp/tests/frontend/fixtures$1', - '^test_fixtures_static(/.*)$': '<rootDir>/spec/frontend/fixtures/static$1', - '\\.(jpg|jpeg|png|svg|css)$': '<rootDir>/spec/frontend/__mocks__/file_mock.js', - '\\.svg\\?url$': '<rootDir>/spec/frontend/__mocks__/file_mock.js', '^public(/.*)$': '<rootDir>/public$1', 'emojis(/.*).json': '<rootDir>/fixtures/emojis$1.json', '^spec/test_constants$': '<rootDir>/spec/frontend/__helpers__/test_constants', diff --git a/locale/gitlab.pot b/locale/gitlab.pot index fbb92f4b14e..fc126de2e55 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -21424,6 +21424,9 @@ msgstr "" msgid "If enabled, only protected branches will be mirrored." msgstr "" +msgid "If the email address is incorrect, you can %{registration_link_start}register again with a different email%{registration_link_end}." +msgstr "" + msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation." msgstr "" @@ -38764,6 +38767,9 @@ msgstr "" msgid "SecurityOrchestration|No rules defined - policy will not run." msgstr "" +msgid "SecurityOrchestration|Non-existing tags have been detected in the policy yaml. As a result, rule mode has been disabled. To enable rule mode, remove those non-existing tags from the policy yaml." +msgstr "" + msgid "SecurityOrchestration|Not enabled" msgstr "" diff --git a/scripts/pipeline_test_report_builder.rb b/scripts/pipeline_test_report_builder.rb index 15a78969266..c84acf2fd94 100755 --- a/scripts/pipeline_test_report_builder.rb +++ b/scripts/pipeline_test_report_builder.rb @@ -19,7 +19,7 @@ require_relative 'api/default_options' # Push into expected format for failed tests class PipelineTestReportBuilder DEFAULT_OPTIONS = { - target_project: Host::DEFAULT_OPTIONS[:target_project], + target_project: Host::DEFAULT_OPTIONS[:target_project] || API::DEFAULT_OPTIONS[:project], current_pipeline_id: API::DEFAULT_OPTIONS[:pipeline_id], mr_iid: Host::DEFAULT_OPTIONS[:mr_iid], api_endpoint: API::DEFAULT_OPTIONS[:endpoint], diff --git a/spec/features/projects/pages/user_edits_lets_encrypt_settings_spec.rb b/spec/features/projects/pages/user_edits_lets_encrypt_settings_spec.rb index a7da59200e9..16e64ade665 100644 --- a/spec/features/projects/pages/user_edits_lets_encrypt_settings_spec.rb +++ b/spec/features/projects/pages/user_edits_lets_encrypt_settings_spec.rb @@ -48,13 +48,13 @@ RSpec.describe "Pages with Let's Encrypt", :https_pages_enabled, feature_categor expect(domain.auto_ssl_enabled).to eq false expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'false' - expect(page).to have_selector '.card-header', text: 'Certificate' + expect(page).to have_selector '.gl-card-header', text: 'Certificate' expect(page).to have_text domain.subject find('.js-auto-ssl-toggle-container .js-project-feature-toggle button').click expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'true' - expect(page).not_to have_selector '.card-header', text: 'Certificate' + expect(page).not_to have_selector '.gl-card-header', text: 'Certificate' expect(page).not_to have_text domain.subject click_on 'Save Changes' @@ -108,7 +108,7 @@ RSpec.describe "Pages with Let's Encrypt", :https_pages_enabled, feature_categor it 'user do not see private key' do visit project_pages_domain_path(project, domain) - expect(page).not_to have_selector '.card-header', text: 'Certificate' + expect(page).not_to have_selector '.gl-card-header', text: 'Certificate' expect(page).not_to have_text domain.subject end end @@ -131,16 +131,16 @@ RSpec.describe "Pages with Let's Encrypt", :https_pages_enabled, feature_categor it 'user sees certificate subject' do visit project_pages_domain_path(project, domain) - expect(page).to have_selector '.card-header', text: 'Certificate' + expect(page).to have_selector '.gl-card-header', text: 'Certificate' expect(page).to have_text domain.subject end it 'user can delete the certificate', :js do visit project_pages_domain_path(project, domain) - expect(page).to have_selector '.card-header', text: 'Certificate' + expect(page).to have_selector '.gl-card-header', text: 'Certificate' expect(page).to have_text domain.subject - within('.card') { click_on 'Remove' } + within('.gl-card') { click_on 'Remove' } accept_gl_confirm(button_text: 'Remove certificate') expect(page).to have_field 'Certificate (PEM)', with: '' expect(page).to have_field 'Key (PEM)', with: '' diff --git a/spec/frontend/boards/mock_data.js b/spec/frontend/boards/mock_data.js index 1d011eacf1c..0f58d7cf9fa 100644 --- a/spec/frontend/boards/mock_data.js +++ b/spec/frontend/boards/mock_data.js @@ -477,6 +477,9 @@ export const mockList = { loading: false, issuesCount: 1, maxIssueCount: 0, + metadata: { + epicsCount: 1, + }, __typename: 'BoardList', }; diff --git a/spec/frontend/super_sidebar/components/super_sidebar_spec.js b/spec/frontend/super_sidebar/components/super_sidebar_spec.js index 57c84bc87a6..32921da23aa 100644 --- a/spec/frontend/super_sidebar/components/super_sidebar_spec.js +++ b/spec/frontend/super_sidebar/components/super_sidebar_spec.js @@ -3,11 +3,17 @@ import SuperSidebar from '~/super_sidebar/components/super_sidebar.vue'; import HelpCenter from '~/super_sidebar/components/help_center.vue'; import UserBar from '~/super_sidebar/components/user_bar.vue'; import SidebarPortalTarget from '~/super_sidebar/components/sidebar_portal_target.vue'; +import { isCollapsed } from '~/super_sidebar/super_sidebar_collapsed_state_manager'; import { sidebarData } from '../mock_data'; +jest.mock('~/super_sidebar/super_sidebar_collapsed_state_manager', () => ({ + isCollapsed: jest.fn(), +})); + describe('SuperSidebar component', () => { let wrapper; + const findSidebar = () => wrapper.find('.super-sidebar'); const findUserBar = () => wrapper.findComponent(UserBar); const findHelpCenter = () => wrapper.findComponent(HelpCenter); const findSidebarPortalTarget = () => wrapper.findComponent(SidebarPortalTarget); @@ -22,19 +28,32 @@ describe('SuperSidebar component', () => { }; describe('default', () => { - beforeEach(() => { + it('add aria-hidden and inert attributes when collapsed', () => { + isCollapsed.mockReturnValue(true); + createWrapper(); + expect(findSidebar().attributes('aria-hidden')).toBe('true'); + expect(findSidebar().attributes('inert')).toBe('inert'); + }); + + it('does not add aria-hidden and inert attributes when expanded', () => { + isCollapsed.mockReturnValue(false); createWrapper(); + expect(findSidebar().attributes('aria-hidden')).toBe('false'); + expect(findSidebar().attributes('inert')).toBe(undefined); }); it('renders UserBar with sidebarData', () => { + createWrapper(); expect(findUserBar().props('sidebarData')).toBe(sidebarData); }); it('renders HelpCenter with sidebarData', () => { + createWrapper(); expect(findHelpCenter().props('sidebarData')).toBe(sidebarData); }); it('renders SidebarPortalTarget', () => { + createWrapper(); expect(findSidebarPortalTarget().exists()).toBe(true); }); }); diff --git a/spec/frontend/super_sidebar/super_sidebar_collapsed_state_manager_spec.js b/spec/frontend/super_sidebar/super_sidebar_collapsed_state_manager_spec.js new file mode 100644 index 00000000000..27fa451cf7b --- /dev/null +++ b/spec/frontend/super_sidebar/super_sidebar_collapsed_state_manager_spec.js @@ -0,0 +1,132 @@ +import { GlBreakpointInstance as bp, breakpoints } from '@gitlab/ui/dist/utils'; +import { getCookie, setCookie } from '~/lib/utils/common_utils'; +import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures'; +import { + SIDEBAR_COLLAPSED_CLASS, + SIDEBAR_COLLAPSED_COOKIE, + SIDEBAR_COLLAPSED_COOKIE_EXPIRATION, + toggleSuperSidebarCollapsed, + initSuperSidebarCollapsedState, + bindSuperSidebarCollapsedEvents, + findPage, + findSidebar, + findToggles, +} from '~/super_sidebar/super_sidebar_collapsed_state_manager'; + +const { xl, sm } = breakpoints; + +jest.mock('~/lib/utils/common_utils', () => ({ + getCookie: jest.fn(), + setCookie: jest.fn(), +})); + +const pageHasCollapsedClass = (hasClass) => { + if (hasClass) { + expect(findPage().classList).toContain(SIDEBAR_COLLAPSED_CLASS); + } else { + expect(findPage().classList).not.toContain(SIDEBAR_COLLAPSED_CLASS); + } +}; + +describe('Super Sidebar Collapsed State Manager', () => { + beforeEach(() => { + setHTMLFixture(` + <button class="js-super-sidebar-toggle"></button> + <div class="page-with-super-sidebar"></div> + <aside class="super-sidebar"></aside> + `); + }); + + afterEach(() => { + resetHTMLFixture(); + }); + + describe('toggleSuperSidebarCollapsed', () => { + it.each` + collapsed | saveCookie | windowWidth | hasClass + ${true} | ${true} | ${xl} | ${true} + ${true} | ${false} | ${xl} | ${true} + ${true} | ${true} | ${sm} | ${true} + ${true} | ${false} | ${sm} | ${true} + ${false} | ${true} | ${xl} | ${false} + ${false} | ${false} | ${xl} | ${false} + ${false} | ${true} | ${sm} | ${false} + ${false} | ${false} | ${sm} | ${false} + `( + 'when collapsed is $collapsed, saveCookie is $saveCookie, and windowWidth is $windowWidth then page class contains `page-with-super-sidebar-collapsed` is $hasClass', + ({ collapsed, saveCookie, windowWidth, hasClass }) => { + jest.spyOn(bp, 'windowWidth').mockReturnValue(windowWidth); + + toggleSuperSidebarCollapsed(collapsed, saveCookie); + + pageHasCollapsedClass(hasClass); + expect(findSidebar().ariaHidden).toBe(collapsed); + expect(findSidebar().inert).toBe(collapsed); + + if (saveCookie && windowWidth >= xl) { + expect(setCookie).toHaveBeenCalledWith(SIDEBAR_COLLAPSED_COOKIE, collapsed, { + expires: SIDEBAR_COLLAPSED_COOKIE_EXPIRATION, + }); + } else { + expect(setCookie).not.toHaveBeenCalled(); + } + }, + ); + }); + + describe('initSuperSidebarCollapsedState', () => { + it.each` + windowWidth | cookie | hasClass + ${xl} | ${undefined} | ${false} + ${sm} | ${undefined} | ${true} + ${xl} | ${'true'} | ${true} + ${sm} | ${'true'} | ${true} + `( + 'sets page class to `page-with-super-sidebar-collapsed` when windowWidth is $windowWidth and cookie value is $cookie', + ({ windowWidth, cookie, hasClass }) => { + jest.spyOn(bp, 'windowWidth').mockReturnValue(windowWidth); + getCookie.mockReturnValue(cookie); + + initSuperSidebarCollapsedState(); + + pageHasCollapsedClass(hasClass); + expect(setCookie).not.toHaveBeenCalled(); + }, + ); + }); + + describe('bindSuperSidebarCollapsedEvents', () => { + it.each` + windowWidth | cookie | hasClass + ${xl} | ${undefined} | ${true} + ${sm} | ${undefined} | ${true} + ${xl} | ${'true'} | ${false} + ${sm} | ${'true'} | ${false} + `( + 'toggle click sets page class to `page-with-super-sidebar-collapsed` when windowWidth is $windowWidth and cookie value is $cookie', + ({ windowWidth, cookie, hasClass }) => { + setHTMLFixture(` + <button class="js-super-sidebar-toggle"></button> + <div class="page-with-super-sidebar ${cookie ? SIDEBAR_COLLAPSED_CLASS : ''}"></div> + <aside class="super-sidebar"></aside> + `); + jest.spyOn(bp, 'windowWidth').mockReturnValue(windowWidth); + getCookie.mockReturnValue(cookie); + + bindSuperSidebarCollapsedEvents(); + + findToggles()[0].click(); + + pageHasCollapsedClass(hasClass); + + if (windowWidth >= xl) { + expect(setCookie).toHaveBeenCalledWith(SIDEBAR_COLLAPSED_COOKIE, !cookie, { + expires: SIDEBAR_COLLAPSED_COOKIE_EXPIRATION, + }); + } else { + expect(setCookie).not.toHaveBeenCalled(); + } + }, + ); + }); +}); diff --git a/spec/services/jira_connect_installations/proxy_lifecycle_event_service_spec.rb b/spec/services/jira_connect_installations/proxy_lifecycle_event_service_spec.rb index c621388a734..3c144de2208 100644 --- a/spec/services/jira_connect_installations/proxy_lifecycle_event_service_spec.rb +++ b/spec/services/jira_connect_installations/proxy_lifecycle_event_service_spec.rb @@ -94,9 +94,9 @@ RSpec.describe JiraConnectInstallations::ProxyLifecycleEventService, feature_cat expect(Gitlab::IntegrationsLogger).to receive(:info).with( integration: 'JiraConnect', message: 'Proxy lifecycle event received error response', - event_type: evnet_type, - status_code: 422, - body: 'Error message' + jira_event_type: evnet_type, + jira_status_code: 422, + jira_body: 'Error message' ) execute_service diff --git a/spec/views/devise/confirmations/almost_there.html.haml_spec.rb b/spec/views/devise/confirmations/almost_there.html.haml_spec.rb index c091efe9295..8e12fb5a17e 100644 --- a/spec/views/devise/confirmations/almost_there.html.haml_spec.rb +++ b/spec/views/devise/confirmations/almost_there.html.haml_spec.rb @@ -3,9 +3,9 @@ require 'spec_helper' RSpec.describe 'devise/confirmations/almost_there' do - describe 'confirmations text' do - subject { render(template: 'devise/confirmations/almost_there') } + subject { render(template: 'devise/confirmations/almost_there') } + describe 'confirmations text' do before do allow(view).to receive(:params).and_return(email: email) end @@ -34,4 +34,17 @@ RSpec.describe 'devise/confirmations/almost_there' do end end end + + describe 'register again prompt' do + specify do + subject + + expect(rendered).to have_content( + 'If the email address is incorrect, you can register again with a different email' + ) + expect(rendered).to have_link( + 'register again with a different email', href: new_user_registration_path + ) + end + end end |