Skip to content
Snippets Groups Projects
Unverified Commit d17de657 authored by Phil Hughes's avatar Phil Hughes
Browse files

Make the file tree in merge requests resizable

parent 3f55633a
No related branches found
No related tags found
No related merge requests found
Showing
with 143 additions and 42 deletions
Loading
Loading
@@ -4,6 +4,7 @@ import Icon from '~/vue_shared/components/icon.vue';
import { __ } from '~/locale';
import createFlash from '~/flash';
import { GlLoadingIcon } from '@gitlab/ui';
import PanelResizer from '~/vue_shared/components/panel_resizer.vue';
import eventHub from '../../notes/event_hub';
import CompareVersions from './compare_versions.vue';
import DiffFile from './diff_file.vue';
Loading
Loading
@@ -11,6 +12,13 @@ import NoChanges from './no_changes.vue';
import HiddenFilesWarning from './hidden_files_warning.vue';
import CommitWidget from './commit_widget.vue';
import TreeList from './tree_list.vue';
import {
TREE_LIST_WIDTH_STORAGE_KEY,
INITIAL_TREE_WIDTH,
MIN_TREE_WIDTH,
MAX_TREE_WIDTH,
TREE_HIDE_STATS_WIDTH,
} from '../constants';
 
export default {
name: 'DiffsApp',
Loading
Loading
@@ -23,6 +31,7 @@ export default {
CommitWidget,
TreeList,
GlLoadingIcon,
PanelResizer,
},
props: {
endpoint: {
Loading
Loading
@@ -54,8 +63,12 @@ export default {
},
},
data() {
const treeWidth =
parseInt(localStorage.getItem(TREE_LIST_WIDTH_STORAGE_KEY), 10) || INITIAL_TREE_WIDTH;
return {
assignedDiscussions: false,
treeWidth,
};
},
computed: {
Loading
Loading
@@ -96,6 +109,9 @@ export default {
this.startVersion.version_index === this.mergeRequestDiff.version_index)
);
},
hideFileStats() {
return this.treeWidth <= TREE_HIDE_STATS_WIDTH;
},
},
watch: {
diffViewType() {
Loading
Loading
@@ -142,6 +158,7 @@ export default {
'startRenderDiffsQueue',
'assignDiscussionsToDiff',
'setHighlightedRow',
'cacheTreeListWidth',
]),
fetchData() {
this.fetchDiffFiles()
Loading
Loading
@@ -184,6 +201,8 @@ export default {
}
},
},
minTreeWidth: MIN_TREE_WIDTH,
maxTreeWidth: MAX_TREE_WIDTH,
};
</script>
 
