summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/registry
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-03-25 12:08:19 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-03-25 12:08:19 +0000
commite6baeabaa9651d90b03bb64ffce75a2c3cb89aab (patch)
tree85f3cbd6e437b17be59505cf3ac4794c1838609e /app/assets/javascripts/registry
parent5064bf8c5647d4c4430cbb4d097cf1592416de29 (diff)
downloadgitlab-ce-e6baeabaa9651d90b03bb64ffce75a2c3cb89aab.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/registry')
-rw-r--r--app/assets/javascripts/registry/explorer/constants.js2
-rw-r--r--app/assets/javascripts/registry/explorer/index.js2
-rw-r--r--app/assets/javascripts/registry/explorer/pages/details.vue30
-rw-r--r--app/assets/javascripts/registry/explorer/pages/index.vue41
-rw-r--r--app/assets/javascripts/registry/explorer/pages/list.vue75
-rw-r--r--app/assets/javascripts/registry/explorer/stores/actions.js19
-rw-r--r--app/assets/javascripts/registry/explorer/stores/getters.js4
-rw-r--r--app/assets/javascripts/registry/explorer/stores/mutation_types.js1
-rw-r--r--app/assets/javascripts/registry/explorer/stores/mutations.js5
-rw-r--r--app/assets/javascripts/registry/explorer/stores/state.js1
10 files changed, 129 insertions, 51 deletions
diff --git a/app/assets/javascripts/registry/explorer/constants.js b/app/assets/javascripts/registry/explorer/constants.js
index f5d935a2d70..586231d19c7 100644
--- a/app/assets/javascripts/registry/explorer/constants.js
+++ b/app/assets/javascripts/registry/explorer/constants.js
@@ -34,7 +34,7 @@ export const LIST_KEY_CHECKBOX = 'checkbox';
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_SIZE = s__('ContainerRegistry|Compressed Size');
export const LIST_LABEL_LAST_UPDATED = s__('ContainerRegistry|Last Updated');
export const EXPIRATION_POLICY_ALERT_TITLE = s__(
diff --git a/app/assets/javascripts/registry/explorer/index.js b/app/assets/javascripts/registry/explorer/index.js
index a36978303c6..9269aa074f8 100644
--- a/app/assets/javascripts/registry/explorer/index.js
+++ b/app/assets/javascripts/registry/explorer/index.js
@@ -1,4 +1,5 @@
import Vue from 'vue';
+import { GlToast } from '@gitlab/ui';
import Translate from '~/vue_shared/translate';
import RegistryExplorer from './pages/index.vue';
import RegistryBreadcrumb from './components/registry_breadcrumb.vue';
@@ -6,6 +7,7 @@ import { createStore } from './stores';
import createRouter from './router';
Vue.use(Translate);
+Vue.use(GlToast);
export default () => {
const el = document.getElementById('js-container-registry');
diff --git a/app/assets/javascripts/registry/explorer/pages/details.vue b/app/assets/javascripts/registry/explorer/pages/details.vue
index be9a27e2c42..68a066f97e1 100644
--- a/app/assets/javascripts/registry/explorer/pages/details.vue
+++ b/app/assets/javascripts/registry/explorer/pages/details.vue
@@ -31,6 +31,10 @@ import {
LIST_LABEL_IMAGE_ID,
LIST_LABEL_SIZE,
LIST_LABEL_LAST_UPDATED,
+ DELETE_TAG_SUCCESS_MESSAGE,
+ DELETE_TAG_ERROR_MESSAGE,
+ DELETE_TAGS_SUCCESS_MESSAGE,
+ DELETE_TAGS_ERROR_MESSAGE,
} from '../constants';
export default {
@@ -176,17 +180,37 @@ export default {
},
handleSingleDelete(itemToDelete) {
this.itemsToBeDeleted = [];
- this.requestDeleteTag({ tag: itemToDelete, params: this.$route.params.id });
+ return this.requestDeleteTag({ tag: itemToDelete, params: this.$route.params.id })
+ .then(() =>
+ this.$toast.show(DELETE_TAG_SUCCESS_MESSAGE, {
+ type: 'success',
+ }),
+ )
+ .catch(() =>
+ this.$toast.show(DELETE_TAG_ERROR_MESSAGE, {
+ type: 'error',
+ }),
+ );
},
handleMultipleDelete() {
const { itemsToBeDeleted } = this;
this.itemsToBeDeleted = [];
this.selectedItems = [];
- this.requestDeleteTags({
+ return this.requestDeleteTags({
ids: itemsToBeDeleted.map(x => this.tags[x].name),
params: this.$route.params.id,
- });
+ })
+ .then(() =>
+ this.$toast.show(DELETE_TAGS_SUCCESS_MESSAGE, {
+ type: 'success',
+ }),
+ )
+ .catch(() =>
+ this.$toast.show(DELETE_TAGS_ERROR_MESSAGE, {
+ type: 'error',
+ }),
+ );
},
onDeletionConfirmed() {
this.track('confirm_delete');
diff --git a/app/assets/javascripts/registry/explorer/pages/index.vue b/app/assets/javascripts/registry/explorer/pages/index.vue
index 19ae3bee640..95d83c82987 100644
--- a/app/assets/javascripts/registry/explorer/pages/index.vue
+++ b/app/assets/javascripts/registry/explorer/pages/index.vue
@@ -1,11 +1,48 @@
<script>
-export default {};
+import { GlAlert, GlSprintf, GlLink } from '@gitlab/ui';
+import { mapState, mapActions, mapGetters } from 'vuex';
+import { s__ } from '~/locale';
+
+export default {
+ components: {
+ GlAlert,
+ GlSprintf,
+ GlLink,
+ },
+ i18n: {
+ garbageCollectionTipText: s__(
+ 'ContainerRegistry|This Registry contains deleted image tag data. Remember to run %{docLinkStart}garbage collection%{docLinkEnd} to remove the stale data from storage.',
+ ),
+ },
+ computed: {
+ ...mapState(['config']),
+ ...mapGetters(['showGarbageCollection']),
+ },
+ methods: {
+ ...mapActions(['setShowGarbageCollectionTip']),
+ },
+};
</script>
<template>
<div>
+ <gl-alert
+ v-if="showGarbageCollection"
+ variant="tip"
+ class="my-2"
+ @dismiss="setShowGarbageCollectionTip(false)"
+ >
+ <gl-sprintf :message="$options.i18n.garbageCollectionTipText">
+ <template #docLink="{content}">
+ <gl-link :href="config.garbageCollectionHelpPagePath" target="_blank">
+ {{ content }}
+ </gl-link>
+ </template>
+ </gl-sprintf>
+ </gl-alert>
+
<transition name="slide">
- <router-view />
+ <router-view ref="router-view" />
</transition>
</div>
</template>
diff --git a/app/assets/javascripts/registry/explorer/pages/list.vue b/app/assets/javascripts/registry/explorer/pages/list.vue
index 7e321e927d3..1ed24fbb59f 100644
--- a/app/assets/javascripts/registry/explorer/pages/list.vue
+++ b/app/assets/javascripts/registry/explorer/pages/list.vue
@@ -12,11 +12,13 @@ import {
GlSkeletonLoader,
} from '@gitlab/ui';
import Tracking from '~/tracking';
+import { s__ } from '~/locale';
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';
import QuickstartDropdown from '../components/quickstart_dropdown.vue';
+import { DELETE_IMAGE_SUCCESS_MESSAGE, DELETE_IMAGE_ERROR_MESSAGE } from '../constants';
export default {
name: 'RegistryListApp',
@@ -44,6 +46,23 @@ export default {
width: 1000,
height: 40,
},
+ i18n: {
+ containerRegistryTitle: s__('ContainerRegistry|Container Registry'),
+ connectionErrorTitle: s__('ContainerRegistry|Docker connection error'),
+ connectionErrorMessage: s__(
+ `ContainerRegistry|We are having trouble connecting to Docker, which could be due to an issue with your project name or path. %{docLinkStart}More Information%{docLinkEnd}`,
+ ),
+ introText: s__(
+ `ContainerRegistry|With the Docker Container Registry integrated into GitLab, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}`,
+ ),
+ deleteButtonDisabled: s__(
+ 'ContainerRegistry|Missing or insufficient permission, delete button disabled',
+ ),
+ removeRepositoryLabel: s__('ContainerRegistry|Remove repository'),
+ removeRepositoryModalText: s__(
+ 'ContainerRegistry|You are about to remove repository %{title}. Once you confirm, this repository will be permanently deleted.',
+ ),
+ },
data() {
return {
itemToDelete: {},
@@ -76,10 +95,22 @@ export default {
this.itemToDelete = item;
this.$refs.deleteModal.show();
},
- handleDeleteRepository() {
+ handleDeleteImage() {
this.track('confirm_delete');
- this.requestDeleteImage(this.itemToDelete.destroy_path);
- this.itemToDelete = {};
+ return this.requestDeleteImage(this.itemToDelete.destroy_path)
+ .then(() =>
+ this.$toast.show(DELETE_IMAGE_SUCCESS_MESSAGE, {
+ type: 'success',
+ }),
+ )
+ .catch(() =>
+ this.$toast.show(DELETE_IMAGE_ERROR_MESSAGE, {
+ type: 'error',
+ }),
+ )
+ .finally(() => {
+ this.itemToDelete = {};
+ });
},
encodeListItem(item) {
const params = JSON.stringify({ name: item.path, tags_path: item.tags_path, id: item.id });
@@ -95,18 +126,12 @@ export default {
<gl-empty-state
v-if="config.characterError"
- :title="s__('ContainerRegistry|Docker connection error')"
+ :title="$options.i18n.connectionErrorTitle"
:svg-path="config.containersErrorImage"
>
<template #description>
<p>
- <gl-sprintf
- :message="
- s__(`ContainerRegistry|We are having trouble connecting to Docker, which could be due to an
- issue with your project name or path.
- %{docLinkStart}More Information%{docLinkEnd}`)
- "
- >
+ <gl-sprintf :message="$options.i18n.connectionErrorMessage">
<template #docLink="{content}">
<gl-link :href="`${config.helpPagePath}#docker-connection-error`" target="_blank">
{{ content }}
@@ -120,17 +145,11 @@ export default {
<template v-else>
<div>
<div class="d-flex justify-content-between align-items-center">
- <h4>{{ s__('ContainerRegistry|Container Registry') }}</h4>
+ <h4>{{ $options.i18n.containerRegistryTitle }}</h4>
<quickstart-dropdown v-if="showQuickStartDropdown" class="d-none d-sm-block" />
</div>
<p>
- <gl-sprintf
- :message="
- s__(`ContainerRegistry|With the Docker Container Registry integrated into GitLab, every
- project can have its own space to store its Docker images.
- %{docLinkStart}More Information%{docLinkEnd}`)
- "
- >
+ <gl-sprintf :message="$options.i18n.introText">
<template #docLink="{content}">
<gl-link :href="config.helpPagePath" target="_blank">
{{ content }}
@@ -180,16 +199,14 @@ export default {
<div
v-gl-tooltip="{ disabled: listItem.destroy_path }"
class="d-none d-sm-block"
- :title="
- s__('ContainerRegistry|Missing or insufficient permission, delete button disabled')
- "
+ :title="$options.i18n.deleteButtonDisabled"
>
<gl-button
ref="deleteImageButton"
v-gl-tooltip
:disabled="!listItem.destroy_path"
- :title="s__('ContainerRegistry|Remove repository')"
- :aria-label="s__('ContainerRegistry|Remove repository')"
+ :title="$options.i18n.removeRepositoryLabel"
+ :aria-label="$options.i18n.removeRepositoryLabel"
class="btn-inverted"
variant="danger"
@click="deleteImage(listItem)"
@@ -217,16 +234,12 @@ export default {
ref="deleteModal"
modal-id="delete-image-modal"
ok-variant="danger"
- @ok="handleDeleteRepository"
+ @ok="handleDeleteImage"
@cancel="track('cancel_delete')"
>
- <template #modal-title>{{ s__('ContainerRegistry|Remove repository') }}</template>
+ <template #modal-title>{{ $options.i18n.removeRepositoryLabel }}</template>
<p>
- <gl-sprintf
- :message=" s__(
- 'ContainerRegistry|You are about to remove repository %{title}. Once you confirm, this repository will be permanently deleted.',
- ),"
- >
+ <gl-sprintf :message="$options.i18n.removeRepositoryModalText">
<template #title>
<b>{{ itemToDelete.path }}</b>
</template>
diff --git a/app/assets/javascripts/registry/explorer/stores/actions.js b/app/assets/javascripts/registry/explorer/stores/actions.js
index 7d8201949f4..2abd72cb9a8 100644
--- a/app/assets/javascripts/registry/explorer/stores/actions.js
+++ b/app/assets/javascripts/registry/explorer/stores/actions.js
@@ -6,16 +6,12 @@ import {
DEFAULT_PAGE,
DEFAULT_PAGE_SIZE,
FETCH_TAGS_LIST_ERROR_MESSAGE,
- DELETE_TAG_SUCCESS_MESSAGE,
- DELETE_TAG_ERROR_MESSAGE,
- DELETE_TAGS_SUCCESS_MESSAGE,
- DELETE_TAGS_ERROR_MESSAGE,
- DELETE_IMAGE_ERROR_MESSAGE,
- DELETE_IMAGE_SUCCESS_MESSAGE,
} from '../constants';
import { decodeAndParse } from '../utils';
export const setInitialState = ({ commit }, data) => commit(types.SET_INITIAL_STATE, data);
+export const setShowGarbageCollectionTip = ({ commit }, data) =>
+ commit(types.SET_SHOW_GARBAGE_COLLECTION_TIP, data);
export const receiveImagesListSuccess = ({ commit }, { data, headers }) => {
commit(types.SET_IMAGES_LIST_SUCCESS, data);
@@ -67,11 +63,10 @@ export const requestDeleteTag = ({ commit, dispatch, state }, { tag, params }) =
return axios
.delete(tag.destroy_path)
.then(() => {
- createFlash(DELETE_TAG_SUCCESS_MESSAGE, 'success');
+ dispatch('setShowGarbageCollectionTip', true);
return dispatch('requestTagsList', { pagination: state.tagsPagination, params });
})
.catch(() => {
- createFlash(DELETE_TAG_ERROR_MESSAGE);
commit(types.SET_MAIN_LOADING, false);
});
};
@@ -85,11 +80,10 @@ export const requestDeleteTags = ({ commit, dispatch, state }, { ids, params })
return axios
.delete(url, { params: { ids } })
.then(() => {
- createFlash(DELETE_TAGS_SUCCESS_MESSAGE, 'success');
+ dispatch('setShowGarbageCollectionTip', true);
return dispatch('requestTagsList', { pagination: state.tagsPagination, params });
})
.catch(() => {
- createFlash(DELETE_TAGS_ERROR_MESSAGE);
commit(types.SET_MAIN_LOADING, false);
});
};
@@ -100,11 +94,8 @@ export const requestDeleteImage = ({ commit, dispatch, state }, destroyPath) =>
return axios
.delete(destroyPath)
.then(() => {
+ dispatch('setShowGarbageCollectionTip', true);
dispatch('requestImagesList', { pagination: state.pagination });
- createFlash(DELETE_IMAGE_SUCCESS_MESSAGE, 'success');
- })
- .catch(() => {
- createFlash(DELETE_IMAGE_ERROR_MESSAGE);
})
.finally(() => {
commit(types.SET_MAIN_LOADING, false);
diff --git a/app/assets/javascripts/registry/explorer/stores/getters.js b/app/assets/javascripts/registry/explorer/stores/getters.js
index 1136257a024..a371d0e6356 100644
--- a/app/assets/javascripts/registry/explorer/stores/getters.js
+++ b/app/assets/javascripts/registry/explorer/stores/getters.js
@@ -18,3 +18,7 @@ export const dockerLoginCommand = state => {
/* eslint-disable @gitlab/require-i18n-strings */
return `docker login ${state.config.registryHostUrlWithPort}`;
};
+
+export const showGarbageCollection = state => {
+ return state.showGarbageCollectionTip && state.config.isAdmin;
+};
diff --git a/app/assets/javascripts/registry/explorer/stores/mutation_types.js b/app/assets/javascripts/registry/explorer/stores/mutation_types.js
index 92b747dffc5..86eaa0dd2f1 100644
--- a/app/assets/javascripts/registry/explorer/stores/mutation_types.js
+++ b/app/assets/javascripts/registry/explorer/stores/mutation_types.js
@@ -5,3 +5,4 @@ export const SET_PAGINATION = 'SET_PAGINATION';
export const SET_MAIN_LOADING = 'SET_MAIN_LOADING';
export const SET_TAGS_PAGINATION = 'SET_TAGS_PAGINATION';
export const SET_TAGS_LIST_SUCCESS = 'SET_TAGS_LIST_SUCCESS';
+export const SET_SHOW_GARBAGE_COLLECTION_TIP = 'SET_SHOW_GARBAGE_COLLECTION_TIP';
diff --git a/app/assets/javascripts/registry/explorer/stores/mutations.js b/app/assets/javascripts/registry/explorer/stores/mutations.js
index 6055efcbd46..fda788051c0 100644
--- a/app/assets/javascripts/registry/explorer/stores/mutations.js
+++ b/app/assets/javascripts/registry/explorer/stores/mutations.js
@@ -7,6 +7,7 @@ export default {
...config,
expirationPolicy: config.expirationPolicy ? JSON.parse(config.expirationPolicy) : undefined,
isGroupPage: config.isGroupPage !== undefined,
+ isAdmin: config.isAdmin !== undefined,
};
},
@@ -22,6 +23,10 @@ export default {
state.isLoading = isLoading;
},
+ [types.SET_SHOW_GARBAGE_COLLECTION_TIP](state, showGarbageCollectionTip) {
+ state.showGarbageCollectionTip = showGarbageCollectionTip;
+ },
+
[types.SET_PAGINATION](state, headers) {
const normalizedHeaders = normalizeHeaders(headers);
state.pagination = parseIntPagination(normalizedHeaders);
diff --git a/app/assets/javascripts/registry/explorer/stores/state.js b/app/assets/javascripts/registry/explorer/stores/state.js
index 91a378f139b..694006aac81 100644
--- a/app/assets/javascripts/registry/explorer/stores/state.js
+++ b/app/assets/javascripts/registry/explorer/stores/state.js
@@ -1,5 +1,6 @@
export default () => ({
isLoading: false,
+ showGarbageCollectionTip: false,
config: {},
images: [],
tags: [],