gitlab-org--gitlab-foss/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/image_list_row.vue

202 lines
5.4 KiB
Vue

<script>
import { GlTooltipDirective, GlIcon, GlSprintf, GlSkeletonLoader, GlButton } from '@gitlab/ui';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { n__ } from '~/locale';
import Tracking from '~/tracking';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import ListItem from '~/vue_shared/components/registry/list_item.vue';
import { joinPaths } from '~/lib/utils/url_utility';
import {
LIST_DELETE_BUTTON_DISABLED,
LIST_DELETE_BUTTON_DISABLED_FOR_MIGRATION,
REMOVE_REPOSITORY_LABEL,
ROW_SCHEDULED_FOR_DELETION,
IMAGE_DELETE_SCHEDULED_STATUS,
IMAGE_FAILED_DELETED_STATUS,
IMAGE_MIGRATING_STATE,
COPY_IMAGE_PATH_TITLE,
IMAGE_FULL_PATH_LABEL,
TRACKING_ACTION_CLICK_SHOW_FULL_PATH,
TRACKING_LABEL_REGISTRY_IMAGE_LIST,
} from '../../constants/index';
import DeleteButton from '../delete_button.vue';
import CleanupStatus from './cleanup_status.vue';
export default {
name: 'ImageListRow',
components: {
ClipboardButton,
DeleteButton,
GlSprintf,
GlButton,
GlIcon,
ListItem,
GlSkeletonLoader,
CleanupStatus,
},
directives: {
GlTooltip: GlTooltipDirective,
},
mixins: [Tracking.mixin()],
inject: ['config'],
props: {
item: {
type: Object,
required: true,
},
metadataLoading: {
type: Boolean,
default: false,
required: false,
},
expirationPolicy: {
type: Object,
default: () => ({}),
required: false,
},
},
i18n: {
REMOVE_REPOSITORY_LABEL,
ROW_SCHEDULED_FOR_DELETION,
COPY_IMAGE_PATH_TITLE,
IMAGE_FULL_PATH_LABEL,
},
data() {
return {
showFullPath: false,
};
},
computed: {
disabledDelete() {
return !this.item.canDelete || this.deleting || this.migrating;
},
id() {
return getIdFromGraphQLId(this.item.id);
},
deleting() {
return this.item.status === IMAGE_DELETE_SCHEDULED_STATUS;
},
migrating() {
return this.item.migrationState === IMAGE_MIGRATING_STATE;
},
failedDelete() {
return this.item.status === IMAGE_FAILED_DELETED_STATUS;
},
tagsCountText() {
return n__(
'ContainerRegistry|%{count} Tag',
'ContainerRegistry|%{count} Tags',
this.item.tagsCount,
);
},
imageName() {
if (this.showFullPath) {
return this.item.path;
}
const projectPath = this.item?.project?.path?.toLowerCase() ?? '';
if (this.item.name) {
return joinPaths(projectPath, this.item.name);
}
return projectPath;
},
routerLinkEvent() {
return this.deleting ? '' : 'click';
},
deleteButtonTooltipTitle() {
return this.migrating
? LIST_DELETE_BUTTON_DISABLED_FOR_MIGRATION
: LIST_DELETE_BUTTON_DISABLED;
},
},
methods: {
hideButton() {
this.showFullPath = true;
this.$refs.imageName.$el.focus();
this.track(TRACKING_ACTION_CLICK_SHOW_FULL_PATH, {
label: TRACKING_LABEL_REGISTRY_IMAGE_LIST,
});
},
},
};
</script>
<template>
<list-item
v-gl-tooltip="{
placement: 'left',
disabled: !deleting,
title: $options.i18n.ROW_SCHEDULED_FOR_DELETION,
}"
v-bind="$attrs"
:disabled="deleting"
>
<template #left-primary>
<gl-button
v-if="!showFullPath"
v-gl-tooltip="{
placement: 'top',
title: $options.i18n.IMAGE_FULL_PATH_LABEL,
}"
icon="ellipsis_h"
size="small"
class="gl-mr-2"
:aria-label="$options.i18n.IMAGE_FULL_PATH_LABEL"
@click="hideButton"
/>
<router-link
ref="imageName"
class="gl-text-body gl-font-weight-bold"
data-testid="details-link"
data-qa-selector="registry_image_content"
:event="routerLinkEvent"
:to="{ name: 'details', params: { id } }"
>
{{ imageName }}
</router-link>
<clipboard-button
v-if="item.location"
:disabled="deleting"
:text="item.location"
:title="$options.i18n.COPY_IMAGE_PATH_TITLE"
category="tertiary"
/>
</template>
<template #left-secondary>
<template v-if="!metadataLoading">
<span class="gl-display-flex gl-align-items-center" data-testid="tags-count">
<gl-icon name="tag" class="gl-mr-2" />
<gl-sprintf :message="tagsCountText">
<template #count>
{{ item.tagsCount }}
</template>
</gl-sprintf>
</span>
<cleanup-status
v-if="item.expirationPolicyCleanupStatus"
class="ml-2"
:status="item.expirationPolicyCleanupStatus"
:expiration-policy="expirationPolicy"
/>
</template>
<div v-else class="gl-w-full">
<gl-skeleton-loader :width="900" :height="16" preserve-aspect-ratio="xMinYMax meet">
<circle cx="6" cy="8" r="6" />
<rect x="16" y="4" width="100" height="8" rx="4" />
</gl-skeleton-loader>
</div>
</template>
<template #right-action>
<delete-button
:title="$options.i18n.REMOVE_REPOSITORY_LABEL"
:disabled="disabledDelete"
:tooltip-disabled="!disabledDelete"
:tooltip-link="config.containerRegistryImportingHelpPagePath"
:tooltip-title="deleteButtonTooltipTitle"
@delete="$emit('delete', item)"
/>
</template>
</list-item>
</template>