diff options
author | Phil Hughes <me@iamphill.com> | 2018-10-03 10:05:43 +0100 |
---|---|---|
committer | Phil Hughes <me@iamphill.com> | 2018-10-03 10:05:43 +0100 |
commit | 33c4c5b8f30c07ff30de4cd26494becd3ad058c0 (patch) | |
tree | b8c380912b47b697d8e2d2c7e41149e69be32040 /app/assets/javascripts/vue_shared | |
parent | 974fe0797079f4f7ddc57b45d15ee7d39a06e78a (diff) | |
download | gitlab-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.vue | 112 | ||||
-rw-r--r-- | app/assets/javascripts/vue_shared/components/file_row.vue | 29 |
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> |