Commit 83f24355 authored by Jose Ivan Vargas's avatar Jose Ivan Vargas

Merge branch '334140-limit-tree-entries' into 'master'

Use paginated tree query for retrieving repository files

See merge request gitlab-org/gitlab!69274
parents 9ddea6ee d6147dba
...@@ -100,9 +100,9 @@ export default { ...@@ -100,9 +100,9 @@ export default {
/> />
<template v-for="val in entries"> <template v-for="val in entries">
<table-row <table-row
v-for="entry in val" v-for="(entry, index) in val"
:id="entry.id" :id="entry.id"
:key="`${entry.flatPath}-${entry.id}`" :key="`${entry.flatPath}-${entry.id}-${index}`"
:sha="entry.sha" :sha="entry.sha"
:project-path="projectPath" :project-path="projectPath"
:current-path="path" :current-path="path"
......
...@@ -10,6 +10,7 @@ import { ...@@ -10,6 +10,7 @@ import {
} from '@gitlab/ui'; } from '@gitlab/ui';
import { escapeRegExp } from 'lodash'; import { escapeRegExp } from 'lodash';
import filesQuery from 'shared_queries/repository/files.query.graphql'; import filesQuery from 'shared_queries/repository/files.query.graphql';
import paginatedTreeQuery from 'shared_queries/repository/paginated_tree.query.graphql';
import { escapeFileUrl } from '~/lib/utils/url_utility'; import { escapeFileUrl } from '~/lib/utils/url_utility';
import { TREE_PAGE_SIZE } from '~/repository/constants'; import { TREE_PAGE_SIZE } from '~/repository/constants';
import FileIcon from '~/vue_shared/components/file_icon.vue'; import FileIcon from '~/vue_shared/components/file_icon.vue';
...@@ -153,7 +154,8 @@ export default { ...@@ -153,7 +154,8 @@ export default {
return this.isFolder ? this.loadFolder() : this.loadBlob(); return this.isFolder ? this.loadFolder() : this.loadBlob();
}, },
loadFolder() { loadFolder() {
this.apolloQuery(filesQuery, { const query = this.glFeatures.paginatedTreeGraphqlQuery ? paginatedTreeQuery : filesQuery;
this.apolloQuery(query, {
projectPath: this.projectPath, projectPath: this.projectPath,
ref: this.ref, ref: this.ref,
path: this.path, path: this.path,
......
<script> <script>
import filesQuery from 'shared_queries/repository/files.query.graphql'; import filesQuery from 'shared_queries/repository/files.query.graphql';
import paginatedTreeQuery from 'shared_queries/repository/paginated_tree.query.graphql';
import createFlash from '~/flash'; import createFlash from '~/flash';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { __ } from '../../locale'; import { __ } from '../../locale';
...@@ -69,6 +70,9 @@ export default { ...@@ -69,6 +70,9 @@ export default {
hasShowMore() { hasShowMore() {
return !this.clickedShowMore && this.pageLimitReached; return !this.clickedShowMore && this.pageLimitReached;
}, },
paginatedTreeEnabled() {
return this.glFeatures.paginatedTreeGraphqlQuery;
},
}, },
watch: { watch: {
...@@ -91,7 +95,7 @@ export default { ...@@ -91,7 +95,7 @@ export default {
return this.$apollo return this.$apollo
.query({ .query({
query: filesQuery, query: this.paginatedTreeEnabled ? paginatedTreeQuery : filesQuery,
variables: { variables: {
projectPath: this.projectPath, projectPath: this.projectPath,
ref: this.ref, ref: this.ref,
...@@ -104,13 +108,20 @@ export default { ...@@ -104,13 +108,20 @@ export default {
if (data.errors) throw data.errors; if (data.errors) throw data.errors;
if (!data?.project?.repository || originalPath !== (this.path || '/')) return; if (!data?.project?.repository || originalPath !== (this.path || '/')) return;
const pageInfo = this.hasNextPage(data.project.repository.tree); const pageInfo = this.paginatedTreeEnabled
? data.project.repository.paginatedTree.pageInfo
: this.hasNextPage(data.project.repository.tree);
this.isLoadingFiles = false; this.isLoadingFiles = false;
this.entries = Object.keys(this.entries).reduce( this.entries = Object.keys(this.entries).reduce(
(acc, key) => ({ (acc, key) => ({
...acc, ...acc,
[key]: this.normalizeData(key, data.project.repository.tree[key].edges), [key]: this.normalizeData(
key,
this.paginatedTreeEnabled
? data.project.repository.paginatedTree.nodes[0][key]
: data.project.repository.tree[key].edges,
),
}), }),
{}, {},
); );
...@@ -132,7 +143,9 @@ export default { ...@@ -132,7 +143,9 @@ export default {
}); });
}, },
normalizeData(key, data) { normalizeData(key, data) {
return this.entries[key].concat(data.map(({ node }) => node)); return this.entries[key].concat(
this.paginatedTreeEnabled ? data.nodes : data.map(({ node }) => node),
);
}, },
hasNextPage(data) { hasNextPage(data) {
return [] return []
......
import filesQuery from 'shared_queries/repository/files.query.graphql'; import filesQuery from 'shared_queries/repository/files.query.graphql';
import paginatedTreeQuery from 'shared_queries/repository/paginated_tree.query.graphql';
import projectPathQuery from '../queries/project_path.query.graphql'; import projectPathQuery from '../queries/project_path.query.graphql';
import getRefMixin from './get_ref'; import getRefMixin from './get_ref';
...@@ -21,7 +22,7 @@ export default { ...@@ -21,7 +22,7 @@ export default {
return this.$apollo return this.$apollo
.query({ .query({
query: filesQuery, query: gon.features.paginatedTreeGraphqlQuery ? paginatedTreeQuery : filesQuery,
variables: { variables: {
projectPath: this.projectPath, projectPath: this.projectPath,
ref: this.ref, ref: this.ref,
......
...@@ -15,6 +15,10 @@ class Projects::TreeController < Projects::ApplicationController ...@@ -15,6 +15,10 @@ class Projects::TreeController < Projects::ApplicationController
before_action :authorize_download_code! before_action :authorize_download_code!
before_action :authorize_edit_tree!, only: [:create_dir] before_action :authorize_edit_tree!, only: [:create_dir]
before_action do
push_frontend_feature_flag(:paginated_tree_graphql_query, @project, default_enabled: :yaml)
end
feature_category :source_code_management feature_category :source_code_management
def show def show
......
...@@ -34,6 +34,7 @@ class ProjectsController < Projects::ApplicationController ...@@ -34,6 +34,7 @@ class ProjectsController < Projects::ApplicationController
before_action do before_action do
push_frontend_feature_flag(:refactor_blob_viewer, @project, default_enabled: :yaml) push_frontend_feature_flag(:refactor_blob_viewer, @project, default_enabled: :yaml)
push_frontend_feature_flag(:increase_page_size_exponentially, @project, default_enabled: :yaml) push_frontend_feature_flag(:increase_page_size_exponentially, @project, default_enabled: :yaml)
push_frontend_feature_flag(:paginated_tree_graphql_query, @project, default_enabled: :yaml)
end end
layout :determine_layout layout :determine_layout
......
fragment TreeEntry on Entry {
__typename
id
sha
name
flatPath
type
}
query getPaginatedTree($projectPath: ID!, $path: String, $ref: String!, $nextPageCursor: String) {
project(fullPath: $projectPath) {
id
__typename
repository {
__typename
paginatedTree(path: $path, ref: $ref, after: $nextPageCursor) {
__typename
pageInfo {
__typename
endCursor
startCursor
hasNextPage
}
nodes {
__typename
trees {
__typename
nodes {
...TreeEntry
webPath
}
}
submodules {
__typename
nodes {
...TreeEntry
webUrl
treeUrl
}
}
blobs {
__typename
nodes {
...TreeEntry
mode
webPath
lfsOid
}
}
}
}
}
}
}
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import filesQuery from 'shared_queries/repository/files.query.graphql'; import paginatedTreeQuery from 'shared_queries/repository/paginated_tree.query.graphql';
import FilePreview from '~/repository/components/preview/index.vue'; import FilePreview from '~/repository/components/preview/index.vue';
import FileTable from '~/repository/components/table/index.vue'; import FileTable from '~/repository/components/table/index.vue';
import TreeContent from '~/repository/components/tree_content.vue'; import TreeContent from '~/repository/components/tree_content.vue';
...@@ -22,6 +22,7 @@ function factory(path, data = () => ({})) { ...@@ -22,6 +22,7 @@ function factory(path, data = () => ({})) {
provide: { provide: {
glFeatures: { glFeatures: {
increasePageSizeExponentially: true, increasePageSizeExponentially: true,
paginatedTreeGraphqlQuery: true,
}, },
}, },
}); });
...@@ -58,7 +59,7 @@ describe('Repository table component', () => { ...@@ -58,7 +59,7 @@ describe('Repository table component', () => {
it('normalizes edge nodes', () => { it('normalizes edge nodes', () => {
factory('/'); factory('/');
const output = vm.vm.normalizeData('blobs', [{ node: '1' }, { node: '2' }]); const output = vm.vm.normalizeData('blobs', { nodes: ['1', '2'] });
expect(output).toEqual(['1', '2']); expect(output).toEqual(['1', '2']);
}); });
...@@ -168,7 +169,7 @@ describe('Repository table component', () => { ...@@ -168,7 +169,7 @@ describe('Repository table component', () => {
vm.vm.fetchFiles(); vm.vm.fetchFiles();
expect($apollo.query).toHaveBeenCalledWith({ expect($apollo.query).toHaveBeenCalledWith({
query: filesQuery, query: paginatedTreeQuery,
variables: { variables: {
pageSize, pageSize,
nextPageCursor: '', nextPageCursor: '',
......
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