In the previous solution article we ended with the user creating a new record with a generated ID and the system redirecting the user to request.aspx?rid=123 where 123 is the generated ID. Now we will create request.aspx.
<html>
<head>
<title>Request</title>
<link rel="stylesheet" href="style.css" />
<script src="javascript.js"></script>
</head>
<body>
<div id="header">
<table id="headerbody">
<tbody>
<tr>
<td id="breadcrumbcell"><span style='font-weight:bold;'>Approvals</span> › Request</td>
<td id="emailaddress"></td>
</tr>
</tbody>
</table>
</div>
<div class='page'>
<div id='requestid' style='display:none;'></div>
<div id='uniqueid' style='display:none;'></div>
<div id='downloadpdffountain' style='display:none;'>
<img style='padding:10px;' src='../images/fountain.gif' />
</div>
<div id='downloadpdf'>Download</div>
<div id='cancelledlabel' style='display:none;color:red;font-size:1.5em;border:3px solid red;text-transform:uppercase;padding:5px;margin-bottom:10px;text-align:center;font-weight:bold;'>
Cancelled
</div>
<div style='border:1px solid #ccc;'>
<div style='background-color:#eee;padding:10px;font-size:1.6em;'>
<div id='mytitlelist' style='display:none;'></div>
<input id='mytitle' style='width:100%;font-size:1.6em;padding:5px;box-sizing:border-box;display:none;border:1px solid #ddd;' placeholder='Title' />
</div>
<div style='margin-left:10px;margin-right:10px;'>
<table style='width:100%;'>
<tr>
<td style='width:100px;'>Created by</td>
<td id='creator'></td>
</tr>
<tr>
<td>Date created</td>
<td id='datecreated'></td>
</tr>
<tr id='datesentoutrow' style='display:none;'>
<td>Date sent out</td>
<td id='datesentout'></td>
</tr>
<tr id='datecompletedrow' style='display:none;'>
<td style='padding-right:10px;'>Date completed</td>
<td id='datecompleted'></td>
</tr>
<tr>
<td>Status</td>
<td id='status'></td>
</tr>
<tr>
<td style='vertical-align:top;'>Description</td>
<td>
<div id='descriptionlist' style='display:none;'></div>
<textarea id='description' style='width:100%;display:none;box-sizing:border-box;resize:none;' placeholder='Description'><textarea>
</td>
</tr>
</table>
</div>
</div>
<div style='height:10px;'></div>
<div class='requestboxes'>
<div id='fileslabel'>Files</div>
<div id='addfilerealbutton' class='actionbutton' style='width:120px;display:none;margin-left:5px;margin-bottom:15px;'>
Add file
</div>
<input type="file" id="file" style='position:absolute;left:-1000px;' />
<label id='filelabel' for='file' style='display:none;'>Add file</label>
<div id='newfilefromlocaldrivefilelist' style='display:none;padding-left:10px;'>
No file selected
</div>
<div id='uploadnewfileerror' style='margin:20px;display:none;'></div>
<div id='newfilefromlocaldriveuploadfountain' style='text-align:center;display:none;'>
<img style='padding:20px;' src='../images/fountain.gif' />
</div>
<div id='filesfountain' style='display:none;padding-left:15px;'>
<img style='padding:10px;' src='../images/fountain.gif' />
</div>
<div id='fileslist' style='padding-top:0px;padding-left:15px;'></div>
</div>
<div class='requestboxes' style='border-bottom:1px solid #ddd;'>
<div id='approverslabel'>Approvers</div>
<div id='addapprovers' style='display:none;'>
<table style='width:100%;'>
<tr>
<td>
<input id='addapproverinput' style='width:300px;padding:10px;border:1px solid #ddd;' />
</td>
<td id='addapproverbutton' class='actionbutton' style='width:80px;'>
Add approver
</td>
</tr>
<tr>
<td style='height:10px;'></td>
</tr>
</table>
</div>
<div id='approverslist' style='margin-top:-10px;padding-left:13px;'>
<img style='padding:10px;' src='../images/fountain.gif' />
</div>
</div>
<div id='submitbuttonfountain' style='padding:20px;text-align:center;display:none;'>
<img src='../images/fountain.gif' />
</div>
<div id='submitbutton' class='actionbutton' style='display:none;'>
Submit
</div>
<div id='savebuttonfountain' style='padding:20px;display:none;'>
<img src='../images/fountain.gif' />
</div>
<div id='savebutton' class='actionbutton' style='display:none;margin-top:20px; width:170px;'>
Save draft
</div>
<div id='cancelrequestrow' style='font-size:.9em;margin-top:15px;display:none;'>
<a href='#' id='cancelrequest'>Cancel request</a>
</div>
<div id='requesturl' style='color:#888;margin-top:20px;font-size:.9em;'></div>
</div>
</body>
</html>
In request.aspx we refer to style.css and javascript.js externally inside the . Below is style.css.
#workstreambody{
max-width:800px;
}
body{
margin:0;
}
#header{
background-color:#579;
box-shadow:0px 0px 5px rgba(0,0,0,.2);
width:100%;
}
#headerbody{
min-height:50px;
max-height:50px;
overflow:hidden;
width:100%;
max-width:1000px;
font-size:22px;
font-family:"Segoe UI", "Segoe UI Web (West European)", "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", sans-serif;
border-collapse:collapse;
border-spacing:0;
border:none;
table-layout:fixed;
color:#fff
}
#headerbody td{
padding-left:0;
padding-right:0;
color:#fff;
}
#headerbody td:not(#breadcrumbcell){
vertical-align:middle;
}
#headerbody a{
color:#fff;
text-decoration:none;
}
#headerbody a:hover{
background-color:rgba(0,0,0,.1);
}
#breadcrumbcell{
vertical-align:top;
padding-top:8px;
padding-left:20px;
overflow:hidden;
max-height:50px;
overflow:hidden;
white-space:nowrap;
text-overflow:ellipsis;
}
#emailaddress{
text-align:right;
font-size:14px;
padding-right:15px !important;
overflow:hidden;
width:200px;
color:#fff;
}
.page{
text-align:left;
margin:0;
margin-bottom:50px;
padding:10px;
max-width:800px;
}
.pointer{
cursor:pointer;
}
.whitegray:hover{
background-color:#eee;
}
#awaitingmyapprovaltable a{
color:#000;
text-decoration:none;
height:100%;
width:100%;
display:inline-block;
padding:10px;
}
.requestboxes{
border:1px solid #ddd;
border-bottom:0px;
}
.requestboxes:last-child{
border-bottom:1px solid #ddd;
}
#fileslabel,#approverslabel{
font-weight:bold;
margin:10px;
margin-bottom:0px;
}
.filerow{
cursor:pointer;
}
.filerow:hover{
background-color:#def;
}
#addapproverbutton:hover{
background-color:#79b;
}
#downloadpdf{
background:red url('images/pdf.png') 5px 5px no-repeat;
background-size:33px 40px;
border-radius:3px;
height:42px;
margin-bottom:10px;
color:white;
padding-left:50px;
padding-top:10px;
width:140px;
font-size:1.5em;
font-weight:bold;
cursor:pointer;
display:none;
}
#downloadpdf:hover{
background-color:#dd0000;
}
.actionbutton{
background-color:#579;
color:#fff;
text-align:center;
padding:20px;
cursor:pointer;
}
.actionbutton:hover{
background-color:#79b;
}
.filedelete, .approverdelete{
display:table-cell;
margin-top:5px;
vertical-align:middle;
font-size:0px;
cursor:pointer;
padding:10px;
width:180px;
border:#f00;
background-repeat:no-repeat;
background-position:4.5px 4.5px;
background-color:#f88;
border-radius:3px;
background-image:url('images/whitex.png');
}
.filedelete:hover{
background-color:#f11;
background-image:url('images/whitex.png');
}
.approverdelete:hover{
background-color:#f11;
background-image:url('images/whitex.png');
}
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
margin-below:10px;
}
.switch input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #F33621;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked + .slider {
background-color: #2196F3;
}
input:focus + .slider {
box-shadow: 0 0 1px #2196F3;
}
input:checked + .slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
And below is javascript.js
$(document).ready(function(){
$.ajax({
url: "/sites/mydepartmentorproject/_api/web/currentuser?select=Email",
headers: {
"Accept":"application/json; odata=nometadata"
}
}).done(function(data) {
$('#emailaddress').html(data.Email.toLowerCase());
request();
}
}).fail(function(error){
console.log(JSON.stringify(error));
});
function nicedate(dateinput){
var months = ["","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
var d = dateinput;
var nicedate = "";
if(dateinput!=undefined){
nicedate = parseInt(d.slice(8,10))+'Â '+months[parseInt(d.slice(5,7))]+'Â '+d.slice(0,4);
}
return nicedate;
}
function getQueryVariable(variable) //example https://mydomain.com?rid=123xyz
{
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i=0;i<vars.length;i++) {
var pair = vars[i].split("=");
if(pair[0] == variable){return pair[1];}
}
return(false);
}
var id = getQueryVariable('rid');
function request(){
if(id!==""){
$.ajax({
//Send an HTTP request to SharePoint 565a;
url: "https://prod-121.westus.logic.azure.com:443/workflows/565af31042d94c7bacbe0ee62c35eebd/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=Y6-TZHHzRfAHLSGGlmCG3W-zdeyYEYLV2Ay-LA4",
method: 'POST',
headers: {
"Content-Type": "application/json;odata=nometadata",
"Accept": "application/json;odata=nometadata"
},
data: JSON.stringify({
siteaddress:"https://mycompany.sharepoint.com/sites/mydepartmentorproject",
method:"GET",
uri:"_api/web/lists/GetByTitle('approvals')/items()?$filter=Title eq '"+id+"'&$top=1",
headers:{
"Accept":"application/json"
}
})
}).done(function(data){
if(data.value[0]!==undefined){
$('#requestid').html(data.value[0].Id);
$('#uniqueid').html(data.value[0].Title);
$('#creator').html(data.value[0].Createdby);
var datecreated = nicedate(data.value[0].Createddate);
$('#datecreated').html(datecreated);
var datesentout = nicedate(data.value[0].Datesentout);
$('#datesentout').html(datesentout);
var datecompleted = nicedate(data.value[0].Datecompleted);
$('#datecompleted').html(datecompleted);
$('#mytitle').val(data.value[0].Mytitle);
$('#mytitlelist').html(data.value[0].Mytitle);
$('#description').val(data.value[0].Message);
$('#descriptionlist').html(data.value[0].Message);
$('#status').html(data.value[0].Status);
listfiles();
$('#requesturl').html('https://mycompany.sharepoint.com/sites/mydepartmentorproject/approvals/request.aspx?rid='+$('#uniqueid').html());
if($('#status').html()!=='Inputs needed from requester'){
$('#datesentoutrow').show();
}
if($('#status').html()=='Completed'){
$('#downloadpdf').show();
$('#datecompletedrow').show();
}
if($('#emailaddress').html()==$('#creator').html() && $('#status').html()=='Inputs needed from requester'){
$('#addfilerealbutton').show();
$('#addapprovers').css('display','table-row');
$('#mytitle').show();
$('#description').show();
$('#submitbutton').show();
$('#savebutton').show();
$('.cconly').css('cursor','pointer');
}else{
$('#mytitlelist').show();
$('#descriptionlist').show();
}
if($('#emailaddress').html()==$('#creator').html() && $('#status').html()!=='Completed' && $('#status').html()!=='Cancelled'){
$('#cancelrequestrow').show();
}
if($('#status').html()=='Cancelled'){
$('#cancelledlabel').show();
}
listapprovers();
}else{
$('#workstreambody').css('background','url(../images/notfound.png) no-repeat');
$('#workstreambody').css('padding-top','265px');
$('#workstreambody').css('padding-left','75px');
$('#workstreambody').css('font-size','18px');
$('#workstreambody').css('color','#888');
$('#workstreambody').css('max-width','800px');
$('#workstreambody').css('margin-left','auto');
$('#workstreambody').css('margin-right','auto');
$('#workstreambody').html("No such Approval Request found :(<div style='margin-left:20px;'><a href='../'>Go Home</a></div>");
}
}).fail(function(error){
console.log(JSON.stringify(error));
});
}else{
$('#workstreambody').html('rid cannot be blank');
}
}
function listfiles(){
$('#filesfountain').show();
$('#fileslist').html('');
var path = $('#uniqueid').html();
$.ajax({
//Send an HTTP request to SharePoint 565a;
url: "https://prod-121.westus.logic.azure.com:443/workflows/565af31042d94c7bacbe0ee62c35eebd/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=Y6-TZHHzRfAHLSGGlmCG3W-zdeyYEYLV2Ay-LA4",
method: 'POST',
headers: {
"Content-Type": "application/json;odata=nometadata",
"Accept": "application/json;odata=nometadata"
},
data: JSON.stringify({
siteaddress:"https://mycompany.sharepoint.com/sites/mydepartmentorproject",
method:"GET",
uri:"/_vti_bin/ListData.svc/Requests?$filter=Path eq '/sites/mydepartmentorproject/approvals/"+path+"'",
headers:{
"Content-Type":"application/json;odata=nometadata",
"Accept":"application/json;odata=nometadata"
}
})
}).done(function(data){
console.log(JSON.stringify(data));
$('#filesfountain').hide();
var filecount=0;
var results="<table style='width:100%;'>";
for(var i=0;i<data.d.results.length;++i){
if(data.d.results[i].ContentTypeID.slice(0,6)!=='0x0120'){
filecount++;
if(i>0){
results+="<tr style='height:2px;'><td style='height:5px;width:2px;'></td></tr>";
}
results+="<tr>";
if($('#emailaddress').html()==$('#creator').html() && $('#status').html()=='Inputs needed from requester'){
results+="<td class='filedelete' id='filedelete"+data.d.results[i].Id+"' style='width:3px;padding-left:20px;padding-right:20px;'>x</td>";
}
results+="<td class='filerow' id='file"+data.d.results[i].Id+"'>";
results+="<a href='#' class='downloadfile' path='"+data.d.results[i].__metadata.media_src;
results+="' filename='"+data.d.results[i].Name+"' id='fileurl"+data.d.results[i].Id+"' style='display:inline-block;height:100%;width:100%;padding:5px;'>";
results+="<img src='../images/doc.png' style='vertical-align:middle;margin-right:15px;' />";
results+="<span class='filename' style='position:relative;top:2px;'>"+data.d.results[i].Name+"</span></a>";
results+="</td>";
}
}
if(filecount==0){
results+="<div style='margin:10px;'>No files</div>";
}
results+="</tr>";
$('#fileslist').html(results);
deletefile();
$(".downloadfile").click(function(){
var path = $(this).attr('path').split("/sites/mydepartmentorproject/")[1];
var name=$(this).attr('filename');
$.ajax({
//General get file contents Base64 56ef
url: "https://prod-92.westus.logic.azure.com:443/workflows/56efa1d1b968407fa78a1a71f788347f/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=G7YEweN3PvNdCowM-IVmJCV111I2UiGYH4FjyPxHEHo",
method: "POST",
headers: {
"Content-Type": "application/json;odata=nometadata",
"Accept": "application/json;odata=nometadata"
},
data: JSON.stringify({
"site":"https://mycompany.sharepoint.com/sites/mydepartmentorproject",
"path":path
})
}).done(function(data){
var downloaddata="";
if(data.content!==undefined){
downloaddata="data:"+data.contenttype+";base64,"+data.content;
}else{
downloaddata="data:text/plain,"+data.replace(/#/g,"%23");
}
var element = document.createElement('a');
element.setAttribute('href',downloaddata);
element.setAttribute('download',name);
element.style.display = 'none';
document.body.appendChild(element);
element.click()
document.body.removeChild(element);
}).fail(function(error){
console.log(JSON.stringify(error));
});
return false;
});
}).fail(function(error){
$('#filesfountain').hide();
console.log(JSON.stringify(error));
});
}
function deletefile(){
$('.filedelete').click(function(){
var name = $(this).parent().find('.filename').html();
if (window.confirm("Are you sure you want to delete?")) {
var path = $('#uniqueid').html();
$.ajax({
//Send an HTTP request to SharePoint 565a;
url: "https://prod-121.westus.logic.azure.com:443/workflows/565af31042d94c7bacbe0ee62c35eebd/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=Y6-TZHHzRfAHLSGGlmCG3W-zdeyYEYLV2Ay-LA4",
method: 'POST',
headers: {
"Content-Type": "application/json;odata=verbose",
"Accept": "application/json;odata=verbose"
},
data: JSON.stringify({
siteaddress:"https://mycompany.sharepoint.com/sites/mydepartmentorproject",
method:"POST",
uri:"_api/web/GetFileByServerRelativeUrl('/sites/mydepartmentorproject/approvals/"+path+"/"+name+"')",
headers:{
"X-HTTP-METHOD":"DELETE",
"IF-MATCH":"*"
}
})
}).done(function(data){
listfiles();
}).fail(function(error){
console.log(JSON.stringify(error));
});
}
});
}
$('#newfilefromlocaldriveuploadbutton').click(function(){
uploadFile('matter');
});
$('#file').on('change', function(){
var f = document.getElementById('file').files[0];
var fr=new FileReader();
fr.onload = (function(theFile){
return function(e) {
var filename=f.name;
$.ajax({
//General create file c56d
url: "https://prod-82.westus.logic.azure.com:443/workflows/c56d3e2acc314330abaf01d98f2ed7be/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=GnPdiI6sOIiYkXETQfoWQwzqwo69PuzrFPiA",
method: 'POST',
headers:{
"Content-Type": "application/json"
},
data:JSON.stringify({
siteaddress:"https://mycompany.sharepoint.com/sites/mydepartmentorproject",
folderpath:"approvals/"+$('#uniqueid').html(),
filename:filename,
file:e.target.result
})
}).done(function(item){
setTimeout(function(){listfiles();},600);
$('#newfilefromlocaldriveuploadfountain').hide();
}).fail(function(error){
console.log("ERROR "+JSON.stringify(error));
});
};
})(f);
fr.readAsDataURL(f);
});
function listapprovers(){
$.ajax({
//Send an HTTP request to SharePoint 565a;
url: "https://prod-121.westus.logic.azure.com:443/workflows/565af31042d94c7bacbe0ee62c35eebd/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=Y6-TZHHzRfAHLcSGGlmCG3W-zdeyYEYLV2Ay-LA4",
method: 'POST',
headers: {
"Content-Type": "application/json;odata=nometadata",
"Accept": "application/json;odata=nometadata"
},
data: JSON.stringify({
siteaddress:"https://mycompany.sharepoint.com/sites/mydepartmentorproject",
method:"GET",
uri:"/_api/web/lists/GetByTitle('approvalslist')/items/?$filter=Request eq '"+$('#uniqueid').html()+"'",
headers:{
"Content-Type":"application/json;odata=nometadata",
"Accept":"application/json;odata=nometadata"
}
})
}).done(function(approversdata){
var approverscount=0;
var results="<table style='width:100%;'>";
for(var i=0;i<approversdata.value.length;++i){
approverscount++;
if(i==0){
results+="<tr><td><div style='font-size:.8em;text-align:right;'>CCÂ only</div></td></tr>";
}
if(i>1){
results+="<tr style='height:2px;' id='prerow"+approversdata.value[i].Id+"'><td style='height:2px;width:2px;'></td></tr>";
}
results+="<tr id='tablerow"+approversdata.value[i].Id+"'><td><table style='width:100%;'><tr>";
if($('#emailaddress').html()==$('#creator').html() && $('#status').html()=='Inputs needed from requester'){
results+="<td class='approverdelete' class='approverdelete' id='approver"+approversdata.value[i].Id+"' ";
results+="style='width:3px;padding-left:20px;padding-right:20px;margin-left:-12px;margin-right:5px;'>x</div>";
}
results+="<td class='approverrow' id='approver"+approversdata.value[i].Id+"'>";
results+="<img src='../images/profile.png' style='vertical-align:middle;margin-right:15px;margin-left:5px;' />";
results+="<span style='position:relative;top:2px;'>"+approversdata.value[i].Approver+"</span></td>";
results+="<td style='width:30px;'><input type='checkbox' class='cconly' id='cconly"+approversdata.value[i].Id+"'";
if($('#emailaddress').html()!=$('#creator').html() || $('#status').html()!='Inputs needed from requester'){
results+=" disabled";
}
if(approversdata.value[i].CConly=='yes'){
results+=" checked";
}
results+=" style='height:30px;width:30px;' /></td>";
results+="</tr></table></td></tr>";
var status=approversdata.value[i].Status;
if(status!='Sent out for approvals' && $('#status').html()!='Inputs needed from requester'){
results+="<tr><td>";
var image = "";
if(status=='approved'){
image='approve';
}else if(status=='rejected'){
image='reject';
}
var tip = status.charAt(0).toUpperCase()+status.slice(1);
if(image!==''){
results+="<table style='width:100%;'><tr><td style='width:200px;'><img src='../images/"+image+"32.png' title='"+tip+"' style='vertical-align:middle;float:left;margin-left:5px;' />";
var dateapproved = nicedate(approversdata.value[i].Datecompleted);
results+="<div style='margin-left:15px;float:left;width:90px;position:relative;top:5px;'>"+dateapproved+"</div></td>";
results+="</tr></table>";
}
results+="</td></tr>";
var comment = approversdata.value[i].Comment;
if(comment!==null){
results+="<tr><td><table style='width:100%;'><tr><td style='width:48px;'></td><td style='background-color:#eee;border:1px solid #ddd;color:#888;padding:5px;'>";
results+=comment;
results+="</td></tr></table></td></tr>";
}
results+="</table></td></tr>";
}
}
if(approverscount==0){
results+="<div style='margin:10px;'>No approvers</div>";
}
results+="</table></td></tr></table>";
$('#approverslist').html(results);
deleteapprover();
if($('#status').html()=="Sent out for approvals"){
searchapproveraccess();
}
}).fail(function(error){
console.log(JSON.stringify(error));
});
}
function deleteapprover(){
$('.approverdelete').click(function(){
var id=$(this).attr('id').replace('approver','');
$.ajax({
//Send an HTTP request to SharePoint 565a;
url: "https://prod-121.westus.logic.azure.com:443/workflows/565af31042d94c7bacbe0ee62c35eebd/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=Y6-TZHHzRfAHLSGGlmCG3W-zdeyYEYLV2Ay-LA4",
method: 'POST',
headers: {
"Content-Type": "application/json;odata=nometadata",
"Accept": "application/json;odata=nometadata"
},
data: JSON.stringify({
siteaddress:"https://mycompany.sharepoint.com/sites/mydepartmentorproject",
method:"POST",
uri:"_api/web/lists/GetByTitle('approvalslist')/items("+id+")",
headers:{
"X-HTTP-METHOD":"DELETE",
"IF-MATCH":"*"
}
})
}).done(function(item){
$('#prerow'+id).remove();
$('#tablerow'+id).remove();
}).fail(function(error){
console.log("ERROR "+JSON.stringify(error));
});
});
}
function addapprover(){
$('#addapproverbutton').attr('busy',true);
var email = $('#addapproverinput').val();
if(email.indexOf('@automateofficework.com')==-1){
alert('Must be a automateofficework.com email address');
$('#addapproverbutton').removeAttr('busy');
}else if($('#approverslist').html().indexOf(">"+email+"<")>-1){
alert('Already on list of approvers');
$('#addapproverbutton').removeAttr('busy');
}else{
var title = (Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15)).toUpperCase();
$.ajax({
//Send an HTTP request to SharePoint 565a;
url: "https://prod-121.westus.logic.azure.com:443/workflows/565af31042d94c7bacbe0ee62c35eebd/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=Y6-TZHHzRfAHLSGGlmCG3W-zdeyYEYLV2Ay-LA4",
method: 'POST',
headers: {
"Content-Type": "application/json;odata=nometadata",
"Accept": "application/json;odata=nometadata"
},
data: JSON.stringify({
siteaddress:"https://mycompany.sharepoint.com/sites/mydepartmentorproject",
method:"POST",
uri:"_api/web/lists/GetByTitle('approvalslist')/items",
headers:{
"ACCEPT":"application/json;odata=verbose",
"CONTENT-TYPE":"application/json;odata=verbose"
},
body: JSON.stringify({
"__metadata":{"type":"SP.Data.ApprovalslistListItem"},
"Title":title,
"Approver":$('#addapproverinput').val(),
"Request":$('#uniqueid').html(),
"Createdby": $('#emailaddress').html(),
"Mytitle":$('#mytitle').val()
})
})
}).done(function(item){
$('#addapproverinput').val('');
listapprovers();
$('#addapproverbutton').removeAttr('busy');
}).fail(function(error){
alert("Not a valid email address");
console.log("ERROR "+JSON.stringify(error));
$('#addapproverbutton').removeAttr('busy');
});
}
}
function savedraft(){
var idcc=""
$('.cconly').each(function(){
var id = $(this).attr('id').replace('cconly','');
var checked="";
if($(this).is(':checked')){
checked="yes";
}
idcc+="|"+id+":"+checked+"|";
});
idcc=idcc.slice(1,-1);
$.ajax({
//Flow Approvals request save draft 5568
url: "https://prod-78.westus.logic.azure.com:443/workflows/556859a9b3f54ba89e6d020c7ab8bd64/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=0ofMLzdhrYY-2FqCUl0p-Gho4kiKgCWmxD3qRk0",
method: 'POST',
headers: {
"Content-Type": "application/json;odata=nometadata",
"Accept": "application/json;odata=nometadata"
},
data: JSON.stringify({
id : $('#requestid').html(),
title: $('#mytitle').val(),
description: $('#description').val(),
idcc: idcc,
createdby: $("#creator").text()
})
}).done(function(item){
$('#savebutton').show();
$('#savebuttonfountain').hide();
}).fail(function(error){
console.log("ERROR "+JSON.stringify(error));
$('#savebutton').show();
$('#savebuttonfountain').hide();
});
}
if($('#addapproverinput').length>0){
document.getElementById('addapproverinput').onkeydown=function(e){if(e.keyCode==13){addapprover();}};
}
$('#addapproverbutton').click(function(){
if($(this).attr('busy')==undefined){
addapprover();
}
});
$('#savebutton').click(function(){
$('#savebutton').hide();
$('#savebuttonfountain').show();
savedraft();
});
$('#submitbutton').click(function(){submitrequest()});
function submitrequest(){
$('#submitbutton').hide();
$('#submitbuttonfountain').show();
var error="";
if($('#mytitle').val()==""){error+="Title cannot be blank. ";}
if($('#description').val()==""){error+="Description cannot be blank. ";}
var approvercount=0;
$('.cconly').each(function(){
if(!$(this).is(':checked')){
approvercount++;
}
});
if(approvercount==0){error+="At least one approver required (not CC only). ";}
if(error!==""){
alert(error);
$('#submitbuttonfountain').hide();
$('#submitbutton').show();
}else{
var idcc=""
$('.cconly').each(function(){
var id = $(this).attr('id').replace('cconly','');
var checked="";
if($(this).is(':checked')){
checked="yes";
}
idcc+="|"+id+":"+checked+"|";
});
idcc=idcc.slice(1,-1);
today = new Date();
var day = ("0"+today.getUTCDate().toString()).slice(-2);
var month = ("0"+(today.getUTCMonth()+1).toString()).slice(-2);
var year = today.getUTCFullYear().toString();
var months = ["","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
var d = today;
datesentout = parseInt(day)+' '+months[parseInt(month)]+' '+year;
datesentoutstring = year+month+day;
$.ajax({
//Flow Approvals request save draft 5568
url: "https://prod-78.westus.logic.azure.com:443/workflows/556859a9b3f54ba89e6d020c7ab8bd64/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=0ofMLzdhrYY-2FqCUl0p-Gho4kiKgCWmxD3qRk0",
method: 'POST',
headers: {
"Content-Type": "application/json;odata=nometadata",
"Accept": "application/json;odata=nometadata"
},
data: JSON.stringify({
id : $('#requestid').html(),
title: $('#mytitle').val(),
description: $('#description').val(),
idcc: idcc,
action: 'submit',
datesentout : datesentout,
datesentoutstring : datesentoutstring
})
}).done(function(item){
if(item=='submit'){
location.reload();
}
}).fail(function(error){
console.log("ERROR "+JSON.stringify(error));
$('#submitbutton').show();
$('#submitbuttonfountain').hide();
});
}
}
function searchapproveraccess(){
$.ajax({
//Flow List approvals request approvers c369
url: "https://prod-109.westus.logic.azure.com:443/workflows/c369d32483784c62a8a14c2529969c8c/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=baL_w6_54Rl_FPw3wtTjC3C5zSzXf7vYmiC5sXDhbQk",
method: 'POST',
headers: {
"Content-Type": "application/json;odata=nometadata",
"Accept": "application/json;odata=nometadata"
},
data: JSON.stringify({
request : $('#uniqueid').html(),
approver : $('#emailaddress').html()
})
}).done(function(approversdata){
if(approversdata.value[0].Status=="Sent out for approvals"){
var div="<tr id='tablerowtools"+approversdata.value[0].Id+"'>";
div+="<td style='border:1px solid #ddd;padding:5px;background-color:#eee'>";
div+="<div style='background-color:#ffb500;margin-bottom:5px;padding:10px;'>";
div+="Please review the details and files before approving. You can also leave comments.";
div+="</div>";
div+="<label class='switch'><input type='checkbox' id='approvalcheckbox' checked><span class='slider round'></span>";
div+="<span id='inputlabel' style='position:relative;left:60px;top:8px;cursor:pointer;'>Approve</span></label>";
div+="<div><textarea id='commentsinput' style='box-sizing:border-box;width:100%;height:88px;resize:none;margin-top:5px;' ";
div+="placeholder='Comments'><textarea></div>";
div+="<div id='submitapprovalfountain' style='display:none;'><img src='../images/fountain.gif' style='margin:20px;' /></div>";
divs+="<div id='submitapproval' class='actionbutton'>"
div+="Submit";
div+="</div><div id='approvalid' style='display:none;'>"+approversdata.value[0].Id+"</div>";
div+="</td>";
div+="</tr>";
$('#tablerow'+approversdata.value[0].Id).after(div);
$('#commentsinput').focus();
$('#approvalselect').change(function(){
$('#commentsinput').focus();
});
$('#submitapproval').click(function(){
submitapproval();
})
$('.switch').click(function(){
if($('#approvalcheckbox').is(":checked")==true){
$('#inputlabel').html('Approve');
}else{
$('#inputlabel').html('Reject');
}
});
};
}).fail(function(error){
console.log(JSON.stringify(error));
});
}
function submitapproval(){
$('#submitapproval').hide();
$('#submitapprovalfountain').show();
var action=$('#inputlabel').html();
if(action=="Approve"){
action="approved";
}else{
action="rejected";
}
var id=$('#approvalid').html();
var email=$('#emailaddress').html();
var request = $('#uniqueid').html();
var comment = $('#commentsinput').val();
$.ajax({
//Flow Approvals request submit approval d6ed
url: "https://prod-18.westus.logic.azure.com:443/workflows/d6ed0c006614409c8900f98f35398811/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=dPpb6yWPkc_cwD5hEPrpuR-tI_S2bKuLtyv3EQ",
method: 'POST',
headers: {
"Content-Type": "application/json;odata=nometadata",
"Accept": "application/json;odata=nometadata"
},
data: JSON.stringify({
id : id,
action: action,
request: request,
requestid: $('#requestid').html(),
comment: comment
})
}).done(function(data){
location.reload();
}).fail(function(error){
console.log(JSON.stringify(error));
$('#submitapprovalfountain').hide();
$('#submitapproval').show();
});
}
$('#downloadpdf').click(function(){
$('#downloadpdf').hide();
$('#downloadpdffountain').show();
getpdfreport();
});
function getpdfreport(){
$.ajax({
//Flow Approvals request download file 9ebf
url: "https://prod-99.westus.logic.azure.com:443/workflows/9ebfd5dcceaa4105b33ac35af3ff9a8f/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=7jqhZA0fBtEaCQ1T1lN9ChmEdz5uicO2Hc",
method: 'POST',
headers: {
"Content-Type": "application/json;odata=nometadata",
"Accept": "application/json;odata=nometadata"
},
data: JSON.stringify({
path : $('#uniqueid').html()+'/Report/PDF_Report_'+$('#uniqueid').html()+'.pdf'
})
}).done(function(data){
var element = document.createElement('a');
blobUrl = 'data:application/octet-stream;base64,'+data;
element.setAttribute('href',blobUrl);
element.setAttribute('download','PDF_Report_'+$('#uniqueid').html()+'.pdf');
element.style.display = 'none';
document.body.appendChild(element);
element.click()
document.body.removeChild(element);
$('#downloadpdffountain').hide();
$('#downloadpdf').show();
}).fail(function(error){
console.log(JSON.stringify(error));
$('#downloadpdffountain').hide();
$('#downloadpdf').show();
});
}
const b64toBlob = (b64Data, contentType='', sliceSize=512) => {
const byteCharacters = atob(b64Data);
const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
const slice = byteCharacters.slice(offset, offset + sliceSize);
const byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
const blob = new Blob(byteArrays, {type: contentType});
return blob;
}
$('#addfilerealbutton').on('click',function(){
$('#filelabel').trigger('click');
});
function myrequests(){
$.ajax({
//Send an HTTP request to SharePoint 565a;
url: "https://prod-121.westus.logic.azure.com:443/workflows/565af31042d94c7bacbe0ee62c35eebd/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=Y6-TZHHzRfAHLSGGlmCG3W-zdeyYEYLV2Ay-LA4",
method: 'POST',
headers: {
"Content-Type": "application/json;odata=nometadata",
"Accept": "application/json;odata=nometadata"
},
data: JSON.stringify({
siteaddress:"https://mycompany.sharepoint.com/sites/mydepartmentorproject",
method:"GET",
uri:"_api/web/lists/GetByTitle('approvals')/items()?$filter=Createdby eq '"+$('#emailaddress').html()+"'&$orderby=Id desc",
headers:{
"Accept":"application/json;odata=nometadata",
"Content-Type":"applciation/json;odata=nometadata"
}
})
}).done(function(data){
var step=0;
var divs="";
for(i=0;i<data.value.length;++i){
step++;
var student = data.value[i];
divs+="<tr class='pointer whitegray goto'><td style='display:none;'>"+student.Title+"</td>";
divs+="<td><img src='../images/statuses.png' style='height:40px;width:40px;margin-right:10px;vertical-align:middle;object-fit:none;object-position:";
if(student.Status=="Completed"){
divs+="-158px 0px"; //completed -158
}else if(student.Status=="Cancelled"){
divs+="-106px 0px";
}else if(student.Status=="Sent out for approvals"){
divs+="0px 0px";
}else{
divs+="-54px 0px";
}
divs+=";' title='"+student.Status+"' /></td><td style='padding-right:10px;'>"+nicedate(student.Createddate)+"</td>";
divs+="<td style='padding-right:10px;'>"+student.Title+"</td><td style='padding-right:10px;'>"+student.Mytitle+"</td></tr>";
}
if(divs===""){
divs="No results";
}else{
divs="<table style='width:100%;' cellspacing='0'><tr><td style='display:none;'></td><td>Request status</td><td>Date created</td><td>Unique ID</td><td>Title</td></tr>"+divs+"</table>";
}
$('#myrequests').html(divs);
$('.goto').click(function(){
var uniqueid = $(this).find('td:first').text();
goto(uniqueid);
});
}).fail(function(error){
console.log(JSON.stringify(error));
});
}
function goto(path){
window.location='Request.aspx?rid='+path;
}
function myapprovals(){
var step=0;
$.ajax({
//Send an HTTP request to SharePoint 565a;
url: "https://prod-121.westus.logic.azure.com:443/workflows/565af31042d94c7bacbe0ee62c35eebd/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=Y6-TZHHzRfAHLSGGlmCG3W-zdeyYEYLV2Ay-LA4",
method: 'POST',
headers: {
"Content-Type": "application/json;odata=nometadata",
"Accept": "application/json;odata=nometadata"
},
data: JSON.stringify({
siteaddress:"https://mycompany.sharepoint.com/sites/mydepartmentorproject",
method:"GET",
uri:"_api/web/lists/GetByTitle('approvalslist')/items()?$filter=Approver eq '"+$('#emailaddress').html()+"'&$select=Request,Status,Id&$orderby=Id desc",
headers:{
"Accept":"application/json;odata=nometadata",
"Content-Type":"applciation/json;odata=nometadata"
}
})
}).done(function(data){
var step=0;
var gotten=0;
var divs="";
for(i=0;i<data.value.length;++i){
step++;
var student = data.value[i];
console.log(student.Id);
$.ajax({
//Send an HTTP request to SharePoint 565a;
url: "https://prod-121.westus.logic.azure.com:443/workflows/565af31042d94c7bacbe0ee62c35eebd/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=Y6-TZHHzRfAHLSGGlmCG3W-zdeyYEYLV2Ay-LA4",
method: 'POST',
headers: {
"Content-Type": "application/json;odata=nometadata",
"Accept": "application/json;odata=nometadata"
},
data: JSON.stringify({
siteaddress:"https://mycompany.sharepoint.com/sites/mydepartmentorproject",
method:"GET",
uri:"_api/web/lists/GetByTitle('approvals')/items()?$filter=Title eq '"+student.Request+"'&$select=Title,Status,Createddate,Createdby,Mytitle",
headers:{
"Accept":"application/json;odata=nometadata",
"Content-Type":"applciation/json;odata=nometadata"
}
})
}).done(function(requestdata){
gotten++;
console.log(JSON.stringify(requestdata));
var requeststudent = requestdata.value[0];
divs+="<tr class='pointer whitegray goto'><td style='display:none;'>"+requeststudent.Title+"</td>";
divs+="<td><img src='../images/statuses.png' style='height:40px;width:40px;margin-right:10px;vertical-align:middle;object-fit:none;object-position:";
if(requeststudent.Status=="Completed"){
divs+="-158px 0px"; //completed -158
}else if(requeststudent.Status=="Cancelled"){
divs+="-106px 0px";
}else if(requeststudent.Status=="Sent out for approvals"){
divs+="0px 0px";
}else{
divs+="-54px 0px";
}
divs+=";' title='"+student.Status+"' /></td><td>";
divs+="<img src='../images/statuses.png' style='height:40px;width:40px;margin-right:10px;vertical-align:middle;object-fit:none;object-position:";
if(student.Status=="approved"){
divs+="-158px 0px"; //completed -158
}else if(student.Status=="rejected"){
divs+="-106px 0px";
}else{
divs+="0px 0px";
}
divs+=";' title='"+student.Status+"' /></td><td style='padding-right:10px;'>"+nicedate(requeststudent.Createddate)+"</td>";
divs+="<td style='padding-right:10px;'>"+requeststudent.Title+"</td><td style='padding-right:10px;'>"+requeststudent.Createdby+"</td>";
divs+="<td style='padding-right:10px;'>"+requeststudent.Mytitle+"</td></tr>";
if(step==gotten){
if(divs===""){
divs="No results";
}else{
divs="<table style='width:100%;' cellspacing='0'><tr><td>Request status</td><td>Approval status</td><td>Date created</td><td>Unique ID</td><td>Created by</td><td>Title</td></tr>"+divs+"</table>";
}
$('#myapprovals').html(divs);
$('.goto').click(function(){
var uniqueid = $(this).find('td:first').text();
goto(uniqueid);
});
}
});
}
}).fail(function(error){
console.log(JSON.stringify(error));
});
}
$('#cancelrequest').click(function(){
if (window.confirm("Are you sure you want to cancel this request?")) {
$.ajax({
//Flow Approval request cancel request 622f
async: false,
url: "https://prod-117.westus.logic.azure.com:443/workflows/622f7277f8864f0c9ccc4d0f5a8ba1e1/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=phtFMdAreuwq4xBXSlR3JXV2s6wEamsWpxuPA-RnI0Q",
method: 'POST',
headers: {
"Content-Type": "application/json;odata=nometadata",
"Accept": "application/json;odata=nometadata"
},
data: JSON.stringify({
path: $('#uniqueid').html(),
id : $('#requestid').html()
})
}).done(function(requestdata){
location.reload();
}).fail(function(error){
console.log(JSON.stringify(error));
});
}
});
});
This is all the HTML, CSS, and JavaScript we need for interacting with the approval request for its entire lifecycle. From the beginning to the end. The HTML contains all the structures for every phase this approval request will go through. The JavaScript contains every function.
Our user is now presented with a web page that looks like below.
The user's browser is at the URL https://mycompany.sharepoint.com/sites/mydepartmentorproject/approvals/request.aspx?rid=S800VZJFYJSCAMMJ8CP6DS. Like the previous pages default.aspx and newrequest.aspx, the first thing we do is load the jQuery JavaScript library. We then load the external style.css and javascript.js file.
Once everything is loaded, the $(document).ready() function starts the JavaScript within it. The very first thing we do is to get the email address of the user who is visiting the page. This we insert in to the HTML element with ID "emailaddress". We next call the function request() which is declared on line 34. Just before the request() function we declare a variable "id" which is defined by calling the function getQueryVariable("rid") which is declared on line 23.
The function getQueryVariable("rid") says to look in the browser's URL for a URL variable URL and to return the value of this URL variable. For our user, the browser is at the URL https://mycompany.sharepoint.com/sites/mydepartmentorproject/approvals/request.aspx?rid=S800VZJFYJSCAMMJ8CP6DS. Thus, the variable returned is "S800VZJFYJSCAMMJ8CP6DS" and so this value is stored in our "id" variable.
The request() function first looks to see if our "id" variable is not equal to blank. If it is not, it goes further. If this variable is blank, the else() party of this conditional check is shown on line 110. It removes all the HTML from the content portion of the page and simply puts in the message "rid cannot be blank".
Going forward for when the "rid" variable in the URL is not blank, we use Power Automate to look up this value in our SharePoint document library.
$.ajax({
//Send an HTTP request to SharePoint 565a;
url: "https://prod-121.westus.logic.azure.com:443/workflows/565af31042d94c7bacbe0ee62c35eebd/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=Y6-TZHHzRfAHLSGGlmCG3W-zdeyYEYLV2Ay-LA4",
method: 'POST',
headers: {
"Content-Type": "application/json;odata=nometadata",
"Accept": "application/json;odata=nometadata"
},
data: JSON.stringify({
siteaddress:"https://mycompany.sharepoint.com/sites/mydepartmentorproject",
method:"GET",
uri:"_api/web/lists/GetByTitle('approvals')/items()?$filter=Title eq '"+id+"'&$top=1",
headers:{
"Accept":"application/json"
}
})
}).done(function(data){
if(data.value[0]!==undefined){
$('#requestid').html(data.value[0].Id);
$('#uniqueid').html(data.value[0].Title);
$('#creator').html(data.value[0].Createdby);
var datecreated = nicedate(data.value[0].Createddate);
$('#datecreated').html(datecreated);
var datesentout = nicedate(data.value[0].Datesentout);
$('#datesentout').html(datesentout);
var datecompleted = nicedate(data.value[0].Datecompleted);
$('#datecompleted').html(datecompleted);
$('#mytitle').val(data.value[0].Mytitle);
$('#mytitlelist').html(data.value[0].Mytitle);
$('#description').val(data.value[0].Message);
$('#descriptionlist').html(data.value[0].Message);
$('#status').html(data.value[0].Status);
listfiles();
$('#requesturl').html('https://mycompany.sharepoint.com/sites/mydepartmentorproject/approvals/request.aspx?rid='+$('#uniqueid').html());
if($('#status').html()!=='Inputs needed from requester'){
$('#datesentoutrow').show();
}
if($('#status').html()=='Completed'){
$('#downloadpdf').show();
$('#datecompletedrow').show();
}
if($('#emailaddress').html()==$('#creator').html() && $('#status').html()=='Inputs needed from requester'){
$('#addfilerealbutton').show();
$('#addapprovers').css('display','table-row');
$('#mytitle').show();
$('#description').show();
$('#submitbutton').show();
$('#savebutton').show();
$('.cconly').css('cursor','pointer');
}else{
$('#mytitlelist').show();
$('#descriptionlist').show();
}
if($('#emailaddress').html()==$('#creator').html() && $('#status').html()!=='Completed' && $('#status').html()!=='Cancelled'){
$('#cancelrequestrow').show();
}
if($('#status').html()=='Cancelled'){
$('#cancelledlabel').show();
}
listapprovers();
}else{
$('#workstreambody').css('background','url(../images/notfound.png) no-repeat');
$('#workstreambody').css('padding-top','265px');
$('#workstreambody').css('padding-left','75px');
$('#workstreambody').css('font-size','18px');
$('#workstreambody').css('color','#888');
$('#workstreambody').css('max-width','800px');
$('#workstreambody').css('margin-left','auto');
$('#workstreambody').css('margin-right','auto');
$('#workstreambody').html("No such Approval Request found :(<div style='margin-left:20px;'><a href='../'>Go Home</a></div>");
}
}).fail(function(error){
console.log(JSON.stringify(error));
});
The "uri" variable on line 47 is taken from the documentation about the SharePoint REST API. You can read more about working with lists and list items at
Working With Lists and List Items With REST. This uri is for getting an array of list items. We identity the list by its name. We then filter to see we only want list items where the Title (the name of the folder in case of the list being a document library) and the $top=1 means that we want a maximum of one matching item returned. Line 53 is a conditional check where we look to see that the first item in the array of matched items is not undefined. If it is not undefined, we go further. If there is to matching item in the document library with that Title, then the else() portion of the conditional check is at line 96 where we re-style the page and show an image that lets the user know that no request was found with that Title.
Line 54 starts taking all the data of the item that was found with the matching Title and fills in all the appropriate boxes in the page. Dates are stored in SharePoint like "2022-01-22T:00:00:00Z" but we use a function nicedate() declared on line 14 to convert these dates to "22 Jan 2022". If the email address of the person logged in matches the email address of the creator of the approval request and if the status of the request is "Inputs needed from requester", then we show buttons for the requester to be able to edit the list of files, list of approvers, the details of the request are editable and we show buttons to save and submit the request. If the request status is at another stage or if the person accessing the page is not the creator of the request, then they will see this request differently, based on the stage of the request and the access level of the person viewing the page.
For now, the requester is visiting the newly created request and they need to fill in all the details. They must fill in a title and a description. They must add at least one file and at least one approver.
Clicking on the "Add file" button triggers the function at line 238.
$('#file').on('change', function(){
var f = document.getElementById('file').files[0];
var fr=new FileReader();
fr.onload = (function(theFile){
return function(e) {
var filename=f.name;
$.ajax({
//General create file c56d
url: "https://prod-82.westus.logic.azure.com:443/workflows/c56d3e2acc314330abaf01d98f2ed7be/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=GnPdiI6sOIiYkXETQfoWQwzqwo69PuzrFPiA",
method: 'POST',
headers:{
"Content-Type": "application/json"
},
data:JSON.stringify({
siteaddress:"https://mycompany.sharepoint.com/sites/mydepartmentorproject",
folderpath:"approvals/"+$('#uniqueid').html(),
filename:filename,
file:e.target.result
})
}).done(function(item){
setTimeout(function(){listfiles();},600);
$('#newfilefromlocaldriveuploadfountain').hide();
}).fail(function(error){
console.log("ERROR "+JSON.stringify(error));
});
};
})(f);
fr.readAsDataURL(f);
});
Clicking the button prompts the user to select a file to upload. This function is listening for a file to be submitted for uploading. When a file is submitted it gets the file name and file contents and the unique Title of the folder of the item in the document library and sends all this to a Power Automate flow to create the file in the folder.

