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 @@
return {
openModal: false,
modalType: '',
dropdownOpen: false,
};
},
methods: {
createNewItem(type) {
this.modalType = type;
this.openModal = true;
this.dropdownOpen = false;
},
hideModal() {
this.openModal = false;
},
openDropdown() {
this.dropdownOpen = !this.dropdownOpen;
},
},
};
</script>
<template>
<div class="repo-new-btn pull-right">
<div class="dropdown">
<div
class="dropdown"
:class="{
open: dropdownOpen,
}"
>
<button
type="button"
class="btn btn-sm btn-default dropdown-toggle add-to-tree"
data-toggle="dropdown"
aria-label="Create new file or directory"
@click.stop="openDropdown()"
>
<icon
name="plus"
......@@ -66,7 +76,7 @@
<a
href="#"
role="button"
@click.prevent="createNewItem('blob')"
@click.stop.prevent="createNewItem('blob')"
>
{{ __('New file') }}
</a>
......@@ -82,7 +92,7 @@
<a
href="#"
role="button"
@click.prevent="createNewItem('tree')"
@click.stop.prevent="createNewItem('tree')"
>
{{ __('New directory') }}
</a>
......
......@@ -73,7 +73,7 @@
<a
href="#"
role="button"
@click.prevent="startFileUpload"
@click.stop.prevent="startFileUpload"
>
{{ __('Upload file') }}
</a>
......
......@@ -93,10 +93,12 @@ export default {
this.editor.attachModel(this.model);
this.model.onChange((m) => {
this.changeFileContent({
file: this.activeFile,
content: m.getValue(),
});
if (this.model.file.active) {
this.changeFileContent({
file: this.model.file,
content: m.getValue(),
});
}
});
// Handle Cursor Position
......
......@@ -91,10 +91,11 @@
<tr
class="file"
:class="fileClass"
@click="clickFile(file)">
>
<td
class="multi-file-table-name"
:colspan="submoduleColSpan"
@click="clickFile(file)"
>
<a
class="repo-file-name str-truncated"
......
......@@ -21,7 +21,7 @@ export const closeFile = ({ commit, state, dispatch }, file) => {
const nextIndexToOpen = indexOfClosedFile === 0 ? 0 : indexOfClosedFile - 1;
const nextFileToOpen = state.openFiles[nextIndexToOpen];
dispatch('setFileActive', nextFileToOpen);
router.push(`/project${nextFileToOpen.url}`);
} else if (!state.openFiles.length) {
router.push(`/project/${file.projectId}/tree/${file.branchId}/`);
}
......
......@@ -38,7 +38,7 @@ export const getTreeData = (
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}`];
commit(types.SET_PARENT_TREE_URL, data.parent_tree_url);
......@@ -84,7 +84,11 @@ export const handleTreeEntryAction = ({ commit, dispatch }, row) => {
} else if (row.type === 'submodule') {
commit(types.TOGGLE_LOADING, row);
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);
} else {
dispatch('getFileData', row);
......@@ -156,7 +160,7 @@ export const getLastCommitData = ({ state, commit, dispatch, getters }, tree = s
export const updateDirectoryData = (
{ commit, state },
{ data, tree, projectId, branch },
{ data, tree, projectId, branch, clearTree = true },
) => {
if (!tree) {
const existingTree = state.trees[`${projectId}/${branch}`];
......@@ -169,20 +173,28 @@ export const updateDirectoryData = (
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 createEntry = (entry, type) => createOrMergeEntry({
tree: selectedTree,
projectId: `${projectId}`,
branchId: branch,
entry,
level,
type,
parentTreeUrl,
state,
});
const formattedData = [
let formattedData = [
...data.trees.map(t => createEntry(t, 'tree')),
...data.submodules.map(m => createEntry(m, 'submodule')),
...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 });
};
......@@ -155,21 +155,27 @@ export const createTemp = ({
});
};
export const createOrMergeEntry = ({ tree,
projectId,
export const createOrMergeEntry = ({ projectId,
branchId,
entry,
type,
parentTreeUrl,
level }) => {
const found = findEntry(tree.tree || tree, type, entry.name);
if (found) {
return Object.assign({}, found, {
id: entry.id,
url: entry.url,
tempFile: false,
});
level,
state }) => {
if (state.changedFiles.length) {
const foundChangedFile = findEntry(state.changedFiles, type, entry.name);
if (foundChangedFile) {
return foundChangedFile;
}
}
if (state.openFiles.length) {
const foundOpenFile = findEntry(state.openFiles, type, entry.name);
if (foundOpenFile) {
return foundOpenFile;
}
}
return decorateData({
......
......@@ -66,7 +66,7 @@ describe('RepoFile', () => {
spyOn(vm, 'clickFile');
vm.$el.click();
vm.$el.querySelector('td').click();
expect(vm.clickFile).toHaveBeenCalledWith(vm.file);
});
......
......@@ -55,20 +55,6 @@ describe('Multi-file store file actions', () => {
.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) => {
store.dispatch('closeFile', localFile)
.then(() => {
......
......@@ -39,7 +39,7 @@ describe('Multi-file store tree actions', () => {
last_commit_path: 'last_commit_path',
parent_tree_url: 'parent_tree_url',
path: '/',
trees: [{ name: 'tree' }],
trees: [{ name: 'tree', path: 'tree' }],
blobs: [{ name: 'blob' }],
submodules: [{ name: 'submodule' }],
}),
......@@ -68,6 +68,30 @@ describe('Multi-file store tree actions', () => {
}).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) => {
store.dispatch('getTreeData', basicCallParameters)
.then(() => {
......@@ -346,5 +370,61 @@ describe('Multi-file store tree actions', () => {
done();
}).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