Commit d0cef8ed authored by Ezekiel Kigbo's avatar Ezekiel Kigbo

Merge branch '257864-paginate-cluster-list' into 'master'

Add Pagination to Agent Cluster List

See merge request gitlab-org/gitlab!50713
parents 5f258c9e 02b58e50
<script> <script>
import { GlAlert, GlLoadingIcon } from '@gitlab/ui'; import { GlAlert, GlKeysetPagination, GlLoadingIcon } from '@gitlab/ui';
import AgentEmptyState from './agent_empty_state.vue'; import AgentEmptyState from './agent_empty_state.vue';
import AgentTable from './agent_table.vue'; import AgentTable from './agent_table.vue';
import getAgentsQuery from '../graphql/queries/get_agents.query.graphql'; import getAgentsQuery from '../graphql/queries/get_agents.query.graphql';
import { MAX_LIST_COUNT } from '../constants';
export default { export default {
apollo: { apollo: {
...@@ -12,13 +13,12 @@ export default { ...@@ -12,13 +13,12 @@ export default {
return { return {
defaultBranchName: this.defaultBranchName, defaultBranchName: this.defaultBranchName,
projectPath: this.projectPath, projectPath: this.projectPath,
...this.cursor,
}; };
}, },
update: (data) => { update(data) {
return { this.updateTreeList(data);
list: data?.project?.clusterAgents?.nodes, return data;
folders: data?.project?.repository?.tree?.trees?.nodes,
};
}, },
}, },
}, },
...@@ -26,6 +26,7 @@ export default { ...@@ -26,6 +26,7 @@ export default {
AgentEmptyState, AgentEmptyState,
AgentTable, AgentTable,
GlAlert, GlAlert,
GlKeysetPagination,
GlLoadingIcon, GlLoadingIcon,
}, },
props: { props: {
...@@ -43,23 +44,67 @@ export default { ...@@ -43,23 +44,67 @@ export default {
type: String, type: String,
}, },
}, },
data() {
return {
cursor: {
first: MAX_LIST_COUNT,
last: null,
},
folderList: {},
};
},
computed: { computed: {
isLoading() {
return this.$apollo.queries.agents.loading;
},
agentList() { agentList() {
let list = this.agents?.list; let list = this.agents?.project?.clusterAgents?.nodes;
const configFolders = this.agents?.folders;
if (list && configFolders) { if (list) {
list = list.map((agent) => { list = list.map((agent) => {
const configFolder = configFolders.find(({ name }) => name === agent.name); const configFolder = this.folderList[agent.name];
return { ...agent, configFolder }; return { ...agent, configFolder };
}); });
} }
return list; return list;
}, },
agentPageInfo() {
return this.agents?.project?.clusterAgents?.pageInfo || {};
},
isLoading() {
return this.$apollo.queries.agents.loading;
},
showPagination() {
return this.agentPageInfo.hasPreviousPage || this.agentPageInfo.hasNextPage;
},
treePageInfo() {
return this.agents?.project?.repository?.tree?.trees?.pageInfo || {};
},
},
methods: {
nextPage() {
this.cursor = {
first: MAX_LIST_COUNT,
last: null,
afterAgent: this.agentPageInfo.endCursor,
afterTree: this.treePageInfo.endCursor,
};
},
prevPage() {
this.cursor = {
first: null,
last: MAX_LIST_COUNT,
beforeAgent: this.agentPageInfo.startCursor,
beforeTree: this.treePageInfo.endCursor,
};
},
updateTreeList(data) {
const configFolders = data?.project?.repository?.tree?.trees?.nodes;
if (configFolders) {
configFolders.forEach((folder) => {
this.folderList[folder.name] = folder;
});
}
},
}, },
}; };
</script> </script>
...@@ -68,7 +113,13 @@ export default { ...@@ -68,7 +113,13 @@ export default {
<gl-loading-icon v-if="isLoading" size="md" class="gl-mt-3" /> <gl-loading-icon v-if="isLoading" size="md" class="gl-mt-3" />
<section v-else-if="agentList" class="gl-mt-3"> <section v-else-if="agentList" class="gl-mt-3">
<AgentTable v-if="agentList.length" :agents="agentList" /> <div v-if="agentList.length">
<AgentTable :agents="agentList" />
<div v-if="showPagination" class="gl-display-flex gl-justify-content-center gl-mt-5">
<gl-keyset-pagination v-bind="agentPageInfo" @prev="prevPage" @next="nextPage" />
</div>
</div>
<AgentEmptyState v-else :image="emptyStateImage" /> <AgentEmptyState v-else :image="emptyStateImage" />
</section> </section>
......
query getAgents($defaultBranchName: String!, $projectPath: ID!) { #import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
query getAgents(
$defaultBranchName: String!
$projectPath: ID!
$first: Int
$last: Int
$afterAgent: String
$afterTree: String
$beforeAgent: String
$beforeTree: String
) {
project(fullPath: $projectPath) { project(fullPath: $projectPath) {
clusterAgents { clusterAgents(first: $first, last: $last, before: $beforeAgent, after: $afterAgent) {
nodes { nodes {
id id
name name
} }
pageInfo {
...PageInfo
}
} }
repository { repository {
tree(path: ".gitlab/agents", ref: $defaultBranchName) { tree(path: ".gitlab/agents", ref: $defaultBranchName) {
trees { trees(first: $first, last: $last, after: $afterTree, before: $beforeTree) {
nodes { nodes {
name name
path path
webPath webPath
} }
pageInfo {
...PageInfo
}
} }
} }
} }
......
import Agents from './components/agents.vue'; import Agents from './components/agents.vue';
import createDefaultClient from '~/lib/graphql'; import createDefaultClient from '~/lib/graphql';
import getAgentsQuery from './graphql/queries/get_agents.query.graphql';
export default (Vue, VueApollo) => { export default (Vue, VueApollo) => {
const el = document.querySelector('#js-cluster-agents-list'); const el = document.querySelector('#js-cluster-agents-list');
...@@ -11,31 +10,6 @@ export default (Vue, VueApollo) => { ...@@ -11,31 +10,6 @@ export default (Vue, VueApollo) => {
const defaultClient = createDefaultClient(); const defaultClient = createDefaultClient();
defaultClient.cache.writeQuery({
query: getAgentsQuery,
/* eslint-disable @gitlab/require-i18n-strings */
data: {
project: {
__typename: 'Project',
clusterAgents: {
__typename: 'ClusterAgents',
nodes: [],
},
repository: {
__typename: 'Repository',
tree: {
__typename: 'Tree',
trees: {
__typename: 'Trees',
nodes: [],
},
},
},
},
},
});
const { emptyStateImage, defaultBranchName, projectPath } = el.dataset; const { emptyStateImage, defaultBranchName, projectPath } = el.dataset;
return new Vue({ return new Vue({
......
---
title: Add Pagination to Agent Cluster List
merge_request: 50713
author:
type: changed
import { GlAlert, GlLoadingIcon } from '@gitlab/ui'; import { GlAlert, GlKeysetPagination, GlLoadingIcon } from '@gitlab/ui';
import { createLocalVue, shallowMount } from '@vue/test-utils'; import { createLocalVue, shallowMount } from '@vue/test-utils';
import VueApollo from 'vue-apollo'; import VueApollo from 'vue-apollo';
import AgentEmptyState from 'ee/clusters_list/components/agent_empty_state.vue'; import AgentEmptyState from 'ee/clusters_list/components/agent_empty_state.vue';
...@@ -19,12 +19,12 @@ describe('Agents', () => { ...@@ -19,12 +19,12 @@ describe('Agents', () => {
projectPath: 'path/to/project', projectPath: 'path/to/project',
}; };
const createWrapper = ({ agents }) => { const createWrapper = ({ agents = [], pageInfo = null, trees = [] }) => {
const apolloQueryResponse = { const apolloQueryResponse = {
data: { data: {
project: { project: {
clusterAgents: { nodes: agents }, clusterAgents: { nodes: agents, pageInfo },
repository: { tree: { trees: { nodes: [] } } }, repository: { tree: { trees: { nodes: trees, pageInfo } } },
}, },
}, },
}; };
...@@ -42,6 +42,10 @@ describe('Agents', () => { ...@@ -42,6 +42,10 @@ describe('Agents', () => {
return wrapper.vm.$nextTick(); return wrapper.vm.$nextTick();
}; };
const findAgentTable = () => wrapper.find(AgentTable);
const findEmptyState = () => wrapper.find(AgentEmptyState);
const findPaginationButtons = () => wrapper.find(GlKeysetPagination);
afterEach(() => { afterEach(() => {
if (wrapper) { if (wrapper) {
wrapper.destroy(); wrapper.destroy();
...@@ -61,13 +65,64 @@ describe('Agents', () => { ...@@ -61,13 +65,64 @@ describe('Agents', () => {
}, },
]; ];
const trees = [
{
name: 'agent-2',
path: '.gitlab/agents/agent-2',
webPath: '/project/path/.gitlab/agents/agent-2',
},
];
beforeEach(() => { beforeEach(() => {
return createWrapper({ agents }); return createWrapper({ agents, trees });
}); });
it('should render agent table', () => { it('should render agent table', () => {
expect(wrapper.find(AgentTable).exists()).toBe(true); expect(findAgentTable().exists()).toBe(true);
expect(wrapper.find(AgentEmptyState).exists()).toBe(false); expect(findEmptyState().exists()).toBe(false);
});
it('should pass agent and folder info to table component', () => {
expect(findAgentTable().props('agents')).toEqual([
{ id: '1', name: 'agent-1', configFolder: undefined },
{
id: '2',
name: 'agent-2',
configFolder: {
name: 'agent-2',
path: '.gitlab/agents/agent-2',
webPath: '/project/path/.gitlab/agents/agent-2',
},
},
]);
});
it('should not render pagination buttons when there are no additional pages', () => {
expect(findPaginationButtons().exists()).toBe(false);
});
describe('when the list has additional pages', () => {
const pageInfo = {
hasNextPage: true,
hasPreviousPage: false,
startCursor: 'prev',
endCursor: 'next',
};
beforeEach(() => {
return createWrapper({
agents,
pageInfo,
});
});
it('should render pagination buttons', () => {
expect(findPaginationButtons().exists()).toBe(true);
});
it('should pass pageInfo to the pagination component', () => {
expect(findPaginationButtons().props()).toMatchObject(pageInfo);
});
}); });
}); });
...@@ -77,8 +132,8 @@ describe('Agents', () => { ...@@ -77,8 +132,8 @@ describe('Agents', () => {
}); });
it('should render empty state', () => { it('should render empty state', () => {
expect(wrapper.find(AgentTable).exists()).toBe(false); expect(findAgentTable().exists()).toBe(false);
expect(wrapper.find(AgentEmptyState).exists()).toBe(true); expect(findEmptyState().exists()).toBe(true);
}); });
}); });
......
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