Commit 7fbb5add authored by Tim Zallmann's avatar Tim Zallmann Committed by Filipa Lacerda

Resolve "Resizable file list and commit panel"

parent 0e7e9e32
...@@ -2,11 +2,18 @@ ...@@ -2,11 +2,18 @@
import { mapGetters, mapState, mapActions } from 'vuex'; import { mapGetters, mapState, mapActions } from 'vuex';
import repoCommitSection from './repo_commit_section.vue'; import repoCommitSection from './repo_commit_section.vue';
import icon from '../../vue_shared/components/icon.vue'; import icon from '../../vue_shared/components/icon.vue';
import panelResizer from '../../vue_shared/components/panel_resizer.vue';
export default { export default {
data() {
return {
width: 290,
};
},
components: { components: {
repoCommitSection, repoCommitSection,
icon, icon,
panelResizer,
}, },
computed: { computed: {
...mapState([ ...mapState([
...@@ -18,10 +25,20 @@ export default { ...@@ -18,10 +25,20 @@ export default {
currentIcon() { currentIcon() {
return this.rightPanelCollapsed ? 'angle-double-left' : 'angle-double-right'; return this.rightPanelCollapsed ? 'angle-double-left' : 'angle-double-right';
}, },
maxSize() {
return window.innerWidth / 2;
},
panelStyle() {
if (!this.rightPanelCollapsed) {
return { width: `${this.width}px` };
}
return {};
},
}, },
methods: { methods: {
...mapActions([ ...mapActions([
'setPanelCollapsedStatus', 'setPanelCollapsedStatus',
'setResizingStatus',
]), ]),
toggleCollapsed() { toggleCollapsed() {
this.setPanelCollapsedStatus({ this.setPanelCollapsedStatus({
...@@ -29,6 +46,12 @@ export default { ...@@ -29,6 +46,12 @@ export default {
collapsed: !this.rightPanelCollapsed, collapsed: !this.rightPanelCollapsed,
}); });
}, },
resizingStarted() {
this.setResizingStatus(true);
},
resizingEnded() {
this.setResizingStatus(false);
},
}, },
}; };
</script> </script>
...@@ -39,6 +62,7 @@ export default { ...@@ -39,6 +62,7 @@ export default {
:class="{ :class="{
'is-collapsed': rightPanelCollapsed, 'is-collapsed': rightPanelCollapsed,
}" }"
:style="panelStyle"
> >
<div <div
class="multi-file-commit-panel-section"> class="multi-file-commit-panel-section">
...@@ -71,5 +95,14 @@ export default { ...@@ -71,5 +95,14 @@ export default {
<repo-commit-section <repo-commit-section
class=""/> class=""/>
</div> </div>
<panel-resizer
:size.sync="width"
:enabled="!rightPanelCollapsed"
:start-size="290"
:min-size="200"
:max-size="maxSize"
@resize-start="resizingStarted"
@resize-end="resizingEnded"
side="left"/>
</div> </div>
</template> </template>
...@@ -2,11 +2,18 @@ ...@@ -2,11 +2,18 @@
import { mapState, mapActions } from 'vuex'; import { mapState, mapActions } from 'vuex';
import projectTree from './ide_project_tree.vue'; import projectTree from './ide_project_tree.vue';
import icon from '../../vue_shared/components/icon.vue'; import icon from '../../vue_shared/components/icon.vue';
import panelResizer from '../../vue_shared/components/panel_resizer.vue';
export default { export default {
data() {
return {
width: 290,
};
},
components: { components: {
projectTree, projectTree,
icon, icon,
panelResizer,
}, },
computed: { computed: {
...mapState([ ...mapState([
...@@ -16,10 +23,20 @@ export default { ...@@ -16,10 +23,20 @@ export default {
currentIcon() { currentIcon() {
return this.leftPanelCollapsed ? 'angle-double-right' : 'angle-double-left'; return this.leftPanelCollapsed ? 'angle-double-right' : 'angle-double-left';
}, },
maxSize() {
return window.innerWidth / 2;
},
panelStyle() {
if (!this.leftPanelCollapsed) {
return { width: `${this.width}px` };
}
return {};
},
}, },
methods: { methods: {
...mapActions([ ...mapActions([
'setPanelCollapsedStatus', 'setPanelCollapsedStatus',
'setResizingStatus',
]), ]),
toggleCollapsed() { toggleCollapsed() {
this.setPanelCollapsedStatus({ this.setPanelCollapsedStatus({
...@@ -27,6 +44,12 @@ export default { ...@@ -27,6 +44,12 @@ export default {
collapsed: !this.leftPanelCollapsed, collapsed: !this.leftPanelCollapsed,
}); });
}, },
resizingStarted() {
this.setResizingStatus(true);
},
resizingEnded() {
this.setResizingStatus(false);
},
}, },
}; };
</script> </script>
...@@ -37,6 +60,7 @@ export default { ...@@ -37,6 +60,7 @@ export default {
:class="{ :class="{
'is-collapsed': leftPanelCollapsed, 'is-collapsed': leftPanelCollapsed,
}" }"
:style="panelStyle"
> >
<div class="multi-file-commit-panel-inner"> <div class="multi-file-commit-panel-inner">
<project-tree <project-tree
...@@ -58,5 +82,14 @@ export default { ...@@ -58,5 +82,14 @@ export default {
class="collapse-text" class="collapse-text"
>Collapse sidebar</span> >Collapse sidebar</span>
</button> </button>
<panel-resizer
:size.sync="width"
:enabled="!leftPanelCollapsed"
:start-size="290"
:min-size="200"
:max-size="maxSize"
@resize-start="resizingStarted"
@resize-end="resizingEnded"
side="right"/>
</div> </div>
</template> </template>
...@@ -90,6 +90,11 @@ export default { ...@@ -90,6 +90,11 @@ export default {
rightPanelCollapsed() { rightPanelCollapsed() {
this.editor.updateDimensions(); this.editor.updateDimensions();
}, },
panelResizing(isResizing) {
if (isResizing === false) {
this.editor.updateDimensions();
}
},
}, },
computed: { computed: {
...mapGetters([ ...mapGetters([
...@@ -99,6 +104,7 @@ export default { ...@@ -99,6 +104,7 @@ export default {
...mapState([ ...mapState([
'leftPanelCollapsed', 'leftPanelCollapsed',
'rightPanelCollapsed', 'rightPanelCollapsed',
'panelResizing',
]), ]),
shouldHideEditor() { shouldHideEditor() {
return this.activeFile.binary && !this.activeFile.raw; return this.activeFile.binary && !this.activeFile.raw;
......
...@@ -63,6 +63,10 @@ export const setPanelCollapsedStatus = ({ commit }, { side, collapsed }) => { ...@@ -63,6 +63,10 @@ export const setPanelCollapsedStatus = ({ commit }, { side, collapsed }) => {
} }
}; };
export const setResizingStatus = ({ commit }, resizing) => {
commit(types.SET_RESIZING_STATUS, resizing);
};
export const checkCommitStatus = ({ state }) => export const checkCommitStatus = ({ state }) =>
service service
.getBranchData(state.currentProjectId, state.currentBranchId) .getBranchData(state.currentProjectId, state.currentBranchId)
......
...@@ -5,6 +5,7 @@ export const SET_ROOT = 'SET_ROOT'; ...@@ -5,6 +5,7 @@ export const SET_ROOT = 'SET_ROOT';
export const SET_LAST_COMMIT_DATA = 'SET_LAST_COMMIT_DATA'; export const SET_LAST_COMMIT_DATA = 'SET_LAST_COMMIT_DATA';
export const SET_LEFT_PANEL_COLLAPSED = 'SET_LEFT_PANEL_COLLAPSED'; export const SET_LEFT_PANEL_COLLAPSED = 'SET_LEFT_PANEL_COLLAPSED';
export const SET_RIGHT_PANEL_COLLAPSED = 'SET_RIGHT_PANEL_COLLAPSED'; export const SET_RIGHT_PANEL_COLLAPSED = 'SET_RIGHT_PANEL_COLLAPSED';
export const SET_RESIZING_STATUS = 'SET_RESIZING_STATUS';
// Project Mutation Types // Project Mutation Types
export const SET_PROJECT = 'SET_PROJECT'; export const SET_PROJECT = 'SET_PROJECT';
......
...@@ -49,6 +49,11 @@ export default { ...@@ -49,6 +49,11 @@ export default {
rightPanelCollapsed: collapsed, rightPanelCollapsed: collapsed,
}); });
}, },
[types.SET_RESIZING_STATUS](state, resizing) {
Object.assign(state, {
panelResizing: resizing,
});
},
[types.SET_LAST_COMMIT_DATA](state, { entry, lastCommit }) { [types.SET_LAST_COMMIT_DATA](state, { entry, lastCommit }) {
Object.assign(entry.lastCommit, { Object.assign(entry.lastCommit, {
id: lastCommit.commit.id, id: lastCommit.commit.id,
......
...@@ -19,4 +19,5 @@ export default () => ({ ...@@ -19,4 +19,5 @@ export default () => ({
projects: {}, projects: {},
leftPanelCollapsed: false, leftPanelCollapsed: false,
rightPanelCollapsed: true, rightPanelCollapsed: true,
panelResizing: false,
}); });
<script>
export default {
props: {
startSize: {
type: Number,
required: true,
},
side: {
type: String,
required: true,
},
minSize: {
type: Number,
required: false,
default: 0,
},
maxSize: {
type: Number,
required: false,
default: Number.MAX_VALUE,
},
enabled: {
type: Boolean,
required: false,
default: true,
},
},
data() {
return {
size: this.startSize,
};
},
computed: {
className() {
return `drag${this.side}`;
},
cursorStyle() {
if (this.enabled) {
return { cursor: 'ew-resize' };
}
return {};
},
},
methods: {
resetSize(e) {
e.preventDefault();
this.size = this.startSize;
this.$emit('update:size', this.size);
},
startDrag(e) {
if (this.enabled) {
e.preventDefault();
this.startPos = e.clientX;
this.currentStartSize = this.size;
document.addEventListener('mousemove', this.drag);
document.addEventListener('mouseup', this.endDrag, { once: true });
this.$emit('resize-start', this.size);
}
},
drag(e) {
e.preventDefault();
let moved = e.clientX - this.startPos;
if (this.side === 'left') moved = -moved;
let newSize = this.currentStartSize + moved;
if (newSize < this.minSize) {
newSize = this.minSize;
} else if (newSize > this.maxSize) {
newSize = this.maxSize;
}
this.size = newSize;
this.$emit('update:size', newSize);
},
endDrag(e) {
e.preventDefault();
document.removeEventListener('mousemove', this.drag);
this.$emit('resize-end', this.size);
},
},
};
</script>
<template>
<div
class="dragHandle"
:class="className"
:style="cursorStyle"
@mousedown="startDrag"
@dblclick="resetSize"
></div>
</template>
...@@ -36,10 +36,6 @@ ...@@ -36,10 +36,6 @@
} }
} }
.with-performance-bar .ide-view {
height: calc(100vh - #{$header-height});
}
.ide-file-list { .ide-file-list {
flex: 1; flex: 1;
...@@ -242,12 +238,13 @@ table.table tr td.multi-file-table-name { ...@@ -242,12 +238,13 @@ table.table tr td.multi-file-table-name {
.multi-file-commit-panel { .multi-file-commit-panel {
display: flex; display: flex;
position: relative;
flex-direction: column; flex-direction: column;
height: 100%; height: 100%;
width: 290px; width: 290px;
padding: 0; padding: 0;
background-color: $gray-light; background-color: $gray-light;
border-left: 1px solid $white-dark; padding-right: 3px;
.projects-sidebar { .projects-sidebar {
display: flex; display: flex;
...@@ -496,3 +493,30 @@ table.table tr td.multi-file-table-name { ...@@ -496,3 +493,30 @@ table.table tr td.multi-file-table-name {
margin-top: $header-height; margin-top: $header-height;
margin-bottom: 0; margin-bottom: 0;
} }
.with-performance-bar {
.ide-flash-container.flash-container {
margin-top: $header-height + $performance-bar-height;
}
.ide-view {
height: calc(100vh - #{$header-height + $performance-bar-height});
}
}
.dragHandle {
position: absolute;
top: 0;
bottom: 0;
width: 3px;
background-color: $white-dark;
&.dragright {
right: 0;
}
&.dragleft {
left: 0;
}
}
import Vue from 'vue';
import panelResizer from '~/vue_shared/components/panel_resizer.vue';
import mountComponent from '../../helpers/vue_mount_component_helper';
describe('Panel Resizer component', () => {
let vm;
let PanelResizer;
const triggerEvent = (eventName, el = vm.$el, clientX = 0) => {
const event = document.createEvent('MouseEvents');
event.initMouseEvent(eventName, true, true, window, 1, clientX, 0, clientX, 0, false, false,
false, false, 0, null);
el.dispatchEvent(event);
};
beforeEach(() => {
PanelResizer = Vue.extend(panelResizer);
});
afterEach(() => {
vm.$destroy();
});
it('should render a div element with the correct classes and styles', () => {
vm = mountComponent(PanelResizer, {
startSize: 100,
side: 'left',
});
expect(vm.$el.tagName).toEqual('DIV');
expect(vm.$el.getAttribute('class')).toBe('dragHandle dragleft');
expect(vm.$el.getAttribute('style')).toBe('cursor: ew-resize;');
});
it('should render a div element with the correct classes for a right side panel', () => {
vm = mountComponent(PanelResizer, {
startSize: 100,
side: 'right',
});
expect(vm.$el.tagName).toEqual('DIV');
expect(vm.$el.getAttribute('class')).toBe('dragHandle dragright');
});
it('drag the resizer', () => {
vm = mountComponent(PanelResizer, {
startSize: 100,
side: 'left',
});
spyOn(vm, '$emit');
triggerEvent('mousedown', vm.$el);
triggerEvent('mousemove', document);
triggerEvent('mouseup', document);
expect(vm.$emit.calls.allArgs()).toEqual([['resize-start', 100], ['update:size', 100], ['resize-end', 100]]);
expect(vm.size).toBe(100);
});
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment