Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-07-20 18:40:28 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-07-20 18:40:28 +0300
commitb595cb0c1dec83de5bdee18284abe86614bed33b (patch)
tree8c3d4540f193c5ff98019352f554e921b3a41a72 /app/assets/javascripts/packages_and_registries
parent2f9104a328fc8a4bddeaa4627b595166d24671d0 (diff)
Add latest changes from gitlab-org/gitlab@15-2-stable-eev15.2.0-rc42
Diffstat (limited to 'app/assets/javascripts/packages_and_registries')
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/details_header.vue3
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/cleanup_status.vue10
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/image_list_row.vue52
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/common.js3
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/list.js7
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/details.vue3
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/details/file_sha.vue20
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/details/package_files.vue24
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/constants.js7
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/pages/details.vue6
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/group/bundle.js2
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/group/components/dependency_proxy_settings.vue18
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/group/components/duplicates_settings.vue65
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/group/components/packages_settings.vue28
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/group/constants.js15
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/project/components/container_expiration_policy.vue2
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/project/components/expiration_dropdown.vue10
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/project/components/packages_cleanup_policy.vue68
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/project/components/packages_cleanup_policy_form.vue137
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/project/components/registry_settings_app.vue10
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/project/constants.js25
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/project/graphql/fragments/packages_cleanup_policy.fragment.graphql4
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/project/graphql/mutations/update_packages_cleanup_policy.mutation.graphql10
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/project/graphql/queries/get_packages_cleanup_policy.query.graphql10
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/project/registry_settings_bundle.js4
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/project/utils.js9
-rw-r--r--app/assets/javascripts/packages_and_registries/shared/components/settings_block.vue17
-rw-r--r--app/assets/javascripts/packages_and_registries/shared/constants/package_registry.js2
28 files changed, 464 insertions, 107 deletions
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/details_header.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/details_header.vue
index ab0418388cd..5d77ff9dc0d 100644
--- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/details_header.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/details_header.vue
@@ -20,7 +20,6 @@ import {
UNSCHEDULED_STATUS,
SCHEDULED_STATUS,
ONGOING_STATUS,
- ROOT_IMAGE_TEXT,
ROOT_IMAGE_TOOLTIP,
} from '../../constants/index';
@@ -100,7 +99,7 @@ export default {
return !this.imageDetails.name ? ROOT_IMAGE_TOOLTIP : '';
},
imageName() {
- return this.imageDetails.name || ROOT_IMAGE_TEXT;
+ return this.imageDetails.name || this.imageDetails.project?.path;
},
formattedSize() {
const { size } = this.imageDetails;
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/cleanup_status.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/cleanup_status.vue
index 56da8e88b7a..bfa99c01c3f 100644
--- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/cleanup_status.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/cleanup_status.vue
@@ -1,4 +1,5 @@
<script>
+import { uniqueId } from 'lodash';
import { GlIcon, GlPopover, GlLink, GlSprintf } from '@gitlab/ui';
import { helpPagePath } from '~/helpers/help_page_helper';
import { timeTilRun } from '../../utils';
@@ -43,6 +44,11 @@ export default {
CLEANUP_STATUS_UNFINISHED,
PARTIAL_CLEANUP_CONTINUE_MESSAGE,
},
+ data() {
+ return {
+ iconId: uniqueId('status-info-'),
+ };
+ },
computed: {
showStatus() {
return this.status !== UNSCHEDULED_STATUS;
@@ -85,14 +91,14 @@ export default {
</span>
<gl-icon
v-if="failedDelete"
- id="status-info"
+ :id="iconId"
:size="14"
class="gl-text-gray-500"
data-testid="extra-info"
name="information-o"
/>
<gl-popover
- target="status-info"
+ :target="iconId"
container="status-popover-container"
v-bind="$options.statusPopoverOptions"
>
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/image_list_row.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/image_list_row.vue
index e67d77210bb..aecc0bf92ea 100644
--- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/image_list_row.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/image_list_row.vue
@@ -1,10 +1,12 @@
<script>
-import { GlTooltipDirective, GlIcon, GlSprintf, GlSkeletonLoader } from '@gitlab/ui';
+import { GlTooltipDirective, GlIcon, GlSprintf, GlSkeletonLoader, GlButton } from '@gitlab/ui';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { n__ } from '~/locale';
-
+import Tracking from '~/tracking';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import ListItem from '~/vue_shared/components/registry/list_item.vue';
+import { joinPaths } from '~/lib/utils/url_utility';
import {
LIST_DELETE_BUTTON_DISABLED,
LIST_DELETE_BUTTON_DISABLED_FOR_MIGRATION,
@@ -13,8 +15,10 @@ import {
IMAGE_DELETE_SCHEDULED_STATUS,
IMAGE_FAILED_DELETED_STATUS,
IMAGE_MIGRATING_STATE,
- ROOT_IMAGE_TEXT,
COPY_IMAGE_PATH_TITLE,
+ IMAGE_FULL_PATH_LABEL,
+ TRACKING_ACTION_CLICK_SHOW_FULL_PATH,
+ TRACKING_LABEL_REGISTRY_IMAGE_LIST,
} from '../../constants/index';
import DeleteButton from '../delete_button.vue';
import CleanupStatus from './cleanup_status.vue';
@@ -25,6 +29,7 @@ export default {
ClipboardButton,
DeleteButton,
GlSprintf,
+ GlButton,
GlIcon,
ListItem,
GlSkeletonLoader,
@@ -33,6 +38,7 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
+ mixins: [Tracking.mixin(), glFeatureFlagsMixin()],
inject: ['config'],
props: {
item: {
@@ -54,6 +60,12 @@ export default {
REMOVE_REPOSITORY_LABEL,
ROW_SCHEDULED_FOR_DELETION,
COPY_IMAGE_PATH_TITLE,
+ IMAGE_FULL_PATH_LABEL,
+ },
+ data() {
+ return {
+ showFullPath: false,
+ };
},
computed: {
disabledDelete() {
@@ -79,7 +91,17 @@ export default {
);
},
imageName() {
- return this.item.name ? this.item.path : `${this.item.path}/ ${ROOT_IMAGE_TEXT}`;
+ if (this.glFeatures.containerRegistryShowShortenedPath) {
+ if (this.showFullPath) {
+ return this.item.path;
+ }
+ const projectPath = this.item?.project?.path ?? '';
+ if (this.item.name) {
+ return joinPaths(projectPath, this.item.name);
+ }
+ return projectPath;
+ }
+ return this.item.path;
},
routerLinkEvent() {
return this.deleting ? '' : 'click';
@@ -90,6 +112,15 @@ export default {
: LIST_DELETE_BUTTON_DISABLED;
},
},
+ methods: {
+ hideButton() {
+ this.showFullPath = true;
+ this.$refs.imageName.$el.focus();
+ this.track(TRACKING_ACTION_CLICK_SHOW_FULL_PATH, {
+ label: TRACKING_LABEL_REGISTRY_IMAGE_LIST,
+ });
+ },
+ },
};
</script>
@@ -104,7 +135,20 @@ export default {
:disabled="deleting"
>
<template #left-primary>
+ <gl-button
+ v-if="glFeatures.containerRegistryShowShortenedPath && !showFullPath"
+ v-gl-tooltip="{
+ placement: 'top',
+ title: $options.i18n.IMAGE_FULL_PATH_LABEL,
+ }"
+ icon="ellipsis_h"
+ size="small"
+ class="gl-mr-2"
+ :aria-label="$options.i18n.IMAGE_FULL_PATH_LABEL"
+ @click="hideButton"
+ />
<router-link
+ ref="imageName"
class="gl-text-body gl-font-weight-bold"
data-testid="details-link"
data-qa-selector="registry_image_content"
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/common.js b/app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/common.js
index 17adaec7a7d..67ad281b835 100644
--- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/common.js
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/common.js
@@ -1,6 +1,5 @@
-import { s__, __ } from '~/locale';
+import { __ } from '~/locale';
-export const ROOT_IMAGE_TEXT = s__('ContainerRegistry|Root image');
export const MORE_ACTIONS_TEXT = __('More actions');
export const NAME_SORT_FIELD = { orderBy: 'NAME', label: __('Name') };
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/list.js b/app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/list.js
index c6a7591e0d9..020d78ad364 100644
--- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/list.js
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/list.js
@@ -43,6 +43,13 @@ export const EMPTY_RESULT_MESSAGE = s__(
export const COPY_IMAGE_PATH_TITLE = s__('ContainerRegistry|Copy image path');
+export const IMAGE_FULL_PATH_LABEL = s__('ContainerRegistry|Show full path');
+
+// Tracking
+
+export const TRACKING_LABEL_REGISTRY_IMAGE_LIST = 'registry_image_list';
+export const TRACKING_ACTION_CLICK_SHOW_FULL_PATH = 'click_show_full_path';
+
// Parameters
export const IMAGE_DELETE_SCHEDULED_STATUS = 'DELETE_SCHEDULED';
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/details.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/details.vue
index 71a85d8885e..9ebbdfa920d 100644
--- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/details.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/details.vue
@@ -24,7 +24,6 @@ import {
FETCH_IMAGES_LIST_ERROR_MESSAGE,
UNFINISHED_STATUS,
MISSING_OR_DELETED_IMAGE_BREADCRUMB,
- ROOT_IMAGE_TEXT,
GRAPHQL_PAGE_SIZE,
MISSING_OR_DELETED_IMAGE_TITLE,
MISSING_OR_DELETED_IMAGE_MESSAGE,
@@ -111,7 +110,7 @@ export default {
methods: {
updateBreadcrumb() {
const name = this.containerRepository?.id
- ? this.containerRepository?.name || ROOT_IMAGE_TEXT
+ ? this.containerRepository?.name || this.containerRepository?.project?.path
: MISSING_OR_DELETED_IMAGE_BREADCRUMB;
this.breadCrumbState.updateName(name);
},
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/details/file_sha.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/details/file_sha.vue
index a25839be7e1..b91af19d623 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/details/file_sha.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/details/file_sha.vue
@@ -2,6 +2,12 @@
import { s__ } from '~/locale';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import DetailsRow from '~/vue_shared/components/registry/details_row.vue';
+import Tracking from '~/tracking';
+import { packageTypeToTrackCategory } from '~/packages_and_registries/package_registry/utils';
+import {
+ TRACKING_ACTION_COPY_PACKAGE_ASSET_SHA,
+ TRACKING_LABEL_PACKAGE_ASSET,
+} from '~/packages_and_registries/package_registry/constants';
export default {
name: 'FileSha',
@@ -9,6 +15,7 @@ export default {
DetailsRow,
ClipboardButton,
},
+ mixins: [Tracking.mixin()],
props: {
sha: {
type: String,
@@ -22,6 +29,18 @@ export default {
i18n: {
copyButtonTitle: s__('PackageRegistry|Copy SHA'),
},
+ computed: {
+ tracking() {
+ return {
+ category: packageTypeToTrackCategory(this.packageType),
+ };
+ },
+ },
+ methods: {
+ copySha() {
+ this.track(TRACKING_ACTION_COPY_PACKAGE_ASSET_SHA, { label: TRACKING_LABEL_PACKAGE_ASSET });
+ },
+ },
};
</script>
@@ -35,6 +54,7 @@ export default {
:title="$options.i18n.copyButtonTitle"
category="tertiary"
size="small"
+ @click="copySha"
/>
</div>
</details-row>
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_files.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_files.vue
index 9e700a5236f..a049b0eff8d 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_files.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_files.vue
@@ -5,8 +5,13 @@ import { numberToHumanSize } from '~/lib/utils/number_utils';
import { __ } from '~/locale';
import FileSha from '~/packages_and_registries/package_registry/components/details/file_sha.vue';
import Tracking from '~/tracking';
+import { packageTypeToTrackCategory } from '~/packages_and_registries/package_registry/utils';
import FileIcon from '~/vue_shared/components/file_icon.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+import {
+ TRACKING_LABEL_PACKAGE_ASSET,
+ TRACKING_ACTION_EXPAND_PACKAGE_ASSET,
+} from '~/packages_and_registries/package_registry/constants';
export default {
name: 'PackageFiles',
@@ -76,6 +81,11 @@ export default {
},
].filter((c) => !c.hide);
},
+ tracking() {
+ return {
+ category: packageTypeToTrackCategory(this.packageType),
+ };
+ },
},
methods: {
formatSize(size) {
@@ -84,6 +94,11 @@ export default {
hasDetails(item) {
return item.fileSha256 || item.fileMd5 || item.fileSha1;
},
+ trackToggleDetails(detailsShowing) {
+ if (!detailsShowing) {
+ this.track(TRACKING_ACTION_EXPAND_PACKAGE_ASSET, { label: TRACKING_LABEL_PACKAGE_ASSET });
+ }
+ },
},
i18n: {
deleteFile: __('Delete file'),
@@ -106,7 +121,10 @@ export default {
:aria-label="detailsShowing ? __('Collapse') : __('Expand')"
category="tertiary"
size="small"
- @click="toggleDetails"
+ @click="
+ toggleDetails();
+ trackToggleDetails(detailsShowing);
+ "
/>
<gl-link
:href="item.downloadPath"
@@ -129,8 +147,8 @@ export default {
:href="item.pipeline.commitPath"
class="gl-text-gray-500"
data-testid="commit-link"
- >{{ item.pipeline.sha }}</gl-link
- >
+ >{{ item.pipeline.sha }}
+ </gl-link>
</template>
<template #cell(created)="{ item }">
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/constants.js b/app/assets/javascripts/packages_and_registries/package_registry/constants.js
index 3c090951b7d..cea053992f8 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/constants.js
+++ b/app/assets/javascripts/packages_and_registries/package_registry/constants.js
@@ -9,6 +9,7 @@ export {
DELETE_PACKAGE_FILE_TRACKING_ACTION,
REQUEST_DELETE_PACKAGE_FILE_TRACKING_ACTION,
CANCEL_DELETE_PACKAGE_FILE_TRACKING_ACTION,
+ DOWNLOAD_PACKAGE_ASSET_TRACKING_ACTION,
} from '~/packages_and_registries/shared/constants';
export const PACKAGE_TYPE_CONAN = 'CONAN';
@@ -62,6 +63,12 @@ export const TRACKING_ACTION_COPY_COMPOSER_REGISTRY_INCLUDE_COMMAND =
export const TRACKING_ACTION_COPY_COMPOSER_PACKAGE_INCLUDE_COMMAND =
'copy_composer_package_include_command';
+export const TRACKING_LABEL_PACKAGE_ASSET = 'package_assets';
+
+export const TRACKING_ACTION_DOWNLOAD_PACKAGE_ASSET = 'download_package_asset';
+export const TRACKING_ACTION_EXPAND_PACKAGE_ASSET = 'expand_package_asset';
+export const TRACKING_ACTION_COPY_PACKAGE_ASSET_SHA = 'copy_package_asset_sha';
+
export const SHOW_DELETE_SUCCESS_ALERT = 'showSuccessDeleteAlert';
export const DELETE_PACKAGE_FILE_ERROR_MESSAGE = s__(
'PackageRegistry|Something went wrong while deleting the package file.',
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/pages/details.vue b/app/assets/javascripts/packages_and_registries/package_registry/pages/details.vue
index 768c8d6478b..29438fba86b 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/pages/details.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/pages/details.vue
@@ -33,7 +33,6 @@ import {
DELETE_PACKAGE_TRACKING_ACTION,
REQUEST_DELETE_PACKAGE_TRACKING_ACTION,
CANCEL_DELETE_PACKAGE_TRACKING_ACTION,
- PULL_PACKAGE_TRACKING_ACTION,
DELETE_PACKAGE_FILE_TRACKING_ACTION,
REQUEST_DELETE_PACKAGE_FILE_TRACKING_ACTION,
CANCEL_DELETE_PACKAGE_FILE_TRACKING_ACTION,
@@ -41,6 +40,7 @@ import {
FETCH_PACKAGE_DETAILS_ERROR_MESSAGE,
DELETE_PACKAGE_FILE_ERROR_MESSAGE,
DELETE_PACKAGE_FILE_SUCCESS_MESSAGE,
+ DOWNLOAD_PACKAGE_ASSET_TRACKING_ACTION,
} from '~/packages_and_registries/package_registry/constants';
import destroyPackageFileMutation from '~/packages_and_registries/package_registry/graphql/mutations/destroy_package_file.mutation.graphql';
@@ -76,10 +76,10 @@ export default {
DELETE_PACKAGE_TRACKING_ACTION,
REQUEST_DELETE_PACKAGE_TRACKING_ACTION,
CANCEL_DELETE_PACKAGE_TRACKING_ACTION,
- PULL_PACKAGE_TRACKING_ACTION,
DELETE_PACKAGE_FILE_TRACKING_ACTION,
REQUEST_DELETE_PACKAGE_FILE_TRACKING_ACTION,
CANCEL_DELETE_PACKAGE_FILE_TRACKING_ACTION,
+ DOWNLOAD_PACKAGE_ASSET_TRACKING_ACTION,
},
data() {
return {
@@ -288,7 +288,7 @@ export default {
v-if="showFiles"
:can-delete="packageEntity.canDestroy"
:package-files="packageFiles"
- @download-file="track($options.trackingActions.PULL_PACKAGE)"
+ @download-file="track($options.trackingActions.DOWNLOAD_PACKAGE_ASSET_TRACKING_ACTION)"
@delete-file="handleFileDelete"
/>
</gl-tab>
diff --git a/app/assets/javascripts/packages_and_registries/settings/group/bundle.js b/app/assets/javascripts/packages_and_registries/settings/group/bundle.js
index 482a3ef2ead..3689199751d 100644
--- a/app/assets/javascripts/packages_and_registries/settings/group/bundle.js
+++ b/app/assets/javascripts/packages_and_registries/settings/group/bundle.js
@@ -1,7 +1,6 @@
import { GlToast } from '@gitlab/ui';
import Vue from 'vue';
-import { parseBoolean } from '~/lib/utils/common_utils';
import Translate from '~/vue_shared/translate';
import SettingsApp from './components/group_settings_app.vue';
import { apolloProvider } from './graphql';
@@ -20,7 +19,6 @@ export default () => {
provide: {
groupPath: el.dataset.groupPath,
groupDependencyProxyPath: el.dataset.groupDependencyProxyPath,
- defaultExpanded: parseBoolean(el.dataset.defaultExpanded),
},
render(createElement) {
return createElement(SettingsApp);
diff --git a/app/assets/javascripts/packages_and_registries/settings/group/components/dependency_proxy_settings.vue b/app/assets/javascripts/packages_and_registries/settings/group/components/dependency_proxy_settings.vue
index 130d6977936..59d4f5e24d0 100644
--- a/app/assets/javascripts/packages_and_registries/settings/group/components/dependency_proxy_settings.vue
+++ b/app/assets/javascripts/packages_and_registries/settings/group/components/dependency_proxy_settings.vue
@@ -1,8 +1,7 @@
<script>
import { GlToggle, GlSprintf, GlLink } from '@gitlab/ui';
import { s__ } from '~/locale';
-import SettingsBlock from '~/vue_shared/components/settings/settings_block.vue';
-import SettingsTitles from '~/packages_and_registries/settings/group/components/settings_titles.vue';
+import SettingsBlock from '~/packages_and_registries/shared/components/settings_block.vue';
import updateDependencyProxySettings from '~/packages_and_registries/settings/group/graphql/mutations/update_dependency_proxy_settings.mutation.graphql';
import updateDependencyProxyImageTtlGroupPolicy from '~/packages_and_registries/settings/group/graphql/mutations/update_dependency_proxy_image_ttl_group_policy.mutation.graphql';
import { updateGroupPackageSettings } from '~/packages_and_registries/settings/group/graphql/utils/cache_update';
@@ -13,6 +12,7 @@ import {
import {
DEPENDENCY_PROXY_HEADER,
+ DEPENDENCY_PROXY_DESCRIPTION,
DEPENDENCY_PROXY_DOCS_PATH,
} from '~/packages_and_registries/settings/group/constants';
@@ -23,15 +23,14 @@ export default {
GlSprintf,
GlLink,
SettingsBlock,
- SettingsTitles,
},
i18n: {
DEPENDENCY_PROXY_HEADER,
+ DEPENDENCY_PROXY_DESCRIPTION,
enabledProxyLabel: s__('DependencyProxy|Enable Dependency Proxy'),
enabledProxyHelpText: s__(
'DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}',
),
- storageSettingsTitle: s__('DependencyProxy|Storage settings'),
ttlPolicyEnabledLabel: s__('DependencyProxy|Clear the Dependency Proxy cache automatically'),
ttlPolicyEnabledHelpText: s__(
'DependencyProxy|When enabled, images older than 90 days will be removed from the cache.',
@@ -40,7 +39,7 @@ export default {
links: {
DEPENDENCY_PROXY_DOCS_PATH,
},
- inject: ['defaultExpanded', 'groupPath', 'groupDependencyProxyPath'],
+ inject: ['groupPath', 'groupDependencyProxyPath'],
props: {
dependencyProxySettings: {
type: Object,
@@ -130,11 +129,9 @@ export default {
</script>
<template>
- <settings-block
- :default-expanded="defaultExpanded"
- data-qa-selector="dependency_proxy_settings_content"
- >
+ <settings-block data-qa-selector="dependency_proxy_settings_content">
<template #title> {{ $options.i18n.DEPENDENCY_PROXY_HEADER }} </template>
+ <template #description> {{ $options.i18n.DEPENDENCY_PROXY_DESCRIPTION }} </template>
<template #default>
<div>
<gl-toggle
@@ -156,13 +153,12 @@ export default {
</span>
</template>
</gl-toggle>
-
- <settings-titles :title="$options.i18n.storageSettingsTitle" class="gl-my-6" />
<gl-toggle
v-model="ttlEnabled"
:disabled="isLoading"
:label="$options.i18n.ttlPolicyEnabledLabel"
:help="$options.i18n.ttlPolicyEnabledHelpText"
+ class="gl-mt-6"
data-testid="dependency-proxy-ttl-policies-toggle"
/>
</div>
diff --git a/app/assets/javascripts/packages_and_registries/settings/group/components/duplicates_settings.vue b/app/assets/javascripts/packages_and_registries/settings/group/components/duplicates_settings.vue
index b0088838acc..51a97aead49 100644
--- a/app/assets/javascripts/packages_and_registries/settings/group/components/duplicates_settings.vue
+++ b/app/assets/javascripts/packages_and_registries/settings/group/components/duplicates_settings.vue
@@ -1,11 +1,9 @@
<script>
-import { GlSprintf, GlToggle, GlFormGroup, GlFormInput } from '@gitlab/ui';
+import { GlToggle, GlFormGroup, GlFormInput } from '@gitlab/ui';
import { isEqual } from 'lodash';
import {
DUPLICATES_TOGGLE_LABEL,
- DUPLICATES_ALLOWED_DISABLED,
- DUPLICATES_ALLOWED_ENABLED,
DUPLICATES_SETTING_EXCEPTION_TITLE,
DUPLICATES_SETTINGS_EXCEPTION_LEGEND,
} from '~/packages_and_registries/settings/group/constants';
@@ -18,7 +16,6 @@ export default {
DUPLICATES_SETTINGS_EXCEPTION_LEGEND,
},
components: {
- GlSprintf,
GlToggle,
GlFormGroup,
GlFormInput,
@@ -63,9 +60,6 @@ export default {
},
},
computed: {
- enabledButtonLabel() {
- return this.duplicatesAllowed ? DUPLICATES_ALLOWED_ENABLED : DUPLICATES_ALLOWED_DISABLED;
- },
isExceptionRegexValid() {
return !this.duplicateExceptionRegexError;
},
@@ -80,41 +74,30 @@ export default {
<template>
<form>
- <div class="gl-display-flex">
- <gl-toggle
- :data-qa-selector="toggleQaSelector"
- :label="$options.i18n.DUPLICATES_TOGGLE_LABEL"
- label-position="hidden"
- :value="duplicatesAllowed"
+ <gl-toggle
+ :data-qa-selector="toggleQaSelector"
+ :label="$options.i18n.DUPLICATES_TOGGLE_LABEL"
+ :value="!duplicatesAllowed"
+ :disabled="loading"
+ @change="update(modelNames.allowed, !$event)"
+ />
+ <gl-form-group
+ v-if="!duplicatesAllowed"
+ class="gl-mt-4"
+ :label="$options.i18n.DUPLICATES_SETTING_EXCEPTION_TITLE"
+ label-size="sm"
+ :state="isExceptionRegexValid"
+ :invalid-feedback="duplicateExceptionRegexError"
+ :description="$options.i18n.DUPLICATES_SETTINGS_EXCEPTION_LEGEND"
+ label-for="maven-duplicated-settings-regex-input"
+ >
+ <gl-form-input
+ id="maven-duplicated-settings-regex-input"
:disabled="loading"
- @change="update(modelNames.allowed, $event)"
+ size="lg"
+ :value="duplicateExceptionRegex"
+ @change="update(modelNames.exception, $event)"
/>
- <div class="gl-ml-5">
- <div data-testid="toggle-label" :data-qa-selector="labelQaSelector">
- <gl-sprintf :message="enabledButtonLabel">
- <template #bold="{ content }">
- <strong>{{ content }}</strong>
- </template>
- </gl-sprintf>
- </div>
- <gl-form-group
- v-if="!duplicatesAllowed"
- class="gl-mt-4"
- :label="$options.i18n.DUPLICATES_SETTING_EXCEPTION_TITLE"
- label-size="sm"
- :state="isExceptionRegexValid"
- :invalid-feedback="duplicateExceptionRegexError"
- :description="$options.i18n.DUPLICATES_SETTINGS_EXCEPTION_LEGEND"
- label-for="maven-duplicated-settings-regex-input"
- >
- <gl-form-input
- id="maven-duplicated-settings-regex-input"
- :disabled="loading"
- :value="duplicateExceptionRegex"
- @change="update(modelNames.exception, $event)"
- />
- </gl-form-group>
- </div>
- </div>
+ </gl-form-group>
</form>
</template>
diff --git a/app/assets/javascripts/packages_and_registries/settings/group/components/packages_settings.vue b/app/assets/javascripts/packages_and_registries/settings/group/components/packages_settings.vue
index b7e88945dbd..abb9f02d290 100644
--- a/app/assets/javascripts/packages_and_registries/settings/group/components/packages_settings.vue
+++ b/app/assets/javascripts/packages_and_registries/settings/group/components/packages_settings.vue
@@ -1,17 +1,15 @@
<script>
-import { GlSprintf, GlLink } from '@gitlab/ui';
import DuplicatesSettings from '~/packages_and_registries/settings/group/components/duplicates_settings.vue';
import GenericSettings from '~/packages_and_registries/settings/group/components/generic_settings.vue';
import MavenSettings from '~/packages_and_registries/settings/group/components/maven_settings.vue';
import {
PACKAGE_SETTINGS_HEADER,
PACKAGE_SETTINGS_DESCRIPTION,
- PACKAGES_DOCS_PATH,
} from '~/packages_and_registries/settings/group/constants';
import updateNamespacePackageSettings from '~/packages_and_registries/settings/group/graphql/mutations/update_group_packages_settings.mutation.graphql';
import { updateGroupPackageSettings } from '~/packages_and_registries/settings/group/graphql/utils/cache_update';
import { updateGroupPackagesSettingsOptimisticResponse } from '~/packages_and_registries/settings/group/graphql/utils/optimistic_responses';
-import SettingsBlock from '~/vue_shared/components/settings/settings_block.vue';
+import SettingsBlock from '~/packages_and_registries/shared/components/settings_block.vue';
export default {
name: 'PackageSettings',
@@ -19,18 +17,13 @@ export default {
PACKAGE_SETTINGS_HEADER,
PACKAGE_SETTINGS_DESCRIPTION,
},
- links: {
- PACKAGES_DOCS_PATH,
- },
components: {
- GlSprintf,
- GlLink,
SettingsBlock,
MavenSettings,
GenericSettings,
DuplicatesSettings,
},
- inject: ['defaultExpanded', 'groupPath'],
+ inject: ['groupPath'],
props: {
packageSettings: {
type: Object,
@@ -91,20 +84,11 @@ export default {
</script>
<template>
- <settings-block
- :default-expanded="defaultExpanded"
- data-qa-selector="package_registry_settings_content"
- >
+ <settings-block data-qa-selector="package_registry_settings_content">
<template #title> {{ $options.i18n.PACKAGE_SETTINGS_HEADER }}</template>
<template #description>
<span data-testid="description">
- <gl-sprintf :message="$options.i18n.PACKAGE_SETTINGS_DESCRIPTION">
- <template #link="{ content }">
- <gl-link :href="$options.links.PACKAGES_DOCS_PATH" target="_blank">{{
- content
- }}</gl-link>
- </template>
- </gl-sprintf>
+ {{ $options.i18n.PACKAGE_SETTINGS_DESCRIPTION }}
</span>
</template>
<template #default>
@@ -116,8 +100,8 @@ export default {
:duplicate-exception-regex-error="errors.mavenDuplicateExceptionRegex"
:model-names="modelNames"
:loading="isLoading"
- toggle-qa-selector="allow_duplicates_toggle"
- label-qa-selector="allow_duplicates_label"
+ toggle-qa-selector="reject_duplicates_toggle"
+ label-qa-selector="reject_duplicates_label"
@update="updateSettings"
/>
</template>
diff --git a/app/assets/javascripts/packages_and_registries/settings/group/constants.js b/app/assets/javascripts/packages_and_registries/settings/group/constants.js
index 0249b475e46..34764663892 100644
--- a/app/assets/javascripts/packages_and_registries/settings/group/constants.js
+++ b/app/assets/javascripts/packages_and_registries/settings/group/constants.js
@@ -1,17 +1,13 @@
import { helpPagePath } from '~/helpers/help_page_helper';
import { s__, __ } from '~/locale';
-export const PACKAGE_SETTINGS_HEADER = s__('PackageRegistry|Package Registry');
+export const PACKAGE_SETTINGS_HEADER = s__('PackageRegistry|Duplicate packages');
export const PACKAGE_SETTINGS_DESCRIPTION = s__(
- 'PackageRegistry|Use GitLab as a private registry for common package formats. %{linkStart}Learn more.%{linkEnd}',
+ 'PackageRegistry|Allow packages with the same name and version to be uploaded to the registry. The newest version of a package is always used when installing.',
);
-export const DUPLICATES_TOGGLE_LABEL = s__('PackageRegistry|Allow duplicates');
-export const DUPLICATES_ALLOWED_DISABLED = s__(
- 'PackageRegistry|%{boldStart}Do not allow duplicates%{boldEnd} - Reject packages with the same name and version.',
-);
-export const DUPLICATES_ALLOWED_ENABLED = s__(
- 'PackageRegistry|%{boldStart}Allow duplicates%{boldEnd} - Accept packages with the same name and version.',
+export const DUPLICATES_TOGGLE_LABEL = s__(
+ 'PackageRegistry|Reject packages with the same name and version',
);
export const DUPLICATES_SETTING_EXCEPTION_TITLE = __('Exceptions');
export const DUPLICATES_SETTINGS_EXCEPTION_LEGEND = s__(
@@ -19,6 +15,9 @@ export const DUPLICATES_SETTINGS_EXCEPTION_LEGEND = s__(
);
export const DEPENDENCY_PROXY_HEADER = s__('DependencyProxy|Dependency Proxy');
+export const DEPENDENCY_PROXY_DESCRIPTION = s__(
+ 'DependencyProxy|Enable the Dependency Proxy and settings for clearing the cache.',
+);
// Parameters
diff --git a/app/assets/javascripts/packages_and_registries/settings/project/components/container_expiration_policy.vue b/app/assets/javascripts/packages_and_registries/settings/project/components/container_expiration_policy.vue
index fdc7bd39780..90a18d5cf5a 100644
--- a/app/assets/javascripts/packages_and_registries/settings/project/components/container_expiration_policy.vue
+++ b/app/assets/javascripts/packages_and_registries/settings/project/components/container_expiration_policy.vue
@@ -81,7 +81,7 @@ export default {
</script>
<template>
- <settings-block :collapsible="false">
+ <settings-block data-testid="container-expiration-policy-project-settings">
<template #title> {{ $options.i18n.CONTAINER_CLEANUP_POLICY_TITLE }}</template>
<template #description>
<span>
diff --git a/app/assets/javascripts/packages_and_registries/settings/project/components/expiration_dropdown.vue b/app/assets/javascripts/packages_and_registries/settings/project/components/expiration_dropdown.vue
index d75fb31fd98..7682754fdcb 100644
--- a/app/assets/javascripts/packages_and_registries/settings/project/components/expiration_dropdown.vue
+++ b/app/assets/javascripts/packages_and_registries/settings/project/components/expiration_dropdown.vue
@@ -30,6 +30,11 @@ export default {
type: String,
required: true,
},
+ description: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
};
</script>
@@ -46,5 +51,10 @@ export default {
{{ option.label }}
</option>
</gl-form-select>
+ <template v-if="description" #description>
+ <span data-testid="description" class="gl-text-gray-400">
+ {{ description }}
+ </span>
+ </template>
</gl-form-group>
</template>
diff --git a/app/assets/javascripts/packages_and_registries/settings/project/components/packages_cleanup_policy.vue b/app/assets/javascripts/packages_and_registries/settings/project/components/packages_cleanup_policy.vue
new file mode 100644
index 00000000000..1170407a349
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/settings/project/components/packages_cleanup_policy.vue
@@ -0,0 +1,68 @@
+<script>
+import { GlAlert, GlSprintf } from '@gitlab/ui';
+import {
+ FETCH_SETTINGS_ERROR_MESSAGE,
+ PACKAGES_CLEANUP_POLICY_TITLE,
+ PACKAGES_CLEANUP_POLICY_DESCRIPTION,
+} from '~/packages_and_registries/settings/project/constants';
+import packagesCleanupPolicyQuery from '~/packages_and_registries/settings/project/graphql/queries/get_packages_cleanup_policy.query.graphql';
+import SettingsBlock from '~/vue_shared/components/settings/settings_block.vue';
+
+import PackagesCleanupPolicyForm from './packages_cleanup_policy_form.vue';
+
+export default {
+ components: {
+ SettingsBlock,
+ GlAlert,
+ GlSprintf,
+ PackagesCleanupPolicyForm,
+ },
+ inject: ['projectPath'],
+ i18n: {
+ FETCH_SETTINGS_ERROR_MESSAGE,
+ PACKAGES_CLEANUP_POLICY_TITLE,
+ PACKAGES_CLEANUP_POLICY_DESCRIPTION,
+ },
+ apollo: {
+ packagesCleanupPolicy: {
+ query: packagesCleanupPolicyQuery,
+ variables() {
+ return {
+ projectPath: this.projectPath,
+ };
+ },
+ update: (data) => data.project?.packagesCleanupPolicy || {},
+ error(e) {
+ this.fetchSettingsError = e;
+ },
+ },
+ },
+ data() {
+ return {
+ fetchSettingsError: false,
+ packagesCleanupPolicy: {},
+ };
+ },
+};
+</script>
+
+<template>
+ <settings-block>
+ <template #title> {{ $options.i18n.PACKAGES_CLEANUP_POLICY_TITLE }}</template>
+ <template #description>
+ <span data-testid="description">
+ <gl-sprintf :message="$options.i18n.PACKAGES_CLEANUP_POLICY_DESCRIPTION" />
+ </span>
+ </template>
+ <template #default>
+ <gl-alert v-if="fetchSettingsError" variant="warning" :dismissible="false">
+ <gl-sprintf :message="$options.i18n.FETCH_SETTINGS_ERROR_MESSAGE" />
+ </gl-alert>
+ <packages-cleanup-policy-form
+ v-else
+ v-model="packagesCleanupPolicy"
+ :is-loading="$apollo.queries.packagesCleanupPolicy.loading"
+ />
+ </template>
+ </settings-block>
+</template>
diff --git a/app/assets/javascripts/packages_and_registries/settings/project/components/packages_cleanup_policy_form.vue b/app/assets/javascripts/packages_and_registries/settings/project/components/packages_cleanup_policy_form.vue
new file mode 100644
index 00000000000..b1751d5174a
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/settings/project/components/packages_cleanup_policy_form.vue
@@ -0,0 +1,137 @@
+<script>
+import { GlButton } from '@gitlab/ui';
+import {
+ UPDATE_SETTINGS_ERROR_MESSAGE,
+ UPDATE_SETTINGS_SUCCESS_MESSAGE,
+ SET_CLEANUP_POLICY_BUTTON,
+ KEEP_N_DUPLICATED_PACKAGE_FILES_DESCRIPTION,
+ KEEP_N_DUPLICATED_PACKAGE_FILES_FIELDNAME,
+ KEEP_N_DUPLICATED_PACKAGE_FILES_LABEL,
+} from '~/packages_and_registries/settings/project/constants';
+import updatePackagesCleanupPolicyMutation from '~/packages_and_registries/settings/project/graphql/mutations/update_packages_cleanup_policy.mutation.graphql';
+import { formOptionsGenerator } from '~/packages_and_registries/settings/project/utils';
+import Tracking from '~/tracking';
+import ExpirationDropdown from './expiration_dropdown.vue';
+
+export default {
+ components: {
+ GlButton,
+ ExpirationDropdown,
+ },
+ mixins: [Tracking.mixin()],
+ inject: ['projectPath'],
+ props: {
+ value: {
+ type: Object,
+ required: true,
+ },
+ isLoading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ formOptions: formOptionsGenerator(),
+ i18n: {
+ KEEP_N_DUPLICATED_PACKAGE_FILES_LABEL,
+ KEEP_N_DUPLICATED_PACKAGE_FILES_DESCRIPTION,
+ SET_CLEANUP_POLICY_BUTTON,
+ },
+ data() {
+ return {
+ tracking: {
+ label: 'packages_cleanup_policies',
+ },
+ mutationLoading: false,
+ };
+ },
+ computed: {
+ prefilledForm() {
+ return {
+ ...this.value,
+ keepNDuplicatedPackageFiles: this.findDefaultOption(
+ KEEP_N_DUPLICATED_PACKAGE_FILES_FIELDNAME,
+ ),
+ };
+ },
+ showLoadingIcon() {
+ return this.isLoading || this.mutationLoading;
+ },
+ isSubmitButtonDisabled() {
+ return this.showLoadingIcon;
+ },
+ isFieldDisabled() {
+ return this.showLoadingIcon;
+ },
+ mutationVariables() {
+ return {
+ projectPath: this.projectPath,
+ keepNDuplicatedPackageFiles: this.prefilledForm.keepNDuplicatedPackageFiles,
+ };
+ },
+ },
+ methods: {
+ findDefaultOption(option) {
+ return this.value[option] || this.$options.formOptions[option].find((f) => f.default)?.key;
+ },
+ submit() {
+ this.track('submit_packages_cleanup_form');
+ this.mutationLoading = true;
+ return this.$apollo
+ .mutate({
+ mutation: updatePackagesCleanupPolicyMutation,
+ variables: {
+ input: this.mutationVariables,
+ },
+ })
+ .then(({ data }) => {
+ const [errorMessage] = data?.updatePackagesCleanupPolicy?.errors ?? [];
+ if (errorMessage) {
+ throw errorMessage;
+ } else {
+ this.$toast.show(UPDATE_SETTINGS_SUCCESS_MESSAGE);
+ }
+ })
+ .catch(() => {
+ this.$toast.show(UPDATE_SETTINGS_ERROR_MESSAGE);
+ })
+ .finally(() => {
+ this.mutationLoading = false;
+ });
+ },
+ onModelChange(newValue, model) {
+ this.$emit('input', { ...this.value, [model]: newValue });
+ },
+ },
+};
+</script>
+
+<template>
+ <form ref="form-element" @submit.prevent="submit">
+ <div class="gl-md-max-w-50p">
+ <expiration-dropdown
+ v-model="prefilledForm.keepNDuplicatedPackageFiles"
+ :disabled="isFieldDisabled"
+ :form-options="$options.formOptions.keepNDuplicatedPackageFiles"
+ :label="$options.i18n.KEEP_N_DUPLICATED_PACKAGE_FILES_LABEL"
+ :description="$options.i18n.KEEP_N_DUPLICATED_PACKAGE_FILES_DESCRIPTION"
+ name="keep-n-duplicated-package-files"
+ data-testid="keep-n-duplicated-package-files-dropdown"
+ @input="onModelChange($event, 'keepNDuplicatedPackageFiles')"
+ />
+ </div>
+ <div class="gl-mt-7 gl-display-flex gl-align-items-center">
+ <gl-button
+ data-testid="save-button"
+ type="submit"
+ :disabled="isSubmitButtonDisabled"
+ :loading="showLoadingIcon"
+ category="primary"
+ variant="confirm"
+ class="js-no-auto-disable gl-mr-4"
+ >
+ {{ $options.i18n.SET_CLEANUP_POLICY_BUTTON }}
+ </gl-button>
+ </div>
+ </form>
+</template>
diff --git a/app/assets/javascripts/packages_and_registries/settings/project/components/registry_settings_app.vue b/app/assets/javascripts/packages_and_registries/settings/project/components/registry_settings_app.vue
index 95af19e6d85..710cfe7b1eb 100644
--- a/app/assets/javascripts/packages_and_registries/settings/project/components/registry_settings_app.vue
+++ b/app/assets/javascripts/packages_and_registries/settings/project/components/registry_settings_app.vue
@@ -1,15 +1,19 @@
<script>
import ContainerExpirationPolicy from './container_expiration_policy.vue';
+import PackagesCleanupPolicy from './packages_cleanup_policy.vue';
export default {
components: {
ContainerExpirationPolicy,
+ PackagesCleanupPolicy,
},
+ inject: ['showContainerRegistrySettings', 'showPackageRegistrySettings'],
};
</script>
<template>
- <section data-testid="registry-settings-app">
- <container-expiration-policy />
- </section>
+ <div>
+ <packages-cleanup-policy v-if="showPackageRegistrySettings" />
+ <container-expiration-policy v-if="showContainerRegistrySettings" />
+ </div>
</template>
diff --git a/app/assets/javascripts/packages_and_registries/settings/project/constants.js b/app/assets/javascripts/packages_and_registries/settings/project/constants.js
index 40f980d15fb..948520151ce 100644
--- a/app/assets/javascripts/packages_and_registries/settings/project/constants.js
+++ b/app/assets/javascripts/packages_and_registries/settings/project/constants.js
@@ -55,6 +55,31 @@ export const EXPIRATION_POLICY_FOOTER_NOTE = s__(
'ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time',
);
+export const PACKAGES_CLEANUP_POLICY_TITLE = s__(
+ 'PackageRegistry|Manage storage used by package assets',
+);
+export const PACKAGES_CLEANUP_POLICY_DESCRIPTION = s__(
+ 'PackageRegistry|When a package with same name and version is uploaded to the registry, more assets are added to the package. To save storage space, keep only the most recent assets.',
+);
+export const KEEP_N_DUPLICATED_PACKAGE_FILES_LABEL = s__(
+ 'PackageRegistry|Number of duplicate assets to keep',
+);
+export const KEEP_N_DUPLICATED_PACKAGE_FILES_DESCRIPTION = s__(
+ 'PackageRegistry|Examples of assets include .pom & .jar files',
+);
+
+export const KEEP_N_DUPLICATED_PACKAGE_FILES_FIELDNAME = 'keepNDuplicatedPackageFiles';
+
+export const KEEP_N_DUPLICATED_PACKAGE_FILES_OPTIONS = [
+ { key: 'ONE_PACKAGE_FILE', label: 1, default: false },
+ { key: 'TEN_PACKAGE_FILES', label: 10, default: false },
+ { key: 'TWENTY_PACKAGE_FILES', label: 20, default: false },
+ { key: 'THIRTY_PACKAGE_FILES', label: 30, default: false },
+ { key: 'FORTY_PACKAGE_FILES', label: 40, default: false },
+ { key: 'FIFTY_PACKAGE_FILES', label: 50, default: false },
+ { key: 'ALL_PACKAGE_FILES', label: __('All'), default: true },
+];
+
export const KEEP_N_OPTIONS = [
{ key: 'ONE_TAG', variable: 1, default: false },
{ key: 'FIVE_TAGS', variable: 5, default: false },
diff --git a/app/assets/javascripts/packages_and_registries/settings/project/graphql/fragments/packages_cleanup_policy.fragment.graphql b/app/assets/javascripts/packages_and_registries/settings/project/graphql/fragments/packages_cleanup_policy.fragment.graphql
new file mode 100644
index 00000000000..a77ede37884
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/settings/project/graphql/fragments/packages_cleanup_policy.fragment.graphql
@@ -0,0 +1,4 @@
+fragment PackagesCleanupPolicyFields on PackagesCleanupPolicy {
+ keepNDuplicatedPackageFiles
+ nextRunAt
+}
diff --git a/app/assets/javascripts/packages_and_registries/settings/project/graphql/mutations/update_packages_cleanup_policy.mutation.graphql b/app/assets/javascripts/packages_and_registries/settings/project/graphql/mutations/update_packages_cleanup_policy.mutation.graphql
new file mode 100644
index 00000000000..31cdd67e881
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/settings/project/graphql/mutations/update_packages_cleanup_policy.mutation.graphql
@@ -0,0 +1,10 @@
+#import "../fragments/packages_cleanup_policy.fragment.graphql"
+
+mutation updatePackagesCleanupPolicy($input: UpdatePackagesCleanupPolicyInput!) {
+ updatePackagesCleanupPolicy(input: $input) {
+ packagesCleanupPolicy {
+ ...PackagesCleanupPolicyFields
+ }
+ errors
+ }
+}
diff --git a/app/assets/javascripts/packages_and_registries/settings/project/graphql/queries/get_packages_cleanup_policy.query.graphql b/app/assets/javascripts/packages_and_registries/settings/project/graphql/queries/get_packages_cleanup_policy.query.graphql
new file mode 100644
index 00000000000..0e9af253f2c
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/settings/project/graphql/queries/get_packages_cleanup_policy.query.graphql
@@ -0,0 +1,10 @@
+#import "../fragments/packages_cleanup_policy.fragment.graphql"
+
+query getProjectPackagesCleanupPolicy($projectPath: ID!) {
+ project(fullPath: $projectPath) {
+ id
+ packagesCleanupPolicy {
+ ...PackagesCleanupPolicyFields
+ }
+ }
+}
diff --git a/app/assets/javascripts/packages_and_registries/settings/project/registry_settings_bundle.js b/app/assets/javascripts/packages_and_registries/settings/project/registry_settings_bundle.js
index 17c33073668..daf1da6eac8 100644
--- a/app/assets/javascripts/packages_and_registries/settings/project/registry_settings_bundle.js
+++ b/app/assets/javascripts/packages_and_registries/settings/project/registry_settings_bundle.js
@@ -20,6 +20,8 @@ export default () => {
adminSettingsPath,
tagsRegexHelpPagePath,
helpPagePath,
+ showContainerRegistrySettings,
+ showPackageRegistrySettings,
} = el.dataset;
return new Vue({
el,
@@ -34,6 +36,8 @@ export default () => {
adminSettingsPath,
tagsRegexHelpPagePath,
helpPagePath,
+ showContainerRegistrySettings: parseBoolean(showContainerRegistrySettings),
+ showPackageRegistrySettings: parseBoolean(showPackageRegistrySettings),
},
render(createElement) {
return createElement('registry-settings-app', {});
diff --git a/app/assets/javascripts/packages_and_registries/settings/project/utils.js b/app/assets/javascripts/packages_and_registries/settings/project/utils.js
index b577a051862..847965454e9 100644
--- a/app/assets/javascripts/packages_and_registries/settings/project/utils.js
+++ b/app/assets/javascripts/packages_and_registries/settings/project/utils.js
@@ -1,5 +1,11 @@
import { n__ } from '~/locale';
-import { KEEP_N_OPTIONS, CADENCE_OPTIONS, OLDER_THAN_OPTIONS } from './constants';
+import {
+ KEEP_N_OPTIONS,
+ CADENCE_OPTIONS,
+ OLDER_THAN_OPTIONS,
+ KEEP_N_DUPLICATED_PACKAGE_FILES_FIELDNAME,
+ KEEP_N_DUPLICATED_PACKAGE_FILES_OPTIONS,
+} from './constants';
export const findDefaultOption = (options) => {
const item = options.find((o) => o.default);
@@ -25,5 +31,6 @@ export const formOptionsGenerator = () => {
olderThan: optionLabelGenerator(OLDER_THAN_OPTIONS, olderThanTranslationGenerator),
cadence: CADENCE_OPTIONS,
keepN: optionLabelGenerator(KEEP_N_OPTIONS, keepNTranslationGenerator),
+ [KEEP_N_DUPLICATED_PACKAGE_FILES_FIELDNAME]: KEEP_N_DUPLICATED_PACKAGE_FILES_OPTIONS,
};
};
diff --git a/app/assets/javascripts/packages_and_registries/shared/components/settings_block.vue b/app/assets/javascripts/packages_and_registries/shared/components/settings_block.vue
new file mode 100644
index 00000000000..5caf95cd050
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/shared/components/settings_block.vue
@@ -0,0 +1,17 @@
+<template>
+ <section class="settings gl-py-7">
+ <div class="gl-lg-display-flex">
+ <div class="gl-lg-w-half gl-pr-10">
+ <h4>
+ <slot name="title"></slot>
+ </h4>
+ <p>
+ <slot name="description"></slot>
+ </p>
+ </div>
+ <div class="gl-lg-w-half gl-pt-3">
+ <slot></slot>
+ </div>
+ </div>
+ </section>
+</template>
diff --git a/app/assets/javascripts/packages_and_registries/shared/constants/package_registry.js b/app/assets/javascripts/packages_and_registries/shared/constants/package_registry.js
index afc72a2c627..5505205cf33 100644
--- a/app/assets/javascripts/packages_and_registries/shared/constants/package_registry.js
+++ b/app/assets/javascripts/packages_and_registries/shared/constants/package_registry.js
@@ -11,6 +11,7 @@ export const PULL_PACKAGE_TRACKING_ACTION = 'pull_package';
export const DELETE_PACKAGE_FILE_TRACKING_ACTION = 'delete_package_file';
export const REQUEST_DELETE_PACKAGE_FILE_TRACKING_ACTION = 'request_delete_package_file';
export const CANCEL_DELETE_PACKAGE_FILE_TRACKING_ACTION = 'cancel_delete_package_file';
+export const DOWNLOAD_PACKAGE_ASSET_TRACKING_ACTION = 'download_package_asset';
export const TRACKING_ACTIONS = {
DELETE_PACKAGE: DELETE_PACKAGE_TRACKING_ACTION,
@@ -20,6 +21,7 @@ export const TRACKING_ACTIONS = {
DELETE_PACKAGE_FILE: DELETE_PACKAGE_FILE_TRACKING_ACTION,
REQUEST_DELETE_PACKAGE_FILE: REQUEST_DELETE_PACKAGE_FILE_TRACKING_ACTION,
CANCEL_DELETE_PACKAGE_FILE: CANCEL_DELETE_PACKAGE_FILE_TRACKING_ACTION,
+ DOWNLOAD_PACKAGE_ASSET: DOWNLOAD_PACKAGE_ASSET_TRACKING_ACTION,
};
export const SHOW_DELETE_SUCCESS_ALERT = 'showSuccessDeleteAlert';