mirror of
https://github.com/gitlabhq/gitlabhq.git
synced 2025-07-21 23:37:47 +00:00
Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
@ -93,6 +93,9 @@ export default {
|
||||
});
|
||||
return hasScope;
|
||||
},
|
||||
isLoading() {
|
||||
return this.$apollo.queries.board.loading;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@ -105,7 +108,11 @@ export default {
|
||||
<div
|
||||
class="gl-display-flex gl-flex-direction-column gl-md-flex-direction-row gl-flex-grow-1 gl-lg-mb-0 gl-mb-3 gl-w-full gl-min-w-0"
|
||||
>
|
||||
<boards-selector :board-apollo="board" @switchBoard="$emit('switchBoard', $event)" />
|
||||
<boards-selector
|
||||
:board-apollo="board"
|
||||
:is-current-board-loading="isLoading"
|
||||
@switchBoard="$emit('switchBoard', $event)"
|
||||
/>
|
||||
<new-board-button />
|
||||
<issue-board-filtered-search
|
||||
v-if="isIssueBoard"
|
||||
|
@ -70,6 +70,11 @@ export default {
|
||||
required: false,
|
||||
default: () => ({}),
|
||||
},
|
||||
isCurrentBoardLoading: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@ -92,6 +97,9 @@ export default {
|
||||
boardToUse() {
|
||||
return this.isApolloBoard ? this.boardApollo : this.board;
|
||||
},
|
||||
isBoardToUseLoading() {
|
||||
return this.isApolloBoard ? this.isCurrentBoardLoading : this.isBoardLoading;
|
||||
},
|
||||
parentType() {
|
||||
return this.boardType;
|
||||
},
|
||||
@ -301,7 +309,7 @@ export default {
|
||||
data-qa-selector="boards_dropdown"
|
||||
toggle-class="dropdown-menu-toggle"
|
||||
menu-class="flex-column dropdown-extended-height"
|
||||
:loading="isBoardLoading"
|
||||
:loading="isBoardToUseLoading"
|
||||
:text="boardToUse.name"
|
||||
@show="loadBoards"
|
||||
>
|
||||
|
@ -2,7 +2,6 @@
|
||||
import * as Sentry from '@sentry/browser';
|
||||
import { GlBreakpointInstance, breakpoints } from '@gitlab/ui/dist/utils';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import { s__ } from '~/locale';
|
||||
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
||||
import { PANELS_WITH_PINS } from '../constants';
|
||||
import NavItem from './nav_item.vue';
|
||||
@ -51,10 +50,6 @@ export default {
|
||||
},
|
||||
},
|
||||
|
||||
i18n: {
|
||||
mainNavigation: s__('Navigation|Main navigation'),
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
showFlyoutMenus: false,
|
||||
@ -164,7 +159,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<nav :aria-label="$options.i18n.mainNavigation" class="gl-p-2 gl-relative">
|
||||
<div class="gl-p-2 gl-relative">
|
||||
<ul v-if="hasStaticItems" class="gl-p-0 gl-m-0" data-testid="static-items-section">
|
||||
<nav-item v-for="item in staticItems" :key="item.id" :item="item" is-static />
|
||||
</ul>
|
||||
@ -202,5 +197,5 @@ export default {
|
||||
/>
|
||||
</template>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -2,7 +2,7 @@
|
||||
import { GlButton } from '@gitlab/ui';
|
||||
import { Mousetrap } from '~/lib/mousetrap';
|
||||
import { keysFor, TOGGLE_SUPER_SIDEBAR } from '~/behaviors/shortcuts/keybindings';
|
||||
import { __ } from '~/locale';
|
||||
import { __, s__ } from '~/locale';
|
||||
import Tracking from '~/tracking';
|
||||
import { sidebarState } from '../constants';
|
||||
import { isCollapsed, toggleSuperSidebarCollapsed } from '../super_sidebar_collapsed_state_manager';
|
||||
@ -29,6 +29,7 @@ export default {
|
||||
mixins: [Tracking.mixin()],
|
||||
i18n: {
|
||||
skipToMainContent: __('Skip to main content'),
|
||||
primary: s__('Navigation|Primary'),
|
||||
},
|
||||
inject: ['showTrialStatusWidget'],
|
||||
props: {
|
||||
@ -111,8 +112,9 @@ export default {
|
||||
>
|
||||
{{ $options.i18n.skipToMainContent }}
|
||||
</gl-button>
|
||||
<aside
|
||||
<nav
|
||||
id="super-sidebar"
|
||||
:aria-label="$options.i18n.primary"
|
||||
class="super-sidebar"
|
||||
:class="peekClasses"
|
||||
data-testid="super-sidebar"
|
||||
@ -150,7 +152,7 @@ export default {
|
||||
<help-center :sidebar-data="sidebarData" />
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
</nav>
|
||||
<a
|
||||
v-for="shortcutLink in sidebarData.shortcut_links"
|
||||
:key="shortcutLink.href"
|
||||
|
@ -28,7 +28,7 @@ export default {
|
||||
i18n: {
|
||||
collapseSidebar: __('Hide sidebar'),
|
||||
expandSidebar: __('Show sidebar'),
|
||||
navigationSidebar: __('Navigation sidebar'),
|
||||
primaryNavigationSidebar: __('Primary navigation sidebar'),
|
||||
},
|
||||
data() {
|
||||
return sidebarState;
|
||||
@ -77,7 +77,7 @@ export default {
|
||||
v-gl-tooltip.hover.noninteractive.ds500="tooltip"
|
||||
aria-controls="super-sidebar"
|
||||
:aria-expanded="ariaExpanded"
|
||||
:aria-label="$options.i18n.navigationSidebar"
|
||||
:aria-label="$options.i18n.primaryNavigationSidebar"
|
||||
icon="sidebar"
|
||||
category="tertiary"
|
||||
:disabled="isPeek"
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
module PreferredLanguageSwitcher
|
||||
extend ActiveSupport::Concern
|
||||
include Gitlab::Utils::StrongMemoize
|
||||
include PreferredLanguageSwitcherHelper
|
||||
|
||||
private
|
||||
|
||||
@ -11,8 +13,37 @@ module PreferredLanguageSwitcher
|
||||
|
||||
def preferred_language
|
||||
cookies[:preferred_language].presence_in(Gitlab::I18n.available_locales) ||
|
||||
selectable_language(marketing_site_language) ||
|
||||
selectable_language(browser_languages) ||
|
||||
Gitlab::CurrentSettings.default_preferred_language
|
||||
end
|
||||
|
||||
def selectable_language(language_options)
|
||||
language_options.find { |lan| ordered_selectable_locales_codes.include?(lan) }
|
||||
end
|
||||
|
||||
def ordered_selectable_locales_codes
|
||||
ordered_selectable_locales.pluck(:value) # rubocop:disable CodeReuse/ActiveRecord
|
||||
end
|
||||
|
||||
def browser_languages
|
||||
formatted_http_language_header = request.env['HTTP_ACCEPT_LANGUAGE']&.tr('-', '_')
|
||||
|
||||
return [] unless formatted_http_language_header
|
||||
|
||||
formatted_http_language_header.split(%r{[;,]}).reject { |str| str.start_with?('q') }
|
||||
end
|
||||
strong_memoize_attr :browser_languages
|
||||
|
||||
def marketing_site_language
|
||||
return [] unless params[:glm_source]
|
||||
|
||||
locale = params[:glm_source].scan(%r{(\w{2})-(\w{2})}).flatten
|
||||
|
||||
return [] if locale.empty?
|
||||
|
||||
[locale[0], "#{locale[0]}_#{locale[1]}"]
|
||||
end
|
||||
end
|
||||
|
||||
PreferredLanguageSwitcher.prepend_mod
|
||||
|
@ -0,0 +1,8 @@
|
||||
---
|
||||
name: ci_editor_assistant_tool
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/130162
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/423524
|
||||
milestone: '16.4'
|
||||
type: development
|
||||
group: group::environments
|
||||
default_enabled: false
|
@ -0,0 +1,18 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class DropIndexSuccessfulDeploymentsOnClusterIdAndEnvironmentId < Gitlab::Database::Migration[2.1]
|
||||
INDEX_NAME = 'index_successful_deployments_on_cluster_id_and_environment_id'
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
remove_concurrent_index_by_name :deployments, name: INDEX_NAME
|
||||
end
|
||||
|
||||
def down
|
||||
# This is based on the following `CREATE INDEX` command in db/init_structure.sql:
|
||||
# CREATE INDEX index_successful_deployments_on_cluster_id_and_environment_id ON deployments
|
||||
# USING btree (cluster_id, environment_id) WHERE (status = 2);
|
||||
add_concurrent_index :deployments, %i[cluster_id environment_id], name: INDEX_NAME, where: 'status = 2'
|
||||
end
|
||||
end
|
1
db/schema_migrations/20230904103804
Normal file
1
db/schema_migrations/20230904103804
Normal file
@ -0,0 +1 @@
|
||||
daa7361dae1258a9fae12e7d0cc86e2484dd945f9cef26430817a761d198b34d
|
@ -33667,8 +33667,6 @@ CREATE UNIQUE INDEX index_subscriptions_on_subscribable_and_user_id_and_project_
|
||||
|
||||
CREATE INDEX index_successful_authentication_events_for_metrics ON authentication_events USING btree (user_id, provider, created_at) WHERE (result = 1);
|
||||
|
||||
CREATE INDEX index_successful_deployments_on_cluster_id_and_environment_id ON deployments USING btree (cluster_id, environment_id) WHERE (status = 2);
|
||||
|
||||
CREATE UNIQUE INDEX index_suggestions_on_note_id_and_relative_order ON suggestions USING btree (note_id, relative_order);
|
||||
|
||||
CREATE UNIQUE INDEX index_system_access_microsoft_applications_on_namespace_id ON system_access_microsoft_applications USING btree (namespace_id);
|
||||
|
@ -127,7 +127,7 @@ This rule schedules a scan pipeline, enforcing the defined actions on the schedu
|
||||
|
||||
1. You must specify only one of `branches`, `branch_type`, or `agents`.
|
||||
|
||||
Scheduled scan pipelines are triggered by a security policy bot user that is a guest member of the project. Security policy bot users are automatically created when the security policy project is linked, and removed when the security policy project is unlinked.
|
||||
Scheduled scan pipelines are triggered by a security policy bot user that is a guest member of the project with elevated permissions for users of type `security_policy_bot` so it may carry out this task. Security policy bot users are automatically created when the security policy project is linked, and removed when the security policy project is unlinked.
|
||||
|
||||
If the project does not have a security policy bot user, the scheduled scan pipeline is triggered by the user that modified the security policy project last.
|
||||
|
||||
|
@ -30589,9 +30589,6 @@ msgstr ""
|
||||
msgid "Navigation|Leave admin mode"
|
||||
msgstr ""
|
||||
|
||||
msgid "Navigation|Main navigation"
|
||||
msgstr ""
|
||||
|
||||
msgid "Navigation|Manage"
|
||||
msgstr ""
|
||||
|
||||
@ -30622,6 +30619,9 @@ msgstr ""
|
||||
msgid "Navigation|Plan"
|
||||
msgstr ""
|
||||
|
||||
msgid "Navigation|Primary"
|
||||
msgstr ""
|
||||
|
||||
msgid "Navigation|Projects"
|
||||
msgstr ""
|
||||
|
||||
@ -35329,6 +35329,9 @@ msgstr ""
|
||||
msgid "Primary Action"
|
||||
msgstr ""
|
||||
|
||||
msgid "Primary navigation sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Print as PDF"
|
||||
msgstr ""
|
||||
|
||||
|
@ -13,13 +13,79 @@ RSpec.describe PreferredLanguageSwitcher, type: :controller do
|
||||
end
|
||||
end
|
||||
|
||||
subject { cookies[:preferred_language] }
|
||||
|
||||
context 'when first visit' do
|
||||
let(:glm_source) { 'about.gitlab.com' }
|
||||
let(:accept_language_header) { nil }
|
||||
|
||||
before do
|
||||
get :new
|
||||
request.env['HTTP_ACCEPT_LANGUAGE'] = accept_language_header
|
||||
|
||||
get :new, params: { glm_source: glm_source }
|
||||
end
|
||||
|
||||
it 'sets preferred_language to default' do
|
||||
expect(cookies[:preferred_language]).to eq Gitlab::CurrentSettings.default_preferred_language
|
||||
expect(subject).to eq Gitlab::CurrentSettings.default_preferred_language
|
||||
end
|
||||
|
||||
context 'when language param is valid' do
|
||||
let(:glm_source) { 'about.gitlab.com/fr-fr/' }
|
||||
|
||||
it 'sets preferred_language accordingly' do
|
||||
expect(subject).to eq 'fr'
|
||||
end
|
||||
|
||||
context 'when language param is invalid' do
|
||||
let(:glm_source) { 'about.gitlab.com/ko-ko/' }
|
||||
|
||||
it 'sets preferred_language to default' do
|
||||
expect(subject).to eq Gitlab::CurrentSettings.default_preferred_language
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when browser preferred language is not english' do
|
||||
context 'with selectable language' do
|
||||
let(:accept_language_header) { 'zh-CN,zh;q=0.8,zh-TW;q=0.7' }
|
||||
|
||||
it 'sets preferred_language accordingly' do
|
||||
expect(subject).to eq 'zh_CN'
|
||||
end
|
||||
end
|
||||
|
||||
context 'with unselectable language' do
|
||||
let(:accept_language_header) { 'nl-NL;q=0.8' }
|
||||
|
||||
it 'sets preferred_language to default' do
|
||||
expect(subject).to eq Gitlab::CurrentSettings.default_preferred_language
|
||||
end
|
||||
end
|
||||
|
||||
context 'with empty string in language header' do
|
||||
let(:accept_language_header) { '' }
|
||||
|
||||
it 'sets preferred_language to default' do
|
||||
expect(subject).to eq Gitlab::CurrentSettings.default_preferred_language
|
||||
end
|
||||
end
|
||||
|
||||
context 'with language header without dashes' do
|
||||
let(:accept_language_header) { 'fr;q=8' }
|
||||
|
||||
it 'sets preferred_language accordingly' do
|
||||
expect(subject).to eq 'fr'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when language params and language header are both valid' do
|
||||
let(:accept_language_header) { 'zh-CN,zh;q=0.8,zh-TW;q=0.7' }
|
||||
let(:glm_source) { 'about.gitlab.com/fr-fr/' }
|
||||
|
||||
it 'sets preferred_language according to language params' do
|
||||
expect(subject).to eq 'fr'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -36,7 +102,7 @@ RSpec.describe PreferredLanguageSwitcher, type: :controller do
|
||||
let(:user_preferred_language) { 'zh_CN' }
|
||||
|
||||
it 'keeps preferred language unchanged' do
|
||||
expect(cookies[:preferred_language]).to eq user_preferred_language
|
||||
expect(subject).to eq user_preferred_language
|
||||
end
|
||||
end
|
||||
|
||||
@ -44,7 +110,7 @@ RSpec.describe PreferredLanguageSwitcher, type: :controller do
|
||||
let(:user_preferred_language) { 'xxx' }
|
||||
|
||||
it 'sets preferred_language to default' do
|
||||
expect(cookies[:preferred_language]).to eq Gitlab::CurrentSettings.default_preferred_language
|
||||
expect(subject).to eq Gitlab::CurrentSettings.default_preferred_language
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -87,6 +87,7 @@ describe('BoardsSelector', () => {
|
||||
isGroupBoard = false,
|
||||
isProjectBoard = false,
|
||||
provide = {},
|
||||
props = {},
|
||||
} = {}) => {
|
||||
fakeApollo = createMockApollo([
|
||||
[projectBoardsQuery, projectBoardsQueryHandler],
|
||||
@ -100,6 +101,7 @@ describe('BoardsSelector', () => {
|
||||
apolloProvider: fakeApollo,
|
||||
propsData: {
|
||||
throttleDuration,
|
||||
...props,
|
||||
},
|
||||
attachTo: document.body,
|
||||
provide: {
|
||||
@ -307,4 +309,14 @@ describe('BoardsSelector', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Apollo boards', () => {
|
||||
it('displays loading state of dropdown while current board is being fetched', () => {
|
||||
createComponent({
|
||||
props: { isCurrentBoardLoading: true },
|
||||
provide: { isApolloBoard: true },
|
||||
});
|
||||
expect(findDropdown().props('loading')).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -201,11 +201,4 @@ describe('Sidebar Menu', () => {
|
||||
expect(findMainMenuSeparator().exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('ARIA attributes', () => {
|
||||
it('adds aria-label attribute to nav element', () => {
|
||||
createWrapper();
|
||||
expect(wrapper.find('nav').attributes('aria-label')).toBe('Main navigation');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -274,4 +274,11 @@ describe('SuperSidebar component', () => {
|
||||
expect(findTrialStatusPopover().exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('ARIA attributes', () => {
|
||||
it('adds aria-label attribute to nav element', () => {
|
||||
createWrapper();
|
||||
expect(wrapper.find('nav').attributes('aria-label')).toBe('Primary');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -53,7 +53,7 @@ describe('SuperSidebarToggle component', () => {
|
||||
|
||||
it('has aria-label attribute', () => {
|
||||
createWrapper();
|
||||
expect(findButton().attributes('aria-label')).toBe(__('Navigation sidebar'));
|
||||
expect(findButton().attributes('aria-label')).toBe(__('Primary navigation sidebar'));
|
||||
});
|
||||
|
||||
it('is disabled when isPeek is true', () => {
|
||||
|
@ -73,7 +73,13 @@ export default defineConfig({
|
||||
},
|
||||
plugins: [
|
||||
fixedRubyPlugin,
|
||||
vue(),
|
||||
vue({
|
||||
template: {
|
||||
compilerOptions: {
|
||||
whitespace: 'preserve',
|
||||
},
|
||||
},
|
||||
}),
|
||||
graphql(),
|
||||
svgLoader({
|
||||
defaultImport: 'raw',
|
||||
|
Reference in New Issue
Block a user