summaryrefslogtreecommitdiff
path: root/app/assets
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets')
-rw-r--r--app/assets/javascripts/registry/explorer/components/project_policy_alert.vue69
-rw-r--r--app/assets/javascripts/registry/explorer/constants.js47
-rw-r--r--app/assets/javascripts/registry/explorer/pages/list.vue4
-rw-r--r--app/assets/javascripts/registry/explorer/stores/mutations.js1
4 files changed, 106 insertions, 15 deletions
diff --git a/app/assets/javascripts/registry/explorer/components/project_policy_alert.vue b/app/assets/javascripts/registry/explorer/components/project_policy_alert.vue
new file mode 100644
index 00000000000..6acf366e531
--- /dev/null
+++ b/app/assets/javascripts/registry/explorer/components/project_policy_alert.vue
@@ -0,0 +1,69 @@
+<script>
+import { GlAlert, GlSprintf, GlLink } from '@gitlab/ui';
+import { mapState } from 'vuex';
+import { approximateDuration, calculateRemainingMilliseconds } from '~/lib/utils/datetime_utility';
+import {
+ EXPIRATION_POLICY_ALERT_TITLE,
+ EXPIRATION_POLICY_ALERT_PRIMARY_BUTTON,
+ EXPIRATION_POLICY_ALERT_FULL_MESSAGE,
+ EXPIRATION_POLICY_ALERT_SHORT_MESSAGE,
+} from '../constants';
+
+export default {
+ components: {
+ GlAlert,
+ GlSprintf,
+ GlLink,
+ },
+
+ computed: {
+ ...mapState(['config', 'images', 'isLoading']),
+ isEmpty() {
+ return !this.images || this.images.length === 0;
+ },
+ showAlert() {
+ return this.config.expirationPolicy?.enabled;
+ },
+ timeTillRun() {
+ const difference = calculateRemainingMilliseconds(this.config.expirationPolicy?.next_run_at);
+ return approximateDuration(difference / 1000);
+ },
+ alertConfiguration() {
+ if (this.isEmpty || this.isLoading) {
+ return {
+ title: null,
+ primaryButton: null,
+ message: EXPIRATION_POLICY_ALERT_SHORT_MESSAGE,
+ };
+ }
+ return {
+ title: EXPIRATION_POLICY_ALERT_TITLE,
+ primaryButton: EXPIRATION_POLICY_ALERT_PRIMARY_BUTTON,
+ message: EXPIRATION_POLICY_ALERT_FULL_MESSAGE,
+ };
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-alert
+ v-if="showAlert"
+ :dismissible="false"
+ :primary-button-text="alertConfiguration.primaryButton"
+ :primary-button-link="config.settingsPath"
+ :title="alertConfiguration.title"
+ class="my-2"
+ >
+ <gl-sprintf :message="alertConfiguration.message">
+ <template #days>
+ <strong>{{ timeTillRun }}</strong>
+ </template>
+ <template #link="{content}">
+ <gl-link :href="config.expirationPolicyHelpPagePath" target="_blank">
+ {{ content }}
+ </gl-link>
+ </template>
+ </gl-sprintf>
+ </gl-alert>
+</template>
diff --git a/app/assets/javascripts/registry/explorer/constants.js b/app/assets/javascripts/registry/explorer/constants.js
index bb311157627..ef72c085972 100644
--- a/app/assets/javascripts/registry/explorer/constants.js
+++ b/app/assets/javascripts/registry/explorer/constants.js
@@ -1,18 +1,24 @@
-import { __ } from '~/locale';
+import { s__ } from '~/locale';
-export const FETCH_IMAGES_LIST_ERROR_MESSAGE = __(
- 'Something went wrong while fetching the packages list.',
+export const FETCH_IMAGES_LIST_ERROR_MESSAGE = s__(
+ 'ContainerRegistry|Something went wrong while fetching the packages list.',
);
-export const FETCH_TAGS_LIST_ERROR_MESSAGE = __(
- 'Something went wrong while fetching the tags list.',
+export const FETCH_TAGS_LIST_ERROR_MESSAGE = s__(
+ 'ContainerRegistry|Something went wrong while fetching the tags list.',
);
-export const DELETE_IMAGE_ERROR_MESSAGE = __('Something went wrong while deleting the image.');
-export const DELETE_IMAGE_SUCCESS_MESSAGE = __('Image deleted successfully');
-export const DELETE_TAG_ERROR_MESSAGE = __('Something went wrong while deleting the tag.');
-export const DELETE_TAG_SUCCESS_MESSAGE = __('Tag deleted successfully');
-export const DELETE_TAGS_ERROR_MESSAGE = __('Something went wrong while deleting the tags.');
-export const DELETE_TAGS_SUCCESS_MESSAGE = __('Tags deleted successfully');
+export const DELETE_IMAGE_ERROR_MESSAGE = s__(
+ 'ContainerRegistry|Something went wrong while deleting the image.',
+);
+export const DELETE_IMAGE_SUCCESS_MESSAGE = s__('ContainerRegistry|Image deleted successfully');
+export const DELETE_TAG_ERROR_MESSAGE = s__(
+ 'ContainerRegistry|Something went wrong while deleting the tag.',
+);
+export const DELETE_TAG_SUCCESS_MESSAGE = s__('ContainerRegistry|Tag deleted successfully');
+export const DELETE_TAGS_ERROR_MESSAGE = s__(
+ 'ContainerRegistry|Something went wrong while deleting the tags.',
+);
+export const DELETE_TAGS_SUCCESS_MESSAGE = s__('ContainerRegistry|Tags deleted successfully');
export const DEFAULT_PAGE = 1;
export const DEFAULT_PAGE_SIZE = 10;
@@ -26,7 +32,18 @@ export const LIST_KEY_LAST_UPDATED = 'created_at';
export const LIST_KEY_ACTIONS = 'actions';
export const LIST_KEY_CHECKBOX = 'checkbox';
-export const LIST_LABEL_TAG = __('Tag');
-export const LIST_LABEL_IMAGE_ID = __('Image ID');
-export const LIST_LABEL_SIZE = __('Size');
-export const LIST_LABEL_LAST_UPDATED = __('Last Updated');
+export const LIST_LABEL_TAG = s__('ContainerRegistry|Tag');
+export const LIST_LABEL_IMAGE_ID = s__('ContainerRegistry|Image ID');
+export const LIST_LABEL_SIZE = s__('ContainerRegistry|Size');
+export const LIST_LABEL_LAST_UPDATED = s__('ContainerRegistry|Last Updated');
+
+export const EXPIRATION_POLICY_ALERT_TITLE = s__(
+ 'ContainerRegistry|Retention policy has been Enabled',
+);
+export const EXPIRATION_POLICY_ALERT_PRIMARY_BUTTON = s__('ContainerRegistry|Edit Settings');
+export const EXPIRATION_POLICY_ALERT_FULL_MESSAGE = s__(
+ 'ContainerRegistry|The retention and expiration policy for this Container Registry has been enabled and will run in %{days}. For more information visit the %{linkStart}documentation%{linkEnd}',
+);
+export const EXPIRATION_POLICY_ALERT_SHORT_MESSAGE = s__(
+ 'ContainerRegistry|The retention and expiration policy for this Container Registry has been enabled. For more information visit the %{linkStart}documentation%{linkEnd}',
+);
diff --git a/app/assets/javascripts/registry/explorer/pages/list.vue b/app/assets/javascripts/registry/explorer/pages/list.vue
index 4e9f0a83501..c6ba06cd68c 100644
--- a/app/assets/javascripts/registry/explorer/pages/list.vue
+++ b/app/assets/javascripts/registry/explorer/pages/list.vue
@@ -15,6 +15,7 @@ import Tracking from '~/tracking';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import ProjectEmptyState from '../components/project_empty_state.vue';
import GroupEmptyState from '../components/group_empty_state.vue';
+import ProjectPolicyAlert from '../components/project_policy_alert.vue';
export default {
name: 'RegistryListApp',
@@ -23,6 +24,7 @@ export default {
GlPagination,
ProjectEmptyState,
GroupEmptyState,
+ ProjectPolicyAlert,
ClipboardButton,
GlButton,
GlIcon,
@@ -84,6 +86,8 @@ export default {
<template>
<div class="w-100 slide-enter-from-element">
+ <project-policy-alert v-if="!config.isGroupPage" />
+
<gl-empty-state
v-if="config.characterError"
:title="s__('ContainerRegistry|Docker connection error')"
diff --git a/app/assets/javascripts/registry/explorer/stores/mutations.js b/app/assets/javascripts/registry/explorer/stores/mutations.js
index a2c6a11de20..6055efcbd46 100644
--- a/app/assets/javascripts/registry/explorer/stores/mutations.js
+++ b/app/assets/javascripts/registry/explorer/stores/mutations.js
@@ -5,6 +5,7 @@ export default {
[types.SET_INITIAL_STATE](state, config) {
state.config = {
...config,
+ expirationPolicy: config.expirationPolicy ? JSON.parse(config.expirationPolicy) : undefined,
isGroupPage: config.isGroupPage !== undefined,
};
},