summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/projects/settings_service_desk
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-07-20 12:26:25 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-07-20 12:26:25 +0000
commita09983ae35713f5a2bbb100981116d31ce99826e (patch)
tree2ee2af7bd104d57086db360a7e6d8c9d5d43667a /app/assets/javascripts/projects/settings_service_desk
parent18c5ab32b738c0b6ecb4d0df3994000482f34bd8 (diff)
downloadgitlab-ce-a09983ae35713f5a2bbb100981116d31ce99826e.tar.gz
Add latest changes from gitlab-org/gitlab@13-2-stable-ee
Diffstat (limited to 'app/assets/javascripts/projects/settings_service_desk')
-rw-r--r--app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue160
-rw-r--r--app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue169
-rw-r--r--app/assets/javascripts/projects/settings_service_desk/event_hub.js3
-rw-r--r--app/assets/javascripts/projects/settings_service_desk/index.js41
-rw-r--r--app/assets/javascripts/projects/settings_service_desk/services/service_desk_service.js27
5 files changed, 400 insertions, 0 deletions
diff --git a/app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue
new file mode 100644
index 00000000000..d61569fcd6e
--- /dev/null
+++ b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue
@@ -0,0 +1,160 @@
+<script>
+import { GlAlert } from '@gitlab/ui';
+import { __ } from '~/locale';
+import ServiceDeskSetting from './service_desk_setting.vue';
+import ServiceDeskService from '../services/service_desk_service';
+import eventHub from '../event_hub';
+
+export default {
+ name: 'ServiceDeskRoot',
+ components: {
+ GlAlert,
+ ServiceDeskSetting,
+ },
+ props: {
+ initialIsEnabled: {
+ type: Boolean,
+ required: true,
+ },
+ endpoint: {
+ type: String,
+ required: true,
+ },
+ initialIncomingEmail: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ selectedTemplate: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ outgoingName: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ projectKey: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ templates: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ },
+
+ data() {
+ return {
+ isEnabled: this.initialIsEnabled,
+ incomingEmail: this.initialIncomingEmail,
+ isTemplateSaving: false,
+ isAlertShowing: false,
+ alertVariant: 'danger',
+ alertMessage: '',
+ };
+ },
+
+ created() {
+ eventHub.$on('serviceDeskEnabledCheckboxToggled', this.onEnableToggled);
+ eventHub.$on('serviceDeskTemplateSave', this.onSaveTemplate);
+
+ this.service = new ServiceDeskService(this.endpoint);
+
+ if (this.isEnabled && !this.incomingEmail) {
+ this.fetchIncomingEmail();
+ }
+ },
+
+ beforeDestroy() {
+ eventHub.$off('serviceDeskEnabledCheckboxToggled', this.onEnableToggled);
+ eventHub.$off('serviceDeskTemplateSave', this.onSaveTemplate);
+ },
+
+ methods: {
+ fetchIncomingEmail() {
+ this.service
+ .fetchIncomingEmail()
+ .then(({ data }) => {
+ const email = data.service_desk_address;
+ if (!email) {
+ throw new Error(__("Response didn't include `service_desk_address`"));
+ }
+
+ this.incomingEmail = email;
+ })
+ .catch(() =>
+ this.showAlert(__('An error occurred while fetching the Service Desk address.')),
+ );
+ },
+
+ onEnableToggled(isChecked) {
+ this.isEnabled = isChecked;
+ this.incomingEmail = '';
+
+ this.service
+ .toggleServiceDesk(isChecked)
+ .then(({ data }) => {
+ const email = data.service_desk_address;
+ if (isChecked && !email) {
+ throw new Error(__("Response didn't include `service_desk_address`"));
+ }
+
+ this.incomingEmail = email;
+ })
+ .catch(() => {
+ const message = isChecked
+ ? __('An error occurred while enabling Service Desk.')
+ : __('An error occurred while disabling Service Desk.');
+
+ this.showAlert(message);
+ });
+ },
+
+ onSaveTemplate({ selectedTemplate, outgoingName, projectKey }) {
+ this.isTemplateSaving = true;
+ this.service
+ .updateTemplate({ selectedTemplate, outgoingName, projectKey }, this.isEnabled)
+ .then(() => this.showAlert(__('Template was successfully saved.'), 'success'))
+ .catch(() =>
+ this.showAlert(
+ __('An error occurred while saving the template. Please check if the template exists.'),
+ ),
+ )
+ .finally(() => {
+ this.isTemplateSaving = false;
+ });
+ },
+
+ showAlert(message, variant = 'danger') {
+ this.isAlertShowing = true;
+ this.alertMessage = message;
+ this.alertVariant = variant;
+ },
+
+ onDismiss() {
+ this.isAlertShowing = false;
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <gl-alert v-if="isAlertShowing" class="mb-3" :variant="alertVariant" @dismiss="onDismiss">
+ {{ alertMessage }}
+ </gl-alert>
+ <service-desk-setting
+ :is-enabled="isEnabled"
+ :incoming-email="incomingEmail"
+ :initial-selected-template="selectedTemplate"
+ :initial-outgoing-name="outgoingName"
+ :initial-project-key="projectKey"
+ :templates="templates"
+ :is-template-saving="isTemplateSaving"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue
new file mode 100644
index 00000000000..43c20fea43e
--- /dev/null
+++ b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue
@@ -0,0 +1,169 @@
+<script>
+import { GlDeprecatedButton, GlFormSelect, GlToggle, GlLoadingIcon } from '@gitlab/ui';
+import { __ } from '~/locale';
+import tooltip from '~/vue_shared/directives/tooltip';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import eventHub from '../event_hub';
+
+export default {
+ name: 'ServiceDeskSetting',
+ directives: {
+ tooltip,
+ },
+ components: {
+ ClipboardButton,
+ GlDeprecatedButton,
+ GlFormSelect,
+ GlToggle,
+ GlLoadingIcon,
+ },
+ mixins: [glFeatureFlagsMixin()],
+ props: {
+ isEnabled: {
+ type: Boolean,
+ required: true,
+ },
+ incomingEmail: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ initialSelectedTemplate: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ initialOutgoingName: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ initialProjectKey: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ templates: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ isTemplateSaving: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ data() {
+ return {
+ selectedTemplate: this.initialSelectedTemplate,
+ outgoingName: this.initialOutgoingName || __('GitLab Support Bot'),
+ projectKey: this.initialProjectKey,
+ };
+ },
+ computed: {
+ templateOptions() {
+ return [''].concat(this.templates);
+ },
+ hasProjectKeySupport() {
+ return Boolean(this.glFeatures.serviceDeskCustomAddress);
+ },
+ },
+ methods: {
+ onCheckboxToggle(isChecked) {
+ eventHub.$emit('serviceDeskEnabledCheckboxToggled', isChecked);
+ },
+ onSaveTemplate() {
+ eventHub.$emit('serviceDeskTemplateSave', {
+ selectedTemplate: this.selectedTemplate,
+ outgoingName: this.outgoingName,
+ projectKey: this.projectKey,
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <gl-toggle
+ id="service-desk-checkbox"
+ :value="isEnabled"
+ class="d-inline-block align-middle mr-1"
+ label="Service desk"
+ label-position="left"
+ @change="onCheckboxToggle"
+ />
+ <label class="align-middle" for="service-desk-checkbox">
+ {{ __('Activate Service Desk') }}
+ </label>
+ <div v-if="isEnabled" class="row mt-3">
+ <div class="col-md-9 mb-0">
+ <strong id="incoming-email-describer" class="d-block mb-1">
+ {{ __('Forward external support email address to') }}
+ </strong>
+ <template v-if="incomingEmail">
+ <div class="input-group">
+ <input
+ ref="service-desk-incoming-email"
+ type="text"
+ class="form-control incoming-email h-auto"
+ :placeholder="__('Incoming email')"
+ :aria-label="__('Incoming email')"
+ aria-describedby="incoming-email-describer"
+ :value="incomingEmail"
+ disabled="true"
+ />
+ <div class="input-group-append">
+ <clipboard-button
+ :title="__('Copy')"
+ :text="incomingEmail"
+ css-class="btn qa-clipboard-button"
+ />
+ </div>
+ </div>
+ </template>
+ <template v-else>
+ <gl-loading-icon :inline="true" />
+ <span class="sr-only">{{ __('Fetching incoming email') }}</span>
+ </template>
+
+ <label for="service-desk-template-select" class="mt-3">
+ {{ __('Template to append to all Service Desk issues') }}
+ </label>
+ <gl-form-select
+ id="service-desk-template-select"
+ v-model="selectedTemplate"
+ :options="templateOptions"
+ />
+ <label for="service-desk-email-from-name" class="mt-3">
+ {{ __('Email display name') }}
+ </label>
+ <input id="service-desk-email-from-name" v-model.trim="outgoingName" class="form-control" />
+ <span class="form-text text-muted">
+ {{ __('Emails sent from Service Desk will have this name') }}
+ </span>
+ <template v-if="hasProjectKeySupport">
+ <label for="service-desk-project-suffix" class="mt-3">
+ {{ __('Project name suffix') }}
+ </label>
+ <input id="service-desk-project-suffix" v-model.trim="projectKey" class="form-control" />
+ <span class="form-text text-muted mb-3">
+ {{
+ __(
+ 'Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address.',
+ )
+ }}
+ </span>
+ </template>
+ <gl-deprecated-button
+ variant="success"
+ :disabled="isTemplateSaving"
+ @click="onSaveTemplate"
+ >{{ __('Save template') }}</gl-deprecated-button
+ >
+ </div>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/projects/settings_service_desk/event_hub.js b/app/assets/javascripts/projects/settings_service_desk/event_hub.js
new file mode 100644
index 00000000000..e31806ad199
--- /dev/null
+++ b/app/assets/javascripts/projects/settings_service_desk/event_hub.js
@@ -0,0 +1,3 @@
+import createEventHub from '~/helpers/event_hub_factory';
+
+export default createEventHub();
diff --git a/app/assets/javascripts/projects/settings_service_desk/index.js b/app/assets/javascripts/projects/settings_service_desk/index.js
new file mode 100644
index 00000000000..15c077de72e
--- /dev/null
+++ b/app/assets/javascripts/projects/settings_service_desk/index.js
@@ -0,0 +1,41 @@
+import Vue from 'vue';
+import { parseBoolean } from '~/lib/utils/common_utils';
+import ServiceDeskRoot from './components/service_desk_root.vue';
+
+export default () => {
+ const serviceDeskRootElement = document.querySelector('.js-service-desk-setting-root');
+ if (serviceDeskRootElement) {
+ // eslint-disable-next-line no-new
+ new Vue({
+ el: serviceDeskRootElement,
+ components: {
+ ServiceDeskRoot,
+ },
+ data() {
+ const { dataset } = serviceDeskRootElement;
+ return {
+ initialIsEnabled: parseBoolean(dataset.enabled),
+ endpoint: dataset.endpoint,
+ incomingEmail: dataset.incomingEmail,
+ selectedTemplate: dataset.selectedTemplate,
+ outgoingName: dataset.outgoingName,
+ projectKey: dataset.projectKey,
+ templates: JSON.parse(dataset.templates),
+ };
+ },
+ render(createElement) {
+ return createElement('service-desk-root', {
+ props: {
+ initialIsEnabled: this.initialIsEnabled,
+ endpoint: this.endpoint,
+ initialIncomingEmail: this.incomingEmail,
+ selectedTemplate: this.selectedTemplate,
+ outgoingName: this.outgoingName,
+ projectKey: this.projectKey,
+ templates: this.templates,
+ },
+ });
+ },
+ });
+ }
+};
diff --git a/app/assets/javascripts/projects/settings_service_desk/services/service_desk_service.js b/app/assets/javascripts/projects/settings_service_desk/services/service_desk_service.js
new file mode 100644
index 00000000000..d707763c64e
--- /dev/null
+++ b/app/assets/javascripts/projects/settings_service_desk/services/service_desk_service.js
@@ -0,0 +1,27 @@
+import axios from '~/lib/utils/axios_utils';
+
+class ServiceDeskService {
+ constructor(endpoint) {
+ this.endpoint = endpoint;
+ }
+
+ fetchIncomingEmail() {
+ return axios.get(this.endpoint);
+ }
+
+ toggleServiceDesk(enable) {
+ return axios.put(this.endpoint, { service_desk_enabled: enable });
+ }
+
+ updateTemplate({ selectedTemplate, outgoingName, projectKey = '' }, isEnabled) {
+ const body = {
+ issue_template_key: selectedTemplate,
+ outgoing_name: outgoingName,
+ project_key: projectKey,
+ service_desk_enabled: isEnabled,
+ };
+ return axios.put(this.endpoint, body);
+ }
+}
+
+export default ServiceDeskService;