debian-mirror-gitlab/app/assets/javascripts/registry/explorer/pages/details.vue
2021-02-22 17:27:13 +05:30

213 lines
6.4 KiB
Vue

<script>
import { GlKeysetPagination, GlResizeObserverDirective } from '@gitlab/ui';
import { GlBreakpointInstance } from '@gitlab/ui/dist/utils';
import createFlash from '~/flash';
import Tracking from '~/tracking';
import { joinPaths } from '~/lib/utils/url_utility';
import DeleteAlert from '../components/details_page/delete_alert.vue';
import PartialCleanupAlert from '../components/details_page/partial_cleanup_alert.vue';
import DeleteModal from '../components/details_page/delete_modal.vue';
import DetailsHeader from '../components/details_page/details_header.vue';
import TagsList from '../components/details_page/tags_list.vue';
import TagsLoader from '../components/details_page/tags_loader.vue';
import EmptyTagsState from '../components/details_page/empty_tags_state.vue';
import getContainerRepositoryDetailsQuery from '../graphql/queries/get_container_repository_details.query.graphql';
import deleteContainerRepositoryTagsMutation from '../graphql/mutations/delete_container_repository_tags.mutation.graphql';
import {
ALERT_SUCCESS_TAG,
ALERT_DANGER_TAG,
ALERT_SUCCESS_TAGS,
ALERT_DANGER_TAGS,
GRAPHQL_PAGE_SIZE,
FETCH_IMAGES_LIST_ERROR_MESSAGE,
} from '../constants/index';
export default {
components: {
DeleteAlert,
PartialCleanupAlert,
DetailsHeader,
GlKeysetPagination,
DeleteModal,
TagsList,
TagsLoader,
EmptyTagsState,
},
inject: ['breadCrumbState', 'config'],
directives: {
GlResizeObserver: GlResizeObserverDirective,
},
mixins: [Tracking.mixin()],
apollo: {
image: {
query: getContainerRepositoryDetailsQuery,
variables() {
return this.queryVariables;
},
update(data) {
return data.containerRepository;
},
result({ data }) {
this.tagsPageInfo = data.containerRepository?.tags?.pageInfo;
this.breadCrumbState.updateName(data.containerRepository?.name);
},
error() {
createFlash({ message: FETCH_IMAGES_LIST_ERROR_MESSAGE });
},
},
},
data() {
return {
image: {},
tagsPageInfo: {},
itemsToBeDeleted: [],
isMobile: false,
mutationLoading: false,
deleteAlertType: null,
dismissPartialCleanupWarning: false,
};
},
computed: {
queryVariables() {
return {
id: joinPaths(this.config.gidPrefix, `${this.$route.params.id}`),
first: GRAPHQL_PAGE_SIZE,
};
},
isLoading() {
return this.$apollo.queries.image.loading || this.mutationLoading;
},
tags() {
return this.image?.tags?.nodes || [];
},
showPartialCleanupWarning() {
return this.image?.expirationPolicyStartedAt && !this.dismissPartialCleanupWarning;
},
tracking() {
return {
label:
this.itemsToBeDeleted?.length > 1 ? 'bulk_registry_tag_delete' : 'registry_tag_delete',
};
},
showPagination() {
return this.tagsPageInfo.hasPreviousPage || this.tagsPageInfo.hasNextPage;
},
},
methods: {
deleteTags(toBeDeleted) {
this.itemsToBeDeleted = this.tags.filter(tag => toBeDeleted[tag.name]);
this.track('click_button');
this.$refs.deleteModal.show();
},
async handleDelete() {
this.track('confirm_delete');
const { itemsToBeDeleted } = this;
this.itemsToBeDeleted = [];
this.mutationLoading = true;
try {
const { data } = await this.$apollo.mutate({
mutation: deleteContainerRepositoryTagsMutation,
variables: {
id: this.queryVariables.id,
tagNames: itemsToBeDeleted.map(i => i.name),
},
awaitRefetchQueries: true,
refetchQueries: [
{
query: getContainerRepositoryDetailsQuery,
variables: this.queryVariables,
},
],
});
if (data?.destroyContainerRepositoryTags?.errors[0]) {
throw new Error();
}
this.deleteAlertType =
itemsToBeDeleted.length === 0 ? ALERT_SUCCESS_TAG : ALERT_SUCCESS_TAGS;
} catch (e) {
this.deleteAlertType = itemsToBeDeleted.length === 0 ? ALERT_DANGER_TAG : ALERT_DANGER_TAGS;
}
this.mutationLoading = false;
},
handleResize() {
this.isMobile = GlBreakpointInstance.getBreakpointSize() === 'xs';
},
fetchNextPage() {
if (this.tagsPageInfo?.hasNextPage) {
this.$apollo.queries.image.fetchMore({
variables: {
after: this.tagsPageInfo?.endCursor,
first: GRAPHQL_PAGE_SIZE,
},
updateQuery(previousResult, { fetchMoreResult }) {
return fetchMoreResult;
},
});
}
},
fetchPreviousPage() {
if (this.tagsPageInfo?.hasPreviousPage) {
this.$apollo.queries.image.fetchMore({
variables: {
first: null,
before: this.tagsPageInfo?.startCursor,
last: GRAPHQL_PAGE_SIZE,
},
updateQuery(previousResult, { fetchMoreResult }) {
return fetchMoreResult;
},
});
}
},
},
};
</script>
<template>
<div v-gl-resize-observer="handleResize" class="gl-my-3">
<delete-alert
v-model="deleteAlertType"
:garbage-collection-help-page-path="config.garbageCollectionHelpPagePath"
:is-admin="config.isAdmin"
class="gl-my-2"
/>
<partial-cleanup-alert
v-if="showPartialCleanupWarning"
:run-cleanup-policies-help-page-path="config.runCleanupPoliciesHelpPagePath"
:cleanup-policies-help-page-path="config.cleanupPoliciesHelpPagePath"
@dismiss="dismissPartialCleanupWarning = true"
/>
<details-header :image="image" />
<tags-loader v-if="isLoading" />
<template v-else>
<empty-tags-state v-if="tags.length === 0" :no-containers-image="config.noContainersImage" />
<template v-else>
<tags-list :tags="tags" :is-mobile="isMobile" @delete="deleteTags" />
<div class="gl-display-flex gl-justify-content-center">
<gl-keyset-pagination
v-if="showPagination"
:has-next-page="tagsPageInfo.hasNextPage"
:has-previous-page="tagsPageInfo.hasPreviousPage"
class="gl-mt-3"
@prev="fetchPreviousPage"
@next="fetchNextPage"
/>
</div>
</template>
</template>
<delete-modal
ref="deleteModal"
:items-to-be-deleted="itemsToBeDeleted"
@confirmDelete="handleDelete"
@cancel="track('cancel_delete')"
/>
</div>
</template>