diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-12-17 11:59:07 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-12-17 11:59:07 +0000 |
commit | 8b573c94895dc0ac0e1d9d59cf3e8745e8b539ca (patch) | |
tree | 544930fb309b30317ae9797a9683768705d664c4 /app/assets/javascripts/ide | |
parent | 4b1de649d0168371549608993deac953eb692019 (diff) | |
download | gitlab-ce-8b573c94895dc0ac0e1d9d59cf3e8745e8b539ca.tar.gz |
Add latest changes from gitlab-org/gitlab@13-7-stable-eev13.7.0-rc42
Diffstat (limited to 'app/assets/javascripts/ide')
22 files changed, 189 insertions, 124 deletions
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/form.vue b/app/assets/javascripts/ide/components/commit_sidebar/form.vue index 9d2deb1d4d0..7c3e522a488 100644 --- a/app/assets/javascripts/ide/components/commit_sidebar/form.vue +++ b/app/assets/javascripts/ide/components/commit_sidebar/form.vue @@ -134,15 +134,17 @@ export default { @after-enter="afterEndTransition" > <div v-if="isCompact" ref="compactEl" class="commit-form-compact"> - <button + <gl-button :disabled="!someUncommittedChanges" - type="button" - class="btn btn-primary btn-sm btn-block qa-begin-commit-button" + category="primary" + variant="info" + block + class="qa-begin-commit-button" data-testid="begin-commit-button" @click="beginCommit" > {{ __('Commit…') }} - </button> + </gl-button> <p class="text-center bold">{{ overviewText }}</p> </div> <form v-else ref="formEl" @submit.prevent.stop="commit"> @@ -158,28 +160,21 @@ export default { <gl-button :loading="submitCommitLoading" class="float-left qa-commit-button" - size="small" category="primary" variant="success" @click="commit" > {{ __('Commit') }} </gl-button> - <button - v-if="!discardDraftButtonDisabled" - type="button" - class="btn btn-default btn-sm float-right" - @click="discardDraft" - > + <gl-button v-if="!discardDraftButtonDisabled" class="float-right" @click="discardDraft"> {{ __('Discard draft') }} - </button> + </gl-button> <gl-button v-else type="button" class="float-right" category="secondary" variant="default" - size="small" @click="toggleIsCompact" > {{ __('Collapse') }} 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 7d08815b033..8f0e5aef456 100644 --- a/app/assets/javascripts/ide/components/commit_sidebar/message_field.vue +++ b/app/assets/javascripts/ide/components/commit_sidebar/message_field.vue @@ -1,13 +1,9 @@ <script> import { GlIcon, GlPopover } from '@gitlab/ui'; import { __, sprintf } from '../../../locale'; -import popover from '../../../vue_shared/directives/popover'; import { MAX_TITLE_LENGTH, MAX_BODY_LENGTH } from '../../constants'; export default { - directives: { - popover, - }, components: { GlIcon, GlPopover, diff --git a/app/assets/javascripts/ide/components/editor_mode_dropdown.vue b/app/assets/javascripts/ide/components/editor_mode_dropdown.vue index dec8aa61838..52593aabfea 100644 --- a/app/assets/javascripts/ide/components/editor_mode_dropdown.vue +++ b/app/assets/javascripts/ide/components/editor_mode_dropdown.vue @@ -1,11 +1,12 @@ <script> -import { GlButton } from '@gitlab/ui'; +import { GlDropdown, GlDropdownItem } from '@gitlab/ui'; import { __, sprintf } from '~/locale'; import { viewerTypes } from '../constants'; export default { components: { - GlButton, + GlDropdown, + GlDropdownItem, }, props: { viewer: { @@ -18,10 +19,21 @@ export default { }, }, computed: { - mergeReviewLine() { - return sprintf(__('Reviewing (merge request !%{mergeRequestId})'), { - mergeRequestId: this.mergeRequestId, - }); + modeDropdownItems() { + return [ + { + viewerType: this.$options.viewerTypes.mr, + title: sprintf(__('Reviewing (merge request !%{mergeRequestId})'), { + mergeRequestId: this.mergeRequestId, + }), + content: __('Compare changes with the merge request target branch'), + }, + { + viewerType: this.$options.viewerTypes.diff, + title: __('Reviewing'), + content: __('Compare changes with the last commit'), + }, + ]; }, }, methods: { @@ -34,39 +46,16 @@ export default { </script> <template> - <div class="dropdown"> - <gl-button variant="link" data-toggle="dropdown">{{ __('Edit') }}</gl-button> - <div class="dropdown-menu dropdown-menu-selectable dropdown-open-left"> - <ul> - <li> - <a - :class="{ - 'is-active': viewer === $options.viewerTypes.mr, - }" - href="#" - @click.prevent="changeMode($options.viewerTypes.mr)" - > - <strong class="dropdown-menu-inner-title"> {{ mergeReviewLine }} </strong> - <span class="dropdown-menu-inner-content"> - {{ __('Compare changes with the merge request target branch') }} - </span> - </a> - </li> - <li> - <a - :class="{ - 'is-active': viewer === $options.viewerTypes.diff, - }" - href="#" - @click.prevent="changeMode($options.viewerTypes.diff)" - > - <strong class="dropdown-menu-inner-title">{{ __('Reviewing') }}</strong> - <span class="dropdown-menu-inner-content"> - {{ __('Compare changes with the last commit') }} - </span> - </a> - </li> - </ul> - </div> - </div> + <gl-dropdown :text="__('Edit')" size="small"> + <gl-dropdown-item + v-for="mode in modeDropdownItems" + :key="mode.viewerType" + :is-check-item="true" + :is-checked="viewer === mode.viewerType" + @click="changeMode(mode.viewerType)" + > + <strong class="dropdown-menu-inner-title"> {{ mode.title }} </strong> + <span class="dropdown-menu-inner-content"> {{ mode.content }} </span> + </gl-dropdown-item> + </gl-dropdown> </template> diff --git a/app/assets/javascripts/ide/components/file_templates/dropdown.vue b/app/assets/javascripts/ide/components/file_templates/dropdown.vue index cfd2555b769..5d5b66a6444 100644 --- a/app/assets/javascripts/ide/components/file_templates/dropdown.vue +++ b/app/assets/javascripts/ide/components/file_templates/dropdown.vue @@ -86,7 +86,7 @@ export default { type="search" class="dropdown-input-field qa-dropdown-filter-input" /> - <gl-icon name="search" class="dropdown-input-search" aria-hidden="true" /> + <gl-icon name="search" class="dropdown-input-search" /> </div> <div class="dropdown-content"> <gl-loading-icon v-if="showLoading" size="lg" /> diff --git a/app/assets/javascripts/ide/components/ide.vue b/app/assets/javascripts/ide/components/ide.vue index e1d2895831a..f8568f46cd6 100644 --- a/app/assets/javascripts/ide/components/ide.vue +++ b/app/assets/javascripts/ide/components/ide.vue @@ -1,14 +1,13 @@ <script> import { mapActions, mapGetters, mapState } from 'vuex'; +import { GlButton, GlLoadingIcon } from '@gitlab/ui'; import { __ } from '~/locale'; import { WEBIDE_MARK_APP_START, WEBIDE_MARK_FILE_FINISH, WEBIDE_MARK_FILE_CLICKED, - WEBIDE_MARK_TREE_FINISH, - WEBIDE_MEASURE_TREE_FROM_REQUEST, - WEBIDE_MEASURE_FILE_FROM_REQUEST, WEBIDE_MEASURE_FILE_AFTER_INTERACTION, + WEBIDE_MEASURE_BEFORE_VUE, } from '~/performance/constants'; import { performanceMarkAndMeasure } from '~/performance/utils'; import { modalTypes } from '../constants'; @@ -19,12 +18,6 @@ import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { measurePerformance } from '../utils'; -eventHub.$on(WEBIDE_MEASURE_TREE_FROM_REQUEST, () => - measurePerformance(WEBIDE_MARK_TREE_FINISH, WEBIDE_MEASURE_TREE_FROM_REQUEST), -); -eventHub.$on(WEBIDE_MEASURE_FILE_FROM_REQUEST, () => - measurePerformance(WEBIDE_MARK_FILE_FINISH, WEBIDE_MEASURE_FILE_FROM_REQUEST), -); eventHub.$on(WEBIDE_MEASURE_FILE_AFTER_INTERACTION, () => measurePerformance( WEBIDE_MARK_FILE_FINISH, @@ -37,15 +30,17 @@ export default { components: { IdeSidebar, RepoEditor, - 'error-message': () => import('./error_message.vue'), - 'gl-button': () => import('@gitlab/ui/src/components/base/button/button.vue'), - 'gl-loading-icon': () => import('@gitlab/ui/src/components/base/loading_icon/loading_icon.vue'), - 'commit-editor-header': () => import('./commit_sidebar/editor_header.vue'), - 'repo-tabs': () => import('./repo_tabs.vue'), - 'ide-status-bar': () => import('./ide_status_bar.vue'), - 'find-file': () => import('~/vue_shared/components/file_finder/index.vue'), - 'right-pane': () => import('./panes/right.vue'), - 'new-modal': () => import('./new_dropdown/modal.vue'), + GlButton, + GlLoadingIcon, + ErrorMessage: () => import(/* webpackChunkName: 'ide_runtime' */ './error_message.vue'), + CommitEditorHeader: () => + import(/* webpackChunkName: 'ide_runtime' */ './commit_sidebar/editor_header.vue'), + RepoTabs: () => import(/* webpackChunkName: 'ide_runtime' */ './repo_tabs.vue'), + IdeStatusBar: () => import(/* webpackChunkName: 'ide_runtime' */ './ide_status_bar.vue'), + FindFile: () => + import(/* webpackChunkName: 'ide_runtime' */ '~/vue_shared/components/file_finder/index.vue'), + RightPane: () => import(/* webpackChunkName: 'ide_runtime' */ './panes/right.vue'), + NewModal: () => import(/* webpackChunkName: 'ide_runtime' */ './new_dropdown/modal.vue'), }, mixins: [glFeatureFlagsMixin()], data() { @@ -84,7 +79,14 @@ export default { document.querySelector('.navbar-gitlab').classList.add(`theme-${this.themeName}`); }, beforeCreate() { - performanceMarkAndMeasure({ mark: WEBIDE_MARK_APP_START }); + performanceMarkAndMeasure({ + mark: WEBIDE_MARK_APP_START, + measures: [ + { + name: WEBIDE_MEASURE_BEFORE_VUE, + }, + ], + }); }, methods: { ...mapActions(['toggleFileFinder']), diff --git a/app/assets/javascripts/ide/components/ide_side_bar.vue b/app/assets/javascripts/ide/components/ide_side_bar.vue index 99215d6c3f1..135b28685ed 100644 --- a/app/assets/javascripts/ide/components/ide_side_bar.vue +++ b/app/assets/javascripts/ide/components/ide_side_bar.vue @@ -14,8 +14,10 @@ export default { ResizablePanel, ActivityBar, IdeTree, - [leftSidebarViews.review.name]: () => import('./ide_review.vue'), - [leftSidebarViews.commit.name]: () => import('./repo_commit_section.vue'), + [leftSidebarViews.review.name]: () => + import(/* webpackChunkName: 'ide_runtime' */ './ide_review.vue'), + [leftSidebarViews.commit.name]: () => + import(/* webpackChunkName: 'ide_runtime' */ './repo_commit_section.vue'), CommitForm, IdeProjectHeader, }, diff --git a/app/assets/javascripts/ide/components/ide_tree_list.vue b/app/assets/javascripts/ide/components/ide_tree_list.vue index e7e94f5b5da..b67881b14f4 100644 --- a/app/assets/javascripts/ide/components/ide_tree_list.vue +++ b/app/assets/javascripts/ide/components/ide_tree_list.vue @@ -2,17 +2,13 @@ import { mapActions, mapGetters, mapState } from 'vuex'; import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui'; import FileTree from '~/vue_shared/components/file_tree.vue'; -import { - WEBIDE_MARK_TREE_START, - WEBIDE_MEASURE_TREE_FROM_REQUEST, - WEBIDE_MARK_FILE_CLICKED, -} from '~/performance/constants'; +import { WEBIDE_MARK_FILE_CLICKED } from '~/performance/constants'; import { performanceMarkAndMeasure } from '~/performance/utils'; -import eventHub from '../eventhub'; import IdeFileRow from './ide_file_row.vue'; import NavDropdown from './nav_dropdown.vue'; export default { + name: 'IdeTreeList', components: { GlSkeletonLoading, NavDropdown, @@ -39,14 +35,6 @@ export default { } }, }, - beforeCreate() { - performanceMarkAndMeasure({ mark: WEBIDE_MARK_TREE_START }); - }, - updated() { - if (this.currentTree?.tree?.length) { - eventHub.$emit(WEBIDE_MEASURE_TREE_FROM_REQUEST); - } - }, methods: { ...mapActions(['toggleTreeOpen']), clickedFile() { diff --git a/app/assets/javascripts/ide/components/jobs/detail.vue b/app/assets/javascripts/ide/components/jobs/detail.vue index d65304034c2..7f07a5dbe43 100644 --- a/app/assets/javascripts/ide/components/jobs/detail.vue +++ b/app/assets/javascripts/ide/components/jobs/detail.vue @@ -92,7 +92,7 @@ export default { class="controllers-buttons" target="_blank" > - <gl-icon name="doc-text" aria-hidden="true" /> + <gl-icon name="doc-text" /> </a> <scroll-button :disabled="isScrolledToTop" direction="up" @click="scrollUp" /> <scroll-button :disabled="isScrolledToBottom" direction="down" @click="scrollDown" /> diff --git a/app/assets/javascripts/ide/components/nav_dropdown.vue b/app/assets/javascripts/ide/components/nav_dropdown.vue index 2307efd1d24..8cea8655461 100644 --- a/app/assets/javascripts/ide/components/nav_dropdown.vue +++ b/app/assets/javascripts/ide/components/nav_dropdown.vue @@ -30,6 +30,7 @@ export default { .on('hide.bs.dropdown', () => this.hideDropdown()); }, removeDropdownListeners() { + // eslint-disable-next-line @gitlab/no-global-event-off $(this.$refs.dropdown) .off('show.bs.dropdown') .off('hide.bs.dropdown'); @@ -45,7 +46,7 @@ export default { </script> <template> - <div ref="dropdown" class="btn-group ide-nav-dropdown dropdown"> + <div ref="dropdown" class="btn-group ide-nav-dropdown dropdown" data-testid="ide-nav-dropdown"> <nav-dropdown-button :show-merge-requests="canReadMergeRequests" /> <div class="dropdown-menu dropdown-menu-left p-0"> <nav-form v-if="isVisibleDropdown" :show-merge-requests="canReadMergeRequests" /> diff --git a/app/assets/javascripts/ide/components/new_dropdown/modal.vue b/app/assets/javascripts/ide/components/new_dropdown/modal.vue index 5ad836f346a..22eefb6634f 100644 --- a/app/assets/javascripts/ide/components/new_dropdown/modal.vue +++ b/app/assets/javascripts/ide/components/new_dropdown/modal.vue @@ -137,6 +137,7 @@ export default { ref="modal" modal-id="ide-new-entry" data-qa-selector="new_file_modal" + data-testid="ide-new-entry" :title="modalTitle" :ok-title="buttonLabel" ok-variant="success" diff --git a/app/assets/javascripts/ide/components/pipelines/list.vue b/app/assets/javascripts/ide/components/pipelines/list.vue index 6f15773c9ab..a4a13389fbf 100644 --- a/app/assets/javascripts/ide/components/pipelines/list.vue +++ b/app/assets/javascripts/ide/components/pipelines/list.vue @@ -8,6 +8,7 @@ import { GlTabs, GlTab, GlBadge, + GlAlert, } from '@gitlab/ui'; import { sprintf, __ } from '../../../locale'; import CiIcon from '../../../vue_shared/components/ci_icon.vue'; @@ -26,6 +27,7 @@ export default { GlTabs, GlTab, GlBadge, + GlAlert, }, directives: { SafeHtml, @@ -89,11 +91,16 @@ export default { :can-set-ci="true" class="mb-auto mt-auto" /> - <div v-else-if="latestPipeline.yamlError" class="bs-callout bs-callout-danger"> + <gl-alert + v-else-if="latestPipeline.yamlError" + variant="danger" + :dismissible="false" + class="gl-mt-5" + > <p class="gl-mb-0">{{ __('Found errors in your .gitlab-ci.yml:') }}</p> <p class="gl-mb-0 break-word">{{ latestPipeline.yamlError }}</p> <p v-safe-html="ciLintText" class="gl-mb-0"></p> - </div> + </gl-alert> <gl-tabs v-else> <gl-tab :active="!pipelineFailed"> <template #title> diff --git a/app/assets/javascripts/ide/components/preview/clientside.vue b/app/assets/javascripts/ide/components/preview/clientside.vue index 3852f2fdfa4..f65b1201d94 100644 --- a/app/assets/javascripts/ide/components/preview/clientside.vue +++ b/app/assets/javascripts/ide/components/preview/clientside.vue @@ -152,7 +152,7 @@ export default { </script> <template> - <div class="preview h-100 w-100 d-flex flex-column"> + <div class="preview h-100 w-100 d-flex flex-column gl-bg-white"> <template v-if="showPreview"> <navigator :manager="manager" /> <div id="ide-preview"></div> diff --git a/app/assets/javascripts/ide/components/repo_editor.vue b/app/assets/javascripts/ide/components/repo_editor.vue index c8a825065f1..1f029612c29 100644 --- a/app/assets/javascripts/ide/components/repo_editor.vue +++ b/app/assets/javascripts/ide/components/repo_editor.vue @@ -6,9 +6,10 @@ import ContentViewer from '~/vue_shared/components/content_viewer/content_viewer import DiffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue'; import { WEBIDE_MARK_FILE_CLICKED, - WEBIDE_MARK_FILE_START, + WEBIDE_MARK_REPO_EDITOR_START, + WEBIDE_MARK_REPO_EDITOR_FINISH, + WEBIDE_MEASURE_REPO_EDITOR, WEBIDE_MEASURE_FILE_AFTER_INTERACTION, - WEBIDE_MEASURE_FILE_FROM_REQUEST, } from '~/performance/constants'; import { performanceMarkAndMeasure } from '~/performance/utils'; import eventHub from '../eventhub'; @@ -28,6 +29,7 @@ import { getRulesWithTraversal } from '../lib/editorconfig/parser'; import mapRulesToMonaco from '../lib/editorconfig/rules_mapper'; export default { + name: 'RepoEditor', components: { ContentViewer, DiffViewer, @@ -175,9 +177,6 @@ export default { } }, }, - beforeCreate() { - performanceMarkAndMeasure({ mark: WEBIDE_MARK_FILE_START }); - }, beforeDestroy() { this.editor.dispose(); }, @@ -204,6 +203,7 @@ export default { ]), ...mapActions('editor', ['updateFileEditor']), initEditor() { + performanceMarkAndMeasure({ mark: WEBIDE_MARK_REPO_EDITOR_START }); if (this.shouldHideEditor && (this.file.content || this.file.raw)) { return; } @@ -305,7 +305,15 @@ export default { if (performance.getEntriesByName(WEBIDE_MARK_FILE_CLICKED).length) { eventHub.$emit(WEBIDE_MEASURE_FILE_AFTER_INTERACTION); } else { - eventHub.$emit(WEBIDE_MEASURE_FILE_FROM_REQUEST); + performanceMarkAndMeasure({ + mark: WEBIDE_MARK_REPO_EDITOR_FINISH, + measures: [ + { + name: WEBIDE_MEASURE_REPO_EDITOR, + start: WEBIDE_MARK_REPO_EDITOR_START, + }, + ], + }); } }, refreshEditorDimensions() { diff --git a/app/assets/javascripts/ide/components/terminal/session.vue b/app/assets/javascripts/ide/components/terminal/session.vue index a8fe9ea6866..0e67a2ab45f 100644 --- a/app/assets/javascripts/ide/components/terminal/session.vue +++ b/app/assets/javascripts/ide/components/terminal/session.vue @@ -1,5 +1,6 @@ <script> import { mapActions, mapState } from 'vuex'; +import { GlButton } from '@gitlab/ui'; import { __ } from '~/locale'; import Terminal from './terminal.vue'; import { isEndingStatus } from '../../stores/modules/terminal/utils'; @@ -7,6 +8,7 @@ import { isEndingStatus } from '../../stores/modules/terminal/utils'; export default { components: { Terminal, + GlButton, }, computed: { ...mapState('terminal', ['session']), @@ -14,15 +16,17 @@ export default { if (isEndingStatus(this.session.status)) { return { action: () => this.restartSession(), + variant: 'info', + category: 'primary', text: __('Restart Terminal'), - class: 'btn-primary', }; } return { action: () => this.stopSession(), + variant: 'danger', + category: 'secondary', text: __('Stop Terminal'), - class: 'btn-inverted btn-remove', }; }, }, @@ -37,15 +41,13 @@ export default { <header class="ide-job-header d-flex align-items-center"> <h5>{{ __('Web Terminal') }}</h5> <div class="ml-auto align-self-center"> - <button + <gl-button v-if="actionButton" - type="button" - class="btn btn-sm" - :class="actionButton.class" + :variant="actionButton.variant" + :category="actionButton.category" @click="actionButton.action" + >{{ actionButton.text }}</gl-button > - {{ actionButton.text }} - </button> </div> </header> <terminal :terminal-path="session.terminalPath" :status="session.status" /> diff --git a/app/assets/javascripts/ide/components/terminal/view.vue b/app/assets/javascripts/ide/components/terminal/view.vue index db97e95eed9..fcf23eb1f73 100644 --- a/app/assets/javascripts/ide/components/terminal/view.vue +++ b/app/assets/javascripts/ide/components/terminal/view.vue @@ -1,12 +1,11 @@ <script> import { mapActions, mapGetters, mapState } from 'vuex'; import EmptyState from './empty_state.vue'; -import TerminalSession from './session.vue'; export default { components: { EmptyState, - TerminalSession, + TerminalSession: () => import(/* webpackChunkName: 'ide_terminal' */ './session.vue'), }, computed: { ...mapState('terminal', ['isShowSplash', 'paths']), diff --git a/app/assets/javascripts/ide/ide_router.js b/app/assets/javascripts/ide/ide_router.js index 396aedbfa10..b9ebacef7e1 100644 --- a/app/assets/javascripts/ide/ide_router.js +++ b/app/assets/javascripts/ide/ide_router.js @@ -3,6 +3,12 @@ import IdeRouter from '~/ide/ide_router_extension'; import { joinPaths } from '~/lib/utils/url_utility'; import { deprecatedCreateFlash as flash } from '~/flash'; import { __ } from '~/locale'; +import { performanceMarkAndMeasure } from '~/performance/utils'; +import { + WEBIDE_MARK_FETCH_PROJECT_DATA_START, + WEBIDE_MARK_FETCH_PROJECT_DATA_FINISH, + WEBIDE_MEASURE_FETCH_PROJECT_DATA, +} from '~/performance/constants'; import { syncRouterAndStore } from './sync_router_and_store'; Vue.use(IdeRouter); @@ -69,6 +75,7 @@ export const createRouter = store => { router.beforeEach((to, from, next) => { if (to.params.namespace && to.params.project) { + performanceMarkAndMeasure({ mark: WEBIDE_MARK_FETCH_PROJECT_DATA_START }); store .dispatch('getProjectData', { namespace: to.params.namespace, @@ -81,6 +88,15 @@ export const createRouter = store => { const mergeRequestId = to.params.mrid; if (branchId) { + performanceMarkAndMeasure({ + mark: WEBIDE_MARK_FETCH_PROJECT_DATA_FINISH, + measures: [ + { + name: WEBIDE_MEASURE_FETCH_PROJECT_DATA, + start: WEBIDE_MARK_FETCH_PROJECT_DATA_START, + }, + ], + }); store.dispatch('openBranch', { projectId, branchId, diff --git a/app/assets/javascripts/ide/index.js b/app/assets/javascripts/ide/index.js index 56d48e87c18..62f49ba56b1 100644 --- a/app/assets/javascripts/ide/index.js +++ b/app/assets/javascripts/ide/index.js @@ -2,6 +2,7 @@ import Vue from 'vue'; import { mapActions } from 'vuex'; import { identity } from 'lodash'; import Translate from '~/vue_shared/translate'; +import PerformancePlugin from '~/performance/vue_performance_plugin'; import ide from './components/ide.vue'; import { createStore } from './stores'; import { createRouter } from './ide_router'; @@ -11,6 +12,10 @@ import { DEFAULT_THEME } from './lib/themes'; Vue.use(Translate); +Vue.use(PerformancePlugin, { + components: ['FileTree'], +}); + /** * Function that receives the default store and returns an extended one. * @callback extendStoreCallback diff --git a/app/assets/javascripts/ide/lib/common/model.js b/app/assets/javascripts/ide/lib/common/model.js index c5bb00c3dee..2471b3627ce 100644 --- a/app/assets/javascripts/ide/lib/common/model.js +++ b/app/assets/javascripts/ide/lib/common/model.js @@ -1,7 +1,8 @@ import { editor as monacoEditor, Uri } from 'monaco-editor'; import Disposable from './disposable'; import eventHub from '../../eventhub'; -import { trimTrailingWhitespace, insertFinalNewline } from '../../utils'; +import { trimTrailingWhitespace } from '../../utils'; +import { insertFinalNewline } from '~/lib/utils/text_utility'; import { defaultModelOptions } from '../editor_options'; export default class Model { diff --git a/app/assets/javascripts/ide/stores/actions.js b/app/assets/javascripts/ide/stores/actions.js index 1496170447d..710256b6377 100644 --- a/app/assets/javascripts/ide/stores/actions.js +++ b/app/assets/javascripts/ide/stores/actions.js @@ -3,6 +3,12 @@ import { escape } from 'lodash'; import { __, sprintf } from '~/locale'; import { visitUrl } from '~/lib/utils/url_utility'; import { deprecatedCreateFlash as flash } from '~/flash'; +import { performanceMarkAndMeasure } from '~/performance/utils'; +import { + WEBIDE_MARK_FETCH_BRANCH_DATA_START, + WEBIDE_MARK_FETCH_BRANCH_DATA_FINISH, + WEBIDE_MEASURE_FETCH_BRANCH_DATA, +} from '~/performance/constants'; import * as types from './mutation_types'; import { decorateFiles } from '../lib/files'; import { stageKeys, commitActionTypes } from '../constants'; @@ -245,13 +251,23 @@ export const renameEntry = ({ dispatch, commit, state, getters }, { path, name, dispatch('triggerFilesChange', { type: commitActionTypes.move, path, newPath }); }; -export const getBranchData = ({ commit, state }, { projectId, branchId, force = false } = {}) => - new Promise((resolve, reject) => { +export const getBranchData = ({ commit, state }, { projectId, branchId, force = false } = {}) => { + return new Promise((resolve, reject) => { + performanceMarkAndMeasure({ mark: WEBIDE_MARK_FETCH_BRANCH_DATA_START }); const currentProject = state.projects[projectId]; if (!currentProject || !currentProject.branches[branchId] || force) { service .getBranchData(projectId, branchId) .then(({ data }) => { + performanceMarkAndMeasure({ + mark: WEBIDE_MARK_FETCH_BRANCH_DATA_FINISH, + measures: [ + { + name: WEBIDE_MEASURE_FETCH_BRANCH_DATA, + start: WEBIDE_MARK_FETCH_BRANCH_DATA_START, + }, + ], + }); const { id } = data.commit; commit(types.SET_BRANCH, { projectPath: projectId, @@ -291,6 +307,7 @@ export const getBranchData = ({ commit, state }, { projectId, branchId, force = resolve(currentProject.branches[branchId]); } }); +}; export * from './actions/tree'; export * from './actions/file'; diff --git a/app/assets/javascripts/ide/stores/actions/file.js b/app/assets/javascripts/ide/stores/actions/file.js index 4b9b958ddd6..8b43c7238fd 100644 --- a/app/assets/javascripts/ide/stores/actions/file.js +++ b/app/assets/javascripts/ide/stores/actions/file.js @@ -1,5 +1,11 @@ import { joinPaths, escapeFileUrl } from '~/lib/utils/url_utility'; import { __ } from '~/locale'; +import { performanceMarkAndMeasure } from '~/performance/utils'; +import { + WEBIDE_MARK_FETCH_FILE_DATA_START, + WEBIDE_MARK_FETCH_FILE_DATA_FINISH, + WEBIDE_MEASURE_FETCH_FILE_DATA, +} from '~/performance/constants'; import eventHub from '../../eventhub'; import service from '../../services'; import * as types from '../mutation_types'; @@ -61,6 +67,7 @@ export const getFileData = ( { state, commit, dispatch, getters }, { path, makeFileActive = true, openFile = makeFileActive, toggleLoading = true }, ) => { + performanceMarkAndMeasure({ mark: WEBIDE_MARK_FETCH_FILE_DATA_START }); const file = state.entries[path]; const fileDeletedAndReadded = getters.isFileDeletedAndReadded(path); @@ -81,6 +88,15 @@ export const getFileData = ( return service .getFileData(url) .then(({ data }) => { + performanceMarkAndMeasure({ + mark: WEBIDE_MARK_FETCH_FILE_DATA_FINISH, + measures: [ + { + name: WEBIDE_MEASURE_FETCH_FILE_DATA, + start: WEBIDE_MARK_FETCH_FILE_DATA_START, + }, + ], + }); if (data) commit(types.SET_FILE_DATA, { data, file }); if (openFile) commit(types.TOGGLE_FILE_OPEN, path); @@ -150,6 +166,13 @@ export const getRawFileData = ({ state, commit, dispatch, getters }, { path }) = export const changeFileContent = ({ commit, 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. + // See issue https://gitlab.com/gitlab-org/gitlab/-/issues/284930 + if (!file) { + return; + } + commit(types.UPDATE_FILE_CONTENT, { path, content, diff --git a/app/assets/javascripts/ide/stores/actions/tree.js b/app/assets/javascripts/ide/stores/actions/tree.js index 3a7daf30cc4..23a5e26bc1c 100644 --- a/app/assets/javascripts/ide/stores/actions/tree.js +++ b/app/assets/javascripts/ide/stores/actions/tree.js @@ -1,4 +1,10 @@ import { defer } from 'lodash'; +import { performanceMarkAndMeasure } from '~/performance/utils'; +import { + WEBIDE_MARK_FETCH_FILES_FINISH, + WEBIDE_MEASURE_FETCH_FILES, + WEBIDE_MARK_FETCH_FILES_START, +} from '~/performance/constants'; import { __ } from '../../../locale'; import service from '../../services'; import * as types from '../mutation_types'; @@ -46,8 +52,9 @@ export const setDirectoryData = ({ state, commit }, { projectId, branchId, treeL }); }; -export const getFiles = ({ state, commit, dispatch }, payload = {}) => - new Promise((resolve, reject) => { +export const getFiles = ({ state, commit, dispatch }, payload = {}) => { + performanceMarkAndMeasure({ mark: WEBIDE_MARK_FETCH_FILES_START }); + return new Promise((resolve, reject) => { const { projectId, branchId, ref = branchId } = payload; if ( @@ -61,6 +68,15 @@ export const getFiles = ({ state, commit, dispatch }, payload = {}) => service .getFiles(selectedProject.path_with_namespace, ref) .then(({ data }) => { + performanceMarkAndMeasure({ + mark: WEBIDE_MARK_FETCH_FILES_FINISH, + measures: [ + { + name: WEBIDE_MEASURE_FETCH_FILES, + start: WEBIDE_MARK_FETCH_FILES_START, + }, + ], + }); const { entries, treeList } = decorateFiles({ data }); commit(types.SET_ENTRIES, entries); @@ -85,6 +101,7 @@ export const getFiles = ({ state, commit, dispatch }, payload = {}) => resolve(); } }); +}; export const restoreTree = ({ dispatch, commit, state }, path) => { const entry = state.entries[path]; diff --git a/app/assets/javascripts/ide/utils.js b/app/assets/javascripts/ide/utils.js index 1ca1b971de1..43276f32322 100644 --- a/app/assets/javascripts/ide/utils.js +++ b/app/assets/javascripts/ide/utils.js @@ -97,10 +97,6 @@ export function trimTrailingWhitespace(content) { return content.replace(/[^\S\r\n]+$/gm, ''); } -export function insertFinalNewline(content, eol = '\n') { - return content.slice(-eol.length) !== eol ? `${content}${eol}` : content; -} - export function getPathParents(path, maxDepth = Infinity) { const pathComponents = path.split('/'); const paths = []; |