summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/ide
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/ide')
-rw-r--r--app/assets/javascripts/ide/commit_icon.js2
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/list_item.vue2
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue1
-rw-r--r--app/assets/javascripts/ide/components/file_templates/bar.vue2
-rw-r--r--app/assets/javascripts/ide/components/file_templates/dropdown.vue2
-rw-r--r--app/assets/javascripts/ide/components/ide.vue2
-rw-r--r--app/assets/javascripts/ide/components/ide_sidebar_nav.vue2
-rw-r--r--app/assets/javascripts/ide/components/nav_dropdown.vue4
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/upload.vue14
-rw-r--r--app/assets/javascripts/ide/components/panes/collapsible_sidebar.vue6
-rw-r--r--app/assets/javascripts/ide/components/preview/clientside.vue42
-rw-r--r--app/assets/javascripts/ide/components/preview/navigator.vue2
-rw-r--r--app/assets/javascripts/ide/components/repo_commit_section.vue4
-rw-r--r--app/assets/javascripts/ide/components/repo_editor.vue19
-rw-r--r--app/assets/javascripts/ide/constants.js3
-rw-r--r--app/assets/javascripts/ide/ide_router.js10
-rw-r--r--app/assets/javascripts/ide/index.js4
-rw-r--r--app/assets/javascripts/ide/lib/common/disposable.js4
-rw-r--r--app/assets/javascripts/ide/lib/common/model.js4
-rw-r--r--app/assets/javascripts/ide/lib/create_diff.js16
-rw-r--r--app/assets/javascripts/ide/lib/create_file_diff.js10
-rw-r--r--app/assets/javascripts/ide/lib/decorations/controller.js2
-rw-r--r--app/assets/javascripts/ide/lib/diff/controller.js6
-rw-r--r--app/assets/javascripts/ide/lib/diff/diff.js2
-rw-r--r--app/assets/javascripts/ide/lib/diff/diff_worker.js2
-rw-r--r--app/assets/javascripts/ide/lib/editor.js12
-rw-r--r--app/assets/javascripts/ide/lib/editor_options.js4
-rw-r--r--app/assets/javascripts/ide/lib/editorconfig/parser.js13
-rw-r--r--app/assets/javascripts/ide/lib/editorconfig/rules_mapper.js12
-rw-r--r--app/assets/javascripts/ide/lib/errors.js14
-rw-r--r--app/assets/javascripts/ide/lib/files.js21
-rw-r--r--app/assets/javascripts/ide/lib/languages/hcl.js14
-rw-r--r--app/assets/javascripts/ide/lib/languages/vue.js8
-rw-r--r--app/assets/javascripts/ide/lib/mirror.js26
-rw-r--r--app/assets/javascripts/ide/services/index.js11
-rw-r--r--app/assets/javascripts/ide/services/terminals.js2
-rw-r--r--app/assets/javascripts/ide/stores/actions.js17
-rw-r--r--app/assets/javascripts/ide/stores/actions/file.js47
-rw-r--r--app/assets/javascripts/ide/stores/actions/merge_request.js18
-rw-r--r--app/assets/javascripts/ide/stores/actions/project.js15
-rw-r--r--app/assets/javascripts/ide/stores/actions/tree.js4
-rw-r--r--app/assets/javascripts/ide/stores/extend.js2
-rw-r--r--app/assets/javascripts/ide/stores/getters.js66
-rw-r--r--app/assets/javascripts/ide/stores/modules/branches/actions.js2
-rw-r--r--app/assets/javascripts/ide/stores/modules/branches/mutations.js2
-rw-r--r--app/assets/javascripts/ide/stores/modules/commit/actions.js41
-rw-r--r--app/assets/javascripts/ide/stores/modules/commit/getters.js10
-rw-r--r--app/assets/javascripts/ide/stores/modules/editor/setup.js15
-rw-r--r--app/assets/javascripts/ide/stores/modules/file_templates/actions.js2
-rw-r--r--app/assets/javascripts/ide/stores/modules/file_templates/getters.js4
-rw-r--r--app/assets/javascripts/ide/stores/modules/merge_requests/actions.js2
-rw-r--r--app/assets/javascripts/ide/stores/modules/merge_requests/mutations.js2
-rw-r--r--app/assets/javascripts/ide/stores/modules/pane/getters.js2
-rw-r--r--app/assets/javascripts/ide/stores/modules/pipelines/actions.js6
-rw-r--r--app/assets/javascripts/ide/stores/modules/pipelines/getters.js19
-rw-r--r--app/assets/javascripts/ide/stores/modules/pipelines/mutations.js10
-rw-r--r--app/assets/javascripts/ide/stores/modules/pipelines/utils.js2
-rw-r--r--app/assets/javascripts/ide/stores/modules/terminal/actions/checks.js4
-rw-r--r--app/assets/javascripts/ide/stores/modules/terminal/actions/session_controls.js6
-rw-r--r--app/assets/javascripts/ide/stores/modules/terminal/actions/session_status.js2
-rw-r--r--app/assets/javascripts/ide/stores/modules/terminal/getters.js6
-rw-r--r--app/assets/javascripts/ide/stores/modules/terminal/messages.js2
-rw-r--r--app/assets/javascripts/ide/stores/modules/terminal/utils.js6
-rw-r--r--app/assets/javascripts/ide/stores/modules/terminal_sync/actions.js4
-rw-r--r--app/assets/javascripts/ide/stores/mutations.js12
-rw-r--r--app/assets/javascripts/ide/stores/mutations/file.js46
-rw-r--r--app/assets/javascripts/ide/stores/mutations/tree.js2
-rw-r--r--app/assets/javascripts/ide/stores/plugins/terminal.js2
-rw-r--r--app/assets/javascripts/ide/stores/plugins/terminal_sync.js20
-rw-r--r--app/assets/javascripts/ide/stores/utils.js34
-rw-r--r--app/assets/javascripts/ide/sync_router_and_store.js8
-rw-r--r--app/assets/javascripts/ide/utils.js33
72 files changed, 421 insertions, 358 deletions
diff --git a/app/assets/javascripts/ide/commit_icon.js b/app/assets/javascripts/ide/commit_icon.js
index 4984b5bb91d..70ee9cff22b 100644
--- a/app/assets/javascripts/ide/commit_icon.js
+++ b/app/assets/javascripts/ide/commit_icon.js
@@ -1,6 +1,6 @@
import { commitItemIconMap } from './constants';
-export default file => {
+export default (file) => {
if (file.deleted) {
return commitItemIconMap.deleted;
} else if (file.tempFile && !file.prevPath) {
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue b/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue
index 123e0aba959..4192a002486 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue
@@ -63,7 +63,7 @@ export default {
return this.openPendingTab({
file: this.file,
keyPrefix: this.keyPrefix,
- }).then(changeViewer => {
+ }).then((changeViewer) => {
if (changeViewer) {
this.updateViewer(viewerTypes.diff);
}
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue b/app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue
index aed7b792902..91cce44382c 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue
@@ -74,6 +74,7 @@ export default {
<input
:placeholder="placeholderBranchName"
:value="newBranchName"
+ data-testid="ide-new-branch-name"
type="text"
class="form-control monospace"
@input="updateBranchName($event.target.value)"
diff --git a/app/assets/javascripts/ide/components/file_templates/bar.vue b/app/assets/javascripts/ide/components/file_templates/bar.vue
index 88dca2f0556..bd4c4f18141 100644
--- a/app/assets/javascripts/ide/components/file_templates/bar.vue
+++ b/app/assets/javascripts/ide/components/file_templates/bar.vue
@@ -29,7 +29,7 @@ export default {
'undoFileTemplate',
]),
setInitialType() {
- const initialTemplateType = this.templateTypes.find(t => t.name === this.activeFile.name);
+ const initialTemplateType = this.templateTypes.find((t) => t.name === this.activeFile.name);
if (initialTemplateType) {
this.setSelectedTemplateType(initialTemplateType);
diff --git a/app/assets/javascripts/ide/components/file_templates/dropdown.vue b/app/assets/javascripts/ide/components/file_templates/dropdown.vue
index 5d5b66a6444..772dab3fed3 100644
--- a/app/assets/javascripts/ide/components/file_templates/dropdown.vue
+++ b/app/assets/javascripts/ide/components/file_templates/dropdown.vue
@@ -44,7 +44,7 @@ export default {
computed: {
...mapState('fileTemplates', ['templates', 'isLoading']),
outputData() {
- return (this.isAsyncData ? this.templates : this.data).filter(t => {
+ return (this.isAsyncData ? this.templates : this.data).filter((t) => {
if (!this.searchable) return true;
return t.name.toLowerCase().indexOf(this.search.toLowerCase()) >= 0;
diff --git a/app/assets/javascripts/ide/components/ide.vue b/app/assets/javascripts/ide/components/ide.vue
index f8568f46cd6..aac899fde0d 100644
--- a/app/assets/javascripts/ide/components/ide.vue
+++ b/app/assets/javascripts/ide/components/ide.vue
@@ -73,7 +73,7 @@ export default {
},
},
mounted() {
- window.onbeforeunload = e => this.onBeforeUnload(e);
+ window.onbeforeunload = (e) => this.onBeforeUnload(e);
if (this.themeName)
document.querySelector('.navbar-gitlab').classList.add(`theme-${this.themeName}`);
diff --git a/app/assets/javascripts/ide/components/ide_sidebar_nav.vue b/app/assets/javascripts/ide/components/ide_sidebar_nav.vue
index 966c36d6e71..9dbed0ace40 100644
--- a/app/assets/javascripts/ide/components/ide_sidebar_nav.vue
+++ b/app/assets/javascripts/ide/components/ide_sidebar_nav.vue
@@ -37,7 +37,7 @@ export default {
},
methods: {
isActiveTab(tab) {
- return this.isOpen && tab.views.some(view => view.name === this.currentView);
+ return this.isOpen && tab.views.some((view) => view.name === this.currentView);
},
buttonClasses(tab) {
return [
diff --git a/app/assets/javascripts/ide/components/nav_dropdown.vue b/app/assets/javascripts/ide/components/nav_dropdown.vue
index 8cea8655461..6ff77e556c0 100644
--- a/app/assets/javascripts/ide/components/nav_dropdown.vue
+++ b/app/assets/javascripts/ide/components/nav_dropdown.vue
@@ -31,9 +31,7 @@ export default {
},
removeDropdownListeners() {
// eslint-disable-next-line @gitlab/no-global-event-off
- $(this.$refs.dropdown)
- .off('show.bs.dropdown')
- .off('hide.bs.dropdown');
+ $(this.$refs.dropdown).off('show.bs.dropdown').off('hide.bs.dropdown');
},
showDropdown() {
this.isVisibleDropdown = true;
diff --git a/app/assets/javascripts/ide/components/new_dropdown/upload.vue b/app/assets/javascripts/ide/components/new_dropdown/upload.vue
index 4a9a2a57acd..5704129c10f 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/upload.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/upload.vue
@@ -25,23 +25,24 @@ export default {
},
methods: {
createFile(target, file) {
- const { name } = file;
+ const { name, type: mimeType } = file;
const encodedContent = target.result.split('base64,')[1];
const rawContent = encodedContent ? atob(encodedContent) : '';
- const isText = isTextFile({ content: rawContent, mimeType: file.type, name });
+ const isText = isTextFile({ content: rawContent, mimeType, name });
- const emitCreateEvent = content =>
+ const emitCreateEvent = (content) =>
this.$emit('create', {
name: `${this.path ? `${this.path}/` : ''}${name}`,
type: 'blob',
content,
rawPath: !isText ? URL.createObjectURL(file) : '',
+ mimeType,
});
if (isText) {
const reader = new FileReader();
- reader.addEventListener('load', e => emitCreateEvent(e.target.result), { once: true });
+ reader.addEventListener('load', (e) => emitCreateEvent(e.target.result), { once: true });
reader.readAsText(file);
} else {
emitCreateEvent(rawContent);
@@ -50,11 +51,11 @@ export default {
readFile(file) {
const reader = new FileReader();
- reader.addEventListener('load', e => this.createFile(e.target, file), { once: true });
+ reader.addEventListener('load', (e) => this.createFile(e.target, file), { once: true });
reader.readAsDataURL(file);
},
openFile() {
- Array.from(this.$refs.fileUpload.files).forEach(file => this.readFile(file));
+ Array.from(this.$refs.fileUpload.files).forEach((file) => this.readFile(file));
},
startFileUpload() {
this.$refs.fileUpload.click();
@@ -80,6 +81,7 @@ export default {
type="file"
class="hidden"
multiple
+ data-qa-selector="file_upload_field"
@change="openFile"
/>
</div>
diff --git a/app/assets/javascripts/ide/components/panes/collapsible_sidebar.vue b/app/assets/javascripts/ide/components/panes/collapsible_sidebar.vue
index 87019c3b2a5..6f42ae48cc9 100644
--- a/app/assets/javascripts/ide/components/panes/collapsible_sidebar.vue
+++ b/app/assets/javascripts/ide/components/panes/collapsible_sidebar.vue
@@ -35,13 +35,13 @@ export default {
return `${this.side}Pane`;
},
tabs() {
- return this.extensionTabs.filter(tab => tab.show);
+ return this.extensionTabs.filter((tab) => tab.show);
},
tabViews() {
- return this.tabs.map(tab => tab.views).flat();
+ return this.tabs.map((tab) => tab.views).flat();
},
aliveTabViews() {
- return this.tabViews.filter(view => this.isAliveView(view.name));
+ return this.tabViews.filter((view) => this.isAliveView(view.name));
},
},
methods: {
diff --git a/app/assets/javascripts/ide/components/preview/clientside.vue b/app/assets/javascripts/ide/components/preview/clientside.vue
index f65b1201d94..4c2a369226e 100644
--- a/app/assets/javascripts/ide/components/preview/clientside.vue
+++ b/app/assets/javascripts/ide/components/preview/clientside.vue
@@ -1,12 +1,13 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
-import { isEmpty } from 'lodash';
+import { isEmpty, debounce } from 'lodash';
import { Manager } from 'smooshpack';
import { listen } from 'codesandbox-api';
import { GlLoadingIcon } from '@gitlab/ui';
import Navigator from './navigator.vue';
-import { packageJsonPath } from '../../constants';
+import { packageJsonPath, LIVE_PREVIEW_DEBOUNCE } from '../../constants';
import { createPathWithExt } from '../../utils';
+import eventHub from '../../eventhub';
export default {
components: {
@@ -61,13 +62,10 @@ export default {
};
},
},
- watch: {
- entries: {
- deep: true,
- handler: 'update',
- },
- },
mounted() {
+ this.onFilesChangeCallback = debounce(() => this.update(), LIVE_PREVIEW_DEBOUNCE);
+ eventHub.$on('ide.files.change', this.onFilesChangeCallback);
+
this.loading = true;
return this.loadFileContent(packageJsonPath)
@@ -78,17 +76,19 @@ export default {
.then(() => this.initPreview());
},
beforeDestroy() {
+ // Setting sandpackReady = false protects us form a phantom `update()` being called when `debounce` finishes.
+ this.sandpackReady = false;
+ eventHub.$off('ide.files.change', this.onFilesChangeCallback);
+
if (!isEmpty(this.manager)) {
this.manager.listener();
}
+
this.manager = {};
if (this.listener) {
this.listener();
}
-
- clearTimeout(this.timeout);
- this.timeout = null;
},
methods: {
...mapActions(['getFileData', 'getRawFileData']),
@@ -108,7 +108,7 @@ export default {
.then(() => {
this.initManager();
- this.listener = listen(e => {
+ this.listener = listen((e) => {
switch (e.type) {
case 'done':
this.sandpackReady = true;
@@ -122,25 +122,21 @@ export default {
update() {
if (!this.sandpackReady) return;
- clearTimeout(this.timeout);
-
- this.timeout = setTimeout(() => {
- if (isEmpty(this.manager)) {
- this.initPreview();
+ if (isEmpty(this.manager)) {
+ this.initPreview();
- return;
- }
+ return;
+ }
- this.manager.updatePreview(this.sandboxOpts);
- }, 250);
+ this.manager.updatePreview(this.sandboxOpts);
},
initManager() {
const { codesandboxBundlerUrl: bundlerURL } = this;
const settings = {
fileResolver: {
- isFile: p => Promise.resolve(Boolean(this.entries[createPathWithExt(p)])),
- readFile: p => this.loadFileContent(createPathWithExt(p)).then(content => content),
+ isFile: (p) => Promise.resolve(Boolean(this.entries[createPathWithExt(p)])),
+ readFile: (p) => this.loadFileContent(createPathWithExt(p)).then((content) => content),
},
...(bundlerURL ? { bundlerURL } : {}),
};
diff --git a/app/assets/javascripts/ide/components/preview/navigator.vue b/app/assets/javascripts/ide/components/preview/navigator.vue
index 60710251fef..8986359427f 100644
--- a/app/assets/javascripts/ide/components/preview/navigator.vue
+++ b/app/assets/javascripts/ide/components/preview/navigator.vue
@@ -31,7 +31,7 @@ export default {
},
},
mounted() {
- this.listener = listen(e => {
+ this.listener = listen((e) => {
switch (e.type) {
case 'urlchange':
this.onUrlChange(e);
diff --git a/app/assets/javascripts/ide/components/repo_commit_section.vue b/app/assets/javascripts/ide/components/repo_commit_section.vue
index dfd25feed08..8092ef3bce6 100644
--- a/app/assets/javascripts/ide/components/repo_commit_section.vue
+++ b/app/assets/javascripts/ide/components/repo_commit_section.vue
@@ -41,12 +41,12 @@ export default {
file,
keyPrefix: file.staged ? stageKeys.staged : stageKeys.unstaged,
})
- .then(changeViewer => {
+ .then((changeViewer) => {
if (changeViewer) {
this.updateViewer('diff');
}
})
- .catch(e => {
+ .catch((e) => {
throw e;
});
},
diff --git a/app/assets/javascripts/ide/components/repo_editor.vue b/app/assets/javascripts/ide/components/repo_editor.vue
index 1f029612c29..a9c05f2e1ac 100644
--- a/app/assets/javascripts/ide/components/repo_editor.vue
+++ b/app/assets/javascripts/ide/components/repo_editor.vue
@@ -74,8 +74,11 @@ export default {
fileEditor() {
return getFileEditorOrDefault(this.fileEditors, this.file.path);
},
+ isBinaryFile() {
+ return !isTextFile(this.file);
+ },
shouldHideEditor() {
- return this.file && !this.file.loading && !isTextFile(this.file);
+ return this.file && !this.file.loading && this.isBinaryFile;
},
showContentViewer() {
return (
@@ -216,7 +219,7 @@ export default {
.then(() => {
this.createEditorInstance();
})
- .catch(err => {
+ .catch((err) => {
flash(
__('Error setting up editor. Please try again.'),
'alert',
@@ -244,6 +247,10 @@ export default {
);
},
createEditorInstance() {
+ if (this.isBinaryFile) {
+ return;
+ }
+
this.editor.dispose();
this.$nextTick(() => {
@@ -274,7 +281,7 @@ export default {
this.model.updateOptions(this.rules);
- this.model.onChange(model => {
+ this.model.onChange((model) => {
const { file } = model;
if (!file.active) return;
@@ -322,7 +329,7 @@ export default {
}
},
fetchEditorconfigRules() {
- return getRulesWithTraversal(this.file.path, path => {
+ return getRulesWithTraversal(this.file.path, (path) => {
const entry = this.entries[path];
if (!entry) return Promise.resolve(null);
@@ -332,7 +339,7 @@ export default {
return this.getFileData({ path: entry.path, makeFileActive: false }).then(() =>
this.getRawFileData({ path: entry.path }),
);
- }).then(rules => {
+ }).then((rules) => {
this.rules = mapRulesToMonaco(rules);
});
},
@@ -346,7 +353,7 @@ export default {
event.preventDefault();
event.stopImmediatePropagation();
- return readFileAsDataURL(file).then(content => {
+ return readFileAsDataURL(file).then((content) => {
const parentPath = getPathParent(this.file.path);
const path = `${parentPath ? `${parentPath}/` : ''}${file.name}`;
diff --git a/app/assets/javascripts/ide/constants.js b/app/assets/javascripts/ide/constants.js
index bdb11e6b004..e5618466395 100644
--- a/app/assets/javascripts/ide/constants.js
+++ b/app/assets/javascripts/ide/constants.js
@@ -97,3 +97,6 @@ export const packageJsonPath = 'package.json';
export const SIDE_LEFT = 'left';
export const SIDE_RIGHT = 'right';
+
+// Live Preview feature
+export const LIVE_PREVIEW_DEBOUNCE = 2000;
diff --git a/app/assets/javascripts/ide/ide_router.js b/app/assets/javascripts/ide/ide_router.js
index b9ebacef7e1..0e6775d87f1 100644
--- a/app/assets/javascripts/ide/ide_router.js
+++ b/app/assets/javascripts/ide/ide_router.js
@@ -39,7 +39,7 @@ const EmptyRouterComponent = {
},
};
-export const createRouter = store => {
+export const createRouter = (store) => {
const router = new IdeRouter({
mode: 'history',
base: joinPaths(gon.relative_url_root || '', '/-/ide/'),
@@ -54,11 +54,11 @@ export const createRouter = store => {
},
{
path: ':targetmode(edit|tree|blob)/:branchid+/',
- redirect: to => joinPaths(to.path, '/-/'),
+ redirect: (to) => joinPaths(to.path, '/-/'),
},
{
path: ':targetmode(edit|tree|blob)',
- redirect: to => joinPaths(to.path, '/master/-/'),
+ redirect: (to) => joinPaths(to.path, '/master/-/'),
},
{
path: 'merge_requests/:mrid',
@@ -66,7 +66,7 @@ export const createRouter = store => {
},
{
path: '',
- redirect: to => joinPaths(to.path, '/edit/master/-/'),
+ redirect: (to) => joinPaths(to.path, '/edit/master/-/'),
},
],
},
@@ -110,7 +110,7 @@ export const createRouter = store => {
});
}
})
- .catch(e => {
+ .catch((e) => {
flash(
__('Error while loading the project data. Please try again.'),
'alert',
diff --git a/app/assets/javascripts/ide/index.js b/app/assets/javascripts/ide/index.js
index 62f49ba56b1..af408c06556 100644
--- a/app/assets/javascripts/ide/index.js
+++ b/app/assets/javascripts/ide/index.js
@@ -63,6 +63,10 @@ export function initIde(el, options = {}) {
codesandboxBundlerUrl: el.dataset.codesandboxBundlerUrl,
});
},
+ beforeDestroy() {
+ // This helps tests do Singleton cleanups which we don't really have responsibility to know about here.
+ this.$emit('destroy');
+ },
methods: {
...mapActions(['setEmptyStateSvgs', 'setLinks', 'setInitialData']),
},
diff --git a/app/assets/javascripts/ide/lib/common/disposable.js b/app/assets/javascripts/ide/lib/common/disposable.js
index 84b29bdb600..c5d0773c9a2 100644
--- a/app/assets/javascripts/ide/lib/common/disposable.js
+++ b/app/assets/javascripts/ide/lib/common/disposable.js
@@ -4,11 +4,11 @@ export default class Disposable {
}
add(...disposers) {
- disposers.forEach(disposer => this.disposers.add(disposer));
+ disposers.forEach((disposer) => this.disposers.add(disposer));
}
dispose() {
- this.disposers.forEach(disposer => disposer.dispose());
+ this.disposers.forEach((disposer) => disposer.dispose());
this.disposers.clear();
}
}
diff --git a/app/assets/javascripts/ide/lib/common/model.js b/app/assets/javascripts/ide/lib/common/model.js
index 2471b3627ce..4969875439e 100644
--- a/app/assets/javascripts/ide/lib/common/model.js
+++ b/app/assets/javascripts/ide/lib/common/model.js
@@ -75,7 +75,7 @@ export default class Model {
}
onChange(cb) {
- this.events.add(this.disposable.add(this.model.onDidChangeContent(e => cb(this, e))));
+ this.events.add(this.disposable.add(this.model.onDidChangeContent((e) => cb(this, e))));
}
onDispose(cb) {
@@ -121,7 +121,7 @@ export default class Model {
dispose() {
if (!this.model.isDisposed()) this.applyCustomOptions();
- this.events.forEach(cb => {
+ this.events.forEach((cb) => {
if (typeof cb === 'function') cb();
});
diff --git a/app/assets/javascripts/ide/lib/create_diff.js b/app/assets/javascripts/ide/lib/create_diff.js
index 3e915afdbcb..51d4967fb23 100644
--- a/app/assets/javascripts/ide/lib/create_diff.js
+++ b/app/assets/javascripts/ide/lib/create_diff.js
@@ -32,8 +32,8 @@ const filesWithChanges = ({ stagedFiles = [], changedFiles = [], entries = {} })
// We need to clean "move" actions, because we can only support 100% similarity moves at the moment.
// This is because the previous file's content might not be loaded.
Object.values(changes)
- .filter(change => change.action === commitActionTypes.move)
- .forEach(change => {
+ .filter((change) => change.action === commitActionTypes.move)
+ .forEach((change) => {
const prev = changes[change.file.prevPath];
if (!prev) {
@@ -51,14 +51,14 @@ const filesWithChanges = ({ stagedFiles = [], changedFiles = [], entries = {} })
// Next, we need to add deleted directories by looking at the parents
Object.values(changes)
- .filter(change => change.action === commitActionTypes.delete && change.file.parentPath)
+ .filter((change) => change.action === commitActionTypes.delete && change.file.parentPath)
.forEach(({ file }) => {
// Do nothing if we've already visited this directory.
if (changes[file.parentPath]) {
return;
}
- getDeletedParents(entries, file).forEach(parent => {
+ getDeletedParents(entries, file).forEach((parent) => {
changes[parent.path] = { action: commitActionTypes.delete, file: parent };
});
});
@@ -66,13 +66,15 @@ const filesWithChanges = ({ stagedFiles = [], changedFiles = [], entries = {} })
return Object.values(changes);
};
-const createDiff = state => {
+const createDiff = (state) => {
const changes = filesWithChanges(state);
- const toDelete = changes.filter(x => x.action === commitActionTypes.delete).map(x => x.file.path);
+ const toDelete = changes
+ .filter((x) => x.action === commitActionTypes.delete)
+ .map((x) => x.file.path);
const patch = changes
- .filter(x => x.action !== commitActionTypes.delete)
+ .filter((x) => x.action !== commitActionTypes.delete)
.map(({ file, action }) => createFileDiff(file, action))
.join('');
diff --git a/app/assets/javascripts/ide/lib/create_file_diff.js b/app/assets/javascripts/ide/lib/create_file_diff.js
index 5ae4993321c..b417b4765d8 100644
--- a/app/assets/javascripts/ide/lib/create_file_diff.js
+++ b/app/assets/javascripts/ide/lib/create_file_diff.js
@@ -12,13 +12,13 @@ const NEW_LINE = '\n';
*
* - Removes "=======" separator added at the beginning
*/
-const cleanTwoFilesPatch = text => text.replace(/^(=+\s*)/, '');
+const cleanTwoFilesPatch = (text) => text.replace(/^(=+\s*)/, '');
-const endsWithNewLine = val => !val || val[val.length - 1] === NEW_LINE;
+const endsWithNewLine = (val) => !val || val[val.length - 1] === NEW_LINE;
-const addEndingNewLine = val => (endsWithNewLine(val) ? val : val + NEW_LINE);
+const addEndingNewLine = (val) => (endsWithNewLine(val) ? val : val + NEW_LINE);
-const removeEndingNewLine = val => (endsWithNewLine(val) ? val.substr(0, val.length - 1) : val);
+const removeEndingNewLine = (val) => (endsWithNewLine(val) ? val.substr(0, val.length - 1) : val);
const diffHead = (prevPath, newPath = '') =>
`diff --git "a/${prevPath}" "b/${newPath || prevPath}"`;
@@ -37,7 +37,7 @@ const createDiffBody = (path, content, isCreate) => {
const chunkHead = isCreate ? `@@ -0,0 +1,${lines.length} @@` : `@@ -1,${lines.length} +0,0 @@`;
const chunk = lines
- .map(line => `${prefix}${line}`)
+ .map((line) => `${prefix}${line}`)
.concat(!hasNewLine ? [NO_NEW_LINE] : [])
.join(NEW_LINE);
diff --git a/app/assets/javascripts/ide/lib/decorations/controller.js b/app/assets/javascripts/ide/lib/decorations/controller.js
index 13d477bb2cf..b5d3eb10952 100644
--- a/app/assets/javascripts/ide/lib/decorations/controller.js
+++ b/app/assets/javascripts/ide/lib/decorations/controller.js
@@ -11,7 +11,7 @@ export default class DecorationsController {
const modelDecorations = this.decorations.get(model.url);
const decorations = [];
- modelDecorations.forEach(val => decorations.push(...val));
+ modelDecorations.forEach((val) => decorations.push(...val));
return decorations;
}
diff --git a/app/assets/javascripts/ide/lib/diff/controller.js b/app/assets/javascripts/ide/lib/diff/controller.js
index 35fcda6a6c5..3efe692be13 100644
--- a/app/assets/javascripts/ide/lib/diff/controller.js
+++ b/app/assets/javascripts/ide/lib/diff/controller.js
@@ -3,7 +3,7 @@ import { throttle } from 'lodash';
import DirtyDiffWorker from './diff_worker';
import Disposable from '../common/disposable';
-export const getDiffChangeType = change => {
+export const getDiffChangeType = (change) => {
if (change.modified) {
return 'modified';
} else if (change.added) {
@@ -15,7 +15,7 @@ export const getDiffChangeType = change => {
return '';
};
-export const getDecorator = change => ({
+export const getDecorator = (change) => ({
range: new Range(change.lineNumber, 1, change.endLineNumber, 1),
options: {
isWholeLine: true,
@@ -71,7 +71,7 @@ export default class DirtyDiffController {
}
decorate({ data }) {
- const decorations = data.changes.map(change => getDecorator(change));
+ const decorations = data.changes.map((change) => getDecorator(change));
const model = this.modelManager.getModel(data.path);
this.decorationsController.addDecorations(model, 'dirtyDiff', decorations);
}
diff --git a/app/assets/javascripts/ide/lib/diff/diff.js b/app/assets/javascripts/ide/lib/diff/diff.js
index 62ec798b372..5a6401f56ec 100644
--- a/app/assets/javascripts/ide/lib/diff/diff.js
+++ b/app/assets/javascripts/ide/lib/diff/diff.js
@@ -11,7 +11,7 @@ export const computeDiff = (originalContent, newContent) => {
let lineNumber = 1;
return changes.reduce((acc, change) => {
- const findOnLine = acc.find(c => c.lineNumber === lineNumber);
+ const findOnLine = acc.find((c) => c.lineNumber === lineNumber);
if (findOnLine) {
Object.assign(findOnLine, change, {
diff --git a/app/assets/javascripts/ide/lib/diff/diff_worker.js b/app/assets/javascripts/ide/lib/diff/diff_worker.js
index 77416a8de9d..78b2eab6399 100644
--- a/app/assets/javascripts/ide/lib/diff/diff_worker.js
+++ b/app/assets/javascripts/ide/lib/diff/diff_worker.js
@@ -1,7 +1,7 @@
import { computeDiff } from './diff';
// eslint-disable-next-line no-restricted-globals
-self.addEventListener('message', e => {
+self.addEventListener('message', (e) => {
const { data } = e;
// eslint-disable-next-line no-restricted-globals
diff --git a/app/assets/javascripts/ide/lib/editor.js b/app/assets/javascripts/ide/lib/editor.js
index 493dedcd89a..4fad0c09ce7 100644
--- a/app/assets/javascripts/ide/lib/editor.js
+++ b/app/assets/javascripts/ide/lib/editor.js
@@ -12,7 +12,7 @@ import { clearDomElement } from '~/editor/utils';
import { registerLanguages } from '../utils';
function setupThemes() {
- themes.forEach(theme => {
+ themes.forEach((theme) => {
monacoEditor.defineTheme(theme.name, theme.data);
});
}
@@ -108,7 +108,7 @@ export default class Editor {
this.instance.updateOptions(
editorOptions.reduce((acc, obj) => {
- Object.keys(obj).forEach(key => {
+ Object.keys(obj).forEach((key) => {
Object.assign(acc, {
[key]: obj[key](model),
});
@@ -177,7 +177,7 @@ export default class Editor {
onPositionChange(cb) {
if (!this.instance.onDidChangeCursorPosition) return;
- this.disposable.add(this.instance.onDidChangeCursorPosition(e => cb(this.instance, e)));
+ this.disposable.add(this.instance.onDidChangeCursorPosition((e) => cb(this.instance, e)));
}
updateDiffView() {
@@ -213,14 +213,14 @@ export default class Editor {
addCommands() {
const { store } = this;
- const getKeyCode = key => {
+ const getKeyCode = (key) => {
const monacoKeyMod = key.indexOf('KEY_') === 0;
return monacoKeyMod ? KeyCode[key] : KeyMod[key];
};
- keymap.forEach(command => {
- const keybindings = command.bindings.map(binding => {
+ keymap.forEach((command) => {
+ const keybindings = command.bindings.map((binding) => {
const keys = binding.split('+');
// eslint-disable-next-line no-bitwise
diff --git a/app/assets/javascripts/ide/lib/editor_options.js b/app/assets/javascripts/ide/lib/editor_options.js
index f182a1ec50e..9f2a9a8cf4a 100644
--- a/app/assets/javascripts/ide/lib/editor_options.js
+++ b/app/assets/javascripts/ide/lib/editor_options.js
@@ -31,7 +31,7 @@ export const defaultModelOptions = {
export const editorOptions = [
{
- readOnly: model => Boolean(model.file.file_lock),
- quickSuggestions: model => !(model.language === 'markdown'),
+ readOnly: (model) => Boolean(model.file.file_lock),
+ quickSuggestions: (model) => !(model.language === 'markdown'),
},
];
diff --git a/app/assets/javascripts/ide/lib/editorconfig/parser.js b/app/assets/javascripts/ide/lib/editorconfig/parser.js
index 1597e4a8bfa..2adc643a15b 100644
--- a/app/assets/javascripts/ide/lib/editorconfig/parser.js
+++ b/app/assets/javascripts/ide/lib/editorconfig/parser.js
@@ -2,7 +2,7 @@ import { parseString } from 'editorconfig/src/lib/ini';
import minimatch from 'minimatch';
import { getPathParents } from '../../utils';
-const dirname = path => path.replace(/\.editorconfig$/, '');
+const dirname = (path) => path.replace(/\.editorconfig$/, '');
function isRootConfig(config) {
return config.some(([pattern, rules]) => !pattern && rules?.root === 'true');
@@ -44,11 +44,16 @@ function getRulesWithConfigs(filePath, configFiles = [], rules = {}) {
export function getRulesWithTraversal(filePath, getFileContent) {
const editorconfigPaths = [
- ...getPathParents(filePath).map(x => `${x}/.editorconfig`),
+ ...getPathParents(filePath).map((x) => `${x}/.editorconfig`),
'.editorconfig',
];
return Promise.all(
- editorconfigPaths.map(path => getFileContent(path).then(content => ({ path, content }))),
- ).then(results => getRulesWithConfigs(filePath, results.filter(x => x.content)));
+ editorconfigPaths.map((path) => getFileContent(path).then((content) => ({ path, content }))),
+ ).then((results) =>
+ getRulesWithConfigs(
+ filePath,
+ results.filter((x) => x.content),
+ ),
+ );
}
diff --git a/app/assets/javascripts/ide/lib/editorconfig/rules_mapper.js b/app/assets/javascripts/ide/lib/editorconfig/rules_mapper.js
index f9d5579511a..25ffa9a15be 100644
--- a/app/assets/javascripts/ide/lib/editorconfig/rules_mapper.js
+++ b/app/assets/javascripts/ide/lib/editorconfig/rules_mapper.js
@@ -1,23 +1,23 @@
import { isBoolean, isNumber } from 'lodash';
-const map = (key, validValues) => value =>
+const map = (key, validValues) => (value) =>
value in validValues ? { [key]: validValues[value] } : {};
-const bool = key => value => (isBoolean(value) ? { [key]: value } : {});
+const bool = (key) => (value) => (isBoolean(value) ? { [key]: value } : {});
-const int = (key, isValid) => value =>
+const int = (key, isValid) => (value) =>
isNumber(value) && isValid(value) ? { [key]: Math.trunc(value) } : {};
const rulesMapper = {
indent_style: map('insertSpaces', { tab: false, space: true }),
- indent_size: int('tabSize', n => n > 0),
- tab_width: int('tabSize', n => n > 0),
+ indent_size: int('tabSize', (n) => n > 0),
+ tab_width: int('tabSize', (n) => n > 0),
trim_trailing_whitespace: bool('trimTrailingWhitespace'),
end_of_line: map('endOfLine', { crlf: 1, lf: 0 }),
insert_final_newline: bool('insertFinalNewline'),
};
-const parseValue = x => {
+const parseValue = (x) => {
let value = typeof x === 'string' ? x.toLowerCase() : x;
if (/^[0-9.-]+$/.test(value)) value = Number(value);
if (value === 'true') value = true;
diff --git a/app/assets/javascripts/ide/lib/errors.js b/app/assets/javascripts/ide/lib/errors.js
index e62d9d1e77f..f975034a872 100644
--- a/app/assets/javascripts/ide/lib/errors.js
+++ b/app/assets/javascripts/ide/lib/errors.js
@@ -6,17 +6,17 @@ const CODEOWNERS_REGEX = /Push.*protected branches.*CODEOWNERS/;
const BRANCH_CHANGED_REGEX = /changed.*since.*start.*edit/;
const BRANCH_ALREADY_EXISTS = /branch.*already.*exists/;
-const createNewBranchAndCommit = store =>
+const createNewBranchAndCommit = (store) =>
store
.dispatch('commit/updateCommitAction', consts.COMMIT_TO_NEW_BRANCH)
.then(() => store.dispatch('commit/commitChanges'));
-export const createUnexpectedCommitError = message => ({
+export const createUnexpectedCommitError = (message) => ({
title: __('Unexpected error'),
messageHTML: escape(message) || __('Could not commit. An unexpected error occurred.'),
});
-export const createCodeownersCommitError = message => ({
+export const createCodeownersCommitError = (message) => ({
title: __('CODEOWNERS rule violation'),
messageHTML: escape(message),
primaryAction: {
@@ -25,7 +25,7 @@ export const createCodeownersCommitError = message => ({
},
});
-export const createBranchChangedCommitError = message => ({
+export const createBranchChangedCommitError = (message) => ({
title: __('Branch changed'),
messageHTML: `${escape(message)}<br/><br/>${__('Would you like to create a new branch?')}`,
primaryAction: {
@@ -34,19 +34,19 @@ export const createBranchChangedCommitError = message => ({
},
});
-export const branchAlreadyExistsCommitError = message => ({
+export const branchAlreadyExistsCommitError = (message) => ({
title: __('Branch already exists'),
messageHTML: `${escape(message)}<br/><br/>${__(
'Would you like to try auto-generating a branch name?',
)}`,
primaryAction: {
text: __('Create new branch'),
- callback: store =>
+ callback: (store) =>
store.dispatch('commit/addSuffixToBranchName').then(() => createNewBranchAndCommit(store)),
},
});
-export const parseCommitError = e => {
+export const parseCommitError = (e) => {
const { message } = e?.response?.data || {};
if (!message) {
diff --git a/app/assets/javascripts/ide/lib/files.js b/app/assets/javascripts/ide/lib/files.js
index 789e09fa8f2..3fdf012bbb2 100644
--- a/app/assets/javascripts/ide/lib/files.js
+++ b/app/assets/javascripts/ide/lib/files.js
@@ -1,6 +1,6 @@
import { decorateData, sortTree } from '../stores/utils';
-export const splitParent = path => {
+export const splitParent = (path) => {
const idx = path.lastIndexOf('/');
return {
@@ -11,8 +11,20 @@ export const splitParent = path => {
/**
* Create file objects from a list of file paths.
+ *
+ * @param {Array} options.data Array of blob paths to parse and create a file tree from.
+ * @param {Boolean} options.tempFile Web IDE flag for whether this is a "new" file or not.
+ * @param {String} options.content Content to initialize the new blob with.
+ * @param {String} options.rawPath Raw path used for the new blob.
+ * @param {Object} options.blobData Extra values to initialize each blob with.
*/
-export const decorateFiles = ({ data, tempFile = false, content = '', rawPath = '' }) => {
+export const decorateFiles = ({
+ data,
+ tempFile = false,
+ content = '',
+ rawPath = '',
+ blobData = {},
+}) => {
const treeList = [];
const entries = {};
@@ -20,7 +32,7 @@ export const decorateFiles = ({ data, tempFile = false, content = '', rawPath =
let file;
let parentPath;
- const insertParent = path => {
+ const insertParent = (path) => {
if (!path) {
return null;
} else if (entries[path]) {
@@ -55,7 +67,7 @@ export const decorateFiles = ({ data, tempFile = false, content = '', rawPath =
return tree;
};
- data.forEach(path => {
+ data.forEach((path) => {
const { parent, name } = splitParent(path);
const fileFolder = parent && insertParent(parent);
@@ -73,6 +85,7 @@ export const decorateFiles = ({ data, tempFile = false, content = '', rawPath =
content,
rawPath,
parentPath,
+ ...blobData,
});
Object.assign(entries, {
diff --git a/app/assets/javascripts/ide/lib/languages/hcl.js b/app/assets/javascripts/ide/lib/languages/hcl.js
index 4539719b1f2..bbb2ca66f33 100644
--- a/app/assets/javascripts/ide/lib/languages/hcl.js
+++ b/app/assets/javascripts/ide/lib/languages/hcl.js
@@ -11,7 +11,11 @@ const conf = {
lineComment: '//',
blockComment: ['/*', '*/'],
},
- brackets: [['{', '}'], ['[', ']'], ['(', ')']],
+ brackets: [
+ ['{', '}'],
+ ['[', ']'],
+ ['(', ')'],
+ ],
autoClosingPairs: [
{ open: '{', close: '}' },
{ open: '[', close: ']' },
@@ -140,7 +144,7 @@ const language = {
],
heredocBody: [
[
- /^([\w\-]+)$/,
+ /([\w\-]+)$/,
{
cases: {
'$1==$S2': [
@@ -161,7 +165,11 @@ const language = {
[/\/\/.*$/, 'comment'],
[/#.*$/, 'comment'],
],
- comment: [[/[^\/*]+/, 'comment'], [/\*\//, 'comment', '@pop'], [/[\/*]/, 'comment']],
+ comment: [
+ [/[^\/*]+/, 'comment'],
+ [/\*\//, 'comment', '@pop'],
+ [/[\/*]/, 'comment'],
+ ],
string: [
[/\$\{/, { token: 'delimiter', next: '@stringExpression' }],
[/[^\\"\$]+/, 'string'],
diff --git a/app/assets/javascripts/ide/lib/languages/vue.js b/app/assets/javascripts/ide/lib/languages/vue.js
index b9ff5c5d776..f2f81307981 100644
--- a/app/assets/javascripts/ide/lib/languages/vue.js
+++ b/app/assets/javascripts/ide/lib/languages/vue.js
@@ -37,7 +37,13 @@ const conf = {
blockComment: ['{{!--', '--}}'],
},
- brackets: [['<!--', '-->'], ['<', '>'], ['{{', '}}'], ['{', '}'], ['(', ')']],
+ brackets: [
+ ['<!--', '-->'],
+ ['<', '>'],
+ ['{{', '}}'],
+ ['{', '}'],
+ ['(', ')'],
+ ],
autoClosingPairs: [
{ open: '{', close: '}' },
diff --git a/app/assets/javascripts/ide/lib/mirror.js b/app/assets/javascripts/ide/lib/mirror.js
index a516c28ad7a..6f9cfec9465 100644
--- a/app/assets/javascripts/ide/lib/mirror.js
+++ b/app/assets/javascripts/ide/lib/mirror.js
@@ -12,23 +12,23 @@ export const MSG_CONNECTION_ERROR = __('Could not connect to Web IDE file mirror
const noop = () => {};
export const SERVICE_DELAY = 8000;
-const cancellableWait = time => {
+const cancellableWait = (time) => {
let timeoutId = 0;
const cancel = () => clearTimeout(timeoutId);
- const promise = new Promise(resolve => {
+ const promise = new Promise((resolve) => {
timeoutId = setTimeout(resolve, time);
});
return [promise, cancel];
};
-const isErrorResponse = error => error && error.code !== 0;
+const isErrorResponse = (error) => error && error.code !== 0;
-const isErrorPayload = payload => payload && payload.status_code !== 200;
+const isErrorPayload = (payload) => payload && payload.status_code !== 200;
-const getErrorFromResponse = data => {
+const getErrorFromResponse = (data) => {
if (isErrorResponse(data.error)) {
return { message: data.error.Message };
} else if (isErrorPayload(data.payload)) {
@@ -38,9 +38,9 @@ const getErrorFromResponse = data => {
return null;
};
-const getFullPath = path => mergeUrlParams({ service: SERVICE_NAME }, getWebSocketUrl(path));
+const getFullPath = (path) => mergeUrlParams({ service: SERVICE_NAME }, getWebSocketUrl(path));
-const createWebSocket = fullPath =>
+const createWebSocket = (fullPath) =>
new Promise((resolve, reject) => {
const socket = new WebSocket(fullPath, [PROTOCOL]);
const resetCallbacks = () => {
@@ -59,7 +59,7 @@ const createWebSocket = fullPath =>
};
});
-export const canConnect = ({ services = [] }) => services.some(name => name === SERVICE_NAME);
+export const canConnect = ({ services = [] }) => services.some((name) => name === SERVICE_NAME);
export const createMirror = () => {
let socket = null;
@@ -71,23 +71,23 @@ export const createMirror = () => {
cancelHandler = noop;
};
- const onCancelConnect = fn => {
+ const onCancelConnect = (fn) => {
cancelHandler = fn;
};
- const receiveMessage = ev => {
+ const receiveMessage = (ev) => {
const handle = nextMessageHandler;
nextMessageHandler = noop;
handle(JSON.parse(ev.data));
};
- const onNextMessage = fn => {
+ const onNextMessage = (fn) => {
nextMessageHandler = fn;
};
const waitForNextMessage = () =>
new Promise((resolve, reject) => {
- onNextMessage(data => {
+ onNextMessage((data) => {
const err = getErrorFromResponse(data);
if (err) {
@@ -133,7 +133,7 @@ export const createMirror = () => {
return wait
.then(() => createWebSocket(fullPath))
- .then(newSocket => {
+ .then((newSocket) => {
socket = newSocket;
socket.onmessage = receiveMessage;
});
diff --git a/app/assets/javascripts/ide/services/index.js b/app/assets/javascripts/ide/services/index.js
index 70a6a6b423d..2264d63c737 100644
--- a/app/assets/javascripts/ide/services/index.js
+++ b/app/assets/javascripts/ide/services/index.js
@@ -4,9 +4,9 @@ import Api from '~/api';
import getUserPermissions from '../queries/getUserPermissions.query.graphql';
import { query } from './gql';
-const fetchApiProjectData = projectPath => Api.project(projectPath).then(({ data }) => data);
+const fetchApiProjectData = (projectPath) => Api.project(projectPath).then(({ data }) => data);
-const fetchGqlProjectData = projectPath =>
+const fetchGqlProjectData = (projectPath) =>
query({
query: getUserPermissions,
variables: { projectPath },
@@ -27,9 +27,12 @@ export default {
return Promise.resolve(file.raw);
}
+ const options = file.binary ? { responseType: 'arraybuffer' } : {};
+
return axios
.get(file.rawPath, {
- transformResponse: [f => f],
+ transformResponse: [(f) => f],
+ ...options,
})
.then(({ data }) => data);
},
@@ -51,7 +54,7 @@ export default {
escapeFileUrl(filePath),
),
{
- transformResponse: [f => f],
+ transformResponse: [(f) => f],
},
)
.then(({ data }) => data);
diff --git a/app/assets/javascripts/ide/services/terminals.js b/app/assets/javascripts/ide/services/terminals.js
index 17b4329037d..ea54733baa4 100644
--- a/app/assets/javascripts/ide/services/terminals.js
+++ b/app/assets/javascripts/ide/services/terminals.js
@@ -1,6 +1,6 @@
import axios from '~/lib/utils/axios_utils';
-export const baseUrl = projectPath => `/${projectPath}/ide_terminals`;
+export const baseUrl = (projectPath) => `/${projectPath}/ide_terminals`;
export const checkConfig = (projectPath, branch) =>
axios.post(`${baseUrl(projectPath)}/check_config`, {
diff --git a/app/assets/javascripts/ide/stores/actions.js b/app/assets/javascripts/ide/stores/actions.js
index 710256b6377..d62dfc35d15 100644
--- a/app/assets/javascripts/ide/stores/actions.js
+++ b/app/assets/javascripts/ide/stores/actions.js
@@ -20,7 +20,7 @@ export const redirectToUrl = (self, url) => visitUrl(url);
export const setInitialData = ({ commit }, data) => commit(types.SET_INITIAL_DATA, data);
export const discardAllChanges = ({ state, commit, dispatch }) => {
- state.changedFiles.forEach(file => dispatch('restoreOriginalFile', file.path));
+ state.changedFiles.forEach((file) => dispatch('restoreOriginalFile', file.path));
commit(types.REMOVE_ALL_CHANGES_FILES);
};
@@ -31,7 +31,7 @@ export const setResizingStatus = ({ commit }, resizing) => {
export const createTempEntry = (
{ state, commit, dispatch, getters },
- { name, type, content = '', rawPath = '', openFile = true, makeFileActive = true },
+ { name, type, content = '', rawPath = '', openFile = true, makeFileActive = true, mimeType = '' },
) => {
const fullName = name.slice(-1) !== '/' && type === 'tree' ? `${name}/` : name;
@@ -56,6 +56,9 @@ export const createTempEntry = (
tempFile: true,
content,
rawPath,
+ blobData: {
+ mimeType,
+ },
});
const { file, parentPath } = data;
@@ -103,7 +106,7 @@ export const stageAllChanges = ({ state, commit, dispatch, getters }) => {
commit(types.SET_LAST_COMMIT_MSG, '');
- state.changedFiles.forEach(file =>
+ state.changedFiles.forEach((file) =>
commit(types.STAGE_CHANGE, { path: file.path, diffInfo: getters.getDiffInfo(file.path) }),
);
@@ -120,7 +123,7 @@ export const stageAllChanges = ({ state, commit, dispatch, getters }) => {
export const unstageAllChanges = ({ state, commit, dispatch, getters }) => {
const openFile = state.openFiles[0];
- state.stagedFiles.forEach(file =>
+ state.stagedFiles.forEach((file) =>
commit(types.UNSTAGE_CHANGE, { path: file.path, diffInfo: getters.getDiffInfo(file.path) }),
);
@@ -191,7 +194,7 @@ export const deleteEntry = ({ commit, dispatch, state }, path) => {
if (entry.opened) dispatch('closeFile', entry);
if (isTree) {
- entry.tree.forEach(f => dispatch('deleteEntry', f.path));
+ entry.tree.forEach((f) => dispatch('deleteEntry', f.path));
}
commit(types.DELETE_ENTRY, path);
@@ -218,7 +221,7 @@ export const renameEntry = ({ dispatch, commit, state, getters }, { path, name,
commit(types.RENAME_ENTRY, { path, name, parentPath });
if (entry.type === 'tree') {
- state.entries[newPath].tree.forEach(f => {
+ state.entries[newPath].tree.forEach((f) => {
dispatch('renameEntry', {
path: f.path,
name: f.name,
@@ -277,7 +280,7 @@ export const getBranchData = ({ commit, state }, { projectId, branchId, force =
commit(types.SET_BRANCH_WORKING_REFERENCE, { projectId, branchId, reference: id });
resolve(data);
})
- .catch(e => {
+ .catch((e) => {
if (e.response.status === 404) {
reject(e);
} else {
diff --git a/app/assets/javascripts/ide/stores/actions/file.js b/app/assets/javascripts/ide/stores/actions/file.js
index 8b43c7238fd..42668dec63a 100644
--- a/app/assets/javascripts/ide/stores/actions/file.js
+++ b/app/assets/javascripts/ide/stores/actions/file.js
@@ -10,22 +10,15 @@ import eventHub from '../../eventhub';
import service from '../../services';
import * as types from '../mutation_types';
import { setPageTitleForFile } from '../utils';
-import { viewerTypes, stageKeys } from '../../constants';
+import { viewerTypes, stageKeys, commitActionTypes } from '../../constants';
export const closeFile = ({ commit, state, dispatch, getters }, file) => {
const { path } = file;
- const indexOfClosedFile = state.openFiles.findIndex(f => f.key === file.key);
+ const indexOfClosedFile = state.openFiles.findIndex((f) => f.key === file.key);
const fileWasActive = file.active;
- if (file.pending) {
- commit(types.REMOVE_PENDING_TAB, file);
- } else {
- commit(types.TOGGLE_FILE_OPEN, path);
- commit(types.SET_FILE_ACTIVE, { path, active: false });
- }
-
- if (state.openFiles.length > 0 && fileWasActive) {
- const nextIndexToOpen = indexOfClosedFile === 0 ? 0 : indexOfClosedFile - 1;
+ if (state.openFiles.length > 1 && fileWasActive) {
+ const nextIndexToOpen = indexOfClosedFile === 0 ? 1 : indexOfClosedFile - 1;
const nextFileToOpen = state.openFiles[nextIndexToOpen];
if (nextFileToOpen.pending) {
@@ -35,14 +28,22 @@ export const closeFile = ({ commit, state, dispatch, getters }, file) => {
keyPrefix: nextFileToOpen.staged ? 'staged' : 'unstaged',
});
} else {
+ dispatch('setFileActive', nextFileToOpen.path);
dispatch('router/push', getters.getUrlForPath(nextFileToOpen.path), { root: true });
}
- } else if (!state.openFiles.length) {
+ } else if (state.openFiles.length === 1) {
dispatch('router/push', `/project/${state.currentProjectId}/tree/${state.currentBranchId}/`, {
root: true,
});
}
+ if (file.pending) {
+ commit(types.REMOVE_PENDING_TAB, file);
+ } else {
+ commit(types.TOGGLE_FILE_OPEN, path);
+ commit(types.SET_FILE_ACTIVE, { path, active: false });
+ }
+
eventHub.$emit(`editor.update.model.dispose.${file.key}`);
};
@@ -108,7 +109,7 @@ export const getFileData = (
.catch(() => {
dispatch('setErrorMessage', {
text: __('An error occurred while loading the file.'),
- action: payload =>
+ action: (payload) =>
dispatch('getFileData', payload).then(() => dispatch('setErrorMessage', null)),
actionText: __('Please try again'),
actionPayload: { path, makeFileActive },
@@ -125,13 +126,13 @@ export const setFileMrChange = ({ commit }, { file, mrChange }) => {
export const getRawFileData = ({ state, commit, dispatch, getters }, { path }) => {
const file = state.entries[path];
- const stagedFile = state.stagedFiles.find(f => f.path === path);
+ const stagedFile = state.stagedFiles.find((f) => f.path === path);
const fileDeletedAndReadded = getters.isFileDeletedAndReadded(path);
commit(types.TOGGLE_LOADING, { entry: file, forceValue: true });
return service
.getRawFileData(fileDeletedAndReadded ? stagedFile : file)
- .then(raw => {
+ .then((raw) => {
if (!(file.tempFile && !file.prevPath && !fileDeletedAndReadded))
commit(types.SET_FILE_RAW_DATA, { file, raw, fileDeletedAndReadded });
@@ -139,7 +140,7 @@ export const getRawFileData = ({ state, commit, dispatch, getters }, { path }) =
const baseSha =
(getters.currentMergeRequest && getters.currentMergeRequest.baseCommitSha) || '';
- return service.getBaseRawFileData(file, state.currentProjectId, baseSha).then(baseRaw => {
+ return service.getBaseRawFileData(file, state.currentProjectId, baseSha).then((baseRaw) => {
commit(types.SET_FILE_BASE_RAW_DATA, {
file,
baseRaw,
@@ -149,10 +150,10 @@ export const getRawFileData = ({ state, commit, dispatch, getters }, { path }) =
}
return raw;
})
- .catch(e => {
+ .catch((e) => {
dispatch('setErrorMessage', {
text: __('An error occurred while loading the file content.'),
- action: payload =>
+ action: (payload) =>
dispatch('getRawFileData', payload).then(() => dispatch('setErrorMessage', null)),
actionText: __('Please try again'),
actionPayload: { path },
@@ -164,7 +165,7 @@ export const getRawFileData = ({ state, commit, dispatch, getters }, { path }) =
});
};
-export const changeFileContent = ({ commit, state, getters }, { path, content }) => {
+export const changeFileContent = ({ commit, dispatch, state, getters }, { path, content }) => {
const file = state.entries[path];
// It's possible for monaco to hit a race condition where it tries to update renamed files.
@@ -178,13 +179,15 @@ export const changeFileContent = ({ commit, state, getters }, { path, content })
content,
});
- const indexOfChangedFile = state.changedFiles.findIndex(f => f.path === path);
+ const indexOfChangedFile = state.changedFiles.findIndex((f) => f.path === path);
if (file.changed && indexOfChangedFile === -1) {
commit(types.STAGE_CHANGE, { path, diffInfo: getters.getDiffInfo(path) });
} else if (!file.changed && !file.tempFile && indexOfChangedFile !== -1) {
commit(types.REMOVE_FILE_FROM_CHANGED, path);
}
+
+ dispatch('triggerFilesChange', { type: commitActionTypes.update, path });
};
export const restoreOriginalFile = ({ dispatch, state, commit }, path) => {
@@ -225,7 +228,7 @@ export const discardFileChanges = ({ dispatch, state, commit, getters }, path) =
.then(() => {
dispatch('router/push', getters.getUrlForPath(file.path), { root: true });
})
- .catch(e => {
+ .catch((e) => {
throw e;
});
}
@@ -275,7 +278,7 @@ export const unstageChange = ({ commit, dispatch, getters }, path) => {
export const openPendingTab = ({ commit, dispatch, getters, state }, { file, keyPrefix }) => {
if (getters.activeFile && getters.activeFile.key === `${keyPrefix}-${file.key}`) return false;
- state.openFiles.forEach(f => eventHub.$emit(`editor.update.model.dispose.${f.key}`));
+ state.openFiles.forEach((f) => eventHub.$emit(`editor.update.model.dispose.${f.key}`));
commit(types.ADD_PENDING_TAB, { file, keyPrefix });
diff --git a/app/assets/javascripts/ide/stores/actions/merge_request.js b/app/assets/javascripts/ide/stores/actions/merge_request.js
index 547665b49c6..8215cba7ccf 100644
--- a/app/assets/javascripts/ide/stores/actions/merge_request.js
+++ b/app/assets/javascripts/ide/stores/actions/merge_request.js
@@ -33,7 +33,7 @@ export const getMergeRequestsForBranch = (
commit(types.SET_CURRENT_MERGE_REQUEST, `${currentMR.iid}`);
}
})
- .catch(e => {
+ .catch((e) => {
flash(
__(`Error fetching merge requests for ${branchId}`),
'alert',
@@ -66,7 +66,7 @@ export const getMergeRequestData = (
.catch(() => {
dispatch('setErrorMessage', {
text: __('An error occurred while loading the merge request.'),
- action: payload =>
+ action: (payload) =>
dispatch('getMergeRequestData', payload).then(() =>
dispatch('setErrorMessage', null),
),
@@ -99,7 +99,7 @@ export const getMergeRequestChanges = (
.catch(() => {
dispatch('setErrorMessage', {
text: __('An error occurred while loading the merge request changes.'),
- action: payload =>
+ action: (payload) =>
dispatch('getMergeRequestChanges', payload).then(() =>
dispatch('setErrorMessage', null),
),
@@ -121,8 +121,8 @@ export const getMergeRequestVersions = (
if (!state.projects[projectId].mergeRequests[mergeRequestId].versions.length || force) {
service
.getProjectMergeRequestVersions(targetProjectId || projectId, mergeRequestId)
- .then(res => res.data)
- .then(data => {
+ .then((res) => res.data)
+ .then((data) => {
commit(types.SET_MERGE_REQUEST_VERSIONS, {
projectPath: projectId,
mergeRequestId,
@@ -133,7 +133,7 @@ export const getMergeRequestVersions = (
.catch(() => {
dispatch('setErrorMessage', {
text: __('An error occurred while loading the merge request version data.'),
- action: payload =>
+ action: (payload) =>
dispatch('getMergeRequestVersions', payload).then(() =>
dispatch('setErrorMessage', null),
),
@@ -156,7 +156,7 @@ export const openMergeRequest = (
targetProjectId,
mergeRequestId,
})
- .then(mr => {
+ .then((mr) => {
dispatch('setCurrentBranchId', mr.source_branch);
return dispatch('getBranchData', {
@@ -186,7 +186,7 @@ export const openMergeRequest = (
mergeRequestId,
}),
)
- .then(mrChanges => {
+ .then((mrChanges) => {
if (mrChanges.changes.length) {
dispatch('updateActivityBarView', leftSidebarViews.review.name);
}
@@ -210,7 +210,7 @@ export const openMergeRequest = (
}
});
})
- .catch(e => {
+ .catch((e) => {
flash(__('Error while loading the merge request. Please try again.'));
throw e;
});
diff --git a/app/assets/javascripts/ide/stores/actions/project.js b/app/assets/javascripts/ide/stores/actions/project.js
index 51e9bf6a84c..27f6848f1d6 100644
--- a/app/assets/javascripts/ide/stores/actions/project.js
+++ b/app/assets/javascripts/ide/stores/actions/project.js
@@ -11,8 +11,8 @@ export const getProjectData = ({ commit, state }, { namespace, projectId, force
commit(types.TOGGLE_LOADING, { entry: state });
service
.getProjectData(namespace, projectId)
- .then(res => res.data)
- .then(data => {
+ .then((res) => res.data)
+ .then((data) => {
commit(types.TOGGLE_LOADING, { entry: state });
commit(types.SET_PROJECT, { projectPath: `${namespace}/${projectId}`, project: data });
commit(types.SET_CURRENT_PROJECT, `${namespace}/${projectId}`);
@@ -44,8 +44,9 @@ export const refreshLastCommitData = ({ commit }, { projectId, branchId } = {})
commit: data.commit,
});
})
- .catch(() => {
+ .catch((e) => {
flash(__('Error loading last commit.'), 'alert', document, null, false, true);
+ throw e;
});
export const createNewBranchFromDefault = ({ state, dispatch, getters }, branch) =>
@@ -61,7 +62,7 @@ export const createNewBranchFromDefault = ({ state, dispatch, getters }, branch)
.catch(() => {
dispatch('setErrorMessage', {
text: __('An error occurred creating the new branch.'),
- action: payload => dispatch('createNewBranchFromDefault', payload),
+ action: (payload) => dispatch('createNewBranchFromDefault', payload),
actionText: __('Please try again'),
actionPayload: branch,
});
@@ -76,7 +77,7 @@ export const showBranchNotFoundError = ({ dispatch }, branchId) => {
},
false,
),
- action: payload => dispatch('createNewBranchFromDefault', payload),
+ action: (payload) => dispatch('createNewBranchFromDefault', payload),
actionText: __('Create branch'),
actionPayload: branchId,
});
@@ -102,7 +103,7 @@ export const loadFile = ({ dispatch, state }, { basePath }) => {
if (basePath) {
const path = basePath.slice(-1) === '/' ? basePath.slice(0, -1) : basePath;
const treeEntryKey = Object.keys(state.entries).find(
- key => key === path && !state.entries[key].pending,
+ (key) => key === path && !state.entries[key].pending,
);
const treeEntry = state.entries[treeEntryKey];
@@ -144,7 +145,7 @@ export const loadBranch = ({ dispatch, getters, state }, { projectId, branchId }
ref: branch.commit.id,
});
})
- .catch(err => {
+ .catch((err) => {
dispatch('showBranchNotFoundError', branchId);
throw err;
});
diff --git a/app/assets/javascripts/ide/stores/actions/tree.js b/app/assets/javascripts/ide/stores/actions/tree.js
index 23a5e26bc1c..150dfcb2726 100644
--- a/app/assets/javascripts/ide/stores/actions/tree.js
+++ b/app/assets/javascripts/ide/stores/actions/tree.js
@@ -87,10 +87,10 @@ export const getFiles = ({ state, commit, dispatch }, payload = {}) => {
resolve();
})
- .catch(e => {
+ .catch((e) => {
dispatch('setErrorMessage', {
text: __('An error occurred while loading all the files.'),
- action: actionPayload =>
+ action: (actionPayload) =>
dispatch('getFiles', actionPayload).then(() => dispatch('setErrorMessage', null)),
actionText: __('Please try again'),
actionPayload: { projectId, branchId },
diff --git a/app/assets/javascripts/ide/stores/extend.js b/app/assets/javascripts/ide/stores/extend.js
index 1c1636cf6ca..b2777ec89ff 100644
--- a/app/assets/javascripts/ide/stores/extend.js
+++ b/app/assets/javascripts/ide/stores/extend.js
@@ -8,7 +8,7 @@ const plugins = () => [
export default (store, el) => {
// plugins is actually an array of plugin factories, so we have to create first then call
- plugins().forEach(plugin => plugin(el)(store));
+ plugins().forEach((plugin) => plugin(el)(store));
return store;
};
diff --git a/app/assets/javascripts/ide/stores/getters.js b/app/assets/javascripts/ide/stores/getters.js
index 500ce9f32d5..59e8d37a92a 100644
--- a/app/assets/javascripts/ide/stores/getters.js
+++ b/app/assets/javascripts/ide/stores/getters.js
@@ -9,19 +9,19 @@ import {
import { addNumericSuffix } from '~/ide/utils';
import Api from '~/api';
-export const activeFile = state => state.openFiles.find(file => file.active) || null;
+export const activeFile = (state) => state.openFiles.find((file) => file.active) || null;
-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 projectsWithTrees = state =>
- Object.keys(state.projects).map(projectId => {
+export const projectsWithTrees = (state) =>
+ Object.keys(state.projects).map((projectId) => {
const project = state.projects[projectId];
return {
...project,
- branches: Object.keys(project.branches).map(branchId => {
+ branches: Object.keys(project.branches).map((branchId) => {
const branch = project.branches[branchId];
return {
@@ -32,7 +32,7 @@ export const projectsWithTrees = state =>
};
});
-export const currentMergeRequest = state => {
+export const currentMergeRequest = (state) => {
if (
state.projects[state.currentProjectId] &&
state.projects[state.currentProjectId].mergeRequests
@@ -42,19 +42,19 @@ export const currentMergeRequest = state => {
return null;
};
-export const findProject = state => projectId => state.projects[projectId];
+export const findProject = (state) => (projectId) => state.projects[projectId];
export const currentProject = (state, getters) => getters.findProject(state.currentProjectId);
-export const emptyRepo = state =>
+export const emptyRepo = (state) =>
state.projects[state.currentProjectId] && state.projects[state.currentProjectId].empty_repo;
-export const currentTree = state =>
+export const currentTree = (state) =>
state.trees[`${state.currentProjectId}/${state.currentBranchId}`];
-export const hasMergeRequest = state => Boolean(state.currentMergeRequestId);
+export const hasMergeRequest = (state) => Boolean(state.currentMergeRequestId);
-export const allBlobs = state =>
+export const allBlobs = (state) =>
Object.keys(state.entries)
.reduce((acc, key) => {
const entry = state.entries[key];
@@ -67,35 +67,35 @@ export const allBlobs = state =>
}, [])
.sort((a, b) => b.lastOpenedAt - a.lastOpenedAt);
-export const getChangedFile = state => path => state.changedFiles.find(f => f.path === path);
-export const getStagedFile = state => path => state.stagedFiles.find(f => f.path === path);
-export const getOpenFile = state => path => state.openFiles.find(f => f.path === path);
+export const getChangedFile = (state) => (path) => state.changedFiles.find((f) => f.path === path);
+export const getStagedFile = (state) => (path) => state.stagedFiles.find((f) => f.path === path);
+export const getOpenFile = (state) => (path) => state.openFiles.find((f) => f.path === path);
-export const lastOpenedFile = state =>
+export const lastOpenedFile = (state) =>
[...state.changedFiles, ...state.stagedFiles].sort((a, b) => b.lastOpenedAt - a.lastOpenedAt)[0];
-export const isEditModeActive = state => state.currentActivityView === leftSidebarViews.edit.name;
-export const isCommitModeActive = state =>
+export const isEditModeActive = (state) => state.currentActivityView === leftSidebarViews.edit.name;
+export const isCommitModeActive = (state) =>
state.currentActivityView === leftSidebarViews.commit.name;
-export const isReviewModeActive = state =>
+export const isReviewModeActive = (state) =>
state.currentActivityView === leftSidebarViews.review.name;
-export const someUncommittedChanges = state =>
+export const someUncommittedChanges = (state) =>
Boolean(state.changedFiles.length || state.stagedFiles.length);
-export const getChangesInFolder = state => path => {
- const changedFilesCount = state.changedFiles.filter(f => filePathMatches(f.path, path)).length;
+export const getChangesInFolder = (state) => (path) => {
+ const changedFilesCount = state.changedFiles.filter((f) => filePathMatches(f.path, path)).length;
const stagedFilesCount = state.stagedFiles.filter(
- f => filePathMatches(f.path, path) && !getChangedFile(state)(f.path),
+ (f) => filePathMatches(f.path, path) && !getChangedFile(state)(f.path),
).length;
return changedFilesCount + stagedFilesCount;
};
-export const getUnstagedFilesCountForPath = state => path =>
+export const getUnstagedFilesCountForPath = (state) => (path) =>
getChangesCountForFiles(state.changedFiles, path);
-export const getStagedFilesCountForPath = state => path =>
+export const getStagedFilesCountForPath = (state) => (path) =>
getChangesCountForFiles(state.stagedFiles, path);
export const lastCommit = (state, getters) => {
@@ -115,7 +115,7 @@ export const currentBranch = (state, getters) =>
export const branchName = (_state, getters) => getters.currentBranch && getters.currentBranch.name;
-export const packageJson = state => state.entries[packageJsonPath];
+export const packageJson = (state) => state.entries[packageJsonPath];
export const isOnDefaultBranch = (_state, getters) =>
getters.currentProject && getters.currentProject.default_branch === getters.branchName;
@@ -124,14 +124,14 @@ export const canPushToBranch = (_state, getters) => {
return Boolean(getters.currentBranch ? getters.currentBranch.can_push : getters.canPushCode);
};
-export const isFileDeletedAndReadded = (state, getters) => path => {
+export const isFileDeletedAndReadded = (state, getters) => (path) => {
const stagedFile = getters.getStagedFile(path);
const file = state.entries[path];
return Boolean(stagedFile && stagedFile.deleted && file.tempFile);
};
// checks if any diff exists in the staged or unstaged changes for this path
-export const getDiffInfo = (state, getters) => path => {
+export const getDiffInfo = (state, getters) => (path) => {
const stagedFile = getters.getStagedFile(path);
const file = state.entries[path];
const renamed = file.prevPath ? file.path !== file.prevPath : false;
@@ -149,7 +149,7 @@ export const getDiffInfo = (state, getters) => path => {
};
};
-export const findProjectPermissions = (state, getters) => projectId =>
+export const findProjectPermissions = (state, getters) => (projectId) =>
getters.findProject(projectId)?.userPermissions || {};
export const canReadMergeRequests = (state, getters) =>
@@ -161,10 +161,10 @@ export const canCreateMergeRequests = (state, getters) =>
export const canPushCode = (state, getters) =>
Boolean(getters.findProjectPermissions(state.currentProjectId)[PERMISSION_PUSH_CODE]);
-export const entryExists = state => path =>
+export const entryExists = (state) => (path) =>
Boolean(state.entries[path] && !state.entries[path].deleted);
-export const getAvailableFileName = (state, getters) => path => {
+export const getAvailableFileName = (state, getters) => (path) => {
let newPath = path;
while (getters.entryExists(newPath)) {
@@ -174,10 +174,10 @@ export const getAvailableFileName = (state, getters) => path => {
return newPath;
};
-export const getUrlForPath = state => path =>
+export const getUrlForPath = (state) => (path) =>
`/project/${state.currentProjectId}/tree/${state.currentBranchId}/-/${path}/`;
-export const getJsonSchemaForPath = (state, getters) => path => {
+export const getJsonSchemaForPath = (state, getters) => (path) => {
const [namespace, ...project] = state.currentProjectId.split('/');
return {
uri:
diff --git a/app/assets/javascripts/ide/stores/modules/branches/actions.js b/app/assets/javascripts/ide/stores/modules/branches/actions.js
index c46289f77e2..74a4cd9848b 100644
--- a/app/assets/javascripts/ide/stores/modules/branches/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/branches/actions.js
@@ -8,7 +8,7 @@ export const receiveBranchesError = ({ commit, dispatch }, { search }) => {
'setErrorMessage',
{
text: __('Error loading branches.'),
- action: payload =>
+ action: (payload) =>
dispatch('fetchBranches', payload).then(() =>
dispatch('setErrorMessage', null, { root: true }),
),
diff --git a/app/assets/javascripts/ide/stores/modules/branches/mutations.js b/app/assets/javascripts/ide/stores/modules/branches/mutations.js
index 0a455f4500f..3883e1cc905 100644
--- a/app/assets/javascripts/ide/stores/modules/branches/mutations.js
+++ b/app/assets/javascripts/ide/stores/modules/branches/mutations.js
@@ -9,7 +9,7 @@ export default {
},
[types.RECEIVE_BRANCHES_SUCCESS](state, data) {
state.isLoading = false;
- state.branches = data.map(branch => ({
+ state.branches = data.map((branch) => ({
name: branch.name,
committedDate: branch.commit.committed_date,
}));
diff --git a/app/assets/javascripts/ide/stores/modules/commit/actions.js b/app/assets/javascripts/ide/stores/modules/commit/actions.js
index e0d2028d2e1..29b9a8a9521 100644
--- a/app/assets/javascripts/ide/stores/modules/commit/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/commit/actions.js
@@ -78,8 +78,8 @@ export const updateFilesAfterCommit = ({ commit, dispatch, rootState, rootGetter
{ root: true },
);
- rootState.stagedFiles.forEach(file => {
- const changedFile = rootState.changedFiles.find(f => f.path === file.path);
+ rootState.stagedFiles.forEach((file) => {
+ const changedFile = rootState.changedFiles.find((f) => f.path === file.path);
commit(
rootTypes.UPDATE_FILE_AFTER_COMMIT,
@@ -133,7 +133,7 @@ export const commitChanges = ({ commit, state, getters, dispatch, rootState, roo
return service.commit(rootState.currentProjectId, payload);
})
- .catch(e => {
+ .catch((e) => {
commit(types.UPDATE_LOADING, false);
commit(types.SET_ERROR, parseCommitError(e));
@@ -193,37 +193,36 @@ export const commitChanges = ({ commit, state, getters, dispatch, rootState, roo
},
{ root: true },
)
- .then(changeViewer => {
+ .then((changeViewer) => {
if (changeViewer) {
dispatch('updateViewer', 'diff', { root: true });
}
})
- .catch(e => {
+ .catch((e) => {
throw e;
});
} else {
dispatch('updateActivityBarView', leftSidebarViews.edit.name, { root: true });
dispatch('updateViewer', 'editor', { root: true });
-
- if (rootGetters.activeFile) {
- dispatch(
- 'router/push',
- `/project/${rootState.currentProjectId}/blob/${branchName}/-/${rootGetters.activeFile.path}`,
- { root: true },
- );
- }
}
})
.then(() => dispatch('updateCommitAction', consts.COMMIT_TO_CURRENT_BRANCH))
- .then(() =>
- dispatch(
+ .then(() => {
+ if (newBranch) {
+ const path = rootGetters.activeFile ? rootGetters.activeFile.path : '';
+
+ return dispatch(
+ 'router/push',
+ `/project/${rootState.currentProjectId}/blob/${branchName}/-/${path}`,
+ { root: true },
+ );
+ }
+
+ return dispatch(
'refreshLastCommitData',
- {
- projectId: rootState.currentProjectId,
- branchId: rootState.currentBranchId,
- },
+ { projectId: rootState.currentProjectId, branchId: branchName },
{ root: true },
- ),
- );
+ );
+ });
});
};
diff --git a/app/assets/javascripts/ide/stores/modules/commit/getters.js b/app/assets/javascripts/ide/stores/modules/commit/getters.js
index 416ca88d6c9..2301cf23f9f 100644
--- a/app/assets/javascripts/ide/stores/modules/commit/getters.js
+++ b/app/assets/javascripts/ide/stores/modules/commit/getters.js
@@ -11,7 +11,7 @@ const createTranslatedTextForFiles = (files, text) => {
});
};
-export const discardDraftButtonDisabled = state =>
+export const discardDraftButtonDisabled = (state) =>
state.commitMessage === '' || state.submitCommitLoading;
// Note: If changing the structure of the placeholder branch name, please also
@@ -37,18 +37,18 @@ export const preBuiltCommitMessage = (state, _, rootState) => {
if (state.commitMessage) return state.commitMessage;
const files = rootState.stagedFiles.length ? rootState.stagedFiles : rootState.changedFiles;
- const modifiedFiles = files.filter(f => !f.deleted);
- const deletedFiles = files.filter(f => f.deleted);
+ const modifiedFiles = files.filter((f) => !f.deleted);
+ const deletedFiles = files.filter((f) => f.deleted);
return [
createTranslatedTextForFiles(modifiedFiles, __('Update')),
createTranslatedTextForFiles(deletedFiles, __('Deleted')),
]
- .filter(t => t)
+ .filter((t) => t)
.join('\n');
};
-export const isCreatingNewBranch = state => state.commitAction === consts.COMMIT_TO_NEW_BRANCH;
+export const isCreatingNewBranch = (state) => state.commitAction === consts.COMMIT_TO_NEW_BRANCH;
export const shouldHideNewMrOption = (_state, getters, _rootState, rootGetters) =>
!getters.isCreatingNewBranch &&
diff --git a/app/assets/javascripts/ide/stores/modules/editor/setup.js b/app/assets/javascripts/ide/stores/modules/editor/setup.js
index c5a613c6baa..9f3163aa6f5 100644
--- a/app/assets/javascripts/ide/stores/modules/editor/setup.js
+++ b/app/assets/javascripts/ide/stores/modules/editor/setup.js
@@ -1,18 +1,23 @@
import eventHub from '~/ide/eventhub';
import { commitActionTypes } from '~/ide/constants';
-const removeUnusedFileEditors = store => {
+const removeUnusedFileEditors = (store) => {
Object.keys(store.state.editor.fileEditors)
- .filter(path => !store.state.entries[path])
- .forEach(path => store.dispatch('editor/removeFileEditor', path));
+ .filter((path) => !store.state.entries[path])
+ .forEach((path) => store.dispatch('editor/removeFileEditor', path));
};
-export const setupFileEditorsSync = store => {
+export const setupFileEditorsSync = (store) => {
eventHub.$on('ide.files.change', ({ type, ...payload } = {}) => {
+ // Do nothing on file update because the file tree itself hasn't changed.
+ if (type === commitActionTypes.update) {
+ return;
+ }
+
if (type === commitActionTypes.move) {
store.dispatch('editor/renameFileEditor', payload);
} else {
- // The files have changed, but the specific change is not known.
+ // The file tree has changed, but the specific change is not known.
removeUnusedFileEditors(store);
}
});
diff --git a/app/assets/javascripts/ide/stores/modules/file_templates/actions.js b/app/assets/javascripts/ide/stores/modules/file_templates/actions.js
index 6b2c929cd44..6800f824da0 100644
--- a/app/assets/javascripts/ide/stores/modules/file_templates/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/file_templates/actions.js
@@ -68,7 +68,7 @@ export const receiveTemplateError = ({ dispatch }, template) => {
'setErrorMessage',
{
text: __('Error loading template.'),
- action: payload =>
+ action: (payload) =>
dispatch('fetchTemplateTypes', payload).then(() =>
dispatch('setErrorMessage', null, { root: true }),
),
diff --git a/app/assets/javascripts/ide/stores/modules/file_templates/getters.js b/app/assets/javascripts/ide/stores/modules/file_templates/getters.js
index 4a407aea557..0613fe9b12b 100644
--- a/app/assets/javascripts/ide/stores/modules/file_templates/getters.js
+++ b/app/assets/javascripts/ide/stores/modules/file_templates/getters.js
@@ -24,6 +24,6 @@ export const templateTypes = () => [
},
];
-export const showFileTemplatesBar = (_, getters, rootState) => name =>
- getters.templateTypes.find(t => t.name === name) &&
+export const showFileTemplatesBar = (_, getters, rootState) => (name) =>
+ getters.templateTypes.find((t) => t.name === name) &&
rootState.currentActivityView === leftSidebarViews.edit.name;
diff --git a/app/assets/javascripts/ide/stores/modules/merge_requests/actions.js b/app/assets/javascripts/ide/stores/modules/merge_requests/actions.js
index 6a1a0de033e..299f7a883d2 100644
--- a/app/assets/javascripts/ide/stores/modules/merge_requests/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/merge_requests/actions.js
@@ -9,7 +9,7 @@ export const receiveMergeRequestsError = ({ commit, dispatch }, { type, search }
'setErrorMessage',
{
text: __('Error loading merge requests.'),
- action: payload =>
+ action: (payload) =>
dispatch('fetchMergeRequests', payload).then(() =>
dispatch('setErrorMessage', null, { root: true }),
),
diff --git a/app/assets/javascripts/ide/stores/modules/merge_requests/mutations.js b/app/assets/javascripts/ide/stores/modules/merge_requests/mutations.js
index 7576b2477d1..eae64ad80c3 100644
--- a/app/assets/javascripts/ide/stores/modules/merge_requests/mutations.js
+++ b/app/assets/javascripts/ide/stores/modules/merge_requests/mutations.js
@@ -9,7 +9,7 @@ export default {
},
[types.RECEIVE_MERGE_REQUESTS_SUCCESS](state, data) {
state.isLoading = false;
- state.mergeRequests = data.map(mergeRequest => ({
+ state.mergeRequests = data.map((mergeRequest) => ({
id: mergeRequest.id,
iid: mergeRequest.iid,
title: mergeRequest.title,
diff --git a/app/assets/javascripts/ide/stores/modules/pane/getters.js b/app/assets/javascripts/ide/stores/modules/pane/getters.js
index ce597329df1..66d23c8ebdc 100644
--- a/app/assets/javascripts/ide/stores/modules/pane/getters.js
+++ b/app/assets/javascripts/ide/stores/modules/pane/getters.js
@@ -1,2 +1,2 @@
-export const isAliveView = state => view =>
+export const isAliveView = (state) => (view) =>
state.keepAliveViews[view] || (state.isOpen && state.currentView === view);
diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/actions.js b/app/assets/javascripts/ide/stores/modules/pipelines/actions.js
index 99bd08ee876..2c2034d76d0 100644
--- a/app/assets/javascripts/ide/stores/modules/pipelines/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/pipelines/actions.js
@@ -47,7 +47,7 @@ export const receiveLatestPipelineSuccess = ({ rootGetters, commit }, { pipeline
if (pipelines && pipelines.length) {
const lastCommitHash = rootGetters.lastCommit && rootGetters.lastCommit.id;
- lastCommitPipeline = pipelines.find(pipeline => pipeline.commit.id === lastCommitHash);
+ lastCommitPipeline = pipelines.find((pipeline) => pipeline.commit.id === lastCommitHash);
}
commit(types.RECEIVE_LASTEST_PIPELINE_SUCCESS, lastCommitPipeline);
@@ -63,7 +63,7 @@ export const fetchLatestPipeline = ({ dispatch, rootGetters }) => {
method: 'lastCommitPipelines',
data: { getters: rootGetters },
successCallback: ({ data }) => dispatch('receiveLatestPipelineSuccess', data),
- errorCallback: err => dispatch('receiveLatestPipelineError', err),
+ errorCallback: (err) => dispatch('receiveLatestPipelineError', err),
});
if (!Visibility.hidden()) {
@@ -85,7 +85,7 @@ export const receiveJobsError = ({ commit, dispatch }, stage) => {
'setErrorMessage',
{
text: __('An error occurred while loading the pipelines jobs.'),
- action: payload =>
+ action: (payload) =>
dispatch('fetchJobs', payload).then(() =>
dispatch('setErrorMessage', null, { root: true }),
),
diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/getters.js b/app/assets/javascripts/ide/stores/modules/pipelines/getters.js
index eb3cc027494..051159a0fd5 100644
--- a/app/assets/javascripts/ide/stores/modules/pipelines/getters.js
+++ b/app/assets/javascripts/ide/stores/modules/pipelines/getters.js
@@ -1,22 +1,23 @@
import { states } from './constants';
-export const hasLatestPipeline = state => !state.isLoadingPipeline && Boolean(state.latestPipeline);
+export const hasLatestPipeline = (state) =>
+ !state.isLoadingPipeline && Boolean(state.latestPipeline);
-export const pipelineFailed = state =>
+export const pipelineFailed = (state) =>
state.latestPipeline && state.latestPipeline.details.status.text === states.failed;
-export const failedStages = state =>
+export const failedStages = (state) =>
state.stages
- .filter(stage => stage.status.text.toLowerCase() === states.failed)
- .map(stage => ({
+ .filter((stage) => stage.status.text.toLowerCase() === states.failed)
+ .map((stage) => ({
...stage,
- jobs: stage.jobs.filter(job => job.status.text.toLowerCase() === states.failed),
+ jobs: stage.jobs.filter((job) => job.status.text.toLowerCase() === states.failed),
}));
-export const failedJobsCount = state =>
+export const failedJobsCount = (state) =>
state.stages.reduce(
- (acc, stage) => acc + stage.jobs.filter(j => j.status.text === states.failed).length,
+ (acc, stage) => acc + stage.jobs.filter((j) => j.status.text === states.failed).length,
0,
);
-export const jobsCount = state => state.stages.reduce((acc, stage) => acc + stage.jobs.length, 0);
+export const jobsCount = (state) => state.stages.reduce((acc, stage) => acc + stage.jobs.length, 0);
diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/mutations.js b/app/assets/javascripts/ide/stores/modules/pipelines/mutations.js
index 3a3cb4a7cb2..09006df7e94 100644
--- a/app/assets/javascripts/ide/stores/modules/pipelines/mutations.js
+++ b/app/assets/javascripts/ide/stores/modules/pipelines/mutations.js
@@ -23,7 +23,7 @@ export default {
yamlError: pipeline.yaml_errors,
};
state.stages = pipeline.details.stages.map((stage, i) => {
- const foundStage = state.stages.find(s => s.id === i);
+ const foundStage = state.stages.find((s) => s.id === i);
return {
id: i,
dropdownPath: stage.dropdown_path,
@@ -39,26 +39,26 @@ export default {
}
},
[types.REQUEST_JOBS](state, id) {
- state.stages = state.stages.map(stage => ({
+ state.stages = state.stages.map((stage) => ({
...stage,
isLoading: stage.id === id ? true : stage.isLoading,
}));
},
[types.RECEIVE_JOBS_ERROR](state, id) {
- state.stages = state.stages.map(stage => ({
+ state.stages = state.stages.map((stage) => ({
...stage,
isLoading: stage.id === id ? false : stage.isLoading,
}));
},
[types.RECEIVE_JOBS_SUCCESS](state, { id, data }) {
- state.stages = state.stages.map(stage => ({
+ state.stages = state.stages.map((stage) => ({
...stage,
isLoading: stage.id === id ? false : stage.isLoading,
jobs: stage.id === id ? data.latest_statuses.map(normalizeJob) : stage.jobs,
}));
},
[types.TOGGLE_STAGE_COLLAPSE](state, id) {
- state.stages = state.stages.map(stage => ({
+ state.stages = state.stages.map((stage) => ({
...stage,
isCollapsed: stage.id === id ? !stage.isCollapsed : stage.isCollapsed,
}));
diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/utils.js b/app/assets/javascripts/ide/stores/modules/pipelines/utils.js
index 95716e0a0c6..ded00196ab7 100644
--- a/app/assets/javascripts/ide/stores/modules/pipelines/utils.js
+++ b/app/assets/javascripts/ide/stores/modules/pipelines/utils.js
@@ -1,4 +1,4 @@
-export const normalizeJob = job => ({
+export const normalizeJob = (job) => ({
id: job.id,
name: job.name,
status: job.status,
diff --git a/app/assets/javascripts/ide/stores/modules/terminal/actions/checks.js b/app/assets/javascripts/ide/stores/modules/terminal/actions/checks.js
index 43b6650b241..b2c1ddd877c 100644
--- a/app/assets/javascripts/ide/stores/modules/terminal/actions/checks.js
+++ b/app/assets/javascripts/ide/stores/modules/terminal/actions/checks.js
@@ -36,7 +36,7 @@ export const fetchConfigCheck = ({ dispatch, rootState, rootGetters }) => {
.then(() => {
dispatch('receiveConfigCheckSuccess');
})
- .catch(e => {
+ .catch((e) => {
dispatch('receiveConfigCheckError', e);
});
};
@@ -92,7 +92,7 @@ export const fetchRunnersCheck = ({ dispatch, rootGetters }, options = {}) => {
.then(({ data }) => {
dispatch('receiveRunnersCheckSuccess', data);
})
- .catch(e => {
+ .catch((e) => {
dispatch('receiveRunnersCheckError', e);
});
};
diff --git a/app/assets/javascripts/ide/stores/modules/terminal/actions/session_controls.js b/app/assets/javascripts/ide/stores/modules/terminal/actions/session_controls.js
index f20f7fc9cd6..aa460859b4c 100644
--- a/app/assets/javascripts/ide/stores/modules/terminal/actions/session_controls.js
+++ b/app/assets/javascripts/ide/stores/modules/terminal/actions/session_controls.js
@@ -45,7 +45,7 @@ export const startSession = ({ state, dispatch, rootGetters, rootState }) => {
.then(({ data }) => {
dispatch('receiveStartSessionSuccess', data);
})
- .catch(error => {
+ .catch((error) => {
dispatch('receiveStartSessionError', error);
});
};
@@ -73,7 +73,7 @@ export const stopSession = ({ state, dispatch }) => {
.then(() => {
dispatch('receiveStopSessionSuccess');
})
- .catch(err => {
+ .catch((err) => {
dispatch('receiveStopSessionError', err);
});
};
@@ -103,7 +103,7 @@ export const restartSession = ({ state, dispatch, rootState }) => {
.then(({ data }) => {
dispatch('receiveStartSessionSuccess', data);
})
- .catch(error => {
+ .catch((error) => {
const responseStatus = error.response && error.response.status;
// We may have removed the build, in this case we'll just create a new session
if (
diff --git a/app/assets/javascripts/ide/stores/modules/terminal/actions/session_status.js b/app/assets/javascripts/ide/stores/modules/terminal/actions/session_status.js
index d715d555aa9..3ab1817e662 100644
--- a/app/assets/javascripts/ide/stores/modules/terminal/actions/session_status.js
+++ b/app/assets/javascripts/ide/stores/modules/terminal/actions/session_status.js
@@ -58,7 +58,7 @@ export const fetchSessionStatus = ({ dispatch, state }) => {
.then(({ data }) => {
dispatch('receiveSessionStatusSuccess', data);
})
- .catch(error => {
+ .catch((error) => {
dispatch('receiveSessionStatusError', error);
});
};
diff --git a/app/assets/javascripts/ide/stores/modules/terminal/getters.js b/app/assets/javascripts/ide/stores/modules/terminal/getters.js
index b29d391845d..fb9a1a2fa39 100644
--- a/app/assets/javascripts/ide/stores/modules/terminal/getters.js
+++ b/app/assets/javascripts/ide/stores/modules/terminal/getters.js
@@ -1,11 +1,11 @@
-export const allCheck = state => {
+export const allCheck = (state) => {
const checks = Object.values(state.checks);
- if (checks.some(check => check.isLoading)) {
+ if (checks.some((check) => check.isLoading)) {
return { isLoading: true };
}
- const invalidCheck = checks.find(check => !check.isValid);
+ const invalidCheck = checks.find((check) => !check.isValid);
const isValid = !invalidCheck;
const message = !invalidCheck ? '' : invalidCheck.message;
diff --git a/app/assets/javascripts/ide/stores/modules/terminal/messages.js b/app/assets/javascripts/ide/stores/modules/terminal/messages.js
index bf35ce0f0bc..967ba80cd2c 100644
--- a/app/assets/javascripts/ide/stores/modules/terminal/messages.js
+++ b/app/assets/javascripts/ide/stores/modules/terminal/messages.js
@@ -46,7 +46,7 @@ export const configCheckError = (status, helpUrl) => {
return UNEXPECTED_ERROR_CONFIG;
};
-export const runnersCheckEmpty = helpUrl =>
+export const runnersCheckEmpty = (helpUrl) =>
sprintf(
EMPTY_RUNNERS,
{
diff --git a/app/assets/javascripts/ide/stores/modules/terminal/utils.js b/app/assets/javascripts/ide/stores/modules/terminal/utils.js
index c30136b5277..1f4bca9f50a 100644
--- a/app/assets/javascripts/ide/stores/modules/terminal/utils.js
+++ b/app/assets/javascripts/ide/stores/modules/terminal/utils.js
@@ -1,5 +1,5 @@
import { STARTING, PENDING, RUNNING } from './constants';
-export const isStartingStatus = status => status === STARTING || status === PENDING;
-export const isRunningStatus = status => status === RUNNING;
-export const isEndingStatus = status => !isStartingStatus(status) && !isRunningStatus(status);
+export const isStartingStatus = (status) => status === STARTING || status === PENDING;
+export const isRunningStatus = (status) => status === RUNNING;
+export const isEndingStatus = (status) => !isStartingStatus(status) && !isRunningStatus(status);
diff --git a/app/assets/javascripts/ide/stores/modules/terminal_sync/actions.js b/app/assets/javascripts/ide/stores/modules/terminal_sync/actions.js
index 2fee6b4e974..006800f58c2 100644
--- a/app/assets/javascripts/ide/stores/modules/terminal_sync/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/terminal_sync/actions.js
@@ -9,7 +9,7 @@ export const upload = ({ rootState, commit }) => {
.then(() => {
commit(types.SET_SUCCESS);
})
- .catch(err => {
+ .catch((err) => {
commit(types.SET_ERROR, err);
});
};
@@ -34,7 +34,7 @@ export const start = ({ rootState, commit }) => {
.then(() => {
commit(types.SET_SUCCESS);
})
- .catch(err => {
+ .catch((err) => {
commit(types.SET_ERROR, err);
throw err;
});
diff --git a/app/assets/javascripts/ide/stores/mutations.js b/app/assets/javascripts/ide/stores/mutations.js
index 460d3ced381..6ed6798a5b6 100644
--- a/app/assets/javascripts/ide/stores/mutations.js
+++ b/app/assets/javascripts/ide/stores/mutations.js
@@ -61,7 +61,7 @@ export default {
});
} else {
const tree = entry.tree.filter(
- f => foundEntry.tree.find(e => e.path === f.path) === undefined,
+ (f) => foundEntry.tree.find((e) => e.path === f.path) === undefined,
);
Object.assign(foundEntry, {
tree: sortTree(foundEntry.tree.concat(tree)),
@@ -72,7 +72,7 @@ export default {
}, []);
const currentTree = state.trees[`${state.currentProjectId}/${state.currentBranchId}`];
- const foundEntry = currentTree.tree.find(e => e.path === data.treeList[0].path);
+ const foundEntry = currentTree.tree.find((e) => e.path === data.treeList[0].path);
if (!foundEntry) {
Object.assign(currentTree, {
@@ -125,7 +125,7 @@ export default {
});
},
[types.UPDATE_FILE_AFTER_COMMIT](state, { file, lastCommit }) {
- const changedFile = state.changedFiles.find(f => f.path === file.path);
+ const changedFile = state.changedFiles.find((f) => f.path === file.path);
const { prevPath } = file;
Object.assign(state.entries[file.path], {
@@ -172,7 +172,7 @@ export default {
entry.deleted = true;
if (parent) {
- parent.tree = parent.tree.filter(f => f.path !== entry.path);
+ parent.tree = parent.tree.filter((f) => f.path !== entry.path);
}
if (entry.type === 'blob') {
@@ -181,8 +181,8 @@ export default {
// changed and staged. Otherwise, we'd need to somehow evaluate the difference between
// changed and HEAD.
// https://gitlab.com/gitlab-org/create-stage/-/issues/12669
- state.changedFiles = state.changedFiles.filter(f => f.path !== path);
- state.stagedFiles = state.stagedFiles.filter(f => f.path !== path);
+ state.changedFiles = state.changedFiles.filter((f) => f.path !== path);
+ state.stagedFiles = state.stagedFiles.filter((f) => f.path !== path);
} else {
state.changedFiles = state.changedFiles.concat(entry);
}
diff --git a/app/assets/javascripts/ide/stores/mutations/file.js b/app/assets/javascripts/ide/stores/mutations/file.js
index 61a55d45128..4446971d5d6 100644
--- a/app/assets/javascripts/ide/stores/mutations/file.js
+++ b/app/assets/javascripts/ide/stores/mutations/file.js
@@ -12,7 +12,7 @@ export default {
if (active && !state.entries[path].pending) {
Object.assign(state, {
- openFiles: state.openFiles.map(f =>
+ openFiles: state.openFiles.map((f) =>
Object.assign(f, { active: f.pending ? false : f.active }),
),
});
@@ -28,21 +28,21 @@ export default {
if (entry.opened) {
Object.assign(state, {
- openFiles: state.openFiles.filter(f => f.path !== path).concat(state.entries[path]),
+ openFiles: state.openFiles.filter((f) => f.path !== path).concat(state.entries[path]),
});
} else {
Object.assign(state, {
- openFiles: state.openFiles.filter(f => f.key !== entry.key),
+ openFiles: state.openFiles.filter((f) => f.key !== entry.key),
});
}
},
[types.SET_FILE_DATA](state, { data, file }) {
const stateEntry = state.entries[file.path];
- const stagedFile = state.stagedFiles.find(f => f.path === file.path);
- const openFile = state.openFiles.find(f => f.path === file.path);
- const changedFile = state.changedFiles.find(f => f.path === file.path);
+ const stagedFile = state.stagedFiles.find((f) => f.path === file.path);
+ const openFile = state.openFiles.find((f) => f.path === file.path);
+ const changedFile = state.changedFiles.find((f) => f.path === file.path);
- [stateEntry, stagedFile, openFile, changedFile].forEach(f => {
+ [stateEntry, stagedFile, openFile, changedFile].forEach((f) => {
if (f) {
Object.assign(
f,
@@ -57,10 +57,10 @@ export default {
},
[types.SET_FILE_RAW_DATA](state, { file, raw, fileDeletedAndReadded = false }) {
const openPendingFile = state.openFiles.find(
- f =>
+ (f) =>
f.path === file.path && f.pending && !(f.tempFile && !f.prevPath && !fileDeletedAndReadded),
);
- const stagedFile = state.stagedFiles.find(f => f.path === file.path);
+ const stagedFile = state.stagedFiles.find((f) => f.path === file.path);
if (file.tempFile && file.content === '' && !fileDeletedAndReadded) {
Object.assign(state.entries[file.path], { content: raw });
@@ -86,7 +86,7 @@ export default {
});
},
[types.UPDATE_FILE_CONTENT](state, { path, content }) {
- const stagedFile = state.stagedFiles.find(f => f.path === path);
+ const stagedFile = state.stagedFiles.find((f) => f.path === path);
const rawContent = stagedFile ? stagedFile.content : state.entries[path].raw;
const changed = content !== rawContent;
@@ -112,7 +112,7 @@ export default {
});
},
[types.DISCARD_FILE_CHANGES](state, path) {
- const stagedFile = state.stagedFiles.find(f => f.path === path);
+ const stagedFile = state.stagedFiles.find((f) => f.path === path);
const entry = state.entries[path];
const { deleted } = entry;
@@ -137,14 +137,14 @@ export default {
},
[types.REMOVE_FILE_FROM_CHANGED](state, path) {
Object.assign(state, {
- changedFiles: state.changedFiles.filter(f => f.path !== path),
+ changedFiles: state.changedFiles.filter((f) => f.path !== path),
});
},
[types.STAGE_CHANGE](state, { path, diffInfo }) {
- const stagedFile = state.stagedFiles.find(f => f.path === path);
+ const stagedFile = state.stagedFiles.find((f) => f.path === path);
Object.assign(state, {
- changedFiles: state.changedFiles.filter(f => f.path !== path),
+ changedFiles: state.changedFiles.filter((f) => f.path !== path),
entries: Object.assign(state.entries, {
[path]: Object.assign(state.entries[path], {
staged: diffInfo.exists,
@@ -162,12 +162,12 @@ export default {
}
if (!diffInfo.exists) {
- state.stagedFiles = state.stagedFiles.filter(f => f.path !== path);
+ state.stagedFiles = state.stagedFiles.filter((f) => f.path !== path);
}
},
[types.UNSTAGE_CHANGE](state, { path, diffInfo }) {
- const changedFile = state.changedFiles.find(f => f.path === path);
- const stagedFile = state.stagedFiles.find(f => f.path === path);
+ const changedFile = state.changedFiles.find((f) => f.path === path);
+ const stagedFile = state.stagedFiles.find((f) => f.path === path);
if (!changedFile && stagedFile) {
Object.assign(state.entries[path], {
@@ -182,11 +182,11 @@ export default {
}
if (!diffInfo.exists) {
- state.changedFiles = state.changedFiles.filter(f => f.path !== path);
+ state.changedFiles = state.changedFiles.filter((f) => f.path !== path);
}
Object.assign(state, {
- stagedFiles: state.stagedFiles.filter(f => f.path !== path),
+ stagedFiles: state.stagedFiles.filter((f) => f.path !== path),
entries: Object.assign(state.entries, {
[path]: Object.assign(state.entries[path], {
staged: false,
@@ -206,7 +206,7 @@ export default {
state.entries[file.path].opened = false;
state.entries[file.path].active = false;
state.entries[file.path].lastOpenedAt = new Date().getTime();
- state.openFiles.forEach(f =>
+ state.openFiles.forEach((f) =>
Object.assign(f, {
opened: false,
active: false,
@@ -224,13 +224,13 @@ export default {
},
[types.REMOVE_PENDING_TAB](state, file) {
Object.assign(state, {
- openFiles: state.openFiles.filter(f => f.key !== file.key),
+ openFiles: state.openFiles.filter((f) => f.key !== file.key),
});
},
[types.REMOVE_FILE_FROM_STAGED_AND_CHANGED](state, file) {
Object.assign(state, {
- changedFiles: state.changedFiles.filter(f => f.key !== file.key),
- stagedFiles: state.stagedFiles.filter(f => f.key !== file.key),
+ changedFiles: state.changedFiles.filter((f) => f.key !== file.key),
+ stagedFiles: state.stagedFiles.filter((f) => f.key !== file.key),
});
Object.assign(state.entries[file.path], {
diff --git a/app/assets/javascripts/ide/stores/mutations/tree.js b/app/assets/javascripts/ide/stores/mutations/tree.js
index cce43a99bd9..c38002bd4e0 100644
--- a/app/assets/javascripts/ide/stores/mutations/tree.js
+++ b/app/assets/javascripts/ide/stores/mutations/tree.js
@@ -45,7 +45,7 @@ export default {
? state.entries[entry.parentPath]
: state.trees[`${state.currentProjectId}/${state.currentBranchId}`];
- if (!parent.tree.find(f => f.path === path)) {
+ if (!parent.tree.find((f) => f.path === path)) {
parent.tree = sortTree(parent.tree.concat(entry));
}
},
diff --git a/app/assets/javascripts/ide/stores/plugins/terminal.js b/app/assets/javascripts/ide/stores/plugins/terminal.js
index 66539c7bd4f..94139d5bdf0 100644
--- a/app/assets/javascripts/ide/stores/plugins/terminal.js
+++ b/app/assets/javascripts/ide/stores/plugins/terminal.js
@@ -11,7 +11,7 @@ function getPathsFromData(el) {
}
export default function createTerminalPlugin(el) {
- return store => {
+ return (store) => {
store.registerModule('terminal', terminalModule());
store.dispatch('terminal/setPaths', getPathsFromData(el));
diff --git a/app/assets/javascripts/ide/stores/plugins/terminal_sync.js b/app/assets/javascripts/ide/stores/plugins/terminal_sync.js
index c60bba4293a..d925a5f7567 100644
--- a/app/assets/javascripts/ide/stores/plugins/terminal_sync.js
+++ b/app/assets/javascripts/ide/stores/plugins/terminal_sync.js
@@ -1,5 +1,6 @@
import { debounce } from 'lodash';
import eventHub from '~/ide/eventhub';
+import { commitActionTypes } from '~/ide/constants';
import terminalSyncModule from '../modules/terminal_sync';
import { isEndingStatus, isRunningStatus } from '../modules/terminal/utils';
@@ -12,23 +13,32 @@ const UPLOAD_DEBOUNCE = 200;
* - Listens for file change event to control upload.
*/
export default function createMirrorPlugin() {
- return store => {
+ return (store) => {
store.registerModule('terminalSync', terminalSyncModule());
const upload = debounce(() => {
store.dispatch(`terminalSync/upload`);
}, UPLOAD_DEBOUNCE);
+ const onFilesChange = (payload) => {
+ // Do nothing on a file update since we only want to trigger manually on "save".
+ if (payload?.type === commitActionTypes.update) {
+ return;
+ }
+
+ upload();
+ };
+
const stop = () => {
store.dispatch(`terminalSync/stop`);
- eventHub.$off('ide.files.change', upload);
+ eventHub.$off('ide.files.change', onFilesChange);
};
const start = () => {
store
.dispatch(`terminalSync/start`)
.then(() => {
- eventHub.$on('ide.files.change', upload);
+ eventHub.$on('ide.files.change', onFilesChange);
})
.catch(() => {
// error is handled in store
@@ -36,8 +46,8 @@ export default function createMirrorPlugin() {
};
store.watch(
- x => x.terminal && x.terminal.session && x.terminal.session.status,
- val => {
+ (x) => x.terminal && x.terminal.session && x.terminal.session.status,
+ (val) => {
if (isRunningStatus(val)) {
start();
} else if (isEndingStatus(val)) {
diff --git a/app/assets/javascripts/ide/stores/utils.js b/app/assets/javascripts/ide/stores/utils.js
index 96f3caf1e98..04eacf271b8 100644
--- a/app/assets/javascripts/ide/stores/utils.js
+++ b/app/assets/javascripts/ide/stores/utils.js
@@ -31,9 +31,10 @@ export const dataStructure = () => ({
mrChange: null,
deleted: false,
prevPath: undefined,
+ mimeType: '',
});
-export const decorateData = entity => {
+export const decorateData = (entity) => {
const {
id,
type,
@@ -47,6 +48,7 @@ export const decorateData = entity => {
rawPath = '',
file_lock,
parentPath = '',
+ mimeType = '',
} = entity;
return Object.assign(dataStructure(), {
@@ -63,10 +65,11 @@ export const decorateData = entity => {
rawPath,
file_lock,
parentPath,
+ mimeType,
});
};
-export const setPageTitle = title => {
+export const setPageTitle = (title) => {
document.title = title;
};
@@ -75,7 +78,7 @@ export const setPageTitleForFile = (state, file) => {
setPageTitle(title);
};
-export const commitActionForFile = file => {
+export const commitActionForFile = (file) => {
if (file.prevPath) {
return commitActionTypes.move;
} else if (file.deleted) {
@@ -87,7 +90,7 @@ export const commitActionForFile = file => {
return commitActionTypes.update;
};
-export const getCommitFiles = stagedFiles =>
+export const getCommitFiles = (stagedFiles) =>
stagedFiles.reduce((acc, file) => {
if (file.type === 'tree') return acc;
@@ -106,7 +109,7 @@ export const createCommitPayload = ({
}) => ({
branch,
commit_message: state.commitMessage || getters.preBuiltCommitMessage,
- actions: getCommitFiles(rootState.stagedFiles).map(f => {
+ actions: getCommitFiles(rootState.stagedFiles).map((f) => {
const isBlob = isBlobUrl(f.rawPath);
const content = isBlob ? btoa(f.content) : f.content;
@@ -136,9 +139,9 @@ const sortTreesByTypeAndName = (a, b) => {
return 0;
};
-export const sortTree = sortedTree =>
+export const sortTree = (sortedTree) =>
sortedTree
- .map(entity =>
+ .map((entity) =>
Object.assign(entity, {
tree: entity.tree.length ? sortTree(entity.tree) : [],
}),
@@ -148,7 +151,7 @@ export const sortTree = sortedTree =>
export const filePathMatches = (filePath, path) => filePath.indexOf(`${path}/`) === 0;
export const getChangesCountForFiles = (files, path) =>
- files.filter(f => filePathMatches(f.path, path)).length;
+ files.filter((f) => filePathMatches(f.path, path)).length;
export const mergeTrees = (fromTree, toTree) => {
if (!fromTree || !fromTree.length) {
@@ -159,7 +162,7 @@ export const mergeTrees = (fromTree, toTree) => {
if (!n) {
return t;
}
- const existingTreeNode = t.find(el => el.path === n.path);
+ const existingTreeNode = t.find((el) => el.path === n.path);
if (existingTreeNode && n.tree.length > 0) {
existingTreeNode.opened = true;
@@ -180,7 +183,7 @@ export const mergeTrees = (fromTree, toTree) => {
export const swapInStateArray = (state, arr, key, entryPath) =>
Object.assign(state, {
- [arr]: state[arr].map(f => (f.key === key ? state.entries[entryPath] : f)),
+ [arr]: state[arr].map((f) => (f.key === key ? state.entries[entryPath] : f)),
});
export const getEntryOrRoot = (state, path) =>
@@ -213,12 +216,12 @@ export const removeFromParentTree = (state, oldKey, parentPath) => {
};
export const updateFileCollections = (state, key, entryPath) => {
- ['openFiles', 'changedFiles', 'stagedFiles'].forEach(fileCollection => {
+ ['openFiles', 'changedFiles', 'stagedFiles'].forEach((fileCollection) => {
swapInStateArray(state, fileCollection, key, entryPath);
});
};
-export const cleanTrailingSlash = path => path.replace(/\/$/, '');
+export const cleanTrailingSlash = (path) => path.replace(/\/$/, '');
export const pathsAreEqual = (a, b) => {
const cleanA = a ? cleanTrailingSlash(a) : '';
@@ -251,12 +254,7 @@ export function extractMarkdownImagesFromEntries(mdFile, entries) {
const imageContent = entries[imagePath]?.content || entries[imagePath]?.raw;
if (!isAbsolute(path) && imageContent) {
- const ext = path.includes('.')
- ? path
- .split('.')
- .pop()
- .trim()
- : 'jpeg';
+ const ext = path.includes('.') ? path.split('.').pop().trim() : 'jpeg';
const src = `data:image/${ext};base64,${imageContent}`;
i += 1;
const key = `{{${prefix}${i}}}`;
diff --git a/app/assets/javascripts/ide/sync_router_and_store.js b/app/assets/javascripts/ide/sync_router_and_store.js
index b33bcbb94ea..d73ac93dc1d 100644
--- a/app/assets/javascripts/ide/sync_router_and_store.js
+++ b/app/assets/javascripts/ide/sync_router_and_store.js
@@ -21,8 +21,8 @@ export const syncRouterAndStore = (router, store) => {
// sync store to router
disposables.push(
store.watch(
- state => state.router.fullPath,
- fullPath => {
+ (state) => state.router.fullPath,
+ (fullPath) => {
if (currentPath === fullPath) {
return;
}
@@ -36,7 +36,7 @@ export const syncRouterAndStore = (router, store) => {
// sync router to store
disposables.push(
- router.afterEach(to => {
+ router.afterEach((to) => {
if (currentPath === to.fullPath) {
return;
}
@@ -47,7 +47,7 @@ export const syncRouterAndStore = (router, store) => {
);
const unsync = () => {
- disposables.forEach(fn => fn());
+ disposables.forEach((fn) => fn());
};
return unsync;
diff --git a/app/assets/javascripts/ide/utils.js b/app/assets/javascripts/ide/utils.js
index 43276f32322..8eb2d17b876 100644
--- a/app/assets/javascripts/ide/utils.js
+++ b/app/assets/javascripts/ide/utils.js
@@ -3,17 +3,17 @@ import { flatten, isString } from 'lodash';
import { SIDE_LEFT, SIDE_RIGHT } from './constants';
import { performanceMarkAndMeasure } from '~/performance/utils';
-const toLowerCase = x => x.toLowerCase();
+const toLowerCase = (x) => x.toLowerCase();
const monacoLanguages = languages.getLanguages();
const monacoExtensions = new Set(
- flatten(monacoLanguages.map(lang => lang.extensions?.map(toLowerCase) || [])),
+ flatten(monacoLanguages.map((lang) => lang.extensions?.map(toLowerCase) || [])),
);
const monacoMimetypes = new Set(
- flatten(monacoLanguages.map(lang => lang.mimetypes?.map(toLowerCase) || [])),
+ flatten(monacoLanguages.map((lang) => lang.mimetypes?.map(toLowerCase) || [])),
);
const monacoFilenames = new Set(
- flatten(monacoLanguages.map(lang => lang.filenames?.map(toLowerCase) || [])),
+ flatten(monacoLanguages.map((lang) => lang.filenames?.map(toLowerCase) || [])),
);
const KNOWN_TYPES = [
@@ -44,7 +44,7 @@ const KNOWN_TYPES = [
];
export function isTextFile({ name, raw, content, mimeType = '' }) {
- const knownType = KNOWN_TYPES.find(type => type.isMatch(mimeType, name));
+ const knownType = KNOWN_TYPES.find((type) => type.isMatch(mimeType, name));
if (knownType) return knownType.isText;
// does the string contain ascii characters only (ranges from space to tilde, tabs and new lines)
@@ -56,20 +56,20 @@ export function isTextFile({ name, raw, content, mimeType = '' }) {
return isString(fileContents) && (fileContents === '' || asciiRegex.test(fileContents));
}
-export const createPathWithExt = p => {
+export const createPathWithExt = (p) => {
const ext = p.lastIndexOf('.') >= 0 ? p.substring(p.lastIndexOf('.') + 1) : '';
return `${p.substring(1, p.lastIndexOf('.') + 1 || p.length)}${ext || '.js'}`;
};
-export const trimPathComponents = path =>
+export const trimPathComponents = (path) =>
path
.split('/')
- .map(s => s.trim())
+ .map((s) => s.trim())
.join('/');
export function registerLanguages(def, ...defs) {
- defs.forEach(lang => registerLanguages(lang));
+ defs.forEach((lang) => registerLanguages(lang));
const languageId = def.id;
@@ -80,7 +80,7 @@ export function registerLanguages(def, ...defs) {
export function registerSchema(schema) {
const defaults = [languages.json.jsonDefaults, languages.yaml.yamlDefaults];
- defaults.forEach(d =>
+ defaults.forEach((d) =>
d.setDiagnosticsOptions({
validate: true,
enableSchemaRequest: true,
@@ -91,7 +91,7 @@ export function registerSchema(schema) {
);
}
-export const otherSide = side => (side === SIDE_RIGHT ? SIDE_LEFT : SIDE_RIGHT);
+export const otherSide = (side) => (side === SIDE_RIGHT ? SIDE_LEFT : SIDE_RIGHT);
export function trimTrailingWhitespace(content) {
return content.replace(/[^\S\r\n]+$/gm, '');
@@ -125,9 +125,9 @@ export function getPathParent(path) {
* @param {File} file
*/
export function readFileAsDataURL(file) {
- return new Promise(resolve => {
+ return new Promise((resolve) => {
const reader = new FileReader();
- reader.addEventListener('load', e => resolve(e.target.result), { once: true });
+ reader.addEventListener('load', (e) => resolve(e.target.result), { once: true });
reader.readAsDataURL(file);
});
}
@@ -154,12 +154,7 @@ export function getFileEOL(content = '') {
*/
export function addNumericSuffix(filename, randomize = false) {
return filename.replace(/([ _-]?)(\d*)(\..+?$|$)/, (_, before, number, after) => {
- const n = randomize
- ? Math.random()
- .toString()
- .substring(2, 7)
- .slice(-5)
- : Number(number) + 1;
+ const n = randomize ? Math.random().toString().substring(2, 7).slice(-5) : Number(number) + 1;
return `${before || '-'}${n}${after}`;
});
}