summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-03-31 18:08:39 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2022-03-31 18:08:39 +0000
commite7fb61499317b3c044845817b991e13aea276955 (patch)
tree127aef09952fa595b8e5b886db5dd89d974d91da /app
parent85ea3dd4f4855e99d9a69c8e609095199597195a (diff)
downloadgitlab-ce-e7fb61499317b3c044845817b991e13aea276955.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/boards/components/board_card_inner.vue2
-rw-r--r--app/assets/javascripts/boards/components/board_form.vue2
-rw-r--r--app/assets/javascripts/boards/components/board_list.vue2
-rw-r--r--app/assets/javascripts/boards/components/board_list_header.vue4
-rw-r--r--app/assets/javascripts/boards/components/boards_selector.vue13
-rw-r--r--app/assets/javascripts/boards/components/issue_time_estimate.vue2
-rw-r--r--app/assets/javascripts/boards/components/item_count.vue2
-rw-r--r--app/assets/javascripts/boards/components/toggle_focus.vue1
-rw-r--r--app/assets/javascripts/boards/config_toggle.js25
-rw-r--r--app/assets/javascripts/boards/index.js3
-rw-r--r--app/assets/javascripts/boards/mount_filtered_search_issue_boards.js42
-rw-r--r--app/assets/javascripts/boards/mount_multiple_boards_switcher.js50
-rw-r--r--app/assets/javascripts/boards/new_board.js29
-rw-r--r--app/assets/javascripts/boards/toggle_epics_swimlanes.js1
-rw-r--r--app/assets/javascripts/boards/toggle_focus.js18
-rw-r--r--app/assets/javascripts/boards/toggle_labels.js1
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/registry_header.vue17
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/expiration_policies.js3
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/index.js4
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/list.vue10
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/project/components/registry_settings_app.vue12
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/project/registry_settings_bundle.js2
-rw-r--r--app/assets/javascripts/packages_and_registries/shared/components/cleanup_policy_enabled_alert.vue54
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/shared/init_form.js12
-rw-r--r--app/assets/stylesheets/page_bundles/boards.scss2
-rw-r--r--app/controllers/groups/boards_controller.rb2
-rw-r--r--app/controllers/import/base_controller.rb2
-rw-r--r--app/controllers/projects/boards_controller.rb2
-rw-r--r--app/controllers/projects/pipeline_schedules_controller.rb4
-rw-r--r--app/helpers/boards_helper.rb14
-rw-r--r--app/helpers/packages_helper.rb2
-rw-r--r--app/models/ci/namespace_mirror.rb2
-rw-r--r--app/models/container_repository.rb2
-rw-r--r--app/models/project_import_state.rb19
-rw-r--r--app/models/user.rb46
-rw-r--r--app/services/incident_management/issuable_escalation_statuses/build_service.rb34
-rw-r--r--app/services/incident_management/issuable_escalation_statuses/create_service.rb19
-rw-r--r--app/services/incident_management/issuable_escalation_statuses/prepare_update_service.rb6
-rw-r--r--app/views/projects/pipeline_schedules/_form.html.haml2
-rw-r--r--app/views/projects/registry/repositories/index.html.haml2
-rw-r--r--app/views/projects/settings/packages_and_registries/show.html.haml2
-rw-r--r--app/views/shared/boards/_switcher.html.haml12
-rw-r--r--app/views/shared/issuable/_search_bar.html.haml357
43 files changed, 305 insertions, 537 deletions
diff --git a/app/assets/javascripts/boards/components/board_card_inner.vue b/app/assets/javascripts/boards/components/board_card_inner.vue
index aee61a5b2a5..02b99e86fd3 100644
--- a/app/assets/javascripts/boards/components/board_card_inner.vue
+++ b/app/assets/javascripts/boards/components/board_card_inner.vue
@@ -240,7 +240,7 @@ export default {
class="board-card-footer gl-display-flex gl-justify-content-space-between gl-align-items-flex-end"
>
<div
- class="gl-display-flex align-items-start flex-wrap-reverse board-card-number-container gl-overflow-hidden js-board-card-number-container"
+ class="gl-display-flex align-items-start flex-wrap-reverse board-card-number-container gl-overflow-hidden"
>
<gl-loading-icon v-if="item.isLoading" size="md" class="mt-3" />
<span
diff --git a/app/assets/javascripts/boards/components/board_form.vue b/app/assets/javascripts/boards/components/board_form.vue
index aba1f42ead5..a874c9e070a 100644
--- a/app/assets/javascripts/boards/components/board_form.vue
+++ b/app/assets/javascripts/boards/components/board_form.vue
@@ -289,7 +289,7 @@ export default {
<p v-if="isDeleteForm" data-testid="delete-confirmation-message">
{{ $options.i18n.deleteConfirmationMessage }}
</p>
- <form v-else class="js-board-config-modal" data-testid="board-form-wrapper" @submit.prevent>
+ <form v-else data-testid="board-form-wrapper" @submit.prevent>
<div v-if="!readonly" class="gl-mb-5" data-testid="board-form">
<label class="gl-font-weight-bold gl-font-lg" for="board-new-name">
{{ $options.i18n.titleFieldLabel }}
diff --git a/app/assets/javascripts/boards/components/board_list.vue b/app/assets/javascripts/boards/components/board_list.vue
index 1024be61359..858cd368b12 100644
--- a/app/assets/javascripts/boards/components/board_list.vue
+++ b/app/assets/javascripts/boards/components/board_list.vue
@@ -287,7 +287,7 @@ export default {
:data-board-type="list.listType"
:class="{ 'bg-danger-100': boardItemsSizeExceedsMax }"
draggable=".board-card"
- class="board-list gl-w-full gl-h-full gl-list-style-none gl-mb-0 gl-p-2 js-board-list"
+ class="board-list gl-w-full gl-h-full gl-list-style-none gl-mb-0 gl-p-2"
data-testid="tree-root-wrapper"
@start="handleDragOnStart"
@end="handleDragOnEnd"
diff --git a/app/assets/javascripts/boards/components/board_list_header.vue b/app/assets/javascripts/boards/components/board_list_header.vue
index 46b28d20da9..f02feab264c 100644
--- a/app/assets/javascripts/boards/components/board_list_header.vue
+++ b/app/assets/javascripts/boards/components/board_list_header.vue
@@ -262,7 +262,7 @@ export default {
'gl-py-2': list.collapsed && isSwimlanesHeader,
'gl-flex-direction-column': list.collapsed,
}"
- class="board-title gl-m-0 gl-display-flex gl-align-items-center gl-font-base gl-px-3 js-board-handle"
+ class="board-title gl-m-0 gl-display-flex gl-align-items-center gl-font-base gl-px-3"
>
<gl-button
v-gl-tooltip.hover
@@ -443,7 +443,7 @@ export default {
ref="settingsBtn"
v-gl-tooltip.hover
:aria-label="$options.i18n.listSettings"
- class="no-drag js-board-settings-button"
+ class="no-drag"
:title="$options.i18n.listSettings"
icon="settings"
@click="openSidebarSettings"
diff --git a/app/assets/javascripts/boards/components/boards_selector.vue b/app/assets/javascripts/boards/components/boards_selector.vue
index 8333856e996..2951eda1112 100644
--- a/app/assets/javascripts/boards/components/boards_selector.vue
+++ b/app/assets/javascripts/boards/components/boards_selector.vue
@@ -239,11 +239,12 @@ export default {
</script>
<template>
- <div class="boards-switcher js-boards-selector gl-mr-3">
- <span class="boards-selector-wrapper js-boards-selector-wrapper">
+ <div class="boards-switcher gl-mr-3" data-testid="boards-selector">
+ <span class="boards-selector-wrapper">
<gl-dropdown
+ data-testid="boards-dropdown"
data-qa-selector="boards_dropdown"
- toggle-class="dropdown-menu-toggle js-dropdown-toggle"
+ toggle-class="dropdown-menu-toggle"
menu-class="flex-column dropdown-extended-height"
:loading="isBoardLoading"
:text="board.name"
@@ -276,8 +277,8 @@ export default {
<gl-dropdown-item
v-for="recentBoard in recentBoards"
:key="`recent-${recentBoard.id}`"
- class="js-dropdown-item"
:href="`${boardBaseUrl}/${recentBoard.id}`"
+ data-testid="dropdown-item"
>
{{ recentBoard.name }}
</gl-dropdown-item>
@@ -292,8 +293,8 @@ export default {
<gl-dropdown-item
v-for="otherBoard in filteredBoards"
:key="otherBoard.id"
- class="js-dropdown-item"
:href="`${boardBaseUrl}/${otherBoard.id}`"
+ data-testid="dropdown-item"
>
{{ otherBoard.name }}
</gl-dropdown-item>
@@ -331,7 +332,7 @@ export default {
<gl-dropdown-item
v-if="showDelete"
v-gl-modal-directive="'board-config-modal'"
- class="text-danger js-delete-board"
+ class="text-danger"
@click.prevent="showPage('delete')"
>
{{ s__('IssueBoards|Delete board') }}
diff --git a/app/assets/javascripts/boards/components/issue_time_estimate.vue b/app/assets/javascripts/boards/components/issue_time_estimate.vue
index 1ab7deebfaf..9312db06efe 100644
--- a/app/assets/javascripts/boards/components/issue_time_estimate.vue
+++ b/app/assets/javascripts/boards/components/issue_time_estimate.vue
@@ -43,7 +43,7 @@ export default {
<gl-tooltip
:target="() => $refs.issueTimeEstimate"
placement="bottom"
- class="js-issue-time-estimate"
+ data-testid="issue-time-estimate"
>
<span class="gl-font-weight-bold gl-display-block">{{ $options.i18n.timeEstimate }}</span>
{{ title }}
diff --git a/app/assets/javascripts/boards/components/item_count.vue b/app/assets/javascripts/boards/components/item_count.vue
index 9b1ff254766..a11c23e5625 100644
--- a/app/assets/javascripts/boards/components/item_count.vue
+++ b/app/assets/javascripts/boards/components/item_count.vue
@@ -29,7 +29,7 @@ export default {
<span :class="{ 'text-danger': issuesExceedMax }" data-testid="board-items-count">
{{ itemsSize }}
</span>
- <span v-if="isMaxLimitSet" class="js-max-issue-size">
+ <span v-if="isMaxLimitSet" class="max-issue-size">
{{ maxIssueCount }}
</span>
</div>
diff --git a/app/assets/javascripts/boards/components/toggle_focus.vue b/app/assets/javascripts/boards/components/toggle_focus.vue
index 0169c9c72ed..71612e0742f 100644
--- a/app/assets/javascripts/boards/components/toggle_focus.vue
+++ b/app/assets/javascripts/boards/components/toggle_focus.vue
@@ -38,7 +38,6 @@ export default {
v-gl-tooltip
category="tertiary"
:icon="isFullscreen ? 'minimize' : 'maximize'"
- class="js-focus-mode-btn"
data-qa-selector="focus_mode_button"
:title="$options.i18n.toggleFocusMode"
:aria-label="$options.i18n.toggleFocusMode"
diff --git a/app/assets/javascripts/boards/config_toggle.js b/app/assets/javascripts/boards/config_toggle.js
deleted file mode 100644
index 1e54c2511b8..00000000000
--- a/app/assets/javascripts/boards/config_toggle.js
+++ /dev/null
@@ -1,25 +0,0 @@
-import Vue from 'vue';
-import { parseBoolean } from '~/lib/utils/common_utils';
-import ConfigToggle from './components/config_toggle.vue';
-
-export default () => {
- const el = document.querySelector('.js-board-config');
-
- if (!el) {
- return;
- }
-
- // eslint-disable-next-line no-new
- new Vue({
- el,
- name: 'ConfigToggleRoot',
- render(h) {
- return h(ConfigToggle, {
- props: {
- canAdminList: parseBoolean(el.dataset.canAdminList),
- hasScope: parseBoolean(el.dataset.hasScope),
- },
- });
- },
- });
-};
diff --git a/app/assets/javascripts/boards/index.js b/app/assets/javascripts/boards/index.js
index 2abc283c5b4..77c5994b5a1 100644
--- a/app/assets/javascripts/boards/index.js
+++ b/app/assets/javascripts/boards/index.js
@@ -13,7 +13,6 @@ import {
} from '~/lib/utils/common_utils';
import { queryToObject } from '~/lib/utils/url_utility';
import { fullBoardId } from './boards_util';
-import initNewBoard from './new_board';
import { gqlClient } from './graphql';
Vue.use(VueApollo);
@@ -112,6 +111,4 @@ export default () => {
});
mountBoardApp($boardApp);
-
- initNewBoard();
};
diff --git a/app/assets/javascripts/boards/mount_filtered_search_issue_boards.js b/app/assets/javascripts/boards/mount_filtered_search_issue_boards.js
deleted file mode 100644
index bb659eb075a..00000000000
--- a/app/assets/javascripts/boards/mount_filtered_search_issue_boards.js
+++ /dev/null
@@ -1,42 +0,0 @@
-import Vue from 'vue';
-import IssueBoardFilteredSearch from 'ee_else_ce/boards/components/issue_board_filtered_search.vue';
-import store from '~/boards/stores';
-import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
-import { queryToObject } from '~/lib/utils/url_utility';
-
-export default (
- apolloProvider,
- isSignedIn,
- releasesFetchPath,
- epicFeatureAvailable,
- iterationFeatureAvailable,
-) => {
- const el = document.getElementById('js-issue-board-filtered-search');
- const rawFilterParams = queryToObject(window.location.search, { gatherArrays: true });
-
- const initialFilterParams = {
- ...convertObjectPropsToCamelCase(rawFilterParams, {}),
- };
-
- if (!el) {
- return null;
- }
-
- return new Vue({
- el,
- name: 'BoardFilteredSearchRoot',
- provide: {
- initialFilterParams,
- isSignedIn,
- releasesFetchPath,
- epicFeatureAvailable,
- iterationFeatureAvailable,
- },
- store, // TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/324094
- apolloProvider,
- render: (createElement) =>
- createElement(IssueBoardFilteredSearch, {
- props: { fullPath: store.state?.fullPath || '', boardType: store.state?.boardType || '' },
- }),
- });
-};
diff --git a/app/assets/javascripts/boards/mount_multiple_boards_switcher.js b/app/assets/javascripts/boards/mount_multiple_boards_switcher.js
deleted file mode 100644
index 0bc9cfbd867..00000000000
--- a/app/assets/javascripts/boards/mount_multiple_boards_switcher.js
+++ /dev/null
@@ -1,50 +0,0 @@
-import Vue from 'vue';
-import VueApollo from 'vue-apollo';
-import BoardsSelector from 'ee_else_ce/boards/components/boards_selector.vue';
-import store from '~/boards/stores';
-import createDefaultClient from '~/lib/graphql';
-import { parseBoolean } from '~/lib/utils/common_utils';
-
-Vue.use(VueApollo);
-
-const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(),
-});
-
-export default (params = {}) => {
- const boardsSwitcherElement = document.getElementById('js-multiple-boards-switcher');
- const { dataset } = boardsSwitcherElement;
- return new Vue({
- el: boardsSwitcherElement,
- name: 'BoardsSelectorRoot',
- components: {
- BoardsSelector,
- },
- apolloProvider,
- store,
- provide: {
- fullPath: params.fullPath,
- rootPath: params.rootPath,
- allowScopedLabels: params.allowScopedLabels,
- labelsManagePath: params.labelsManagePath,
- allowLabelCreate: parseBoolean(dataset.canAdminBoard),
- },
- data() {
- const boardsSelectorProps = {
- ...dataset,
- hasMissingBoards: parseBoolean(dataset.hasMissingBoards),
- canAdminBoard: parseBoolean(dataset.canAdminBoard),
- multipleIssueBoardsAvailable: parseBoolean(dataset.multipleIssueBoardsAvailable),
- scopedIssueBoardFeatureEnabled: parseBoolean(dataset.scopedIssueBoardFeatureEnabled),
- weights: JSON.parse(dataset.weights),
- };
-
- return { boardsSelectorProps };
- },
- render(createElement) {
- return createElement(BoardsSelector, {
- props: this.boardsSelectorProps,
- });
- },
- });
-};
diff --git a/app/assets/javascripts/boards/new_board.js b/app/assets/javascripts/boards/new_board.js
deleted file mode 100644
index 34f2fea79a9..00000000000
--- a/app/assets/javascripts/boards/new_board.js
+++ /dev/null
@@ -1,29 +0,0 @@
-import Vue from 'vue';
-import { parseBoolean } from '~/lib/utils/common_utils';
-import { getExperimentVariant } from '~/experimentation/utils';
-import { CANDIDATE_VARIANT } from '~/experimentation/constants';
-import NewBoardButton from './components/new_board_button.vue';
-
-export default () => {
- if (getExperimentVariant('prominent_create_board_btn') !== CANDIDATE_VARIANT) {
- return;
- }
-
- const el = document.querySelector('.js-new-board');
-
- if (!el) {
- return;
- }
-
- // eslint-disable-next-line no-new
- new Vue({
- el,
- provide: {
- multipleIssueBoardsAvailable: parseBoolean(el.dataset.multipleIssueBoardsAvailable),
- canAdminBoard: parseBoolean(el.dataset.canAdminBoard),
- },
- render(h) {
- return h(NewBoardButton);
- },
- });
-};
diff --git a/app/assets/javascripts/boards/toggle_epics_swimlanes.js b/app/assets/javascripts/boards/toggle_epics_swimlanes.js
deleted file mode 100644
index 2d1ec238274..00000000000
--- a/app/assets/javascripts/boards/toggle_epics_swimlanes.js
+++ /dev/null
@@ -1 +0,0 @@
-export default () => {};
diff --git a/app/assets/javascripts/boards/toggle_focus.js b/app/assets/javascripts/boards/toggle_focus.js
deleted file mode 100644
index 8f057e192dd..00000000000
--- a/app/assets/javascripts/boards/toggle_focus.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import Vue from 'vue';
-import ToggleFocus from './components/toggle_focus.vue';
-
-export default () => {
- const issueBoardsContentSelector = '.content-wrapper > .js-focus-mode-board';
-
- return new Vue({
- el: '#js-toggle-focus-btn',
- name: 'ToggleFocusRoot',
- render(h) {
- return h(ToggleFocus, {
- props: {
- issueBoardsContentSelector,
- },
- });
- },
- });
-};
diff --git a/app/assets/javascripts/boards/toggle_labels.js b/app/assets/javascripts/boards/toggle_labels.js
deleted file mode 100644
index 2d1ec238274..00000000000
--- a/app/assets/javascripts/boards/toggle_labels.js
+++ /dev/null
@@ -1 +0,0 @@
-export default () => {};
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/registry_header.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/registry_header.vue
index 6d2ff9ea7b6..154e176dc6e 100644
--- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/registry_header.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/registry_header.vue
@@ -1,4 +1,5 @@
<script>
+import { GlLink } from '@gitlab/ui';
import { approximateDuration, calculateRemainingMilliseconds } from '~/lib/utils/datetime_utility';
import { n__, sprintf } from '~/locale';
import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue';
@@ -9,6 +10,7 @@ import {
LIST_INTRO_TEXT,
EXPIRATION_POLICY_WILL_RUN_IN,
EXPIRATION_POLICY_DISABLED_TEXT,
+ SET_UP_CLEANUP,
} from '../../constants/index';
export default {
@@ -16,6 +18,7 @@ export default {
components: {
TitleArea,
MetadataItem,
+ GlLink,
},
props: {
expirationPolicy: {
@@ -43,6 +46,16 @@ export default {
required: false,
default: false,
},
+ cleanupPoliciesSettingsPath: {
+ type: String,
+ default: '',
+ required: false,
+ },
+ showCleanupPolicyLink: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
loader: {
repeat: 10,
@@ -51,6 +64,7 @@ export default {
},
i18n: {
CONTAINER_REGISTRY_TITLE,
+ SET_UP_CLEANUP,
},
computed: {
imagesCountText() {
@@ -105,6 +119,9 @@ export default {
:text="expirationPolicyText"
size="xl"
/>
+ <gl-link v-if="showCleanupPolicyLink" class="gl-ml-2" :href="cleanupPoliciesSettingsPath">{{
+ $options.i18n.SET_UP_CLEANUP
+ }}</gl-link>
</template>
</title-area>
</template>
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/expiration_policies.js b/app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/expiration_policies.js
index 40f9b09a982..e584da23edb 100644
--- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/expiration_policies.js
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/expiration_policies.js
@@ -4,7 +4,7 @@ export const EXPIRATION_POLICY_WILL_RUN_IN = s__(
'ContainerRegistry|Expiration policy will run in %{time}',
);
export const EXPIRATION_POLICY_DISABLED_TEXT = s__(
- 'ContainerRegistry|Expiration policy is disabled',
+ 'ContainerRegistry|Expiration policy is disabled.',
);
export const DELETE_ALERT_TITLE = s__('ContainerRegistry|Some tags were not deleted');
export const DELETE_ALERT_LINK_TEXT = s__(
@@ -13,3 +13,4 @@ export const DELETE_ALERT_LINK_TEXT = s__(
export const CLEANUP_TIMED_OUT_ERROR_MESSAGE = s__(
'ContainerRegistry|Cleanup timed out before it could delete all tags',
);
+export const SET_UP_CLEANUP = s__('ContainerRegistry|Set up cleanup');
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/index.js b/app/assets/javascripts/packages_and_registries/container_registry/explorer/index.js
index ca5bd8d6964..a558550c91f 100644
--- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/index.js
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/index.js
@@ -35,7 +35,7 @@ export default () => {
expirationPolicy,
isGroupPage,
isAdmin,
- showCleanupPolicyOnAlert,
+ showCleanupPolicyLink,
showUnfinishedTagCleanupCallout,
connectionError,
invalidPathError,
@@ -68,7 +68,7 @@ export default () => {
expirationPolicy: expirationPolicy ? JSON.parse(expirationPolicy) : undefined,
isGroupPage: parseBoolean(isGroupPage),
isAdmin: parseBoolean(isAdmin),
- showCleanupPolicyOnAlert: parseBoolean(showCleanupPolicyOnAlert),
+ showCleanupPolicyLink: parseBoolean(showCleanupPolicyLink),
showUnfinishedTagCleanupCallout: parseBoolean(showUnfinishedTagCleanupCallout),
connectionError: parseBoolean(connectionError),
invalidPathError: parseBoolean(invalidPathError),
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/list.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/list.vue
index 5f9e614bebb..d1cab406984 100644
--- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/list.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/list.vue
@@ -11,7 +11,6 @@ import {
import { get } from 'lodash';
import getContainerRepositoriesQuery from 'shared_queries/container_registry/get_container_repositories.query.graphql';
import createFlash from '~/flash';
-import CleanupPolicyEnabledAlert from '~/packages_and_registries/shared/components/cleanup_policy_enabled_alert.vue';
import { FILTERED_SEARCH_TERM } from '~/packages_and_registries/shared/constants';
import Tracking from '~/tracking';
import PersistedSearch from '~/packages_and_registries/shared/components/persisted_search.vue';
@@ -60,7 +59,6 @@ export default {
GlSkeletonLoader,
RegistryHeader,
DeleteImage,
- CleanupPolicyEnabledAlert,
PersistedSearch,
},
directives: {
@@ -273,12 +271,6 @@ export default {
</gl-sprintf>
</gl-alert>
- <cleanup-policy-enabled-alert
- v-if="config.showCleanupPolicyOnAlert"
- :project-path="config.projectPath"
- :cleanup-policies-settings-path="config.cleanupPoliciesSettingsPath"
- />
-
<gl-empty-state
v-if="showConnectionError"
:title="$options.i18n.CONNECTION_ERROR_TITLE"
@@ -304,6 +296,8 @@ export default {
:expiration-policy="config.expirationPolicy"
:help-page-path="config.helpPagePath"
:hide-expiration-policy-data="config.isGroupPage"
+ :cleanup-policies-settings-path="config.cleanupPoliciesSettingsPath"
+ :show-cleanup-policy-link="config.showCleanupPolicyLink"
>
<template #commands>
<cli-commands
diff --git a/app/assets/javascripts/packages_and_registries/settings/project/components/registry_settings_app.vue b/app/assets/javascripts/packages_and_registries/settings/project/components/registry_settings_app.vue
index 7be3bba7cae..854c88b2ad3 100644
--- a/app/assets/javascripts/packages_and_registries/settings/project/components/registry_settings_app.vue
+++ b/app/assets/javascripts/packages_and_registries/settings/project/components/registry_settings_app.vue
@@ -9,7 +9,6 @@ import {
UNAVAILABLE_ADMIN_FEATURE_TEXT,
} from '~/packages_and_registries/settings/project/constants';
import expirationPolicyQuery from '~/packages_and_registries/settings/project/graphql/queries/get_expiration_policy.query.graphql';
-import CleanupPolicyEnabledAlert from '~/packages_and_registries/shared/components/cleanup_policy_enabled_alert.vue';
import SettingsBlock from '~/vue_shared/components/settings/settings_block.vue';
import SettingsForm from './settings_form.vue';
@@ -18,19 +17,11 @@ export default {
components: {
SettingsBlock,
SettingsForm,
- CleanupPolicyEnabledAlert,
GlAlert,
GlSprintf,
GlLink,
},
- inject: [
- 'projectPath',
- 'isAdmin',
- 'adminSettingsPath',
- 'enableHistoricEntries',
- 'helpPagePath',
- 'showCleanupPolicyOnAlert',
- ],
+ inject: ['projectPath', 'isAdmin', 'adminSettingsPath', 'enableHistoricEntries', 'helpPagePath'],
i18n: {
UNAVAILABLE_FEATURE_TITLE,
UNAVAILABLE_FEATURE_INTRO_TEXT,
@@ -87,7 +78,6 @@ export default {
<template>
<section data-testid="registry-settings-app">
- <cleanup-policy-enabled-alert v-if="showCleanupPolicyOnAlert" :project-path="projectPath" />
<settings-block :collapsible="false">
<template #title> {{ __('Clean up image tags') }}</template>
<template #description>
diff --git a/app/assets/javascripts/packages_and_registries/settings/project/registry_settings_bundle.js b/app/assets/javascripts/packages_and_registries/settings/project/registry_settings_bundle.js
index 2a3e2c28fa6..17c33073668 100644
--- a/app/assets/javascripts/packages_and_registries/settings/project/registry_settings_bundle.js
+++ b/app/assets/javascripts/packages_and_registries/settings/project/registry_settings_bundle.js
@@ -20,7 +20,6 @@ export default () => {
adminSettingsPath,
tagsRegexHelpPagePath,
helpPagePath,
- showCleanupPolicyOnAlert,
} = el.dataset;
return new Vue({
el,
@@ -35,7 +34,6 @@ export default () => {
adminSettingsPath,
tagsRegexHelpPagePath,
helpPagePath,
- showCleanupPolicyOnAlert: parseBoolean(showCleanupPolicyOnAlert),
},
render(createElement) {
return createElement('registry-settings-app', {});
diff --git a/app/assets/javascripts/packages_and_registries/shared/components/cleanup_policy_enabled_alert.vue b/app/assets/javascripts/packages_and_registries/shared/components/cleanup_policy_enabled_alert.vue
deleted file mode 100644
index d51c62e0623..00000000000
--- a/app/assets/javascripts/packages_and_registries/shared/components/cleanup_policy_enabled_alert.vue
+++ /dev/null
@@ -1,54 +0,0 @@
-<script>
-import { GlSprintf, GlAlert, GlLink } from '@gitlab/ui';
-import { s__ } from '~/locale';
-import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
-
-export default {
- components: {
- GlAlert,
- GlLink,
- GlSprintf,
- LocalStorageSync,
- },
- props: {
- projectPath: {
- type: String,
- required: true,
- },
- cleanupPoliciesSettingsPath: {
- type: String,
- required: false,
- default: '',
- },
- },
- data() {
- return {
- dismissed: false,
- };
- },
- computed: {
- storageKey() {
- return `cleanup_policy_enabled_for_project_${this.projectPath}`;
- },
- },
- i18n: {
- message: s__(
- 'ContainerRegistry|Cleanup policies are now available for this project. %{linkStart}Click here to get started.%{linkEnd}',
- ),
- },
-};
-</script>
-
-<template>
- <local-storage-sync v-model="dismissed" :storage-key="storageKey">
- <gl-alert v-if="!dismissed" class="gl-mt-2" dismissible @dismiss="dismissed = true">
- <gl-sprintf :message="$options.i18n.message">
- <template #link="{ content }">
- <gl-link v-if="cleanupPoliciesSettingsPath" :href="cleanupPoliciesSettingsPath">{{
- content
- }}</gl-link>
- </template>
- </gl-sprintf>
- </gl-alert>
- </local-storage-sync>
-</template>
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/init_form.js b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/init_form.js
index 88ff05b20a0..5dae812bbcb 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/init_form.js
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/init_form.js
@@ -33,13 +33,7 @@ function initIntervalPatternInput() {
}
function getEnabledRefTypes() {
- const refTypes = [REF_TYPE_BRANCHES];
-
- if (gon.features.pipelineSchedulesWithTags) {
- refTypes.push(REF_TYPE_TAGS);
- }
-
- return refTypes;
+ return [REF_TYPE_BRANCHES, REF_TYPE_TAGS];
}
function initTargetRefDropdown() {
@@ -61,9 +55,7 @@ function initTargetRefDropdown() {
value: $refField.value,
useSymbolicRefNames: true,
translations: {
- dropdownHeader: gon.features.pipelineSchedulesWithTags
- ? __('Select target branch or tag')
- : __('Select target branch'),
+ dropdownHeader: __('Select target branch or tag'),
},
},
class: 'gl-w-full',
diff --git a/app/assets/stylesheets/page_bundles/boards.scss b/app/assets/stylesheets/page_bundles/boards.scss
index f91ca489bdf..eecd4954e39 100644
--- a/app/assets/stylesheets/page_bundles/boards.scss
+++ b/app/assets/stylesheets/page_bundles/boards.scss
@@ -198,7 +198,7 @@
border-bottom: 1px solid var(--gray-100, $gray-100);
height: 3rem;
- .js-max-issue-size::before {
+ .max-issue-size::before {
content: '/';
}
}
diff --git a/app/controllers/groups/boards_controller.rb b/app/controllers/groups/boards_controller.rb
index 641b3adb12b..e223e2a914d 100644
--- a/app/controllers/groups/boards_controller.rb
+++ b/app/controllers/groups/boards_controller.rb
@@ -43,8 +43,6 @@ class Groups::BoardsController < Groups::ApplicationController
def assign_endpoint_vars
@boards_endpoint = group_boards_path(group)
- @namespace_path = group.to_param
- @labels_endpoint = group_labels_path(group)
end
def authorize_read_board!
diff --git a/app/controllers/import/base_controller.rb b/app/controllers/import/base_controller.rb
index 7ad3a2ee358..936ecc171d7 100644
--- a/app/controllers/import/base_controller.rb
+++ b/app/controllers/import/base_controller.rb
@@ -70,7 +70,7 @@ class Import::BaseController < ApplicationController
end
def already_added_projects
- @already_added_projects ||= filtered(find_already_added_projects(provider_name))
+ @already_added_projects ||= find_already_added_projects(provider_name)
end
# rubocop: disable CodeReuse/ActiveRecord
diff --git a/app/controllers/projects/boards_controller.rb b/app/controllers/projects/boards_controller.rb
index c44a0830e2e..b82e60e9ac7 100644
--- a/app/controllers/projects/boards_controller.rb
+++ b/app/controllers/projects/boards_controller.rb
@@ -44,8 +44,6 @@ class Projects::BoardsController < Projects::ApplicationController
def assign_endpoint_vars
@boards_endpoint = project_boards_path(project)
@bulk_issues_path = bulk_update_project_issues_path(project)
- @namespace_path = project.namespace.full_path
- @labels_endpoint = project_labels_path(project)
end
def authorize_read_board!
diff --git a/app/controllers/projects/pipeline_schedules_controller.rb b/app/controllers/projects/pipeline_schedules_controller.rb
index 271c31b6429..ac94cc001dd 100644
--- a/app/controllers/projects/pipeline_schedules_controller.rb
+++ b/app/controllers/projects/pipeline_schedules_controller.rb
@@ -10,10 +10,6 @@ class Projects::PipelineSchedulesController < Projects::ApplicationController
before_action :authorize_update_pipeline_schedule!, except: [:index, :new, :create, :play]
before_action :authorize_admin_pipeline_schedule!, only: [:destroy]
- before_action do
- push_frontend_feature_flag(:pipeline_schedules_with_tags, @project, default_enabled: :yaml)
- end
-
feature_category :continuous_integration
# rubocop: disable CodeReuse/ActiveRecord
diff --git a/app/helpers/boards_helper.rb b/app/helpers/boards_helper.rb
index 7b4d87a77e4..f849f36bf84 100644
--- a/app/helpers/boards_helper.rb
+++ b/app/helpers/boards_helper.rb
@@ -127,20 +127,6 @@ module BoardsHelper
can?(current_user, :admin_issue, current_board_parent)
end
- def board_list_data
- include_descendant_groups = @group&.present?
-
- {
- toggle: "dropdown",
- list_labels_path: labels_filter_path_with_defaults(only_group_labels: true, include_ancestor_groups: true),
- labels: labels_filter_path_with_defaults(only_group_labels: true, include_descendant_groups: include_descendant_groups),
- labels_endpoint: @labels_endpoint,
- namespace_path: @namespace_path,
- project_path: @project&.path,
- group_path: @group&.path
- }
- end
-
def serializer
CurrentBoardSerializer.new
end
diff --git a/app/helpers/packages_helper.rb b/app/helpers/packages_helper.rb
index 01075862618..20d40626449 100644
--- a/app/helpers/packages_helper.rb
+++ b/app/helpers/packages_helper.rb
@@ -46,7 +46,7 @@ module PackagesHelper
::Gitlab::Tracking.event(category, event_name.to_s, **args)
end
- def show_cleanup_policy_on_alert(project)
+ def show_cleanup_policy_link(project)
Gitlab.com? &&
Gitlab.config.registry.enabled &&
project.feature_available?(:container_registry, current_user) &&
diff --git a/app/models/ci/namespace_mirror.rb b/app/models/ci/namespace_mirror.rb
index b4b9574942e..d5cbbb96134 100644
--- a/app/models/ci/namespace_mirror.rb
+++ b/app/models/ci/namespace_mirror.rb
@@ -11,8 +11,6 @@ module Ci
end
scope :contains_any_of_namespaces, -> (ids) do
- return none if ids.empty?
-
where('traversal_ids && ARRAY[?]::int[]', ids)
end
diff --git a/app/models/container_repository.rb b/app/models/container_repository.rb
index 03ac5c8e5df..28b4b0dcca1 100644
--- a/app/models/container_repository.rb
+++ b/app/models/container_repository.rb
@@ -174,7 +174,7 @@ class ContainerRepository < ApplicationRecord
end
end
- before_transition %i[importing import_aborted] => :import_done do |container_repository|
+ before_transition any => :import_done do |container_repository|
container_repository.migration_import_done_at = Time.zone.now
end
diff --git a/app/models/project_import_state.rb b/app/models/project_import_state.rb
index 42914b0d668..fabbd5b49cb 100644
--- a/app/models/project_import_state.rb
+++ b/app/models/project_import_state.rb
@@ -6,6 +6,8 @@ class ProjectImportState < ApplicationRecord
self.table_name = "project_mirror_data"
+ after_commit :expire_etag_cache
+
belongs_to :project, inverse_of: :import_state
validates :project, presence: true
@@ -76,6 +78,23 @@ class ProjectImportState < ApplicationRecord
end
end
+ def expire_etag_cache
+ if realtime_changes_path
+ Gitlab::EtagCaching::Store.new.tap do |store|
+ store.touch(realtime_changes_path)
+ rescue Gitlab::EtagCaching::Store::InvalidKeyError
+ # no-op: not every realtime changes endpoint is using etag caching
+ end
+ end
+ end
+
+ def realtime_changes_path
+ Gitlab::Routing.url_helpers.polymorphic_path([:realtime_changes_import, project.import_type.to_sym], format: :json)
+ rescue NoMethodError
+ # polymorphic_path throws NoMethodError when no such path exists
+ nil
+ end
+
def relation_hard_failures(limit:)
project.import_failures.hard_failures_by_correlation_id(correlation_id).limit(limit)
end
diff --git a/app/models/user.rb b/app/models/user.rb
index c683f5dd252..281e52b90b0 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -2220,27 +2220,43 @@ class User < ApplicationRecord
end
def ci_owned_project_runners_from_project_members
- Ci::RunnerProject
- .select('ci_runners.*')
- .joins(:runner)
- .where(project: project_members.where('access_level >= ?', Gitlab::Access::MAINTAINER).pluck(:source_id))
+ project_ids = project_members.where('access_level >= ?', Gitlab::Access::MAINTAINER).pluck(:source_id)
+
+ Ci::Runner
+ .joins(:runner_projects)
+ .where(runner_projects: { project: project_ids })
end
def ci_owned_project_runners_from_group_members
- Ci::RunnerProject
- .select('ci_runners.*')
- .joins(:runner)
- .joins('JOIN ci_project_mirrors ON ci_project_mirrors.project_id = ci_runner_projects.project_id')
- .joins('JOIN ci_namespace_mirrors ON ci_namespace_mirrors.namespace_id = ci_project_mirrors.namespace_id')
- .merge(ci_namespace_mirrors_for_group_members(Gitlab::Access::MAINTAINER))
+ cte_namespace_ids = Gitlab::SQL::CTE.new(
+ :cte_namespace_ids,
+ ci_namespace_mirrors_for_group_members(Gitlab::Access::MAINTAINER).select(:namespace_id)
+ )
+
+ cte_project_ids = Gitlab::SQL::CTE.new(
+ :cte_project_ids,
+ Ci::ProjectMirror
+ .select(:project_id)
+ .where('ci_project_mirrors.namespace_id IN (SELECT namespace_id FROM cte_namespace_ids)')
+ )
+
+ Ci::Runner
+ .with(cte_namespace_ids.to_arel)
+ .with(cte_project_ids.to_arel)
+ .joins(:runner_projects)
+ .where('ci_runner_projects.project_id IN (SELECT project_id FROM cte_project_ids)')
end
def ci_owned_group_runners
- Ci::RunnerNamespace
- .select('ci_runners.*')
- .joins(:runner)
- .joins('JOIN ci_namespace_mirrors ON ci_namespace_mirrors.namespace_id = ci_runner_namespaces.namespace_id')
- .merge(ci_namespace_mirrors_for_group_members(Gitlab::Access::OWNER))
+ cte_namespace_ids = Gitlab::SQL::CTE.new(
+ :cte_namespace_ids,
+ ci_namespace_mirrors_for_group_members(Gitlab::Access::OWNER).select(:namespace_id)
+ )
+
+ Ci::Runner
+ .with(cte_namespace_ids.to_arel)
+ .joins(:runner_namespaces)
+ .where('ci_runner_namespaces.namespace_id IN (SELECT namespace_id FROM cte_namespace_ids)')
end
def ci_namespace_mirrors_for_group_members(level)
diff --git a/app/services/incident_management/issuable_escalation_statuses/build_service.rb b/app/services/incident_management/issuable_escalation_statuses/build_service.rb
new file mode 100644
index 00000000000..9ebcf72a0c9
--- /dev/null
+++ b/app/services/incident_management/issuable_escalation_statuses/build_service.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module IncidentManagement
+ module IssuableEscalationStatuses
+ class BuildService < ::BaseProjectService
+ def initialize(issue)
+ @issue = issue
+ @alert = issue.alert_management_alert
+
+ super(project: issue.project)
+ end
+
+ def execute
+ return issue.escalation_status if issue.escalation_status
+
+ issue.build_incident_management_issuable_escalation_status(alert_params)
+ end
+
+ private
+
+ attr_reader :issue, :alert
+
+ def alert_params
+ return {} unless alert
+
+ {
+ status_event: alert.status_event_for(alert.status_name)
+ }
+ end
+ end
+ end
+end
+
+IncidentManagement::IssuableEscalationStatuses::BuildService.prepend_mod
diff --git a/app/services/incident_management/issuable_escalation_statuses/create_service.rb b/app/services/incident_management/issuable_escalation_statuses/create_service.rb
index e28debf0fa3..9b22fb97e0d 100644
--- a/app/services/incident_management/issuable_escalation_statuses/create_service.rb
+++ b/app/services/incident_management/issuable_escalation_statuses/create_service.rb
@@ -2,14 +2,15 @@
module IncidentManagement
module IssuableEscalationStatuses
- class CreateService < BaseService
+ class CreateService < ::BaseProjectService
def initialize(issue)
@issue = issue
- @alert = issue.alert_management_alert
+
+ super(project: issue.project)
end
def execute
- escalation_status = ::IncidentManagement::IssuableEscalationStatus.new(issue: issue, **alert_params)
+ escalation_status = BuildService.new(issue).execute
if escalation_status.save
ServiceResponse.success(payload: { escalation_status: escalation_status })
@@ -20,17 +21,7 @@ module IncidentManagement
private
- attr_reader :issue, :alert
-
- def alert_params
- return {} unless alert
-
- {
- status_event: alert.status_event_for(alert.status_name)
- }
- end
+ attr_reader :issue
end
end
end
-
-IncidentManagement::IssuableEscalationStatuses::CreateService.prepend_mod
diff --git a/app/services/incident_management/issuable_escalation_statuses/prepare_update_service.rb b/app/services/incident_management/issuable_escalation_statuses/prepare_update_service.rb
index 8f591b375ee..1d0504a6e80 100644
--- a/app/services/incident_management/issuable_escalation_statuses/prepare_update_service.rb
+++ b/app/services/incident_management/issuable_escalation_statuses/prepare_update_service.rb
@@ -31,9 +31,7 @@ module IncidentManagement
attr_reader :issuable, :param_errors
def available?
- issuable.supports_escalation? &&
- user_has_permissions? &&
- escalation_status.present?
+ issuable.supports_escalation? && user_has_permissions?
end
def user_has_permissions?
@@ -42,7 +40,7 @@ module IncidentManagement
def escalation_status
strong_memoize(:escalation_status) do
- issuable.escalation_status
+ issuable.escalation_status || BuildService.new(issuable).execute
end
end
diff --git a/app/views/projects/pipeline_schedules/_form.html.haml b/app/views/projects/pipeline_schedules/_form.html.haml
index 0818c3d5cff..e00d8e2c050 100644
--- a/app/views/projects/pipeline_schedules/_form.html.haml
+++ b/app/views/projects/pipeline_schedules/_form.html.haml
@@ -15,7 +15,7 @@
= f.text_field :cron_timezone, value: @schedule.cron_timezone, id: 'schedule_cron_timezone', class: 'hidden', name: 'schedule[cron_timezone]', required: true
.form-group.row
.col-md-9
- = f.label :ref, Feature.enabled?(:pipeline_schedules_with_tags, default_enabled: :yaml) ? _('Target branch or tag') : _('Target branch'), class: 'label-bold'
+ = f.label :ref, _('Target branch or tag'), class: 'label-bold'
%div{ data: { testid: 'schedule-target-ref' } }
.js-target-ref-dropdown{ data: { project_id: @project.id, default_branch: @project.default_branch } }
= f.text_field :ref, value: @schedule.ref, id: 'schedule_ref', class: 'hidden', name: 'schedule[ref]', required: true
diff --git a/app/views/projects/registry/repositories/index.html.haml b/app/views/projects/registry/repositories/index.html.haml
index aab5e9fca98..51f0b6319a1 100644
--- a/app/views/projects/registry/repositories/index.html.haml
+++ b/app/views/projects/registry/repositories/index.html.haml
@@ -19,7 +19,7 @@
"project_path": @project.full_path,
"gid_prefix": container_repository_gid_prefix,
"is_admin": current_user&.admin.to_s,
- "show_cleanup_policy_on_alert": show_cleanup_policy_on_alert(@project).to_s,
+ "show_cleanup_policy_link": show_cleanup_policy_link(@project).to_s,
"cleanup_policies_settings_path": project_settings_packages_and_registries_path(@project),
connection_error: (!!@connection_error).to_s,
invalid_path_error: (!!@invalid_path_error).to_s,
diff --git a/app/views/projects/settings/packages_and_registries/show.html.haml b/app/views/projects/settings/packages_and_registries/show.html.haml
index 658b2f2e65c..378bb0f9306 100644
--- a/app/views/projects/settings/packages_and_registries/show.html.haml
+++ b/app/views/projects/settings/packages_and_registries/show.html.haml
@@ -11,5 +11,5 @@
admin_settings_path: ci_cd_admin_application_settings_path(anchor: 'js-registry-settings'),
enable_historic_entries: container_expiration_policies_historic_entry_enabled?.to_s,
help_page_path: help_page_path('user/packages/container_registry/reduce_container_registry_storage', anchor: 'cleanup-policy'),
- show_cleanup_policy_on_alert: show_cleanup_policy_on_alert(@project).to_s,
+ show_cleanup_policy_link: show_cleanup_policy_link(@project).to_s,
tags_regex_help_page_path: help_page_path('user/packages/container_registry/reduce_container_registry_storage', anchor: 'regex-pattern-examples') } }
diff --git a/app/views/shared/boards/_switcher.html.haml b/app/views/shared/boards/_switcher.html.haml
deleted file mode 100644
index c667b3a4626..00000000000
--- a/app/views/shared/boards/_switcher.html.haml
+++ /dev/null
@@ -1,12 +0,0 @@
-- parent = board.resource_parent
-- milestone_filter_opts = { format: :json }
-- milestone_filter_opts = milestone_filter_opts.merge(only_group_milestones: true) if board.group_board?
-- weights = Gitlab.ee? ? ([Issue::WEIGHT_ANY] + Issue.weight_options) : []
-
-#js-multiple-boards-switcher.inline.boards-switcher{ data: { milestone_path: milestones_filter_path(milestone_filter_opts),
- board_base_url: board_base_url,
- has_missing_boards: (!multiple_boards_available? && current_board_parent.boards.size > 1).to_s,
- can_admin_board: can?(current_user, :admin_issue_board, parent).to_s,
- multiple_issue_boards_available: parent.multiple_issue_boards_available?.to_s,
- scoped_issue_board_feature_enabled: Gitlab.ee? && parent.feature_available?(:scoped_issue_board) ? 'true' : 'false',
- weights: weights.to_json } }
diff --git a/app/views/shared/issuable/_search_bar.html.haml b/app/views/shared/issuable/_search_bar.html.haml
index 37a79a50fb1..7fdf8ea7796 100644
--- a/app/views/shared/issuable/_search_bar.html.haml
+++ b/app/views/shared/issuable/_search_bar.html.haml
@@ -1,22 +1,12 @@
- type = local_assigns.fetch(:type)
-- board = local_assigns.fetch(:board, nil)
- show_sorting_dropdown = local_assigns.fetch(:show_sorting_dropdown, true)
- disable_target_branch = local_assigns.fetch(:disable_target_branch, false)
- placeholder = local_assigns[:placeholder] || _('Search or filter results...')
- block_css_class = type != :productivity_analytics ? 'row-content-block second-block' : ''
-- is_epic_board = board&.to_type == "EpicBoard"
-
-- if is_epic_board
- - user_can_admin_list = can?(current_user, :admin_epic_board_list, board.resource_parent)
-- elsif board
- - user_can_admin_list = can?(current_user, :admin_issue_board_list, board.resource_parent)
.issues-filters
.issues-details-filters.filtered-search-block.d-flex.flex-column.flex-lg-row{ class: block_css_class }
.d-flex.flex-column.flex-md-row.flex-grow-1.mb-lg-0.mb-md-2.mb-sm-0.w-100
- - if type == :boards
- = render "shared/boards/switcher", board: board
- .js-new-board{ data: { multiple_issue_boards_available: parent.multiple_issue_boards_available?.to_s, can_admin_board: can?(current_user, :admin_issue_board, parent).to_s, } }
= form_tag page_filter_path, method: :get, class: 'filter-form js-filter-form w-100' do
- if params[:search].present?
= hidden_field_tag :search, params[:search]
@@ -25,201 +15,188 @@
- checkbox_id = 'check-all-issues'
%label.gl-sr-only{ for: checkbox_id }= _('Select all')
= check_box_tag checkbox_id, nil, false, class: "check-all-issues left"
- - if is_epic_board
- #js-board-filtered-search{ data: { full_path: @group&.full_path } }
- - elsif board
- #js-issue-board-filtered-search
- - else
- .issues-other-filters.filtered-search-wrapper.d-flex.flex-column.flex-md-row
- .filtered-search-box
- - if type != :boards
- - text = tag.span(sprite_icon('history'), class: "d-md-none") + tag.span(_('Recent searches'), class: "d-none d-md-inline")
- = dropdown_tag(text,
- options: { wrapper_class: "filtered-search-history-dropdown-wrapper",
- toggle_class: "gl-button btn btn-default filtered-search-history-dropdown-toggle-button",
- dropdown_class: "filtered-search-history-dropdown",
- content_class: "filtered-search-history-dropdown-content" }) do
- .js-filtered-search-history-dropdown{ data: { full_path: search_history_storage_prefix } }
- .filtered-search-box-input-container.droplab-dropdown
- .scroll-container
- %ul.tokens-container.list-unstyled
- %li.input-token
- %input.form-control.filtered-search{ search_filter_input_options(type, placeholder) }
- #js-dropdown-hint.filtered-search-input-dropdown-menu.dropdown-menu.hint-dropdown
- %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
- %li.filter-dropdown-item{ data: {hint: "#{'{{hint}}'}", tag: "#{'{{tag}}'}", action: "#{'{{hint === \'search\' ? \'submit\' : \'\' }}'}" } }
- %button.gl-button.btn.btn-link{ type: 'button' }
- -# Encapsulate static class name `{{icon}}` inside #{} to bypass
- -# haml lint's ClassAttributeWithStaticValue
- %svg
- %use{ 'xlink:href': "#{'{{icon}}'}" }
- %span.js-filter-hint
- {{formattedKey}}
- #js-dropdown-operator.filtered-search-input-dropdown-menu.dropdown-menu
- %ul.filter-dropdown{ data: { dropdown: true, dynamic: true } }
- %li.filter-dropdown-item{ data: { value: "{{ title }}" } }
- %button.gl-button.btn.btn-link{ type: 'button' }
- {{ title }}
- %span.btn-helptext
- {{ help }}
- #js-dropdown-author.filtered-search-input-dropdown-menu.dropdown-menu
+ .issues-other-filters.filtered-search-wrapper.d-flex.flex-column.flex-md-row
+ .filtered-search-box
+ - if type != :boards
+ - text = tag.span(sprite_icon('history'), class: "d-md-none") + tag.span(_('Recent searches'), class: "d-none d-md-inline")
+ = dropdown_tag(text,
+ options: { wrapper_class: "filtered-search-history-dropdown-wrapper",
+ toggle_class: "gl-button btn btn-default filtered-search-history-dropdown-toggle-button",
+ dropdown_class: "filtered-search-history-dropdown",
+ content_class: "filtered-search-history-dropdown-content" }) do
+ .js-filtered-search-history-dropdown{ data: { full_path: search_history_storage_prefix } }
+ .filtered-search-box-input-container.droplab-dropdown
+ .scroll-container
+ %ul.tokens-container.list-unstyled
+ %li.input-token
+ %input.form-control.filtered-search{ search_filter_input_options(type, placeholder) }
+ #js-dropdown-hint.filtered-search-input-dropdown-menu.dropdown-menu.hint-dropdown
+ %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
+ %li.filter-dropdown-item{ data: {hint: "#{'{{hint}}'}", tag: "#{'{{tag}}'}", action: "#{'{{hint === \'search\' ? \'submit\' : \'\' }}'}" } }
+ %button.gl-button.btn.btn-link{ type: 'button' }
+ -# Encapsulate static class name `{{icon}}` inside #{} to bypass
+ -# haml lint's ClassAttributeWithStaticValue
+ %svg
+ %use{ 'xlink:href': "#{'{{icon}}'}" }
+ %span.js-filter-hint
+ {{formattedKey}}
+ #js-dropdown-operator.filtered-search-input-dropdown-menu.dropdown-menu
+ %ul.filter-dropdown{ data: { dropdown: true, dynamic: true } }
+ %li.filter-dropdown-item{ data: { value: "{{ title }}" } }
+ %button.gl-button.btn.btn-link{ type: 'button' }
+ {{ title }}
+ %span.btn-helptext
+ {{ help }}
+ #js-dropdown-author.filtered-search-input-dropdown-menu.dropdown-menu
+ - if current_user
+ %ul{ data: { dropdown: true } }
+ = render 'shared/issuable/user_dropdown_item',
+ user: current_user
+ %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
+ = render 'shared/issuable/user_dropdown_item',
+ user: User.new(username: '{{username}}', name: '{{name}}'),
+ avatar: { lazy: true, url: '{{avatar_url}}' }
+ #js-dropdown-assignee.filtered-search-input-dropdown-menu.dropdown-menu
+ %ul{ data: { dropdown: true } }
+ %li.filter-dropdown-item{ data: { value: 'None' } }
+ %button.gl-button.btn.btn-link{ type: 'button' }
+ = _('None')
+ %li.filter-dropdown-item{ data: { value: 'Any' } }
+ %button.gl-button.btn.btn-link{ type: 'button' }
+ = _('Any')
+ %li.divider.droplab-item-ignore
- if current_user
- %ul{ data: { dropdown: true } }
- = render 'shared/issuable/user_dropdown_item',
- user: current_user
- %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
= render 'shared/issuable/user_dropdown_item',
- user: User.new(username: '{{username}}', name: '{{name}}'),
- avatar: { lazy: true, url: '{{avatar_url}}' }
- #js-dropdown-assignee.filtered-search-input-dropdown-menu.dropdown-menu
- %ul{ data: { dropdown: true } }
- %li.filter-dropdown-item{ data: { value: 'None' } }
- %button.gl-button.btn.btn-link{ type: 'button' }
- = _('None')
- %li.filter-dropdown-item{ data: { value: 'Any' } }
- %button.gl-button.btn.btn-link{ type: 'button' }
- = _('Any')
- %li.divider.droplab-item-ignore
- - if current_user
- = render 'shared/issuable/user_dropdown_item',
- user: current_user
- %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
+ user: current_user
+ %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
+ = render 'shared/issuable/user_dropdown_item',
+ user: User.new(username: '{{username}}', name: '{{name}}'),
+ avatar: { lazy: true, url: '{{avatar_url}}' }
+ #js-dropdown-reviewer.filtered-search-input-dropdown-menu.dropdown-menu
+ %ul{ data: { dropdown: true } }
+ %li.filter-dropdown-item{ data: { value: 'None' } }
+ %button.gl-button.btn.btn-link{ type: 'button' }
+ = _('None')
+ %li.filter-dropdown-item{ data: { value: 'Any' } }
+ %button.gl-button.btn.btn-link{ type: 'button' }
+ = _('Any')
+ %li.divider.droplab-item-ignore
+ - if current_user
= render 'shared/issuable/user_dropdown_item',
- user: User.new(username: '{{username}}', name: '{{name}}'),
- avatar: { lazy: true, url: '{{avatar_url}}' }
- #js-dropdown-reviewer.filtered-search-input-dropdown-menu.dropdown-menu
- %ul{ data: { dropdown: true } }
- %li.filter-dropdown-item{ data: { value: 'None' } }
- %button.gl-button.btn.btn-link{ type: 'button' }
- = _('None')
- %li.filter-dropdown-item{ data: { value: 'Any' } }
- %button.gl-button.btn.btn-link{ type: 'button' }
- = _('Any')
- %li.divider.droplab-item-ignore
- - if current_user
+ user: current_user
+ %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
+ = render 'shared/issuable/user_dropdown_item',
+ user: User.new(username: '{{username}}', name: '{{name}}'),
+ avatar: { lazy: true, url: '{{avatar_url}}' }
+ - if Feature.enabled?(:mr_attention_requests, default_enabled: :yaml)
+ #js-dropdown-attention-requested.filtered-search-input-dropdown-menu.dropdown-menu
+ - if current_user
+ %ul{ data: { dropdown: true } }
= render 'shared/issuable/user_dropdown_item',
user: current_user
%ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
= render 'shared/issuable/user_dropdown_item',
user: User.new(username: '{{username}}', name: '{{name}}'),
avatar: { lazy: true, url: '{{avatar_url}}' }
- - if Feature.enabled?(:mr_attention_requests, default_enabled: :yaml)
- #js-dropdown-attention-requested.filtered-search-input-dropdown-menu.dropdown-menu
- - if current_user
- %ul{ data: { dropdown: true } }
- = render 'shared/issuable/user_dropdown_item',
- user: current_user
- %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
- = render 'shared/issuable/user_dropdown_item',
- user: User.new(username: '{{username}}', name: '{{name}}'),
- avatar: { lazy: true, url: '{{avatar_url}}' }
- = render_if_exists 'shared/issuable/approver_dropdown'
- = render_if_exists 'shared/issuable/approved_by_dropdown'
- #js-dropdown-milestone.filtered-search-input-dropdown-menu.dropdown-menu
- %ul{ data: { dropdown: true } }
- %li.filter-dropdown-item{ data: { value: 'None' } }
- %button.gl-button.btn.btn-link{ type: 'button' }
- = _('None')
- %li.filter-dropdown-item{ data: { value: 'Any' } }
- %button.gl-button.btn.btn-link{ type: 'button' }
- = _('Any')
- %li.filter-dropdown-item{ data: { value: 'Upcoming' } }
- %button.gl-button.btn.btn-link{ type: 'button' }
- = _('Upcoming')
- %li.filter-dropdown-item{ data: { value: 'Started' } }
- %button.gl-button.btn.btn-link{ type: 'button' }
- = _('Started')
- %li.divider.droplab-item-ignore
- %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
- %li.filter-dropdown-item
- %button.gl-button.btn.btn-link.js-data-value{ type: 'button' }
+ = render_if_exists 'shared/issuable/approver_dropdown'
+ = render_if_exists 'shared/issuable/approved_by_dropdown'
+ #js-dropdown-milestone.filtered-search-input-dropdown-menu.dropdown-menu
+ %ul{ data: { dropdown: true } }
+ %li.filter-dropdown-item{ data: { value: 'None' } }
+ %button.gl-button.btn.btn-link{ type: 'button' }
+ = _('None')
+ %li.filter-dropdown-item{ data: { value: 'Any' } }
+ %button.gl-button.btn.btn-link{ type: 'button' }
+ = _('Any')
+ %li.filter-dropdown-item{ data: { value: 'Upcoming' } }
+ %button.gl-button.btn.btn-link{ type: 'button' }
+ = _('Upcoming')
+ %li.filter-dropdown-item{ data: { value: 'Started' } }
+ %button.gl-button.btn.btn-link{ type: 'button' }
+ = _('Started')
+ %li.divider.droplab-item-ignore
+ %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
+ %li.filter-dropdown-item
+ %button.gl-button.btn.btn-link.js-data-value{ type: 'button' }
+ {{title}}
+ = render_if_exists 'shared/issuable/filter_iteration', type: type
+ #js-dropdown-release.filtered-search-input-dropdown-menu.dropdown-menu
+ %ul{ data: { dropdown: true } }
+ %li.filter-dropdown-item{ data: { value: 'None' } }
+ %button.gl-button.btn.btn-link{ type: 'button' }
+ = _('None')
+ %li.filter-dropdown-item{ data: { value: 'Any' } }
+ %button.gl-button.btn.btn-link{ type: 'button' }
+ = _('Any')
+ %li.divider.droplab-item-ignore
+ %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
+ %li.filter-dropdown-item
+ %button.gl-button.btn.btn-link.js-data-value{ type: 'button' }
+ {{title}}
+ #js-dropdown-label.filtered-search-input-dropdown-menu.dropdown-menu
+ %ul{ data: { dropdown: true } }
+ %li.filter-dropdown-item{ data: { value: 'None' } }
+ %button.gl-button.btn.btn-link{ type: 'button' }
+ = _('None')
+ %li.filter-dropdown-item{ data: { value: 'Any' } }
+ %button.gl-button.btn.btn-link{ type: 'button' }
+ = _('Any')
+ %li.divider.droplab-item-ignore
+ %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
+ %li.filter-dropdown-item
+ %button.gl-button.btn.btn-link{ type: 'button' }
+ %span.dropdown-label-box{ style: 'background: {{color}}' }
+ %span.label-title.js-data-value
{{title}}
- = render_if_exists 'shared/issuable/filter_iteration', type: type
- #js-dropdown-release.filtered-search-input-dropdown-menu.dropdown-menu
- %ul{ data: { dropdown: true } }
- %li.filter-dropdown-item{ data: { value: 'None' } }
- %button.gl-button.btn.btn-link{ type: 'button' }
- = _('None')
- %li.filter-dropdown-item{ data: { value: 'Any' } }
- %button.gl-button.btn.btn-link{ type: 'button' }
- = _('Any')
- %li.divider.droplab-item-ignore
- %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
- %li.filter-dropdown-item
- %button.gl-button.btn.btn-link.js-data-value{ type: 'button' }
- {{title}}
- #js-dropdown-label.filtered-search-input-dropdown-menu.dropdown-menu
- %ul{ data: { dropdown: true } }
- %li.filter-dropdown-item{ data: { value: 'None' } }
- %button.gl-button.btn.btn-link{ type: 'button' }
- = _('None')
- %li.filter-dropdown-item{ data: { value: 'Any' } }
- %button.gl-button.btn.btn-link{ type: 'button' }
- = _('Any')
- %li.divider.droplab-item-ignore
- %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
- %li.filter-dropdown-item
- %button.gl-button.btn.btn-link{ type: 'button' }
- %span.dropdown-label-box{ style: 'background: {{color}}' }
- %span.label-title.js-data-value
- {{title}}
- #js-dropdown-my-reaction.filtered-search-input-dropdown-menu.dropdown-menu
- %ul{ data: { dropdown: true } }
- %li.filter-dropdown-item{ data: { value: 'None' } }
- %button.gl-button.btn.btn-link{ type: 'button' }
- = _('None')
- %li.filter-dropdown-item{ data: { value: 'Any' } }
- %button.gl-button.btn.btn-link{ type: 'button' }
- = _('Any')
- %li.divider.droplab-item-ignore
- %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
- %li.filter-dropdown-item
- %button.gl-button.btn.btn-link{ type: 'button' }
- %gl-emoji
- %span.js-data-value.gl-ml-3
- {{name}}
- #js-dropdown-wip.filtered-search-input-dropdown-menu.dropdown-menu
- %ul.filter-dropdown{ data: { dropdown: true } }
- %li.filter-dropdown-item{ data: { value: 'yes', capitalize: true } }
- %button.gl-button.btn.btn-link{ type: 'button' }
- = _('Yes')
- %li.filter-dropdown-item{ data: { value: 'no', capitalize: true } }
- %button.gl-button.btn.btn-link{ type: 'button' }
- = _('No')
- #js-dropdown-confidential.filtered-search-input-dropdown-menu.dropdown-menu
- %ul.filter-dropdown{ data: { dropdown: true } }
- %li.filter-dropdown-item{ data: { value: 'yes', capitalize: true } }
- %button.gl-button.btn.btn-link{ type: 'button' }
- = _('Yes')
- %li.filter-dropdown-item{ data: { value: 'no', capitalize: true } }
- %button.gl-button.btn.btn-link{ type: 'button' }
- = _('No')
- - unless disable_target_branch
- #js-dropdown-target-branch.filtered-search-input-dropdown-menu.dropdown-menu
- %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
- %li.filter-dropdown-item
- %button.gl-button.btn.btn-link.js-data-value.monospace
- {{title}}
- #js-dropdown-environment.filtered-search-input-dropdown-menu.dropdown-menu
+ #js-dropdown-my-reaction.filtered-search-input-dropdown-menu.dropdown-menu
+ %ul{ data: { dropdown: true } }
+ %li.filter-dropdown-item{ data: { value: 'None' } }
+ %button.gl-button.btn.btn-link{ type: 'button' }
+ = _('None')
+ %li.filter-dropdown-item{ data: { value: 'Any' } }
+ %button.gl-button.btn.btn-link{ type: 'button' }
+ = _('Any')
+ %li.divider.droplab-item-ignore
+ %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
+ %li.filter-dropdown-item
+ %button.gl-button.btn.btn-link{ type: 'button' }
+ %gl-emoji
+ %span.js-data-value.gl-ml-3
+ {{name}}
+ #js-dropdown-wip.filtered-search-input-dropdown-menu.dropdown-menu
+ %ul.filter-dropdown{ data: { dropdown: true } }
+ %li.filter-dropdown-item{ data: { value: 'yes', capitalize: true } }
+ %button.gl-button.btn.btn-link{ type: 'button' }
+ = _('Yes')
+ %li.filter-dropdown-item{ data: { value: 'no', capitalize: true } }
+ %button.gl-button.btn.btn-link{ type: 'button' }
+ = _('No')
+ #js-dropdown-confidential.filtered-search-input-dropdown-menu.dropdown-menu
+ %ul.filter-dropdown{ data: { dropdown: true } }
+ %li.filter-dropdown-item{ data: { value: 'yes', capitalize: true } }
+ %button.gl-button.btn.btn-link{ type: 'button' }
+ = _('Yes')
+ %li.filter-dropdown-item{ data: { value: 'no', capitalize: true } }
+ %button.gl-button.btn.btn-link{ type: 'button' }
+ = _('No')
+ - unless disable_target_branch
+ #js-dropdown-target-branch.filtered-search-input-dropdown-menu.dropdown-menu
%ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
%li.filter-dropdown-item
- %button.gl-button.btn.btn-link.js-data-value{ type: 'button' }
+ %button.gl-button.btn.btn-link.js-data-value.monospace
{{title}}
+ #js-dropdown-environment.filtered-search-input-dropdown-menu.dropdown-menu
+ %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
+ %li.filter-dropdown-item
+ %button.gl-button.btn.btn-link.js-data-value{ type: 'button' }
+ {{title}}
- = render_if_exists 'shared/issuable/filter_weight', type: type
+ = render_if_exists 'shared/issuable/filter_weight', type: type
- = render_if_exists 'shared/issuable/filter_epic', type: type
+ = render_if_exists 'shared/issuable/filter_epic', type: type
- %button.clear-search.hidden{ type: 'button' }
- = sprite_icon('close', size: 16, css_class: 'clear-search-icon')
+ %button.clear-search.hidden{ type: 'button' }
+ = sprite_icon('close', size: 16, css_class: 'clear-search-icon')
.filter-dropdown-container.gl-display-flex.gl-flex-direction-column.gl-md-flex-direction-row.gl-align-items-flex-start
- - if type == :boards
- #js-board-labels-toggle
- - if current_user
- #js-board-epics-swimlanes-toggle
- .js-board-config{ data: { can_admin_list: user_can_admin_list.to_s, has_scope: board.scoped?.to_s } }
- - if user_can_admin_list
- .js-create-column-trigger{ data: board_list_data }
- #js-toggle-focus-btn
- - elsif type != :productivity_analytics && show_sorting_dropdown
+ - if type != :productivity_analytics && show_sorting_dropdown
= render 'shared/issuable/sort_dropdown'