We need to discuss binary and base64 file formats. If you have ever opened a .TXT file or a .HTML file in Notepad or another simple text editor, you know you can read these in a simple text editor. But if you've ever tried to open a .DOCX file, or a PDF or an image like a PNG or a JPG in the same text editor, you know that these files look more or less like garbage in a text editor. They don't just contain simple letters and numbers. The text editor is reading the binary and trying to decode it into the characters that it knows. Power Automate and SharePoint and many, many applications online don't like to receive data in this format. For one thing, it's very difficult to transfer it over the Internet and to be certain that the data has gotten to the other end in one piece. Instead, the way to transfer data over the Internet is in a format called Base64. We take all the crazy characters that we see in Notepad and we convert them reliably to simple letters and numbers. You can try it for yourself at
https://base64.guru/converter/encode/file. You can upload a file and see the Base64 version of it. Then use
https://base64.guru/converter/decode/file to decode the Base64 back to the file. So this is the format that we have to transfer to Power Automate to give to SharePoint. The fr.readAsDataURL(f) function on line 265 has theportion readAsDataURL, which means that the data should be converted to Base64. The data passed to Power Automate looks like ""data:image/png;base64,abcdefghijklmnopqrstuvwxyz0123456789", but we only need to pass the portion after "base64," to SharePoint. So in Power Automate in teh "File Content" box we do an expression that says "split(triggerBody()?['file'],'base64,')[1]" to do exactly that.
If you need any help with creating this flow yourself, you should see the previous article where we teach you how to start a Power Automate flow, set up the trigger and prepare it to receive variables and then how to use those variable in the flow. The only thing new here is that we need to massage the data we already received by using an expression. To create an expression, just click in the text box and click "Add dynamic content". Then click the "Expression" tab. In the expression function box type or paste the function I gave you and click the "Update" button. Sometimes Power Automate notifies you about an error. Just click OK and click the "Update" button again. It sometimes says there is an error when there is no error. Save your flow and now your users can upload files to your SharePoint document library.

