debian-mirror-gitlab/app/assets/javascripts/registry/explorer/pages/list.vue

295 lines
8.8 KiB
Vue
Raw Normal View History

2020-03-13 15:44:24 +05:30
<script>
import { mapState, mapActions } from 'vuex';
import {
GlEmptyState,
GlPagination,
GlTooltipDirective,
2020-04-22 19:07:51 +05:30
GlDeprecatedButton,
2020-03-13 15:44:24 +05:30
GlIcon,
GlModal,
GlSprintf,
GlLink,
2020-04-22 19:07:51 +05:30
GlAlert,
2020-04-08 14:13:33 +05:30
GlSkeletonLoader,
2020-03-13 15:44:24 +05:30
} from '@gitlab/ui';
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';
2020-04-08 14:13:33 +05:30
import ProjectPolicyAlert from '../components/project_policy_alert.vue';
2020-04-22 19:07:51 +05:30
import QuickstartDropdown from '../components/quickstart_dropdown.vue';
import {
DELETE_IMAGE_SUCCESS_MESSAGE,
DELETE_IMAGE_ERROR_MESSAGE,
ASYNC_DELETE_IMAGE_ERROR_MESSAGE,
CONTAINER_REGISTRY_TITLE,
CONNECTION_ERROR_TITLE,
CONNECTION_ERROR_MESSAGE,
LIST_INTRO_TEXT,
LIST_DELETE_BUTTON_DISABLED,
REMOVE_REPOSITORY_LABEL,
REMOVE_REPOSITORY_MODAL_TEXT,
ROW_SCHEDULED_FOR_DELETION,
} from '../constants';
2020-03-13 15:44:24 +05:30
export default {
name: 'RegistryListApp',
components: {
GlEmptyState,
GlPagination,
ProjectEmptyState,
GroupEmptyState,
2020-04-08 14:13:33 +05:30
ProjectPolicyAlert,
2020-03-13 15:44:24 +05:30
ClipboardButton,
2020-04-22 19:07:51 +05:30
QuickstartDropdown,
GlDeprecatedButton,
2020-03-13 15:44:24 +05:30
GlIcon,
GlModal,
GlSprintf,
GlLink,
2020-04-22 19:07:51 +05:30
GlAlert,
2020-04-08 14:13:33 +05:30
GlSkeletonLoader,
2020-03-13 15:44:24 +05:30
},
directives: {
GlTooltip: GlTooltipDirective,
},
mixins: [Tracking.mixin()],
2020-04-08 14:13:33 +05:30
loader: {
repeat: 10,
width: 1000,
height: 40,
},
2020-04-22 19:07:51 +05:30
i18n: {
containerRegistryTitle: CONTAINER_REGISTRY_TITLE,
connectionErrorTitle: CONNECTION_ERROR_TITLE,
connectionErrorMessage: CONNECTION_ERROR_MESSAGE,
introText: LIST_INTRO_TEXT,
deleteButtonDisabled: LIST_DELETE_BUTTON_DISABLED,
removeRepositoryLabel: REMOVE_REPOSITORY_LABEL,
removeRepositoryModalText: REMOVE_REPOSITORY_MODAL_TEXT,
rowScheduledForDeletion: ROW_SCHEDULED_FOR_DELETION,
asyncDeleteErrorMessage: ASYNC_DELETE_IMAGE_ERROR_MESSAGE,
},
2020-03-13 15:44:24 +05:30
data() {
return {
itemToDelete: {},
2020-04-22 19:07:51 +05:30
deleteAlertType: null,
2020-03-13 15:44:24 +05:30
};
},
computed: {
...mapState(['config', 'isLoading', 'images', 'pagination']),
tracking() {
return {
label: 'registry_repository_delete',
};
},
currentPage: {
get() {
return this.pagination.page;
},
set(page) {
this.requestImagesList({ page });
},
},
2020-04-22 19:07:51 +05:30
showQuickStartDropdown() {
return Boolean(!this.isLoading && !this.config?.isGroupPage && this.images?.length);
},
showDeleteAlert() {
return this.deleteAlertType && this.itemToDelete?.path;
},
deleteImageAlertMessage() {
return this.deleteAlertType === 'success'
? DELETE_IMAGE_SUCCESS_MESSAGE
: DELETE_IMAGE_ERROR_MESSAGE;
},
2020-03-13 15:44:24 +05:30
},
methods: {
...mapActions(['requestImagesList', 'requestDeleteImage']),
deleteImage(item) {
this.track('click_button');
this.itemToDelete = item;
this.$refs.deleteModal.show();
},
2020-04-22 19:07:51 +05:30
handleDeleteImage() {
2020-03-13 15:44:24 +05:30
this.track('confirm_delete');
2020-04-22 19:07:51 +05:30
return this.requestDeleteImage(this.itemToDelete)
.then(() => {
this.deleteAlertType = 'success';
})
.catch(() => {
this.deleteAlertType = 'danger';
});
2020-03-13 15:44:24 +05:30
},
encodeListItem(item) {
const params = JSON.stringify({ name: item.path, tags_path: item.tags_path, id: item.id });
return window.btoa(params);
},
2020-04-22 19:07:51 +05:30
dismissDeleteAlert() {
this.deleteAlertType = null;
this.itemToDelete = {};
},
2020-03-13 15:44:24 +05:30
},
};
</script>
<template>
2020-04-08 14:13:33 +05:30
<div class="w-100 slide-enter-from-element">
2020-04-22 19:07:51 +05:30
<gl-alert
v-if="showDeleteAlert"
:variant="deleteAlertType"
class="mt-2"
dismissible
@dismiss="dismissDeleteAlert"
>
<gl-sprintf :message="deleteImageAlertMessage">
<template #title>
{{ itemToDelete.path }}
</template>
</gl-sprintf>
</gl-alert>
<project-policy-alert v-if="!config.isGroupPage" class="mt-2" />
2020-04-08 14:13:33 +05:30
2020-03-13 15:44:24 +05:30
<gl-empty-state
v-if="config.characterError"
2020-04-22 19:07:51 +05:30
:title="$options.i18n.connectionErrorTitle"
2020-03-13 15:44:24 +05:30
:svg-path="config.containersErrorImage"
>
<template #description>
<p>
2020-04-22 19:07:51 +05:30
<gl-sprintf :message="$options.i18n.connectionErrorMessage">
2020-03-13 15:44:24 +05:30
<template #docLink="{content}">
<gl-link :href="`${config.helpPagePath}#docker-connection-error`" target="_blank">
{{ content }}
</gl-link>
</template>
</gl-sprintf>
</p>
</template>
</gl-empty-state>
<template v-else>
2020-04-08 14:13:33 +05:30
<div>
2020-04-22 19:07:51 +05:30
<div class="d-flex justify-content-between align-items-center">
<h4>{{ $options.i18n.containerRegistryTitle }}</h4>
<quickstart-dropdown v-if="showQuickStartDropdown" class="d-none d-sm-block" />
</div>
2020-04-08 14:13:33 +05:30
<p>
2020-04-22 19:07:51 +05:30
<gl-sprintf :message="$options.i18n.introText">
2020-04-08 14:13:33 +05:30
<template #docLink="{content}">
<gl-link :href="config.helpPagePath" target="_blank">
{{ content }}
</gl-link>
</template>
</gl-sprintf>
</p>
</div>
2020-03-13 15:44:24 +05:30
2020-04-08 14:13:33 +05:30
<div v-if="isLoading" class="mt-2">
<gl-skeleton-loader
v-for="index in $options.loader.repeat"
:key="index"
:width="$options.loader.width"
:height="$options.loader.height"
preserve-aspect-ratio="xMinYMax meet"
>
<rect width="500" x="10" y="10" height="20" rx="4" />
<circle cx="525" cy="20" r="10" />
<rect x="960" y="0" width="40" height="40" rx="4" />
</gl-skeleton-loader>
</div>
<template v-else>
<div v-if="images.length" ref="imagesList" class="d-flex flex-column">
<div
v-for="(listItem, index) in images"
:key="index"
ref="rowItem"
2020-04-22 19:07:51 +05:30
v-gl-tooltip="{
placement: 'left',
disabled: !listItem.deleting,
title: $options.i18n.rowScheduledForDeletion,
}"
2020-04-08 14:13:33 +05:30
>
2020-03-13 15:44:24 +05:30
<div
2020-04-22 19:07:51 +05:30
class="d-flex justify-content-between align-items-center py-2 px-1 border-bottom"
:class="{ 'border-top': index === 0, 'disabled-content': listItem.deleting }"
2020-03-13 15:44:24 +05:30
>
2020-04-22 19:07:51 +05:30
<div class="d-felx align-items-center">
<router-link
ref="detailsLink"
:to="{ name: 'details', params: { id: encodeListItem(listItem) } }"
>
{{ listItem.path }}
</router-link>
<clipboard-button
v-if="listItem.location"
ref="clipboardButton"
:disabled="listItem.deleting"
:text="listItem.location"
:title="listItem.location"
css-class="btn-default btn-transparent btn-clipboard"
/>
<gl-icon
v-if="listItem.failedDelete"
v-gl-tooltip
:title="$options.i18n.asyncDeleteErrorMessage"
name="warning"
class="text-warning align-middle"
/>
</div>
<div
v-gl-tooltip="{ disabled: listItem.destroy_path }"
class="d-none d-sm-block"
:title="$options.i18n.deleteButtonDisabled"
2020-03-13 15:44:24 +05:30
>
2020-04-22 19:07:51 +05:30
<gl-deprecated-button
ref="deleteImageButton"
v-gl-tooltip
:disabled="!listItem.destroy_path || listItem.deleting"
:title="$options.i18n.removeRepositoryLabel"
:aria-label="$options.i18n.removeRepositoryLabel"
class="btn-inverted"
variant="danger"
@click="deleteImage(listItem)"
>
<gl-icon name="remove" />
</gl-deprecated-button>
</div>
2020-03-13 15:44:24 +05:30
</div>
</div>
<gl-pagination
v-model="currentPage"
:per-page="pagination.perPage"
:total-items="pagination.total"
align="center"
class="w-100 mt-2"
/>
</div>
2020-04-08 14:13:33 +05:30
2020-03-13 15:44:24 +05:30
<template v-else>
<project-empty-state v-if="!config.isGroupPage" />
<group-empty-state v-else />
</template>
</template>
<gl-modal
ref="deleteModal"
modal-id="delete-image-modal"
ok-variant="danger"
2020-04-22 19:07:51 +05:30
@ok="handleDeleteImage"
2020-03-13 15:44:24 +05:30
@cancel="track('cancel_delete')"
>
2020-04-22 19:07:51 +05:30
<template #modal-title>{{ $options.i18n.removeRepositoryLabel }}</template>
2020-03-13 15:44:24 +05:30
<p>
2020-04-22 19:07:51 +05:30
<gl-sprintf :message="$options.i18n.removeRepositoryModalText">
2020-03-13 15:44:24 +05:30
<template #title>
<b>{{ itemToDelete.path }}</b>
</template>
</gl-sprintf>
</p>
<template #modal-ok>{{ __('Remove') }}</template>
</gl-modal>
</template>
</div>
</template>