summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhil Hughes <me@iamphill.com>2017-10-26 15:12:34 +0100
committerPhil Hughes <me@iamphill.com>2017-10-26 15:12:34 +0100
commitb4f7496b1c82f54e0fd94d0335526e37a0a20996 (patch)
treeff0fa4a354b6b82474ae76807f5a0d59825f12d5
parent05728e785ce7cd39c4c517aa0ea50b3bba44d537 (diff)
downloadgitlab-ce-b4f7496b1c82f54e0fd94d0335526e37a0a20996.tar.gz
moved new file/directory into new store
removed old store, helper & monaco loader moved monaco loader into editor component because it is the only component that requires monaco [ci skip]
-rw-r--r--app/assets/javascripts/repo/components/new_dropdown/index.vue21
-rw-r--r--app/assets/javascripts/repo/components/new_dropdown/modal.vue12
-rw-r--r--app/assets/javascripts/repo/components/repo.vue4
-rw-r--r--app/assets/javascripts/repo/components/repo_editor.vue18
-rw-r--r--app/assets/javascripts/repo/event_hub.js3
-rw-r--r--app/assets/javascripts/repo/helpers/monaco_loader_helper.js21
-rw-r--r--app/assets/javascripts/repo/helpers/repo_helper.js317
-rw-r--r--app/assets/javascripts/repo/index.js24
-rw-r--r--app/assets/javascripts/repo/services/index.js9
-rw-r--r--app/assets/javascripts/repo/services/repo_service.js101
-rw-r--r--app/assets/javascripts/repo/stores/actions.js24
-rw-r--r--app/assets/javascripts/repo/stores/actions/file.js27
-rw-r--r--app/assets/javascripts/repo/stores/actions/tree.js39
-rw-r--r--app/assets/javascripts/repo/stores/mutation_types.js2
-rw-r--r--app/assets/javascripts/repo/stores/mutations/file.js3
-rw-r--r--app/assets/javascripts/repo/stores/mutations/tree.js24
-rw-r--r--app/assets/javascripts/repo/stores/repo_store.js182
-rw-r--r--app/assets/javascripts/repo/stores/state.js4
-rw-r--r--app/assets/javascripts/repo/stores/utils.js33
19 files changed, 176 insertions, 692 deletions
diff --git a/app/assets/javascripts/repo/components/new_dropdown/index.vue b/app/assets/javascripts/repo/components/new_dropdown/index.vue
index 3ccb50213ab..96b2087e1b9 100644
--- a/app/assets/javascripts/repo/components/new_dropdown/index.vue
+++ b/app/assets/javascripts/repo/components/new_dropdown/index.vue
@@ -1,7 +1,5 @@
<script>
- import RepoStore from '../../stores/repo_store';
- import RepoHelper from '../../helpers/repo_helper';
- import eventHub from '../../event_hub';
+ import { mapState } from 'vuex';
import newModal from './modal.vue';
export default {
@@ -12,9 +10,13 @@
return {
openModal: false,
modalType: '',
- currentPath: RepoStore.path,
};
},
+ computed: {
+ ...mapState({
+ currentPath: 'path',
+ }),
+ },
methods: {
createNewItem(type) {
this.modalType = type;
@@ -23,17 +25,6 @@
toggleModalOpen() {
this.openModal = !this.openModal;
},
- createNewEntryInStore(name, type) {
- RepoHelper.createNewEntry(name, type);
-
- this.toggleModalOpen();
- },
- },
- created() {
- eventHub.$on('createNewEntry', this.createNewEntryInStore);
- },
- beforeDestroy() {
- eventHub.$off('createNewEntry', this.createNewEntryInStore);
},
};
</script>
diff --git a/app/assets/javascripts/repo/components/new_dropdown/modal.vue b/app/assets/javascripts/repo/components/new_dropdown/modal.vue
index 5ef629e0dde..e3496f26b8b 100644
--- a/app/assets/javascripts/repo/components/new_dropdown/modal.vue
+++ b/app/assets/javascripts/repo/components/new_dropdown/modal.vue
@@ -1,7 +1,7 @@
<script>
+ import { mapActions } from 'vuex';
import { __ } from '../../../locale';
import popupDialog from '../../../vue_shared/components/popup_dialog.vue';
- import eventHub from '../../event_hub';
export default {
props: {
@@ -23,8 +23,16 @@
popupDialog,
},
methods: {
+ ...mapActions([
+ 'createTempEntry',
+ ]),
createEntryInStore() {
- eventHub.$emit('createNewEntry', this.entryName, this.type);
+ this.createTempEntry({
+ name: this.entryName,
+ type: this.type,
+ });
+
+ this.toggleModalOpen();
},
toggleModalOpen() {
this.$emit('toggle');
diff --git a/app/assets/javascripts/repo/components/repo.vue b/app/assets/javascripts/repo/components/repo.vue
index 0bc5271f95c..e072af5c151 100644
--- a/app/assets/javascripts/repo/components/repo.vue
+++ b/app/assets/javascripts/repo/components/repo.vue
@@ -5,7 +5,7 @@ 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 MonacoLoaderHelper from '../helpers/monaco_loader_helper';
+import repoEditor from './repo_editor.vue';
export default {
computed: {
@@ -22,7 +22,7 @@ export default {
RepoSidebar,
RepoTabs,
RepoFileButtons,
- 'repo-editor': MonacoLoaderHelper.repoEditorLoader,
+ repoEditor,
RepoCommitSection,
RepoPreview,
},
diff --git a/app/assets/javascripts/repo/components/repo_editor.vue b/app/assets/javascripts/repo/components/repo_editor.vue
index 06ded6332e1..0714ba90b6f 100644
--- a/app/assets/javascripts/repo/components/repo_editor.vue
+++ b/app/assets/javascripts/repo/components/repo_editor.vue
@@ -1,8 +1,8 @@
<script>
/* global monaco */
import { mapGetters, mapActions } from 'vuex';
-import Helper from '../helpers/repo_helper';
import flash from '../../flash';
+import monacoLoader from '../monaco_loader';
export default {
destroyed() {
@@ -11,7 +11,15 @@ export default {
}
},
mounted() {
- this.initMonaco();
+ if (this.monaco) {
+ this.initMonaco();
+ } else {
+ monacoLoader(['vs/editor/editor.main'], () => {
+ this.monaco = monaco;
+
+ this.initMonaco();
+ });
+ }
},
methods: {
...mapActions([
@@ -26,14 +34,14 @@ export default {
this.getRawFileData(this.activeFile)
.then(() => {
if (!this.monacoInstance) {
- this.monacoInstance = Helper.monaco.editor.create(this.$el, {
+ this.monacoInstance = this.monaco.editor.create(this.$el, {
model: null,
readOnly: false,
contextmenu: true,
scrollBeyondLastLine: false,
});
- this.languages = Helper.monaco.languages.getLanguages();
+ this.languages = this.monaco.languages.getLanguages();
this.addMonacoEvents();
}
@@ -46,7 +54,7 @@ export default {
const foundLang = this.languages.find(lang =>
lang.extensions && lang.extensions.indexOf(this.activeFileExtension) === 0,
);
- const newModel = Helper.monaco.editor.createModel(
+ const newModel = this.monaco.editor.createModel(
this.activeFile.raw, foundLang ? foundLang.id : 'plaintext',
);
diff --git a/app/assets/javascripts/repo/event_hub.js b/app/assets/javascripts/repo/event_hub.js
deleted file mode 100644
index 0948c2e5352..00000000000
--- a/app/assets/javascripts/repo/event_hub.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import Vue from 'vue';
-
-export default new Vue();
diff --git a/app/assets/javascripts/repo/helpers/monaco_loader_helper.js b/app/assets/javascripts/repo/helpers/monaco_loader_helper.js
deleted file mode 100644
index 4d5ff92fbea..00000000000
--- a/app/assets/javascripts/repo/helpers/monaco_loader_helper.js
+++ /dev/null
@@ -1,21 +0,0 @@
-/* global monaco */
-import RepoEditor from '../components/repo_editor.vue';
-import Helper from '../helpers/repo_helper';
-import monacoLoader from '../monaco_loader';
-
-function repoEditorLoader() {
- return new Promise((resolve, reject) => {
- monacoLoader(['vs/editor/editor.main'], () => {
- Helper.monaco = monaco;
- resolve(RepoEditor);
- }, () => {
- reject();
- });
- });
-}
-
-const MonacoLoaderHelper = {
- repoEditorLoader,
-};
-
-export default MonacoLoaderHelper;
diff --git a/app/assets/javascripts/repo/helpers/repo_helper.js b/app/assets/javascripts/repo/helpers/repo_helper.js
deleted file mode 100644
index fb26f3b7380..00000000000
--- a/app/assets/javascripts/repo/helpers/repo_helper.js
+++ /dev/null
@@ -1,317 +0,0 @@
-import Service from '../services/repo_service';
-import Store from '../stores/repo_store';
-import Flash from '../../flash';
-
-const RepoHelper = {
- monacoInstance: null,
-
- getDefaultActiveFile() {
- return {
- id: '',
- active: true,
- binary: false,
- extension: '',
- html: '',
- mime_type: '',
- name: '',
- plain: '',
- size: 0,
- url: '',
- raw: false,
- newContent: '',
- changed: false,
- loading: false,
- };
- },
-
- key: '',
-
- Time: window.performance
- && window.performance.now
- ? window.performance
- : Date,
-
- getFileExtension(fileName) {
- return fileName.split('.').pop();
- },
-
- getLanguageIDForFile(file, langs) {
- const ext = RepoHelper.getFileExtension(file.name);
- const foundLang = RepoHelper.findLanguage(ext, langs);
-
- return foundLang ? foundLang.id : 'plaintext';
- },
-
- setMonacoModelFromLanguage() {
- RepoHelper.monacoInstance.setModel(null);
- const languages = RepoHelper.monaco.languages.getLanguages();
- const languageID = RepoHelper.getLanguageIDForFile(Store.activeFile, languages);
- const newModel = RepoHelper.monaco.editor.createModel(Store.blobRaw, languageID);
- RepoHelper.monacoInstance.setModel(newModel);
- },
-
- findLanguage(ext, langs) {
- return langs.find(lang => lang.extensions && lang.extensions.indexOf(`.${ext}`) > -1);
- },
-
- setDirectoryOpen(tree, title) {
- if (!tree) return;
-
- Object.assign(tree, {
- opened: true,
- });
-
- RepoHelper.updateHistoryEntry(tree.url, title);
- Store.path = tree.path;
- },
-
- setDirectoryToClosed(entry) {
- Object.assign(entry, {
- opened: false,
- files: [],
- });
- },
-
- isRenderable() {
- const okExts = ['md', 'svg'];
- return okExts.indexOf(Store.activeFile.extension) > -1;
- },
-
- setBinaryDataAsBase64(file) {
- Service.getBase64Content(file.raw_path)
- .then((response) => {
- Store.blobRaw = response;
- file.base64 = response; // eslint-disable-line no-param-reassign
- })
- .catch(RepoHelper.loadingError);
- },
-
- getContent(treeOrFile, emptyFiles = false) {
- let file = treeOrFile;
-
- if (!Store.files.length) {
- Store.loading.tree = true;
- }
-
- return Service.getContent()
- .then((response) => {
- const data = response.data;
- if (response.headers && response.headers['page-title']) data.pageTitle = decodeURI(response.headers['page-title']);
- if (data.path && !Store.isInitialRoot) {
- Store.isRoot = data.path === '/';
- Store.isInitialRoot = Store.isRoot;
- }
-
- if (file && file.type === 'blob') {
- if (!file) file = data;
- Store.binary = data.binary;
-
- if (data.binary) {
- // file might be undefined
- RepoHelper.setBinaryDataAsBase64(data);
- Store.setViewToPreview();
- } else if (!Store.isPreviewView() && !data.render_error) {
- Service.getRaw(data)
- .then((rawResponse) => {
- Store.blobRaw = rawResponse.data;
- data.plain = rawResponse.data;
- RepoHelper.setFile(data, file);
- }).catch(RepoHelper.loadingError);
- }
-
- if (Store.isPreviewView()) {
- RepoHelper.setFile(data, file);
- }
- } else {
- Store.loading.tree = false;
- RepoHelper.setDirectoryOpen(file, data.pageTitle || data.name);
-
- if (emptyFiles) {
- Store.files = [];
- }
-
- this.addToDirectory(file, data);
-
- Store.prevURL = Service.blobURLtoParentTree(Service.url);
- }
- }).catch(RepoHelper.loadingError);
- },
-
- addToDirectory(file, data) {
- const tree = file || Store;
-
- // TODO: Figure out why `popstate` is being trigger in the specs
- if (!tree.files) return;
-
- const files = tree.files.concat(this.dataToListOfFiles(data, file ? file.level + 1 : 0));
-
- tree.files = files;
- },
-
- setFile(data, file) {
- const newFile = data;
- newFile.url = file.url || Service.url; // Grab the URL from service, happens on page refresh.
-
- if (newFile.render_error === 'too_large' || newFile.render_error === 'collapsed') {
- newFile.tooLarge = true;
- }
- newFile.newContent = '';
-
- Store.addToOpenedFiles(newFile);
- Store.setActiveFiles(newFile);
- },
-
- serializeRepoEntity(type, entity, level = 0) {
- const {
- id,
- url,
- name,
- icon,
- last_commit,
- tree_url,
- path,
- tempFile,
- active,
- opened,
- } = entity;
-
- return {
- id,
- type,
- name,
- url,
- tree_url,
- path,
- level,
- tempFile,
- icon: `fa-${icon}`,
- files: [],
- loading: false,
- opened,
- active,
- // eslint-disable-next-line camelcase
- lastCommit: last_commit ? {
- url: `${Store.projectUrl}/commit/${last_commit.id}`,
- message: last_commit.message,
- updatedAt: last_commit.committed_date,
- } : {},
- };
- },
-
- scrollTabsRight() {
- const tabs = document.getElementById('tabs');
- if (!tabs) return;
- tabs.scrollLeft = tabs.scrollWidth;
- },
-
- dataToListOfFiles(data, level) {
- const { blobs, trees, submodules } = data;
- return [
- ...trees.map(tree => RepoHelper.serializeRepoEntity('tree', tree, level)),
- ...submodules.map(submodule => RepoHelper.serializeRepoEntity('submodule', submodule, level)),
- ...blobs.map(blob => RepoHelper.serializeRepoEntity('blob', blob, level)),
- ];
- },
-
- genKey() {
- return RepoHelper.Time.now().toFixed(3);
- },
-
- updateHistoryEntry(url, title) {
- const history = window.history;
-
- RepoHelper.key = RepoHelper.genKey();
-
- if (document.location.pathname !== url) {
- history.pushState({ key: RepoHelper.key }, '', url);
- }
-
- if (title) {
- document.title = title;
- }
- },
-
- findOpenedFileFromActive() {
- return Store.openedFiles.find(openedFile => Store.activeFile.id === openedFile.id);
- },
-
- getFileFromPath(path) {
- return Store.openedFiles.find(file => file.url === path);
- },
-
- loadingError() {
- Flash('Unable to load this content at this time.');
- },
- openEditMode() {
- Store.editMode = true;
- Store.currentBlobView = 'repo-editor';
- },
- updateStorePath(path) {
- Store.path = path;
- },
- findOrCreateEntry(type, tree, name) {
- let exists = true;
- let foundEntry = tree.files.find(dir => dir.type === type && dir.name === name);
-
- if (!foundEntry) {
- foundEntry = RepoHelper.serializeRepoEntity(type, {
- id: name,
- name,
- path: tree.path ? `${tree.path}/${name}` : name,
- icon: type === 'tree' ? 'folder' : 'file-text-o',
- tempFile: true,
- opened: true,
- active: true,
- }, tree.level !== undefined ? tree.level + 1 : 0);
-
- exists = false;
- tree.files.push(foundEntry);
- }
-
- return {
- entry: foundEntry,
- exists,
- };
- },
- removeAllTmpFiles(storeFilesKey) {
- Store[storeFilesKey] = Store[storeFilesKey].filter(f => !f.tempFile);
- },
- createNewEntry(name, type) {
- const originalPath = Store.path;
- let entryName = name;
-
- if (entryName.indexOf(`${originalPath}/`) !== 0) {
- this.updateStorePath('');
- } else {
- entryName = entryName.replace(`${originalPath}/`, '');
- }
-
- if (entryName === '') return;
-
- const fileName = type === 'tree' ? '.gitkeep' : entryName;
- let tree = Store;
-
- if (type === 'tree') {
- const dirNames = entryName.split('/');
-
- dirNames.forEach((dirName) => {
- if (dirName === '') return;
-
- tree = this.findOrCreateEntry('tree', tree, dirName).entry;
- });
- }
-
- if ((type === 'tree' && tree.tempFile) || type === 'blob') {
- const file = this.findOrCreateEntry('blob', tree, fileName);
-
- if (!file.exists) {
- this.setFile(file.entry, file.entry);
- this.openEditMode();
- }
- }
-
- this.updateStorePath(originalPath);
- },
-};
-
-export default RepoHelper;
diff --git a/app/assets/javascripts/repo/index.js b/app/assets/javascripts/repo/index.js
index 475d53e5765..8ca5bb45d05 100644
--- a/app/assets/javascripts/repo/index.js
+++ b/app/assets/javascripts/repo/index.js
@@ -1,8 +1,6 @@
import Vue from 'vue';
import { mapActions } from 'vuex';
import { convertPermissionToBoolean } from '../lib/utils/common_utils';
-import Service from './services/repo_service';
-import Store from './stores/repo_store';
import Repo from './components/repo.vue';
import RepoEditButton from './components/repo_edit_button.vue';
import newBranchForm from './components/new_branch_form.vue';
@@ -10,24 +8,6 @@ import newDropdown from './components/new_dropdown/index.vue';
import vStore from './stores';
import Translate from '../vue_shared/translate';
-function setInitialStore(data) {
- Store.service = Service;
- Store.service.refsUrl = data.refsUrl;
- Store.path = data.currentPath;
- Store.projectId = data.projectId;
- Store.projectName = data.projectName;
- Store.projectUrl = data.projectUrl;
- Store.canCommit = data.canCommit;
- Store.onTopOfBranch = data.onTopOfBranch;
- Store.newMrTemplateUrl = decodeURIComponent(data.newMrTemplateUrl);
- Store.customBranchURL = decodeURIComponent(data.blobUrl);
- Store.isRoot = convertPermissionToBoolean(data.root);
- Store.isInitialRoot = convertPermissionToBoolean(data.root);
- Store.currentBranch = $('button.dropdown-menu-toggle').attr('data-ref');
- Store.checkIsCommitable();
- Store.setBranchHash();
-}
-
function initRepo(el) {
return new Vue({
el,
@@ -47,6 +27,7 @@ function initRepo(el) {
project: {
id: data.projectId,
name: data.projectName,
+ url: data.projectUrl,
},
endpoints: {
rootEndpoint: data.url,
@@ -56,6 +37,7 @@ function initRepo(el) {
canCommit: convertPermissionToBoolean(data.canCommit),
onTopOfBranch: convertPermissionToBoolean(data.onTopOfBranch),
currentRef: data.ref,
+ path: data.currentPath,
// TODO: get through data attribute
currentBranch: document.querySelector('.js-project-refs-dropdown').dataset.ref,
isRoot: convertPermissionToBoolean(data.root),
@@ -81,6 +63,7 @@ function initRepoEditButton(el) {
function initNewDropdown(el) {
return new Vue({
el,
+ store: vStore,
components: {
newDropdown,
},
@@ -110,7 +93,6 @@ function initNewBranchForm() {
const repo = document.getElementById('repo');
const editButton = document.querySelector('.editable-mode');
const newDropdownHolder = document.querySelector('.js-new-dropdown');
-setInitialStore(repo.dataset);
Vue.use(Translate);
diff --git a/app/assets/javascripts/repo/services/index.js b/app/assets/javascripts/repo/services/index.js
index 57c234cd4c9..49301fb47d5 100644
--- a/app/assets/javascripts/repo/services/index.js
+++ b/app/assets/javascripts/repo/services/index.js
@@ -11,8 +11,13 @@ export default {
getFileData(endpoint) {
return Vue.http.get(endpoint, { params: { format: 'json' } });
},
- getRawFileData(endpoint) {
- return Vue.http.get(endpoint);
+ getRawFileData(file) {
+ if (file.tempFile) {
+ return Promise.resolve('');
+ }
+
+ return Vue.http.get(file.rawPath, { params: { format: 'json' } })
+ .then(res => res.text());
},
getBranchData(projectId, currentBranch) {
return Api.branchSingle(projectId, currentBranch);
diff --git a/app/assets/javascripts/repo/services/repo_service.js b/app/assets/javascripts/repo/services/repo_service.js
deleted file mode 100644
index c9fa5cc8bf8..00000000000
--- a/app/assets/javascripts/repo/services/repo_service.js
+++ /dev/null
@@ -1,101 +0,0 @@
-import axios from 'axios';
-import csrf from '../../lib/utils/csrf';
-import Store from '../stores/repo_store';
-import Api from '../../api';
-import Helper from '../helpers/repo_helper';
-
-axios.defaults.headers.common[csrf.headerKey] = csrf.token;
-
-const RepoService = {
- url: '',
- options: {
- params: {
- format: 'json',
- },
- },
- createBranchPath: '/api/:version/projects/:id/repository/branches',
- richExtensionRegExp: /md/,
-
- getRaw(file) {
- if (file.tempFile) {
- return Promise.resolve({
- data: '',
- });
- }
-
- return axios.get(file.raw_path, {
- // Stop Axios from parsing a JSON file into a JS object
- transformResponse: [res => res],
- });
- },
-
- buildParams(url = this.url) {
- // shallow clone object without reference
- const params = Object.assign({}, this.options.params);
-
- if (this.urlIsRichBlob(url)) params.viewer = 'rich';
-
- return params;
- },
-
- urlIsRichBlob(url = this.url) {
- const extension = Helper.getFileExtension(url);
-
- return this.richExtensionRegExp.test(extension);
- },
-
- getContent(url = this.url) {
- const params = this.buildParams(url);
-
- return axios.get(url, {
- params,
- });
- },
-
- getBase64Content(url = this.url) {
- const request = axios.get(url, {
- responseType: 'arraybuffer',
- });
-
- return request.then(response => this.bufferToBase64(response.data));
- },
-
- bufferToBase64(data) {
- return new Buffer(data, 'binary').toString('base64');
- },
-
- blobURLtoParentTree(url) {
- const urlArray = url.split('/');
- urlArray.pop();
- const blobIndex = urlArray.lastIndexOf('blob');
-
- if (blobIndex > -1) urlArray[blobIndex] = 'tree';
-
- return urlArray.join('/');
- },
-
- getBranch() {
- return Api.branchSingle(Store.projectId, Store.currentBranch);
- },
-
- commitFiles(payload) {
- return Api.commitMultiple(Store.projectId, payload)
- .then(this.commitFlash);
- },
-
- createBranch(payload) {
- const url = Api.buildUrl(this.createBranchPath)
- .replace(':id', Store.projectId);
- return axios.post(url, payload);
- },
-
- commitFlash(data) {
- if (data.short_id && data.stats) {
- window.Flash(`Your changes have been committed. Commit ${data.short_id} with ${data.stats.additions} additions, ${data.stats.deletions} deletions.`, 'notice');
- } else {
- window.Flash(data.message);
- }
- },
-};
-
-export default RepoService;
diff --git a/app/assets/javascripts/repo/stores/actions.js b/app/assets/javascripts/repo/stores/actions.js
index c0b5ce47398..20aee8707b4 100644
--- a/app/assets/javascripts/repo/stores/actions.js
+++ b/app/assets/javascripts/repo/stores/actions.js
@@ -1,7 +1,6 @@
import flash from '../../flash';
import service from '../services';
import * as types from './mutation_types';
-import * as getters from './getters';
import { visitUrl } from '../../lib/utils/url_utility';
export const redirectToUrl = url => visitUrl(url);
@@ -10,8 +9,8 @@ export const setInitialData = ({ commit }, data) => commit(types.SET_INITIAL_DAT
export const closeDiscardPopup = ({ commit }) => commit(types.TOGGLE_DISCARD_POPUP, false);
-export const discardAllChanges = ({ commit, state }) => {
- const changedFiles = getters.changedFiles(state);
+export const discardAllChanges = ({ commit, getters }) => {
+ const changedFiles = getters.changedFiles;
changedFiles.forEach(file => commit(types.DISCARD_FILE_CHANGES, file));
};
@@ -20,8 +19,8 @@ export const closeAllFiles = ({ state, dispatch }) => {
state.openFiles.forEach(file => dispatch('closeFile', file));
};
-export const toggleEditMode = ({ commit, state, dispatch }, force = false) => {
- const changedFiles = getters.changedFiles(state);
+export const toggleEditMode = ({ commit, getters, dispatch }, force = false) => {
+ const changedFiles = getters.changedFiles;
if (changedFiles.length && !force) {
commit(types.TOGGLE_DISCARD_POPUP, true);
@@ -78,8 +77,19 @@ export const commitChanges = ({ commit, state, dispatch }, { payload, newMr }) =
})
.catch(() => flash('Error committing changes. Please try again.'));
-export const popHistoryState = ({ state, dispatch }) => {
- const treeList = getters.treeList(state);
+export const createTempEntry = ({ state, dispatch }, { name, type }) => {
+ if (type === 'tree') {
+ dispatch('createTempTree', name);
+ } else if (type === 'blob') {
+ dispatch('createTempFile', {
+ tree: state,
+ name,
+ });
+ }
+};
+
+export const popHistoryState = ({ state, dispatch, getters }) => {
+ const treeList = getters.treeList;
const tree = treeList.find(file => file.url === state.previousUrl);
if (!tree) return;
diff --git a/app/assets/javascripts/repo/stores/actions/file.js b/app/assets/javascripts/repo/stores/actions/file.js
index 887eecf83f8..60964f90d34 100644
--- a/app/assets/javascripts/repo/stores/actions/file.js
+++ b/app/assets/javascripts/repo/stores/actions/file.js
@@ -1,7 +1,7 @@
import flash from '../../../flash';
import service from '../../services';
import * as types from '../mutation_types';
-import { activeFile } from '../getters';
+import { createTemp } from '../utils';
export const closeFile = ({ commit }, file) => {
if (file.changed || file.tempFile) return;
@@ -10,8 +10,8 @@ export const closeFile = ({ commit }, file) => {
commit(types.SET_FILE_ACTIVE, { file, active: false });
};
-export const setFileActive = ({ commit, state }, file) => {
- const currentActiveFile = activeFile(state);
+export const setFileActive = ({ commit, state, getters }, file) => {
+ const currentActiveFile = getters.activeFile;
if (currentActiveFile) {
commit(types.SET_FILE_ACTIVE, { file: currentActiveFile, active: false });
@@ -38,8 +38,7 @@ export const getFileData = ({ commit, dispatch }, file) => {
});
};
-export const getRawFileData = ({ commit, dispatch }, file) => service.getRawFileData(file.rawPath)
- .then(res => res.text())
+export const getRawFileData = ({ commit, dispatch }, file) => service.getRawFileData(file)
.then((raw) => {
commit(types.SET_FILE_RAW_DATA, { file, raw });
})
@@ -48,3 +47,21 @@ export const getRawFileData = ({ commit, dispatch }, file) => service.getRawFile
export const changeFileContent = ({ commit }, { file, content }) => {
commit(types.UPDATE_FILE_CONTENT, { file, content });
};
+
+export const createTempFile = ({ state, commit, dispatch }, { tree, name }) => {
+ const file = createTemp({
+ name: name.replace(`${state.path}/`, ''),
+ path: tree.path,
+ type: 'blob',
+ level: tree.level !== undefined ? tree.level + 1 : 0,
+ changed: true,
+ });
+
+ commit(types.CREATE_TMP_FILE, {
+ parent: tree,
+ file,
+ });
+ commit(types.TOGGLE_FILE_OPEN, file);
+ dispatch('setFileActive', file);
+ dispatch('toggleEditMode', true);
+};
diff --git a/app/assets/javascripts/repo/stores/actions/tree.js b/app/assets/javascripts/repo/stores/actions/tree.js
index 8869bb8da2a..a0be8d4c556 100644
--- a/app/assets/javascripts/repo/stores/actions/tree.js
+++ b/app/assets/javascripts/repo/stores/actions/tree.js
@@ -2,7 +2,12 @@ import { normalizeHeaders } from '../../../lib/utils/common_utils';
import flash from '../../../flash';
import service from '../../services';
import * as types from '../mutation_types';
-import { pushState, setPageTitle } from '../utils';
+import {
+ pushState,
+ setPageTitle,
+ findEntry,
+ createTemp,
+} from '../utils';
export const getTreeData = (
{ commit, state },
@@ -68,3 +73,35 @@ export const clickedTreeRow = ({ commit, dispatch }, row) => {
dispatch('getFileData', row);
}
};
+
+export const createTempTree = ({ state, commit, dispatch }, name) => {
+ let tree = state;
+ const dirNames = name.replace(`${state.path}/`, '').split('/');
+
+ dirNames.forEach((dirName) => {
+ const foundEntry = findEntry(tree, 'tree', dirName);
+
+ if (!foundEntry) {
+ const tmpEntry = createTemp({
+ name: dirName,
+ path: tree.path,
+ type: 'tree',
+ level: tree.level !== undefined ? tree.level + 1 : 0,
+ });
+
+ commit(types.CREATE_TMP_TREE, {
+ parent: tree,
+ tmpEntry,
+ });
+
+ tree = tmpEntry;
+ } else {
+ tree = foundEntry;
+ }
+ });
+
+ dispatch('createTempFile', {
+ tree,
+ name: '.gitkeep',
+ });
+};
diff --git a/app/assets/javascripts/repo/stores/mutation_types.js b/app/assets/javascripts/repo/stores/mutation_types.js
index c6d0816080c..4722a7dd0df 100644
--- a/app/assets/javascripts/repo/stores/mutation_types.js
+++ b/app/assets/javascripts/repo/stores/mutation_types.js
@@ -8,6 +8,7 @@ export const SET_PREVIOUS_URL = 'SET_PREVIOUS_URL';
// Tree mutation types
export const SET_DIRECTORY_DATA = 'SET_DIRECTORY_DATA';
export const TOGGLE_TREE_OPEN = 'TOGGLE_TREE_OPEN';
+export const CREATE_TMP_TREE = 'CREATE_TMP_TREE';
// File mutation types
export const SET_FILE_DATA = 'SET_FILE_DATA';
@@ -16,6 +17,7 @@ export const SET_FILE_ACTIVE = 'SET_FILE_ACTIVE';
export const SET_FILE_RAW_DATA = 'SET_FILE_RAW_DATA';
export const UPDATE_FILE_CONTENT = 'UPDATE_FILE_CONTENT';
export const DISCARD_FILE_CHANGES = 'DISCARD_FILE_CHANGES';
+export const CREATE_TMP_FILE = 'CREATE_TMP_FILE';
// Viewer mutation types
export const SET_PREVIEW_MODE = 'SET_PREVIEW_MODE';
diff --git a/app/assets/javascripts/repo/stores/mutations/file.js b/app/assets/javascripts/repo/stores/mutations/file.js
index 50d8a51d9b7..4d10fa8169d 100644
--- a/app/assets/javascripts/repo/stores/mutations/file.js
+++ b/app/assets/javascripts/repo/stores/mutations/file.js
@@ -47,4 +47,7 @@ export default {
changed: false,
});
},
+ [types.CREATE_TMP_FILE](state, { file, parent }) {
+ parent.tree.push(file);
+ },
};
diff --git a/app/assets/javascripts/repo/stores/mutations/tree.js b/app/assets/javascripts/repo/stores/mutations/tree.js
index 700aff46827..52be2673107 100644
--- a/app/assets/javascripts/repo/stores/mutations/tree.js
+++ b/app/assets/javascripts/repo/stores/mutations/tree.js
@@ -13,9 +13,24 @@ export default {
Object.assign(tree, {
tree: [
- ...data.trees.map(t => utils.decorateData(t, 'tree', parentTreeUrl, level)),
- ...data.submodules.map(m => utils.decorateData(m, 'submodule', parentTreeUrl, level)),
- ...data.blobs.map(b => utils.decorateData(b, 'blob', parentTreeUrl, level)),
+ ...data.trees.map(t => utils.decorateData({
+ ...t,
+ type: 'tree',
+ parentTreeUrl,
+ level,
+ }, state.project.url)),
+ ...data.submodules.map(m => utils.decorateData({
+ ...m,
+ type: 'submodule',
+ parentTreeUrl,
+ level,
+ }, state.project.url)),
+ ...data.blobs.map(b => utils.decorateData({
+ ...b,
+ type: 'blob',
+ parentTreeUrl,
+ level,
+ }, state.project.url)),
],
});
},
@@ -24,4 +39,7 @@ export default {
parentTreeUrl: url,
});
},
+ [types.CREATE_TMP_TREE](state, { parent, tmpEntry }) {
+ parent.tree.push(tmpEntry);
+ },
};
diff --git a/app/assets/javascripts/repo/stores/repo_store.js b/app/assets/javascripts/repo/stores/repo_store.js
deleted file mode 100644
index b68e2289319..00000000000
--- a/app/assets/javascripts/repo/stores/repo_store.js
+++ /dev/null
@@ -1,182 +0,0 @@
-import Helper from '../helpers/repo_helper';
-import Service from '../services/repo_service';
-
-const RepoStore = {
- monacoLoading: false,
- service: '',
- canCommit: false,
- onTopOfBranch: false,
- editMode: false,
- prevURL: '',
- projectId: '',
- projectName: '',
- projectUrl: '',
- branchUrl: '',
- blobRaw: '',
- openedFiles: [],
- submitCommitsLoading: false,
- dialog: {
- open: false,
- title: '',
- status: false,
- },
- showNewBranchDialog: false,
- activeFile: Helper.getDefaultActiveFile(),
- activeFileIndex: 0,
- activeLine: -1,
- activeFileLabel: 'Raw',
- files: [],
- isCommitable: false,
- binary: false,
- currentBranch: '',
- startNewMR: false,
- currentHash: '',
- currentShortHash: '',
- customBranchURL: '',
- newMrTemplateUrl: '',
- branchChanged: false,
- commitMessage: '',
- path: '',
-
- setBranchHash() {
- return Service.getBranch()
- .then((data) => {
- if (RepoStore.currentHash !== '' && data.commit.id !== RepoStore.currentHash) {
- RepoStore.branchChanged = true;
- }
- RepoStore.currentHash = data.commit.id;
- RepoStore.currentShortHash = data.commit.short_id;
- });
- },
-
- // mutations
- checkIsCommitable() {
- RepoStore.isCommitable = RepoStore.onTopOfBranch && RepoStore.canCommit;
- },
-
- toggleRawPreview() {
- RepoStore.activeFile.raw = !RepoStore.activeFile.raw;
- RepoStore.activeFileLabel = RepoStore.activeFile.raw ? 'Display rendered file' : 'Display source';
- },
-
- setActiveFiles(file) {
- if (RepoStore.isActiveFile(file)) return;
- RepoStore.openedFiles = RepoStore.openedFiles
- .map((openedFile, i) => RepoStore.setFileActivity(file, openedFile, i));
-
- RepoStore.setActiveToRaw();
-
- if (file.binary) {
- RepoStore.blobRaw = file.base64;
- } else if (file.newContent || file.plain) {
- RepoStore.blobRaw = file.newContent || file.plain;
- } else {
- Service.getRaw(file)
- .then((rawResponse) => {
- RepoStore.blobRaw = rawResponse.data;
- Helper.findOpenedFileFromActive().plain = rawResponse.data;
- }).catch(Helper.loadingError);
- }
-
- if (!file.loading && !file.tempFile) {
- Helper.updateHistoryEntry(file.url, file.pageTitle || file.name);
- }
- RepoStore.binary = file.binary;
- RepoStore.setActiveLine(-1);
- },
-
- setFileActivity(file, openedFile, i) {
- const activeFile = openedFile;
- activeFile.active = file.id === activeFile.id;
-
- if (activeFile.active) RepoStore.setActiveFile(activeFile, i);
-
- return activeFile;
- },
-
- setActiveFile(activeFile, i) {
- RepoStore.activeFile = Object.assign({}, Helper.getDefaultActiveFile(), activeFile);
- RepoStore.activeFileIndex = i;
- },
-
- setActiveLine(activeLine) {
- if (!isNaN(activeLine)) RepoStore.activeLine = activeLine;
- },
-
- setActiveToRaw() {
- RepoStore.activeFile.raw = false;
- // can't get vue to listen to raw for some reason so RepoStore for now.
- RepoStore.activeFileLabel = 'Display source';
- },
-
- removeFromOpenedFiles(file) {
- if (file.type === 'tree') return;
- let foundIndex;
- RepoStore.openedFiles = RepoStore.openedFiles.filter((openedFile, i) => {
- if (openedFile.path === file.path) foundIndex = i;
- return openedFile.path !== file.path;
- });
-
- // remove the file from the sidebar if it is a tempFile
- if (file.tempFile) {
- RepoStore.files = RepoStore.files.filter(f => !(f.tempFile && f.path === file.path));
- }
-
- // now activate the right tab based on what you closed.
- if (RepoStore.openedFiles.length === 0) {
- RepoStore.activeFile = {};
- return;
- }
-
- if (RepoStore.openedFiles.length === 1 || foundIndex === 0) {
- RepoStore.setActiveFiles(RepoStore.openedFiles[0]);
- return;
- }
-
- if (foundIndex && foundIndex > 0) {
- RepoStore.setActiveFiles(RepoStore.openedFiles[foundIndex - 1]);
- }
- },
-
- addToOpenedFiles(file) {
- const openFile = file;
-
- const openedFilesAlreadyExists = RepoStore.openedFiles
- .some(openedFile => openedFile.path === openFile.path);
-
- if (openedFilesAlreadyExists) return;
-
- openFile.changed = false;
- openFile.active = true;
- RepoStore.openedFiles.push(openFile);
- },
-
- setActiveFileContents(contents) {
- if (!RepoStore.editMode) return;
- const currentFile = RepoStore.openedFiles[RepoStore.activeFileIndex];
- RepoStore.activeFile.newContent = contents;
- RepoStore.activeFile.changed = RepoStore.activeFile.plain !== RepoStore.activeFile.newContent;
- currentFile.changed = RepoStore.activeFile.changed;
- currentFile.newContent = contents;
- },
-
- toggleBlobView() {
- RepoStore.currentBlobView = RepoStore.isPreviewView() ? 'repo-editor' : 'repo-preview';
- },
-
- setViewToPreview() {
- RepoStore.currentBlobView = 'repo-preview';
- },
-
- // getters
-
- isActiveFile(file) {
- return file && file.id === RepoStore.activeFile.id;
- },
-
- isPreviewView() {
- return RepoStore.currentBlobView === 'repo-preview';
- },
-};
-
-export default RepoStore;
diff --git a/app/assets/javascripts/repo/stores/state.js b/app/assets/javascripts/repo/stores/state.js
index 6cf7565c955..0166490aac0 100644
--- a/app/assets/javascripts/repo/stores/state.js
+++ b/app/assets/javascripts/repo/stores/state.js
@@ -2,12 +2,14 @@ export default {
project: {
id: 0,
name: '',
+ url: '',
},
- currentBranch: '',
endpoints: {},
isRoot: false,
isInitialRoot: false,
+ currentBranch: '',
currentRef: '',
+ path: '',
canCommit: false,
onTopOfBranch: false,
editMode: false,
diff --git a/app/assets/javascripts/repo/stores/utils.js b/app/assets/javascripts/repo/stores/utils.js
index ec733200552..81638e46672 100644
--- a/app/assets/javascripts/repo/stores/utils.js
+++ b/app/assets/javascripts/repo/stores/utils.js
@@ -1,4 +1,4 @@
-export const dataStructure = ({
+export const dataStructure = () => ({
id: '',
type: '',
name: '',
@@ -25,9 +25,10 @@ export const dataStructure = ({
parentTreeUrl: '',
});
-export const decorateData = (entity, type, parentTreeUrl = '', level = 0) => {
+export const decorateData = (entity, projectUrl = '') => {
const {
id,
+ type,
url,
name,
icon,
@@ -37,10 +38,13 @@ export const decorateData = (entity, type, parentTreeUrl = '', level = 0) => {
tempFile,
active = false,
opened = false,
+ changed = false,
+ parentTreeUrl = '',
+ level = 0,
} = entity;
return {
- ...dataStructure,
+ ...dataStructure(),
id,
type,
name,
@@ -53,15 +57,19 @@ export const decorateData = (entity, type, parentTreeUrl = '', level = 0) => {
opened,
active,
parentTreeUrl,
+ changed,
// eslint-disable-next-line camelcase
lastCommit: last_commit ? {
- // url: `${Store.projectUrl}/commit/${last_commit.id}`,
+ url: `${projectUrl}/commit/${last_commit.id}`,
message: last_commit.message,
updatedAt: last_commit.committed_date,
} : {},
};
};
+export const findEntry = (state, type, name) => state.tree.find(
+ f => f.type === type && f.name === name,
+);
export const findIndexOfFile = (state, file) => state.findIndex(f => f.path === file.path);
export const setPageTitle = (title) => {
@@ -71,3 +79,20 @@ export const setPageTitle = (title) => {
export const pushState = (url) => {
history.pushState({ url }, '', url);
};
+
+export const createTemp = ({ name, path, type, level, changed, content }) => {
+ const treePath = path ? `${path}/${name}` : name;
+
+ return decorateData({
+ id: new Date().getTime().toString(),
+ name,
+ type,
+ tempFile: true,
+ path: treePath,
+ icon: type === 'tree' ? 'folder' : 'file-text-o',
+ changed,
+ content,
+ parentTreeUrl: '',
+ level,
+ });
+};