Commit 7539bb17 authored by Illya Klymov's avatar Illya Klymov

Merge branch '227262-migrate-project-new-popover' into 'master'

Migrate project new popover

See merge request gitlab-org/gitlab!54700
parents d17e2ab4 2f5e1192
<script>
import { GlPopover, GlFormInputGroup } from '@gitlab/ui';
import { __ } from '~/locale';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
export default {
components: {
GlPopover,
GlFormInputGroup,
ClipboardButton,
},
inject: ['pushToCreateProjectCommand', 'workingWithProjectsHelpPath'],
props: {
target: {
type: [Function, HTMLElement],
required: true,
},
},
i18n: {
clipboardButtonTitle: __('Copy command'),
commandInputAriaLabel: __('Push project from command line'),
helpLinkText: __('What does this command do?'),
labelText: __('Private projects can be created in your personal namespace with:'),
popoverTitle: __('Push to create a project'),
},
};
</script>
<template>
<gl-popover
:target="target"
:title="$options.i18n.popoverTitle"
triggers="click blur"
placement="top"
>
<p>
<label for="push-to-create-tip" class="gl-font-weight-normal">
{{ $options.i18n.labelText }}
</label>
</p>
<p>
<gl-form-input-group
id="push-to-create-tip"
:value="pushToCreateProjectCommand"
readonly
select-on-click
:aria-label="$options.i18n.commandInputAriaLabel"
>
<template #append>
<clipboard-button
:text="pushToCreateProjectCommand"
:title="$options.i18n.clipboardButtonTitle"
tooltip-placement="right"
/>
</template>
</gl-form-input-group>
</p>
<p>
<a
:href="`${workingWithProjectsHelpPath}#push-to-create-a-new-project`"
class="gl-font-sm"
target="_blank"
>{{ $options.i18n.helpLinkText }}</a
>
</p>
</gl-popover>
</template>
<script>
/* eslint-disable vue/no-v-html */
import { GlPopover } from '@gitlab/ui';
import Tracking from '~/tracking';
import LegacyContainer from './legacy_container.vue';
import NewProjectPushTipPopover from './new_project_push_tip_popover.vue';
const trackingMixin = Tracking.mixin(gon.tracking_data);
export default {
components: {
GlPopover,
LegacyContainer,
NewProjectPushTipPopover,
},
mixins: [trackingMixin],
props: {
......@@ -52,19 +50,15 @@ export default {
<p>
{{ __('You can also create a project from the command line.') }}
<a
id="cli-tip"
ref="clipTip"
href="#"
click.prevent
class="push-new-project-tip"
data-title="Push to create a project"
rel="noopener noreferrer"
>
{{ __('Show command') }}
</a>
<gl-popover target="cli-tip" triggers="click blur" placement="top">
<legacy-container selector=".push-new-project-tip-template" />
</gl-popover>
<new-project-push-tip-popover :target="() => $refs.clipTip" />
</p>
</div>
</div>
......
......@@ -2,11 +2,17 @@ import Vue from 'vue';
import NewProjectCreationApp from './components/app.vue';
export default function initNewProjectCreation(el, props) {
const { pushToCreateProjectCommand, workingWithProjectsHelpPath } = el.dataset;
return new Vue({
el,
components: {
NewProjectCreationApp,
},
provide: {
workingWithProjectsHelpPath,
pushToCreateProjectCommand,
},
render(h) {
return h(NewProjectCreationApp, { props });
},
......
import $ from 'jquery';
import DEFAULT_PROJECT_TEMPLATES from 'ee_else_ce/projects/default_project_templates';
import { addSelectOnFocusBehaviour } from '../lib/utils/common_utils';
import {
convertToTitleCase,
humanize,
......@@ -81,7 +80,6 @@ const bindEvents = () => {
const $selectedTemplateText = $('.selected-template');
const $changeTemplateBtn = $('.change-template');
const $selectedIcon = $('.selected-icon');
const $pushNewProjectTipTrigger = $('.push-new-project-tip');
const $projectTemplateButtons = $('.project-templates-buttons');
const $projectName = $('.tab-pane.active #project_name');
......@@ -108,39 +106,6 @@ const bindEvents = () => {
);
});
if ($pushNewProjectTipTrigger) {
$pushNewProjectTipTrigger
.removeAttr('rel')
.removeAttr('target')
.on('click', (e) => {
e.preventDefault();
})
.popover({
title: $pushNewProjectTipTrigger.data('title'),
placement: 'bottom',
html: true,
content: $('.push-new-project-tip-template').html(),
})
.on('shown.bs.popover', () => {
$(document).on('click.popover touchstart.popover', (event) => {
if ($(event.target).closest('.popover').length === 0) {
$pushNewProjectTipTrigger.trigger('click');
}
});
const target = $(`#${$pushNewProjectTipTrigger.attr('aria-describedby')}`).find(
'.js-select-on-focus',
);
addSelectOnFocusBehaviour(target);
target.focus();
})
.on('hide.bs.popover', () => {
// eslint-disable-next-line @gitlab/no-global-event-off
$(document).off('click.popover touchstart.popover');
});
}
function chooseTemplate() {
$projectTemplateButtons.addClass('hidden');
$projectFieldsForm.addClass('selected');
......
.push-to-create-popover
%p
= label_tag(:push_to_create_tip, _("Private projects can be created in your personal namespace with:"), class: "weight-normal")
%p.input-group.project-tip-command
%span
= text_field_tag :push_to_create_tip, push_to_create_project_command, class: "js-select-on-focus form-control monospace", readonly: true, aria: { label: _("Push project from command line") }
%span.input-group-append
= clipboard_button(text: push_to_create_project_command, title: _("Copy command"), class: 'input-group-text', placement: "right")
%p
= link_to("What does this command do?", help_page_path("user/project/working_with_projects", anchor: "push-to-create-a-new-project"), target: "_blank")
......@@ -8,7 +8,7 @@
.project-edit-errors
= render 'projects/errors'
.js-experiment-new-project-creation{ data: { is_ci_cd_available: (ci_cd_projects_available? if Gitlab.ee?), has_errors: @project.errors.any?, new_project_guidelines: brand_new_project_guidelines } }
.js-experiment-new-project-creation{ data: { is_ci_cd_available: (ci_cd_projects_available? if Gitlab.ee?), has_errors: @project.errors.any?, new_project_guidelines: brand_new_project_guidelines, push_to_create_project_command: push_to_create_project_command, working_with_projects_help_path: help_page_path("user/project/working_with_projects") } }
.row{ 'v-cloak': true }
.col-lg-3.profile-settings-sidebar
......@@ -28,9 +28,6 @@
%p
%strong= _("Tip:")
= _("You can also create a project from the command line.")
%a.push-new-project-tip{ data: { title: _("Push to create a project") }, href: help_page_path('user/project/working_with_projects', anchor: 'push-to-create-a-new-project'), target: "_blank", rel: "noopener noreferrer" }
= _("Show command")
%template.push-new-project-tip-template= render partial: "new_project_push_tip"
.col-lg-9.js-toggle-container
%ul.nav.nav-tabs.nav-links.gitlab-tabs{ role: 'tablist' }
......
......@@ -105,7 +105,6 @@ exports[`RotationsListSectionComponent when the timeframe includes today renders
<div
class="gl-popover"
title="nora.schaden"
>
<p
class="gl-m-0"
......@@ -151,7 +150,6 @@ exports[`RotationsListSectionComponent when the timeframe includes today renders
<div
class="gl-popover"
title="racheal.loving"
>
<p
class="gl-m-0"
......
......@@ -33547,6 +33547,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
msgid "What does this command do?"
msgstr ""
msgid "What is squashing?"
msgstr ""
......
......@@ -49,7 +49,7 @@ RSpec.describe 'Project' do
it 'shows the command in a popover', :js do
click_link 'Show command'
expect(page).to have_css('.popover .push-to-create-popover #push_to_create_tip')
expect(page).to have_css('.popover #push-to-create-tip')
expect(page).to have_content 'Private projects can be created in your personal namespace with:'
end
end
......
......@@ -39,7 +39,10 @@ jest.mock('@gitlab/ui/dist/components/base/popover/popover.js', () => ({
default: () => [],
},
...Object.fromEntries(
['target', 'triggers', 'placement', 'boundary', 'container'].map((prop) => [prop, {}]),
['title', 'target', 'triggers', 'placement', 'boundary', 'container'].map((prop) => [
prop,
{},
]),
),
},
render(h) {
......
import { GlPopover, GlFormInputGroup } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import NewProjectPushTipPopover from '~/projects/experiment_new_project_creation/components/new_project_push_tip_popover.vue';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
describe('New project push tip popover', () => {
let wrapper;
const targetId = 'target';
const pushToCreateProjectCommand = 'command';
const workingWithProjectsHelpPath = 'path';
const findPopover = () => wrapper.findComponent(GlPopover);
const findClipboardButton = () => wrapper.findComponent(ClipboardButton);
const findFormInput = () => wrapper.findComponent(GlFormInputGroup);
const findHelpLink = () => wrapper.find('a');
const findTarget = () => document.getElementById(targetId);
const buildWrapper = () => {
wrapper = shallowMount(NewProjectPushTipPopover, {
propsData: {
target: findTarget(),
},
stubs: {
GlFormInputGroup,
},
provide: {
pushToCreateProjectCommand,
workingWithProjectsHelpPath,
},
});
};
beforeEach(() => {
setFixtures(`<a id="${targetId}"></a>`);
buildWrapper();
});
afterEach(() => {
wrapper.destroy();
});
it('renders popover that targets the specified target', () => {
expect(findPopover().props()).toMatchObject({
target: findTarget(),
triggers: 'click blur',
placement: 'top',
title: 'Push to create a project',
});
});
it('renders a readonly form input with the push to create command', () => {
expect(findFormInput().props()).toMatchObject({
value: pushToCreateProjectCommand,
selectOnClick: true,
});
expect(findFormInput().attributes()).toMatchObject({
'aria-label': 'Push project from command line',
readonly: 'readonly',
});
});
it('allows copying the push command using the clipboard button', () => {
expect(findClipboardButton().props()).toMatchObject({
text: pushToCreateProjectCommand,
tooltipPlacement: 'right',
title: 'Copy command',
});
});
it('displays a link to open the push command help page reference', () => {
expect(findHelpLink().attributes().href).toBe(
`${workingWithProjectsHelpPath}#push-to-create-a-new-project`,
);
});
});
import { shallowMount } from '@vue/test-utils';
import { mockTracking } from 'helpers/tracking_helper';
import NewProjectPushTipPopover from '~/projects/experiment_new_project_creation/components/new_project_push_tip_popover.vue';
import WelcomePage from '~/projects/experiment_new_project_creation/components/welcome.vue';
describe('Welcome page', () => {
......@@ -28,4 +29,13 @@ describe('Welcome page', () => {
expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_tab', { label: 'test' });
});
});
it('renders new project push tip popover', () => {
createComponent({ panels: [{ name: 'test', href: '#' }] });
const popover = wrapper.findComponent(NewProjectPushTipPopover);
expect(popover.exists()).toBe(true);
expect(popover.props().target()).toBe(wrapper.find({ ref: 'clipTip' }).element);
});
});
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