Commit a7b7ba36 authored by Robert Speicher's avatar Robert Speicher

Merge branch 'add-suggest-pipeline-success' into 'master'

Add success modal for pipeline tour success

Closes gitlab-org/growth/ui-ux#65

See merge request gitlab-org/gitlab!25547
parents a29c2a71 9ba9c8a2
<script>
import { GlModal, GlSprintf, GlLink } from '@gitlab/ui';
import { sprintf, s__, __ } from '~/locale';
import Cookies from 'js-cookie';
import { glEmojiTag } from '~/emoji';
export default {
beginnerLink:
'https://about.gitlab.com/blog/2018/01/22/a-beginners-guide-to-continuous-integration/',
exampleLink: 'https://docs.gitlab.com/ee/ci/examples/',
bodyMessage: s__(
'MR widget|The pipeline will now run automatically every time you commit code. Pipelines are useful for deploying static web pages, detecting vulnerabilities in dependencies, static or dynamic application security testing (SAST and DAST), and so much more!',
),
modalTitle: sprintf(
__("That's it, well done!%{celebrate}"),
{
celebrate: glEmojiTag('tada'),
},
false,
),
components: {
GlModal,
GlSprintf,
GlLink,
},
props: {
goToPipelinesPath: {
type: String,
required: true,
},
commitCookie: {
type: String,
required: true,
},
},
mounted() {
this.disableModalFromRenderingAgain();
},
methods: {
disableModalFromRenderingAgain() {
Cookies.remove(this.commitCookie);
},
},
};
</script>
<template>
<gl-modal
visible
size="sm"
:title="$options.modalTitle"
modal-id="success-pipeline-modal-id-not-used"
>
<p>
{{ $options.bodyMessage }}
</p>
<gl-sprintf
:message="
s__(`MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd}
and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd}
to see all the cool stuff you can do with it.`)
"
>
<template #beginnerLink="{content}">
<gl-link :href="$options.beginnerLink" target="_blank">
{{ content }}
</gl-link>
</template>
<template #exampleLink="{content}">
<gl-link :href="$options.exampleLink" target="_blank">
{{ content }}
</gl-link>
</template>
</gl-sprintf>
<template #modal-footer>
<a :href="goToPipelinesPath" class="btn btn-success">{{ __('Go to Pipelines') }}</a>
</template>
</gl-modal>
</template>
......@@ -4,6 +4,7 @@ import BlobViewer from '~/blob/viewer/index';
import initBlob from '~/pages/projects/init_blob';
import GpgBadges from '~/gpg_badges';
import '~/sourcegraph/load';
import PipelineTourSuccessModal from '~/blob/pipeline_tour_success_modal.vue';
document.addEventListener('DOMContentLoaded', () => {
new BlobViewer(); // eslint-disable-line no-new
......@@ -35,4 +36,25 @@ document.addEventListener('DOMContentLoaded', () => {
// eslint-disable-next-line promise/catch-or-return
import('~/code_navigation').then(m => m.default());
}
if (gon.features?.suggestPipeline) {
const successPipelineEl = document.querySelector('.js-success-pipeline-modal');
if (successPipelineEl) {
// eslint-disable-next-line no-new
new Vue({
el: successPipelineEl,
render(createElement) {
const { commitCookie, pipelinesPath: goToPipelinesPath } = this.$el.dataset;
return createElement(PipelineTourSuccessModal, {
props: {
goToPipelinesPath,
commitCookie,
},
});
},
});
}
}
});
......@@ -31,6 +31,7 @@ class Projects::BlobController < Projects::ApplicationController
before_action only: :show do
push_frontend_feature_flag(:code_navigation, @project)
push_frontend_feature_flag(:suggest_pipeline) if experiment_enabled?(:suggest_pipeline)
end
def new
......
......@@ -341,4 +341,16 @@ module BlobHelper
edit_fork_button_tag(common_classes, project, text, edit_blob_fork_params(edit_path))
end
end
def show_suggest_pipeline_creation_celebration?
experiment_enabled?(:suggest_pipeline) &&
@blob.auxiliary_viewer.valid?(project: @project, sha: @commit.sha, user: current_user) &&
@blob.path == Gitlab::FileDetector::PATTERNS[:gitlab_ci] &&
@project.uses_default_ci_config? &&
cookies[suggest_pipeline_commit_cookie_name].present?
end
def suggest_pipeline_commit_cookie_name
"suggest_gitlab_ci_yml_commit_#{@project.id}"
end
end
.js-success-pipeline-modal{ 'data-commit-cookie': suggest_pipeline_commit_cookie_name, 'data-pipelines-path': project_pipelines_path(@project) }
......@@ -14,3 +14,5 @@
- title = "Replace #{@blob.name}"
= render 'projects/blob/upload', title: title, placeholder: title, button_title: 'Replace file', form_path: project_update_blob_path(@project, @id), method: :put
= render partial: 'pipeline_tour_success' if show_suggest_pipeline_creation_celebration?
......@@ -9448,6 +9448,9 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
msgid "Go to Pipelines"
msgstr ""
msgid "Go to Webhooks"
msgstr ""
......@@ -11687,6 +11690,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to see all the cool stuff you can do with it."
msgstr ""
msgid "MR widget|The pipeline will now run automatically every time you commit code. Pipelines are useful for deploying static web pages, detecting vulnerabilities in dependencies, static or dynamic application security testing (SAST and DAST), and so much more!"
msgstr ""
msgid "MRApprovals|Approved by"
msgstr ""
......@@ -19029,6 +19038,9 @@ msgstr ""
msgid "Thanks! Don't show me this again"
msgstr ""
msgid "That's it, well done!%{celebrate}"
msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
......
import pipelineTourSuccess from '~/blob/pipeline_tour_success_modal.vue';
import { shallowMount } from '@vue/test-utils';
import Cookies from 'js-cookie';
import { GlSprintf, GlModal } from '@gitlab/ui';
describe('PipelineTourSuccessModal', () => {
let wrapper;
let cookieSpy;
const goToPipelinesPath = 'some_pipeline_path';
const commitCookie = 'some_cookie';
beforeEach(() => {
wrapper = shallowMount(pipelineTourSuccess, {
propsData: {
goToPipelinesPath,
commitCookie,
},
});
cookieSpy = jest.spyOn(Cookies, 'remove');
});
afterEach(() => {
wrapper.destroy();
});
it('has expected structure', () => {
const modal = wrapper.find(GlModal);
const sprintf = modal.find(GlSprintf);
expect(modal.attributes('title')).toContain("That's it, well done!");
expect(sprintf.exists()).toBe(true);
});
it('calls to remove cookie', () => {
wrapper.vm.disableModalFromRenderingAgain();
expect(cookieSpy).toHaveBeenCalledWith(commitCookie);
});
});
......@@ -27,7 +27,7 @@ describe BlobHelper do
end
describe "#edit_blob_link" do
let(:namespace) { create(:namespace, name: 'gitlab' )}
let(:namespace) { create(:namespace, name: 'gitlab') }
let(:project) { create(:project, :repository, namespace: namespace) }
before do
......@@ -202,6 +202,90 @@ describe BlobHelper do
end
end
end
describe '#show_suggest_pipeline_creation_celebration?' do
let(:blob) { fake_blob(path: Gitlab::FileDetector::PATTERNS[:gitlab_ci]) }
let(:current_user) { create(:user) }
before do
assign(:project, project)
assign(:blob, blob)
assign(:commit, double('Commit', sha: 'whatever'))
helper.request.cookies["suggest_gitlab_ci_yml_commit_#{project.id}"] = 'true'
allow(blob).to receive(:auxiliary_viewer).and_return(double('viewer', valid?: true))
allow(helper).to receive(:current_user).and_return(current_user)
end
context 'experiment enabled' do
before do
allow(helper).to receive(:experiment_enabled?).and_return(true)
end
it 'is true' do
expect(helper.show_suggest_pipeline_creation_celebration?).to be_truthy
end
context 'file is invalid format' do
before do
allow(blob).to receive(:auxiliary_viewer).and_return(double('viewer', valid?: false))
end
it 'is false' do
expect(helper.show_suggest_pipeline_creation_celebration?).to be_falsey
end
end
context 'path is not a ci file' do
before do
allow(blob).to receive(:path).and_return('something_bad')
end
it 'is false' do
expect(helper.show_suggest_pipeline_creation_celebration?).to be_falsey
end
end
context 'does not use the default ci config' do
before do
project.ci_config_path = 'something_bad'
end
it 'is false' do
expect(helper.show_suggest_pipeline_creation_celebration?).to be_falsey
end
end
context 'does not have the needed cookie' do
before do
helper.request.cookies.delete "suggest_gitlab_ci_yml_commit_#{project.id}"
end
it 'is false' do
expect(helper.show_suggest_pipeline_creation_celebration?).to be_falsey
end
end
end
context 'experiment disabled' do
before do
allow(helper).to receive(:experiment_enabled?).and_return(false)
end
it 'is false' do
expect(helper.show_suggest_pipeline_creation_celebration?).to be_falsey
end
end
end
end
describe 'suggest_pipeline_commit_cookie_name' do
let(:project) { create(:project) }
it 'uses project id to make up the cookie name' do
assign(:project, project)
expect(helper.suggest_pipeline_commit_cookie_name).to eq "suggest_gitlab_ci_yml_commit_#{project.id}"
end
end
describe '#ide_edit_path' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment