Commit 3689c4bd authored by Martin Wortschack's avatar Martin Wortschack

Merge branch...

Merge branch 'gitlab-org-growth-ui-ux-64-nudge-users-to-commit-their-changes-and-set-up-a-pipeline-file' into 'master'

Nudge users to commit their changes

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

See merge request gitlab-org/gitlab!26468
parents c099de77 631fc8c9
...@@ -9,6 +9,7 @@ import GitignoreSelector from './template_selectors/gitignore_selector'; ...@@ -9,6 +9,7 @@ import GitignoreSelector from './template_selectors/gitignore_selector';
import LicenseSelector from './template_selectors/license_selector'; import LicenseSelector from './template_selectors/license_selector';
import toast from '~/vue_shared/plugins/global_toast'; import toast from '~/vue_shared/plugins/global_toast';
import { __ } from '~/locale'; import { __ } from '~/locale';
import initPopover from '~/blob/suggest_gitlab_ci_yml';
export default class FileTemplateMediator { export default class FileTemplateMediator {
constructor({ editor, currentAction, projectId }) { constructor({ editor, currentAction, projectId }) {
...@@ -128,6 +129,7 @@ export default class FileTemplateMediator { ...@@ -128,6 +129,7 @@ export default class FileTemplateMediator {
selectTemplateFile(selector, query, data) { selectTemplateFile(selector, query, data) {
const self = this; const self = this;
const { name } = selector.config; const { name } = selector.config;
const suggestCommitChanges = document.querySelector('.js-suggest-gitlab-ci-yml-commit-changes');
selector.renderLoading(); selector.renderLoading();
...@@ -146,6 +148,10 @@ export default class FileTemplateMediator { ...@@ -146,6 +148,10 @@ export default class FileTemplateMediator {
}, },
}, },
}); });
if (suggestCommitChanges) {
initPopover(suggestCommitChanges);
}
}) })
.catch(err => new Flash(`An error occurred while fetching the template: ${err}`)); .catch(err => new Flash(`An error occurred while fetching the template: ${err}`));
} }
......
<script> <script>
import { GlPopover, GlSprintf, GlButton, GlIcon } from '@gitlab/ui'; import { GlPopover, GlSprintf, GlButton, GlIcon } from '@gitlab/ui';
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
import { parseBoolean } from '~/lib/utils/common_utils'; import { parseBoolean, scrollToElement } from '~/lib/utils/common_utils';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import { glEmojiTag } from '~/emoji'; import { glEmojiTag } from '~/emoji';
const popoverStates = {
suggest_gitlab_ci_yml: {
title: s__(`suggestPipeline|1/2: Choose a template`),
content: s__(
`suggestPipeline|We recommend the %{boldStart}Code Quality%{boldEnd} template, which will add a report widget to your Merge Requests. This way you’ll learn about code quality degradations much sooner. %{footerStart} Goodbye technical debt! %{footerEnd}`,
),
emoji: glEmojiTag('wave'),
},
suggest_commit_first_project_gitlab_ci_yml: {
title: s__(`suggestPipeline|2/2: Commit your changes`),
content: s__(
`suggestPipeline|Commit the changes and your pipeline will automatically run for the first time.`,
),
},
};
export default { export default {
components: { components: {
GlPopover, GlPopover,
...@@ -17,7 +32,7 @@ export default { ...@@ -17,7 +32,7 @@ export default {
type: String, type: String,
required: true, required: true,
}, },
cssClass: { trackLabel: {
type: String, type: String,
required: true, required: true,
}, },
...@@ -33,17 +48,19 @@ export default { ...@@ -33,17 +48,19 @@ export default {
}, },
computed: { computed: {
suggestTitle() { suggestTitle() {
return s__(`suggestPipeline|1/2: Choose a template`); return popoverStates[this.trackLabel].title || '';
}, },
suggestContent() { suggestContent() {
return s__( return popoverStates[this.trackLabel].content || '';
`suggestPipeline|We recommend the %{boldStart}Code Quality%{boldEnd} template, which will add a report widget to your Merge Requests. This way you’ll learn about code quality degradations much sooner. %{footerStart} Goodbye technical debt! %{footerEnd}`,
);
}, },
emoji() { emoji() {
return glEmojiTag('wave'); return popoverStates[this.trackLabel].emoji || '';
}, },
}, },
mounted() {
if (this.trackLabel === 'suggest_commit_first_project_gitlab_ci_yml' && !this.popoverDismissed)
scrollToElement(document.querySelector(this.target));
},
methods: { methods: {
onDismiss() { onDismiss() {
this.popoverDismissed = true; this.popoverDismissed = true;
...@@ -61,13 +78,15 @@ export default { ...@@ -61,13 +78,15 @@ export default {
placement="rightbottom" placement="rightbottom"
trigger="manual" trigger="manual"
container="viewport" container="viewport"
:css-classes="[cssClass]" :css-classes="['suggest-gitlab-ci-yml', 'ml-4']"
> >
<template #title> <template #title>
<gl-button :aria-label="__('Close')" class="btn-blank float-right" @click="onDismiss"> <span v-html="suggestTitle"></span>
<gl-icon name="close" aria-hidden="true" /> <span class="ml-auto">
</gl-button> <gl-button :aria-label="__('Close')" class="btn-blank" @click="onDismiss">
{{ suggestTitle }} <gl-icon name="close" aria-hidden="true" />
</gl-button>
</span>
</template> </template>
<gl-sprintf :message="suggestContent"> <gl-sprintf :message="suggestContent">
......
...@@ -8,7 +8,7 @@ export default el => ...@@ -8,7 +8,7 @@ export default el =>
return createElement(Popover, { return createElement(Popover, {
props: { props: {
target: el.dataset.target, target: el.dataset.target,
cssClass: el.dataset.cssClass, trackLabel: el.dataset.trackLabel,
dismissKey: el.dataset.dismissKey, dismissKey: el.dataset.dismissKey,
}, },
}); });
......
...@@ -4,11 +4,13 @@ import $ from 'jquery'; ...@@ -4,11 +4,13 @@ import $ from 'jquery';
import NewCommitForm from '../new_commit_form'; import NewCommitForm from '../new_commit_form';
import EditBlob from './edit_blob'; import EditBlob from './edit_blob';
import BlobFileDropzone from '../blob/blob_file_dropzone'; import BlobFileDropzone from '../blob/blob_file_dropzone';
import initPopover from '~/blob/suggest_gitlab_ci_yml';
export default () => { export default () => {
const editBlobForm = $('.js-edit-blob-form'); const editBlobForm = $('.js-edit-blob-form');
const uploadBlobForm = $('.js-upload-blob-form'); const uploadBlobForm = $('.js-upload-blob-form');
const deleteBlobForm = $('.js-delete-blob-form'); const deleteBlobForm = $('.js-delete-blob-form');
const suggestEl = document.querySelector('.js-suggest-gitlab-ci-yml');
if (editBlobForm.length) { if (editBlobForm.length) {
const urlRoot = editBlobForm.data('relativeUrlRoot'); const urlRoot = editBlobForm.data('relativeUrlRoot');
...@@ -56,4 +58,8 @@ export default () => { ...@@ -56,4 +58,8 @@ export default () => {
if (deleteBlobForm.length) { if (deleteBlobForm.length) {
new NewCommitForm(deleteBlobForm); new NewCommitForm(deleteBlobForm);
} }
if (suggestEl) {
initPopover(suggestEl);
}
}; };
...@@ -144,9 +144,7 @@ ...@@ -144,9 +144,7 @@
.popover-header { .popover-header {
padding: $gl-padding; padding: $gl-padding;
display: flex;
.ic-close { align-items: center;
margin-top: -1em;
}
} }
} }
.form-actions .form-actions
= button_tag 'Commit changes', class: 'btn commit-btn js-commit-button btn-success qa-commit-button' = button_tag 'Commit changes', id: 'commit-changes', class: 'btn commit-btn js-commit-button btn-success qa-commit-button'
= link_to 'Cancel', cancel_path, = link_to 'Cancel', cancel_path,
class: 'btn btn-cancel', data: {confirm: leave_edit_message} class: 'btn btn-cancel', data: {confirm: leave_edit_message}
......
...@@ -20,7 +20,10 @@ ...@@ -20,7 +20,10 @@
required: true, class: 'form-control new-file-name js-file-path-name-input', value: params[:file_name] || (should_suggest_gitlab_ci_yml? ? '.gitlab-ci.yml' : '') required: true, class: 'form-control new-file-name js-file-path-name-input', value: params[:file_name] || (should_suggest_gitlab_ci_yml? ? '.gitlab-ci.yml' : '')
= render 'template_selectors' = render 'template_selectors'
- if should_suggest_gitlab_ci_yml? - if should_suggest_gitlab_ci_yml?
= render partial: 'suggest_gitlab_ci_yml', locals: { target: '#gitlab-ci-yml-selector', dismiss_key: "suggest_gitlab_ci_yml_#{@project.id}" } .js-suggest-gitlab-ci-yml{ data: { toggle: 'popover',
target: '#gitlab-ci-yml-selector',
track_label: 'suggest_gitlab_ci_yml',
dismiss_key: "suggest_gitlab_ci_yml_#{@project.id}" } }
.file-buttons .file-buttons
- if is_markdown - if is_markdown
......
.js-suggest-gitlab-ci-yml{ data: { toggle: 'popover',
target: target,
css_class: 'suggest-gitlab-ci-yml ml-4',
dismiss_key: dismiss_key } }
...@@ -13,3 +13,8 @@ ...@@ -13,3 +13,8 @@
= hidden_field_tag 'content', '', id: 'file-content' = hidden_field_tag 'content', '', id: 'file-content'
= render 'projects/commit_button', ref: @ref, = render 'projects/commit_button', ref: @ref,
cancel_path: project_tree_path(@project, @id) cancel_path: project_tree_path(@project, @id)
- if should_suggest_gitlab_ci_yml?
.js-suggest-gitlab-ci-yml-commit-changes{ data: { toggle: 'popover',
target: '#commit-changes',
track_label: 'suggest_commit_first_project_gitlab_ci_yml',
dismiss_key: "suggest_commit_first_project_gitlab_ci_yml_#{@project.id}" } }
...@@ -24211,6 +24211,12 @@ msgstr "" ...@@ -24211,6 +24211,12 @@ msgstr ""
msgid "suggestPipeline|1/2: Choose a template" msgid "suggestPipeline|1/2: Choose a template"
msgstr "" msgstr ""
msgid "suggestPipeline|2/2: Commit your changes"
msgstr ""
msgid "suggestPipeline|Commit the changes and your pipeline will automatically run for the first time."
msgstr ""
msgid "suggestPipeline|We recommend the %{boldStart}Code Quality%{boldEnd} template, which will add a report widget to your Merge Requests. This way you’ll learn about code quality degradations much sooner. %{footerStart} Goodbye technical debt! %{footerEnd}" msgid "suggestPipeline|We recommend the %{boldStart}Code Quality%{boldEnd} template, which will add a report widget to your Merge Requests. This way you’ll learn about code quality degradations much sooner. %{footerStart} Goodbye technical debt! %{footerEnd}"
msgstr "" msgstr ""
......
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import Popover from '~/blob/suggest_gitlab_ci_yml/components/popover.vue'; import Popover from '~/blob/suggest_gitlab_ci_yml/components/popover.vue';
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
import * as utils from '~/lib/utils/common_utils';
const popoverTarget = 'gitlab-ci-yml-selector'; jest.mock('~/lib/utils/common_utils', () => ({
...jest.requireActual('~/lib/utils/common_utils'),
scrollToElement: jest.fn(),
}));
const target = 'gitlab-ci-yml-selector';
const dismissKey = 'suggest_gitlab_ci_yml_99'; const dismissKey = 'suggest_gitlab_ci_yml_99';
const defaultTrackLabel = 'suggest_gitlab_ci_yml';
describe('Suggest gitlab-ci.yml Popover', () => { describe('Suggest gitlab-ci.yml Popover', () => {
let wrapper; let wrapper;
function createWrapper() { function createWrapper(trackLabel) {
wrapper = shallowMount(Popover, { wrapper = shallowMount(Popover, {
propsData: { propsData: {
target: popoverTarget, target,
cssClass: 'js-class', trackLabel,
dismissKey, dismissKey,
}, },
}); });
...@@ -25,7 +32,7 @@ describe('Suggest gitlab-ci.yml Popover', () => { ...@@ -25,7 +32,7 @@ describe('Suggest gitlab-ci.yml Popover', () => {
describe('when no dismiss cookie is set', () => { describe('when no dismiss cookie is set', () => {
beforeEach(() => { beforeEach(() => {
createWrapper(); createWrapper(defaultTrackLabel);
}); });
it('sets popoverDismissed to false', () => { it('sets popoverDismissed to false', () => {
...@@ -36,11 +43,26 @@ describe('Suggest gitlab-ci.yml Popover', () => { ...@@ -36,11 +43,26 @@ describe('Suggest gitlab-ci.yml Popover', () => {
describe('when the dismiss cookie is set', () => { describe('when the dismiss cookie is set', () => {
beforeEach(() => { beforeEach(() => {
Cookies.set(dismissKey, true); Cookies.set(dismissKey, true);
createWrapper(); createWrapper(defaultTrackLabel);
}); });
it('sets popoverDismissed to true', () => { it('sets popoverDismissed to true', () => {
expect(wrapper.vm.popoverDismissed).toEqual(true); expect(wrapper.vm.popoverDismissed).toEqual(true);
}); });
beforeEach(() => {
Cookies.remove(dismissKey);
});
});
describe('when the popover is mounted with the trackLabel of the Confirm button popover at the bottom of the page', () => {
it('calls scrollToElement so that the Confirm button and popover will be in sight', () => {
const scrollToElementSpy = jest.spyOn(utils, 'scrollToElement');
const commitTrackLabel = 'suggest_commit_first_project_gitlab_ci_yml';
createWrapper(commitTrackLabel);
expect(scrollToElementSpy).toHaveBeenCalled();
});
}); });
}); });
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