Hi @Raviraj,
here are my html and js files:
dialog.html
<!DOCTYPE html>
<html lang="de">
<head>
<title>Time Protocol Helper</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>
<script async src="scripts/dialog.js"></script>
<link rel="stylesheet" type="text/css" href="styles/style.css" />
</head>
<body>
<div class='container-fluid'>
<form>
<fw-input id="input_worked_time" type="number" min="0" label="Geleistete Zeit (in Minuten)" required></fw-input>
<fw-input id="input_billable_time" type="number" min="0" label="Abrechenbare Zeit (in Minuten)"
required></fw-input>
<fw-textarea id="textarea_description" rows="4" max-rows="10" label="Was wurde gemacht? (Beschreibung)"
required></fw-textarea>
</br>
<fw-button id="submit_button" color="primary">Protokoll anlegen</fw-button>
</form>
</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>
dialog.js
document.addEventListener("DOMContentLoaded", async function () {
const client = await app.initialized();
const workedTimeInput = document.getElementById("input_worked_time");
const billableTimeInput = document.getElementById("input_billable_time");
const descriptionTextarea = document.getElementById("textarea_description");
const submitButton = document.getElementById("submit_button");
// Add an event listener that copies the worked time into the billable time field
workedTimeInput.addEventListener("fwBlur", function () {
const workedTimeValue = workedTimeInput.value;
billableTimeInput.value = workedTimeValue;
billableTimeInput.setAttribute("max", workedTimeValue);
});
// Add event listener for the form submit
submitButton.addEventListener("click", async function (event) {
event.preventDefault();
// Reset error states
resetForm(workedTimeInput, billableTimeInput, descriptionTextarea);
// Validate Form Input
const isValid = validateForm(workedTimeInput, billableTimeInput, descriptionTextarea);
// Create Entries if Input is valid
if (isValid) {
try {
// Parse TimeEntries
const billableTimeMinutes = parseInt(billableTimeInput.value);
const workedTimeMinutes = parseInt(workedTimeInput.value);
// Create billable TimeEntry
await createTimeEntryForTicket(
client,
descriptionTextarea.value,
billableTimeMinutes,
true
);
// If workedTime is greater then billableTime create a second TimeEntry
if (workedTimeMinutes > billableTimeMinutes) {
// Calculate how much time is left for workedTime Entry
const calculatedTimeMinutes = workedTimeMinutes - billableTimeMinutes;
// Create worked TimeEntry
await createTimeEntryForTicket(
client,
descriptionTextarea.value,
calculatedTimeMinutes,
false
);
}
} catch (error) {
// Log Error
console.error(error);
}
// Close Dialog
await client.instance.close();
}
});
});
// Convert Minute TimeFormat in HH:MM
function convertMinutesToHHMM(minutes) {
const hrs = Math.floor(minutes / 60);
const mins = minutes % 60;
const paddedHrs = String(hrs).padStart(2, '0');
const paddedMins = String(mins).padStart(2, '0');
return `${paddedHrs}:${paddedMins}`;
}
// Invoke a TimeEntry Request with given Parameters
async function createTimeEntryForTicket(client, note, timeSpent, billable) {
// Get agentId from loggedInUser
const loggedInAgent = await client.data.get("loggedInUser");
const agentId = loggedInAgent.loggedInUser.id;
// Get ticketId from opened Ticket
const ticketData = await client.data.get("ticket");
const ticketId = ticketData.ticket.id;
// Convert spent time
const timeSpentHHMM = convertMinutesToHHMM(timeSpent);
// Create request body
const body = {
"note": note,
"time_spent": timeSpentHHMM,
"agent_id": agentId,
"billable": billable
}
// Invoke API Request for TimeEntry
await client.request.invokeTemplate("createTimeEntryForTicket", {
context: {
ticketId: ticketId
},
body: JSON.stringify(body)
});
}
// Validates Form Input
function validateForm(workedTimeInput, billableTimeInput, descriptionTextarea) {
let isValid = true;
// Check if worked time is not empty
if (!workedTimeInput.value) {
isValid = false;
workedTimeInput.setAttribute("state", "error");
workedTimeInput.setAttribute("error-text", "Dieses Feld ist erforderlich.");
}
// Check if billable time is not empty and is not greater then worked time
if (!billableTimeInput.value || parseInt(billableTimeInput.value) > parseInt(workedTimeInput.value)) {
billableTimeInput.setAttribute("state", "error");
billableTimeInput.setAttribute("error-text", "Dieses Feld ist erforderlich und darf nicht größer als die geleistete Zeit sein.");
}
// Check if description is not empty
if (!descriptionTextarea.value) {
isValid = false;
descriptionTextarea.setAttribute("state", "error");
descriptionTextarea.setAttribute("error-text", "Dieses Feld ist erforderlich.");
}
return isValid;
}
// Reset the Form
function resetForm(workedTimeInput, billableTimeInput, descriptionTextarea) {
workedTimeInput.removeAttribute("state");
workedTimeInput.removeAttribute("error-text");
billableTimeInput.removeAttribute("state");
billableTimeInput.removeAttribute("error-text");
descriptionTextarea.removeAttribute("state");
descriptionTextarea.removeAttribute("error-text");
}
app.js
init();
async function init() {
const client = await app.initialized();
client.events.on('app.activated', () => {
showTimeEntryDialog(client);
});
}
function showTimeEntryDialog(client) {
try {
client.interface.trigger('showDialog', {
title: 'Arbeitszeit protokollieren',
template: 'dialog.html'
});
} catch (error) {
console.error(error);
}
}