diff options
author | Phil Hughes <me@iamphill.com> | 2018-10-08 11:50:22 +0100 |
---|---|---|
committer | Phil Hughes <me@iamphill.com> | 2018-10-23 09:12:36 +0100 |
commit | 2d00e7fce5b33f2a8c89dccd33d5d1758cc846c7 (patch) | |
tree | 146ece7201a5ec88b4c99053f53fb18cc2b9f1b6 /app | |
parent | 10bb8297ebe5fc01540b20c3fd365234779b6837 (diff) | |
download | gitlab-ce-2d00e7fce5b33f2a8c89dccd33d5d1758cc846c7.tar.gz |
Add list mode to file browser in diffs
This adds toggle buttons to switch between file & tree list.
For file list, it renders the truncated paths with the ellipsis
at the start of the path.
When focusing the input, it hides the toggle buttons.
On blur, the buttons get shown again.
Closes https://gitlab.com/gitlab-org/gitlab-ce/issues/51859
Diffstat (limited to 'app')
-rw-r--r-- | app/assets/javascripts/diffs/components/tree_list.vue | 101 | ||||
-rw-r--r-- | app/assets/javascripts/diffs/store/utils.js | 13 | ||||
-rw-r--r-- | app/assets/javascripts/vue_shared/components/file_row.vue | 8 | ||||
-rw-r--r-- | app/assets/stylesheets/pages/diff.scss | 14 |
4 files changed, 112 insertions, 24 deletions
diff --git a/app/assets/javascripts/diffs/components/tree_list.vue b/app/assets/javascripts/diffs/components/tree_list.vue index cfe4273742f..ea1a73d40cd 100644 --- a/app/assets/javascripts/diffs/components/tree_list.vue +++ b/app/assets/javascripts/diffs/components/tree_list.vue @@ -1,10 +1,14 @@ <script> import { mapActions, mapGetters, mapState } from 'vuex'; +import { TooltipDirective as Tooltip } from '@gitlab-org/gitlab-ui'; import Icon from '~/vue_shared/components/icon.vue'; import FileRow from '~/vue_shared/components/file_row.vue'; import FileRowStats from './file_row_stats.vue'; export default { + directives: { + Tooltip, + }, components: { Icon, FileRow, @@ -12,6 +16,8 @@ export default { data() { return { search: '', + renderTreeList: true, + focusSearch: false, }; }, computed: { @@ -20,16 +26,29 @@ export default { filteredTreeList() { const search = this.search.toLowerCase().trim(); - if (search === '') return this.tree; + if (search === '') return this.renderTreeList ? this.tree : this.allBlobs; return this.allBlobs.filter(f => f.name.toLowerCase().indexOf(search) >= 0); }, + rowDisplayTextKey() { + if (this.renderTreeList && this.search.trim() === '') { + return 'name'; + } + + return 'truncatedPath'; + }, }, methods: { ...mapActions('diffs', ['toggleTreeOpen', 'scrollToFile']), clearSearch() { this.search = ''; }, + toggleRenderTreeList(toggle) { + this.renderTreeList = toggle; + }, + toggleFocusSearch(toggle) { + this.focusSearch = toggle; + }, }, FileRowStats, }; @@ -37,28 +56,67 @@ export default { <template> <div class="tree-list-holder d-flex flex-column"> - <div class="append-bottom-8 position-relative tree-list-search"> - <icon - name="search" - class="position-absolute tree-list-icon" - /> - <input - v-model="search" - :placeholder="s__('MergeRequest|Filter files')" - type="search" - class="form-control" - /> - <button - v-show="search" - :aria-label="__('Clear search')" - type="button" - class="position-absolute tree-list-icon tree-list-clear-icon border-0 p-0" - @click="clearSearch" - > + <div class="append-bottom-8 position-relative tree-list-search d-flex"> + <div class="flex-fill d-flex"> <icon - name="close" + name="search" + class="position-absolute tree-list-icon" + /> + <input + v-model="search" + :placeholder="s__('MergeRequest|Filter files')" + type="search" + class="form-control" + @focus="toggleFocusSearch(true)" + @blur="toggleFocusSearch(false)" /> - </button> + <button + v-show="search" + :aria-label="__('Clear search')" + type="button" + class="position-absolute tree-list-icon tree-list-clear-icon border-0 p-0" + @click="clearSearch" + > + <icon + name="close" + /> + </button> + </div> + <div + v-show="!focusSearch" + class="btn-group prepend-left-8 tree-list-view-toggle" + > + <button + v-tooltip.hover + :aria-label="__('Switch to file list')" + :title="__('Switch to file list')" + :class="{ + active: !renderTreeList + }" + class="btn btn-default pt-0 pb-0 d-flex align-items-center" + type="button" + @click="toggleRenderTreeList(false)" + > + <icon + name="hamburger" + /> + </button> + <button + v-tooltip.hover + :aria-label="__('Switch to tree list')" + :title="__('Switch to tree list')" + :class="{ + active: renderTreeList + }" + class="btn btn-default pt-0 pb-0 d-flex align-items-center" + type="button" + @click="toggleRenderTreeList(true)" + > + <icon + name="hamburger" + /> + </button> + </div> </div> <div class="tree-list-scroll" @@ -72,6 +130,7 @@ export default { :hide-extra-on-tree="true" :extra-component="$options.FileRowStats" :show-changed-icon="true" + :display-text-key="rowDisplayTextKey" @toggleTreeOpen="toggleTreeOpen" @clickFile="scrollToFile" /> diff --git a/app/assets/javascripts/diffs/store/utils.js b/app/assets/javascripts/diffs/store/utils.js index a482a2b82c0..7c093dcf1fe 100644 --- a/app/assets/javascripts/diffs/store/utils.js +++ b/app/assets/javascripts/diffs/store/utils.js @@ -275,6 +275,18 @@ export function isDiscussionApplicableToLine({ discussion, diffPosition, latestD return latestDiff && discussion.active && lineCode === discussion.line_code; } +export const truncatedName = path => { + const maxLength = 30; + + if (path.length > maxLength) { + const start = path.length - maxLength; + const end = start + maxLength; + return `...${path.slice(start, end)}`; + } + + return path; +}; + export const generateTreeList = files => files.reduce( (acc, file) => { @@ -290,6 +302,7 @@ export const generateTreeList = files => acc.treeEntries[path] = { key: path, path, + truncatedPath: truncatedName(path), name, type, tree: [], diff --git a/app/assets/javascripts/vue_shared/components/file_row.vue b/app/assets/javascripts/vue_shared/components/file_row.vue index 36a345130c0..7c34d776c7f 100644 --- a/app/assets/javascripts/vue_shared/components/file_row.vue +++ b/app/assets/javascripts/vue_shared/components/file_row.vue @@ -34,6 +34,11 @@ export default { required: false, default: false, }, + displayTextKey: { + type: String, + required: false, + default: 'name', + }, }, data() { return { @@ -156,7 +161,7 @@ export default { :size="16" class="append-right-5" /> - {{ file.name }} + {{ file[displayTextKey] }} </span> <component :is="extraComponent" @@ -175,6 +180,7 @@ export default { :hide-extra-on-tree="hideExtraOnTree" :extra-component="extraComponent" :show-changed-icon="showChangedIcon" + :display-text-key="displayTextKey" @toggleTreeOpen="toggleTreeOpen" @clickFile="clickedFile" /> diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss index 8d884ad6891..52c91266ff4 100644 --- a/app/assets/stylesheets/pages/diff.scss +++ b/app/assets/stylesheets/pages/diff.scss @@ -1027,8 +1027,12 @@ overflow-x: auto; } -.tree-list-search .form-control { - padding-left: 30px; +.tree-list-search { + flex: 0 0 34px; + + .form-control { + padding-left: 30px; + } } .tree-list-icon { @@ -1063,3 +1067,9 @@ } } } + +.tree-list-view-toggle { + svg { + top: 0; + } +} |