Commit 03974580 authored by Phil Hughes's avatar Phil Hughes

Tidy up IDE code

[ci skip]
parent 1a294f8e
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
import repoTabs from './repo_tabs.vue'; import repoTabs from './repo_tabs.vue';
import repoFileButtons from './repo_file_buttons.vue'; import repoFileButtons from './repo_file_buttons.vue';
import ideStatusBar from './ide_status_bar.vue'; import ideStatusBar from './ide_status_bar.vue';
import repoPreview from './repo_preview.vue';
import repoEditor from './repo_editor.vue'; import repoEditor from './repo_editor.vue';
export default { export default {
...@@ -16,7 +15,6 @@ ...@@ -16,7 +15,6 @@
repoFileButtons, repoFileButtons,
ideStatusBar, ideStatusBar,
repoEditor, repoEditor,
repoPreview,
}, },
props: { props: {
emptyStateSvgPath: { emptyStateSvgPath: {
...@@ -34,8 +32,6 @@ ...@@ -34,8 +32,6 @@
}, },
computed: { computed: {
...mapState([ ...mapState([
'currentBlobView',
'selectedFile',
'changedFiles', 'changedFiles',
]), ]),
...mapGetters([ ...mapGetters([
...@@ -68,13 +64,12 @@ ...@@ -68,13 +64,12 @@
v-if="activeFile" v-if="activeFile"
> >
<repo-tabs/> <repo-tabs/>
<component <repo-editor
class="multi-file-edit-pane-content" class="multi-file-edit-pane-content"
:is="currentBlobView"
/> />
<repo-file-buttons /> <repo-file-buttons />
<ide-status-bar <ide-status-bar
:file="selectedFile" :file="activeFile"
/> />
</template> </template>
<template <template
......
...@@ -3,12 +3,14 @@ ...@@ -3,12 +3,14 @@
import icon from '~/vue_shared/components/icon.vue'; import icon from '~/vue_shared/components/icon.vue';
import panelResizer from '~/vue_shared/components/panel_resizer.vue'; import panelResizer from '~/vue_shared/components/panel_resizer.vue';
import repoCommitSection from './repo_commit_section.vue'; import repoCommitSection from './repo_commit_section.vue';
import ResizablePanel from './resizable_panel.vue';
export default { export default {
components: { components: {
repoCommitSection, repoCommitSection,
icon, icon,
panelResizer, panelResizer,
ResizablePanel,
}, },
props: { props: {
noChangesStateSvgPath: { noChangesStateSvgPath: {
...@@ -70,13 +72,10 @@ ...@@ -70,13 +72,10 @@
</script> </script>
<template> <template>
<div <resizable-panel
class="multi-file-commit-panel" :collapsible="true"
:class="{ :initial-width="340"
'is-collapsed': rightPanelCollapsed, side="right"
}"
:style="panelStyle"
@click="toggleFullbarCollapsed"
> >
<div <div
class="multi-file-commit-panel-section" class="multi-file-commit-panel-section"
...@@ -117,15 +116,5 @@ ...@@ -117,15 +116,5 @@
:committed-state-svg-path="committedStateSvgPath" :committed-state-svg-path="committedStateSvgPath"
/> />
</div> </div>
<panel-resizer </resizable-panel>
:size.sync="width"
:enabled="!rightPanelCollapsed"
:start-size="340"
:min-size="200"
:max-size="maxSize"
@resize-start="resizingStarted"
@resize-end="resizingEnded"
side="left"
/>
</div>
</template> </template>
<script> <script>
import { mapState } from 'vuex'; import { mapState, mapGetters } from 'vuex';
import skeletonLoadingContainer from '~/vue_shared/components/skeleton_loading_container.vue'; import skeletonLoadingContainer from '~/vue_shared/components/skeleton_loading_container.vue';
import repoFile from './repo_file.vue'; import repoFile from './repo_file.vue';
...@@ -23,6 +23,9 @@ export default { ...@@ -23,6 +23,9 @@ export default {
return state.project.name; return state.project.name;
}, },
}), }),
...mapGetters([
'treeList',
]),
selctedTree() { selctedTree() {
return this.trees[this.treeId].tree; return this.trees[this.treeId].tree;
}, },
...@@ -48,7 +51,7 @@ export default { ...@@ -48,7 +51,7 @@ export default {
</div> </div>
</template> </template>
<repo-file <repo-file
v-for="file in selctedTree" v-for="file in treeList"
:key="file.key" :key="file.key"
:file="file" :file="file"
/> />
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
import panelResizer from '~/vue_shared/components/panel_resizer.vue'; import panelResizer from '~/vue_shared/components/panel_resizer.vue';
import skeletonLoadingContainer from '~/vue_shared/components/skeleton_loading_container.vue'; import skeletonLoadingContainer from '~/vue_shared/components/skeleton_loading_container.vue';
import projectTree from './ide_project_tree.vue'; import projectTree from './ide_project_tree.vue';
import ResizablePanel from './resizable_panel.vue';
export default { export default {
components: { components: {
...@@ -11,6 +12,7 @@ ...@@ -11,6 +12,7 @@
icon, icon,
panelResizer, panelResizer,
skeletonLoadingContainer, skeletonLoadingContainer,
ResizablePanel,
}, },
data() { data() {
return { return {
...@@ -61,12 +63,10 @@ ...@@ -61,12 +63,10 @@
</script> </script>
<template> <template>
<div <resizable-panel
class="multi-file-commit-panel" :collapsible="false"
:class="{ :initial-width="290"
'is-collapsed': leftPanelCollapsed, side="left"
}"
:style="panelStyle"
> >
<div class="multi-file-commit-panel-inner"> <div class="multi-file-commit-panel-inner">
<template v-if="showLoading"> <template v-if="showLoading">
...@@ -84,31 +84,5 @@ ...@@ -84,31 +84,5 @@
:project="project" :project="project"
/> />
</div> </div>
<button </resizable-panel>
type="button"
class="btn btn-transparent left-collapse-btn"
@click="toggleCollapsed"
>
<icon
:name="currentIcon"
:size="18"
/>
<span
v-if="!leftPanelCollapsed"
class="collapse-text"
>
Collapse sidebar
</span>
</button>
<panel-resizer
:size.sync="width"
:enabled="!leftPanelCollapsed"
:start-size="290"
:min-size="200"
:max-size="maxSize"
@resize-start="resizingStarted"
@resize-end="resizingEnded"
side="right"
/>
</div>
</template> </template>
<script> <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 tooltip from '~/vue_shared/directives/tooltip';
import timeAgoMixin from '~/vue_shared/mixins/timeago'; import timeAgoMixin from '~/vue_shared/mixins/timeago';
...@@ -20,11 +19,6 @@ ...@@ -20,11 +19,6 @@
required: true, required: true,
}, },
}, },
computed: {
...mapState([
'selectedFile',
]),
},
}; };
</script> </script>
...@@ -35,32 +29,32 @@ ...@@ -35,32 +29,32 @@
name="branch" name="branch"
:size="12" :size="12"
/> />
{{ selectedFile.branchId }} {{ file.branchId }}
</div> </div>
<div> <div>
<div v-if="selectedFile.lastCommit && selectedFile.lastCommit.id"> <div v-if="file.lastCommit && file.lastCommit.id">
Last commit: Last commit:
<a <a
v-tooltip v-tooltip
:title="selectedFile.lastCommit.message" :title="file.lastCommit.message"
:href="selectedFile.lastCommit.url" :href="file.lastCommit.url"
> >
{{ timeFormated(selectedFile.lastCommit.updatedAt) }} by {{ timeFormated(file.lastCommit.updatedAt) }} by
{{ selectedFile.lastCommit.author }} {{ file.lastCommit.author }}
</a> </a>
</div> </div>
</div> </div>
<div class="text-right"> <div class="text-right">
{{ selectedFile.name }} {{ file.name }}
</div> </div>
<div class="text-right"> <div class="text-right">
{{ selectedFile.eol }} {{ file.eol }}
</div> </div>
<div class="text-right"> <div class="text-right">
{{ file.editorRow }}:{{ file.editorColumn }} {{ file.editorRow }}:{{ file.editorColumn }}
</div> </div>
<div class="text-right"> <div class="text-right">
{{ selectedFile.fileLanguage }} {{ file.fileLanguage }}
</div> </div>
</div> </div>
</template> </template>
<script>
import { mapGetters, mapActions, mapState } from 'vuex';
import modal from '~/vue_shared/components/modal.vue';
export default {
components: {
modal,
},
computed: {
...mapState([
'editMode',
]),
...mapGetters([
'canEditFile',
]),
buttonLabel() {
return this.editMode ? this.__('Cancel edit') : this.__('Edit');
},
},
methods: {
...mapActions([
'toggleEditMode',
]),
},
};
</script>
<template>
<div class="editable-mode">
<button
v-if="canEditFile"
class="btn btn-default"
type="button"
@click.prevent="toggleEditMode()">
<i
v-if="!editMode"
class="fa fa-pencil"
aria-hidden="true">
</i>
<span>
{{ buttonLabel }}
</span>
</button>
</div>
</template>
...@@ -9,7 +9,6 @@ export default { ...@@ -9,7 +9,6 @@ export default {
computed: { computed: {
...mapGetters([ ...mapGetters([
'activeFile', 'activeFile',
'activeFileExtension',
]), ]),
...mapState([ ...mapState([
'leftPanelCollapsed', 'leftPanelCollapsed',
...@@ -22,7 +21,7 @@ export default { ...@@ -22,7 +21,7 @@ export default {
}, },
watch: { watch: {
activeFile(oldVal, newVal) { activeFile(oldVal, newVal) {
if (newVal && !newVal.active) { if (newVal.path !== this.activeFile.path) {
this.initMonaco(); this.initMonaco();
} }
}, },
......
<script>
import $ from 'jquery';
import { mapGetters } from 'vuex';
import LineHighlighter from '~/line_highlighter';
import syntaxHighlight from '~/syntax_highlight';
export default {
computed: {
...mapGetters([
'activeFile',
]),
renderErrorTooLarge() {
return this.activeFile.renderError === 'too_large';
},
},
mounted() {
this.highlightFile();
this.lineHighlighter = new LineHighlighter({
fileHolderSelector: '.blob-viewer-container',
scrollFileHolder: true,
});
},
updated() {
this.$nextTick(() => {
this.highlightFile();
});
},
methods: {
highlightFile() {
syntaxHighlight($(this.$el).find('.file-content'));
},
},
};
</script>
<template>
<div>
<div
v-if="!activeFile.renderError"
v-html="activeFile.html"
class="multi-file-preview-holder"
>
</div>
<div
v-else-if="activeFile.tempFile"
class="vertical-center render-error">
<p class="text-center">
The source could not be displayed for this temporary file.
</p>
</div>
<div
v-else-if="renderErrorTooLarge"
class="vertical-center render-error">
<p class="text-center">
The source could not be displayed because it is too large.
You can <a
:href="activeFile.rawPath"
download>download</a> it instead.
</p>
</div>
<div
v-else
class="vertical-center render-error">
<p class="text-center">
The source could not be displayed because a rendering error occurred.
You can <a
:href="activeFile.rawPath"
download>download</a> it instead.
</p>
</div>
</div>
</template>
<script> <script>
import { mapState } from 'vuex'; import { mapGetters } from 'vuex';
import RepoTab from './repo_tab.vue'; import RepoTab from './repo_tab.vue';
export default { export default {
...@@ -7,8 +7,8 @@ ...@@ -7,8 +7,8 @@
'repo-tab': RepoTab, 'repo-tab': RepoTab,
}, },
computed: { computed: {
...mapState([ ...mapGetters([
'openFiles', 'openFilesMap',
]), ]),
}, },
}; };
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
class="multi-file-tabs list-unstyled append-bottom-0" class="multi-file-tabs list-unstyled append-bottom-0"
> >
<repo-tab <repo-tab
v-for="tab in openFiles" v-for="tab in openFilesMap"
:key="tab.key" :key="tab.key"
:tab="tab" :tab="tab"
/> />
......
<script>
import { mapActions, mapState } from 'vuex';
import PanelResizer from '~/vue_shared/components/panel_resizer.vue';
export default {
components: {
PanelResizer,
},
props: {
collapsible: {
type: Boolean,
required: true,
},
initialWidth: {
type: Number,
required: true,
},
minSize: {
type: Number,
required: false,
default: 200,
},
side: {
type: String,
required: true,
},
},
data() {
return {
width: this.initialWidth,
};
},
computed: {
...mapState({
collapsed(state) {
return state[`${this.side}PanelCollapsed`];
},
}),
panelStyle() {
if (!this.collapsed) {
return {
width: `${this.width}px`,
};
}
return {};
},
},
methods: {
...mapActions([
'setPanelCollapsedStatus',
'setResizingStatus',
]),
toggleFullbarCollapsed() {
if (this.collapsed && this.collapsible) {
this.setPanelCollapsedStatus({
side: this.side,
collapsed: !this.collapsed,
});
}
},
},
maxSize: (window.innerWidth / 2),
};
</script>
<template>
<div
class="multi-file-commit-panel"
:class="{
'is-collapsed': collapsed && collapsible,
}"
:style="panelStyle"
@click="toggleFullbarCollapsed"
>
<slot></slot>
<panel-resizer
:size.sync="width"
:enabled="!collapsed"
:start-size="initialWidth"
:min-size="minSize"
:max-size="$options.maxSize"
@resize-start="setResizingStatus(true)"
@resize-end="setResizingStatus(false)"
:side="side === 'right' ? 'left' : 'right'"
/>
</div>
</template>
...@@ -2,9 +2,6 @@ import Vue from 'vue'; ...@@ -2,9 +2,6 @@ import Vue from 'vue';
import VueRouter from 'vue-router'; import VueRouter from 'vue-router';
import flash from '~/flash'; import flash from '~/flash';
import store from './stores'; import store from './stores';
import {
getTreeEntry,
} from './stores/utils';
Vue.use(VueRouter); Vue.use(VueRouter);
...@@ -76,7 +73,7 @@ router.beforeEach((to, from, next) => { ...@@ -76,7 +73,7 @@ router.beforeEach((to, from, next) => {
}) })
.then(() => { .then(() => {
if (to.params[0]) { if (to.params[0]) {
const treeEntry = getTreeEntry(store, `${to.params.namespace}/${to.params.project}/${to.params.branch}`, to.params[0]); const treeEntry = store.state.entries[to.params[0]];
if (treeEntry) { if (treeEntry) {
store.dispatch('handleTreeEntryAction', treeEntry); store.dispatch('handleTreeEntryAction', treeEntry);
} }
......
...@@ -23,19 +23,6 @@ export const closeAllFiles = ({ state, dispatch }) => { ...@@ -23,19 +23,6 @@ export const closeAllFiles = ({ state, dispatch }) => {
state.openFiles.forEach(file => dispatch('closeFile', file)); state.openFiles.forEach(file => dispatch('closeFile', file));
}; };
export const toggleEditMode = ({ commit, dispatch }) => {
commit(types.TOGGLE_EDIT_MODE);
dispatch('toggleBlobView');
};
export const toggleBlobView = ({ commit, state }) => {
if (state.editMode) {
commit(types.SET_EDIT_MODE);
} else {
commit(types.SET_PREVIEW_MODE);
}
};
export const setPanelCollapsedStatus = ({ commit }, { side, collapsed }) => { export const setPanelCollapsedStatus = ({ commit }, { side, collapsed }) => {
if (side === 'left') { if (side === 'left') {
commit(types.SET_LEFT_PANEL_COLLAPSED, collapsed); commit(types.SET_LEFT_PANEL_COLLAPSED, collapsed);
......
...@@ -10,8 +10,8 @@ import { ...@@ -10,8 +10,8 @@ import {
findIndexOfFile, findIndexOfFile,
} from '../utils'; } from '../utils';
export const closeFile = ({ commit, state, dispatch }, file) => { export const closeFile = ({ commit, state, getters, dispatch }, file) => {
const indexOfClosedFile = findIndexOfFile(state.openFiles, file); const indexOfClosedFile = state.openFiles.indexOf(file.path);
const fileWasActive = file.active; const fileWasActive = file.active;
commit(types.TOGGLE_FILE_OPEN, file); commit(types.TOGGLE_FILE_OPEN, file);
...@@ -19,7 +19,7 @@ export const closeFile = ({ commit, state, dispatch }, file) => { ...@@ -19,7 +19,7 @@ export const closeFile = ({ commit, state, dispatch }, file) => {
if (state.openFiles.length > 0 && fileWasActive) { if (state.openFiles.length > 0 && fileWasActive) {
const nextIndexToOpen = indexOfClosedFile === 0 ? 0 : indexOfClosedFile - 1; const nextIndexToOpen = indexOfClosedFile === 0 ? 0 : indexOfClosedFile - 1;
const nextFileToOpen = state.openFiles[nextIndexToOpen]; const nextFileToOpen = state.entries[state.openFiles[nextIndexToOpen]];
router.push(`/project${nextFileToOpen.url}`); router.push(`/project${nextFileToOpen.url}`);
} else if (!state.openFiles.length) { } else if (!state.openFiles.length) {
...@@ -89,21 +89,21 @@ export const changeFileContent = ({ state, commit }, { file, content }) => { ...@@ -89,21 +89,21 @@ export const changeFileContent = ({ state, commit }, { file, content }) => {
} }
}; };
export const setFileLanguage = ({ state, commit }, { fileLanguage }) => { export const setFileLanguage = ({ getters, commit }, { fileLanguage }) => {
if (state.selectedFile) { if (getters.activeFile) {
commit(types.SET_FILE_LANGUAGE, { file: state.selectedFile, fileLanguage }); commit(types.SET_FILE_LANGUAGE, { file: getters.activeFile, fileLanguage });
} }
}; };
export const setFileEOL = ({ state, commit }, { eol }) => { export const setFileEOL = ({ getters, commit }, { eol }) => {
if (state.selectedFile) { if (getters.activeFile) {
commit(types.SET_FILE_EOL, { file: state.selectedFile, eol }); commit(types.SET_FILE_EOL, { file: getters.activeFile, eol });
} }
}; };
export const setEditorPosition = ({ state, commit }, { editorRow, editorColumn }) => { export const setEditorPosition = ({ getters, commit }, { editorRow, editorColumn }) => {
if (state.selectedFile) { if (getters.activeFile) {
commit(types.SET_FILE_POSITION, { file: state.selectedFile, editorRow, editorColumn }); commit(types.SET_FILE_POSITION, { file: getters.activeFile, editorRow, editorColumn });
} }
}; };
...@@ -134,10 +134,6 @@ export const createTempFile = ({ state, commit, dispatch }, { projectId, branchI ...@@ -134,10 +134,6 @@ export const createTempFile = ({ state, commit, dispatch }, { projectId, branchI
commit(types.ADD_FILE_TO_CHANGED, file); commit(types.ADD_FILE_TO_CHANGED, file);
dispatch('setFileActive', file); dispatch('setFileActive', file);
if (!state.editMode && !file.base64) {
dispatch('toggleEditMode', true);
}
router.push(`/project${file.url}`); router.push(`/project${file.url}`);
return Promise.resolve(file); return Promise.resolve(file);
......
...@@ -9,7 +9,7 @@ import { ...@@ -9,7 +9,7 @@ import {
findEntry, findEntry,
createTemp, createTemp,
createOrMergeEntry, createOrMergeEntry,
sortTree, decorateData,
} from '../utils'; } from '../utils';
export const getTreeData = ( export const getTreeData = (
...@@ -199,72 +199,70 @@ export const getFiles = ( ...@@ -199,72 +199,70 @@ export const getFiles = (
.getFiles(selectedProject.web_url, branchId) .getFiles(selectedProject.web_url, branchId)
.then(res => res.json()) .then(res => res.json())
.then((data) => { .then((data) => {
const newTree = data.reduce((outputArray, file) => { const treeList = [];
const pathSplit = file.split('/'); const entries = data.reduce((acc, path) => {
const pathSplit = path.split('/');
const blobName = pathSplit.pop(); const blobName = pathSplit.pop();
let selectedFolderTree;
let foundFolder = null;
let fullPath = '';
if (pathSplit.length > 0) { if (pathSplit.length > 0) {
const newBaseFolders = pathSplit.reduce((newFolders, folder, currentIndex) => { pathSplit.reduce((pathAcc, folderName, folderLevel) => {
fullPath += `/${folder}`; const folderPath = `${(pathAcc.length ? `${pathAcc[pathAcc.length - 1]}/` : '')}${folderName}`;
foundFolder = findEntry(selectedFolderTree || outputArray, 'tree', fullPath, 'path'); const foundEntry = state.entries[folderPath];
if (!foundFolder) {
foundFolder = createOrMergeEntry({ if (!foundEntry) {
const tree = decorateData({
projectId, projectId,
branchId, branchId,
entry: { id: folderPath,
id: fullPath, name: folderName,
name: folder, path: folderPath,
path: fullPath, url: `/${projectId}/tree/${branchId}/${folderPath}`,
url: `/${projectId}/tree/${branchId}/${fullPath}`, level: folderLevel,
},
level: currentIndex,
type: 'tree', type: 'tree',
parentTreeUrl: '',
state,
}); });
if (selectedFolderTree) { Object.assign(acc, {
selectedFolderTree.push(foundFolder); [folderPath]: tree,
} else { });
newFolders.push(foundFolder);
if (folderLevel === 0) {
treeList.push(tree.path);
} }
} }
selectedFolderTree = foundFolder.tree;
return newFolders; return pathAcc;
}, []); }, []);
if (newBaseFolders.length) outputArray.push(newBaseFolders[0]);
} }
// Add file const fileFolder = acc[pathSplit.join('/')];
const blobEntry = createOrMergeEntry({ const file = decorateData({
projectId, projectId,
branchId, branchId,
entry: { id: path,
id: file,
name: blobName, name: blobName,
path: file, path,
url: `/${projectId}/blob/${branchId}/${file}`, url: `/${projectId}/blob/${branchId}/${path}`,
}, level: fileFolder ? fileFolder.level + 1 : 0,
level: foundFolder ? (foundFolder.level + 1) : 0,
type: 'blob', type: 'blob',
parentTreeUrl: foundFolder ? foundFolder.url : '',
state,
}); });
if (selectedFolderTree) { Object.assign(acc, {
selectedFolderTree.push(blobEntry); [path]: file,
});
if (fileFolder) {
fileFolder.tree.push(path);
} else { } else {
outputArray.push(blobEntry); treeList.push(file.path);
} }
return outputArray; return acc;
}, []); }, {});
const selectedTree = state.trees[`${projectId}/${branchId}`]; const selectedTree = state.trees[`${projectId}/${branchId}`];
commit(types.SET_DIRECTORY_DATA, { tree: selectedTree, data: sortTree(newTree) });
commit(types.SET_ENTRIES, entries);
commit(types.SET_DIRECTORY_DATA, { tree: selectedTree, data: treeList });
commit(types.TOGGLE_LOADING, { entry: selectedTree, forceValue: false }); commit(types.TOGGLE_LOADING, { entry: selectedTree, forceValue: false });
resolve(); resolve();
......
export const activeFile = state => state.openFiles.find(file => file.active) || null; import { sortTree } from './utils';
export const activeFileExtension = (state) => { export const openFilesMap = state => state.openFiles.map(path => state.entries[path]);
const file = activeFile(state);
return file ? `.${file.path.split('.').pop()}` : ''; export const activeFile = state => openFilesMap(state).find(file => file.active) || null;
};
export const canEditFile = (state) => { export const canEditFile = (state) => {
const currentActiveFile = activeFile(state); const currentActiveFile = activeFile(state);
...@@ -15,3 +14,28 @@ export const canEditFile = (state) => { ...@@ -15,3 +14,28 @@ export const canEditFile = (state) => {
export const addedFiles = state => state.changedFiles.filter(f => f.tempFile); 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 treeList = (state) => {
const tree = state.trees['root/testing-123/master'];
if (!tree) return [];
const map = (arr) => {
if (!arr.tree.length) return [];
return sortTree(arr.tree.reduce((acc, key) => {
const entity = state.entries[key];
if (entity) {
return acc.concat({
...entity,
tree: map(entity),
});
}
return acc;
}, []));
};
return map(tree);
};
...@@ -40,9 +40,6 @@ export const ADD_FILE_TO_CHANGED = 'ADD_FILE_TO_CHANGED'; ...@@ -40,9 +40,6 @@ export const ADD_FILE_TO_CHANGED = 'ADD_FILE_TO_CHANGED';
export const REMOVE_FILE_FROM_CHANGED = 'REMOVE_FILE_FROM_CHANGED'; export const REMOVE_FILE_FROM_CHANGED = 'REMOVE_FILE_FROM_CHANGED';
export const TOGGLE_FILE_CHANGED = 'TOGGLE_FILE_CHANGED'; export const TOGGLE_FILE_CHANGED = 'TOGGLE_FILE_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 SET_CURRENT_BRANCH = 'SET_CURRENT_BRANCH'; export const SET_CURRENT_BRANCH = 'SET_CURRENT_BRANCH';
export const SET_ENTRIES = 'SET_ENTRIES';
...@@ -8,25 +8,22 @@ export default { ...@@ -8,25 +8,22 @@ export default {
[types.SET_INITIAL_DATA](state, data) { [types.SET_INITIAL_DATA](state, data) {
Object.assign(state, data); Object.assign(state, data);
}, },
[types.SET_PREVIEW_MODE](state) { [types.TOGGLE_LOADING](state, { entry, forceValue = undefined }) {
if (entry.path) {
Object.assign(state, { Object.assign(state, {
currentBlobView: 'repo-preview', entries: {
}); ...state.entries,
[entry.path]: {
...state.entries[entry.path],
loading: forceValue !== undefined ? forceValue : !state.entries[entry.path].loading,
}, },
[types.SET_EDIT_MODE](state) {
Object.assign(state, {
currentBlobView: 'repo-editor',
});
}, },
[types.TOGGLE_LOADING](state, { entry, forceValue = undefined }) { });
} else {
Object.assign(entry, { Object.assign(entry, {
loading: forceValue !== undefined ? forceValue : !entry.loading, loading: forceValue !== undefined ? forceValue : !entry.loading,
}); });
}, }
[types.TOGGLE_EDIT_MODE](state) {
Object.assign(state, {
editMode: !state.editMode,
});
}, },
[types.SET_LEFT_PANEL_COLLAPSED](state, collapsed) { [types.SET_LEFT_PANEL_COLLAPSED](state, collapsed) {
Object.assign(state, { Object.assign(state, {
...@@ -57,6 +54,11 @@ export default { ...@@ -57,6 +54,11 @@ export default {
lastCommitMsg, lastCommitMsg,
}); });
}, },
[types.SET_ENTRIES](state, entries) {
Object.assign(state, {
entries,
});
},
...projectMutations, ...projectMutations,
...fileMutations, ...fileMutations,
...treeMutations, ...treeMutations,
......
...@@ -3,27 +3,39 @@ import { findIndexOfFile } from '../utils'; ...@@ -3,27 +3,39 @@ import { findIndexOfFile } from '../utils';
export default { export default {
[types.SET_FILE_ACTIVE](state, { file, active }) { [types.SET_FILE_ACTIVE](state, { file, active }) {
Object.assign(file, {
active,
});
Object.assign(state, { Object.assign(state, {
selectedFile: file, entries: {
...state.entries,
[file.path]: {
...state.entries[file.path],
active,
},
},
}); });
}, },
[types.TOGGLE_FILE_OPEN](state, file) { [types.TOGGLE_FILE_OPEN](state, file) {
Object.assign(file, { Object.assign(state, {
opened: !file.opened, entries: {
...state.entries,
[file.path]: {
...state.entries[file.path],
opened: !state.entries[file.path].opened,
},
},
}); });
if (file.opened) { if (state.entries[file.path].opened) {
state.openFiles.push(file); state.openFiles.push(file.path);
} else { } else {
state.openFiles.splice(findIndexOfFile(state.openFiles, file), 1); state.openFiles.splice(state.openFiles.indexOf(file.path), 1);
} }
}, },
[types.SET_FILE_DATA](state, { data, file }) { [types.SET_FILE_DATA](state, { data, file }) {
Object.assign(file, { Object.assign(state, {
entries: {
...state.entries,
[file.path]: {
...state.entries[file.path],
id: data.id, id: data.id,
blamePath: data.blame_path, blamePath: data.blame_path,
commitsPath: data.commits_path, commitsPath: data.commits_path,
...@@ -31,11 +43,19 @@ export default { ...@@ -31,11 +43,19 @@ export default {
rawPath: data.raw_path, rawPath: data.raw_path,
binary: data.binary, binary: data.binary,
renderError: data.render_error, renderError: data.render_error,
},
},
}); });
}, },
[types.SET_FILE_RAW_DATA](state, { file, raw }) { [types.SET_FILE_RAW_DATA](state, { file, raw }) {
Object.assign(file, { Object.assign(state, {
entries: {
...state.entries,
[file.path]: {
...state.entries[file.path],
raw, raw,
},
},
}); });
}, },
[types.UPDATE_FILE_CONTENT](state, { file, content }) { [types.UPDATE_FILE_CONTENT](state, { file, content }) {
...@@ -47,19 +67,37 @@ export default { ...@@ -47,19 +67,37 @@ export default {
}); });
}, },
[types.SET_FILE_LANGUAGE](state, { file, fileLanguage }) { [types.SET_FILE_LANGUAGE](state, { file, fileLanguage }) {
Object.assign(file, { Object.assign(state, {
entries: {
...state.entries,
[file.path]: {
...state.entries[file.path],
fileLanguage, fileLanguage,
},
},
}); });
}, },
[types.SET_FILE_EOL](state, { file, eol }) { [types.SET_FILE_EOL](state, { file, eol }) {
Object.assign(file, { Object.assign(state, {
entries: {
...state.entries,
[file.path]: {
...state.entries[file.path],
eol, eol,
},
},
}); });
}, },
[types.SET_FILE_POSITION](state, { file, editorRow, editorColumn }) { [types.SET_FILE_POSITION](state, { file, editorRow, editorColumn }) {
Object.assign(file, { Object.assign(state, {
entries: {
...state.entries,
[file.path]: {
...state.entries[file.path],
editorRow, editorRow,
editorColumn, editorColumn,
},
},
}); });
}, },
[types.DISCARD_FILE_CHANGES](state, file) { [types.DISCARD_FILE_CHANGES](state, file) {
......
...@@ -2,8 +2,14 @@ import * as types from '../mutation_types'; ...@@ -2,8 +2,14 @@ import * as types from '../mutation_types';
export default { export default {
[types.TOGGLE_TREE_OPEN](state, tree) { [types.TOGGLE_TREE_OPEN](state, tree) {
Object.assign(tree, { Object.assign(state, {
opened: !tree.opened, entries: {
...state.entries,
[tree.path]: {
...state.entries[tree.path],
opened: !state.entries[tree.path].opened,
},
},
}); });
}, },
[types.CREATE_TREE](state, { treePath }) { [types.CREATE_TREE](state, { treePath }) {
......
...@@ -2,9 +2,7 @@ export default () => ({ ...@@ -2,9 +2,7 @@ export default () => ({
canCommit: false, canCommit: false,
currentProjectId: '', currentProjectId: '',
currentBranchId: '', currentBranchId: '',
currentBlobView: 'repo-editor',
changedFiles: [], changedFiles: [],
editMode: true,
endpoints: {}, endpoints: {},
isInitialRoot: false, isInitialRoot: false,
lastCommitMsg: '', lastCommitMsg: '',
...@@ -20,4 +18,5 @@ export default () => ({ ...@@ -20,4 +18,5 @@ export default () => ({
leftPanelCollapsed: false, leftPanelCollapsed: false,
rightPanelCollapsed: false, rightPanelCollapsed: false,
panelResizing: false, panelResizing: false,
entries: {},
}); });
...@@ -11,7 +11,6 @@ export const dataStructure = () => ({ ...@@ -11,7 +11,6 @@ export const dataStructure = () => ({
path: '', path: '',
level: 0, level: 0,
tempFile: false, tempFile: false,
icon: '',
tree: [], tree: [],
loading: false, loading: false,
opened: false, opened: false,
...@@ -51,7 +50,6 @@ export const decorateData = (entity) => { ...@@ -51,7 +50,6 @@ export const decorateData = (entity) => {
type, type,
url, url,
name, name,
icon,
tree_url, tree_url,
path, path,
renderError, renderError,
...@@ -81,7 +79,6 @@ export const decorateData = (entity) => { ...@@ -81,7 +79,6 @@ export const decorateData = (entity) => {
path, path,
level, level,
tempFile, tempFile,
icon: `fa-${icon}`,
opened, opened,
active, active,
parentTreeUrl, parentTreeUrl,
...@@ -144,7 +141,6 @@ export const createTemp = ({ ...@@ -144,7 +141,6 @@ export const createTemp = ({
type, type,
tempFile: true, tempFile: true,
path: treePath, path: treePath,
icon: type === 'tree' ? 'folder' : 'file-text-o',
changed, changed,
content, content,
parentTreeUrl: '', parentTreeUrl: '',
......
...@@ -117,16 +117,6 @@ describe('new file modal component', () => { ...@@ -117,16 +117,6 @@ describe('new file modal component', () => {
}); });
}); });
it('toggles blob view', (done) => {
vm.createEntryInStore();
setTimeout(() => {
expect(vm.$store.state.currentBlobView).toBe('repo-editor');
done();
});
});
it('opens newly created file', (done) => { it('opens newly created file', (done) => {
if (type === 'blob') { if (type === 'blob') {
vm.createEntryInStore(); vm.createEntryInStore();
......
import Vue from 'vue';
import store from 'ee/ide/stores';
import repoEditButton from 'ee/ide/components/repo_edit_button.vue';
import { file, resetStore } from '../helpers';
describe('RepoEditButton', () => {
let vm;
beforeEach(() => {
const f = file();
const RepoEditButton = Vue.extend(repoEditButton);
vm = new RepoEditButton({
store,
});
f.active = true;
vm.$store.dispatch('setInitialData', {
canCommit: true,
onTopOfBranch: true,
});
vm.$store.state.openFiles.push(f);
});
afterEach(() => {
vm.$destroy();
resetStore(vm.$store);
});
it('renders an edit button', () => {
vm.$mount();
expect(vm.$el.querySelector('.btn')).not.toBeNull();
expect(vm.$el.querySelector('.btn').textContent.trim()).toBe('Cancel edit');
});
it('renders edit button with cancel text', () => {
vm.$store.state.editMode = true;
vm.$mount();
expect(vm.$el.querySelector('.btn')).not.toBeNull();
expect(vm.$el.querySelector('.btn').textContent.trim()).toBe('Cancel edit');
});
it('toggles edit mode on click', (done) => {
vm.$mount();
vm.$el.querySelector('.btn').click();
vm.$nextTick(() => {
expect(vm.$el.querySelector('.btn').textContent.trim()).toBe('Edit');
done();
});
});
});
import Vue from 'vue';
import store from 'ee/ide/stores';
import repoPreview from 'ee/ide/components/repo_preview.vue';
import { file, resetStore } from '../helpers';
describe('RepoPreview', () => {
let vm;
function createComponent() {
const f = file();
const RepoPreview = Vue.extend(repoPreview);
const comp = new RepoPreview({
store,
});
f.active = true;
f.html = 'test';
comp.$store.state.openFiles.push(f);
return comp.$mount();
}
afterEach(() => {
vm.$destroy();
resetStore(vm.$store);
});
it('renders a div with the activeFile html', () => {
vm = createComponent();
expect(vm.$el.tagName).toEqual('DIV');
expect(vm.$el.innerHTML).toContain('test');
});
});
import Vue from 'vue';
import * as urlUtils from '~/lib/utils/url_utility'; import * as urlUtils from '~/lib/utils/url_utility';
import store from 'ee/ide/stores'; import store from 'ee/ide/stores';
import router from 'ee/ide/ide_router'; import router from 'ee/ide/ide_router';
...@@ -84,56 +83,6 @@ describe('Multi-file store actions', () => { ...@@ -84,56 +83,6 @@ describe('Multi-file store actions', () => {
}); });
}); });
describe('toggleEditMode', () => {
it('toggles edit mode', (done) => {
store.state.editMode = true;
store.dispatch('toggleEditMode')
.then(() => {
expect(store.state.editMode).toBeFalsy();
done();
}).catch(done.fail);
});
it('sets preview mode', (done) => {
store.state.currentBlobView = 'repo-editor';
store.state.editMode = true;
store.dispatch('toggleEditMode')
.then(Vue.nextTick)
.then(() => {
expect(store.state.currentBlobView).toBe('repo-preview');
done();
}).catch(done.fail);
});
});
describe('toggleBlobView', () => {
it('sets edit mode view if in edit mode', (done) => {
store.dispatch('toggleBlobView')
.then(() => {
expect(store.state.currentBlobView).toBe('repo-editor');
done();
})
.catch(done.fail);
});
it('sets preview mode view if not in edit mode', (done) => {
store.state.editMode = false;
store.dispatch('toggleBlobView')
.then(() => {
expect(store.state.currentBlobView).toBe('repo-preview');
done();
})
.catch(done.fail);
});
});
describe('createTempEntry', () => { describe('createTempEntry', () => {
beforeEach(() => { beforeEach(() => {
store.state.trees['abcproject/mybranch'] = { store.state.trees['abcproject/mybranch'] = {
......
...@@ -26,20 +26,6 @@ describe('Multi-file store getters', () => { ...@@ -26,20 +26,6 @@ describe('Multi-file store getters', () => {
}); });
}); });
describe('activeFileExtension', () => {
it('returns the file extension for the current active file', () => {
localState.openFiles.push(file('active'));
localState.openFiles[0].active = true;
localState.openFiles[0].path = 'test.js';
expect(getters.activeFileExtension(localState)).toBe('.js');
localState.openFiles[0].path = 'test.es6.js';
expect(getters.activeFileExtension(localState)).toBe('.js');
});
});
describe('canEditFile', () => { describe('canEditFile', () => {
beforeEach(() => { beforeEach(() => {
localState.onTopOfBranch = true; localState.onTopOfBranch = true;
......
...@@ -21,34 +21,6 @@ describe('Multi-file store mutations', () => { ...@@ -21,34 +21,6 @@ describe('Multi-file store mutations', () => {
}); });
}); });
describe('SET_PREVIEW_MODE', () => {
it('sets currentBlobView to repo-preview', () => {
mutations.SET_PREVIEW_MODE(localState);
expect(localState.currentBlobView).toBe('repo-preview');
localState.currentBlobView = 'testing';
mutations.SET_PREVIEW_MODE(localState);
expect(localState.currentBlobView).toBe('repo-preview');
});
});
describe('SET_EDIT_MODE', () => {
it('sets currentBlobView to repo-editor', () => {
mutations.SET_EDIT_MODE(localState);
expect(localState.currentBlobView).toBe('repo-editor');
localState.currentBlobView = 'testing';
mutations.SET_EDIT_MODE(localState);
expect(localState.currentBlobView).toBe('repo-editor');
});
});
describe('TOGGLE_LOADING', () => { describe('TOGGLE_LOADING', () => {
it('toggles loading of entry', () => { it('toggles loading of entry', () => {
mutations.TOGGLE_LOADING(localState, { entry }); mutations.TOGGLE_LOADING(localState, { entry });
...@@ -71,18 +43,6 @@ describe('Multi-file store mutations', () => { ...@@ -71,18 +43,6 @@ describe('Multi-file store mutations', () => {
}); });
}); });
describe('TOGGLE_EDIT_MODE', () => {
it('toggles editMode', () => {
mutations.TOGGLE_EDIT_MODE(localState);
expect(localState.editMode).toBeFalsy();
mutations.TOGGLE_EDIT_MODE(localState);
expect(localState.editMode).toBeTruthy();
});
});
describe('SET_LEFT_PANEL_COLLAPSED', () => { describe('SET_LEFT_PANEL_COLLAPSED', () => {
it('sets left panel collapsed', () => { it('sets left panel collapsed', () => {
mutations.SET_LEFT_PANEL_COLLAPSED(localState, true); mutations.SET_LEFT_PANEL_COLLAPSED(localState, true);
......
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