Skip to content

Commit 7408950

Browse files
authored
HP-1646 Feat/zendesk (#1587)
* feat migrate from kayako to zendesk * feat code change * update csp * fix fetch * fix content * update
1 parent 0c93840 commit 7408950

8 files changed

+55
-47
lines changed

dev.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
- https://atlas.qa-mickey.planx-pla.net for Atlas iframe in VHDC qa-mickey
1212
- https://*.quicksight.aws.amazon.com for loading AWS Quicksight dashboards into COVID-19 Home page
1313
-->
14-
<meta http-equiv="Content-Security-Policy" content="default-src 'self' https://login.bionimbus.org https://wayf.incommonfederation.org; child-src blob:; connect-src 'self' blob: localhost https://localhost:9443 wss://localhost:9443 https://*.s3.amazonaws.com https://*.mapbox.com https://opendata.datacommons.io https://static.planx-pla.net https://*.logs.datadoghq.com https://clinicaltrials.gov https://*.google-analytics.com https://*.analytics.google.com; img-src 'self' https://opendata.datacommons.io https://static.planx-pla.net https://www.google-analytics.com data: https://*.s3.amazonaws.com https://www.google-analytics.com; script-src 'self' 'unsafe-eval' https://*.google-analytics.com https://www.googletagmanager.com localhost https://localhost:9443; worker-src 'self' blob:; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com localhost https://localhost:9443; object-src 'none'; font-src 'self' data: https://fonts.googleapis.com https://fonts.gstatic.com; frame-src 'self' https://auspice.planx-pla.net https://auspice.pandemicresponsecommons.org https://atlas.qa-mickey.planx-pla.net https://*.quicksight.aws.amazon.com; ">
14+
<meta http-equiv="Content-Security-Policy" content="default-src 'self' https://login.bionimbus.org https://wayf.incommonfederation.org; child-src blob:; connect-src 'self' blob: localhost https://localhost:9443 wss://localhost:9443 https://*.s3.amazonaws.com https://*.mapbox.com https://opendata.datacommons.io https://static.planx-pla.net https://*.logs.datadoghq.com https://clinicaltrials.gov https://*.google-analytics.com https://*.analytics.google.com https://*.zendesk.com; img-src 'self' https://opendata.datacommons.io https://static.planx-pla.net https://www.google-analytics.com data: https://*.s3.amazonaws.com https://www.google-analytics.com; script-src 'self' 'unsafe-eval' https://*.google-analytics.com https://www.googletagmanager.com localhost https://localhost:9443; worker-src 'self' blob:; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com localhost https://localhost:9443; object-src 'none'; font-src 'self' data: https://fonts.googleapis.com https://fonts.gstatic.com; frame-src 'self' https://auspice.planx-pla.net https://auspice.pandemicresponsecommons.org https://atlas.qa-mickey.planx-pla.net https://*.quicksight.aws.amazon.com; ">
1515
<meta name="viewport" content="width=device-width" />
1616
<link href="https://fonts.googleapis.com/icon?family=Source+Sans+Pro" rel="stylesheet">
1717
<link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,700;1,700&display=swap" rel="stylesheet">

docs/portal_config.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -743,7 +743,7 @@ Below is an example, with inline comments describing what each JSON block config
743743
...
744744
],
745745
"stridesPortalURL": "https://strides-admin-portal.org", // optional; If configured, will display a link on the workspace page which can direct user to the STRIDES admin portal,
746-
"registrationConfigs": { // optional; Required when using Kayako integration with Study/Workspace registration
746+
"registrationConfigs": { // optional; Required when using Zendesk integration with Study/Workspace registration
747747
"features":{ // Optional; Required when using study/Workspace registration
748748
"studyRegistrationConfig": { // optional, config for Study Registration and Study Registration Request Access page.
749749
"studyRegistrationTrackingField": "registrant_username", // optional, one of the extra field that is being added to metadata when a study is registered, will be useful in the future. Defaults to "registrant_username"
@@ -765,8 +765,8 @@ Below is an example, with inline comments describing what each JSON block config
765765
}
766766
}
767767
},
768-
"kayakoConfig":{ //Required; if using either of the study/workspace registration feature
769-
"kayakoDepartmentId": 21 // Required; the department ID in the kayako portal. Refer to Ops team to get more info
768+
"zendeskConfig":{ // Optional; add this if you want to customize the subdomain that Zendesk is using in either of the study/workspace registration feature
769+
"zendeskSubdomainName": "projectSupport" // Optional; the subdomain name of the Zendesk server. Refer to User Service team to get more info. If omitted, will default to 'gen3support'
770770
}
771771
}
772772
}

