Initial Commit
This commit is contained in:
commit
6b5fabdbbe
11
.gitignore
vendored
Normal file
11
.gitignore
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
.DS_Store
|
||||||
|
.fdk/
|
||||||
|
coverage/
|
||||||
|
.report.json
|
||||||
|
.vscode/
|
||||||
|
node_modules/
|
||||||
|
test_data/
|
||||||
|
dist/
|
||||||
|
config/oauth_config.json
|
||||||
|
config/iparam_test_data.json
|
||||||
|
log/
|
||||||
20
README.md
Normal file
20
README.md
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
## Your First App
|
||||||
|
|
||||||
|
This app displays the name of the requester of a freshdesk ticket in the ticket_sidebar placeholder
|
||||||
|
|
||||||
|
### Files and Folders
|
||||||
|
.
|
||||||
|
├── README.md A file for your future self and developer friends to learn about app
|
||||||
|
├── app A folder to place all assets required for frontend components
|
||||||
|
│ ├── index.html A landing page for the user to use the app
|
||||||
|
│ ├── scripts JavaScript to place files frontend components business logic
|
||||||
|
│ │ └── app.js
|
||||||
|
│ └── styles A folder to place all the styles for app
|
||||||
|
│ ├── images
|
||||||
|
│ │ └── icon.svg
|
||||||
|
│ └── style.css
|
||||||
|
├── config A folder to place all the configuration files
|
||||||
|
│ └── iparams.json
|
||||||
|
└── manifest.json A JSON file holding meta data for app to run on platform
|
||||||
|
|
||||||
|
Explore [more of app sample apps](https://community.developers.freshworks.com/t/freshworks-sample-apps/3604) on the Freshworks github respository.
|
||||||
22
app/index.html
Normal file
22
app/index.html
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>A Template App</title>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<script async src="{{{appclient}}}"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="styles/style.css" />
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="main">
|
||||||
|
<p id="apptext"></p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<script defer src="scripts/app.js"></script>
|
||||||
|
<script async type="module" src="https://cdn.jsdelivr.net/npm/@freshworks/crayons@v4/dist/crayons/crayons.esm.js"></script>
|
||||||
|
<script async nomodule src="https://cdn.jsdelivr.net/npm/@freshworks/crayons@v4/dist/crayons/crayons.js"></script>
|
||||||
|
</html>
|
||||||
133
app/scripts/app.js
Normal file
133
app/scripts/app.js
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
var client;
|
||||||
|
let apiKey = 'wzGvV5YzPzuOCRBnQ09';
|
||||||
|
|
||||||
|
init();
|
||||||
|
|
||||||
|
async function init() {
|
||||||
|
client = await app.initialized();
|
||||||
|
client.events.on('app.activated', function () { renderText('init')});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getInfo() {
|
||||||
|
try {
|
||||||
|
const [ticketData, contactData] = await Promise.all([
|
||||||
|
client.data.get('ticket'),
|
||||||
|
client.data.get('contact')
|
||||||
|
]);
|
||||||
|
|
||||||
|
const { contact } = contactData;
|
||||||
|
const { ticket } = ticketData;
|
||||||
|
|
||||||
|
const ticketInfo = {
|
||||||
|
name: contact.name,
|
||||||
|
email: contact.email,
|
||||||
|
phone: contact.phone,
|
||||||
|
subject: ticket.subject,
|
||||||
|
description: ticket.description,
|
||||||
|
status: 2,
|
||||||
|
priority: 1,
|
||||||
|
source: ticket.source,
|
||||||
|
attachments: ticket.attachments ? ticket.attachments.map(attachment => ({
|
||||||
|
name: attachment.name,
|
||||||
|
url: attachment.attachment_url,
|
||||||
|
size: attachment.size
|
||||||
|
})) : []
|
||||||
|
};
|
||||||
|
|
||||||
|
return ticketInfo;
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
renderText('<font color="#B21508">Error gathering ticket data:\n</font>' + error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function encodeAttachments(fileUrl) {
|
||||||
|
try {
|
||||||
|
const response = await fetch(fileUrl);
|
||||||
|
const blob = await response.blob();
|
||||||
|
const reader = new FileReader();
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
reader.onloadend = () => resolve(reader.result, split(',')[1]);
|
||||||
|
reader.onerror = reject;
|
||||||
|
reader.readAsDataURL(blob);
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
renderText('<font color="#B21508">Error encoding attachment data:</font>\n' + error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function sendTicket(ticketInfo) {
|
||||||
|
try {
|
||||||
|
const encodedAttachments = await Promise.all(
|
||||||
|
ticketInfo.attachments.map(async (att) => ({
|
||||||
|
name: att.name,
|
||||||
|
content: await encodeAttachments(att.url)
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
|
||||||
|
const response = await fetch('https://cramalotsales.freshdesk.com/api/v2/tickets', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Authorization': 'Basic ' + btoa(apiKey + ':X')
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
name: ticketInfo.name,
|
||||||
|
email: ticketInfo.email,
|
||||||
|
phone: ticketInfo.phone,
|
||||||
|
subject: ticketInfo.subject,
|
||||||
|
description: ticketInfo.description,
|
||||||
|
status: ticketInfo.status,
|
||||||
|
priority: ticketInfo.priority,
|
||||||
|
source: ticketInfo.source,
|
||||||
|
attachments: encodedAttachments
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
console.log('Ticket successfully transferred:', response.status, response.statusText);
|
||||||
|
renderText('success');
|
||||||
|
} else {
|
||||||
|
renderText('Ticket creation refused by server:\n', response.status, response.statusText);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
renderText('<font color="#B21508">Error sending ticket:</font>\n'+ error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function sendTicketHandler() {
|
||||||
|
try {
|
||||||
|
const ticketInfo = await getInfo();
|
||||||
|
await sendTicket(ticketInfo);
|
||||||
|
} catch {
|
||||||
|
renderText('<font color="#B21508">Error sending ticket:</font>\n'+ error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderText(status) {
|
||||||
|
const textElement = document.getElementById('apptext');
|
||||||
|
|
||||||
|
if (status === 'init') {
|
||||||
|
textElement.innerHTML = '<p>Ticket Ready to be Transferred</p><br><button onclick="sendTicketHandler()">Transfer</button>';
|
||||||
|
} else if (status === 'success') {
|
||||||
|
textElement.innerHTML = '<p><font color="#9900FF">Ticket Transfer Successful!</font></p>';
|
||||||
|
} else {
|
||||||
|
textElement.innerHtml = status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
async function renderText() {
|
||||||
|
const textElement = document.getElementById('apptext');
|
||||||
|
const contactData = await client.data.get('contact');
|
||||||
|
const {
|
||||||
|
contact: { name }
|
||||||
|
} = contactData;
|
||||||
|
|
||||||
|
textElement.innerHTML = `Ticket is created by ${name}`;
|
||||||
|
}
|
||||||
|
*/
|
||||||
14
app/styles/images/icon.svg
Normal file
14
app/styles/images/icon.svg
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
width="64px" height="64px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||||
|
<path d="M56.7,257c0-100.5,81.8-182.2,182.2-182.2h210.5c20.5-0.7,37-16.6,38.9-36.7H238.9C118.2,38,20,136.2,20,257
|
||||||
|
c0,120.7,98.2,219,218.9,219s219-98.2,219-219V118.6c0-9.9-7.3-18.3-17.6-18.4c0,0-174.9,0-189.9,0c-115.2,0-178.5,91.1-168.6,185.2
|
||||||
|
c9.1,86.2,68.8,143.7,146.4,153.4C132.7,433.2,56.7,353.8,56.7,257z M191.9,294.8c0.6,1.6,1.4,3.1,2.1,4.7
|
||||||
|
c7.1,13.6,16.7,25.1,27.8,33.9c-4.3,5.9-10,10.5-17,13.2c-21.9,8.5-47.5-5.2-57.2-30.6c-8.4-22-2-45.5,14.1-56.9
|
||||||
|
c2.3-43.1,29.2-82.9,71.7-99.3c42.4-16.4,88.6-5,118.9,25.2c19.9-3.1,40.9,10.2,49.4,32.7c8.8,23.2,1.3,48.1-16.8,58.7
|
||||||
|
c0,0.1,0,0.3,0,0.4c-0.1-0.1-0.3-0.1-0.4-0.1c-1.6,0.9-3.2,1.7-4.9,2.4c-4.3,1.7-8.7,2.4-13.1,2.4c-2.3,19.9-9.9,38.8-21.9,54.8
|
||||||
|
c1.4,3.5,1,7.6-1.6,10.7l-9.5,11.6c-3.7,4.6-10.3,5.3-14.8,1.6c-4.5-3.7-5.2-10.4-1.6-14.9l9.5-11.6c2.6-3.2,6.6-4.5,10.4-3.7
|
||||||
|
c10.3-14.4,16.9-31.7,19.3-49.6h-0.1c0.1-0.6,0.2-1.1,0.3-1.7c1.5-12.5,3.1-25.2,0.3-37.4c0,0-0.9-5.1-1.7-7.1
|
||||||
|
c-0.2-0.7-0.4-1.3-0.7-2c-17.2-45.3-67.6-67.9-112.4-50.5C197.1,198.7,174.7,249.5,191.9,294.8z" fill="#404543"></path>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.4 KiB |
16
app/styles/style.css
Normal file
16
app/styles/style.css
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
html {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
*,
|
||||||
|
*:after,
|
||||||
|
*::before {
|
||||||
|
box-sizing: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column wrap;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
3
config/app_settings.json
Normal file
3
config/app_settings.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"api_key": {}
|
||||||
|
}
|
||||||
1
config/iparams.json
Normal file
1
config/iparams.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
17
manifest.json
Normal file
17
manifest.json
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"platform-version": "2.3",
|
||||||
|
"product": {
|
||||||
|
"freshdesk": {
|
||||||
|
"location": {
|
||||||
|
"ticket_sidebar": {
|
||||||
|
"url": "index.html",
|
||||||
|
"icon": "styles/images/icon.svg"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "18.20.4",
|
||||||
|
"fdk": "9.2.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user