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:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-08-12 15:11:05 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-08-12 15:11:05 +0300
commit2fe5ea34a5f63661a050404d3b5fbe3056a39765 (patch)
tree630d5b896d2933d38a206abf4e2baf7e1b773027 /app
parentdcb517514405d6f550cc077686889dbb34c37c75 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/content_editor/extensions/code_block_highlight.js12
-rw-r--r--app/assets/javascripts/content_editor/services/markdown_serializer.js8
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard_panel.vue13
-rw-r--r--app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue15
-rw-r--r--app/assets/javascripts/sidebar/mount_sidebar.js2
-rw-r--r--app/assets/javascripts/tracking/constants.js6
-rw-r--r--app/assets/javascripts/tracking/tracking.js3
-rw-r--r--app/assets/javascripts/tracking/utils.js10
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue34
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue260
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/project_labels.query.graphql12
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue32
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/actions.js22
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/mutation_types.js8
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/mutations.js21
-rw-r--r--app/helpers/analytics/navbar_helper.rb28
-rw-r--r--app/models/remote_mirror.rb17
-rw-r--r--app/services/git/branch_hooks_service.rb2
-rw-r--r--app/services/service_ping/service_ping_settings.rb6
-rw-r--r--app/views/layouts/nav/sidebar/_analytics_links.html.haml22
-rw-r--r--app/views/layouts/nav/sidebar/_group_menus.html.haml2
21 files changed, 260 insertions, 275 deletions
diff --git a/app/assets/javascripts/content_editor/extensions/code_block_highlight.js b/app/assets/javascripts/content_editor/extensions/code_block_highlight.js
index 177ea4c2e7d..c6d32fb8547 100644
--- a/app/assets/javascripts/content_editor/extensions/code_block_highlight.js
+++ b/app/assets/javascripts/content_editor/extensions/code_block_highlight.js
@@ -14,18 +14,6 @@ export default CodeBlockLowlight.extend({
};
},
},
- /* `params` is the name of the attribute that
- prosemirror-markdown uses to extract the language
- of a codeblock.
- https://github.com/ProseMirror/prosemirror-markdown/blob/master/src/to_markdown.js#L62
- */
- params: {
- parseHTML: (element) => {
- return {
- params: extractLanguage(element),
- };
- },
- },
class: {
default: 'code highlight js-syntax-highlight',
},
diff --git a/app/assets/javascripts/content_editor/services/markdown_serializer.js b/app/assets/javascripts/content_editor/services/markdown_serializer.js
index 702344f5514..5c59fb7710a 100644
--- a/app/assets/javascripts/content_editor/services/markdown_serializer.js
+++ b/app/assets/javascripts/content_editor/services/markdown_serializer.js
@@ -51,7 +51,13 @@ const defaultSerializerConfig = {
nodes: {
[Blockquote.name]: defaultMarkdownSerializer.nodes.blockquote,
[BulletList.name]: defaultMarkdownSerializer.nodes.bullet_list,
- [CodeBlockHighlight.name]: defaultMarkdownSerializer.nodes.code_block,
+ [CodeBlockHighlight.name]: (state, node) => {
+ state.write(`\`\`\`${node.attrs.language || ''}\n`);
+ state.text(node.textContent, false);
+ state.ensureNewLine();
+ state.write('```');
+ state.closeBlock(node);
+ },
[Emoji.name]: (state, node) => {
const { name } = node.attrs;
diff --git a/app/assets/javascripts/monitoring/components/dashboard_panel.vue b/app/assets/javascripts/monitoring/components/dashboard_panel.vue
index b786d015f3b..446c6b52602 100644
--- a/app/assets/javascripts/monitoring/components/dashboard_panel.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard_panel.vue
@@ -404,21 +404,16 @@ export default {
-->
<gl-dropdown
v-gl-tooltip
+ icon="ellipsis_v"
+ :text="__('More actions')"
+ :text-sr-only="true"
toggle-class="gl-px-3!"
no-caret
data-qa-selector="prometheus_widgets_dropdown"
right
:title="__('More actions')"
>
- <template #button-content>
- <gl-icon class="gl-mr-0!" name="ellipsis_v" />
- </template>
- <gl-dropdown-item
- v-if="expandBtnAvailable"
- ref="expandBtn"
- :href="clipboardText"
- @click.prevent="onExpand"
- >
+ <gl-dropdown-item v-if="expandBtnAvailable" ref="expandBtn" @click.prevent="onExpand">
{{ s__('Metrics|Expand panel') }}
</gl-dropdown-item>
<gl-dropdown-item
diff --git a/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue b/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue
index b7832ca679c..55179947756 100644
--- a/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue
+++ b/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue
@@ -55,12 +55,13 @@ export default {
},
getUpdateVariables(dropdownLabels) {
const currentLabelIds = this.selectedLabels.map((label) => label.id);
- const userAddedLabelIds = dropdownLabels
- .filter((label) => label.set)
- .map((label) => label.id);
- const userRemovedLabelIds = dropdownLabels
- .filter((label) => !label.set)
- .map((label) => label.id);
+ const dropdownLabelIds = dropdownLabels.map((label) => label.id);
+ const userAddedLabelIds = this.glFeatures.labelsWidget
+ ? difference(dropdownLabelIds, currentLabelIds)
+ : dropdownLabels.filter((label) => label.set).map((label) => label.id);
+ const userRemovedLabelIds = this.glFeatures.labelsWidget
+ ? difference(currentLabelIds, dropdownLabelIds)
+ : dropdownLabels.filter((label) => !label.set).map((label) => label.id);
const labelIds = difference(union(currentLabelIds, userAddedLabelIds), userRemovedLabelIds);
@@ -155,7 +156,7 @@ export default {
:labels-manage-path="labelsManagePath"
:labels-select-in-progress="isLabelsSelectInProgress"
:selected-labels="selectedLabels"
- :variant="$options.sidebar"
+ :variant="$options.variant"
data-qa-selector="labels_block"
@onDropdownClose="handleDropdownClose"
@onLabelRemove="handleLabelRemove"
diff --git a/app/assets/javascripts/sidebar/mount_sidebar.js b/app/assets/javascripts/sidebar/mount_sidebar.js
index 8837f3601e4..031472a7d20 100644
--- a/app/assets/javascripts/sidebar/mount_sidebar.js
+++ b/app/assets/javascripts/sidebar/mount_sidebar.js
@@ -24,6 +24,7 @@ import SidebarDropdownWidget from '~/sidebar/components/sidebar_dropdown_widget.
import SidebarTodoWidget from '~/sidebar/components/todo_toggle/sidebar_todo_widget.vue';
import { apolloProvider } from '~/sidebar/graphql';
import trackShowInviteMemberLink from '~/sidebar/track_invite_members';
+import { DropdownVariant } from '~/vue_shared/components/sidebar/labels_select_vue/constants';
import Translate from '../vue_shared/translate';
import SidebarAssignees from './components/assignees/sidebar_assignees.vue';
import CopyEmailToClipboard from './components/copy_email_to_clipboard.vue';
@@ -256,6 +257,7 @@ export function mountSidebarLabels() {
allowLabelEdit: parseBoolean(el.dataset.canEdit),
allowScopedLabels: parseBoolean(el.dataset.allowScopedLabels),
initiallySelectedLabels: JSON.parse(el.dataset.selectedLabels),
+ variant: DropdownVariant.Sidebar,
},
render: (createElement) => createElement(SidebarLabels),
});
diff --git a/app/assets/javascripts/tracking/constants.js b/app/assets/javascripts/tracking/constants.js
index dfca633dc24..598111e4086 100644
--- a/app/assets/javascripts/tracking/constants.js
+++ b/app/assets/javascripts/tracking/constants.js
@@ -18,3 +18,9 @@ export const DEFAULT_SNOWPLOW_OPTIONS = {
fields: { allow: [] },
},
};
+
+export const ACTION_ATTR_SELECTOR = '[data-track-action]';
+export const LOAD_ACTION_ATTR_SELECTOR = '[data-track-action="render"]';
+
+export const DEPRECATED_EVENT_ATTR_SELECTOR = '[data-track-event]';
+export const DEPRECATED_LOAD_EVENT_ATTR_SELECTOR = '[data-track-event="render"]';
diff --git a/app/assets/javascripts/tracking/tracking.js b/app/assets/javascripts/tracking/tracking.js
index 7ae3a8cd834..a1f745bc172 100644
--- a/app/assets/javascripts/tracking/tracking.js
+++ b/app/assets/javascripts/tracking/tracking.js
@@ -1,3 +1,4 @@
+import { LOAD_ACTION_ATTR_SELECTOR, DEPRECATED_LOAD_EVENT_ATTR_SELECTOR } from './constants';
import { dispatchSnowplowEvent } from './dispatch_snowplow_event';
import getStandardContext from './get_standard_context';
import { getEventHandlers, createEventPayload, renameKey, addExperimentContext } from './utils';
@@ -98,7 +99,7 @@ export default class Tracking {
}
const loadEvents = parent.querySelectorAll(
- '[data-track-action="render"], [data-track-event="render"]',
+ `${LOAD_ACTION_ATTR_SELECTOR}, ${DEPRECATED_LOAD_EVENT_ATTR_SELECTOR}`,
);
loadEvents.forEach((element) => {
diff --git a/app/assets/javascripts/tracking/utils.js b/app/assets/javascripts/tracking/utils.js
index 3647280c41a..1189b2168ad 100644
--- a/app/assets/javascripts/tracking/utils.js
+++ b/app/assets/javascripts/tracking/utils.js
@@ -1,6 +1,12 @@
import { omitBy, isUndefined } from 'lodash';
import { TRACKING_CONTEXT_SCHEMA } from '~/experimentation/constants';
import { getExperimentData } from '~/experimentation/utils';
+import {
+ ACTION_ATTR_SELECTOR,
+ LOAD_ACTION_ATTR_SELECTOR,
+ DEPRECATED_EVENT_ATTR_SELECTOR,
+ DEPRECATED_LOAD_EVENT_ATTR_SELECTOR,
+} from './constants';
export const addExperimentContext = (opts) => {
const { experiment, ...options } = opts;
@@ -65,7 +71,9 @@ export const createEventPayload = (el, { suffix = '' } = {}) => {
};
export const eventHandler = (e, func, opts = {}) => {
- const el = e.target.closest('[data-track-event], [data-track-action]');
+ const actionSelector = `${ACTION_ATTR_SELECTOR}:not(${LOAD_ACTION_ATTR_SELECTOR})`;
+ const deprecatedEventSelector = `${DEPRECATED_EVENT_ATTR_SELECTOR}:not(${DEPRECATED_LOAD_EVENT_ATTR_SELECTOR})`;
+ const el = e.target.closest(`${actionSelector}, ${deprecatedEventSelector}`);
if (!el) {
return;
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue
index 1f0704f7308..6694e349b6e 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue
@@ -21,9 +21,29 @@ export default {
type: String,
required: true,
},
+ selectedLabels: {
+ type: Array,
+ required: true,
+ },
+ allowMultiselect: {
+ type: Boolean,
+ required: true,
+ },
+ labelsListTitle: {
+ type: String,
+ required: true,
+ },
+ footerCreateLabelTitle: {
+ type: String,
+ required: true,
+ },
+ footerManageLabelTitle: {
+ type: String,
+ required: true,
+ },
},
computed: {
- ...mapState(['showDropdownContentsCreateView', 'labelsListTitle']),
+ ...mapState(['showDropdownContentsCreateView']),
...mapGetters(['isDropdownVariantSidebar', 'isDropdownVariantEmbedded']),
dropdownContentsView() {
if (this.showDropdownContentsCreateView) {
@@ -75,6 +95,16 @@ export default {
@click="toggleDropdownContents"
/>
</div>
- <component :is="dropdownContentsView" @hideCreateView="toggleDropdownContentsCreateView" />
+ <component
+ :is="dropdownContentsView"
+ :selected-labels="selectedLabels"
+ :allow-multiselect="allowMultiselect"
+ :labels-list-title="labelsListTitle"
+ :footer-create-label-title="footerCreateLabelTitle"
+ :footer-manage-label-title="footerManageLabelTitle"
+ @hideCreateView="toggleDropdownContentsCreateView"
+ @closeDropdown="$emit('closeDropdown', $event)"
+ @toggleDropdownContentsCreateView="toggleDropdownContentsCreateView"
+ />
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue
index bff34743344..ffa37424c2c 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue
@@ -1,38 +1,91 @@
<script>
-import { GlIntersectionObserver, GlLoadingIcon, GlSearchBoxByType, GlLink } from '@gitlab/ui';
+import { GlLoadingIcon, GlSearchBoxByType, GlLink } from '@gitlab/ui';
import fuzzaldrinPlus from 'fuzzaldrin-plus';
-import { mapState, mapGetters, mapActions } from 'vuex';
-
+import { debounce } from 'lodash';
+import createFlash from '~/flash';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
import { UP_KEY_CODE, DOWN_KEY_CODE, ENTER_KEY_CODE, ESC_KEY_CODE } from '~/lib/utils/keycodes';
-
+import { __ } from '~/locale';
+import { DropdownVariant } from './constants';
+import projectLabelsQuery from './graphql/project_labels.query.graphql';
import LabelItem from './label_item.vue';
export default {
components: {
- GlIntersectionObserver,
GlLoadingIcon,
GlSearchBoxByType,
GlLink,
LabelItem,
},
+ inject: ['projectPath', 'allowLabelCreate', 'labelsManagePath', 'variant'],
+ props: {
+ selectedLabels: {
+ type: Array,
+ required: true,
+ },
+ allowMultiselect: {
+ type: Boolean,
+ required: true,
+ },
+ labelsListTitle: {
+ type: String,
+ required: true,
+ },
+ footerCreateLabelTitle: {
+ type: String,
+ required: true,
+ },
+ footerManageLabelTitle: {
+ type: String,
+ required: true,
+ },
+ },
data() {
return {
searchKey: '',
+ labels: [],
currentHighlightItem: -1,
+ localSelectedLabels: [...this.selectedLabels],
};
},
+ apollo: {
+ labels: {
+ query: projectLabelsQuery,
+ variables() {
+ return {
+ fullPath: this.projectPath,
+ searchTerm: this.searchKey,
+ };
+ },
+ skip() {
+ return this.searchKey.length === 1;
+ },
+ update: (data) => data.workspace?.labels?.nodes || [],
+ async result() {
+ if (this.$refs.searchInput) {
+ await this.$nextTick();
+ this.$refs.searchInput.focusInput();
+ }
+ },
+ error() {
+ createFlash({ message: __('Error fetching labels.') });
+ },
+ },
+ },
computed: {
- ...mapState([
- 'allowLabelCreate',
- 'allowMultiselect',
- 'labelsManagePath',
- 'labels',
- 'labelsFetchInProgress',
- 'labelsListTitle',
- 'footerCreateLabelTitle',
- 'footerManageLabelTitle',
- ]),
- ...mapGetters(['selectedLabelsList', 'isDropdownVariantSidebar', 'isDropdownVariantEmbedded']),
+ isDropdownVariantSidebar() {
+ return this.variant === DropdownVariant.Sidebar;
+ },
+ isDropdownVariantEmbedded() {
+ return this.variant === DropdownVariant.Embedded;
+ },
+ labelsFetchInProgress() {
+ return this.$apollo.queries.labels.loading;
+ },
+ localSelectedLabelsIds() {
+ return this.localSelectedLabels.map((label) => label.id);
+ },
visibleLabels() {
if (this.searchKey) {
return fuzzaldrinPlus.filter(this.labels, this.searchKey, {
@@ -55,17 +108,16 @@ export default {
}
},
},
+ created() {
+ this.debouncedSearchKeyUpdate = debounce(this.setSearchKey, DEFAULT_DEBOUNCE_AND_THROTTLE_MS);
+ },
+ beforeDestroy() {
+ this.$emit('closeDropdown', this.localSelectedLabels);
+ this.debouncedSearchKeyUpdate.cancel();
+ },
methods: {
- ...mapActions([
- 'toggleDropdownContents',
- 'toggleDropdownContentsCreateView',
- 'fetchLabels',
- 'receiveLabelsSuccess',
- 'updateSelectedLabels',
- 'toggleDropdownContents',
- ]),
isLabelSelected(label) {
- return this.selectedLabelsList.includes(label.id);
+ return this.localSelectedLabelsIds.includes(getIdFromGraphQLId(label.id));
},
/**
* This method scrolls item from dropdown into
@@ -86,23 +138,17 @@ export default {
}
}
},
- handleComponentAppear() {
- // We can avoid putting `catch` block here
- // as failure is handled within actions.js already.
- return this.fetchLabels().then(() => {
- this.$refs.searchInput.focusInput();
- });
- },
- /**
- * We want to remove loaded labels to ensure component
- * fetches fresh set of labels every time when shown.
- */
- handleComponentDisappear() {
- this.receiveLabelsSuccess([]);
- },
- handleCreateLabelClick() {
- this.receiveLabelsSuccess([]);
- this.toggleDropdownContentsCreateView();
+ updateSelectedLabels(label) {
+ if (this.isLabelSelected(label)) {
+ this.localSelectedLabels = this.localSelectedLabels.filter(
+ ({ id }) => id !== getIdFromGraphQLId(label.id),
+ );
+ } else {
+ this.localSelectedLabels.push({
+ ...label,
+ id: getIdFromGraphQLId(label.id),
+ });
+ }
},
/**
* This method enables keyboard navigation support for
@@ -117,10 +163,10 @@ export default {
) {
this.currentHighlightItem += 1;
} else if (e.keyCode === ENTER_KEY_CODE && this.currentHighlightItem > -1) {
- this.updateSelectedLabels([this.visibleLabels[this.currentHighlightItem]]);
+ this.updateSelectedLabels(this.visibleLabels[this.currentHighlightItem]);
this.searchKey = '';
} else if (e.keyCode === ESC_KEY_CODE) {
- this.toggleDropdownContents();
+ this.$emit('closeDropdown', this.localSelectedLabels);
}
if (e.keyCode !== ESC_KEY_CODE) {
@@ -132,68 +178,82 @@ export default {
}
},
handleLabelClick(label) {
- this.updateSelectedLabels([label]);
- if (!this.allowMultiselect) this.toggleDropdownContents();
+ this.updateSelectedLabels(label);
+ if (!this.allowMultiselect) {
+ this.$emit('closeDropdown', this.localSelectedLabels);
+ }
+ },
+ setSearchKey(value) {
+ this.searchKey = value;
},
},
};
</script>
<template>
- <gl-intersection-observer @appear="handleComponentAppear" @disappear="handleComponentDisappear">
- <div class="labels-select-contents-list js-labels-list" @keydown="handleKeyDown">
- <div class="dropdown-input" @click.stop="() => {}">
- <gl-search-box-by-type
- ref="searchInput"
- v-model="searchKey"
- :disabled="labelsFetchInProgress"
- data-qa-selector="dropdown_input_field"
- />
- </div>
- <div ref="labelsListContainer" class="dropdown-content" data-testid="dropdown-content">
- <gl-loading-icon
- v-if="labelsFetchInProgress"
- class="labels-fetch-loading gl-align-items-center w-100 h-100"
- size="md"
+ <div
+ class="labels-select-contents-list js-labels-list"
+ data-testid="dropdown-wrapper"
+ @keydown="handleKeyDown"
+ >
+ <div class="dropdown-input" @click.stop="() => {}">
+ <gl-search-box-by-type
+ ref="searchInput"
+ :value="searchKey"
+ :disabled="labelsFetchInProgress"
+ data-qa-selector="dropdown_input_field"
+ data-testid="dropdown-input-field"
+ @input="debouncedSearchKeyUpdate"
+ />
+ </div>
+ <div ref="labelsListContainer" class="dropdown-content" data-testid="dropdown-content">
+ <gl-loading-icon
+ v-if="labelsFetchInProgress"
+ class="labels-fetch-loading gl-align-items-center gl-w-full gl-h-full"
+ size="md"
+ />
+ <ul v-else class="list-unstyled gl-mb-0 gl-word-break-word" data-testid="labels-list">
+ <label-item
+ v-for="(label, index) in visibleLabels"
+ :key="label.id"
+ :label="label"
+ :is-label-set="isLabelSelected(label)"
+ :highlight="index === currentHighlightItem"
+ @clickLabel="handleLabelClick(label)"
/>
- <ul v-else class="list-unstyled gl-mb-0 gl-word-break-word">
- <label-item
- v-for="(label, index) in visibleLabels"
- :key="label.id"
- :label="label"
- :is-label-set="label.set"
- :highlight="index === currentHighlightItem"
- @clickLabel="handleLabelClick(label)"
- />
- <li v-show="showNoMatchingResultsMessage" class="gl-p-3 gl-text-center">
- {{ __('No matching results') }}
- </li>
- </ul>
- </div>
- <div
- v-if="isDropdownVariantSidebar || isDropdownVariantEmbedded"
- class="dropdown-footer"
- data-testid="dropdown-footer"
- >
- <ul class="list-unstyled">
- <li v-if="allowLabelCreate">
- <gl-link
- class="gl-display-flex w-100 flex-row text-break-word label-item"
- @click="handleCreateLabelClick"
- >
- {{ footerCreateLabelTitle }}
- </gl-link>
- </li>
- <li>
- <gl-link
- :href="labelsManagePath"
- class="gl-display-flex flex-row text-break-word label-item"
- >
- {{ footerManageLabelTitle }}
- </gl-link>
- </li>
- </ul>
- </div>
+ <li
+ v-show="showNoMatchingResultsMessage"
+ class="gl-p-3 gl-text-center"
+ data-testid="no-results"
+ >
+ {{ __('No matching results') }}
+ </li>
+ </ul>
+ </div>
+ <div
+ v-if="isDropdownVariantSidebar || isDropdownVariantEmbedded"
+ class="dropdown-footer"
+ data-testid="dropdown-footer"
+ >
+ <ul class="list-unstyled">
+ <li v-if="allowLabelCreate">
+ <gl-link
+ class="gl-display-flex gl-flex-direction-row gl-w-full gl-overflow-break-word label-item"
+ data-testid="create-label-button"
+ @click="$emit('toggleDropdownContentsCreateView')"
+ >
+ {{ footerCreateLabelTitle }}
+ </gl-link>
+ </li>
+ <li>
+ <gl-link
+ :href="labelsManagePath"
+ class="gl-display-flex gl-flex-direction-row gl-w-full gl-overflow-break-word label-item"
+ >
+ {{ footerManageLabelTitle }}
+ </gl-link>
+ </li>
+ </ul>
</div>
- </gl-intersection-observer>
+ </div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/project_labels.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/project_labels.query.graphql
new file mode 100644
index 00000000000..dc39220487d
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/project_labels.query.graphql
@@ -0,0 +1,12 @@
+query projectLabels($fullPath: ID!, $searchTerm: String) {
+ workspace: project(fullPath: $fullPath) {
+ labels(searchTerm: $searchTerm, includeAncestorGroups: true) {
+ nodes {
+ id
+ title
+ color
+ description
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue
index 6cc14def14b..0499dfe468f 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue
@@ -197,23 +197,6 @@ export default {
methods: {
...mapActions(['setInitialState', 'toggleDropdownContents']),
/**
- * This method differentiates between
- * dispatched actions and calls necessary method.
- */
- handleVuexActionDispatch(action, state) {
- if (
- action.type === 'toggleDropdownContents' &&
- !state.showDropdownButton &&
- !state.showDropdownContents
- ) {
- let filterFn = (label) => label.touched;
- if (this.isDropdownVariantEmbedded) {
- filterFn = (label) => label.set;
- }
- this.handleDropdownClose(state.labels.filter(filterFn));
- }
- },
- /**
* This method stores a mousedown event's target.
* Required by the click listener because the click
* event itself has no reference to this element.
@@ -276,6 +259,9 @@ export default {
handleDropdownClose(labels) {
// Only emit label updates if there are any labels to update
// on UI.
+ if (this.showDropdownContents) {
+ this.toggleDropdownContents();
+ }
if (labels.length) this.$emit('updateSelectedLabels', labels);
this.$emit('onDropdownClose');
},
@@ -332,8 +318,14 @@ export default {
<dropdown-contents
v-if="dropdownButtonVisible && showDropdownContents"
ref="dropdownContents"
+ :allow-multiselect="allowMultiselect"
+ :labels-list-title="labelsListTitle"
+ :footer-create-label-title="footerCreateLabelTitle"
+ :footer-manage-label-title="footerManageLabelTitle"
:render-on-top="!contentIsOnViewport"
:labels-create-title="labelsCreateTitle"
+ :selected-labels="selectedLabels"
+ @closeDropdown="handleDropdownClose"
/>
</template>
<template v-if="isDropdownVariantStandalone || isDropdownVariantEmbedded">
@@ -341,7 +333,13 @@ export default {
<dropdown-contents
v-if="dropdownButtonVisible && showDropdownContents"
ref="dropdownContents"
+ :allow-multiselect="allowMultiselect"
+ :labels-list-title="labelsListTitle"
+ :footer-create-label-title="footerCreateLabelTitle"
+ :footer-manage-label-title="footerManageLabelTitle"
:render-on-top="!contentIsOnViewport"
+ :selected-labels="selectedLabels"
+ @closeDropdown="handleDropdownClose"
/>
</template>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/actions.js b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/actions.js
index 935f020f559..b3d4a204a81 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/actions.js
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/actions.js
@@ -1,6 +1,3 @@
-import createFlash from '~/flash';
-import axios from '~/lib/utils/axios_utils';
-import { __ } from '~/locale';
import * as types from './mutation_types';
export const setInitialState = ({ commit }, props) => commit(types.SET_INITIAL_STATE, props);
@@ -11,24 +8,5 @@ export const toggleDropdownContents = ({ commit }) => commit(types.TOGGLE_DROPDO
export const toggleDropdownContentsCreateView = ({ commit }) =>
commit(types.TOGGLE_DROPDOWN_CONTENTS_CREATE_VIEW);
-export const requestLabels = ({ commit }) => commit(types.REQUEST_LABELS);
-export const receiveLabelsSuccess = ({ commit }, labels) =>
- commit(types.RECEIVE_SET_LABELS_SUCCESS, labels);
-export const receiveLabelsFailure = ({ commit }) => {
- commit(types.RECEIVE_SET_LABELS_FAILURE);
- createFlash({
- message: __('Error fetching labels.'),
- });
-};
-export const fetchLabels = ({ state, dispatch }) => {
- dispatch('requestLabels');
- return axios
- .get(state.labelsFetchPath)
- .then(({ data }) => {
- dispatch('receiveLabelsSuccess', data);
- })
- .catch(() => dispatch('receiveLabelsFailure'));
-};
-
export const updateSelectedLabels = ({ commit }, labels) =>
commit(types.UPDATE_SELECTED_LABELS, { labels });
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/mutation_types.js b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/mutation_types.js
index b8da7a90b36..bd71c3b85f1 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/mutation_types.js
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/mutation_types.js
@@ -1,13 +1,5 @@
export const SET_INITIAL_STATE = 'SET_INITIAL_STATE';
-export const REQUEST_LABELS = 'REQUEST_LABELS';
-export const RECEIVE_LABELS_SUCCESS = 'RECEIVE_LABELS_SUCCESS';
-export const RECEIVE_LABELS_FAILURE = 'RECEIVE_LABELS_FAILURE';
-
-export const REQUEST_SET_LABELS = 'REQUEST_SET_LABELS';
-export const RECEIVE_SET_LABELS_SUCCESS = 'RECEIVE_SET_LABELS_SUCCESS';
-export const RECEIVE_SET_LABELS_FAILURE = 'RECEIVE_SET_LABELS_FAILURE';
-
export const TOGGLE_DROPDOWN_BUTTON = 'TOGGLE_DROPDOWN_VISIBILITY';
export const TOGGLE_DROPDOWN_CONTENTS = 'TOGGLE_DROPDOWN_CONTENTS';
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/mutations.js b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/mutations.js
index 1c03d95f37b..45ec4d7ae04 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/mutations.js
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/mutations.js
@@ -26,27 +26,6 @@ export default {
[types.TOGGLE_DROPDOWN_CONTENTS_CREATE_VIEW](state) {
state.showDropdownContentsCreateView = !state.showDropdownContentsCreateView;
},
-
- [types.REQUEST_LABELS](state) {
- state.labelsFetchInProgress = true;
- },
- [types.RECEIVE_SET_LABELS_SUCCESS](state, labels) {
- // Iterate over every label and add a `set` prop
- // to determine whether it is already a part of
- // selectedLabels array.
- const selectedLabelIds = state.selectedLabels.map((label) => label.id);
- state.labelsFetchInProgress = false;
- state.labels = labels.reduce((allLabels, label) => {
- allLabels.push({
- ...label,
- set: selectedLabelIds.includes(label.id),
- });
- return allLabels;
- }, []);
- },
- [types.RECEIVE_SET_LABELS_FAILURE](state) {
- state.labelsFetchInProgress = false;
- },
[types.UPDATE_SELECTED_LABELS](state, { labels }) {
// Find the label to update from all the labels
// and change `set` prop value to represent their current state.
diff --git a/app/helpers/analytics/navbar_helper.rb b/app/helpers/analytics/navbar_helper.rb
deleted file mode 100644
index 091571ff15a..00000000000
--- a/app/helpers/analytics/navbar_helper.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-module Analytics
- module NavbarHelper
- class NavbarSubItem
- attr_reader :title, :path, :link, :link_to_options
-
- def initialize(title:, path:, link:, link_to_options: {})
- @title = title
- @path = path
- @link = link
- @link_to_options = link_to_options.merge(title: title)
- end
- end
-
- def group_analytics_navbar_links(group, current_user)
- []
- end
-
- private
-
- def navbar_sub_item(args)
- NavbarSubItem.new(**args)
- end
- end
-end
-
-Analytics::NavbarHelper.prepend_mod_with('Analytics::NavbarHelper')
diff --git a/app/models/remote_mirror.rb b/app/models/remote_mirror.rb
index 4937f2e862b..7f41f0907d5 100644
--- a/app/models/remote_mirror.rb
+++ b/app/models/remote_mirror.rb
@@ -22,8 +22,6 @@ class RemoteMirror < ApplicationRecord
validates :url, presence: true, public_url: { schemes: %w(ssh git http https), allow_blank: true, enforce_user: true }
- before_save :set_new_remote_name, if: :mirror_url_changed?
-
after_save :set_override_remote_mirror_available, unless: -> { Gitlab::CurrentSettings.current_application_settings.mirror_available }
after_update :reset_fields, if: :saved_change_to_mirror_url?
@@ -85,10 +83,6 @@ class RemoteMirror < ApplicationRecord
end
end
- def remote_name
- super || fallback_remote_name
- end
-
def update_failed?
update_status == 'failed'
end
@@ -100,7 +94,6 @@ class RemoteMirror < ApplicationRecord
def update_repository
Gitlab::Git::RemoteMirror.new(
project.repository.raw,
- remote_name,
remote_url,
**options_for_update
).update
@@ -268,12 +261,6 @@ class RemoteMirror < ApplicationRecord
super
end
- def fallback_remote_name
- return unless id
-
- "remote_mirror_#{id}"
- end
-
def recently_scheduled?
return false unless self.last_update_started_at
@@ -296,10 +283,6 @@ class RemoteMirror < ApplicationRecord
project.update(remote_mirror_available_overridden: enabled)
end
- def set_new_remote_name
- self.remote_name = "remote_mirror_#{SecureRandom.hex}"
- end
-
def mirror_url_changed?
url_changed? || attribute_changed?(:credentials)
end
diff --git a/app/services/git/branch_hooks_service.rb b/app/services/git/branch_hooks_service.rb
index a49b981c680..9738615c804 100644
--- a/app/services/git/branch_hooks_service.rb
+++ b/app/services/git/branch_hooks_service.rb
@@ -95,7 +95,7 @@ module Git
end
def track_ci_config_change_event
- return unless Gitlab::CurrentSettings.usage_ping_enabled?
+ return unless ::ServicePing::ServicePingSettings.enabled?
return unless default_branch?
commits_changing_ci_config.each do |commit|
diff --git a/app/services/service_ping/service_ping_settings.rb b/app/services/service_ping/service_ping_settings.rb
index 2b6535d89d1..6964210b1db 100644
--- a/app/services/service_ping/service_ping_settings.rb
+++ b/app/services/service_ping/service_ping_settings.rb
@@ -5,12 +5,10 @@ module ServicePing
extend self
def product_intelligence_enabled?
- pings_enabled? && !User.single_user&.requires_usage_stats_consent?
+ enabled? && !User.single_user&.requires_usage_stats_consent?
end
- private
-
- def pings_enabled?
+ def enabled?
::Gitlab::CurrentSettings.usage_ping_enabled?
end
end
diff --git a/app/views/layouts/nav/sidebar/_analytics_links.html.haml b/app/views/layouts/nav/sidebar/_analytics_links.html.haml
deleted file mode 100644
index 92a7b97203f..00000000000
--- a/app/views/layouts/nav/sidebar/_analytics_links.html.haml
+++ /dev/null
@@ -1,22 +0,0 @@
-- navbar_links = links.sort_by(&:title)
-- all_paths = navbar_links.map(&:path)
-- analytics_link = navbar_links.find { |link| link.title == _('Value stream') } || navbar_links.first
-
-- if navbar_links.any?
- = nav_link(path: all_paths) do
- = link_to analytics_link.link, {class: 'shortcuts-analytics has-sub-items', data: { qa_selector: 'analytics_anchor' } } do
- .nav-icon-container
- = sprite_icon('chart')
- %span.nav-item-name{ data: { qa_selector: 'analytics_link' } }
- = _('Analytics')
-
- %ul.sidebar-sub-level-items{ data: { qa_selector: 'analytics_sidebar_submenu' } }
- = nav_link(path: analytics_link.path, html_options: { class: "fly-out-top-item" } ) do
- = link_to analytics_link.link do
- %strong.fly-out-top-item-name
- = _('Analytics')
- %li.divider.fly-out-top-item
- - navbar_links.each do |menu_item|
- = nav_link(path: menu_item.path) do
- = link_to(menu_item.link, menu_item.link_to_options) do
- %span= menu_item.title
diff --git a/app/views/layouts/nav/sidebar/_group_menus.html.haml b/app/views/layouts/nav/sidebar/_group_menus.html.haml
index 2eea076f8db..8a6183f8efe 100644
--- a/app/views/layouts/nav/sidebar/_group_menus.html.haml
+++ b/app/views/layouts/nav/sidebar/_group_menus.html.haml
@@ -1,5 +1,3 @@
-= render 'layouts/nav/sidebar/analytics_links', links: group_analytics_navbar_links(@group, current_user)
-
- if group_sidebar_link?(:wiki)
= render 'layouts/nav/sidebar/wiki_link', wiki_url: @group.wiki.web_url