Commit 2174f407 authored by Eric Eastwood's avatar Eric Eastwood Committed by Sean McGivern

Use actual /group/project/service_desk endpoint

 - Prerender data-* attributes for endpoint, enabled, incoming_email to
   hydrate Vue component
 - Use actual /group/project/service_desk endpoint GET/PUT
parent 2b541e6c
...@@ -49,7 +49,7 @@ import BlobForkSuggestion from './blob/blob_fork_suggestion'; ...@@ -49,7 +49,7 @@ import BlobForkSuggestion from './blob/blob_fork_suggestion';
import UserCallout from './user_callout'; import UserCallout from './user_callout';
import GeoNodes from './geo_nodes'; import GeoNodes from './geo_nodes';
import ServiceDeskEntry from './projects/settings_service_desk/service_desk_entry'; import ServiceDeskRoot from './projects/settings_service_desk/service_desk_root';
const ShortcutsBlob = require('./shortcuts_blob'); const ShortcutsBlob = require('./shortcuts_blob');
...@@ -230,8 +230,11 @@ const ShortcutsBlob = require('./shortcuts_blob'); ...@@ -230,8 +230,11 @@ const ShortcutsBlob = require('./shortcuts_blob');
shortcut_handler = new ShortcutsNavigation(); shortcut_handler = new ShortcutsNavigation();
break; break;
case 'projects:edit': case 'projects:edit':
const serviceDeskEntry = new ServiceDeskEntry(document.querySelector('.js-service-desk-setting-wrapper')); const el = document.querySelector('.js-service-desk-setting-root');
serviceDeskEntry.init(); if (el) {
const serviceDeskRoot = new ServiceDeskRoot(el);
serviceDeskRoot.init();
}
break; break;
case 'projects:show': case 'projects:show':
shortcut_handler = new ShortcutsNavigation(); shortcut_handler = new ShortcutsNavigation();
......
...@@ -5,7 +5,7 @@ export default { ...@@ -5,7 +5,7 @@ export default {
name: 'ServiceDeskSetting', name: 'ServiceDeskSetting',
props: { props: {
isActivated: { isEnabled: {
type: Boolean, type: Boolean,
required: true, required: true,
}, },
...@@ -15,7 +15,7 @@ export default { ...@@ -15,7 +15,7 @@ export default {
default: '', default: '',
}, },
fetchError: { fetchError: {
type: Object, type: Error,
required: false, required: false,
default: null, default: null,
}, },
...@@ -48,14 +48,14 @@ export default { ...@@ -48,14 +48,14 @@ export default {
<input <input
type="checkbox" type="checkbox"
id="service-desk-enabled-checkbox" id="service-desk-enabled-checkbox"
:checked="isActivated" :checked="isEnabled"
@change="onCheckboxToggle($event)"> @change="onCheckboxToggle($event)">
<span class="descr"> <span class="descr">
Activate service desk Activate service desk
</span> </span>
</label> </label>
</div> </div>
<template v-if="isActivated"> <template v-if="isEnabled">
<div <div
class="panel-slim panel-default"> class="panel-slim panel-default">
<div class="panel-heading"> <div class="panel-heading">
......
...@@ -5,17 +5,28 @@ import ServiceDeskStore from './stores/service_desk_store'; ...@@ -5,17 +5,28 @@ import ServiceDeskStore from './stores/service_desk_store';
import ServiceDeskService from './services/service_desk_service'; import ServiceDeskService from './services/service_desk_service';
import eventHub from './event_hub'; import eventHub from './event_hub';
class ServiceDeskEntry { class ServiceDeskRoot {
constructor(wrapperElement) { constructor(wrapperElement) {
this.wrapperElement = wrapperElement; this.wrapperElement = wrapperElement;
const isEnabled = this.wrapperElement.dataset.enabled !== undefined &&
this.wrapperElement.dataset.enabled !== 'false';
const incomingEmail = this.wrapperElement.dataset.incomingEmail;
const endpoint = this.wrapperElement.dataset.endpoint; const endpoint = this.wrapperElement.dataset.endpoint;
this.store = new ServiceDeskStore(); this.store = new ServiceDeskStore({
isEnabled,
incomingEmail,
});
this.service = new ServiceDeskService(endpoint); this.service = new ServiceDeskService(endpoint);
} }
init() { init() {
this.bindEvents(); this.bindEvents();
if (this.store.state.isEnabled && !this.store.state.incomingEmail) {
this.fetchIncomingEmail();
}
this.render(); this.render();
} }
...@@ -35,7 +46,7 @@ class ServiceDeskEntry { ...@@ -35,7 +46,7 @@ class ServiceDeskEntry {
data: this.store.state, data: this.store.state,
template: ` template: `
<service-desk-setting <service-desk-setting
:isActivated="isActivated" :isEnabled="isEnabled"
:incomingEmail="incomingEmail" :incomingEmail="incomingEmail"
:fetchError="fetchError" /> :fetchError="fetchError" />
`, `,
...@@ -45,12 +56,22 @@ class ServiceDeskEntry { ...@@ -45,12 +56,22 @@ class ServiceDeskEntry {
}); });
} }
fetchIncomingEmail() {
this.service.fetchIncomingEmail()
.then((incomingEmail) => {
this.store.setIncomingEmail(incomingEmail);
})
.catch((err) => {
this.store.setFetchError(err);
});
}
onEnableToggled(isChecked) { onEnableToggled(isChecked) {
this.store.setIsActivated(isChecked); this.store.setIsActivated(isChecked);
if (isChecked) {
this.store.setIncomingEmail(''); this.store.setIncomingEmail('');
this.store.setFetchError(null); this.store.setFetchError(null);
this.service.fetchIncomingEmail()
this.service.toggleServiceDesk(isChecked)
.then((incomingEmail) => { .then((incomingEmail) => {
this.store.setIncomingEmail(incomingEmail); this.store.setIncomingEmail(incomingEmail);
}) })
...@@ -58,7 +79,6 @@ class ServiceDeskEntry { ...@@ -58,7 +79,6 @@ class ServiceDeskEntry {
this.store.setFetchError(err); this.store.setFetchError(err);
}); });
} }
}
destroy() { destroy() {
this.unbindEvents(); this.unbindEvents();
...@@ -68,4 +88,4 @@ class ServiceDeskEntry { ...@@ -68,4 +88,4 @@ class ServiceDeskEntry {
} }
} }
export default ServiceDeskEntry; export default ServiceDeskRoot;
...@@ -6,12 +6,33 @@ Vue.use(vueResource); ...@@ -6,12 +6,33 @@ Vue.use(vueResource);
class ServiceDeskService { class ServiceDeskService {
constructor(endpoint) { constructor(endpoint) {
this.serviceDeskEnabledResource = Vue.resource(`${endpoint}/service_desk_address`); this.serviceDeskResource = Vue.resource(`${endpoint}`);
} }
fetchIncomingEmail() { fetchIncomingEmail() {
return this.serviceDeskEnabledResource.get() return this.serviceDeskResource.get()
.then(res => res.data.incomingEmail); .then((res) => {
const email = res.data.service_desk_address;
if (!email) {
throw new Error('Response didn\'t include `service_desk_address`');
}
return email;
});
}
toggleServiceDesk(enable) {
return this.serviceDeskResource.update({
service_desk_enabled: enable,
})
.then((res) => {
const email = res.data.service_desk_address;
if (enable && !email) {
throw new Error('Response didn\'t include `service_desk_address`');
}
return email;
});
} }
} }
......
class ServiceDeskStore { class ServiceDeskStore {
constructor(initialState = {}) { constructor(initialState = {}) {
this.state = Object.assign({ this.state = Object.assign({
isActivated: false, isEnabled: false,
incomingEmail: '', incomingEmail: '',
fetchError: null, fetchError: null,
}, initialState); }, initialState);
} }
setIsActivated(value) { setIsActivated(value) {
this.state.isActivated = value; this.state.isEnabled = value;
} }
setIncomingEmail(value) { setIncomingEmail(value) {
......
...@@ -126,12 +126,15 @@ ...@@ -126,12 +126,15 @@
= render 'merge_request_settings', form: f = render 'merge_request_settings', form: f
- if EE::Gitlab::ServiceDesk.enabled?
%hr %hr
%fieldset.features.append-bottom-default %fieldset.js-service-desk-setting-wrapper.features.append-bottom-default
%h5.prepend-top-0 %h5.prepend-top-0
Service Desk Service Desk
= link_to icon('question-circle'), help_page_path("TODO") = link_to icon('question-circle'), help_page_path("TODO")
.js-service-desk-setting-wrapper{ data: { endpoint: namespace_project_path(@project.namespace, @project), enabled: @project.service_desk_enabled?, incomingAddress: (@project.service_desk_address if @project.service_desk_enabled? ) } } .js-service-desk-setting-root{ data: { endpoint: namespace_project_service_desk_path(@project.namespace, @project),
enabled: @project.service_desk_enabled,
incoming_email: (@project.service_desk_address if @project.service_desk_enabled) } }
%hr %hr
%fieldset.features.append-bottom-default %fieldset.features.append-bottom-default
......
require 'spec_helper'
describe 'Service Desk Setting', js: true, feature: true do
include WaitForAjax
let(:project) { create(:project_empty_repo, :private) }
let(:user) { create(:user) }
before do
project.add_master(user)
login_as(user)
allow_any_instance_of(License).to receive(:add_on?).and_call_original
allow_any_instance_of(License).to receive(:add_on?).with('GitLab_ServiceDesk') { true }
visit edit_namespace_project_path(project.namespace, project)
end
it 'shows service desk activation checkbox' do
expect(page).to have_selector("#service-desk-enabled-checkbox")
end
it 'shows incoming email after activating' do
find("#service-desk-enabled-checkbox").click
wait_for_ajax
expect(find('.js-service-desk-setting-wrapper .panel-body')).to have_content(project.service_desk_address)
end
end
...@@ -19,13 +19,13 @@ describe('ServiceDeskSetting', () => { ...@@ -19,13 +19,13 @@ describe('ServiceDeskSetting', () => {
} }
}); });
describe('when isActivated=true', () => { describe('when isEnabled=true', () => {
let el; let el;
describe('only isActivated', () => { describe('only isEnabled', () => {
beforeEach(() => { beforeEach(() => {
vm = createComponent({ vm = createComponent({
isActivated: true, isEnabled: true,
}); });
el = vm.$el; el = vm.$el;
}); });
...@@ -48,7 +48,7 @@ describe('ServiceDeskSetting', () => { ...@@ -48,7 +48,7 @@ describe('ServiceDeskSetting', () => {
describe('with incomingEmail', () => { describe('with incomingEmail', () => {
beforeEach(() => { beforeEach(() => {
vm = createComponent({ vm = createComponent({
isActivated: true, isEnabled: true,
incomingEmail: 'foo@bar.com', incomingEmail: 'foo@bar.com',
}); });
el = vm.$el; el = vm.$el;
...@@ -64,7 +64,7 @@ describe('ServiceDeskSetting', () => { ...@@ -64,7 +64,7 @@ describe('ServiceDeskSetting', () => {
describe('with fetchError', () => { describe('with fetchError', () => {
beforeEach(() => { beforeEach(() => {
vm = createComponent({ vm = createComponent({
isActivated: true, isEnabled: true,
fetchError: new Error('some-fake-failure'), fetchError: new Error('some-fake-failure'),
}); });
el = vm.$el; el = vm.$el;
...@@ -79,12 +79,12 @@ describe('ServiceDeskSetting', () => { ...@@ -79,12 +79,12 @@ describe('ServiceDeskSetting', () => {
}); });
}); });
describe('when isActivated=false', () => { describe('when isEnabled=false', () => {
let el; let el;
beforeEach(() => { beforeEach(() => {
vm = createComponent({ vm = createComponent({
isActivated: false, isEnabled: false,
}); });
el = vm.$el; el = vm.$el;
}); });
...@@ -107,7 +107,7 @@ describe('ServiceDeskSetting', () => { ...@@ -107,7 +107,7 @@ describe('ServiceDeskSetting', () => {
eventHub.$on('serviceDeskEnabledCheckboxToggled', onCheckboxToggleSpy); eventHub.$on('serviceDeskEnabledCheckboxToggled', onCheckboxToggleSpy);
vm = createComponent({ vm = createComponent({
isActivated: false, isEnabled: false,
}); });
}); });
...@@ -139,7 +139,7 @@ describe('ServiceDeskSetting', () => { ...@@ -139,7 +139,7 @@ describe('ServiceDeskSetting', () => {
describe('copyIncomingEmail', () => { describe('copyIncomingEmail', () => {
beforeEach(() => { beforeEach(() => {
vm = createComponent({ vm = createComponent({
isActivated: true, isEnabled: true,
incomingEmail: 'foo@bar.com', incomingEmail: 'foo@bar.com',
}); });
}); });
......
...@@ -8,9 +8,10 @@ describe('ServiceDeskService', () => { ...@@ -8,9 +8,10 @@ describe('ServiceDeskService', () => {
}); });
it('fetchIncomingEmail', (done) => { it('fetchIncomingEmail', (done) => {
spyOn(service.project, 'get').and.returnValue(Promise.resolve({ spyOn(service.serviceDeskResource, 'get').and.returnValue(Promise.resolve({
data: { data: {
incomingEmail: 'foo@bar.com', service_desk_enabled: true,
service_desk_address: 'foo@bar.com',
}, },
})); }));
...@@ -23,4 +24,42 @@ describe('ServiceDeskService', () => { ...@@ -23,4 +24,42 @@ describe('ServiceDeskService', () => {
done.fail(`Failed to fetch incoming email:\n${err}`); done.fail(`Failed to fetch incoming email:\n${err}`);
}); });
}); });
describe('toggleServiceDesk', () => {
it('enable service desk', (done) => {
spyOn(service.serviceDeskResource, 'update').and.returnValue(Promise.resolve({
data: {
service_desk_enabled: true,
service_desk_address: 'foo@bar.com',
},
}));
service.toggleServiceDesk(true)
.then((incomingEmail) => {
expect(incomingEmail).toEqual('foo@bar.com');
done();
})
.catch((err) => {
done.fail(`Failed to enable service desk and fetch incoming email:\n${err}`);
});
});
it('disable service desk', (done) => {
spyOn(service.serviceDeskResource, 'update').and.returnValue(Promise.resolve({
data: {
service_desk_enabled: false,
service_desk_address: null,
},
}));
service.toggleServiceDesk(false)
.then((incomingEmail) => {
expect(incomingEmail).toEqual(null);
done();
})
.catch((err) => {
done.fail(`Failed to disable service desk and reset incoming email:\n${err}`);
});
});
});
}); });
...@@ -9,19 +9,19 @@ describe('ServiceDeskStore', () => { ...@@ -9,19 +9,19 @@ describe('ServiceDeskStore', () => {
describe('setIsActivated', () => { describe('setIsActivated', () => {
it('defaults to false', () => { it('defaults to false', () => {
expect(store.state.isActivated).toEqual(false); expect(store.state.isEnabled).toEqual(false);
}); });
it('set true', () => { it('set true', () => {
store.setIsActivated(true); store.setIsActivated(true);
expect(store.state.isActivated).toEqual(true); expect(store.state.isEnabled).toEqual(true);
}); });
it('set false', () => { it('set false', () => {
store.setIsActivated(false); store.setIsActivated(false);
expect(store.state.isActivated).toEqual(false); expect(store.state.isEnabled).toEqual(false);
}); });
}); });
......
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