Commit 6b310d57 authored by Heinrich Lee Yu's avatar Heinrich Lee Yu

Merge branch '225818-add-an-upgrade-banner-for-non-premium-plans' into 'master'

Add an upgrade banner for non-premium plans

See merge request gitlab-org/gitlab!36725
parents 42649c60 e97dff4f
......@@ -106,10 +106,11 @@ export default {
return {
id: this.fieldId,
name: this.fieldName,
state: this.valid,
};
},
valid() {
return !this.required || !isEmpty(this.model) || !this.validated;
return !this.required || !isEmpty(this.model) || this.isNonEmptyPassword || !this.validated;
},
},
created() {
......
<script>
import { GlFormGroup, GlFormCheckbox, GlFormInput, GlSprintf, GlLink } from '@gitlab/ui';
import eventHub from '../event_hub';
import {
GlFormGroup,
GlFormCheckbox,
GlFormInput,
GlSprintf,
GlLink,
GlButton,
GlCard,
} from '@gitlab/ui';
export default {
name: 'JiraIssuesFields',
......@@ -9,17 +18,30 @@ export default {
GlFormInput,
GlSprintf,
GlLink,
GlButton,
GlCard,
},
props: {
showJiraIssuesIntegration: {
type: Boolean,
required: false,
default: false,
},
initialEnableJiraIssues: {
type: Boolean,
required: false,
default: null,
},
initialProjectKey: {
type: String,
required: false,
default: null,
},
upgradePlanPath: {
type: String,
required: false,
default: null,
},
editProjectPath: {
type: String,
required: false,
......@@ -30,8 +52,25 @@ export default {
return {
enableJiraIssues: this.initialEnableJiraIssues,
projectKey: this.initialProjectKey,
validated: false,
};
},
computed: {
validProjectKey() {
return !this.enableJiraIssues || Boolean(this.projectKey) || !this.validated;
},
},
created() {
eventHub.$on('validateForm', this.validateForm);
},
beforeDestroy() {
eventHub.$off('validateForm', this.validateForm);
},
methods: {
validateForm() {
this.validated = true;
},
},
};
</script>
......@@ -45,44 +84,66 @@ export default {
<p>
{{
s__(
'JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of issues and view any issue as read-only.',
'JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only.',
)
}}
</p>
<input name="service[issues_enabled]" type="hidden" value="false" />
<gl-form-checkbox v-model="enableJiraIssues" name="service[issues_enabled]">
{{ s__('JiraService|Enable Jira issues') }}
<template #help>
{{
s__(
'JiraService|Warning: All GitLab users that have access to this GitLab project will be able to view all issues from the Jira project specified below.',
)
}}
</template>
</gl-form-checkbox>
<template v-if="showJiraIssuesIntegration">
<input name="service[issues_enabled]" type="hidden" value="false" />
<gl-form-checkbox v-model="enableJiraIssues" name="service[issues_enabled]">
{{ s__('JiraService|Enable Jira issues') }}
<template #help>
{{
s__(
'JiraService|Warning: All GitLab users that have access to this GitLab project will be able to view all issues from the Jira project specified below.',
)
}}
</template>
</gl-form-checkbox>
</template>
<gl-card v-else class="gl-mt-7">
<strong>{{ __('This is a Premium feature') }}</strong>
<p>{{ __('Upgrade your plan to enable this feature of the Jira Integration.') }}</p>
<gl-button
v-if="upgradePlanPath"
category="primary"
variant="info"
:href="upgradePlanPath"
target="_blank"
>
{{ __('Upgrade your plan') }}
</gl-button>
</gl-card>
</div>
</gl-form-group>
<gl-form-group :label="s__('JiraService|Jira project key')">
<gl-form-input
v-model="projectKey"
type="text"
name="service[project_key]"
:placeholder="s__('JiraService|e.g. AB')"
:disabled="!enableJiraIssues"
/>
</gl-form-group>
<p>
<gl-sprintf
:message="
s__(
'JiraService|Displaying Jira issues while leaving the GitLab issue functionality enabled might be confusing. Consider %{linkStart}disabling GitLab issues%{linkEnd} if they won’t otherwise be used.',
)
"
<template v-if="showJiraIssuesIntegration">
<gl-form-group
:label="s__('JiraService|Jira project key')"
:invalid-feedback="__('This field is required.')"
:state="validProjectKey"
>
<template #link="{ content }">
<gl-link :href="editProjectPath" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
</p>
<gl-form-input
v-model="projectKey"
name="service[project_key]"
:placeholder="s__('JiraService|e.g. AB')"
:required="enableJiraIssues"
:state="validProjectKey"
:disabled="!enableJiraIssues"
/>
</gl-form-group>
<p>
<gl-sprintf
:message="
s__(
'JiraService|Displaying Jira issues while leaving the GitLab issue functionality enabled might be confusing. Consider %{linkStart}disabling GitLab issues%{linkEnd} if they won’t otherwise be used.',
)
"
>
<template #link="{ content }">
<gl-link :href="editProjectPath" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
</p>
</template>
</div>
</template>
......@@ -19,6 +19,7 @@ export default el => {
type,
commentDetail,
projectKey,
upgradePlanPath,
editProjectPath,
triggerEvents,
fields,
......@@ -30,6 +31,7 @@ export default el => {
commitEvents,
mergeRequestEvents,
enableComments,
showJiraIssuesIntegration,
enableJiraIssues,
} = parseBooleanInData(booleanAttributes);
......@@ -50,8 +52,10 @@ export default el => {
initialCommentDetail: commentDetail,
},
jiraIssuesProps: {
showJiraIssuesIntegration,
initialEnableJiraIssues: enableJiraIssues,
initialProjectKey: projectKey,
upgradePlanPath,
editProjectPath,
},
triggerEvents: JSON.parse(triggerEvents),
......
......@@ -15,8 +15,10 @@ module EE
if integration.is_a?(JiraService)
form_data.merge!(
show_jira_issues_integration: @project&.feature_available?(:jira_issues_integration).to_s,
enable_jira_issues: integration.issues_enabled.to_s,
project_key: integration.project_key,
upgrade_plan_path: @project && ::Gitlab::CurrentSettings.should_check_namespace_plan? ? upgrade_plan_path(@project.group) : nil,
edit_project_path: @project ? edit_project_path(@project, anchor: 'js-shared-permissions') : nil
)
end
......
......@@ -24,7 +24,7 @@ RSpec.describe EE::ServicesHelper do
let(:integration) { build(:slack_service) }
it 'does not include Jira specific fields' do
is_expected.not_to include(:enable_jira_issues, :project_key, :edit_project_path)
is_expected.not_to include(:show_jira_issues_integration, :enable_jira_issues, :project_key, :edit_project_path)
end
end
......@@ -32,7 +32,7 @@ RSpec.describe EE::ServicesHelper do
let(:integration) { build(:jira_service) }
it 'includes Jira specific fields' do
is_expected.to include(:enable_jira_issues, :project_key, :edit_project_path)
is_expected.to include(:show_jira_issues_integration, :enable_jira_issues, :project_key, :edit_project_path)
end
end
end
......
......@@ -13122,7 +13122,7 @@ msgstr ""
msgid "JiraService|Web URL"
msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of issues and view any issue as read-only."
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
msgid "JiraService|e.g. AB"
......@@ -23857,6 +23857,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
msgid "This is a Premium feature"
msgstr ""
msgid "This is a Work in Progress"
msgstr ""
......@@ -25265,6 +25268,9 @@ msgstr ""
msgid "Upgrade plan to unlock Canary Deployments feature"
msgstr ""
msgid "Upgrade your plan"
msgstr ""
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr ""
......@@ -25274,6 +25280,9 @@ msgstr ""
msgid "Upgrade your plan to activate Group Webhooks."
msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
msgid "Upgrade your plan to improve Issue boards."
msgstr ""
......
......@@ -189,5 +189,39 @@ describe('DynamicField', () => {
});
});
});
describe('validations', () => {
describe('password field', () => {
beforeEach(() => {
createComponent({
type: 'password',
required: true,
value: null,
});
wrapper.vm.validated = true;
});
describe('without value', () => {
it('requires validation', () => {
expect(wrapper.vm.valid).toBe(false);
expect(findGlFormGroup().classes('is-invalid')).toBe(true);
expect(findGlFormInput().classes('is-invalid')).toBe(true);
});
});
describe('with value', () => {
beforeEach(() => {
wrapper.setProps({ value: 'true' });
});
it('does not require validation', () => {
expect(wrapper.vm.valid).toBe(true);
expect(findGlFormGroup().classes('is-valid')).toBe(true);
expect(findGlFormInput().classes('is-valid')).toBe(true);
});
});
});
});
});
});
......@@ -6,6 +6,7 @@ describe('JiraIssuesFields', () => {
let wrapper;
const defaultProps = {
showJiraIssuesIntegration: true,
editProjectPath: '/edit',
};
......@@ -24,13 +25,33 @@ describe('JiraIssuesFields', () => {
const findEnableCheckbox = () => wrapper.find(GlFormCheckbox);
const findProjectKey = () => wrapper.find(GlFormInput);
const expectedBannerText = 'This is a Premium feature';
describe('template', () => {
describe('upgrade banner for non-Premium user', () => {
beforeEach(() => {
createComponent({ initialProjectKey: '', showJiraIssuesIntegration: false });
});
it('shows upgrade banner', () => {
expect(wrapper.text()).toContain(expectedBannerText);
});
it('does not show checkbox and input field', () => {
expect(findEnableCheckbox().exists()).toBe(false);
expect(findProjectKey().exists()).toBe(false);
});
});
describe('Enable Jira issues checkbox', () => {
beforeEach(() => {
createComponent({ initialProjectKey: '' });
});
it('does not show upgrade banner', () => {
expect(wrapper.text()).not.toContain(expectedBannerText);
});
// As per https://vuejs.org/v2/guide/forms.html#Checkbox-1,
// browsers don't include unchecked boxes in form submissions.
it('includes issues_enabled as false even if unchecked', () => {
......@@ -41,6 +62,10 @@ describe('JiraIssuesFields', () => {
expect(findProjectKey().attributes('disabled')).toBe('disabled');
});
it('does not require project_key', () => {
expect(findProjectKey().attributes('required')).toBeUndefined();
});
describe('on enable issues', () => {
it('enables project_key input', () => {
findEnableCheckbox().vm.$emit('input', true);
......@@ -49,6 +74,14 @@ describe('JiraIssuesFields', () => {
expect(findProjectKey().attributes('disabled')).toBeUndefined();
});
});
it('requires project_key input', () => {
findEnableCheckbox().vm.$emit('input', true);
return wrapper.vm.$nextTick().then(() => {
expect(findProjectKey().attributes('required')).toBe('required');
});
});
});
});
......
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