diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-10-31 15:11:01 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-10-31 15:11:01 +0300 |
commit | f52f8542b47c9e00ddf420abaf2263de168988f9 (patch) | |
tree | 568225882da5cc4deb746d2d4fc362c6076fb708 /app/assets | |
parent | 6a5ef9b75d38f39cd2a6a2392fadfbd3b966b884 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets')
13 files changed, 234 insertions, 14 deletions
diff --git a/app/assets/javascripts/blob/filepath_form/components/template_selector.vue b/app/assets/javascripts/blob/filepath_form/components/template_selector.vue index 51c69590796..379d5e38197 100644 --- a/app/assets/javascripts/blob/filepath_form/components/template_selector.vue +++ b/app/assets/javascripts/blob/filepath_form/components/template_selector.vue @@ -2,6 +2,7 @@ import { GlCollapsibleListbox } from '@gitlab/ui'; import SuggestGitlabCiYml from '~/blob/suggest_gitlab_ci_yml/components/popover.vue'; import { __ } from '~/locale'; +import { DEFAULT_CI_CONFIG_PATH, CI_CONFIG_PATH_EXTENSION } from '~/lib/utils/constants'; const templateSelectors = [ { @@ -12,8 +13,8 @@ const templateSelectors = [ }, { key: 'gitlab_ci_ymls', - name: '.gitlab-ci.yml', - pattern: /(.gitlab-ci.yml)/, + name: DEFAULT_CI_CONFIG_PATH, + pattern: CI_CONFIG_PATH_EXTENSION, type: 'gitlab_ci_ymls', }, { diff --git a/app/assets/javascripts/editor/constants.js b/app/assets/javascripts/editor/constants.js index 2be671ec7d8..2d50b7e4319 100644 --- a/app/assets/javascripts/editor/constants.js +++ b/app/assets/javascripts/editor/constants.js @@ -53,11 +53,6 @@ export const EDITOR_EXTENSION_STORE_IS_MISSING_ERROR = s__( export const EXTENSION_BASE_LINE_LINK_ANCHOR_CLASS = 'link-anchor'; export const EXTENSION_BASE_LINE_NUMBERS_CLASS = 'line-numbers'; -// For CI config schemas the filename must match -// '*.gitlab-ci.yml' regardless of project configuration. -// https://gitlab.com/gitlab-org/gitlab/-/issues/293641 -export const EXTENSION_CI_SCHEMA_FILE_NAME_MATCH = '.gitlab-ci.yml'; - export const EXTENSION_MARKDOWN_PREVIEW_PANEL_CLASS = 'md'; export const EXTENSION_MARKDOWN_PREVIEW_PANEL_PARENT_CLASS = 'source-editor-preview'; export const EXTENSION_MARKDOWN_PREVIEW_ACTION_ID = 'markdown-preview'; diff --git a/app/assets/javascripts/header.js b/app/assets/javascripts/header.js index 25a84d17379..095a2dc1324 100644 --- a/app/assets/javascripts/header.js +++ b/app/assets/javascripts/header.js @@ -1,3 +1,6 @@ +// TODO: Remove this with the removal of the old navigation. +// See https://gitlab.com/groups/gitlab-org/-/epics/11875. + import Vue from 'vue'; import NewNavToggle from '~/nav/components/new_nav_toggle.vue'; import { highCountTrim } from '~/lib/utils/text_utility'; diff --git a/app/assets/javascripts/ide/components/repo_editor.vue b/app/assets/javascripts/ide/components/repo_editor.vue index 137df9aa102..3b59fe86764 100644 --- a/app/assets/javascripts/ide/components/repo_editor.vue +++ b/app/assets/javascripts/ide/components/repo_editor.vue @@ -8,7 +8,6 @@ import { EDITOR_TYPE_CODE, EDITOR_CODE_INSTANCE_FN, EDITOR_DIFF_INSTANCE_FN, - EXTENSION_CI_SCHEMA_FILE_NAME_MATCH, } from '~/editor/constants'; import { SourceEditorExtension } from '~/editor/extensions/source_editor_extension_base'; import { EditorWebIdeExtension } from '~/editor/extensions/source_editor_webide_ext'; @@ -30,6 +29,7 @@ import { viewerInformationForPath } from '~/vue_shared/components/content_viewer import DiffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue'; import { markRaw } from '~/lib/utils/vue3compat/mark_raw'; import { readFileAsDataURL } from '~/lib/utils/file_utility'; +import { isDefaultCiConfig, hasCiConfigExtension } from '~/lib/utils/common_utils'; import { leftSidebarViews, @@ -152,8 +152,9 @@ export default { }, isCiConfigFile() { return ( - this.file.path === EXTENSION_CI_SCHEMA_FILE_NAME_MATCH && - this.editor?.getEditorType() === EDITOR_TYPE_CODE + // For CI config schemas the filename must match '*.gitlab-ci.yml' regardless of project configuration. + // https://gitlab.com/gitlab-org/gitlab/-/issues/293641 + hasCiConfigExtension(this.file.path) && this.editor?.getEditorType() === EDITOR_TYPE_CODE ); }, }, @@ -162,7 +163,7 @@ export default { handler() { this.stopWatchingCiYaml(); - if (this.file.name === '.gitlab-ci.yml') { + if (isDefaultCiConfig(this.file.name)) { this.startWatchingCiYaml(); } }, diff --git a/app/assets/javascripts/ide/lib/alerts/index.js b/app/assets/javascripts/ide/lib/alerts/index.js index c9db9779b1f..ac4eeb0386f 100644 --- a/app/assets/javascripts/ide/lib/alerts/index.js +++ b/app/assets/javascripts/ide/lib/alerts/index.js @@ -1,3 +1,4 @@ +import { isDefaultCiConfig } from '~/lib/utils/common_utils'; import { leftSidebarViews } from '../../constants'; import EnvironmentsMessage from './environments.vue'; @@ -6,7 +7,7 @@ const alerts = [ key: Symbol('ALERT_ENVIRONMENT'), show: (state, file) => state.currentActivityView === leftSidebarViews.commit.name && - file.path === '.gitlab-ci.yml' && + isDefaultCiConfig(file.path) && state.environmentsGuidanceAlertDetected && !state.environmentsGuidanceAlertDismissed, props: { variant: 'tip' }, diff --git a/app/assets/javascripts/ide/stores/modules/file_templates/getters.js b/app/assets/javascripts/ide/stores/modules/file_templates/getters.js index bf0d3ed337c..5681f6cdec5 100644 --- a/app/assets/javascripts/ide/stores/modules/file_templates/getters.js +++ b/app/assets/javascripts/ide/stores/modules/file_templates/getters.js @@ -1,9 +1,10 @@ import { __ } from '~/locale'; +import { DEFAULT_CI_CONFIG_PATH } from '~/lib/utils/constants'; import { leftSidebarViews } from '../../../constants'; export const templateTypes = () => [ { - name: '.gitlab-ci.yml', + name: DEFAULT_CI_CONFIG_PATH, key: 'gitlab_ci_ymls', }, { diff --git a/app/assets/javascripts/issues/issue.js b/app/assets/javascripts/issues/issue.js index 06bbcdc12ea..b83db65caa6 100644 --- a/app/assets/javascripts/issues/issue.js +++ b/app/assets/javascripts/issues/issue.js @@ -53,6 +53,8 @@ export default class Issue { $(document).trigger('issuable:change', isClosed); + // TODO: Remove this with the removal of the old navigation. + // See https://gitlab.com/groups/gitlab-org/-/epics/11875. let numProjectIssues = Number( projectIssuesCounter.first().text().trim().replace(/[^\d]/, ''), ); diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js index 7d16af003e4..27da2ac6ce1 100644 --- a/app/assets/javascripts/lib/utils/common_utils.js +++ b/app/assets/javascripts/lib/utils/common_utils.js @@ -7,6 +7,7 @@ import $ from 'jquery'; import { isFunction, defer, escape, partial, toLower } from 'lodash'; import Cookies from '~/lib/utils/cookies'; import { SCOPED_LABEL_DELIMITER } from '~/sidebar/components/labels/labels_select_widget/constants'; +import { DEFAULT_CI_CONFIG_PATH, CI_CONFIG_PATH_EXTENSION } from '~/lib/utils/constants'; import { convertToCamelCase, convertToSnakeCase } from './text_utility'; import { isObject } from './type_utility'; import { getLocationHash } from './url_utility'; @@ -737,3 +738,17 @@ export const isCurrentUser = (userId) => { export const cloneWithoutReferences = (obj) => { return JSON.parse(JSON.stringify(obj)); }; + +/** + * Returns true if the given path is the default CI config path. + */ +export const isDefaultCiConfig = (path) => { + return path === DEFAULT_CI_CONFIG_PATH; +}; + +/** + * Returns true if the given path has the CI config path extension. + */ +export const hasCiConfigExtension = (path) => { + return CI_CONFIG_PATH_EXTENSION.test(path); +}; diff --git a/app/assets/javascripts/lib/utils/constants.js b/app/assets/javascripts/lib/utils/constants.js index da5fb831ae5..d9ac0abf7b3 100644 --- a/app/assets/javascripts/lib/utils/constants.js +++ b/app/assets/javascripts/lib/utils/constants.js @@ -23,3 +23,6 @@ export const BYTES_FORMAT_BYTES = 'B'; export const BYTES_FORMAT_KIB = 'KiB'; export const BYTES_FORMAT_MIB = 'MiB'; export const BYTES_FORMAT_GIB = 'GiB'; + +export const DEFAULT_CI_CONFIG_PATH = '.gitlab-ci.yml'; +export const CI_CONFIG_PATH_EXTENSION = /(\.gitlab-ci\.yml)/; diff --git a/app/assets/javascripts/pipeline_wizard/pipeline_wizard.vue b/app/assets/javascripts/pipeline_wizard/pipeline_wizard.vue index 5a93de3b1be..3676ba96254 100644 --- a/app/assets/javascripts/pipeline_wizard/pipeline_wizard.vue +++ b/app/assets/javascripts/pipeline_wizard/pipeline_wizard.vue @@ -1,5 +1,6 @@ <script> import { parseDocument } from 'yaml'; +import { DEFAULT_CI_CONFIG_PATH } from '~/lib/utils/constants'; import WizardWrapper from './components/wrapper.vue'; export default { @@ -23,7 +24,7 @@ export default { defaultFilename: { type: String, required: false, - default: '.gitlab-ci.yml', + default: DEFAULT_CI_CONFIG_PATH, }, }, computed: { diff --git a/app/assets/javascripts/vue_shared/components/list_selector/constants.js b/app/assets/javascripts/vue_shared/components/list_selector/constants.js new file mode 100644 index 00000000000..c9db79581d1 --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/list_selector/constants.js @@ -0,0 +1,7 @@ +import { __ } from '~/locale'; + +// Note, we can extend this config in future to make the component work in other contexts +// https://gitlab.com/gitlab-org/gitlab/-/issues/428865 +export const CONFIG = { + users: { title: __('Users'), icon: 'user', filterKey: 'username' }, +}; diff --git a/app/assets/javascripts/vue_shared/components/list_selector/index.vue b/app/assets/javascripts/vue_shared/components/list_selector/index.vue new file mode 100644 index 00000000000..237369f5900 --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/list_selector/index.vue @@ -0,0 +1,135 @@ +<script> +import { GlCard, GlIcon, GlCollapsibleListbox, GlSearchBoxByType } from '@gitlab/ui'; +import usersAutocompleteQuery from '~/graphql_shared/queries/users_autocomplete.query.graphql'; +import User from './user.vue'; +import { CONFIG } from './constants'; + +export default { + name: 'ListSelector', + components: { + GlCard, + GlIcon, + GlSearchBoxByType, + GlCollapsibleListbox, + User, + }, + props: { + title: { + type: String, + required: true, + }, + type: { + type: String, + required: true, + }, + selectedItems: { + type: Array, + required: false, + default: () => [], + }, + projectPath: { + type: String, + required: false, + default: null, + }, + }, + data() { + return { + searchValue: '', + isProject: true, // TODO: implement a way to distinguish between project/group + selected: [], + items: [], + }; + }, + computed: { + config() { + return CONFIG[this.type]; + }, + searchItems() { + return ( + this.items?.map((item) => ({ + value: item.username, + text: item.name, + ...item, + })) || [] + ); + }, + component() { + // Note, we can extend this for the component to support other contexts + // https://gitlab.com/gitlab-org/gitlab/-/issues/428865 + return User; + }, + }, + methods: { + async handleSearchInput(search) { + this.$refs.results.open(); + this.items = await this.fetchUsersBySearchTerm(search); + }, + fetchUsersBySearchTerm(search) { + const namespace = this.isProject ? 'project' : 'group'; + return this.$apollo + .query({ + query: usersAutocompleteQuery, + variables: { fullPath: this.projectPath, search, isProject: this.isProject }, + }) + .then(({ data }) => data[namespace]?.autocompleteUsers); + }, + getItemByKey(key) { + return this.searchItems.find((item) => item[this.config.filterKey] === key); + }, + handleSelectItem(key) { + this.$emit('select', this.getItemByKey(key)); + }, + handleDeleteItem(key) { + this.$emit('delete', key); + }, + }, +}; +</script> + +<template> + <gl-card header-class="gl-new-card-header gl-border-none" body-class="gl-card-footer"> + <template #header + ><strong + >{{ title }} + <span class="gl-text-gray-500" + ><gl-icon :name="config.icon" /> {{ selectedItems.length }}</span + ></strong + ></template + > + + <gl-collapsible-listbox + ref="results" + v-model="selected" + class="list-selector gl-mb-4 gl-display-block" + :items="searchItems" + multiple + @shown="$refs.search.focusInput()" + > + <template #toggle> + <gl-search-box-by-type + ref="search" + v-model="searchValue" + autofocus + debounce="500" + @input="handleSearchInput" + /> + </template> + + <template #list-item="{ item }"> + <component :is="component" :data="item" @select="handleSelectItem" /> + </template> + </gl-collapsible-listbox> + + <component + :is="component" + v-for="(item, index) of selectedItems" + :key="index" + :class="{ 'gl-border-t': index > 0 }" + class="gl-p-3" + :data="item" + can-delete + @delete="handleDeleteItem" + /> + </gl-card> +</template> diff --git a/app/assets/javascripts/vue_shared/components/list_selector/user.vue b/app/assets/javascripts/vue_shared/components/list_selector/user.vue new file mode 100644 index 00000000000..fdbc767db81 --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/list_selector/user.vue @@ -0,0 +1,55 @@ +<script> +import { GlAvatar, GlButton } from '@gitlab/ui'; +import { sprintf, __ } from '~/locale'; + +export default { + name: 'UserItem', + components: { + GlAvatar, + GlButton, + }, + props: { + data: { + type: Object, + required: true, + }, + canDelete: { + type: Boolean, + required: false, + default: false, + }, + }, + computed: { + deleteButtonLabel() { + return sprintf(__('Delete %{name}'), { name: this.name }); + }, + name() { + return this.data.name; + }, + username() { + return this.data.username; + }, + avatarUrl() { + return this.data.avatarUrl; + }, + }, +}; +</script> + +<template> + <span class="gl-display-flex gl-align-items-center gl-gap-3" @click="$emit('select', username)"> + <gl-avatar :alt="name" :size="32" :src="avatarUrl" /> + <span class="gl-display-flex gl-flex-direction-column gl-flex-grow-1"> + <span class="gl-font-weight-bold">{{ name }}</span> + <span class="gl-text-gray-600">@{{ username }}</span> + </span> + + <gl-button + v-if="canDelete" + icon="remove" + :aria-label="deleteButtonLabel" + category="tertiary" + @click="$emit('delete', username)" + /> + </span> +</template> |