diff options
author | Phil Hughes <me@iamphill.com> | 2019-05-24 10:39:18 +0100 |
---|---|---|
committer | Phil Hughes <me@iamphill.com> | 2019-05-24 13:58:11 +0100 |
commit | d8bb8d458c09146d70261026a5c90e97903b99c4 (patch) | |
tree | 5403eb594816cf2010aa213d1446d1fa871a6a4a /app/assets/javascripts/repository/components/table | |
parent | c509b35b489ff69121c4760faa52d81e7666e9ca (diff) | |
download | gitlab-ce-d8bb8d458c09146d70261026a5c90e97903b99c4.tar.gz |
Pull files for repository tree from GraphQL API
Diffstat (limited to 'app/assets/javascripts/repository/components/table')
-rw-r--r-- | app/assets/javascripts/repository/components/table/index.vue | 103 | ||||
-rw-r--r-- | app/assets/javascripts/repository/components/table/row.vue | 20 |
2 files changed, 99 insertions, 24 deletions
diff --git a/app/assets/javascripts/repository/components/table/index.vue b/app/assets/javascripts/repository/components/table/index.vue index ad3d8f9329d..758f4b88be2 100644 --- a/app/assets/javascripts/repository/components/table/index.vue +++ b/app/assets/javascripts/repository/components/table/index.vue @@ -1,11 +1,15 @@ <script> import { GlLoadingIcon } from '@gitlab/ui'; +import createFlash from '~/flash'; import { sprintf, __ } from '../../../locale'; import getRefMixin from '../../mixins/get_ref'; import getFiles from '../../queries/getFiles.graphql'; +import getProjectPath from '../../queries/getProjectPath.graphql'; import TableHeader from './header.vue'; import TableRow from './row.vue'; +const PAGE_SIZE = 100; + export default { components: { GlLoadingIcon, @@ -14,14 +18,8 @@ export default { }, mixins: [getRefMixin], apollo: { - files: { - query: getFiles, - variables() { - return { - ref: this.ref, - path: this.path, - }; - }, + projectPath: { + query: getProjectPath, }, }, props: { @@ -32,7 +30,14 @@ export default { }, data() { return { - files: [], + projectPath: '', + nextPageCursor: '', + entries: { + trees: [], + submodules: [], + blobs: [], + }, + isLoadingFiles: false, }; }, computed: { @@ -42,8 +47,63 @@ export default { { path: this.path, ref: this.ref }, ); }, - isLoadingFiles() { - return this.$apollo.queries.files.loading; + }, + watch: { + $route: function routeChange() { + this.entries.trees = []; + this.entries.submodules = []; + this.entries.blobs = []; + this.nextPageCursor = ''; + this.fetchFiles(); + }, + }, + mounted() { + // We need to wait for `ref` and `projectPath` to be set + this.$nextTick(() => this.fetchFiles()); + }, + methods: { + fetchFiles() { + this.isLoadingFiles = true; + + return this.$apollo + .query({ + query: getFiles, + variables: { + projectPath: this.projectPath, + ref: this.ref, + path: this.path, + nextPageCursor: this.nextPageCursor, + pageSize: PAGE_SIZE, + }, + }) + .then(({ data }) => { + if (!data) return; + + const pageInfo = this.hasNextPage(data.project.repository.tree); + + this.isLoadingFiles = false; + this.entries = Object.keys(this.entries).reduce( + (acc, key) => ({ + ...acc, + [key]: this.normalizeData(key, data.project.repository.tree[key].edges), + }), + {}, + ); + + if (pageInfo && pageInfo.hasNextPage) { + this.nextPageCursor = pageInfo.endCursor; + this.fetchFiles(); + } + }) + .catch(() => createFlash(__('An error occurding while fetching folder content.'))); + }, + normalizeData(key, data) { + return this.entries[key].concat(data.map(({ node }) => node)); + }, + hasNextPage(data) { + return [] + .concat(data.trees.pageInfo, data.submodules.pageInfo, data.blobs.pageInfo) + .find(({ hasNextPage }) => hasNextPage); }, }, }; @@ -58,18 +118,21 @@ export default { tableCaption }} </caption> - <table-header /> + <table-header v-once /> <tbody> - <table-row - v-for="entry in files" - :id="entry.id" - :key="entry.id" - :path="entry.flatPath" - :type="entry.type" - /> + <template v-for="val in entries"> + <table-row + v-for="entry in val" + :id="entry.id" + :key="`${entry.flatPath}-${entry.id}`" + :current-path="path" + :path="entry.flatPath" + :type="entry.type" + /> + </template> </tbody> </table> - <gl-loading-icon v-if="isLoadingFiles" class="my-3" size="md" /> + <gl-loading-icon v-show="isLoadingFiles" class="my-3" size="md" /> </div> </div> </template> diff --git a/app/assets/javascripts/repository/components/table/row.vue b/app/assets/javascripts/repository/components/table/row.vue index 0ad0fdbd605..9a264bef87e 100644 --- a/app/assets/javascripts/repository/components/table/row.vue +++ b/app/assets/javascripts/repository/components/table/row.vue @@ -6,7 +6,11 @@ export default { mixins: [getRefMixin], props: { id: { - type: Number, + type: String, + required: true, + }, + currentPath: { + type: String, required: true, }, path: { @@ -26,7 +30,7 @@ export default { return `fa-${getIconName(this.type, this.path)}`; }, isFolder() { - return this.type === 'folder'; + return this.type === 'tree'; }, isSubmodule() { return this.type === 'commit'; @@ -34,6 +38,12 @@ export default { linkComponent() { return this.isFolder ? 'router-link' : 'a'; }, + fullPath() { + return this.path.replace(new RegExp(`^${this.currentPath}/`), ''); + }, + shortSha() { + return this.id.slice(0, 8); + }, }, methods: { openRow() { @@ -49,9 +59,11 @@ export default { <tr v-once :class="`file_${id}`" class="tree-item" @click="openRow"> <td class="tree-item-file-name"> <i :aria-label="type" role="img" :class="iconName" class="fa fa-fw"></i> - <component :is="linkComponent" :to="routerLinkTo" class="str-truncated">{{ path }}</component> + <component :is="linkComponent" :to="routerLinkTo" class="str-truncated"> + {{ fullPath }} + </component> <template v-if="isSubmodule"> - @ <a href="#" class="commit-sha">{{ id }}</a> + @ <a href="#" class="commit-sha">{{ shortSha }}</a> </template> </td> <td class="d-none d-sm-table-cell tree-commit"></td> |