Commit 3b1f97e0 authored by Kushal Pandya's avatar Kushal Pandya

Merge branch...

Merge branch '344559-migrate-app-views-projects-_bitbucket_import_modal-html-haml-modal-implementation-to-glmodal' into 'master'

Migrate bitbucket import modal implementation to `GlModal`

See merge request gitlab-org/gitlab!80434
parents 323e56f0 516ee15f
<script> <script>
import { GlModal } from '@gitlab/ui'; import { GlModal, GlSafeHtmlDirective } from '@gitlab/ui';
import { __ } from '~/locale'; import { __ } from '~/locale';
export default { export default {
cancelAction: { text: __('Cancel') }, cancelAction: { text: __('Cancel') },
directives: {
SafeHtml: GlSafeHtmlDirective,
},
components: { components: {
GlModal, GlModal,
}, },
props: { props: {
title: {
type: String,
required: false,
default: '',
},
primaryText: { primaryText: {
type: String, type: String,
required: false, required: false,
...@@ -18,11 +26,27 @@ export default { ...@@ -18,11 +26,27 @@ export default {
required: false, required: false,
default: 'confirm', default: 'confirm',
}, },
modalHtmlMessage: {
type: String,
required: false,
default: '',
},
hideCancel: {
type: Boolean,
required: false,
default: false,
},
}, },
computed: { computed: {
primaryAction() { primaryAction() {
return { text: this.primaryText, attributes: { variant: this.primaryVariant } }; return { text: this.primaryText, attributes: { variant: this.primaryVariant } };
}, },
cancelAction() {
return this.hideCancel ? null : this.$options.cancelAction;
},
shouldShowHeader() {
return Boolean(this.title?.length);
},
}, },
mounted() { mounted() {
this.$refs.modal.show(); this.$refs.modal.show();
...@@ -36,12 +60,14 @@ export default { ...@@ -36,12 +60,14 @@ export default {
size="sm" size="sm"
modal-id="confirmationModal" modal-id="confirmationModal"
body-class="gl-display-flex" body-class="gl-display-flex"
:title="title"
:action-primary="primaryAction" :action-primary="primaryAction"
:action-cancel="$options.cancelAction" :action-cancel="cancelAction"
hide-header :hide-header="!shouldShowHeader"
@primary="$emit('confirmed')" @primary="$emit('confirmed')"
@hidden="$emit('closed')" @hidden="$emit('closed')"
> >
<div class="gl-align-self-center"><slot></slot></div> <div v-if="!modalHtmlMessage" class="gl-align-self-center"><slot></slot></div>
<div v-else v-safe-html="modalHtmlMessage" class="gl-align-self-center"></div>
</gl-modal> </gl-modal>
</template> </template>
import Vue from 'vue'; import Vue from 'vue';
export function confirmAction(message, { primaryBtnVariant, primaryBtnText } = {}) { export function confirmAction(
message,
{ primaryBtnVariant, primaryBtnText, modalHtmlMessage, title, hideCancel } = {},
) {
return new Promise((resolve) => { return new Promise((resolve) => {
let confirmed = false; let confirmed = false;
...@@ -15,6 +18,9 @@ export function confirmAction(message, { primaryBtnVariant, primaryBtnText } = { ...@@ -15,6 +18,9 @@ export function confirmAction(message, { primaryBtnVariant, primaryBtnText } = {
props: { props: {
primaryVariant: primaryBtnVariant, primaryVariant: primaryBtnVariant,
primaryText: primaryBtnText, primaryText: primaryBtnText,
title,
modalHtmlMessage,
hideCancel,
}, },
on: { on: {
confirmed() { confirmed() {
......
import $ from 'jquery'; import $ from 'jquery';
import { debounce } from 'lodash'; import { debounce } from 'lodash';
import DEFAULT_PROJECT_TEMPLATES from 'ee_else_ce/projects/default_project_templates'; import DEFAULT_PROJECT_TEMPLATES from 'ee_else_ce/projects/default_project_templates';
import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '../lib/utils/constants'; import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '../lib/utils/constants';
import axios from '../lib/utils/axios_utils'; import axios from '../lib/utils/axios_utils';
import { import {
...@@ -105,6 +106,21 @@ const deriveProjectPathFromUrl = ($projectImportUrl) => { ...@@ -105,6 +106,21 @@ const deriveProjectPathFromUrl = ($projectImportUrl) => {
}; };
const bindHowToImport = () => { const bindHowToImport = () => {
const importLinks = document.querySelectorAll('.js-how-to-import-link');
importLinks.forEach((link) => {
const { modalTitle: title, modalMessage: modalHtmlMessage } = link.dataset;
link.addEventListener('click', (e) => {
e.preventDefault();
confirmAction('', {
modalHtmlMessage,
title,
hideCancel: true,
});
});
});
$('.how_to_import_link').on('click', (e) => { $('.how_to_import_link').on('click', (e) => {
e.preventDefault(); e.preventDefault();
$(e.currentTarget).next('.modal').show(); $(e.currentTarget).next('.modal').show();
......
...@@ -430,6 +430,18 @@ module ProjectsHelper ...@@ -430,6 +430,18 @@ module ProjectsHelper
end end
end end
def import_from_bitbucket_message
link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path("integration/bitbucket") }
str = if current_user.admin?
'ImportProjects|To enable importing projects from Bitbucket, as administrator you need to configure %{link_start}OAuth integration%{link_end}'
else
'ImportProjects|To enable importing projects from Bitbucket, ask your GitLab administrator to configure %{link_start}OAuth integration%{link_end}'
end
s_(str).html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
end
private private
def tab_ability_map def tab_ability_map
......
#bitbucket_import_modal.modal
.modal-dialog
.modal-content
.modal-header
%h3.modal-title Import projects from Bitbucket
%button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') }
%span{ "aria-hidden": "true" } &times;
.modal-body
To enable importing projects from Bitbucket,
- if current_user.admin?
as administrator you need to configure
- else
ask your GitLab administrator to configure
= link_to 'OAuth integration', help_page_path("integration/bitbucket")
...@@ -22,13 +22,11 @@ ...@@ -22,13 +22,11 @@
- if bitbucket_import_enabled? - if bitbucket_import_enabled?
%div %div
= link_to status_import_bitbucket_path, class: "gl-button btn-default btn import_bitbucket js-import-project-btn #{'how_to_import_link' unless bitbucket_import_configured?}", = link_to status_import_bitbucket_path, class: "gl-button btn-default btn import_bitbucket js-import-project-btn #{'js-how-to-import-link' unless bitbucket_import_configured?}",
data: { platform: 'bitbucket_cloud', **tracking_attrs_data(track_label, 'click_button', 'bitbucket_cloud') } do data: { modal_title: _("Import projects from Bitbucket"), modal_message: import_from_bitbucket_message, platform: 'bitbucket_cloud', **tracking_attrs_data(track_label, 'click_button', 'bitbucket_cloud') } do
.gl-button-icon .gl-button-icon
= sprite_icon('bitbucket') = sprite_icon('bitbucket')
Bitbucket Cloud Bitbucket Cloud
- unless bitbucket_import_configured?
= render 'projects/bitbucket_import_modal'
- if bitbucket_server_import_enabled? - if bitbucket_server_import_enabled?
%div %div
= link_to status_import_bitbucket_server_path, class: "gl-button btn-default btn import_bitbucket js-import-project-btn", data: { platform: 'bitbucket_server', **tracking_attrs_data(track_label, 'click_button', 'bitbucket_server') } do = link_to status_import_bitbucket_server_path, class: "gl-button btn-default btn import_bitbucket js-import-project-btn", data: { platform: 'bitbucket_server', **tracking_attrs_data(track_label, 'click_button', 'bitbucket_server') } do
......
...@@ -404,4 +404,47 @@ RSpec.describe 'New project', :js do ...@@ -404,4 +404,47 @@ RSpec.describe 'New project', :js do
end end
end end
end end
context 'from Bitbucket', :js do
shared_examples 'has a link to bitbucket cloud' do
context 'when bitbucket is not configured' do
before do
allow(Gitlab::Auth::OAuth::Provider).to receive(:enabled?).and_call_original
allow(Gitlab::Auth::OAuth::Provider)
.to receive(:enabled?).with(:bitbucket)
.and_return(false)
visit new_project_path
click_link 'Import project'
click_link 'Bitbucket Cloud'
end
it 'shows import instructions' do
expect(find('.modal-body')).to have_content(bitbucket_link_content)
end
end
end
context 'as a user' do
let(:user) { create(:user) }
let(:bitbucket_link_content) { 'To enable importing projects from Bitbucket, ask your GitLab administrator to configure OAuth integration' }
before do
sign_in(user)
end
it_behaves_like 'has a link to bitbucket cloud'
end
context 'as an admin' do
let(:user) { create(:admin) }
let(:bitbucket_link_content) { 'To enable importing projects from Bitbucket, as administrator you need to configure OAuth integration' }
before do
sign_in(user)
end
it_behaves_like 'has a link to bitbucket cloud'
end
end
end end
...@@ -6,11 +6,13 @@ describe('Confirm Modal', () => { ...@@ -6,11 +6,13 @@ describe('Confirm Modal', () => {
let wrapper; let wrapper;
let modal; let modal;
const createComponent = ({ primaryText, primaryVariant } = {}) => { const createComponent = ({ primaryText, primaryVariant, title, hideCancel = false } = {}) => {
wrapper = mount(ConfirmModal, { wrapper = mount(ConfirmModal, {
propsData: { propsData: {
primaryText, primaryText,
primaryVariant, primaryVariant,
hideCancel,
title,
}, },
}); });
}; };
...@@ -55,5 +57,19 @@ describe('Confirm Modal', () => { ...@@ -55,5 +57,19 @@ describe('Confirm Modal', () => {
expect(customProps.text).toBe('OK'); expect(customProps.text).toBe('OK');
expect(customProps.attributes.variant).toBe('confirm'); expect(customProps.attributes.variant).toBe('confirm');
}); });
it('should hide the cancel button if `hideCancel` is set', () => {
createComponent({ hideCancel: true });
const props = findGlModal().props();
expect(props.actionCancel).toBeNull();
});
it('should set the modal title when the `title` prop is set', () => {
const title = 'Modal title';
createComponent({ title });
expect(findGlModal().props().title).toBe(title);
});
}); });
}); });
...@@ -1026,4 +1026,26 @@ RSpec.describe ProjectsHelper do ...@@ -1026,4 +1026,26 @@ RSpec.describe ProjectsHelper do
end end
end end
end end
describe '#import_from_bitbucket_message' do
before do
allow(helper).to receive(:current_user).and_return(user)
end
context 'as a user' do
it 'returns a link to contact an administrator' do
allow(user).to receive(:admin?).and_return(false)
expect(helper.import_from_bitbucket_message).to have_text('To enable importing projects from Bitbucket, ask your GitLab administrator to configure OAuth integration')
end
end
context 'as an administrator' do
it 'returns a link to configure bitbucket' do
allow(user).to receive(:admin?).and_return(true)
expect(helper.import_from_bitbucket_message).to have_text('To enable importing projects from Bitbucket, as administrator you need to configure OAuth integration')
end
end
end
end end
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