summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/registry/explorer/pages/list.vue
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/registry/explorer/pages/list.vue')
-rw-r--r--app/assets/javascripts/registry/explorer/pages/list.vue138
1 files changed, 94 insertions, 44 deletions
diff --git a/app/assets/javascripts/registry/explorer/pages/list.vue b/app/assets/javascripts/registry/explorer/pages/list.vue
index 3192ba82db8..336a997d629 100644
--- a/app/assets/javascripts/registry/explorer/pages/list.vue
+++ b/app/assets/javascripts/registry/explorer/pages/list.vue
@@ -9,17 +9,13 @@ import {
GlSkeletonLoader,
GlSearchBoxByClick,
} from '@gitlab/ui';
+import { get } from 'lodash';
+import getContainerRepositoriesQuery from 'shared_queries/container_registry/get_container_repositories.query.graphql';
import Tracking from '~/tracking';
import createFlash from '~/flash';
-
-import ProjectEmptyState from '../components/list_page/project_empty_state.vue';
-import GroupEmptyState from '../components/list_page/group_empty_state.vue';
import RegistryHeader from '../components/list_page/registry_header.vue';
-import ImageList from '../components/list_page/image_list.vue';
-import CliCommands from '../components/list_page/cli_commands.vue';
-import getProjectContainerRepositoriesQuery from '../graphql/queries/get_project_container_repositories.query.graphql';
-import getGroupContainerRepositoriesQuery from '../graphql/queries/get_group_container_repositories.query.graphql';
+import getContainerRepositoriesDetails from '../graphql/queries/get_container_repositories_details.query.graphql';
import deleteContainerRepositoryMutation from '../graphql/mutations/delete_container_repository.mutation.graphql';
import {
@@ -38,12 +34,25 @@ import {
} from '../constants/index';
export default {
- name: 'RegistryListApp',
+ name: 'RegistryListPage',
components: {
GlEmptyState,
- ProjectEmptyState,
- GroupEmptyState,
- ImageList,
+ ProjectEmptyState: () =>
+ import(
+ /* webpackChunkName: 'container_registry_components' */ '../components/list_page/project_empty_state.vue'
+ ),
+ GroupEmptyState: () =>
+ import(
+ /* webpackChunkName: 'container_registry_components' */ '../components/list_page/group_empty_state.vue'
+ ),
+ ImageList: () =>
+ import(
+ /* webpackChunkName: 'container_registry_components' */ '../components/list_page/image_list.vue'
+ ),
+ CliCommands: () =>
+ import(
+ /* webpackChunkName: 'container_registry_components' */ '../components/list_page/cli_commands.vue'
+ ),
GlModal,
GlSprintf,
GlLink,
@@ -51,13 +60,12 @@ export default {
GlSkeletonLoader,
GlSearchBoxByClick,
RegistryHeader,
- CliCommands,
},
- inject: ['config'],
directives: {
GlTooltip: GlTooltipDirective,
},
mixins: [Tracking.mixin()],
+ inject: ['config'],
loader: {
repeat: 10,
width: 1000,
@@ -74,10 +82,8 @@ export default {
EMPTY_RESULT_MESSAGE,
},
apollo: {
- images: {
- query() {
- return this.graphQlQuery;
- },
+ baseImages: {
+ query: getContainerRepositoriesQuery,
variables() {
return this.queryVariables;
},
@@ -92,10 +98,26 @@ export default {
createFlash({ message: FETCH_IMAGES_LIST_ERROR_MESSAGE });
},
},
+ additionalDetails: {
+ skip() {
+ return !this.fetchAdditionalDetails;
+ },
+ query: getContainerRepositoriesDetails,
+ variables() {
+ return this.queryVariables;
+ },
+ update(data) {
+ return data[this.graphqlResource]?.containerRepositories.nodes;
+ },
+ error() {
+ createFlash({ message: FETCH_IMAGES_LIST_ERROR_MESSAGE });
+ },
+ },
},
data() {
return {
- images: [],
+ baseImages: [],
+ additionalDetails: [],
pageInfo: {},
containerRepositoriesCount: 0,
itemToDelete: {},
@@ -103,21 +125,24 @@ export default {
searchValue: null,
name: null,
mutationLoading: false,
+ fetchAdditionalDetails: false,
};
},
computed: {
+ images() {
+ return this.baseImages.map((image, index) => ({
+ ...image,
+ ...get(this.additionalDetails, index, {}),
+ }));
+ },
graphqlResource() {
return this.config.isGroupPage ? 'group' : 'project';
},
- graphQlQuery() {
- return this.config.isGroupPage
- ? getGroupContainerRepositoriesQuery
- : getProjectContainerRepositoriesQuery;
- },
queryVariables() {
return {
name: this.name,
fullPath: this.config.isGroupPage ? this.config.groupPath : this.config.projectPath,
+ isGroupPage: this.config.isGroupPage,
first: GRAPHQL_PAGE_SIZE,
};
},
@@ -127,7 +152,7 @@ export default {
};
},
isLoading() {
- return this.$apollo.queries.images.loading || this.mutationLoading;
+ return this.$apollo.queries.baseImages.loading || this.mutationLoading;
},
showCommands() {
return Boolean(!this.isLoading && !this.config?.isGroupPage && this.images?.length);
@@ -141,6 +166,13 @@ export default {
: DELETE_IMAGE_ERROR_MESSAGE;
},
},
+ mounted() {
+ // If the two graphql calls - which are not batched - resolve togheter we will have a race
+ // condition when apollo sets the cache, with this we give the 'base' call an headstart
+ setTimeout(() => {
+ this.fetchAdditionalDetails = true;
+ }, 200);
+ },
methods: {
deleteImage(item) {
this.track('click_button');
@@ -175,30 +207,46 @@ export default {
this.deleteAlertType = null;
this.itemToDelete = {};
},
- fetchNextPage() {
+ updateQuery(_, { fetchMoreResult }) {
+ return fetchMoreResult;
+ },
+ async fetchNextPage() {
if (this.pageInfo?.hasNextPage) {
- this.$apollo.queries.images.fetchMore({
- variables: {
- after: this.pageInfo?.endCursor,
- first: GRAPHQL_PAGE_SIZE,
- },
- updateQuery(previousResult, { fetchMoreResult }) {
- return fetchMoreResult;
- },
+ const variables = {
+ after: this.pageInfo?.endCursor,
+ first: GRAPHQL_PAGE_SIZE,
+ };
+
+ this.$apollo.queries.baseImages.fetchMore({
+ variables,
+ updateQuery: this.updateQuery,
+ });
+
+ await this.$nextTick();
+
+ this.$apollo.queries.additionalDetails.fetchMore({
+ variables,
+ updateQuery: this.updateQuery,
});
}
},
- fetchPreviousPage() {
+ async fetchPreviousPage() {
if (this.pageInfo?.hasPreviousPage) {
- this.$apollo.queries.images.fetchMore({
- variables: {
- first: null,
- before: this.pageInfo?.startCursor,
- last: GRAPHQL_PAGE_SIZE,
- },
- updateQuery(previousResult, { fetchMoreResult }) {
- return fetchMoreResult;
- },
+ const variables = {
+ first: null,
+ before: this.pageInfo?.startCursor,
+ last: GRAPHQL_PAGE_SIZE,
+ };
+ this.$apollo.queries.baseImages.fetchMore({
+ variables,
+ updateQuery: this.updateQuery,
+ });
+
+ await this.$nextTick();
+
+ this.$apollo.queries.additionalDetails.fetchMore({
+ variables,
+ updateQuery: this.updateQuery,
});
}
},
@@ -230,7 +278,7 @@ export default {
<template #description>
<p>
<gl-sprintf :message="$options.i18n.CONNECTION_ERROR_MESSAGE">
- <template #docLink="{content}">
+ <template #docLink="{ content }">
<gl-link :href="`${config.helpPagePath}#docker-connection-error`" target="_blank">
{{ content }}
</gl-link>
@@ -242,6 +290,7 @@ export default {
<template v-else>
<registry-header
+ :metadata-loading="isLoading"
:images-count="containerRepositoriesCount"
:expiration-policy="config.expirationPolicy"
:help-page-path="config.helpPagePath"
@@ -285,6 +334,7 @@ export default {
<image-list
v-if="images.length"
:images="images"
+ :metadata-loading="$apollo.queries.additionalDetails.loading"
:page-info="pageInfo"
@delete="deleteImage"
@prev-page="fetchPreviousPage"