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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/ide')
-rw-r--r--app/assets/javascripts/ide/components/activity_bar.vue14
-rw-r--r--app/assets/javascripts/ide/components/branches/item.vue6
-rw-r--r--app/assets/javascripts/ide/components/branches/search_list.vue7
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/actions.vue1
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/form.vue46
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/list.vue9
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/list_collapsed.vue10
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/list_item.vue6
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/message_field.vue6
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/success_message.vue1
-rw-r--r--app/assets/javascripts/ide/components/error_message.vue1
-rw-r--r--app/assets/javascripts/ide/components/file_row_extra.vue6
-rw-r--r--app/assets/javascripts/ide/components/ide.vue3
-rw-r--r--app/assets/javascripts/ide/components/ide_file_row.vue12
-rw-r--r--app/assets/javascripts/ide/components/ide_review.vue4
-rw-r--r--app/assets/javascripts/ide/components/ide_side_bar.vue2
-rw-r--r--app/assets/javascripts/ide/components/ide_status_bar.vue7
-rw-r--r--app/assets/javascripts/ide/components/ide_status_list.vue7
-rw-r--r--app/assets/javascripts/ide/components/ide_tree.vue4
-rw-r--r--app/assets/javascripts/ide/components/ide_tree_list.vue2
-rw-r--r--app/assets/javascripts/ide/components/jobs/detail.vue15
-rw-r--r--app/assets/javascripts/ide/components/jobs/detail/description.vue14
-rw-r--r--app/assets/javascripts/ide/components/jobs/detail/scroll_button.vue6
-rw-r--r--app/assets/javascripts/ide/components/jobs/stage.vue7
-rw-r--r--app/assets/javascripts/ide/components/merge_requests/item.vue6
-rw-r--r--app/assets/javascripts/ide/components/merge_requests/list.vue9
-rw-r--r--app/assets/javascripts/ide/components/mr_file_icon.vue6
-rw-r--r--app/assets/javascripts/ide/components/nav_dropdown_button.vue8
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/button.vue6
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/index.vue6
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/modal.vue12
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/upload.vue3
-rw-r--r--app/assets/javascripts/ide/components/panes/collapsible_sidebar.vue2
-rw-r--r--app/assets/javascripts/ide/components/pipelines/list.vue12
-rw-r--r--app/assets/javascripts/ide/components/preview/navigator.vue11
-rw-r--r--app/assets/javascripts/ide/components/repo_editor.vue16
-rw-r--r--app/assets/javascripts/ide/components/repo_file_status_icon.vue6
-rw-r--r--app/assets/javascripts/ide/components/repo_tab.vue13
-rw-r--r--app/assets/javascripts/ide/components/repo_tabs.vue7
-rw-r--r--app/assets/javascripts/ide/components/shared/tokened_input.vue6
-rw-r--r--app/assets/javascripts/ide/components/terminal/empty_state.vue1
-rw-r--r--app/assets/javascripts/ide/components/terminal_sync/terminal_sync_status.vue7
-rw-r--r--app/assets/javascripts/ide/ide_router.js1
-rw-r--r--app/assets/javascripts/ide/lib/diff/diff.js2
-rw-r--r--app/assets/javascripts/ide/lib/editor.js7
-rw-r--r--app/assets/javascripts/ide/lib/editorconfig/parser.js1
-rw-r--r--app/assets/javascripts/ide/lib/errors.js39
-rw-r--r--app/assets/javascripts/ide/lib/files.js19
-rw-r--r--app/assets/javascripts/ide/lib/schemas/index.js4
-rw-r--r--app/assets/javascripts/ide/lib/schemas/json/index.js8
-rw-r--r--app/assets/javascripts/ide/lib/schemas/yaml/gitlab_ci.js4
-rw-r--r--app/assets/javascripts/ide/lib/schemas/yaml/index.js12
-rw-r--r--app/assets/javascripts/ide/services/gql.js1
-rw-r--r--app/assets/javascripts/ide/services/index.js6
-rw-r--r--app/assets/javascripts/ide/stores/actions.js22
-rw-r--r--app/assets/javascripts/ide/stores/actions/file.js14
-rw-r--r--app/assets/javascripts/ide/stores/actions/tree.js6
-rw-r--r--app/assets/javascripts/ide/stores/getters.js19
-rw-r--r--app/assets/javascripts/ide/stores/modules/commit/actions.js28
-rw-r--r--app/assets/javascripts/ide/stores/modules/commit/mutation_types.js3
-rw-r--r--app/assets/javascripts/ide/stores/modules/commit/mutations.js6
-rw-r--r--app/assets/javascripts/ide/stores/modules/commit/state.js1
-rw-r--r--app/assets/javascripts/ide/stores/modules/pane/getters.js1
-rw-r--r--app/assets/javascripts/ide/stores/modules/pipelines/actions.js22
-rw-r--r--app/assets/javascripts/ide/stores/modules/pipelines/constants.js1
-rw-r--r--app/assets/javascripts/ide/stores/modules/pipelines/mutation_types.js6
-rw-r--r--app/assets/javascripts/ide/stores/modules/pipelines/mutations.js6
-rw-r--r--app/assets/javascripts/ide/stores/modules/pipelines/utils.js1
-rw-r--r--app/assets/javascripts/ide/stores/modules/router/actions.js1
-rw-r--r--app/assets/javascripts/ide/stores/modules/router/mutation_types.js1
-rw-r--r--app/assets/javascripts/ide/stores/modules/terminal/getters.js1
-rw-r--r--app/assets/javascripts/ide/stores/mutations.js19
-rw-r--r--app/assets/javascripts/ide/stores/utils.js17
-rw-r--r--app/assets/javascripts/ide/sync_router_and_store.js1
-rw-r--r--app/assets/javascripts/ide/utils.js31
75 files changed, 324 insertions, 320 deletions
diff --git a/app/assets/javascripts/ide/components/activity_bar.vue b/app/assets/javascripts/ide/components/activity_bar.vue
index a65af55fcac..183816921c1 100644
--- a/app/assets/javascripts/ide/components/activity_bar.vue
+++ b/app/assets/javascripts/ide/components/activity_bar.vue
@@ -1,13 +1,13 @@
<script>
import $ from 'jquery';
import { mapActions, mapState } from 'vuex';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlIcon } from '@gitlab/ui';
import tooltip from '~/vue_shared/directives/tooltip';
import { leftSidebarViews } from '../constants';
export default {
components: {
- Icon,
+ GlIcon,
},
directives: {
tooltip,
@@ -44,11 +44,12 @@ export default {
:aria-label="s__('IDE|Edit')"
data-container="body"
data-placement="right"
+ data-qa-selector="edit_mode_tab"
type="button"
class="ide-sidebar-link js-ide-edit-mode"
@click.prevent="changedActivityView($event, $options.leftSidebarViews.edit.name)"
>
- <icon name="code" />
+ <gl-icon name="code" />
</button>
</li>
<li>
@@ -65,7 +66,7 @@ export default {
class="ide-sidebar-link js-ide-review-mode"
@click.prevent="changedActivityView($event, $options.leftSidebarViews.review.name)"
>
- <icon name="file-modified" />
+ <gl-icon name="file-modified" />
</button>
</li>
<li>
@@ -78,11 +79,12 @@ export default {
:aria-label="s__('IDE|Commit')"
data-container="body"
data-placement="right"
+ data-qa-selector="commit_mode_tab"
type="button"
- class="ide-sidebar-link js-ide-commit-mode qa-commit-mode-tab"
+ class="ide-sidebar-link js-ide-commit-mode"
@click.prevent="changedActivityView($event, $options.leftSidebarViews.commit.name)"
>
- <icon name="commit" />
+ <gl-icon name="commit" />
</button>
</li>
</ul>
diff --git a/app/assets/javascripts/ide/components/branches/item.vue b/app/assets/javascripts/ide/components/branches/item.vue
index 49744d573da..2fe435b92ab 100644
--- a/app/assets/javascripts/ide/components/branches/item.vue
+++ b/app/assets/javascripts/ide/components/branches/item.vue
@@ -1,11 +1,11 @@
<script>
/* eslint-disable @gitlab/vue-require-i18n-strings */
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlIcon } from '@gitlab/ui';
import Timeago from '~/vue_shared/components/time_ago_tooltip.vue';
export default {
components: {
- Icon,
+ GlIcon,
Timeago,
},
props: {
@@ -34,7 +34,7 @@ export default {
<template>
<a :href="branchHref" class="btn-link d-flex align-items-center">
<span class="d-flex gl-mr-3 ide-search-list-current-icon">
- <icon v-if="isActive" :size="18" name="mobile-issue-close" />
+ <gl-icon v-if="isActive" :size="18" name="mobile-issue-close" />
</span>
<span>
<strong> {{ item.name }} </strong>
diff --git a/app/assets/javascripts/ide/components/branches/search_list.vue b/app/assets/javascripts/ide/components/branches/search_list.vue
index dd2d726d525..c317fadb656 100644
--- a/app/assets/javascripts/ide/components/branches/search_list.vue
+++ b/app/assets/javascripts/ide/components/branches/search_list.vue
@@ -1,14 +1,13 @@
<script>
import { mapActions, mapState } from 'vuex';
import { debounce } from 'lodash';
-import { GlLoadingIcon } from '@gitlab/ui';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
import Item from './item.vue';
export default {
components: {
Item,
- Icon,
+ GlIcon,
GlLoadingIcon,
},
data() {
@@ -67,7 +66,7 @@ export default {
class="form-control dropdown-input-field"
@input="searchBranches"
/>
- <icon :size="18" name="search" class="ml-3 input-icon" />
+ <gl-icon :size="18" name="search" class="ml-3 input-icon" />
</label>
<div class="dropdown-content ide-merge-requests-dropdown-content d-flex">
<gl-loading-icon
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/actions.vue b/app/assets/javascripts/ide/components/commit_sidebar/actions.vue
index 407e4c57cd8..de4b0a34002 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/actions.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/actions.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { escape } from 'lodash';
import { mapState, mapGetters, createNamespacedHelpers } from 'vuex';
import { sprintf, s__ } from '~/locale';
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/form.vue b/app/assets/javascripts/ide/components/commit_sidebar/form.vue
index 9342ab87c1a..73c56514fce 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/form.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/form.vue
@@ -1,6 +1,6 @@
<script>
import { mapState, mapActions, mapGetters } from 'vuex';
-import { GlModal } from '@gitlab/ui';
+import { GlModal, GlSafeHtmlDirective } from '@gitlab/ui';
import { n__, __ } from '~/locale';
import LoadingButton from '~/vue_shared/components/loading_button.vue';
import CommitMessageField from './message_field.vue';
@@ -8,6 +8,7 @@ import Actions from './actions.vue';
import SuccessMessage from './success_message.vue';
import { leftSidebarViews, MAX_WINDOW_HEIGHT_COMPACT } from '../../constants';
import consts from '../../stores/modules/commit/constants';
+import { createUnexpectedCommitError } from '../../lib/errors';
export default {
components: {
@@ -17,15 +18,20 @@ export default {
SuccessMessage,
GlModal,
},
+ directives: {
+ SafeHtml: GlSafeHtmlDirective,
+ },
data() {
return {
isCompact: true,
componentHeight: null,
+ // Keep track of "lastCommitError" so we hold onto the value even when "commitError" is cleared.
+ lastCommitError: createUnexpectedCommitError(),
};
},
computed: {
...mapState(['changedFiles', 'stagedFiles', 'currentActivityView', 'lastCommitMsg']),
- ...mapState('commit', ['commitMessage', 'submitCommitLoading']),
+ ...mapState('commit', ['commitMessage', 'submitCommitLoading', 'commitError']),
...mapGetters(['someUncommittedChanges']),
...mapGetters('commit', ['discardDraftButtonDisabled', 'preBuiltCommitMessage']),
overviewText() {
@@ -38,11 +44,28 @@ export default {
currentViewIsCommitView() {
return this.currentActivityView === leftSidebarViews.commit.name;
},
+ commitErrorPrimaryAction() {
+ if (!this.lastCommitError?.canCreateBranch) {
+ return undefined;
+ }
+
+ return {
+ text: __('Create new branch'),
+ };
+ },
},
watch: {
currentActivityView: 'handleCompactState',
someUncommittedChanges: 'handleCompactState',
lastCommitMsg: 'handleCompactState',
+ commitError(val) {
+ if (!val) {
+ return;
+ }
+
+ this.lastCommitError = val;
+ this.$refs.commitErrorModal.show();
+ },
},
methods: {
...mapActions(['updateActivityBarView']),
@@ -53,9 +76,7 @@ export default {
'updateCommitAction',
]),
commit() {
- return this.commitChanges().catch(() => {
- this.$refs.createBranchModal.show();
- });
+ return this.commitChanges();
},
forceCreateNewBranch() {
return this.updateCommitAction(consts.COMMIT_TO_NEW_BRANCH).then(() => this.commit());
@@ -164,17 +185,14 @@ export default {
</button>
</div>
<gl-modal
- ref="createBranchModal"
- modal-id="ide-create-branch-modal"
- :ok-title="__('Create new branch')"
- :title="__('Branch has changed')"
- ok-variant="success"
+ ref="commitErrorModal"
+ modal-id="ide-commit-error-modal"
+ :title="lastCommitError.title"
+ :action-primary="commitErrorPrimaryAction"
+ :action-cancel="{ text: __('Cancel') }"
@ok="forceCreateNewBranch"
>
- {{
- __(`This branch has changed since you started editing.
- Would you like to create a new branch?`)
- }}
+ <div v-safe-html="lastCommitError.messageHTML"></div>
</gl-modal>
</form>
</transition>
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/list.vue b/app/assets/javascripts/ide/components/commit_sidebar/list.vue
index d1422a506e7..609ce287d3f 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/list.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/list.vue
@@ -1,14 +1,13 @@
<script>
import { mapActions } from 'vuex';
-import { GlModal } from '@gitlab/ui';
+import { GlModal, GlIcon } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
-import Icon from '~/vue_shared/components/icon.vue';
import tooltip from '~/vue_shared/directives/tooltip';
import ListItem from './list_item.vue';
export default {
components: {
- Icon,
+ GlIcon,
ListItem,
GlModal,
},
@@ -74,7 +73,7 @@ export default {
<div class="ide-commit-list-container">
<header class="multi-file-commit-panel-header d-flex mb-0">
<div class="d-flex align-items-center flex-fill">
- <icon v-once :name="iconName" :size="18" class="gl-mr-3" />
+ <gl-icon v-once :name="iconName" :size="18" class="gl-mr-3" />
<strong> {{ titleText }} </strong>
<div class="d-flex ml-auto">
<button
@@ -93,7 +92,7 @@ export default {
data-boundary="viewport"
@click="openDiscardModal"
>
- <icon :size="16" name="remove-all" class="ml-auto mr-auto position-top-0" />
+ <gl-icon :size="16" name="remove-all" class="ml-auto mr-auto position-top-0" />
</button>
</div>
</div>
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/list_collapsed.vue b/app/assets/javascripts/ide/components/commit_sidebar/list_collapsed.vue
index 1b257ca11cc..4821b8389ff 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/list_collapsed.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/list_collapsed.vue
@@ -1,11 +1,11 @@
<script>
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlIcon } from '@gitlab/ui';
import tooltip from '~/vue_shared/directives/tooltip';
import { sprintf, n__, __ } from '~/locale';
export default {
components: {
- Icon,
+ GlIcon,
},
directives: {
tooltip,
@@ -77,7 +77,7 @@ export default {
data-placement="left"
class="gl-mb-5"
>
- <icon v-once :name="iconName" :size="18" />
+ <gl-icon v-once :name="iconName" :size="18" />
</div>
<div
v-tooltip
@@ -86,7 +86,7 @@ export default {
data-placement="left"
class="gl-mb-3"
>
- <icon :name="additionIconName" :size="18" :class="addedFilesIconClass" />
+ <gl-icon :name="additionIconName" :size="18" :class="addedFilesIconClass" />
</div>
{{ addedFilesLength }}
<div
@@ -96,7 +96,7 @@ export default {
data-placement="left"
class="gl-mt-3 gl-mb-3"
>
- <icon :name="modifiedIconName" :size="18" :class="modifiedFilesClass" />
+ <gl-icon :name="modifiedIconName" :size="18" :class="modifiedFilesClass" />
</div>
{{ modifiedFilesLength }}
</div>
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 c65169f5d31..a0d6cf3c42d 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue
@@ -1,14 +1,14 @@
<script>
import { mapActions } from 'vuex';
+import { GlIcon } from '@gitlab/ui';
import tooltip from '~/vue_shared/directives/tooltip';
-import Icon from '~/vue_shared/components/icon.vue';
import FileIcon from '~/vue_shared/components/file_icon.vue';
import { viewerTypes } from '../../constants';
import getCommitIconMap from '../../commit_icon';
export default {
components: {
- Icon,
+ GlIcon,
FileIcon,
},
directives: {
@@ -95,7 +95,7 @@ export default {
</span>
<div class="ml-auto d-flex align-items-center">
<div class="d-flex align-items-center ide-commit-list-changed-icon">
- <icon :name="iconName" :size="16" :class="iconClass" />
+ <gl-icon :name="iconName" :size="16" :class="iconClass" />
</div>
</div>
</div>
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/message_field.vue b/app/assets/javascripts/ide/components/commit_sidebar/message_field.vue
index b37c7280a30..2787b10a48b 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/message_field.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/message_field.vue
@@ -1,6 +1,6 @@
<script>
+import { GlIcon } from '@gitlab/ui';
import { __, sprintf } from '../../../locale';
-import Icon from '../../../vue_shared/components/icon.vue';
import popover from '../../../vue_shared/directives/popover';
import { MAX_TITLE_LENGTH, MAX_BODY_LENGTH } from '../../constants';
@@ -9,7 +9,7 @@ export default {
popover,
},
components: {
- Icon,
+ GlIcon,
},
props: {
text: {
@@ -84,7 +84,7 @@ export default {
<li>
{{ __('Commit Message') }}
<span v-popover="$options.popoverOptions" class="form-text text-muted gl-ml-3">
- <icon name="question" />
+ <gl-icon name="question" />
</span>
</li>
</ul>
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/success_message.vue b/app/assets/javascripts/ide/components/commit_sidebar/success_message.vue
index 327b0b8172f..977efb0ca22 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/success_message.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/success_message.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapState } from 'vuex';
export default {
diff --git a/app/assets/javascripts/ide/components/error_message.vue b/app/assets/javascripts/ide/components/error_message.vue
index d36adbd798e..08635b43b91 100644
--- a/app/assets/javascripts/ide/components/error_message.vue
+++ b/app/assets/javascripts/ide/components/error_message.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapActions } from 'vuex';
import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
diff --git a/app/assets/javascripts/ide/components/file_row_extra.vue b/app/assets/javascripts/ide/components/file_row_extra.vue
index f7cf7a5b251..48ab58e1cb7 100644
--- a/app/assets/javascripts/ide/components/file_row_extra.vue
+++ b/app/assets/javascripts/ide/components/file_row_extra.vue
@@ -1,8 +1,8 @@
<script>
import { mapGetters } from 'vuex';
+import { GlIcon } from '@gitlab/ui';
import { n__ } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip';
-import Icon from '~/vue_shared/components/icon.vue';
import ChangedFileIcon from '~/vue_shared/components/changed_file_icon.vue';
import NewDropdown from './new_dropdown/index.vue';
import MrFileIcon from './mr_file_icon.vue';
@@ -13,7 +13,7 @@ export default {
tooltip,
},
components: {
- Icon,
+ GlIcon,
NewDropdown,
ChangedFileIcon,
MrFileIcon,
@@ -69,7 +69,7 @@ export default {
<mr-file-icon v-if="file.mrChange" />
<span v-if="showTreeChangesCount" class="ide-tree-changes">
{{ changesCount }}
- <icon
+ <gl-icon
v-tooltip
:title="folderChangesTooltip"
:size="12"
diff --git a/app/assets/javascripts/ide/components/ide.vue b/app/assets/javascripts/ide/components/ide.vue
index 55b3eaf9737..1b03d9eee8b 100644
--- a/app/assets/javascripts/ide/components/ide.vue
+++ b/app/assets/javascripts/ide/components/ide.vue
@@ -47,6 +47,7 @@ export default {
'emptyRepo',
'currentTree',
'editorTheme',
+ 'getUrlForPath',
]),
themeName() {
return window.gon?.user_color_scheme;
@@ -71,7 +72,7 @@ export default {
return returnValue;
},
openFile(file) {
- this.$router.push(`/project${file.url}`);
+ this.$router.push(this.getUrlForPath(file.path));
},
createNewFile() {
this.$refs.newModal.open(modalTypes.blob);
diff --git a/app/assets/javascripts/ide/components/ide_file_row.vue b/app/assets/javascripts/ide/components/ide_file_row.vue
index b777d89f0bb..248677d6a99 100644
--- a/app/assets/javascripts/ide/components/ide_file_row.vue
+++ b/app/assets/javascripts/ide/components/ide_file_row.vue
@@ -3,6 +3,7 @@
* This component is an iterative step towards refactoring and simplifying `vue_shared/components/file_row.vue`
* https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23720
*/
+import { mapGetters } from 'vuex';
import FileRow from '~/vue_shared/components/file_row.vue';
import FileRowExtra from './file_row_extra.vue';
@@ -23,6 +24,9 @@ export default {
dropdownOpen: false,
};
},
+ computed: {
+ ...mapGetters(['getUrlForPath']),
+ },
methods: {
toggleDropdown(val) {
this.dropdownOpen = val;
@@ -32,7 +36,13 @@ export default {
</script>
<template>
- <file-row :file="file" v-bind="$attrs" @mouseleave="toggleDropdown(false)" v-on="$listeners">
+ <file-row
+ :file="file"
+ :file-url="getUrlForPath(file.path)"
+ v-bind="$attrs"
+ @mouseleave="toggleDropdown(false)"
+ v-on="$listeners"
+ >
<file-row-extra :file="file" :dropdown-open="dropdownOpen" @toggle="toggleDropdown($event)" />
</file-row>
</template>
diff --git a/app/assets/javascripts/ide/components/ide_review.vue b/app/assets/javascripts/ide/components/ide_review.vue
index 95348711e1d..e36d0a5a5b1 100644
--- a/app/assets/javascripts/ide/components/ide_review.vue
+++ b/app/assets/javascripts/ide/components/ide_review.vue
@@ -10,7 +10,7 @@ export default {
EditorModeDropdown,
},
computed: {
- ...mapGetters(['currentMergeRequest', 'activeFile']),
+ ...mapGetters(['currentMergeRequest', 'activeFile', 'getUrlForPath']),
...mapState(['viewer', 'currentMergeRequestId']),
showLatestChangesText() {
return !this.currentMergeRequestId || this.viewer === viewerTypes.diff;
@@ -24,7 +24,7 @@ export default {
},
mounted() {
if (this.activeFile && this.activeFile.pending && !this.activeFile.deleted) {
- this.$router.push(`/project${this.activeFile.url}`, () => {
+ this.$router.push(this.getUrlForPath(this.activeFile.path), () => {
this.updateViewer('editor');
});
} else if (this.activeFile && this.activeFile.deleted) {
diff --git a/app/assets/javascripts/ide/components/ide_side_bar.vue b/app/assets/javascripts/ide/components/ide_side_bar.vue
index 1eb89b41495..ed68ca5cae9 100644
--- a/app/assets/javascripts/ide/components/ide_side_bar.vue
+++ b/app/assets/javascripts/ide/components/ide_side_bar.vue
@@ -1,6 +1,6 @@
<script>
import { mapState, mapGetters } from 'vuex';
-import { GlSkeletonLoading } from '@gitlab/ui';
+import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
import IdeTree from './ide_tree.vue';
import ResizablePanel from './resizable_panel.vue';
import ActivityBar from './activity_bar.vue';
diff --git a/app/assets/javascripts/ide/components/ide_status_bar.vue b/app/assets/javascripts/ide/components/ide_status_bar.vue
index ddc126c3d77..146e818d654 100644
--- a/app/assets/javascripts/ide/components/ide_status_bar.vue
+++ b/app/assets/javascripts/ide/components/ide_status_bar.vue
@@ -1,9 +1,9 @@
<script>
/* eslint-disable @gitlab/vue-require-i18n-strings */
import { mapActions, mapState, mapGetters } from 'vuex';
+import { GlIcon } from '@gitlab/ui';
import IdeStatusList from './ide_status_list.vue';
import IdeStatusMr from './ide_status_mr.vue';
-import icon from '~/vue_shared/components/icon.vue';
import tooltip from '~/vue_shared/directives/tooltip';
import timeAgoMixin from '~/vue_shared/mixins/timeago';
import CiIcon from '../../vue_shared/components/ci_icon.vue';
@@ -12,7 +12,7 @@ import { rightSidebarViews } from '../constants';
export default {
components: {
- icon,
+ GlIcon,
userAvatarImage,
CiIcon,
IdeStatusList,
@@ -97,12 +97,13 @@ export default {
{{ latestPipeline.details.status.text }} for
</span>
- <icon name="commit" />
+ <gl-icon name="commit" />
<a
v-tooltip
:title="lastCommit.message"
:href="getCommitPath(lastCommit.short_id)"
class="commit-sha"
+ data-qa-selector="commit_sha_content"
>{{ lastCommit.short_id }}</a
>
by
diff --git a/app/assets/javascripts/ide/components/ide_status_list.vue b/app/assets/javascripts/ide/components/ide_status_list.vue
index 1354fdc3d98..caa122f6ed2 100644
--- a/app/assets/javascripts/ide/components/ide_status_list.vue
+++ b/app/assets/javascripts/ide/components/ide_status_list.vue
@@ -2,7 +2,7 @@
import { mapGetters } from 'vuex';
import { GlLink, GlTooltipDirective } from '@gitlab/ui';
import TerminalSyncStatusSafe from './terminal_sync/terminal_sync_status_safe.vue';
-import { getFileEOL } from '../utils';
+import { isTextFile, getFileEOL } from '~/ide/utils';
export default {
components: {
@@ -17,6 +17,9 @@ export default {
activeFileEOL() {
return getFileEOL(this.activeFile.content);
},
+ activeFileIsText() {
+ return isTextFile(this.activeFile);
+ },
},
};
</script>
@@ -30,7 +33,7 @@ export default {
</gl-link>
</div>
<div>{{ activeFileEOL }}</div>
- <div v-if="!activeFile.binary">{{ activeFile.editorRow }}:{{ activeFile.editorColumn }}</div>
+ <div v-if="activeFileIsText">{{ activeFile.editorRow }}:{{ activeFile.editorColumn }}</div>
<div>{{ activeFile.fileLanguage }}</div>
</template>
<terminal-sync-status-safe />
diff --git a/app/assets/javascripts/ide/components/ide_tree.vue b/app/assets/javascripts/ide/components/ide_tree.vue
index 647f4d4be85..747d5044790 100644
--- a/app/assets/javascripts/ide/components/ide_tree.vue
+++ b/app/assets/javascripts/ide/components/ide_tree.vue
@@ -15,13 +15,13 @@ export default {
},
computed: {
...mapState(['currentBranchId']),
- ...mapGetters(['currentProject', 'currentTree', 'activeFile']),
+ ...mapGetters(['currentProject', 'currentTree', 'activeFile', 'getUrlForPath']),
},
mounted() {
if (!this.activeFile) return;
if (this.activeFile.pending && !this.activeFile.deleted) {
- this.$router.push(`/project${this.activeFile.url}`, () => {
+ this.$router.push(this.getUrlForPath(this.activeFile.path), () => {
this.updateViewer('editor');
});
} else if (this.activeFile.deleted) {
diff --git a/app/assets/javascripts/ide/components/ide_tree_list.vue b/app/assets/javascripts/ide/components/ide_tree_list.vue
index 36e8951bea3..776d8459515 100644
--- a/app/assets/javascripts/ide/components/ide_tree_list.vue
+++ b/app/assets/javascripts/ide/components/ide_tree_list.vue
@@ -1,6 +1,6 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
-import { GlSkeletonLoading } from '@gitlab/ui';
+import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
import FileTree from '~/vue_shared/components/file_tree.vue';
import IdeFileRow from './ide_file_row.vue';
import NavDropdown from './nav_dropdown.vue';
diff --git a/app/assets/javascripts/ide/components/jobs/detail.vue b/app/assets/javascripts/ide/components/jobs/detail.vue
index 975d54c7a4e..11033a5cc88 100644
--- a/app/assets/javascripts/ide/components/jobs/detail.vue
+++ b/app/assets/javascripts/ide/components/jobs/detail.vue
@@ -1,9 +1,10 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapActions, mapState } from 'vuex';
import { throttle } from 'lodash';
+import { GlIcon } from '@gitlab/ui';
import { __ } from '../../../locale';
import tooltip from '../../../vue_shared/directives/tooltip';
-import Icon from '../../../vue_shared/components/icon.vue';
import ScrollButton from './detail/scroll_button.vue';
import JobDescription from './detail/description.vue';
@@ -17,7 +18,7 @@ export default {
tooltip,
},
components: {
- Icon,
+ GlIcon,
ScrollButton,
JobDescription,
},
@@ -39,10 +40,10 @@ export default {
},
},
mounted() {
- this.getTrace();
+ this.getLogs();
},
methods: {
- ...mapActions('pipelines', ['fetchJobTrace', 'setDetailJob']),
+ ...mapActions('pipelines', ['fetchJobLogs', 'setDetailJob']),
scrollDown() {
if (this.$refs.buildTrace) {
this.$refs.buildTrace.scrollTo(0, this.$refs.buildTrace.scrollHeight);
@@ -65,8 +66,8 @@ export default {
this.scrollPos = '';
}
}),
- getTrace() {
- return this.fetchJobTrace().then(() => this.scrollDown());
+ getLogs() {
+ return this.fetchJobLogs().then(() => this.scrollDown());
},
},
};
@@ -76,7 +77,7 @@ export default {
<div class="ide-pipeline build-page d-flex flex-column flex-fill">
<header class="ide-job-header d-flex align-items-center">
<button class="btn btn-default btn-sm d-flex" @click="setDetailJob(null)">
- <icon name="chevron-left" /> {{ __('View jobs') }}
+ <gl-icon name="chevron-left" /> {{ __('View jobs') }}
</button>
</header>
<div class="top-bar d-flex border-left-0 mr-3">
diff --git a/app/assets/javascripts/ide/components/jobs/detail/description.vue b/app/assets/javascripts/ide/components/jobs/detail/description.vue
index f1ba102fffe..9eaeabad5ef 100644
--- a/app/assets/javascripts/ide/components/jobs/detail/description.vue
+++ b/app/assets/javascripts/ide/components/jobs/detail/description.vue
@@ -1,10 +1,10 @@
<script>
-import Icon from '../../../../vue_shared/components/icon.vue';
+import { GlIcon } from '@gitlab/ui';
import CiIcon from '../../../../vue_shared/components/ci_icon.vue';
export default {
components: {
- Icon,
+ GlIcon,
CiIcon,
},
props: {
@@ -26,8 +26,14 @@ export default {
<ci-icon :status="job.status" :borderless="true" :size="24" class="d-flex" />
<span class="gl-ml-3">
{{ job.name }}
- <a :href="job.path" target="_blank" class="ide-external-link position-relative">
- {{ jobId }} <icon :size="12" name="external-link" />
+ <a
+ v-if="job.path"
+ :href="job.path"
+ target="_blank"
+ class="ide-external-link gl-relative"
+ data-testid="description-detail-link"
+ >
+ {{ jobId }} <gl-icon :size="12" name="external-link" />
</a>
</span>
</div>
diff --git a/app/assets/javascripts/ide/components/jobs/detail/scroll_button.vue b/app/assets/javascripts/ide/components/jobs/detail/scroll_button.vue
index 5674d3ffa80..2c679a3edc7 100644
--- a/app/assets/javascripts/ide/components/jobs/detail/scroll_button.vue
+++ b/app/assets/javascripts/ide/components/jobs/detail/scroll_button.vue
@@ -1,6 +1,6 @@
<script>
+import { GlIcon } from '@gitlab/ui';
import { __ } from '../../../../locale';
-import Icon from '../../../../vue_shared/components/icon.vue';
import tooltip from '../../../../vue_shared/directives/tooltip';
const directions = {
@@ -13,7 +13,7 @@ export default {
tooltip,
},
components: {
- Icon,
+ GlIcon,
},
props: {
direction: {
@@ -58,7 +58,7 @@ export default {
type="button"
@click="clickedScroll"
>
- <icon :name="iconName" />
+ <gl-icon :name="iconName" />
</button>
</div>
</template>
diff --git a/app/assets/javascripts/ide/components/jobs/stage.vue b/app/assets/javascripts/ide/components/jobs/stage.vue
index 75441e8c1c8..0b643947139 100644
--- a/app/assets/javascripts/ide/components/jobs/stage.vue
+++ b/app/assets/javascripts/ide/components/jobs/stage.vue
@@ -1,7 +1,6 @@
<script>
-import { GlLoadingIcon } from '@gitlab/ui';
+import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
import tooltip from '../../../vue_shared/directives/tooltip';
-import Icon from '../../../vue_shared/components/icon.vue';
import CiIcon from '../../../vue_shared/components/ci_icon.vue';
import Item from './item.vue';
@@ -10,7 +9,7 @@ export default {
tooltip,
},
components: {
- Icon,
+ GlIcon,
CiIcon,
Item,
GlLoadingIcon,
@@ -78,7 +77,7 @@ export default {
<div v-if="!stage.isLoading || stage.jobs.length" class="gl-mr-3 gl-ml-2">
<span class="badge badge-pill"> {{ jobsCount }} </span>
</div>
- <icon :name="collapseIcon" class="ide-stage-collapse-icon" />
+ <gl-icon :name="collapseIcon" class="ide-stage-collapse-icon" />
</div>
<div v-show="!stage.isCollapsed" ref="jobList" class="card-body p-0">
<gl-loading-icon v-if="showLoadingIcon" />
diff --git a/app/assets/javascripts/ide/components/merge_requests/item.vue b/app/assets/javascripts/ide/components/merge_requests/item.vue
index 8b7b8d5a91c..7aa9a4f864a 100644
--- a/app/assets/javascripts/ide/components/merge_requests/item.vue
+++ b/app/assets/javascripts/ide/components/merge_requests/item.vue
@@ -1,9 +1,9 @@
<script>
-import Icon from '../../../vue_shared/components/icon.vue';
+import { GlIcon } from '@gitlab/ui';
export default {
components: {
- Icon,
+ GlIcon,
},
props: {
item: {
@@ -41,7 +41,7 @@ export default {
<template>
<a :href="mergeRequestHref" class="btn-link d-flex align-items-center">
<span class="d-flex gl-mr-3 ide-search-list-current-icon">
- <icon v-if="isActive" :size="18" name="mobile-issue-close" />
+ <gl-icon v-if="isActive" :size="18" name="mobile-issue-close" />
</span>
<span>
<strong> {{ item.title }} </strong>
diff --git a/app/assets/javascripts/ide/components/merge_requests/list.vue b/app/assets/javascripts/ide/components/merge_requests/list.vue
index af45d88b84a..4b3c6e61e11 100644
--- a/app/assets/javascripts/ide/components/merge_requests/list.vue
+++ b/app/assets/javascripts/ide/components/merge_requests/list.vue
@@ -1,9 +1,8 @@
<script>
import { mapActions, mapState } from 'vuex';
import { debounce } from 'lodash';
-import { GlLoadingIcon } from '@gitlab/ui';
+import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
-import Icon from '~/vue_shared/components/icon.vue';
import Item from './item.vue';
import TokenedInput from '../shared/tokened_input.vue';
@@ -16,7 +15,7 @@ export default {
components: {
TokenedInput,
Item,
- Icon,
+ GlIcon,
GlLoadingIcon,
},
data() {
@@ -85,7 +84,7 @@ export default {
@input="searchMergeRequests"
@removeToken="setSearchType(null)"
/>
- <icon :size="18" name="search" class="ml-3 input-icon" />
+ <gl-icon :size="18" name="search" class="ml-3 input-icon" />
</label>
<div class="dropdown-content ide-merge-requests-dropdown-content d-flex">
<gl-loading-icon
@@ -103,7 +102,7 @@ export default {
@click.stop="setSearchType(searchType)"
>
<span class="d-flex gl-mr-3 ide-search-list-current-icon">
- <icon :size="18" name="search" />
+ <gl-icon :size="18" name="search" />
</span>
<span>{{ searchType.label }}</span>
</button>
diff --git a/app/assets/javascripts/ide/components/mr_file_icon.vue b/app/assets/javascripts/ide/components/mr_file_icon.vue
index 4fab57b6f3e..c8629a869e0 100644
--- a/app/assets/javascripts/ide/components/mr_file_icon.vue
+++ b/app/assets/javascripts/ide/components/mr_file_icon.vue
@@ -1,10 +1,10 @@
<script>
-import icon from '~/vue_shared/components/icon.vue';
+import { GlIcon } from '@gitlab/ui';
import tooltip from '~/vue_shared/directives/tooltip';
export default {
components: {
- icon,
+ GlIcon,
},
directives: {
tooltip,
@@ -13,7 +13,7 @@ export default {
</script>
<template>
- <icon
+ <gl-icon
v-tooltip
:title="__('Part of merge request changes')"
:size="12"
diff --git a/app/assets/javascripts/ide/components/nav_dropdown_button.vue b/app/assets/javascripts/ide/components/nav_dropdown_button.vue
index 8dc22620eca..116d3cec03e 100644
--- a/app/assets/javascripts/ide/components/nav_dropdown_button.vue
+++ b/app/assets/javascripts/ide/components/nav_dropdown_button.vue
@@ -1,13 +1,13 @@
<script>
import { mapState } from 'vuex';
+import { GlIcon } from '@gitlab/ui';
import DropdownButton from '~/vue_shared/components/dropdown/dropdown_button.vue';
-import Icon from '~/vue_shared/components/icon.vue';
const EMPTY_LABEL = '-';
export default {
components: {
- Icon,
+ GlIcon,
DropdownButton,
},
props: {
@@ -33,10 +33,10 @@ export default {
<dropdown-button>
<span class="row flex-nowrap">
<span class="col-auto flex-fill text-truncate">
- <icon :size="16" :aria-label="__('Current Branch')" name="branch" /> {{ branchLabel }}
+ <gl-icon :size="16" :aria-label="__('Current Branch')" name="branch" /> {{ branchLabel }}
</span>
<span v-if="showMergeRequests" class="col-5 pl-0 text-truncate">
- <icon :size="16" :aria-label="__('Merge Request')" name="merge-request" />
+ <gl-icon :size="16" :aria-label="__('Merge Request')" name="merge-request" />
{{ mergeRequestLabel }}
</span>
</span>
diff --git a/app/assets/javascripts/ide/components/new_dropdown/button.vue b/app/assets/javascripts/ide/components/new_dropdown/button.vue
index 5bd6642930c..8ae8f97f237 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/button.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/button.vue
@@ -1,5 +1,5 @@
<script>
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlIcon } from '@gitlab/ui';
import tooltip from '~/vue_shared/directives/tooltip';
export default {
@@ -7,7 +7,7 @@ export default {
tooltip,
},
components: {
- Icon,
+ GlIcon,
},
props: {
label: {
@@ -52,7 +52,7 @@ export default {
class="btn-blank"
@click.stop.prevent="clicked"
>
- <icon :name="icon" :class="iconClasses" />
+ <gl-icon :name="icon" :class="iconClasses" />
<template v-if="showLabel">
{{ label }}
</template>
diff --git a/app/assets/javascripts/ide/components/new_dropdown/index.vue b/app/assets/javascripts/ide/components/new_dropdown/index.vue
index b656e35f150..692878de5e1 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/index.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/index.vue
@@ -1,6 +1,6 @@
<script>
import { mapActions } from 'vuex';
-import icon from '~/vue_shared/components/icon.vue';
+import { GlIcon } from '@gitlab/ui';
import upload from './upload.vue';
import ItemButton from './button.vue';
import { modalTypes } from '../../constants';
@@ -8,7 +8,7 @@ import NewModal from './modal.vue';
export default {
components: {
- icon,
+ GlIcon,
upload,
ItemButton,
NewModal,
@@ -67,7 +67,7 @@ export default {
data-qa-selector="dropdown_button"
@click.stop="openDropdown()"
>
- <icon name="ellipsis_v" /> <icon name="chevron-down" />
+ <gl-icon name="ellipsis_v" /> <gl-icon name="chevron-down" />
</button>
<ul ref="dropdownMenu" class="dropdown-menu dropdown-menu-right">
<template v-if="type === 'tree'">
diff --git a/app/assets/javascripts/ide/components/new_dropdown/modal.vue b/app/assets/javascripts/ide/components/new_dropdown/modal.vue
index 44986c8c575..528475849de 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/modal.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/modal.vue
@@ -1,6 +1,6 @@
<script>
import { mapActions, mapState, mapGetters } from 'vuex';
-import { GlModal } from '@gitlab/ui';
+import { GlModal, GlButton } from '@gitlab/ui';
import { deprecatedCreateFlash as flash } from '~/flash';
import { __, sprintf, s__ } from '~/locale';
import { modalTypes } from '../../constants';
@@ -9,6 +9,7 @@ import { trimPathComponents, getPathParent } from '../../utils';
export default {
components: {
GlModal,
+ GlButton,
},
data() {
return {
@@ -156,13 +157,14 @@ export default {
/>
<ul v-if="isCreatingNewFile" class="file-templates gl-mt-3 list-inline qa-template-list">
<li v-for="(template, index) in templateTypes" :key="index" class="list-inline-item">
- <button
- type="button"
- class="btn btn-missing p-1 pr-2 pl-2"
+ <gl-button
+ variant="dashed"
+ category="secondary"
+ class="p-1 pr-2 pl-2"
@click="createFromTemplate(template)"
>
{{ template.name }}
- </button>
+ </gl-button>
</li>
</ul>
</div>
diff --git a/app/assets/javascripts/ide/components/new_dropdown/upload.vue b/app/assets/javascripts/ide/components/new_dropdown/upload.vue
index b2141c13d9f..84ff05c9750 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/upload.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/upload.vue
@@ -28,14 +28,13 @@ export default {
const { name } = file;
const encodedContent = target.result.split('base64,')[1];
const rawContent = encodedContent ? atob(encodedContent) : '';
- const isText = isTextFile(rawContent, file.type, name);
+ const isText = isTextFile({ content: rawContent, mimeType: file.type, name });
const emitCreateEvent = content =>
this.$emit('create', {
name: `${this.path ? `${this.path}/` : ''}${name}`,
type: 'blob',
content,
- binary: !isText,
rawPath: !isText ? target.result : '',
});
diff --git a/app/assets/javascripts/ide/components/panes/collapsible_sidebar.vue b/app/assets/javascripts/ide/components/panes/collapsible_sidebar.vue
index 4e8e1e3a470..f1b882d8f29 100644
--- a/app/assets/javascripts/ide/components/panes/collapsible_sidebar.vue
+++ b/app/assets/javascripts/ide/components/panes/collapsible_sidebar.vue
@@ -1,7 +1,6 @@
<script>
import { mapActions, mapState } from 'vuex';
import tooltip from '~/vue_shared/directives/tooltip';
-import Icon from '~/vue_shared/components/icon.vue';
import IdeSidebarNav from '../ide_sidebar_nav.vue';
export default {
@@ -10,7 +9,6 @@ export default {
tooltip,
},
components: {
- Icon,
IdeSidebarNav,
},
props: {
diff --git a/app/assets/javascripts/ide/components/pipelines/list.vue b/app/assets/javascripts/ide/components/pipelines/list.vue
index 6038e92f254..91bd64a2c9c 100644
--- a/app/assets/javascripts/ide/components/pipelines/list.vue
+++ b/app/assets/javascripts/ide/components/pipelines/list.vue
@@ -1,9 +1,8 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
import { escape } from 'lodash';
-import { GlLoadingIcon } from '@gitlab/ui';
+import { GlLoadingIcon, GlIcon, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import { sprintf, __ } from '../../../locale';
-import Icon from '../../../vue_shared/components/icon.vue';
import CiIcon from '../../../vue_shared/components/ci_icon.vue';
import Tabs from '../../../vue_shared/components/tabs/tabs';
import Tab from '../../../vue_shared/components/tabs/tab.vue';
@@ -14,7 +13,7 @@ import IDEServices from '~/ide/services';
export default {
components: {
- Icon,
+ GlIcon,
CiIcon,
Tabs,
Tab,
@@ -22,6 +21,9 @@ export default {
EmptyState,
GlLoadingIcon,
},
+ directives: {
+ SafeHtml,
+ },
computed: {
...mapState(['pipelinesEmptyStateSvgPath', 'links']),
...mapGetters(['currentProject']),
@@ -70,7 +72,7 @@ export default {
target="_blank"
class="ide-external-link position-relative"
>
- #{{ latestPipeline.id }} <icon :size="12" name="external-link" />
+ #{{ latestPipeline.id }} <gl-icon :size="12" name="external-link" />
</a>
</span>
</header>
@@ -84,7 +86,7 @@ export default {
<div v-else-if="latestPipeline.yamlError" class="bs-callout bs-callout-danger">
<p class="gl-mb-0">{{ __('Found errors in your .gitlab-ci.yml:') }}</p>
<p class="gl-mb-0 break-word">{{ latestPipeline.yamlError }}</p>
- <p class="gl-mb-0" v-html="ciLintText"></p>
+ <p v-safe-html="ciLintText" class="gl-mb-0"></p>
</div>
<tabs v-else class="ide-pipeline-list">
<tab :active="!pipelineFailed">
diff --git a/app/assets/javascripts/ide/components/preview/navigator.vue b/app/assets/javascripts/ide/components/preview/navigator.vue
index 0de9dfd8827..60710251fef 100644
--- a/app/assets/javascripts/ide/components/preview/navigator.vue
+++ b/app/assets/javascripts/ide/components/preview/navigator.vue
@@ -1,11 +1,10 @@
<script>
import { listen } from 'codesandbox-api';
-import { GlLoadingIcon } from '@gitlab/ui';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
export default {
components: {
- Icon,
+ GlIcon,
GlLoadingIcon,
},
props: {
@@ -97,7 +96,7 @@ export default {
class="ide-navigator-btn d-flex align-items-center d-transparent border-0 bg-transparent"
@click="back"
>
- <icon :size="24" name="chevron-left" class="m-auto" />
+ <gl-icon :size="24" name="chevron-left" class="m-auto" />
</button>
<button
:aria-label="s__('IDE|Back')"
@@ -109,7 +108,7 @@ export default {
class="ide-navigator-btn d-flex align-items-center d-transparent border-0 bg-transparent"
@click="forward"
>
- <icon :size="24" name="chevron-right" class="m-auto" />
+ <gl-icon :size="24" name="chevron-right" class="m-auto" />
</button>
<button
:aria-label="s__('IDE|Refresh preview')"
@@ -117,7 +116,7 @@ export default {
class="ide-navigator-btn d-flex align-items-center d-transparent border-0 bg-transparent"
@click="refresh"
>
- <icon :size="18" name="retry" class="m-auto" />
+ <gl-icon :size="18" name="retry" class="m-auto" />
</button>
<div class="position-relative w-100 gl-ml-2">
<input
diff --git a/app/assets/javascripts/ide/components/repo_editor.vue b/app/assets/javascripts/ide/components/repo_editor.vue
index d22d430cb4a..f342ce1739c 100644
--- a/app/assets/javascripts/ide/components/repo_editor.vue
+++ b/app/assets/javascripts/ide/components/repo_editor.vue
@@ -14,7 +14,7 @@ import Editor from '../lib/editor';
import FileTemplatesBar from './file_templates/bar.vue';
import { __ } from '~/locale';
import { extractMarkdownImagesFromEntries } from '../stores/utils';
-import { getPathParent, readFileAsDataURL } from '../utils';
+import { getPathParent, readFileAsDataURL, registerSchema, isTextFile } from '../utils';
import { getRulesWithTraversal } from '../lib/editorconfig/parser';
import mapRulesToMonaco from '../lib/editorconfig/rules_mapper';
@@ -48,6 +48,7 @@ export default {
'renderWhitespaceInCode',
'editorTheme',
'entries',
+ 'currentProjectId',
]),
...mapGetters([
'currentMergeRequest',
@@ -55,10 +56,11 @@ export default {
'isEditModeActive',
'isCommitModeActive',
'currentBranch',
+ 'getJsonSchemaForPath',
]),
...mapGetters('fileTemplates', ['showFileTemplatesBar']),
shouldHideEditor() {
- return this.file && this.file.binary;
+ return this.file && !isTextFile(this.file);
},
showContentViewer() {
return (
@@ -196,6 +198,8 @@ export default {
this.editor.clearEditor();
+ this.registerSchemaForFile();
+
Promise.all([this.fetchFileData(), this.fetchEditorconfigRules()])
.then(() => {
this.createEditorInstance();
@@ -329,6 +333,10 @@ export default {
// do nothing if no image is found in the clipboard
return Promise.resolve();
},
+ registerSchemaForFile() {
+ const schema = this.getJsonSchemaForPath(this.file.path);
+ registerSchema(schema);
+ },
},
viewerTypes,
FILE_VIEW_MODE_EDITOR,
@@ -379,7 +387,7 @@ export default {
:path="file.rawPath || file.path"
:file-path="file.path"
:file-size="file.size"
- :project-path="file.projectId"
+ :project-path="currentProjectId"
:commit-sha="currentBranchCommit"
:type="fileType"
/>
@@ -390,7 +398,7 @@ export default {
:new-sha="currentMergeRequest.sha"
:old-path="file.mrChange.old_path"
:old-sha="currentMergeRequest.baseCommitSha"
- :project-path="file.projectId"
+ :project-path="currentProjectId"
/>
</div>
</template>
diff --git a/app/assets/javascripts/ide/components/repo_file_status_icon.vue b/app/assets/javascripts/ide/components/repo_file_status_icon.vue
index 9773e835a5c..1402f7aaf39 100644
--- a/app/assets/javascripts/ide/components/repo_file_status_icon.vue
+++ b/app/assets/javascripts/ide/components/repo_file_status_icon.vue
@@ -1,12 +1,12 @@
<script>
+import { GlIcon } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
-import icon from '~/vue_shared/components/icon.vue';
import tooltip from '~/vue_shared/directives/tooltip';
import '~/lib/utils/datetime_utility';
export default {
components: {
- icon,
+ GlIcon,
},
directives: {
tooltip,
@@ -29,6 +29,6 @@ export default {
<template>
<span v-if="file.file_lock" v-tooltip :title="lockTooltip" data-container="body">
- <icon name="lock" class="file-status-icon" />
+ <gl-icon name="lock" class="file-status-icon" />
</span>
</template>
diff --git a/app/assets/javascripts/ide/components/repo_tab.vue b/app/assets/javascripts/ide/components/repo_tab.vue
index 8370833233a..60a80a31a8b 100644
--- a/app/assets/javascripts/ide/components/repo_tab.vue
+++ b/app/assets/javascripts/ide/components/repo_tab.vue
@@ -1,9 +1,9 @@
<script>
-import { mapActions } from 'vuex';
+import { mapActions, mapGetters } from 'vuex';
+import { GlIcon } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
import FileIcon from '~/vue_shared/components/file_icon.vue';
-import Icon from '~/vue_shared/components/icon.vue';
import ChangedFileIcon from '~/vue_shared/components/changed_file_icon.vue';
import FileStatusIcon from './repo_file_status_icon.vue';
@@ -11,7 +11,7 @@ export default {
components: {
FileStatusIcon,
FileIcon,
- Icon,
+ GlIcon,
ChangedFileIcon,
},
props: {
@@ -26,6 +26,7 @@ export default {
};
},
computed: {
+ ...mapGetters(['getUrlForPath']),
closeLabel() {
if (this.fileHasChanged) {
return sprintf(__(`%{tabname} changed`), { tabname: this.tab.name });
@@ -52,7 +53,7 @@ export default {
if (tab.pending) {
this.openPendingTab({ file: tab, keyPrefix: tab.staged ? 'staged' : 'unstaged' });
} else {
- this.$router.push(`/project${tab.url}`);
+ this.$router.push(this.getUrlForPath(tab.path));
}
},
mouseOverTab() {
@@ -79,7 +80,7 @@ export default {
@mouseover="mouseOverTab"
@mouseout="mouseOutTab"
>
- <div :title="tab.url" class="multi-file-tab">
+ <div :title="getUrlForPath(tab.path)" class="multi-file-tab">
<file-icon :file-name="tab.name" :size="16" />
{{ tab.name }}
<file-status-icon :file="tab" />
@@ -91,7 +92,7 @@ export default {
class="multi-file-tab-close"
@click.stop.prevent="closeFile(tab)"
>
- <icon v-if="!showChangedIcon" :size="12" name="close" />
+ <gl-icon v-if="!showChangedIcon" :size="12" name="close" />
<changed-file-icon v-else :file="tab" />
</button>
</li>
diff --git a/app/assets/javascripts/ide/components/repo_tabs.vue b/app/assets/javascripts/ide/components/repo_tabs.vue
index 47c75be3f7c..c03694e3619 100644
--- a/app/assets/javascripts/ide/components/repo_tabs.vue
+++ b/app/assets/javascripts/ide/components/repo_tabs.vue
@@ -1,5 +1,5 @@
<script>
-import { mapActions } from 'vuex';
+import { mapActions, mapGetters } from 'vuex';
import RepoTab from './repo_tab.vue';
export default {
@@ -20,6 +20,9 @@ export default {
required: true,
},
},
+ computed: {
+ ...mapGetters(['getUrlForPath']),
+ },
methods: {
...mapActions(['updateViewer', 'removePendingTab']),
openFileViewer(viewer) {
@@ -27,7 +30,7 @@ export default {
if (this.activeFile.pending) {
return this.removePendingTab(this.activeFile).then(() => {
- this.$router.push(`/project${this.activeFile.url}`);
+ this.$router.push(this.getUrlForPath(this.activeFile.path));
});
}
diff --git a/app/assets/javascripts/ide/components/shared/tokened_input.vue b/app/assets/javascripts/ide/components/shared/tokened_input.vue
index de3e71dad92..e7a4c5487d1 100644
--- a/app/assets/javascripts/ide/components/shared/tokened_input.vue
+++ b/app/assets/javascripts/ide/components/shared/tokened_input.vue
@@ -1,10 +1,10 @@
<script>
+import { GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
-import Icon from '~/vue_shared/components/icon.vue';
export default {
components: {
- Icon,
+ GlIcon,
},
props: {
placeholder: {
@@ -81,7 +81,7 @@ export default {
>
<div class="value-container rounded">
<div class="value">{{ token.label }}</div>
- <div class="remove-token inverted"><icon :size="10" name="close" /></div>
+ <div class="remove-token inverted"><gl-icon :size="10" name="close" /></div>
</div>
</button>
</div>
diff --git a/app/assets/javascripts/ide/components/terminal/empty_state.vue b/app/assets/javascripts/ide/components/terminal/empty_state.vue
index 5dd12e62820..3668dd24e81 100644
--- a/app/assets/javascripts/ide/components/terminal/empty_state.vue
+++ b/app/assets/javascripts/ide/components/terminal/empty_state.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlLoadingIcon } from '@gitlab/ui';
export default {
diff --git a/app/assets/javascripts/ide/components/terminal_sync/terminal_sync_status.vue b/app/assets/javascripts/ide/components/terminal_sync/terminal_sync_status.vue
index deb13b5615e..c3f722d6052 100644
--- a/app/assets/javascripts/ide/components/terminal_sync/terminal_sync_status.vue
+++ b/app/assets/javascripts/ide/components/terminal_sync/terminal_sync_status.vue
@@ -1,8 +1,7 @@
<script>
import { throttle } from 'lodash';
-import { GlTooltipDirective, GlLoadingIcon } from '@gitlab/ui';
+import { GlTooltipDirective, GlLoadingIcon, GlIcon } from '@gitlab/ui';
import { mapState } from 'vuex';
-import Icon from '~/vue_shared/components/icon.vue';
import {
MSG_TERMINAL_SYNC_CONNECTING,
MSG_TERMINAL_SYNC_UPLOADING,
@@ -11,7 +10,7 @@ import {
export default {
components: {
- Icon,
+ GlIcon,
GlLoadingIcon,
},
directives: {
@@ -70,7 +69,7 @@ export default {
<span>{{ __('Terminal') }}:</span>
<span class="square s16 d-flex-center ml-1" :aria-label="status.text">
<gl-loading-icon v-if="isLoading" inline size="sm" class="d-flex-center" />
- <icon v-else-if="status.icon" :name="status.icon" :size="16" />
+ <gl-icon v-else-if="status.icon" :name="status.icon" :size="16" />
</span>
</div>
</template>
diff --git a/app/assets/javascripts/ide/ide_router.js b/app/assets/javascripts/ide/ide_router.js
index 82cf8d7a10a..396aedbfa10 100644
--- a/app/assets/javascripts/ide/ide_router.js
+++ b/app/assets/javascripts/ide/ide_router.js
@@ -33,7 +33,6 @@ const EmptyRouterComponent = {
},
};
-// eslint-disable-next-line import/prefer-default-export
export const createRouter = store => {
const router = new IdeRouter({
mode: 'history',
diff --git a/app/assets/javascripts/ide/lib/diff/diff.js b/app/assets/javascripts/ide/lib/diff/diff.js
index 3a456b7c4d6..62ec798b372 100644
--- a/app/assets/javascripts/ide/lib/diff/diff.js
+++ b/app/assets/javascripts/ide/lib/diff/diff.js
@@ -1,8 +1,6 @@
import { diffLines } from 'diff';
import { defaultDiffOptions } from '../editor_options';
-// See: https://gitlab.com/gitlab-org/frontend/rfcs/-/issues/20
-// eslint-disable-next-line import/prefer-default-export
export const computeDiff = (originalContent, newContent) => {
// prevent EOL changes from highlighting the entire file
const changes = diffLines(
diff --git a/app/assets/javascripts/ide/lib/editor.js b/app/assets/javascripts/ide/lib/editor.js
index f061fcb1259..2b12230c7cd 100644
--- a/app/assets/javascripts/ide/lib/editor.js
+++ b/app/assets/javascripts/ide/lib/editor.js
@@ -7,10 +7,9 @@ import ModelManager from './common/model_manager';
import { editorOptions, defaultEditorOptions, defaultDiffEditorOptions } from './editor_options';
import { themes } from './themes';
import languages from './languages';
-import schemas from './schemas';
import keymap from './keymap.json';
import { clearDomElement } from '~/editor/utils';
-import { registerLanguages, registerSchemas } from '../utils';
+import { registerLanguages } from '../utils';
function setupThemes() {
themes.forEach(theme => {
@@ -46,10 +45,6 @@ export default class Editor {
setupThemes();
registerLanguages(...languages);
- if (gon.features?.schemaLinting) {
- registerSchemas(...schemas);
- }
-
this.debouncedUpdate = debounce(() => {
this.updateDimensions();
}, 200);
diff --git a/app/assets/javascripts/ide/lib/editorconfig/parser.js b/app/assets/javascripts/ide/lib/editorconfig/parser.js
index a30a8cb868d..1597e4a8bfa 100644
--- a/app/assets/javascripts/ide/lib/editorconfig/parser.js
+++ b/app/assets/javascripts/ide/lib/editorconfig/parser.js
@@ -42,7 +42,6 @@ function getRulesWithConfigs(filePath, configFiles = [], rules = {}) {
return isRoot ? result : getRulesWithConfigs(filePath, nextConfigs, result);
}
-// eslint-disable-next-line import/prefer-default-export
export function getRulesWithTraversal(filePath, getFileContent) {
const editorconfigPaths = [
...getPathParents(filePath).map(x => `${x}/.editorconfig`),
diff --git a/app/assets/javascripts/ide/lib/errors.js b/app/assets/javascripts/ide/lib/errors.js
new file mode 100644
index 00000000000..6ae18bc8180
--- /dev/null
+++ b/app/assets/javascripts/ide/lib/errors.js
@@ -0,0 +1,39 @@
+import { escape } from 'lodash';
+import { __ } from '~/locale';
+
+const CODEOWNERS_REGEX = /Push.*protected branches.*CODEOWNERS/;
+const BRANCH_CHANGED_REGEX = /changed.*since.*start.*edit/;
+
+export const createUnexpectedCommitError = () => ({
+ title: __('Unexpected error'),
+ messageHTML: __('Could not commit. An unexpected error occurred.'),
+ canCreateBranch: false,
+});
+
+export const createCodeownersCommitError = message => ({
+ title: __('CODEOWNERS rule violation'),
+ messageHTML: escape(message),
+ canCreateBranch: true,
+});
+
+export const createBranchChangedCommitError = message => ({
+ title: __('Branch changed'),
+ messageHTML: `${escape(message)}<br/><br/>${__('Would you like to create a new branch?')}`,
+ canCreateBranch: true,
+});
+
+export const parseCommitError = e => {
+ const { message } = e?.response?.data || {};
+
+ if (!message) {
+ return createUnexpectedCommitError();
+ }
+
+ if (CODEOWNERS_REGEX.test(message)) {
+ return createCodeownersCommitError(message);
+ } else if (BRANCH_CHANGED_REGEX.test(message)) {
+ return createBranchChangedCommitError(message);
+ }
+
+ return createUnexpectedCommitError();
+};
diff --git a/app/assets/javascripts/ide/lib/files.js b/app/assets/javascripts/ide/lib/files.js
index 6d85e225fd5..789e09fa8f2 100644
--- a/app/assets/javascripts/ide/lib/files.js
+++ b/app/assets/javascripts/ide/lib/files.js
@@ -1,4 +1,3 @@
-import { viewerInformationForPath } from '~/vue_shared/components/content_viewer/lib/viewer_utils';
import { decorateData, sortTree } from '../stores/utils';
export const splitParent = path => {
@@ -13,15 +12,7 @@ export const splitParent = path => {
/**
* Create file objects from a list of file paths.
*/
-export const decorateFiles = ({
- data,
- projectId,
- branchId,
- tempFile = false,
- content = '',
- binary = false,
- rawPath = '',
-}) => {
+export const decorateFiles = ({ data, tempFile = false, content = '', rawPath = '' }) => {
const treeList = [];
const entries = {};
@@ -41,12 +32,9 @@ export const decorateFiles = ({
parentPath = parentFolder && parentFolder.path;
const tree = decorateData({
- projectId,
- branchId,
id: path,
name,
path,
- url: `/${projectId}/tree/${branchId}/-/${path}/`,
type: 'tree',
tempFile,
changed: tempFile,
@@ -73,21 +61,16 @@ export const decorateFiles = ({
const fileFolder = parent && insertParent(parent);
if (name) {
- const previewMode = viewerInformationForPath(name);
parentPath = fileFolder && fileFolder.path;
file = decorateData({
- projectId,
- branchId,
id: path,
name,
path,
- url: `/${projectId}/blob/${branchId}/-/${path}`,
type: 'blob',
tempFile,
changed: tempFile,
content,
- binary: (previewMode && previewMode.binary) || binary,
rawPath,
parentPath,
});
diff --git a/app/assets/javascripts/ide/lib/schemas/index.js b/app/assets/javascripts/ide/lib/schemas/index.js
deleted file mode 100644
index 38a2f81921b..00000000000
--- a/app/assets/javascripts/ide/lib/schemas/index.js
+++ /dev/null
@@ -1,4 +0,0 @@
-import json from './json';
-import yaml from './yaml';
-
-export default [json, yaml];
diff --git a/app/assets/javascripts/ide/lib/schemas/json/index.js b/app/assets/javascripts/ide/lib/schemas/json/index.js
deleted file mode 100644
index 900d5442bec..00000000000
--- a/app/assets/javascripts/ide/lib/schemas/json/index.js
+++ /dev/null
@@ -1,8 +0,0 @@
-export default {
- language: 'json',
- options: {
- validate: true,
- enableSchemaRequest: true,
- schemas: [],
- },
-};
diff --git a/app/assets/javascripts/ide/lib/schemas/yaml/gitlab_ci.js b/app/assets/javascripts/ide/lib/schemas/yaml/gitlab_ci.js
deleted file mode 100644
index af20744abb3..00000000000
--- a/app/assets/javascripts/ide/lib/schemas/yaml/gitlab_ci.js
+++ /dev/null
@@ -1,4 +0,0 @@
-export default {
- uri: 'https://json.schemastore.org/gitlab-ci',
- fileMatch: ['*.gitlab-ci.yml'],
-};
diff --git a/app/assets/javascripts/ide/lib/schemas/yaml/index.js b/app/assets/javascripts/ide/lib/schemas/yaml/index.js
deleted file mode 100644
index e3fc406df4b..00000000000
--- a/app/assets/javascripts/ide/lib/schemas/yaml/index.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import gitlabCi from './gitlab_ci';
-
-export default {
- language: 'yaml',
- options: {
- validate: true,
- enableSchemaRequest: true,
- hover: true,
- completion: true,
- schemas: [gitlabCi],
- },
-};
diff --git a/app/assets/javascripts/ide/services/gql.js b/app/assets/javascripts/ide/services/gql.js
index 211cc78bd99..89dda187360 100644
--- a/app/assets/javascripts/ide/services/gql.js
+++ b/app/assets/javascripts/ide/services/gql.js
@@ -17,5 +17,4 @@ const getClient = memoize(() =>
),
);
-// eslint-disable-next-line import/prefer-default-export
export const query = (...args) => getClient().query(...args);
diff --git a/app/assets/javascripts/ide/services/index.js b/app/assets/javascripts/ide/services/index.js
index ae4a1ba3db5..70a6a6b423d 100644
--- a/app/assets/javascripts/ide/services/index.js
+++ b/app/assets/javascripts/ide/services/index.js
@@ -33,7 +33,7 @@ export default {
})
.then(({ data }) => data);
},
- getBaseRawFileData(file, sha) {
+ getBaseRawFileData(file, projectId, ref) {
if (file.tempFile || file.baseRaw) return Promise.resolve(file.baseRaw);
// if files are renamed, their base path has changed
@@ -44,10 +44,10 @@ export default {
.get(
joinPaths(
gon.relative_url_root || '/',
- file.projectId,
+ projectId,
'-',
'raw',
- sha,
+ ref,
escapeFileUrl(filePath),
),
{
diff --git a/app/assets/javascripts/ide/stores/actions.js b/app/assets/javascripts/ide/stores/actions.js
index b083dc6325f..b8d59f8bd36 100644
--- a/app/assets/javascripts/ide/stores/actions.js
+++ b/app/assets/javascripts/ide/stores/actions.js
@@ -25,15 +25,7 @@ export const setResizingStatus = ({ commit }, resizing) => {
export const createTempEntry = (
{ state, commit, dispatch, getters },
- {
- name,
- type,
- content = '',
- binary = false,
- rawPath = '',
- openFile = true,
- makeFileActive = true,
- },
+ { name, type, content = '', rawPath = '', openFile = true, makeFileActive = true },
) => {
const fullName = name.slice(-1) !== '/' && type === 'tree' ? `${name}/` : name;
@@ -54,21 +46,14 @@ export const createTempEntry = (
const data = decorateFiles({
data: [fullName],
- projectId: state.currentProjectId,
- branchId: state.currentBranchId,
type,
tempFile: true,
content,
- binary,
rawPath,
});
const { file, parentPath } = data;
- commit(types.CREATE_TMP_ENTRY, {
- data,
- projectId: state.currentProjectId,
- branchId: state.currentBranchId,
- });
+ commit(types.CREATE_TMP_ENTRY, { data });
if (type === 'blob') {
if (openFile) commit(types.TOGGLE_FILE_OPEN, file.path);
@@ -90,7 +75,6 @@ export const addTempImage = ({ dispatch, getters }, { name, rawPath = '' }) =>
name: getters.getAvailableFileName(name),
type: 'blob',
content: rawPath.split('base64,')[1],
- binary: true,
rawPath,
openFile: false,
makeFileActive: false,
@@ -254,7 +238,7 @@ export const renameEntry = ({ dispatch, commit, state, getters }, { path, name,
}
if (newEntry.opened) {
- dispatch('router/push', `/project${newEntry.url}`, { root: true });
+ dispatch('router/push', getters.getUrlForPath(newEntry.path), { root: true });
}
}
diff --git a/app/assets/javascripts/ide/stores/actions/file.js b/app/assets/javascripts/ide/stores/actions/file.js
index c0cb924e749..3515d1fc933 100644
--- a/app/assets/javascripts/ide/stores/actions/file.js
+++ b/app/assets/javascripts/ide/stores/actions/file.js
@@ -6,7 +6,7 @@ import * as types from '../mutation_types';
import { setPageTitleForFile } from '../utils';
import { viewerTypes, stageKeys } from '../../constants';
-export const closeFile = ({ commit, state, dispatch }, file) => {
+export const closeFile = ({ commit, state, dispatch, getters }, file) => {
const { path } = file;
const indexOfClosedFile = state.openFiles.findIndex(f => f.key === file.key);
const fileWasActive = file.active;
@@ -29,10 +29,12 @@ export const closeFile = ({ commit, state, dispatch }, file) => {
keyPrefix: nextFileToOpen.staged ? 'staged' : 'unstaged',
});
} else {
- dispatch('router/push', `/project${nextFileToOpen.url}`, { root: true });
+ dispatch('router/push', getters.getUrlForPath(nextFileToOpen.path), { root: true });
}
} else if (!state.openFiles.length) {
- dispatch('router/push', `/project/${file.projectId}/tree/${file.branchId}/`, { root: true });
+ dispatch('router/push', `/project/${state.currentProjectId}/tree/${state.currentBranchId}/`, {
+ root: true,
+ });
}
eventHub.$emit(`editor.update.model.dispose.${file.key}`);
@@ -121,7 +123,7 @@ export const getRawFileData = ({ state, commit, dispatch, getters }, { path }) =
const baseSha =
(getters.currentMergeRequest && getters.currentMergeRequest.baseCommitSha) || '';
- return service.getBaseRawFileData(file, baseSha).then(baseRaw => {
+ return service.getBaseRawFileData(file, state.currentProjectId, baseSha).then(baseRaw => {
commit(types.SET_FILE_BASE_RAW_DATA, {
file,
baseRaw,
@@ -218,7 +220,7 @@ export const discardFileChanges = ({ dispatch, state, commit, getters }, path) =
if (!isDestructiveDiscard && file.path === getters.activeFile?.path) {
dispatch('updateDelayViewerUpdated', true)
.then(() => {
- dispatch('router/push', `/project${file.url}`, { root: true });
+ dispatch('router/push', getters.getUrlForPath(file.path), { root: true });
})
.catch(e => {
throw e;
@@ -274,7 +276,7 @@ export const openPendingTab = ({ commit, dispatch, getters, state }, { file, key
commit(types.ADD_PENDING_TAB, { file, keyPrefix });
- dispatch('router/push', `/project/${file.projectId}/tree/${state.currentBranchId}/`, {
+ dispatch('router/push', `/project/${state.currentProjectId}/tree/${state.currentBranchId}/`, {
root: true,
});
diff --git a/app/assets/javascripts/ide/stores/actions/tree.js b/app/assets/javascripts/ide/stores/actions/tree.js
index 1ca608f1287..3a7daf30cc4 100644
--- a/app/assets/javascripts/ide/stores/actions/tree.js
+++ b/app/assets/javascripts/ide/stores/actions/tree.js
@@ -61,11 +61,7 @@ export const getFiles = ({ state, commit, dispatch }, payload = {}) =>
service
.getFiles(selectedProject.path_with_namespace, ref)
.then(({ data }) => {
- const { entries, treeList } = decorateFiles({
- data,
- projectId,
- branchId,
- });
+ const { entries, treeList } = decorateFiles({ data });
commit(types.SET_ENTRIES, entries);
diff --git a/app/assets/javascripts/ide/stores/getters.js b/app/assets/javascripts/ide/stores/getters.js
index 53734fa626b..b8304a9b68d 100644
--- a/app/assets/javascripts/ide/stores/getters.js
+++ b/app/assets/javascripts/ide/stores/getters.js
@@ -6,6 +6,7 @@ import {
PERMISSION_CREATE_MR,
PERMISSION_PUSH_CODE,
} from '../constants';
+import Api from '~/api';
export const activeFile = state => state.openFiles.find(file => file.active) || null;
@@ -174,3 +175,21 @@ export const getAvailableFileName = (state, getters) => path => {
return newPath;
};
+
+export const getUrlForPath = state => path =>
+ `/project/${state.currentProjectId}/tree/${state.currentBranchId}/-/${path}/`;
+
+export const getJsonSchemaForPath = (state, getters) => path => {
+ const [namespace, ...project] = state.currentProjectId.split('/');
+ return {
+ uri:
+ // eslint-disable-next-line no-restricted-globals
+ location.origin +
+ Api.buildUrl(Api.projectFileSchemaPath)
+ .replace(':namespace_path', namespace)
+ .replace(':project_path', project.join('/'))
+ .replace(':ref', getters.currentBranch?.commit.id || state.currentBranchId)
+ .replace(':filename', path),
+ fileMatch: [`*${path}`],
+ };
+};
diff --git a/app/assets/javascripts/ide/stores/modules/commit/actions.js b/app/assets/javascripts/ide/stores/modules/commit/actions.js
index 277e6923f17..90a6c644d17 100644
--- a/app/assets/javascripts/ide/stores/modules/commit/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/commit/actions.js
@@ -1,6 +1,5 @@
import { sprintf, __ } from '~/locale';
import { deprecatedCreateFlash as flash } from '~/flash';
-import httpStatusCodes from '~/lib/utils/http_status';
import * as rootTypes from '../../mutation_types';
import { createCommitPayload, createNewMergeRequestUrl } from '../../utils';
import service from '../../../services';
@@ -8,6 +7,7 @@ import * as types from './mutation_types';
import consts from './constants';
import { leftSidebarViews } from '../../../constants';
import eventHub from '../../../eventhub';
+import { parseCommitError } from '../../../lib/errors';
export const updateCommitMessage = ({ commit }, message) => {
commit(types.UPDATE_COMMIT_MESSAGE, message);
@@ -113,6 +113,7 @@ export const commitChanges = ({ commit, state, getters, dispatch, rootState, roo
? Promise.resolve()
: dispatch('stageAllChanges', null, { root: true });
+ commit(types.CLEAR_ERROR);
commit(types.UPDATE_LOADING, true);
return stageFilesPromise
@@ -128,6 +129,12 @@ export const commitChanges = ({ commit, state, getters, dispatch, rootState, roo
return service.commit(rootState.currentProjectId, payload);
})
+ .catch(e => {
+ commit(types.UPDATE_LOADING, false);
+ commit(types.SET_ERROR, parseCommitError(e));
+
+ throw e;
+ })
.then(({ data }) => {
commit(types.UPDATE_LOADING, false);
@@ -214,24 +221,5 @@ export const commitChanges = ({ commit, state, getters, dispatch, rootState, roo
{ root: true },
),
);
- })
- .catch(err => {
- commit(types.UPDATE_LOADING, false);
-
- // don't catch bad request errors, let the view handle them
- if (err.response.status === httpStatusCodes.BAD_REQUEST) throw err;
-
- dispatch(
- 'setErrorMessage',
- {
- text: __('An error occurred while committing your changes.'),
- action: () =>
- dispatch('commitChanges').then(() => dispatch('setErrorMessage', null, { root: true })),
- actionText: __('Please try again'),
- },
- { root: true },
- );
-
- window.dispatchEvent(new Event('resize'));
});
};
diff --git a/app/assets/javascripts/ide/stores/modules/commit/mutation_types.js b/app/assets/javascripts/ide/stores/modules/commit/mutation_types.js
index 7ad8f3570b7..47ec2ffbdde 100644
--- a/app/assets/javascripts/ide/stores/modules/commit/mutation_types.js
+++ b/app/assets/javascripts/ide/stores/modules/commit/mutation_types.js
@@ -3,3 +3,6 @@ export const UPDATE_COMMIT_ACTION = 'UPDATE_COMMIT_ACTION';
export const UPDATE_NEW_BRANCH_NAME = 'UPDATE_NEW_BRANCH_NAME';
export const UPDATE_LOADING = 'UPDATE_LOADING';
export const TOGGLE_SHOULD_CREATE_MR = 'TOGGLE_SHOULD_CREATE_MR';
+
+export const CLEAR_ERROR = 'CLEAR_ERROR';
+export const SET_ERROR = 'SET_ERROR';
diff --git a/app/assets/javascripts/ide/stores/modules/commit/mutations.js b/app/assets/javascripts/ide/stores/modules/commit/mutations.js
index 73b618e250f..2cf6e8e6f36 100644
--- a/app/assets/javascripts/ide/stores/modules/commit/mutations.js
+++ b/app/assets/javascripts/ide/stores/modules/commit/mutations.js
@@ -24,4 +24,10 @@ export default {
shouldCreateMR: shouldCreateMR === undefined ? !state.shouldCreateMR : shouldCreateMR,
});
},
+ [types.CLEAR_ERROR](state) {
+ state.commitError = null;
+ },
+ [types.SET_ERROR](state, error) {
+ state.commitError = error;
+ },
};
diff --git a/app/assets/javascripts/ide/stores/modules/commit/state.js b/app/assets/javascripts/ide/stores/modules/commit/state.js
index f49737485f2..de092a569ad 100644
--- a/app/assets/javascripts/ide/stores/modules/commit/state.js
+++ b/app/assets/javascripts/ide/stores/modules/commit/state.js
@@ -4,4 +4,5 @@ export default () => ({
newBranchName: '',
submitCommitLoading: false,
shouldCreateMR: true,
+ commitError: null,
});
diff --git a/app/assets/javascripts/ide/stores/modules/pane/getters.js b/app/assets/javascripts/ide/stores/modules/pane/getters.js
index 7816172bb6f..ce597329df1 100644
--- a/app/assets/javascripts/ide/stores/modules/pane/getters.js
+++ b/app/assets/javascripts/ide/stores/modules/pane/getters.js
@@ -1,3 +1,2 @@
-// eslint-disable-next-line import/prefer-default-export
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 86b889546b0..99bd08ee876 100644
--- a/app/assets/javascripts/ide/stores/modules/pipelines/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/pipelines/actions.js
@@ -118,31 +118,31 @@ export const setDetailJob = ({ commit, dispatch }, job) => {
});
};
-export const requestJobTrace = ({ commit }) => commit(types.REQUEST_JOB_TRACE);
-export const receiveJobTraceError = ({ commit, dispatch }) => {
+export const requestJobLogs = ({ commit }) => commit(types.REQUEST_JOB_LOGS);
+export const receiveJobLogsError = ({ commit, dispatch }) => {
dispatch(
'setErrorMessage',
{
- text: __('An error occurred while fetching the job trace.'),
+ text: __('An error occurred while fetching the job logs.'),
action: () =>
- dispatch('fetchJobTrace').then(() => dispatch('setErrorMessage', null, { root: true })),
+ dispatch('fetchJobLogs').then(() => dispatch('setErrorMessage', null, { root: true })),
actionText: __('Please try again'),
actionPayload: null,
},
{ root: true },
);
- commit(types.RECEIVE_JOB_TRACE_ERROR);
+ commit(types.RECEIVE_JOB_LOGS_ERROR);
};
-export const receiveJobTraceSuccess = ({ commit }, data) =>
- commit(types.RECEIVE_JOB_TRACE_SUCCESS, data);
+export const receiveJobLogsSuccess = ({ commit }, data) =>
+ commit(types.RECEIVE_JOB_LOGS_SUCCESS, data);
-export const fetchJobTrace = ({ dispatch, state }) => {
- dispatch('requestJobTrace');
+export const fetchJobLogs = ({ dispatch, state }) => {
+ dispatch('requestJobLogs');
return axios
.get(`${state.detailJob.path}/trace`, { params: { format: 'json' } })
- .then(({ data }) => dispatch('receiveJobTraceSuccess', data))
- .catch(() => dispatch('receiveJobTraceError'));
+ .then(({ data }) => dispatch('receiveJobLogsSuccess', data))
+ .catch(() => dispatch('receiveJobLogsError'));
};
export const resetLatestPipeline = ({ commit }) => {
diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/constants.js b/app/assets/javascripts/ide/stores/modules/pipelines/constants.js
index f5b96327e40..bb4145934ff 100644
--- a/app/assets/javascripts/ide/stores/modules/pipelines/constants.js
+++ b/app/assets/javascripts/ide/stores/modules/pipelines/constants.js
@@ -1,4 +1,3 @@
-// eslint-disable-next-line import/prefer-default-export
export const states = {
failed: 'failed',
};
diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/mutation_types.js b/app/assets/javascripts/ide/stores/modules/pipelines/mutation_types.js
index f4c36b9d96f..fea3055e0fe 100644
--- a/app/assets/javascripts/ide/stores/modules/pipelines/mutation_types.js
+++ b/app/assets/javascripts/ide/stores/modules/pipelines/mutation_types.js
@@ -10,6 +10,6 @@ export const TOGGLE_STAGE_COLLAPSE = 'TOGGLE_STAGE_COLLAPSE';
export const SET_DETAIL_JOB = 'SET_DETAIL_JOB';
-export const REQUEST_JOB_TRACE = 'REQUEST_JOB_TRACE';
-export const RECEIVE_JOB_TRACE_ERROR = 'RECEIVE_JOB_TRACE_ERROR';
-export const RECEIVE_JOB_TRACE_SUCCESS = 'RECEIVE_JOB_TRACE_SUCCESS';
+export const REQUEST_JOB_LOGS = 'REQUEST_JOB_LOGS';
+export const RECEIVE_JOB_LOGS_ERROR = 'RECEIVE_JOB_LOGS_ERROR';
+export const RECEIVE_JOB_LOGS_SUCCESS = 'RECEIVE_JOB_LOGS_SUCCESS';
diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/mutations.js b/app/assets/javascripts/ide/stores/modules/pipelines/mutations.js
index eaaa82cb339..3a3cb4a7cb2 100644
--- a/app/assets/javascripts/ide/stores/modules/pipelines/mutations.js
+++ b/app/assets/javascripts/ide/stores/modules/pipelines/mutations.js
@@ -66,13 +66,13 @@ export default {
[types.SET_DETAIL_JOB](state, job) {
state.detailJob = { ...job };
},
- [types.REQUEST_JOB_TRACE](state) {
+ [types.REQUEST_JOB_LOGS](state) {
state.detailJob.isLoading = true;
},
- [types.RECEIVE_JOB_TRACE_ERROR](state) {
+ [types.RECEIVE_JOB_LOGS_ERROR](state) {
state.detailJob.isLoading = false;
},
- [types.RECEIVE_JOB_TRACE_SUCCESS](state, data) {
+ [types.RECEIVE_JOB_LOGS_SUCCESS](state, data) {
state.detailJob.isLoading = false;
state.detailJob.output = data.html;
},
diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/utils.js b/app/assets/javascripts/ide/stores/modules/pipelines/utils.js
index a6caca2d2dc..95716e0a0c6 100644
--- a/app/assets/javascripts/ide/stores/modules/pipelines/utils.js
+++ b/app/assets/javascripts/ide/stores/modules/pipelines/utils.js
@@ -1,4 +1,3 @@
-// eslint-disable-next-line import/prefer-default-export
export const normalizeJob = job => ({
id: job.id,
name: job.name,
diff --git a/app/assets/javascripts/ide/stores/modules/router/actions.js b/app/assets/javascripts/ide/stores/modules/router/actions.js
index 849067599f2..321ac57817f 100644
--- a/app/assets/javascripts/ide/stores/modules/router/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/router/actions.js
@@ -1,6 +1,5 @@
import * as types from './mutation_types';
-// eslint-disable-next-line import/prefer-default-export
export const push = ({ commit }, fullPath) => {
commit(types.PUSH, fullPath);
};
diff --git a/app/assets/javascripts/ide/stores/modules/router/mutation_types.js b/app/assets/javascripts/ide/stores/modules/router/mutation_types.js
index ae99073cc4c..8f5f949bd5f 100644
--- a/app/assets/javascripts/ide/stores/modules/router/mutation_types.js
+++ b/app/assets/javascripts/ide/stores/modules/router/mutation_types.js
@@ -1,2 +1 @@
-// eslint-disable-next-line import/prefer-default-export
export const PUSH = 'PUSH';
diff --git a/app/assets/javascripts/ide/stores/modules/terminal/getters.js b/app/assets/javascripts/ide/stores/modules/terminal/getters.js
index ef98547ccc4..b29d391845d 100644
--- a/app/assets/javascripts/ide/stores/modules/terminal/getters.js
+++ b/app/assets/javascripts/ide/stores/modules/terminal/getters.js
@@ -1,4 +1,3 @@
-// eslint-disable-next-line import/prefer-default-export
export const allCheck = state => {
const checks = Object.values(state.checks);
diff --git a/app/assets/javascripts/ide/stores/mutations.js b/app/assets/javascripts/ide/stores/mutations.js
index c64839e5019..460d3ced381 100644
--- a/app/assets/javascripts/ide/stores/mutations.js
+++ b/app/assets/javascripts/ide/stores/mutations.js
@@ -7,7 +7,6 @@ import treeMutations from './mutations/tree';
import branchMutations from './mutations/branch';
import {
sortTree,
- replaceFileUrl,
swapInParentTreeWithSorting,
updateFileCollections,
removeFromParentTree,
@@ -49,7 +48,7 @@ export default {
entries,
});
},
- [types.CREATE_TMP_ENTRY](state, { data, projectId, branchId }) {
+ [types.CREATE_TMP_ENTRY](state, { data }) {
Object.keys(data.entries).reduce((acc, key) => {
const entry = data.entries[key];
const foundEntry = state.entries[key];
@@ -72,13 +71,12 @@ export default {
return acc.concat(key);
}, []);
- const foundEntry = state.trees[`${projectId}/${branchId}`].tree.find(
- e => e.path === data.treeList[0].path,
- );
+ const currentTree = state.trees[`${state.currentProjectId}/${state.currentBranchId}`];
+ const foundEntry = currentTree.tree.find(e => e.path === data.treeList[0].path);
if (!foundEntry) {
- Object.assign(state.trees[`${projectId}/${branchId}`], {
- tree: sortTree(state.trees[`${projectId}/${branchId}`].tree.concat(data.treeList)),
+ Object.assign(currentTree, {
+ tree: sortTree(currentTree.tree.concat(data.treeList)),
});
}
},
@@ -139,7 +137,6 @@ export default {
prevId: undefined,
prevPath: undefined,
prevName: undefined,
- prevUrl: undefined,
prevKey: undefined,
prevParentPath: undefined,
});
@@ -195,9 +192,6 @@ export default {
const oldEntry = state.entries[path];
const newPath = parentPath ? `${parentPath}/${name}` : name;
const isRevert = newPath === oldEntry.prevPath;
-
- const newUrl = replaceFileUrl(oldEntry.url, oldEntry.path, newPath);
-
const newKey = oldEntry.key.replace(new RegExp(oldEntry.path, 'g'), newPath);
const baseProps = {
@@ -205,7 +199,6 @@ export default {
name,
id: newPath,
path: newPath,
- url: newUrl,
key: newKey,
parentPath: parentPath || '',
};
@@ -216,7 +209,6 @@ export default {
prevId: undefined,
prevPath: undefined,
prevName: undefined,
- prevUrl: undefined,
prevKey: undefined,
prevParentPath: undefined,
}
@@ -224,7 +216,6 @@ export default {
prevId: oldEntry.prevId || oldEntry.id,
prevPath: oldEntry.prevPath || oldEntry.path,
prevName: oldEntry.prevName || oldEntry.name,
- prevUrl: oldEntry.prevUrl || oldEntry.url,
prevKey: oldEntry.prevKey || oldEntry.key,
prevParentPath: oldEntry.prevParentPath || oldEntry.parentPath,
};
diff --git a/app/assets/javascripts/ide/stores/utils.js b/app/assets/javascripts/ide/stores/utils.js
index f074e6880d0..d9cdc7727ad 100644
--- a/app/assets/javascripts/ide/stores/utils.js
+++ b/app/assets/javascripts/ide/stores/utils.js
@@ -12,10 +12,7 @@ export const dataStructure = () => ({
// it can also contain a prefix `pending-` for files opened in review mode
key: '',
type: '',
- projectId: '',
- branchId: '',
name: '',
- url: '',
path: '',
tempFile: false,
tree: [],
@@ -26,7 +23,6 @@ export const dataStructure = () => ({
staged: false,
lastCommitSha: '',
rawPath: '',
- binary: false,
raw: '',
content: '',
editorRow: 1,
@@ -44,10 +40,7 @@ export const dataStructure = () => ({
export const decorateData = entity => {
const {
id,
- projectId,
- branchId,
type,
- url,
name,
path,
content = '',
@@ -55,7 +48,6 @@ export const decorateData = entity => {
active = false,
opened = false,
changed = false,
- binary = false,
rawPath = '',
file_lock,
parentPath = '',
@@ -63,19 +55,15 @@ export const decorateData = entity => {
return Object.assign(dataStructure(), {
id,
- projectId,
- branchId,
key: `${name}-${type}-${id}`,
type,
name,
- url,
path,
tempFile,
opened,
active,
changed,
content,
- binary,
rawPath,
file_lock,
parentPath,
@@ -189,11 +177,6 @@ export const mergeTrees = (fromTree, toTree) => {
return toTree;
};
-export const replaceFileUrl = (url, oldPath, newPath) => {
- // Add `/-/` so that we don't accidentally replace project path
- return url.replace(`/-/${oldPath}`, `/-/${newPath}`);
-};
-
export const swapInStateArray = (state, arr, key, entryPath) =>
Object.assign(state, {
[arr]: state[arr].map(f => (f.key === key ? state.entries[entryPath] : f)),
diff --git a/app/assets/javascripts/ide/sync_router_and_store.js b/app/assets/javascripts/ide/sync_router_and_store.js
index 1782c32b3b2..b33bcbb94ea 100644
--- a/app/assets/javascripts/ide/sync_router_and_store.js
+++ b/app/assets/javascripts/ide/sync_router_and_store.js
@@ -1,4 +1,3 @@
-/* eslint-disable import/prefer-default-export */
/**
* This method adds listeners to the given router and store and syncs their state with eachother
*
diff --git a/app/assets/javascripts/ide/utils.js b/app/assets/javascripts/ide/utils.js
index 58a6712c232..cde53e1ef00 100644
--- a/app/assets/javascripts/ide/utils.js
+++ b/app/assets/javascripts/ide/utils.js
@@ -1,5 +1,5 @@
import { languages } from 'monaco-editor';
-import { flatten } from 'lodash';
+import { flatten, isString } from 'lodash';
import { SIDE_LEFT, SIDE_RIGHT } from './constants';
const toLowerCase = x => x.toLowerCase();
@@ -42,15 +42,16 @@ const KNOWN_TYPES = [
},
];
-export function isTextFile(content, mimeType, fileName) {
- const knownType = KNOWN_TYPES.find(type => type.isMatch(mimeType, fileName));
+export function isTextFile({ name, content, mimeType = '' }) {
+ 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)
const asciiRegex = /^[ -~\t\n\r]+$/;
+
// for unknown types, determine the type by evaluating the file contents
- return asciiRegex.test(content);
+ return isString(content) && (content === '' || asciiRegex.test(content));
}
export const createPathWithExt = p => {
@@ -75,17 +76,17 @@ export function registerLanguages(def, ...defs) {
languages.setLanguageConfiguration(languageId, def.conf);
}
-export function registerSchemas({ language, options }, ...schemas) {
- schemas.forEach(schema => registerSchemas(schema));
-
- const defaults = {
- json: languages.json.jsonDefaults,
- yaml: languages.yaml.yamlDefaults,
- };
-
- if (defaults[language]) {
- defaults[language].setDiagnosticsOptions(options);
- }
+export function registerSchema(schema) {
+ const defaults = [languages.json.jsonDefaults, languages.yaml.yamlDefaults];
+ defaults.forEach(d =>
+ d.setDiagnosticsOptions({
+ validate: true,
+ enableSchemaRequest: true,
+ hover: true,
+ completion: true,
+ schemas: [schema],
+ }),
+ );
}
export const otherSide = side => (side === SIDE_RIGHT ? SIDE_LEFT : SIDE_RIGHT);