Commit d5138d6a authored by Phil Hughes's avatar Phil Hughes

IDE open changed files in diff viewer

Closes #4568
parent 5ea0fbfc
...@@ -132,13 +132,33 @@ ...@@ -132,13 +132,33 @@
.multi-file-tabs { .multi-file-tabs {
display: flex; display: flex;
overflow-x: auto;
background-color: $white-normal; background-color: $white-normal;
box-shadow: inset 0 -1px $white-dark; box-shadow: inset 0 -1px $white-dark;
> li { > ul {
display: flex;
overflow-x: auto;
}
li {
position: relative; position: relative;
} }
.dropdown {
display: flex;
margin-left: auto;
padding: 0 $grid-size;
background-color: $white-light;
&.shadow {
box-shadow: 0 0 10px rgba(0,0,0,.4);
}
.btn {
margin-top: auto;
margin-bottom: auto;
}
}
} }
.multi-file-tab { .multi-file-tab {
......
...@@ -24,8 +24,11 @@ ...@@ -24,8 +24,11 @@
methods: { methods: {
...mapActions([ ...mapActions([
'discardFileChanges', 'discardFileChanges',
'updateViewer',
]), ]),
openFileInEditor(file) { openFileInEditor(file) {
this.updateViewer('diff');
router.push(`/project${file.url}`); router.push(`/project${file.url}`);
}, },
}, },
......
...@@ -15,6 +15,7 @@ export default { ...@@ -15,6 +15,7 @@ export default {
'leftPanelCollapsed', 'leftPanelCollapsed',
'rightPanelCollapsed', 'rightPanelCollapsed',
'panelResizing', 'panelResizing',
'viewer',
]), ]),
shouldHideEditor() { shouldHideEditor() {
return this.activeFile && this.activeFile.binary && !this.activeFile.raw; return this.activeFile && this.activeFile.binary && !this.activeFile.raw;
...@@ -37,6 +38,9 @@ export default { ...@@ -37,6 +38,9 @@ export default {
this.editor.updateDimensions(); this.editor.updateDimensions();
} }
}, },
viewer() {
this.createEditorInstance();
},
}, },
beforeDestroy() { beforeDestroy() {
this.editor.dispose(); this.editor.dispose();
...@@ -66,15 +70,25 @@ export default { ...@@ -66,15 +70,25 @@ export default {
this.editor.clearEditor(); this.editor.clearEditor();
this.getRawFileData(this.activeFile) this.getRawFileData(this.activeFile)
.then(() => { .then(() => this.createEditorInstance())
this.editor.createInstance(this.$refs.editor);
})
.then(() => this.setupEditor())
.catch((err) => { .catch((err) => {
flash('Error setting up monaco. Please try again.', 'alert', document, null, false, true); flash('Error setting up monaco. Please try again.', 'alert', document, null, false, true);
throw err; throw err;
}); });
}, },
createEditorInstance() {
this.editor.dispose();
this.$nextTick(() => {
if (this.viewer === 'editor') {
this.editor.createInstance(this.$refs.editor);
} else {
this.editor.createDiffInstance(this.$refs.editor);
}
this.setupEditor();
});
},
setupEditor() { setupEditor() {
if (!this.activeFile) return; if (!this.activeFile) return;
......
<script> <script>
import { mapState } from 'vuex'; import { mapActions, mapState } from 'vuex';
import RepoTab from './repo_tab.vue'; import RepoTab from './repo_tab.vue';
export default { export default {
components: { components: {
'repo-tab': RepoTab, 'repo-tab': RepoTab,
}, },
data() {
return {
showShadow: false,
};
},
computed: { computed: {
...mapState([ ...mapState([
'openFiles', 'openFiles',
'viewer',
]),
},
methods: {
...mapActions([
'updateViewer',
]), ]),
}, },
updated() {
if (!this.$refs.tabsScroller) return;
this.showShadow = this.$refs.tabsScroller.scrollWidth > this.$refs.tabsScroller.offsetWidth;
},
}; };
</script> </script>
<template> <template>
<ul <div class="multi-file-tabs">
class="multi-file-tabs list-unstyled append-bottom-0" <ul
> class="list-unstyled append-bottom-0"
<repo-tab ref="tabsScroller"
v-for="tab in openFiles" >
:key="tab.key" <repo-tab
:tab="tab" v-for="tab in openFiles"
/> :key="tab.key"
</ul> :tab="tab"
/>
</ul>
<div
class="dropdown"
:class="{
shadow: showShadow,
}"
>
<button class="btn btn-primary btn-sm" data-toggle="dropdown">
<template v-if="viewer === 'editor'">
Editing
</template>
<template v-else>
Reviewing
</template>
<i class="fa fa-chevron-down"></i>
</button>
<div class="dropdown-menu dropdown-menu-selectable dropdown-open-left">
<ul>
<li>
<a
href="#"
@click.prevent="updateViewer('editor')"
:class="{
'is-active': viewer === 'editor',
}"
>
<strong class="dropdown-menu-inner-title">Editing</strong>
<span class="dropdown-menu-inner-content">
View and edit lines
</span>
</a>
</li>
<li>
<a
href="#"
@click.prevent="updateViewer('diff')"
:class="{
'is-active': viewer === 'diff',
}"
>
<strong class="dropdown-menu-inner-title">Reviewing</strong>
<span class="dropdown-menu-inner-content">
Compare changes with the last commit
</span>
</a>
</li>
</ul>
</div>
</div>
</div>
</template> </template>
...@@ -26,6 +26,9 @@ export default class Model { ...@@ -26,6 +26,9 @@ export default class Model {
this.events = new Map(); this.events = new Map();
this.updateContent = this.updateContent.bind(this); this.updateContent = this.updateContent.bind(this);
this.dispose = this.dispose.bind(this);
eventHub.$on(`editor.update.model.dispose.${this.file.path}`, this.dispose);
eventHub.$on(`editor.update.model.content.${this.file.path}`, this.updateContent); eventHub.$on(`editor.update.model.content.${this.file.path}`, this.updateContent);
} }
...@@ -75,6 +78,7 @@ export default class Model { ...@@ -75,6 +78,7 @@ export default class Model {
this.disposable.dispose(); this.disposable.dispose();
this.events.clear(); this.events.clear();
eventHub.$off(`editor.update.model.dispose.${this.file.path}`, this.dispose);
eventHub.$off(`editor.update.model.content.${this.file.path}`, this.updateContent); eventHub.$off(`editor.update.model.content.${this.file.path}`, this.updateContent);
} }
} }
import eventHub from 'ee/ide/eventhub';
import Disposable from './disposable'; import Disposable from './disposable';
import Model from './model'; import Model from './model';
...@@ -25,9 +26,17 @@ export default class ModelManager { ...@@ -25,9 +26,17 @@ export default class ModelManager {
this.models.set(model.path, model); this.models.set(model.path, model);
this.disposable.add(model); this.disposable.add(model);
eventHub.$on(`editor.update.model.dispose.${file.path}`, this.removeCachedModel.bind(this, file));
return model; return model;
} }
removeCachedModel(file) {
this.models.delete(file.path);
eventHub.$off(`editor.update.model.dispose.${file.path}`, this.removeCachedModel);
}
dispose() { dispose() {
// dispose of all the models // dispose of all the models
this.disposable.dispose(); this.disposable.dispose();
......
...@@ -34,6 +34,10 @@ export default class Editor { ...@@ -34,6 +34,10 @@ export default class Editor {
createInstance(domElement) { createInstance(domElement) {
if (!this.instance) { if (!this.instance) {
Object.assign(domElement, {
innerHTML: '',
});
this.disposable.add( this.disposable.add(
this.instance = this.monaco.editor.create(domElement, { this.instance = this.monaco.editor.create(domElement, {
model: null, model: null,
...@@ -53,11 +57,36 @@ export default class Editor { ...@@ -53,11 +57,36 @@ export default class Editor {
} }
} }
createDiffInstance(domElement) {
if (!this.instance) {
Object.assign(domElement, {
innerHTML: '',
});
this.disposable.add(
this.instance = this.monaco.editor.createDiffEditor(domElement, {
readOnly: true,
}),
);
window.addEventListener('resize', this.debouncedUpdate, false);
}
}
createModel(file) { createModel(file) {
return this.modelManager.addModel(file); return this.modelManager.addModel(file);
} }
attachModel(model) { attachModel(model) {
if (this.instance.getEditorType() === 'vs.editor.IDiffEditor') {
this.instance.setModel({
original: model.getOriginalModel(),
modified: model.getModel(),
});
return;
}
this.instance.setModel(model.getModel()); this.instance.setModel(model.getModel());
if (this.dirtyDiffController) this.dirtyDiffController.attachModel(model); if (this.dirtyDiffController) this.dirtyDiffController.attachModel(model);
...@@ -113,6 +142,8 @@ export default class Editor { ...@@ -113,6 +142,8 @@ export default class Editor {
} }
onPositionChange(cb) { onPositionChange(cb) {
if (!this.instance.onDidChangeCursorPosition) return;
this.disposable.add( this.disposable.add(
this.instance.onDidChangeCursorPosition(e => cb(this.instance, e)), this.instance.onDidChangeCursorPosition(e => cb(this.instance, e)),
); );
......
...@@ -84,6 +84,10 @@ export const scrollToTab = () => { ...@@ -84,6 +84,10 @@ export const scrollToTab = () => {
}); });
}; };
export const updateViewer = ({ commit }, viewer) => {
commit(types.UPDATE_VIEWER, viewer);
};
export * from './actions/tree'; export * from './actions/tree';
export * from './actions/file'; export * from './actions/file';
export * from './actions/project'; export * from './actions/project';
......
import { normalizeHeaders } from '~/lib/utils/common_utils'; import { normalizeHeaders } from '~/lib/utils/common_utils';
import flash from '~/flash'; import flash from '~/flash';
import eventHub from 'ee/ide/eventhub';
import service from '../../services'; import service from '../../services';
import * as types from '../mutation_types'; import * as types from '../mutation_types';
import router from '../../ide_router'; import router from '../../ide_router';
...@@ -27,6 +28,8 @@ export const closeFile = ({ commit, state, dispatch }, file) => { ...@@ -27,6 +28,8 @@ export const closeFile = ({ commit, state, dispatch }, file) => {
} }
dispatch('getLastCommitData'); dispatch('getLastCommitData');
eventHub.$emit(`editor.update.model.dispose.${file.path}`);
}; };
export const setFileActive = ({ commit, state, getters, dispatch }, file) => { export const setFileActive = ({ commit, state, getters, dispatch }, file) => {
......
...@@ -46,3 +46,5 @@ export const SET_EDIT_MODE = 'SET_EDIT_MODE'; ...@@ -46,3 +46,5 @@ export const SET_EDIT_MODE = 'SET_EDIT_MODE';
export const TOGGLE_EDIT_MODE = 'TOGGLE_EDIT_MODE'; export const TOGGLE_EDIT_MODE = 'TOGGLE_EDIT_MODE';
export const SET_CURRENT_BRANCH = 'SET_CURRENT_BRANCH'; export const SET_CURRENT_BRANCH = 'SET_CURRENT_BRANCH';
export const UPDATE_VIEWER = 'UPDATE_VIEWER';
...@@ -57,6 +57,11 @@ export default { ...@@ -57,6 +57,11 @@ export default {
lastCommitMsg, lastCommitMsg,
}); });
}, },
[types.UPDATE_VIEWER](state, viewer) {
Object.assign(state, {
viewer,
});
},
...projectMutations, ...projectMutations,
...fileMutations, ...fileMutations,
...treeMutations, ...treeMutations,
......
...@@ -20,4 +20,5 @@ export default () => ({ ...@@ -20,4 +20,5 @@ export default () => ({
leftPanelCollapsed: false, leftPanelCollapsed: false,
rightPanelCollapsed: false, rightPanelCollapsed: false,
panelResizing: false, panelResizing: false,
viewer: 'editor',
}); });
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