Commit 6c511775 authored by Jose Vargas's avatar Jose Vargas

Change container registry policy banner

This changes the container registry cleanup
policy banner to a more subtle link that takes
the user to the settings page

Changelog: changed
parent 11bfe91d
<script>
import { GlLink } from '@gitlab/ui';
import { approximateDuration, calculateRemainingMilliseconds } from '~/lib/utils/datetime_utility';
import { n__, sprintf } from '~/locale';
import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue';
......@@ -9,6 +10,7 @@ import {
LIST_INTRO_TEXT,
EXPIRATION_POLICY_WILL_RUN_IN,
EXPIRATION_POLICY_DISABLED_TEXT,
SET_UP_CLEANUP,
} from '../../constants/index';
export default {
......@@ -16,6 +18,7 @@ export default {
components: {
TitleArea,
MetadataItem,
GlLink,
},
props: {
expirationPolicy: {
......@@ -43,6 +46,16 @@ export default {
required: false,
default: false,
},
cleanupPoliciesSettingsPath: {
type: String,
default: '',
required: false,
},
showCleanupPolicyLink: {
type: Boolean,
required: false,
default: false,
},
},
loader: {
repeat: 10,
......@@ -51,6 +64,7 @@ export default {
},
i18n: {
CONTAINER_REGISTRY_TITLE,
SET_UP_CLEANUP,
},
computed: {
imagesCountText() {
......@@ -105,6 +119,9 @@ export default {
:text="expirationPolicyText"
size="xl"
/>
<gl-link v-if="showCleanupPolicyLink" class="gl-ml-2" :href="cleanupPoliciesSettingsPath">{{
$options.i18n.SET_UP_CLEANUP
}}</gl-link>
</template>
</title-area>
</template>
......@@ -4,7 +4,7 @@ export const EXPIRATION_POLICY_WILL_RUN_IN = s__(
'ContainerRegistry|Expiration policy will run in %{time}',
);
export const EXPIRATION_POLICY_DISABLED_TEXT = s__(
'ContainerRegistry|Expiration policy is disabled',
'ContainerRegistry|Expiration policy is disabled.',
);
export const DELETE_ALERT_TITLE = s__('ContainerRegistry|Some tags were not deleted');
export const DELETE_ALERT_LINK_TEXT = s__(
......@@ -13,3 +13,4 @@ export const DELETE_ALERT_LINK_TEXT = s__(
export const CLEANUP_TIMED_OUT_ERROR_MESSAGE = s__(
'ContainerRegistry|Cleanup timed out before it could delete all tags',
);
export const SET_UP_CLEANUP = s__('ContainerRegistry|Set up cleanup');
......@@ -35,7 +35,7 @@ export default () => {
expirationPolicy,
isGroupPage,
isAdmin,
showCleanupPolicyOnAlert,
showCleanupPolicyLink,
showUnfinishedTagCleanupCallout,
connectionError,
invalidPathError,
......@@ -68,7 +68,7 @@ export default () => {
expirationPolicy: expirationPolicy ? JSON.parse(expirationPolicy) : undefined,
isGroupPage: parseBoolean(isGroupPage),
isAdmin: parseBoolean(isAdmin),
showCleanupPolicyOnAlert: parseBoolean(showCleanupPolicyOnAlert),
showCleanupPolicyLink: parseBoolean(showCleanupPolicyLink),
showUnfinishedTagCleanupCallout: parseBoolean(showUnfinishedTagCleanupCallout),
connectionError: parseBoolean(connectionError),
invalidPathError: parseBoolean(invalidPathError),
......
......@@ -11,7 +11,6 @@ import {
import { get } from 'lodash';
import getContainerRepositoriesQuery from 'shared_queries/container_registry/get_container_repositories.query.graphql';
import createFlash from '~/flash';
import CleanupPolicyEnabledAlert from '~/packages_and_registries/shared/components/cleanup_policy_enabled_alert.vue';
import { FILTERED_SEARCH_TERM } from '~/packages_and_registries/shared/constants';
import Tracking from '~/tracking';
import PersistedSearch from '~/packages_and_registries/shared/components/persisted_search.vue';
......@@ -60,7 +59,6 @@ export default {
GlSkeletonLoader,
RegistryHeader,
DeleteImage,
CleanupPolicyEnabledAlert,
PersistedSearch,
},
directives: {
......@@ -273,12 +271,6 @@ export default {
</gl-sprintf>
</gl-alert>
<cleanup-policy-enabled-alert
v-if="config.showCleanupPolicyOnAlert"
:project-path="config.projectPath"
:cleanup-policies-settings-path="config.cleanupPoliciesSettingsPath"
/>
<gl-empty-state
v-if="showConnectionError"
:title="$options.i18n.CONNECTION_ERROR_TITLE"
......@@ -304,6 +296,8 @@ export default {
:expiration-policy="config.expirationPolicy"
:help-page-path="config.helpPagePath"
:hide-expiration-policy-data="config.isGroupPage"
:cleanup-policies-settings-path="config.cleanupPoliciesSettingsPath"
:show-cleanup-policy-link="config.showCleanupPolicyLink"
>
<template #commands>
<cli-commands
......
......@@ -9,7 +9,6 @@ import {
UNAVAILABLE_ADMIN_FEATURE_TEXT,
} from '~/packages_and_registries/settings/project/constants';
import expirationPolicyQuery from '~/packages_and_registries/settings/project/graphql/queries/get_expiration_policy.query.graphql';
import CleanupPolicyEnabledAlert from '~/packages_and_registries/shared/components/cleanup_policy_enabled_alert.vue';
import SettingsBlock from '~/vue_shared/components/settings/settings_block.vue';
import SettingsForm from './settings_form.vue';
......@@ -18,19 +17,11 @@ export default {
components: {
SettingsBlock,
SettingsForm,
CleanupPolicyEnabledAlert,
GlAlert,
GlSprintf,
GlLink,
},
inject: [
'projectPath',
'isAdmin',
'adminSettingsPath',
'enableHistoricEntries',
'helpPagePath',
'showCleanupPolicyOnAlert',
],
inject: ['projectPath', 'isAdmin', 'adminSettingsPath', 'enableHistoricEntries', 'helpPagePath'],
i18n: {
UNAVAILABLE_FEATURE_TITLE,
UNAVAILABLE_FEATURE_INTRO_TEXT,
......@@ -87,7 +78,6 @@ export default {
<template>
<section data-testid="registry-settings-app">
<cleanup-policy-enabled-alert v-if="showCleanupPolicyOnAlert" :project-path="projectPath" />
<settings-block :collapsible="false">
<template #title> {{ __('Clean up image tags') }}</template>
<template #description>
......
......@@ -20,7 +20,6 @@ export default () => {
adminSettingsPath,
tagsRegexHelpPagePath,
helpPagePath,
showCleanupPolicyOnAlert,
} = el.dataset;
return new Vue({
el,
......@@ -35,7 +34,6 @@ export default () => {
adminSettingsPath,
tagsRegexHelpPagePath,
helpPagePath,
showCleanupPolicyOnAlert: parseBoolean(showCleanupPolicyOnAlert),
},
render(createElement) {
return createElement('registry-settings-app', {});
......
<script>
import { GlSprintf, GlAlert, GlLink } from '@gitlab/ui';
import { s__ } from '~/locale';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
export default {
components: {
GlAlert,
GlLink,
GlSprintf,
LocalStorageSync,
},
props: {
projectPath: {
type: String,
required: true,
},
cleanupPoliciesSettingsPath: {
type: String,
required: false,
default: '',
},
},
data() {
return {
dismissed: false,
};
},
computed: {
storageKey() {
return `cleanup_policy_enabled_for_project_${this.projectPath}`;
},
},
i18n: {
message: s__(
'ContainerRegistry|Cleanup policies are now available for this project. %{linkStart}Click here to get started.%{linkEnd}',
),
},
};
</script>
<template>
<local-storage-sync v-model="dismissed" :storage-key="storageKey">
<gl-alert v-if="!dismissed" class="gl-mt-2" dismissible @dismiss="dismissed = true">
<gl-sprintf :message="$options.i18n.message">
<template #link="{ content }">
<gl-link v-if="cleanupPoliciesSettingsPath" :href="cleanupPoliciesSettingsPath">{{
content
}}</gl-link>
</template>
</gl-sprintf>
</gl-alert>
</local-storage-sync>
</template>
......@@ -46,7 +46,7 @@ module PackagesHelper
::Gitlab::Tracking.event(category, event_name.to_s, **args)
end
def show_cleanup_policy_on_alert(project)
def show_cleanup_policy_link(project)
Gitlab.com? &&
Gitlab.config.registry.enabled &&
project.feature_available?(:container_registry, current_user) &&
......
......@@ -19,7 +19,7 @@
"project_path": @project.full_path,
"gid_prefix": container_repository_gid_prefix,
"is_admin": current_user&.admin.to_s,
"show_cleanup_policy_on_alert": show_cleanup_policy_on_alert(@project).to_s,
"show_cleanup_policy_link": show_cleanup_policy_link(@project).to_s,
"cleanup_policies_settings_path": project_settings_packages_and_registries_path(@project),
connection_error: (!!@connection_error).to_s,
invalid_path_error: (!!@invalid_path_error).to_s,
......
......@@ -11,5 +11,5 @@
admin_settings_path: ci_cd_admin_application_settings_path(anchor: 'js-registry-settings'),
enable_historic_entries: container_expiration_policies_historic_entry_enabled?.to_s,
help_page_path: help_page_path('user/packages/container_registry/reduce_container_registry_storage', anchor: 'cleanup-policy'),
show_cleanup_policy_on_alert: show_cleanup_policy_on_alert(@project).to_s,
show_cleanup_policy_link: show_cleanup_policy_link(@project).to_s,
tags_regex_help_page_path: help_page_path('user/packages/container_registry/reduce_container_registry_storage', anchor: 'regex-pattern-examples') } }
......@@ -9678,9 +9678,6 @@ msgstr ""
msgid "ContainerRegistry|Cleanup pending"
msgstr ""
msgid "ContainerRegistry|Cleanup policies are now available for this project. %{linkStart}Click here to get started.%{linkEnd}"
msgstr ""
msgid "ContainerRegistry|Cleanup policy for tags is disabled"
msgstr ""
......@@ -9738,7 +9735,7 @@ msgstr ""
msgid "ContainerRegistry|Enable expiration policy"
msgstr ""
msgid "ContainerRegistry|Expiration policy is disabled"
msgid "ContainerRegistry|Expiration policy is disabled."
msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
......@@ -9833,6 +9830,9 @@ msgstr ""
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
msgid "ContainerRegistry|Set up cleanup"
msgstr ""
msgid "ContainerRegistry|Some tags were not deleted"
msgstr ""
......
import { GlSprintf } from '@gitlab/ui';
import { GlSprintf, GlLink } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import Component from '~/packages_and_registries/container_registry/explorer/components/list_page/registry_header.vue';
......@@ -6,6 +6,7 @@ import {
CONTAINER_REGISTRY_TITLE,
LIST_INTRO_TEXT,
EXPIRATION_POLICY_DISABLED_TEXT,
SET_UP_CLEANUP,
} from '~/packages_and_registries/container_registry/explorer/constants';
import TitleArea from '~/vue_shared/components/registry/title_area.vue';
......@@ -21,6 +22,7 @@ describe('registry_header', () => {
const findCommandsSlot = () => wrapper.find('[data-testid="commands-slot"]');
const findImagesCountSubHeader = () => wrapper.find('[data-testid="images-count"]');
const findExpirationPolicySubHeader = () => wrapper.find('[data-testid="expiration-policy"]');
const findSetupCleanUpLink = () => wrapper.findComponent(GlLink);
const mountComponent = async (propsData, slots) => {
wrapper = shallowMount(Component, {
......@@ -88,6 +90,7 @@ describe('registry_header', () => {
});
const text = findExpirationPolicySubHeader();
expect(text.exists()).toBe(true);
expect(text.props()).toMatchObject({
text: EXPIRATION_POLICY_DISABLED_TEXT,
......@@ -100,12 +103,17 @@ describe('registry_header', () => {
await mountComponent({
expirationPolicy: { enabled: true },
expirationPolicyHelpPagePath: 'foo',
showCleanupPolicyLink: true,
imagesCount: 1,
});
const text = findExpirationPolicySubHeader();
const cleanupLink = findSetupCleanUpLink();
expect(text.exists()).toBe(true);
expect(text.props('text')).toBe('Expiration policy will run in ');
expect(cleanupLink.exists()).toBe(true);
expect(cleanupLink.text()).toBe(SET_UP_CLEANUP);
});
it('when the expiration policy is completely disabled', async () => {
await mountComponent({
......
......@@ -6,7 +6,6 @@ import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import getContainerRepositoriesQuery from 'shared_queries/container_registry/get_container_repositories.query.graphql';
import CleanupPolicyEnabledAlert from '~/packages_and_registries/shared/components/cleanup_policy_enabled_alert.vue';
import { FILTERED_SEARCH_TERM } from '~/packages_and_registries/shared/constants';
import DeleteImage from '~/packages_and_registries/container_registry/explorer/components/delete_image.vue';
import CliCommands from '~/packages_and_registries/shared/components/cli_commands.vue';
......@@ -58,7 +57,6 @@ describe('List Page', () => {
const findPersistedSearch = () => wrapper.findComponent(PersistedSearch);
const findEmptySearchMessage = () => wrapper.find('[data-testid="emptySearch"]');
const findDeleteImage = () => wrapper.findComponent(DeleteImage);
const findCleanupAlert = () => wrapper.findComponent(CleanupPolicyEnabledAlert);
const fireFirstSortUpdate = () => {
findPersistedSearch().vm.$emit('update', { sort: 'UPDATED_DESC', filters: [] });
......@@ -511,33 +509,4 @@ describe('List Page', () => {
testTrackingCall('confirm_delete');
});
});
describe('cleanup is on alert', () => {
it('exist when showCleanupPolicyOnAlert is true and has the correct props', async () => {
mountComponent({
config: {
showCleanupPolicyOnAlert: true,
projectPath: 'foo',
isGroupPage: false,
cleanupPoliciesSettingsPath: 'bar',
},
});
await waitForApolloRequestRender();
expect(findCleanupAlert().exists()).toBe(true);
expect(findCleanupAlert().props()).toMatchObject({
projectPath: 'foo',
cleanupPoliciesSettingsPath: 'bar',
});
});
it('is hidden when showCleanupPolicyOnAlert is false', async () => {
mountComponent();
await waitForApolloRequestRender();
expect(findCleanupAlert().exists()).toBe(false);
});
});
});
......@@ -12,7 +12,6 @@ import {
UNAVAILABLE_USER_FEATURE_TEXT,
} from '~/packages_and_registries/settings/project/constants';
import expirationPolicyQuery from '~/packages_and_registries/settings/project/graphql/queries/get_expiration_policy.query.graphql';
import CleanupPolicyEnabledAlert from '~/packages_and_registries/shared/components/cleanup_policy_enabled_alert.vue';
import SettingsBlock from '~/vue_shared/components/settings/settings_block.vue';
import {
......@@ -31,12 +30,11 @@ describe('Registry Settings App', () => {
adminSettingsPath: 'settingsPath',
enableHistoricEntries: false,
helpPagePath: 'helpPagePath',
showCleanupPolicyOnAlert: false,
showCleanupPolicyLink: false,
};
const findSettingsComponent = () => wrapper.find(SettingsForm);
const findAlert = () => wrapper.find(GlAlert);
const findCleanupAlert = () => wrapper.findComponent(CleanupPolicyEnabledAlert);
const mountComponent = (provide = defaultProvidedValues, config) => {
wrapper = shallowMount(component, {
......@@ -69,26 +67,6 @@ describe('Registry Settings App', () => {
wrapper.destroy();
});
describe('cleanup is on alert', () => {
it('exist when showCleanupPolicyOnAlert is true and has the correct props', () => {
mountComponent({
...defaultProvidedValues,
showCleanupPolicyOnAlert: true,
});
expect(findCleanupAlert().exists()).toBe(true);
expect(findCleanupAlert().props()).toMatchObject({
projectPath: 'path',
});
});
it('is hidden when showCleanupPolicyOnAlert is false', async () => {
mountComponent();
expect(findCleanupAlert().exists()).toBe(false);
});
});
describe('isEdited status', () => {
it.each`
description | apiResponse | workingCopy | result
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`CleanupPolicyEnabledAlert renders 1`] = `
<gl-alert-stub
class="gl-mt-2"
dismissible="true"
dismisslabel="Dismiss"
primarybuttonlink=""
primarybuttontext=""
secondarybuttonlink=""
secondarybuttontext=""
title=""
variant="info"
>
<gl-sprintf-stub
message="Cleanup policies are now available for this project. %{linkStart}Click here to get started.%{linkEnd}"
/>
</gl-alert-stub>
`;
import { GlAlert } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import component from '~/packages_and_registries/shared/components/cleanup_policy_enabled_alert.vue';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
describe('CleanupPolicyEnabledAlert', () => {
let wrapper;
const defaultProps = {
projectPath: 'foo',
cleanupPoliciesSettingsPath: 'label-bar',
};
const findAlert = () => wrapper.findComponent(GlAlert);
const mountComponent = (props) => {
wrapper = shallowMount(component, {
stubs: {
LocalStorageSync,
},
propsData: {
...defaultProps,
...props,
},
});
};
afterEach(() => {
wrapper.destroy();
});
it('renders', () => {
mountComponent();
expect(wrapper.element).toMatchSnapshot();
});
it('when dismissed is not visible', async () => {
mountComponent();
expect(findAlert().exists()).toBe(true);
findAlert().vm.$emit('dismiss');
await nextTick();
expect(findAlert().exists()).toBe(false);
});
});
......@@ -65,11 +65,11 @@ RSpec.describe PackagesHelper do
end
end
describe '#show_cleanup_policy_on_alert' do
describe '#show_cleanup_policy_link' do
let_it_be(:user) { create(:user) }
let_it_be_with_reload(:container_repository) { create(:container_repository) }
subject { helper.show_cleanup_policy_on_alert(project.reload) }
subject { helper.show_cleanup_policy_link(project.reload) }
where(:com, :config_registry, :project_registry, :nil_policy, :container_repositories_exist, :expected_result) do
false | false | false | false | false | false
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment