diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-05-02 12:10:46 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-05-02 12:10:46 +0300 |
commit | f3b405856d99583bcd2f27c909abe779a48db512 (patch) | |
tree | 82d3ec2494523fb5b52f3f852be978c6b7263651 /app/assets/javascripts/pipelines | |
parent | 9ecca14b2b3f05673a15399a2d1cc439206f3e0f (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/pipelines')
7 files changed, 277 insertions, 43 deletions
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/empty_state.vue b/app/assets/javascripts/pipelines/components/pipelines_list/empty_state.vue index 5a9c85a0f10..3bbdfc73e1b 100644 --- a/app/assets/javascripts/pipelines/components/pipelines_list/empty_state.vue +++ b/app/assets/javascripts/pipelines/components/pipelines_list/empty_state.vue @@ -1,7 +1,9 @@ <script> import { GlEmptyState } from '@gitlab/ui'; import { s__ } from '~/locale'; +import GitlabExperiment from '~/experimentation/components/gitlab_experiment.vue'; import PipelinesCiTemplates from './empty_state/pipelines_ci_templates.vue'; +import IosTemplates from './empty_state/ios_templates.vue'; export default { i18n: { @@ -10,7 +12,9 @@ export default { name: 'PipelinesEmptyState', components: { GlEmptyState, + GitlabExperiment, PipelinesCiTemplates, + IosTemplates, }, props: { emptyStateSvgPath: { @@ -21,26 +25,24 @@ export default { type: Boolean, required: true, }, - ciRunnerSettingsPath: { + registrationToken: { type: String, required: false, default: null, }, - anyRunnersAvailable: { - type: Boolean, - required: false, - default: true, - }, }, }; </script> <template> <div> - <pipelines-ci-templates - v-if="canSetCi" - :ci-runner-settings-path="ciRunnerSettingsPath" - :any-runners-available="anyRunnersAvailable" - /> + <gitlab-experiment v-if="canSetCi" name="ios_specific_templates"> + <template #control> + <pipelines-ci-templates /> + </template> + <template #candidate> + <ios-templates :registration-token="registrationToken" /> + </template> + </gitlab-experiment> <gl-empty-state v-else title="" diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/empty_state/ci_templates.vue b/app/assets/javascripts/pipelines/components/pipelines_list/empty_state/ci_templates.vue index 3b312e78d11..64d4414eb94 100644 --- a/app/assets/javascripts/pipelines/components/pipelines_list/empty_state/ci_templates.vue +++ b/app/assets/javascripts/pipelines/components/pipelines_list/empty_state/ci_templates.vue @@ -12,15 +12,31 @@ export default { }, mixins: [Tracking.mixin()], inject: ['pipelineEditorPath', 'suggestedCiTemplates'], + props: { + disabled: { + type: Boolean, + required: false, + default: false, + }, + filterTemplates: { + type: Array, + required: false, + default: () => [], + }, + }, data() { - const templates = this.suggestedCiTemplates.map(({ name, logo }) => { - return { - name, - logo, - link: mergeUrlParams({ template: name }, this.pipelineEditorPath), - description: sprintf(this.$options.i18n.description, { name }), - }; - }); + const templates = this.suggestedCiTemplates + .filter( + (template) => !this.filterTemplates.length || this.filterTemplates.includes(template.name), + ) + .map(({ name, logo, title }) => { + return { + name: title || name, + logo, + link: mergeUrlParams({ template: name }, this.pipelineEditorPath), + description: sprintf(this.$options.i18n.description, { name: title || name }), + }; + }); return { templates, @@ -34,7 +50,9 @@ export default { }, }, i18n: { - description: s__('Pipelines|CI/CD template to test and deploy your %{name} project.'), + description: s__( + 'Pipelines|Continuous integration and deployment template to test and deploy your %{name} project.', + ), cta: s__('Pipelines|Use template'), }, AVATAR_SHAPE_OPTION_RECT, @@ -67,6 +85,7 @@ export default { </div> </div> <gl-button + :disabled="disabled" category="primary" variant="confirm" :href="template.link" diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/empty_state/ios_templates.vue b/app/assets/javascripts/pipelines/components/pipelines_list/empty_state/ios_templates.vue new file mode 100644 index 00000000000..b0f5b26367e --- /dev/null +++ b/app/assets/javascripts/pipelines/components/pipelines_list/empty_state/ios_templates.vue @@ -0,0 +1,218 @@ +<script> +import { GlButton, GlCard, GlSprintf, GlLink, GlPopover, GlModalDirective } from '@gitlab/ui'; +import { s__ } from '~/locale'; +import { helpPagePath } from '~/helpers/help_page_helper'; +import { mergeUrlParams } from '~/lib/utils/url_utility'; +import RunnerInstructionsModal from '~/vue_shared/components/runner_instructions/runner_instructions_modal.vue'; +import apolloProvider from '~/pipelines/graphql/provider'; +import CiTemplates from './ci_templates.vue'; + +export default { + components: { + GlButton, + GlCard, + GlSprintf, + GlLink, + GlPopover, + RunnerInstructionsModal, + CiTemplates, + }, + directives: { + GlModalDirective, + }, + inject: ['pipelineEditorPath', 'iosRunnersAvailable'], + props: { + registrationToken: { + type: String, + required: false, + default: null, + }, + }, + apolloProvider, + iOSTemplateName: 'iOS-Fastlane', + modalId: 'runner-instructions-modal', + runnerDocsLink: 'https://docs.gitlab.com/runner/install/osx', + whatElseLink: helpPagePath('ci/index.md'), + i18n: { + title: s__('Pipelines|Get started with GitLab CI/CD'), + subtitle: s__('Pipelines|Building for iOS?'), + explanation: s__("Pipelines|We'll walk you through how to deploy to iOS in two easy steps."), + runnerSetupTitle: s__('Pipelines|1. Set up a runner'), + runnerSetupButton: s__('Pipelines|Set up a runner'), + runnerSetupBodyUnfinished: s__( + 'Pipelines|GitLab Runner is an application that works with GitLab CI/CD to run jobs in a pipeline.', + ), + runnerSetupBodyFinished: s__( + 'Pipelines|You have runners available to run your job now. No need to do anything else.', + ), + runnerSetupPopoverTitle: s__( + "Pipelines|Let's get that runner set up! %{emojiStart}tada%{emojiEnd}", + ), + runnerSetupPopoverBodyLine1: s__( + 'Pipelines|Follow these instructions to install GitLab Runner on macOS.', + ), + runnerSetupPopoverBodyLine2: s__( + 'Pipelines|Need more information to set up your runner? %{linkStart}Check out our documentation%{linkEnd}.', + ), + configurePipelineTitle: s__('Pipelines|2. Configure deployment pipeline'), + configurePipelineBody: s__("Pipelines|We'll guide you through a simple pipeline set-up."), + configurePipelineButton: s__('Pipelines|Configure pipeline'), + noWalkthroughTitle: s__("Pipelines|Don't need a guide? Jump in right away with a template."), + noWalkthroughExplanation: s__('Pipelines|Based on your project, we recommend this template:'), + notBuildingForIos: s__( + "Pipelines|Not building for iOS or not what you're looking for? %{linkStart}See what else%{linkEnd} GitLab CI/CD has to offer.", + ), + }, + data() { + return { + isModalShown: false, + isPopoverShown: false, + isRunnerSetupFinished: this.iosRunnersAvailable, + popoverTarget: `${this.$options.modalId}___BV_modal_content_`, + configurePipelineLink: mergeUrlParams( + { template: this.$options.iOSTemplateName }, + this.pipelineEditorPath, + ), + }; + }, + computed: { + runnerSetupBodyText() { + return this.iosRunnersAvailable + ? this.$options.i18n.runnerSetupBodyFinished + : this.$options.i18n.runnerSetupBodyUnfinished; + }, + }, + methods: { + showModal() { + this.isModalShown = true; + }, + hideModal() { + this.togglePopover(); + this.isRunnerSetupFinished = true; + }, + togglePopover() { + this.isPopoverShown = !this.isPopoverShown; + }, + }, +}; +</script> + +<template> + <div> + <h2 class="gl-font-size-h2 gl-text-gray-900">{{ $options.i18n.title }}</h2> + <h3 class="gl-font-lg gl-text-gray-900 gl-mt-1">{{ $options.i18n.subtitle }}</h3> + <p>{{ $options.i18n.explanation }}</p> + + <div class="gl-lg-display-flex"> + <div class="gl-lg-display-flex gl-lg-w-25p gl-lg-pr-4 gl-mb-4"> + <gl-card body-class="gl-display-flex gl-flex-grow-1"> + <div + class="gl-display-flex gl-flex-grow-1 gl-flex-direction-column gl-justify-content-space-between gl-align-items-flex-start" + > + <div> + <div class="gl-py-5"> + <gl-emoji + v-show="isRunnerSetupFinished" + class="gl-font-size-h2-xl" + data-name="white_check_mark" + data-testid="runner-setup-marked-completed" + /> + <gl-emoji + v-show="!isRunnerSetupFinished" + class="gl-font-size-h2-xl" + data-name="tools" + data-testid="runner-setup-marked-todo" + /> + </div> + <span class="gl-text-gray-800 gl-font-weight-bold"> + {{ $options.i18n.runnerSetupTitle }} + </span> + <p class="gl-font-sm gl-mt-3">{{ runnerSetupBodyText }}</p> + </div> + + <gl-button + v-if="!iosRunnersAvailable" + v-gl-modal-directive="$options.modalId" + category="primary" + variant="confirm" + @click="showModal" + > + {{ $options.i18n.runnerSetupButton }} + </gl-button> + <runner-instructions-modal + v-if="isModalShown" + :modal-id="$options.modalId" + :registration-token="registrationToken" + default-platform-name="osx" + @shown="togglePopover" + @hide="hideModal" + /> + <gl-popover + v-if="isPopoverShown" + :show="true" + :show-close-button="true" + :target="popoverTarget" + triggers="manual" + placement="left" + fallback-placement="clockwise" + > + <template #title> + <gl-sprintf :message="$options.i18n.runnerSetupPopoverTitle"> + <template #emoji="{ content }"> + <gl-emoji class="gl-ml-2" :data-name="content" /> + </template> + </gl-sprintf> + </template> + <div class="gl-mb-5"> + {{ $options.i18n.runnerSetupPopoverBodyLine1 }} + </div> + <gl-sprintf :message="$options.i18n.runnerSetupPopoverBodyLine2"> + <template #link="{ content }"> + <gl-link :href="$options.runnerDocsLink" target="_blank">{{ content }}</gl-link> + </template> + </gl-sprintf> + </gl-popover> + </div> + </gl-card> + </div> + <div class="gl-lg-display-flex gl-lg-w-25p gl-lg-pr-4 gl-mb-4"> + <gl-card body-class="gl-display-flex gl-flex-grow-1"> + <div + class="gl-display-flex gl-flex-grow-1 gl-flex-direction-column gl-justify-content-space-between gl-align-items-flex-start" + > + <div> + <div class="gl-py-5"><gl-emoji class="gl-font-size-h2-xl" data-name="tools" /></div> + <span class="gl-text-gray-800 gl-font-weight-bold"> + {{ $options.i18n.configurePipelineTitle }} + </span> + <p class="gl-font-sm gl-mt-3">{{ $options.i18n.configurePipelineBody }}</p> + </div> + + <gl-button + :disabled="!isRunnerSetupFinished" + category="primary" + variant="confirm" + data-testid="configure-pipeline-link" + :href="configurePipelineLink" + > + {{ $options.i18n.configurePipelineButton }} + </gl-button> + </div> + </gl-card> + </div> + </div> + <h3 class="gl-font-lg gl-text-gray-900 gl-mt-5">{{ $options.i18n.noWalkthroughTitle }}</h3> + <p>{{ $options.i18n.noWalkthroughExplanation }}</p> + <ci-templates + :filter-templates="[$options.iOSTemplateName]" + :disabled="!isRunnerSetupFinished" + /> + <p> + <gl-sprintf :message="$options.i18n.notBuildingForIos"> + <template #link="{ content }"> + <gl-link :href="$options.whatElseLink">{{ content }}</gl-link> + </template> + </gl-sprintf> + </p> + </div> +</template> diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/empty_state/pipelines_ci_templates.vue b/app/assets/javascripts/pipelines/components/pipelines_list/empty_state/pipelines_ci_templates.vue index be46a7f5cec..3eafb36bd1d 100644 --- a/app/assets/javascripts/pipelines/components/pipelines_list/empty_state/pipelines_ci_templates.vue +++ b/app/assets/javascripts/pipelines/components/pipelines_list/empty_state/pipelines_ci_templates.vue @@ -33,19 +33,7 @@ export default { RUNNERS_DOCUMENTATION_LINK_CLICKED_EVENT, RUNNERS_SETTINGS_BUTTON_CLICKED_EVENT, I18N, - inject: ['pipelineEditorPath'], - props: { - ciRunnerSettingsPath: { - type: String, - required: false, - default: null, - }, - anyRunnersAvailable: { - type: Boolean, - required: false, - default: true, - }, - }, + inject: ['anyRunnersAvailable', 'pipelineEditorPath', 'ciRunnerSettingsPath'], data() { return { gettingStartedTemplateUrl: mergeUrlParams( diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue index db9dc74863d..485e338f639 100644 --- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue +++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue @@ -107,16 +107,11 @@ export default { type: Object, required: true, }, - ciRunnerSettingsPath: { + registrationToken: { type: String, required: false, default: null, }, - anyRunnersAvailable: { - type: Boolean, - required: false, - default: true, - }, }, data() { return { @@ -386,8 +381,7 @@ export default { v-else-if="stateToRender === $options.stateMap.emptyState" :empty-state-svg-path="emptyStateSvgPath" :can-set-ci="canCreatePipeline" - :ci-runner-settings-path="ciRunnerSettingsPath" - :any-runners-available="anyRunnersAvailable" + :registration-token="registrationToken" /> <gl-empty-state diff --git a/app/assets/javascripts/pipelines/graphql/provider.js b/app/assets/javascripts/pipelines/graphql/provider.js new file mode 100644 index 00000000000..ef96b443da8 --- /dev/null +++ b/app/assets/javascripts/pipelines/graphql/provider.js @@ -0,0 +1,9 @@ +import Vue from 'vue'; +import VueApollo from 'vue-apollo'; +import createDefaultClient from '~/lib/graphql'; + +Vue.use(VueApollo); + +export default new VueApollo({ + defaultClient: createDefaultClient(), +}); diff --git a/app/assets/javascripts/pipelines/pipelines_index.js b/app/assets/javascripts/pipelines/pipelines_index.js index f4d9a44a754..6dccdb1a3e6 100644 --- a/app/assets/javascripts/pipelines/pipelines_index.js +++ b/app/assets/javascripts/pipelines/pipelines_index.js @@ -40,6 +40,8 @@ export const initPipelinesIndex = (selector = '#pipelines-list-vue') => { params, ciRunnerSettingsPath, anyRunnersAvailable, + iosRunnersAvailable, + registrationToken, } = el.dataset; return new Vue({ @@ -49,6 +51,9 @@ export const initPipelinesIndex = (selector = '#pipelines-list-vue') => { artifactsEndpoint, artifactsEndpointPlaceholder, suggestedCiTemplates: JSON.parse(suggestedCiTemplates), + ciRunnerSettingsPath, + anyRunnersAvailable: parseBoolean(anyRunnersAvailable), + iosRunnersAvailable: parseBoolean(iosRunnersAvailable), }, data() { return { @@ -78,8 +83,7 @@ export const initPipelinesIndex = (selector = '#pipelines-list-vue') => { projectId, defaultBranchName, params: JSON.parse(params), - ciRunnerSettingsPath, - anyRunnersAvailable: parseBoolean(anyRunnersAvailable), + registrationToken, }, }); }, |