Commit 73a41bd8 authored by Andrew Fontaine's avatar Andrew Fontaine

Merge branch...

Merge branch '347350-surface-deduplicated-size-of-individual-image-repositories-in-the-ui' into 'master'

Container Registry: surface size image repository

See merge request gitlab-org/gitlab!82114
parents 8e6c17f6 6d9d013c
...@@ -4,6 +4,7 @@ import { sprintf, n__, s__ } from '~/locale'; ...@@ -4,6 +4,7 @@ import { sprintf, n__, s__ } from '~/locale';
import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue'; import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue';
import TitleArea from '~/vue_shared/components/registry/title_area.vue'; import TitleArea from '~/vue_shared/components/registry/title_area.vue';
import timeagoMixin from '~/vue_shared/mixins/timeago'; import timeagoMixin from '~/vue_shared/mixins/timeago';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import { import {
UPDATED_AT, UPDATED_AT,
CLEANUP_UNSCHEDULED_TEXT, CLEANUP_UNSCHEDULED_TEXT,
...@@ -23,7 +24,7 @@ import { ...@@ -23,7 +24,7 @@ import {
ROOT_IMAGE_TOOLTIP, ROOT_IMAGE_TOOLTIP,
} from '../../constants/index'; } from '../../constants/index';
import getContainerRepositoryTagsCountQuery from '../../graphql/queries/get_container_repository_tags_count.query.graphql'; import getContainerRepositoryMetadata from '../../graphql/queries/get_container_repository_metadata.query.graphql';
export default { export default {
name: 'DetailsHeader', name: 'DetailsHeader',
...@@ -50,7 +51,7 @@ export default { ...@@ -50,7 +51,7 @@ export default {
}, },
apollo: { apollo: {
containerRepository: { containerRepository: {
query: getContainerRepositoryTagsCountQuery, query: getContainerRepositoryMetadata,
variables() { variables() {
return { return {
id: this.image.id, id: this.image.id,
...@@ -101,6 +102,10 @@ export default { ...@@ -101,6 +102,10 @@ export default {
imageName() { imageName() {
return this.imageDetails.name || ROOT_IMAGE_TEXT; return this.imageDetails.name || ROOT_IMAGE_TEXT;
}, },
formattedSize() {
const { size } = this.imageDetails;
return size ? numberToHumanSize(Number(size)) : null;
},
}, },
}; };
</script> </script>
...@@ -119,10 +124,15 @@ export default { ...@@ -119,10 +124,15 @@ export default {
:aria-label="rootImageTooltip" :aria-label="rootImageTooltip"
/> />
</template> </template>
<template #metadata-tags-count> <template #metadata-tags-count>
<metadata-item icon="tag" :text="tagCountText" data-testid="tags-count" /> <metadata-item icon="tag" :text="tagCountText" data-testid="tags-count" />
</template> </template>
<template v-if="formattedSize" #metadata-size>
<metadata-item icon="disk" :text="formattedSize" data-testid="image-size" />
</template>
<template #metadata-cleanup> <template #metadata-cleanup>
<metadata-item <metadata-item
icon="expire" icon="expire"
......
...@@ -2,6 +2,7 @@ import { GlDropdownItem, GlIcon, GlDropdown } from '@gitlab/ui'; ...@@ -2,6 +2,7 @@ import { GlDropdownItem, GlIcon, GlDropdown } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils'; import { shallowMount, createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo'; import VueApollo from 'vue-apollo';
import { nextTick } from 'vue'; import { nextTick } from 'vue';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import { useFakeDate } from 'helpers/fake_date'; import { useFakeDate } from 'helpers/fake_date';
import createMockApollo from 'helpers/mock_apollo_helper'; import createMockApollo from 'helpers/mock_apollo_helper';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive'; import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
...@@ -20,7 +21,7 @@ import { ...@@ -20,7 +21,7 @@ import {
ROOT_IMAGE_TEXT, ROOT_IMAGE_TEXT,
ROOT_IMAGE_TOOLTIP, ROOT_IMAGE_TOOLTIP,
} from '~/packages_and_registries/container_registry/explorer/constants'; } from '~/packages_and_registries/container_registry/explorer/constants';
import getContainerRepositoryTagCountQuery from '~/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_tags_count.query.graphql'; import getContainerRepositoryMetadata from '~/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_metadata.query.graphql';
import TitleArea from '~/vue_shared/components/registry/title_area.vue'; import TitleArea from '~/vue_shared/components/registry/title_area.vue';
import { imageTagsCountMock } from '../../mock_data'; import { imageTagsCountMock } from '../../mock_data';
...@@ -52,6 +53,7 @@ describe('Details Header', () => { ...@@ -52,6 +53,7 @@ describe('Details Header', () => {
const findDeleteButton = () => wrapper.findComponent(GlDropdownItem); const findDeleteButton = () => wrapper.findComponent(GlDropdownItem);
const findInfoIcon = () => wrapper.findComponent(GlIcon); const findInfoIcon = () => wrapper.findComponent(GlIcon);
const findMenu = () => wrapper.findComponent(GlDropdown); const findMenu = () => wrapper.findComponent(GlDropdown);
const findSize = () => findByTestId('image-size');
const waitForMetadataItems = async () => { const waitForMetadataItems = async () => {
// Metadata items are printed by a loop in the title-area and it takes two ticks for them to be available // Metadata items are printed by a loop in the title-area and it takes two ticks for them to be available
...@@ -72,7 +74,7 @@ describe('Details Header', () => { ...@@ -72,7 +74,7 @@ describe('Details Header', () => {
localVue = createLocalVue(); localVue = createLocalVue();
localVue.use(VueApollo); localVue.use(VueApollo);
const requestHandlers = [[getContainerRepositoryTagCountQuery, resolver]]; const requestHandlers = [[getContainerRepositoryMetadata, resolver]];
apolloProvider = createMockApollo(requestHandlers); apolloProvider = createMockApollo(requestHandlers);
} }
...@@ -230,6 +232,30 @@ describe('Details Header', () => { ...@@ -230,6 +232,30 @@ describe('Details Header', () => {
}); });
}); });
describe('size metadata item', () => {
it('when size is not returned, it hides the item', async () => {
mountComponent();
await waitForMetadataItems();
expect(findSize().exists()).toBe(false);
});
it('when size is returned shows the item', async () => {
const size = 1000;
mountComponent({
resolver: jest.fn().mockResolvedValue(imageTagsCountMock({ size })),
});
await waitForPromises();
await waitForMetadataItems();
expect(findSize().props()).toMatchObject({
icon: 'disk',
text: numberToHumanSize(size),
});
});
});
describe('cleanup metadata item', () => { describe('cleanup metadata item', () => {
it('has the correct icon', async () => { it('has the correct icon', async () => {
mountComponent(); mountComponent();
......
...@@ -187,6 +187,7 @@ export const imageTagsCountMock = (override) => ({ ...@@ -187,6 +187,7 @@ export const imageTagsCountMock = (override) => ({
containerRepository: { containerRepository: {
id: containerRepositoryMock.id, id: containerRepositoryMock.id,
tagsCount: 13, tagsCount: 13,
size: null,
...override, ...override,
}, },
}, },
......
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