Once uploaded, it calls the listfiles() function to refesh the list of uploaded files. When listed, files have an "X" next to them so the requester can delete them. The deletefile() function is declared at line 203. We get the name of the file and ask the requester to confirm that they really want to delete the file. If they confirm, then we use our general flow to sent an HTTP call to SharePoint and we use the URI to identify the exact file and we set the X-HTTP-METHOD to DELETE in order to delete the file. Once done, we call the listfiles() function again to show the current list of files.
The addapprover() function is declared at line 381 and is triggered when the requester clicks the "Add approver" button. We first check that "@automateofficework.com" is present in the text input. If not, an alert pops up. If it is present, then we go forward. We look to see if the email address is already present in the list of approvers. If it it, an alert is shown. If not, we go forward.
I should mention here that we have a separate list where we track all the individual approvers and the approvals they have to give. For this we can use a simple SharePoint list. Mine is called "approvallist". The columns for the list are:
- ID (created by default)
- Title (created by default)
- Approver: single line of text
- Request: single line of text
- Status: single line of text
- Comment: multiple lines of text
- Datesentout: date
- Datesentoutstring: single line of text
- Datecompleted: date
- Datecompletedstring: single line of text
- CConly: yes/no
- Createdby: single line of text
- Mytitle: single line of text
Next we generate a random string to identify this unique approver's task. We create a new item in the "approvalslist" list and we refresh the list of approvers by triggering the listapprovers() function. Just like the list of files, the list of approvers has an "X" next to each approver to delete approvers. The deleteapprover() function is declared at line 353 and works very similar to deleting files. I should mention that the list of approvers also include a check box next to each approver to indicate that the approver is "CC only" so they will be merely emailed at the beginning of the approval flow to let them be aware that the approval flow has started and they will be emailed at the very end to let them know that it is completed.
The savedraft() function declared on line 428 is triggered by clicking on the "Save draft" button. It passes the unique numeric ID of the document library item, the title, description, email address of the creator, and a table of the approvers and whether they are CC only (this table has been formatted into a flat string) to Power Automate.
This flow is super complex. Is simply saves all the pieces when simply saving. When the requester is ready to submit and they click the "Submit" button, this flow is also triggered and sends an extra variable that the "action" variable is equal to "submit". When this is true, emails go to all the parties notifying them that the workflow has started and the status of the request goes to the "Sent out for approvals" stage.
When the requester clicks the "Submit" button, we check that the title and description are not blank. We also check that there is at least one file uploaded and at least one approver who is not CC only.
The emails go to the approvers inviting them to come to this same page to review and approver or reject and leave optional comments. When an approver comes, the prior details filled in by the requester are read only. We check to see if the person visiting the page is on the list of approvers and that they still need to approve or reject. If both conditions are true, then the person has a button to toggle between approve and reject, they have a text area where they can leave optional comments and they have a button to submit. Submitting an approval triggers the submitapproval() function declared at line 591.
We update the record of the individual approval and trigger another flow we will show further.
This second flow checks to see that all approvals have been captured. If so, then it emails everyone the final email letting them know that the approval flow is done. It also kicks off the flow to generate the PDF.