src/GenericAccessRequestForm/GenericAccessRequestForm.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ const GenericAccessRequestForm: React.FunctionComponent<StudyRegistrationProps>
8080
if (!useArboristUI) {
8181
return true;
8282
}
83+
// We don't need this method anymore after we migrated to Zendesk, but just an extra layer of check here
84+
// This may get removed in the future
8385
return userHasMethodForServiceOnResource(
8486
'create',
8587
'kayako',

src/GenericAccessRequestForm/handleRegisterFormSubmission.ts

+8-19
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
import { doesUserHaveRequestPending } from '../StudyRegistration/utils';
22
import {
3-
kayakoConfig, hostname, workspaceRegistrationConfig, requestorPath,
3+
zendeskConfig, hostname, workspaceRegistrationConfig, requestorPath,
44
} from '../localconf';
55
import { fetchWithCreds } from '../actions';
6-
import { createKayakoTicket } from '../utils';
7-
8-
const KAYAKO_MAX_SUBJECT_LENGTH = 255;
6+
import { createZendeskTicket } from '../utils';
97

108
const handleRegisterFormSubmission = async (
119
specificFormInfo,
@@ -29,7 +27,7 @@ const handleRegisterFormSubmission = async (
2927

3028
// first, check if there is already a pending request in requestor
3129
let userHaveRequestPending : boolean;
32-
let policyID : string;
30+
let policyID : string = '';
3331
try {
3432
if (specificFormInfo.name === 'WorkspaceAccessRequest') {
3533
policyID = workspaceRegistrationConfig?.workspacePolicyId ? workspaceRegistrationConfig.workspacePolicyId : 'workspace';
@@ -77,20 +75,11 @@ const handleRegisterFormSubmission = async (
7775
.then(({ data, status }) => {
7876
if (status === 201) {
7977
if (data && data.request_id) {
80-
// request created, now create a kayako ticket
78+
// request created, now create a zendesk ticket
8179
const fullName = `${formValues['First Name']} ${formValues['Last Name']}`;
8280
const email = formValues['E-mail Address'];
83-
let subject = determineSubjectLine();
84-
if (subject.length > KAYAKO_MAX_SUBJECT_LENGTH) {
85-
subject = `${subject.substring(
86-
0,
87-
KAYAKO_MAX_SUBJECT_LENGTH - 3,
88-
)}...`;
89-
}
90-
let contents = `Request ID: ${data.request_id}\n
91-
Grant Number: ${studyNumber}\n
92-
Study Name: ${studyName}\n
93-
Environment: ${hostname}`;
81+
const subject = determineSubjectLine();
82+
let contents = `Request ID: ${data.request_id}\nGrant Number: ${studyNumber}\nStudy Name: ${studyName}\nEnvironment: ${hostname}`;
9483
if (specificFormInfo.name === 'WorkspaceAccessRequest') {
9584
contents = `Request ID: ${data.request_id}\nEnvironment: ${hostname}`;
9685
}
@@ -101,12 +90,12 @@ const handleRegisterFormSubmission = async (
10190
const [key, value] = entry;
10291
contents = contents.concat(`\n${key}: ${value}`);
10392
});
104-
createKayakoTicket(
93+
createZendeskTicket(
10594
subject,
10695
fullName,
10796
email,
10897
contents,
109-
kayakoConfig?.kayakoDepartmentId,
98+
zendeskConfig?.zendeskSubdomainName,
11099
).then(
111100
() => setFormSubmissionStatus({ status: 'success' }),
112101
(err) => setFormSubmissionStatus({

src/StudyRegistration/DataDictionarySubmission.tsx

+4-9
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ import {
2424
import './StudyRegistration.css';
2525
import { Link, useLocation } from 'react-router-dom';
2626
import {
27-
hostname, kayakoConfig, studyRegistrationConfig, useArboristUI,
27+
hostname, zendeskConfig, studyRegistrationConfig, useArboristUI,
2828
} from '../localconf';
2929
import { cleanUpFileRecord, generatePresignedURL, handleDataDictionaryNameValidation } from './utils';
30-
import { createKayakoTicket } from '../utils';
30+
import { createZendeskTicket } from '../utils';
3131
import { userHasMethodForServiceOnResource } from '../authMappingUtils';
3232
import { StudyRegistrationProps } from './StudyRegistration';
3333

@@ -39,8 +39,6 @@ export interface FormSubmissionState {
3939
text?: string;
4040
}
4141

42-
const KAYAKO_MAX_SUBJECT_LENGTH = 255;
43-
4442
const layout = {
4543
labelCol: {
4644
span: 8,
@@ -165,10 +163,7 @@ const DataDictionarySubmission: React.FunctionComponent<StudyRegistrationProps>
165163
uploadToS3(url, fileInfo, setUploadProgress)
166164
.then(() => {
167165
setFormSubmissionStatus({ status: 'info', text: 'Finishing upload' });
168-
let subject = `Data dictionary submission for ${studyNumber} ${studyName}`;
169-
if (subject.length > KAYAKO_MAX_SUBJECT_LENGTH) {
170-
subject = `${subject.substring(0, KAYAKO_MAX_SUBJECT_LENGTH - 3)}...`;
171-
}
166+
const subject = `Data dictionary submission for ${studyNumber} ${studyName}`;
172167
const fullName = `${formValues['First Name']} ${formValues['Last Name']}`;
173168
const email = formValues['E-mail Address'];
174169
let contents = `Grant Number: ${studyNumber}\nStudy Name: ${studyName}\nEnvironment: ${hostname}\nStudy UID: ${studyUID}\nData Dictionary GUID: ${guid}`;
@@ -179,7 +174,7 @@ const DataDictionarySubmission: React.FunctionComponent<StudyRegistrationProps>
179174
// This is the CLI command to kick off the argo wf from AdminVM
180175
const cliCmd = `argo submit -n argo --watch HEAL-Workflows/vlmd_submission_workflows/vlmd_submission_wrapper.yaml -p data_dict_guid=${guid} -p dictionary_name="${formValues['Data Dictionary Name']}" -p study_id=${studyUID}`;
181176
contents = contents.concat(`\n\nCLI Command: ${cliCmd}`);
182-
createKayakoTicket(subject, fullName, email, contents, kayakoConfig?.kayakoDepartmentId).then(() => setFormSubmissionStatus({ status: 'success' }),
177+
createZendeskTicket(subject, fullName, email, contents, zendeskConfig?.zendeskSubdomainName).then(() => setFormSubmissionStatus({ status: 'success' }),
183178
(err) => {
184179
cleanUpFileRecord(guid);
185180
setFormSubmissionStatus({ status: 'error', text: err.message });

src/index.ejs

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
- https://dap.digitalgov.gov will be inserted by htmlWebpackPlugin if env is configured with DAPTrackingURL. This hostname is needed for fetching and executing the DAP tracking script
1313
- https://*.quicksight.aws.amazon.com for loading AWS Quicksight dashboards into COVID-19 Home page
1414
-->
15-
<meta http-equiv="Content-Security-Policy" content="default-src 'self' https://login.bionimbus.org https://wayf.incommonfederation.org; child-src blob:; img-src 'self' <%= htmlWebpackPlugin.options.imgSrc %> https://opendata.datacommons.io https://static.planx-pla.net data: https://*.s3.amazonaws.com blob:; script-src 'self' 'unsafe-eval' <%= htmlWebpackPlugin.options.scriptSrc %>; worker-src 'self' blob:; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; object-src 'none'; font-src 'self' data: https://fonts.googleapis.com https://fonts.gstatic.com; connect-src 'self' https://login.bionimbus.org https://wayf.incommonfederation.org https://opendata.datacommons.io https://static.planx-pla.net <%= htmlWebpackPlugin.options.connectSrc %>; frame-src <%= htmlWebpackPlugin.options.connectSrc %> 'self' https://auspice.planx-pla.net https://auspice.pandemicresponsecommons.org https://*.quicksight.aws.amazon.com;">
15+
<meta http-equiv="Content-Security-Policy" content="default-src 'self' https://login.bionimbus.org https://wayf.incommonfederation.org; child-src blob:; img-src 'self' <%= htmlWebpackPlugin.options.imgSrc %> https://opendata.datacommons.io https://static.planx-pla.net data: https://*.s3.amazonaws.com blob:; script-src 'self' 'unsafe-eval' <%= htmlWebpackPlugin.options.scriptSrc %>; worker-src 'self' blob:; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; object-src 'none'; font-src 'self' data: https://fonts.googleapis.com https://fonts.gstatic.com; connect-src 'self' https://login.bionimbus.org https://wayf.incommonfederation.org https://opendata.datacommons.io https://static.planx-pla.net https://*.zendesk.com <%= htmlWebpackPlugin.options.connectSrc %>; frame-src <%= htmlWebpackPlugin.options.connectSrc %> 'self' https://auspice.planx-pla.net https://auspice.pandemicresponsecommons.org https://*.quicksight.aws.amazon.com;">
1616
<meta name="viewport" content="width=device-width" />
1717
<link href="https://fonts.googleapis.com/icon?family=Source+Sans+Pro" rel="stylesheet">
1818
<link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,700;1,400;1,700&display=swap" rel="stylesheet">

src/localconf.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ function buildConfig(opts) {
334334
const { workspacePageDescription } = config;
335335
const workspaceRegistrationConfig = (registrationConfigs && registrationConfigs.features)
336336
? registrationConfigs.features.workspaceRegistrationConfig : null;
337-
const kayakoConfig = registrationConfigs ? registrationConfigs.kayakoConfig : null;
337+
const zendeskConfig = registrationConfigs ? registrationConfigs.zendeskConfig : null;
338338

339339
const colorsForCharts = {
340340
categorical9Colors: components.categorical9Colors ? components.categorical9Colors : [
@@ -471,7 +471,7 @@ function buildConfig(opts) {
471471
const aggMDSURL = `${hostname}mds/aggregate`;
472472
const aggMDSDataURL = `${aggMDSURL}/metadata`;
473473
const cedarWrapperURL = `${hostname}cedar`;
474-
const kayakoWrapperURL = `${hostname}kayako`;
474+
const gen3ZendeskURL = 'https://<SUBDOMAIN_NAME>.zendesk.com';
475475

476476
// Disallow gitops.json configurability of Gen3 Data Commons and CTDS logo alt text.
477477
// This allows for one point-of-change in the case of future rebranding.
@@ -573,7 +573,7 @@ function buildConfig(opts) {
573573
studyViewerConfig,
574574
covid19DashboardConfig,
575575
discoveryConfig,
576-
kayakoConfig,
576+
zendeskConfig,
577577
studyRegistrationConfig,
578578
mapboxAPIToken,
579579
auspiceUrl,
@@ -589,7 +589,7 @@ function buildConfig(opts) {
589589
mdsURL,
590590
aggMDSDataURL,
591591
cedarWrapperURL,
592-
kayakoWrapperURL,
592+
gen3ZendeskURL,
593593
commonsWideAltText,
594594
ddApplicationId,
595595
ddClientToken,

src/utils.js

+32-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { submissionApiPath, kayakoWrapperURL } from './localconf';
1+
import { submissionApiPath, gen3ZendeskURL } from './localconf';
22
import { getCategoryColor } from './DataDictionary/NodeCategories/helper';
3-
import { fetchWithCreds } from './actions';
3+
4+
const ZENDESK_MAX_SUBJECT_LENGTH = 255;
45

56
export const humanFileSize = (size) => {
67
if (typeof size !== 'number') {
@@ -233,24 +234,45 @@ export const isFooterHidden = (pathname) => (!!((pathname
233234
|| pathname.toLowerCase().startsWith('/dd/')
234235
))));
235236

236-
export const createKayakoTicket = async (subject, fullName, email, contents, departmentID) => {
237+
export const createZendeskTicket = async (subject, fullName, email, contents, zendeskSubdomainName) => {
237238
try {
238-
const kayakoTicketCreationURL = `${kayakoWrapperURL}/ticket`;
239-
await fetchWithCreds({
240-
path: kayakoTicketCreationURL,
239+
let zendeskTicketCreationURL = `${gen3ZendeskURL}/api/v2/requests`;
240+
if (zendeskSubdomainName) {
241+
zendeskTicketCreationURL = zendeskTicketCreationURL.replace('<SUBDOMAIN_NAME>', zendeskSubdomainName);
242+
} else {
243+
// This is the default Gen3 helpdesk subdomain
244+
zendeskTicketCreationURL = zendeskTicketCreationURL.replace('<SUBDOMAIN_NAME>', 'gen3support');
245+
}
246+
let ticketSubject = subject;
247+
if (subject.length > ZENDESK_MAX_SUBJECT_LENGTH) {
248+
ticketSubject = `${subject.substring(
249+
0,
250+
ZENDESK_MAX_SUBJECT_LENGTH - 3,
251+
)}...`;
252+
}
253+
await fetch(zendeskTicketCreationURL, {
241254
method: 'POST',
242-
customHeaders: { 'Content-Type': 'application/json' },
255+
headers: { 'Content-Type': 'application/json' },
243256
body: JSON.stringify({
244-
subject, fullname: fullName, email, contents, departmentid: departmentID,
257+
request: {
258+
subject: ticketSubject,
259+
comment: {
260+
body: contents,
261+
},
262+
requester: {
263+
name: fullName,
264+
email,
265+
},
266+
},
245267
}),
246268
}).then((response) => {
247269
if (response.status !== 201) {
248-
throw new Error(`Request for create Kayako ticket failed with status ${response.status}`);
270+
throw new Error(`Request for create Zendesk ticket failed with status ${response.status}`);
249271
}
250272
return response;
251273
});
252274
} catch (err) {
253-
throw new Error(`Request for create Kayako ticket failed: ${err}`);
275+
throw new Error(`Request for create Zendesk ticket failed: ${err}`);
254276
}
255277
};
256278

0 commit comments

Comments
 (0)