summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhil Hughes <me@iamphill.com>2018-01-10 12:52:30 +0000
committerPhil Hughes <me@iamphill.com>2018-02-07 09:10:01 +0000
commitf9be0a48e9292b0234be06ab9765e6d3b524db65 (patch)
tree1e616eb9cbd142c0a5f555269690c5b3a1e12dd2
parent826105dfda91081e92dfd5ca7f85a1343893e049 (diff)
downloadgitlab-ce-f9be0a48e9292b0234be06ab9765e6d3b524db65.tar.gz
Added changed state to IDE
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/list_item.vue13
-rw-r--r--app/assets/javascripts/ide/components/ide.vue2
-rw-r--r--app/assets/javascripts/ide/components/ide_context_bar.vue4
-rw-r--r--app/assets/javascripts/ide/components/repo_commit_section.vue4
-rw-r--r--app/assets/javascripts/ide/components/repo_edit_button.vue12
-rw-r--r--app/assets/javascripts/ide/components/repo_editor.vue20
-rw-r--r--app/assets/javascripts/ide/components/repo_tab.vue42
-rw-r--r--app/assets/javascripts/ide/lib/common/model.js4
-rw-r--r--app/assets/javascripts/ide/stores/actions.js37
-rw-r--r--app/assets/javascripts/ide/stores/actions/file.js24
-rw-r--r--app/assets/javascripts/ide/stores/getters.js2
-rw-r--r--app/assets/javascripts/ide/stores/mutation_types.js4
-rw-r--r--app/assets/javascripts/ide/stores/mutations.js5
-rw-r--r--app/assets/javascripts/ide/stores/mutations/file.js8
-rw-r--r--app/assets/javascripts/ide/stores/state.js2
-rw-r--r--app/assets/stylesheets/pages/repo.scss17
-rw-r--r--spec/javascripts/repo/components/commit_sidebar/list_collapsed_spec.js9
-rw-r--r--spec/javascripts/repo/components/commit_sidebar/list_item_spec.js8
-rw-r--r--spec/javascripts/repo/components/repo_commit_section_spec.js8
-rw-r--r--spec/javascripts/repo/components/repo_edit_button_spec.js25
-rw-r--r--spec/javascripts/repo/components/repo_editor_spec.js14
-rw-r--r--spec/javascripts/repo/components/repo_tab_spec.js36
-rw-r--r--spec/javascripts/repo/lib/common/model_spec.js8
-rw-r--r--spec/javascripts/repo/stores/actions/file_spec.js161
-rw-r--r--spec/javascripts/repo/stores/actions_spec.js62
-rw-r--r--spec/javascripts/repo/stores/getters_spec.js23
-rw-r--r--spec/javascripts/repo/stores/mutations/file_spec.js33
-rw-r--r--spec/javascripts/repo/stores/mutations_spec.js12
28 files changed, 361 insertions, 238 deletions
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue b/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue
index 742f746e02f..6421f3b8681 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue
@@ -1,4 +1,5 @@
<script>
+ import { mapActions } from 'vuex';
import icon from '../../../vue_shared/components/icon.vue';
export default {
@@ -19,6 +20,11 @@
return `multi-file-${this.file.tempFile ? 'addition' : 'modified'} append-right-8`;
},
},
+ methods: {
+ ...mapActions([
+ 'discardFileChanges',
+ ]),
+ },
};
</script>
@@ -32,5 +38,12 @@
<span class="multi-file-commit-list-path">
{{ file.path }}
</span>
+ <button
+ type="button"
+ class="btn btn-blank multi-file-discard-btn"
+ @click="discardFileChanges(file)"
+ >
+ Discard
+ </button>
</div>
</template>
diff --git a/app/assets/javascripts/ide/components/ide.vue b/app/assets/javascripts/ide/components/ide.vue
index 89981ab2c65..74ac4be5b3c 100644
--- a/app/assets/javascripts/ide/components/ide.vue
+++ b/app/assets/javascripts/ide/components/ide.vue
@@ -28,9 +28,9 @@
...mapState([
'currentBlobView',
'selectedFile',
+ 'changedFiles',
]),
...mapGetters([
- 'changedFiles',
'activeFile',
]),
},
diff --git a/app/assets/javascripts/ide/components/ide_context_bar.vue b/app/assets/javascripts/ide/components/ide_context_bar.vue
index dd947f66969..dd792ba87d7 100644
--- a/app/assets/javascripts/ide/components/ide_context_bar.vue
+++ b/app/assets/javascripts/ide/components/ide_context_bar.vue
@@ -1,5 +1,5 @@
<script>
- import { mapGetters, mapState, mapActions } from 'vuex';
+ import { mapState, mapActions } from 'vuex';
import repoCommitSection from './repo_commit_section.vue';
import icon from '../../vue_shared/components/icon.vue';
import panelResizer from '../../vue_shared/components/panel_resizer.vue';
@@ -18,8 +18,6 @@
computed: {
...mapState([
'rightPanelCollapsed',
- ]),
- ...mapGetters([
'changedFiles',
]),
currentIcon() {
diff --git a/app/assets/javascripts/ide/components/repo_commit_section.vue b/app/assets/javascripts/ide/components/repo_commit_section.vue
index 96b1bb78c1d..8cdd34857a9 100644
--- a/app/assets/javascripts/ide/components/repo_commit_section.vue
+++ b/app/assets/javascripts/ide/components/repo_commit_section.vue
@@ -1,5 +1,5 @@
<script>
-import { mapGetters, mapState, mapActions } from 'vuex';
+import { mapState, mapActions } from 'vuex';
import tooltip from '../../vue_shared/directives/tooltip';
import icon from '../../vue_shared/components/icon.vue';
import modal from '../../vue_shared/components/modal.vue';
@@ -27,8 +27,6 @@ export default {
'currentProjectId',
'currentBranchId',
'rightPanelCollapsed',
- ]),
- ...mapGetters([
'changedFiles',
]),
commitButtonDisabled() {
diff --git a/app/assets/javascripts/ide/components/repo_edit_button.vue b/app/assets/javascripts/ide/components/repo_edit_button.vue
index c43e9163340..280da6efae1 100644
--- a/app/assets/javascripts/ide/components/repo_edit_button.vue
+++ b/app/assets/javascripts/ide/components/repo_edit_button.vue
@@ -9,7 +9,6 @@ export default {
computed: {
...mapState([
'editMode',
- 'discardPopupOpen',
]),
...mapGetters([
'canEditFile',
@@ -21,7 +20,6 @@ export default {
methods: {
...mapActions([
'toggleEditMode',
- 'closeDiscardPopup',
]),
},
};
@@ -43,15 +41,5 @@ export default {
{{ buttonLabel }}
</span>
</button>
- <modal
- v-if="discardPopupOpen"
- class="text-left"
- :primary-button-label="__('Discard changes')"
- kind="warning"
- :title="__('Are you sure?')"
- :text="__('Are you sure you want to discard your changes?')"
- @cancel="closeDiscardPopup"
- @submit="toggleEditMode(true)"
- />
</div>
</template>
diff --git a/app/assets/javascripts/ide/components/repo_editor.vue b/app/assets/javascripts/ide/components/repo_editor.vue
index f99228012f4..8aeb64027b9 100644
--- a/app/assets/javascripts/ide/components/repo_editor.vue
+++ b/app/assets/javascripts/ide/components/repo_editor.vue
@@ -19,6 +19,9 @@ export default {
shouldHideEditor() {
return this.activeFile.binary && !this.activeFile.raw;
},
+ activeFileChanged() {
+ return this.activeFile && this.activeFile.changed;
+ },
},
watch: {
activeFile(oldVal, newVal) {
@@ -26,6 +29,13 @@ export default {
this.initMonaco();
}
},
+ activeFileChanged(newVal) {
+ if (!this.editor) return;
+
+ if (!newVal && this.model) {
+ this.model.setValue(this.model.getOriginalModel().getValue());
+ }
+ },
leftPanelCollapsed() {
this.editor.updateDimensions();
},
@@ -78,11 +88,11 @@ export default {
setupEditor() {
if (!this.activeFile) return;
- const model = this.editor.createModel(this.activeFile);
+ this.model = this.editor.createModel(this.activeFile);
- this.editor.attachModel(model);
+ this.editor.attachModel(this.model);
- model.onChange((m) => {
+ this.model.onChange((m) => {
this.changeFileContent({
file: this.activeFile,
content: m.getValue(),
@@ -104,12 +114,12 @@ export default {
// Handle File Language
this.setFileLanguage({
- fileLanguage: model.language,
+ fileLanguage: this.model.language,
});
// Get File eol
this.setFileEOL({
- eol: model.eol,
+ eol: this.model.eol,
});
},
},
diff --git a/app/assets/javascripts/ide/components/repo_tab.vue b/app/assets/javascripts/ide/components/repo_tab.vue
index 5ed7bddf6ae..006987ffaf6 100644
--- a/app/assets/javascripts/ide/components/repo_tab.vue
+++ b/app/assets/javascripts/ide/components/repo_tab.vue
@@ -12,6 +12,11 @@
required: true,
},
},
+ data() {
+ return {
+ tabMouseOver: false,
+ };
+ },
computed: {
closeLabel() {
if (this.tab.changed || this.tab.tempFile) {
@@ -19,12 +24,8 @@
}
return `Close ${this.tab.name}`;
},
- changedClass() {
- const tabChangedObj = {
- 'fa-times close-icon': !this.tab.changed && !this.tab.tempFile,
- 'fa-circle unsaved-icon': this.tab.changed || this.tab.tempFile,
- };
- return tabChangedObj;
+ showChangedIcon() {
+ return this.tab.changed ? !this.tabMouseOver : false;
},
},
@@ -35,25 +36,44 @@
clickFile(tab) {
this.$router.push(`/project${tab.url}`);
},
+ mouseOverTab() {
+ if (this.tab.changed) {
+ this.tabMouseOver = true;
+ }
+ },
+ mouseOutTab() {
+ if (this.tab.changed) {
+ this.tabMouseOver = false;
+ }
+ },
},
};
</script>
<template>
- <li @click="clickFile(tab)">
+ <li
+ @click="clickFile(tab)"
+ @mouseover="mouseOverTab"
+ @mouseout="mouseOutTab"
+ >
<button
type="button"
class="multi-file-tab-close"
- @click.stop.prevent="closeFile({ file: tab })"
+ @click.stop.prevent="closeFile(tab)"
:aria-label="closeLabel"
:class="{
'modified': tab.changed,
}"
- :disabled="tab.changed"
>
<i
- class="fa"
- :class="changedClass"
+ v-if="!showChangedIcon"
+ class="fa fa-times close-icon"
+ aria-hidden="true"
+ >
+ </i>
+ <i
+ v-else
+ class="fa fa-circle unsaved-icon"
aria-hidden="true"
>
</i>
diff --git a/app/assets/javascripts/ide/lib/common/model.js b/app/assets/javascripts/ide/lib/common/model.js
index 14d9fe4771e..f4e1b14e258 100644
--- a/app/assets/javascripts/ide/lib/common/model.js
+++ b/app/assets/javascripts/ide/lib/common/model.js
@@ -48,6 +48,10 @@ export default class Model {
return this.originalModel;
}
+ setValue(value) {
+ this.getModel().setValue(value);
+ }
+
onChange(cb) {
this.events.set(
this.path,
diff --git a/app/assets/javascripts/ide/stores/actions.js b/app/assets/javascripts/ide/stores/actions.js
index d007d0ae78f..385349e8219 100644
--- a/app/assets/javascripts/ide/stores/actions.js
+++ b/app/assets/javascripts/ide/stores/actions.js
@@ -10,42 +10,23 @@ export const redirectToUrl = (_, url) => visitUrl(url);
export const setInitialData = ({ commit }, data) =>
commit(types.SET_INITIAL_DATA, data);
-export const closeDiscardPopup = ({ commit }) =>
- commit(types.TOGGLE_DISCARD_POPUP, false);
-
-export const discardAllChanges = ({ commit, getters, dispatch }) => {
- const changedFiles = getters.changedFiles;
-
- changedFiles.forEach((file) => {
+export const discardAllChanges = ({ state, commit, dispatch }) => {
+ state.changedFiles.forEach((file) => {
commit(types.DISCARD_FILE_CHANGES, file);
if (file.tempFile) {
- dispatch('closeFile', { file, force: true });
+ dispatch('closeFile', file);
}
});
};
export const closeAllFiles = ({ state, dispatch }) => {
- state.openFiles.forEach(file => dispatch('closeFile', { file }));
+ state.openFiles.forEach(file => dispatch('closeFile', file));
};
-export const toggleEditMode = (
- { state, commit, getters, dispatch },
- force = false,
-) => {
- const changedFiles = getters.changedFiles;
-
- if (changedFiles.length && !force) {
- commit(types.TOGGLE_DISCARD_POPUP, true);
- } else {
- commit(types.TOGGLE_EDIT_MODE);
- commit(types.TOGGLE_DISCARD_POPUP, false);
- dispatch('toggleBlobView');
-
- if (!state.editMode) {
- dispatch('discardAllChanges');
- }
- }
+export const toggleEditMode = ({ commit, dispatch }) => {
+ commit(types.TOGGLE_EDIT_MODE);
+ dispatch('toggleBlobView');
};
export const toggleBlobView = ({ commit, state }) => {
@@ -85,7 +66,7 @@ export const checkCommitStatus = ({ state }) =>
.catch(() => flash('Error checking branch data. Please try again.', 'alert', document, null, false, true));
export const commitChanges = (
- { commit, state, dispatch, getters },
+ { commit, state, dispatch },
{ payload, newMr },
) =>
service
@@ -133,7 +114,7 @@ export const commitChanges = (
reference: data.id,
});
- getters.changedFiles.forEach((entry) => {
+ state.changedFiles.forEach((entry) => {
commit(types.SET_LAST_COMMIT_DATA, {
entry,
lastCommit,
diff --git a/app/assets/javascripts/ide/stores/actions/file.js b/app/assets/javascripts/ide/stores/actions/file.js
index 670af2fb89e..d1b3a6ce374 100644
--- a/app/assets/javascripts/ide/stores/actions/file.js
+++ b/app/assets/javascripts/ide/stores/actions/file.js
@@ -10,9 +10,7 @@ import {
findIndexOfFile,
} from '../utils';
-export const closeFile = ({ commit, state, dispatch }, { file, force = false }) => {
- if ((file.changed || file.tempFile) && !force) return;
-
+export const closeFile = ({ commit, state, dispatch }, file) => {
const indexOfClosedFile = findIndexOfFile(state.openFiles, file);
const fileWasActive = file.active;
@@ -79,8 +77,16 @@ export const getRawFileData = ({ commit, dispatch }, file) => service.getRawFile
})
.catch(() => flash('Error loading file content. Please try again.', 'alert', document, null, false, true));
-export const changeFileContent = ({ commit }, { file, content }) => {
+export const changeFileContent = ({ state, commit }, { file, content }) => {
commit(types.UPDATE_FILE_CONTENT, { file, content });
+
+ const indexOfChangedFile = findIndexOfFile(state.changedFiles, file);
+
+ if (file.changed && indexOfChangedFile === -1) {
+ commit(types.ADD_FILE_TO_CHANGED, file);
+ } else if (!file.changed && indexOfChangedFile !== -1) {
+ commit(types.REMOVE_FILE_FROM_CHANGED, file);
+ }
};
export const setFileLanguage = ({ state, commit }, { fileLanguage }) => {
@@ -125,6 +131,7 @@ export const createTempFile = ({ state, commit, dispatch }, { projectId, branchI
file,
});
commit(types.TOGGLE_FILE_OPEN, file);
+ commit(types.ADD_FILE_TO_CHANGED, file);
dispatch('setFileActive', file);
if (!state.editMode && !file.base64) {
@@ -135,3 +142,12 @@ export const createTempFile = ({ state, commit, dispatch }, { projectId, branchI
return Promise.resolve(file);
};
+
+export const discardFileChanges = ({ commit }, file) => {
+ commit(types.DISCARD_FILE_CHANGES, file);
+ commit(types.REMOVE_FILE_FROM_CHANGED, file);
+
+ if (file.tempFile && file.opened) {
+ commit(types.TOGGLE_FILE_OPEN, file);
+ }
+};
diff --git a/app/assets/javascripts/ide/stores/getters.js b/app/assets/javascripts/ide/stores/getters.js
index 6b51ccff817..4073aafe979 100644
--- a/app/assets/javascripts/ide/stores/getters.js
+++ b/app/assets/javascripts/ide/stores/getters.js
@@ -1,4 +1,4 @@
-export const changedFiles = state => state.openFiles.filter(file => file.changed);
+export const changedFiles = state => state.changedFiles;
export const activeFile = state => state.openFiles.find(file => file.active) || null;
diff --git a/app/assets/javascripts/ide/stores/mutation_types.js b/app/assets/javascripts/ide/stores/mutation_types.js
index 69b218a5e7d..ea38084fd3c 100644
--- a/app/assets/javascripts/ide/stores/mutation_types.js
+++ b/app/assets/javascripts/ide/stores/mutation_types.js
@@ -35,12 +35,12 @@ export const SET_FILE_POSITION = 'SET_FILE_POSITION';
export const SET_FILE_EOL = 'SET_FILE_EOL';
export const DISCARD_FILE_CHANGES = 'DISCARD_FILE_CHANGES';
export const CREATE_TMP_FILE = 'CREATE_TMP_FILE';
+export const ADD_FILE_TO_CHANGED = 'ADD_FILE_TO_CHANGED';
+export const REMOVE_FILE_FROM_CHANGED = 'REMOVE_FILE_FROM_CHANGED';
// Viewer mutation types
export const SET_PREVIEW_MODE = 'SET_PREVIEW_MODE';
export const SET_EDIT_MODE = 'SET_EDIT_MODE';
export const TOGGLE_EDIT_MODE = 'TOGGLE_EDIT_MODE';
-export const TOGGLE_DISCARD_POPUP = 'TOGGLE_DISCARD_POPUP';
export const SET_CURRENT_BRANCH = 'SET_CURRENT_BRANCH';
-
diff --git a/app/assets/javascripts/ide/stores/mutations.js b/app/assets/javascripts/ide/stores/mutations.js
index 03d81be10a1..22b0086af79 100644
--- a/app/assets/javascripts/ide/stores/mutations.js
+++ b/app/assets/javascripts/ide/stores/mutations.js
@@ -28,11 +28,6 @@ export default {
editMode: !state.editMode,
});
},
- [types.TOGGLE_DISCARD_POPUP](state, discardPopupOpen) {
- Object.assign(state, {
- discardPopupOpen,
- });
- },
[types.SET_ROOT](state, isRoot) {
Object.assign(state, {
isRoot,
diff --git a/app/assets/javascripts/ide/stores/mutations/file.js b/app/assets/javascripts/ide/stores/mutations/file.js
index 72db1c180c9..5c10c8f624e 100644
--- a/app/assets/javascripts/ide/stores/mutations/file.js
+++ b/app/assets/javascripts/ide/stores/mutations/file.js
@@ -71,4 +71,12 @@ export default {
[types.CREATE_TMP_FILE](state, { file, parent }) {
parent.tree.push(file);
},
+ [types.ADD_FILE_TO_CHANGED](state, file) {
+ state.changedFiles.push(file);
+ },
+ [types.REMOVE_FILE_FROM_CHANGED](state, file) {
+ const indexOfChangedFile = findIndexOfFile(state.changedFiles, file);
+
+ state.changedFiles.splice(indexOfChangedFile, 1);
+ },
};
diff --git a/app/assets/javascripts/ide/stores/state.js b/app/assets/javascripts/ide/stores/state.js
index 61d12096946..d9c49ec81e3 100644
--- a/app/assets/javascripts/ide/stores/state.js
+++ b/app/assets/javascripts/ide/stores/state.js
@@ -3,7 +3,7 @@ export default () => ({
currentProjectId: '',
currentBranchId: '',
currentBlobView: 'repo-editor',
- discardPopupOpen: false,
+ changedFiles: [],
editMode: true,
endpoints: {},
isRoot: false,
diff --git a/app/assets/stylesheets/pages/repo.scss b/app/assets/stylesheets/pages/repo.scss
index 8265b8370f7..4eb8b21404b 100644
--- a/app/assets/stylesheets/pages/repo.scss
+++ b/app/assets/stylesheets/pages/repo.scss
@@ -395,7 +395,24 @@ table.table tr td.multi-file-table-name {
.multi-file-commit-list-item {
display: flex;
+ margin-bottom: $grid-size;
align-items: center;
+
+ > svg {
+ min-width: 16px;
+ }
+
+ .multi-file-discard-btn {
+ display: none;
+ margin-left: auto;
+ color: $gl-link-color;
+ }
+
+ &:hover {
+ .multi-file-discard-btn {
+ display: block;
+ }
+ }
}
.multi-file-addition {
diff --git a/spec/javascripts/repo/components/commit_sidebar/list_collapsed_spec.js b/spec/javascripts/repo/components/commit_sidebar/list_collapsed_spec.js
index debde1bb357..357ab6010ea 100644
--- a/spec/javascripts/repo/components/commit_sidebar/list_collapsed_spec.js
+++ b/spec/javascripts/repo/components/commit_sidebar/list_collapsed_spec.js
@@ -12,13 +12,8 @@ describe('Multi-file editor commit sidebar list collapsed', () => {
vm = createComponentWithStore(Component, store);
- vm.$store.state.openFiles.push(file('file1'), file('file2'));
- vm.$store.state.openFiles[0].tempFile = true;
- vm.$store.state.openFiles.forEach((f) => {
- Object.assign(f, {
- changed: true,
- });
- });
+ vm.$store.state.changedFiles.push(file('file1'), file('file2'));
+ vm.$store.state.changedFiles[0].tempFile = true;
vm.$mount();
});
diff --git a/spec/javascripts/repo/components/commit_sidebar/list_item_spec.js b/spec/javascripts/repo/components/commit_sidebar/list_item_spec.js
index 4b20fdf70d6..5a17e3a10a9 100644
--- a/spec/javascripts/repo/components/commit_sidebar/list_item_spec.js
+++ b/spec/javascripts/repo/components/commit_sidebar/list_item_spec.js
@@ -25,6 +25,14 @@ describe('Multi-file editor commit sidebar list item', () => {
expect(vm.$el.querySelector('.multi-file-commit-list-path').textContent.trim()).toBe(f.path);
});
+ it('calls discardFileChanges when clicking discard button', () => {
+ spyOn(vm, 'discardFileChanges');
+
+ vm.$el.querySelector('.multi-file-discard-btn').click();
+
+ expect(vm.discardFileChanges).toHaveBeenCalled();
+ });
+
describe('computed', () => {
describe('iconName', () => {
it('returns modified when not a tempFile', () => {
diff --git a/spec/javascripts/repo/components/repo_commit_section_spec.js b/spec/javascripts/repo/components/repo_commit_section_spec.js
index 93e94b4f24c..0a1b8259009 100644
--- a/spec/javascripts/repo/components/repo_commit_section_spec.js
+++ b/spec/javascripts/repo/components/repo_commit_section_spec.js
@@ -29,8 +29,8 @@ describe('RepoCommitSection', () => {
comp.$store.state.rightPanelCollapsed = false;
comp.$store.state.currentBranch = 'master';
- comp.$store.state.openFiles = [file('file1'), file('file2')];
- comp.$store.state.openFiles.forEach(f => Object.assign(f, {
+ comp.$store.state.changedFiles = [file('file1'), file('file2')];
+ comp.$store.state.changedFiles.forEach(f => Object.assign(f, {
changed: true,
content: 'testing',
}));
@@ -72,7 +72,7 @@ describe('RepoCommitSection', () => {
expect(changedFileElements.length).toEqual(2);
changedFileElements.forEach((changedFile, i) => {
- expect(changedFile.textContent.trim()).toEqual(vm.$store.getters.changedFiles[i].path);
+ expect(changedFile.textContent.trim()).toEqual(vm.$store.state.changedFiles[i].path);
});
expect(submitCommit.disabled).toBeTruthy();
@@ -84,7 +84,7 @@ describe('RepoCommitSection', () => {
beforeEach(() => {
vm.commitMessage = 'testing';
- changedFiles = JSON.parse(JSON.stringify(vm.$store.getters.changedFiles));
+ changedFiles = JSON.parse(JSON.stringify(vm.$store.state.changedFiles));
spyOn(service, 'commit').and.returnValue(Promise.resolve({
data: {
diff --git a/spec/javascripts/repo/components/repo_edit_button_spec.js b/spec/javascripts/repo/components/repo_edit_button_spec.js
index 2895b794506..7979765c2a3 100644
--- a/spec/javascripts/repo/components/repo_edit_button_spec.js
+++ b/spec/javascripts/repo/components/repo_edit_button_spec.js
@@ -55,29 +55,4 @@ describe('RepoEditButton', () => {
done();
});
});
-
- describe('discardPopupOpen', () => {
- beforeEach(() => {
- vm.$store.state.discardPopupOpen = true;
- vm.$store.state.editMode = true;
- vm.$store.state.openFiles[0].changed = true;
-
- vm.$mount();
- });
-
- it('renders popup', () => {
- expect(vm.$el.querySelector('.modal')).not.toBeNull();
- });
-
- it('removes all changed files', (done) => {
- vm.$el.querySelector('.btn-warning').click();
-
- vm.$nextTick(() => {
- expect(vm.$store.getters.changedFiles.length).toBe(0);
- expect(vm.$el.querySelector('.modal')).toBeNull();
-
- done();
- });
- });
- });
});
diff --git a/spec/javascripts/repo/components/repo_editor_spec.js b/spec/javascripts/repo/components/repo_editor_spec.js
index e7b2ed08acd..6d47fecacc9 100644
--- a/spec/javascripts/repo/components/repo_editor_spec.js
+++ b/spec/javascripts/repo/components/repo_editor_spec.js
@@ -57,4 +57,18 @@ describe('RepoEditor', () => {
expect(vm.$el.textContent).toContain('testing');
});
});
+
+ describe('computed', () => {
+ describe('activeFileChanged', () => {
+ it('returns false when file has no changes', () => {
+ expect(vm.activeFileChanged).toBeFalsy();
+ });
+
+ it('returns true when file has changes', () => {
+ vm.$store.getters.activeFile.changed = true;
+
+ expect(vm.activeFileChanged).toBeTruthy();
+ });
+ });
+ });
});
diff --git a/spec/javascripts/repo/components/repo_tab_spec.js b/spec/javascripts/repo/components/repo_tab_spec.js
index 933e8d3a06a..866c7eb83c2 100644
--- a/spec/javascripts/repo/components/repo_tab_spec.js
+++ b/spec/javascripts/repo/components/repo_tab_spec.js
@@ -52,7 +52,7 @@ describe('RepoTab', () => {
vm.$el.querySelector('.multi-file-tab-close').click();
- expect(vm.closeFile).toHaveBeenCalledWith({ file: vm.tab });
+ expect(vm.closeFile).toHaveBeenCalledWith(vm.tab);
});
it('renders an fa-circle icon if tab is changed', () => {
@@ -65,22 +65,50 @@ describe('RepoTab', () => {
expect(vm.$el.querySelector('.multi-file-tab-close .fa-circle')).not.toBeNull();
});
+ it('changes icon on hover', (done) => {
+ const tab = file();
+ tab.changed = true;
+ vm = createComponent({
+ tab,
+ });
+
+ vm.$el.dispatchEvent(new Event('mouseover'));
+
+ Vue.nextTick()
+ .then(() => {
+ expect(vm.$el.querySelector('.unsaved-icon')).toBeNull();
+ expect(vm.$el.querySelector('.close-icon')).not.toBeNull();
+
+ vm.$el.dispatchEvent(new Event('mouseout'));
+ })
+ .then(Vue.nextTick)
+ .then(() => {
+ expect(vm.$el.querySelector('.close-icon')).toBeNull();
+ expect(vm.$el.querySelector('.unsaved-icon')).not.toBeNull();
+
+ done();
+ })
+ .catch(done.fail);
+ });
+
describe('methods', () => {
describe('closeTab', () => {
- it('does not close tab if is changed', (done) => {
- const tab = file('closeFile');
+ it('closes tab if file has changed', (done) => {
+ const tab = file();
tab.changed = true;
tab.opened = true;
vm = createComponent({
tab,
});
vm.$store.state.openFiles.push(tab);
+ vm.$store.state.changedFiles.push(tab);
vm.$store.dispatch('setFileActive', tab);
vm.$el.querySelector('.multi-file-tab-close').click();
vm.$nextTick(() => {
- expect(tab.opened).toBeTruthy();
+ expect(tab.opened).toBeFalsy();
+ expect(vm.$store.state.changedFiles.length).toBe(1);
done();
});
diff --git a/spec/javascripts/repo/lib/common/model_spec.js b/spec/javascripts/repo/lib/common/model_spec.js
index 878a4a3f3fe..9f23b9a435d 100644
--- a/spec/javascripts/repo/lib/common/model_spec.js
+++ b/spec/javascripts/repo/lib/common/model_spec.js
@@ -41,6 +41,14 @@ describe('Multi-file editor library model', () => {
});
});
+ describe('setValue', () => {
+ it('updates models value', () => {
+ model.setValue('testing 123');
+
+ expect(model.getModel().getValue()).toBe('testing 123');
+ });
+ });
+
describe('onChange', () => {
it('caches event by path', () => {
model.onChange(() => {});
diff --git a/spec/javascripts/repo/stores/actions/file_spec.js b/spec/javascripts/repo/stores/actions/file_spec.js
index e2d8f002e27..419844bb5b4 100644
--- a/spec/javascripts/repo/stores/actions/file_spec.js
+++ b/spec/javascripts/repo/stores/actions/file_spec.js
@@ -31,7 +31,7 @@ describe('Multi-file store file actions', () => {
});
it('closes open files', (done) => {
- store.dispatch('closeFile', { file: localFile })
+ store.dispatch('closeFile', localFile)
.then(() => {
expect(localFile.opened).toBeFalsy();
expect(localFile.active).toBeFalsy();
@@ -41,43 +41,18 @@ describe('Multi-file store file actions', () => {
}).catch(done.fail);
});
- it('does not close file if has changed', (done) => {
- localFile.changed = true;
+ it('closes file even if file has changes', (done) => {
+ store.state.changedFiles.push(localFile);
- store.dispatch('closeFile', { file: localFile })
- .then(() => {
- expect(localFile.opened).toBeTruthy();
- expect(localFile.active).toBeTruthy();
- expect(store.state.openFiles.length).toBe(1);
-
- done();
- }).catch(done.fail);
- });
-
- it('does not close file if temp file', (done) => {
- localFile.tempFile = true;
-
- store.dispatch('closeFile', { file: localFile })
- .then(() => {
- expect(localFile.opened).toBeTruthy();
- expect(localFile.active).toBeTruthy();
- expect(store.state.openFiles.length).toBe(1);
-
- done();
- }).catch(done.fail);
- });
-
- it('force closes a changed file', (done) => {
- localFile.changed = true;
-
- store.dispatch('closeFile', { file: localFile, force: true })
+ store.dispatch('closeFile', localFile)
+ .then(Vue.nextTick)
.then(() => {
- expect(localFile.opened).toBeFalsy();
- expect(localFile.active).toBeFalsy();
expect(store.state.openFiles.length).toBe(0);
+ expect(store.state.changedFiles.length).toBe(1);
done();
- }).catch(done.fail);
+ })
+ .catch(done.fail);
});
it('sets next file as active', (done) => {
@@ -86,7 +61,7 @@ describe('Multi-file store file actions', () => {
expect(f.active).toBeFalsy();
- store.dispatch('closeFile', { file: localFile })
+ store.dispatch('closeFile', localFile)
.then(() => {
expect(f.active).toBeTruthy();
@@ -95,7 +70,7 @@ describe('Multi-file store file actions', () => {
});
it('calls getLastCommitData', (done) => {
- store.dispatch('closeFile', { file: localFile })
+ store.dispatch('closeFile', localFile)
.then(() => {
expect(getLastCommitDataSpy).toHaveBeenCalled();
@@ -315,6 +290,50 @@ describe('Multi-file store file actions', () => {
done();
}).catch(done.fail);
});
+
+ it('adds file into changedFiles array', (done) => {
+ store.dispatch('changeFileContent', {
+ file: tmpFile,
+ content: 'content',
+ })
+ .then(() => {
+ expect(store.state.changedFiles.length).toBe(1);
+
+ done();
+ }).catch(done.fail);
+ });
+
+ it('adds file once into changedFiles array', (done) => {
+ store.dispatch('changeFileContent', {
+ file: tmpFile,
+ content: 'content',
+ })
+ .then(() => store.dispatch('changeFileContent', {
+ file: tmpFile,
+ content: 'content 123',
+ }))
+ .then(() => {
+ expect(store.state.changedFiles.length).toBe(1);
+
+ done();
+ }).catch(done.fail);
+ });
+
+ it('removes file from changedFiles array if not changed', (done) => {
+ store.dispatch('changeFileContent', {
+ file: tmpFile,
+ content: 'content',
+ })
+ .then(() => store.dispatch('changeFileContent', {
+ file: tmpFile,
+ content: '',
+ }))
+ .then(() => {
+ expect(store.state.changedFiles.length).toBe(0);
+
+ done();
+ }).catch(done.fail);
+ });
});
describe('createTempFile', () => {
@@ -372,6 +391,20 @@ describe('Multi-file store file actions', () => {
}).catch(done.fail);
});
+ it('adds tmp file to changed files', (done) => {
+ store.dispatch('createTempFile', {
+ name: 'test',
+ projectId: 'abcproject',
+ branchId: 'mybranch',
+ parent: projectTree,
+ }).then((f) => {
+ expect(store.state.changedFiles.length).toBe(1);
+ expect(store.state.changedFiles[0].name).toBe(f.name);
+
+ done();
+ }).catch(done.fail);
+ });
+
it('sets tmp file as active', (done) => {
store.dispatch('createTempFile', {
name: 'test',
@@ -428,4 +461,62 @@ describe('Multi-file store file actions', () => {
}).catch(done.fail);
});
});
+
+ describe('discardFileChanges', () => {
+ let tmpFile;
+
+ beforeEach(() => {
+ tmpFile = file();
+ tmpFile.content = 'testing';
+
+ store.state.changedFiles.push(tmpFile);
+ });
+
+ it('resets file content', (done) => {
+ store.dispatch('discardFileChanges', tmpFile)
+ .then(() => {
+ expect(tmpFile.content).not.toBe('testing');
+
+ done();
+ })
+ .catch(done.fail);
+ });
+
+ it('removes file from changedFiles array', (done) => {
+ store.dispatch('discardFileChanges', tmpFile)
+ .then(() => {
+ expect(store.state.changedFiles.length).toBe(0);
+
+ done();
+ })
+ .catch(done.fail);
+ });
+
+ it('closes temp file', (done) => {
+ tmpFile.tempFile = true;
+ tmpFile.opened = true;
+
+ store.dispatch('discardFileChanges', tmpFile)
+ .then(() => {
+ expect(tmpFile.opened).toBeFalsy();
+
+ done();
+ })
+ .catch(done.fail);
+ });
+
+ it('does not re-open a closed temp file', (done) => {
+ tmpFile.tempFile = true;
+
+ expect(tmpFile.opened).toBeFalsy();
+
+ store.dispatch('discardFileChanges', tmpFile)
+ .then(() => {
+ expect(tmpFile.opened).toBeFalsy();
+
+ done();
+ })
+ .catch(done.fail);
+ });
+ });
});
diff --git a/spec/javascripts/repo/stores/actions_spec.js b/spec/javascripts/repo/stores/actions_spec.js
index f678967b092..bae84960d8d 100644
--- a/spec/javascripts/repo/stores/actions_spec.js
+++ b/spec/javascripts/repo/stores/actions_spec.js
@@ -34,18 +34,6 @@ describe('Multi-file store actions', () => {
});
});
- describe('closeDiscardPopup', () => {
- it('closes the discard popup', (done) => {
- store.dispatch('closeDiscardPopup', false)
- .then(() => {
- expect(store.state.discardPopupOpen).toBeFalsy();
-
- done();
- })
- .catch(done.fail);
- });
- });
-
describe('discardAllChanges', () => {
beforeEach(() => {
store.state.openFiles.push(file('discardAll'));
@@ -94,49 +82,6 @@ describe('Multi-file store actions', () => {
done();
}).catch(done.fail);
});
-
- it('opens discard popup if there are changed files', (done) => {
- store.state.editMode = true;
- store.state.openFiles.push(file('discardChanges'));
- store.state.openFiles[0].changed = true;
-
- store.dispatch('toggleEditMode')
- .then(() => {
- expect(store.state.discardPopupOpen).toBeTruthy();
-
- done();
- }).catch(done.fail);
- });
-
- it('can force closed if there are changed files', (done) => {
- store.state.editMode = true;
-
- store.state.openFiles.push(file('forceClose'));
- store.state.openFiles[0].changed = true;
-
- store.dispatch('toggleEditMode', true)
- .then(() => {
- expect(store.state.discardPopupOpen).toBeFalsy();
- expect(store.state.editMode).toBeFalsy();
-
- done();
- }).catch(done.fail);
- });
-
- it('discards file changes', (done) => {
- const f = file('discard');
- store.state.editMode = true;
- store.state.openFiles.push(f);
- f.changed = true;
-
- store.dispatch('toggleEditMode', true)
- .then(Vue.nextTick)
- .then(() => {
- expect(f.changed).toBeFalsy();
-
- done();
- }).catch(done.fail);
- });
});
describe('toggleBlobView', () => {
@@ -293,16 +238,19 @@ describe('Multi-file store actions', () => {
});
it('adds commit data to changed files', (done) => {
+<<<<<<< HEAD
const changedFile = file('changed');
const f = file('newfile');
changedFile.changed = true;
+=======
+ const changedFile = file();
+>>>>>>> Added changed state to IDE
- store.state.openFiles.push(changedFile, f);
+ store.state.changedFiles.push(changedFile);
store.dispatch('commitChanges', { payload, newMr: false })
.then(() => {
expect(changedFile.lastCommit.message).toBe('test message');
- expect(f.lastCommit.message).not.toBe('test message');
done();
}).catch(done.fail);
diff --git a/spec/javascripts/repo/stores/getters_spec.js b/spec/javascripts/repo/stores/getters_spec.js
index d0d5934f29a..5f78b99d7b1 100644
--- a/spec/javascripts/repo/stores/getters_spec.js
+++ b/spec/javascripts/repo/stores/getters_spec.js
@@ -9,19 +9,6 @@ describe('Multi-file store getters', () => {
localState = state();
});
- describe('changedFiles', () => {
- it('returns a list of changed opened files', () => {
- localState.openFiles.push(file());
- localState.openFiles.push(file('changed'));
- localState.openFiles[1].changed = true;
-
- const changedFiles = getters.changedFiles(localState);
-
- expect(changedFiles.length).toBe(1);
- expect(changedFiles[0].name).toBe('changed');
- });
- });
-
describe('activeFile', () => {
it('returns the current active file', () => {
localState.openFiles.push(file());
@@ -88,8 +75,8 @@ describe('Multi-file store getters', () => {
describe('modifiedFiles', () => {
it('returns a list of modified files', () => {
localState.openFiles.push(file());
- localState.openFiles.push(file('changed'));
- localState.openFiles[1].changed = true;
+ localState.changedFiles.push(file('changed'));
+ localState.changedFiles[0].changed = true;
const modifiedFiles = getters.modifiedFiles(localState);
@@ -101,9 +88,9 @@ describe('Multi-file store getters', () => {
describe('addedFiles', () => {
it('returns a list of added files', () => {
localState.openFiles.push(file());
- localState.openFiles.push(file('added'));
- localState.openFiles[1].changed = true;
- localState.openFiles[1].tempFile = true;
+ localState.changedFiles.push(file('added'));
+ localState.changedFiles[0].changed = true;
+ localState.changedFiles[0].tempFile = true;
const modifiedFiles = getters.addedFiles(localState);
diff --git a/spec/javascripts/repo/stores/mutations/file_spec.js b/spec/javascripts/repo/stores/mutations/file_spec.js
index 6e204ef0404..b908153dfa9 100644
--- a/spec/javascripts/repo/stores/mutations/file_spec.js
+++ b/spec/javascripts/repo/stores/mutations/file_spec.js
@@ -99,6 +99,17 @@ describe('Multi-file store file mutations', () => {
expect(localFile.content).toBe('testing');
expect(localFile.changed).toBeTruthy();
});
+
+ it('sets changed if file is a temp file', () => {
+ localFile.tempFile = true;
+
+ mutations.UPDATE_FILE_CONTENT(localState, {
+ file: localFile,
+ content: '',
+ });
+
+ expect(localFile.changed).toBeTruthy();
+ });
});
describe('DISCARD_FILE_CHANGES', () => {
@@ -128,4 +139,26 @@ describe('Multi-file store file mutations', () => {
expect(localFile.tree[0].name).toBe(f.name);
});
});
+
+ describe('ADD_FILE_TO_CHANGED', () => {
+ it('adds file into changed files array', () => {
+ const f = file();
+
+ mutations.ADD_FILE_TO_CHANGED(localState, f);
+
+ expect(localState.changedFiles.length).toBe(1);
+ });
+ });
+
+ describe('REMOVE_FILE_FROM_CHANGED', () => {
+ it('removes files from changed files array', () => {
+ const f = file();
+
+ localState.changedFiles.push(f);
+
+ mutations.REMOVE_FILE_FROM_CHANGED(localState, f);
+
+ expect(localState.changedFiles.length).toBe(0);
+ });
+ });
});
diff --git a/spec/javascripts/repo/stores/mutations_spec.js b/spec/javascripts/repo/stores/mutations_spec.js
index 5fd8ad94972..bed97415187 100644
--- a/spec/javascripts/repo/stores/mutations_spec.js
+++ b/spec/javascripts/repo/stores/mutations_spec.js
@@ -73,18 +73,6 @@ describe('Multi-file store mutations', () => {
});
});
- describe('TOGGLE_DISCARD_POPUP', () => {
- it('sets discardPopupOpen', () => {
- mutations.TOGGLE_DISCARD_POPUP(localState, true);
-
- expect(localState.discardPopupOpen).toBeTruthy();
-
- mutations.TOGGLE_DISCARD_POPUP(localState, false);
-
- expect(localState.discardPopupOpen).toBeFalsy();
- });
- });
-
describe('SET_ROOT', () => {
it('sets isRoot & initialRoot', () => {
mutations.SET_ROOT(localState, true);