Commit 8f72bdfd authored by Tim Zallmann's avatar Tim Zallmann

Merge branch 'ide-open-file-bug' into 'master'

Restore changed file status in IDE

See merge request gitlab-org/gitlab-ee!4462
parents d2330777 90b9d07f
...@@ -27,28 +27,38 @@ ...@@ -27,28 +27,38 @@
return { return {
openModal: false, openModal: false,
modalType: '', modalType: '',
dropdownOpen: false,
}; };
}, },
methods: { methods: {
createNewItem(type) { createNewItem(type) {
this.modalType = type; this.modalType = type;
this.openModal = true; this.openModal = true;
this.dropdownOpen = false;
}, },
hideModal() { hideModal() {
this.openModal = false; this.openModal = false;
}, },
openDropdown() {
this.dropdownOpen = !this.dropdownOpen;
},
}, },
}; };
</script> </script>
<template> <template>
<div class="repo-new-btn pull-right"> <div class="repo-new-btn pull-right">
<div class="dropdown"> <div
class="dropdown"
:class="{
open: dropdownOpen,
}"
>
<button <button
type="button" type="button"
class="btn btn-sm btn-default dropdown-toggle add-to-tree" class="btn btn-sm btn-default dropdown-toggle add-to-tree"
data-toggle="dropdown"
aria-label="Create new file or directory" aria-label="Create new file or directory"
@click.stop="openDropdown()"
> >
<icon <icon
name="plus" name="plus"
...@@ -66,7 +76,7 @@ ...@@ -66,7 +76,7 @@
<a <a
href="#" href="#"
role="button" role="button"
@click.prevent="createNewItem('blob')" @click.stop.prevent="createNewItem('blob')"
> >
{{ __('New file') }} {{ __('New file') }}
</a> </a>
...@@ -82,7 +92,7 @@ ...@@ -82,7 +92,7 @@
<a <a
href="#" href="#"
role="button" role="button"
@click.prevent="createNewItem('tree')" @click.stop.prevent="createNewItem('tree')"
> >
{{ __('New directory') }} {{ __('New directory') }}
</a> </a>
......
...@@ -73,7 +73,7 @@ ...@@ -73,7 +73,7 @@
<a <a
href="#" href="#"
role="button" role="button"
@click.prevent="startFileUpload" @click.stop.prevent="startFileUpload"
> >
{{ __('Upload file') }} {{ __('Upload file') }}
</a> </a>
......
...@@ -93,10 +93,12 @@ export default { ...@@ -93,10 +93,12 @@ export default {
this.editor.attachModel(this.model); this.editor.attachModel(this.model);
this.model.onChange((m) => { this.model.onChange((m) => {
this.changeFileContent({ if (this.model.file.active) {
file: this.activeFile, this.changeFileContent({
content: m.getValue(), file: this.model.file,
}); content: m.getValue(),
});
}
}); });
// Handle Cursor Position // Handle Cursor Position
......
...@@ -91,10 +91,11 @@ ...@@ -91,10 +91,11 @@
<tr <tr
class="file" class="file"
:class="fileClass" :class="fileClass"
@click="clickFile(file)"> >
<td <td
class="multi-file-table-name" class="multi-file-table-name"
:colspan="submoduleColSpan" :colspan="submoduleColSpan"
@click="clickFile(file)"
> >
<a <a
class="repo-file-name str-truncated" class="repo-file-name str-truncated"
......
...@@ -21,7 +21,7 @@ export const closeFile = ({ commit, state, dispatch }, file) => { ...@@ -21,7 +21,7 @@ export const closeFile = ({ commit, state, dispatch }, file) => {
const nextIndexToOpen = indexOfClosedFile === 0 ? 0 : indexOfClosedFile - 1; const nextIndexToOpen = indexOfClosedFile === 0 ? 0 : indexOfClosedFile - 1;
const nextFileToOpen = state.openFiles[nextIndexToOpen]; const nextFileToOpen = state.openFiles[nextIndexToOpen];
dispatch('setFileActive', nextFileToOpen); router.push(`/project${nextFileToOpen.url}`);
} else if (!state.openFiles.length) { } else if (!state.openFiles.length) {
router.push(`/project/${file.projectId}/tree/${file.branchId}/`); router.push(`/project/${file.projectId}/tree/${file.branchId}/`);
} }
......
...@@ -38,7 +38,7 @@ export const getTreeData = ( ...@@ -38,7 +38,7 @@ export const getTreeData = (
commit(types.SET_ROOT, data.path === '/'); commit(types.SET_ROOT, data.path === '/');
} }
dispatch('updateDirectoryData', { data, tree, projectId, branch }); dispatch('updateDirectoryData', { data, tree, projectId, branch, clearTree: false });
const selectedTree = tree || state.trees[`${projectId}/${branch}`]; const selectedTree = tree || state.trees[`${projectId}/${branch}`];
commit(types.SET_PARENT_TREE_URL, data.parent_tree_url); commit(types.SET_PARENT_TREE_URL, data.parent_tree_url);
...@@ -84,7 +84,11 @@ export const handleTreeEntryAction = ({ commit, dispatch }, row) => { ...@@ -84,7 +84,11 @@ export const handleTreeEntryAction = ({ commit, dispatch }, row) => {
} else if (row.type === 'submodule') { } else if (row.type === 'submodule') {
commit(types.TOGGLE_LOADING, row); commit(types.TOGGLE_LOADING, row);
visitUrl(row.url); visitUrl(row.url);
} else if (row.type === 'blob' && row.opened) { } else if (row.type === 'blob' && (row.opened || row.changed)) {
if (row.changed && !row.opened) {
commit(types.TOGGLE_FILE_OPEN, row);
}
dispatch('setFileActive', row); dispatch('setFileActive', row);
} else { } else {
dispatch('getFileData', row); dispatch('getFileData', row);
...@@ -156,7 +160,7 @@ export const getLastCommitData = ({ state, commit, dispatch, getters }, tree = s ...@@ -156,7 +160,7 @@ export const getLastCommitData = ({ state, commit, dispatch, getters }, tree = s
export const updateDirectoryData = ( export const updateDirectoryData = (
{ commit, state }, { commit, state },
{ data, tree, projectId, branch }, { data, tree, projectId, branch, clearTree = true },
) => { ) => {
if (!tree) { if (!tree) {
const existingTree = state.trees[`${projectId}/${branch}`]; const existingTree = state.trees[`${projectId}/${branch}`];
...@@ -169,20 +173,28 @@ export const updateDirectoryData = ( ...@@ -169,20 +173,28 @@ export const updateDirectoryData = (
const level = selectedTree.level !== undefined ? selectedTree.level + 1 : 0; const level = selectedTree.level !== undefined ? selectedTree.level + 1 : 0;
const parentTreeUrl = data.parent_tree_url ? `${data.parent_tree_url}${data.path}` : state.endpoints.rootUrl; const parentTreeUrl = data.parent_tree_url ? `${data.parent_tree_url}${data.path}` : state.endpoints.rootUrl;
const createEntry = (entry, type) => createOrMergeEntry({ const createEntry = (entry, type) => createOrMergeEntry({
tree: selectedTree,
projectId: `${projectId}`, projectId: `${projectId}`,
branchId: branch, branchId: branch,
entry, entry,
level, level,
type, type,
parentTreeUrl, parentTreeUrl,
state,
}); });
const formattedData = [ let formattedData = [
...data.trees.map(t => createEntry(t, 'tree')), ...data.trees.map(t => createEntry(t, 'tree')),
...data.submodules.map(m => createEntry(m, 'submodule')), ...data.submodules.map(m => createEntry(m, 'submodule')),
...data.blobs.map(b => createEntry(b, 'blob')), ...data.blobs.map(b => createEntry(b, 'blob')),
]; ];
if (!clearTree && tree) {
const tempFiles = state.changedFiles.filter(f => f.tempFile && f.path === `${tree.path}/${f.name}`);
if (tempFiles.length) {
formattedData = formattedData.concat(tempFiles);
}
}
commit(types.SET_DIRECTORY_DATA, { tree: selectedTree, data: formattedData }); commit(types.SET_DIRECTORY_DATA, { tree: selectedTree, data: formattedData });
}; };
...@@ -155,21 +155,27 @@ export const createTemp = ({ ...@@ -155,21 +155,27 @@ export const createTemp = ({
}); });
}; };
export const createOrMergeEntry = ({ tree, export const createOrMergeEntry = ({ projectId,
projectId,
branchId, branchId,
entry, entry,
type, type,
parentTreeUrl, parentTreeUrl,
level }) => { level,
const found = findEntry(tree.tree || tree, type, entry.name); state }) => {
if (state.changedFiles.length) {
if (found) { const foundChangedFile = findEntry(state.changedFiles, type, entry.name);
return Object.assign({}, found, {
id: entry.id, if (foundChangedFile) {
url: entry.url, return foundChangedFile;
tempFile: false, }
}); }
if (state.openFiles.length) {
const foundOpenFile = findEntry(state.openFiles, type, entry.name);
if (foundOpenFile) {
return foundOpenFile;
}
} }
return decorateData({ return decorateData({
......
...@@ -66,7 +66,7 @@ describe('RepoFile', () => { ...@@ -66,7 +66,7 @@ describe('RepoFile', () => {
spyOn(vm, 'clickFile'); spyOn(vm, 'clickFile');
vm.$el.click(); vm.$el.querySelector('td').click();
expect(vm.clickFile).toHaveBeenCalledWith(vm.file); expect(vm.clickFile).toHaveBeenCalledWith(vm.file);
}); });
......
...@@ -55,20 +55,6 @@ describe('Multi-file store file actions', () => { ...@@ -55,20 +55,6 @@ describe('Multi-file store file actions', () => {
.catch(done.fail); .catch(done.fail);
}); });
it('sets next file as active', (done) => {
const f = file('otherfile');
store.state.openFiles.push(f);
expect(f.active).toBeFalsy();
store.dispatch('closeFile', localFile)
.then(() => {
expect(f.active).toBeTruthy();
done();
}).catch(done.fail);
});
it('calls getLastCommitData', (done) => { it('calls getLastCommitData', (done) => {
store.dispatch('closeFile', localFile) store.dispatch('closeFile', localFile)
.then(() => { .then(() => {
......
...@@ -39,7 +39,7 @@ describe('Multi-file store tree actions', () => { ...@@ -39,7 +39,7 @@ describe('Multi-file store tree actions', () => {
last_commit_path: 'last_commit_path', last_commit_path: 'last_commit_path',
parent_tree_url: 'parent_tree_url', parent_tree_url: 'parent_tree_url',
path: '/', path: '/',
trees: [{ name: 'tree' }], trees: [{ name: 'tree', path: 'tree' }],
blobs: [{ name: 'blob' }], blobs: [{ name: 'blob' }],
submodules: [{ name: 'submodule' }], submodules: [{ name: 'submodule' }],
}), }),
...@@ -68,6 +68,30 @@ describe('Multi-file store tree actions', () => { ...@@ -68,6 +68,30 @@ describe('Multi-file store tree actions', () => {
}).catch(done.fail); }).catch(done.fail);
}); });
it('adds temp files into tree', (done) => {
const f = {
...file('tempFile'),
path: 'tree/tempFile',
tempFile: true,
};
store.state.changedFiles.push(f);
store.dispatch('getTreeData', basicCallParameters)
.then(() => store.dispatch('getTreeData', {
...basicCallParameters,
tree: store.state.trees['abcproject/master'].tree[0],
}))
.then(() => {
const tree = store.state.trees['abcproject/master'].tree[0].tree;
expect(tree.length).toBe(4);
expect(tree[3].name).toBe(f.name);
done();
}).catch(done.fail);
});
it('sets parent tree URL', (done) => { it('sets parent tree URL', (done) => {
store.dispatch('getTreeData', basicCallParameters) store.dispatch('getTreeData', basicCallParameters)
.then(() => { .then(() => {
...@@ -346,5 +370,61 @@ describe('Multi-file store tree actions', () => { ...@@ -346,5 +370,61 @@ describe('Multi-file store tree actions', () => {
done(); done();
}).catch(done.fail); }).catch(done.fail);
}); });
it('adds changed state of an already existing file', (done) => {
const f = file('changedFile');
const tree = {
tree: [],
};
const data = {
trees: [{ name: 'tree' }],
submodules: [{ name: 'submodule' }],
blobs: [f],
};
store.state.changedFiles.push({
...f,
type: 'blob',
changed: true,
});
store.dispatch('updateDirectoryData', {
data,
tree,
clearTree: false,
}).then(() => {
expect(tree.tree[2].changed).toBeTruthy();
done();
}).catch(done.fail);
});
it('adds opened state of an already existing file', (done) => {
const f = file('openedFile');
const tree = {
tree: [],
};
const data = {
trees: [{ name: 'tree' }],
submodules: [{ name: 'submodule' }],
blobs: [f],
};
store.state.openFiles.push({
...f,
type: 'blob',
opened: true,
});
store.dispatch('updateDirectoryData', {
data,
tree,
clearTree: false,
}).then(() => {
expect(tree.tree[2].opened).toBeTruthy();
done();
}).catch(done.fail);
});
}); });
}); });
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