146 lines
3.8 KiB
Vue
146 lines
3.8 KiB
Vue
<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';
|
|
import ParentRow from './parent_row.vue';
|
|
|
|
const PAGE_SIZE = 100;
|
|
|
|
export default {
|
|
components: {
|
|
GlLoadingIcon,
|
|
TableHeader,
|
|
TableRow,
|
|
ParentRow,
|
|
},
|
|
mixins: [getRefMixin],
|
|
apollo: {
|
|
projectPath: {
|
|
query: getProjectPath,
|
|
},
|
|
},
|
|
props: {
|
|
path: {
|
|
type: String,
|
|
required: true,
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
projectPath: '',
|
|
nextPageCursor: '',
|
|
entries: {
|
|
trees: [],
|
|
submodules: [],
|
|
blobs: [],
|
|
},
|
|
isLoadingFiles: false,
|
|
};
|
|
},
|
|
computed: {
|
|
tableCaption() {
|
|
return sprintf(
|
|
__('Files, directories, and submodules in the path %{path} for commit reference %{ref}'),
|
|
{ path: this.path, ref: this.ref },
|
|
);
|
|
},
|
|
showParentRow() {
|
|
return !this.isLoadingFiles && ['', '/'].indexOf(this.path) === -1;
|
|
},
|
|
},
|
|
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 occurred 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);
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<div class="tree-content-holder">
|
|
<div class="table-holder bordered-box">
|
|
<table class="table tree-table qa-file-tree" aria-live="polite">
|
|
<caption class="sr-only">
|
|
{{
|
|
tableCaption
|
|
}}
|
|
</caption>
|
|
<table-header v-once />
|
|
<tbody>
|
|
<parent-row v-show="showParentRow" :commit-ref="ref" :path="path" />
|
|
<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"
|
|
:url="entry.webUrl"
|
|
:lfs-oid="entry.lfsOid"
|
|
/>
|
|
</template>
|
|
</tbody>
|
|
</table>
|
|
<gl-loading-icon v-show="isLoadingFiles" class="my-3" size="md" />
|
|
</div>
|
|
</div>
|
|
</template>
|