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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/organizations/profile/preferences/index.js4
-rw-r--r--app/assets/javascripts/persistent_user_callout.js5
-rw-r--r--app/assets/javascripts/persistent_user_callouts.js1
-rw-r--r--app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue6
-rw-r--r--app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue26
-rw-r--r--app/assets/javascripts/projects/settings_service_desk/index.js2
-rw-r--r--app/assets/javascripts/repository/commits_service.js5
-rw-r--r--app/assets/javascripts/search/index.js27
-rw-r--r--app/assets/javascripts/search/sidebar/components/all_scopes_start_filters.vue19
-rw-r--r--app/assets/javascripts/search/sidebar/components/app.vue16
-rw-r--r--app/assets/javascripts/search/sidebar/components/group_filter.vue (renamed from app/assets/javascripts/search/topbar/components/group_filter.vue)50
-rw-r--r--app/assets/javascripts/search/sidebar/components/project_filter.vue (renamed from app/assets/javascripts/search/topbar/components/project_filter.vue)58
-rw-r--r--app/assets/javascripts/search/sidebar/components/scope_sidebar_navigation.vue3
-rw-r--r--app/assets/javascripts/search/sidebar/components/searchable_dropdown.vue (renamed from app/assets/javascripts/search/topbar/components/searchable_dropdown.vue)0
-rw-r--r--app/assets/javascripts/search/sidebar/constants/index.js22
-rw-r--r--app/assets/javascripts/search/sidebar/index.js20
-rw-r--r--app/assets/javascripts/search/store/state.js5
-rw-r--r--app/assets/javascripts/search/topbar/components/app.vue54
-rw-r--r--app/assets/javascripts/search/topbar/constants.js22
-rw-r--r--app/assets/javascripts/search/topbar/index.js9
-rw-r--r--app/assets/javascripts/search/under_topbar/index.js1
-rw-r--r--app/assets/javascripts/super_sidebar/components/super_sidebar.vue7
-rw-r--r--app/assets/stylesheets/framework/animations.scss3
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss8
-rw-r--r--app/assets/stylesheets/framework/header.scss82
-rw-r--r--app/controllers/explore/catalog_controller.rb5
-rw-r--r--app/controllers/profiles/preferences_controller.rb1
-rw-r--r--app/controllers/projects/blob_controller.rb1
-rw-r--r--app/controllers/projects/service_desk_controller.rb9
-rw-r--r--app/controllers/projects/tree_controller.rb1
-rw-r--r--app/controllers/projects_controller.rb1
-rw-r--r--app/graphql/resolvers/namespaces/work_item_state_counts_resolver.rb30
-rw-r--r--app/graphql/resolvers/work_item_state_counts_resolver.rb16
-rw-r--r--app/graphql/types/group_type.rb8
-rw-r--r--app/graphql/types/project_type.rb7
-rw-r--r--app/graphql/types/work_item_state_counts_type.rb25
-rw-r--r--app/helpers/application_helper.rb4
-rw-r--r--app/helpers/dashboard_helper.rb12
-rw-r--r--app/helpers/issuables_helper.rb10
-rw-r--r--app/helpers/nav_helper.rb8
-rw-r--r--app/helpers/organizations/organization_helper.rb3
-rw-r--r--app/helpers/todos_helper.rb4
-rw-r--r--app/models/issue.rb5
-rw-r--r--app/models/user.rb5
-rw-r--r--app/models/user_preference.rb13
-rw-r--r--app/services/groups/participants_service.rb4
-rw-r--r--app/services/merge_requests/create_ref_service.rb6
-rw-r--r--app/services/namespaces/in_product_marketing_emails_service.rb50
-rw-r--r--app/services/users/in_product_marketing_email_records.rb26
-rw-r--r--app/views/layouts/_head.html.haml2
-rw-r--r--app/views/layouts/header/_current_user_dropdown.html.haml51
-rw-r--r--app/views/layouts/header/_current_user_dropdown_item.html.haml12
-rw-r--r--app/views/layouts/header/_default.html.haml82
-rw-r--r--app/views/layouts/help.html.haml3
-rw-r--r--app/views/layouts/search.html.haml3
-rw-r--r--app/views/projects/_service_desk_settings.html.haml1
-rw-r--r--app/views/search/_results_list.html.haml4
-rw-r--r--app/views/search/_results_status.html.haml5
-rw-r--r--app/views/search/show.html.haml4
-rw-r--r--app/views/shared/_ci_catalog_badge.html.haml3
-rw-r--r--app/views/shared/runners/_runner_description.html.haml2
61 files changed, 348 insertions, 533 deletions
diff --git a/app/assets/javascripts/organizations/profile/preferences/index.js b/app/assets/javascripts/organizations/profile/preferences/index.js
index 0b0dd313cd8..11686b62eca 100644
--- a/app/assets/javascripts/organizations/profile/preferences/index.js
+++ b/app/assets/javascripts/organizations/profile/preferences/index.js
@@ -30,8 +30,8 @@ export const initHomeOrganizationSetting = () => {
block: true,
label: s__('Organization|Home organization'),
description: s__('Organization|Choose what organization you want to see by default.'),
- inputName: 'home_organization',
- inputId: 'home_organization',
+ inputName: 'user[home_organization_id]',
+ inputId: 'user_home_organization_id',
initialSelection,
toggleClass: 'gl-form-input-xl',
},
diff --git a/app/assets/javascripts/persistent_user_callout.js b/app/assets/javascripts/persistent_user_callout.js
index 71dc8c3d020..007b1454138 100644
--- a/app/assets/javascripts/persistent_user_callout.js
+++ b/app/assets/javascripts/persistent_user_callout.js
@@ -22,12 +22,17 @@ export default class PersistentUserCallout {
init() {
const followLink = this.container.querySelector('.js-follow-link');
+ const closeAndFollowLink = this.container.querySelector('.js-close-and-follow-link');
if (this.closeButtons.length) {
this.handleCloseButtonCallout();
} else if (followLink) {
this.handleFollowLinkCallout(followLink);
}
+
+ if (closeAndFollowLink) {
+ this.handleFollowLinkCallout(closeAndFollowLink);
+ }
}
handleCloseButtonCallout() {
diff --git a/app/assets/javascripts/persistent_user_callouts.js b/app/assets/javascripts/persistent_user_callouts.js
index 39c6d3bd14d..7420542a065 100644
--- a/app/assets/javascripts/persistent_user_callouts.js
+++ b/app/assets/javascripts/persistent_user_callouts.js
@@ -4,7 +4,6 @@ const PERSISTENT_USER_CALLOUTS = [
'.js-recovery-settings-callout',
'.js-users-over-license-callout',
'.js-admin-licensed-user-count-threshold',
- '.js-buy-pipeline-minutes-notification-callout',
'.js-token-expiry-callout',
'.js-registration-enabled-callout',
'.js-new-user-signups-cap-reached',
diff --git a/app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue
index 69ea29edc14..a9dca81b9f4 100644
--- a/app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue
+++ b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue
@@ -53,6 +53,9 @@ export default {
projectKey: {
default: '',
},
+ reopenIssueOnExternalParticipantNote: {
+ default: false,
+ },
addExternalParticipantsFromCc: {
default: false,
},
@@ -115,6 +118,7 @@ export default {
fileTemplateProjectId,
outgoingName,
projectKey,
+ reopenIssueOnExternalParticipantNote,
addExternalParticipantsFromCc,
}) {
this.isTemplateSaving = true;
@@ -123,6 +127,7 @@ export default {
issue_template_key: selectedTemplate,
outgoing_name: outgoingName,
project_key: projectKey,
+ reopen_issue_on_external_participant_note: reopenIssueOnExternalParticipantNote,
add_external_participants_from_cc: addExternalParticipantsFromCc,
service_desk_enabled: this.isEnabled,
file_template_project_id: fileTemplateProjectId,
@@ -195,6 +200,7 @@ export default {
:initial-selected-file-template-project-id="selectedFileTemplateProjectId"
:initial-outgoing-name="outgoingName"
:initial-project-key="projectKey"
+ :initial-reopen-issue-on-external-participant-note="reopenIssueOnExternalParticipantNote"
:initial-add-external-participants-from-cc="addExternalParticipantsFromCc"
:templates="templates"
:is-template-saving="isTemplateSaving"
diff --git a/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue
index 891ad53dd10..2853a7d8d72 100644
--- a/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue
+++ b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue
@@ -23,6 +23,12 @@ export default {
issueTrackerEnableMessage: __(
'To use Service Desk in this project, you must %{linkStart}activate the issue tracker%{linkEnd}.',
),
+ reopenIssueOnExternalParticipantNote: {
+ label: s__('ServiceDesk|Reopen issues when an external participant comments'),
+ help: s__(
+ 'ServiceDesk|This also adds an internal comment that mentions the assignees of the issue.',
+ ),
+ },
addExternalParticipantsFromCc: {
label: s__('ServiceDesk|Add external participants from the %{codeStart}Cc%{codeEnd} header'),
help: s__(
@@ -91,6 +97,11 @@ export default {
required: false,
default: '',
},
+ initialReopenIssueOnExternalParticipantNote: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
initialAddExternalParticipantsFromCc: {
type: Boolean,
required: false,
@@ -113,6 +124,7 @@ export default {
selectedFileTemplateProjectId: this.initialSelectedFileTemplateProjectId,
outgoingName: this.initialOutgoingName || __('GitLab Support Bot'),
projectKey: this.initialProjectKey,
+ reopenIssueOnExternalParticipantNote: this.initialReopenIssueOnExternalParticipantNote,
addExternalParticipantsFromCc: this.initialAddExternalParticipantsFromCc,
searchTerm: '',
projectKeyError: null,
@@ -156,6 +168,7 @@ export default {
selectedTemplate: this.selectedTemplate,
outgoingName: this.outgoingName,
projectKey: this.projectKey,
+ reopenIssueOnExternalParticipantNote: this.reopenIssueOnExternalParticipantNote,
addExternalParticipantsFromCc: this.addExternalParticipantsFromCc,
fileTemplateProjectId: this.selectedFileTemplateProjectId,
});
@@ -323,9 +336,22 @@ export default {
</gl-form-group>
<gl-form-checkbox
+ v-model="reopenIssueOnExternalParticipantNote"
+ :disabled="!isIssueTrackerEnabled"
+ data-testid="reopen-issue-on-external-participant-note"
+ >
+ {{ $options.i18n.reopenIssueOnExternalParticipantNote.label }}
+
+ <template #help>
+ {{ $options.i18n.reopenIssueOnExternalParticipantNote.help }}
+ </template>
+ </gl-form-checkbox>
+
+ <gl-form-checkbox
v-if="showAddExternalParticipantsFromCC"
v-model="addExternalParticipantsFromCc"
:disabled="!isIssueTrackerEnabled"
+ data-testid="add-external-participants-from-cc"
>
<gl-sprintf :message="$options.i18n.addExternalParticipantsFromCc.label">
<template #code="{ content }">
diff --git a/app/assets/javascripts/projects/settings_service_desk/index.js b/app/assets/javascripts/projects/settings_service_desk/index.js
index ce223b349bf..a3c310ec501 100644
--- a/app/assets/javascripts/projects/settings_service_desk/index.js
+++ b/app/assets/javascripts/projects/settings_service_desk/index.js
@@ -21,6 +21,7 @@ export default () => {
incomingEmail,
outgoingName,
projectKey,
+ reopenIssueOnExternalParticipantNote,
addExternalParticipantsFromCc,
selectedTemplate,
selectedFileTemplateProjectId,
@@ -40,6 +41,7 @@ export default () => {
isIssueTrackerEnabled: parseBoolean(issueTrackerEnabled),
outgoingName,
projectKey,
+ reopenIssueOnExternalParticipantNote: parseBoolean(reopenIssueOnExternalParticipantNote),
addExternalParticipantsFromCc: parseBoolean(addExternalParticipantsFromCc),
selectedTemplate,
selectedFileTemplateProjectId: parseInt(selectedFileTemplateProjectId, 10) || null,
diff --git a/app/assets/javascripts/repository/commits_service.js b/app/assets/javascripts/repository/commits_service.js
index 1e0de045d39..44113788716 100644
--- a/app/assets/javascripts/repository/commits_service.js
+++ b/app/assets/javascripts/repository/commits_service.js
@@ -31,13 +31,14 @@ const fetchData = (projectPath, path, ref, offset, refType) => {
fetchedBatches.push(offset);
+ const encodePathFunc = gon.features.encodingLogsTree ? encodeURI : encodeURIComponent;
const url = joinPaths(
gon.relative_url_root || '/',
projectPath,
'/-/refs/',
- encodeURIComponent(ref),
+ encodePathFunc(ref),
'/logs_tree/',
- encodeURIComponent(removeLeadingSlash(path)),
+ encodePathFunc(removeLeadingSlash(path)),
);
return axios
diff --git a/app/assets/javascripts/search/index.js b/app/assets/javascripts/search/index.js
index 5879735d0f6..0c70a3e70f2 100644
--- a/app/assets/javascripts/search/index.js
+++ b/app/assets/javascripts/search/index.js
@@ -1,30 +1,41 @@
import setHighlightClass from 'ee_else_ce/search/highlight_blob_search_result';
import { queryToObject } from '~/lib/utils/url_utility';
import syntaxHighlight from '~/syntax_highlight';
-import { initSidebar, sidebarInitState } from './sidebar';
+import { initSidebar } from './sidebar';
import { initSearchSort } from './sort';
import createStore from './store';
import { initTopbar } from './topbar';
import { initBlobRefSwitcher } from './under_topbar';
-const topbarInitState = () => {
- const el = document.getElementById('js-search-topbar');
+const sidebarInitState = () => {
+ const el = document.getElementById('js-search-sidebar');
if (!el) return {};
- const { defaultBranchName } = el.dataset;
- return { defaultBranchName };
+
+ const { navigationJson, searchType, groupInitialJson, projectInitialJson } = el.dataset;
+
+ const navigationJsonParsed = JSON.parse(navigationJson);
+ const groupInitialJsonParsed = JSON.parse(groupInitialJson);
+ const projectInitialJsonParsed = JSON.parse(projectInitialJson);
+
+ return { navigationJsonParsed, searchType, groupInitialJsonParsed, projectInitialJsonParsed };
};
export const initSearchApp = () => {
syntaxHighlight(document.querySelectorAll('.js-search-results'));
const query = queryToObject(window.location.search, { gatherArrays: true });
- const { navigationJsonParsed: navigation, searchType } = sidebarInitState() || {};
- const { defaultBranchName } = topbarInitState() || {};
+ const {
+ navigationJsonParsed: navigation,
+ searchType,
+ groupInitialJsonParsed: groupInitialJson,
+ projectInitialJsonParsed: projectInitialJson,
+ } = sidebarInitState() || {};
const store = createStore({
query,
navigation,
searchType,
- defaultBranchName,
+ groupInitialJson,
+ projectInitialJson,
});
initTopbar(store);
diff --git a/app/assets/javascripts/search/sidebar/components/all_scopes_start_filters.vue b/app/assets/javascripts/search/sidebar/components/all_scopes_start_filters.vue
new file mode 100644
index 00000000000..cb017b6898b
--- /dev/null
+++ b/app/assets/javascripts/search/sidebar/components/all_scopes_start_filters.vue
@@ -0,0 +1,19 @@
+<script>
+import GroupFilter from './group_filter.vue';
+import ProjectFilter from './project_filter.vue';
+
+export default {
+ name: 'AllScopesStartFilters',
+ components: {
+ GroupFilter,
+ ProjectFilter,
+ },
+};
+</script>
+
+<template>
+ <div class="gl-px-5 gl-pt-6">
+ <group-filter class="gl-mb-5" />
+ <project-filter class="gl-mb-5" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/search/sidebar/components/app.vue b/app/assets/javascripts/search/sidebar/components/app.vue
index 307be0b0aa0..bbee0e441cc 100644
--- a/app/assets/javascripts/search/sidebar/components/app.vue
+++ b/app/assets/javascripts/search/sidebar/components/app.vue
@@ -25,6 +25,7 @@ import NotesFilters from './notes_filters.vue';
import CommitsFilters from './commits_filters.vue';
import MilestonesFilters from './milestones_filters.vue';
import WikiBlobsFilters from './wiki_blobs_filters.vue';
+import AllScopesStartFilters from './all_scopes_start_filters.vue';
export default {
name: 'GlobalSearchSidebar',
@@ -40,8 +41,16 @@ export default {
DomElementListener,
CommitsFilters,
MilestonesFilters,
+ AllScopesStartFilters,
},
mixins: [glFeatureFlagsMixin()],
+ props: {
+ headerText: {
+ required: false,
+ type: String,
+ default: '',
+ },
+ },
computed: {
...mapState(['searchType']),
...mapGetters(['currentScope']),
@@ -82,6 +91,13 @@ export default {
<section>
<dom-element-listener selector="#js-open-mobile-filters" @click="toggleFiltersFromSidebar" />
<sidebar-portal>
+ <all-scopes-start-filters />
+ <div
+ v-if="headerText"
+ class="gl-px-5 gl-pt-3 gl-pb-2 gl-m-0 gl-reset-line-height gl-font-weight-bold gl-font-sm super-sidebar-context-header"
+ >
+ {{ headerText }}
+ </div>
<scope-sidebar-navigation />
<issues-filters v-if="showIssuesFilters" />
<merge-requests-filters v-if="showMergeRequestFilters" />
diff --git a/app/assets/javascripts/search/topbar/components/group_filter.vue b/app/assets/javascripts/search/sidebar/components/group_filter.vue
index 7f13def8a0f..20231cdda6a 100644
--- a/app/assets/javascripts/search/topbar/components/group_filter.vue
+++ b/app/assets/javascripts/search/sidebar/components/group_filter.vue
@@ -2,34 +2,27 @@
import { isEmpty } from 'lodash';
// eslint-disable-next-line no-restricted-imports
import { mapState, mapActions, mapGetters } from 'vuex';
+import { s__ } from '~/locale';
import { visitUrl, setUrlParams } from '~/lib/utils/url_utility';
import { ANY_OPTION, GROUP_DATA, PROJECT_DATA } from '../constants';
import SearchableDropdown from './searchable_dropdown.vue';
export default {
name: 'GroupFilter',
+ i18n: {
+ groupFieldLabel: s__('GlobalSearch|Group'),
+ },
components: {
SearchableDropdown,
},
- props: {
- groupInitialJson: {
- type: Object,
- required: false,
- default: () => ({}),
- },
- labelId: {
- type: String,
- required: false,
- default: 'labelId',
- },
- },
data() {
return {
search: '',
+ labelId: 'group-filter-dropdown-id',
};
},
computed: {
- ...mapState(['query', 'groups', 'fetchingGroups']),
+ ...mapState(['query', 'groups', 'fetchingGroups', 'groupInitialJson', 'useSidebarNavigation']),
...mapGetters(['frequentGroups', 'currentScope']),
selectedGroup() {
return isEmpty(this.groupInitialJson) ? ANY_OPTION : this.groupInitialJson;
@@ -73,17 +66,22 @@ export default {
</script>
<template>
- <searchable-dropdown
- data-testid="group-filter"
- :header-text="$options.GROUP_DATA.headerText"
- :name="$options.GROUP_DATA.name"
- :loading="fetchingGroups"
- :selected-item="selectedGroup"
- :items="groups"
- :frequent-items="frequentGroups"
- :search-handler="fetchGroups"
- :label-id="labelId"
- @first-open="firstLoad"
- @change="handleGroupChange"
- />
+ <div>
+ <h5 :id="labelId" class="gl-mt-0 gl-mb-5 gl-font-sm">
+ {{ $options.i18n.groupFieldLabel }}
+ </h5>
+ <searchable-dropdown
+ data-testid="group-filter"
+ :header-text="$options.GROUP_DATA.headerText"
+ :name="$options.GROUP_DATA.name"
+ :loading="fetchingGroups"
+ :selected-item="selectedGroup"
+ :items="groups"
+ :frequent-items="frequentGroups"
+ :search-handler="fetchGroups"
+ :label-id="labelId"
+ @first-open="firstLoad"
+ @change="handleGroupChange"
+ />
+ </div>
</template>
diff --git a/app/assets/javascripts/search/topbar/components/project_filter.vue b/app/assets/javascripts/search/sidebar/components/project_filter.vue
index ecd118a07ac..76983644e60 100644
--- a/app/assets/javascripts/search/topbar/components/project_filter.vue
+++ b/app/assets/javascripts/search/sidebar/components/project_filter.vue
@@ -2,34 +2,33 @@
import { isEmpty } from 'lodash';
// eslint-disable-next-line no-restricted-imports
import { mapState, mapActions, mapGetters } from 'vuex';
+import { s__ } from '~/locale';
import { visitUrl, setUrlParams } from '~/lib/utils/url_utility';
-import { ANY_OPTION, GROUP_DATA, PROJECT_DATA } from '../constants';
+import { ANY_OPTION, GROUP_DATA, PROJECT_DATA } from '~/search/sidebar/constants';
import SearchableDropdown from './searchable_dropdown.vue';
export default {
name: 'ProjectFilter',
+ i18n: {
+ projectFieldLabel: s__('GlobalSearch|Project'),
+ },
components: {
SearchableDropdown,
},
- props: {
- projectInitialJson: {
- type: Object,
- required: false,
- default: () => null,
- },
- labelId: {
- type: String,
- required: false,
- default: '',
- },
- },
data() {
return {
search: '',
+ labelId: 'projects-filter-dropdown-id',
};
},
computed: {
- ...mapState(['query', 'projects', 'fetchingProjects']),
+ ...mapState([
+ 'query',
+ 'projects',
+ 'fetchingProjects',
+ 'projectInitialJson',
+ 'useSidebarNavigation',
+ ]),
...mapGetters(['frequentProjects', 'currentScope']),
selectedProject() {
return isEmpty(this.projectInitialJson) ? ANY_OPTION : this.projectInitialJson;
@@ -74,17 +73,22 @@ export default {
</script>
<template>
- <searchable-dropdown
- data-testid="project-filter"
- :header-text="$options.PROJECT_DATA.headerText"
- :name="$options.PROJECT_DATA.name"
- :loading="fetchingProjects"
- :selected-item="selectedProject"
- :items="projects"
- :frequent-items="frequentProjects"
- :search-handler="fetchProjects"
- :label-id="labelId"
- @first-open="firstLoad"
- @change="handleProjectChange"
- />
+ <div>
+ <h5 :id="labelId" class="gl-mt-0 gl-mb-5 gl-font-sm">
+ {{ $options.i18n.projectFieldLabel }}
+ </h5>
+ <searchable-dropdown
+ data-testid="project-filter"
+ :header-text="$options.PROJECT_DATA.headerText"
+ :name="$options.PROJECT_DATA.name"
+ :loading="fetchingProjects"
+ :selected-item="selectedProject"
+ :items="projects"
+ :frequent-items="frequentProjects"
+ :search-handler="fetchProjects"
+ :label-id="labelId"
+ @first-open="firstLoad"
+ @change="handleProjectChange"
+ />
+ </div>
</template>
diff --git a/app/assets/javascripts/search/sidebar/components/scope_sidebar_navigation.vue b/app/assets/javascripts/search/sidebar/components/scope_sidebar_navigation.vue
index f30618ad9b7..874803a720d 100644
--- a/app/assets/javascripts/search/sidebar/components/scope_sidebar_navigation.vue
+++ b/app/assets/javascripts/search/sidebar/components/scope_sidebar_navigation.vue
@@ -2,6 +2,7 @@
// eslint-disable-next-line no-restricted-imports
import { mapActions, mapState, mapGetters } from 'vuex';
import { s__ } from '~/locale';
+import eventHub from '~/super_sidebar/event_hub';
import NavItem from '~/super_sidebar/components/nav_item.vue';
import { NAV_LINK_DEFAULT_CLASSES, NAV_LINK_COUNT_DEFAULT_CLASSES } from '../constants';
@@ -18,6 +19,8 @@ export default {
...mapGetters(['navigationItems']),
},
created() {
+ eventHub.$emit('toggle-menu-header', false);
+
if (this.urlQuery?.search) {
this.fetchSidebarCount();
}
diff --git a/app/assets/javascripts/search/topbar/components/searchable_dropdown.vue b/app/assets/javascripts/search/sidebar/components/searchable_dropdown.vue
index c1f0bfc59f3..c1f0bfc59f3 100644
--- a/app/assets/javascripts/search/topbar/components/searchable_dropdown.vue
+++ b/app/assets/javascripts/search/sidebar/components/searchable_dropdown.vue
diff --git a/app/assets/javascripts/search/sidebar/constants/index.js b/app/assets/javascripts/search/sidebar/constants/index.js
index 95906c840d7..e3b0db670b5 100644
--- a/app/assets/javascripts/search/sidebar/constants/index.js
+++ b/app/assets/javascripts/search/sidebar/constants/index.js
@@ -1,3 +1,5 @@
+import { __ } from '~/locale';
+
export const SCOPE_ISSUES = 'issues';
export const SCOPE_MERGE_REQUESTS = 'merge_requests';
export const SCOPE_BLOB = 'blobs';
@@ -26,3 +28,23 @@ export const TRACKING_LABEL_RESET = 'Reset Filters';
export const SEARCH_TYPE_BASIC = 'basic';
export const SEARCH_TYPE_ADVANCED = 'advanced';
export const SEARCH_TYPE_ZOEKT = 'zoekt';
+
+export const ANY_OPTION = {
+ id: null,
+ name: __('Any'),
+ name_with_namespace: __('Any'),
+};
+
+export const GROUP_DATA = {
+ headerText: __('Filter results by group'),
+ queryParam: 'group_id',
+ name: 'name',
+ fullName: 'full_name',
+};
+
+export const PROJECT_DATA = {
+ headerText: __('Filter results by project'),
+ queryParam: 'project_id',
+ name: 'name',
+ fullName: 'name_with_namespace',
+};
diff --git a/app/assets/javascripts/search/sidebar/index.js b/app/assets/javascripts/search/sidebar/index.js
index 3a699355dc9..9a7472ccad3 100644
--- a/app/assets/javascripts/search/sidebar/index.js
+++ b/app/assets/javascripts/search/sidebar/index.js
@@ -4,27 +4,23 @@ import GlobalSearchSidebar from './components/app.vue';
Vue.use(Translate);
-export const sidebarInitState = () => {
- const el = document.getElementById('js-search-sidebar');
- if (!el) return {};
-
- const { navigationJson, searchType } = el.dataset;
-
- const navigationJsonParsed = JSON.parse(navigationJson);
-
- return { navigationJsonParsed, searchType };
-};
-
export const initSidebar = (store) => {
const el = document.getElementById('js-search-sidebar');
+ const hederEl = document.getElementById('super-sidebar-context-header');
+ const headerText = hederEl.innerText;
if (!el) return false;
return new Vue({
el,
+ name: 'GlobalSearchSidebar',
store,
render(createElement) {
- return createElement(GlobalSearchSidebar);
+ return createElement(GlobalSearchSidebar, {
+ props: {
+ headerText,
+ },
+ });
},
});
};
diff --git a/app/assets/javascripts/search/store/state.js b/app/assets/javascripts/search/store/state.js
index a0e4d8c5596..3daa6b9d98c 100644
--- a/app/assets/javascripts/search/store/state.js
+++ b/app/assets/javascripts/search/store/state.js
@@ -1,7 +1,7 @@
import { cloneDeep } from 'lodash';
import { GROUPS_LOCAL_STORAGE_KEY, PROJECTS_LOCAL_STORAGE_KEY } from './constants';
-const createState = ({ query, navigation, defaultBranchName, searchType }) => ({
+const createState = ({ query, navigation, searchType, groupInitialJson, projectInitialJson }) => ({
urlQuery: cloneDeep(query),
query,
groups: [],
@@ -21,7 +21,8 @@ const createState = ({ query, navigation, defaultBranchName, searchType }) => ({
},
searchLabelString: '',
searchType,
- defaultBranchName,
+ groupInitialJson,
+ projectInitialJson,
});
export default createState;
diff --git a/app/assets/javascripts/search/topbar/components/app.vue b/app/assets/javascripts/search/topbar/components/app.vue
index c604189ee24..555892659fd 100644
--- a/app/assets/javascripts/search/topbar/components/app.vue
+++ b/app/assets/javascripts/search/topbar/components/app.vue
@@ -3,13 +3,10 @@ import { GlSearchBoxByType, GlButton } from '@gitlab/ui';
// eslint-disable-next-line no-restricted-imports
import { mapState, mapActions } from 'vuex';
import { s__ } from '~/locale';
-import { parseBoolean } from '~/lib/utils/common_utils';
import MarkdownDrawer from '~/vue_shared/components/markdown_drawer/markdown_drawer.vue';
import { ZOEKT_SEARCH_TYPE, ADVANCED_SEARCH_TYPE } from '~/search/store/constants';
import { SYNTAX_OPTIONS_ADVANCED_DOCUMENT, SYNTAX_OPTIONS_ZOEKT_DOCUMENT } from '../constants';
import SearchTypeIndicator from './search_type_indicator.vue';
-import GroupFilter from './group_filter.vue';
-import ProjectFilter from './project_filter.vue';
export default {
name: 'GlobalSearchTopbar',
@@ -23,22 +20,10 @@ export default {
components: {
GlButton,
GlSearchBoxByType,
- GroupFilter,
- ProjectFilter,
MarkdownDrawer,
SearchTypeIndicator,
},
props: {
- groupInitialJson: {
- type: Object,
- required: false,
- default: () => ({}),
- },
- projectInitialJson: {
- type: Object,
- required: false,
- default: () => ({}),
- },
defaultBranchName: {
type: String,
required: false,
@@ -55,9 +40,6 @@ export default {
this.setQuery({ key: 'search', value });
},
},
- showFilters() {
- return !parseBoolean(this.query.snippets);
- },
showSyntaxOptions() {
return (
(this.searchType === ZOEKT_SEARCH_TYPE || this.searchType === ADVANCED_SEARCH_TYPE) &&
@@ -103,31 +85,17 @@ export default {
</template>
<search-type-indicator />
</div>
- <div class="search-page-form gl-lg-display-flex gl-flex-direction-row gl-align-items-flex-end">
- <div class="gl-flex-grow-1 gl-lg-mb-0 gl-lg-mr-2">
- <gl-search-box-by-type
- id="dashboard_search"
- v-model="search"
- name="search"
- :placeholder="$options.i18n.searchPlaceholder"
- @submit="applyQuery"
- @keydown.enter.stop.prevent="applyQuery"
- />
- </div>
- <div v-if="showFilters" class="gl-mb-4 gl-lg-mb-0 gl-lg-mx-3 gl-min-w-20">
- <label id="groupfilterDropdown" class="gl-display-block gl-mb-1 gl-md-pb-2">{{
- $options.i18n.groupFieldLabel
- }}</label>
- <group-filter label-id="groupfilterDropdown" :group-initial-json="groupInitialJson" />
- </div>
- <div v-if="showFilters" class="gl-mb-4 gl-lg-mb-0 gl-lg-ml-3 gl-min-w-20">
- <label id="projectfilterDropdown" class="gl-display-block gl-mb-1 gl-md-pb-2">{{
- $options.i18n.projectFieldLabel
- }}</label>
- <project-filter
- label-id="projectfilterDropdown"
- :project-initial-json="projectInitialJson"
- />
+ <div class="search-page-form gl-lg-display-flex gl-flex-direction-column">
+ <div class="gl-lg-display-flex gl-flex-direction-row gl-align-items-flex-start">
+ <div class="gl-flex-grow-1 gl-pb-8 gl-lg-mb-0 gl-lg-mr-2">
+ <gl-search-box-by-type
+ id="dashboard_search"
+ v-model="search"
+ name="search"
+ :placeholder="$options.i18n.searchPlaceholder"
+ @keydown.enter.stop.prevent="applyQuery"
+ />
+ </div>
</div>
</div>
</section>
diff --git a/app/assets/javascripts/search/topbar/constants.js b/app/assets/javascripts/search/topbar/constants.js
index 279f315f89f..2bd0a4d2c66 100644
--- a/app/assets/javascripts/search/topbar/constants.js
+++ b/app/assets/javascripts/search/topbar/constants.js
@@ -1,25 +1,3 @@
-import { __ } from '~/locale';
-
-export const ANY_OPTION = Object.freeze({
- id: null,
- name: __('Any'),
- name_with_namespace: __('Any'),
-});
-
-export const GROUP_DATA = {
- headerText: __('Filter results by group'),
- queryParam: 'group_id',
- name: 'name',
- fullName: 'full_name',
-};
-
-export const PROJECT_DATA = {
- headerText: __('Filter results by project'),
- queryParam: 'project_id',
- name: 'name',
- fullName: 'name_with_namespace',
-};
-
export const SYNTAX_OPTIONS_ADVANCED_DOCUMENT = 'drawers/drawers/advanced_search_syntax.md';
export const SYNTAX_OPTIONS_ZOEKT_DOCUMENT = 'drawers/drawers/exact_code_search_syntax.md';
diff --git a/app/assets/javascripts/search/topbar/index.js b/app/assets/javascripts/search/topbar/index.js
index 95e15afd597..6aac91a40d3 100644
--- a/app/assets/javascripts/search/topbar/index.js
+++ b/app/assets/javascripts/search/topbar/index.js
@@ -11,19 +11,16 @@ export const initTopbar = (store) => {
return false;
}
- const { groupInitialJson, projectInitialJson } = el.dataset;
-
- const groupInitialJsonParsed = JSON.parse(groupInitialJson);
- const projectInitialJsonParsed = JSON.parse(projectInitialJson);
+ const { defaultBranchName } = el.dataset;
return new Vue({
el,
+ name: 'GlobalSearchTopbar',
store,
render(createElement) {
return createElement(GlobalSearchTopbar, {
props: {
- groupInitialJson: groupInitialJsonParsed,
- projectInitialJson: projectInitialJsonParsed,
+ defaultBranchName,
},
});
},
diff --git a/app/assets/javascripts/search/under_topbar/index.js b/app/assets/javascripts/search/under_topbar/index.js
index 8e50c6655dd..0be803d68fd 100644
--- a/app/assets/javascripts/search/under_topbar/index.js
+++ b/app/assets/javascripts/search/under_topbar/index.js
@@ -14,6 +14,7 @@ export const initBlobRefSwitcher = () => {
return new Vue({
el,
+ name: 'GlobalSearchUnderTopbar',
render(createElement) {
return createElement(RefSelector, {
props: {
diff --git a/app/assets/javascripts/super_sidebar/components/super_sidebar.vue b/app/assets/javascripts/super_sidebar/components/super_sidebar.vue
index 3beec4ccc14..f2970f05ebc 100644
--- a/app/assets/javascripts/super_sidebar/components/super_sidebar.vue
+++ b/app/assets/javascripts/super_sidebar/components/super_sidebar.vue
@@ -7,6 +7,7 @@ import { TAB_KEY_CODE } from '~/lib/utils/keycodes';
import { keysFor, TOGGLE_SUPER_SIDEBAR } from '~/behaviors/shortcuts/keybindings';
import { __, s__ } from '~/locale';
import Tracking from '~/tracking';
+import eventHub from '../event_hub';
import {
sidebarState,
SUPER_SIDEBAR_PEEK_STATE_CLOSED as STATE_CLOSED,
@@ -58,6 +59,7 @@ export default {
showPeekHint: false,
isMouseover: false,
breakpoint: null,
+ showSuperSidebarContextHeader: true,
};
},
computed: {
@@ -96,6 +98,7 @@ export default {
mounted() {
this.setupFocusTrapListener();
Mousetrap.bind(keysFor(TOGGLE_SUPER_SIDEBAR), this.toggleSidebar);
+ eventHub.$on('toggle-menu-header', this.onToggleMenuHeader);
},
beforeDestroy() {
document.removeEventListener('keydown', this.focusTrap);
@@ -166,6 +169,9 @@ export default {
event.preventDefault();
}
},
+ onToggleMenuHeader(forceState) {
+ this.showSuperSidebarContextHeader = forceState;
+ },
},
};
</script>
@@ -207,6 +213,7 @@ export default {
>
<scroll-scrim class="gl-flex-grow-1" data-testid="nav-container">
<div
+ v-if="showSuperSidebarContextHeader"
id="super-sidebar-context-header"
class="gl-px-5 gl-pt-3 gl-pb-2 gl-m-0 gl-reset-line-height gl-font-weight-bold gl-font-sm super-sidebar-context-header"
>
diff --git a/app/assets/stylesheets/framework/animations.scss b/app/assets/stylesheets/framework/animations.scss
index c93ef2287a8..3512f059911 100644
--- a/app/assets/stylesheets/framework/animations.scss
+++ b/app/assets/stylesheets/framework/animations.scss
@@ -92,8 +92,7 @@
@include transition(background-color, border-color, color, box-shadow);
}
-.dropdown-menu-toggle,
-.header-user-avatar {
+.dropdown-menu-toggle {
@include transition(border-color);
}
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index 0ae88f579e6..e791a0dbbbd 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -810,14 +810,6 @@
.navbar-gitlab {
li.dropdown {
position: static;
-
- &.user-counter {
- margin-left: 8px !important;
-
- > a {
- padding: 0 4px !important;
- }
- }
}
}
diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
index 9608e294d30..2265d425e1f 100644
--- a/app/assets/stylesheets/framework/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -98,12 +98,6 @@
.container-fluid {
padding: 0;
- .user-counter {
- svg {
- margin-right: 3px;
- }
- }
-
.navbar-nav {
@include media-breakpoint-down(xs) {
display: flex;
@@ -120,12 +114,6 @@
}
.nav > li {
- &.header-user {
- @include media-breakpoint-down(xs) {
- padding-left: 10px;
- }
- }
-
> a {
will-change: color;
margin: 4px 0;
@@ -137,38 +125,11 @@
padding: 0;
}
}
-
- &.header-user-dropdown-toggle {
- margin-left: 2px;
-
- .header-user-avatar {
- margin-right: 0;
- }
- }
}
.header-new-dropdown-toggle {
margin-right: 0;
}
-
- .impersonated-user,
- .impersonated-user:hover {
- margin-right: 1px;
- background-color: $white;
- border-top-right-radius: 0;
- border-bottom-right-radius: 0;
- }
-
- .impersonation-btn,
- .impersonation-btn:hover {
- background-color: $white;
- border-top-left-radius: 0;
- border-bottom-left-radius: 0;
-
- svg {
- color: $orange-500;
- }
- }
}
}
}
@@ -223,10 +184,6 @@
top: -1px;
font-size: 10px;
}
-
- .impersonation i {
- color: $red-500;
- }
}
.caret-down,
@@ -238,7 +195,6 @@
fill: currentColor;
}
-.header-user .dropdown-menu,
.header-new .dropdown-menu {
margin-top: $dropdown-vertical-offset;
}
@@ -304,44 +260,6 @@
}
}
}
-
- .header-user-dropdown-toggle {
- text-align: center;
- }
-
- .header-user-avatar {
- float: none;
- }
-}
-
-.header-user {
- &.show .dropdown-menu {
- margin-top: 4px;
- color: var(--gl-text-color, $gl-text-color);
- left: auto;
- max-height: $dropdown-max-height-lg;
-
- .user-status {
- max-width: 240px;
- }
-
- svg {
- vertical-align: text-top;
- }
-
- a.ci-minutes-emoji gl-emoji,
- a.trial-link gl-emoji {
- font-size: $gl-font-size;
- vertical-align: baseline;
- }
- }
-}
-
-.header-user-avatar {
- float: left;
- margin-right: 5px;
- border-radius: 50%;
- border: 1px solid $gray-normal;
}
.notification-dot {
diff --git a/app/controllers/explore/catalog_controller.rb b/app/controllers/explore/catalog_controller.rb
index 50846c21b1b..0c78c1fbdb8 100644
--- a/app/controllers/explore/catalog_controller.rb
+++ b/app/controllers/explore/catalog_controller.rb
@@ -3,7 +3,6 @@
module Explore
class CatalogController < Explore::ApplicationController
feature_category :pipeline_composition
- before_action :check_feature_flag
before_action :check_resource_access, only: :show
def show; end
@@ -14,10 +13,6 @@ module Explore
private
- def check_feature_flag
- render_404 unless Feature.enabled?(:global_ci_catalog, current_user)
- end
-
def check_resource_access
render_404 unless catalog_resource.present?
end
diff --git a/app/controllers/profiles/preferences_controller.rb b/app/controllers/profiles/preferences_controller.rb
index 7059e2a0371..4c93c738484 100644
--- a/app/controllers/profiles/preferences_controller.rb
+++ b/app/controllers/profiles/preferences_controller.rb
@@ -41,6 +41,7 @@ class Profiles::PreferencesController < Profiles::ApplicationController
:color_scheme_id,
:diffs_deletion_color,
:diffs_addition_color,
+ :home_organization_id,
:layout,
:dashboard,
:project_view,
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index 7371902a6bd..7851e2ac80b 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -52,6 +52,7 @@ class Projects::BlobController < Projects::ApplicationController
push_frontend_feature_flag(:blob_blame_info, @project)
push_frontend_feature_flag(:highlight_js_worker, @project)
push_frontend_feature_flag(:explain_code_chat, current_user)
+ push_frontend_feature_flag(:encoding_logs_tree)
push_licensed_feature(:file_locks) if @project.licensed_feature_available?(:file_locks)
end
diff --git a/app/controllers/projects/service_desk_controller.rb b/app/controllers/projects/service_desk_controller.rb
index 70cb439c4f3..a53e8859ee6 100644
--- a/app/controllers/projects/service_desk_controller.rb
+++ b/app/controllers/projects/service_desk_controller.rb
@@ -29,7 +29,13 @@ class Projects::ServiceDeskController < Projects::ApplicationController
end
def allowed_update_attributes
- %i[issue_template_key outgoing_name project_key add_external_participants_from_cc]
+ %i[
+ issue_template_key
+ outgoing_name
+ project_key
+ reopen_issue_on_external_participant_note
+ add_external_participants_from_cc
+ ]
end
def service_desk_attributes
@@ -42,6 +48,7 @@ class Projects::ServiceDeskController < Projects::ApplicationController
template_file_missing: service_desk_settings&.issue_template_missing?,
outgoing_name: service_desk_settings&.outgoing_name,
project_key: service_desk_settings&.project_key,
+ reopen_issue_on_external_participant_note: service_desk_settings&.reopen_issue_on_external_participant_note,
add_external_participants_from_cc: service_desk_settings&.add_external_participants_from_cc
}
end
diff --git a/app/controllers/projects/tree_controller.rb b/app/controllers/projects/tree_controller.rb
index cfcc27edf3e..1bbf272e8f9 100644
--- a/app/controllers/projects/tree_controller.rb
+++ b/app/controllers/projects/tree_controller.rb
@@ -22,6 +22,7 @@ class Projects::TreeController < Projects::ApplicationController
push_frontend_feature_flag(:blob_blame_info, @project)
push_frontend_feature_flag(:highlight_js_worker, @project)
push_frontend_feature_flag(:explain_code_chat, current_user)
+ push_frontend_feature_flag(:encoding_logs_tree)
push_licensed_feature(:file_locks) if @project.licensed_feature_available?(:file_locks)
end
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index b8b79192d3f..12decbbfeee 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -43,6 +43,7 @@ class ProjectsController < Projects::ApplicationController
push_frontend_feature_flag(:remove_monitor_metrics, @project)
push_frontend_feature_flag(:explain_code_chat, current_user)
push_frontend_feature_flag(:issue_email_participants, @project)
+ push_frontend_feature_flag(:encoding_logs_tree)
# TODO: We need to remove the FF eventually when we rollout page_specific_styles
push_frontend_feature_flag(:page_specific_styles, current_user)
push_licensed_feature(:file_locks) if @project.present? && @project.licensed_feature_available?(:file_locks)
diff --git a/app/graphql/resolvers/namespaces/work_item_state_counts_resolver.rb b/app/graphql/resolvers/namespaces/work_item_state_counts_resolver.rb
new file mode 100644
index 00000000000..099b509f77f
--- /dev/null
+++ b/app/graphql/resolvers/namespaces/work_item_state_counts_resolver.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module Resolvers
+ module Namespaces
+ class WorkItemStateCountsResolver < WorkItemsResolver
+ type Types::WorkItemStateCountsType, null: true
+
+ def ready?(**args)
+ # The search filter is not supported for work times at the namespace level.
+ # See https://gitlab.com/gitlab-org/gitlab/-/work_items/393126
+ if args[:search]
+ raise Gitlab::Graphql::Errors::ArgumentError,
+ 'Searching is not available for work items at the namespace level yet'
+ end
+
+ super
+ end
+
+ def resolve(**args)
+ return if resource_parent.nil?
+
+ Gitlab::IssuablesCountForState.new(
+ finder(args),
+ resource_parent,
+ store_in_redis_cache: true
+ )
+ end
+ end
+ end
+end
diff --git a/app/graphql/resolvers/work_item_state_counts_resolver.rb b/app/graphql/resolvers/work_item_state_counts_resolver.rb
new file mode 100644
index 00000000000..93551a57694
--- /dev/null
+++ b/app/graphql/resolvers/work_item_state_counts_resolver.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class WorkItemStateCountsResolver < WorkItemsResolver
+ type Types::WorkItemStateCountsType, null: true
+
+ def resolve(**args)
+ return if resource_parent.nil?
+
+ work_item_finder = finder(prepare_finder_params(args))
+ work_item_finder.parent_param = resource_parent
+
+ Gitlab::IssuablesCountForState.new(work_item_finder, resource_parent)
+ end
+ end
+end
diff --git a/app/graphql/types/group_type.rb b/app/graphql/types/group_type.rb
index a4eba3c63ae..7234948033b 100644
--- a/app/graphql/types/group_type.rb
+++ b/app/graphql/types/group_type.rb
@@ -275,6 +275,14 @@ module Types
description: 'Find a work item by IID directly associated with the group. Returns `null` if the ' \
'`namespace_level_work_items` feature flag is disabled.'
+ field :work_item_state_counts,
+ Types::WorkItemStateCountsType,
+ null: true,
+ alpha: { milestone: '16.7' },
+ description: 'Counts of work items by state for the namespace. Returns `null` if the ' \
+ '`namespace_level_work_items` feature flag is disabled.',
+ resolver: Resolvers::Namespaces::WorkItemStateCountsResolver
+
field :autocomplete_users,
null: true,
resolver: Resolvers::AutocompleteUsersResolver,
diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb
index befac90ef42..8e84605cb05 100644
--- a/app/graphql/types/project_type.rb
+++ b/app/graphql/types/project_type.rb
@@ -254,6 +254,13 @@ module Types
extras: [:lookahead],
resolver: Resolvers::WorkItemsResolver
+ field :work_item_state_counts,
+ Types::WorkItemStateCountsType,
+ null: true,
+ alpha: { milestone: '16.7' },
+ description: 'Counts of work items by state for the project.',
+ resolver: Resolvers::WorkItemStateCountsResolver
+
field :issue_status_counts,
Types::IssueStatusCountsType,
null: true,
diff --git a/app/graphql/types/work_item_state_counts_type.rb b/app/graphql/types/work_item_state_counts_type.rb
new file mode 100644
index 00000000000..a5fdf542464
--- /dev/null
+++ b/app/graphql/types/work_item_state_counts_type.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Types
+ # rubocop: disable Graphql/AuthorizeTypes -- Parent node applies authorization
+ class WorkItemStateCountsType < BaseObject
+ graphql_name 'WorkItemStateCountsType'
+ description 'Represents total number of work items for the represented states'
+
+ field :all,
+ GraphQL::Types::Int,
+ null: true,
+ description: 'Number of work items for the project or group.'
+
+ field :closed,
+ GraphQL::Types::Int,
+ null: true,
+ description: 'Number of work items with state CLOSED for the project or group.'
+
+ field :opened,
+ GraphQL::Types::Int,
+ null: true,
+ description: 'Number of work items with state OPENED for the project or group.'
+ end
+ # rubocop: enable Graphql/AuthorizeTypes
+end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 3c64a685ba3..49230e558a8 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -315,8 +315,8 @@ module ApplicationHelper
class_names << 'issue-boards-page gl-overflow-auto' if current_controller?(:boards)
class_names << 'epic-boards-page gl-overflow-auto' if current_controller?(:epic_boards)
class_names << 'with-performance-bar' if performance_bar_enabled?
- class_names << 'with-header' if !show_super_sidebar? || !current_user
- class_names << 'with-top-bar' if show_super_sidebar? && !@hide_top_bar_padding
+ class_names << 'with-header' unless current_user
+ class_names << 'with-top-bar' unless @hide_top_bar_padding
class_names << system_message_class
class_names
diff --git a/app/helpers/dashboard_helper.rb b/app/helpers/dashboard_helper.rb
index d19b0a9a43a..3756584e3b3 100644
--- a/app/helpers/dashboard_helper.rb
+++ b/app/helpers/dashboard_helper.rb
@@ -3,18 +3,6 @@
module DashboardHelper
include IconsHelper
- def assigned_issues_dashboard_path
- issues_dashboard_path(assignee_username: current_user.username)
- end
-
- def assigned_mrs_dashboard_path
- merge_requests_dashboard_path(assignee_username: current_user.username)
- end
-
- def reviewer_mrs_dashboard_path
- merge_requests_dashboard_path(reviewer_username: current_user.username)
- end
-
def has_start_trial?
false
end
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index 2cc83a936d8..e02b4fa0410 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -149,16 +149,6 @@ module IssuablesHelper
end
end
- def assigned_open_issues_count_text
- count = assigned_issuables_count(:issues)
-
- if count > User::MAX_LIMIT_FOR_ASSIGNEED_ISSUES_COUNT - 1
- "#{count - 1}+"
- else
- count.to_s
- end
- end
-
def issuable_reference(issuable)
@show_full_reference ? issuable.to_reference(full: true) : issuable.to_reference(@group || @project)
end
diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb
index 4b561914f2f..cb9a270253f 100644
--- a/app/helpers/nav_helper.rb
+++ b/app/helpers/nav_helper.rb
@@ -40,14 +40,6 @@ module NavHelper
end
end
- def user_dropdown_class
- class_names = []
- class_names << 'header-user-dropdown-toggle'
- class_names << 'impersonated-user' if session[:impersonator_id]
-
- class_names
- end
-
def page_has_markdown?
current_path?('projects/merge_requests#show') ||
current_path?('projects/merge_requests/conflicts#show') ||
diff --git a/app/helpers/organizations/organization_helper.rb b/app/helpers/organizations/organization_helper.rb
index 533d5409ab7..d0dd9dc5aea 100644
--- a/app/helpers/organizations/organization_helper.rb
+++ b/app/helpers/organizations/organization_helper.rb
@@ -51,8 +51,7 @@ module Organizations
def home_organization_setting_app_data
{
- # TODO: use real setting - https://gitlab.com/gitlab-org/gitlab/-/issues/428668
- initial_selection: 1
+ initial_selection: current_user.home_organization_id
}.to_json
end
diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb
index d053aeb7bfe..fc4d69dcdbc 100644
--- a/app/helpers/todos_helper.rb
+++ b/app/helpers/todos_helper.rb
@@ -5,10 +5,6 @@ module TodosHelper
@todos_pending_count ||= current_user.todos_pending_count
end
- def todos_count_format(count)
- count > 99 ? '99+' : count.to_s
- end
-
def todos_done_count
@todos_done_count ||= current_user.todos_done_count
end
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 4d73db8caac..d589c55af02 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -758,6 +758,11 @@ class Issue < ApplicationRecord
Gitlab::HookData::IssueBuilder.new(self).build
end
+ override :gfm_reference
+ def gfm_reference(from = nil)
+ "#{work_item_type_with_default.name.underscore} #{to_reference(from)}"
+ end
+
private
def project_level_readable_by?(user)
diff --git a/app/models/user.rb b/app/models/user.rb
index fd15ee035ea..d7880579092 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -400,6 +400,7 @@ class User < MainClusterwide::ApplicationRecord
:pinned_nav_items, :pinned_nav_items=,
:achievements_enabled, :achievements_enabled=,
:enabled_following, :enabled_following=,
+ :home_organization, :home_organization_id, :home_organization_id=,
to: :user_preference
delegate :path, to: :namespace, allow_nil: true, prefix: true
@@ -613,6 +614,10 @@ class User < MainClusterwide::ApplicationRecord
strip_attributes! :name
+ def user_belongs_to_organization?(organization)
+ organization_users.exists?(organization: organization)
+ end
+
def preferred_language
read_attribute('preferred_language').presence || Gitlab::CurrentSettings.default_preferred_language
end
diff --git a/app/models/user_preference.rb b/app/models/user_preference.rb
index aef221623e9..b8c4c8597a4 100644
--- a/app/models/user_preference.rb
+++ b/app/models/user_preference.rb
@@ -10,6 +10,7 @@ class UserPreference < MainClusterwide::ApplicationRecord
TIME_DISPLAY_FORMATS = { system: 0, non_iso_format: 1, iso_format: 2 }.freeze
belongs_to :user
+ belongs_to :home_organization, class_name: "Organizations::Organization", optional: true
scope :with_user, -> { joins(:user) }
scope :gitpod_enabled, -> { where(gitpod_enabled: true) }
@@ -30,6 +31,8 @@ class UserPreference < MainClusterwide::ApplicationRecord
validates :time_display_format, inclusion: { in: TIME_DISPLAY_FORMATS.values }, presence: true
+ validate :user_belongs_to_home_organization, if: :home_organization_changed?
+
# 2023-06-22 is after 16.1 release and during 16.2 release https://docs.gitlab.com/ee/development/database/avoiding_downtime_in_migrations.html#ignoring-the-column-release-m
ignore_columns :use_legacy_web_ide, remove_with: '16.2', remove_after: '2023-06-22'
@@ -52,6 +55,16 @@ class UserPreference < MainClusterwide::ApplicationRecord
end
end
+ def user_belongs_to_home_organization
+ # If we don't ignore the default organization id below then all users need to have their corresponding entry
+ # with default organization id as organization id in the `organization_users` table.
+ # Otherwise, the user won't be able to the default organization as the home organization.
+ return if home_organization_id == Organizations::Organization::DEFAULT_ORGANIZATION_ID
+ return if user.user_belongs_to_organization?(home_organization_id)
+
+ errors.add(:user, _("is not part of the given organization"))
+ end
+
def set_notes_filter(filter_id, issuable)
# No need to update the column if the value is already set.
if filter_id && NOTES_FILTERS.value?(filter_id)
diff --git a/app/services/groups/participants_service.rb b/app/services/groups/participants_service.rb
index a2238264295..7b68b435f14 100644
--- a/app/services/groups/participants_service.rb
+++ b/app/services/groups/participants_service.rb
@@ -12,8 +12,8 @@ module Groups
noteable_owner +
participants_in_noteable +
all_members +
- groups +
- group_hierarchy_users
+ group_hierarchy_users +
+ groups
render_participants_as_hash(participants.uniq)
end
diff --git a/app/services/merge_requests/create_ref_service.rb b/app/services/merge_requests/create_ref_service.rb
index eae6845335a..1e5e127072e 100644
--- a/app/services/merge_requests/create_ref_service.rb
+++ b/app/services/merge_requests/create_ref_service.rb
@@ -35,8 +35,6 @@ module MergeRequests
result = maybe_rebase!(**result)
result = maybe_merge!(**result)
- update_merge_request!(merge_request, result)
-
ServiceResponse.success(payload: result)
rescue CreateRefError => error
ServiceResponse.error(message: error.message)
@@ -118,10 +116,6 @@ module MergeRequests
).compact
end
- def update_merge_request!(merge_request, result)
- # overridden in EE
- end
-
def safe_gitaly_operation
yield
rescue Gitlab::Git::PreReceiveError, Gitlab::Git::CommandError, ArgumentError => error
diff --git a/app/services/namespaces/in_product_marketing_emails_service.rb b/app/services/namespaces/in_product_marketing_emails_service.rb
deleted file mode 100644
index 14e670126c6..00000000000
--- a/app/services/namespaces/in_product_marketing_emails_service.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-# frozen_string_literal: true
-
-module Namespaces
- class InProductMarketingEmailsService
- TRACKS = {
- create: {
- interval_days: [1, 5, 10],
- completed_actions: [:created],
- incomplete_actions: [:git_write]
- },
- team_short: {
- interval_days: [1],
- completed_actions: [:git_write],
- incomplete_actions: [:user_added]
- },
- trial_short: {
- interval_days: [2],
- completed_actions: [:git_write],
- incomplete_actions: [:trial_started]
- },
- admin_verify: {
- interval_days: [3],
- completed_actions: [:git_write],
- incomplete_actions: [:pipeline_created]
- },
- verify: {
- interval_days: [4, 8, 13],
- completed_actions: [:git_write],
- incomplete_actions: [:pipeline_created]
- },
- trial: {
- interval_days: [1, 5, 10],
- completed_actions: [:git_write, :pipeline_created],
- incomplete_actions: [:trial_started]
- },
- team: {
- interval_days: [1, 5, 10],
- completed_actions: [:git_write, :pipeline_created, :trial_started],
- incomplete_actions: [:user_added]
- }
- }.freeze
-
- def self.email_count_for_track(track)
- interval_days = TRACKS.dig(track.to_sym, :interval_days)
- interval_days&.count || 0
- end
- end
-end
-
-Namespaces::InProductMarketingEmailsService.prepend_mod
diff --git a/app/services/users/in_product_marketing_email_records.rb b/app/services/users/in_product_marketing_email_records.rb
deleted file mode 100644
index fcb252536b3..00000000000
--- a/app/services/users/in_product_marketing_email_records.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-module Users
- class InProductMarketingEmailRecords
- attr_reader :records
-
- def initialize
- @records = []
- end
-
- def save!
- Users::InProductMarketingEmail.bulk_insert!(@records)
- @records = []
- end
-
- def add(user, track: nil, series: nil)
- @records << Users::InProductMarketingEmail.new(
- user: user,
- track: track,
- series: series,
- created_at: Time.zone.now,
- updated_at: Time.zone.now
- )
- end
- end
-end
diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml
index 2c97df90110..5f038ac467d 100644
--- a/app/views/layouts/_head.html.haml
+++ b/app/views/layouts/_head.html.haml
@@ -62,7 +62,7 @@
= yield :page_specific_javascripts
- = webpack_bundle_tag 'super_sidebar' if show_super_sidebar?
+ = webpack_bundle_tag 'super_sidebar'
= webpack_controller_bundle_tags
diff --git a/app/views/layouts/header/_current_user_dropdown.html.haml b/app/views/layouts/header/_current_user_dropdown.html.haml
deleted file mode 100644
index 75de13d4862..00000000000
--- a/app/views/layouts/header/_current_user_dropdown.html.haml
+++ /dev/null
@@ -1,51 +0,0 @@
-- return unless current_user
-
-%ul
- %li.current-user
- - if current_user_menu?(:profile)
- = link_to current_user, class: 'gl-line-height-20!', data: { user: current_user.username, testid: 'user-profile-link', track_action: "click_link", track_label: "user_profile", track_property: "navigation_top" } do
- = render 'layouts/header/current_user_dropdown_item'
- - else
- .gl-py-3.gl-px-4
- = render 'layouts/header/current_user_dropdown_item'
- %li.divider
- - if can?(current_user, :update_user_status, current_user)
- %li
- = render Pajamas::ButtonComponent.new(button_options: { class: 'menu-item js-set-status-modal-trigger' }) do
- - if current_user.status&.busy? || current_user.status&.customized?
- = s_('SetStatusModal|Edit status')
- - else
- = s_('SetStatusModal|Set status')
- = dispensable_render_if_exists 'layouts/header/start_trial'
- - if current_user_menu?(:settings)
- %li
- = link_to s_("CurrentUser|Edit profile"), profile_path, data: { testid: 'edit_profile_link', track_action: "click_link", track_label: "user_edit_profile", track_property: "navigation_top" }
- %li
- = link_to s_("CurrentUser|Preferences"), profile_preferences_path, data: { track_action: "click_link", track_label: "user_preferences", track_property: "navigation_top" }
- = render_if_exists 'layouts/header/buy_pipeline_minutes', project: @project, namespace: @group
-
- - if current_user_menu?(:help)
- %li.divider.d-md-none
- %li.d-md-none
- = link_to _("Help"), help_path, data: {track_action: 'click_link', track_label: 'help', track_property: 'navigation_top'}
- %li.d-md-none
- = link_to _("Support"), support_url, data: {track_action: 'click_link', track_label: 'support', track_property: 'navigation_top'}
- %li.d-md-none
- = render 'shared/help_dropdown_forum_link'
- %li.d-md-none
- = link_to _("Submit feedback"), Gitlab::Utils.append_path(promo_url, "submit-feedback"), data: {track_action: 'click_link', track_label: 'submit_feedback', track_property: 'navigation_top'}
- - if current_user_menu?(:help) || current_user_menu?(:settings) || current_user_menu?(:profile)
- %li.d-md-none
- = render 'shared/user_dropdown_contributing_link'
- = render 'shared/user_dropdown_instance_review'
- - if Gitlab.com_but_not_canary?
- %li.d-md-none
- = link_to _("Switch to GitLab Next"), Gitlab::Saas.canary_toggle_com_url, data: { track_action: "click_link", track_label: "switch_to_canary", track_property: "navigation_top" }
-
- %li.divider
- .js-new-nav-toggle{ data: { enabled: show_super_sidebar?.to_s, endpoint: profile_preferences_path} }
-
- - if current_user_menu?(:sign_out)
- %li.divider
- %li
- = link_to _("Sign out"), destroy_user_session_path, method: :post, class: "sign-out-link", data: { testid: 'sign_out_link', track_action: "click_link", track_label: "user_sign_out", track_property: "navigation_top" }
diff --git a/app/views/layouts/header/_current_user_dropdown_item.html.haml b/app/views/layouts/header/_current_user_dropdown_item.html.haml
deleted file mode 100644
index fa0a6364a15..00000000000
--- a/app/views/layouts/header/_current_user_dropdown_item.html.haml
+++ /dev/null
@@ -1,12 +0,0 @@
-.gl-font-weight-bold
- = current_user.name
- - if current_user.status&.busy?
- = render Pajamas::BadgeComponent.new(s_('UserProfile|Busy'), size: 'sm', variant: 'warning')
-= current_user.to_reference
-- if current_user.status
- .user-status.d-flex.align-items-center.gl-mt-2.gl-mr-0.gl-font-sm.has-tooltip{ title: current_user.status.message_html, data: { html: 'true', placement: 'bottom' } }
- - if current_user.status.customized?
- .user-status-emoji.d-flex.align-items-center
- = emoji_icon current_user.status.emoji
- %span.user-status-message.str-truncated
- = current_user.status.message_html.html_safe
diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
index dbfd8a99fbb..7f7758d4081 100644
--- a/app/views/layouts/header/_default.html.haml
+++ b/app/views/layouts/header/_default.html.haml
@@ -1,6 +1,3 @@
-- has_impersonation_link = header_link?(:admin_impersonation)
-- user_status_data = user_status_properties(current_user)
-
%header.navbar.navbar-gitlab.navbar-expand-sm.js-navbar.legacy-top-bar{ data: { testid: 'navbar' } }
%a.gl-sr-only.gl-accessibility{ href: "#content-body" } Skip to content
.container-fluid
@@ -12,64 +9,6 @@
%ul.nav.navbar-nav.gl-w-full.gl-align-items-center.gl-justify-content-end
- if current_user
= render 'layouts/header/new_dropdown', class: 'gl-display-none gl-sm-display-block gl-white-space-nowrap gl-text-right'
- - if header_link?(:issues)
- = nav_link(path: 'dashboard#issues', html_options: { class: "user-counter" }) do
- = link_to assigned_issues_dashboard_path, title: _('Issues'), class: 'dashboard-shortcuts-issues js-prefetch-document', aria: { label: _('Issues') },
- data: { testid: 'issues_shortcut_button', toggle: 'tooltip', placement: 'bottom',
- track_label: 'main_navigation',
- track_action: 'click_issues_link',
- track_property: 'navigation_top',
- container: 'body' } do
- = sprite_icon('issues')
- - issues_count = assigned_issuables_count(:issues)
- = gl_badge_tag({ size: :sm, variant: :success }, { class: "gl-ml-n2 #{'gl-display-none' if issues_count == 0}", "aria-label": n_("%d assigned issue", "%d assigned issues", issues_count) % issues_count }) do
- = assigned_open_issues_count_text
- - if header_link?(:merge_requests)
- = nav_link(path: 'dashboard#merge_requests', html_options: { class: "user-counter dropdown" }) do
- - top_level_link = assigned_mrs_dashboard_path
- = link_to top_level_link, class: 'dashboard-shortcuts-merge_requests has-tooltip', title: _('Merge requests'), aria: { label: _('Merge requests') },
- data: { testid: 'merge_requests_shortcut_button',
- toggle: "dropdown",
- placement: 'bottom',
- track_label: 'merge_requests_menu',
- track_action: 'click_dropdown',
- track_property: 'navigation_top',
- container: 'body' } do
- = sprite_icon('git-merge')
- = gl_badge_tag({ size: :sm, variant: :warning }, { class: "js-merge-requests-count gl-ml-n2 #{'gl-display-none' if user_merge_requests_counts[:total] == 0}", "aria-label": n_("%d merge request", "%d merge requests", user_merge_requests_counts[:total]) % user_merge_requests_counts[:total] }) do
- = number_with_delimiter(user_merge_requests_counts[:total])
- = sprite_icon('chevron-down', css_class: 'caret-down gl-mx-0!')
- .dropdown-menu.dropdown-menu-right
- %ul
- %li.dropdown-header
- = _('Merge requests')
- %li
- = link_to assigned_mrs_dashboard_path,
- class: 'gl-display-flex! gl-align-items-center js-prefetch-document',
- data: {track_action: 'click_link', track_label: 'merge_requests_assigned', track_property: 'navigation_top'} do
- = _('Assigned')
- = gl_badge_tag({ variant: :neutral, size: :sm }, { class: "js-assigned-mr-count gl-ml-auto" }) do
- = user_merge_requests_counts[:assigned]
- %li
- = link_to reviewer_mrs_dashboard_path,
- class: 'dashboard-shortcuts-review_requests gl-display-flex! gl-align-items-center js-prefetch-document',
- data: {track_action: 'click_link', track_label: 'merge_requests_to_review', track_property: 'navigation_top'} do
- = _('Review requests')
- = gl_badge_tag({ variant: :neutral, size: :sm }, { class: "js-reviewer-mr-count gl-ml-auto" }) do
- = user_merge_requests_counts[:review_requested]
- - if header_link?(:todos)
- = nav_link(controller: 'dashboard/todos', html_options: { class: "user-counter" }) do
- = link_to dashboard_todos_path, title: _('To-Do List'), aria: { label: _('To-Do List') }, class: 'shortcuts-todos js-prefetch-document',
- data: { testid: 'todos-shortcut-button', toggle: 'tooltip', placement: 'bottom',
- track_label: 'main_navigation',
- track_action: 'click_to_do_link',
- track_property: 'navigation_top',
- container: 'body' } do
- = sprite_icon('todo-done')
- -# The todos' counter badge's visibility is being toggled by adding or removing the .hidden class in Js.
- -# We'll eventually migrate to .gl-display-none: https://gitlab.com/gitlab-org/gitlab/-/issues/351792.
- = gl_badge_tag({ size: :sm, variant: :info }, { class: "js-todos-count gl-ml-n2 #{'hidden' if todos_pending_count == 0}", "aria-label": _("Todos count") }) do
- = todos_count_format(todos_pending_count)
%li.nav-item.header-help.dropdown.d-none.d-md-block
= link_to help_path, class: 'header-help-dropdown-toggle gl-relative', data: { toggle: "dropdown", track_action: 'click_question_mark_link', track_label: 'main_navigation', track_property: 'navigation_top' } do
%span.gl-sr-only
@@ -79,27 +18,6 @@
= sprite_icon('chevron-down', css_class: 'caret-down')
.dropdown-menu.dropdown-menu-right
= render 'layouts/header/help_dropdown'
- - if header_link?(:user_dropdown)
- %li.nav-item.header-user.js-nav-user-dropdown.dropdown{ data: { testid: 'user-dropdown' }, class: ('mr-0' if has_impersonation_link) }
- = link_to current_user, class: user_dropdown_class, data: { toggle: "dropdown", track_label: "profile_dropdown", track_action: "click_dropdown", track_property: "navigation_top" } do
- = render Pajamas::AvatarComponent.new(current_user, size: 24, class: 'header-user-avatar', avatar_options: { data: { testid: 'user-avatar-content' } })
- = render_if_exists 'layouts/header/user_notification_dot', project: project, namespace: group
- = sprite_icon('chevron-down', css_class: 'caret-down')
- .dropdown-menu.dropdown-menu-right
- = render 'layouts/header/current_user_dropdown'
- - if has_impersonation_link
- %li.nav-item.impersonation.ml-0
- = render Pajamas::ButtonComponent.new(href: admin_impersonation_path, icon: 'incognito', button_options: { title: _('Stop impersonation'), class: 'impersonation-btn', aria: { label: _('Stop impersonation') }, data: { method: :delete, toggle: 'tooltip', placement: 'bottom', container: 'body', testid: 'stop_impersonation_btn' } })
- - if header_link?(:sign_in)
- - if allow_signup?
- %li.nav-item
- = render Pajamas::ButtonComponent.new(href: new_user_registration_path) do
- = _('Register')
- %li.nav-item{ class: 'gl-flex-grow-0! gl-flex-basis-half!' }
- = link_to _('Sign in'), new_session_path(:user, redirect_to_referer: 'yes')
- if display_whats_new?
#whats-new-app{ data: { version_digest: whats_new_version_digest } }
-
-- if can?(current_user, :update_user_status, current_user)
- .js-set-status-modal-wrapper{ data: user_status_data }
diff --git a/app/views/layouts/help.html.haml b/app/views/layouts/help.html.haml
index 68426f71879..89467efcc6e 100644
--- a/app/views/layouts/help.html.haml
+++ b/app/views/layouts/help.html.haml
@@ -1,7 +1,6 @@
- @breadcrumb_title = _("Help")
- page_title _("Help")
- header_title _("Help"), help_path
-- if show_super_sidebar?
- - @force_desktop_expanded_sidebar = true
+- @force_desktop_expanded_sidebar = true
= render template: "layouts/application"
diff --git a/app/views/layouts/search.html.haml b/app/views/layouts/search.html.haml
index 885fda10744..06192469833 100644
--- a/app/views/layouts/search.html.haml
+++ b/app/views/layouts/search.html.haml
@@ -1,7 +1,6 @@
- page_title _("Search")
- header_title _("Search"), search_path
- add_page_specific_style 'page_bundles/search'
-- if show_super_sidebar?
- - @force_desktop_expanded_sidebar = true
+- @force_desktop_expanded_sidebar = true
= render template: "layouts/application"
diff --git a/app/views/projects/_service_desk_settings.html.haml b/app/views/projects/_service_desk_settings.html.haml
index 115788e7764..d6b28e94645 100644
--- a/app/views/projects/_service_desk_settings.html.haml
+++ b/app/views/projects/_service_desk_settings.html.haml
@@ -18,6 +18,7 @@
selected_file_template_project_id: "#{@project.service_desk_setting&.file_template_project_id}",
outgoing_name: "#{@project.service_desk_setting&.outgoing_name}",
project_key: "#{@project.service_desk_setting&.project_key}",
+ reopen_issue_on_external_participant_note: "#{@project.service_desk_setting&.reopen_issue_on_external_participant_note}",
add_external_participants_from_cc: "#{@project.service_desk_setting&.add_external_participants_from_cc}",
templates: available_service_desk_templates_for(@project),
public_project: "#{@project.public?}",
diff --git a/app/views/search/_results_list.html.haml b/app/views/search/_results_list.html.haml
index fb96672cf99..dad352e376b 100644
--- a/app/views/search/_results_list.html.haml
+++ b/app/views/search/_results_list.html.haml
@@ -8,9 +8,7 @@
- elsif @search_objects.blank?
= render partial: "search/results/empty"
- else
- - statusBarClass = !show_super_sidebar? ? 'gl-lg-pl-5' : ''
-
- .section{ class: statusBarClass }
+ .section
- if @scope == 'commits'
%ul.content-list.commit-list
= render partial: "search/results/commit", collection: @search_objects
diff --git a/app/views/search/_results_status.html.haml b/app/views/search/_results_status.html.haml
index 8417b66eb34..3c42126e480 100644
--- a/app/views/search/_results_status.html.haml
+++ b/app/views/search/_results_status.html.haml
@@ -1,7 +1,4 @@
-- statusBarClass = !show_super_sidebar? ? 'gl-lg-pl-5' : ''
-- statusBarClass = statusBarClass + ' gl-lg-display-none' if @search_objects.to_a.empty?
-
-.section{ class: statusBarClass }
+.section{ class: ('gl-lg-display-none' if @search_objects.to_a.empty?) }
.search-results-status
.gl-display-flex.gl-flex-direction-column
.gl-p-5.gl-display-flex.gl-flex-wrap
diff --git a/app/views/search/show.html.haml b/app/views/search/show.html.haml
index 4ddeca64c7d..af3177e4422 100644
--- a/app/views/search/show.html.haml
+++ b/app/views/search/show.html.haml
@@ -16,8 +16,8 @@
- page_description(_("%{count} %{scope} for term '%{term}'") % { count: @search_results.formatted_count(@scope), scope: @scope, term: @search_term })
- page_card_attributes("Namespace" => @group&.full_path, "Project" => @project&.full_path)
-#js-search-topbar{ data: { "group-initial-json": group_attributes.to_json, "project-initial-json": project_attributes.to_json, "default-branch-name": @project&.default_branch } }
+#js-search-topbar{ data: { "default-branch-name": @project&.default_branch } }
.results.gl-lg-display-flex.gl-mt-0
- #js-search-sidebar{ data: { navigation_json: search_navigation_json, search_type: search_service.search_type } }
+ #js-search-sidebar{ data: { navigation_json: search_navigation_json, search_type: search_service.search_type, group_initial_json: group_attributes.to_json, project_initial_json: project_attributes.to_json, } }
- if @search_term
= render 'search/results'
diff --git a/app/views/shared/_ci_catalog_badge.html.haml b/app/views/shared/_ci_catalog_badge.html.haml
index 18e0cb37d7d..7f8f4f6143b 100644
--- a/app/views/shared/_ci_catalog_badge.html.haml
+++ b/app/views/shared/_ci_catalog_badge.html.haml
@@ -1,2 +1 @@
-- current_href = Feature.enabled?(:global_ci_catalog, @user) ? href : nil
-= render Pajamas::BadgeComponent.new(s_('CiCatalog|CI/CD catalog resource'), variant: 'info', icon: 'catalog-checkmark', class: css_class, href: current_href)
+= render Pajamas::BadgeComponent.new(s_('CiCatalog|CI/CD catalog resource'), variant: 'info', icon: 'catalog-checkmark', class: css_class, href: href)
diff --git a/app/views/shared/runners/_runner_description.html.haml b/app/views/shared/runners/_runner_description.html.haml
index dc689303f77..6f918ae8103 100644
--- a/app/views/shared/runners/_runner_description.html.haml
+++ b/app/views/shared/runners/_runner_description.html.haml
@@ -19,4 +19,4 @@
%p
= s_("Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run.")
- = link_to _("Learn more."), help_page_path("ci/runners/configure_runners", anchor: "use-tags-to-control-which-jobs-a-runner-can-run"), target: '_blank'
+ = link_to _("Learn more."), help_page_path("ci/runners/configure_runners", anchor: "how-the-runner-uses-tags"), target: '_blank'