Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
b9f4411b1b
commit
cbb6a29694
|
|
@ -76,7 +76,7 @@ workflow:
|
||||||
# they serve no purpose and will run anyway when the changes are merged.
|
# they serve no purpose and will run anyway when the changes are merged.
|
||||||
- if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^release-tools\/\d+\.\d+\.\d+-rc\d+$/ && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME =~ /^[\d-]+-stable(-ee)?$/ && $CI_PROJECT_PATH == "gitlab-org/gitlab"'
|
- if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^release-tools\/\d+\.\d+\.\d+-rc\d+$/ && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME =~ /^[\d-]+-stable(-ee)?$/ && $CI_PROJECT_PATH == "gitlab-org/gitlab"'
|
||||||
when: never
|
when: never
|
||||||
- if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:run-in-ruby3_1/'
|
- if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:run-in-ruby3_1/ || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME =~ /^[\d-]+-stable(-ee)?$/'
|
||||||
variables:
|
variables:
|
||||||
<<: [*default-ruby-variables, *default-merge-request-variables]
|
<<: [*default-ruby-variables, *default-merge-request-variables]
|
||||||
PIPELINE_NAME: 'Ruby $RUBY_VERSION MR'
|
PIPELINE_NAME: 'Ruby $RUBY_VERSION MR'
|
||||||
|
|
|
||||||
|
|
@ -220,7 +220,7 @@
|
||||||
{"name":"gitlab-glfm-markdown","version":"0.0.17","platform":"ruby","checksum":"f379545fc53a71c31525025fdb422f46081133af5cced3130ce680b155c2aa69"},
|
{"name":"gitlab-glfm-markdown","version":"0.0.17","platform":"ruby","checksum":"f379545fc53a71c31525025fdb422f46081133af5cced3130ce680b155c2aa69"},
|
||||||
{"name":"gitlab-glfm-markdown","version":"0.0.17","platform":"x86_64-darwin","checksum":"50e0f4865ef7c455426c7c058fc10ff9c8366482d48a63d6f6693b38c4a49c1c"},
|
{"name":"gitlab-glfm-markdown","version":"0.0.17","platform":"x86_64-darwin","checksum":"50e0f4865ef7c455426c7c058fc10ff9c8366482d48a63d6f6693b38c4a49c1c"},
|
||||||
{"name":"gitlab-glfm-markdown","version":"0.0.17","platform":"x86_64-linux","checksum":"cc877ff8ceb3aa8a331fdb8991592e35897823e0f77ba9e4b2b65082c665089b"},
|
{"name":"gitlab-glfm-markdown","version":"0.0.17","platform":"x86_64-linux","checksum":"cc877ff8ceb3aa8a331fdb8991592e35897823e0f77ba9e4b2b65082c665089b"},
|
||||||
{"name":"gitlab-labkit","version":"0.36.0","platform":"ruby","checksum":"35f21d1c3870ed0c9b8321e25d0b0b0b5021805a5d0525d1eb0fde6b103af981"},
|
{"name":"gitlab-labkit","version":"0.36.1","platform":"ruby","checksum":"04fb6941b7e5fc1fdcee8f9971fa2086a4dc442e39e67a74b992403dd580c300"},
|
||||||
{"name":"gitlab-license","version":"2.5.0","platform":"ruby","checksum":"4c166c469c2ad17876ca43188a4ccebe3feb0726c4c1770047f8dcef96573f4d"},
|
{"name":"gitlab-license","version":"2.5.0","platform":"ruby","checksum":"4c166c469c2ad17876ca43188a4ccebe3feb0726c4c1770047f8dcef96573f4d"},
|
||||||
{"name":"gitlab-mail_room","version":"0.0.25","platform":"ruby","checksum":"223ce7c3c0797b6015eaa37147884e6ddc7be9a7ee90a424358c96bc18613b1a"},
|
{"name":"gitlab-mail_room","version":"0.0.25","platform":"ruby","checksum":"223ce7c3c0797b6015eaa37147884e6ddc7be9a7ee90a424358c96bc18613b1a"},
|
||||||
{"name":"gitlab-markup","version":"1.9.0","platform":"ruby","checksum":"7eda045a08ec2d110084252fa13a8c9eac8bdac0e302035ca7db4b82bcbd7ed4"},
|
{"name":"gitlab-markup","version":"1.9.0","platform":"ruby","checksum":"7eda045a08ec2d110084252fa13a8c9eac8bdac0e302035ca7db4b82bcbd7ed4"},
|
||||||
|
|
|
||||||
|
|
@ -706,7 +706,7 @@ GEM
|
||||||
mime-types
|
mime-types
|
||||||
gitlab-glfm-markdown (0.0.17)
|
gitlab-glfm-markdown (0.0.17)
|
||||||
rb_sys (= 0.9.94)
|
rb_sys (= 0.9.94)
|
||||||
gitlab-labkit (0.36.0)
|
gitlab-labkit (0.36.1)
|
||||||
actionpack (>= 5.0.0, < 8.0.0)
|
actionpack (>= 5.0.0, < 8.0.0)
|
||||||
activesupport (>= 5.0.0, < 8.0.0)
|
activesupport (>= 5.0.0, < 8.0.0)
|
||||||
grpc (>= 1.62)
|
grpc (>= 1.62)
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ export default {
|
||||||
<gl-collapsible-listbox
|
<gl-collapsible-listbox
|
||||||
v-model="selected"
|
v-model="selected"
|
||||||
:items="databases"
|
:items="databases"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
:toggle-text="selectedDatabase"
|
:toggle-text="selectedDatabase"
|
||||||
toggle-aria-labelled-by="label"
|
toggle-aria-labelled-by="label"
|
||||||
@select="selectDatabase"
|
@select="selectDatabase"
|
||||||
|
|
|
||||||
|
|
@ -206,7 +206,7 @@ export default {
|
||||||
<template>
|
<template>
|
||||||
<gl-disclosure-dropdown
|
<gl-disclosure-dropdown
|
||||||
ref="submitDropdown"
|
ref="submitDropdown"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
class="submit-review-dropdown"
|
class="submit-review-dropdown"
|
||||||
:class="{ 'submit-review-dropdown-animated': shouldAnimateReviewButton }"
|
:class="{ 'submit-review-dropdown-animated': shouldAnimateReviewButton }"
|
||||||
data-testid="submit-review-dropdown"
|
data-testid="submit-review-dropdown"
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,7 @@ export default {
|
||||||
:toggle-text="$options.i18n.toggleText"
|
:toggle-text="$options.i18n.toggleText"
|
||||||
icon="ellipsis_v"
|
icon="ellipsis_v"
|
||||||
category="tertiary"
|
category="tertiary"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
data-testid="branch-more-actions"
|
data-testid="branch-more-actions"
|
||||||
text-sr-only
|
text-sr-only
|
||||||
no-caret
|
no-caret
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,7 @@ export default {
|
||||||
icon="ellipsis_v"
|
icon="ellipsis_v"
|
||||||
category="tertiary"
|
category="tertiary"
|
||||||
no-caret
|
no-caret
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
class="gl-hidden md:!gl-block"
|
class="gl-hidden md:!gl-block"
|
||||||
:items="dropdownItems"
|
:items="dropdownItems"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -157,7 +157,7 @@ export default {
|
||||||
text-sr-only
|
text-sr-only
|
||||||
icon="ellipsis_v"
|
icon="ellipsis_v"
|
||||||
category="tertiary"
|
category="tertiary"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
class="note-action-button more-actions-toggle"
|
class="note-action-button more-actions-toggle"
|
||||||
no-caret
|
no-caret
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,7 @@ export default {
|
||||||
v-else-if="isManualJob"
|
v-else-if="isManualJob"
|
||||||
icon="retry"
|
icon="retry"
|
||||||
category="primary"
|
category="primary"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
positioning-strategy="fixed"
|
positioning-strategy="fixed"
|
||||||
variant="confirm"
|
variant="confirm"
|
||||||
:items="dropdownItems"
|
:items="dropdownItems"
|
||||||
|
|
|
||||||
|
|
@ -135,7 +135,7 @@ export default {
|
||||||
:aria-label="$options.i18n.downloadArtifacts"
|
:aria-label="$options.i18n.downloadArtifacts"
|
||||||
:items="items"
|
:items="items"
|
||||||
icon="download"
|
icon="download"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
text-sr-only
|
text-sr-only
|
||||||
data-testid="pipeline-multi-actions-dropdown"
|
data-testid="pipeline-multi-actions-dropdown"
|
||||||
@shown="onDisclosureDropdownShown"
|
@shown="onDisclosureDropdownShown"
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ export default {
|
||||||
:toggle-text="$options.i18n.artifacts"
|
:toggle-text="$options.i18n.artifacts"
|
||||||
:aria-label="$options.i18n.artifacts"
|
:aria-label="$options.i18n.artifacts"
|
||||||
icon="download"
|
icon="download"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
text-sr-only
|
text-sr-only
|
||||||
:items="items"
|
:items="items"
|
||||||
data-testid="artifacts-dropdown"
|
data-testid="artifacts-dropdown"
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ export default {
|
||||||
v-if="actionItems.length"
|
v-if="actionItems.length"
|
||||||
category="primary"
|
category="primary"
|
||||||
variant="confirm"
|
variant="confirm"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
:toggle-text="defaultActionText"
|
:toggle-text="defaultActionText"
|
||||||
:items="actionItems"
|
:items="actionItems"
|
||||||
:disabled="!canAddCluster"
|
:disabled="!canAddCluster"
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ export default {
|
||||||
icon="ellipsis_v"
|
icon="ellipsis_v"
|
||||||
no-caret
|
no-caret
|
||||||
text-sr-only
|
text-sr-only
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
:toggle-text="__('Comment template actions')"
|
:toggle-text="__('Comment template actions')"
|
||||||
:loading="isDeleting"
|
:loading="isDeleting"
|
||||||
category="tertiary"
|
category="tertiary"
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ export default {
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
placement() {
|
placement() {
|
||||||
return this.right ? 'right' : 'left';
|
return this.right ? 'bottom-end' : 'bottom-start';
|
||||||
},
|
},
|
||||||
newCustomEmoji() {
|
newCustomEmoji() {
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
|
|
@ -824,7 +824,7 @@ export default {
|
||||||
no-caret
|
no-caret
|
||||||
icon="ellipsis_v"
|
icon="ellipsis_v"
|
||||||
category="secondary"
|
category="secondary"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
:toggle-text="__('More actions')"
|
:toggle-text="__('More actions')"
|
||||||
>
|
>
|
||||||
<rollback-component
|
<rollback-component
|
||||||
|
|
|
||||||
|
|
@ -372,7 +372,7 @@ export default {
|
||||||
block
|
block
|
||||||
:toggle-text="__('Options')"
|
:toggle-text="__('Options')"
|
||||||
toggle-class="md:gl-hidden"
|
toggle-class="md:gl-hidden"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
:disabled="issueUpdateInProgress"
|
:disabled="issueUpdateInProgress"
|
||||||
:items="dropdownItems"
|
:items="dropdownItems"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -292,6 +292,7 @@ export const resolvers = {
|
||||||
healthStatus,
|
healthStatus,
|
||||||
isGroup,
|
isGroup,
|
||||||
fullPath,
|
fullPath,
|
||||||
|
workItemType,
|
||||||
assignees,
|
assignees,
|
||||||
color,
|
color,
|
||||||
title,
|
title,
|
||||||
|
|
@ -301,9 +302,10 @@ export const resolvers = {
|
||||||
const query = isGroup ? groupWorkItemByIidQuery : workItemByIidQuery;
|
const query = isGroup ? groupWorkItemByIidQuery : workItemByIidQuery;
|
||||||
|
|
||||||
const variables = {
|
const variables = {
|
||||||
fullPath: newWorkItemFullPath(fullPath),
|
fullPath: newWorkItemFullPath(fullPath, workItemType),
|
||||||
iid: NEW_WORK_ITEM_IID,
|
iid: NEW_WORK_ITEM_IID,
|
||||||
};
|
};
|
||||||
|
|
||||||
cache.updateQuery({ query, variables }, (sourceData) =>
|
cache.updateQuery({ query, variables }, (sourceData) =>
|
||||||
produce(sourceData, (draftData) => {
|
produce(sourceData, (draftData) => {
|
||||||
if (healthStatus) {
|
if (healthStatus) {
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<gl-badge v-gl-tooltip :title="title" variant="warning">
|
<gl-badge v-gl-tooltip :title="title" variant="warning" class="gl-shrink-0">
|
||||||
<gl-icon name="spam" />
|
<gl-icon name="spam" />
|
||||||
<span class="gl-sr-only">{{ __('Hidden') }}</span>
|
<span class="gl-sr-only">{{ __('Hidden') }}</span>
|
||||||
</gl-badge>
|
</gl-badge>
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,13 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<gl-badge v-gl-tooltip :title="title" variant="warning" data-testid="locked-badge">
|
<gl-badge
|
||||||
|
v-gl-tooltip
|
||||||
|
:title="title"
|
||||||
|
variant="warning"
|
||||||
|
data-testid="locked-badge"
|
||||||
|
class="gl-shrink-0"
|
||||||
|
>
|
||||||
<gl-icon name="lock" />
|
<gl-icon name="lock" />
|
||||||
<span class="gl-sr-only">{{ __('Locked') }}</span>
|
<span class="gl-sr-only">{{ __('Locked') }}</span>
|
||||||
</gl-badge>
|
</gl-badge>
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,11 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<gl-badge :variant="badgeProperties.variant" :aria-label="badgeProperties.text">
|
<gl-badge
|
||||||
|
:variant="badgeProperties.variant"
|
||||||
|
:aria-label="badgeProperties.text"
|
||||||
|
class="gl-shrink-0"
|
||||||
|
>
|
||||||
<gl-icon :name="badgeProperties.icon" />
|
<gl-icon :name="badgeProperties.icon" />
|
||||||
{{ badgeProperties.text }}
|
{{ badgeProperties.text }}
|
||||||
</gl-badge>
|
</gl-badge>
|
||||||
|
|
|
||||||
|
|
@ -345,7 +345,7 @@ export default {
|
||||||
:auto-close="false"
|
:auto-close="false"
|
||||||
data-testid="mobile-dropdown"
|
data-testid="mobile-dropdown"
|
||||||
:loading="isToggleStateButtonLoading"
|
:loading="isToggleStateButtonLoading"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
>
|
>
|
||||||
<template v-if="showMovedSidebarOptions && !glFeatures.notificationsTodosButtons">
|
<template v-if="showMovedSidebarOptions && !glFeatures.notificationsTodosButtons">
|
||||||
<sidebar-subscriptions-widget
|
<sidebar-subscriptions-widget
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,7 @@ export default {
|
||||||
</div>
|
</div>
|
||||||
<gl-disclosure-dropdown
|
<gl-disclosure-dropdown
|
||||||
v-if="canUpdateTimelineEvent"
|
v-if="canUpdateTimelineEvent"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
class="event-note-actions gl-align-self-start"
|
class="event-note-actions gl-align-self-start"
|
||||||
icon="ellipsis_v"
|
icon="ellipsis_v"
|
||||||
text-sr-only
|
text-sr-only
|
||||||
|
|
|
||||||
|
|
@ -81,10 +81,8 @@ export default {
|
||||||
class="issue-sticky-header gl-fixed gl-z-3 gl-bg-white gl-border-1 gl-border-b-solid gl-border-b-gray-100 gl-py-3"
|
class="issue-sticky-header gl-fixed gl-z-3 gl-bg-white gl-border-1 gl-border-b-solid gl-border-b-gray-100 gl-py-3"
|
||||||
data-testid="issue-sticky-header"
|
data-testid="issue-sticky-header"
|
||||||
>
|
>
|
||||||
<div
|
<div class="issue-sticky-header-text gl-flex gl-items-center gl-gap-2 gl-mx-auto">
|
||||||
class="issue-sticky-header-text gl-display-flex gl-align-items-center gl-gap-2 gl-mx-auto"
|
<gl-badge :variant="statusVariant" :icon="statusIcon" class="gl-shrink-0">
|
||||||
>
|
|
||||||
<gl-badge :variant="statusVariant" :icon="statusIcon">
|
|
||||||
{{ statusText }}
|
{{ statusText }}
|
||||||
</gl-badge>
|
</gl-badge>
|
||||||
<confidentiality-badge
|
<confidentiality-badge
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ export default {
|
||||||
category="tertiary"
|
category="tertiary"
|
||||||
icon="ellipsis_v"
|
icon="ellipsis_v"
|
||||||
no-caret
|
no-caret
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
:toggle-text="$options.i18n.taskActions"
|
:toggle-text="$options.i18n.taskActions"
|
||||||
text-sr-only
|
text-sr-only
|
||||||
toggle-class="task-list-item-actions gl-opacity-0 gl-p-2! "
|
toggle-class="task-list-item-actions gl-opacity-0 gl-p-2! "
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ export default {
|
||||||
:toggle-text="preferredLocale.text"
|
:toggle-text="preferredLocale.text"
|
||||||
:items="locales"
|
:items="locales"
|
||||||
category="tertiary"
|
category="tertiary"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
icon="earth"
|
icon="earth"
|
||||||
size="small"
|
size="small"
|
||||||
toggle-class="py-0 gl-h-6"
|
toggle-class="py-0 gl-h-6"
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,7 @@ export default {
|
||||||
icon="ellipsis_v"
|
icon="ellipsis_v"
|
||||||
category="tertiary"
|
category="tertiary"
|
||||||
no-caret
|
no-caret
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
data-testid="user-action-dropdown"
|
data-testid="user-action-dropdown"
|
||||||
>
|
>
|
||||||
<disable-two-factor-dropdown-item
|
<disable-two-factor-dropdown-item
|
||||||
|
|
|
||||||
|
|
@ -121,7 +121,7 @@ export default {
|
||||||
<div>
|
<div>
|
||||||
<gl-collapsible-listbox
|
<gl-collapsible-listbox
|
||||||
v-if="permissions.canUpdate"
|
v-if="permissions.canUpdate"
|
||||||
:placement="isDesktop ? 'left' : 'right'"
|
:placement="isDesktop ? 'bottom-start' : 'bottom-end'"
|
||||||
:header-text="__('Change role')"
|
:header-text="__('Change role')"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
:loading="busy"
|
:loading="busy"
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ export default {
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<gl-disclosure-dropdown
|
<gl-disclosure-dropdown
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
category="tertiary"
|
category="tertiary"
|
||||||
:aria-label="__('More actions')"
|
:aria-label="__('More actions')"
|
||||||
icon="ellipsis_v"
|
icon="ellipsis_v"
|
||||||
|
|
|
||||||
|
|
@ -138,7 +138,7 @@ export default {
|
||||||
icon="ellipsis_v"
|
icon="ellipsis_v"
|
||||||
size="small"
|
size="small"
|
||||||
category="tertiary"
|
category="tertiary"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
no-caret
|
no-caret
|
||||||
:title="__('Thread options')"
|
:title="__('Thread options')"
|
||||||
:aria-label="__('Thread options')"
|
:aria-label="__('Thread options')"
|
||||||
|
|
@ -179,7 +179,7 @@ export default {
|
||||||
icon="ellipsis_v"
|
icon="ellipsis_v"
|
||||||
size="small"
|
size="small"
|
||||||
category="tertiary"
|
category="tertiary"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
no-caret
|
no-caret
|
||||||
:title="__('Thread options')"
|
:title="__('Thread options')"
|
||||||
:aria-label="__('Thread options')"
|
:aria-label="__('Thread options')"
|
||||||
|
|
|
||||||
|
|
@ -178,7 +178,7 @@ export default {
|
||||||
data-testid="discussion-preferences-dropdown"
|
data-testid="discussion-preferences-dropdown"
|
||||||
:toggle-text="__('Sort or filter')"
|
:toggle-text="__('Sort or filter')"
|
||||||
:disabled="isLoading"
|
:disabled="isLoading"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
>
|
>
|
||||||
<gl-disclosure-dropdown-group id="discussion-sort">
|
<gl-disclosure-dropdown-group id="discussion-sort">
|
||||||
<gl-disclosure-dropdown-item
|
<gl-disclosure-dropdown-item
|
||||||
|
|
|
||||||
|
|
@ -138,7 +138,7 @@ export default {
|
||||||
:show-select-all-button-label="__('Select all')"
|
:show-select-all-button-label="__('Select all')"
|
||||||
:reset-button-label="__('Deselect all')"
|
:reset-button-label="__('Deselect all')"
|
||||||
multiple
|
multiple
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
@shown="filterListShown"
|
@shown="filterListShown"
|
||||||
@hidden="applyFilters"
|
@hidden="applyFilters"
|
||||||
@reset="deselectAll"
|
@reset="deselectAll"
|
||||||
|
|
|
||||||
|
|
@ -355,7 +355,7 @@ export default {
|
||||||
text-sr-only
|
text-sr-only
|
||||||
icon="ellipsis_v"
|
icon="ellipsis_v"
|
||||||
category="tertiary"
|
category="tertiary"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
class="note-action-button more-actions-toggle"
|
class="note-action-button more-actions-toggle"
|
||||||
no-caret
|
no-caret
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -199,7 +199,7 @@ export default {
|
||||||
<gl-disclosure-dropdown
|
<gl-disclosure-dropdown
|
||||||
category="tertiary"
|
category="tertiary"
|
||||||
icon="ellipsis_v"
|
icon="ellipsis_v"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
:toggle-text="$options.i18n.MORE_ACTIONS_TEXT"
|
:toggle-text="$options.i18n.MORE_ACTIONS_TEXT"
|
||||||
text-sr-only
|
text-sr-only
|
||||||
no-caret
|
no-caret
|
||||||
|
|
|
||||||
|
|
@ -227,7 +227,7 @@ export default {
|
||||||
:text-sr-only="true"
|
:text-sr-only="true"
|
||||||
category="tertiary"
|
category="tertiary"
|
||||||
no-caret
|
no-caret
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
:class="{ 'gl-opacity-0 gl-pointer-events-none': disabled }"
|
:class="{ 'gl-opacity-0 gl-pointer-events-none': disabled }"
|
||||||
data-testid="additional-actions"
|
data-testid="additional-actions"
|
||||||
:items="items"
|
:items="items"
|
||||||
|
|
|
||||||
|
|
@ -162,7 +162,7 @@ export default {
|
||||||
:toggle-text="__('More actions')"
|
:toggle-text="__('More actions')"
|
||||||
:text-sr-only="true"
|
:text-sr-only="true"
|
||||||
category="tertiary"
|
category="tertiary"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
no-caret
|
no-caret
|
||||||
>
|
>
|
||||||
<gl-disclosure-dropdown-item v-gl-modal-directive="$options.confirmClearCacheModal">
|
<gl-disclosure-dropdown-item v-gl-modal-directive="$options.confirmClearCacheModal">
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import { GlLink, GlSprintf } from '@gitlab/ui';
|
import { GlLink, GlSprintf } from '@gitlab/ui';
|
||||||
import { s__ } from '~/locale';
|
import { s__ } from '~/locale';
|
||||||
|
import { helpPagePath } from '~/helpers/help_page_helper';
|
||||||
import CodeInstruction from '~/vue_shared/components/registry/code_instruction.vue';
|
import CodeInstruction from '~/vue_shared/components/registry/code_instruction.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
@ -9,7 +10,7 @@ export default {
|
||||||
GlLink,
|
GlLink,
|
||||||
GlSprintf,
|
GlSprintf,
|
||||||
},
|
},
|
||||||
inject: ['terraformHelpPath', 'gitlabHost', 'projectPath'],
|
inject: ['gitlabHost', 'projectPath'],
|
||||||
props: {
|
props: {
|
||||||
packageName: {
|
packageName: {
|
||||||
type: String,
|
type: String,
|
||||||
|
|
@ -38,6 +39,9 @@ export default {
|
||||||
'InfrastructureRegistry|For more information on the Terraform registry, %{linkStart}see our documentation%{linkEnd}.',
|
'InfrastructureRegistry|For more information on the Terraform registry, %{linkStart}see our documentation%{linkEnd}.',
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
terraformHelpPath: helpPagePath('user/packages/terraform_module_registry/index', {
|
||||||
|
anchor: 'reference-a-terraform-module',
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -66,7 +70,7 @@ export default {
|
||||||
/>
|
/>
|
||||||
<gl-sprintf :message="$options.i18n.helpText">
|
<gl-sprintf :message="$options.i18n.helpText">
|
||||||
<template #link="{ content }">
|
<template #link="{ content }">
|
||||||
<gl-link :href="terraformHelpPath">{{ content }}</gl-link>
|
<gl-link :href="$options.terraformHelpPath">{{ content }}</gl-link>
|
||||||
</template>
|
</template>
|
||||||
</gl-sprintf>
|
</gl-sprintf>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,11 @@ export default () => {
|
||||||
const {
|
const {
|
||||||
package: packageJson,
|
package: packageJson,
|
||||||
canDelete: canDeleteStr,
|
canDelete: canDeleteStr,
|
||||||
terraformHelpPath,
|
|
||||||
gitlabHost,
|
gitlabHost,
|
||||||
projectPath,
|
projectPath,
|
||||||
projectName,
|
projectName,
|
||||||
projectListUrl,
|
projectListUrl,
|
||||||
|
svgPath,
|
||||||
} = el.dataset;
|
} = el.dataset;
|
||||||
const packageEntity = JSON.parse(packageJson);
|
const packageEntity = JSON.parse(packageJson);
|
||||||
const canDelete = parseBoolean(canDeleteStr);
|
const canDelete = parseBoolean(canDeleteStr);
|
||||||
|
|
@ -34,7 +34,7 @@ export default () => {
|
||||||
projectListUrl,
|
projectListUrl,
|
||||||
projectName,
|
projectName,
|
||||||
projectPath,
|
projectPath,
|
||||||
terraformHelpPath,
|
svgPath,
|
||||||
},
|
},
|
||||||
render(createElement) {
|
render(createElement) {
|
||||||
return createElement(PackagesApp);
|
return createElement(PackagesApp);
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,13 @@
|
||||||
#import "~/packages_and_registries/package_registry/graphql/fragments/package_group_settings.fragment.graphql"
|
#import "~/packages_and_registries/package_registry/graphql/fragments/package_group_settings.fragment.graphql"
|
||||||
|
|
||||||
query getGroupPackageSettings($fullPath: ID!) {
|
query getGroupPackageSettings($fullPath: ID!, $isGroupPage: Boolean = false) {
|
||||||
project(fullPath: $fullPath) {
|
project(fullPath: $fullPath) @skip(if: $isGroupPage) {
|
||||||
id
|
id
|
||||||
group {
|
group {
|
||||||
...GroupPackageSettings
|
...GroupPackageSettings
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
group(fullPath: $fullPath) @include(if: $isGroupPage) {
|
||||||
|
...GroupPackageSettings
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
#import "~/packages_and_registries/package_registry/graphql/fragments/package_data.fragment.graphql"
|
#import "~/packages_and_registries/package_registry/graphql/fragments/package_data.fragment.graphql"
|
||||||
#import "~/packages_and_registries/package_registry/graphql/fragments/package_group_settings.fragment.graphql"
|
|
||||||
#import "~/graphql_shared/fragments/page_info.fragment.graphql"
|
#import "~/graphql_shared/fragments/page_info.fragment.graphql"
|
||||||
|
|
||||||
query getPackages(
|
query getPackages(
|
||||||
|
|
@ -37,9 +36,6 @@ query getPackages(
|
||||||
...PageInfo
|
...PageInfo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
group {
|
|
||||||
...GroupPackageSettings
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
group(fullPath: $fullPath) @include(if: $isGroupPage) {
|
group(fullPath: $fullPath) @include(if: $isGroupPage) {
|
||||||
id
|
id
|
||||||
|
|
@ -67,6 +63,5 @@ query getPackages(
|
||||||
...PageInfo
|
...PageInfo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
...GroupPackageSettings
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import { createAlert, VARIANT_INFO } from '~/alert';
|
||||||
import { WORKSPACE_GROUP, WORKSPACE_PROJECT } from '~/issues/constants';
|
import { WORKSPACE_GROUP, WORKSPACE_PROJECT } from '~/issues/constants';
|
||||||
import { fetchPolicies } from '~/lib/graphql';
|
import { fetchPolicies } from '~/lib/graphql';
|
||||||
import { historyReplaceState } from '~/lib/utils/common_utils';
|
import { historyReplaceState } from '~/lib/utils/common_utils';
|
||||||
|
import * as Sentry from '~/sentry/sentry_browser_wrapper';
|
||||||
import { s__ } from '~/locale';
|
import { s__ } from '~/locale';
|
||||||
import { SHOW_DELETE_SUCCESS_ALERT } from '~/packages_and_registries/shared/constants';
|
import { SHOW_DELETE_SUCCESS_ALERT } from '~/packages_and_registries/shared/constants';
|
||||||
import {
|
import {
|
||||||
|
|
@ -15,6 +16,7 @@ import {
|
||||||
PACKAGE_HELP_URL,
|
PACKAGE_HELP_URL,
|
||||||
} from '~/packages_and_registries/package_registry/constants';
|
} from '~/packages_and_registries/package_registry/constants';
|
||||||
import getPackagesQuery from '~/packages_and_registries/package_registry/graphql/queries/get_packages.query.graphql';
|
import getPackagesQuery from '~/packages_and_registries/package_registry/graphql/queries/get_packages.query.graphql';
|
||||||
|
import getGroupPackageSettings from '~/packages_and_registries/package_registry/graphql/queries/get_group_package_settings.query.graphql';
|
||||||
import DeletePackages from '~/packages_and_registries/package_registry/components/functional/delete_packages.vue';
|
import DeletePackages from '~/packages_and_registries/package_registry/components/functional/delete_packages.vue';
|
||||||
import PackageTitle from '~/packages_and_registries/package_registry/components/list/package_title.vue';
|
import PackageTitle from '~/packages_and_registries/package_registry/components/list/package_title.vue';
|
||||||
import PackageSearch from '~/packages_and_registries/package_registry/components/list/package_search.vue';
|
import PackageSearch from '~/packages_and_registries/package_registry/components/list/package_search.vue';
|
||||||
|
|
@ -41,7 +43,7 @@ export default {
|
||||||
directives: {
|
directives: {
|
||||||
GlTooltip: GlTooltipDirective,
|
GlTooltip: GlTooltipDirective,
|
||||||
},
|
},
|
||||||
inject: ['emptyListIllustration', 'isGroupPage', 'fullPath', 'settingsPath'],
|
inject: ['emptyListIllustration', 'canDeletePackages', 'isGroupPage', 'fullPath', 'settingsPath'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
packagesResource: {},
|
packagesResource: {},
|
||||||
|
|
@ -49,6 +51,7 @@ export default {
|
||||||
filters: {},
|
filters: {},
|
||||||
isDeleteInProgress: false,
|
isDeleteInProgress: false,
|
||||||
pageParams: {},
|
pageParams: {},
|
||||||
|
groupSettings: {},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
apollo: {
|
apollo: {
|
||||||
|
|
@ -65,16 +68,31 @@ export default {
|
||||||
return !this.sort;
|
return !this.sort;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
groupSettings: {
|
||||||
|
query: getGroupPackageSettings,
|
||||||
|
variables() {
|
||||||
|
return {
|
||||||
|
fullPath: this.fullPath,
|
||||||
|
isGroupPage: this.isGroupPage,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
update(data) {
|
||||||
|
return this.isGroupPage
|
||||||
|
? data[this.graphqlResource].packageSettings ?? {}
|
||||||
|
: data[this.graphqlResource].group?.packageSettings ?? {};
|
||||||
|
},
|
||||||
|
skip() {
|
||||||
|
return !(this.packagesCount > 0 && this.canDeletePackages);
|
||||||
|
},
|
||||||
|
error(error) {
|
||||||
|
Sentry.captureException(error);
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
packages() {
|
packages() {
|
||||||
return this.packagesResource?.packages ?? {};
|
return this.packagesResource?.packages ?? {};
|
||||||
},
|
},
|
||||||
groupSettings() {
|
|
||||||
return this.isGroupPage
|
|
||||||
? this.packagesResource?.packageSettings ?? {}
|
|
||||||
: this.packagesResource?.group?.packageSettings ?? {};
|
|
||||||
},
|
|
||||||
queryVariables() {
|
queryVariables() {
|
||||||
return {
|
return {
|
||||||
isGroupPage: this.isGroupPage,
|
isGroupPage: this.isGroupPage,
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ export default {
|
||||||
<gl-disclosure-dropdown
|
<gl-disclosure-dropdown
|
||||||
:toggle-text="$options.i18n.QUICK_START"
|
:toggle-text="$options.i18n.QUICK_START"
|
||||||
variant="confirm"
|
variant="confirm"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
@shown="track('click_dropdown')"
|
@shown="track('click_dropdown')"
|
||||||
>
|
>
|
||||||
<div class="gl-px-3 gl-py-2">
|
<div class="gl-px-3 gl-py-2">
|
||||||
|
|
|
||||||
|
|
@ -169,7 +169,7 @@ export default {
|
||||||
v-model="sortOrder"
|
v-model="sortOrder"
|
||||||
:toggle-text="$options.sortOrderOptions[sortOrder].text"
|
:toggle-text="$options.sortOrderOptions[sortOrder].text"
|
||||||
:items="Object.values($options.sortOrderOptions)"
|
:items="Object.values($options.sortOrderOptions)"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
data-testid="performance-bar-sort-order"
|
data-testid="performance-bar-sort-order"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,7 @@ export default {
|
||||||
<gl-button-group>
|
<gl-button-group>
|
||||||
<gl-collapsible-listbox
|
<gl-collapsible-listbox
|
||||||
v-model="selectedSortOptionTitle"
|
v-model="selectedSortOptionTitle"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
class="gl-z-1"
|
class="gl-z-1"
|
||||||
toggle-class="gl-rounded-top-right-none! gl-rounded-bottom-right-none!"
|
toggle-class="gl-rounded-top-right-none! gl-rounded-bottom-right-none!"
|
||||||
:toggle-text="selectedSortOptionTitle"
|
:toggle-text="selectedSortOptionTitle"
|
||||||
|
|
|
||||||
|
|
@ -303,7 +303,7 @@ export default {
|
||||||
|
|
||||||
<gl-disclosure-dropdown
|
<gl-disclosure-dropdown
|
||||||
data-testid="snippets-more-actions-dropdown"
|
data-testid="snippets-more-actions-dropdown"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
block
|
block
|
||||||
@shown="onShowDropdown"
|
@shown="onShowDropdown"
|
||||||
@hidden="onHideDropdown"
|
@hidden="onHideDropdown"
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ export default {
|
||||||
v-model="selectedKey"
|
v-model="selectedKey"
|
||||||
data-testid="tags-dropdown"
|
data-testid="tags-dropdown"
|
||||||
:items="sortOptionsListboxItems"
|
:items="sortOptionsListboxItems"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
:toggle-text="selectedSortMethod"
|
:toggle-text="selectedSortMethod"
|
||||||
@select="visitUrlFromOption"
|
@select="visitUrlFromOption"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ export default {
|
||||||
<gl-collapsible-listbox
|
<gl-collapsible-listbox
|
||||||
:items="filteredChanges"
|
:items="filteredChanges"
|
||||||
size="small"
|
size="small"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
searchable
|
searchable
|
||||||
@search="search"
|
@search="search"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ export default {
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<gl-disclosure-dropdown
|
<gl-disclosure-dropdown
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
toggle-text="Use an existing commit message"
|
toggle-text="Use an existing commit message"
|
||||||
category="tertiary"
|
category="tertiary"
|
||||||
:items="dropdownItems"
|
:items="dropdownItems"
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ export default {
|
||||||
icon="ellipsis_v"
|
icon="ellipsis_v"
|
||||||
no-caret
|
no-caret
|
||||||
category="tertiary"
|
category="tertiary"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
text-sr-only
|
text-sr-only
|
||||||
size="small"
|
size="small"
|
||||||
toggle-class="gl-p-2!"
|
toggle-class="gl-p-2!"
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@ export default {
|
||||||
<gl-collapsible-listbox
|
<gl-collapsible-listbox
|
||||||
ref="dropdown"
|
ref="dropdown"
|
||||||
v-model="alertStatus"
|
v-model="alertStatus"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
:header-text="headerText"
|
:header-text="headerText"
|
||||||
:items="items"
|
:items="items"
|
||||||
block
|
block
|
||||||
|
|
|
||||||
|
|
@ -140,7 +140,7 @@ export default {
|
||||||
:toggle-text="$options.i18n.defaultLabel"
|
:toggle-text="$options.i18n.defaultLabel"
|
||||||
category="primary"
|
category="primary"
|
||||||
variant="confirm"
|
variant="confirm"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
class="code-dropdown gl-text-left"
|
class="code-dropdown gl-text-left"
|
||||||
fluid-width
|
fluid-width
|
||||||
data-testid="code-dropdown"
|
data-testid="code-dropdown"
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ export default {
|
||||||
<gl-disclosure-dropdown
|
<gl-disclosure-dropdown
|
||||||
category="primary"
|
category="primary"
|
||||||
variant="confirm"
|
variant="confirm"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
block
|
block
|
||||||
:toggle-text="$options.labels.defaultLabel"
|
:toggle-text="$options.labels.defaultLabel"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<gl-badge v-gl-tooltip :title="confidentialTooltip" variant="warning">
|
<gl-badge v-gl-tooltip :title="confidentialTooltip" variant="warning" class="gl-shrink-0">
|
||||||
<gl-icon name="eye-slash" :size="16" />
|
<gl-icon name="eye-slash" :size="16" />
|
||||||
<span data-testid="confidential-badge-text" :class="confidentialTextClass">{{
|
<span data-testid="confidential-badge-text" :class="confidentialTextClass">{{
|
||||||
__('Confidential')
|
__('Confidential')
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,7 @@ export default {
|
||||||
:toggle-text="$options.i18n.defaultLabel"
|
:toggle-text="$options.i18n.defaultLabel"
|
||||||
:title="$options.i18n.defaultLabel"
|
:title="$options.i18n.defaultLabel"
|
||||||
category="secondary"
|
category="secondary"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
icon="download"
|
icon="download"
|
||||||
text-sr-only
|
text-sr-only
|
||||||
fluid-width
|
fluid-width
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ export default {
|
||||||
<span v-if="textOnly" v-gl-tooltip="title">
|
<span v-if="textOnly" v-gl-tooltip="title">
|
||||||
{{ __('Imported') }}
|
{{ __('Imported') }}
|
||||||
</span>
|
</span>
|
||||||
<gl-badge v-else v-gl-tooltip="title">
|
<gl-badge v-else v-gl-tooltip="title" class="gl-shrink-0">
|
||||||
{{ __('Imported') }}
|
{{ __('Imported') }}
|
||||||
</gl-badge>
|
</gl-badge>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ export default {
|
||||||
no-caret
|
no-caret
|
||||||
:toggle-text="$options.i18n.actions"
|
:toggle-text="$options.i18n.actions"
|
||||||
text-sr-only
|
text-sr-only
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
category="tertiary"
|
category="tertiary"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ export default {
|
||||||
<gl-disclosure-dropdown
|
<gl-disclosure-dropdown
|
||||||
data-testid="apply-suggestion-dropdown"
|
data-testid="apply-suggestion-dropdown"
|
||||||
fluid-width
|
fluid-width
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
size="small"
|
size="small"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
:toggle-text="dropdownText"
|
:toggle-text="dropdownText"
|
||||||
|
|
|
||||||
|
|
@ -229,7 +229,7 @@ export default {
|
||||||
v-gl-tooltip="showDropdownTooltip"
|
v-gl-tooltip="showDropdownTooltip"
|
||||||
:title="$options.i18n.mergeRequestActions"
|
:title="$options.i18n.mergeRequestActions"
|
||||||
data-testid="dropdown-toggle"
|
data-testid="dropdown-toggle"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
block
|
block
|
||||||
class="gl-w-full"
|
class="gl-w-full"
|
||||||
:auto-close="false"
|
:auto-close="false"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
import SettingsSection from './settings_section.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
component: SettingsSection,
|
||||||
|
title: 'vue_shared/settings/settings_section',
|
||||||
|
};
|
||||||
|
|
||||||
|
const Template = (args, { argTypes }) => ({
|
||||||
|
components: { SettingsSection },
|
||||||
|
props: Object.keys(argTypes),
|
||||||
|
template: `
|
||||||
|
<settings-section v-bind="$props" heading="Settings section heading">
|
||||||
|
<template #description>Settings section description</template>
|
||||||
|
<template #default>
|
||||||
|
<p>Settings section content</p>
|
||||||
|
</template>
|
||||||
|
</settings-section>
|
||||||
|
`,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const Default = Template.bind({});
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
heading: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<section class="settings-section">
|
||||||
|
<div class="settings-sticky-header">
|
||||||
|
<div class="settings-sticky-header-inner">
|
||||||
|
<h2 class="gl-heading-2 !gl-mb-2">
|
||||||
|
<slot v-if="$scopedSlots.heading" name="heading"></slot>
|
||||||
|
<template v-else>{{ heading }}</template>
|
||||||
|
</h2>
|
||||||
|
<p v-if="$scopedSlots.description || description" class="gl-text-secondary gl-m-0">
|
||||||
|
<slot v-if="$scopedSlots.description" name="description"></slot>
|
||||||
|
<template v-else>{{ description }}</template>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
@ -55,6 +55,6 @@ export default {
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
icon="download"
|
icon="download"
|
||||||
size="small"
|
size="small"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
|
||||||
import { fetchPolicies } from '~/lib/graphql';
|
import { fetchPolicies } from '~/lib/graphql';
|
||||||
import { setNewWorkItemCache } from '~/work_items/graphql/cache_utils';
|
import { setNewWorkItemCache } from '~/work_items/graphql/cache_utils';
|
||||||
import { findWidget } from '~/issues/list/utils';
|
import { findWidget } from '~/issues/list/utils';
|
||||||
import { newWorkItemFullPath, isWorkItemItemValidEnum } from '~/work_items/utils';
|
import { newWorkItemFullPath } from '~/work_items/utils';
|
||||||
import {
|
import {
|
||||||
I18N_WORK_ITEM_CREATE_BUTTON_LABEL,
|
I18N_WORK_ITEM_CREATE_BUTTON_LABEL,
|
||||||
I18N_WORK_ITEM_ERROR_CREATING,
|
I18N_WORK_ITEM_ERROR_CREATING,
|
||||||
|
|
@ -79,7 +79,6 @@ export default {
|
||||||
selectedWorkItemTypeId: null,
|
selectedWorkItemTypeId: null,
|
||||||
loading: false,
|
loading: false,
|
||||||
showWorkItemTypeSelect: false,
|
showWorkItemTypeSelect: false,
|
||||||
newWorkItemPath: newWorkItemFullPath(this.fullPath),
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
apollo: {
|
apollo: {
|
||||||
|
|
@ -94,7 +93,7 @@ export default {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
skip() {
|
skip() {
|
||||||
return !this.fullPath;
|
return !this.fullPath || !this.selectedWorkItemTypeName;
|
||||||
},
|
},
|
||||||
update(data) {
|
update(data) {
|
||||||
return data?.workspace?.workItem ?? {};
|
return data?.workspace?.workItem ?? {};
|
||||||
|
|
@ -119,13 +118,22 @@ export default {
|
||||||
update(data) {
|
update(data) {
|
||||||
return data.workspace?.workItemTypes?.nodes;
|
return data.workspace?.workItemTypes?.nodes;
|
||||||
},
|
},
|
||||||
result() {
|
async result() {
|
||||||
if (!this.workItemTypes?.length) {
|
if (!this.workItemTypes?.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.workItemTypes?.length === 1) {
|
if (this.workItemTypes?.length === 1) {
|
||||||
this.selectedWorkItemTypeId = this.workItemTypes[0].id;
|
this.selectedWorkItemTypeId = this.workItemTypes[0].id;
|
||||||
} else {
|
} else {
|
||||||
|
this.workItemTypes.forEach(async (workItemType) => {
|
||||||
|
await setNewWorkItemCache(
|
||||||
|
this.isGroup,
|
||||||
|
this.fullPath,
|
||||||
|
workItemType?.widgetDefinitions,
|
||||||
|
workItemType.name,
|
||||||
|
workItemType.id,
|
||||||
|
);
|
||||||
|
});
|
||||||
this.showWorkItemTypeSelect = true;
|
this.showWorkItemTypeSelect = true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -135,6 +143,9 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
newWorkItemPath() {
|
||||||
|
return newWorkItemFullPath(this.fullPath, this.selectedWorkItemTypeName);
|
||||||
|
},
|
||||||
isLoading() {
|
isLoading() {
|
||||||
return this.$apollo.queries.workItemTypes.loading || this.$apollo.queries.workItem.loading;
|
return this.$apollo.queries.workItemTypes.loading || this.$apollo.queries.workItem.loading;
|
||||||
},
|
},
|
||||||
|
|
@ -161,27 +172,28 @@ export default {
|
||||||
selectedWorkItemType() {
|
selectedWorkItemType() {
|
||||||
return this.workItemTypes?.find((item) => item.id === this.selectedWorkItemTypeId);
|
return this.workItemTypes?.find((item) => item.id === this.selectedWorkItemTypeId);
|
||||||
},
|
},
|
||||||
|
selectedWorkItemTypeName() {
|
||||||
|
return this.selectedWorkItemType?.name;
|
||||||
|
},
|
||||||
formOptions() {
|
formOptions() {
|
||||||
return [{ value: null, text: s__('WorkItem|Select type') }, ...this.workItemTypesForSelect];
|
return [{ value: null, text: s__('WorkItem|Select type') }, ...this.workItemTypesForSelect];
|
||||||
},
|
},
|
||||||
createErrorText() {
|
createErrorText() {
|
||||||
const workItemType = this.selectedWorkItemType?.name;
|
return sprintfWorkItem(I18N_WORK_ITEM_ERROR_CREATING, this.selectedWorkItemTypeName);
|
||||||
return sprintfWorkItem(I18N_WORK_ITEM_ERROR_CREATING, workItemType);
|
|
||||||
},
|
},
|
||||||
createWorkItemText() {
|
createWorkItemText() {
|
||||||
const workItemType = this.selectedWorkItemType?.name;
|
return sprintfWorkItem(I18N_WORK_ITEM_CREATE_BUTTON_LABEL, this.selectedWorkItemTypeName);
|
||||||
return sprintfWorkItem(I18N_WORK_ITEM_CREATE_BUTTON_LABEL, workItemType);
|
|
||||||
},
|
},
|
||||||
makeConfidentialText() {
|
makeConfidentialText() {
|
||||||
return sprintfWorkItem(
|
return sprintfWorkItem(
|
||||||
s__(
|
s__(
|
||||||
'WorkItem|This %{workItemType} is confidential and should only be visible to users having at least Reporter access.',
|
'WorkItem|This %{workItemType} is confidential and should only be visible to users having at least Reporter access.',
|
||||||
),
|
),
|
||||||
this.selectedWorkItemType?.name,
|
this.selectedWorkItemTypeName,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
titleText() {
|
titleText() {
|
||||||
return sprintfWorkItem(s__('WorkItem|New %{workItemType}'), this.selectedWorkItemType?.name);
|
return sprintfWorkItem(s__('WorkItem|New %{workItemType}'), this.selectedWorkItemTypeName);
|
||||||
},
|
},
|
||||||
canUpdate() {
|
canUpdate() {
|
||||||
return this.workItem?.userPermissions?.updateWorkItem;
|
return this.workItem?.userPermissions?.updateWorkItem;
|
||||||
|
|
@ -228,17 +240,6 @@ export default {
|
||||||
const title = newValue || this.workItemTitle;
|
const title = newValue || this.workItemTitle;
|
||||||
this.isTitleValid = Boolean(title.trim());
|
this.isTitleValid = Boolean(title.trim());
|
||||||
},
|
},
|
||||||
updateCache() {
|
|
||||||
if (!this.selectedWorkItemTypeId || !isWorkItemItemValidEnum(this.workItemType)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setNewWorkItemCache(
|
|
||||||
this.isGroup,
|
|
||||||
this.fullPath,
|
|
||||||
this.selectedWorkItemType?.widgetDefinitions,
|
|
||||||
this.workItemType,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
async updateDraftData(type, value) {
|
async updateDraftData(type, value) {
|
||||||
if (type === 'title') {
|
if (type === 'title') {
|
||||||
this.validate(value);
|
this.validate(value);
|
||||||
|
|
@ -251,6 +252,7 @@ export default {
|
||||||
input: {
|
input: {
|
||||||
isGroup: this.isGroup,
|
isGroup: this.isGroup,
|
||||||
fullPath: this.fullPath,
|
fullPath: this.fullPath,
|
||||||
|
workItemType: this.selectedWorkItemTypeName || this.workItemTypeName,
|
||||||
[type]: value,
|
[type]: value,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -367,98 +369,100 @@ export default {
|
||||||
v-model="selectedWorkItemTypeId"
|
v-model="selectedWorkItemTypeId"
|
||||||
:options="formOptions"
|
:options="formOptions"
|
||||||
class="gl-max-w-26"
|
class="gl-max-w-26"
|
||||||
@change="updateCache"
|
|
||||||
/>
|
/>
|
||||||
</gl-form-group>
|
</gl-form-group>
|
||||||
</div>
|
</div>
|
||||||
<work-item-title
|
<div v-if="selectedWorkItemTypeId" data-testid="create-work-item">
|
||||||
ref="title"
|
<work-item-title
|
||||||
data-testid="title-input"
|
ref="title"
|
||||||
is-editing
|
data-testid="title-input"
|
||||||
:is-valid="isTitleValid"
|
is-editing
|
||||||
:title="workItemTitle"
|
:is-valid="isTitleValid"
|
||||||
@updateDraft="updateDraftData('title', $event)"
|
:title="workItemTitle"
|
||||||
@updateWorkItem="createWorkItem"
|
@updateDraft="updateDraftData('title', $event)"
|
||||||
/>
|
@updateWorkItem="createWorkItem"
|
||||||
<div data-testid="work-item-overview" class="work-item-overview">
|
/>
|
||||||
<section>
|
<div data-testid="work-item-overview" class="work-item-overview">
|
||||||
<work-item-description
|
<section>
|
||||||
edit-mode
|
<work-item-description
|
||||||
:autofocus="false"
|
edit-mode
|
||||||
:full-path="fullPath"
|
:autofocus="false"
|
||||||
create-flow
|
|
||||||
:show-buttons-below-field="false"
|
|
||||||
:work-item-id="$options.NEW_WORK_ITEM_GID"
|
|
||||||
:work-item-iid="$options.NEW_WORK_ITEM_IID"
|
|
||||||
@error="updateError = $event"
|
|
||||||
@updateDraft="updateDraftData('description', $event)"
|
|
||||||
/>
|
|
||||||
<gl-form-group :label="__('Confidentiality')" label-for="work-item-confidential">
|
|
||||||
<gl-form-checkbox
|
|
||||||
id="work-item-confidential"
|
|
||||||
v-model="isConfidential"
|
|
||||||
data-testid="confidential-checkbox"
|
|
||||||
@change="updateDraftData('confidential', $event)"
|
|
||||||
>
|
|
||||||
{{ makeConfidentialText }}
|
|
||||||
</gl-form-checkbox>
|
|
||||||
</gl-form-group>
|
|
||||||
</section>
|
|
||||||
<aside
|
|
||||||
v-if="hasWidgets"
|
|
||||||
data-testid="work-item-overview-right-sidebar"
|
|
||||||
class="work-item-overview-right-sidebar"
|
|
||||||
:class="{ 'is-modal': true }"
|
|
||||||
>
|
|
||||||
<template v-if="workItemAssignees">
|
|
||||||
<work-item-assignees
|
|
||||||
class="gl-mb-5 js-assignee"
|
|
||||||
:can-update="canUpdate"
|
|
||||||
:full-path="fullPath"
|
:full-path="fullPath"
|
||||||
:work-item-id="workItem.id"
|
create-flow
|
||||||
:assignees="workItemAssignees.assignees.nodes"
|
:show-buttons-below-field="false"
|
||||||
:participants="workItemParticipantNodes"
|
:work-item-id="$options.NEW_WORK_ITEM_GID"
|
||||||
:work-item-author="workItemAuthor"
|
:work-item-iid="$options.NEW_WORK_ITEM_IID"
|
||||||
:allows-multiple-assignees="workItemAssignees.allowsMultipleAssignees"
|
:work-item-type-name="selectedWorkItemTypeName"
|
||||||
:work-item-type="workItemType"
|
@error="updateError = $event"
|
||||||
:can-invite-members="workItemAssignees.canInviteMembers"
|
@updateDraft="updateDraftData('description', $event)"
|
||||||
@error="$emit('error', $event)"
|
|
||||||
/>
|
/>
|
||||||
</template>
|
<gl-form-group :label="__('Confidentiality')" label-for="work-item-confidential">
|
||||||
<template v-if="workItemHealthStatus">
|
<gl-form-checkbox
|
||||||
<work-item-health-status
|
id="work-item-confidential"
|
||||||
class="gl-mb-5"
|
v-model="isConfidential"
|
||||||
:health-status="workItemHealthStatus.healthStatus"
|
data-testid="confidential-checkbox"
|
||||||
:can-update="canUpdate"
|
@change="updateDraftData('confidential', $event)"
|
||||||
:work-item-id="workItem.id"
|
>
|
||||||
:work-item-iid="workItem.iid"
|
{{ makeConfidentialText }}
|
||||||
:work-item-type="workItemType"
|
</gl-form-checkbox>
|
||||||
:full-path="fullPath"
|
</gl-form-group>
|
||||||
@error="$emit('error', $event)"
|
</section>
|
||||||
/>
|
<aside
|
||||||
</template>
|
v-if="hasWidgets"
|
||||||
<template v-if="workItemColor">
|
data-testid="work-item-overview-right-sidebar"
|
||||||
<work-item-color
|
class="work-item-overview-right-sidebar"
|
||||||
class="gl-mb-5"
|
:class="{ 'is-modal': true }"
|
||||||
:work-item="workItem"
|
|
||||||
:full-path="fullPath"
|
|
||||||
:can-update="canUpdate"
|
|
||||||
@error="$emit('error', $event)"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</aside>
|
|
||||||
<div class="gl-py-3 gl-flex gl-gap-3 gl-col-start-1">
|
|
||||||
<gl-button
|
|
||||||
variant="confirm"
|
|
||||||
:loading="loading"
|
|
||||||
data-testid="create-button"
|
|
||||||
@click="createWorkItem"
|
|
||||||
>
|
>
|
||||||
{{ createWorkItemText }}
|
<template v-if="workItemAssignees">
|
||||||
</gl-button>
|
<work-item-assignees
|
||||||
<gl-button type="button" data-testid="cancel-button" @click="handleCancelClick">
|
class="gl-mb-5 js-assignee"
|
||||||
{{ __('Cancel') }}
|
:can-update="canUpdate"
|
||||||
</gl-button>
|
:full-path="fullPath"
|
||||||
|
:work-item-id="workItem.id"
|
||||||
|
:assignees="workItemAssignees.assignees.nodes"
|
||||||
|
:participants="workItemParticipantNodes"
|
||||||
|
:work-item-author="workItemAuthor"
|
||||||
|
:allows-multiple-assignees="workItemAssignees.allowsMultipleAssignees"
|
||||||
|
:work-item-type="selectedWorkItemTypeName"
|
||||||
|
:can-invite-members="workItemAssignees.canInviteMembers"
|
||||||
|
@error="$emit('error', $event)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template v-if="workItemHealthStatus">
|
||||||
|
<work-item-health-status
|
||||||
|
class="gl-mb-5"
|
||||||
|
:health-status="workItemHealthStatus.healthStatus"
|
||||||
|
:can-update="canUpdate"
|
||||||
|
:work-item-id="workItem.id"
|
||||||
|
:work-item-iid="workItem.iid"
|
||||||
|
:work-item-type="selectedWorkItemTypeName"
|
||||||
|
:full-path="fullPath"
|
||||||
|
@error="$emit('error', $event)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template v-if="workItemColor">
|
||||||
|
<work-item-color
|
||||||
|
class="gl-mb-5"
|
||||||
|
:work-item="workItem"
|
||||||
|
:full-path="fullPath"
|
||||||
|
:can-update="canUpdate"
|
||||||
|
@error="$emit('error', $event)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</aside>
|
||||||
|
<div class="gl-py-3 gl-flex gl-gap-3 gl-col-start-1">
|
||||||
|
<gl-button
|
||||||
|
variant="confirm"
|
||||||
|
:loading="loading"
|
||||||
|
data-testid="create-button"
|
||||||
|
@click="createWorkItem"
|
||||||
|
>
|
||||||
|
{{ createWorkItemText }}
|
||||||
|
</gl-button>
|
||||||
|
<gl-button type="button" data-testid="cancel-button" @click="handleCancelClick">
|
||||||
|
{{ __('Cancel') }}
|
||||||
|
</gl-button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ export default {
|
||||||
:disabled="loading"
|
:disabled="loading"
|
||||||
:items="items"
|
:items="items"
|
||||||
:selected="sortFilterProp"
|
:selected="sortFilterProp"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
size="small"
|
size="small"
|
||||||
@select="fetchFilteredDiscussions"
|
@select="fetchFilteredDiscussions"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -223,7 +223,7 @@ export default {
|
||||||
v-gl-tooltip
|
v-gl-tooltip
|
||||||
icon="ellipsis_v"
|
icon="ellipsis_v"
|
||||||
text-sr-only
|
text-sr-only
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
:toggle-text="$options.i18n.moreActionsText"
|
:toggle-text="$options.i18n.moreActionsText"
|
||||||
:title="$options.i18n.moreActionsText"
|
:title="$options.i18n.moreActionsText"
|
||||||
category="tertiary"
|
category="tertiary"
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import { GlButton } from '@gitlab/ui';
|
import { GlButton } from '@gitlab/ui';
|
||||||
import { unionBy } from 'lodash';
|
import { unionBy } from 'lodash';
|
||||||
import { sortNameAlphabetically } from '~/work_items/utils';
|
import { sortNameAlphabetically, newWorkItemId } from '~/work_items/utils';
|
||||||
import currentUserQuery from '~/graphql_shared/queries/current_user.query.graphql';
|
import currentUserQuery from '~/graphql_shared/queries/current_user.query.graphql';
|
||||||
import usersSearchQuery from '~/graphql_shared/queries/workspace_autocomplete_users.query.graphql';
|
import usersSearchQuery from '~/graphql_shared/queries/workspace_autocomplete_users.query.graphql';
|
||||||
import InviteMembersTrigger from '~/invite_members/components/invite_members_trigger.vue';
|
import InviteMembersTrigger from '~/invite_members/components/invite_members_trigger.vue';
|
||||||
|
|
@ -12,7 +12,7 @@ import { s__, sprintf, __ } from '~/locale';
|
||||||
import Tracking from '~/tracking';
|
import Tracking from '~/tracking';
|
||||||
import updateWorkItemMutation from '../graphql/update_work_item.mutation.graphql';
|
import updateWorkItemMutation from '../graphql/update_work_item.mutation.graphql';
|
||||||
import updateNewWorkItemMutation from '../graphql/update_new_work_item.mutation.graphql';
|
import updateNewWorkItemMutation from '../graphql/update_new_work_item.mutation.graphql';
|
||||||
import { i18n, TRACKING_CATEGORY_SHOW, NEW_WORK_ITEM_GID } from '../constants';
|
import { i18n, TRACKING_CATEGORY_SHOW } from '../constants';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
|
|
@ -236,12 +236,13 @@ export default {
|
||||||
this.updateInProgress = true;
|
this.updateInProgress = true;
|
||||||
const { localAssigneeIds } = this;
|
const { localAssigneeIds } = this;
|
||||||
|
|
||||||
if (this.workItemId === NEW_WORK_ITEM_GID) {
|
if (this.workItemId === newWorkItemId(this.workItemType)) {
|
||||||
this.$apollo.mutate({
|
this.$apollo.mutate({
|
||||||
mutation: updateNewWorkItemMutation,
|
mutation: updateNewWorkItemMutation,
|
||||||
variables: {
|
variables: {
|
||||||
input: {
|
input: {
|
||||||
isGroup: this.isGroup,
|
isGroup: this.isGroup,
|
||||||
|
workItemType: this.workItemType,
|
||||||
fullPath: this.fullPath,
|
fullPath: this.fullPath,
|
||||||
assignees: this.localAssignees,
|
assignees: this.localAssignees,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,11 @@ export default {
|
||||||
required: false,
|
required: false,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
workItemTypeName: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
markdownDocsPath: helpPagePath('user/markdown'),
|
markdownDocsPath: helpPagePath('user/markdown'),
|
||||||
data() {
|
data() {
|
||||||
|
|
@ -99,7 +104,7 @@ export default {
|
||||||
},
|
},
|
||||||
variables() {
|
variables() {
|
||||||
return {
|
return {
|
||||||
fullPath: this.createFlow ? newWorkItemFullPath(this.fullPath) : this.fullPath,
|
fullPath: this.workItemFullPath,
|
||||||
iid: this.workItemIid,
|
iid: this.workItemIid,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
@ -117,6 +122,11 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
workItemFullPath() {
|
||||||
|
return this.createFlow
|
||||||
|
? newWorkItemFullPath(this.fullPath, this.workItemTypeName)
|
||||||
|
: this.fullPath;
|
||||||
|
},
|
||||||
autosaveKey() {
|
autosaveKey() {
|
||||||
return this.workItemId || `new-${this.workItemType}-description-draft`;
|
return this.workItemId || `new-${this.workItemType}-description-draft`;
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ export default {
|
||||||
<gl-disclosure-dropdown
|
<gl-disclosure-dropdown
|
||||||
:toggle-text="__('Add')"
|
:toggle-text="__('Add')"
|
||||||
size="small"
|
size="small"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
:items="actions"
|
:items="actions"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -249,7 +249,7 @@ export default {
|
||||||
/>
|
/>
|
||||||
<gl-disclosure-dropdown
|
<gl-disclosure-dropdown
|
||||||
v-if="canUpdate && canAddTask"
|
v-if="canUpdate && canAddTask"
|
||||||
placement="right"
|
placement="bottom-end"
|
||||||
size="small"
|
size="small"
|
||||||
:toggle-text="$options.i18n.addChildButtonLabel"
|
:toggle-text="$options.i18n.addChildButtonLabel"
|
||||||
data-testid="toggle-form"
|
data-testid="toggle-form"
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,12 @@ import { TYPENAME_USER } from '~/graphql_shared/constants';
|
||||||
import { convertToGraphQLId } from '~/graphql_shared/utils';
|
import { convertToGraphQLId } from '~/graphql_shared/utils';
|
||||||
import { getBaseURL } from '~/lib/utils/url_utility';
|
import { getBaseURL } from '~/lib/utils/url_utility';
|
||||||
import { convertEachWordToTitleCase } from '~/lib/utils/text_utility';
|
import { convertEachWordToTitleCase } from '~/lib/utils/text_utility';
|
||||||
import { findHierarchyWidgetChildren, isNotesWidget, newWorkItemFullPath } from '../utils';
|
import {
|
||||||
|
findHierarchyWidgetChildren,
|
||||||
|
isNotesWidget,
|
||||||
|
newWorkItemFullPath,
|
||||||
|
newWorkItemId,
|
||||||
|
} from '../utils';
|
||||||
import {
|
import {
|
||||||
WIDGET_TYPE_ASSIGNEES,
|
WIDGET_TYPE_ASSIGNEES,
|
||||||
WIDGET_TYPE_COLOR,
|
WIDGET_TYPE_COLOR,
|
||||||
|
|
@ -23,7 +28,6 @@ import {
|
||||||
WIDGET_TYPE_HEALTH_STATUS,
|
WIDGET_TYPE_HEALTH_STATUS,
|
||||||
WIDGET_TYPE_DESCRIPTION,
|
WIDGET_TYPE_DESCRIPTION,
|
||||||
NEW_WORK_ITEM_IID,
|
NEW_WORK_ITEM_IID,
|
||||||
NEW_WORK_ITEM_GID,
|
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import groupWorkItemByIidQuery from './group_work_item_by_iid.query.graphql';
|
import groupWorkItemByIidQuery from './group_work_item_by_iid.query.graphql';
|
||||||
import workItemByIidQuery from './work_item_by_iid.query.graphql';
|
import workItemByIidQuery from './work_item_by_iid.query.graphql';
|
||||||
|
|
@ -265,8 +269,8 @@ export const setNewWorkItemCache = async (
|
||||||
);
|
);
|
||||||
widgets.push({
|
widgets.push({
|
||||||
type: 'ASSIGNEES',
|
type: 'ASSIGNEES',
|
||||||
allowsMultipleAssignees: assigneesWidgetData.allowsMultipleAssignees,
|
allowsMultipleAssignees: assigneesWidgetData.allowsMultipleAssignees || false,
|
||||||
canInviteMembers: assigneesWidgetData.canInviteMembers,
|
canInviteMembers: assigneesWidgetData.canInviteMembers || false,
|
||||||
assignees: {
|
assignees: {
|
||||||
nodes: [],
|
nodes: [],
|
||||||
__typename: 'UserCoreConnection',
|
__typename: 'UserCoreConnection',
|
||||||
|
|
@ -398,17 +402,19 @@ export const setNewWorkItemCache = async (
|
||||||
? issuesListApolloProvider
|
? issuesListApolloProvider
|
||||||
: apolloProvider;
|
: apolloProvider;
|
||||||
|
|
||||||
|
const newWorkItemPath = newWorkItemFullPath(fullPath, workItemType);
|
||||||
|
|
||||||
cacheProvider.clients.defaultClient.cache.writeQuery({
|
cacheProvider.clients.defaultClient.cache.writeQuery({
|
||||||
query: isGroup ? groupWorkItemByIidQuery : workItemByIidQuery,
|
query: isGroup ? groupWorkItemByIidQuery : workItemByIidQuery,
|
||||||
variables: {
|
variables: {
|
||||||
fullPath: newWorkItemFullPath(fullPath),
|
fullPath: newWorkItemPath,
|
||||||
iid: NEW_WORK_ITEM_IID,
|
iid: NEW_WORK_ITEM_IID,
|
||||||
},
|
},
|
||||||
data: {
|
data: {
|
||||||
workspace: {
|
workspace: {
|
||||||
id: newWorkItemFullPath(fullPath),
|
id: newWorkItemPath,
|
||||||
workItem: {
|
workItem: {
|
||||||
id: NEW_WORK_ITEM_GID,
|
id: newWorkItemId(workItemType),
|
||||||
iid: NEW_WORK_ITEM_IID,
|
iid: NEW_WORK_ITEM_IID,
|
||||||
archived: false,
|
archived: false,
|
||||||
title: '',
|
title: '',
|
||||||
|
|
@ -422,9 +428,9 @@ export const setNewWorkItemCache = async (
|
||||||
reference: '',
|
reference: '',
|
||||||
createNoteEmail: null,
|
createNoteEmail: null,
|
||||||
namespace: {
|
namespace: {
|
||||||
id: newWorkItemFullPath(fullPath),
|
id: newWorkItemPath,
|
||||||
fullPath,
|
fullPath,
|
||||||
name: newWorkItemFullPath(fullPath),
|
name: newWorkItemPath,
|
||||||
__typename: 'Namespace', // eslint-disable-line @gitlab/require-i18n-strings
|
__typename: 'Namespace', // eslint-disable-line @gitlab/require-i18n-strings
|
||||||
},
|
},
|
||||||
author: {
|
author: {
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ extend type Mutation {
|
||||||
|
|
||||||
input LocalUpdateNewWorkItemInput {
|
input LocalUpdateNewWorkItemInput {
|
||||||
fullPath: String!
|
fullPath: String!
|
||||||
|
workItemType: String!
|
||||||
isGroup: Boolean!
|
isGroup: Boolean!
|
||||||
healthStatus: String
|
healthStatus: String
|
||||||
assignees: [LocalUserInput]
|
assignees: [LocalUserInput]
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import {
|
||||||
WORK_ITEM_TYPE_ENUM_OBJECTIVE,
|
WORK_ITEM_TYPE_ENUM_OBJECTIVE,
|
||||||
WORK_ITEM_TYPE_ENUM_KEY_RESULT,
|
WORK_ITEM_TYPE_ENUM_KEY_RESULT,
|
||||||
WORK_ITEM_TYPE_ENUM_REQUIREMENTS,
|
WORK_ITEM_TYPE_ENUM_REQUIREMENTS,
|
||||||
|
NEW_WORK_ITEM_GID,
|
||||||
} from './constants';
|
} from './constants';
|
||||||
|
|
||||||
export const isAssigneesWidget = (widget) => widget.type === WIDGET_TYPE_ASSIGNEES;
|
export const isAssigneesWidget = (widget) => widget.type === WIDGET_TYPE_ASSIGNEES;
|
||||||
|
|
@ -156,11 +157,15 @@ export const workItemRoadmapPath = (fullPath, iid) => {
|
||||||
* Builds unique path for new work item
|
* Builds unique path for new work item
|
||||||
*
|
*
|
||||||
* @param {string} fullPath the path to the namespace
|
* @param {string} fullPath the path to the namespace
|
||||||
|
* @param {string} workItemType the type of work item
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const newWorkItemFullPath = (fullPath) => {
|
export const newWorkItemFullPath = (fullPath, workItemType) => {
|
||||||
|
if (!workItemType) return undefined;
|
||||||
|
|
||||||
|
const workItemTypeLowercase = workItemType.split(' ').join('-').toLowerCase();
|
||||||
// eslint-disable-next-line @gitlab/require-i18n-strings
|
// eslint-disable-next-line @gitlab/require-i18n-strings
|
||||||
return `${fullPath}-id`;
|
return `${fullPath}-${workItemTypeLowercase}-id`;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -183,3 +188,10 @@ export const isWorkItemItemValidEnum = (workItemType) => {
|
||||||
].indexOf(workItemType) >= 0
|
].indexOf(workItemType) >= 0
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const newWorkItemId = (workItemType) => {
|
||||||
|
if (!workItemType) return undefined;
|
||||||
|
|
||||||
|
const workItemTypeLowercase = workItemType.split(' ').join('-').toLowerCase();
|
||||||
|
return `${NEW_WORK_ITEM_GID}-${workItemTypeLowercase}`;
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,9 @@
|
||||||
.gl-grow
|
.gl-grow
|
||||||
%h2{ class: title_classes }
|
%h2{ class: title_classes }
|
||||||
= heading || @heading
|
= heading || @heading
|
||||||
%p.gl-text-secondary.gl-m-0
|
- if description || @description
|
||||||
= description || @description
|
%p.gl-text-secondary.gl-m-0
|
||||||
|
= description || @description
|
||||||
.gl-shrink-0.gl-px-2
|
.gl-shrink-0.gl-px-2
|
||||||
= render Pajamas::ButtonComponent.new(button_options: @button_options.merge(class: 'gl-min-w-12 js-settings-toggle')) do
|
= render Pajamas::ButtonComponent.new(button_options: @button_options.merge(class: 'gl-min-w-12 js-settings-toggle')) do
|
||||||
= button_text
|
= button_text
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
%section.settings-section{ id: @id, data: (@testid ? { testid: @testid } : {}) }
|
||||||
|
.settings-sticky-header
|
||||||
|
.settings-sticky-header-inner
|
||||||
|
%h2.gl-heading-2{ class: '!gl-mb-2' }
|
||||||
|
= heading || @heading
|
||||||
|
- if description || @description
|
||||||
|
%p.gl-text-secondary.gl-m-0
|
||||||
|
= description || @description
|
||||||
|
%div{ data: { testid: 'settings-section-body' } }
|
||||||
|
= body
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Layouts
|
||||||
|
class SettingsSectionComponent < ViewComponent::Base
|
||||||
|
# @param [String] heading
|
||||||
|
# @param [String] description
|
||||||
|
# @param [String] id
|
||||||
|
# @param [String] testid
|
||||||
|
def initialize(heading, description: nil, id: nil, testid: nil)
|
||||||
|
@heading = heading
|
||||||
|
@description = description
|
||||||
|
@id = id
|
||||||
|
@testid = testid
|
||||||
|
end
|
||||||
|
|
||||||
|
renders_one :heading
|
||||||
|
renders_one :description
|
||||||
|
renders_one :body
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -20,7 +20,7 @@ module ProtectedRef
|
||||||
end
|
end
|
||||||
|
|
||||||
def commit
|
def commit
|
||||||
project.commit(self.name)
|
project&.commit(name)
|
||||||
end
|
end
|
||||||
|
|
||||||
class_methods do
|
class_methods do
|
||||||
|
|
@ -59,7 +59,7 @@ module ProtectedRef
|
||||||
end
|
end
|
||||||
|
|
||||||
def access_levels_for_ref(ref, action:, protected_refs: nil)
|
def access_levels_for_ref(ref, action:, protected_refs: nil)
|
||||||
self.matching(ref, protected_refs: protected_refs)
|
matching(ref, protected_refs: protected_refs)
|
||||||
.flat_map(&:"#{action}_access_levels")
|
.flat_map(&:"#{action}_access_levels")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -70,14 +70,14 @@ module ProtectedRef
|
||||||
# This method optionally takes in a list of `protected_refs` to search
|
# This method optionally takes in a list of `protected_refs` to search
|
||||||
# through, to avoid calling out to the database.
|
# through, to avoid calling out to the database.
|
||||||
def matching(ref_name, protected_refs: nil)
|
def matching(ref_name, protected_refs: nil)
|
||||||
(protected_refs || self.all).select { |protected_ref| protected_ref.matches?(ref_name) }
|
(protected_refs || all).select { |protected_ref| protected_ref.matches?(ref_name) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def ref_matcher
|
def ref_matcher
|
||||||
@ref_matcher ||= RefMatcher.new(self.name)
|
@ref_matcher ||= RefMatcher.new(name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ class ProtectedBranch < ApplicationRecord
|
||||||
belongs_to :group, foreign_key: :namespace_id, touch: true, inverse_of: :protected_branches
|
belongs_to :group, foreign_key: :namespace_id, touch: true, inverse_of: :protected_branches
|
||||||
|
|
||||||
validate :validate_either_project_or_top_group
|
validate :validate_either_project_or_top_group
|
||||||
validates :name, presence: true
|
|
||||||
validates :name, uniqueness: { scope: [:project_id, :namespace_id] }, if: :name_changed?
|
validates :name, uniqueness: { scope: [:project_id, :namespace_id] }, if: :name_changed?
|
||||||
|
|
||||||
scope :requiring_code_owner_approval, -> { where(code_owner_approval_required: true) }
|
scope :requiring_code_owner_approval, -> { where(code_owner_approval_required: true) }
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,6 @@ module Ci
|
||||||
def execute
|
def execute
|
||||||
in_lock(EXCLUSIVE_LOCK_KEY, ttl: LOCK_TIMEOUT, retries: 1) do
|
in_lock(EXCLUSIVE_LOCK_KEY, ttl: LOCK_TIMEOUT, retries: 1) do
|
||||||
destroy_unlocked_pipeline_artifacts
|
destroy_unlocked_pipeline_artifacts
|
||||||
|
|
||||||
legacy_destroy_pipeline_artifacts
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@removed_artifacts_count
|
@removed_artifacts_count
|
||||||
|
|
@ -40,19 +38,6 @@ module Ci
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def legacy_destroy_pipeline_artifacts
|
|
||||||
loop_until(timeout: LOOP_TIMEOUT, limit: LOOP_LIMIT) do
|
|
||||||
destroy_artifacts_batch
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def destroy_artifacts_batch
|
|
||||||
artifacts = ::Ci::PipelineArtifact.unlocked.expired.limit(BATCH_SIZE).to_a
|
|
||||||
return false if artifacts.empty?
|
|
||||||
|
|
||||||
destroy_batch(artifacts)
|
|
||||||
end
|
|
||||||
|
|
||||||
def destroy_batch(artifacts)
|
def destroy_batch(artifacts)
|
||||||
artifacts.each(&:destroy!)
|
artifacts.each(&:destroy!)
|
||||||
increment_stats(artifacts.size)
|
increment_stats(artifacts.size)
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,13 @@
|
||||||
- if Gitlab.config.packages.enabled
|
- if Gitlab.config.packages.enabled
|
||||||
%section.settings.as-package.no-animate#js-package-settings{ class: ('expanded' if expanded_by_default?) }
|
= render ::Layouts::SettingsBlockComponent.new(_('Package Registry'),
|
||||||
.settings-header
|
id: 'js-package-settings',
|
||||||
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
|
expanded: expanded_by_default?) do |c|
|
||||||
= _('Package Registry')
|
- c.with_description do
|
||||||
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
|
= s_('PackageRegistry|Configure package forwarding and package file size limits.')
|
||||||
= expanded_by_default? ? _('Collapse') : _('Expand')
|
- c.with_body do
|
||||||
%p.gl-text-secondary
|
|
||||||
= s_('PackageRegistry|Configure package forwarding and package file size limits.')
|
|
||||||
|
|
||||||
.settings-content
|
|
||||||
= render_if_exists 'admin/application_settings/ee_package_registry'
|
= render_if_exists 'admin/application_settings/ee_package_registry'
|
||||||
= render 'admin/application_settings/nuget_skip_metadata_url_validation' unless Gitlab.ee?
|
= render 'admin/application_settings/nuget_skip_metadata_url_validation' unless Gitlab.ee?
|
||||||
|
|
||||||
|
|
||||||
.gl-mt-7
|
.gl-mt-7
|
||||||
%h4
|
%h4
|
||||||
= _('Package file size limits')
|
= _('Package file size limits')
|
||||||
|
|
|
||||||
|
|
@ -3,161 +3,140 @@
|
||||||
= gitlab_ui_form_for @appearance, url: admin_application_settings_appearances_path, html: { class: 'gl-mt-3' } do |f|
|
= gitlab_ui_form_for @appearance, url: admin_application_settings_appearances_path, html: { class: 'gl-mt-3' } do |f|
|
||||||
= form_errors(@appearance)
|
= form_errors(@appearance)
|
||||||
|
|
||||||
.settings-section
|
= render ::Layouts::SettingsSectionComponent.new(_('Favicon')) do |c|
|
||||||
.settings-sticky-header
|
- c.with_body do
|
||||||
.settings-sticky-header-inner
|
.form-group
|
||||||
%h4.gl-my-0 Favicon
|
= f.label :favicon, _('Favicon'), class: 'col-form-label gl-pt-0'
|
||||||
|
%p
|
||||||
.form-group
|
- if @appearance.favicon?
|
||||||
= f.label :favicon, _('Favicon'), class: 'col-form-label gl-pt-0'
|
= image_tag @appearance.favicon_path, class: 'appearance-light-logo-preview'
|
||||||
%p
|
- if @appearance.persisted?
|
||||||
- if @appearance.favicon?
|
%br
|
||||||
= image_tag @appearance.favicon_path, class: 'appearance-light-logo-preview'
|
= render Pajamas::ButtonComponent.new(variant: :danger, category: :secondary, size: :small, method: :delete, href: favicon_admin_application_settings_appearances_path, button_options: { data: { confirm: _("Favicon will be removed. Are you sure?"), confirm_btn_variant: "danger" }, aria: { label: _('Remove favicon') } }) do
|
||||||
- if @appearance.persisted?
|
= _('Remove favicon')
|
||||||
|
%hr
|
||||||
|
= f.hidden_field :favicon_cache
|
||||||
|
= f.file_field :favicon, class: '', accept: 'image/*'
|
||||||
|
.form-text.gl-text-secondary
|
||||||
|
= _("Maximum file size is 1 MB. Image size must be 32 x 32 pixels. Allowed image formats are %{favicon_extension_allowlist}.") % { favicon_extension_allowlist: favicon_extension_allowlist }
|
||||||
%br
|
%br
|
||||||
= render Pajamas::ButtonComponent.new(variant: :danger, category: :secondary, size: :small, method: :delete, href: favicon_admin_application_settings_appearances_path, button_options: { data: { confirm: _("Favicon will be removed. Are you sure?"), confirm_btn_variant: "danger" }, aria: { label: _('Remove favicon') } }) do
|
= _("Images with incorrect dimensions are not resized automatically, and may result in unexpected behavior.")
|
||||||
= _('Remove favicon')
|
|
||||||
%hr
|
|
||||||
= f.hidden_field :favicon_cache
|
|
||||||
= f.file_field :favicon, class: '', accept: 'image/*'
|
|
||||||
.form-text.text-muted
|
|
||||||
= _("Maximum file size is 1 MB. Image size must be 32 x 32 pixels. Allowed image formats are %{favicon_extension_allowlist}.") % { favicon_extension_allowlist: favicon_extension_allowlist }
|
|
||||||
%br
|
|
||||||
= _("Images with incorrect dimensions are not resized automatically, and may result in unexpected behavior.")
|
|
||||||
|
|
||||||
.settings-section
|
= render ::Layouts::SettingsSectionComponent.new(_('Member guidelines')) do |c|
|
||||||
.settings-sticky-header
|
- c.with_description do
|
||||||
.settings-sticky-header-inner
|
|
||||||
%h4.gl-my-0= _('Member guidelines')
|
|
||||||
|
|
||||||
.form-text.text-muted
|
|
||||||
= _('These guidelines are displayed on the group\'s or project\'s members page, and are visible to users who can manage team member permissions.')
|
= _('These guidelines are displayed on the group\'s or project\'s members page, and are visible to users who can manage team member permissions.')
|
||||||
|
- c.with_body do
|
||||||
|
.form-group
|
||||||
|
= f.label :member_guidelines, class: 'col-form-label'
|
||||||
|
%p
|
||||||
|
= f.text_area :member_guidelines, class: "form-control gl-form-input", rows: 10
|
||||||
|
.form-text.gl-text-secondary
|
||||||
|
= parsed_with_gfm
|
||||||
|
|
||||||
.form-group
|
= render ::Layouts::SettingsSectionComponent.new(_('Navigation bar')) do |c|
|
||||||
= f.label :member_guidelines, class: 'col-form-label'
|
- c.with_body do
|
||||||
%p
|
.form-group
|
||||||
= f.text_area :member_guidelines, class: "form-control gl-form-input", rows: 10
|
= f.label :header_logo, _('Header logo'), class: 'col-form-label gl-pt-0'
|
||||||
.form-text.text-muted
|
%p
|
||||||
= parsed_with_gfm
|
- if @appearance.header_logo?
|
||||||
|
= image_tag @appearance.header_logo_path, class: 'appearance-light-logo-preview'
|
||||||
|
- if @appearance.persisted?
|
||||||
|
%br
|
||||||
|
= render Pajamas::ButtonComponent.new(variant: :danger, category: :secondary, size: :small, method: :delete, href: header_logos_admin_application_settings_appearances_path, button_options: { data: { confirm: _("Header logo will be removed. Are you sure?"), confirm_btn_variant: "danger" }, aria: { label: _('Remove header logo') } }) do
|
||||||
|
= _('Remove header logo')
|
||||||
|
%hr
|
||||||
|
= f.hidden_field :header_logo_cache
|
||||||
|
= f.file_field :header_logo, class: "", accept: 'image/*'
|
||||||
|
.form-text.gl-text-secondary
|
||||||
|
= _('Maximum file size is 1MB. Pages are optimized for a 24px tall header logo')
|
||||||
|
|
||||||
.settings-section
|
|
||||||
.settings-sticky-header
|
|
||||||
.settings-sticky-header-inner
|
|
||||||
%h4.gl-my-0= _('Navigation bar')
|
|
||||||
|
|
||||||
.form-group
|
= render ::Layouts::SettingsSectionComponent.new(_('New project pages')) do |c|
|
||||||
= f.label :header_logo, _('Header logo'), class: 'col-form-label gl-pt-0'
|
- c.with_body do
|
||||||
%p
|
.form-group
|
||||||
- if @appearance.header_logo?
|
= f.label :new_project_guidelines, class: 'col-form-label'
|
||||||
= image_tag @appearance.header_logo_path, class: 'appearance-light-logo-preview'
|
%p
|
||||||
- if @appearance.persisted?
|
= f.text_area :new_project_guidelines, class: "form-control gl-form-input", rows: 10
|
||||||
%br
|
.form-text.gl-text-secondary
|
||||||
= render Pajamas::ButtonComponent.new(variant: :danger, category: :secondary, size: :small, method: :delete, href: header_logos_admin_application_settings_appearances_path, button_options: { data: { confirm: _("Header logo will be removed. Are you sure?"), confirm_btn_variant: "danger" }, aria: { label: _('Remove header logo') } }) do
|
= parsed_with_gfm
|
||||||
= _('Remove header logo')
|
|
||||||
%hr
|
|
||||||
= f.hidden_field :header_logo_cache
|
|
||||||
= f.file_field :header_logo, class: "", accept: 'image/*'
|
|
||||||
.form-text.text-muted
|
|
||||||
= _('Maximum file size is 1MB. Pages are optimized for a 24px tall header logo')
|
|
||||||
|
|
||||||
.settings-section
|
= render ::Layouts::SettingsSectionComponent.new(_('Profile image guidelines')) do |c|
|
||||||
.settings-sticky-header
|
- c.with_description do
|
||||||
.settings-sticky-header-inner
|
|
||||||
%h4.gl-my-0= _('New project pages')
|
|
||||||
|
|
||||||
.form-group
|
|
||||||
= f.label :new_project_guidelines, class: 'col-form-label'
|
|
||||||
%p
|
|
||||||
= f.text_area :new_project_guidelines, class: "form-control gl-form-input", rows: 10
|
|
||||||
.form-text.text-muted
|
|
||||||
= parsed_with_gfm
|
|
||||||
|
|
||||||
.settings-section
|
|
||||||
.settings-sticky-header
|
|
||||||
.settings-sticky-header-inner
|
|
||||||
%h4.gl-my-0= _('Profile image guidelines')
|
|
||||||
|
|
||||||
%p.gl-text-secondary
|
|
||||||
= _('These guidelines for public avatars are displayed on the user settings page.')
|
= _('These guidelines for public avatars are displayed on the user settings page.')
|
||||||
|
- c.with_body do
|
||||||
|
.form-group
|
||||||
|
= f.label :profile_image_guidelines, class: 'col-form-label'
|
||||||
|
%p
|
||||||
|
= f.text_area :profile_image_guidelines, class: "form-control gl-form-input", rows: 10
|
||||||
|
.form-text.gl-text-secondary
|
||||||
|
= parsed_with_gfm
|
||||||
|
|
||||||
.form-group
|
= render ::Layouts::SettingsSectionComponent.new(_('Progressive Web App (PWA)')) do |c|
|
||||||
= f.label :profile_image_guidelines, class: 'col-form-label'
|
- c.with_body do
|
||||||
%p
|
.form-group
|
||||||
= f.text_area :profile_image_guidelines, class: "form-control gl-form-input", rows: 10
|
= f.label _("Name"), class: 'col-form-label'
|
||||||
.form-text.text-muted
|
= f.text_field :pwa_name, class: "form-control gl-form-input"
|
||||||
|
.form-group
|
||||||
|
= f.label _("Short name"), class: 'col-form-label'
|
||||||
|
= f.text_field :pwa_short_name, class: "form-control gl-form-input"
|
||||||
|
.form-group
|
||||||
|
= f.label _("Description"), class: 'col-form-label'
|
||||||
|
= f.text_area :pwa_description, class: "form-control gl-form-input", rows: 10
|
||||||
|
.form-text.gl-text-secondary
|
||||||
= parsed_with_gfm
|
= parsed_with_gfm
|
||||||
|
.form-group
|
||||||
|
= f.label :pwa_icon, class: 'col-form-label gl-pt-0'
|
||||||
|
%p
|
||||||
|
- if @appearance.pwa_icon?
|
||||||
|
= image_tag @appearance.pwa_icon_path, class: 'appearance-pwa-icon-preview'
|
||||||
|
- if @appearance.persisted?
|
||||||
|
%br
|
||||||
|
= render Pajamas::ButtonComponent.new(variant: :danger, category: :secondary, size: :small, method: :delete, href: pwa_icon_admin_application_settings_appearances_path, button_options: { data: { confirm: _("Icon will be removed. Are you sure?"), confirm_btn_variant: "danger" }, aria: { label: _('Remove icon') } }) do
|
||||||
|
= _('Remove icon')
|
||||||
|
%hr
|
||||||
|
= f.hidden_field :pwa_icon_cache
|
||||||
|
= f.file_field :pwa_icon, class: "", accept: 'image/*'
|
||||||
|
.form-text.gl-text-secondary
|
||||||
|
= _('Maximum file size is 1MB.')
|
||||||
|
|
||||||
.settings-section
|
= render ::Layouts::SettingsSectionComponent.new(_('Sign in/Sign up pages')) do |c|
|
||||||
.settings-sticky-header
|
- c.with_body do
|
||||||
.settings-sticky-header-inner
|
.form-group
|
||||||
%h4.gl-my-0= _('Progressive Web App (PWA)')
|
= f.label :title, class: 'col-form-label'
|
||||||
|
= f.text_field :title, class: "form-control gl-form-input"
|
||||||
.form-group
|
.form-group
|
||||||
= f.label _("Name"), class: 'col-form-label'
|
= f.label :description, class: 'col-form-label'
|
||||||
= f.text_field :pwa_name, class: "form-control gl-form-input"
|
= f.text_area :description, class: "form-control gl-form-input", rows: 10
|
||||||
.form-group
|
.form-text.gl-text-secondary
|
||||||
= f.label _("Short name"), class: 'col-form-label'
|
= parsed_with_gfm
|
||||||
= f.text_field :pwa_short_name, class: "form-control gl-form-input"
|
.form-group
|
||||||
.form-group
|
= f.label :logo, class: 'col-form-label gl-pt-0'
|
||||||
= f.label _("Description"), class: 'col-form-label'
|
%p
|
||||||
= f.text_area :pwa_description, class: "form-control gl-form-input", rows: 10
|
- if @appearance.logo?
|
||||||
.form-text.text-muted
|
= image_tag @appearance.logo_path, class: 'appearance-logo-preview'
|
||||||
= parsed_with_gfm
|
- if @appearance.persisted?
|
||||||
.form-group
|
%br
|
||||||
= f.label :pwa_icon, class: 'col-form-label gl-pt-0'
|
= render Pajamas::ButtonComponent.new(variant: :danger, category: :secondary, size: :small, method: :delete, href: logo_admin_application_settings_appearances_path, button_options: { data: { confirm: _("Logo will be removed. Are you sure?"), confirm_btn_variant: "danger" }, aria: { label: _('Remove logo') } }) do
|
||||||
%p
|
= _('Remove logo')
|
||||||
- if @appearance.pwa_icon?
|
%hr
|
||||||
= image_tag @appearance.pwa_icon_path, class: 'appearance-pwa-icon-preview'
|
= f.hidden_field :logo_cache
|
||||||
- if @appearance.persisted?
|
= f.file_field :logo, class: "", accept: 'image/*'
|
||||||
%br
|
.form-text.gl-text-secondary
|
||||||
= render Pajamas::ButtonComponent.new(variant: :danger, category: :secondary, size: :small, method: :delete, href: pwa_icon_admin_application_settings_appearances_path, button_options: { data: { confirm: _("Icon will be removed. Are you sure?"), confirm_btn_variant: "danger" }, aria: { label: _('Remove icon') } }) do
|
= _('Maximum file size is 1 MB. Pages are optimized for a 128x128 px logo.')
|
||||||
= _('Remove icon')
|
|
||||||
%hr
|
|
||||||
= f.hidden_field :pwa_icon_cache
|
|
||||||
= f.file_field :pwa_icon, class: "", accept: 'image/*'
|
|
||||||
.form-text.text-muted
|
|
||||||
= _('Maximum file size is 1MB.')
|
|
||||||
|
|
||||||
.settings-section
|
|
||||||
.settings-sticky-header
|
|
||||||
.settings-sticky-header-inner
|
|
||||||
%h4.gl-my-0= _('Sign in/Sign up pages')
|
|
||||||
|
|
||||||
.form-group
|
|
||||||
= f.label :title, class: 'col-form-label'
|
|
||||||
= f.text_field :title, class: "form-control gl-form-input"
|
|
||||||
.form-group
|
|
||||||
= f.label :description, class: 'col-form-label'
|
|
||||||
= f.text_area :description, class: "form-control gl-form-input", rows: 10
|
|
||||||
.form-text.text-muted
|
|
||||||
= parsed_with_gfm
|
|
||||||
.form-group
|
|
||||||
= f.label :logo, class: 'col-form-label gl-pt-0'
|
|
||||||
%p
|
|
||||||
- if @appearance.logo?
|
|
||||||
= image_tag @appearance.logo_path, class: 'appearance-logo-preview'
|
|
||||||
- if @appearance.persisted?
|
|
||||||
%br
|
|
||||||
= render Pajamas::ButtonComponent.new(variant: :danger, category: :secondary, size: :small, method: :delete, href: logo_admin_application_settings_appearances_path, button_options: { data: { confirm: _("Logo will be removed. Are you sure?"), confirm_btn_variant: "danger" }, aria: { label: _('Remove logo') } }) do
|
|
||||||
= _('Remove logo')
|
|
||||||
%hr
|
|
||||||
= f.hidden_field :logo_cache
|
|
||||||
= f.file_field :logo, class: "", accept: 'image/*'
|
|
||||||
.form-text.text-muted
|
|
||||||
= _('Maximum file size is 1 MB. Pages are optimized for a 128x128 px logo.')
|
|
||||||
|
|
||||||
= render partial: 'admin/application_settings/appearances/system_header_footer_form', locals: { form: f }
|
= render partial: 'admin/application_settings/appearances/system_header_footer_form', locals: { form: f }
|
||||||
|
|
||||||
- if @appearance.persisted? || @appearance.updated_at
|
- if @appearance.persisted? || @appearance.updated_at
|
||||||
.settings-section
|
.settings-section
|
||||||
- if @appearance.persisted?
|
- if @appearance.persisted?
|
||||||
Preview last save:
|
= s_('AppearanceSettings|Preview last save:')
|
||||||
= link_to _('Sign-in page'), preview_sign_in_admin_application_settings_appearances_path, class: 'btn', target: '_blank', rel: 'noopener noreferrer'
|
= link_to _('Sign-in page'), preview_sign_in_admin_application_settings_appearances_path, class: 'btn', target: '_blank', rel: 'noopener noreferrer'
|
||||||
= link_to _('New project page'), new_project_path, class: 'btn', target: '_blank', rel: 'noopener noreferrer'
|
= link_to _('New project page'), new_project_path, class: 'btn', target: '_blank', rel: 'noopener noreferrer'
|
||||||
|
|
||||||
- if @appearance.updated_at
|
- if @appearance.updated_at
|
||||||
%span.gl-float-right
|
%span.gl-float-right.gl-text-secondary
|
||||||
Last edit #{time_ago_with_tooltip(@appearance.updated_at)}
|
= s_('AppearanceSettings|Last edit')
|
||||||
|
#{time_ago_with_tooltip(@appearance.updated_at)}
|
||||||
|
|
||||||
.settings-sticky-footer
|
.settings-sticky-footer
|
||||||
= f.submit _('Update appearance settings'), pajamas_button: true
|
= f.submit _('Update appearance settings'), pajamas_button: true
|
||||||
|
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
- expanded = local_assigns.fetch(:expanded)
|
|
||||||
|
|
||||||
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
|
|
||||||
= _('Variables')
|
|
||||||
|
|
||||||
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
|
|
||||||
= expanded ? _('Collapse') : _('Expand')
|
|
||||||
|
|
||||||
%p.gl-text-secondary
|
|
||||||
= s_('CiVariables|Variables store information that you can use in job scripts. All projects on the instance can use these variables.')
|
|
||||||
= link_to _('Learn more.'), help_page_path('ci/variables/index', anchor: 'for-an-instance'), target: '_blank', rel: 'noopener noreferrer'
|
|
||||||
|
|
@ -3,10 +3,13 @@
|
||||||
- add_page_specific_style 'page_bundles/settings'
|
- add_page_specific_style 'page_bundles/settings'
|
||||||
- @force_desktop_expanded_sidebar = true
|
- @force_desktop_expanded_sidebar = true
|
||||||
|
|
||||||
%section.settings.no-animate#js-ci-cd-variables{ class: ('expanded' if expanded_by_default?) }
|
= render ::Layouts::SettingsBlockComponent.new(_('Variables'),
|
||||||
.settings-header
|
id: 'js-ci-cd-variables',
|
||||||
= render 'admin/application_settings/ci/header', expanded: expanded_by_default?
|
expanded: expanded_by_default?) do |c|
|
||||||
.settings-content
|
- c.with_description do
|
||||||
|
= s_('CiVariables|Variables store information that you can use in job scripts. All projects on the instance can use these variables.')
|
||||||
|
= link_to _('Learn more.'), help_page_path('ci/variables/index', anchor: 'for-an-instance'), target: '_blank', rel: 'noopener noreferrer'
|
||||||
|
- c.with_body do
|
||||||
= render 'ci/variables/attributes'
|
= render 'ci/variables/attributes'
|
||||||
- if ci_variable_protected_by_default?
|
- if ci_variable_protected_by_default?
|
||||||
%p.settings-message.gl-text-center
|
%p.settings-message.gl-text-center
|
||||||
|
|
@ -14,35 +17,32 @@
|
||||||
= safe_format(s_('Environment variables on this GitLab instance are configured to be %{help_link_start}protected%{help_link_end} by default.'), tag_pair(help_link, :help_link_start, :help_link_end))
|
= safe_format(s_('Environment variables on this GitLab instance are configured to be %{help_link_start}protected%{help_link_end} by default.'), tag_pair(help_link, :help_link_start, :help_link_end))
|
||||||
#js-instance-variables{ data: { endpoint: admin_ci_variables_path, maskable_regex: ci_variable_maskable_regex, protected_by_default: ci_variable_protected_by_default?.to_s} }
|
#js-instance-variables{ data: { endpoint: admin_ci_variables_path, maskable_regex: ci_variable_maskable_regex, protected_by_default: ci_variable_protected_by_default?.to_s} }
|
||||||
|
|
||||||
%section.settings.as-ci-cd.no-animate#js-ci-cd-settings{ class: ('expanded' if expanded_by_default?) }
|
= render ::Layouts::SettingsBlockComponent.new(_('Continuous Integration and Deployment'),
|
||||||
.settings-header
|
id: 'js-continuous-integration-settings',
|
||||||
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
|
testid: 'ci-cd-settings',
|
||||||
= _('Continuous Integration and Deployment')
|
expanded: expanded_by_default?) do |c|
|
||||||
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
|
- c.with_description do
|
||||||
= expanded_by_default? ? _('Collapse') : _('Expand')
|
= _('Customize CI/CD settings, including Auto DevOps, instance runners, and job artifacts.')
|
||||||
%p.gl-text-secondary
|
- c.with_body do
|
||||||
= _('Customize CI/CD settings, including Auto DevOps, instance runners, and job artifacts.')
|
= render 'ci_cd'
|
||||||
= render 'ci_cd'
|
|
||||||
|
|
||||||
= render_if_exists 'admin/application_settings/package_registry', expanded: expanded_by_default?
|
= render_if_exists 'admin/application_settings/package_registry', expanded: expanded_by_default?
|
||||||
|
|
||||||
- if Gitlab.config.registry.enabled
|
- if Gitlab.config.registry.enabled
|
||||||
%section.settings.as-registry.no-animate#js-registry-settings{ class: ('expanded' if expanded_by_default?) }
|
= render ::Layouts::SettingsBlockComponent.new(_('Container Registry'),
|
||||||
.settings-header
|
id: 'js-registry-settings',
|
||||||
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
|
testid: 'registry-settings',
|
||||||
= _('Container Registry')
|
expanded: expanded_by_default?) do |c|
|
||||||
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
|
- c.with_description do
|
||||||
= expanded_by_default? ? _('Collapse') : _('Expand')
|
= _('Various container registry settings.')
|
||||||
%p.gl-text-secondary
|
- c.with_body do
|
||||||
= _('Various container registry settings.')
|
|
||||||
.settings-content
|
|
||||||
= render 'registry'
|
= render 'registry'
|
||||||
|
|
||||||
%section.settings.as-runner.no-animate#js-runner-settings{ class: ('expanded' if expanded_by_default?) }
|
= render ::Layouts::SettingsBlockComponent.new(s_('Runners|Runners'),
|
||||||
.settings-header
|
id: 'js-runner-settings',
|
||||||
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
|
testid: 'runner-settings',
|
||||||
= s_('Runners|Runners')
|
expanded: expanded_by_default?) do |c|
|
||||||
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
|
- c.with_description do
|
||||||
= expanded_by_default? ? 'Collapse' : 'Expand'
|
= _('Configure runner version management and registration settings.')
|
||||||
.settings-content
|
- c.with_body do
|
||||||
= render 'runner_registrars_form'
|
= render 'runner_registrars_form'
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@
|
||||||
|
|
||||||
%tr.section
|
%tr.section
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:0 15px;border:1px solid #ededed;border-radius:3px;overflow:hidden;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:0 15px;border:1px solid #ededed;border-radius:3px;overflow:hidden;" }
|
||||||
%table.info{ border: "0", cellpadding: "0", cellspacing: "0", style: "width:100%;" }
|
%table.info{ border: "0", cellpadding: "0", cellspacing: "0", style: "text-align: left; width:100%;" }
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;" }= _("Project")
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;" }= _("Project")
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
|
|
||||||
%tr.section
|
%tr.section
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:0 15px;border:1px solid #ededed;border-radius:3px;overflow:hidden;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:0 15px;border:1px solid #ededed;border-radius:3px;overflow:hidden;" }
|
||||||
%table.info{ border: "0", cellpadding: "0", cellspacing: "0", style: "width:100%;" }
|
%table.info{ border: "0", cellpadding: "0", cellspacing: "0", style: "text-align: left; width:100%;" }
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;" }= _('Project')
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;" }= _('Project')
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
|
|
||||||
%tr.section
|
%tr.section
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:0 15px;border:1px solid #ededed;border-radius:3px;overflow:hidden;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:0 15px;border:1px solid #ededed;border-radius:3px;overflow:hidden;" }
|
||||||
%table.info{ border: "0", cellpadding: "0", cellspacing: "0", style: "width:100%;" }
|
%table.info{ border: "0", cellpadding: "0", cellspacing: "0", style: "text-align: left; width:100%;" }
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;" }
|
||||||
|
|
|
||||||
|
|
@ -12,4 +12,4 @@
|
||||||
- if setting
|
- if setting
|
||||||
.js-vue-notification-dropdown{ data: { disabled: emails_disabled.to_s, dropdown_items: notification_dropdown_items(setting).to_json, notification_level: setting.level, help_page_path: help_page_path('user/profile/notifications'), group_id: group.id, show_label: "true" } }
|
.js-vue-notification-dropdown{ data: { disabled: emails_disabled.to_s, dropdown_items: notification_dropdown_items(setting).to_json, notification_level: setting.level, help_page_path: help_page_path('user/profile/notifications'), group_id: group.id, show_label: "true" } }
|
||||||
= form_for setting, url: profile_group_notifications_path(group), method: :put, html: { class: 'update-notifications gl-display-flex' } do |f|
|
= form_for setting, url: profile_group_notifications_path(group), method: :put, html: { class: 'update-notifications gl-display-flex' } do |f|
|
||||||
.js-notification-email-listbox-input{ data: { name: 'notification_setting[notification_email]', emails: @user.public_verified_emails.to_json, empty_value_text: _('Global notification email') , value: setting.notification_email, placement: 'right' } }
|
.js-notification-email-listbox-input{ data: { name: 'notification_setting[notification_email]', emails: @user.public_verified_emails.to_json, empty_value_text: _('Global notification email') , value: setting.notification_email, placement: 'bottom-end' } }
|
||||||
|
|
|
||||||
|
|
@ -11,5 +11,4 @@
|
||||||
project_name: @project.name,
|
project_name: @project.name,
|
||||||
project_path: @project.root_ancestor.full_path,
|
project_path: @project.root_ancestor.full_path,
|
||||||
gitlab_host: Gitlab.config.gitlab.host,
|
gitlab_host: Gitlab.config.gitlab.host,
|
||||||
terraform_help_path: help_page_path('user/infrastructure/index'),
|
|
||||||
project_list_url: project_infrastructure_registry_index_path(@project)} }
|
project_list_url: project_infrastructure_registry_index_path(@project)} }
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
---
|
---
|
||||||
migration_job_name: BackfillSbomOccurrencesTraversalIdsAndArchived
|
migration_job_name: BackfillSbomOccurrencesTraversalIdsAndArchived
|
||||||
description: >
|
description: 'Backfills sbom_occurrences.traversal_ids and sbom_occurrences.archived
|
||||||
Backfills sbom_occurrences.traversal_ids and sbom_occurrences.archived columns with
|
columns with values from sbom_occurrences.project.namespace.traversal_ids and sbom_occurrences.project.archived.
|
||||||
values from sbom_occurrences.project.namespace.traversal_ids and
|
|
||||||
sbom_occurrences.project.archived.
|
'
|
||||||
feature_category: dependency_management
|
feature_category: dependency_management
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/144802
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/144802
|
||||||
milestone: '16.10'
|
milestone: '16.10'
|
||||||
queued_migration_version: 20240214203242
|
queued_migration_version: 20240214203242
|
||||||
finalize_after: '2024-04-11'
|
finalize_after: '2024-04-11'
|
||||||
finalized_by: # Not yet implemented
|
finalized_by: '20240626231944'
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class RemoveMemberRolesIndividualPermissionsColumns < Gitlab::Database::Migration[2.2]
|
||||||
|
milestone '17.2'
|
||||||
|
|
||||||
|
PERMISSION_COLUMNS = %i[
|
||||||
|
admin_cicd_variables
|
||||||
|
admin_group_member
|
||||||
|
admin_merge_request
|
||||||
|
admin_terraform_state
|
||||||
|
admin_vulnerability
|
||||||
|
archive_project
|
||||||
|
manage_group_access_tokens
|
||||||
|
manage_project_access_tokens
|
||||||
|
read_code
|
||||||
|
read_dependency
|
||||||
|
read_vulnerability
|
||||||
|
remove_group
|
||||||
|
remove_project
|
||||||
|
]
|
||||||
|
|
||||||
|
def change
|
||||||
|
remove_columns :member_roles, *PERMISSION_COLUMNS, type: :boolean, null: false, default: false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class DropIndexSecurityFindingsConfidenceIdx < Gitlab::Database::Migration[2.2]
|
||||||
|
include Gitlab::Database::PartitioningMigrationHelpers
|
||||||
|
|
||||||
|
disable_ddl_transaction!
|
||||||
|
milestone '17.2'
|
||||||
|
|
||||||
|
INDEX_NAME = 'security_findings_confidence_idx'
|
||||||
|
TABLE_NAME = :security_findings
|
||||||
|
|
||||||
|
def up
|
||||||
|
remove_concurrent_partitioned_index_by_name TABLE_NAME, INDEX_NAME
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
add_concurrent_partitioned_index TABLE_NAME, :confidence, name: INDEX_NAME
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class FinalizeBackfillSbomOccurrencesTraversalIdsAndArchived < Gitlab::Database::Migration[2.2]
|
||||||
|
milestone '17.2'
|
||||||
|
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
restrict_gitlab_migration gitlab_schema: :gitlab_main
|
||||||
|
|
||||||
|
def up
|
||||||
|
ensure_batched_background_migration_is_finished(
|
||||||
|
job_class_name: 'BackfillSbomOccurrencesTraversalIdsAndArchived',
|
||||||
|
table_name: :sbom_occurrences,
|
||||||
|
column_name: :id,
|
||||||
|
job_arguments: [],
|
||||||
|
finalize: true
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def down; end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
ba1a13140ac43c4640f2cb49bb1d162ed36751ba35cf66c45f49b3410a23507a
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
3375b9d5de363d25c4be4669a94a68dbce9cec8a5e6954f01926057163e5650a
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
767d2d4a0f15dfe73608c8db586777a1f55014d3e66f599e719ba3c997364a0d
|
||||||
|
|
@ -12177,21 +12177,8 @@ CREATE TABLE member_roles (
|
||||||
created_at timestamp with time zone NOT NULL,
|
created_at timestamp with time zone NOT NULL,
|
||||||
updated_at timestamp with time zone NOT NULL,
|
updated_at timestamp with time zone NOT NULL,
|
||||||
base_access_level integer NOT NULL,
|
base_access_level integer NOT NULL,
|
||||||
read_code boolean DEFAULT false,
|
|
||||||
read_vulnerability boolean DEFAULT false NOT NULL,
|
|
||||||
admin_vulnerability boolean DEFAULT false NOT NULL,
|
|
||||||
read_dependency boolean DEFAULT false NOT NULL,
|
|
||||||
name text DEFAULT 'Custom'::text NOT NULL,
|
name text DEFAULT 'Custom'::text NOT NULL,
|
||||||
description text,
|
description text,
|
||||||
admin_merge_request boolean DEFAULT false NOT NULL,
|
|
||||||
admin_group_member boolean DEFAULT false NOT NULL,
|
|
||||||
manage_project_access_tokens boolean DEFAULT false NOT NULL,
|
|
||||||
archive_project boolean DEFAULT false NOT NULL,
|
|
||||||
manage_group_access_tokens boolean DEFAULT false NOT NULL,
|
|
||||||
remove_project boolean DEFAULT false NOT NULL,
|
|
||||||
admin_terraform_state boolean DEFAULT false NOT NULL,
|
|
||||||
admin_cicd_variables boolean DEFAULT false NOT NULL,
|
|
||||||
remove_group boolean DEFAULT false NOT NULL,
|
|
||||||
occupies_seat boolean DEFAULT false NOT NULL,
|
occupies_seat boolean DEFAULT false NOT NULL,
|
||||||
permissions jsonb DEFAULT '{}'::jsonb NOT NULL,
|
permissions jsonb DEFAULT '{}'::jsonb NOT NULL,
|
||||||
CONSTRAINT check_4364846f58 CHECK ((char_length(description) <= 255)),
|
CONSTRAINT check_4364846f58 CHECK ((char_length(description) <= 255)),
|
||||||
|
|
@ -29649,8 +29636,6 @@ CREATE INDEX scan_finding_approval_project_rule_index_created_at_project_id ON a
|
||||||
|
|
||||||
CREATE INDEX scan_finding_approval_project_rule_index_project_id ON approval_project_rules USING btree (project_id) WHERE (report_type = 4);
|
CREATE INDEX scan_finding_approval_project_rule_index_project_id ON approval_project_rules USING btree (project_id) WHERE (report_type = 4);
|
||||||
|
|
||||||
CREATE INDEX security_findings_confidence_idx ON ONLY security_findings USING btree (confidence);
|
|
||||||
|
|
||||||
CREATE INDEX security_findings_project_fingerprint_idx ON ONLY security_findings USING btree (project_fingerprint);
|
CREATE INDEX security_findings_project_fingerprint_idx ON ONLY security_findings USING btree (project_fingerprint);
|
||||||
|
|
||||||
CREATE INDEX security_findings_scan_id_deduplicated_idx ON ONLY security_findings USING btree (scan_id, deduplicated);
|
CREATE INDEX security_findings_scan_id_deduplicated_idx ON ONLY security_findings USING btree (scan_id, deduplicated);
|
||||||
|
|
|
||||||
|
|
@ -615,6 +615,8 @@ flow of how we construct a Chat prompt:
|
||||||
GitLab Duo Chat has error codes with specified meanings to assist in debugging.
|
GitLab Duo Chat has error codes with specified meanings to assist in debugging.
|
||||||
Currently, they are only logged, but in the future, they will be displayed on the UI.
|
Currently, they are only logged, but in the future, they will be displayed on the UI.
|
||||||
|
|
||||||
|
See the [GitLab Duo Chat troubleshooting documentation](../../user/gitlab_duo_chat/troubleshooting.md) for a list of all GitLab Duo Chat error codes.
|
||||||
|
|
||||||
When developing for GitLab Duo Chat, please include these error codes when returning an error and [document them](../../user/gitlab_duo_chat/troubleshooting.md), especially for user-facing errors.
|
When developing for GitLab Duo Chat, please include these error codes when returning an error and [document them](../../user/gitlab_duo_chat/troubleshooting.md), especially for user-facing errors.
|
||||||
|
|
||||||
### Error Code Format
|
### Error Code Format
|
||||||
|
|
|
||||||
|
|
@ -230,10 +230,13 @@ To update the linting images:
|
||||||
|
|
||||||
1. In `gitlab-docs`, open a merge request to update `.gitlab-ci.yml` to use the new tooling
|
1. In `gitlab-docs`, open a merge request to update `.gitlab-ci.yml` to use the new tooling
|
||||||
version. ([Example MR](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/2571))
|
version. ([Example MR](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/2571))
|
||||||
1. When merged, start a `Build docs.gitlab.com every hour` [scheduled pipeline](https://gitlab.com/gitlab-org/gitlab-docs/-/pipeline_schedules).
|
1. When merged, start a `Build docker images manually` [scheduled pipeline](https://gitlab.com/gitlab-org/gitlab-docs/-/pipeline_schedules).
|
||||||
1. Go the pipeline you started, and manually run the relevant build-images job,
|
1. Go the pipeline you started, and wait for the relevant `test:image` job to complete,
|
||||||
for example, `image:docs-lint-markdown`.
|
for example `test:image:docs-lint-markdown`. If the job:
|
||||||
1. In the job output, get the name of the new image.
|
- Passes, start the relevant `image:` job, for example, `image:docs-lint-markdown`.
|
||||||
|
- Fails, review the test job log and start troubleshooting the issue. The image configuration
|
||||||
|
likely needs some manual tweaks to work with the updated dependency.
|
||||||
|
1. After the `image:` job passes, check the job's log for the name of the new image.
|
||||||
([Example job output](https://gitlab.com/gitlab-org/gitlab-docs/-/jobs/2335033884#L334))
|
([Example job output](https://gitlab.com/gitlab-org/gitlab-docs/-/jobs/2335033884#L334))
|
||||||
1. Verify that the new image was added to the container registry.
|
1. Verify that the new image was added to the container registry.
|
||||||
1. Open merge requests to update each of these configuration files to point to the new image.
|
1. Open merge requests to update each of these configuration files to point to the new image.
|
||||||
|
|
|
||||||
|
|
@ -747,55 +747,64 @@ When GitLab receives a SAML response from a SAML SSO provider, GitLab looks for
|
||||||
|
|
||||||
You must include these values correctly in the attribute `Name` field so that GitLab can parse the SAML response. For example, GitLab can parse the following SAML response snippets:
|
You must include these values correctly in the attribute `Name` field so that GitLab can parse the SAML response. For example, GitLab can parse the following SAML response snippets:
|
||||||
|
|
||||||
```xml
|
- This is accepted because the `Name` attribute is set to one of the required values from the previous table.
|
||||||
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname">
|
|
||||||
<AttributeValue>Alvin</AttributeValue>
|
|
||||||
</Attribute>
|
|
||||||
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname">
|
|
||||||
<AttributeValue>Test</AttributeValue>
|
|
||||||
</Attribute>
|
|
||||||
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress">
|
|
||||||
<AttributeValue>alvintest@example.com</AttributeValue>
|
|
||||||
</Attribute>
|
|
||||||
```
|
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<Attribute Name="firstname">
|
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname">
|
||||||
<AttributeValue>Alvin</AttributeValue>
|
<AttributeValue>Alvin</AttributeValue>
|
||||||
</Attribute>
|
</Attribute>
|
||||||
<Attribute Name="lastname">
|
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname">
|
||||||
<AttributeValue>Test</AttributeValue>
|
<AttributeValue>Test</AttributeValue>
|
||||||
</Attribute>
|
</Attribute>
|
||||||
<Attribute Name="email">
|
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress">
|
||||||
<AttributeValue>alvintest@example.com</AttributeValue>
|
<AttributeValue>alvintest@example.com</AttributeValue>
|
||||||
</Attribute>
|
</Attribute>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- This is accepted because the `Name` attribute matches one of the values from the previous table.
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<Attribute Name="firstname">
|
||||||
|
<AttributeValue>Alvin</AttributeValue>
|
||||||
|
</Attribute>
|
||||||
|
<Attribute Name="lastname">
|
||||||
|
<AttributeValue>Test</AttributeValue>
|
||||||
|
</Attribute>
|
||||||
|
<Attribute Name="email">
|
||||||
|
<AttributeValue>alvintest@example.com</AttributeValue>
|
||||||
|
</Attribute>
|
||||||
|
```
|
||||||
|
|
||||||
However, GitLab cannot parse the following SAML response snippets:
|
However, GitLab cannot parse the following SAML response snippets:
|
||||||
|
|
||||||
```xml
|
- This will not be accepted because value in the `Name` attribute is not one of the supported
|
||||||
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/firstname">
|
values in the previous table.
|
||||||
<AttributeValue>Alvin</AttributeValue>
|
|
||||||
</Attribute>
|
|
||||||
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/lastname">
|
|
||||||
<AttributeValue>Test</AttributeValue>
|
|
||||||
</Attribute>
|
|
||||||
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/mail">
|
|
||||||
<AttributeValue>alvintest@example.com</AttributeValue>
|
|
||||||
</Attribute>
|
|
||||||
```
|
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<Attribute FriendlyName="firstname" Name="urn:oid:2.5.4.42">
|
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/firstname">
|
||||||
<AttributeValue>Alvin</AttributeValue>
|
<AttributeValue>Alvin</AttributeValue>
|
||||||
</Attribute>
|
</Attribute>
|
||||||
<Attribute FriendlyName="lastname" Name="urn:oid:2.5.4.4">
|
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/lastname">
|
||||||
<AttributeValue>Test</AttributeValue>
|
<AttributeValue>Test</AttributeValue>
|
||||||
</Attribute>
|
</Attribute>
|
||||||
<Attribute FriendlyName="email" Name="urn:oid:0.9.2342.19200300.100.1.3">
|
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/mail">
|
||||||
<AttributeValue>alvintest@example.com</AttributeValue>
|
<AttributeValue>alvintest@example.com</AttributeValue>
|
||||||
</Attribute>
|
</Attribute>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- This will fail because, even though the `FriendlyName` has a supported value, the `Name` attribute does not.
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<Attribute FriendlyName="firstname" Name="urn:oid:2.5.4.42">
|
||||||
|
<AttributeValue>Alvin</AttributeValue>
|
||||||
|
</Attribute>
|
||||||
|
<Attribute FriendlyName="lastname" Name="urn:oid:2.5.4.4">
|
||||||
|
<AttributeValue>Test</AttributeValue>
|
||||||
|
</Attribute>
|
||||||
|
<Attribute FriendlyName="email" Name="urn:oid:0.9.2342.19200300.100.1.3">
|
||||||
|
<AttributeValue>alvintest@example.com</AttributeValue>
|
||||||
|
</Attribute>
|
||||||
|
```
|
||||||
|
|
||||||
See [`attribute_statements`](#map-saml-response-attribute-names) for:
|
See [`attribute_statements`](#map-saml-response-attribute-names) for:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6341,6 +6341,12 @@ msgstr ""
|
||||||
msgid "Appearance was successfully updated."
|
msgid "Appearance was successfully updated."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "AppearanceSettings|Last edit"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "AppearanceSettings|Preview last save:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Append the comment with %{shrug}"
|
msgid "Append the comment with %{shrug}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
@ -13991,6 +13997,9 @@ msgstr ""
|
||||||
msgid "Configure repository storage."
|
msgid "Configure repository storage."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Configure runner version management and registration settings."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Configure settings for Advanced Search with Elasticsearch."
|
msgid "Configure settings for Advanced Search with Elasticsearch."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -215,14 +215,14 @@
|
||||||
"url-loader": "^4.1.1",
|
"url-loader": "^4.1.1",
|
||||||
"uuid": "8.1.0",
|
"uuid": "8.1.0",
|
||||||
"visibilityjs": "^1.2.4",
|
"visibilityjs": "^1.2.4",
|
||||||
"vue": "2.7.15",
|
"vue": "2.7.16",
|
||||||
"vue-apollo": "^3.0.7",
|
"vue-apollo": "^3.0.7",
|
||||||
"vue-loader": "15.11.1",
|
"vue-loader": "15.11.1",
|
||||||
"vue-observe-visibility": "^1.0.0",
|
"vue-observe-visibility": "^1.0.0",
|
||||||
"vue-resize": "^1.0.1",
|
"vue-resize": "^1.0.1",
|
||||||
"vue-router": "3.6.5",
|
"vue-router": "3.6.5",
|
||||||
"vue-router-vue3": "npm:vue-router@4.1.6",
|
"vue-router-vue3": "npm:vue-router@4.1.6",
|
||||||
"vue-template-compiler": "2.7.15",
|
"vue-template-compiler": "2.7.16",
|
||||||
"vue-virtual-scroll-list": "^1.4.7",
|
"vue-virtual-scroll-list": "^1.4.7",
|
||||||
"vuedraggable": "^2.23.0",
|
"vuedraggable": "^2.23.0",
|
||||||
"vuex": "^3.6.2",
|
"vuex": "^3.6.2",
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
diff --git a/node_modules/vue/node_modules/@vue/compiler-sfc/dist/compiler-sfc.js b/node_modules/vue/node_modules/@vue/compiler-sfc/dist/compiler-sfc.js
|
diff --git a/node_modules/vue/node_modules/@vue/compiler-sfc/dist/compiler-sfc.js b/node_modules/vue/node_modules/@vue/compiler-sfc/dist/compiler-sfc.js
|
||||||
index ec32339..91e43a7 100644
|
index 91da3e0..001cf4f 100644
|
||||||
--- a/node_modules/vue/node_modules/@vue/compiler-sfc/dist/compiler-sfc.js
|
--- a/node_modules/vue/node_modules/@vue/compiler-sfc/dist/compiler-sfc.js
|
||||||
+++ b/node_modules/vue/node_modules/@vue/compiler-sfc/dist/compiler-sfc.js
|
+++ b/node_modules/vue/node_modules/@vue/compiler-sfc/dist/compiler-sfc.js
|
||||||
@@ -9645,7 +9645,23 @@ const splitRE = /\r?\n/g;
|
@@ -9658,7 +9658,23 @@ const splitRE = /\r?\n/g;
|
||||||
const emptyRE = /^(?:\/\/)?\s*$/;
|
const emptyRE = /^(?:\/\/)?\s*$/;
|
||||||
function parse(options) {
|
function parse(options) {
|
||||||
const { source, filename = DEFAULT_FILENAME, compiler, compilerParseOptions = { pad: false }, sourceRoot = '', needMap = true, sourceMap = needMap } = options;
|
const { source, filename = DEFAULT_FILENAME, compiler, compilerParseOptions = { pad: false }, sourceRoot = '', needMap = true, sourceMap = needMap } = options;
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "spec_helper"
|
||||||
|
|
||||||
|
RSpec.describe Layouts::SettingsSectionComponent, type: :component, feature_category: :shared do
|
||||||
|
let(:heading) { 'Settings section heading' }
|
||||||
|
let(:description) { 'Settings section description' }
|
||||||
|
let(:body) { 'Settings section content' }
|
||||||
|
let(:id) { 'js-settings-section-id' }
|
||||||
|
let(:testid) { 'settings-section-testid' }
|
||||||
|
|
||||||
|
describe 'slots' do
|
||||||
|
it 'renders heading' do
|
||||||
|
render_inline described_class.new(heading)
|
||||||
|
|
||||||
|
expect(page).to have_css('h2.gl-heading-2', text: heading)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'renders description' do
|
||||||
|
render_inline described_class.new(heading, description: description)
|
||||||
|
|
||||||
|
expect(page).to have_css('.gl-text-secondary', text: description)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'renders description slot' do
|
||||||
|
render_inline described_class.new(heading) do |c|
|
||||||
|
c.with_description { description }
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(page).to have_css('.gl-text-secondary', text: description)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'renders body slot' do
|
||||||
|
render_inline described_class.new(heading) do |c|
|
||||||
|
c.with_body { body }
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(page).to have_css('[data-testid="settings-section-body"]', text: body)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'renders id' do
|
||||||
|
render_inline described_class.new(heading, id: id)
|
||||||
|
|
||||||
|
expect(page).to have_css('#js-settings-section-id')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'renders testid' do
|
||||||
|
render_inline described_class.new(heading, testid: testid)
|
||||||
|
|
||||||
|
expect(page).to have_css('[data-testid="settings-section-testid"]')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue