summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/vue_shared
diff options
context:
space:
mode:
authorPhil Hughes <me@iamphill.com>2018-10-03 10:05:43 +0100
committerPhil Hughes <me@iamphill.com>2018-10-03 10:05:43 +0100
commit33c4c5b8f30c07ff30de4cd26494becd3ad058c0 (patch)
treeb8c380912b47b697d8e2d2c7e41149e69be32040 /app/assets/javascripts/vue_shared
parent974fe0797079f4f7ddc57b45d15ee7d39a06e78a (diff)
downloadgitlab-ce-33c4c5b8f30c07ff30de4cd26494becd3ad058c0.tar.gz
Added file tree to merge request diffs
This file tree displays all the diff files in a tree like format Each file is taken and converted into a tree with folders Each folder can be toggled open & closed Clicking a file will scroll to the diff file & highlight with a glow affect Searching the tree list will search only files & return a list of the files without any folders Each file row contains an icon to show changed, new file or deleted Each row will also contain the added & removed lines count Closes https://gitlab.com/gitlab-org/gitlab-ce/issues/14249
Diffstat (limited to 'app/assets/javascripts/vue_shared')
-rw-r--r--app/assets/javascripts/vue_shared/components/changed_file_icon.vue112
-rw-r--r--app/assets/javascripts/vue_shared/components/file_row.vue29
2 files changed, 140 insertions, 1 deletions
diff --git a/app/assets/javascripts/vue_shared/components/changed_file_icon.vue b/app/assets/javascripts/vue_shared/components/changed_file_icon.vue
new file mode 100644
index 00000000000..8684005e0fb
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/changed_file_icon.vue
@@ -0,0 +1,112 @@
+<script>
+import tooltip from '~/vue_shared/directives/tooltip';
+import Icon from '~/vue_shared/components/icon.vue';
+import { pluralize } from '~/lib/utils/text_utility';
+import { __, sprintf } from '~/locale';
+import { getCommitIconMap } from '~/ide/utils';
+
+export default {
+ components: {
+ Icon,
+ },
+ directives: {
+ tooltip,
+ },
+ props: {
+ file: {
+ type: Object,
+ required: true,
+ },
+ showTooltip: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ showStagedIcon: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ forceModifiedIcon: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ size: {
+ type: Number,
+ required: false,
+ default: 12,
+ },
+ },
+ computed: {
+ changedIcon() {
+ const suffix = !this.file.changed && this.file.staged && !this.showStagedIcon ? '-solid' : '';
+
+ if (this.forceModifiedIcon) return `file-modified${suffix}`;
+
+ return `${getCommitIconMap(this.file).icon}${suffix}`;
+ },
+ changedIconClass() {
+ return `${this.changedIcon} float-left d-block`;
+ },
+ tooltipTitle() {
+ if (!this.showTooltip) return undefined;
+
+ const type = this.file.tempFile ? 'addition' : 'modification';
+
+ if (this.file.changed && !this.file.staged) {
+ return sprintf(__('Unstaged %{type}'), {
+ type,
+ });
+ } else if (!this.file.changed && this.file.staged) {
+ return sprintf(__('Staged %{type}'), {
+ type,
+ });
+ } else if (this.file.changed && this.file.staged) {
+ return sprintf(__('Unstaged and staged %{type}'), {
+ type: pluralize(type),
+ });
+ }
+
+ return undefined;
+ },
+ showIcon() {
+ return this.file.changed || this.file.tempFile || this.file.staged || this.file.deleted;
+ },
+ },
+};
+</script>
+
+<template>
+ <span
+ v-tooltip
+ :title="tooltipTitle"
+ data-container="body"
+ data-placement="right"
+ class="file-changed-icon ml-auto"
+ >
+ <icon
+ v-if="showIcon"
+ :name="changedIcon"
+ :size="size"
+ :css-classes="changedIconClass"
+ />
+ </span>
+</template>
+
+<style>
+.file-addition,
+.file-addition-solid {
+ color: #1aaa55;
+}
+
+.file-modified,
+.file-modified-solid {
+ color: #fc9403;
+}
+
+.file-deletion,
+.file-deletion-solid {
+ color: #db3b21;
+}
+</style>
diff --git a/app/assets/javascripts/vue_shared/components/file_row.vue b/app/assets/javascripts/vue_shared/components/file_row.vue
index c797ad62a5d..36a345130c0 100644
--- a/app/assets/javascripts/vue_shared/components/file_row.vue
+++ b/app/assets/javascripts/vue_shared/components/file_row.vue
@@ -1,12 +1,14 @@
<script>
import Icon from '~/vue_shared/components/icon.vue';
import FileIcon from '~/vue_shared/components/file_icon.vue';
+import ChangedFileIcon from '~/vue_shared/components/changed_file_icon.vue';
export default {
name: 'FileRow',
components: {
FileIcon,
Icon,
+ ChangedFileIcon,
},
props: {
file: {
@@ -22,6 +24,16 @@ export default {
required: false,
default: null,
},
+ hideExtraOnTree: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ showChangedIcon: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
@@ -65,6 +77,9 @@ export default {
toggleTreeOpen(path) {
this.$emit('toggleTreeOpen', path);
},
+ clickedFile(path) {
+ this.$emit('clickFile', path);
+ },
clickFile() {
// Manual Action if a tree is selected/opened
if (this.isTree && this.hasUrlAtCurrentRoute()) {
@@ -72,6 +87,8 @@ export default {
}
if (this.$router) this.$router.push(`/project${this.file.url}`);
+
+ if (this.isBlob) this.clickedFile(this.file.path);
},
scrollIntoView(isInit = false) {
const block = isInit && this.isTree ? 'center' : 'nearest';
@@ -126,17 +143,24 @@ export default {
class="file-row-name str-truncated"
>
<file-icon
+ v-if="!showChangedIcon || file.type === 'tree'"
:file-name="file.name"
:loading="file.loading"
:folder="isTree"
:opened="file.opened"
:size="16"
/>
+ <changed-file-icon
+ v-else
+ :file="file"
+ :size="16"
+ class="append-right-5"
+ />
{{ file.name }}
</span>
<component
:is="extraComponent"
- v-if="extraComponent"
+ v-if="extraComponent && !(hideExtraOnTree && file.type === 'tree')"
:file="file"
:mouse-over="mouseOver"
/>
@@ -148,8 +172,11 @@ export default {
:key="childFile.key"
:file="childFile"
:level="level + 1"
+ :hide-extra-on-tree="hideExtraOnTree"
:extra-component="extraComponent"
+ :show-changed-icon="showChangedIcon"
@toggleTreeOpen="toggleTreeOpen"
+ @clickFile="clickedFile"
/>
</template>
</div>