Commit ed0a62df authored by Emily Ring's avatar Emily Ring Committed by Brandon Labuschagne

Add pagination to agent token table

Update clusters/agents vues and GraphQl to include pagination
parent 0d347294
<script>
import { GlAlert, GlBadge, GlLoadingIcon, GlSprintf, GlTab, GlTabs } from '@gitlab/ui';
import {
GlAlert,
GlBadge,
GlKeysetPagination,
GlLoadingIcon,
GlSprintf,
GlTab,
GlTabs,
} from '@gitlab/ui';
import { s__ } from '~/locale';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import { MAX_LIST_COUNT } from '../constants';
import getClusterAgentQuery from '../graphql/queries/get_cluster_agent.query.graphql';
import TokenTable from './token_table.vue';
......@@ -19,6 +28,7 @@ export default {
return {
agentName: this.agentName,
projectPath: this.projectPath,
...this.cursor,
};
},
update: (data) => data?.project?.clusterAgent,
......@@ -30,6 +40,7 @@ export default {
components: {
GlAlert,
GlBadge,
GlKeysetPagination,
GlLoadingIcon,
GlSprintf,
GlTab,
......@@ -47,6 +58,14 @@ export default {
type: String,
},
},
data() {
return {
cursor: {
first: MAX_LIST_COUNT,
last: null,
},
};
},
computed: {
createdAt() {
return this.clusterAgent?.createdAt;
......@@ -57,13 +76,35 @@ export default {
isLoading() {
return this.$apollo.queries.clusterAgent.loading;
},
showPagination() {
return this.tokenPageInfo.hasPreviousPage || this.tokenPageInfo.hasNextPage;
},
tokenCount() {
return this.clusterAgent?.tokens?.count;
},
tokenPageInfo() {
return this.clusterAgent?.tokens?.pageInfo || {};
},
tokens() {
return this.clusterAgent?.tokens?.nodes || [];
},
},
methods: {
nextPage() {
this.cursor = {
first: MAX_LIST_COUNT,
last: null,
afterToken: this.tokenPageInfo.endCursor,
};
},
prevPage() {
this.cursor = {
first: null,
last: MAX_LIST_COUNT,
beforeToken: this.tokenPageInfo.startCursor,
};
},
},
};
</script>
......@@ -71,7 +112,7 @@ export default {
<section>
<h2>{{ agentName }}</h2>
<gl-loading-icon v-if="isLoading" size="lg" class="gl-m-3" />
<gl-loading-icon v-if="isLoading && clusterAgent == null" size="lg" class="gl-m-3" />
<div v-else-if="clusterAgent">
<p data-testid="cluster-agent-create-info">
......@@ -98,7 +139,15 @@ export default {
</span>
</template>
<TokenTable :tokens="tokens" />
<gl-loading-icon v-if="isLoading" size="md" class="gl-m-3" />
<div v-else>
<TokenTable :tokens="tokens" />
<div v-if="showPagination" class="gl-display-flex gl-justify-content-center gl-mt-5">
<gl-keyset-pagination v-bind="tokenPageInfo" @prev="prevPage" @next="nextPage" />
</div>
</div>
</gl-tab>
</gl-tabs>
</div>
......
#import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
#import "../fragments/cluster_agent_token.fragment.graphql"
query getClusterAgent($projectPath: ID!, $agentName: String!) {
query getClusterAgent(
$projectPath: ID!
$agentName: String!
$first: Int
$last: Int
$afterToken: String
$beforeToken: String
) {
project(fullPath: $projectPath) {
clusterAgent(name: $agentName) {
id
......@@ -10,12 +18,16 @@ query getClusterAgent($projectPath: ID!, $agentName: String!) {
name
}
tokens {
tokens(first: $first, last: $last, before: $beforeToken, after: $afterToken) {
count
nodes {
...Token
}
pageInfo {
...PageInfo
}
}
}
}
......
---
title: Add pagination to agent token table
merge_request: 55788
author:
type: changed
import { GlAlert, GlLoadingIcon, GlSprintf } from '@gitlab/ui';
import { GlAlert, GlKeysetPagination, GlLoadingIcon, GlSprintf } from '@gitlab/ui';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import ClusterAgentShow from 'ee/clusters/agents/components/show.vue';
......@@ -31,6 +31,7 @@ describe('ClusterAgentShow', () => {
tokens: {
count: 1,
nodes: [],
pageInfo: null,
},
};
......@@ -47,23 +48,50 @@ describe('ClusterAgentShow', () => {
});
};
const createWrapperWithoutApollo = ({ clusterAgent, loading = false }) => {
const $apollo = { queries: { clusterAgent: { loading } } };
wrapper = shallowMount(ClusterAgentShow, {
propsData,
mocks: { $apollo, clusterAgent },
});
};
const findCreatedText = () => wrapper.find('[data-testid="cluster-agent-create-info"]').text();
const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
const findPaginationButtons = () => wrapper.find(GlKeysetPagination);
const findTokenCount = () => wrapper.find('[data-testid="cluster-agent-token-count"]').text();
beforeEach(() => {
return createWrapper({ clusterAgent: defaultClusterAgent });
});
afterEach(() => {
wrapper.destroy();
});
it('displays the agent name', () => {
expect(wrapper.text()).toContain(propsData.agentName);
});
describe('default behaviour', () => {
beforeEach(() => {
return createWrapper({ clusterAgent: defaultClusterAgent });
});
it('displays the agent name', () => {
expect(wrapper.text()).toContain(propsData.agentName);
});
it('displays agent create information', () => {
expect(findCreatedText()).toMatchInterpolatedText('Created by user-1 2 days ago');
});
it('displays agent create information', () => {
expect(findCreatedText()).toMatchInterpolatedText('Created by user-1 2 days ago');
it('displays token count', () => {
expect(findTokenCount()).toMatchInterpolatedText(
`${ClusterAgentShow.i18n.tokens} ${defaultClusterAgent.tokens.count}`,
);
});
it('renders token table', () => {
expect(wrapper.find(TokenTable).exists()).toBe(true);
});
it('should not render pagination buttons when there are no additional pages', () => {
expect(findPaginationButtons().exists()).toBe(false);
});
});
describe('when create user is unknown', () => {
......@@ -81,12 +109,6 @@ describe('ClusterAgentShow', () => {
});
});
it('displays token count', () => {
expect(findTokenCount()).toMatchInterpolatedText(
`${ClusterAgentShow.i18n.tokens} ${defaultClusterAgent.tokens.count}`,
);
});
describe('when token count is missing', () => {
const missingTokens = {
...defaultClusterAgent,
......@@ -102,20 +124,59 @@ describe('ClusterAgentShow', () => {
});
});
it('renders token table', () => {
expect(wrapper.find(TokenTable).exists()).toBe(true);
describe('when the token list has additional pages', () => {
const pageInfo = {
hasNextPage: true,
hasPreviousPage: false,
startCursor: 'prev',
endCursor: 'next',
};
const tokenPagination = {
...defaultClusterAgent,
tokens: {
...defaultClusterAgent.tokens,
pageInfo,
},
};
beforeEach(() => {
return createWrapper({ clusterAgent: tokenPagination });
});
it('should render pagination buttons', () => {
expect(findPaginationButtons().exists()).toBe(true);
});
it('should pass pageInfo to the pagination component', () => {
expect(findPaginationButtons().props()).toMatchObject(pageInfo);
});
});
describe('when the agent query is loading', () => {
beforeEach(() => {
return createWrapper({
clusterAgent: null,
queryResponse: jest.fn().mockReturnValue(new Promise(() => {})),
describe('when the clusterAgent is missing', () => {
beforeEach(() => {
return createWrapper({
clusterAgent: null,
queryResponse: jest.fn().mockReturnValue(new Promise(() => {})),
});
});
it('displays a loading icon and hides the token tab', () => {
expect(findLoadingIcon().exists()).toBe(true);
expect(wrapper.text()).not.toContain(ClusterAgentShow.i18n.tokens);
});
});
it('displays a loading icon', () => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
describe('when the clusterAgent is present', () => {
beforeEach(() => {
createWrapperWithoutApollo({ clusterAgent: defaultClusterAgent, loading: true });
});
it('displays a loading icon and token tab', () => {
expect(findLoadingIcon().exists()).toBe(true);
expect(wrapper.text()).toContain(ClusterAgentShow.i18n.tokens);
});
});
});
......
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