Commit 41311111 authored by Rémy Coutable's avatar Rémy Coutable

Merge branch '297685-jira-connect-app-ui-polish' into 'master'

Jira Connect app UI polish and improvements

See merge request gitlab-org/gitlab!52212
parents 7fd93540 360fe7ad
...@@ -8,6 +8,14 @@ export const getJwt = () => { ...@@ -8,6 +8,14 @@ export const getJwt = () => {
}); });
}; };
export const getLocation = () => {
return new Promise((resolve) => {
AP.getLocation((location) => {
resolve(location);
});
});
};
export const addSubscription = async (addPath, namespace) => { export const addSubscription = async (addPath, namespace) => {
const jwt = await getJwt(); const jwt = await getJwt();
......
...@@ -3,6 +3,8 @@ import { mapState } from 'vuex'; ...@@ -3,6 +3,8 @@ import { mapState } from 'vuex';
import { GlAlert, GlButton, GlModal, GlModalDirective } from '@gitlab/ui'; import { GlAlert, GlButton, GlModal, GlModalDirective } from '@gitlab/ui';
import { __ } from '~/locale'; import { __ } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { getLocation } from '~/jira_connect/api';
import GroupsList from './groups_list.vue'; import GroupsList from './groups_list.vue';
export default { export default {
...@@ -17,17 +19,42 @@ export default { ...@@ -17,17 +19,42 @@ export default {
GlModalDirective, GlModalDirective,
}, },
mixins: [glFeatureFlagsMixin()], mixins: [glFeatureFlagsMixin()],
inject: {
usersPath: {
default: '',
},
},
data() {
return {
location: '',
};
},
computed: { computed: {
...mapState(['errorMessage']), ...mapState(['errorMessage']),
showNewUI() { showNewUI() {
return this.glFeatures.newJiraConnectUi; return this.glFeatures.newJiraConnectUi;
}, },
usersPathWithReturnTo() {
if (this.location) {
return `${this.usersPath}?return_to=${this.location}`;
}
return this.usersPath;
},
}, },
modal: { modal: {
cancelProps: { cancelProps: {
text: __('Cancel'), text: __('Cancel'),
}, },
}, },
created() {
this.setLocation();
},
methods: {
async setLocation() {
this.location = await getLocation();
},
},
}; };
</script> </script>
...@@ -37,13 +64,25 @@ export default { ...@@ -37,13 +64,25 @@ export default {
{{ errorMessage }} {{ errorMessage }}
</gl-alert> </gl-alert>
<h1>GitLab for Jira Configuration</h1> <h2>{{ s__('JiraService|GitLab for Jira Configuration') }}</h2>
<div <div
v-if="showNewUI" v-if="showNewUI"
class="gl-display-flex gl-justify-content-space-between gl-my-5 gl-pb-4 gl-border-b-solid gl-border-b-1 gl-border-b-gray-200" class="gl-display-flex gl-justify-content-space-between gl-my-7 gl-pb-4 gl-border-b-solid gl-border-b-1 gl-border-b-gray-200"
>
<h5 class="gl-align-self-center gl-mb-0" data-testid="new-jira-connect-ui-heading">
{{ s__('Integrations|Linked namespaces') }}
</h5>
<gl-button
v-if="usersPath"
category="primary"
variant="info"
class="gl-align-self-center"
:href="usersPathWithReturnTo"
target="_blank"
>{{ s__('Integrations|Sign in to add namespaces') }}</gl-button
> >
<h3 data-testid="new-jira-connect-ui-heading">{{ s__('Integrations|Linked namespaces') }}</h3> <template v-else>
<gl-button <gl-button
v-gl-modal-directive="'add-namespace-modal'" v-gl-modal-directive="'add-namespace-modal'"
category="primary" category="primary"
...@@ -58,6 +97,7 @@ export default { ...@@ -58,6 +97,7 @@ export default {
> >
<groups-list /> <groups-list />
</gl-modal> </gl-modal>
</template>
</div> </div>
</div> </div>
</template> </template>
...@@ -70,7 +70,7 @@ function initJiraConnect() { ...@@ -70,7 +70,7 @@ function initJiraConnect() {
Vue.use(Translate); Vue.use(Translate);
Vue.use(GlFeatureFlagsPlugin); Vue.use(GlFeatureFlagsPlugin);
const { groupsPath, subscriptionsPath } = el.dataset; const { groupsPath, subscriptionsPath, usersPath } = el.dataset;
return new Vue({ return new Vue({
el, el,
...@@ -78,6 +78,7 @@ function initJiraConnect() { ...@@ -78,6 +78,7 @@ function initJiraConnect() {
provide: { provide: {
groupsPath, groupsPath,
subscriptionsPath, subscriptionsPath,
usersPath,
}, },
render(createElement) { render(createElement) {
return createElement(JiraConnectApp); return createElement(JiraConnectApp);
......
...@@ -79,12 +79,6 @@ $header-height: 40px; ...@@ -79,12 +79,6 @@ $header-height: 40px;
margin-top: 16px; margin-top: 16px;
} }
.heading-with-border {
border-bottom: 1px solid $gray-100;
display: inline-block;
padding-bottom: 16px;
}
svg { svg {
fill: currentColor; fill: currentColor;
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
module ExternalLinkHelper module ExternalLinkHelper
def external_link(body, url, options = {}) def external_link(body, url, options = {})
link_to url, { target: '_blank', rel: 'noopener noreferrer' }.merge(options) do link_to url, { target: '_blank', rel: 'noopener noreferrer' }.merge(options) do
"#{body} #{sprite_icon('external-link')}".html_safe "#{body}#{sprite_icon('external-link', css_class: 'gl-ml-1')}".html_safe
end end
end end
end end
...@@ -12,7 +12,8 @@ module JiraConnectHelper ...@@ -12,7 +12,8 @@ module JiraConnectHelper
{ {
groups_path: api_v4_groups_path(params: { min_access_level: Gitlab::Access::MAINTAINER, skip_groups: skip_groups }), groups_path: api_v4_groups_path(params: { min_access_level: Gitlab::Access::MAINTAINER, skip_groups: skip_groups }),
subscriptions_path: jira_connect_subscriptions_path subscriptions_path: jira_connect_subscriptions_path,
users_path: current_user ? nil : jira_connect_users_path
} }
end end
end end
...@@ -3,21 +3,21 @@ ...@@ -3,21 +3,21 @@
.jira-connect-user .jira-connect-user
- if current_user - if current_user
- user_link = link_to(current_user.to_reference, user_path(current_user), target: '_blank', rel: 'noopener noreferrer') - user_link = link_to(current_user.to_reference, jira_connect_users_path, target: '_blank', rel: 'noopener noreferrer', class: 'js-jira-connect-sign-in')
= _('Signed in to GitLab as %{user_link}').html_safe % { user_link: user_link } = _('Signed in to GitLab as %{user_link}').html_safe % { user_link: user_link }
- elsif @subscriptions.present? - elsif @subscriptions.present?
= link_to _('Sign in to GitLab'), jira_connect_users_path, target: '_blank', rel: 'noopener noreferrer', class: 'js-jira-connect-sign-in' = link_to _('Sign in to GitLab'), jira_connect_users_path, target: '_blank', rel: 'noopener noreferrer', class: 'js-jira-connect-sign-in'
.jira-connect-app .jira-connect-app
- if current_user.blank? && @subscriptions.empty? - if current_user.blank? && @subscriptions.empty?
%h1 %h2= s_('JiraService|GitLab for Jira Configuration')
GitLab for Jira Configuration %p= s_('JiraService|Sign in to GitLab.com to get started.')
%h2.heading-with-border Sign in to GitLab.com to get started.
.gl-mt-5 .gl-mt-7
= external_link _('Sign in to GitLab'), jira_connect_users_path, class: 'ak-button ak-button__appearance-primary js-jira-connect-sign-in' - sign_in_button_class = new_jira_connect_ui? ? 'btn gl-button btn-confirm' : 'ak-button ak-button__appearance-primary'
= external_link _('Sign in to GitLab'), jira_connect_users_path, class: "#{sign_in_button_class} js-jira-connect-sign-in"
.gl-mt-5 .gl-mt-7
%p Note: this integration only works with accounts on GitLab.com (SaaS). %p Note: this integration only works with accounts on GitLab.com (SaaS).
- else - else
.js-jira-connect-app{ data: jira_connect_app_data(@subscriptions) } .js-jira-connect-app{ data: jira_connect_app_data(@subscriptions) }
...@@ -55,10 +55,8 @@ ...@@ -55,10 +55,8 @@
%strong Browser limitations: %strong Browser limitations:
Adding a namespace currently works only in browsers that allow cross‑site cookies. Please make sure to use Adding a namespace currently works only in browsers that allow cross‑site cookies. Please make sure to use
%a{ href: 'https://www.mozilla.org/en-US/firefox/', target: '_blank', rel: 'noopener noreferrer' } Firefox %a{ href: 'https://www.mozilla.org/en-US/firefox/', target: '_blank', rel: 'noopener noreferrer' } Firefox
or
%a{ href: 'https://www.google.com/chrome/index.html', target: '_blank', rel: 'noopener noreferrer' } Google Chrome
or enable cross‑site cookies in your browser when adding a namespace. or enable cross‑site cookies in your browser when adding a namespace.
%a{ href: 'https://gitlab.com/gitlab-org/gitlab/-/issues/263509', target: '_blank', rel: 'noopener noreferrer' } Learn more = link_to _('Learn more'), 'https://gitlab.com/gitlab-org/gitlab/-/issues/284211', target: '_blank', rel: 'noopener noreferrer'
= webpack_bundle_tag 'performance_bar' if performance_bar_enabled? = webpack_bundle_tag 'performance_bar' if performance_bar_enabled?
= webpack_bundle_tag 'jira_connect_app' = webpack_bundle_tag 'jira_connect_app'
......
...@@ -15482,6 +15482,9 @@ msgstr "" ...@@ -15482,6 +15482,9 @@ msgstr ""
msgid "Integrations|Search Jira issues" msgid "Integrations|Search Jira issues"
msgstr "" msgstr ""
msgid "Integrations|Sign in to add namespaces"
msgstr ""
msgid "Integrations|Standard" msgid "Integrations|Standard"
msgstr "" msgstr ""
...@@ -16148,6 +16151,9 @@ msgstr "" ...@@ -16148,6 +16151,9 @@ msgstr ""
msgid "JiraService|For example, 12, 24" msgid "JiraService|For example, 12, 24"
msgstr "" msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
msgid "JiraService|If different from Web URL" msgid "JiraService|If different from Web URL"
msgstr "" msgstr ""
...@@ -16199,6 +16205,9 @@ msgstr "" ...@@ -16199,6 +16205,9 @@ msgstr ""
msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}" msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr "" msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
msgstr ""
msgid "JiraService|This feature requires a Premium plan." msgid "JiraService|This feature requires a Premium plan."
msgstr "" msgstr ""
......
import Vue from 'vue';
import Vuex from 'vuex';
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import { GlAlert } from '@gitlab/ui'; import { GlAlert, GlButton, GlModal } from '@gitlab/ui';
import JiraConnectApp from '~/jira_connect/components/app.vue'; import JiraConnectApp from '~/jira_connect/components/app.vue';
import createStore from '~/jira_connect/store'; import createStore from '~/jira_connect/store';
import { SET_ERROR_MESSAGE } from '~/jira_connect/store/mutation_types'; import { SET_ERROR_MESSAGE } from '~/jira_connect/store/mutation_types';
Vue.use(Vuex); jest.mock('~/jira_connect/api');
describe('JiraConnectApp', () => { describe('JiraConnectApp', () => {
let wrapper; let wrapper;
let store; let store;
const findAlert = () => wrapper.findComponent(GlAlert); const findAlert = () => wrapper.findComponent(GlAlert);
const findGlButton = () => wrapper.findComponent(GlButton);
const findGlModal = () => wrapper.findComponent(GlModal);
const findHeader = () => wrapper.findByTestId('new-jira-connect-ui-heading'); const findHeader = () => wrapper.findByTestId('new-jira-connect-ui-heading');
const findHeaderText = () => findHeader().text(); const findHeaderText = () => findHeader().text();
...@@ -44,6 +45,33 @@ describe('JiraConnectApp', () => { ...@@ -44,6 +45,33 @@ describe('JiraConnectApp', () => {
expect(findHeaderText()).toBe('Linked namespaces'); expect(findHeaderText()).toBe('Linked namespaces');
}); });
describe('when user is not logged in', () => {
beforeEach(() => {
createComponent({
provide: {
glFeatures: { newJiraConnectUi: true },
usersPath: '/users',
},
});
});
it('renders "Sign in" button', () => {
expect(findGlButton().text()).toBe('Sign in to add namespaces');
expect(findGlModal().exists()).toBe(false);
});
});
describe('when user is logged in', () => {
beforeEach(() => {
createComponent();
});
it('renders "Add" button and modal', () => {
expect(findGlButton().text()).toBe('Add namespace');
expect(findGlModal().exists()).toBe(true);
});
});
describe('newJiraConnectUi is false', () => { describe('newJiraConnectUi is false', () => {
it('does not render new UI', () => { it('does not render new UI', () => {
createComponent({ createComponent({
......
...@@ -5,20 +5,42 @@ require 'spec_helper' ...@@ -5,20 +5,42 @@ require 'spec_helper'
RSpec.describe JiraConnectHelper do RSpec.describe JiraConnectHelper do
describe '#jira_connect_app_data' do describe '#jira_connect_app_data' do
let_it_be(:subscription) { create(:jira_connect_subscription) } let_it_be(:subscription) { create(:jira_connect_subscription) }
let(:user) { create(:user) }
subject { helper.jira_connect_app_data([subscription]) } subject { helper.jira_connect_app_data([subscription]) }
context 'user is not logged in' do
before do
allow(view).to receive(:current_user).and_return(nil)
end
it 'includes Jira Connect app attributes' do it 'includes Jira Connect app attributes' do
is_expected.to include( is_expected.to include(
:groups_path, :groups_path,
:subscriptions_path :subscriptions_path,
:users_path
) )
end end
it 'assigns users_path with value' do
expect(subject[:users_path]).to eq(jira_connect_users_path)
end
it 'passes group as "skip_groups" param' do it 'passes group as "skip_groups" param' do
skip_groups_param = CGI.escape('skip_groups[]') skip_groups_param = CGI.escape('skip_groups[]')
expect(subject[:groups_path]).to include("#{skip_groups_param}=#{subscription.namespace.id}") expect(subject[:groups_path]).to include("#{skip_groups_param}=#{subscription.namespace.id}")
end end
end end
context 'user is logged in' do
before do
allow(view).to receive(:current_user).and_return(user)
end
it 'assigns users_path to nil' do
expect(subject[:users_path]).to be_nil
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