index.vue 4.4 KB
Newer Older
1
<script>
2
import { GlSkeletonLoading } from '@gitlab/ui';
3
import createFlash from '~/flash';
4 5
import { sprintf, __ } from '../../../locale';
import getRefMixin from '../../mixins/get_ref';
6 7
import getFiles from '../../queries/getFiles.query.graphql';
import getProjectPath from '../../queries/getProjectPath.query.graphql';
8
import TableHeader from './header.vue';
P
Phil Hughes 已提交
9
import TableRow from './row.vue';
10
import ParentRow from './parent_row.vue';
11

12 13
const PAGE_SIZE = 100;

14 15
export default {
  components: {
16
    GlSkeletonLoading,
17
    TableHeader,
P
Phil Hughes 已提交
18
    TableRow,
19
    ParentRow,
20 21 22
  },
  mixins: [getRefMixin],
  apollo: {
23 24
    projectPath: {
      query: getProjectPath,
25 26 27 28 29 30 31 32 33 34
    },
  },
  props: {
    path: {
      type: String,
      required: true,
    },
  },
  data() {
    return {
35 36 37 38 39 40 41 42
      projectPath: '',
      nextPageCursor: '',
      entries: {
        trees: [],
        submodules: [],
        blobs: [],
      },
      isLoadingFiles: false,
43 44 45 46
    };
  },
  computed: {
    tableCaption() {
47 48 49 50 51 52 53 54 55
      if (this.isLoadingFiles) {
        return sprintf(
          __(
            'Loading files, directories, and submodules in the path %{path} for commit reference %{ref}',
          ),
          { path: this.path, ref: this.ref },
        );
      }

56 57 58 59 60
      return sprintf(
        __('Files, directories, and submodules in the path %{path} for commit reference %{ref}'),
        { path: this.path, ref: this.ref },
      );
    },
61
    showParentRow() {
62
      return !this.isLoadingFiles && ['', '/'].indexOf(this.path) === -1;
63
    },
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
  },
  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,
88
            path: this.path || '/',
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
            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();
          }
        })
112
        .catch(() => createFlash(__('An error occurred while fetching folder content.')));
113 114 115 116 117 118 119 120
    },
    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);
121 122 123 124 125 126 127 128
    },
  },
};
</script>

<template>
  <div class="tree-content-holder">
    <div class="table-holder bordered-box">
129
      <table :aria-label="tableCaption" class="table tree-table qa-file-tree" aria-live="polite">
130
        <table-header v-once />
P
Phil Hughes 已提交
131
        <tbody>
132
          <parent-row v-show="showParentRow" :commit-ref="ref" :path="path" />
133 134 135 136 137
          <template v-for="val in entries">
            <table-row
              v-for="entry in val"
              :id="entry.id"
              :key="`${entry.flatPath}-${entry.id}`"
138
              :project-path="projectPath"
139
              :current-path="path"
140
              :name="entry.name"
141 142
              :path="entry.flatPath"
              :type="entry.type"
143
              :url="entry.webUrl"
144
              :submodule-tree-url="entry.treeUrl"
145
              :lfs-oid="entry.lfsOid"
146 147
            />
          </template>
148 149 150 151 152 153 154
          <template v-if="isLoadingFiles">
            <tr v-for="i in 5" :key="i" aria-hidden="true">
              <td><gl-skeleton-loading :lines="1" class="h-auto" /></td>
              <td><gl-skeleton-loading :lines="1" class="h-auto" /></td>
              <td><gl-skeleton-loading :lines="1" class="ml-auto h-auto w-50" /></td>
            </tr>
          </template>
P
Phil Hughes 已提交
155
        </tbody>
156 157 158 159
      </table>
    </div>
  </div>
</template>