Commit a3254abf authored by Frédéric Caplette's avatar Frédéric Caplette

Merge branch '336934-improved-ux-for-bulk-deleting-container-image-tags' into 'master'

Enable bulk delete in container registry tags list

See merge request gitlab-org/gitlab!75655
parents 7eb2f2d7 edc3beb1
<script>
import { GlButton, GlKeysetPagination } from '@gitlab/ui';
import createFlash from '~/flash';
import { n__ } from '~/locale';
import { joinPaths } from '~/lib/utils/url_utility';
import RegistryList from '~/packages_and_registries/shared/components/registry_list.vue';
import {
REMOVE_TAGS_BUTTON_TITLE,
TAGS_LIST_TITLE,
......@@ -16,11 +17,10 @@ import TagsLoader from './tags_loader.vue';
export default {
name: 'TagsList',
components: {
GlButton,
GlKeysetPagination,
TagsListRow,
EmptyState,
TagsLoader,
RegistryList,
},
inject: ['config'],
props: {
......@@ -61,11 +61,13 @@ export default {
},
data() {
return {
selectedItems: {},
containerRepository: {},
};
},
computed: {
listTitle() {
return n__('%d tag', '%d tags', this.tags.length);
},
tags() {
return this.containerRepository?.tags?.nodes || [];
},
......@@ -78,18 +80,9 @@ export default {
first: GRAPHQL_PAGE_SIZE,
};
},
hasSelectedItems() {
return this.tags.some((tag) => this.selectedItems[tag.name]);
},
showMultiDeleteButton() {
return this.tags.some((tag) => tag.canDelete) && !this.isMobile;
},
multiDeleteButtonIsDisabled() {
return !this.hasSelectedItems || this.disabled;
},
showPagination() {
return this.tagsPageInfo.hasPreviousPage || this.tagsPageInfo.hasNextPage;
},
hasNoTags() {
return this.tags.length === 0;
},
......@@ -98,19 +91,13 @@ export default {
},
},
methods: {
updateSelectedItems(name) {
this.$set(this.selectedItems, name, !this.selectedItems[name]);
},
mapTagsToBeDleeted(items) {
return this.tags.filter((tag) => items[tag.name]);
},
fetchNextPage() {
this.$apollo.queries.containerRepository.fetchMore({
variables: {
after: this.tagsPageInfo?.endCursor,
first: GRAPHQL_PAGE_SIZE,
},
updateQuery(previousResult, { fetchMoreResult }) {
updateQuery(_, { fetchMoreResult }) {
return fetchMoreResult;
},
});
......@@ -122,7 +109,7 @@ export default {
before: this.tagsPageInfo?.startCursor,
last: GRAPHQL_PAGE_SIZE,
},
updateQuery(previousResult, { fetchMoreResult }) {
updateQuery(_, { fetchMoreResult }) {
return fetchMoreResult;
},
});
......@@ -137,42 +124,27 @@ export default {
<template v-else>
<empty-state v-if="hasNoTags" :no-containers-image="config.noContainersImage" />
<template v-else>
<div class="gl-display-flex gl-justify-content-space-between gl-mb-3">
<h5 data-testid="list-title">
{{ $options.i18n.TAGS_LIST_TITLE }}
</h5>
<gl-button
v-if="showMultiDeleteButton"
:disabled="multiDeleteButtonIsDisabled"
category="secondary"
variant="danger"
@click="$emit('delete', mapTagsToBeDleeted(selectedItems))"
>
{{ $options.i18n.REMOVE_TAGS_BUTTON_TITLE }}
</gl-button>
</div>
<tags-list-row
v-for="(tag, index) in tags"
:key="tag.path"
:tag="tag"
:first="index === 0"
:selected="selectedItems[tag.name]"
:is-mobile="isMobile"
:disabled="disabled"
@select="updateSelectedItems(tag.name)"
@delete="$emit('delete', mapTagsToBeDleeted({ [tag.name]: true }))"
/>
<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>
<registry-list
:title="listTitle"
:pagination="tagsPageInfo"
:items="tags"
id-property="name"
@prev-page="fetchPreviousPage"
@next-page="fetchNextPage"
@delete="$emit('delete', $event)"
>
<template #default="{ selectItem, isSelected, item, first }">
<tags-list-row
:tag="item"
:first="first"
:selected="isSelected(item)"
:is-mobile="isMobile"
:disabled="disabled"
@select="selectItem(item)"
@delete="$emit('delete', [item])"
/>
</template>
</registry-list>
</template>
</template>
</div>
......
......@@ -82,7 +82,7 @@ RSpec.describe 'Container Registry', :js do
end
it 'shows the image tags' do
expect(page).to have_content 'Image tags'
expect(page).to have_content '1 tag'
first_tag = first('[data-testid="name"]')
expect(first_tag).to have_content 'latest'
end
......
......@@ -87,7 +87,7 @@ RSpec.describe 'Container Registry', :js do
end
it 'shows the image tags' do
expect(page).to have_content 'Image tags'
expect(page).to have_content '20 tags'
first_tag = first('[data-testid="name"]')
expect(first_tag).to have_content '1'
end
......
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