<<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<base target="_top">
<!-- Metro UI -->
<link rel="stylesheet" href="https://cdn.korzh.com/metroui/v4/css/metro-all.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<style>
.container-small {
max-width:800px;
margin:0 auto;
}
</style>
</head>
<body>
<div class="container-small">
<!-- content here -->
<div class = "grid">
<div class="row flex-align-center">
<div class="cell d-flex flex-row"><h1>EPI Webform</h1></div>
<div class="cell flex-align-self-center"></div>
<div class="cell d-flex flex-row-r"><a href="<?= ScriptApp.getService().getUrl(); ?>?" align="right" class="button primary outline">Home</a></div>
</div>
</div>
</div>
<div class="container-small">
<!-- content here -->
<div class="grid">
<form id="epi-form" data-role="validator" action="javascript:" data-on-submit="addRecord">
<div class="form-group">
<label>Data</label>
<input name="date" type="date" placeholder="Data" class="metro-input"data-validate="required date"/>
</div>
<div class="form-group">
<label>Full Name</label>
<select data-role="select" name="name" data-validate="required not=''">
<option disable selected></option>
<? for(const name of names) { ?>
<option><?= name ?></option>
<? } ?>
</select>
</div>
<div class="form-group">
<label>EPIS</label>
<select data-role="select" name="equipment" data-validate="required not=''">
<option disable selected></option>
<? for(const equipment of equipments) { ?>
<option><?= equipment ?></option>
<? } ?>
</select>
</div>
<div class="form-group">
<label>Project</label>
<select data-role="select" name="site" data-validate="required not=''">
<option disable selected></option>
<? for(const site of sites) { ?>
<option><?= site ?></option>
<? } ?>
</select>
</div>
<div class="form-group">
<label>Values</label>
<input name="value" type="currency" placeholder="kr" class="metro-input" min="0.01" max="100000"/>
</div>
<div class="form-group">
<label>Notes</label>
<textarea data-role="textarea" data-auto-size="true" data-max-height="200" name="notes"></textarea>
</div>
<div class="form-group">
<button class="button success">Submit</button>
</div>
</form>
<div class="form-group d-none" id="success-message"> <!-- Success Message -->
Thanks for submitting! <button id="back-to-form">Back to Form</button>
</div>
</div>
</div>
</div>
<!-- Metro UI -->
<script src="https://cdn.korzh.com/metroui/v4/js/metro.min.js"></script>
<!-- Javascript to collect data -->
<script>
const epiForm = document.getElementById("epi-form")
const successMessage = document.getElementById("success-message")
const backToForm = document.getElementById("back-to-form")
epiForm.addEventListener("submit",submitData)
function submitData(e){
e.preventDefault()
console.log("Form Submitted")
console.log(this)
}
//Function to add record and validate fields
function addRecord(){
google.script.run.withSuccessHandler(() => { //Success case
epiForm.reset() //reset
const selectElements = epiForm.querySelectorAll("select") //reset select form
selectElements.forEach(element => {
const tempSelect = Metro.getPlugin(element,"select")
tempSelect.val("")
})
epiForm.classList.add("d-none") //submit and send success message
successMessage.classList.remove("d-none")
}).withFailureHandler(() => {
}).collectData(this)
}
backToForm.addEventListener("click",() => {
epiForm.classList.remove("d-none") //submit and send success message
successMessage.classList.add("d-none")
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<base target="_top">
<!-- Metro UI -->
<link rel="stylesheet" href="https://cdn.korzh.com/metroui/v4/css/metro-all.min.css">
<style>
.container-small {
max-width:800px;
margin:0 auto;
}
</style>
</head>
<body>
<div class="row flex-align-center">
<div class="cell-2">
<ul class="v-menu">
<li class="menu-title">Main Menu</li>
<li><a><span class="mif-home icon mif-3x"></span> Home</a></li>
<li class="menu-title">Options</li>
<li><a href="<?= ScriptApp.getService().getUrl(); ?>?v=form"><span class="mif-add icon mif-3x"></span> Add EPI Record</a></li>
<li><a href="<?= ScriptApp.getService().getUrl(); ?>?v=table"><span class="mif-table icon mif-3x"></span> EPI Table Search</a></li>
<li><a><span class="mif-tools icon mif-3x"></span>In development</a></li>
</ul>
</div>
<div class="cell-10 d-flex flex-justify-center">
<h1>EPI Management Menu</h1>
</div>
</div>
</body>
</html>
var Route = {};
Route.path = function(route,callback){
Route[route] = callback;
}
function doGet(e) {
//Connect diferent web pages
Route.path("form",loadForm);
Route.path("table",loadTable);
if(Route[e.parameters.v]) {
return Route[e.parameters.v]();
} else {
return HtmlService.createTemplateFromFile("Home").evaluate();
}
}
// Load dropdowns
function loadForm(){
const htmlService = HtmlService.createTemplateFromFile("Index")
htmlService.names = getNames_() // service to get values from list
htmlService.equipments = getEquip_() // service to get values from list
htmlService.sites = getSites_() // service to get values from list
const html = htmlService.evaluate().addMetaTag("viewport","width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no")
return html
}
//Load table page
function loadTable(){
const htmlService = HtmlService.createTemplateFromFile("table")
const html = htmlService.evaluate().addMetaTag("viewport","width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no")
return html
}
//Get data from data sheet to datatable
function getData(){
var spreadSheetId = "1aRRiUgFpIO6Ga07sU7bv9iXBslHLOn88Lq8sDUdHF6U"; // Please set your Spreadsheet ID.
var sheet = SpreadsheetApp.openById(spreadSheetId).getSheetByName("DATA"); //Name of sheet
var values = sheet.getRange("A2:F" + sheet.getLastRow()).getDisplayValues(); //Insert range
return values;
}
//Function to collect data from form
function collectData(formData){
console.log(formData)
formData.date //names of fields
const ss = SpreadsheetApp.getActiveSpreadsheet()
const ws = ss.getSheetByName("DATA") //Sheet name to save
ws.appendRow([
formData.date,
formData.name,
formData.equipment,
formData.site,
formData.value,
formData.notes]) //fix values to google sheet rows
}
function getNames_(){
const ss = SpreadsheetApp.getActiveSpreadsheet()
const ws = ss.getSheetByName("WORKER_NAME") //Sheet name to get values
const names = ws.getRange("A2:A").getValues().filter(r => r[0] !=="").map(r => r[0])
return names
}
function getEquip_(){
const ss = SpreadsheetApp.getActiveSpreadsheet()
const ws = ss.getSheetByName("EQUIPS") //Sheet name to get values
const equipments = ws.getRange("A2:A").getValues().filter(r => r[0] !=="").map(r => r[0])
return equipments
}
function getSites_(){
const ss = SpreadsheetApp.getActiveSpreadsheet()
const ws = ss.getSheetByName("SITE_NR") //Sheet name to get values
const sites = ws.getRange("A2:A").getValues().filter(r => r[0] !=="").map(r => r[0])
return sites
}
//INCLUDE JAVASCRIPT AND CSS FILES
//REF: https://developers.google.com/apps-script/guides/html/best-practices#separate_html_css_and_javascript
function include(filename) {
return HtmlService.createHtmlOutputFromFile(filename)
.getContent();
}
<script>
/*
*THIS FUNCTION CALL THE getData() FUNCTION IN THE Code.gs FILE,
*AND PASS RETURNED DATA TO showData() FUNCTION
*/
google.script.run.withSuccessHandler(showData).getData();
//THIS FUNCTION GENERATE THE DATA TABLE FROM THE DATA ARRAY
function showData(dataArray){
$(document).ready(function(){
$('#data-table').DataTable({
dom: '<"container-fluid"<"row"<"col"B><"col"l><"col"f>>>tr<"container-fluid"<"row"<"col"i><"col"p>>>',
buttons: [
'excel', 'pdf', 'print'
],
fixedHeader: true,
scrollY: '60vh',
responsive: true,
autoWidth: true,
//scrollCollapse: true,
//paging: false,
data: dataArray,
//CHANGE THE TABLE HEADINGS BELOW TO MATCH WITH YOUR SELECTED DATA RANGE
columns: [
{"title":"Data"},
{"title":"Full Name"},
{"title":"EPIS"},
{"title":"Project"},
{
"title":"Values", render: $.fn.dataTable.render.number('.',',', 0, 'kr')
},
{"title":"Notes"}
],
footerCallback: function (row, data, start, end, display) {
var api = this.api();
// Remove the formatting to get integer data for summation
var intVal = function (i) {
return typeof i === 'string' ? i.replace(/[\$,]/g, '') * 1 : typeof i === 'number' ? i : 0;
};
// Total over all pages
total = api
.column(4)
.data()
.reduce(function (a, b) {
return intVal(a) + intVal(b);
}, 0);
// Total over this page
pageTotal = api
.column(4, { page: 'current' })
.data()
.reduce(function (a, b) {
return intVal(a) + intVal(b);
}, 0);
// Update footer
$(api.column(4).footer()).html('kr' + pageTotal + ' ( kr' + total + ' total)');
},
});
});
}
</script>
!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<base target="_top">
<!--INCLUDE REQUIRED EXTERNAL JAVASCRIPT AND CSS LIBRARIES-->
<script src="https://code.jquery.com/jquery-3.5.1.js"></script>
<script src="https://cdn.datatables.net/1.13.1/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/fixedheader/3.3.1/js/dataTables.fixedHeader.min.js"></script>
<script src="https://cdn.datatables.net/1.13.1/js/dataTables.bootstrap5.min.js"></script>
<script src="https://cdn.datatables.net/buttons/2.3.2/js/dataTables.buttons.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.3/jszip.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.53/pdfmake.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.53/vfs_fonts.js"></script>
<script src="https://cdn.datatables.net/buttons/2.3.2/js/buttons.html5.min.js"></script>
<script src="https://cdn.datatables.net/buttons/2.3.2/js/buttons.print.min.js"></script>
<script src="cdn.datatables.net/plug-ins/1.12.1/api/sum().js"></script>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.2.0/css/bootstrap.css">
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.13.1/css/dataTables.bootstrap5.min.css">
<link rel="stylesheet" href="https://cdn.korzh.com/metroui/v4/css/metro-all.min.css">
<style>
.container-small {
max-width:1400px;
margin:0 auto;
}
</style>
<?!= include('JavaScript'); ?> <!--INCLUDE JavaScript.html FILE-->
</head>
<body>
<div class="container-small">
<!-- content here -->
<div class = "grid">
<div class="row">
<div class="cell d-flex flex-row"><h2>Search Table</h2></div>
<div class="cell flex-align-self-center"></div>
<div class="cell d-flex flex-row-r">
<a href="<?= ScriptApp.getService().getUrl(); ?>?" align="right" class="button primary outline">Home</a>
</div>
</div>
</div>
</div>
<div class="container-small">
<table id="data-table" class="table table-striped table-border table-hover" style="width:100%">
<!-- TABLE DATA IS ADDED BY THE showData() JAVASCRIPT FUNCTION ABOVE -->
<tfoot>
<tr>
<th></th>
<th></th>
<th></th>
<th>Total:</th>
<th colspan="2" style="text-align:left"></th>
</tr>
</tfoot>
</table>
</div>
<style>
th { white-space: nowrap; }
</style>
</body>
</html>