aboutsummaryrefslogtreecommitdiffstats
path: root/web_src/js/components/DiffFileTree.vue
blob: d0962254cda582398b06ff3ffcd1975445945288 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
<template>
  <div
    v-show="fileTreeIsVisible"
    id="diff-file-tree"
    class="mr-3 mt-3 diff-detail-box"
  >
    <!-- only render the tree if we're visible. in many cases this is something that doesn't change very often -->
    <div class="ui list" v-if="fileTreeIsVisible">
      <DiffFileTreeItem v-for="item in fileTree" :key="item.name" :item="item" />
    </div>
    <div v-if="isIncomplete" id="diff-too-many-files-stats" class="pt-2">
      <span>{{ tooManyFilesMessage }}</span><a :class="['ui', 'basic', 'tiny', 'button', isLoadingNewData === true ? 'disabled' : '']" id="diff-show-more-files-stats" @click.stop="loadMoreData">{{ showMoreMessage }}</a>
    </div>
  </div>
</template>

<script>
import DiffFileTreeItem from './DiffFileTreeItem.vue';
import {doLoadMoreFiles} from '../features/repo-diff.js';

const {pageData} = window.config;
const LOCAL_STORAGE_KEY = 'diff_file_tree_visible';

export default {
  name: 'DiffFileTree',
  components: {DiffFileTreeItem},

  data: () => {
    const fileTreeIsVisible = localStorage.getItem(LOCAL_STORAGE_KEY) === 'true';
    pageData.diffFileInfo.fileTreeIsVisible = fileTreeIsVisible;
    return pageData.diffFileInfo;
  },

  computed: {
    fileTree() {
      const result = [];
      for (const file of this.files) {
        // Split file into directories
        const splits = file.Name.split('/');
        let index = 0;
        let parent = null;
        let isFile = false;
        for (const split of splits) {
          index += 1;
          // reached the end
          if (index === splits.length) {
            isFile = true;
          }
          let newParent = {
            name: split,
            children: [],
            isFile
          };

          if (isFile === true) {
            newParent.file = file;
          }

          if (parent) {
            // check if the folder already exists
            const existingFolder = parent.children.find(
              (x) => x.name === split
            );
            if (existingFolder) {
              newParent = existingFolder;
            } else {
              parent.children.push(newParent);
            }
          } else {
            const existingFolder = result.find((x) => x.name === split);
            if (existingFolder) {
              newParent = existingFolder;
            } else {
              result.push(newParent);
            }
          }
          parent = newParent;
        }
      }
      const mergeChildIfOnlyOneDir = (entries) => {
        for (const entry of entries) {
          if (entry.children) {
            mergeChildIfOnlyOneDir(entry.children);
          }
          if (entry.children.length === 1 && entry.children[0].isFile === false) {
            // Merge it to the parent
            entry.name = `${entry.name}/${entry.children[0].name}`;
            entry.children = entry.children[0].children;
          }
        }
      };
      // Merge folders with just a folder as children in order to
      // reduce the depth of our tree.
      mergeChildIfOnlyOneDir(result);
      return result;
    }
  },

  mounted() {
    // ensure correct buttons when we are mounted to the dom
    this.adjustToggleButton(this.fileTreeIsVisible);
    document.querySelector('.diff-toggle-file-tree-button').addEventListener('click', this.toggleVisibility);
  },
  unmounted() {
    document.querySelector('.diff-toggle-file-tree-button').removeEventListener('click', this.toggleVisibility);
  },
  methods: {
    toggleVisibility() {
      this.updateVisibility(!this.fileTreeIsVisible);
    },
    updateVisibility(visible) {
      this.fileTreeIsVisible = visible;
      localStorage.setItem(LOCAL_STORAGE_KEY, this.fileTreeIsVisible);
      this.adjustToggleButton(this.fileTreeIsVisible);
    },
    adjustToggleButton(visible) {
      const [toShow, toHide] = document.querySelectorAll('.diff-toggle-file-tree-button .icon');
      toShow.classList.toggle('hide', visible);  // hide the toShow icon if the tree is visible
      toHide.classList.toggle('hide', !visible); // similarly
    },
    loadMoreData() {
      this.isLoadingNewData = true;
      doLoadMoreFiles(this.link, this.diffEnd, () => {
        this.isLoadingNewData = false;
      });
    }
  },
};
</script>