Loading
Loading
@@ -209,7 +228,21 @@ export default {
:data-can-create-note="getNoteableData.current_user.can_create_note"
class="files d-flex prepend-top-default"
>
<div v-show="showTreeList" class="diff-tree-list"><tree-list /></div>
<div
v-show="showTreeList"
:style="{ width: `${treeWidth}px` }"
class="diff-tree-list js-diff-tree-list"
>
<panel-resizer
:size.sync="treeWidth"
:start-size="treeWidth"
:min-size="$options.minTreeWidth"
:max-size="$options.maxTreeWidth"
side="right"
@resize-end="cacheTreeListWidth"
/>
<tree-list :hide-file-stats="hideFileStats" />
</div>
<div class="diff-files-holder">
<commit-widget v-if="commit" :commit="commit" />
<template v-if="renderDiffFiles">
Loading
Loading
Loading
Loading
@@ -13,6 +13,12 @@ export default {
Icon,
FileRow,
},
props: {
hideFileStats: {
type: Boolean,
required: true,
},
},
data() {
return {
search: '',
Loading
Loading
@@ -40,6 +46,9 @@ export default {
return acc;
}, []);
},
fileRowExtraComponent() {
return this.hideFileStats ? null : FileRowStats;
},
},
methods: {
...mapActions('diffs', ['toggleTreeOpen', 'scrollToFile', 'toggleFileFinder']),
Loading
Loading
@@ -48,7 +57,6 @@ export default {
},
},
shortcutKeyCharacter: `${/Mac/i.test(navigator.userAgent) ? '&#8984;' : 'Ctrl'}+P`,
FileRowStats,
diffTreeFiltering: gon.features && gon.features.diffTreeFiltering,
};
</script>
Loading
Loading
@@ -98,7 +106,7 @@ export default {
:file="file"
:level="0"
:hide-extra-on-tree="true"
:extra-component="$options.FileRowStats"
:extra-component="fileRowExtraComponent"
:show-changed-icon="true"
@toggleTreeOpen="toggleTreeOpen"
@clickFile="scrollToFile"
Loading
Loading
Loading
Loading
@@ -36,3 +36,9 @@ export const MR_TREE_SHOW_KEY = 'mr_tree_show';
export const TREE_TYPE = 'tree';
export const TREE_LIST_STORAGE_KEY = 'mr_diff_tree_list';
export const WHITESPACE_STORAGE_KEY = 'mr_show_whitespace';
export const TREE_LIST_WIDTH_STORAGE_KEY = 'mr_tree_list_width';
export const INITIAL_TREE_WIDTH = 320;
export const MIN_TREE_WIDTH = 240;
export const MAX_TREE_WIDTH = 400;
export const TREE_HIDE_STATS_WIDTH = 260;
Loading
Loading
@@ -16,6 +16,7 @@ import {
MR_TREE_SHOW_KEY,
TREE_LIST_STORAGE_KEY,
WHITESPACE_STORAGE_KEY,
TREE_LIST_WIDTH_STORAGE_KEY,
} from '../constants';
 
export const setBaseConfig = ({ commit }, options) => {
Loading
Loading
@@ -300,5 +301,9 @@ export const toggleFileFinder = ({ commit }, visible) => {
commit(types.TOGGLE_FILE_FINDER_VISIBLE, visible);
};
 
export const cacheTreeListWidth = (_, size) => {
localStorage.setItem(TREE_LIST_WIDTH_STORAGE_KEY, size);
};
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};
Loading
Loading
@@ -28,11 +28,12 @@ export default {
data() {
return {
size: this.startSize,
isDragging: false,
};
},
computed: {
className() {
return `drag-${this.side}`;
return [`position-${this.side}-0`, { 'is-dragging': this.isDragging }];
},
cursorStyle() {
if (this.enabled) {
Loading
Loading
@@ -57,6 +58,7 @@ export default {
startDrag(e) {
if (this.enabled) {
e.preventDefault();
this.isDragging = true;
this.startPos = e.clientX;
this.currentStartSize = this.size;
document.addEventListener('mousemove', this.drag);
Loading
Loading
@@ -80,6 +82,7 @@ export default {
},
endDrag(e) {
e.preventDefault();
this.isDragging = false;
document.removeEventListener('mousemove', this.drag);
this.$emit('resize-end', this.size);
},
Loading
Loading
@@ -91,7 +94,7 @@ export default {
<div
:class="className"
:style="cursorStyle"
class="drag-handle"
class="position-absolute position-top-0 position-bottom-0 drag-handle"
@mousedown="startDrag"
@dblclick="resetSize"
></div>
Loading
Loading
Loading
Loading
@@ -442,3 +442,15 @@ img.emoji {
.position-left-0 { left: 0; }
.position-right-0 { right: 0; }
.position-top-0 { top: 0; }
.drag-handle {
width: 4px;
&:hover {
background-color: $white-normal;
}
&.is-dragging {
background-color: $gray-600;
}
}
Loading
Loading
@@ -682,25 +682,6 @@ $ide-commit-header-height: 48px;
flex: 1;
}
 
.drag-handle {
position: absolute;
top: 0;
bottom: 0;
width: 4px;
&:hover {
background-color: $white-normal;
}
&.drag-right {
right: 0;
}
&.drag-left {
left: 0;
}
}
.ide-commit-list-container {
display: flex;
flex: 1;
Loading
Loading
Loading
Loading
@@ -1038,12 +1038,30 @@
}
 
.diff-tree-list {
width: 320px;
position: -webkit-sticky;
position: sticky;
$top-pos: $header-height + $mr-tabs-height + $mr-version-controls-height + 10px;
top: $header-height + $mr-tabs-height + $mr-version-controls-height + 10px;
max-height: calc(100vh - #{$top-pos});
padding-right: $gl-padding;
z-index: 202;
.with-performance-bar & {
$performance-bar-top-pos: $performance-bar-height + $top-pos;
top: $performance-bar-top-pos;
max-height: calc(100vh - #{$performance-bar-top-pos});
}
.drag-handle {
bottom: 16px;
transform: translateX(-6px);
}
}
 
.diff-files-holder {
flex: 1;
min-width: 0;
z-index: 201;
}
 
.compare-versions-container {
Loading
Loading
@@ -1051,23 +1069,12 @@
}
 
.tree-list-holder {
position: -webkit-sticky;
position: sticky;
$top-pos: $header-height + $mr-tabs-height + $mr-version-controls-height + 10px;
top: $header-height + $mr-tabs-height + $mr-version-controls-height + 10px;
max-height: calc(100vh - #{$top-pos});
padding-right: $gl-padding;
height: 100%;
 
.file-row {
margin-left: 0;
margin-right: 0;
}
.with-performance-bar & {
$performance-bar-top-pos: $performance-bar-height + $top-pos;
top: $performance-bar-top-pos;
max-height: calc(100vh - #{$performance-bar-top-pos});
}
}
 
.tree-list-scroll {
Loading
Loading
Loading
Loading
@@ -735,7 +735,7 @@
 
.mr-version-controls {
position: relative;
z-index: 103;
z-index: 203;
background: $gray-light;
color: $gl-text-color;
margin-top: -1px;
Loading
Loading
@@ -809,7 +809,7 @@
 
.merge-request-tabs-holder {
top: $header-height;
z-index: 200;
z-index: 300;
background-color: $white-light;
border-bottom: 1px solid $border-color;
 
Loading
Loading
---
title: Make file tree in merge requests resizable
merge_request:
author:
type: added
Loading
Loading
@@ -68,6 +68,32 @@ describe('diffs/components/app', () => {
});
});
 
describe('resizable', () => {
afterEach(() => {
localStorage.removeItem('mr_tree_list_width');
});
it('sets initial width when no localStorage has been set', () => {
createComponent();
expect(vm.vm.treeWidth).toEqual(320);
});
it('sets initial width to localStorage size', () => {
localStorage.setItem('mr_tree_list_width', '200');
createComponent();
expect(vm.vm.treeWidth).toEqual(200);
});
it('sets width of tree list', () => {
createComponent();
expect(vm.find('.js-diff-tree-list').element.style.width).toEqual('320px');
});
});
describe('empty state', () => {
it('renders empty state when no diff files exist', () => {
createComponent();
Loading
Loading
Loading
Loading
@@ -28,7 +28,7 @@ describe('Diffs tree list component', () => {
 
localStorage.removeItem('mr_diff_tree_list');
 
vm = mountComponentWithStore(Component, { store });
vm = mountComponentWithStore(Component, { store, props: { hideFileStats: false } });
});
 
afterEach(() => {
Loading
Loading
@@ -77,6 +77,16 @@ describe('Diffs tree list component', () => {
expect(vm.$el.querySelectorAll('.file-row')[1].textContent).toContain('app');
});
 
it('hides file stats', done => {
vm.hideFileStats = true;
vm.$nextTick(() => {
expect(vm.$el.querySelector('.file-row-stats')).toBe(null);
done();
});
});
it('calls toggleTreeOpen when clicking folder', () => {
spyOn(vm.$store, 'dispatch').and.stub();
 
Loading
Loading
Loading
Loading
@@ -44,7 +44,10 @@ describe('Panel Resizer component', () => {
});
 
expect(vm.$el.tagName).toEqual('DIV');
expect(vm.$el.getAttribute('class')).toBe('drag-handle drag-left');
expect(vm.$el.getAttribute('class')).toBe(
'position-absolute position-top-0 position-bottom-0 drag-handle position-left-0',
);
expect(vm.$el.getAttribute('style')).toBe('cursor: ew-resize;');
});
 
Loading
Loading
@@ -55,7 +58,9 @@ describe('Panel Resizer component', () => {
});
 
expect(vm.$el.tagName).toEqual('DIV');
expect(vm.$el.getAttribute('class')).toBe('drag-handle drag-right');
expect(vm.$el.getAttribute('class')).toBe(
'position-absolute position-top-0 position-bottom-0 drag-handle position-right-0',
);
});
 
it('drag the resizer', () => {
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment