gitlab-org--gitlab-foss/app/assets/javascripts/packages_and_registries/harbor_registry/pages/details.vue

157 lines
4.2 KiB
Vue

<script>
import { GlFilteredSearchToken } from '@gitlab/ui';
import {
NAME_SORT_FIELD,
ROOT_IMAGE_TEXT,
DEFAULT_PER_PAGE,
FETCH_ARTIFACT_LIST_ERROR_MESSAGE,
TOKEN_TYPE_TAG_NAME,
TAG_LABEL,
} from '~/packages_and_registries/harbor_registry/constants/index';
import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants';
import { createAlert } from '~/flash';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import TagsLoader from '~/packages_and_registries/shared/components/tags_loader.vue';
import ArtifactsList from '~/packages_and_registries/harbor_registry/components/details/artifacts_list.vue';
import PersistedSearch from '~/packages_and_registries/shared/components/persisted_search.vue';
import DetailsHeader from '~/packages_and_registries/harbor_registry/components/details/details_header.vue';
import {
extractSortingDetail,
parseFilter,
formatPagination,
} from '~/packages_and_registries/harbor_registry/utils';
import { getHarborArtifacts } from '~/rest_api';
export default {
name: 'HarborDetailsPage',
components: {
ArtifactsList,
TagsLoader,
DetailsHeader,
PersistedSearch,
},
inject: ['endpoint', 'breadCrumbState'],
searchConfig: { nameSortFields: [NAME_SORT_FIELD] },
tokens: [
{
type: TOKEN_TYPE_TAG_NAME,
icon: 'tag',
title: TAG_LABEL,
unique: true,
token: GlFilteredSearchToken,
operators: OPERATOR_IS_ONLY,
},
],
data() {
return {
artifactsList: [],
pageInfo: {},
mutationLoading: false,
deleteAlertType: null,
isLoading: true,
filterString: '',
sorting: null,
};
},
computed: {
currentPage() {
return this.pageInfo.page || 1;
},
imagesDetail() {
return {
name: this.fullName,
artifactCount: this.pageInfo?.total || 0,
};
},
fullName() {
const { project, image } = this.$route.params;
if (project && image) {
return `${project}/${image}`;
}
return '';
},
},
mounted() {
this.updateBreadcrumb();
},
methods: {
updateBreadcrumb() {
const name = this.fullName || ROOT_IMAGE_TEXT;
this.breadCrumbState.updateName(name);
this.breadCrumbState.updateHref(this.$route.path);
},
handleSearchUpdate({ sort, filters }) {
this.sorting = sort;
this.filterString = parseFilter(filters, 'digest');
this.fetchArtifacts(1);
},
fetchPrevPage() {
const prevPageNum = this.currentPage - 1;
this.fetchArtifacts(prevPageNum);
},
fetchNextPage() {
const nextPageNum = this.currentPage + 1;
this.fetchArtifacts(nextPageNum);
},
fetchArtifacts(requestPage) {
this.isLoading = true;
const { orderBy, sort } = extractSortingDetail(this.sorting);
const sortOptions = `${orderBy} ${sort}`;
const { image } = this.$route.params;
const params = {
requestPath: this.endpoint,
repoName: image,
limit: DEFAULT_PER_PAGE,
page: requestPage,
sort: sortOptions,
search: this.filterString,
};
getHarborArtifacts(params)
.then((res) => {
this.pageInfo = formatPagination(res.headers);
this.artifactsList = (res?.data || []).map((artifact) => {
return convertObjectPropsToCamelCase(artifact);
});
})
.catch(() => {
createAlert({ message: FETCH_ARTIFACT_LIST_ERROR_MESSAGE });
})
.finally(() => {
this.isLoading = false;
});
},
},
};
</script>
<template>
<div class="gl-my-3">
<details-header :images-detail="imagesDetail" />
<persisted-search
class="gl-mb-5"
:sortable-fields="$options.searchConfig.nameSortFields"
:default-order="$options.searchConfig.nameSortFields[0].orderBy"
default-sort="asc"
:tokens="$options.tokens"
@update="handleSearchUpdate"
/>
<tags-loader v-if="isLoading" />
<artifacts-list
v-else
:filter="filterString"
:is-loading="isLoading"
:artifacts="artifactsList"
:page-info="pageInfo"
@prev-page="fetchPrevPage"
@next-page="fetchNextPage"
/>
</div>
</template>