summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/repository/components/table
diff options
context:
space:
mode:
authorPhil Hughes <me@iamphill.com>2019-05-24 10:39:18 +0100
committerPhil Hughes <me@iamphill.com>2019-05-24 13:58:11 +0100
commitd8bb8d458c09146d70261026a5c90e97903b99c4 (patch)
tree5403eb594816cf2010aa213d1446d1fa871a6a4a /app/assets/javascripts/repository/components/table
parentc509b35b489ff69121c4760faa52d81e7666e9ca (diff)
downloadgitlab-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.vue103
-rw-r--r--app/assets/javascripts/repository/components/table/row.vue20
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>