Skip to content

Instantly share code, notes, and snippets.

@acabreragnz
Last active June 12, 2022 00:23
Show Gist options
  • Save acabreragnz/9ee0631e6bc15cde6ac72bb8ebdc4f88 to your computer and use it in GitHub Desktop.
Save acabreragnz/9ee0631e6bc15cde6ac72bb8ebdc4f88 to your computer and use it in GitHub Desktop.
document.addEventListener('DOMContentLoaded', function() {
console.log('loading zendesk form builder');
let REPORT_BUG_ARTICLE_ID = '6509556532759';
let REPORT_BUG_TICKET_ID = '6504444995991';
let CONTACT_US_ARTICLE_ID = '6510266315671';
let CONTACT_US_TICKET_ID = '5754824917015';
let FORM_PARENT_ID = 'request-form';
let FORM_PARENT_CLASS = 'article-content';
const CUSTOM_FIELDS = {
firstName: {
id: '6505585946775',
labelText: 'First Name',
},
lastName: {
id: '6505541331223',
labelText: 'Last Name',
},
operatingSystem: {
id: '5843778091287',
labelText: 'Operating System',
},
browser: {
id: '5843796719767',
labelText: 'Browser Type & Version',
hintText: 'Please enter the model and version',
},
}
if (TEST_MODE) {
REPORT_BUG_ARTICLE_ID = '6941241013140';
// https://bixlabs7184.zendesk.com/admin/objects-rules/tickets/ticket-forms
REPORT_BUG_TICKET_ID = '6509556532759';
// CONTACT_US_ARTICLE_ID = '';
// CONTACT_US_TICKET_ID = '';
// https://bixlabs7184.zendesk.com/admin/objects-rules/tickets/ticket-fields
CUSTOM_FIELDS.browser.id = '6942533341204';
}
const CUSTOM_FIELDS_IN_CONTACT_US_REQUEST = [
CUSTOM_FIELDS.firstName,
CUSTOM_FIELDS.lastName,
]
const CUSTOM_FIELDS_IN_REPORT_A_BUG_REQUEST = [
CUSTOM_FIELDS.firstName,
CUSTOM_FIELDS.lastName,
CUSTOM_FIELDS.operatingSystem,
CUSTOM_FIELDS.browser,
]
const hasToBuildReportBugForm = window.location.pathname.includes(REPORT_BUG_ARTICLE_ID);
const hasToBuildContactUsForm = window.location.pathname.includes(CONTACT_US_ARTICLE_ID);
let currentRequestId;
if (hasToBuildReportBugForm) {
currentRequestId = REPORT_BUG_TICKET_ID;
buildReportBugForm();
} else if (hasToBuildContactUsForm) {
currentRequestId = CONTACT_US_TICKET_ID;
buildContactUsForm();
} else {
// NOW: borrar
currentRequestId = REPORT_BUG_TICKET_ID;
buildReportBugForm();
}
function buildReportBugForm() {
const form = createForm(trigger);
appendChildToForm(form, CUSTOM_FIELDS_IN_REPORT_A_BUG_REQUEST);
appendFormToParent(form);
}
function buildContactUsForm() {
const form = createForm(trigger);
appendChildToForm(form, CUSTOM_FIELDS_IN_CONTACT_US_REQUEST);
appendFormToParent(form);
}
function createForm(submitListener) {
const form = document.createElement('form');
form.setAttribute('action', '');
form.setAttribute('method', 'POST');
form.addEventListener('submit', submitListener);
return form;
}
function appendChildToForm(form, customFieldsToAppend) {
const emailEl = createFormInput({
name: 'email',
labelText: 'Your email address',
});
form.appendChild(emailEl);
createAndAppendCustomFields(form, customFieldsToAppend);
const subjectEl = createFormInput({
name: 'subject',
labelText: 'Subject',
});
const descriptionEl = createFormTextArea({
name: 'description',
labelText: 'Description',
hintText: 'Please enter the details of your request. A member of our support staff will respond as soon as possible.',
});
const attachmentsEl = createFormInput({
name: 'attachments',
labelText: 'Attachments (optional)',
type: 'file',
});
form.appendChild(subjectEl);
form.appendChild(descriptionEl);
form.appendChild(attachmentsEl);
createAndAppendSubmitButton(form);
}
function createFormInput({
name = '',
labelText = '',
isCustomField = false,
customFieldId = '',
hintText = '',
type = 'text',
}) {
const baseId = isCustomField && customFieldId ? `request_custom_fields_${customFieldId}` : `request_${name}`;
const inputId = baseId;
const labelEl = createLabelEl({
id: baseId + '_label',
htmlFor: inputId,
text: labelText,
});
const inputEl = createInputEl({
id: inputId,
name: name || (isCustomField ? generateNameForCustomField(customFieldId) : ''),
type,
});
const formFieldEl = document.createElement('div');
formFieldEl.setAttribute('class', 'form-field string required');
formFieldEl.appendChild(labelEl);
formFieldEl.appendChild(inputEl);
if (hintText) {
const hintEl = document.createElement('p');
hintEl.setAttribute('id', baseId + '_hint');
hintEl.innerText = hintText;
formFieldEl.appendChild(hintEl);
}
return formFieldEl;
};
function createAndAppendCustomFields(form, customFieldsToAppend) {
customFieldsToAppend.forEach(({ id, name, labelText, hintText }) => {
form.appendChild(createFormInput({
customFieldId: id,
isCustomField: true,
name,
labelText,
hintText,
}));
});
}
function appendFormToParent(form) {
let formParentEl = document.getElementById(FORM_PARENT_ID);
formParentEl ??= document.getElementsByClassName(FORM_PARENT_CLASS)[0];
formParentEl.appendChild(form);
formParentEl.setAttribute('class', 'form');
}
function createAndAppendSubmitButton(form) {
const footer = document.createElement('footer');
const submitButton = document.createElement('input');
submitButton.setAttribute('type', 'submit');
submitButton.innerText = 'Submit';
footer.appendChild(submitButton);
form.appendChild(footer);
}
function createFormTextArea({
name = '',
labelText = '',
isCustomField = false,
customFieldId = '',
hintText = '',
}) {
const baseId = isCustomField && customFieldId ? `request_custom_fields_${customFieldId}` : `request_${name}`;
const textAreaId = baseId;
const labelEl = createLabelEl({
id: baseId + '_label',
htmlFor: textAreaId,
text: labelText,
});
const textAreaEl = createTextAreaEl({
id: textAreaId,
name: name || (isCustomField ? generateNameForCustomField(customFieldId) : ''),
});
const formFieldEl = document.createElement('div');
formFieldEl.setAttribute('class', 'form-field string required');
formFieldEl.appendChild(labelEl);
formFieldEl.appendChild(textAreaEl);
if (hintText) {
const hintEl = document.createElement('p');
hintEl.setAttribute('id', baseId + '_hint');
hintEl.innerText = hintText;
formFieldEl.appendChild(hintEl);
}
return formFieldEl;
};
function createLabelEl({
id,
text,
htmlFor,
}) {
const labelEl = document.createElement('label');
labelEl.setAttribute('id', id);
labelEl.setAttribute('for', htmlFor);
labelEl.innerText = text;
return labelEl;
}
function createInputEl({
id,
name,
placeholder = '',
type = 'text',
required = false,
className = '',
}) {
const inputEl = document.createElement('input');
inputEl.setAttribute('id', id);
inputEl.setAttribute('type', type);
inputEl.setAttribute('class', className);
inputEl.setAttribute('name', name);
inputEl.setAttribute('required', required);
inputEl.setAttribute('placeholder', placeholder);
if (type === 'file') {
inputEl.setAttribute('multiple', true);
}
return inputEl;
}
function createTextAreaEl({
id,
name,
required = false,
className = '',
}) {
const textAreaEl = document.createElement('textarea');
textAreaEl.setAttribute('id', id);
textAreaEl.setAttribute('class', className);
textAreaEl.setAttribute('name', name);
textAreaEl.setAttribute('required', required);
return textAreaEl;
}
function generateNameForCustomField(fieldId) {
return `request[custom_fields][${fieldId}]`
}
async function trigger(event) {
event.preventDefault();
const formData = new FormData(event.target);
const value = Object.fromEntries(formData.entries());
const uploadResults = await uploadAttachments();
const customFields = buildCustomFields(value)
const uploads = uploadResults
.filter((result) => result.status === 'fulfilled')
.map((result) => result.value);
fetch("/api/v2/requests.json",
{
body: JSON.stringify({
request: {
requester: {
name: value.email
},
subject: value.subject,
comment: {
body: value.description,
uploads: uploads.map(({ upload }) => upload.token),
},
custom_fields: customFields,
ticket_form_id: currentRequestId,
}
}),
headers: {
"Content-Type": "application/json"
},
method: "POST"
})
}
function buildCustomFields(formData) {
return Object
.entries(formData)
.flatMap(([key, value]) => {
const matches = key.match(/request\[custom_fields]\[(\d+)]/);
if (matches) return [{ id: matches[1], value }];
})
.filter(Boolean);
}
async function uploadAttachments() {
const input = document.getElementById('request_attachments')
return Promise.allSettled(Array.from(input.files).map(async (file) => {
var data = new FormData()
data.append('file', file)
// access to file name
console.log(file.name)
// access to file extension
console.log(file.type)
return fetch(`/api/v2/uploads.json?filename=${file.name}`, {
body: data,
// headers: {
// "Content-Type": "application/binary"
// },
method: "POST"
})
.then((response) => response.json())
.then((response) => {
if (response.error) {
return Promise.reject(response);
}
return response.error
? Promise.reject(response)
: response;
})
}))
}
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment