Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/list_item.vue56
-rw-r--r--app/assets/javascripts/ide/components/ide.vue86
-rw-r--r--app/assets/javascripts/ide/components/repo_tab.vue103
-rw-r--r--app/assets/javascripts/ide/components/repo_tabs.vue67
-rw-r--r--app/assets/javascripts/ide/stores/actions.js10
-rw-r--r--app/assets/javascripts/ide/stores/actions/file.js56
-rw-r--r--app/assets/javascripts/ide/stores/getters.js8
-rw-r--r--app/assets/javascripts/ide/stores/mutation_types.js3
-rw-r--r--app/assets/javascripts/ide/stores/mutations/file.js14
-rw-r--r--app/assets/javascripts/ide/stores/state.js1
-rw-r--r--app/assets/stylesheets/pages/repo.scss8
11 files changed, 209 insertions, 203 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 18934af004a..e443bd4e3fa 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue
@@ -1,38 +1,36 @@
<script>
- import { mapActions } from 'vuex';
- import icon from '~/vue_shared/components/icon.vue';
- import router from '../../ide_router';
+import { mapActions } from 'vuex';
+import icon from '~/vue_shared/components/icon.vue';
+import router from '../../ide_router';
- export default {
- components: {
- icon,
+export default {
+ components: {
+ icon,
+ },
+ props: {
+ file: {
+ type: Object,
+ required: true,
},
- props: {
- file: {
- type: Object,
- required: true,
- },
+ },
+ computed: {
+ iconName() {
+ return this.file.tempFile ? 'file-addition' : 'file-modified';
},
- computed: {
- iconName() {
- return this.file.tempFile ? 'file-addition' : 'file-modified';
- },
- iconClass() {
- return `multi-file-${this.file.tempFile ? 'addition' : 'modified'} append-right-8`;
- },
+ iconClass() {
+ return `multi-file-${this.file.tempFile ? 'addition' : 'modified'} append-right-8`;
},
- methods: {
- ...mapActions([
- 'discardFileChanges',
- 'updateViewer',
- ]),
- openFileInEditor(file) {
- this.updateViewer('diff');
-
- router.push(`/project${file.url}`);
- },
+ },
+ methods: {
+ ...mapActions(['discardFileChanges', 'updateViewer', 'openPendingTab']),
+ openFileInEditor(file) {
+ return this.updateViewer('diff').then(() => {
+ this.openPendingTab(file);
+ router.push(`/project/${file.projectId}/tree/master/`);
+ });
},
- };
+ },
+};
</script>
<template>
diff --git a/app/assets/javascripts/ide/components/ide.vue b/app/assets/javascripts/ide/components/ide.vue
index 015e750525a..7048f5fab43 100644
--- a/app/assets/javascripts/ide/components/ide.vue
+++ b/app/assets/javascripts/ide/components/ide.vue
@@ -1,51 +1,51 @@
<script>
- import { mapState, mapGetters } from 'vuex';
- import ideSidebar from './ide_side_bar.vue';
- import ideContextbar from './ide_context_bar.vue';
- import repoTabs from './repo_tabs.vue';
- import repoFileButtons from './repo_file_buttons.vue';
- import ideStatusBar from './ide_status_bar.vue';
- import repoEditor from './repo_editor.vue';
+import { mapState, mapGetters } from 'vuex';
+import ideSidebar from './ide_side_bar.vue';
+import ideContextbar from './ide_context_bar.vue';
+import repoTabs from './repo_tabs.vue';
+import repoFileButtons from './repo_file_buttons.vue';
+import ideStatusBar from './ide_status_bar.vue';
+import repoEditor from './repo_editor.vue';
- export default {
- components: {
- ideSidebar,
- ideContextbar,
- repoTabs,
- repoFileButtons,
- ideStatusBar,
- repoEditor,
+export default {
+ components: {
+ ideSidebar,
+ ideContextbar,
+ repoTabs,
+ repoFileButtons,
+ ideStatusBar,
+ repoEditor,
+ },
+ props: {
+ emptyStateSvgPath: {
+ type: String,
+ required: true,
},
- props: {
- emptyStateSvgPath: {
- type: String,
- required: true,
- },
- noChangesStateSvgPath: {
- type: String,
- required: true,
- },
- committedStateSvgPath: {
- type: String,
- required: true,
- },
+ noChangesStateSvgPath: {
+ type: String,
+ required: true,
},
- computed: {
- ...mapState(['changedFiles', 'openFiles', 'viewer']),
- ...mapGetters(['activeFile', 'hasChanges']),
+ committedStateSvgPath: {
+ type: String,
+ required: true,
},
- mounted() {
- const returnValue = 'Are you sure you want to lose unsaved changes?';
- window.onbeforeunload = e => {
- if (!this.changedFiles.length) return undefined;
+ },
+ computed: {
+ ...mapState(['changedFiles', 'openFiles', 'viewer']),
+ ...mapGetters(['activeFile', 'hasChanges', 'tabs']),
+ },
+ mounted() {
+ const returnValue = 'Are you sure you want to lose unsaved changes?';
+ window.onbeforeunload = e => {
+ if (!this.changedFiles.length) return undefined;
- Object.assign(e, {
- returnValue,
- });
- return returnValue;
- };
- },
- };
+ Object.assign(e, {
+ returnValue,
+ });
+ return returnValue;
+ };
+ },
+};
</script>
<template>
@@ -60,7 +60,7 @@
v-if="activeFile"
>
<repo-tabs
- :files="openFiles"
+ :files="tabs"
:viewer="viewer"
:has-changes="hasChanges"
/>
diff --git a/app/assets/javascripts/ide/components/repo_tab.vue b/app/assets/javascripts/ide/components/repo_tab.vue
index c337bc813e6..b36fb6b4830 100644
--- a/app/assets/javascripts/ide/components/repo_tab.vue
+++ b/app/assets/javascripts/ide/components/repo_tab.vue
@@ -1,60 +1,58 @@
<script>
- import { mapActions } from 'vuex';
+import { mapActions } from 'vuex';
- import fileIcon from '~/vue_shared/components/file_icon.vue';
- import icon from '~/vue_shared/components/icon.vue';
- import fileStatusIcon from './repo_file_status_icon.vue';
- import changedFileIcon from './changed_file_icon.vue';
+import fileIcon from '~/vue_shared/components/file_icon.vue';
+import icon from '~/vue_shared/components/icon.vue';
+import fileStatusIcon from './repo_file_status_icon.vue';
+import changedFileIcon from './changed_file_icon.vue';
- export default {
- components: {
- fileStatusIcon,
- fileIcon,
- icon,
- changedFileIcon,
+export default {
+ components: {
+ fileStatusIcon,
+ fileIcon,
+ icon,
+ changedFileIcon,
+ },
+ props: {
+ tab: {
+ type: Object,
+ required: true,
},
- props: {
- tab: {
- type: Object,
- required: true,
- },
+ },
+ data() {
+ return {
+ tabMouseOver: false,
+ };
+ },
+ computed: {
+ closeLabel() {
+ if (this.tab.changed || this.tab.tempFile) {
+ return `${this.tab.name} changed`;
+ }
+ return `Close ${this.tab.name}`;
},
- data() {
- return {
- tabMouseOver: false,
- };
- },
- computed: {
- closeLabel() {
- if (this.tab.changed || this.tab.tempFile) {
- return `${this.tab.name} changed`;
- }
- return `Close ${this.tab.name}`;
- },
- showChangedIcon() {
- return this.tab.changed ? !this.tabMouseOver : false;
- },
+ showChangedIcon() {
+ return this.tab.changed ? !this.tabMouseOver : false;
},
+ },
- methods: {
- ...mapActions([
- 'closeFile',
- ]),
- clickFile(tab) {
- this.$router.push(`/project${tab.url}`);
- },
- mouseOverTab() {
- if (this.tab.changed) {
- this.tabMouseOver = true;
- }
- },
- mouseOutTab() {
- if (this.tab.changed) {
- this.tabMouseOver = false;
- }
- },
+ methods: {
+ ...mapActions(['closeFile']),
+ 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>
@@ -66,7 +64,7 @@
<button
type="button"
class="multi-file-tab-close"
- @click.stop.prevent="closeFile(tab.path)"
+ @click.stop.prevent="closeFile(tab)"
:aria-label="closeLabel"
>
<icon
@@ -82,7 +80,10 @@
<div
class="multi-file-tab"
- :class="{active : tab.active }"
+ :class="{
+ active: tab.active,
+ pending: tab.pending
+ }"
:title="tab.url"
>
<file-icon
diff --git a/app/assets/javascripts/ide/components/repo_tabs.vue b/app/assets/javascripts/ide/components/repo_tabs.vue
index 8ea64ddf84a..dcb2ff80ce1 100644
--- a/app/assets/javascripts/ide/components/repo_tabs.vue
+++ b/app/assets/javascripts/ide/components/repo_tabs.vue
@@ -1,42 +1,41 @@
<script>
- import { mapActions } from 'vuex';
- import RepoTab from './repo_tab.vue';
- import EditorMode from './editor_mode_dropdown.vue';
+import { mapActions } from 'vuex';
+import RepoTab from './repo_tab.vue';
+import EditorMode from './editor_mode_dropdown.vue';
- export default {
- components: {
- RepoTab,
- EditorMode,
+export default {
+ components: {
+ RepoTab,
+ EditorMode,
+ },
+ props: {
+ files: {
+ type: Array,
+ required: true,
},
- props: {
- files: {
- type: Array,
- required: true,
- },
- viewer: {
- type: String,
- required: true,
- },
- hasChanges: {
- type: Boolean,
- required: true,
- },
+ viewer: {
+ type: String,
+ required: true,
},
- data() {
- return {
- showShadow: false,
- };
+ hasChanges: {
+ type: Boolean,
+ required: true,
},
- updated() {
- if (!this.$refs.tabsScroller) return;
+ },
+ data() {
+ return {
+ showShadow: false,
+ };
+ },
+ updated() {
+ if (!this.$refs.tabsScroller) return;
- this.showShadow =
- this.$refs.tabsScroller.scrollWidth > this.$refs.tabsScroller.offsetWidth;
- },
- methods: {
- ...mapActions(['updateViewer']),
- },
- };
+ this.showShadow = this.$refs.tabsScroller.scrollWidth > this.$refs.tabsScroller.offsetWidth;
+ },
+ methods: {
+ ...mapActions(['updateViewer']),
+ },
+};
</script>
<template>
@@ -47,7 +46,7 @@
>
<repo-tab
v-for="tab in files"
- :key="tab.key"
+ :key="`${tab.key}${tab.pending ? '-pending' : ''}`"
:tab="tab"
/>
</ul>
diff --git a/app/assets/javascripts/ide/stores/actions.js b/app/assets/javascripts/ide/stores/actions.js
index 7e920aa9f30..1300ea8e520 100644
--- a/app/assets/javascripts/ide/stores/actions.js
+++ b/app/assets/javascripts/ide/stores/actions.js
@@ -6,8 +6,7 @@ import FilesDecoratorWorker from './workers/files_decorator_worker';
export const redirectToUrl = (_, url) => visitUrl(url);
-export const setInitialData = ({ commit }, data) =>
- commit(types.SET_INITIAL_DATA, data);
+export const setInitialData = ({ commit }, data) => commit(types.SET_INITIAL_DATA, data);
export const discardAllChanges = ({ state, commit, dispatch }) => {
state.changedFiles.forEach(file => {
@@ -43,14 +42,11 @@ export const createTempEntry = (
) =>
new Promise(resolve => {
const worker = new FilesDecoratorWorker();
- const fullName =
- name.slice(-1) !== '/' && type === 'tree' ? `${name}/` : name;
+ const fullName = name.slice(-1) !== '/' && type === 'tree' ? `${name}/` : name;
if (state.entries[name]) {
flash(
- `The name "${name
- .split('/')
- .pop()}" is already taken in this directory.`,
+ `The name "${name.split('/').pop()}" is already taken in this directory.`,
'alert',
document,
null,
diff --git a/app/assets/javascripts/ide/stores/actions/file.js b/app/assets/javascripts/ide/stores/actions/file.js
index ddc4b757bf9..5a39bfb02c4 100644
--- a/app/assets/javascripts/ide/stores/actions/file.js
+++ b/app/assets/javascripts/ide/stores/actions/file.js
@@ -6,21 +6,26 @@ import * as types from '../mutation_types';
import router from '../../ide_router';
import { setPageTitle } from '../utils';
-export const closeFile = ({ commit, state, getters, dispatch }, path) => {
- const indexOfClosedFile = state.openFiles.findIndex(f => f.path === path);
- const file = state.entries[path];
- const fileWasActive = file.active;
+export const closeFile = ({ commit, state, getters, dispatch }, file) => {
+ const path = file.path;
+
+ if (file.pending) {
+ commit(types.REMOVE_PENDING_TAB, file);
+ } else {
+ const indexOfClosedFile = state.openFiles.findIndex(f => f.path === path);
+ const fileWasActive = file.active;
- commit(types.TOGGLE_FILE_OPEN, path);
- commit(types.SET_FILE_ACTIVE, { path, active: false });
+ commit(types.TOGGLE_FILE_OPEN, path);
+ commit(types.SET_FILE_ACTIVE, { path, active: false });
- if (state.openFiles.length > 0 && fileWasActive) {
- const nextIndexToOpen = indexOfClosedFile === 0 ? 0 : indexOfClosedFile - 1;
- const nextFileToOpen = state.entries[state.openFiles[nextIndexToOpen].path];
+ if (state.openFiles.length > 0 && fileWasActive) {
+ const nextIndexToOpen = indexOfClosedFile === 0 ? 0 : indexOfClosedFile - 1;
+ const nextFileToOpen = state.entries[state.openFiles[nextIndexToOpen].path];
- router.push(`/project${nextFileToOpen.url}`);
- } else if (!state.openFiles.length) {
- router.push(`/project/${file.projectId}/tree/${file.branchId}/`);
+ router.push(`/project${nextFileToOpen.url}`);
+ } else if (!state.openFiles.length) {
+ router.push(`/project/${file.projectId}/tree/${file.branchId}/`);
+ }
}
eventHub.$emit(`editor.update.model.dispose.${file.path}`);
@@ -66,14 +71,7 @@ export const getFileData = ({ state, commit, dispatch }, file) => {
})
.catch(() => {
commit(types.TOGGLE_LOADING, { entry: file });
- flash(
- 'Error loading file data. Please try again.',
- 'alert',
- document,
- null,
- false,
- true,
- );
+ flash('Error loading file data. Please try again.', 'alert', document, null, false, true);
});
};
@@ -84,14 +82,7 @@ export const getRawFileData = ({ commit, dispatch }, file) =>
commit(types.SET_FILE_RAW_DATA, { file, raw });
})
.catch(() =>
- flash(
- 'Error loading file content. Please try again.',
- 'alert',
- document,
- null,
- false,
- true,
- ),
+ flash('Error loading file content. Please try again.', 'alert', document, null, false, true),
);
export const changeFileContent = ({ state, commit }, { path, content }) => {
@@ -119,10 +110,7 @@ export const setFileEOL = ({ getters, commit }, { eol }) => {
}
};
-export const setEditorPosition = (
- { getters, commit },
- { editorRow, editorColumn },
-) => {
+export const setEditorPosition = ({ getters, commit }, { editorRow, editorColumn }) => {
if (getters.activeFile) {
commit(types.SET_FILE_POSITION, {
file: getters.activeFile,
@@ -144,3 +132,7 @@ export const discardFileChanges = ({ state, commit }, path) => {
eventHub.$emit(`editor.update.model.content.${file.path}`, file.raw);
};
+
+export const openPendingTab = ({ commit }, file) => {
+ commit(types.ADD_PENDING_TAB, file);
+};
diff --git a/app/assets/javascripts/ide/stores/getters.js b/app/assets/javascripts/ide/stores/getters.js
index eba325a31df..28006d3ddf8 100644
--- a/app/assets/javascripts/ide/stores/getters.js
+++ b/app/assets/javascripts/ide/stores/getters.js
@@ -1,10 +1,10 @@
-export const activeFile = state =>
- state.openFiles.find(file => file.active) || null;
+export const tabs = state => state.openFiles.concat(state.pendingTabs);
+
+export const activeFile = state => tabs(state).find(file => file.active) || null;
export const addedFiles = state => state.changedFiles.filter(f => f.tempFile);
-export const modifiedFiles = state =>
- state.changedFiles.filter(f => !f.tempFile);
+export const modifiedFiles = state => state.changedFiles.filter(f => !f.tempFile);
export const projectsWithTrees = state =>
Object.keys(state.projects).map(projectId => {
diff --git a/app/assets/javascripts/ide/stores/mutation_types.js b/app/assets/javascripts/ide/stores/mutation_types.js
index e28f190897c..fa2fbaf8683 100644
--- a/app/assets/javascripts/ide/stores/mutation_types.js
+++ b/app/assets/javascripts/ide/stores/mutation_types.js
@@ -41,3 +41,6 @@ export const SET_ENTRIES = 'SET_ENTRIES';
export const CREATE_TMP_ENTRY = 'CREATE_TMP_ENTRY';
export const UPDATE_VIEWER = 'UPDATE_VIEWER';
export const UPDATE_DELAY_VIEWER_CHANGE = 'UPDATE_DELAY_VIEWER_CHANGE';
+
+export const ADD_PENDING_TAB = 'ADD_PENDING_TAB';
+export const REMOVE_PENDING_TAB = 'REMOVE_PENDING_TAB';
diff --git a/app/assets/javascripts/ide/stores/mutations/file.js b/app/assets/javascripts/ide/stores/mutations/file.js
index 2500f13db7c..915126f10eb 100644
--- a/app/assets/javascripts/ide/stores/mutations/file.js
+++ b/app/assets/javascripts/ide/stores/mutations/file.js
@@ -80,4 +80,18 @@ export default {
changed,
});
},
+ [types.ADD_PENDING_TAB](state, file) {
+ Object.assign(state, {
+ pendingTabs: state.pendingTabs.concat({
+ ...file,
+ active: true,
+ pending: true,
+ }),
+ });
+ },
+ [types.REMOVE_PENDING_TAB](state, file) {
+ Object.assign(state, {
+ pendingTabs: state.pendingTabs.filter(f => f.path !== file.path),
+ });
+ },
};
diff --git a/app/assets/javascripts/ide/stores/state.js b/app/assets/javascripts/ide/stores/state.js
index 6110f54951c..52a2400ec42 100644
--- a/app/assets/javascripts/ide/stores/state.js
+++ b/app/assets/javascripts/ide/stores/state.js
@@ -16,4 +16,5 @@ export default () => ({
entries: {},
viewer: 'editor',
delayViewerUpdated: false,
+ pendingTabs: [],
});
diff --git a/app/assets/stylesheets/pages/repo.scss b/app/assets/stylesheets/pages/repo.scss
index 65046f6665e..94aa5130f28 100644
--- a/app/assets/stylesheets/pages/repo.scss
+++ b/app/assets/stylesheets/pages/repo.scss
@@ -177,6 +177,10 @@
background-color: $white-light;
border-bottom-color: $white-light;
}
+
+ &.pending {
+ font-style: italic;
+ }
}
.multi-file-tab-close {
@@ -720,9 +724,7 @@
}
.ide-view {
- height: calc(
- 100vh - #{$header-height + $performance-bar-height + $flash-height}
- );
+ height: calc(100vh - #{$header-height + $performance-bar-height + $flash-height});
}
}
}