Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
1bf756371d
commit
35305bfc83
|
|
@ -1,4 +1,3 @@
|
|||
import Vue from 'vue';
|
||||
import * as types from './mutation_types';
|
||||
|
||||
export default {
|
||||
|
|
@ -12,19 +11,18 @@ export default {
|
|||
state.groupMilestonesAvailable = groupMilestonesAvailable;
|
||||
},
|
||||
[types.SET_SELECTED_MILESTONES](state, selectedMilestones) {
|
||||
Vue.set(state, 'selectedMilestones', selectedMilestones);
|
||||
state.selectedMilestones = selectedMilestones;
|
||||
},
|
||||
[types.CLEAR_SELECTED_MILESTONES](state) {
|
||||
Vue.set(state, 'selectedMilestones', []);
|
||||
state.selectedMilestones = [];
|
||||
},
|
||||
[types.ADD_SELECTED_MILESTONE](state, selectedMilestone) {
|
||||
state.selectedMilestones.push(selectedMilestone);
|
||||
},
|
||||
[types.REMOVE_SELECTED_MILESTONE](state, selectedMilestone) {
|
||||
const filteredMilestones = state.selectedMilestones.filter(
|
||||
state.selectedMilestones = state.selectedMilestones.filter(
|
||||
(milestone) => milestone !== selectedMilestone,
|
||||
);
|
||||
Vue.set(state, 'selectedMilestones', filteredMilestones);
|
||||
},
|
||||
[types.SET_SEARCH_QUERY](state, searchQuery) {
|
||||
state.searchQuery = searchQuery;
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ export default {
|
|||
></div>
|
||||
<noteable-warning
|
||||
v-if="hasWarning"
|
||||
class="gl-pt-4 gl-pb-5 gl-mb-n3 gl-rounded-lg gl-rounded-bottom-left-none gl-rounded-bottom-right-none"
|
||||
class="gl-pt-4 gl-pb-5 -gl-mb-3 gl-rounded-lg gl-rounded-bottom-left-none gl-rounded-bottom-right-none"
|
||||
:is-locked="isLocked"
|
||||
:is-confidential="isConfidential"
|
||||
:noteable-type="noteableType"
|
||||
|
|
@ -80,14 +80,14 @@ export default {
|
|||
v-if="showAttachmentWarning"
|
||||
:class="{
|
||||
'gl-py-3': !showEmailParticipantsWarning,
|
||||
'gl-pt-4 gl-pb-3 gl-mt-n3': showEmailParticipantsWarning,
|
||||
'gl-pt-4 gl-pb-3 -gl-mt-3': showEmailParticipantsWarning,
|
||||
}"
|
||||
/>
|
||||
<email-participants-warning
|
||||
v-if="showEmailParticipantsWarning"
|
||||
class="gl-border-t-1 gl-rounded-lg gl-rounded-top-left-none! gl-rounded-top-right-none!"
|
||||
:class="{
|
||||
'gl-pt-4 gl-pb-3 gl-mt-n3': !showAttachmentWarning,
|
||||
'gl-pt-4 gl-pb-3 -gl-mt-3': !showAttachmentWarning,
|
||||
'gl-py-3 gl-mt-1': showAttachmentWarning,
|
||||
}"
|
||||
:emails="emailParticipants"
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ export default {
|
|||
data-testid="discussion-filter-container"
|
||||
>
|
||||
<div
|
||||
class="gl-float-left gl--flex-center gl-rounded-full gl-mt-n1 gl-ml-2 gl-w-6 gl-h-6 gl-bg-gray-50 gl-text-gray-600"
|
||||
class="gl-float-left gl--flex-center gl-rounded-full -gl-mt-1 gl-ml-2 gl-w-6 gl-h-6 gl-bg-gray-50 gl-text-gray-600"
|
||||
>
|
||||
<gl-icon name="comment" />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -399,7 +399,7 @@ export default {
|
|||
</template>
|
||||
|
||||
<template v-if="showBatchCommentsActions">
|
||||
<div class="gl-display-flex gl-flex-wrap gl-mb-n3">
|
||||
<div class="gl-display-flex gl-flex-wrap -gl-mb-3">
|
||||
<gl-button
|
||||
:disabled="isDisabled"
|
||||
category="primary"
|
||||
|
|
|
|||
|
|
@ -294,7 +294,7 @@ export default {
|
|||
:issuable-type="issuableType"
|
||||
:is-editing="edit"
|
||||
:issuable-author="issuableAuthor"
|
||||
class="gl-w-full dropdown-menu-user gl-mt-n3"
|
||||
class="gl-w-full dropdown-menu-user -gl-mt-3"
|
||||
@toggle="collapseWidget"
|
||||
@error="showError"
|
||||
@input="setDirtyState"
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ export default {
|
|||
<div class="color-input-container gl-display-flex">
|
||||
<gl-form-input
|
||||
v-model.trim="selectedColor"
|
||||
class="gl-rounded-top-right-none gl-rounded-bottom-right-none gl-mr-n1 gl-mb-2 gl-w-8"
|
||||
class="gl-rounded-top-right-none gl-rounded-bottom-right-none -gl-mr-1 gl-mb-2 gl-w-8"
|
||||
type="color"
|
||||
:value="selectedColor"
|
||||
:placeholder="__('Open color picker')"
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ export default {
|
|||
<gl-button
|
||||
category="tertiary"
|
||||
size="small"
|
||||
class="gl-float-right js-sidebar-dropdown-toggle gl-mr-n2"
|
||||
class="gl-float-right js-sidebar-dropdown-toggle -gl-mr-2"
|
||||
@click="toggleDropdownContents"
|
||||
>
|
||||
{{ __('Edit') }}
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ export default {
|
|||
<gl-form-group class="gl-mb-0!">
|
||||
<gl-form-input
|
||||
v-model.trim="selectedColor"
|
||||
class="gl-mr-n1 gl-mb-2 gl-w-8"
|
||||
class="-gl-mr-1 gl-mb-2 gl-w-8"
|
||||
type="color"
|
||||
:value="selectedColor"
|
||||
:placeholder="__('Select color')"
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@ export default {
|
|||
v-gl-tooltip.viewport.html
|
||||
category="tertiary"
|
||||
size="small"
|
||||
class="gl-text-gray-900! gl-ml-auto hide-collapsed gl-mr-n2 shortcut-sidebar-dropdown-toggle"
|
||||
class="gl-text-gray-900! gl-ml-auto hide-collapsed -gl-mr-2 shortcut-sidebar-dropdown-toggle"
|
||||
:title="editTooltipText"
|
||||
:aria-label="editAriaLabelText"
|
||||
:aria-keyshortcuts="editKeyshortcutsText"
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import {
|
|||
TOP_NAV_INVITE_MEMBERS_COMPONENT,
|
||||
TRIGGER_ELEMENT_DISCLOSURE_DROPDOWN,
|
||||
} from '~/invite_members/constants';
|
||||
import { WORK_ITEM_TYPE_ENUM_EPIC, CREATE_NEW_WORK_ITEM_MODAL } from '~/work_items/constants';
|
||||
import { DROPDOWN_Y_OFFSET, IMPERSONATING_OFFSET } from '../constants';
|
||||
|
||||
// Left offset required for the dropdown to be aligned with the super sidebar
|
||||
|
|
@ -23,6 +24,7 @@ export default {
|
|||
GlDisclosureDropdownGroup,
|
||||
GlDisclosureDropdownItem,
|
||||
InviteMembersTrigger,
|
||||
CreateWorkItemModal: () => import('~/work_items/components/create_work_item_modal.vue'),
|
||||
},
|
||||
directives: {
|
||||
GlTooltip: GlTooltipDirective,
|
||||
|
|
@ -54,9 +56,13 @@ export default {
|
|||
isInvitedMembers(groupItem) {
|
||||
return groupItem.component === TOP_NAV_INVITE_MEMBERS_COMPONENT;
|
||||
},
|
||||
isCreateWorkItem(groupItem) {
|
||||
return groupItem.component === CREATE_NEW_WORK_ITEM_MODAL;
|
||||
},
|
||||
},
|
||||
toggleId: 'create-menu-toggle',
|
||||
TRIGGER_ELEMENT_DISCLOSURE_DROPDOWN,
|
||||
WORK_ITEM_TYPE_ENUM_EPIC,
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
@ -87,6 +93,12 @@ export default {
|
|||
trigger-source="top_nav"
|
||||
:trigger-element="$options.TRIGGER_ELEMENT_DISCLOSURE_DROPDOWN"
|
||||
/>
|
||||
<create-work-item-modal
|
||||
v-else-if="isCreateWorkItem(groupItem)"
|
||||
:key="`${groupItem.text}-modal-trigger`"
|
||||
as-dropdown-item
|
||||
:work-item-type="$options.WORK_ITEM_TYPE_ENUM_EPIC"
|
||||
/>
|
||||
<gl-disclosure-dropdown-item v-else :key="groupItem.text" :item="groupItem" />
|
||||
</template>
|
||||
</gl-disclosure-dropdown-group>
|
||||
|
|
|
|||
|
|
@ -71,3 +71,5 @@ export const FIFTEEN_MINUTES_IN_MS = 900000;
|
|||
export const STORAGE_KEY = {
|
||||
projects: 'frequent-projects',
|
||||
};
|
||||
|
||||
export const CONTEXT_NAMESPACE_GROUPS = 'groups';
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { GlToast } from '@gitlab/ui';
|
|||
import VueApollo from 'vue-apollo';
|
||||
import { convertObjectPropsToCamelCase, parseBoolean } from '~/lib/utils/common_utils';
|
||||
import createDefaultClient from '~/lib/graphql';
|
||||
import { JS_TOGGLE_EXPAND_CLASS } from './constants';
|
||||
import { JS_TOGGLE_EXPAND_CLASS, CONTEXT_NAMESPACE_GROUPS } from './constants';
|
||||
import createStore from './components/global_search/store';
|
||||
import {
|
||||
bindSuperSidebarCollapsedEvents,
|
||||
|
|
@ -104,6 +104,8 @@ export const initSuperSidebar = () => {
|
|||
const { searchPath, issuesPath, mrPath, autocompletePath, searchContext } = searchData;
|
||||
const isImpersonating = parseBoolean(sidebarData.is_impersonating);
|
||||
|
||||
const isGroup = Boolean(sidebarData.current_context?.namespace === CONTEXT_NAMESPACE_GROUPS);
|
||||
|
||||
return new Vue({
|
||||
el,
|
||||
name: 'SuperSidebarRoot',
|
||||
|
|
@ -121,6 +123,8 @@ export const initSuperSidebar = () => {
|
|||
projectBlobPath,
|
||||
projectsPath,
|
||||
groupsPath,
|
||||
fullPath: sidebarData.work_items?.full_path,
|
||||
isGroup,
|
||||
},
|
||||
store: createStore({
|
||||
searchPath,
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ export default {
|
|||
>
|
||||
<div class="gl-display-inline-flex gl-align-items-center gl-relative">
|
||||
<div
|
||||
class="gl-display-inline gl-bg-white gl-text-gray-200 gl-border-gray-100 gl-border-1 gl-border-solid gl-rounded-full gl-box-sizing-content-box gl-p-3 gl-mt-n2 gl-mr-6"
|
||||
class="gl-display-inline gl-bg-white gl-text-gray-200 gl-border-gray-100 gl-border-1 gl-border-solid gl-rounded-full gl-box-sizing-content-box gl-p-3 -gl-mt-2 gl-mr-6"
|
||||
>
|
||||
<gl-icon :name="note.systemNoteIconName" />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ export default {
|
|||
<template>
|
||||
<timeline-entry-item class="note note-wrapper">
|
||||
<div
|
||||
class="gl-float-left gl--flex-center gl-rounded-full gl-mt-n1 gl-ml-2 gl-w-6 gl-h-6 gl-bg-gray-50 gl-text-gray-600"
|
||||
class="gl-float-left gl--flex-center gl-rounded-full -gl-mt-1 gl-ml-2 gl-w-6 gl-h-6 gl-bg-gray-50 gl-text-gray-600"
|
||||
></div>
|
||||
<div class="timeline-content">
|
||||
<div class="note-header"></div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div
|
||||
class="gl-float-left gl--flex-center gl-rounded-full gl-mt-n1 gl-ml-2 gl-w-6 gl-h-6 gl-bg-gray-50 gl-text-gray-600"
|
||||
class="gl-float-left gl--flex-center gl-rounded-full -gl-mt-1 gl-ml-2 gl-w-6 gl-h-6 gl-bg-gray-50 gl-text-gray-600"
|
||||
>
|
||||
<slot></slot>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ export default {
|
|||
<template>
|
||||
<timeline-entry-item class="system-note note-wrapper">
|
||||
<div
|
||||
class="gl--flex-center gl-rounded-full gl-mt-n1 gl-ml-2 gl-w-6 gl-h-6 gl-bg-gray-50 gl-text-gray-600 gl-float-left"
|
||||
class="gl--flex-center gl-rounded-full -gl-mt-1 gl-ml-2 gl-w-6 gl-h-6 gl-bg-gray-50 gl-text-gray-600 gl-float-left"
|
||||
>
|
||||
<gl-icon :name="icon" />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ export default {
|
|||
class="gl-py-5 gl-pl-8"
|
||||
:class="{ 'gl-border-b': borderBottom(idx) }"
|
||||
>
|
||||
<div class="gl-mt-n1 gl-pl-4 gl-pb-2 gl-font-weight-bold">
|
||||
<div class="-gl-mt-1 gl-pl-4 gl-pb-2 gl-font-weight-bold">
|
||||
{{ easyButton.description }}
|
||||
<gl-accordion :header-level="3" class="gl-pt-3">
|
||||
<gl-accordion-item
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import { GlButton, GlModal } from '@gitlab/ui';
|
||||
import { GlButton, GlModal, GlDisclosureDropdownItem } from '@gitlab/ui';
|
||||
import { visitUrl } from '~/lib/utils/url_utility';
|
||||
import { I18N_NEW_WORK_ITEM_BUTTON_LABEL, sprintfWorkItem } from '../constants';
|
||||
import CreateWorkItem from './create_work_item.vue';
|
||||
|
|
@ -9,6 +9,7 @@ export default {
|
|||
CreateWorkItem,
|
||||
GlButton,
|
||||
GlModal,
|
||||
GlDisclosureDropdownItem,
|
||||
},
|
||||
props: {
|
||||
workItemType: {
|
||||
|
|
@ -16,6 +17,11 @@ export default {
|
|||
required: false,
|
||||
default: null,
|
||||
},
|
||||
asDropdownItem: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
|
@ -26,6 +32,12 @@ export default {
|
|||
newWorkItemText() {
|
||||
return sprintfWorkItem(I18N_NEW_WORK_ITEM_BUTTON_LABEL, this.workItemType);
|
||||
},
|
||||
dropdownItem() {
|
||||
return {
|
||||
text: this.newWorkItemText,
|
||||
action: this.showModal,
|
||||
};
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
hideModal() {
|
||||
|
|
@ -43,7 +55,9 @@ export default {
|
|||
|
||||
<template>
|
||||
<div>
|
||||
<gl-disclosure-dropdown-item v-if="asDropdownItem" :item="dropdownItem" />
|
||||
<gl-button
|
||||
v-else
|
||||
category="primary"
|
||||
variant="confirm"
|
||||
data-testid="new-epic-button"
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ export default {
|
|||
:aria-label="__('Title')"
|
||||
:data-placeholder="placeholder"
|
||||
:contenteditable="!disabled"
|
||||
class="hide-unfocused-input-decoration gl-px-4 gl-py-3 gl-ml-n4 gl-border gl-rounded-base gl-display-block"
|
||||
class="hide-unfocused-input-decoration gl-px-4 gl-py-3 -gl-ml-4 gl-border gl-rounded-base gl-display-block"
|
||||
:class="{ 'gl-hover-border-gray-200 gl-pseudo-placeholder': !disabled }"
|
||||
@paste="handlePaste"
|
||||
@blur="handleBlur"
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ export default {
|
|||
<template>
|
||||
<li class="timeline-entry note note-wrapper discussion-filter-note">
|
||||
<div
|
||||
class="gl-float-left gl--flex-center gl-rounded-full gl-mt-n1 gl-ml-2 gl-w-6 gl-h-6 gl-bg-gray-50 gl-text-gray-600"
|
||||
class="gl-float-left gl--flex-center gl-rounded-full -gl-mt-1 gl-ml-2 gl-w-6 gl-h-6 gl-bg-gray-50 gl-text-gray-600"
|
||||
>
|
||||
<gl-icon name="comment" />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ export default {
|
|||
<div v-if="canUpdate">
|
||||
<gl-button
|
||||
v-gl-tooltip
|
||||
class="gl-mt-n2 gl-mr-n2"
|
||||
class="-gl-mt-2 -gl-mr-2"
|
||||
category="tertiary"
|
||||
size="small"
|
||||
icon="close"
|
||||
|
|
|
|||
|
|
@ -355,7 +355,7 @@ export default {
|
|||
:title="token.name"
|
||||
:data-user-id="getUserId(token.id)"
|
||||
data-placement="top"
|
||||
class="gl-ml-n2 gl-text-decoration-none! gl-text-body! gl-display-flex gl-md-display-inline-flex! gl-align-items-center js-user-link"
|
||||
class="-gl-ml-2 gl-text-decoration-none! gl-text-body! gl-display-flex gl-md-display-inline-flex! gl-align-items-center js-user-link"
|
||||
>
|
||||
<gl-avatar :size="24" :src="token.avatarUrl" />
|
||||
<span class="gl-pl-2">{{ token.name }}</span>
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ export default {
|
|||
is-modal
|
||||
:work-item-iid="displayedWorkItemIid"
|
||||
:modal-work-item-full-path="workItemFullPath"
|
||||
class="gl-p-5 gl-mt-n3 gl-reset-bg gl-isolate"
|
||||
class="gl-p-5 -gl-mt-3 gl-reset-bg gl-isolate"
|
||||
@close="hide"
|
||||
@deleteWorkItem="deleteWorkItem"
|
||||
@update-modal="updateModal"
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ export default {
|
|||
<div v-else class="gl-display-flex gl-flex-wrap gl-gap-5">
|
||||
<gl-form-group
|
||||
class="gl-display-flex gl-align-items-center gl-m-0"
|
||||
:class="{ 'gl-ml-n3': isReadonlyWithOnlyDueDate }"
|
||||
:class="{ '-gl-ml-3': isReadonlyWithOnlyDueDate }"
|
||||
:label="$options.i18n.startDate"
|
||||
:label-for="$options.startDateInputId"
|
||||
:label-sr-only="!showStartDateInput"
|
||||
|
|
@ -238,7 +238,7 @@ export default {
|
|||
<gl-form-group
|
||||
v-if="!isReadonlyWithOnlyStartDate"
|
||||
class="gl-display-flex gl-align-items-center gl-m-0"
|
||||
:class="{ 'gl-ml-n3': isReadonlyWithOnlyDueDate }"
|
||||
:class="{ '-gl-ml-3': isReadonlyWithOnlyDueDate }"
|
||||
:label="$options.i18n.dueDate"
|
||||
:label-for="$options.dueDateInputId"
|
||||
:label-sr-only="!showDueDateInput"
|
||||
|
|
|
|||
|
|
@ -254,7 +254,7 @@ export default {
|
|||
<span
|
||||
:style="{ background: item.color }"
|
||||
:class="{ 'gl-border gl-border-white': isSelected(item.value) }"
|
||||
class="gl-display-inline-block gl-rounded-base gl-mr-1 gl-w-5 gl-h-3 gl-align-middle gl-mt-n1"
|
||||
class="gl-display-inline-block gl-rounded-base gl-mr-1 gl-w-5 gl-h-3 gl-align-middle -gl-mt-1"
|
||||
></span>
|
||||
{{ item.text }}
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -342,3 +342,5 @@ export const EPIC_COLORS = [
|
|||
];
|
||||
|
||||
export const DEFAULT_EPIC_COLORS = '#1068bf';
|
||||
|
||||
export const CREATE_NEW_WORK_ITEM_MODAL = 'create_new_work_item_modal';
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@ class Projects::MirrorsController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def update
|
||||
result = ::Projects::UpdateService.new(project, current_user, mirror_params).execute
|
||||
result = ::Projects::UpdateService.new(project, current_user, safe_mirror_params).execute
|
||||
|
||||
if result[:status] == :success
|
||||
flash[:notice] = _('Mirroring settings were successfully updated.')
|
||||
flash[:notice] = notice_message
|
||||
else
|
||||
flash[:alert] = project.errors.full_messages.join(', ').html_safe
|
||||
end
|
||||
|
|
@ -64,6 +64,14 @@ class Projects::MirrorsController < Projects::ApplicationController
|
|||
|
||||
private
|
||||
|
||||
def safe_mirror_params
|
||||
mirror_params
|
||||
end
|
||||
|
||||
def notice_message
|
||||
_('Mirroring settings were successfully updated.')
|
||||
end
|
||||
|
||||
def remote_mirror
|
||||
@remote_mirror = project.remote_mirrors.first_or_initialize
|
||||
end
|
||||
|
|
|
|||
|
|
@ -113,10 +113,15 @@ module SidebarsHelper
|
|||
is_impersonating: impersonating?,
|
||||
stop_impersonation_path: admin_impersonation_path,
|
||||
shortcut_links: shortcut_links(user: user, project: project),
|
||||
track_visits_path: track_namespace_visits_path
|
||||
track_visits_path: track_namespace_visits_path,
|
||||
work_items: work_items_modal_data(group)
|
||||
})
|
||||
end
|
||||
|
||||
def work_items_modal_data(group)
|
||||
{ full_path: group.full_path } if group
|
||||
end
|
||||
|
||||
def super_sidebar_nav_panel(
|
||||
nav: nil, project: nil, user: nil, group: nil, current_ref: nil, ref_type: nil,
|
||||
viewed_user: nil, organization: nil)
|
||||
|
|
|
|||
|
|
@ -11,14 +11,15 @@
|
|||
- filter_by_done = params[:state] == 'done'
|
||||
- open_todo_count = todos_has_filtered_results? && !filter_by_done ? @allowed_todos.count : todos_pending_count
|
||||
- done_todo_count = todos_has_filtered_results? && filter_by_done ? @allowed_todos.count : todos_done_count
|
||||
- show_header = @allowed_todos.any? || current_user.todos.any?
|
||||
- user_have_todos = current_user.todos.any?
|
||||
- show_header = @allowed_todos.any? || user_have_todos
|
||||
|
||||
- if show_header
|
||||
.page-title-holder.d-flex.gl-align-items-center
|
||||
%h1.page-title.gl-font-size-h-display= _("To-Do List")
|
||||
|
||||
.js-todos-all
|
||||
- if current_user.todos.any?
|
||||
- if user_have_todos
|
||||
.top-area
|
||||
= gl_tabs_nav({ class: 'gl-flex-grow-1 gl-border-0' }) do
|
||||
= gl_tab_link_to todos_filter_path(state: 'pending'), item_active: params[:state].blank? || params[:state] == 'pending', class: "js-todos-pending" do
|
||||
|
|
@ -92,7 +93,7 @@
|
|||
= render Pajamas::EmptyStateComponent.new(svg_path: 'illustrations/empty-todos-all-done-md.svg',
|
||||
title: s_("Todos|You're all done!"))
|
||||
|
||||
- elsif current_user.todos.any?
|
||||
- elsif user_have_todos
|
||||
- empty_state_image = (!todos_filter_empty? && !todos_has_filtered_results?) ? 'illustrations/empty-todos-all-done-md.svg' : 'illustrations/empty-todos-md.svg'
|
||||
- empty_state_title = s_("Todos|Nothing is on your to-do list. Nice work!")
|
||||
- if todos_filter_empty?
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
name: web_hook_test_api_endpoint_rate_limit
|
||||
feature_issue_url:
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/150066
|
||||
rollout_issue_url:
|
||||
milestone: '17.0'
|
||||
group: group::import and integrate
|
||||
type: ops
|
||||
default_enabled: true
|
||||
|
|
@ -83,6 +83,5 @@ DISCLAIMER:
|
|||
This page contains information related to upcoming products, features, and functionality.
|
||||
It is important to note that the information presented is for informational purposes only.
|
||||
Please do not rely on this information for purchasing or planning purposes.
|
||||
As with all projects, the items mentioned on this page are subject to change or delay.
|
||||
The development, release, and timing of any products, features, or functionality remain at the
|
||||
The development, release, and timing of any products, features, or functionality may be subject to change or delay and remain at the
|
||||
sole discretion of GitLab Inc.
|
||||
|
|
|
|||
|
|
@ -217,11 +217,18 @@ On multinode deployments, make sure that the issuer configured on the Sidekiq no
|
|||
|
||||
### Manually trigger a container registry sync event
|
||||
|
||||
To help with troubleshooting, you can manually trigger the container registry replication process by running the following commands on the secondary's Rails console:
|
||||
To help with troubleshooting, you can manually trigger the container registry replication process:
|
||||
|
||||
1. On the left sidebar, at the bottom, select **Admin Area**.
|
||||
1. Select **Geo > Sites**.
|
||||
1. In **Replication Details** for a **Secondary Site**, select **Container Repositories**.
|
||||
1. Select **Resync** for one row, or **Resync all**.
|
||||
|
||||
You can also manually trigger a resync by running the following commands on the secondary's Rails console:
|
||||
|
||||
```ruby
|
||||
registry = Geo::ContainerRepositoryRegistry.first # Choose a Geo registry entry
|
||||
registry.replicator.sync_repository # Resync the container repository
|
||||
registry.replicator.resync # Resync the container repository
|
||||
pp registry.reload # Look at replication state fields
|
||||
|
||||
#<Geo::ContainerRepositoryRegistry:0x00007f54c2a36060
|
||||
|
|
|
|||
|
|
@ -2876,9 +2876,14 @@ is returned.
|
|||
### Trigger a test project hook
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/147656) in GitLab 16.11.
|
||||
> - Special rate limit [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/150066) in GitLab 17.0 [with a flag](../administration/feature_flags.md) named `web_hook_test_api_endpoint_rate_limit`. Enabled by default.
|
||||
|
||||
Trigger a test hook for a specified project.
|
||||
|
||||
In GitLab 17.0 and later, this endpoint has a special rate limit of three requests per minute per project hook.
|
||||
To disable this limit on self-managed GitLab and GitLab Dedicated, an administrator can
|
||||
[disable the feature flag](../administration/feature_flags.md) named `web_hook_test_api_endpoint_rate_limit`.
|
||||
|
||||
```plaintext
|
||||
POST /projects/:id/hooks/:hook_id/test/:trigger
|
||||
```
|
||||
|
|
@ -2889,6 +2894,10 @@ POST /projects/:id/hooks/:hook_id/test/:trigger
|
|||
| `id` | integer or string | Yes | The ID or [URL-encoded path of the project](rest/index.md#namespaced-path-encoding). |
|
||||
| `trigger` | string | Yes | One of `push_events`, `tag_push_events`, `issues_events`, `confidential_issues_events`, `note_events`, `merge_requests_events`, `job_events`, `pipeline_events`, `wiki_page_events`, `releases_events`, `emoji_events`, or `resource_access_token_events`. |
|
||||
|
||||
```json
|
||||
{"message":"201 Created"}
|
||||
```
|
||||
|
||||
## Fork relationship
|
||||
|
||||
Allows modification of the forked relationship between existing projects.
|
||||
|
|
|
|||
|
|
@ -14,8 +14,7 @@ DISCLAIMER:
|
|||
This page contains information related to upcoming products, features, and functionality.
|
||||
It is important to note that the information presented is for informational purposes only.
|
||||
Please do not rely on this information for purchasing or planning purposes.
|
||||
As with all projects, the items mentioned on this page are subject to change or delay.
|
||||
The development, release, and timing of any products, features, or functionality remain at the
|
||||
The development, release, and timing of any products, features, or functionality may be subject to change or delay and remain at the
|
||||
sole discretion of GitLab Inc.
|
||||
|
||||
In GitLab 16.0, we introduced a new runner creation workflow that uses runner authentication tokens to register
|
||||
|
|
|
|||
|
|
@ -33,14 +33,22 @@ To connect a feature in an existing backend service to Cloud Connector:
|
|||
|
||||
#### GitLab Rails
|
||||
|
||||
1. Call `CloudConnector::AccessService.new.access_token(scopes: [...])` with the list of scopes your feature requires and include
|
||||
this token in the `Authorization` HTTP header field.
|
||||
Note that this can return `nil` if there is no valid token available. If there is no token, the call to Cloud Connector will
|
||||
not pass authorization, so it is recommended to return early.
|
||||
1. Call `CloudConnector::AvailableServices.find_by_name(:feature_name).access_token(user_or_namespace)`
|
||||
and include this token in the `Authorization` HTTP header field.
|
||||
|
||||
On GitLab.com, it will self-issue a token with scopes that depend on the provided resource:
|
||||
|
||||
- For a user: scopes will be based on the user's seat assignment
|
||||
- For a namespace: scopes will be based on purchased add-ons for this namespace
|
||||
- If a feature is a `free_access?` (no addon purchase is required): the token will include all available scopes for that feature
|
||||
|
||||
On self-managed, it will always return `::CloudConnector::ServiceAccessToken` instance token.
|
||||
|
||||
The backend service must validate this token and any scopes it carries when receiving the request.
|
||||
If you need to embed additional claims in the token specific to your use case, you can pass these
|
||||
in the `extra_claims` argument. **Scopes and other claims passed here will only be included in self-issued tokens on GitLab.com.**
|
||||
Refer to [CustomersDot](#customersdot) to see how custom claims are handled for self-managed instances.
|
||||
|
||||
1. Ensure your request sends the required headers to the [backend service](#backend-service).
|
||||
|
||||
These headers are:
|
||||
|
|
@ -53,26 +61,27 @@ Refer to [CustomersDot](#customersdot) to see how custom claims are handled for
|
|||
Some of these headers can be injected by merging the result of the `API::Helpers::CloudConnector#cloud_connector_headers`
|
||||
method to your payload.
|
||||
|
||||
The following example is for a request that includes the `new_feature_scope` scope.
|
||||
The following example is for a request to the feature called `:new_feature`.
|
||||
Here we assume your backend service is called `foo` and is already reachable at `https://cloud.gitlab.com/foo`.
|
||||
We also assume that the backend service exposes the feature using a `/new_feature_endpoint` endpoint.
|
||||
This allows clients to access the feature at `https://cloud.gitlab.com/foo/new_feature_endpoint`.
|
||||
|
||||
Here, the parameters you pass to `access_token` have the following meaning:
|
||||
|
||||
- `audience`: The name of the backend service. The token is bound to this backend
|
||||
using the JWT `aud` claim.
|
||||
- `scopes`: The list of access scopes carried in this token. They should map to access points
|
||||
in your backend, which could be HTTP endpoints or RPC calls.
|
||||
|
||||
```ruby
|
||||
include API::Helpers::CloudConnector
|
||||
|
||||
token = ::CloudConnector::AccessService.new.access_token(
|
||||
audience: 'foo',
|
||||
scopes: [:new_feature_scope]
|
||||
)
|
||||
return unauthorized! if token.nil?
|
||||
new_feature = ::CloudConnector::AvailableServices.find_by_name(:new_feature)
|
||||
|
||||
# (Optional) Handle the free access case separately, if needed
|
||||
if new_feature.free_access?
|
||||
# ...
|
||||
return
|
||||
end
|
||||
|
||||
# Check if the feature is available for the given user based on seat assignment, add-on purchases
|
||||
return unauthorized! unless new_feature.allowed_for?(current_user)
|
||||
|
||||
# Obtain a token
|
||||
token = new_feature.access_token(current_user)
|
||||
|
||||
Gitlab::HTTP.post(
|
||||
"https://cloud.gitlab.com/foo/new_feature_endpoint",
|
||||
|
|
@ -83,7 +92,7 @@ Gitlab::HTTP.post(
|
|||
```
|
||||
|
||||
NOTE:
|
||||
Any arguments you pass to `access_token` that configure the token returned only take hold for
|
||||
Any arguments you pass to `access_token` that configure the token returned (`user` or `namespace`, `extra_claims`) only take hold for
|
||||
tokens issued on GitLab.com. For self-managed GitLab instances the token is read as-is from
|
||||
the database and never modified.
|
||||
|
||||
|
|
|
|||
|
|
@ -286,8 +286,7 @@ DISCLAIMER:
|
|||
This page contains information related to upcoming products, features, and functionality.
|
||||
It is important to note that the information presented is for informational purposes only.
|
||||
Please do not rely on this information for purchasing or planning purposes.
|
||||
As with all projects, the items mentioned on this page are subject to change or delay.
|
||||
The development, release, and timing of any products, features, or functionality remain at the
|
||||
The development, release, and timing of any products, features, or functionality may be subject to change or delay and remain at the
|
||||
sole discretion of GitLab Inc.
|
||||
```
|
||||
|
||||
|
|
@ -297,8 +296,7 @@ DISCLAIMER:
|
|||
This page contains information related to upcoming products, features, and functionality.
|
||||
It is important to note that the information presented is for informational purposes only.
|
||||
Please do not rely on this information for purchasing or planning purposes.
|
||||
As with all projects, the items mentioned on this page are subject to change or delay.
|
||||
The development, release, and timing of any products, features, or functionality remain at the
|
||||
The development, release, and timing of any products, features, or functionality may be subject to change or delay and remain at the
|
||||
sole discretion of GitLab Inc.
|
||||
|
||||
If all of the content on the page is not available, use the disclaimer about forward-looking statements once at the top of the page.
|
||||
|
|
|
|||
|
|
@ -10,8 +10,7 @@ DISCLAIMER:
|
|||
This page contains information related to upcoming products, features, and functionality.
|
||||
It is important to note that the information presented is for informational purposes only.
|
||||
Please do not rely on this information for purchasing or planning purposes.
|
||||
As with all projects, the items mentioned on this page are subject to change or delay.
|
||||
The development, release, and timing of any products, features, or functionality remain at the
|
||||
The development, release, and timing of any products, features, or functionality may be subject to change or delay and remain at the
|
||||
sole discretion of GitLab Inc.
|
||||
|
||||
This page provides a high-level overview of the aggregated backend for
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 77 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 54 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 58 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 118 KiB |
|
|
@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** GitLab.com
|
||||
**Status:** Experiment
|
||||
**Status:** Beta
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/124966) in GitLab 16.7 [with a flag](../administration/feature_flags.md) named `observability_metrics`. Disabled by default. This feature is an [Experiment](../policy/experiment-beta-support.md#experiment).
|
||||
|
||||
|
|
@ -67,13 +67,36 @@ You can view the metrics for a given project:
|
|||
A list of metrics is displayed.
|
||||
Select a metric to view its details.
|
||||
|
||||

|
||||

|
||||
|
||||
Each metric contains one or more attributes. You can filter
|
||||
metrics by attribute with the search bar.
|
||||
|
||||
### Metric details
|
||||
|
||||
Metrics are displayed as either a sum, a gauge, or a histogram.
|
||||
The metric details page displays a chart depending on the type of metric.
|
||||
|
||||
On the metric details page, you can also view a metric for a specific time range.
|
||||
On the metric details page, you can also view metrics for a specific time range, and
|
||||
aggregate metrics by attribute:
|
||||
|
||||

|
||||

|
||||
|
||||
To make data lookups fast, depending on what time period you filter by,
|
||||
GitLab automatically chooses the proper aggregation.
|
||||
For example, if you search for more than seven days of data, the API returns only daily aggregates.
|
||||
|
||||
### Aggregations by search period
|
||||
|
||||
The following table shows what type of aggregation is used for each search period:
|
||||
|
||||
|Period|Aggregation used|
|
||||
|---|---|
|
||||
| Less than 30 minutes | Raw data as ingested |
|
||||
| More than 30 minutes and less than one hour | By minute |
|
||||
| More than one hour and less than 72 hours | Hourly |
|
||||
| More than 72 hours | Daily |
|
||||
|
||||
### Data retention
|
||||
|
||||
GitLab has a retention limit of 30 days for all ingested metrics.
|
||||
|
|
|
|||
|
|
@ -172,3 +172,18 @@ Prerequisites:
|
|||
1. Select **Submit**.
|
||||
|
||||
The trial automatically syncs to your instance within 24 hours. After the trial has synced, [assign seats](#assign-gitlab-duo-pro-seats) to users that you want to access GitLab Duo Pro.
|
||||
|
||||
## Automatic seat removal for seat overages
|
||||
|
||||
If your quantity of purchased GitLab Duo Pro seats is reduced, seat assignments are automatically removed to match the seat quantity available in the subscription.
|
||||
|
||||
For example:
|
||||
|
||||
- You have a 50 seat GitLab Duo Pro subscription with all seats assigned.
|
||||
- You renew the subscription for 30 seats. The 20 users over subscription are automatically removed from GitLab Duo Pro seat assignment.
|
||||
- If only 20 users were assigned a GitLab Duo Pro seat before renewal, then no removal of seats would occur.
|
||||
|
||||
Seats are selected for removal based on the following criteria, in this order:
|
||||
|
||||
1. Users who have not yet used Code Suggestions, ordered by most recently assigned.
|
||||
1. Users who have used Code Suggestions, ordered by least recent usage of Code Suggestions.
|
||||
|
|
|
|||
|
|
@ -5721,6 +5721,5 @@ DISCLAIMER:
|
|||
This page contains information related to upcoming products, features, and functionality.
|
||||
It is important to note that the information presented is for informational purposes only.
|
||||
Please do not rely on this information for purchasing or planning purposes.
|
||||
As with all projects, the items mentioned on this page are subject to change or delay.
|
||||
The development, release, and timing of any products, features, or functionality remain at the
|
||||
The development, release, and timing of any products, features, or functionality may be subject to change or delay and remain at the
|
||||
sole discretion of GitLab Inc.
|
||||
|
|
|
|||
|
|
@ -63,15 +63,22 @@ To enable Beta and Experimental AI-powered features, use the [Experiment and Bet
|
|||
|
||||
To enable Beta and Experimental AI-powered features for GitLab versions where GitLab Duo Chat is not yet generally available, see the [GitLab Duo Chat documentation](gitlab_duo_chat.md#for-self-managed).
|
||||
|
||||
### Enable outbound connections to enable GitLab Duo features on self-managed instances
|
||||
### Network Requirements to enable GitLab Duo features for self-managed GitLab
|
||||
|
||||
#### Enable outbound connections from GitLab instances
|
||||
|
||||
- Your firewalls and HTTP/S proxy servers must allow outbound connections
|
||||
to `cloud.gitlab.com` and `customers.gitlab.com` on port `443` both with `https://` and `wws://`.
|
||||
- Both `HTTP2` and the `'upgrade'` header must be allowed, because GitLab Duo
|
||||
uses both REST and WebSockets.
|
||||
to `cloud.gitlab.com` and `customers.gitlab.com` on port `443` both with `https://`.
|
||||
- To use an HTTP/S proxy, both `gitLab_workhorse` and `gitLab_rails` must have the necessary
|
||||
[web proxy environment variables](https://docs.gitlab.com/omnibus/settings/environment-variables.html) set.
|
||||
- Check for restrictions on WebSocket (`wss://`) traffic to `wss://gitlab.com/-/cable` and other `.com` domains.
|
||||
|
||||
#### Enable inbound connections from Clients to GitLab instances
|
||||
|
||||
- GitLab instances must allow inbound connections from Duo clients (IDEs, Code Editors, and GitLab Web Frontend)
|
||||
on port 443 with `https://` and `wss://`.
|
||||
- Both `HTTP2` and the `'upgrade'` header must be allowed, because GitLab Duo
|
||||
uses both REST and WebSockets.
|
||||
- Check for restrictions on WebSocket (`wss://`) traffic to `wss://gitlab.example.com/-/cable` and other `.com` domains.
|
||||
Network policy restrictions on `wss://` traffic can cause issues with some GitLab Duo Chat
|
||||
services. Consider policy updates to allow these services.
|
||||
|
||||
|
|
|
|||
|
|
@ -114,8 +114,7 @@ DISCLAIMER:
|
|||
This page contains information related to upcoming products, features, and functionality.
|
||||
It is important to note that the information presented is for informational purposes only.
|
||||
Please do not rely on this information for purchasing or planning purposes.
|
||||
As with all projects, the items mentioned on this page are subject to change or delay.
|
||||
The development, release, and timing of any products, features, or functionality remain at the
|
||||
The development, release, and timing of any products, features, or functionality may be subject to change or delay and remain at the
|
||||
sole discretion of GitLab Inc.
|
||||
|
||||
Perform Out-of-Band Application Security Testing (OAST) for certain [active checks](../dast/browser/checks/index.md#active-checks).
|
||||
|
|
|
|||
|
|
@ -17,8 +17,7 @@ DISCLAIMER:
|
|||
This page contains information related to upcoming products, features, and functionality.
|
||||
It is important to note that the information presented is for informational purposes only.
|
||||
Please do not rely on this information for purchasing or planning purposes.
|
||||
As with all projects, the items mentioned on this page are subject to change or delay.
|
||||
The development, release, and timing of any products, features, or functionality remain at the
|
||||
The development, release, and timing of any products, features, or functionality may be subject to change or delay and remain at the
|
||||
sole discretion of GitLab Inc.
|
||||
|
||||
NOTE:
|
||||
|
|
|
|||
|
|
@ -146,7 +146,8 @@ module API
|
|||
failure [
|
||||
{ code: 400, message: 'Bad request' },
|
||||
{ code: 404, message: 'Not found' },
|
||||
{ code: 422, message: 'Unprocessable entity' }
|
||||
{ code: 422, message: 'Unprocessable entity' },
|
||||
{ code: 429, message: 'Too many requests' }
|
||||
]
|
||||
end
|
||||
params do
|
||||
|
|
@ -155,8 +156,13 @@ module API
|
|||
desc: 'The type of trigger hook',
|
||||
values: ProjectHook.triggers.values.map(&:to_s)
|
||||
end
|
||||
post ":id/hooks/:hook_id/test/:trigger" do
|
||||
post ":id/hooks/:hook_id/test/:trigger", urgency: :low do
|
||||
hook = find_hook
|
||||
|
||||
if Feature.enabled?(:web_hook_test_api_endpoint_rate_limit)
|
||||
check_rate_limit!(:web_hook_test_api_endpoint, scope: hook)
|
||||
end
|
||||
|
||||
result = TestHooks::ProjectService.new(hook, current_user, params[:trigger]).execute
|
||||
success = (200..299).cover?(result.payload[:http_status])
|
||||
if success
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ module Gitlab
|
|||
web_hook_calls: { interval: 1.minute },
|
||||
web_hook_calls_mid: { interval: 1.minute },
|
||||
web_hook_calls_low: { interval: 1.minute },
|
||||
web_hook_test_api_endpoint: { threshold: 3, interval: 1.minute },
|
||||
users_get_by_id: { threshold: -> { application_settings.users_get_by_id_limit }, interval: 10.minutes },
|
||||
username_exists: { threshold: 20, interval: 1.minute },
|
||||
user_sign_up: { threshold: 20, interval: 1.minute },
|
||||
|
|
|
|||
|
|
@ -159,27 +159,3 @@ gemnasium-python-dependency_scanning:
|
|||
- if: $CI_COMMIT_BRANCH &&
|
||||
$GITLAB_FEATURES =~ /\bdependency_scanning\b/ &&
|
||||
$PIP_REQUIREMENTS_FILE
|
||||
|
||||
bundler-audit-dependency_scanning:
|
||||
extends: .ds-analyzer
|
||||
variables:
|
||||
DS_ANALYZER_NAME: "bundler-audit"
|
||||
DS_MAJOR_VERSION: 2
|
||||
script:
|
||||
- echo "This job was deprecated in GitLab 14.8 and removed in GitLab 15.0"
|
||||
- echo "For more information see https://gitlab.com/gitlab-org/gitlab/-/issues/347491"
|
||||
- exit 1
|
||||
rules:
|
||||
- when: never
|
||||
|
||||
retire-js-dependency_scanning:
|
||||
extends: .ds-analyzer
|
||||
variables:
|
||||
DS_ANALYZER_NAME: "retire.js"
|
||||
DS_MAJOR_VERSION: 2
|
||||
script:
|
||||
- echo "This job was deprecated in GitLab 14.8 and removed in GitLab 15.0"
|
||||
- echo "For more information see https://gitlab.com/gitlab-org/gitlab/-/issues/289830"
|
||||
- exit 1
|
||||
rules:
|
||||
- when: never
|
||||
|
|
|
|||
|
|
@ -46587,6 +46587,9 @@ msgstr ""
|
|||
msgid "SecurityOrchestration|No exceptions"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|No policies in the security policy project will be enforced until the invalid policies are fixed."
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|No rules defined - policy will not run."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -46634,6 +46637,9 @@ msgstr ""
|
|||
msgid "SecurityOrchestration|Policies"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Policies are invalid"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Policy Type"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -46646,15 +46652,15 @@ msgstr ""
|
|||
msgid "SecurityOrchestration|Policy changes may take some time to be applied."
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Policy contains deprecated syntax"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Policy definition"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Policy editor"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Policy is invalid"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Policy scope"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -46847,9 +46853,6 @@ msgstr ""
|
|||
msgid "SecurityOrchestration|This policy is inherited from the %{linkStart}namespace%{linkEnd} and must be edited there"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|This policy won't work after GitLab 17.0 (May 16, 2024). You must edit the policy and replace the deprecated syntax%{deprecatedProperties}. For details on which syntax has been deprecated, see %{linkStart}Documentation%{linkEnd}."
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|This project"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -46940,6 +46943,9 @@ msgstr ""
|
|||
msgid "SecurityOrchestration|You don't have any security policies yet"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|You must edit the policy and replace the deprecated syntax%{deprecatedProperties}. For details on it's replacement, see the %{linkStart}policy documentation%{linkEnd}."
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|You must select one or more compliance frameworks to which this policy should apply."
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@
|
|||
"@gitlab/favicon-overlay": "2.0.0",
|
||||
"@gitlab/fonts": "^1.3.0",
|
||||
"@gitlab/svgs": "3.97.0",
|
||||
"@gitlab/ui": "79.3.0",
|
||||
"@gitlab/ui": "79.4.1",
|
||||
"@gitlab/web-ide": "^0.0.1-dev-20240422132849",
|
||||
"@mattiasbuelens/web-streams-adapter": "^0.1.0",
|
||||
"@rails/actioncable": "7.0.8-1",
|
||||
|
|
@ -139,7 +139,7 @@
|
|||
"deckar01-task_list": "^2.3.1",
|
||||
"dexie": "^3.2.3",
|
||||
"diff": "^3.4.0",
|
||||
"dompurify": "^3.1.1",
|
||||
"dompurify": "^3.1.2",
|
||||
"dropzone": "^4.2.0",
|
||||
"editorconfig": "^0.15.3",
|
||||
"emoji-regex": "^10.0.0",
|
||||
|
|
|
|||
|
|
@ -12,79 +12,16 @@ exports[`Registry Breadcrumb when is not rootRoute renders 1`] = `
|
|||
<li
|
||||
class="gl-breadcrumb-item"
|
||||
>
|
||||
<div
|
||||
class="gl-disclosure-dropdown gl-new-dropdown"
|
||||
style="height: 16px;"
|
||||
<a
|
||||
target="_self"
|
||||
>
|
||||
<button
|
||||
aria-controls="reference-1"
|
||||
aria-expanded="false"
|
||||
aria-labelledby="reference-0"
|
||||
class="btn btn-default btn-icon btn-sm gl-button gl-new-dropdown-icon-only gl-new-dropdown-toggle gl-new-dropdown-toggle-no-caret"
|
||||
data-testid="base-dropdown-toggle"
|
||||
id="reference-0"
|
||||
type="button"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="gl-button-icon gl-icon s16"
|
||||
data-testid="ellipsis_h-icon"
|
||||
role="img"
|
||||
>
|
||||
<use
|
||||
href="file-mock#ellipsis_h"
|
||||
/>
|
||||
</svg>
|
||||
<span
|
||||
class="gl-button-text"
|
||||
>
|
||||
<span
|
||||
class="gl-new-dropdown-button-text gl-sr-only"
|
||||
>
|
||||
Show more breadcrumbs
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
<div
|
||||
class="gl-new-dropdown-panel"
|
||||
data-testid="base-dropdown-menu"
|
||||
id="reference-1"
|
||||
>
|
||||
<div
|
||||
class="gl-new-dropdown-inner"
|
||||
>
|
||||
<ul
|
||||
aria-labelledby="reference-0"
|
||||
class="gl-new-dropdown-contents"
|
||||
data-testid="disclosure-content"
|
||||
id="reference-2"
|
||||
tabindex="-1"
|
||||
>
|
||||
<li
|
||||
class="gl-new-dropdown-item"
|
||||
data-testid="disclosure-dropdown-item"
|
||||
tabindex="0"
|
||||
>
|
||||
<a
|
||||
class="gl-new-dropdown-item-content"
|
||||
tabindex="-1"
|
||||
target="_self"
|
||||
>
|
||||
<span
|
||||
class="gl-new-dropdown-item-text-wrapper"
|
||||
>
|
||||
mock name
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span>
|
||||
mock name
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li
|
||||
class="gl-breadcrumb-item"
|
||||
style="flex-shrink: 1; text-overflow: ellipsis; overflow-x: hidden; text-wrap: nowrap;"
|
||||
>
|
||||
<a
|
||||
aria-current="page"
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import {
|
|||
} from '@gitlab/ui';
|
||||
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import InviteMembersTrigger from '~/invite_members/components/invite_members_trigger.vue';
|
||||
import CreateWorkItemModal from '~/work_items/components/create_work_item_modal.vue';
|
||||
import { __ } from '~/locale';
|
||||
import CreateMenu from '~/super_sidebar/components/create_menu.vue';
|
||||
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
|
||||
|
|
@ -18,6 +19,7 @@ describe('CreateMenu component', () => {
|
|||
const findGlDisclosureDropdownGroups = () => wrapper.findAllComponents(GlDisclosureDropdownGroup);
|
||||
const findGlDisclosureDropdownItems = () => wrapper.findAllComponents(GlDisclosureDropdownItem);
|
||||
const findInviteMembersTrigger = () => wrapper.findComponent(InviteMembersTrigger);
|
||||
const findCreateWorkItemModal = () => wrapper.findComponent(CreateWorkItemModal);
|
||||
|
||||
const createWrapper = ({ provide = {} } = {}) => {
|
||||
wrapper = shallowMountExtended(CreateMenu, {
|
||||
|
|
@ -30,6 +32,7 @@ describe('CreateMenu component', () => {
|
|||
},
|
||||
stubs: {
|
||||
InviteMembersTrigger,
|
||||
CreateWorkItemModal,
|
||||
GlDisclosureDropdown,
|
||||
GlEmoji: { template: '<div/>' },
|
||||
},
|
||||
|
|
@ -77,6 +80,10 @@ describe('CreateMenu component', () => {
|
|||
expect(findInviteMembersTrigger().exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('renders the create new work item modal', () => {
|
||||
expect(findCreateWorkItemModal().exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('hides the tooltip when the dropdown is opened', async () => {
|
||||
findGlDisclosureDropdown().vm.$emit('shown');
|
||||
await nextTick();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,47 @@
|
|||
import invalidUrl from '~/lib/utils/invalid_url';
|
||||
|
||||
export const createNewMenuGroups = [
|
||||
{
|
||||
name: 'This group',
|
||||
items: [
|
||||
{
|
||||
text: 'New project/repository',
|
||||
href: '/projects/new?namespace_id=22',
|
||||
},
|
||||
{
|
||||
text: 'New subgroup',
|
||||
href: '/groups/new?parent_id=22#create-group-pane',
|
||||
},
|
||||
{
|
||||
text: 'New epic',
|
||||
component: 'create_new_work_item_modal',
|
||||
},
|
||||
{
|
||||
text: 'Invite members',
|
||||
component: 'invite_members',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'GitLab',
|
||||
items: [
|
||||
{
|
||||
text: 'New project/repository',
|
||||
href: '/projects/new',
|
||||
},
|
||||
{
|
||||
text: 'New group',
|
||||
href: '/groups/new',
|
||||
},
|
||||
{
|
||||
text: 'New snippet',
|
||||
href: '/-/snippets/new',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export const createNewMenuGroupsLegacy = [
|
||||
{
|
||||
name: 'This group',
|
||||
items: [
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ exports[`History Item renders the correct markup 1`] = `
|
|||
class="timeline-entry-inner"
|
||||
>
|
||||
<div
|
||||
class="gl--flex-center gl-bg-gray-50 gl-float-left gl-h-6 gl-ml-2 gl-mt-n1 gl-rounded-full gl-text-gray-600 gl-w-6"
|
||||
class="-gl-mt-1 gl--flex-center gl-bg-gray-50 gl-float-left gl-h-6 gl-ml-2 gl-rounded-full gl-text-gray-600 gl-w-6"
|
||||
>
|
||||
<gl-icon-stub
|
||||
name="pencil"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { nextTick } from 'vue';
|
||||
import { GlModal } from '@gitlab/ui';
|
||||
import { GlDisclosureDropdownItem, GlModal } from '@gitlab/ui';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import CreateWorkItem from '~/work_items/components/create_work_item.vue';
|
||||
import CreateWorkItemModal from '~/work_items/components/create_work_item_modal.vue';
|
||||
|
|
@ -13,13 +13,15 @@ describe('CreateWorkItemModal', () => {
|
|||
let wrapper;
|
||||
|
||||
const findTrigger = () => wrapper.find('[data-testid="new-epic-button"]');
|
||||
const findDropdownItem = () => wrapper.findComponent(GlDisclosureDropdownItem);
|
||||
const findModal = () => wrapper.findComponent(GlModal);
|
||||
const findForm = () => wrapper.findComponent(CreateWorkItem);
|
||||
|
||||
const createComponent = ({ workItemType } = {}) => {
|
||||
const createComponent = ({ workItemType, asDropdownItem = false } = {}) => {
|
||||
wrapper = shallowMount(CreateWorkItemModal, {
|
||||
propsData: {
|
||||
workItemType,
|
||||
asDropdownItem,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
|
@ -38,14 +40,24 @@ describe('CreateWorkItemModal', () => {
|
|||
expect(visitUrl).toHaveBeenCalledWith('/');
|
||||
});
|
||||
|
||||
it('opens modal on trigger click', async () => {
|
||||
createComponent();
|
||||
describe('default trigger', () => {
|
||||
it('opens modal on trigger click', async () => {
|
||||
createComponent();
|
||||
|
||||
findTrigger().vm.$emit('click');
|
||||
findTrigger().vm.$emit('click');
|
||||
|
||||
await nextTick();
|
||||
await nextTick();
|
||||
|
||||
expect(findModal().props('visible')).toBe(true);
|
||||
expect(findModal().props('visible')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('dropdown item trigger', () => {
|
||||
it('renders a dropdown item component', () => {
|
||||
createComponent({ asDropdownItem: true });
|
||||
|
||||
expect(findDropdownItem().exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('closes modal on cancel event from form', () => {
|
||||
|
|
|
|||
|
|
@ -179,7 +179,8 @@ RSpec.describe SidebarsHelper, feature_category: :navigation do
|
|||
pinned_items: %w[foo bar],
|
||||
update_pins_url: pins_path,
|
||||
shortcut_links: global_shortcut_links,
|
||||
track_visits_path: track_namespace_visits_path
|
||||
track_visits_path: track_namespace_visits_path,
|
||||
work_items: { full_path: group.full_path }
|
||||
})
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -67,13 +67,38 @@ RSpec.describe API::ProjectHooks, 'ProjectHooks', feature_category: :webhooks do
|
|||
{ push_events: true, confidential_note_events: nil }
|
||||
end
|
||||
|
||||
context "when trigger project webhook test", :aggregate_failures do
|
||||
context "when trigger project webhook test", :aggregate_failures, :clean_gitlab_redis_rate_limiting do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
before do
|
||||
stub_full_request(hook.url, method: :post).to_return(status: 200)
|
||||
end
|
||||
|
||||
specify do
|
||||
expect(post(api("#{hook_uri}/test/push_events", user), params: {}))
|
||||
.to have_request_urgency(:low)
|
||||
end
|
||||
|
||||
it_behaves_like 'rate limited endpoint', rate_limit_key: :web_hook_test_api_endpoint do
|
||||
let(:current_user) { user }
|
||||
|
||||
def request
|
||||
post api("#{hook_uri}/test/push_events", user), params: {}
|
||||
end
|
||||
|
||||
context 'when ops flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(web_hook_test_api_endpoint_rate_limit: false)
|
||||
end
|
||||
|
||||
it 'does not block the request' do
|
||||
request
|
||||
|
||||
expect(response).to have_gitlab_http_status(:created)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when testing is not available for trigger' do
|
||||
where(:trigger_name) do
|
||||
%w[confidential_note_events deployment_events feature_flag_events]
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ RSpec.shared_examples 'web-hook API endpoints' do |prefix|
|
|||
expect(json_response[k.to_s]).to eq(v)
|
||||
end
|
||||
event_names.each do |name|
|
||||
expect(json_response[name.to_s]).to eq(true), name
|
||||
expect(json_response[name.to_s]).to eq(true), name.to_s
|
||||
end
|
||||
expect(json_response['url_variables']).to match_array [
|
||||
{ 'key' => 'token' },
|
||||
|
|
@ -232,7 +232,7 @@ RSpec.shared_examples 'web-hook API endpoints' do |prefix|
|
|||
expect(response).to match_hook_schema
|
||||
expect(json_response['enable_ssl_verification']).to be true
|
||||
event_names.each do |name|
|
||||
expect(json_response[name.to_s]).to eq(default_values.fetch(name, false)), name
|
||||
expect(json_response[name.to_s]).to eq(default_values.fetch(name, false)), name.to_s
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
16
yarn.lock
16
yarn.lock
|
|
@ -1331,10 +1331,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-3.97.0.tgz#d6ffbfdf1a7b78fa35bc9ebec0b3d34376ccee58"
|
||||
integrity sha512-Bt/3k+mHY3Qi+2xjl7tTkhfBMiG8XeE0dTrR+/e6QITYqc7/L/QUFey1iym0cfv1y+iddcUZKDCfgdFyCRnEhg==
|
||||
|
||||
"@gitlab/ui@79.3.0":
|
||||
version "79.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-79.3.0.tgz#7aae82e23e79aae77c6bad074f3d5a273da7eee5"
|
||||
integrity sha512-LWallyRPizI/wVx+Ykm3VuvVcfYQBlUtmphTHkgU41r4Iq8VzhxrrzxQo2lVYFVCJFi260hyBguE+WwFkW0HjA==
|
||||
"@gitlab/ui@79.4.1":
|
||||
version "79.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-79.4.1.tgz#500753516a4f35b4ea71b01916cc2f771f3baf3f"
|
||||
integrity sha512-wvCqDaaFiveTsm+XasdMP0Rvk2iGO3BZCSpKSfiwgdj8NrNfyEH7Bs1ZXjaXVeiLM5XvNO30sUwAaK7e+lAvtg==
|
||||
dependencies:
|
||||
"@floating-ui/dom" "1.4.3"
|
||||
bootstrap-vue "2.23.1"
|
||||
|
|
@ -6185,10 +6185,10 @@ dommatrix@^1.0.3:
|
|||
resolved "https://registry.yarnpkg.com/dommatrix/-/dommatrix-1.0.3.tgz#e7c18e8d6f3abdd1fef3dd4aa74c4d2e620a0525"
|
||||
integrity sha512-l32Xp/TLgWb8ReqbVJAFIvXmY7go4nTxxlWiAFyhoQw9RKEOHBZNnyGvJWqDVSPmq3Y9HlM4npqF/T6VMOXhww==
|
||||
|
||||
dompurify@^3.0.5, dompurify@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.1.1.tgz#e83de1e0ba7f1014f36686fbc63a2a3a1bdb93f6"
|
||||
integrity sha512-tVP8C/GJwnABOn/7cx/ymx/hXpmBfWIPihC1aOEvS8GbMqy3pgeYtJk1HXN3CO7tu+8bpY18f6isjR5Cymj0TQ==
|
||||
dompurify@^3.0.5, dompurify@^3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.1.2.tgz#d1e158457e00666ab40c9c3d8aab57586a072bd1"
|
||||
integrity sha512-hLGGBI1tw5N8qTELr3blKjAML/LY4ANxksbS612UiJyDfyf/2D092Pvm+S7pmeTGJRqvlJkFzBoHBQKgQlOQVg==
|
||||
|
||||
dropzone@^4.2.0:
|
||||
version "4.2.0"
|
||||
|
|
|
|||
Loading…
Reference in New Issue