Commit a29f98f4 authored by Kushal Pandya's avatar Kushal Pandya

Add `Email display name` within Service Desk settings

Adds support for providing custom "Email display name" within
Service Desk settings under Project Settings.
parent dd1e0a51
...@@ -30,6 +30,11 @@ export default { ...@@ -30,6 +30,11 @@ export default {
required: false, required: false,
default: '', default: '',
}, },
outgoingName: {
type: String,
required: false,
default: '',
},
templates: { templates: {
type: Array, type: Array,
required: false, required: false,
...@@ -104,10 +109,10 @@ export default { ...@@ -104,10 +109,10 @@ export default {
}); });
}, },
onSaveTemplate(template) { onSaveTemplate({ selectedTemplate, outgoingName }) {
this.isTemplateSaving = true; this.isTemplateSaving = true;
this.service this.service
.updateTemplate(template, this.isEnabled) .updateTemplate({ selectedTemplate, outgoingName }, this.isEnabled)
.then(() => this.showAlert(__('Template was successfully saved.'), 'success')) .then(() => this.showAlert(__('Template was successfully saved.'), 'success'))
.catch(() => .catch(() =>
this.showAlert( this.showAlert(
...@@ -134,13 +139,14 @@ export default { ...@@ -134,13 +139,14 @@ export default {
<template> <template>
<div> <div>
<gl-alert v-if="isAlertShowing" class="mb-3" :variant="alertVariant" @dismiss="onDismiss"> <gl-alert v-if="isAlertShowing" class="mb-3" :variant="alertVariant" @dismiss="onDismiss">{{
{{ alertMessage }} alertMessage
</gl-alert> }}</gl-alert>
<service-desk-setting <service-desk-setting
:is-enabled="isEnabled" :is-enabled="isEnabled"
:incoming-email="incomingEmail" :incoming-email="incomingEmail"
:initial-selected-template="selectedTemplate" :initial-selected-template="selectedTemplate"
:initial-outgoing-name="outgoingName"
:templates="templates" :templates="templates"
:is-template-saving="isTemplateSaving" :is-template-saving="isTemplateSaving"
/> />
......
<script> <script>
import { GlButton, GlFormSelect, GlToggle } from '@gitlab/ui'; import { GlButton, GlFormSelect, GlToggle } from '@gitlab/ui';
import { __ } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip'; import tooltip from '~/vue_shared/directives/tooltip';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import eventHub from '../event_hub'; import eventHub from '../event_hub';
...@@ -30,6 +31,11 @@ export default { ...@@ -30,6 +31,11 @@ export default {
required: false, required: false,
default: '', default: '',
}, },
initialOutgoingName: {
type: String,
required: false,
default: '',
},
templates: { templates: {
type: Array, type: Array,
required: false, required: false,
...@@ -44,6 +50,7 @@ export default { ...@@ -44,6 +50,7 @@ export default {
data() { data() {
return { return {
selectedTemplate: this.initialSelectedTemplate, selectedTemplate: this.initialSelectedTemplate,
outgoingName: this.initialOutgoingName || __('GitLab Support Bot'),
}; };
}, },
computed: { computed: {
...@@ -56,7 +63,10 @@ export default { ...@@ -56,7 +63,10 @@ export default {
eventHub.$emit('serviceDeskEnabledCheckboxToggled', isChecked); eventHub.$emit('serviceDeskEnabledCheckboxToggled', isChecked);
}, },
onSaveTemplate() { onSaveTemplate() {
eventHub.$emit('serviceDeskTemplateSave', this.selectedTemplate); eventHub.$emit('serviceDeskTemplateSave', {
selectedTemplate: this.selectedTemplate,
outgoingName: this.outgoingName,
});
}, },
}, },
}; };
...@@ -72,14 +82,14 @@ export default { ...@@ -72,14 +82,14 @@ export default {
:label-off="__('Service Desk is off')" :label-off="__('Service Desk is off')"
@change="onCheckboxToggle" @change="onCheckboxToggle"
/> />
<label class="align-middle" for="service-desk-checkbox"> <label class="align-middle" for="service-desk-checkbox">{{
{{ __('Activate Service Desk') }} __('Activate Service Desk')
</label> }}</label>
<div v-if="isEnabled" class="row mt-3"> <div v-if="isEnabled" class="row mt-3">
<div class="col-md-9 mb-0"> <div class="col-md-9 mb-0">
<strong id="incoming-email-describer" class="d-block mb-1"> <strong id="incoming-email-describer" class="d-block mb-1">{{
{{ __('Forward external support email address to') }} __('Forward external support email address to')
</strong> }}</strong>
<template v-if="incomingEmail"> <template v-if="incomingEmail">
<div class="input-group"> <div class="input-group">
<input <input
...@@ -102,22 +112,28 @@ export default { ...@@ -102,22 +112,28 @@ export default {
</div> </div>
</template> </template>
<template v-else> <template v-else>
<i class="fa fa-spinner fa-spin" aria-hidden="true"> </i> <i class="fa fa-spinner fa-spin" aria-hidden="true"></i>
<span class="sr-only">{{ __('Fetching incoming email') }}</span> <span class="sr-only">{{ __('Fetching incoming email') }}</span>
</template> </template>
<label for="service-desk-template-select" class="mt-3"> <label for="service-desk-template-select" class="mt-3">{{
{{ __('Template to append to all Service Desk issues') }} __('Template to append to all Service Desk issues')
</label> }}</label>
<gl-form-select <gl-form-select
id="service-desk-template-select" id="service-desk-template-select"
v-model="selectedTemplate" v-model="selectedTemplate"
class="mb-3"
:options="templateOptions" :options="templateOptions"
/> />
<gl-button variant="success" :disabled="isTemplateSaving" @click="onSaveTemplate"> <label for="service-desk-email-from-name" class="mt-3">{{
{{ __('Save template') }} __('Email display name')
</gl-button> }}</label>
<input id="service-desk-email-from-name" v-model.trim="outgoingName" class="form-control" />
<span class="form-text text-muted mb-3">{{
__('Emails sent from Service Desk will have this name')
}}</span>
<gl-button variant="success" :disabled="isTemplateSaving" @click="onSaveTemplate">{{
__('Save template')
}}</gl-button>
</div> </div>
</div> </div>
</div> </div>
......
...@@ -13,9 +13,10 @@ class ServiceDeskService { ...@@ -13,9 +13,10 @@ class ServiceDeskService {
return axios.put(this.endpoint, { service_desk_enabled: enable }); return axios.put(this.endpoint, { service_desk_enabled: enable });
} }
updateTemplate(template, isEnabled) { updateTemplate({ selectedTemplate, outgoingName }, isEnabled) {
const body = { const body = {
issue_template_key: template, issue_template_key: selectedTemplate,
outgoing_name: outgoingName,
service_desk_enabled: isEnabled, service_desk_enabled: isEnabled,
}; };
return axios.put(this.endpoint, body); return axios.put(this.endpoint, body);
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
enabled: "#{@project.service_desk_enabled}", enabled: "#{@project.service_desk_enabled}",
incoming_email: (@project.service_desk_address if @project.service_desk_enabled), incoming_email: (@project.service_desk_address if @project.service_desk_enabled),
selected_template: "#{@project.service_desk_setting&.issue_template_key}", selected_template: "#{@project.service_desk_setting&.issue_template_key}",
outgoing_name: "#{@project.service_desk_setting&.outgoing_name}",
templates: issuable_templates_names(Issue.new) } } templates: issuable_templates_names(Issue.new) } }
- elsif show_promotions? && show_callout?('promote_service_desk_dismissed') - elsif show_promotions? && show_callout?('promote_service_desk_dismissed')
= render 'shared/promotions/promote_servicedesk' = render 'shared/promotions/promote_servicedesk'
...@@ -158,6 +158,7 @@ describe('ServiceDeskRoot', () => { ...@@ -158,6 +158,7 @@ describe('ServiceDeskRoot', () => {
endpoint, endpoint,
initialIncomingEmail, initialIncomingEmail,
selectedTemplate: 'Bug', selectedTemplate: 'Bug',
outgoingName: 'GitLab Support Bot',
templates: ['Bug', 'Documentation'], templates: ['Bug', 'Documentation'],
}, },
}); });
...@@ -167,6 +168,7 @@ describe('ServiceDeskRoot', () => { ...@@ -167,6 +168,7 @@ describe('ServiceDeskRoot', () => {
return wrapper.vm.$nextTick(() => { return wrapper.vm.$nextTick(() => {
expect(spy).toHaveBeenCalledWith(endpoint, { expect(spy).toHaveBeenCalledWith(endpoint, {
issue_template_key: 'Bug', issue_template_key: 'Bug',
outgoing_name: 'GitLab Support Bot',
service_desk_enabled: true, service_desk_enabled: true,
}); });
}); });
......
...@@ -173,12 +173,16 @@ describe('ServiceDeskSetting', () => { ...@@ -173,12 +173,16 @@ describe('ServiceDeskSetting', () => {
propsData: { propsData: {
isEnabled: true, isEnabled: true,
initialSelectedTemplate: 'Bug', initialSelectedTemplate: 'Bug',
initialOutgoingName: 'GitLab Support Bot',
}, },
}); });
wrapper.find('button.btn-success').trigger('click'); wrapper.find('button.btn-success').trigger('click');
expect(eventSpy).toHaveBeenCalledWith('Bug'); expect(eventSpy).toHaveBeenCalledWith({
selectedTemplate: 'Bug',
outgoingName: 'GitLab Support Bot',
});
eventHub.$off('serviceDeskTemplateSave', eventSpy); eventHub.$off('serviceDeskTemplateSave', eventSpy);
eventSpy.mockRestore(); eventSpy.mockRestore();
......
...@@ -73,17 +73,33 @@ describe('ServiceDeskService', () => { ...@@ -73,17 +73,33 @@ describe('ServiceDeskService', () => {
it('makes a request to update template', () => { it('makes a request to update template', () => {
axiosMock.onPut(endpoint).replyOnce(httpStatusCodes.OK, dummyResponse); axiosMock.onPut(endpoint).replyOnce(httpStatusCodes.OK, dummyResponse);
return service.updateTemplate('Bug', true).then(response => { return service
expect(response.data).toEqual(dummyResponse); .updateTemplate(
}); {
selectedTemplate: 'Bug',
outgoingName: 'GitLab Support Bot',
},
true,
)
.then(response => {
expect(response.data).toEqual(dummyResponse);
});
}); });
it('fails on error response', () => { it('fails on error response', () => {
axiosMock.onPut(endpoint).networkError(); axiosMock.onPut(endpoint).networkError();
return service.updateTemplate('Bug', true).catch(error => { return service
expect(error.message).toBe(errorMessage); .updateTemplate(
}); {
selectedTemplate: 'Bug',
outgoingName: 'GitLab Support Bot',
},
true,
)
.catch(error => {
expect(error.message).toBe(errorMessage);
});
}); });
it('makes a request with the expected body', () => { it('makes a request with the expected body', () => {
...@@ -91,10 +107,17 @@ describe('ServiceDeskService', () => { ...@@ -91,10 +107,17 @@ describe('ServiceDeskService', () => {
const spy = jest.spyOn(axios, 'put'); const spy = jest.spyOn(axios, 'put');
service.updateTemplate('Bug', true); service.updateTemplate(
{
selectedTemplate: 'Bug',
outgoingName: 'GitLab Support Bot',
},
true,
);
expect(spy).toHaveBeenCalledWith(endpoint, { expect(spy).toHaveBeenCalledWith(endpoint, {
issue_template_key: 'Bug', issue_template_key: 'Bug',
outgoing_name: 'GitLab Support Bot',
service_desk_enabled: true, service_desk_enabled: true,
}); });
......
...@@ -6798,6 +6798,9 @@ msgstr "" ...@@ -6798,6 +6798,9 @@ msgstr ""
msgid "Email address" msgid "Email address"
msgstr "" msgstr ""
msgid "Email display name"
msgstr ""
msgid "Email domain is not editable in subgroups. Value inherited from top-level parent group." msgid "Email domain is not editable in subgroups. Value inherited from top-level parent group."
msgstr "" msgstr ""
...@@ -6843,6 +6846,9 @@ msgstr "" ...@@ -6843,6 +6846,9 @@ msgstr ""
msgid "Emails" msgid "Emails"
msgstr "" msgstr ""
msgid "Emails sent from Service Desk will have this name"
msgstr ""
msgid "Emails separated by comma" msgid "Emails separated by comma"
msgstr "" msgstr ""
...@@ -8915,6 +8921,9 @@ msgstr "" ...@@ -8915,6 +8921,9 @@ msgstr ""
msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)." msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
msgstr "" msgstr ""
msgid "GitLab Support Bot"
msgstr ""
msgid "GitLab User" msgid "GitLab User"
msgstr "" msgstr ""
......
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