summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorTim Zallmann <tzallmann@gitlab.com>2017-12-06 14:30:16 +0100
committerTim Zallmann <tzallmann@gitlab.com>2017-12-19 12:26:02 +0100
commit179b05771100a603ba84164fd0b699ef40f9b47c (patch)
tree5faa23ed390fab0c84912b0139d4e7ac662f2758 /app
parent4bc348ce5fd9b143622a52e001949eabbc27142f (diff)
downloadgitlab-ce-179b05771100a603ba84164fd0b699ef40f9b47c.tar.gz
Fixes based on MR review
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/api.js2
-rw-r--r--app/assets/javascripts/ide/components/ide.vue39
-rw-r--r--app/assets/javascripts/ide/components/ide_context_bar.vue4
-rw-r--r--app/assets/javascripts/ide/components/ide_project_branches_tree.vue10
-rw-r--r--app/assets/javascripts/ide/components/ide_project_tree.vue6
-rw-r--r--app/assets/javascripts/ide/components/ide_repo_tree.vue10
-rw-r--r--app/assets/javascripts/ide/components/ide_side_bar.vue4
-rw-r--r--app/assets/javascripts/ide/components/ide_status_bar.vue22
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/index.vue16
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/modal.vue1
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/upload.vue5
-rw-r--r--app/assets/javascripts/ide/components/repo.vue63
-rw-r--r--app/assets/javascripts/ide/components/repo_commit_section.vue3
-rw-r--r--app/assets/javascripts/ide/components/repo_editor.vue5
-rw-r--r--app/assets/javascripts/ide/components/repo_file.vue21
-rw-r--r--app/assets/javascripts/ide/components/repo_file_buttons.vue52
-rw-r--r--app/assets/javascripts/ide/ide_router.js24
-rw-r--r--app/assets/javascripts/ide/index.js4
-rw-r--r--app/assets/javascripts/ide/lib/common/model.js2
-rw-r--r--app/assets/javascripts/ide/lib/editor.js6
-rw-r--r--app/assets/javascripts/ide/stores/actions/branch.js20
-rw-r--r--app/assets/javascripts/ide/stores/actions/file.js13
-rw-r--r--app/assets/javascripts/ide/stores/actions/project.js5
-rw-r--r--app/assets/javascripts/ide/stores/actions/tree.js7
-rw-r--r--app/assets/javascripts/ide/stores/getters.js7
-rw-r--r--app/assets/javascripts/ide/stores/mutations/file.js4
-rw-r--r--app/assets/javascripts/ide/stores/state.js2
-rw-r--r--app/assets/javascripts/ide/stores/utils.js9
-rw-r--r--app/assets/stylesheets/framework/variables.scss1
-rw-r--r--app/assets/stylesheets/pages/repo.scss83
-rw-r--r--app/helpers/blob_helper.rb12
-rw-r--r--app/views/ide/index.html.haml12
-rw-r--r--app/views/shared/repo/_repo.html.haml2
33 files changed, 208 insertions, 268 deletions
diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js
index a04b4937bc9..21d8c790e90 100644
--- a/app/assets/javascripts/api.js
+++ b/app/assets/javascripts/api.js
@@ -1,5 +1,5 @@
import $ from 'jquery';
-import axios from '~/lib/utils/axios_utils';
+import axios from './lib/utils/axios_utils';
const Api = {
groupsPath: '/api/:version/groups.json',
diff --git a/app/assets/javascripts/ide/components/ide.vue b/app/assets/javascripts/ide/components/ide.vue
index f39896e9262..0be30c5cba1 100644
--- a/app/assets/javascripts/ide/components/ide.vue
+++ b/app/assets/javascripts/ide/components/ide.vue
@@ -1,14 +1,12 @@
-/* global Sidebar */
-
<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 RepoPreview from './repo_preview.vue';
-import RepoEditor from './repo_editor.vue';
+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 repoPreview from './repo_preview.vue';
+import repoEditor from './repo_editor.vue';
export default {
computed: {
@@ -23,16 +21,16 @@ export default {
]),
},
components: {
- IdeSidebar,
- IdeContextbar,
- RepoTabs,
- RepoFileButtons,
- IdeStatusBar,
- RepoEditor,
- RepoPreview,
+ ideSidebar,
+ ideContextbar,
+ repoTabs,
+ repoFileButtons,
+ ideStatusBar,
+ repoEditor,
+ repoPreview,
},
mounted() {
- /* const returnValue = 'Are you sure you want to lose unsaved changes?';
+ const returnValue = 'Are you sure you want to lose unsaved changes?';
window.onbeforeunload = (e) => {
if (!this.changedFiles.length) return undefined;
@@ -40,7 +38,7 @@ export default {
returnValue,
});
return returnValue;
- }; */
+ };
},
};
</script>
@@ -66,8 +64,9 @@ export default {
</template>
<template
v-else>
- <br/><br/><br/><br/><br/>
- <h4 class="clgray text-center">Welcome to the GitLab IDE</h4>
+ <div class="ide-empty-state">
+ <h2 class="clgray">Welcome to the GitLab IDE</h2>
+ </div>
</template>
</div>
<ide-contextbar/>
diff --git a/app/assets/javascripts/ide/components/ide_context_bar.vue b/app/assets/javascripts/ide/components/ide_context_bar.vue
index 17737622506..2e319c6309d 100644
--- a/app/assets/javascripts/ide/components/ide_context_bar.vue
+++ b/app/assets/javascripts/ide/components/ide_context_bar.vue
@@ -1,11 +1,11 @@
<script>
import { mapGetters } from 'vuex';
-import RepoCommitSection from './repo_commit_section.vue';
+import repoCommitSection from './repo_commit_section.vue';
import icon from '../../vue_shared/components/icon.vue';
export default {
components: {
- RepoCommitSection,
+ repoCommitSection,
icon,
},
data() {
diff --git a/app/assets/javascripts/ide/components/ide_project_branches_tree.vue b/app/assets/javascripts/ide/components/ide_project_branches_tree.vue
index 84b650939ee..bd3a521ff43 100644
--- a/app/assets/javascripts/ide/components/ide_project_branches_tree.vue
+++ b/app/assets/javascripts/ide/components/ide_project_branches_tree.vue
@@ -1,12 +1,12 @@
<script>
-import RepoTree from './ide_repo_tree.vue';
-import Icon from '../../vue_shared/components/icon.vue';
+import repoTree from './ide_repo_tree.vue';
+import icon from '../../vue_shared/components/icon.vue';
import newDropdown from './new_dropdown/index.vue';
export default {
components: {
- RepoTree,
- Icon,
+ repoTree,
+ icon,
newDropdown,
},
props: {
@@ -34,7 +34,7 @@ export default {
</div>
<div class="branch-header-btns">
<new-dropdown
- :projectId="projectId"
+ :project-id="projectId"
:branch="branch.name"
path=""/>
</div>
diff --git a/app/assets/javascripts/ide/components/ide_project_tree.vue b/app/assets/javascripts/ide/components/ide_project_tree.vue
index ca499b650fc..4df27da3d35 100644
--- a/app/assets/javascripts/ide/components/ide_project_tree.vue
+++ b/app/assets/javascripts/ide/components/ide_project_tree.vue
@@ -1,10 +1,10 @@
<script>
-import BranchesTree from './ide_project_branches_tree.vue';
+import branchesTree from './ide_project_branches_tree.vue';
import projectAvatarImage from '../../vue_shared/components/project_avatar/project_avatar_image.vue';
export default {
components: {
- BranchesTree,
+ branchesTree,
projectAvatarImage,
},
props: {
@@ -40,7 +40,7 @@ export default {
<branches-tree
v-for="(branch, index) in project.branches"
:key="branch.name"
- :projectId="project.path_with_namespace"
+ :project-id="project.path_with_namespace"
:branch="branch"/>
</div>
</div>
diff --git a/app/assets/javascripts/ide/components/ide_repo_tree.vue b/app/assets/javascripts/ide/components/ide_repo_tree.vue
index 0c45864c09b..932f9c955fe 100644
--- a/app/assets/javascripts/ide/components/ide_repo_tree.vue
+++ b/app/assets/javascripts/ide/components/ide_repo_tree.vue
@@ -30,6 +30,12 @@ export default {
'treeList',
'isCollapsed',
]),
+ hasPreviousDirectory() {
+ return !this.isRoot && this.treeList(this.treeId).length;
+ },
+ showLoading() {
+ return (!this.treeId || !this.treeList(this.treeId).length) && this.loading;
+ },
},
};
</script>
@@ -41,10 +47,10 @@ export default {
<tbody
v-if="treeId">
<repo-previous-directory
- v-if="!isRoot && treeList(treeId).length"
+ v-if="hasPreviousDirectory"
/>
<repo-loading-file
- v-if="(!treeId || !treeList(treeId).length) && loading"
+ v-if="showLoading"
v-for="n in 5"
:key="n"
/>
diff --git a/app/assets/javascripts/ide/components/ide_side_bar.vue b/app/assets/javascripts/ide/components/ide_side_bar.vue
index 2644c681d06..de793c347aa 100644
--- a/app/assets/javascripts/ide/components/ide_side_bar.vue
+++ b/app/assets/javascripts/ide/components/ide_side_bar.vue
@@ -1,11 +1,11 @@
<script>
import { mapState } from 'vuex';
-import ProjectTree from './ide_project_tree.vue';
+import projectTree from './ide_project_tree.vue';
import icon from '../../vue_shared/components/icon.vue';
export default {
components: {
- ProjectTree,
+ projectTree,
icon,
},
data() {
diff --git a/app/assets/javascripts/ide/components/ide_status_bar.vue b/app/assets/javascripts/ide/components/ide_status_bar.vue
index 54e05a4633c..a24abadd936 100644
--- a/app/assets/javascripts/ide/components/ide_status_bar.vue
+++ b/app/assets/javascripts/ide/components/ide_status_bar.vue
@@ -1,6 +1,6 @@
<script>
import { mapState } from 'vuex';
-import Icon from '../../vue_shared/components/icon.vue';
+import icon from '../../vue_shared/components/icon.vue';
import tooltip from '../../vue_shared/directives/tooltip';
import timeAgoMixin from '../../vue_shared/mixins/timeago';
@@ -12,7 +12,7 @@ export default {
},
},
components: {
- Icon,
+ icon,
},
directives: {
tooltip,
@@ -31,16 +31,14 @@ export default {
<template>
<div
class="ide-status-bar">
- <div
- class="col-sm-3">
+ <div>
<icon
name="branch"
:size="12">
</icon>
{{ selectedFile.branchId }}
</div>
- <div
- class="col-sm-4">
+ <div>
<div
v-if="selectedFile.lastCommit && selectedFile.lastCommit.id">
Last commit:
@@ -53,20 +51,20 @@ export default {
</a>
</div>
</div>
- <div
- class="col-sm-2 text-right">
+ <div
+ class="text-right">
{{ selectedFile.name }}
</div>
<div
- class="col-sm-1 text-right">
- {{ selectedFile.EOL }}
+ class="text-right">
+ {{ selectedFile.eol }}
</div>
<div
- class="col-sm-1 text-right">
+ class="text-right">
{{ file.editorRow }}:{{ file.editorColumn }}
</div>
<div
- class="col-sm-1 text-right">
+ class="text-right">
{{ selectedFile.fileLanguage }}
</div>
</div>
diff --git a/app/assets/javascripts/ide/components/new_dropdown/index.vue b/app/assets/javascripts/ide/components/new_dropdown/index.vue
index cacaa728309..c70d01c2d04 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/index.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/index.vue
@@ -20,7 +20,6 @@
},
parent: {
type: Object,
- required: false,
},
},
components: {
@@ -43,16 +42,11 @@
this.openModal = !this.openModal;
},
},
- computed: {
- ...mapState([
- 'trees',
- ]),
- },
};
</script>
<template>
- <div class="repo-new-btn">
+ <div class="repo-new-btn pull-right">
<div class="dropdown">
<button
type="button"
@@ -81,8 +75,8 @@
</li>
<li>
<upload
- :projectId="projectId"
- :branchId="branch"
+ :project-id="projectId"
+ :branch-id="branch"
:path="path"
:parent="parent"
/>
@@ -101,8 +95,8 @@
<new-modal
v-if="openModal"
:type="modalType"
- :projectId="projectId"
- :branchId="branch"
+ :project-id="projectId"
+ :branch-id="branch"
:path="path"
:parent="parent"
@toggle="toggleModalOpen"
diff --git a/app/assets/javascripts/ide/components/new_dropdown/modal.vue b/app/assets/javascripts/ide/components/new_dropdown/modal.vue
index 1ae141e2518..2bb723c4b1d 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/modal.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/modal.vue
@@ -15,7 +15,6 @@
},
parent: {
type: Object,
- required: false,
},
type: {
type: String,
diff --git a/app/assets/javascripts/ide/components/new_dropdown/upload.vue b/app/assets/javascripts/ide/components/new_dropdown/upload.vue
index 14a047781c5..54a0ff3573e 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/upload.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/upload.vue
@@ -13,7 +13,6 @@
},
parent: {
type: Object,
- required: false,
},
path: {
type: String,
@@ -24,9 +23,6 @@
...mapState([
'trees',
]),
- fileId() {
- return `file-upload-${encodeURIComponent(this.projectId)}-${this.branchId}-${encodeURIComponent(this.path)}`;
- },
},
methods: {
...mapActions([
@@ -82,7 +78,6 @@
>
{{ __('Upload file') }}
<input
- :id="fileId"
type="file"
class="hidden"
ref="fileUpload"
diff --git a/app/assets/javascripts/ide/components/repo.vue b/app/assets/javascripts/ide/components/repo.vue
deleted file mode 100644
index 14cbe4c6cc2..00000000000
--- a/app/assets/javascripts/ide/components/repo.vue
+++ /dev/null
@@ -1,63 +0,0 @@
-<script>
-import { mapState, mapGetters } from 'vuex';
-import RepoSidebar from './ide_side_bar.vue';
-import RepoCommitSection from './repo_commit_section.vue';
-import RepoTabs from './repo_tabs.vue';
-import RepoFileButtons from './repo_file_buttons.vue';
-import RepoPreview from './repo_preview.vue';
-import repoEditor from './repo_editor.vue';
-
-export default {
- computed: {
- ...mapState([
- 'currentBlobView',
- ]),
- ...mapGetters([
- 'isCollapsed',
- 'changedFiles',
- ]),
- },
- components: {
- RepoSidebar,
- RepoTabs,
- RepoFileButtons,
- repoEditor,
- RepoCommitSection,
- RepoPreview,
- },
- 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;
- };
- },
-};
-</script>
-
-<template>
- <div
- class="multi-file"
- :class="{
- 'is-collapsed': isCollapsed
- }"
- >
- <repo-sidebar/>
- <div
- v-if="isCollapsed"
- class="multi-file-edit-pane"
- >
- <repo-tabs />
- <component
- class="multi-file-edit-pane-content"
- :is="currentBlobView"
- />
- <repo-file-buttons />
- </div>
- <repo-commit-section />
- </div>
-</template>
diff --git a/app/assets/javascripts/ide/components/repo_commit_section.vue b/app/assets/javascripts/ide/components/repo_commit_section.vue
index 2b282b5a26b..a18508c2f96 100644
--- a/app/assets/javascripts/ide/components/repo_commit_section.vue
+++ b/app/assets/javascripts/ide/components/repo_commit_section.vue
@@ -30,6 +30,7 @@ export default {
},
computed: {
...mapState([
+ 'currentProjectId',
'currentBranchId',
]),
...mapGetters([
@@ -72,7 +73,7 @@ export default {
this.$store.dispatch('getTreeData', {
projectId: this.currentProjectId,
branch: this.currentBranchId,
- endpoint: `/${this.currentProjectId}/tree/${this.currentBranchId}`,
+ endpoint: `/tree/${this.currentBranchId}`,
});
})
.catch(() => {
diff --git a/app/assets/javascripts/ide/components/repo_editor.vue b/app/assets/javascripts/ide/components/repo_editor.vue
index cafe5665ce6..081d09984ea 100644
--- a/app/assets/javascripts/ide/components/repo_editor.vue
+++ b/app/assets/javascripts/ide/components/repo_editor.vue
@@ -57,7 +57,6 @@ export default {
// Handle Cursor Position
this.editor.onPositionChange((instance, e) => {
this.setEditorPosition({
- file: this.$store.state.selectedFile,
editorRow: e.position.lineNumber,
editorColumn: e.position.column,
});
@@ -81,10 +80,10 @@ export default {
fileLanguage: model.language,
});
- // Get File EOL
+ // Get File eol
this.setFileEOL({
file: this.$store.state.selectedFile,
- EOL: model.EOL,
+ eol: model.eol,
});
},
},
diff --git a/app/assets/javascripts/ide/components/repo_file.vue b/app/assets/javascripts/ide/components/repo_file.vue
index 1dacc1e2841..18a00cb7426 100644
--- a/app/assets/javascripts/ide/components/repo_file.vue
+++ b/app/assets/javascripts/ide/components/repo_file.vue
@@ -20,6 +20,10 @@
type: Boolean,
default: true,
},
+ showExtraColumns: {
+ type: Boolean,
+ default: false,
+ },
},
computed: {
isSubmodule() {
@@ -28,16 +32,6 @@
isTree() {
return this.file.type === 'tree';
},
- fileIcon() {
- return {
- 'fa-spinner fa-spin': this.file.loading,
- [this.file.icon]: !this.file.loading,
- 'fa-folder-open': !this.file.loading && this.file.opened,
- };
- },
- fileUrl() {
- return this.file.url;
- },
levelIndentation() {
return {
marginLeft: `${this.file.level * 16}px`,
@@ -53,10 +47,9 @@
return this.file.type === 'blob' && this.file.opened ? 'file-open' : '';
},
changedClass() {
- const tabChangedObj = {
+ return {
'fa-circle unsaved-icon': this.file.changed || this.file.tempFile,
};
- return tabChangedObj;
},
},
methods: {
@@ -91,7 +84,7 @@
</a>
<new-dropdown
v-if="isTree"
- :projectId="file.projectId"
+ :project-id="file.projectId"
:branch="file.branchId"
:path="file.path"
:parent="file"/>
@@ -114,7 +107,7 @@
</template>
</td>
- <template v-if="false == true">
+ <template v-if="showExtraColumns">
<td class="multi-file-table-col-commit-message hidden-sm hidden-xs">
<a
v-if="file.lastCommit.message"
diff --git a/app/assets/javascripts/ide/components/repo_file_buttons.vue b/app/assets/javascripts/ide/components/repo_file_buttons.vue
index b33103cb47a..34f0d51819a 100644
--- a/app/assets/javascripts/ide/components/repo_file_buttons.vue
+++ b/app/assets/javascripts/ide/components/repo_file_buttons.vue
@@ -24,35 +24,33 @@ export default {
v-if="showButtons"
class="multi-file-editor-btn-group"
>
- <div class="col-sm-12">
+ <a
+ :href="activeFile.rawPath"
+ target="_blank"
+ class="btn btn-default btn-sm raw"
+ rel="noopener noreferrer">
+ {{ rawDownloadButtonLabel }}
+ </a>
+
+ <div
+ class="btn-group"
+ role="group"
+ aria-label="File actions">
<a
- :href="activeFile.rawPath"
- target="_blank"
- class="btn btn-default btn-sm raw"
- rel="noopener noreferrer">
- {{ rawDownloadButtonLabel }}
+ :href="activeFile.blamePath"
+ class="btn btn-default btn-sm blame">
+ Blame
+ </a>
+ <a
+ :href="activeFile.commitsPath"
+ class="btn btn-default btn-sm history">
+ History
+ </a>
+ <a
+ :href="activeFile.permalink"
+ class="btn btn-default btn-sm permalink">
+ Permalink
</a>
-
- <div
- class="btn-group"
- role="group"
- aria-label="File actions">
- <a
- :href="activeFile.blamePath"
- class="btn btn-default btn-sm blame">
- Blame
- </a>
- <a
- :href="activeFile.commitsPath"
- class="btn btn-default btn-sm history">
- History
- </a>
- <a
- :href="activeFile.permalink"
- class="btn btn-default btn-sm permalink">
- Permalink
- </a>
- </div>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/ide/ide_router.js b/app/assets/javascripts/ide/ide_router.js
index 8aaa168c9da..a3e833bf02d 100644
--- a/app/assets/javascripts/ide/ide_router.js
+++ b/app/assets/javascripts/ide/ide_router.js
@@ -1,6 +1,10 @@
import Vue from 'vue';
import VueRouter from 'vue-router';
import store from './stores';
+import flash from '../flash';
+import {
+ getTreeEntry,
+} from './stores/utils';
Vue.use(VueRouter);
@@ -24,25 +28,27 @@ Vue.use(VueRouter);
// Unfortunately Vue Router doesn't work without at least a fake component
// If you do only data handling
-const FooRouterComponent = {
- template: '<div>foo</div>',
+const EmptyRouterComponent = {
+ render(createElement) {
+ return createElement('div');
+ },
};
const router = new VueRouter({
mode: 'history',
- base: '/-/ide/',
+ base: `${gon.relative_url_root}/-/ide/`,
routes: [
{
path: '/project/:namespace/:project',
- component: FooRouterComponent,
+ component: EmptyRouterComponent,
children: [
{
path: ':targetmode/:branch/*',
- component: FooRouterComponent,
+ component: EmptyRouterComponent,
},
{
path: 'mr/:mrid',
- component: FooRouterComponent,
+ component: EmptyRouterComponent,
},
],
},
@@ -66,22 +72,24 @@ router.beforeEach((to, from, next) => {
store.dispatch('getTreeData', {
projectId: fullProjectId,
branch: to.params.branch,
- endpoint: `/${fullProjectId}/tree/${to.params.branch}`,
+ endpoint: `/tree/${to.params.branch}`,
})
.then(() => {
if (to.params[0]) {
- const treeEntry = store.getters.getTreeEntry(`${to.params.namespace}/${to.params.project}/${to.params.branch}`, to.params[0]);
+ const treeEntry = getTreeEntry(store, `${to.params.namespace}/${to.params.project}/${to.params.branch}`, to.params[0]);
if (treeEntry) {
store.dispatch('handleTreeEntryAction', treeEntry);
}
}
})
.catch((e) => {
+ flash('Error while loading the branch files. Please try again.');
throw e;
});
}
})
.catch((e) => {
+ flash('Error while loading the project data. Please try again.');
throw e;
});
next();
diff --git a/app/assets/javascripts/ide/index.js b/app/assets/javascripts/ide/index.js
index 98954232036..74ee2f14599 100644
--- a/app/assets/javascripts/ide/index.js
+++ b/app/assets/javascripts/ide/index.js
@@ -104,7 +104,3 @@ initNewDropdown(newDropdownHolder);
const contextualSidebar = new ContextualSidebar();
contextualSidebar.bindEvents();
-
-/* global Sidebar */
-// eslint-disable-next-line no-new
-new Sidebar();
diff --git a/app/assets/javascripts/ide/lib/common/model.js b/app/assets/javascripts/ide/lib/common/model.js
index 46ff9beb4c7..71261189182 100644
--- a/app/assets/javascripts/ide/lib/common/model.js
+++ b/app/assets/javascripts/ide/lib/common/model.js
@@ -32,7 +32,7 @@ export default class Model {
return this.model.getModeId();
}
- get EOL() {
+ get eol() {
return encodeURI(this.model.getEOL()) === '%0A' ? 'LF' : 'CRLF';
}
diff --git a/app/assets/javascripts/ide/lib/editor.js b/app/assets/javascripts/ide/lib/editor.js
index 3e762a5c4de..51e202b9348 100644
--- a/app/assets/javascripts/ide/lib/editor.js
+++ b/app/assets/javascripts/ide/lib/editor.js
@@ -23,10 +23,10 @@ export default class Editor {
this.decorationsController = new DecorationsController(this),
);
- const debouncedUpdate = _.debounce(() => {
+ this.debouncedUpdate = _.debounce(() => {
this.updateDimensions();
}, 200);
- window.addEventListener('resize', debouncedUpdate, false);
+ window.addEventListener('resize', this.debouncedUpdate, false);
}
createInstance(domElement) {
@@ -78,7 +78,7 @@ export default class Editor {
dispose() {
this.disposable.dispose();
- window.removeEventListener('resize', this.updateDimensions.bind(this));
+ window.removeEventListener('resize', this.debouncedUpdate);
// dispose main monaco instance
if (this.instance) {
diff --git a/app/assets/javascripts/ide/stores/actions/branch.js b/app/assets/javascripts/ide/stores/actions/branch.js
index f3e74fd7744..0b6968e0973 100644
--- a/app/assets/javascripts/ide/stores/actions/branch.js
+++ b/app/assets/javascripts/ide/stores/actions/branch.js
@@ -2,18 +2,18 @@ import service from '../../services';
import flash from '../../../flash';
import * as types from '../mutation_types';
-// eslint-disable-next-line import/prefer-default-export
export const getBranchData = (
{ commit, state, dispatch },
- { projectId, branchId, enforce = false } = {},
+ { projectId, branchId, force = false } = {},
) => new Promise((resolve, reject) => {
if ((typeof state.projects[`${projectId}`] === 'undefined' ||
!state.projects[`${projectId}`].branches[branchId])
- || enforce) {
+ || force) {
service.getBranchData(`${projectId}`, branchId)
.then((data) => {
+ const { id } = data.commit;
commit(types.SET_BRANCH, { projectPath: `${projectId}`, branchName: branchId, branch: data });
- dispatch('setBranchReference', { projectId, branchId });
+ commit(types.SET_BRANCH_WORKING_REFERENCE, { projectId, branchId, reference: id });
resolve(data);
})
.catch(() => {
@@ -25,18 +25,6 @@ export const getBranchData = (
}
});
-export const setBranchReference = ({ commit, state }, { projectId, branchId }) =>
- service.getBranchData(
- projectId,
- branchId,
- )
- .then((data) => {
- const { id } = data.commit;
- commit(types.SET_BRANCH_WORKING_REFERENCE, { projectId, branchId, reference: id });
- })
- .catch(() => flash('Error checking branch data. Please try again.'));
-
-// eslint-disable-next-line import/prefer-default-export
export const createNewBranch = ({ state, commit }, branch) => service.createBranch(
state.project.id,
{
diff --git a/app/assets/javascripts/ide/stores/actions/file.js b/app/assets/javascripts/ide/stores/actions/file.js
index 7055c81edac..4d4e792a466 100644
--- a/app/assets/javascripts/ide/stores/actions/file.js
+++ b/app/assets/javascripts/ide/stores/actions/file.js
@@ -87,16 +87,19 @@ export const setFileLanguage = ({ commit }, { file, fileLanguage }) => {
commit(types.SET_FILE_LANGUAGE, { file, fileLanguage });
};
-export const setFileEOL = ({ commit }, { file, EOL }) => {
- commit(types.SET_FILE_EOL, { file, EOL });
+export const setFileEOL = ({ commit }, { file, eol }) => {
+ commit(types.SET_FILE_EOL, { file, eol });
};
-export const setEditorPosition = ({ commit }, { file, editorRow, editorColumn }) => {
- commit(types.SET_FILE_POSITION, { file, editorRow, editorColumn });
+export const setEditorPosition = ({ state, commit }, { editorRow, editorColumn }) => {
+ commit(types.SET_FILE_POSITION, { file: state.selectedFile, editorRow, editorColumn });
};
export const createTempFile = ({ state, commit, dispatch }, { projectId, branchId, parent, name, content = '', base64 = '' }) => {
const path = parent.path !== undefined ? parent.path : '';
+ const selectedProject = state.projects[projectId];
+ // We need to do the replacement otherwise the web_url + file.url duplicate
+ const newUrl = `${selectedProject.web_url}/blob/${branchId}/${path}${path ? '/' : ''}${name}`;
const file = createTemp({
projectId,
branchId,
@@ -107,7 +110,7 @@ export const createTempFile = ({ state, commit, dispatch }, { projectId, branchI
changed: true,
content,
base64,
- url: `/${projectId}/blob/${branchId}/${path}${path ? '/' : ''}${name}`,
+ url: newUrl,
});
if (findEntry(parent.tree, 'blob', file.name)) return flash(`The name "${file.name}" is already taken in this directory.`);
diff --git a/app/assets/javascripts/ide/stores/actions/project.js b/app/assets/javascripts/ide/stores/actions/project.js
index a0f092b4f97..3832f7729a2 100644
--- a/app/assets/javascripts/ide/stores/actions/project.js
+++ b/app/assets/javascripts/ide/stores/actions/project.js
@@ -2,12 +2,11 @@ import service from '../../services';
import flash from '../../../flash';
import * as types from '../mutation_types';
-// eslint-disable-next-line import/prefer-default-export
export const getProjectData = (
{ commit, state, dispatch },
- { namespace, projectId, enforce = false } = {},
+ { namespace, projectId, force = false } = {},
) => new Promise((resolve, reject) => {
- if (!state.projects[`${namespace}/${projectId}`] || enforce) {
+ if (!state.projects[`${namespace}/${projectId}`] || force) {
service.getProjectData(namespace, projectId)
.then(res => res.data)
.then((data) => {
diff --git a/app/assets/javascripts/ide/stores/actions/tree.js b/app/assets/javascripts/ide/stores/actions/tree.js
index 2cc0f25fe83..2f879fe00c0 100644
--- a/app/assets/javascripts/ide/stores/actions/tree.js
+++ b/app/assets/javascripts/ide/stores/actions/tree.js
@@ -12,14 +12,17 @@ import {
export const getTreeData = (
{ commit, state, dispatch },
- { endpoint = state.endpoints.rootEndpoint, tree = null, projectId, branch } = {},
+ { endpoint, tree = null, projectId, branch } = {},
) => new Promise((resolve, reject) => {
// We already have the base tree so we resolve immediately
if (!tree && state.trees[`${projectId}/${branch}`]) {
resolve();
} else {
if (tree) commit(types.TOGGLE_LOADING, tree);
- service.getTreeData(endpoint)
+ const selectedProject = state.projects[projectId];
+ // We need to do the replacement otherwise the web_url + file.url duplicate
+ const completeEndpoint = selectedProject.web_url + (endpoint).replace(projectId, '');
+ service.getTreeData(completeEndpoint)
.then((res) => {
const pageTitle = decodeURI(normalizeHeaders(res.headers)['PAGE-TITLE']);
diff --git a/app/assets/javascripts/ide/stores/getters.js b/app/assets/javascripts/ide/stores/getters.js
index 309e411a0c9..dc731f22428 100644
--- a/app/assets/javascripts/ide/stores/getters.js
+++ b/app/assets/javascripts/ide/stores/getters.js
@@ -18,13 +18,6 @@ export const treeList = state => (treeId) => {
return [];
};
-export const getTree = state => (namespace, projectId, branch) => state.trees[`${namespace}/${projectId}/${branch}`];
-
-export const getTreeEntry = (state, getters) => (treeId, path) => {
- const fileList = getters.treeList(treeId);
- return fileList.find(file => file.path === path);
-};
-
export const changedFiles = state => state.openFiles.filter(file => file.changed);
export const activeFile = state => state.openFiles.find(file => file.active) || null;
diff --git a/app/assets/javascripts/ide/stores/mutations/file.js b/app/assets/javascripts/ide/stores/mutations/file.js
index fe8d157dfde..5f3655b0092 100644
--- a/app/assets/javascripts/ide/stores/mutations/file.js
+++ b/app/assets/javascripts/ide/stores/mutations/file.js
@@ -51,9 +51,9 @@ export default {
fileLanguage,
});
},
- [types.SET_FILE_EOL](state, { file, EOL }) {
+ [types.SET_FILE_EOL](state, { file, eol }) {
Object.assign(file, {
- EOL,
+ eol,
});
},
[types.SET_FILE_POSITION](state, { file, editorRow, editorColumn }) {
diff --git a/app/assets/javascripts/ide/stores/state.js b/app/assets/javascripts/ide/stores/state.js
index c66c6e927e8..feb90aaec70 100644
--- a/app/assets/javascripts/ide/stores/state.js
+++ b/app/assets/javascripts/ide/stores/state.js
@@ -18,4 +18,6 @@ export default () => ({
parentTreeUrl: '',
trees: {},
projects: {},
+ leftBarCollapsed: false,
+ rightBarCollapsed: false,
});
diff --git a/app/assets/javascripts/ide/stores/utils.js b/app/assets/javascripts/ide/stores/utils.js
index 522a233b8e1..2e1bcb3a64a 100644
--- a/app/assets/javascripts/ide/stores/utils.js
+++ b/app/assets/javascripts/ide/stores/utils.js
@@ -38,7 +38,7 @@ export const dataStructure = () => ({
editorRow: 1,
editorColumn: 1,
fileLanguage: '',
- EOL: '',
+ eol: '',
});
export const decorateData = (entity) => {
@@ -87,6 +87,13 @@ export const decorateData = (entity) => {
};
};
+export const getTree = state => (namespace, projectId, branch) => state.trees[`${namespace}/${projectId}/${branch}`];
+
+export const getTreeEntry = (store, treeId, path) => {
+ const fileList = store.getters.treeList(treeId);
+ return fileList.find(file => file.path === path);
+};
+
export const findEntry = (tree, type, name) => tree.find(
f => f.type === type && f.name === name,
);
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index b84d6c140be..1d6c7a5c472 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -219,6 +219,7 @@ $gl-input-padding: 10px;
$gl-vert-padding: 6px;
$gl-padding-top: 10px;
$gl-sidebar-padding: 22px;
+$gl-bar-padding: 3px;
/*
* Misc
diff --git a/app/assets/stylesheets/pages/repo.scss b/app/assets/stylesheets/pages/repo.scss
index 393eeecd082..f4b1186139f 100644
--- a/app/assets/stylesheets/pages/repo.scss
+++ b/app/assets/stylesheets/pages/repo.scss
@@ -25,7 +25,6 @@
.ide-view {
display: flex;
height: calc(100vh - #{$header-height});
- margin-top: $header-height;
color: $almost-black;
border-top: 1px solid $white-dark;
border-bottom: 1px solid $white-dark;
@@ -52,7 +51,7 @@
text-overflow: ellipsis;
}
- i.unsaved-icon {
+ .unsaved-icon {
color: $indigo-700;
float: right;
font-size: smaller;
@@ -98,6 +97,7 @@
}
.multi-file-table-col-commit-message {
+ white-space: nowrap;
width: 50%;
}
@@ -160,20 +160,34 @@
height: 0;
}
+.blob-editor-container {
+ flex: 1;
+ height: 0;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+
+ .vertical-center {
+ min-height: auto;
+ }
+}
+
.multi-file-editor-holder {
height: 100%;
}
.multi-file-editor-btn-group {
- padding: 3px 0;
+ padding: $gl-bar-padding $gl-padding;
border-top: 1px solid $white-dark;
border-bottom: 1px solid $white-dark;
background: $white-light;
}
.ide-status-bar {
- padding-bottom: 3px;
+ padding: $gl-bar-padding $gl-padding;
background: $white-light;
+ display: flex;
+ justify-content: space-between;
svg {
vertical-align: middle;
@@ -185,10 +199,6 @@
height: 100%;
overflow: scroll;
- .blob-viewer {
- height: calc(100vh - 140px);
- }
-
.file-content.code {
display: flex;
@@ -231,7 +241,6 @@
flex-direction: column;
overflow: auto;
border-bottom: solid 1px $gray-normal;
- margin-bottom: 1px;
}
&.is-collapsed {
@@ -255,29 +264,30 @@
.branch-container {
border-left: 4px solid $indigo-700;
margin-bottom: 2px;
+ }
- .branch-header {
- background: $white-dark;
- display: flex;
-
- .branch-header-title {
- flex: 1;
- padding: 8px 16px;
- color: $indigo-700;
- font-weight: $gl-font-weight-bold;
-
- svg {
- vertical-align: middle;
- }
- }
+ .branch-header {
+ background: $white-dark;
+ display: flex;
+ }
- .branch-header-btns {
- padding: 6px 16px;
- }
+ .branch-header-title {
+ flex: 1;
+ padding: 8px 16px;
+ color: $indigo-700;
+ font-weight: $gl-font-weight-bold;
+
+ svg {
+ vertical-align: middle;
}
}
+ .branch-header-btns {
+ padding: $gl-vert-padding $gl-padding;
+ }
+
.left-collapse-btn {
+ display: none;
background: $gray-light;
text-align: left;
border-top: 1px solid $white-dark;
@@ -415,14 +425,20 @@
}
.ide-loading {
- padding-top: 200px;
- text-align: center;
- font-size: 140%;
+ display: flex;
+ height: 100vh;
+ align-items: center;
+ justify-content: center;
}
-.repo-new-btn {
- float: right;
+.ide-empty-state {
+ display: flex;
+ height: 100vh;
+ align-items: center;
+ justify-content: center;
+}
+.repo-new-btn {
.dropdown-menu {
left: auto;
right: 0;
@@ -434,3 +450,8 @@
}
}
}
+
+.ide-flash-container.flash-container {
+ margin-top: $header-height;
+ margin-bottom: 0;
+}
diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb
index 94c4a92f71c..74ebc016870 100644
--- a/app/helpers/blob_helper.rb
+++ b/app/helpers/blob_helper.rb
@@ -42,7 +42,7 @@ module BlobHelper
end
def ide_edit_path(project = @project, ref = @ref, path = @path, options = {})
- ide_path + '/project' + edit_path(project, ref, path, options)
+ "#{ide_path}/project#{edit_path(project, ref, path, options)}"
end
def ide_blob_link(project = @project, ref = @ref, path = @path, options = {})
@@ -52,13 +52,13 @@ module BlobHelper
return unless blob && blob.readable_text?
- common_classes = "btn js-edit-blob #{options[:extra_class]}"
+ common_classes = "btn js-edit-ide #{options[:extra_class]}"
if !on_top_of_branch?(project, ref)
- button_tag 'Multi edit', class: "#{common_classes} disabled has-tooltip", title: "You can only edit files when you are on a branch", data: { container: 'body' }
+ button_tag 'Multi Edit <span class="label label-primary">Beta</span>', class: "#{common_classes} disabled has-tooltip", title: "You can only edit files when you are on a branch", data: { container: 'body' }
# This condition applies to anonymous or users who can edit directly
elsif !current_user || (current_user && can_modify_blob?(blob, project, ref))
- link_to 'Multi Edit <span class="lable">Beta</span>', ide_edit_path(project, ref, path, options), class: "#{common_classes} btn-sm"
+ link_to 'Multi Edit <span class="label label-primary">Beta</span>'.html_safe, ide_edit_path(project, ref, path, options), class: "#{common_classes} btn-sm"
elsif current_user && can?(current_user, :fork_project, project)
continue_params = {
to: ide_edit_path(project, ref, path, options),
@@ -67,8 +67,8 @@ module BlobHelper
}
fork_path = project_forks_path(project, namespace_key: current_user.namespace.id, continue: continue_params)
- button_tag 'Multi Edit A',
- class: "#{common_classes} js-edit-blob-link-fork-toggler",
+ button_tag 'Multi Edit <span class="label label-primary">Beta</span>',
+ class: "#{common_classes}",
data: { action: 'edit', fork_path: fork_path }
end
end
diff --git a/app/views/ide/index.html.haml b/app/views/ide/index.html.haml
index e14e32db6b6..902518da2e5 100644
--- a/app/views/ide/index.html.haml
+++ b/app/views/ide/index.html.haml
@@ -4,12 +4,12 @@
- page_title 'IDE'
- content_for :page_specific_javascripts do
- = webpack_bundle_tag 'blob'
= webpack_bundle_tag 'common_vue'
= webpack_bundle_tag 'ide'
-#ide
- #content-body.content
- .ide-loading.clgray
- .text-center= icon('spinner spin', class: 'js-source-loading')
- IDE Loading ...
+.ide-flash-container.flash-container
+
+#ide.ide-loading
+ .text-center
+ = icon('spinner spin 2x', 'aria-hidden' => 'true', 'aria-label' => 'Loading content…')
+ %h2.clgray IDE Loading ...
diff --git a/app/views/shared/repo/_repo.html.haml b/app/views/shared/repo/_repo.html.haml
index 87e8c416194..2ab3ef902a9 100644
--- a/app/views/shared/repo/_repo.html.haml
+++ b/app/views/shared/repo/_repo.html.haml
@@ -1,5 +1,5 @@
- @no_container = true;
-#repo{ data: { root: @path.empty?.to_s,
+#repoa{ data: { root: @path.empty?.to_s,
root_url: project_tree_path(project),
url: content_url,
current_branch: @ref,