Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2024-06-07 18:15:36 +00:00
parent 77b22b2119
commit db299d28dc
47 changed files with 389 additions and 81 deletions

View File

@ -146,6 +146,12 @@ rules:
methods: 'sanitize'
# This rule will be enabled later.
unicorn/no-array-callback-reference: off
vue/no-undef-components:
- error
- ignorePatterns:
- '^router-link$'
- '^router-view$'
- '^gl-emoji$'
overrides:
- files:
- '{,ee/,jh/}spec/frontend*/**/*'

View File

@ -12,6 +12,7 @@ import {
flashAnimationDuration,
listsQuery,
updateListQueries,
ListType,
} from 'ee_else_ce/boards/constants';
import { calculateNewPosition } from 'ee_else_ce/boards/boards_util';
import { setError } from '../graphql/cache_updates';
@ -99,6 +100,14 @@ export default {
return this.canDragColumns ? options : {};
},
backlogListId() {
const backlogList = this.boardListsToUse.find((list) => list.listType === ListType.backlog);
return backlogList?.id || '';
},
closedListId() {
const closedList = this.boardListsToUse.find((list) => list.listType === ListType.closed);
return closedList?.id || '';
},
},
methods: {
afterFormEnters() {
@ -275,8 +284,18 @@ export default {
</div>
</epics-swimlanes>
<board-content-sidebar v-if="isIssueBoard" data-testid="issue-boards-sidebar" />
<board-content-sidebar
v-if="isIssueBoard"
:backlog-list-id="backlogListId"
:closed-list-id="closedListId"
data-testid="issue-boards-sidebar"
/>
<epic-board-content-sidebar v-else-if="isEpicBoard" data-testid="epic-boards-sidebar" />
<epic-board-content-sidebar
v-else-if="isEpicBoard"
:backlog-list-id="backlogListId"
:closed-list-id="closedListId"
data-testid="epic-boards-sidebar"
/>
</div>
</template>

View File

@ -1,13 +1,14 @@
<script>
import { GlDrawer } from '@gitlab/ui';
import { MountingPortal } from 'portal-vue';
import { union } from 'lodash';
import SidebarDropdownWidget from 'ee_else_ce/sidebar/components/sidebar_dropdown_widget.vue';
import activeBoardItemQuery from 'ee_else_ce/boards/graphql/client/active_board_item.query.graphql';
import setActiveBoardItemMutation from 'ee_else_ce/boards/graphql/client/set_active_board_item.mutation.graphql';
import { __, s__, sprintf } from '~/locale';
import SidebarTimeTracker from '~/sidebar/components/time_tracking/time_tracker.vue';
import BoardSidebarTitle from '~/boards/components/sidebar/board_sidebar_title.vue';
import { INCIDENT } from '~/boards/constants';
import { INCIDENT, ListType } from '~/boards/constants';
import { TYPE_ISSUE, WORKSPACE_GROUP, WORKSPACE_PROJECT } from '~/issues/constants';
import SidebarAssigneesWidget from '~/sidebar/components/assignees/sidebar_assignees_widget.vue';
import SidebarConfidentialityWidget from '~/sidebar/components/confidential/sidebar_confidentiality_widget.vue';
@ -17,9 +18,10 @@ import SidebarSubscriptionsWidget from '~/sidebar/components/subscriptions/sideb
import SidebarTodoWidget from '~/sidebar/components/todo_toggle/sidebar_todo_widget.vue';
import SidebarLabelsWidget from '~/sidebar/components/labels/labels_select_widget/labels_select_root.vue';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { setError, updateListWeightCache } from '../graphql/cache_updates';
import { setError, updateListWeightCache, identifyAffectedLists } from '../graphql/cache_updates';
export default {
ListType,
components: {
GlDrawer,
BoardSidebarTitle,
@ -77,6 +79,22 @@ export default {
},
},
inheritAttrs: false,
props: {
backlogListId: {
type: String,
required: true,
},
closedListId: {
type: String,
required: true,
},
},
data() {
return {
affectedListTypes: [],
updatedAttributeIds: [],
};
},
apollo: {
activeBoardCard: {
query: activeBoardItemQuery,
@ -156,21 +174,87 @@ export default {
this.iterationFeatureAvailable && !this.isIncidentSidebar && this.activeBoardIssuable.id
);
},
apolloClient() {
return this.$apollo.provider.clients.defaultClient;
},
},
methods: {
handleClose() {
this.$apollo.mutate({
async handleClose() {
const item = this.activeBoardCard;
await this.$apollo.mutate({
mutation: setActiveBoardItemMutation,
variables: {
boardItem: null,
listId: null,
},
});
if (item.listId !== this.closedListId) {
await this.refetchAffectedLists(item);
}
this.affectedListTypes = [];
this.updatedAttributeIds = [];
},
updateListTotalWeight({ weight }) {
const { cache } = this.$apollo.provider.clients.defaultClient;
const { cache } = this.apolloClient;
updateListWeightCache({ weight, listId: this.activeBoardCard.listId, cache });
},
updateAffectedLists({ listType, attribute }) {
if (!this.affectedListTypes.includes(listType)) {
this.affectedListTypes.push(listType);
}
if (Array.isArray(attribute)) {
this.updatedAttributeIds = union(
this.updatedAttributeIds,
attribute.map(({ id }) => id),
);
} else {
const attr = attribute.issuableSetAttribute.issuable.attribute;
if (attr) {
this.updatedAttributeIds.push(attr.id);
}
}
},
refetchAffectedLists(item) {
if (!this.affectedListTypes.length) {
return;
}
const affectedLists = identifyAffectedLists({
client: this.apolloClient,
item,
issuableType: this.issuableType,
affectedListTypes: this.affectedListTypes,
updatedAttributeIds: this.updatedAttributeIds,
});
if (this.backlogListId && !affectedLists.includes(this.backlogListId)) {
affectedLists.push(this.backlogListId);
}
this.apolloClient.refetchQueries({
updateCache(cache) {
affectedLists.forEach((listId) => {
cache.evict({
id: cache.identify({
__typename: 'BoardList',
id: listId,
}),
fieldName: 'issues',
});
cache.evict({
id: cache.identify({
__typename: 'BoardList',
id: listId,
}),
fieldName: 'issuesCount',
});
});
},
});
},
},
};
</script>
@ -205,6 +289,12 @@ export default {
:initial-assignees="activeBoardIssuable.assignees"
:allow-multiple-assignees="multipleAssigneesFeatureAvailable"
:editable="canUpdate"
@assignees-updated="
updateAffectedLists({
listType: $options.ListType.assignee,
attribute: $event.assignees,
})
"
/>
<sidebar-dropdown-widget
v-if="showEpicSidebarDropdownWidget"
@ -229,6 +319,9 @@ export default {
:issuable-type="issuableType"
:issue-id="activeBoardIssuable.id"
data-testid="sidebar-milestones"
@attribute-updated="
updateAffectedLists({ listType: $options.ListType.milestone, attribute: $event })
"
/>
<sidebar-iteration-widget
v-if="showIterationSidebarDropdownWidget"
@ -240,6 +333,9 @@ export default {
:issuable-type="issuableType"
class="gl-mt-5"
data-testid="iteration-edit"
@iteration-updated="
updateAffectedLists({ listType: $options.ListType.iteration, attribute: $event })
"
/>
</div>
<sidebar-time-tracker
@ -271,6 +367,9 @@ export default {
workspace-type="project"
:issuable-type="issuableType"
:label-create-type="labelType"
@updateSelectedLabels="
updateAffectedLists({ listType: $options.ListType.label, attribute: $event.labels })
"
>
{{ __('None') }}
</sidebar-labels-widget>

View File

@ -1,9 +1,11 @@
import produce from 'immer';
import { toNumber } from 'lodash';
import { toNumber, uniq } from 'lodash';
import * as Sentry from '~/sentry/sentry_browser_wrapper';
import { defaultClient } from '~/graphql_shared/issuable_client';
import listQuery from 'ee_else_ce/boards/graphql/board_lists_deferred.query.graphql';
import { listsDeferredQuery } from 'ee_else_ce/boards/constants';
import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
import { TYPE_ISSUE } from '~/issues/constants';
import setErrorMutation from './client/set_error.mutation.graphql';
@ -166,3 +168,48 @@ export function setError({ message, error, captureError = true }) {
Sentry.captureException(error);
}
}
export function identifyAffectedLists({
client,
item,
issuableType,
affectedListTypes,
updatedAttributeIds,
}) {
const allCache = client.cache.extract();
const listIdsToRefetch = [];
const type = capitalizeFirstCharacter(issuableType);
const typename = issuableType === TYPE_ISSUE ? 'BoardList' : 'EpicList';
Object.values(allCache).forEach((value) => {
const issuablesField = Object.keys(value).find((key) => key.includes(`${issuableType}s:`));
const issuables = value[issuablesField]?.nodes ?? [];
/* eslint-disable no-underscore-dangle */
if (value.__typename === typename) {
// We identify the id of the attribute that was updated. In Apollo Cache, entries are stored in the following format:
// UserCore:gid://gitlab/UserCore/1 (<type>:<global id>). We extract the id from the __ref field.
const attributeId =
value.assignee?.__ref.match(/UserCore:(.*)/)[1] ||
value.label?.__ref.match(/Label:(.*)/)[1] ||
value.milestone?.__ref.match(/Milestone:(.*)/)[1] ||
value.iteration?.__ref.match(/Iteration:(.*)/)[1];
// If the item is in the list, and lists of this type are affected, we need to refetch the list
if (issuables.length > 0) {
const issueExistsInList = issuables.some((i) => i.__ref === `${type}:${item.id}`);
if (issueExistsInList && affectedListTypes.includes(value.listType)) {
listIdsToRefetch.push(value.id);
}
}
// If the item is not in the list, but the list has the attribute from affected attributes list
// we need to refetch the list
if (updatedAttributeIds.includes(attributeId)) {
listIdsToRefetch.push(value.id);
}
}
/* eslint-enable no-underscore-dangle */
});
return uniq(listIdsToRefetch);
}

View File

@ -91,7 +91,7 @@ export default {
<template>
<li :class="{ 'js-toggle-container': collapsible }" class="commit">
<div
class="d-block d-sm-flex flex-row-reverse justify-content-between align-items-start flex-lg-row-reverse"
class="gl-block sm:gl-flex flex-row-reverse justify-content-between align-items-start flex-lg-row-reverse"
>
<div
class="commit-actions flex-row gl-hidden sm:gl-flex gl-align-items-center gl-flex-wrap justify-content-end"
@ -142,7 +142,9 @@ export default {
class="commit-row-message item-title"
></a>
<span class="commit-row-message d-block d-sm-none">&middot; {{ commit.short_id }}</span>
<span class="commit-row-message !gl-block sm:!gl-hidden"
>&middot; {{ commit.short_id }}</span
>
<gl-button
v-if="commit.description_html && collapsible"
@ -172,7 +174,7 @@ export default {
<pre
v-if="commit.description_html"
v-safe-html:[$options.safeHtmlConfig]="commitDescription"
:class="{ 'js-toggle-content': collapsible, 'd-block': !collapsible }"
:class="{ 'js-toggle-content': collapsible, '!gl-block': !collapsible }"
class="commit-row-description gl-mb-3 gl-text-body gl-white-space-pre-wrap"
></pre>
</div>

View File

@ -69,6 +69,7 @@ export default {
</gl-tab>
</gl-tabs>
<!-- eslint-disable-next-line vue/no-undef-components -->
<container
:is-loading="isLoading"
:environments="state.environments"

View File

@ -156,7 +156,7 @@ export default {
/>
<div
v-if="showSuggestions"
class="dropdown-menu d-block dropdown-menu-selectable dropdown-menu-full-width"
class="dropdown-menu !gl-block dropdown-menu-selectable dropdown-menu-full-width"
>
<div class="dropdown-content">
<ul v-if="results.length">

View File

@ -40,6 +40,7 @@ export default {
<template>
<ul class="groups-list group-list-tree gl-display-flex gl-flex-direction-column gl-m-0">
<!-- eslint-disable-next-line vue/no-undef-components -->
<group-item
v-for="(group, index) in groups"
:key="index"

View File

@ -281,6 +281,7 @@ export default {
</div>
</div>
</div>
<!-- eslint-disable-next-line vue/no-undef-components -->
<group-folder
v-if="group.isOpen && hasChildren"
:parent-group="group"

View File

@ -41,6 +41,7 @@ export default {
<template>
<div class="groups-list-tree-container" data-testid="groups-list-tree-container">
<!-- eslint-disable-next-line vue/no-undef-components -->
<group-folder :groups="groups" :action="action" />
<pagination-links
:change="change"

View File

@ -39,7 +39,7 @@ export default {
</span>
<span>
<strong> {{ item.name }} </strong>
<span class="ide-merge-request-project-path d-block mt-1">
<span class="ide-merge-request-project-path gl-block mt-1">
Updated <timeago :time="item.committedDate || ''" />
</span>
</span>

View File

@ -46,7 +46,7 @@ export default {
</span>
<span>
<strong> {{ item.title }} </strong>
<span class="ide-merge-request-project-path d-block mt-1"> {{ pathWithID }} </span>
<span class="ide-merge-request-project-path gl-block mt-1"> {{ pathWithID }} </span>
</span>
</a>
</template>

View File

@ -92,7 +92,7 @@ export default {
data-testid="assignee-link"
>
<span class="js-assignee-tooltip">
<span class="bold d-block">{{ s__('Label|Assignee') }}</span> {{ assignee.name }}
<span class="bold gl-block">{{ s__('Label|Assignee') }}</span> {{ assignee.name }}
<span v-if="assignee.username" class="text-white-50">@{{ assignee.username }}</span>
</span>
</user-avatar-link>

View File

@ -765,7 +765,7 @@ export default {
"
>
<template #link="{ content }">
<span class="d-block">
<span class="gl-display-block">
<gl-link :href="lfsObjectsRemovalHelpPath" target="_blank">
{{ content }}
</gl-link>

View File

@ -262,7 +262,7 @@ const bindEvents = () => {
const selectedTemplate = DEFAULT_PROJECT_TEMPLATES[value];
$selectedTemplateText.textContent = selectedTemplate.text;
const clone = document.querySelector(selectedTemplate.icon).cloneNode(true);
clone.classList.add('d-block');
clone.classList.add('gl-block');
$selectedIcon.append(clone);

View File

@ -451,12 +451,14 @@ export default {
</template>
</gl-sprintf>
<!-- eslint-disable-next-line vue/no-undef-components -->
<approval-rules-app
:is-mr-edit="false"
:is-branch-rules-edit="true"
@submitted="$apollo.queries.project.refetch()"
>
<template #rules>
<!-- eslint-disable-next-line vue/no-undef-components -->
<project-rules :is-branch-rules-edit="true" />
</template>
</approval-rules-app>

View File

@ -101,6 +101,9 @@ export default {
update(data) {
return data.workspace?.issuable;
},
skip() {
return !this.iid;
},
result({ data }) {
if (!data) {
return;

View File

@ -66,6 +66,9 @@ export default {
update(data) {
return data.workspace?.issuable?.confidential || false;
},
skip() {
return !this.iid;
},
result({ data }) {
if (!data) {
return;

View File

@ -87,6 +87,9 @@ export default {
iid: String(this.iid),
};
},
skip() {
return !this.iid;
},
update(data) {
return data.workspace?.issuable || {};
},

View File

@ -182,7 +182,7 @@ export default {
return issuableLabelsQueries[this.issuableType].issuableQuery;
},
skip() {
return !isDropdownVariantSidebar(this.variant);
return !isDropdownVariantSidebar(this.variant) || !this.iid;
},
variables() {
const queryVariables = {

View File

@ -43,6 +43,9 @@ export default {
update(data) {
return data.workspace?.issuable?.participants.nodes || [];
},
skip() {
return !this.iid;
},
error(error) {
this.$emit('fetch-error', {
message: this.$options.i18n.fetchingError,

View File

@ -118,6 +118,9 @@ export default {
this.hasCurrentAttribute = data?.workspace?.issuable.hasEpic;
}
},
skip() {
return !this.iid;
},
error(error) {
createAlert({
message: this.i18n.currentFetchError,

View File

@ -75,6 +75,9 @@ export default {
iid: String(this.iid),
};
},
skip() {
return !this.iid;
},
update(data) {
return data.workspace?.issuable?.subscribed || false;
},

View File

@ -62,6 +62,9 @@ export default {
iid: String(this.issuableIid),
};
},
skip() {
return !this.issuableIid;
},
update(data) {
return data.workspace?.issuable?.currentUserTodos.nodes[0]?.id;
},

View File

@ -45,7 +45,7 @@ export default {
return `${getCommitIconMap(this.file).icon}${suffix}`;
},
changedIconClass() {
return `${this.changedIcon} float-left d-block`;
return `${this.changedIcon} float-left gl-block`;
},
tooltipTitle() {
if (!this.showTooltip) {

View File

@ -33,5 +33,5 @@ export default {
class="code-block rounded code"
:class="$options.userColorScheme"
:style="styleObject"
><slot><code class="d-block">{{ code }}</code></slot></pre>
><slot><code class="gl-block">{{ code }}</code></slot></pre>
</template>

View File

@ -79,7 +79,7 @@ export default {
issuableColor: {
query: epicColorQuery,
skip() {
return !isDropdownVariantSidebar(this.variant);
return !isDropdownVariantSidebar(this.variant) || !this.iid;
},
variables() {
return {

View File

@ -44,7 +44,7 @@ $command-palette-spacing: px-to-rem(14px);
--super-sidebar-nav-item-current-bg: #{$t-gray-a-08};
--super-sidebar-nav-item-icon-color: #{$gray-500};
--super-sidebar-hr-mix-blend-mode: normal;
--super-sidebar-hr-mix-blend-mode: multiply;
.gl-dark & {
--super-sidebar-border-color: #{$t-white-a-08};
@ -61,6 +61,8 @@ $command-palette-spacing: px-to-rem(14px);
--super-sidebar-nav-item-active-bg: #{$t-white-a-16};
--super-sidebar-nav-item-current-bg: #{$t-white-a-08};
--super-sidebar-nav-item-icon-color: #{$gray-600};
--super-sidebar-hr-mix-blend-mode: screen;
}
}
@ -90,8 +92,6 @@ $command-palette-spacing: px-to-rem(14px);
--super-sidebar-user-bar-button-icon-color: #{$user-bar-button-icon-color};
--super-sidebar-user-bar-button-icon-hover-color: #{$user-bar-button-icon-color};
--super-sidebar-user-bar-button-icon-mix-blend-mode: screen;
--super-sidebar-hr-mix-blend-mode: multiply;
}
}

View File

@ -240,6 +240,7 @@ module WikiActions
# rubocop:disable Gitlab/ModuleWithInstanceVariables
def history
if page
@commits_count = page.count_versions
@commits = Kaminari.paginate_array(page.versions(page: params[:page].to_i), total_count: page.count_versions)
.page(params[:page])

View File

@ -29,7 +29,7 @@
.form-group.gl-mt-3.gl-mb-6
= render Pajamas::AvatarComponent.new(@group, size: 96, alt: '', class: 'gl-float-left gl-mr-5')
= f.label :avatar, s_('Groups|Group avatar'), class: 'label-bold d-block'
= f.label :avatar, s_('Groups|Group avatar'), class: 'label-bold gl-block'
= render 'shared/choose_avatar_button', f: f
- if @group.avatar?
%hr

View File

@ -54,7 +54,7 @@
= render_if_exists 'projects/commits/project_namespace', show_project_name: show_project_name, project: project
- if commit.description?
%pre{ class: ["commit-row-description gl-mb-3 gl-white-space-pre-wrap", (collapsible ? "js-toggle-content" : "d-block")] }
%pre{ class: ["commit-row-description gl-mb-3 gl-white-space-pre-wrap", (collapsible ? "js-toggle-content" : "!gl-block")] }
= preserve(markdown_field(commit, :description))
.commit-actions.flex-row

View File

@ -15,7 +15,7 @@
#js-project-show-empty-page.project-page-layout
.project-page-layout-content.gl-mt-5
.project-buttons.gl-mb-5{ data: { testid: 'quick-actions-container' } }
.project-clone-holder.d-block.d-sm-none
.project-clone-holder.gl-block.sm:gl-hidden
= render "shared/mobile_clone_panel"
.project-clone-holder.gl-hidden.sm:gl-flex.gl-justify-content-end.gl-w-full

View File

@ -31,7 +31,7 @@
.form-group.gl-mt-3.gl-mb-3
= render Pajamas::AvatarComponent.new(@project, size: 96, alt: '', class: 'gl-float-left gl-mr-5')
= f.label :avatar, _('Project avatar'), class: 'label-bold d-block'
= f.label :avatar, _('Project avatar'), class: 'label-bold gl-block'
= render 'shared/choose_avatar_button', f: f
- if @project.avatar?
%hr

View File

@ -2,7 +2,7 @@
- wiki_page_title @page, _('History')
- add_page_specific_style 'page_bundles/wiki'
.wiki-page-header.top-area.has-sidebar-toggle.flex-column.flex-lg-row
.wiki-page-header.top-area.has-sidebar-toggle.flex-column.flex-lg-row.gl-border-b-0
= wiki_sidebar_toggle_button
%h1.page-title.gl-font-size-h-display
@ -12,28 +12,38 @@
= _('History')
.prepend-top-default.gl-mb-3
.table-holder{ data: { testid: 'wiki-history-table' } }
%table.table.wiki-history
%thead
%tr
%th= @page.template? ? s_('Wiki|Template version') : s_('Wiki|Page version')
%th= _('Author')
%th= _('Changes')
%th= _('Last updated')
%tbody
- @commits.each do |commit|
%tr
%td
= link_to wiki_page_path(@wiki, @page, version_id: commit.id) do
= truncate_sha(commit.id)
%td
= commit.author_name
%td
.commit-content
= link_to wiki_page_path(@wiki, @page, action: :diff, version_id: commit.id), { title: commit.message } do
= commit.message
%td
= time_ago_with_tooltip(commit.authored_date)
= render Pajamas::CardComponent.new(card_options: { class: 'gl-new-card gl-mt-0 gl-mb-5' }, header_options: { class: 'gl-new-card-header gl-border-b-0' }, body_options: { class: 'gl-new-card-body gl-px-0' }) do |c|
- c.with_header do
.gl-new-card-title-wrapper.gl-flex-col
%h3.gl-new-card-title
= _('Versions')
.gl-new-card-count
= sprite_icon('history', css_class: 'gl-mr-2')
= @commits_count
- c.with_body do
.table-holder{ data: { testid: 'wiki-history-table' } }
%table.table.wiki-history{ class: '!gl-mb-0' }
%thead
%tr
%th= _('Version')
%th= _('Author')
%th= _('Diff')
%th= _('Last updated')
%tbody
- @commits.each_with_index do |commit, i|
%tr
%td
= link_to wiki_page_path(@wiki, @page, version_id: commit.id) do
v#{@commits_count - i}
%td
= commit.author_name
%td
.commit-content
= link_to wiki_page_path(@wiki, @page, action: :diff, version_id: commit.id), { title: commit.message } do
= commit.message
%td
= time_ago_with_tooltip(commit.authored_date)
= paginate @commits, theme: 'gitlab'
= render 'shared/wikis/sidebar'

View File

@ -436,6 +436,17 @@ To determine if there are any differences:
Select the branch that matches your GitLab version. For example, the file for GitLab 16.2: <https://gitlab.com/gitlab-org/gitlab/-/blob/16-2-stable-ee/db/structure.sql>.
1. Compare `/tmp/structure.sql` with the `db/structure.sql` file for your version.
## Check the database for schema inconsistencies
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/390719) in GitLab 15.11.
This Rake task checks the database schema for any inconsistencies
and prints them in the terminal.
```shell
gitlab-rake gitlab:db:schema_checker:run
```
## Import common metrics
Sometimes you may need to re-import the common metrics that power the Metrics dashboards.

View File

@ -60,14 +60,14 @@ Example response:
"project_id": 7,
"package_name_pattern": "@flightjs/flight-package-0",
"package_type": "npm",
"push_protected_up_to_access_level": "maintainer"
"minimum_access_level_for_push": "maintainer"
},
{
"id": 2,
"project_id": 7,
"package_name_pattern": "@flightjs/flight-package-1",
"package_type": "npm",
"push_protected_up_to_access_level": "maintainer"
"minimum_access_level_for_push": "maintainer"
}
]
```

View File

@ -1,7 +1,6 @@
---
stage: Create
group: Editor Extensions
description: Visual Studio Code, JetBrains, Neovim, GitLab CLI.
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
description: "Extend the features of GitLab to Visual Studio Code, JetBrains IDEs, Visual Studio, and Neovim."
---

View File

@ -10,7 +10,7 @@ module API
expose :project_id, documentation: { type: 'integer', example: 1 }
expose :package_name_pattern, documentation: { type: 'string', example: 'flightjs/flight' }
expose :package_type, documentation: { type: 'string', example: 'npm' }
expose :push_protected_up_to_access_level, documentation: { type: 'string', example: 'maintainer' }
expose :minimum_access_level_for_push, documentation: { type: 'string', example: 'maintainer' }
end
end
end

View File

@ -82,7 +82,8 @@ module Gitlab
raise exception if should_raise_for_dev?
end
# This should be used when you only want to track the exception.
# This should be used when you want to track the exception and not raise
# with the default trackers (Sentry and Logger).
#
# If the exception implements the method `sentry_extra_data` and that method
# returns a Hash, then the return value of that method will be merged into
@ -93,7 +94,7 @@ module Gitlab
end
# This should be used when you only want to log the exception,
# but not send it to Sentry.
# but not send it to Sentry or raise.
#
# If the exception implements the method `sentry_extra_data` and that method
# returns a Hash, then the return value of that method will be merged into

View File

@ -18722,6 +18722,9 @@ msgstr ""
msgid "Didn't receive unlock instructions?"
msgstr ""
msgid "Diff"
msgstr ""
msgid "Diff files surpassing this limit will be presented as 'too large' and won't be expandable."
msgstr ""
@ -57715,6 +57718,9 @@ msgstr ""
msgid "VersionCheck|You are currently on version %{currentVersion}! We strongly recommend upgrading your GitLab installation to one of the following versions immediately: %{latestStableVersions}."
msgstr ""
msgid "Versions"
msgstr ""
msgid "View File Metadata"
msgstr ""
@ -59255,18 +59261,12 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
msgid "Wiki|Page version"
msgstr ""
msgid "Wiki|Pages"
msgstr ""
msgid "Wiki|Template history"
msgstr ""
msgid "Wiki|Template version"
msgstr ""
msgid "Wiki|Templates"
msgstr ""

View File

@ -65,7 +65,7 @@
"@gitlab/cluster-client": "^2.2.0",
"@gitlab/favicon-overlay": "2.0.0",
"@gitlab/fonts": "^1.3.0",
"@gitlab/ui": "80.16.1",
"@gitlab/ui": "80.19.0",
"@gitlab/svgs": "3.101.0",
"@gitlab/web-ide": "^0.0.1-dev-20240531032328",
"@mattiasbuelens/web-streams-adapter": "^0.1.0",
@ -290,7 +290,7 @@
"swagger-cli": "^4.0.4",
"tailwindcss": "^3.4.1",
"timezone-mock": "^1.0.8",
"vite": "^5.2.12",
"vite": "^5.2.13",
"vite-plugin-ruby": "^5.0.0",
"vue-loader-vue3": "npm:vue-loader@17.4.2",
"vue-test-utils-compat": "0.0.14",

View File

@ -46,6 +46,12 @@ export const mismatchAllowList = [
'.border-l\\!',
'.border-r\\!',
'.border-t\\!',
// Tailwindy transparent border utils now leverage design tokens, the mismatches are expected.
'.border-transparent',
'.border-t-transparent',
'.border-r-transparent',
'.border-b-transparent',
'.border-l-transparent',
// Tailwind's line-clamp utils don't set `white-space: normal`, while our custom utils did.
// We have added `gl-whitespace-normal` wherever line-clamp utils were being used, so these
// mismatches can be ignored.

View File

@ -14,10 +14,16 @@ RSpec.describe 'Project issue boards sidebar labels', :js, feature_category: :po
let_it_be(:stretch) { create(:label, project: project, name: 'Stretch') }
let_it_be(:issue1) { create(:labeled_issue, project: project, labels: [development], relative_position: 2) }
let_it_be(:issue2) { create(:labeled_issue, project: project, labels: [development, stretch], relative_position: 1) }
let_it_be(:issue3) { create(:issue, project: project) }
let_it_be(:board) { create(:board, project: project) }
let_it_be(:list) { create(:list, board: board, label: development, position: 0) }
let_it_be(:list1) { create(:list, board: board, label: development, position: 0) }
let_it_be(:list2) { create(:list, board: board, label: bug, position: 1) }
let(:card) { find('.board:nth-child(2)').first('.board-card') }
let(:backlog_list) { find('.board:nth-child(1)') }
let(:development_list) { find('.board:nth-child(2)') }
let(:bug_list) { find('.board:nth-child(3)') }
let(:card) { development_list.first('.board-card') }
let(:backlog_card) { backlog_list.first('.board-card') }
before do
project.add_maintainer(user)
@ -65,9 +71,20 @@ RSpec.describe 'Project issue boards sidebar labels', :js, feature_category: :po
end
end
click_button 'Close drawer'
wait_for_requests
# 'Development' label does not show since the card is in a 'Development' list label
expect(card).to have_selector('.gl-label', count: 2)
expect(card).to have_content(bug.title)
# Card is duplicated in the 'Bug' list
page.within(bug_list) do
expect(page).to have_selector('.board-card', count: 1)
expect(page).to have_content(issue2.title)
expect(find('.board-card')).to have_content(development.title)
end
end
it 'adds a multiple labels' do
@ -99,6 +116,69 @@ RSpec.describe 'Project issue boards sidebar labels', :js, feature_category: :po
expect(card).to have_content(regression.title)
end
it 'removes a label and moves card to backlog' do
click_card(card)
page.within('.labels') do
click_button 'Edit'
wait_for_requests
click_button development.title
click_button 'Close'
wait_for_requests
end
click_button 'Close drawer'
wait_for_requests
# Card is moved to the 'Backlog' list
page.within(backlog_list) do
expect(page).to have_selector('.board-card', count: 2)
expect(page).to have_content(issue2.title)
end
# Card is moved away from the 'Development' list
page.within(development_list) do
expect(page).to have_selector('.board-card', count: 1)
expect(page).not_to have_content(issue2.title)
end
end
it 'adds a label to backlog card and moves the card to the list' do
click_card(backlog_card)
page.within('.labels') do
click_button 'Edit'
wait_for_requests
click_on development.title
click_button 'Close'
wait_for_requests
end
click_button 'Close drawer'
wait_for_requests
# Card is removed from backlog
page.within(backlog_list) do
expect(page).to have_selector('.board-card', count: 0)
end
# Card is shown in the 'Development' list
page.within(development_list) do
expect(page).to have_selector('.board-card', count: 3)
expect(page).to have_content(issue3.title)
end
end
it 'removes a label' do
click_card(card)
@ -139,7 +219,7 @@ RSpec.describe 'Project issue boards sidebar labels', :js, feature_category: :po
expect(page).to have_button 'test label'
end
expect(page).to have_selector('.board', count: 3)
expect(page).to have_selector('.board', count: 4)
end
end
end

View File

@ -33,7 +33,7 @@ describe('Code Block', () => {
class="code code-block rounded"
>
<code
class="d-block"
class="gl-block"
/>
</pre>
`);
@ -47,7 +47,7 @@ describe('Code Block', () => {
class="code code-block rounded"
>
<code
class="d-block"
class="gl-block"
>
test-code
</code>
@ -64,7 +64,7 @@ describe('Code Block', () => {
style="max-height: 200px; overflow-y: auto;"
>
<code
class="d-block"
class="gl-block"
>
test-code
</code>

View File

@ -13,7 +13,7 @@ RSpec.describe API::Entities::Projects::Packages::Protection::Rule, feature_cate
:project_id,
:package_name_pattern,
:package_type,
:push_protected_up_to_access_level
:minimum_access_level_for_push
]
end
end

View File

@ -105,7 +105,7 @@ RSpec.describe Banzai::Pipeline::PlainMarkdownPipeline, feature_category: :team_
end
it 'does not have a polynomial regex' do
markdown = "x \\#\n\n#{'mliteralcmliteral-' * 1550000}mliteral"
markdown = "x \\#\n\n#{'mliteralcmliteral-' * 450000}mliteral"
expect do
Timeout.timeout(2.seconds) { described_class.to_html(markdown, project: project) }

View File

@ -1331,10 +1331,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-3.101.0.tgz#a8769490eecd03b8cc2403f5b7faab34a4ad0d82"
integrity sha512-X/3oLr969A9dzVaTD2JfG6EmxadEQwCPXcfn1A6Y+AAI0PLkBgjDXUz0yo1tXJOF6nqOmYpBiUM6uOon3i5N4A==
"@gitlab/ui@80.16.1":
version "80.16.1"
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-80.16.1.tgz#87ed3cf6dd6a1da123422dfa339734440ad35d1f"
integrity sha512-j7yYTvdIXQsznIKmrIwX7G3e67b3s2qt4KbIR+fq78Yko+9FO38t4bceVZo33cpHu26Sx0wqbjq3xAVnE9D/ug==
"@gitlab/ui@80.19.0":
version "80.19.0"
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-80.19.0.tgz#b6e6018d27939a7ac2451b6a41cf49071977aa95"
integrity sha512-aswSSLDkHzjvWdHDKZH5ZPZYiX821+fZ2yPLoN+0OYyA75XzAr5daaV2os4y6PLPtWJHiHF3nWbZSF80wMF68A==
dependencies:
"@floating-ui/dom" "1.4.3"
bootstrap-vue "2.23.1"
@ -14156,10 +14156,10 @@ vite-plugin-ruby@^5.0.0:
debug "^4.3.4"
fast-glob "^3.3.2"
vite@^5.2.12:
version "5.2.12"
resolved "https://registry.yarnpkg.com/vite/-/vite-5.2.12.tgz#3536c93c58ba18edea4915a2ac573e6537409d97"
integrity sha512-/gC8GxzxMK5ntBwb48pR32GGhENnjtY30G4A0jemunsBkiEZFw60s8InGpN8gkhHEkjnRK1aSAxeQgwvFhUHAA==
vite@^5.2.13:
version "5.2.13"
resolved "https://registry.yarnpkg.com/vite/-/vite-5.2.13.tgz#945ababcbe3d837ae2479c29f661cd20bc5e1a80"
integrity sha512-SSq1noJfY9pR3I1TUENL3rQYDQCFqgD+lM6fTRAM8Nv6Lsg5hDLaXkjETVeBt+7vZBCMoibD+6IWnT2mJ+Zb/A==
dependencies:
esbuild "^0.20.1"
postcss "^8.4.38"