Skip to content

Commit

Permalink
HP-1646 Feat/zendesk (#1587)
Browse files Browse the repository at this point in the history
* feat migrate from kayako to zendesk

* feat code change

* update csp

* fix fetch

* fix content

* update
  • Loading branch information
mfshao authored Aug 23, 2024
1 parent 0c93840 commit 7408950
Show file tree
Hide file tree
Showing 8 changed files with 55 additions and 47 deletions.
2 changes: 1 addition & 1 deletion dev.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
- https://atlas.qa-mickey.planx-pla.net for Atlas iframe in VHDC qa-mickey
- https://*.quicksight.aws.amazon.com for loading AWS Quicksight dashboards into COVID-19 Home page
-->
<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; ">
<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; ">
<meta name="viewport" content="width=device-width" />
<link href="https://fonts.googleapis.com/icon?family=Source+Sans+Pro" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,700;1,700&display=swap" rel="stylesheet">
Expand Down
6 changes: 3 additions & 3 deletions docs/portal_config.md
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,7 @@ Below is an example, with inline comments describing what each JSON block config
...
],
"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,
"registrationConfigs": { // optional; Required when using Kayako integration with Study/Workspace registration
"registrationConfigs": { // optional; Required when using Zendesk integration with Study/Workspace registration
"features":{ // Optional; Required when using study/Workspace registration
"studyRegistrationConfig": { // optional, config for Study Registration and Study Registration Request Access page.
"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"
Expand All @@ -765,8 +765,8 @@ Below is an example, with inline comments describing what each JSON block config
}
}
},
"kayakoConfig":{ //Required; if using either of the study/workspace registration feature
"kayakoDepartmentId": 21 // Required; the department ID in the kayako portal. Refer to Ops team to get more info
"zendeskConfig":{ // Optional; add this if you want to customize the subdomain that Zendesk is using in either of the study/workspace registration feature
"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'
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/GenericAccessRequestForm/GenericAccessRequestForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ const GenericAccessRequestForm: React.FunctionComponent<StudyRegistrationProps>
if (!useArboristUI) {
return true;
}
// We don't need this method anymore after we migrated to Zendesk, but just an extra layer of check here
// This may get removed in the future
return userHasMethodForServiceOnResource(
'create',
'kayako',
Expand Down
27 changes: 8 additions & 19 deletions src/GenericAccessRequestForm/handleRegisterFormSubmission.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { doesUserHaveRequestPending } from '../StudyRegistration/utils';
import {
kayakoConfig, hostname, workspaceRegistrationConfig, requestorPath,
zendeskConfig, hostname, workspaceRegistrationConfig, requestorPath,
} from '../localconf';
import { fetchWithCreds } from '../actions';
import { createKayakoTicket } from '../utils';

const KAYAKO_MAX_SUBJECT_LENGTH = 255;
import { createZendeskTicket } from '../utils';

const handleRegisterFormSubmission = async (
specificFormInfo,
Expand All @@ -29,7 +27,7 @@ const handleRegisterFormSubmission = async (

// first, check if there is already a pending request in requestor
let userHaveRequestPending : boolean;
let policyID : string;
let policyID : string = '';
try {
if (specificFormInfo.name === 'WorkspaceAccessRequest') {
policyID = workspaceRegistrationConfig?.workspacePolicyId ? workspaceRegistrationConfig.workspacePolicyId : 'workspace';
Expand Down Expand Up @@ -77,20 +75,11 @@ const handleRegisterFormSubmission = async (
.then(({ data, status }) => {
if (status === 201) {
if (data && data.request_id) {
// request created, now create a kayako ticket
// request created, now create a zendesk ticket
const fullName = `${formValues['First Name']} ${formValues['Last Name']}`;
const email = formValues['E-mail Address'];
let subject = determineSubjectLine();
if (subject.length > KAYAKO_MAX_SUBJECT_LENGTH) {
subject = `${subject.substring(
0,
KAYAKO_MAX_SUBJECT_LENGTH - 3,
)}...`;
}
let contents = `Request ID: ${data.request_id}\n
Grant Number: ${studyNumber}\n
Study Name: ${studyName}\n
Environment: ${hostname}`;
const subject = determineSubjectLine();
let contents = `Request ID: ${data.request_id}\nGrant Number: ${studyNumber}\nStudy Name: ${studyName}\nEnvironment: ${hostname}`;
if (specificFormInfo.name === 'WorkspaceAccessRequest') {
contents = `Request ID: ${data.request_id}\nEnvironment: ${hostname}`;
}
Expand All @@ -101,12 +90,12 @@ const handleRegisterFormSubmission = async (
const [key, value] = entry;
contents = contents.concat(`\n${key}: ${value}`);
});
createKayakoTicket(
createZendeskTicket(
subject,
fullName,
email,
contents,
kayakoConfig?.kayakoDepartmentId,
zendeskConfig?.zendeskSubdomainName,
).then(
() => setFormSubmissionStatus({ status: 'success' }),
(err) => setFormSubmissionStatus({
Expand Down
13 changes: 4 additions & 9 deletions src/StudyRegistration/DataDictionarySubmission.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ import {
import './StudyRegistration.css';
import { Link, useLocation } from 'react-router-dom';
import {
hostname, kayakoConfig, studyRegistrationConfig, useArboristUI,
hostname, zendeskConfig, studyRegistrationConfig, useArboristUI,
} from '../localconf';
import { cleanUpFileRecord, generatePresignedURL, handleDataDictionaryNameValidation } from './utils';
import { createKayakoTicket } from '../utils';
import { createZendeskTicket } from '../utils';
import { userHasMethodForServiceOnResource } from '../authMappingUtils';
import { StudyRegistrationProps } from './StudyRegistration';

Expand All @@ -39,8 +39,6 @@ export interface FormSubmissionState {
text?: string;
}

const KAYAKO_MAX_SUBJECT_LENGTH = 255;

const layout = {
labelCol: {
span: 8,
Expand Down Expand Up @@ -165,10 +163,7 @@ const DataDictionarySubmission: React.FunctionComponent<StudyRegistrationProps>
uploadToS3(url, fileInfo, setUploadProgress)
.then(() => {
setFormSubmissionStatus({ status: 'info', text: 'Finishing upload' });
let subject = `Data dictionary submission for ${studyNumber} ${studyName}`;
if (subject.length > KAYAKO_MAX_SUBJECT_LENGTH) {
subject = `${subject.substring(0, KAYAKO_MAX_SUBJECT_LENGTH - 3)}...`;
}
const subject = `Data dictionary submission for ${studyNumber} ${studyName}`;
const fullName = `${formValues['First Name']} ${formValues['Last Name']}`;
const email = formValues['E-mail Address'];
let contents = `Grant Number: ${studyNumber}\nStudy Name: ${studyName}\nEnvironment: ${hostname}\nStudy UID: ${studyUID}\nData Dictionary GUID: ${guid}`;
Expand All @@ -179,7 +174,7 @@ const DataDictionarySubmission: React.FunctionComponent<StudyRegistrationProps>
// This is the CLI command to kick off the argo wf from AdminVM
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}`;
contents = contents.concat(`\n\nCLI Command: ${cliCmd}`);
createKayakoTicket(subject, fullName, email, contents, kayakoConfig?.kayakoDepartmentId).then(() => setFormSubmissionStatus({ status: 'success' }),
createZendeskTicket(subject, fullName, email, contents, zendeskConfig?.zendeskSubdomainName).then(() => setFormSubmissionStatus({ status: 'success' }),
(err) => {
cleanUpFileRecord(guid);
setFormSubmissionStatus({ status: 'error', text: err.message });
Expand Down
2 changes: 1 addition & 1 deletion src/index.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
- 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
- https://*.quicksight.aws.amazon.com for loading AWS Quicksight dashboards into COVID-19 Home page
-->
<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;">
<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;">
<meta name="viewport" content="width=device-width" />
<link href="https://fonts.googleapis.com/icon?family=Source+Sans+Pro" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,700;1,400;1,700&display=swap" rel="stylesheet">
Expand Down
8 changes: 4 additions & 4 deletions src/localconf.js
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ function buildConfig(opts) {
const { workspacePageDescription } = config;
const workspaceRegistrationConfig = (registrationConfigs && registrationConfigs.features)
? registrationConfigs.features.workspaceRegistrationConfig : null;
const kayakoConfig = registrationConfigs ? registrationConfigs.kayakoConfig : null;
const zendeskConfig = registrationConfigs ? registrationConfigs.zendeskConfig : null;

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

// Disallow gitops.json configurability of Gen3 Data Commons and CTDS logo alt text.
// This allows for one point-of-change in the case of future rebranding.
Expand Down Expand Up @@ -573,7 +573,7 @@ function buildConfig(opts) {
studyViewerConfig,
covid19DashboardConfig,
discoveryConfig,
kayakoConfig,
zendeskConfig,
studyRegistrationConfig,
mapboxAPIToken,
auspiceUrl,
Expand All @@ -589,7 +589,7 @@ function buildConfig(opts) {
mdsURL,
aggMDSDataURL,
cedarWrapperURL,
kayakoWrapperURL,
gen3ZendeskURL,
commonsWideAltText,
ddApplicationId,
ddClientToken,
Expand Down
42 changes: 32 additions & 10 deletions src/utils.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { submissionApiPath, kayakoWrapperURL } from './localconf';
import { submissionApiPath, gen3ZendeskURL } from './localconf';
import { getCategoryColor } from './DataDictionary/NodeCategories/helper';
import { fetchWithCreds } from './actions';

const ZENDESK_MAX_SUBJECT_LENGTH = 255;

export const humanFileSize = (size) => {
if (typeof size !== 'number') {
Expand Down Expand Up @@ -233,24 +234,45 @@ export const isFooterHidden = (pathname) => (!!((pathname
|| pathname.toLowerCase().startsWith('/dd/')
))));

export const createKayakoTicket = async (subject, fullName, email, contents, departmentID) => {
export const createZendeskTicket = async (subject, fullName, email, contents, zendeskSubdomainName) => {
try {
const kayakoTicketCreationURL = `${kayakoWrapperURL}/ticket`;
await fetchWithCreds({
path: kayakoTicketCreationURL,
let zendeskTicketCreationURL = `${gen3ZendeskURL}/api/v2/requests`;
if (zendeskSubdomainName) {
zendeskTicketCreationURL = zendeskTicketCreationURL.replace('<SUBDOMAIN_NAME>', zendeskSubdomainName);
} else {
// This is the default Gen3 helpdesk subdomain
zendeskTicketCreationURL = zendeskTicketCreationURL.replace('<SUBDOMAIN_NAME>', 'gen3support');
}
let ticketSubject = subject;
if (subject.length > ZENDESK_MAX_SUBJECT_LENGTH) {
ticketSubject = `${subject.substring(
0,
ZENDESK_MAX_SUBJECT_LENGTH - 3,
)}...`;
}
await fetch(zendeskTicketCreationURL, {
method: 'POST',
customHeaders: { 'Content-Type': 'application/json' },
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
subject, fullname: fullName, email, contents, departmentid: departmentID,
request: {
subject: ticketSubject,
comment: {
body: contents,
},
requester: {
name: fullName,
email,
},
},
}),
}).then((response) => {
if (response.status !== 201) {
throw new Error(`Request for create Kayako ticket failed with status ${response.status}`);
throw new Error(`Request for create Zendesk ticket failed with status ${response.status}`);
}
return response;
});
} catch (err) {
throw new Error(`Request for create Kayako ticket failed: ${err}`);
throw new Error(`Request for create Zendesk ticket failed: ${err}`);
}
};

Expand Down

0 comments on commit 7408950

Please sign in to comment.