diff options
Diffstat (limited to 'app/assets/javascripts/pipeline_editor')
10 files changed, 96 insertions, 45 deletions
diff --git a/app/assets/javascripts/pipeline_editor/components/commit/commit_form.vue b/app/assets/javascripts/pipeline_editor/components/commit/commit_form.vue index ca78f194a82..8536db78dfb 100644 --- a/app/assets/javascripts/pipeline_editor/components/commit/commit_form.vue +++ b/app/assets/javascripts/pipeline_editor/components/commit/commit_form.vue @@ -31,6 +31,14 @@ export default { required: false, default: '', }, + hasUnsavedChanges: { + type: Boolean, + required: true, + }, + isNewCiConfigFile: { + type: Boolean, + required: true, + }, isSaving: { type: Boolean, required: false, @@ -50,11 +58,14 @@ export default { }; }, computed: { + isCommitFormFilledOut() { + return this.message && this.targetBranch; + }, isCurrentBranchTarget() { return this.targetBranch === this.currentBranch; }, - submitDisabled() { - return !(this.message && this.targetBranch); + isSubmitDisabled() { + return !this.isCommitFormFilledOut || (!this.hasUnsavedChanges && !this.isNewCiConfigFile); }, }, watch: { @@ -125,6 +136,7 @@ export default { v-if="!isCurrentBranchTarget" v-model="openMergeRequest" data-testid="new-mr-checkbox" + data-qa-selector="new_mr_checkbox" class="gl-mt-3" > <gl-sprintf :message="$options.i18n.startMergeRequest"> @@ -143,7 +155,7 @@ export default { category="primary" variant="confirm" data-qa-selector="commit_changes_button" - :disabled="submitDisabled" + :disabled="isSubmitDisabled" :loading="isSaving" > {{ $options.i18n.commitChanges }} diff --git a/app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue b/app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue index 8ff1aea020f..4ef598d6ff3 100644 --- a/app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue +++ b/app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue @@ -37,6 +37,10 @@ export default { required: false, default: '', }, + hasUnsavedChanges: { + type: Boolean, + required: true, + }, isNewCiConfigFile: { type: Boolean, required: false, @@ -151,6 +155,8 @@ export default { <commit-form :current-branch="currentBranch" :default-message="defaultCommitMessage" + :has-unsaved-changes="hasUnsavedChanges" + :is-new-ci-config-file="isNewCiConfigFile" :is-saving="isSaving" :scroll-to-commit-form="scrollToCommitForm" v-on="$listeners" diff --git a/app/assets/javascripts/pipeline_editor/components/drawer/pipeline_editor_drawer.vue b/app/assets/javascripts/pipeline_editor/components/drawer/pipeline_editor_drawer.vue index 7bc096ce2c8..9cb070a5517 100644 --- a/app/assets/javascripts/pipeline_editor/components/drawer/pipeline_editor_drawer.vue +++ b/app/assets/javascripts/pipeline_editor/components/drawer/pipeline_editor_drawer.vue @@ -2,7 +2,6 @@ import { GlButton, GlIcon } from '@gitlab/ui'; import { __ } from '~/locale'; import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue'; -import { experiment } from '~/experimentation/utils'; import { DRAWER_EXPANDED_KEY } from '../../constants'; import FirstPipelineCard from './cards/first_pipeline_card.vue'; import GettingStartedCard from './cards/getting_started_card.vue'; @@ -50,29 +49,8 @@ export default { }, mounted() { this.setTopPosition(); - this.setInitialExpandState(); }, methods: { - setInitialExpandState() { - let isExpanded; - - experiment('pipeline_editor_walkthrough', { - control: () => { - isExpanded = true; - }, - candidate: () => { - isExpanded = false; - }, - }); - - // We check in the local storage and if no value is defined, we want the default - // to be true. We want to explicitly set it to true here so that the drawer - // animates to open on load. - const localValue = localStorage.getItem(this.$options.localDrawerKey); - if (localValue === null) { - this.isExpanded = isExpanded; - } - }, setTopPosition() { const navbarEl = document.querySelector('.js-navbar'); diff --git a/app/assets/javascripts/pipeline_editor/components/editor/text_editor.vue b/app/assets/javascripts/pipeline_editor/components/editor/text_editor.vue index 5177cea900c..255e3cb31f1 100644 --- a/app/assets/javascripts/pipeline_editor/components/editor/text_editor.vue +++ b/app/assets/javascripts/pipeline_editor/components/editor/text_editor.vue @@ -3,6 +3,7 @@ import { EDITOR_READY_EVENT } from '~/editor/constants'; import { CiSchemaExtension } from '~/editor/extensions/source_editor_ci_schema_ext'; import SourceEditor from '~/vue_shared/components/source_editor.vue'; import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; +import { SOURCE_EDITOR_DEBOUNCE } from '../../constants'; export default { editorOptions: { @@ -10,6 +11,7 @@ export default { // autocomplete for keywords quickSuggestions: true, }, + debounceValue: SOURCE_EDITOR_DEBOUNCE, components: { SourceEditor, }, @@ -34,6 +36,7 @@ export default { <div class="gl-border-solid gl-border-gray-100 gl-border-1 gl-border-t-none!"> <source-editor ref="editor" + :debounce-value="$options.debounceValue" :editor-options="$options.editorOptions" :file-name="ciConfigPath" v-bind="$attrs" diff --git a/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue b/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue index c75b1d4bb11..5cff93c884f 100644 --- a/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue +++ b/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue @@ -4,7 +4,6 @@ import { s__ } from '~/locale'; import PipelineGraph from '~/pipelines/components/pipeline_graph/pipeline_graph.vue'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { getParameterValues, setUrlParams, updateHistory } from '~/lib/utils/url_utility'; -import GitlabExperiment from '~/experimentation/components/gitlab_experiment.vue'; import { CREATE_TAB, EDITOR_APP_STATUS_EMPTY, @@ -66,7 +65,6 @@ export default { GlTabs, PipelineGraph, TextEditor, - GitlabExperiment, WalkthroughPopover, }, mixins: [glFeatureFlagsMixin()], @@ -158,11 +156,7 @@ export default { data-testid="editor-tab" @click="setCurrentTab($options.tabConstants.CREATE_TAB)" > - <gitlab-experiment name="pipeline_editor_walkthrough"> - <template #candidate> - <walkthrough-popover v-if="isNewCiConfigFile" v-on="$listeners" /> - </template> - </gitlab-experiment> + <walkthrough-popover v-if="isNewCiConfigFile" v-on="$listeners" /> <ci-editor-header /> <text-editor :commit-sha="commitSha" :value="ciFileContent" v-on="$listeners" /> </editor-tab> diff --git a/app/assets/javascripts/pipeline_editor/components/ui/pipeline_editor_empty_state.vue b/app/assets/javascripts/pipeline_editor/components/ui/pipeline_editor_empty_state.vue index dcd08c9de8d..aee71999373 100644 --- a/app/assets/javascripts/pipeline_editor/components/ui/pipeline_editor_empty_state.vue +++ b/app/assets/javascripts/pipeline_editor/components/ui/pipeline_editor_empty_state.vue @@ -41,7 +41,12 @@ export default { </template> </gl-sprintf> </p> - <gl-button variant="confirm" class="gl-mt-3" @click="createEmptyConfigFile"> + <gl-button + variant="confirm" + class="gl-mt-3" + data-qa-selector="create_new_ci_button" + @click="createEmptyConfigFile" + > {{ $options.i18n.btnText }} </gl-button> </div> diff --git a/app/assets/javascripts/pipeline_editor/constants.js b/app/assets/javascripts/pipeline_editor/constants.js index a65463d02aa..2ebc4306405 100644 --- a/app/assets/javascripts/pipeline_editor/constants.js +++ b/app/assets/javascripts/pipeline_editor/constants.js @@ -1,3 +1,5 @@ +import { s__ } from '~/locale'; + // Values for CI_CONFIG_STATUS_* comes from lint graphQL export const CI_CONFIG_STATUS_INVALID = 'INVALID'; export const CI_CONFIG_STATUS_VALID = 'VALID'; @@ -47,6 +49,7 @@ export const DRAWER_EXPANDED_KEY = 'pipeline_editor_drawer_expanded'; export const BRANCH_PAGINATION_LIMIT = 20; export const BRANCH_SEARCH_DEBOUNCE = '500'; +export const SOURCE_EDITOR_DEBOUNCE = 500; export const STARTER_TEMPLATE_NAME = 'Getting-Started'; @@ -61,3 +64,45 @@ export const TEMPLATE_REPOSITORY_URL = 'https://gitlab.com/gitlab-org/gitlab-foss/tree/master/lib/gitlab/ci/templates'; export const COMMIT_SHA_POLL_INTERVAL = 1000; + +export const RUNNERS_AVAILABILITY_SECTION_EXPERIMENT_NAME = 'runners_availability_section'; +export const RUNNERS_SETTINGS_LINK_CLICKED_EVENT = 'runners_settings_link_clicked'; +export const RUNNERS_DOCUMENTATION_LINK_CLICKED_EVENT = 'runners_documentation_link_clicked'; +export const RUNNERS_SETTINGS_BUTTON_CLICKED_EVENT = 'runners_settings_button_clicked'; +export const I18N = { + title: s__('Pipelines|Get started with GitLab CI/CD'), + runners: { + title: s__('Pipelines|Runners are available to run your jobs now'), + subtitle: s__( + 'Pipelines|GitLab Runner is an application that works with GitLab CI/CD to run jobs in a pipeline. There are active runners available to run your jobs right now. If you prefer, you can %{settingsLinkStart}configure your runners%{settingsLinkEnd} or %{docsLinkStart}learn more%{docsLinkEnd} about runners.', + ), + }, + noRunners: { + title: s__('Pipelines|No runners detected'), + subtitle: s__( + 'Pipelines|A GitLab Runner is an application that works with GitLab CI/CD to run jobs in a pipeline. Install GitLab Runner and register your own runners to get started with CI/CD.', + ), + cta: s__('Pipelines|Install GitLab Runner'), + }, + learnBasics: { + title: s__('Pipelines|Learn the basics of pipelines and .yml files'), + subtitle: s__( + 'Pipelines|Use a sample %{codeStart}.gitlab-ci.yml%{codeEnd} template file to explore how CI/CD works.', + ), + gettingStarted: { + title: s__('Pipelines|"Hello world" with GitLab CI'), + description: s__( + 'Pipelines|Get familiar with GitLab CI syntax by setting up a simple pipeline running a "Hello world" script to see how it runs, explore how CI/CD works.', + ), + cta: s__('Pipelines|Try test template'), + }, + }, + templates: { + title: s__('Pipelines|Ready to set up CI/CD for your project?'), + subtitle: s__( + "Pipelines|Use a template based on your project's language or framework to get started with GitLab CI/CD.", + ), + description: s__('Pipelines|CI/CD template to test and deploy your %{name} project.'), + cta: s__('Pipelines|Use template'), + }, +}; diff --git a/app/assets/javascripts/pipeline_editor/index.js b/app/assets/javascripts/pipeline_editor/index.js index 04f91cb3d1e..732fc665c9e 100644 --- a/app/assets/javascripts/pipeline_editor/index.js +++ b/app/assets/javascripts/pipeline_editor/index.js @@ -2,7 +2,6 @@ import Vue from 'vue'; import VueApollo from 'vue-apollo'; import createDefaultClient from '~/lib/graphql'; -import { resetServiceWorkersPublicPath } from '../lib/utils/webpack'; import { EDITOR_APP_STATUS_LOADING } from './constants'; import { CODE_SNIPPET_SOURCE_SETTINGS } from './components/code_snippet_alert/constants'; import getCurrentBranch from './graphql/queries/client/current_branch.query.graphql'; @@ -14,11 +13,6 @@ import typeDefs from './graphql/typedefs.graphql'; import PipelineEditorApp from './pipeline_editor_app.vue'; export const initPipelineEditor = (selector = '#js-pipeline-editor') => { - // Prevent issues loading syntax validation workers - // Fixes https://gitlab.com/gitlab-org/gitlab/-/issues/297252 - // TODO Remove when https://gitlab.com/gitlab-org/gitlab/-/issues/321656 is resolved - resetServiceWorkersPublicPath(); - const el = document.querySelector(selector); if (!el) { diff --git a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue index 1da50c55a68..a5436ca63cb 100644 --- a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue +++ b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue @@ -69,9 +69,10 @@ export default { // If it's a brand new file, we don't want to fetch the content. // Then when the user commits the first time, the query would run // to get the initial file content, but we already have it in `lastCommitedContent` - // so we skip the loading altogether. - skip({ isNewCiConfigFile, lastCommittedContent }) { - return isNewCiConfigFile || lastCommittedContent; + // so we skip the loading altogether. We also wait for the currentBranch + // to have been fetched + skip() { + return this.shouldSkipBlobContentQuery; }, variables() { return { @@ -128,8 +129,8 @@ export default { }, ciConfigData: { query: getCiConfigData, - skip({ currentCiFileContent }) { - return !currentCiFileContent; + skip() { + return this.shouldSkipCiConfigQuery; }, variables() { return { @@ -174,6 +175,9 @@ export default { }, commitSha: { query: getLatestCommitShaQuery, + skip({ currentBranch }) { + return !currentBranch; + }, variables() { return { projectPath: this.projectFullPath, @@ -181,7 +185,7 @@ export default { }; }, update(data) { - const latestCommitSha = data.project?.repository?.tree?.lastCommit?.sha; + const latestCommitSha = data?.project?.repository?.tree?.lastCommit?.sha; if (this.isFetchingCommitSha && latestCommitSha === this.commitSha) { this.$apollo.queries.commitSha.startPolling(COMMIT_SHA_POLL_INTERVAL); @@ -192,6 +196,9 @@ export default { this.$apollo.queries.commitSha.stopPolling(); return latestCommitSha; }, + error() { + this.reportFailure(LOAD_FAILURE_UNKNOWN); + }, }, currentBranch: { query: getCurrentBranch, @@ -234,6 +241,12 @@ export default { isEmpty() { return this.currentCiFileContent === ''; }, + shouldSkipBlobContentQuery() { + return this.isNewCiConfigFile || this.lastCommittedContent || !this.currentBranch; + }, + shouldSkipCiConfigQuery() { + return !this.currentCiFileContent || !this.commitSha; + }, }, i18n: { resetModal: { diff --git a/app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue b/app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue index bb759477e1e..631dd8a2c00 100644 --- a/app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue +++ b/app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue @@ -131,6 +131,7 @@ export default { :ref="$options.commitSectionRef" :ci-file-content="ciFileContent" :commit-sha="commitSha" + :has-unsaved-changes="hasUnsavedChanges" :is-new-ci-config-file="isNewCiConfigFile" :scroll-to-commit-form="scrollToCommitForm" @scrolled-to-commit-form="setScrollToCommitForm(false)" |